diff options
author | NeilBrown <neilb@suse.de> | 2014-01-13 23:16:10 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2014-01-14 00:44:07 -0500 |
commit | 5af9bef72c074dbe946da8b74eabd79cd5a9ff19 (patch) | |
tree | d2572106b3e41964a96dbf0fe71f4c22e486802d | |
parent | 41a336e011887f73e7c879b60e1e3544045435cb (diff) |
md/raid5: fix a recently broken BUG_ON().
commit 6d183de4077191d1201283a9035ce57a9b05254d
md/raid5: fix newly-broken locking in get_active_stripe.
simplified a BUG_ON, but removed too much so now it sometimes fires
when it shouldn't.
When the STRIPE_EXPANDING flag is set, the stripe_head might be on a
special list while multiple stripe_heads are collected, or it might
not be on any list, even a 'free' list when the refcount is zero. As
long as STRIPE_EXPANDING is set, it will be found and added back to a
list eventually.
So both of the BUG_ONs which test for the ->lru being empty or not
need to avoid the case where STRIPE_EXPANDING is set.
The patch which broke this was marked for -stable, so this patch needs
to be applied to any branch that received 6d183de4
Fixes: 6d183de4077191d1201283a9035ce57a9b05254d
Cc: stable@vger.kernel.org (any release to which above was applied)
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid5.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9168173deaf3..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--; |