186db1e29SJens Axboe /* 286db1e29SJens Axboe * Functions related to io context handling 386db1e29SJens Axboe */ 486db1e29SJens Axboe #include <linux/kernel.h> 586db1e29SJens Axboe #include <linux/module.h> 686db1e29SJens Axboe #include <linux/init.h> 786db1e29SJens Axboe #include <linux/bio.h> 886db1e29SJens Axboe #include <linux/blkdev.h> 986db1e29SJens Axboe #include <linux/bootmem.h> /* for max_pfn/max_low_pfn */ 105a0e3ad6STejun Heo #include <linux/slab.h> 1186db1e29SJens Axboe 1286db1e29SJens Axboe #include "blk.h" 1386db1e29SJens Axboe 1486db1e29SJens Axboe /* 1586db1e29SJens Axboe * For io context allocations 1686db1e29SJens Axboe */ 1786db1e29SJens Axboe static struct kmem_cache *iocontext_cachep; 1886db1e29SJens Axboe 1986db1e29SJens Axboe static void cfq_dtor(struct io_context *ioc) 2086db1e29SJens Axboe { 21ffc4e759SJens Axboe if (!hlist_empty(&ioc->cic_list)) { 22ffc4e759SJens Axboe struct cfq_io_context *cic; 2386db1e29SJens Axboe 24ffc4e759SJens Axboe cic = list_entry(ioc->cic_list.first, struct cfq_io_context, 25ffc4e759SJens Axboe cic_list); 26ffc4e759SJens Axboe cic->dtor(ioc); 27ffc4e759SJens Axboe } 2886db1e29SJens Axboe } 2986db1e29SJens Axboe 3086db1e29SJens Axboe /* 3186db1e29SJens Axboe * IO Context helper functions. put_io_context() returns 1 if there are no 3286db1e29SJens Axboe * more users of this io context, 0 otherwise. 3386db1e29SJens Axboe */ 3486db1e29SJens Axboe int put_io_context(struct io_context *ioc) 3586db1e29SJens Axboe { 3686db1e29SJens Axboe if (ioc == NULL) 3786db1e29SJens Axboe return 1; 3886db1e29SJens Axboe 39d9c7d394SNikanth Karthikesan BUG_ON(atomic_long_read(&ioc->refcount) == 0); 4086db1e29SJens Axboe 41d9c7d394SNikanth Karthikesan if (atomic_long_dec_and_test(&ioc->refcount)) { 4286db1e29SJens Axboe rcu_read_lock(); 4386db1e29SJens Axboe cfq_dtor(ioc); 4407416d29SJens Axboe rcu_read_unlock(); 4586db1e29SJens Axboe 4686db1e29SJens Axboe kmem_cache_free(iocontext_cachep, ioc); 4786db1e29SJens Axboe return 1; 4886db1e29SJens Axboe } 4986db1e29SJens Axboe return 0; 5086db1e29SJens Axboe } 5186db1e29SJens Axboe EXPORT_SYMBOL(put_io_context); 5286db1e29SJens Axboe 5386db1e29SJens Axboe static void cfq_exit(struct io_context *ioc) 5486db1e29SJens Axboe { 5586db1e29SJens Axboe rcu_read_lock(); 5686db1e29SJens Axboe 57ffc4e759SJens Axboe if (!hlist_empty(&ioc->cic_list)) { 58ffc4e759SJens Axboe struct cfq_io_context *cic; 59ffc4e759SJens Axboe 60ffc4e759SJens Axboe cic = list_entry(ioc->cic_list.first, struct cfq_io_context, 61ffc4e759SJens Axboe cic_list); 62ffc4e759SJens Axboe cic->exit(ioc); 63ffc4e759SJens Axboe } 64ffc4e759SJens Axboe rcu_read_unlock(); 6586db1e29SJens Axboe } 6686db1e29SJens Axboe 6727667c99SBart Van Assche /* Called by the exiting task */ 68b69f2292SLouis Rilling void exit_io_context(struct task_struct *task) 6986db1e29SJens Axboe { 7086db1e29SJens Axboe struct io_context *ioc; 7186db1e29SJens Axboe 72b69f2292SLouis Rilling task_lock(task); 73b69f2292SLouis Rilling ioc = task->io_context; 74b69f2292SLouis Rilling task->io_context = NULL; 75b69f2292SLouis Rilling task_unlock(task); 7686db1e29SJens Axboe 7727667c99SBart Van Assche if (atomic_dec_and_test(&ioc->nr_tasks)) 7886db1e29SJens Axboe cfq_exit(ioc); 7986db1e29SJens Axboe 8061cc74fbSLouis Rilling put_io_context(ioc); 8186db1e29SJens Axboe } 8286db1e29SJens Axboe 8386db1e29SJens Axboe struct io_context *alloc_io_context(gfp_t gfp_flags, int node) 8486db1e29SJens Axboe { 8586db1e29SJens Axboe struct io_context *ret; 8686db1e29SJens Axboe 8786db1e29SJens Axboe ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node); 8886db1e29SJens Axboe if (ret) { 89d9c7d394SNikanth Karthikesan atomic_long_set(&ret->refcount, 1); 9086db1e29SJens Axboe atomic_set(&ret->nr_tasks, 1); 9186db1e29SJens Axboe spin_lock_init(&ret->lock); 9286db1e29SJens Axboe ret->ioprio_changed = 0; 9386db1e29SJens Axboe ret->ioprio = 0; 944671a132SRichard Kennedy ret->last_waited = 0; /* doesn't matter... */ 9586db1e29SJens Axboe ret->nr_batch_requests = 0; /* because this is 0 */ 9686db1e29SJens Axboe INIT_RADIX_TREE(&ret->radix_root, GFP_ATOMIC | __GFP_HIGH); 97ffc4e759SJens Axboe INIT_HLIST_HEAD(&ret->cic_list); 9886db1e29SJens Axboe ret->ioc_data = NULL; 9986db1e29SJens Axboe } 10086db1e29SJens Axboe 10186db1e29SJens Axboe return ret; 10286db1e29SJens Axboe } 10386db1e29SJens Axboe 10486db1e29SJens Axboe /* 10586db1e29SJens Axboe * If the current task has no IO context then create one and initialise it. 10686db1e29SJens Axboe * Otherwise, return its existing IO context. 10786db1e29SJens Axboe * 10886db1e29SJens Axboe * This returned IO context doesn't have a specifically elevated refcount, 10986db1e29SJens Axboe * but since the current task itself holds a reference, the context can be 11086db1e29SJens Axboe * used in general code, so long as it stays within `current` context. 11186db1e29SJens Axboe */ 11286db1e29SJens Axboe struct io_context *current_io_context(gfp_t gfp_flags, int node) 11386db1e29SJens Axboe { 11486db1e29SJens Axboe struct task_struct *tsk = current; 11586db1e29SJens Axboe struct io_context *ret; 11686db1e29SJens Axboe 11786db1e29SJens Axboe ret = tsk->io_context; 11886db1e29SJens Axboe if (likely(ret)) 11986db1e29SJens Axboe return ret; 12086db1e29SJens Axboe 12186db1e29SJens Axboe ret = alloc_io_context(gfp_flags, node); 12286db1e29SJens Axboe if (ret) { 12386db1e29SJens Axboe /* make sure set_task_ioprio() sees the settings above */ 12486db1e29SJens Axboe smp_wmb(); 12586db1e29SJens Axboe tsk->io_context = ret; 12686db1e29SJens Axboe } 12786db1e29SJens Axboe 12886db1e29SJens Axboe return ret; 12986db1e29SJens Axboe } 13086db1e29SJens Axboe 13186db1e29SJens Axboe /* 13286db1e29SJens Axboe * If the current task has no IO context then create one and initialise it. 13386db1e29SJens Axboe * If it does have a context, take a ref on it. 13486db1e29SJens Axboe * 13586db1e29SJens Axboe * This is always called in the context of the task which submitted the I/O. 13686db1e29SJens Axboe */ 13786db1e29SJens Axboe struct io_context *get_io_context(gfp_t gfp_flags, int node) 13886db1e29SJens Axboe { 13986db1e29SJens Axboe struct io_context *ret = NULL; 14086db1e29SJens Axboe 14186db1e29SJens Axboe /* 14286db1e29SJens Axboe * Check for unlikely race with exiting task. ioc ref count is 14386db1e29SJens Axboe * zero when ioc is being detached. 14486db1e29SJens Axboe */ 14586db1e29SJens Axboe do { 14686db1e29SJens Axboe ret = current_io_context(gfp_flags, node); 14786db1e29SJens Axboe if (unlikely(!ret)) 14886db1e29SJens Axboe break; 149d9c7d394SNikanth Karthikesan } while (!atomic_long_inc_not_zero(&ret->refcount)); 15086db1e29SJens Axboe 15186db1e29SJens Axboe return ret; 15286db1e29SJens Axboe } 15386db1e29SJens Axboe EXPORT_SYMBOL(get_io_context); 15486db1e29SJens Axboe 15513341598SAdrian Bunk static int __init blk_ioc_init(void) 15686db1e29SJens Axboe { 15786db1e29SJens Axboe iocontext_cachep = kmem_cache_create("blkdev_ioc", 15886db1e29SJens Axboe sizeof(struct io_context), 0, SLAB_PANIC, NULL); 15986db1e29SJens Axboe return 0; 16086db1e29SJens Axboe } 16186db1e29SJens Axboe subsys_initcall(blk_ioc_init); 162