diff options
author | Shaohua Li <shli@kernel.org> | 2013-11-13 23:16:17 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-11-18 23:18:22 -0500 |
commit | 4bda556aea1d2916260326c6afa77b84a1f1345a (patch) | |
tree | 5233a0470d29eb5976ec9f6296ef129adf097ed8 /drivers/md | |
parent | 566c09c53455d7c4f1130928ef8071da1a24ea65 (diff) |
raid5: relieve lock contention in get_active_stripe()
track empty inactive list count, so md_raid5_congested() can use it to make
decision.
Signed-off-by: Shaohua Li <shli@fusionio.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid5.c | 8 | ||||
-rw-r--r-- | drivers/md/raid5.h | 1 |
2 files changed, 8 insertions, 1 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 93090b2afab4..1fb28c56457a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -356,6 +356,9 @@ static void release_inactive_stripe_list(struct r5conf *conf, | |||
356 | */ | 356 | */ |
357 | if (!list_empty_careful(list)) { | 357 | if (!list_empty_careful(list)) { |
358 | spin_lock_irqsave(conf->hash_locks + hash, flags); | 358 | spin_lock_irqsave(conf->hash_locks + hash, flags); |
359 | if (list_empty(conf->inactive_list + hash) && | ||
360 | !list_empty(list)) | ||
361 | atomic_dec(&conf->empty_inactive_list_nr); | ||
359 | list_splice_tail_init(list, conf->inactive_list + hash); | 362 | list_splice_tail_init(list, conf->inactive_list + hash); |
360 | do_wakeup = true; | 363 | do_wakeup = true; |
361 | spin_unlock_irqrestore(conf->hash_locks + hash, flags); | 364 | spin_unlock_irqrestore(conf->hash_locks + hash, flags); |
@@ -477,6 +480,8 @@ static struct stripe_head *get_free_stripe(struct r5conf *conf, int hash) | |||
477 | remove_hash(sh); | 480 | remove_hash(sh); |
478 | atomic_inc(&conf->active_stripes); | 481 | atomic_inc(&conf->active_stripes); |
479 | BUG_ON(hash != sh->hash_lock_index); | 482 | BUG_ON(hash != sh->hash_lock_index); |
483 | if (list_empty(conf->inactive_list + hash)) | ||
484 | atomic_inc(&conf->empty_inactive_list_nr); | ||
480 | out: | 485 | out: |
481 | return sh; | 486 | return sh; |
482 | } | 487 | } |
@@ -4059,7 +4064,7 @@ int md_raid5_congested(struct mddev *mddev, int bits) | |||
4059 | return 1; | 4064 | return 1; |
4060 | if (conf->quiesce) | 4065 | if (conf->quiesce) |
4061 | return 1; | 4066 | return 1; |
4062 | if (atomic_read(&conf->active_stripes) == conf->max_nr_stripes) | 4067 | if (atomic_read(&conf->empty_inactive_list_nr)) |
4063 | return 1; | 4068 | return 1; |
4064 | 4069 | ||
4065 | return 0; | 4070 | return 0; |
@@ -5750,6 +5755,7 @@ static struct r5conf *setup_conf(struct mddev *mddev) | |||
5750 | 5755 | ||
5751 | memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + | 5756 | memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + |
5752 | max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; | 5757 | max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024; |
5758 | atomic_set(&conf->empty_inactive_list_nr, NR_STRIPE_HASH_LOCKS); | ||
5753 | if (grow_stripes(conf, NR_STRIPES)) { | 5759 | if (grow_stripes(conf, NR_STRIPES)) { |
5754 | printk(KERN_ERR | 5760 | printk(KERN_ERR |
5755 | "md/raid:%s: couldn't allocate %dkB for buffers\n", | 5761 | "md/raid:%s: couldn't allocate %dkB for buffers\n", |
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index a9e443a1116f..e4407388670a 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
@@ -475,6 +475,7 @@ struct r5conf { | |||
475 | */ | 475 | */ |
476 | atomic_t active_stripes; | 476 | atomic_t active_stripes; |
477 | struct list_head inactive_list[NR_STRIPE_HASH_LOCKS]; | 477 | struct list_head inactive_list[NR_STRIPE_HASH_LOCKS]; |
478 | atomic_t empty_inactive_list_nr; | ||
478 | struct llist_head released_stripes; | 479 | struct llist_head released_stripes; |
479 | wait_queue_head_t wait_for_stripe; | 480 | wait_queue_head_t wait_for_stripe; |
480 | wait_queue_head_t wait_for_overlap; | 481 | wait_queue_head_t wait_for_overlap; |