[dm-devel] [PATCH] dm-kcopyd: use throttle
Mikulas Patocka
mpatocka at redhat.com
Mon May 30 16:41:36 UTC 2011
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 at 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);
}
More information about the dm-devel
mailing list