diff options
author | NeilBrown <neilb@suse.de> | 2006-01-06 03:21:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-06 11:34:10 -0500 |
commit | 88202a0c84e1951d6630d1d557d4801a8cc5b5ef (patch) | |
tree | 5a1aadc008de1ee68f40a4bb667157f248211230 /drivers/md | |
parent | 6d7ff7380b2e28c2807da3bf9fa614d91d15bacf (diff) |
[PATCH] md: allow sync-speed to be controlled per-device
Also export current (average) speed and status in sysfs.
Signed-off-by: Neil Brown <neilb@suse.de>
Acked-by: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/md.c | 110 |
1 files changed, 105 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 825e235b791b..1b76fb29fb70 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -81,10 +81,22 @@ static DEFINE_SPINLOCK(pers_lock); | |||
81 | * idle IO detection. | 81 | * idle IO detection. |
82 | * | 82 | * |
83 | * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. | 83 | * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. |
84 | * or /sys/block/mdX/md/sync_speed_{min,max} | ||
84 | */ | 85 | */ |
85 | 86 | ||
86 | static int sysctl_speed_limit_min = 1000; | 87 | static int sysctl_speed_limit_min = 1000; |
87 | static int sysctl_speed_limit_max = 200000; | 88 | static int sysctl_speed_limit_max = 200000; |
89 | static inline int speed_min(mddev_t *mddev) | ||
90 | { | ||
91 | return mddev->sync_speed_min ? | ||
92 | mddev->sync_speed_min : sysctl_speed_limit_min; | ||
93 | } | ||
94 | |||
95 | static inline int speed_max(mddev_t *mddev) | ||
96 | { | ||
97 | return mddev->sync_speed_max ? | ||
98 | mddev->sync_speed_max : sysctl_speed_limit_max; | ||
99 | } | ||
88 | 100 | ||
89 | static struct ctl_table_header *raid_table_header; | 101 | static struct ctl_table_header *raid_table_header; |
90 | 102 | ||
@@ -2197,6 +2209,90 @@ md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store); | |||
2197 | static struct md_sysfs_entry | 2209 | static struct md_sysfs_entry |
2198 | md_mismatches = __ATTR_RO(mismatch_cnt); | 2210 | md_mismatches = __ATTR_RO(mismatch_cnt); |
2199 | 2211 | ||
2212 | static ssize_t | ||
2213 | sync_min_show(mddev_t *mddev, char *page) | ||
2214 | { | ||
2215 | return sprintf(page, "%d (%s)\n", speed_min(mddev), | ||
2216 | mddev->sync_speed_min ? "local": "system"); | ||
2217 | } | ||
2218 | |||
2219 | static ssize_t | ||
2220 | sync_min_store(mddev_t *mddev, const char *buf, size_t len) | ||
2221 | { | ||
2222 | int min; | ||
2223 | char *e; | ||
2224 | if (strncmp(buf, "system", 6)==0) { | ||
2225 | mddev->sync_speed_min = 0; | ||
2226 | return len; | ||
2227 | } | ||
2228 | min = simple_strtoul(buf, &e, 10); | ||
2229 | if (buf == e || (*e && *e != '\n') || min <= 0) | ||
2230 | return -EINVAL; | ||
2231 | mddev->sync_speed_min = min; | ||
2232 | return len; | ||
2233 | } | ||
2234 | |||
2235 | static struct md_sysfs_entry md_sync_min = | ||
2236 | __ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store); | ||
2237 | |||
2238 | static ssize_t | ||
2239 | sync_max_show(mddev_t *mddev, char *page) | ||
2240 | { | ||
2241 | return sprintf(page, "%d (%s)\n", speed_max(mddev), | ||
2242 | mddev->sync_speed_max ? "local": "system"); | ||
2243 | } | ||
2244 | |||
2245 | static ssize_t | ||
2246 | sync_max_store(mddev_t *mddev, const char *buf, size_t len) | ||
2247 | { | ||
2248 | int max; | ||
2249 | char *e; | ||
2250 | if (strncmp(buf, "system", 6)==0) { | ||
2251 | mddev->sync_speed_max = 0; | ||
2252 | return len; | ||
2253 | } | ||
2254 | max = simple_strtoul(buf, &e, 10); | ||
2255 | if (buf == e || (*e && *e != '\n') || max <= 0) | ||
2256 | return -EINVAL; | ||
2257 | mddev->sync_speed_max = max; | ||
2258 | return len; | ||
2259 | } | ||
2260 | |||
2261 | static struct md_sysfs_entry md_sync_max = | ||
2262 | __ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store); | ||
2263 | |||
2264 | |||
2265 | static ssize_t | ||
2266 | sync_speed_show(mddev_t *mddev, char *page) | ||
2267 | { | ||
2268 | unsigned long resync, dt, db; | ||
2269 | resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active)); | ||
2270 | dt = ((jiffies - mddev->resync_mark) / HZ); | ||
2271 | if (!dt) dt++; | ||
2272 | db = resync - (mddev->resync_mark_cnt); | ||
2273 | return sprintf(page, "%ld\n", db/dt/2); /* K/sec */ | ||
2274 | } | ||
2275 | |||
2276 | static struct md_sysfs_entry | ||
2277 | md_sync_speed = __ATTR_RO(sync_speed); | ||
2278 | |||
2279 | static ssize_t | ||
2280 | sync_completed_show(mddev_t *mddev, char *page) | ||
2281 | { | ||
2282 | unsigned long max_blocks, resync; | ||
2283 | |||
2284 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) | ||
2285 | max_blocks = mddev->resync_max_sectors; | ||
2286 | else | ||
2287 | max_blocks = mddev->size << 1; | ||
2288 | |||
2289 | resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active)); | ||
2290 | return sprintf(page, "%lu / %lu\n", resync, max_blocks); | ||
2291 | } | ||
2292 | |||
2293 | static struct md_sysfs_entry | ||
2294 | md_sync_completed = __ATTR_RO(sync_completed); | ||
2295 | |||
2200 | static struct attribute *md_default_attrs[] = { | 2296 | static struct attribute *md_default_attrs[] = { |
2201 | &md_level.attr, | 2297 | &md_level.attr, |
2202 | &md_raid_disks.attr, | 2298 | &md_raid_disks.attr, |
@@ -2210,6 +2306,10 @@ static struct attribute *md_default_attrs[] = { | |||
2210 | static struct attribute *md_redundancy_attrs[] = { | 2306 | static struct attribute *md_redundancy_attrs[] = { |
2211 | &md_scan_mode.attr, | 2307 | &md_scan_mode.attr, |
2212 | &md_mismatches.attr, | 2308 | &md_mismatches.attr, |
2309 | &md_sync_min.attr, | ||
2310 | &md_sync_max.attr, | ||
2311 | &md_sync_speed.attr, | ||
2312 | &md_sync_completed.attr, | ||
2213 | NULL, | 2313 | NULL, |
2214 | }; | 2314 | }; |
2215 | static struct attribute_group md_redundancy_group = { | 2315 | static struct attribute_group md_redundancy_group = { |
@@ -4433,10 +4533,10 @@ static void md_do_sync(mddev_t *mddev) | |||
4433 | 4533 | ||
4434 | printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); | 4534 | printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); |
4435 | printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" | 4535 | printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" |
4436 | " %d KB/sec/disc.\n", sysctl_speed_limit_min); | 4536 | " %d KB/sec/disc.\n", speed_min(mddev)); |
4437 | printk(KERN_INFO "md: using maximum available idle IO bandwidth " | 4537 | printk(KERN_INFO "md: using maximum available idle IO bandwidth " |
4438 | "(but not more than %d KB/sec) for reconstruction.\n", | 4538 | "(but not more than %d KB/sec) for reconstruction.\n", |
4439 | sysctl_speed_limit_max); | 4539 | speed_max(mddev)); |
4440 | 4540 | ||
4441 | is_mddev_idle(mddev); /* this also initializes IO event counters */ | 4541 | is_mddev_idle(mddev); /* this also initializes IO event counters */ |
4442 | /* we don't use the checkpoint if there's a bitmap */ | 4542 | /* we don't use the checkpoint if there's a bitmap */ |
@@ -4477,7 +4577,7 @@ static void md_do_sync(mddev_t *mddev) | |||
4477 | 4577 | ||
4478 | skipped = 0; | 4578 | skipped = 0; |
4479 | sectors = mddev->pers->sync_request(mddev, j, &skipped, | 4579 | sectors = mddev->pers->sync_request(mddev, j, &skipped, |
4480 | currspeed < sysctl_speed_limit_min); | 4580 | currspeed < speed_min(mddev)); |
4481 | if (sectors == 0) { | 4581 | if (sectors == 0) { |
4482 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); | 4582 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); |
4483 | goto out; | 4583 | goto out; |
@@ -4542,8 +4642,8 @@ static void md_do_sync(mddev_t *mddev) | |||
4542 | currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 | 4642 | currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 |
4543 | /((jiffies-mddev->resync_mark)/HZ +1) +1; | 4643 | /((jiffies-mddev->resync_mark)/HZ +1) +1; |
4544 | 4644 | ||
4545 | if (currspeed > sysctl_speed_limit_min) { | 4645 | if (currspeed > speed_min(mddev)) { |
4546 | if ((currspeed > sysctl_speed_limit_max) || | 4646 | if ((currspeed > speed_max(mddev)) || |
4547 | !is_mddev_idle(mddev)) { | 4647 | !is_mddev_idle(mddev)) { |
4548 | msleep(500); | 4648 | msleep(500); |
4549 | goto repeat; | 4649 | goto repeat; |