add resync speed control for dm-raid1
v2 cover add resync speed control for dm-raid1
Hi,
These patches are used to add resync speed control for dm-raid1. The second and third patch provide support for user-space tool dmsetup. I have made some modifications by the comments. This is the second version.
Guangliang Zhao (3):
dm raid1: add resync speed control for dm-raid1
dm raid1: add interface to set resync speed
dm raid1: add interface to get resync speed
drivers/md/dm-raid1.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-)
Signature · 1 line
1.7.10.4
PATCH v2 1/3 dm raid1: add resync speed control for dm-raid1
The IO Performance on the already available lv is very bad during the initial sync when we create a mirror lv. This patch add the rate limit for every mirror target to control resync speed.
--- drivers/md/dm-raid1.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-)
drivers/md/dm-raid1.c +29 -1
@@ -13,6 +13,7 @@#include <linux/pagemap.h> #include <linux/slab.h> #include <linux/workqueue.h> +#include <linux/ratelimit.h> #include <linux/device-mapper.h> #include <linux/dm-io.h> #include <linux/dm-dirty-log.h>
@@ -26,6 +27,11 @@#define DM_RAID1_HANDLE_ERRORS 0x01#define errors_handled (p) ((p)->features & DM_RAID1_HANDLE_ERRORS) +/* Default resync interval*/ +#define RESYNC_JIFFIES HZ +/* Default max resync speed in KB/s */ +#define DEFAULT_RESYNC_SPEED (0xFFFFFFF) +static DECLARE_WAIT_QUEUE_HEAD (_kmirrord_recovery_stopped);/*-----------------------------------------------------------------
@@ -69,6 +75,9 @@ struct mirror_set {int log_failure;int leg_failure;atomic_t suspend; +/* recovery speed control */ +struct ratelimit_state ms_rlimit; +struct delayed_work resync_waker;atomic_t default_mirror;/* Default mirror */
@@ -383,12 +392,18 @@ static void do_recovery(struct mirror_set *ms)/* * Copy any already quiesced regions. */ -while ((reg =dm_rh_recovery_start (ms->rh))) { +while (__ratelimit (&ms->ms_rlimit) && + (reg =dm_rh_recovery_start (ms->rh))) { r =recover (ms, reg);if (r)dm_rh_recovery_end (reg,0 ); } +/* Broke off the resync process, so wake up kmirrord later on */ +if (!ms->in_sync) +schedule_delayed_work (&ms->resync_waker, + ms->ms_rlimit.interval); +/* * Update the in sync flag. */
@@ -842,6 +857,14 @@ static void do_mirror(struct work_struct *work)do_failures (ms, &failures); } +static void do_resync_wake (struct work_struct *work) +{ +struct mirror_set *ms = + container_of(work, struct mirror_set, resync_waker.work); + +wakeup_mirrord (ms); +} +/*----------------------------------------------------------------- * Target functions *---------------------------------------------------------------*/
@@ -852,6 +875,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, {size_t len;struct mirror_set *ms =NULL ; +int burst; len =sizeof (*ms) + (sizeof (ms->mirror[0 ]) * nr_mirrors);
@@ -875,6 +899,10 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, ms->leg_failure =0 ;atomic_set (&ms->suspend,0 );atomic_set (&ms->default_mirror,DEFAULT_MIRROR ); + burst = (DEFAULT_RESYNC_SPEED * (RESYNC_JIFFIES /HZ )) <<1 ; + burst =DIV_ROUND_UP (burst, region_size); +ratelimit_state_init (&ms->ms_rlimit,RESYNC_JIFFIES , burst); +INIT_DELAYED_WORK (&ms->resync_waker, do_resync_wake); ms->read_record_pool =mempool_create_slab_pool (MIN_READ_RECORDS , _dm_raid1_read_record_cache);
Signature · 1 line
1.7.10.4
PATCH v2 2/3 dm raid1: add interface to set resync speed
In reply to Guangliang ZhaoAdd ioctl to control resync speed, userspace tool
is dmsetup message, message format is:
dmsetup message $device 0 "set-max-resync-speed $speed"
e.g.
dmsetup message /dev/dm-2 "set-max-resync-speed 12345"
--- drivers/md/dm-raid1.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
drivers/md/dm-raid1.c +44 -0
@@ -1361,6 +1361,49 @@ static void mirror_resume(struct dm_target *ti) }/* +* convert speed into members of ratelimit_state +*/ +static void speed_to_rlimit (struct mirror_set *ms,struct ratelimit_state *rl, +unsigned int speed) +{ +sector_t region_size =dm_rh_get_region_size (ms->rh); + + rl->interval =RESYNC_JIFFIES ; + rl->burst = (speed * (RESYNC_JIFFIES /HZ )) <<1 ; + rl->burst =DIV_ROUND_UP (rl->burst, region_size); +} + +/* +* Message interface +* set-max-resync-speed $speed(KB/s) +*/ +static int mirror_message (struct dm_target *ti,unsigned argc,char **argv) +{ +struct mirror_set *ms = ti->private; +unsigned int speed; +int ret =0 ; + +if (!strcasecmp (argv[0 ],"set-max-resync-speed" )) { +if (sscanf (argv[1 ],"%u" , &speed) !=1 ) { +DMWARN ("invalid speed parameter %s" , argv[1 ]); + ret = -EINVAL ; + goto error; + } + +speed_to_rlimit (ms, &ms->ms_rlimit, speed); + goto out; + }else { + ret = -EINVAL ; + goto error; + } + +error: +DMWARN ("unrecognised message received." ); +out: +return ret; +} + +/* * device_status_char * @m: mirror device/leg we want the status of *
@@ -1450,6 +1493,7 @@ static struct target_type mirror_target = { .presuspend = mirror_presuspend, .postsuspend = mirror_postsuspend, .resume = mirror_resume, + .message = mirror_message, .status = mirror_status, .iterate_devices = mirror_iterate_devices, };
Signature · 1 line
1.7.10.4
PATCH v2 3/3 dm raid1: add interface to get resync speed
In reply to Guangliang ZhaoAdd ioctl to get resync speed, userspace tool
is dmsetup status:
dmsetup status $device
e.g.
dmsetup status /dev/dm-2
--- drivers/md/dm-raid1.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
drivers/md/dm-raid1.c +17 -2
@@ -1427,6 +1427,20 @@ static char device_status_char(struct mirror *m) (test_bit (DM_RAID1_READ_ERROR , &(m->error_type))) ?'R' :'U' ; } +/* +* get speed from ratelimit_state +*/ +static unsigned int rlimit_to_speed (struct mirror_set *ms, +struct ratelimit_state *rl) +{ +sector_t region_size =dm_rh_get_region_size (ms->rh); +unsigned int time, burst; + + time = rl->interval /HZ ; + burst = (rl->burst * region_size) >>1 ; + +return burst / time; +}static int mirror_status (struct dm_target *ti,status_type_t type,char *result,unsigned int maxlen)
@@ -1445,9 +1459,10 @@ static int mirror_status(struct dm_target *ti, status_type_t type, } buffer[m] ='\0' ; -DMEMIT ("%llu/%llu 1 %s " , +DMEMIT ("%llu/%llu 1 %u 1 %s " , (unsigned long long )log->type->get_sync_count (log), - (unsigned long long )ms->nr_regions, buffer); + (unsigned long long )ms->nr_regions, +rlimit_to_speed (ms, &ms->ms_rlimit), buffer); sz += log->type->status (log, type, result+sz, maxlen-sz);
Signature · 1 line
1.7.10.4