diff options
author | Tejun Heo <tj@kernel.org> | 2011-12-13 18:33:39 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2011-12-13 18:33:39 -0500 |
commit | b50b636bce6293fa858cc7ff6c3ffe4920d90006 (patch) | |
tree | 65a4c509ff491aa89bf4d1a5f3e26d600eeea49f /block | |
parent | b9a1920837bc53430d339380e393a6e4c372939f (diff) |
block, cfq: kill ioc_gone
Now that cic's are immediately unlinked under both locks, there's no
need to count and drain cic's before module unload. RCU callback
completion is waited with rcu_barrier().
While at it, remove residual RCU operations on cic_list.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 43 |
1 files changed, 5 insertions, 38 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index ff44435fad50..ae7791a8ded9 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -62,10 +62,6 @@ static const int cfq_hist_divisor = 4; | |||
62 | static struct kmem_cache *cfq_pool; | 62 | static struct kmem_cache *cfq_pool; |
63 | static struct kmem_cache *cfq_ioc_pool; | 63 | static struct kmem_cache *cfq_ioc_pool; |
64 | 64 | ||
65 | static DEFINE_PER_CPU(unsigned long, cfq_ioc_count); | ||
66 | static struct completion *ioc_gone; | ||
67 | static DEFINE_SPINLOCK(ioc_gone_lock); | ||
68 | |||
69 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR | 65 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR |
70 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) | 66 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) |
71 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) | 67 | #define cfq_class_rt(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_RT) |
@@ -2671,26 +2667,8 @@ static void cfq_put_queue(struct cfq_queue *cfqq) | |||
2671 | 2667 | ||
2672 | static void cfq_cic_free_rcu(struct rcu_head *head) | 2668 | static void cfq_cic_free_rcu(struct rcu_head *head) |
2673 | { | 2669 | { |
2674 | struct cfq_io_context *cic; | 2670 | kmem_cache_free(cfq_ioc_pool, |
2675 | 2671 | container_of(head, struct cfq_io_context, rcu_head)); | |
2676 | cic = container_of(head, struct cfq_io_context, rcu_head); | ||
2677 | |||
2678 | kmem_cache_free(cfq_ioc_pool, cic); | ||
2679 | elv_ioc_count_dec(cfq_ioc_count); | ||
2680 | |||
2681 | if (ioc_gone) { | ||
2682 | /* | ||
2683 | * CFQ scheduler is exiting, grab exit lock and check | ||
2684 | * the pending io context count. If it hits zero, | ||
2685 | * complete ioc_gone and set it back to NULL | ||
2686 | */ | ||
2687 | spin_lock(&ioc_gone_lock); | ||
2688 | if (ioc_gone && !elv_ioc_count_read(cfq_ioc_count)) { | ||
2689 | complete(ioc_gone); | ||
2690 | ioc_gone = NULL; | ||
2691 | } | ||
2692 | spin_unlock(&ioc_gone_lock); | ||
2693 | } | ||
2694 | } | 2672 | } |
2695 | 2673 | ||
2696 | static void cfq_cic_free(struct cfq_io_context *cic) | 2674 | static void cfq_cic_free(struct cfq_io_context *cic) |
@@ -2705,7 +2683,7 @@ static void cfq_release_cic(struct cfq_io_context *cic) | |||
2705 | 2683 | ||
2706 | BUG_ON(!(dead_key & CIC_DEAD_KEY)); | 2684 | BUG_ON(!(dead_key & CIC_DEAD_KEY)); |
2707 | radix_tree_delete(&ioc->radix_root, dead_key >> CIC_DEAD_INDEX_SHIFT); | 2685 | radix_tree_delete(&ioc->radix_root, dead_key >> CIC_DEAD_INDEX_SHIFT); |
2708 | hlist_del_rcu(&cic->cic_list); | 2686 | hlist_del(&cic->cic_list); |
2709 | cfq_cic_free(cic); | 2687 | cfq_cic_free(cic); |
2710 | } | 2688 | } |
2711 | 2689 | ||
@@ -2782,7 +2760,6 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
2782 | INIT_HLIST_NODE(&cic->cic_list); | 2760 | INIT_HLIST_NODE(&cic->cic_list); |
2783 | cic->exit = cfq_exit_cic; | 2761 | cic->exit = cfq_exit_cic; |
2784 | cic->release = cfq_release_cic; | 2762 | cic->release = cfq_release_cic; |
2785 | elv_ioc_count_inc(cfq_ioc_count); | ||
2786 | } | 2763 | } |
2787 | 2764 | ||
2788 | return cic; | 2765 | return cic; |
@@ -3072,7 +3049,7 @@ static int cfq_create_cic(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
3072 | 3049 | ||
3073 | ret = radix_tree_insert(&ioc->radix_root, q->id, cic); | 3050 | ret = radix_tree_insert(&ioc->radix_root, q->id, cic); |
3074 | if (likely(!ret)) { | 3051 | if (likely(!ret)) { |
3075 | hlist_add_head_rcu(&cic->cic_list, &ioc->cic_list); | 3052 | hlist_add_head(&cic->cic_list, &ioc->cic_list); |
3076 | list_add(&cic->queue_list, &cfqd->cic_list); | 3053 | list_add(&cic->queue_list, &cfqd->cic_list); |
3077 | cic = NULL; | 3054 | cic = NULL; |
3078 | } else if (ret == -EEXIST) { | 3055 | } else if (ret == -EEXIST) { |
@@ -4156,19 +4133,9 @@ static int __init cfq_init(void) | |||
4156 | 4133 | ||
4157 | static void __exit cfq_exit(void) | 4134 | static void __exit cfq_exit(void) |
4158 | { | 4135 | { |
4159 | DECLARE_COMPLETION_ONSTACK(all_gone); | ||
4160 | blkio_policy_unregister(&blkio_policy_cfq); | 4136 | blkio_policy_unregister(&blkio_policy_cfq); |
4161 | elv_unregister(&iosched_cfq); | 4137 | elv_unregister(&iosched_cfq); |
4162 | ioc_gone = &all_gone; | 4138 | rcu_barrier(); /* make sure all cic RCU frees are complete */ |
4163 | /* ioc_gone's update must be visible before reading ioc_count */ | ||
4164 | smp_wmb(); | ||
4165 | |||
4166 | /* | ||
4167 | * this also protects us from entering cfq_slab_kill() with | ||
4168 | * pending RCU callbacks | ||
4169 | */ | ||
4170 | if (elv_ioc_count_read(cfq_ioc_count)) | ||
4171 | wait_for_completion(&all_gone); | ||
4172 | cfq_slab_kill(); | 4139 | cfq_slab_kill(); |
4173 | } | 4140 | } |
4174 | 4141 | ||