Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 1 | #ifndef IOCONTEXT_H |
| 2 | #define IOCONTEXT_H |
| 3 | |
Jens Axboe | 4ac845a | 2008-01-24 08:44:49 +0100 | [diff] [blame] | 4 | #include <linux/radix-tree.h> |
Fabio Checconi | 34e6bbf | 2008-04-02 14:31:02 +0200 | [diff] [blame] | 5 | #include <linux/rcupdate.h> |
Tejun Heo | b2efa05 | 2011-12-14 00:33:39 +0100 | [diff] [blame] | 6 | #include <linux/workqueue.h> |
Jens Axboe | 4ac845a | 2008-01-24 08:44:49 +0100 | [diff] [blame] | 7 | |
Tejun Heo | dc86900 | 2011-12-14 00:33:38 +0100 | [diff] [blame] | 8 | enum { |
Tejun Heo | 621032a | 2012-02-15 09:45:53 +0100 | [diff] [blame] | 9 | ICQ_EXITED = 1 << 2, |
Tejun Heo | dc86900 | 2011-12-14 00:33:38 +0100 | [diff] [blame] | 10 | }; |
| 11 | |
Tejun Heo | f1f8cc9 | 2011-12-14 00:33:42 +0100 | [diff] [blame] | 12 | /* |
| 13 | * An io_cq (icq) is association between an io_context (ioc) and a |
| 14 | * request_queue (q). This is used by elevators which need to track |
| 15 | * information per ioc - q pair. |
| 16 | * |
| 17 | * Elevator can request use of icq by setting elevator_type->icq_size and |
| 18 | * ->icq_align. Both size and align must be larger than that of struct |
| 19 | * io_cq and elevator can use the tail area for private information. The |
| 20 | * recommended way to do this is defining a struct which contains io_cq as |
| 21 | * the first member followed by private members and using its size and |
| 22 | * align. For example, |
| 23 | * |
| 24 | * struct snail_io_cq { |
| 25 | * struct io_cq icq; |
| 26 | * int poke_snail; |
| 27 | * int feed_snail; |
| 28 | * }; |
| 29 | * |
| 30 | * struct elevator_type snail_elv_type { |
| 31 | * .ops = { ... }, |
| 32 | * .icq_size = sizeof(struct snail_io_cq), |
| 33 | * .icq_align = __alignof__(struct snail_io_cq), |
| 34 | * ... |
| 35 | * }; |
| 36 | * |
| 37 | * If icq_size is set, block core will manage icq's. All requests will |
| 38 | * have its ->elv.icq field set before elevator_ops->elevator_set_req_fn() |
| 39 | * is called and be holding a reference to the associated io_context. |
| 40 | * |
| 41 | * Whenever a new icq is created, elevator_ops->elevator_init_icq_fn() is |
| 42 | * called and, on destruction, ->elevator_exit_icq_fn(). Both functions |
| 43 | * are called with both the associated io_context and queue locks held. |
| 44 | * |
| 45 | * Elevator is allowed to lookup icq using ioc_lookup_icq() while holding |
| 46 | * queue lock but the returned icq is valid only until the queue lock is |
| 47 | * released. Elevators can not and should not try to create or destroy |
| 48 | * icq's. |
| 49 | * |
| 50 | * As icq's are linked from both ioc and q, the locking rules are a bit |
| 51 | * complex. |
| 52 | * |
| 53 | * - ioc lock nests inside q lock. |
| 54 | * |
| 55 | * - ioc->icq_list and icq->ioc_node are protected by ioc lock. |
| 56 | * q->icq_list and icq->q_node by q lock. |
| 57 | * |
| 58 | * - ioc->icq_tree and ioc->icq_hint are protected by ioc lock, while icq |
| 59 | * itself is protected by q lock. However, both the indexes and icq |
| 60 | * itself are also RCU managed and lookup can be performed holding only |
| 61 | * the q lock. |
| 62 | * |
| 63 | * - icq's are not reference counted. They are destroyed when either the |
| 64 | * ioc or q goes away. Each request with icq set holds an extra |
| 65 | * reference to ioc to ensure it stays until the request is completed. |
| 66 | * |
| 67 | * - Linking and unlinking icq's are performed while holding both ioc and q |
| 68 | * locks. Due to the lock ordering, q exit is simple but ioc exit |
| 69 | * requires reverse-order double lock dance. |
| 70 | */ |
Tejun Heo | c586980 | 2011-12-14 00:33:41 +0100 | [diff] [blame] | 71 | struct io_cq { |
| 72 | struct request_queue *q; |
| 73 | struct io_context *ioc; |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 74 | |
Tejun Heo | 7e5a879 | 2011-12-14 00:33:42 +0100 | [diff] [blame] | 75 | /* |
| 76 | * q_node and ioc_node link io_cq through icq_list of q and ioc |
| 77 | * respectively. Both fields are unused once ioc_exit_icq() is |
| 78 | * called and shared with __rcu_icq_cache and __rcu_head which are |
| 79 | * used for RCU free of io_cq. |
| 80 | */ |
| 81 | union { |
| 82 | struct list_head q_node; |
| 83 | struct kmem_cache *__rcu_icq_cache; |
| 84 | }; |
| 85 | union { |
| 86 | struct hlist_node ioc_node; |
| 87 | struct rcu_head __rcu_head; |
| 88 | }; |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 89 | |
Tejun Heo | d705ae6 | 2012-02-15 09:45:49 +0100 | [diff] [blame] | 90 | unsigned int flags; |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 91 | }; |
| 92 | |
| 93 | /* |
Jens Axboe | d38ecf9 | 2008-01-24 08:53:35 +0100 | [diff] [blame] | 94 | * I/O subsystem state of the associated processes. It is refcounted |
| 95 | * and kmalloc'ed. These could be shared between processes. |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 96 | */ |
| 97 | struct io_context { |
Nikanth Karthikesan | d9c7d39 | 2009-06-10 12:57:06 -0700 | [diff] [blame] | 98 | atomic_long_t refcount; |
Tejun Heo | f6e8d01 | 2012-03-05 13:15:26 -0800 | [diff] [blame] | 99 | atomic_t active_ref; |
Jens Axboe | d38ecf9 | 2008-01-24 08:53:35 +0100 | [diff] [blame] | 100 | atomic_t nr_tasks; |
| 101 | |
| 102 | /* all the fields below are protected by this lock */ |
| 103 | spinlock_t lock; |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 104 | |
| 105 | unsigned short ioprio; |
Vivek Goyal | 31e4c28 | 2009-12-03 12:59:42 -0500 | [diff] [blame] | 106 | |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 107 | /* |
| 108 | * For request batching |
| 109 | */ |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 110 | int nr_batch_requests; /* Number of requests left in the batch */ |
Richard Kennedy | 58c24a6 | 2010-02-26 14:00:43 +0100 | [diff] [blame] | 111 | unsigned long last_waited; /* Time last woken after wait for request */ |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 112 | |
Tejun Heo | c586980 | 2011-12-14 00:33:41 +0100 | [diff] [blame] | 113 | struct radix_tree_root icq_tree; |
| 114 | struct io_cq __rcu *icq_hint; |
| 115 | struct hlist_head icq_list; |
Tejun Heo | b2efa05 | 2011-12-14 00:33:39 +0100 | [diff] [blame] | 116 | |
| 117 | struct work_struct release_work; |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 118 | }; |
| 119 | |
Tejun Heo | f6e8d01 | 2012-03-05 13:15:26 -0800 | [diff] [blame] | 120 | /** |
| 121 | * get_io_context_active - get active reference on ioc |
| 122 | * @ioc: ioc of interest |
| 123 | * |
| 124 | * Only iocs with active reference can issue new IOs. This function |
| 125 | * acquires an active reference on @ioc. The caller must already have an |
| 126 | * active reference on @ioc. |
| 127 | */ |
| 128 | static inline void get_io_context_active(struct io_context *ioc) |
Jens Axboe | d38ecf9 | 2008-01-24 08:53:35 +0100 | [diff] [blame] | 129 | { |
Tejun Heo | 3d48749 | 2012-03-05 13:15:25 -0800 | [diff] [blame] | 130 | WARN_ON_ONCE(atomic_long_read(&ioc->refcount) <= 0); |
Tejun Heo | f6e8d01 | 2012-03-05 13:15:26 -0800 | [diff] [blame] | 131 | WARN_ON_ONCE(atomic_read(&ioc->active_ref) <= 0); |
Tejun Heo | 3d48749 | 2012-03-05 13:15:25 -0800 | [diff] [blame] | 132 | atomic_long_inc(&ioc->refcount); |
Tejun Heo | f6e8d01 | 2012-03-05 13:15:26 -0800 | [diff] [blame] | 133 | atomic_inc(&ioc->active_ref); |
| 134 | } |
| 135 | |
| 136 | static inline void ioc_task_link(struct io_context *ioc) |
| 137 | { |
| 138 | get_io_context_active(ioc); |
| 139 | |
| 140 | WARN_ON_ONCE(atomic_read(&ioc->nr_tasks) <= 0); |
Tejun Heo | 3d48749 | 2012-03-05 13:15:25 -0800 | [diff] [blame] | 141 | atomic_inc(&ioc->nr_tasks); |
Jens Axboe | d38ecf9 | 2008-01-24 08:53:35 +0100 | [diff] [blame] | 142 | } |
| 143 | |
Louis Rilling | b69f229 | 2009-12-04 14:52:42 +0100 | [diff] [blame] | 144 | struct task_struct; |
Jens Axboe | da9cbc8 | 2008-06-30 20:42:08 +0200 | [diff] [blame] | 145 | #ifdef CONFIG_BLOCK |
Tejun Heo | 11a3122 | 2012-02-07 07:51:30 +0100 | [diff] [blame] | 146 | void put_io_context(struct io_context *ioc); |
Tejun Heo | f6e8d01 | 2012-03-05 13:15:26 -0800 | [diff] [blame] | 147 | void put_io_context_active(struct io_context *ioc); |
Louis Rilling | b69f229 | 2009-12-04 14:52:42 +0100 | [diff] [blame] | 148 | void exit_io_context(struct task_struct *task); |
Tejun Heo | 6e736be | 2011-12-14 00:33:38 +0100 | [diff] [blame] | 149 | struct io_context *get_task_io_context(struct task_struct *task, |
| 150 | gfp_t gfp_flags, int node); |
Jens Axboe | da9cbc8 | 2008-06-30 20:42:08 +0200 | [diff] [blame] | 151 | #else |
Jens Axboe | da9cbc8 | 2008-06-30 20:42:08 +0200 | [diff] [blame] | 152 | struct io_context; |
Tejun Heo | 11a3122 | 2012-02-07 07:51:30 +0100 | [diff] [blame] | 153 | static inline void put_io_context(struct io_context *ioc) { } |
Tejun Heo | 42ec57a | 2011-12-14 00:33:37 +0100 | [diff] [blame] | 154 | static inline void exit_io_context(struct task_struct *task) { } |
Jens Axboe | da9cbc8 | 2008-06-30 20:42:08 +0200 | [diff] [blame] | 155 | #endif |
| 156 | |
Jens Axboe | fd0928d | 2008-01-24 08:52:45 +0100 | [diff] [blame] | 157 | #endif |