aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/ll_rw_blk.c56
-rw-r--r--include/linux/blkdev.h1
2 files changed, 26 insertions, 31 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 5caebe2cf0a1..1197462bb6ba 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -1876,7 +1876,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
1876{ 1876{
1877 struct request *rq = NULL; 1877 struct request *rq = NULL;
1878 struct request_list *rl = &q->rq; 1878 struct request_list *rl = &q->rq;
1879 struct io_context *ioc = get_io_context(GFP_ATOMIC); 1879 struct io_context *ioc = current_io_context(GFP_ATOMIC);
1880 1880
1881 if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) 1881 if (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)))
1882 goto out; 1882 goto out;
@@ -1959,7 +1959,6 @@ rq_starved:
1959 rq_init(q, rq); 1959 rq_init(q, rq);
1960 rq->rl = rl; 1960 rq->rl = rl;
1961out: 1961out:
1962 put_io_context(ioc);
1963 return rq; 1962 return rq;
1964} 1963}
1965 1964
@@ -1997,9 +1996,8 @@ static struct request *get_request_wait(request_queue_t *q, int rw,
1997 * up to a big batch of them for a small period time. 1996 * up to a big batch of them for a small period time.
1998 * See ioc_batching, ioc_set_batching 1997 * See ioc_batching, ioc_set_batching
1999 */ 1998 */
2000 ioc = get_io_context(GFP_NOIO); 1999 ioc = current_io_context(GFP_NOIO);
2001 ioc_set_batching(q, ioc); 2000 ioc_set_batching(q, ioc);
2002 put_io_context(ioc);
2003 2001
2004 spin_lock_irq(q->queue_lock); 2002 spin_lock_irq(q->queue_lock);
2005 } 2003 }
@@ -3282,24 +3280,20 @@ void exit_io_context(void)
3282 3280
3283/* 3281/*
3284 * If the current task has no IO context then create one and initialise it. 3282 * If the current task has no IO context then create one and initialise it.
3285 * If it does have a context, take a ref on it. 3283 * Otherwise, return its existing IO context.
3286 * 3284 *
3287 * This is always called in the context of the task which submitted the I/O. 3285 * This returned IO context doesn't have a specifically elevated refcount,
3288 * But weird things happen, so we disable local interrupts to ensure exclusive 3286 * but since the current task itself holds a reference, the context can be
3289 * access to *current. 3287 * used in general code, so long as it stays within `current` context.
3290 */ 3288 */
3291struct io_context *get_io_context(int gfp_flags) 3289struct io_context *current_io_context(int gfp_flags)
3292{ 3290{
3293 struct task_struct *tsk = current; 3291 struct task_struct *tsk = current;
3294 unsigned long flags;
3295 struct io_context *ret; 3292 struct io_context *ret;
3296 3293
3297 local_irq_save(flags);
3298 ret = tsk->io_context; 3294 ret = tsk->io_context;
3299 if (ret) 3295 if (likely(ret))
3300 goto out; 3296 return ret;
3301
3302 local_irq_restore(flags);
3303 3297
3304 ret = kmem_cache_alloc(iocontext_cachep, gfp_flags); 3298 ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
3305 if (ret) { 3299 if (ret) {
@@ -3310,25 +3304,25 @@ struct io_context *get_io_context(int gfp_flags)
3310 ret->nr_batch_requests = 0; /* because this is 0 */ 3304 ret->nr_batch_requests = 0; /* because this is 0 */
3311 ret->aic = NULL; 3305 ret->aic = NULL;
3312 ret->cic = NULL; 3306 ret->cic = NULL;
3307 tsk->io_context = ret;
3308 }
3313 3309
3314 local_irq_save(flags); 3310 return ret;
3315 3311}
3316 /* 3312EXPORT_SYMBOL(current_io_context);
3317 * very unlikely, someone raced with us in setting up the task
3318 * io context. free new context and just grab a reference.
3319 */
3320 if (!tsk->io_context)
3321 tsk->io_context = ret;
3322 else {
3323 kmem_cache_free(iocontext_cachep, ret);
3324 ret = tsk->io_context;
3325 }
3326 3313
3327out: 3314/*
3315 * If the current task has no IO context then create one and initialise it.
3316 * If it does have a context, take a ref on it.
3317 *
3318 * This is always called in the context of the task which submitted the I/O.
3319 */
3320struct io_context *get_io_context(int gfp_flags)
3321{
3322 struct io_context *ret;
3323 ret = current_io_context(gfp_flags);
3324 if (likely(ret))
3328 atomic_inc(&ret->refcount); 3325 atomic_inc(&ret->refcount);
3329 local_irq_restore(flags);
3330 }
3331
3332 return ret; 3326 return ret;
3333} 3327}
3334EXPORT_SYMBOL(get_io_context); 3328EXPORT_SYMBOL(get_io_context);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 21a8674cd149..0881b5cdee3d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -96,6 +96,7 @@ struct io_context {
96 96
97void put_io_context(struct io_context *ioc); 97void put_io_context(struct io_context *ioc);
98void exit_io_context(void); 98void exit_io_context(void);
99struct io_context *current_io_context(int gfp_flags);
99struct io_context *get_io_context(int gfp_flags); 100struct io_context *get_io_context(int gfp_flags);
100void copy_io_context(struct io_context **pdst, struct io_context **psrc); 101void copy_io_context(struct io_context **pdst, struct io_context **psrc);
101void swap_io_context(struct io_context **ioc1, struct io_context **ioc2); 102void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);