FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Device-mapper Development

 
 
LinkBack Thread Tools
 
Old 05-30-2011, 04:41 PM
Mikulas Patocka
 
Default dm-kcopyd: use throttle

dm-kcopyd: use throttle

The variable "dm_kcopyd_throttle" is used to throttle kcopyd.

If dm_kcopyd_throttle >= 100, accounting is disabled, otherwise limit kcopyd
to use less than dm_kcopyd_throttle percent of time.

We sleep for 100ms if we overrun the allocated percentage of time.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm-kcopyd.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

Index: linux-2.6.39-fast/drivers/md/dm-kcopyd.c
================================================== =================
--- linux-2.6.39-fast.orig/drivers/md/dm-kcopyd.c 2011-05-30 18:09:45.000000000 +0200
+++ linux-2.6.39-fast/drivers/md/dm-kcopyd.c 2011-05-30 18:13:34.000000000 +0200
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
+#include <linux/delay.h>
#include <linux/device-mapper.h>
#include <linux/dm-kcopyd.h>

@@ -88,12 +89,35 @@ static unsigned last_jiffies = 0;
*/
#define ACOUNT_INTERVAL_SHIFT SHIFT_HZ

+/*
+ * Sleep this number of milliseconds.
+ *
+ * It is experimentally found value.
+ * Smaller values cause increased copy rate above the limit. The reason for
+ * this is unknown. A possible explanations could be jiffies rounding errors
+ * or read/write cache inside the disk.
+ */
+#define SLEEP_MSEC 100
+
+/*
+ * Maximum number of sleep events. There is a theoretical livelock if more
+ * kcopyd clients do work simultaneously, this limit allows us to get out of
+ * the livelock.
+ */
+#define MAX_SLEEPS 10
+
static void io_job_start(void)
{
unsigned now, difference;
+ int slept = 0;
+ int skew;

+try_again:
spin_lock_irq(&activity_spinlock);

+ if (likely(dm_kcopyd_throttle >= 100))
+ goto skip_limit;
+
now = jiffies;
difference = now - last_jiffies;
last_jiffies = now;
@@ -107,6 +131,16 @@ static void io_job_start(void)
io_period >>= shift;
}

+ skew = io_period - dm_kcopyd_throttle * total_period / 100;
+ /* skew = io_period * 100 / dm_kcopyd_throttle - total_period; */
+ if (unlikely(skew > 0) && slept < MAX_SLEEPS) {
+ slept++;
+ spin_unlock_irq(&activity_spinlock);
+ msleep(SLEEP_MSEC);
+ goto try_again;
+ }
+
+skip_limit:
num_io_jobs++;

spin_unlock_irq(&activity_spinlock);
@@ -120,6 +154,9 @@ static void io_job_finish(void)

num_io_jobs--;

+ if (likely(dm_kcopyd_throttle >= 100))
+ goto skip_limit;
+
if (!num_io_jobs) {
unsigned now, difference;

@@ -131,6 +168,7 @@ static void io_job_finish(void)
total_period += difference;
}

+skip_limit:
spin_unlock_irqrestore(&activity_spinlock, flags);
}


--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 05-30-2011, 04:56 PM
Mike Snitzer
 
Default dm-kcopyd: use throttle

Mikulas,

In the future it'd be great if you could use git-format-patch and
git-send-email (or some equivalent) to convey the order of the patches
within your patchsets. E.g. headers with [PATCH 1/3], [PATCH 2/3],
[PATCH 3/3].

Mike

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 05-31-2011, 10:04 PM
Mikulas Patocka
 
Default dm-kcopyd: use throttle

dm-kcopyd: use throttle

This patch allows the administrator to limit kcopyd rate.

We maintain a history of kcopyd usage in variables io_period and
total_period. The actual kcopyd activity is "(100 * io_period /
total_period)" percent of time. If we exceed user-defined percentage
threshold, we sleep.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

---
drivers/md/dm-kcopyd.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+)

Index: linux-2.6.39-fast/drivers/md/dm-kcopyd.c
================================================== =================
--- linux-2.6.39-fast.orig/drivers/md/dm-kcopyd.c 2011-05-31 22:46:40.000000000 +0200
+++ linux-2.6.39-fast/drivers/md/dm-kcopyd.c 2011-05-31 23:40:05.000000000 +0200
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
+#include <linux/delay.h>
#include <linux/device-mapper.h>
#include <linux/dm-kcopyd.h>

