raid5: reduce chance release_stripe() taking device_lock

release_stripe() is a place conf->device_lock is heavily contended. We take the
lock even stripe count isn't 1, which isn't required.

Signed-off-by: Shaohua Li <shli@fusionio.com>
Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Shaohua Li 2012-07-19 16:01:31 +10:00 committed by NeilBrown
parent 58e94ae184
commit 4eb788df67

View File

@ -190,9 +190,8 @@ static int stripe_operations_active(struct stripe_head *sh)
test_bit(STRIPE_COMPUTE_RUN, &sh->state); test_bit(STRIPE_COMPUTE_RUN, &sh->state);
} }
static void __release_stripe(struct r5conf *conf, struct stripe_head *sh) static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
{ {
if (atomic_dec_and_test(&sh->count)) {
BUG_ON(!list_empty(&sh->lru)); BUG_ON(!list_empty(&sh->lru));
BUG_ON(atomic_read(&conf->active_stripes)==0); BUG_ON(atomic_read(&conf->active_stripes)==0);
if (test_bit(STRIPE_HANDLE, &sh->state)) { if (test_bit(STRIPE_HANDLE, &sh->state)) {
@ -223,6 +222,11 @@ static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
} }
} }
} }
static void __release_stripe(struct r5conf *conf, struct stripe_head *sh)
{
if (atomic_dec_and_test(&sh->count))
do_release_stripe(conf, sh);
} }
static void release_stripe(struct stripe_head *sh) static void release_stripe(struct stripe_head *sh)
@ -230,9 +234,12 @@ static void release_stripe(struct stripe_head *sh)
struct r5conf *conf = sh->raid_conf; struct r5conf *conf = sh->raid_conf;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&conf->device_lock, flags); local_irq_save(flags);
__release_stripe(conf, sh); if (atomic_dec_and_lock(&sh->count, &conf->device_lock)) {
spin_unlock_irqrestore(&conf->device_lock, flags); do_release_stripe(conf, sh);
spin_unlock(&conf->device_lock);
}
local_irq_restore(flags);
} }
static inline void remove_hash(struct stripe_head *sh) static inline void remove_hash(struct stripe_head *sh)