aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-12-13 18:33:38 -0500
committerJens Axboe <axboe@kernel.dk>2011-12-13 18:33:38 -0500
commitdc86900e0a8f665122de6faadd27fb4c6d2b3e4d (patch)
treeec24aa4b076f54fcfb0558d5113f5c5e0f4bc173 /block
parent283287a52e3c3f7f8f9da747f4b8c5202740d776 (diff)
block, cfq: move ioc ioprio/cgroup changed handling to cic
ioprio/cgroup change was handled by marking the changed state in ioc and, on the following access to the ioc, performing RCU-protected iteration through all cic's grabbing the matching queue_lock. This patch moves the changed state to each cic. When ioprio or cgroup changes, the respective bit is set on all cic's of the ioc and when each of those cic (not ioc) is accessed, change is applied for that specific ioc-queue pair. This also fixes the following two race conditions between setting and clearing of changed states. * Missing barrier between assign/load of ioprio and ioprio_changed allowed applying old ioprio. * Change requests could happen between application of change and clearing of changed variables. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r--block/blk-cgroup.c2
-rw-r--r--block/blk-ioc.c45
-rw-r--r--block/cfq-iosched.c28
3 files changed, 55 insertions, 20 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 4b001dcd85b0..dc00835aab6a 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1648,7 +1648,7 @@ static void blkiocg_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1648 /* we don't lose anything even if ioc allocation fails */ 1648 /* we don't lose anything even if ioc allocation fails */
1649 ioc = get_task_io_context(tsk, GFP_ATOMIC, NUMA_NO_NODE); 1649 ioc = get_task_io_context(tsk, GFP_ATOMIC, NUMA_NO_NODE);
1650 if (ioc) { 1650 if (ioc) {
1651 ioc->cgroup_changed = 1; 1651 ioc_cgroup_changed(ioc);
1652 put_io_context(ioc); 1652 put_io_context(ioc);
1653 } 1653 }
1654} 1654}
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index b13ed96776c2..6f59fbad93d9 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -188,6 +188,51 @@ struct io_context *get_task_io_context(struct task_struct *task,
188} 188}
189EXPORT_SYMBOL(get_task_io_context); 189EXPORT_SYMBOL(get_task_io_context);
190 190
191void ioc_set_changed(struct io_context *ioc, int which)
192{
193 struct cfq_io_context *cic;
194 struct hlist_node *n;
195
196 hlist_for_each_entry(cic, n, &ioc->cic_list, cic_list)
197 set_bit(which, &cic->changed);
198}
199
200/**
201 * ioc_ioprio_changed - notify ioprio change
202 * @ioc: io_context of interest
203 * @ioprio: new ioprio
204 *
205 * @ioc's ioprio has changed to @ioprio. Set %CIC_IOPRIO_CHANGED for all
206 * cic's. iosched is responsible for checking the bit and applying it on
207 * request issue path.
208 */
209void ioc_ioprio_changed(struct io_context *ioc, int ioprio)
210{
211 unsigned long flags;
212
213 spin_lock_irqsave(&ioc->lock, flags);
214 ioc->ioprio = ioprio;
215 ioc_set_changed(ioc, CIC_IOPRIO_CHANGED);
216 spin_unlock_irqrestore(&ioc->lock, flags);
217}
218
219/**
220 * ioc_cgroup_changed - notify cgroup change
221 * @ioc: io_context of interest
222 *
223 * @ioc's cgroup has changed. Set %CIC_CGROUP_CHANGED for all cic's.
224 * iosched is responsible for checking the bit and applying it on request
225 * issue path.
226 */
227void ioc_cgroup_changed(struct io_context *ioc)
228{
229 unsigned long flags;
230
231 spin_lock_irqsave(&ioc->lock, flags);
232 ioc_set_changed(ioc, CIC_CGROUP_CHANGED);
233 spin_unlock_irqrestore(&ioc->lock, flags);
234}
235
191static int __init blk_ioc_init(void) 236static int __init blk_ioc_init(void)
192{ 237{
193 iocontext_cachep = kmem_cache_create("blkdev_ioc", 238 iocontext_cachep = kmem_cache_create("blkdev_ioc",
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index a612ca65f371..51aece2eea7c 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2904,7 +2904,7 @@ static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
2904 cfq_clear_cfqq_prio_changed(cfqq); 2904 cfq_clear_cfqq_prio_changed(cfqq);
2905} 2905}
2906 2906
2907static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic) 2907static void changed_ioprio(struct cfq_io_context *cic)
2908{ 2908{
2909 struct cfq_data *cfqd = cic_to_cfqd(cic); 2909 struct cfq_data *cfqd = cic_to_cfqd(cic);
2910 struct cfq_queue *cfqq; 2910 struct cfq_queue *cfqq;
@@ -2933,12 +2933,6 @@ static void changed_ioprio(struct io_context *ioc, struct cfq_io_context *cic)
2933 spin_unlock_irqrestore(cfqd->queue->queue_lock, flags); 2933 spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
2934} 2934}
2935 2935
2936static void cfq_ioc_set_ioprio(struct io_context *ioc)
2937{
2938 call_for_each_cic(ioc, changed_ioprio);
2939 ioc->ioprio_changed = 0;
2940}
2941
2942static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq, 2936static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
2943 pid_t pid, bool is_sync) 2937 pid_t pid, bool is_sync)
2944{ 2938{
@@ -2960,7 +2954,7 @@ static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
2960} 2954}
2961 2955
2962#ifdef CONFIG_CFQ_GROUP_IOSCHED 2956#ifdef CONFIG_CFQ_GROUP_IOSCHED
2963static void changed_cgroup(struct io_context *ioc, struct cfq_io_context *cic) 2957static void changed_cgroup(struct cfq_io_context *cic)
2964{ 2958{
2965 struct cfq_queue *sync_cfqq = cic_to_cfqq(cic, 1); 2959 struct cfq_queue *sync_cfqq = cic_to_cfqq(cic, 1);
2966 struct cfq_data *cfqd = cic_to_cfqd(cic); 2960 struct cfq_data *cfqd = cic_to_cfqd(cic);
@@ -2986,12 +2980,6 @@ static void changed_cgroup(struct io_context *ioc, struct cfq_io_context *cic)
2986 2980
2987 spin_unlock_irqrestore(q->queue_lock, flags); 2981 spin_unlock_irqrestore(q->queue_lock, flags);
2988} 2982}
2989
2990static void cfq_ioc_set_cgroup(struct io_context *ioc)
2991{
2992 call_for_each_cic(ioc, changed_cgroup);
2993 ioc->cgroup_changed = 0;
2994}
2995#endif /* CONFIG_CFQ_GROUP_IOSCHED */ 2983#endif /* CONFIG_CFQ_GROUP_IOSCHED */
2996 2984
2997static struct cfq_queue * 2985static struct cfq_queue *
@@ -3222,13 +3210,15 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
3222out: 3210out:
3223 get_io_context(ioc); 3211 get_io_context(ioc);
3224 3212
3225 if (unlikely(ioc->ioprio_changed)) 3213 if (unlikely(cic->changed)) {
3226 cfq_ioc_set_ioprio(ioc); 3214 if (test_and_clear_bit(CIC_IOPRIO_CHANGED, &cic->changed))
3227 3215 changed_ioprio(cic);
3228#ifdef CONFIG_CFQ_GROUP_IOSCHED 3216#ifdef CONFIG_CFQ_GROUP_IOSCHED
3229 if (unlikely(ioc->cgroup_changed)) 3217 if (test_and_clear_bit(CIC_CGROUP_CHANGED, &cic->changed))
3230 cfq_ioc_set_cgroup(ioc); 3218 changed_cgroup(cic);
3231#endif 3219#endif
3220 }
3221
3232 return cic; 3222 return cic;
3233err: 3223err:
3234 if (cic) 3224 if (cic)