aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Brown <neilb@notabene.brown>2008-06-27 18:31:24 -0400
committerNeil Brown <neilb@notabene.brown>2008-06-27 18:31:24 -0400
commit5e96ee65c8bd629ce093da67a066d3946468298a (patch)
treee1ff9e4984d71ffaa842e7e1d19c282fa9e01bcd
parenta0da84f35b25875870270d16b6eccda4884d61a7 (diff)
Allow setting start point for requested check/repair
This makes it possible to just resync a small part of an array. e.g. if a drive reports that it has questionable sectors, a 'repair' of just the region covering those sectors will cause them to be read and, if there is an error, re-written with correct data. Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r--drivers/md/md.c47
-rw-r--r--include/linux/raid/md_k.h2
2 files changed, 44 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2580ac1b9b0..261322722c1 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -278,6 +278,7 @@ static mddev_t * mddev_find(dev_t unit)
278 init_waitqueue_head(&new->sb_wait); 278 init_waitqueue_head(&new->sb_wait);
279 init_waitqueue_head(&new->recovery_wait); 279 init_waitqueue_head(&new->recovery_wait);
280 new->reshape_position = MaxSector; 280 new->reshape_position = MaxSector;
281 new->resync_min = 0;
281 new->resync_max = MaxSector; 282 new->resync_max = MaxSector;
282 new->level = LEVEL_NONE; 283 new->level = LEVEL_NONE;
283 284
@@ -3075,6 +3076,36 @@ sync_completed_show(mddev_t *mddev, char *page)
3075static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); 3076static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed);
3076 3077
3077static ssize_t 3078static ssize_t
3079min_sync_show(mddev_t *mddev, char *page)
3080{
3081 return sprintf(page, "%llu\n",
3082 (unsigned long long)mddev->resync_min);
3083}
3084static ssize_t
3085min_sync_store(mddev_t *mddev, const char *buf, size_t len)
3086{
3087 unsigned long long min;
3088 if (strict_strtoull(buf, 10, &min))
3089 return -EINVAL;
3090 if (min > mddev->resync_max)
3091 return -EINVAL;
3092 if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
3093 return -EBUSY;
3094
3095 /* Must be a multiple of chunk_size */
3096 if (mddev->chunk_size) {
3097 if (min & (sector_t)((mddev->chunk_size>>9)-1))
3098 return -EINVAL;
3099 }
3100 mddev->resync_min = min;
3101
3102 return len;
3103}
3104
3105static struct md_sysfs_entry md_min_sync =
3106__ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store);
3107
3108static ssize_t
3078max_sync_show(mddev_t *mddev, char *page) 3109max_sync_show(mddev_t *mddev, char *page)
3079{ 3110{
3080 if (mddev->resync_max == MaxSector) 3111 if (mddev->resync_max == MaxSector)
@@ -3089,9 +3120,10 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
3089 if (strncmp(buf, "max", 3) == 0) 3120 if (strncmp(buf, "max", 3) == 0)
3090 mddev->resync_max = MaxSector; 3121 mddev->resync_max = MaxSector;
3091 else { 3122 else {
3092 char *ep; 3123 unsigned long long max;
3093 unsigned long long max = simple_strtoull(buf, &ep, 10); 3124 if (strict_strtoull(buf, 10, &max))
3094 if (ep == buf || (*ep != 0 && *ep != '\n')) 3125 return -EINVAL;
3126 if (max < mddev->resync_min)
3095 return -EINVAL; 3127 return -EINVAL;
3096 if (max < mddev->resync_max && 3128 if (max < mddev->resync_max &&
3097 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) 3129 test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
@@ -3222,6 +3254,7 @@ static struct attribute *md_redundancy_attrs[] = {
3222 &md_sync_speed.attr, 3254 &md_sync_speed.attr,
3223 &md_sync_force_parallel.attr, 3255 &md_sync_force_parallel.attr,
3224 &md_sync_completed.attr, 3256 &md_sync_completed.attr,
3257 &md_min_sync.attr,
3225 &md_max_sync.attr, 3258 &md_max_sync.attr,
3226 &md_suspend_lo.attr, 3259 &md_suspend_lo.attr,
3227 &md_suspend_hi.attr, 3260 &md_suspend_hi.attr,
@@ -3777,6 +3810,7 @@ static int do_md_stop(mddev_t * mddev, int mode)
3777 mddev->size = 0; 3810 mddev->size = 0;
3778 mddev->raid_disks = 0; 3811 mddev->raid_disks = 0;
3779 mddev->recovery_cp = 0; 3812 mddev->recovery_cp = 0;
3813 mddev->resync_min = 0;
3780 mddev->resync_max = MaxSector; 3814 mddev->resync_max = MaxSector;
3781 mddev->reshape_position = MaxSector; 3815 mddev->reshape_position = MaxSector;
3782 mddev->external = 0; 3816 mddev->external = 0;
@@ -5625,9 +5659,11 @@ void md_do_sync(mddev_t *mddev)
5625 max_sectors = mddev->resync_max_sectors; 5659 max_sectors = mddev->resync_max_sectors;
5626 mddev->resync_mismatches = 0; 5660 mddev->resync_mismatches = 0;
5627 /* we don't use the checkpoint if there's a bitmap */ 5661 /* we don't use the checkpoint if there's a bitmap */
5628 if (!mddev->bitmap && 5662 if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
5629 !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) 5663 j = mddev->resync_min;
5664 else if (!mddev->bitmap)
5630 j = mddev->recovery_cp; 5665 j = mddev->recovery_cp;
5666
5631 } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) 5667 } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
5632 max_sectors = mddev->size << 1; 5668 max_sectors = mddev->size << 1;
5633 else { 5669 else {
@@ -5796,6 +5832,7 @@ void md_do_sync(mddev_t *mddev)
5796 5832
5797 skip: 5833 skip:
5798 mddev->curr_resync = 0; 5834 mddev->curr_resync = 0;
5835 mddev->resync_min = 0;
5799 mddev->resync_max = MaxSector; 5836 mddev->resync_max = MaxSector;
5800 sysfs_notify(&mddev->kobj, NULL, "sync_completed"); 5837 sysfs_notify(&mddev->kobj, NULL, "sync_completed");
5801 wake_up(&resync_wait); 5838 wake_up(&resync_wait);
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index 3dea9f545c8..780e0613e6d 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -227,6 +227,8 @@ struct mddev_s
227 atomic_t recovery_active; /* blocks scheduled, but not written */ 227 atomic_t recovery_active; /* blocks scheduled, but not written */
228 wait_queue_head_t recovery_wait; 228 wait_queue_head_t recovery_wait;
229 sector_t recovery_cp; 229 sector_t recovery_cp;
230 sector_t resync_min; /* user requested sync
231 * starts here */
230 sector_t resync_max; /* resync should pause 232 sector_t resync_max; /* resync should pause
231 * when it gets here */ 233 * when it gets here */
232 234