aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2008-02-06 04:39:52 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 13:41:18 -0500
commitc620727779f7cc8ea96efb71f0651a26349e59c1 (patch)
tree777abdad9c9ef10cb4df5c0efc736e6c64851ed8 /drivers/md/md.c
parentc303da6d713b87b7b3f999f5acce8ecc76ff1adb (diff)
md: allow a maximum extent to be set for resyncing
This allows userspace to control resync/reshape progress and synchronise it with other activities, such as shared access in a SAN, or backing up critical sections during a tricky reshape. Writing a number of sectors (which must be a multiple of the chunk size if such is meaningful) causes a resync to pause when it gets to that point. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c75
1 files changed, 65 insertions, 10 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 00788c56276f..79eb63fdb4b3 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -275,6 +275,7 @@ static mddev_t * mddev_find(dev_t unit)
275 spin_lock_init(&new->write_lock); 275 spin_lock_init(&new->write_lock);
276 init_waitqueue_head(&new->sb_wait); 276 init_waitqueue_head(&new->sb_wait);
277 new->reshape_position = MaxSector; 277 new->reshape_position = MaxSector;
278 new->resync_max = MaxSector;
278 279
279 new->queue = blk_alloc_queue(GFP_KERNEL); 280 new->queue = blk_alloc_queue(GFP_KERNEL);
280 if (!new->queue) { 281 if (!new->queue) {
@@ -2921,6 +2922,43 @@ sync_completed_show(mddev_t *mddev, char *page)
2921static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); 2922static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
2922 2923
2923static ssize_t 2924static ssize_t
2925max_sync_show(mddev_t *mddev, char *page)
2926{
2927 if (mddev->resync_max == MaxSector)
2928 return sprintf(page, "max\n");
2929 else
2930 return sprintf(page, "%llu\n",
2931 (unsigned long long)mddev->resync_max);
2932}
2933static ssize_t
2934max_sync_store(mddev_t *mddev, const char *buf, size_t len)
2935{
2936 if (strncmp(buf, "max", 3) == 0)
2937 mddev->resync_max = MaxSector;
2938 else {
2939 char *ep;
2940 unsigned long long max = simple_strtoull(buf, &ep, 10);
2941 if (ep == buf || (*ep != 0 && *ep != '\n'))
2942 return -EINVAL;
2943 if (max < mddev->resync_max &&
2944 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
2945 return -EBUSY;
2946
2947 /* Must be a multiple of chunk_size */
2948 if (mddev->chunk_size) {
2949 if (max & (sector_t)((mddev->chunk_size>>9)-1))
2950 return -EINVAL;
2951 }
2952 mddev->resync_max = max;
2953 }
2954 wake_up(&mddev->recovery_wait);
2955 return len;
2956}
2957
2958static struct md_sysfs_entry md_max_sync =
2959__ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store);
2960
2961static ssize_t
2924suspend_lo_show(mddev_t *mddev, char *page) 2962suspend_lo_show(mddev_t *mddev, char *page)
2925{ 2963{
2926 return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); 2964 return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo);
@@ -3030,6 +3068,7 @@ static struct attribute *md_redundancy_attrs[] = {
3030 &md_sync_max.attr, 3068 &md_sync_max.attr,
3031 &md_sync_speed.attr, 3069 &md_sync_speed.attr,
3032 &md_sync_completed.attr, 3070 &md_sync_completed.attr,
3071 &md_max_sync.attr,
3033 &md_suspend_lo.attr, 3072 &md_suspend_lo.attr,
3034 &md_suspend_hi.attr, 3073 &md_suspend_hi.attr,
3035 &md_bitmap.attr, 3074 &md_bitmap.attr,
@@ -3579,6 +3618,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
3579 mddev->size = 0; 3618 mddev->size = 0;
3580 mddev->raid_disks = 0; 3619 mddev->raid_disks = 0;
3581 mddev->recovery_cp = 0; 3620 mddev->recovery_cp = 0;
3621 mddev->resync_max = MaxSector;
3582 mddev->reshape_position = MaxSector; 3622 mddev->reshape_position = MaxSector;
3583 mddev->external = 0; 3623 mddev->external = 0;
3584 3624
@@ -5443,8 +5483,16 @@ void md_do_sync(mddev_t *mddev)
5443 sector_t sectors; 5483 sector_t sectors;
5444 5484
5445 skipped = 0; 5485 skipped = 0;
5486 if (j >= mddev->resync_max) {
5487 sysfs_notify(&mddev->kobj, NULL, "sync_completed");
5488 wait_event(mddev->recovery_wait,
5489 mddev->resync_max > j
5490 || kthread_should_stop());
5491 }
5492 if (kthread_should_stop())
5493 goto interrupted;
5446 sectors = mddev->pers->sync_request(mddev, j, &skipped, 5494 sectors = mddev->pers->sync_request(mddev, j, &skipped,
5447 currspeed < speed_min(mddev)); 5495 currspeed < speed_min(mddev));
5448 if (sectors == 0) { 5496 if (sectors == 0) {
5449 set_bit(MD_RECOVERY_ERR, &mddev->recovery); 5497 set_bit(MD_RECOVERY_ERR, &mddev->recovery);
5450 goto out; 5498 goto out;
@@ -5486,15 +5534,9 @@ void md_do_sync(mddev_t *mddev)
5486 } 5534 }
5487 5535
5488 5536
5489 if (kthread_should_stop()) { 5537 if (kthread_should_stop())
5490 /* 5538 goto interrupted;
5491 * got a signal, exit. 5539
5492 */
5493 printk(KERN_INFO
5494 "md: md_do_sync() got signal ... exiting\n");
5495 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
5496 goto out;
5497 }
5498 5540
5499 /* 5541 /*
5500 * this loop exits only if either when we are slower than 5542 * this loop exits only if either when we are slower than
@@ -5558,9 +5600,22 @@ void md_do_sync(mddev_t *mddev)
5558 5600
5559 skip: 5601 skip:
5560 mddev->curr_resync = 0; 5602 mddev->curr_resync = 0;
5603 mddev->resync_max = MaxSector;
5604 sysfs_notify(&mddev->kobj, NULL, "sync_completed");
5561 wake_up(&resync_wait); 5605 wake_up(&resync_wait);
5562 set_bit(MD_RECOVERY_DONE, &mddev->recovery); 5606 set_bit(MD_RECOVERY_DONE, &mddev->recovery);
5563 md_wakeup_thread(mddev->thread); 5607 md_wakeup_thread(mddev->thread);
5608 return;
5609
5610 interrupted:
5611 /*
5612 * got a signal, exit.
5613 */
5614 printk(KERN_INFO
5615 "md: md_do_sync() got signal ... exiting\n");
5616 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
5617 goto out;
5618
5564} 5619}
5565EXPORT_SYMBOL_GPL(md_do_sync); 5620EXPORT_SYMBOL_GPL(md_do_sync);
5566 5621