md/raid5:Add "BlockedBadBlocks" flag when waitting rdev to be unlocked.
PATCH 1/1 md/raid5:Add "BlockedBadBlocks" flag when waitting rdev to be unlocked.
If rdev became blocked because the unack badblocks, it did not exec md_wait_for_blocked_rdev in handle_stripe().So the rdev->nr_pending did not decrease.So rdev did not remove because the wrong nr_pending.
--- drivers/md/raid5.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/md/raid5.c +2 -1
@@ -3582,7 +3582,8 @@ static void handle_stripe(struct stripe_head *sh) finish:/* wait for this device to become unblocked */ -if (conf->mddev->external &&unlikely (s.blocked_rdev)) +if (unlikely (s.blocked_rdev) && (conf->mddev->external || +test_bit (BlockedBadBlocks, &(s.blocked_rdev->flags))))md_wait_for_blocked_rdev (s.blocked_rdev, conf->mddev);if (s.handle_bad_blocks)
Signature · 1 line
1.7.5.4
Quoted 13 lines · On Mon, 18 Jun 2012 11:13:48 +0800 majianpeng <[email protected]> wrote:
If rdev became blocked because the unack badblocks, it did not exec
md_wait_for_blocked_rdevin handle_stripe().So therdev->nr_pendingdid not decrease.So rdev did not remove because the wrongnr_pending.Signed-off-by majianpeng <[email protected]>--- drivers/md/raid5.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)drivers/md/raid5.c +0
-0
drivers/md/raid5.c static void handle_stripe(struct stripe_head *sh) · line 3589
Quoted 9 lines
drivers/md/raid5.c +2
-1@@ -3582,7 +3582,8 @@ static void handle_stripe(struct stripe_head *sh) finish:/* wait for this device to become unblocked */ -if (conf->mddev->external &&unlikely (s.blocked_rdev)) +if (unlikely (s.blocked_rdev) && (conf->mddev->external || +test_bit (BlockedBadBlocks, &(s.blocked_rdev->flags))))md_wait_for_blocked_rdev (s.blocked_rdev, conf->mddev);if (s.handle_bad_blocks)
Thanks for finding this. However I don't think your patch is quite correct. It would re-introduce a hang fixed by commit 43220aa0f22cd3ce5b3.
I've applied the following instead.
Thanks,
NeilBrown
From 0cee6aeb02b1ef947be62bb455f64720ecba2b4c Mon Sep 17 00:00:00 2001
From: NeilBrown <[email protected]>
Date: Wed, 27 Jun 2012 13:43:54 +1000
Subject: [PATCH] md/raid5: fix refcount problem when blocked_rdev is set.
commit 43220aa0f22cd3ce5b30246d50ccd696d119edea
md/raid5: fix a hang on device failure.
fixed a hang, but introduced a refcounting in balance so that if the presence of bad-blocks ever caused an rdev to be 'blocked' we would increment the refcount on the rdev and never decrement it.
So added the needed rdev_dec_pending when md_wait_for_blocked_rdev is not called.
drivers/md/raid5.c +11 -2
@@ -3588,8 +3588,17 @@ static void handle_stripe(struct stripe_head *sh) finish:/* wait for this device to become unblocked */ -if (conf->mddev->external &&unlikely (s.blocked_rdev)) -md_wait_for_blocked_rdev (s.blocked_rdev, conf->mddev); +if (unlikely (s.blocked_rdev)) { +if (conf->mddev->external) +md_wait_for_blocked_rdev (s.blocked_rdev, + conf->mddev); +else +/* Internal metadata will immediately +* be written by raid5d, so we don't +* need to wait here. +*/ +rdev_dec_pending (rdev, mddev); + }if (s.handle_bad_blocks)for (i = disks; i--; ) {
Quoted 5 lines · On Wed, 27 Jun 2012 13:45:13 +1000 NeilBrown <[email protected]> wrote:
Thanks for finding this. However I don't think your patch is quite correct. It would re-introduce a hang fixed by commit
43220aa0f22cd3ce5b3.I've applied the following instead.
....
drivers/md/raid5.c static void handle_stripe(struct stripe_head *sh) · line 3601
Quoted 7 lines
drivers/md/raid5.c +7
-0+else +/* Internal metadata will immediately +* be written by raid5d, so we don't +* need to wait here. +*/ +rdev_dec_pending (rdev, mddev); + }
... which is clearly wrong. That last line is now
rdev_dec_pending(s.blocked_rdev, conf->mddev);
NeilBrown
Quoted 3 lines
drivers/md/raid5.c +0
-0if (s.handle_bad_blocks)for (i = disks; i--; ) {