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 */ 1086db1e29SJens Axboe 1186db1e29SJens Axboe #include "blk.h" 1286db1e29SJens Axboe 1386db1e29SJens Axboe /* 1486db1e29SJens Axboe * For io context allocations 1586db1e29SJens Axboe */ 1686db1e29SJens Axboe static struct kmem_cache *iocontext_cachep; 1786db1e29SJens Axboe 1886db1e29SJens Axboe static void cfq_dtor(struct io_context *ioc) 1986db1e29SJens Axboe { 20ffc4e759SJens Axboe if (!hlist_empty(&ioc->cic_list)) { 21ffc4e759SJens Axboe struct cfq_io_context *cic; 2286db1e29SJens Axboe 23ffc4e759SJens Axboe cic = list_entry(ioc->cic_list.first, struct cfq_io_context, 24ffc4e759SJens Axboe cic_list); 25ffc4e759SJens Axboe cic->dtor(ioc); 26ffc4e759SJens Axboe } 2786db1e29SJens Axboe } 2886db1e29SJens Axboe 2986db1e29SJens Axboe /* 3086db1e29SJens Axboe * IO Context helper functions. put_io_context() returns 1 if there are no 3186db1e29SJens Axboe * more users of this io context, 0 otherwise. 3286db1e29SJens Axboe */ 3386db1e29SJens Axboe int put_io_context(struct io_context *ioc) 3486db1e29SJens Axboe { 3586db1e29SJens Axboe if (ioc == NULL) 3686db1e29SJens Axboe return 1; 3786db1e29SJens Axboe 38d9c7d394SNikanth Karthikesan BUG_ON(atomic_long_read(&ioc->refcount) == 0); 3986db1e29SJens Axboe 40d9c7d394SNikanth Karthikesan if (atomic_long_dec_and_test(&ioc->refcount)) { 4186db1e29SJens Axboe rcu_read_lock(); 4286db1e29SJens Axboe cfq_dtor(ioc); 4307416d29SJens Axboe rcu_read_unlock(); 4486db1e29SJens Axboe 4586db1e29SJens Axboe kmem_cache_free(iocontext_cachep, ioc); 4686db1e29SJens Axboe return 1; 4786db1e29SJens Axboe } 4886db1e29SJens Axboe return 0; 4986db1e29SJens Axboe } 5086db1e29SJens Axboe EXPORT_SYMBOL(put_io_context); 5186db1e29SJens Axboe 5286db1e29SJens Axboe static void cfq_exit(struct io_context *ioc) 5386db1e29SJens Axboe { 5486db1e29SJens Axboe rcu_read_lock(); 5586db1e29SJens Axboe 56ffc4e759SJens Axboe if (!hlist_empty(&ioc->cic_list)) { 57ffc4e759SJens Axboe struct cfq_io_context *cic; 58ffc4e759SJens Axboe 59ffc4e759SJens Axboe cic = list_entry(ioc->cic_list.first, struct cfq_io_context, 60ffc4e759SJens Axboe cic_list); 61ffc4e759SJens Axboe cic->exit(ioc); 62ffc4e759SJens Axboe } 63ffc4e759SJens Axboe rcu_read_unlock(); 6486db1e29SJens Axboe } 6586db1e29SJens Axboe 6686db1e29SJens Axboe /* Called by the exitting task */ 67b69f2292SLouis Rilling void exit_io_context(struct task_struct *task) 6886db1e29SJens Axboe { 6986db1e29SJens Axboe struct io_context *ioc; 7086db1e29SJens Axboe 71b69f2292SLouis Rilling task_lock(task); 72b69f2292SLouis Rilling ioc = task->io_context; 73b69f2292SLouis Rilling task->io_context = NULL; 74b69f2292SLouis Rilling task_unlock(task); 7586db1e29SJens Axboe 7686db1e29SJens Axboe if (atomic_dec_and_test(&ioc->nr_tasks)) { 7786db1e29SJens Axboe cfq_exit(ioc); 7886db1e29SJens Axboe 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 15586db1e29SJens Axboe void copy_io_context(struct io_context **pdst, struct io_context **psrc) 15686db1e29SJens Axboe { 15786db1e29SJens Axboe struct io_context *src = *psrc; 15886db1e29SJens Axboe struct io_context *dst = *pdst; 15986db1e29SJens Axboe 16086db1e29SJens Axboe if (src) { 161d9c7d394SNikanth Karthikesan BUG_ON(atomic_long_read(&src->refcount) == 0); 162d9c7d394SNikanth Karthikesan atomic_long_inc(&src->refcount); 16386db1e29SJens Axboe put_io_context(dst); 16486db1e29SJens Axboe *pdst = src; 16586db1e29SJens Axboe } 16686db1e29SJens Axboe } 16786db1e29SJens Axboe EXPORT_SYMBOL(copy_io_context); 16886db1e29SJens Axboe 16913341598SAdrian Bunk static int __init blk_ioc_init(void) 17086db1e29SJens Axboe { 17186db1e29SJens Axboe iocontext_cachep = kmem_cache_create("blkdev_ioc", 17286db1e29SJens Axboe sizeof(struct io_context), 0, SLAB_PANIC, NULL); 17386db1e29SJens Axboe return 0; 17486db1e29SJens Axboe } 17586db1e29SJens Axboe subsys_initcall(blk_ioc_init); 176