diff options
author | NeilBrown <neilb@suse.de> | 2012-07-03 12:13:29 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-07-03 12:13:29 +1000 |
commit | 5f066c632fcfd2a33f2eb7077c15c630e9f5ea5b (patch) | |
tree | 9a659a20661d4a2b13f796cd2409879c0596b5c1 | |
parent | 7c2c57c9a98bf5961e438a376486f95346f6b0c5 (diff) |
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.
Reported-by: majianpeng <majianpeng@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid5.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index befadb41a11f..62b6b3a83abf 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3588,8 +3588,18 @@ 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(s.blocked_rdev, + conf->mddev); + } if (s.handle_bad_blocks) for (i = disks; i--; ) { |