aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-12-13 18:33:39 -0500
committerJens Axboe <axboe@kernel.dk>2011-12-13 18:33:39 -0500
commitf1a4f4d35ff30a328d5ea28f6cc826b2083111d2 (patch)
treec0ad51e3136286a9c1e1728fb1cfd7a322e8cf83 /block
parent216284c352a0061f5b20acff2c4e50fb43fea183 (diff)
block, cfq: fix cic lookup locking
* cfq_cic_lookup() may be called without queue_lock and multiple tasks can execute it simultaneously for the same shared ioc. Nothing prevents them racing each other and trying to drop the same dead cic entry multiple times. * smp_wmb() in cfq_exit_cic() doesn't really do anything and nothing prevents cfq_cic_lookup() seeing stale cic->key. This usually doesn't blow up because by the time cic is exited, all requests have been drained and new requests are terminated before going through elevator. However, it can still be triggered by plug merge path which doesn't grab queue_lock and thus can't check DEAD state reliably. This patch updates lookup locking such that, * Lookup is always performed under queue_lock. This doesn't add any more locking. The only issue is cfq_allow_merge() which can be called from plug merge path without holding any lock. For now, this is worked around by using cic of the request to merge into, which is guaranteed to have the same ioc. For longer term, I think it would be best to separate out plug merge method from regular one. * Spurious ioc->lock locking around cic lookup hint assignment dropped. 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.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 181a63d36691..e617b088c59b 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -1682,12 +1682,19 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq,
1682 return false; 1682 return false;
1683 1683
1684 /* 1684 /*
1685 * Lookup the cfqq that this bio will be queued with. Allow 1685 * Lookup the cfqq that this bio will be queued with and allow
1686 * merge only if rq is queued there. 1686 * merge only if rq is queued there. This function can be called
1687 * from plug merge without queue_lock. In such cases, ioc of @rq
1688 * and %current are guaranteed to be equal. Avoid lookup which
1689 * requires queue_lock by using @rq's cic.
1687 */ 1690 */
1688 cic = cfq_cic_lookup(cfqd, current->io_context); 1691 if (current->io_context == RQ_CIC(rq)->ioc) {
1689 if (!cic) 1692 cic = RQ_CIC(rq);
1690 return false; 1693 } else {
1694 cic = cfq_cic_lookup(cfqd, current->io_context);
1695 if (!cic)
1696 return false;
1697 }
1691 1698
1692 cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio)); 1699 cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
1693 return cfqq == RQ_CFQQ(rq); 1700 return cfqq == RQ_CFQQ(rq);
@@ -2784,21 +2791,15 @@ static void cfq_exit_cic(struct cfq_io_context *cic)
2784 struct io_context *ioc = cic->ioc; 2791 struct io_context *ioc = cic->ioc;
2785 2792
2786 list_del_init(&cic->queue_list); 2793 list_del_init(&cic->queue_list);
2794 cic->key = cfqd_dead_key(cfqd);
2787 2795
2788 /* 2796 /*
2789 * Make sure dead mark is seen for dead queues 2797 * Both setting lookup hint to and clearing it from @cic are done
2798 * under queue_lock. If it's not pointing to @cic now, it never
2799 * will. Hint assignment itself can race safely.
2790 */ 2800 */
2791 smp_wmb(); 2801 if (rcu_dereference_raw(ioc->ioc_data) == cic)
2792 cic->key = cfqd_dead_key(cfqd);
2793
2794 rcu_read_lock();
2795 if (rcu_dereference(ioc->ioc_data) == cic) {
2796 rcu_read_unlock();
2797 spin_lock(&ioc->lock);
2798 rcu_assign_pointer(ioc->ioc_data, NULL); 2802 rcu_assign_pointer(ioc->ioc_data, NULL);
2799 spin_unlock(&ioc->lock);
2800 } else
2801 rcu_read_unlock();
2802 2803
2803 if (cic->cfqq[BLK_RW_ASYNC]) { 2804 if (cic->cfqq[BLK_RW_ASYNC]) {
2804 cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]); 2805 cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]);
@@ -3092,12 +3093,20 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc,
3092 cfq_cic_free(cic); 3093 cfq_cic_free(cic);
3093} 3094}
3094 3095
3096/**
3097 * cfq_cic_lookup - lookup cfq_io_context
3098 * @cfqd: the associated cfq_data
3099 * @ioc: the associated io_context
3100 *
3101 * Look up cfq_io_context associated with @cfqd - @ioc pair. Must be
3102 * called with queue_lock held.
3103 */
3095static struct cfq_io_context * 3104static struct cfq_io_context *
3096cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc) 3105cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
3097{ 3106{
3098 struct cfq_io_context *cic; 3107 struct cfq_io_context *cic;
3099 unsigned long flags;
3100 3108
3109 lockdep_assert_held(cfqd->queue->queue_lock);
3101 if (unlikely(!ioc)) 3110 if (unlikely(!ioc))
3102 return NULL; 3111 return NULL;
3103 3112
@@ -3107,28 +3116,22 @@ cfq_cic_lookup(struct cfq_data *cfqd, struct io_context *ioc)
3107 * we maintain a last-hit cache, to avoid browsing over the tree 3116 * we maintain a last-hit cache, to avoid browsing over the tree
3108 */ 3117 */
3109 cic = rcu_dereference(ioc->ioc_data); 3118 cic = rcu_dereference(ioc->ioc_data);
3110 if (cic && cic->key == cfqd) { 3119 if (cic && cic->key == cfqd)
3111 rcu_read_unlock(); 3120 goto out;
3112 return cic;
3113 }
3114 3121
3115 do { 3122 do {
3116 cic = radix_tree_lookup(&ioc->radix_root, cfqd->queue->id); 3123 cic = radix_tree_lookup(&ioc->radix_root, cfqd->queue->id);
3117 rcu_read_unlock();
3118 if (!cic) 3124 if (!cic)
3119 break; 3125 break;
3120 if (unlikely(cic->key != cfqd)) { 3126 if (likely(cic->key == cfqd)) {
3121 cfq_drop_dead_cic(cfqd, ioc, cic); 3127 /* hint assignment itself can race safely */
3122 rcu_read_lock(); 3128 rcu_assign_pointer(ioc->ioc_data, cic);
3123 continue; 3129 break;
3124 } 3130 }
3125 3131 cfq_drop_dead_cic(cfqd, ioc, cic);
3126 spin_lock_irqsave(&ioc->lock, flags);
3127 rcu_assign_pointer(ioc->ioc_data, cic);
3128 spin_unlock_irqrestore(&ioc->lock, flags);
3129 break;
3130 } while (1); 3132 } while (1);
3131 3133out:
3134 rcu_read_unlock();
3132 return cic; 3135 return cic;
3133} 3136}
3134 3137