diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-15 03:07:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-15 03:07:36 -0500 |
commit | 1a60864fc1c3b268a921549bcfc707c98083260b (patch) | |
tree | c38dc16671a83c9cac9860e50d02f39ad21cc298 | |
parent | 145830dfb005961cb507a578c9d2e7622f0b3716 (diff) | |
parent | 8313b8e57f55b15e5b7f7fc5d1630bbf686a9a97 (diff) |
Merge tag 'md/3.13-fixes' of git://neil.brown.name/md
Pull late md fixes from Neil Brown:
"Half a dozen md bug fixes.
All of these fix real bugs the people have hit, and are tagged for
-stable. Sorry they are late .... Christmas holidays and all that.
Hopefully they can still squeak into 3.13"
* tag 'md/3.13-fixes' of git://neil.brown.name/md:
md: fix problem when adding device to read-only array with bitmap.
md/raid10: fix bug when raid10 recovery fails to recover a block.
md/raid5: fix a recently broken BUG_ON().
md/raid1: fix request counting bug in new 'barrier' code.
md/raid10: fix two bugs in handling of known-bad-blocks.
md/raid5: Fix possible confusion when multiple write errors occur.
-rw-r--r-- | drivers/md/md.c | 18 | ||||
-rw-r--r-- | drivers/md/md.h | 3 | ||||
-rw-r--r-- | drivers/md/raid1.c | 3 | ||||
-rw-r--r-- | drivers/md/raid10.c | 12 | ||||
-rw-r--r-- | drivers/md/raid5.c | 7 |
5 files changed, 29 insertions, 14 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 21f4d7ff0da2..369d919bdafe 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1077,6 +1077,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1077 | rdev->raid_disk = -1; | 1077 | rdev->raid_disk = -1; |
1078 | clear_bit(Faulty, &rdev->flags); | 1078 | clear_bit(Faulty, &rdev->flags); |
1079 | clear_bit(In_sync, &rdev->flags); | 1079 | clear_bit(In_sync, &rdev->flags); |
1080 | clear_bit(Bitmap_sync, &rdev->flags); | ||
1080 | clear_bit(WriteMostly, &rdev->flags); | 1081 | clear_bit(WriteMostly, &rdev->flags); |
1081 | 1082 | ||
1082 | if (mddev->raid_disks == 0) { | 1083 | if (mddev->raid_disks == 0) { |
@@ -1155,6 +1156,8 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1155 | */ | 1156 | */ |
1156 | if (ev1 < mddev->bitmap->events_cleared) | 1157 | if (ev1 < mddev->bitmap->events_cleared) |
1157 | return 0; | 1158 | return 0; |
1159 | if (ev1 < mddev->events) | ||
1160 | set_bit(Bitmap_sync, &rdev->flags); | ||
1158 | } else { | 1161 | } else { |
1159 | if (ev1 < mddev->events) | 1162 | if (ev1 < mddev->events) |
1160 | /* just a hot-add of a new device, leave raid_disk at -1 */ | 1163 | /* just a hot-add of a new device, leave raid_disk at -1 */ |
@@ -1563,6 +1566,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1563 | rdev->raid_disk = -1; | 1566 | rdev->raid_disk = -1; |
1564 | clear_bit(Faulty, &rdev->flags); | 1567 | clear_bit(Faulty, &rdev->flags); |
1565 | clear_bit(In_sync, &rdev->flags); | 1568 | clear_bit(In_sync, &rdev->flags); |
1569 | clear_bit(Bitmap_sync, &rdev->flags); | ||
1566 | clear_bit(WriteMostly, &rdev->flags); | 1570 | clear_bit(WriteMostly, &rdev->flags); |
1567 | 1571 | ||
1568 | if (mddev->raid_disks == 0) { | 1572 | if (mddev->raid_disks == 0) { |
@@ -1645,6 +1649,8 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
1645 | */ | 1649 | */ |
1646 | if (ev1 < mddev->bitmap->events_cleared) | 1650 | if (ev1 < mddev->bitmap->events_cleared) |
1647 | return 0; | 1651 | return 0; |
1652 | if (ev1 < mddev->events) | ||
1653 | set_bit(Bitmap_sync, &rdev->flags); | ||
1648 | } else { | 1654 | } else { |
1649 | if (ev1 < mddev->events) | 1655 | if (ev1 < mddev->events) |
1650 | /* just a hot-add of a new device, leave raid_disk at -1 */ | 1656 | /* just a hot-add of a new device, leave raid_disk at -1 */ |
@@ -2788,6 +2794,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2788 | else | 2794 | else |
2789 | rdev->saved_raid_disk = -1; | 2795 | rdev->saved_raid_disk = -1; |
2790 | clear_bit(In_sync, &rdev->flags); | 2796 | clear_bit(In_sync, &rdev->flags); |
2797 | clear_bit(Bitmap_sync, &rdev->flags); | ||
2791 | err = rdev->mddev->pers-> | 2798 | err = rdev->mddev->pers-> |
2792 | hot_add_disk(rdev->mddev, rdev); | 2799 | hot_add_disk(rdev->mddev, rdev); |
2793 | if (err) { | 2800 | if (err) { |
@@ -5760,6 +5767,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) | |||
5760 | info->raid_disk < mddev->raid_disks) { | 5767 | info->raid_disk < mddev->raid_disks) { |
5761 | rdev->raid_disk = info->raid_disk; | 5768 | rdev->raid_disk = info->raid_disk; |
5762 | set_bit(In_sync, &rdev->flags); | 5769 | set_bit(In_sync, &rdev->flags); |
5770 | clear_bit(Bitmap_sync, &rdev->flags); | ||
5763 | } else | 5771 | } else |
5764 | rdev->raid_disk = -1; | 5772 | rdev->raid_disk = -1; |
5765 | } else | 5773 | } else |
@@ -7706,7 +7714,8 @@ static int remove_and_add_spares(struct mddev *mddev, | |||
7706 | if (test_bit(Faulty, &rdev->flags)) | 7714 | if (test_bit(Faulty, &rdev->flags)) |
7707 | continue; | 7715 | continue; |
7708 | if (mddev->ro && | 7716 | if (mddev->ro && |
7709 | rdev->saved_raid_disk < 0) | 7717 | ! (rdev->saved_raid_disk >= 0 && |
7718 | !test_bit(Bitmap_sync, &rdev->flags))) | ||
7710 | continue; | 7719 | continue; |
7711 | 7720 | ||
7712 | rdev->recovery_offset = 0; | 7721 | rdev->recovery_offset = 0; |
@@ -7787,9 +7796,12 @@ void md_check_recovery(struct mddev *mddev) | |||
7787 | * As we only add devices that are already in-sync, | 7796 | * As we only add devices that are already in-sync, |
7788 | * we can activate the spares immediately. | 7797 | * we can activate the spares immediately. |
7789 | */ | 7798 | */ |
7790 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
7791 | remove_and_add_spares(mddev, NULL); | 7799 | remove_and_add_spares(mddev, NULL); |
7792 | mddev->pers->spare_active(mddev); | 7800 | /* There is no thread, but we need to call |
7801 | * ->spare_active and clear saved_raid_disk | ||
7802 | */ | ||
7803 | md_reap_sync_thread(mddev); | ||
7804 | clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
7793 | goto unlock; | 7805 | goto unlock; |
7794 | } | 7806 | } |
7795 | 7807 | ||
diff --git a/drivers/md/md.h b/drivers/md/md.h index 2f5cc8a7ef3e..0095ec84ffc7 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -129,6 +129,9 @@ struct md_rdev { | |||
129 | enum flag_bits { | 129 | enum flag_bits { |
130 | Faulty, /* device is known to have a fault */ | 130 | Faulty, /* device is known to have a fault */ |
131 | In_sync, /* device is in_sync with rest of array */ | 131 | In_sync, /* device is in_sync with rest of array */ |
132 | Bitmap_sync, /* ..actually, not quite In_sync. Need a | ||
133 | * bitmap-based recovery to get fully in sync | ||
134 | */ | ||
132 | Unmerged, /* device is being added to array and should | 135 | Unmerged, /* device is being added to array and should |
133 | * be considerred for bvec_merge_fn but not | 136 | * be considerred for bvec_merge_fn but not |
134 | * yet for actual IO | 137 | * yet for actual IO |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1e5a540995e9..a49cfcc7a343 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -924,9 +924,8 @@ static sector_t wait_barrier(struct r1conf *conf, struct bio *bio) | |||
924 | conf->next_window_requests++; | 924 | conf->next_window_requests++; |
925 | else | 925 | else |
926 | conf->current_window_requests++; | 926 | conf->current_window_requests++; |
927 | } | ||
928 | if (bio->bi_sector >= conf->start_next_window) | ||
929 | sector = conf->start_next_window; | 927 | sector = conf->start_next_window; |
928 | } | ||
930 | } | 929 | } |
931 | 930 | ||
932 | conf->nr_pending++; | 931 | conf->nr_pending++; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c504e8389e69..06eeb99ea6fc 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1319,7 +1319,7 @@ read_again: | |||
1319 | /* Could not read all from this device, so we will | 1319 | /* Could not read all from this device, so we will |
1320 | * need another r10_bio. | 1320 | * need another r10_bio. |
1321 | */ | 1321 | */ |
1322 | sectors_handled = (r10_bio->sectors + max_sectors | 1322 | sectors_handled = (r10_bio->sector + max_sectors |
1323 | - bio->bi_sector); | 1323 | - bio->bi_sector); |
1324 | r10_bio->sectors = max_sectors; | 1324 | r10_bio->sectors = max_sectors; |
1325 | spin_lock_irq(&conf->device_lock); | 1325 | spin_lock_irq(&conf->device_lock); |
@@ -1327,7 +1327,7 @@ read_again: | |||
1327 | bio->bi_phys_segments = 2; | 1327 | bio->bi_phys_segments = 2; |
1328 | else | 1328 | else |
1329 | bio->bi_phys_segments++; | 1329 | bio->bi_phys_segments++; |
1330 | spin_unlock(&conf->device_lock); | 1330 | spin_unlock_irq(&conf->device_lock); |
1331 | /* Cannot call generic_make_request directly | 1331 | /* Cannot call generic_make_request directly |
1332 | * as that will be queued in __generic_make_request | 1332 | * as that will be queued in __generic_make_request |
1333 | * and subsequent mempool_alloc might block | 1333 | * and subsequent mempool_alloc might block |
@@ -3218,10 +3218,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
3218 | if (j == conf->copies) { | 3218 | if (j == conf->copies) { |
3219 | /* Cannot recover, so abort the recovery or | 3219 | /* Cannot recover, so abort the recovery or |
3220 | * record a bad block */ | 3220 | * record a bad block */ |
3221 | put_buf(r10_bio); | ||
3222 | if (rb2) | ||
3223 | atomic_dec(&rb2->remaining); | ||
3224 | r10_bio = rb2; | ||
3225 | if (any_working) { | 3221 | if (any_working) { |
3226 | /* problem is that there are bad blocks | 3222 | /* problem is that there are bad blocks |
3227 | * on other device(s) | 3223 | * on other device(s) |
@@ -3253,6 +3249,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, | |||
3253 | mirror->recovery_disabled | 3249 | mirror->recovery_disabled |
3254 | = mddev->recovery_disabled; | 3250 | = mddev->recovery_disabled; |
3255 | } | 3251 | } |
3252 | put_buf(r10_bio); | ||
3253 | if (rb2) | ||
3254 | atomic_dec(&rb2->remaining); | ||
3255 | r10_bio = rb2; | ||
3256 | break; | 3256 | break; |
3257 | } | 3257 | } |
3258 | } | 3258 | } |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index cc055da02e2a..cbb15716a5db 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -687,7 +687,8 @@ get_active_stripe(struct r5conf *conf, sector_t sector, | |||
687 | } else { | 687 | } else { |
688 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 688 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
689 | atomic_inc(&conf->active_stripes); | 689 | atomic_inc(&conf->active_stripes); |
690 | BUG_ON(list_empty(&sh->lru)); | 690 | BUG_ON(list_empty(&sh->lru) && |
691 | !test_bit(STRIPE_EXPANDING, &sh->state)); | ||
691 | list_del_init(&sh->lru); | 692 | list_del_init(&sh->lru); |
692 | if (sh->group) { | 693 | if (sh->group) { |
693 | sh->group->stripes_cnt--; | 694 | sh->group->stripes_cnt--; |
@@ -3608,7 +3609,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3608 | */ | 3609 | */ |
3609 | set_bit(R5_Insync, &dev->flags); | 3610 | set_bit(R5_Insync, &dev->flags); |
3610 | 3611 | ||
3611 | if (rdev && test_bit(R5_WriteError, &dev->flags)) { | 3612 | if (test_bit(R5_WriteError, &dev->flags)) { |
3612 | /* This flag does not apply to '.replacement' | 3613 | /* This flag does not apply to '.replacement' |
3613 | * only to .rdev, so make sure to check that*/ | 3614 | * only to .rdev, so make sure to check that*/ |
3614 | struct md_rdev *rdev2 = rcu_dereference( | 3615 | struct md_rdev *rdev2 = rcu_dereference( |
@@ -3621,7 +3622,7 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s) | |||
3621 | } else | 3622 | } else |
3622 | clear_bit(R5_WriteError, &dev->flags); | 3623 | clear_bit(R5_WriteError, &dev->flags); |
3623 | } | 3624 | } |
3624 | if (rdev && test_bit(R5_MadeGood, &dev->flags)) { | 3625 | if (test_bit(R5_MadeGood, &dev->flags)) { |
3625 | /* This flag does not apply to '.replacement' | 3626 | /* This flag does not apply to '.replacement' |
3626 | * only to .rdev, so make sure to check that*/ | 3627 | * only to .rdev, so make sure to check that*/ |
3627 | struct md_rdev *rdev2 = rcu_dereference( | 3628 | struct md_rdev *rdev2 = rcu_dereference( |