diff options
author | Tejun Heo <tj@kernel.org> | 2011-12-13 18:33:38 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2011-12-13 18:33:38 -0500 |
commit | dc86900e0a8f665122de6faadd27fb4c6d2b3e4d (patch) | |
tree | ec24aa4b076f54fcfb0558d5113f5c5e0f4bc173 /block/blk-ioc.c | |
parent | 283287a52e3c3f7f8f9da747f4b8c5202740d776 (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/blk-ioc.c')
-rw-r--r-- | block/blk-ioc.c | 45 |
1 files changed, 45 insertions, 0 deletions
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 | } |
189 | EXPORT_SYMBOL(get_task_io_context); | 189 | EXPORT_SYMBOL(get_task_io_context); |
190 | 190 | ||
191 | void 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 | */ | ||
209 | void 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 | */ | ||
227 | void 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 | |||
191 | static int __init blk_ioc_init(void) | 236 | static int __init blk_ioc_init(void) |
192 | { | 237 | { |
193 | iocontext_cachep = kmem_cache_create("blkdev_ioc", | 238 | iocontext_cachep = kmem_cache_create("blkdev_ioc", |