diff options
author | NeilBrown <neilb@suse.de> | 2010-06-17 03:25:21 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2010-06-23 23:35:39 -0400 |
commit | 415e72d034c50520ddb7ff79e7d1792c1306f0c9 (patch) | |
tree | 4558df940a15693e477af206b54423d98d9a04b1 | |
parent | 674806d62fb02a22eea948c9f1b5e58e0947b728 (diff) |
md/raid5: Allow recovered part of partially recovered devices to be in-sync
During a recovery of reshape the early part of some devices might be
in-sync while the later parts are not.
We we know we are looking at an early part it is good to treat that
part as in-sync for stripe calculations.
This is particularly important for a reshape which suffers device
failure. Treating the data as in-sync can mean the difference between
data-safety and data-loss.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid5.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d4b233c25f2e..09f07dadf404 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3031,7 +3031,6 @@ static void handle_stripe5(struct stripe_head *sh) | |||
3031 | mdk_rdev_t *rdev; | 3031 | mdk_rdev_t *rdev; |
3032 | 3032 | ||
3033 | dev = &sh->dev[i]; | 3033 | dev = &sh->dev[i]; |
3034 | clear_bit(R5_Insync, &dev->flags); | ||
3035 | 3034 | ||
3036 | pr_debug("check %d: state 0x%lx toread %p read %p write %p " | 3035 | pr_debug("check %d: state 0x%lx toread %p read %p write %p " |
3037 | "written %p\n", i, dev->flags, dev->toread, dev->read, | 3036 | "written %p\n", i, dev->flags, dev->toread, dev->read, |
@@ -3068,17 +3067,27 @@ static void handle_stripe5(struct stripe_head *sh) | |||
3068 | blocked_rdev = rdev; | 3067 | blocked_rdev = rdev; |
3069 | atomic_inc(&rdev->nr_pending); | 3068 | atomic_inc(&rdev->nr_pending); |
3070 | } | 3069 | } |
3071 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { | 3070 | clear_bit(R5_Insync, &dev->flags); |
3071 | if (!rdev) | ||
3072 | /* Not in-sync */; | ||
3073 | else if (test_bit(In_sync, &rdev->flags)) | ||
3074 | set_bit(R5_Insync, &dev->flags); | ||
3075 | else { | ||
3076 | /* could be in-sync depending on recovery/reshape status */ | ||
3077 | if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) | ||
3078 | set_bit(R5_Insync, &dev->flags); | ||
3079 | } | ||
3080 | if (!test_bit(R5_Insync, &dev->flags)) { | ||
3072 | /* The ReadError flag will just be confusing now */ | 3081 | /* The ReadError flag will just be confusing now */ |
3073 | clear_bit(R5_ReadError, &dev->flags); | 3082 | clear_bit(R5_ReadError, &dev->flags); |
3074 | clear_bit(R5_ReWrite, &dev->flags); | 3083 | clear_bit(R5_ReWrite, &dev->flags); |
3075 | } | 3084 | } |
3076 | if (!rdev || !test_bit(In_sync, &rdev->flags) | 3085 | if (test_bit(R5_ReadError, &dev->flags)) |
3077 | || test_bit(R5_ReadError, &dev->flags)) { | 3086 | clear_bit(R5_Insync, &dev->flags); |
3087 | if (!test_bit(R5_Insync, &dev->flags)) { | ||
3078 | s.failed++; | 3088 | s.failed++; |
3079 | s.failed_num = i; | 3089 | s.failed_num = i; |
3080 | } else | 3090 | } |
3081 | set_bit(R5_Insync, &dev->flags); | ||
3082 | } | 3091 | } |
3083 | rcu_read_unlock(); | 3092 | rcu_read_unlock(); |
3084 | 3093 | ||
@@ -3312,7 +3321,6 @@ static void handle_stripe6(struct stripe_head *sh) | |||
3312 | for (i=disks; i--; ) { | 3321 | for (i=disks; i--; ) { |
3313 | mdk_rdev_t *rdev; | 3322 | mdk_rdev_t *rdev; |
3314 | dev = &sh->dev[i]; | 3323 | dev = &sh->dev[i]; |
3315 | clear_bit(R5_Insync, &dev->flags); | ||
3316 | 3324 | ||
3317 | pr_debug("check %d: state 0x%lx read %p write %p written %p\n", | 3325 | pr_debug("check %d: state 0x%lx read %p write %p written %p\n", |
3318 | i, dev->flags, dev->toread, dev->towrite, dev->written); | 3326 | i, dev->flags, dev->toread, dev->towrite, dev->written); |
@@ -3350,18 +3358,28 @@ static void handle_stripe6(struct stripe_head *sh) | |||
3350 | blocked_rdev = rdev; | 3358 | blocked_rdev = rdev; |
3351 | atomic_inc(&rdev->nr_pending); | 3359 | atomic_inc(&rdev->nr_pending); |
3352 | } | 3360 | } |
3353 | if (!rdev || !test_bit(In_sync, &rdev->flags)) { | 3361 | clear_bit(R5_Insync, &dev->flags); |
3362 | if (!rdev) | ||
3363 | /* Not in-sync */; | ||
3364 | else if (test_bit(In_sync, &rdev->flags)) | ||
3365 | set_bit(R5_Insync, &dev->flags); | ||
3366 | else { | ||
3367 | /* in sync if before recovery_offset */ | ||
3368 | if (sh->sector + STRIPE_SECTORS <= rdev->recovery_offset) | ||
3369 | set_bit(R5_Insync, &dev->flags); | ||
3370 | } | ||
3371 | if (!test_bit(R5_Insync, &dev->flags)) { | ||
3354 | /* The ReadError flag will just be confusing now */ | 3372 | /* The ReadError flag will just be confusing now */ |
3355 | clear_bit(R5_ReadError, &dev->flags); | 3373 | clear_bit(R5_ReadError, &dev->flags); |
3356 | clear_bit(R5_ReWrite, &dev->flags); | 3374 | clear_bit(R5_ReWrite, &dev->flags); |
3357 | } | 3375 | } |
3358 | if (!rdev || !test_bit(In_sync, &rdev->flags) | 3376 | if (test_bit(R5_ReadError, &dev->flags)) |
3359 | || test_bit(R5_ReadError, &dev->flags)) { | 3377 | clear_bit(R5_Insync, &dev->flags); |
3378 | if (!test_bit(R5_Insync, &dev->flags)) { | ||
3360 | if (s.failed < 2) | 3379 | if (s.failed < 2) |
3361 | r6s.failed_num[s.failed] = i; | 3380 | r6s.failed_num[s.failed] = i; |
3362 | s.failed++; | 3381 | s.failed++; |
3363 | } else | 3382 | } |
3364 | set_bit(R5_Insync, &dev->flags); | ||
3365 | } | 3383 | } |
3366 | rcu_read_unlock(); | 3384 | rcu_read_unlock(); |
3367 | 3385 | ||