aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:21:36 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:10 -0500
commit88202a0c84e1951d6630d1d557d4801a8cc5b5ef (patch)
tree5a1aadc008de1ee68f40a4bb667157f248211230
parent6d7ff7380b2e28c2807da3bf9fa614d91d15bacf (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>
-rw-r--r--Documentation/md.txt22
-rw-r--r--drivers/md/md.c110
-rw-r--r--include/linux/raid/md_k.h4
3 files changed, 131 insertions, 5 deletions
diff --git a/Documentation/md.txt b/Documentation/md.txt
index b8d172b254f7..03a13c462cf2 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -207,6 +207,28 @@ All md devices contain:
207 available. It will then appear at md/dev-XXX (depending on the 207 available. It will then appear at md/dev-XXX (depending on the
208 name of the device) and further configuration is then possible. 208 name of the device) and further configuration is then possible.
209 209
210 sync_speed_min
211 sync_speed_max
212 This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
213 however they only apply to the particular array.
214 If no value has been written to these, of if the word 'system'
215 is written, then the system-wide value is used. If a value,
216 in kibibytes-per-second is written, then it is used.
217 When the files are read, they show the currently active value
218 followed by "(local)" or "(system)" depending on whether it is
219 a locally set or system-wide value.
220
221 sync_completed
222 This shows the number of sectors that have been completed of
223 whatever the current sync_action is, followed by the number of
224 sectors in total that could need to be processed. The two
225 numbers are separated by a '/' thus effectively showing one
226 value, a fraction of the process that is complete.
227
228 sync_speed
229 This shows the current actual speed, in K/sec, of the current
230 sync_action. It is averaged over the last 30 seconds.
231
210 232
211As component devices are added to an md array, they appear in the 'md' 233As component devices are added to an md array, they appear in the 'md'
212directory as new directories named 234directory as new directories named
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
86static int sysctl_speed_limit_min = 1000; 87static int sysctl_speed_limit_min = 1000;
87static int sysctl_speed_limit_max = 200000; 88static int sysctl_speed_limit_max = 200000;
89static 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
95static 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
89static struct ctl_table_header *raid_table_header; 101static 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);
2197static struct md_sysfs_entry 2209static struct md_sysfs_entry
2198md_mismatches = __ATTR_RO(mismatch_cnt); 2210md_mismatches = __ATTR_RO(mismatch_cnt);
2199 2211
2212static ssize_t
2213sync_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
2219static ssize_t
2220sync_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
2235static struct md_sysfs_entry md_sync_min =
2236__ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store);
2237
2238static ssize_t
2239sync_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
2245static ssize_t
2246sync_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
2261static struct md_sysfs_entry md_sync_max =
2262__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store);
2263
2264
2265static ssize_t
2266sync_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
2276static struct md_sysfs_entry
2277md_sync_speed = __ATTR_RO(sync_speed);
2278
2279static ssize_t
2280sync_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
2293static struct md_sysfs_entry
2294md_sync_completed = __ATTR_RO(sync_completed);
2295
2200static struct attribute *md_default_attrs[] = { 2296static 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[] = {
2210static struct attribute *md_redundancy_attrs[] = { 2306static 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};
2215static struct attribute_group md_redundancy_group = { 2315static 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;
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 68b929c079ab..617b9506c760 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -143,6 +143,10 @@ struct mddev_s
143 sector_t resync_mismatches; /* count of sectors where 143 sector_t resync_mismatches; /* count of sectors where
144 * parity/replica mismatch found 144 * parity/replica mismatch found
145 */ 145 */
146 /* if zero, use the system-wide default */
147 int sync_speed_min;
148 int sync_speed_max;
149
146 int ok_start_degraded; 150 int ok_start_degraded;
147 /* recovery/resync flags 151 /* recovery/resync flags
148 * NEEDED: we might need to start a resync/recover 152 * NEEDED: we might need to start a resync/recover