diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-01 00:20:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-01 00:20:49 -0400 |
commit | af7eba0158e9b4632dcd94c1cd4100689666e14f (patch) | |
tree | 03184633a438a76bbdd7756e79647b26e33be5a0 | |
parent | d59ebbf19b29f4964b24f38c3ad876c33cdd7368 (diff) | |
parent | d01552a76d71f9879af448e9142389ee9be6e95b (diff) |
Merge tag 'md/4.3-rc7-fixes' of git://neil.brown.name/md
Pull md bug fixes from Neil Brown:
"Two more bug fixes for md.
One bugfix for a list corruption in raid5 because of incorrect
locking.
Other for possible data corruption when a recovering device is failed,
removed, and re-added.
Both tagged for -stable"
* tag 'md/4.3-rc7-fixes' of git://neil.brown.name/md:
Revert "md: allow a partially recovered device to be hot-added to an array."
md/raid5: fix locking in handle_stripe_clean_event()
-rw-r--r-- | drivers/md/md.c | 3 | ||||
-rw-r--r-- | drivers/md/raid5.c | 6 |
2 files changed, 5 insertions, 4 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index c702de18207a..3fe3d04a968a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -8040,8 +8040,7 @@ static int remove_and_add_spares(struct mddev *mddev, | |||
8040 | !test_bit(Bitmap_sync, &rdev->flags))) | 8040 | !test_bit(Bitmap_sync, &rdev->flags))) |
8041 | continue; | 8041 | continue; |
8042 | 8042 | ||
8043 | if (rdev->saved_raid_disk < 0) | 8043 | rdev->recovery_offset = 0; |
8044 | rdev->recovery_offset = 0; | ||
8045 | if (mddev->pers-> | 8044 | if (mddev->pers-> |
8046 | hot_add_disk(mddev, rdev) == 0) { | 8045 | hot_add_disk(mddev, rdev) == 0) { |
8047 | if (sysfs_link_rdev(mddev, rdev)) | 8046 | if (sysfs_link_rdev(mddev, rdev)) |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 49bb8d3ff9be..45933c160697 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3499,6 +3499,7 @@ returnbi: | |||
3499 | } | 3499 | } |
3500 | if (!discard_pending && | 3500 | if (!discard_pending && |
3501 | test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) { | 3501 | test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) { |
3502 | int hash; | ||
3502 | clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags); | 3503 | clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags); |
3503 | clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); | 3504 | clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); |
3504 | if (sh->qd_idx >= 0) { | 3505 | if (sh->qd_idx >= 0) { |
@@ -3512,16 +3513,17 @@ returnbi: | |||
3512 | * no updated data, so remove it from hash list and the stripe | 3513 | * no updated data, so remove it from hash list and the stripe |
3513 | * will be reinitialized | 3514 | * will be reinitialized |
3514 | */ | 3515 | */ |
3515 | spin_lock_irq(&conf->device_lock); | ||
3516 | unhash: | 3516 | unhash: |
3517 | hash = sh->hash_lock_index; | ||
3518 | spin_lock_irq(conf->hash_locks + hash); | ||
3517 | remove_hash(sh); | 3519 | remove_hash(sh); |
3520 | spin_unlock_irq(conf->hash_locks + hash); | ||
3518 | if (head_sh->batch_head) { | 3521 | if (head_sh->batch_head) { |
3519 | sh = list_first_entry(&sh->batch_list, | 3522 | sh = list_first_entry(&sh->batch_list, |
3520 | struct stripe_head, batch_list); | 3523 | struct stripe_head, batch_list); |
3521 | if (sh != head_sh) | 3524 | if (sh != head_sh) |
3522 | goto unhash; | 3525 | goto unhash; |
3523 | } | 3526 | } |
3524 | spin_unlock_irq(&conf->device_lock); | ||
3525 | sh = head_sh; | 3527 | sh = head_sh; |
3526 | 3528 | ||
3527 | if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) | 3529 | if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) |