@@ -51,6 +52,8 @@ struct dm_kcopyd_client {
struct workqueue_struct *kcopyd_wq;
struct work_struct kcopyd_work;

+ struct dm_kcopyd_throttle *throttle;
+
/*
* We maintain three lists of jobs:
*
@@ -66,6 +69,106 @@ struct dm_kcopyd_client {
struct list_head pages_jobs;
};

+static DEFINE_SPINLOCK(throttle_spinlock);
+
+/*
+ * IO/IDLE accounting slowly decays after (1 << ACOUNT_INTERVAL_SHIFT) period.
+ * When total_period >= (1 << ACOUNT_INTERVAL_SHIFT) the counters are divided
+ * by 2.
+ */
+#define ACOUNT_INTERVAL_SHIFT SHIFT_HZ
+
+/*
+ * Sleep this number of milliseconds.
+ *
+ * It is experimentally found value.
+ * Smaller values cause increased copy rate above the limit. The reason for
+ * this is unknown. A possible explanations could be jiffies rounding errors
+ * or read/write cache inside the disk.
+ */
+#define SLEEP_MSEC 100
+
+/*
+ * Maximum number of sleep events. There is a theoretical livelock if more
+ * kcopyd clients do work simultaneously, this limit allows us to get out of
+ * the livelock.
+ */
+#define MAX_SLEEPS 10
+
+static void io_job_start(struct dm_kcopyd_throttle *t)
+{
+ unsigned now, difference;
+ int slept, skew;
+
+ if (unlikely(!t))
+ return;
+
+ slept = 0;
+
+try_again:
+ spin_lock_irq(&throttle_spinlock);
+
+ if (likely(t->throttle >= 100))
+ goto skip_limit;
+
+ now = jiffies;
+ difference = now - t->last_jiffies;
+ t->last_jiffies = now;
+ if (t->num_io_jobs)
+ t->io_period += difference;
+ t->total_period += difference;
+
+ if (unlikely(t->total_period >= (1 << ACOUNT_INTERVAL_SHIFT))) {
+ int shift = fls(t->total_period >> ACOUNT_INTERVAL_SHIFT);
+ t->total_period >>= shift;
+ t->io_period >>= shift;
+ }
+
+ skew = t->io_period - t->throttle * t->total_period / 100;
+ /* skew = t->io_period * 100 / t->throttle - t->total_period; */
+ if (unlikely(skew > 0) && slept < MAX_SLEEPS) {
+ slept++;
+ spin_unlock_irq(&throttle_spinlock);
+ msleep(SLEEP_MSEC);
+ goto try_again;
+ }
+
+skip_limit:
+ t->num_io_jobs++;
+
+ spin_unlock_irq(&throttle_spinlock);
+}
+
+static void io_job_finish(struct dm_kcopyd_throttle *t)
+{
+ unsigned long flags;
+
+ if (unlikely(!t))
+ return;
+
+ spin_lock_irqsave(&throttle_spinlock, flags);
+
+ t->num_io_jobs--;
+
+ if (likely(t->throttle >= 100))
+ goto skip_limit;
+
+ if (!t->num_io_jobs) {
+ unsigned now, difference;
+
+ now = jiffies;
+ difference = now - t->last_jiffies;
+ t->last_jiffies = now;
+
+ t->io_period += difference;
+ t->total_period += difference;
+ }
+
+skip_limit:
+ spin_unlock_irqrestore(&throttle_spinlock, flags);
+}
+
+
static void wake(struct dm_kcopyd_client *kc)
{
queue_work(kc->kcopyd_wq, &kc->kcopyd_work);
@@ -324,6 +427,8 @@ static void complete_io(unsigned long er
struct kcopyd_job *job = (struct kcopyd_job *) context;
struct dm_kcopyd_client *kc = job->kc;

+ io_job_finish(kc->throttle);
+
if (error) {
if (job->rw == WRITE)
job->write_err |= error;
@@ -365,6 +470,8 @@ static int run_io_job(struct kcopyd_job
.client = job->kc->io_client,
};

+ io_job_start(job->kc->throttle);
+
if (job->rw == READ)
r = dm_io(&io_req, 1, &job->source, NULL);
else
@@ -630,6 +737,7 @@ struct dm_kcopyd_client *dm_kcopyd_clien
INIT_LIST_HEAD(&kc->complete_jobs);
INIT_LIST_HEAD(&kc->io_jobs);
INIT_LIST_HEAD(&kc->pages_jobs);
+ kc->throttle = throttle;

kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
if (!kc->job_pool)

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 

Thread Tools




All times are GMT. The time now is 07:52 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org