diff options
author | Neil Brown <neilb@notabene.brown> | 2008-06-27 18:31:24 -0400 |
---|---|---|
committer | Neil Brown <neilb@notabene.brown> | 2008-06-27 18:31:24 -0400 |
commit | 5e96ee65c8bd629ce093da67a066d3946468298a (patch) | |
tree | e1ff9e4984d71ffaa842e7e1d19c282fa9e01bcd | |
parent | a0da84f35b25875870270d16b6eccda4884d61a7 (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.c | 47 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 2 |
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) | |||
3075 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); | 3076 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); |
3076 | 3077 | ||
3077 | static ssize_t | 3078 | static ssize_t |
3079 | min_sync_show(mddev_t *mddev, char *page) | ||
3080 | { | ||
3081 | return sprintf(page, "%llu\n", | ||
3082 | (unsigned long long)mddev->resync_min); | ||
3083 | } | ||
3084 | static ssize_t | ||
3085 | min_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 | |||
3105 | static struct md_sysfs_entry md_min_sync = | ||
3106 | __ATTR(sync_min, S_IRUGO|S_IWUSR, min_sync_show, min_sync_store); | ||
3107 | |||
3108 | static ssize_t | ||
3078 | max_sync_show(mddev_t *mddev, char *page) | 3109 | max_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 | ||