aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
Diffstat (limited to 'block')
-rw-r--r--block/blk-core.c25
-rw-r--r--block/blk-ioc.c62
-rw-r--r--block/blk.h36
-rw-r--r--block/cfq-iosched.c2
4 files changed, 71 insertions, 54 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index fd4749391e17..6804fdf27eff 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -771,9 +771,12 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
771{ 771{
772 struct request *rq = NULL; 772 struct request *rq = NULL;
773 struct request_list *rl = &q->rq; 773 struct request_list *rl = &q->rq;
774 struct io_context *ioc = NULL; 774 struct io_context *ioc;
775 const bool is_sync = rw_is_sync(rw_flags) != 0; 775 const bool is_sync = rw_is_sync(rw_flags) != 0;
776 bool retried = false;
776 int may_queue; 777 int may_queue;
778retry:
779 ioc = current->io_context;
777 780
778 if (unlikely(blk_queue_dead(q))) 781 if (unlikely(blk_queue_dead(q)))
779 return NULL; 782 return NULL;
@@ -784,7 +787,20 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
784 787
785 if (rl->count[is_sync]+1 >= queue_congestion_on_threshold(q)) { 788 if (rl->count[is_sync]+1 >= queue_congestion_on_threshold(q)) {
786 if (rl->count[is_sync]+1 >= q->nr_requests) { 789 if (rl->count[is_sync]+1 >= q->nr_requests) {
787 ioc = current_io_context(GFP_ATOMIC, q->node); 790 /*
791 * We want ioc to record batching state. If it's
792 * not already there, creating a new one requires
793 * dropping queue_lock, which in turn requires
794 * retesting conditions to avoid queue hang.
795 */
796 if (!ioc && !retried) {
797 spin_unlock_irq(q->queue_lock);
798 create_io_context(current, gfp_mask, q->node);
799 spin_lock_irq(q->queue_lock);
800 retried = true;
801 goto retry;
802 }
803
788 /* 804 /*
789 * The queue will fill after this allocation, so set 805 * The queue will fill after this allocation, so set
790 * it as full, and mark this process as "batching". 806 * it as full, and mark this process as "batching".
@@ -892,7 +908,6 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags,
892 rq = get_request(q, rw_flags, bio, GFP_NOIO); 908 rq = get_request(q, rw_flags, bio, GFP_NOIO);
893 while (!rq) { 909 while (!rq) {
894 DEFINE_WAIT(wait); 910 DEFINE_WAIT(wait);
895 struct io_context *ioc;
896 struct request_list *rl = &q->rq; 911 struct request_list *rl = &q->rq;
897 912
898 if (unlikely(blk_queue_dead(q))) 913 if (unlikely(blk_queue_dead(q)))
@@ -912,8 +927,8 @@ static struct request *get_request_wait(struct request_queue *q, int rw_flags,
912 * up to a big batch of them for a small period time. 927 * up to a big batch of them for a small period time.
913 * See ioc_batching, ioc_set_batching 928 * See ioc_batching, ioc_set_batching
914 */ 929 */
915 ioc = current_io_context(GFP_NOIO, q->node); 930 create_io_context(current, GFP_NOIO, q->node);
916 ioc_set_batching(q, ioc); 931 ioc_set_batching(q, current->io_context);
917 932
918 spin_lock_irq(q->queue_lock); 933 spin_lock_irq(q->queue_lock);
919 finish_wait(&rl->wait[is_sync], &wait); 934 finish_wait(&rl->wait[is_sync], &wait);
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index fb23965595da..e23c797b4685 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -205,16 +205,15 @@ void exit_io_context(struct task_struct *task)
205 put_io_context(ioc, NULL); 205 put_io_context(ioc, NULL);
206} 206}
207 207
208static struct io_context *create_task_io_context(struct task_struct *task, 208void create_io_context_slowpath(struct task_struct *task, gfp_t gfp_flags,
209 gfp_t gfp_flags, int node, 209 int node)
210 bool take_ref)
211{ 210{
212 struct io_context *ioc; 211 struct io_context *ioc;
213 212
214 ioc = kmem_cache_alloc_node(iocontext_cachep, gfp_flags | __GFP_ZERO, 213 ioc = kmem_cache_alloc_node(iocontext_cachep, gfp_flags | __GFP_ZERO,
215 node); 214 node);
216 if (unlikely(!ioc)) 215 if (unlikely(!ioc))
217 return NULL; 216 return;
218 217
219 /* initialize */ 218 /* initialize */
220 atomic_long_set(&ioc->refcount, 1); 219 atomic_long_set(&ioc->refcount, 1);
@@ -226,42 +225,13 @@ static struct io_context *create_task_io_context(struct task_struct *task,
226 225
227 /* try to install, somebody might already have beaten us to it */ 226 /* try to install, somebody might already have beaten us to it */
228 task_lock(task); 227 task_lock(task);
229 228 if (!task->io_context && !(task->flags & PF_EXITING))
230 if (!task->io_context && !(task->flags & PF_EXITING)) {
231 task->io_context = ioc; 229 task->io_context = ioc;
232 } else { 230 else
233 kmem_cache_free(iocontext_cachep, ioc); 231 kmem_cache_free(iocontext_cachep, ioc);
234 ioc = task->io_context;
235 }
236
237 if (ioc && take_ref)
238 get_io_context(ioc);
239
240 task_unlock(task); 232 task_unlock(task);
241 return ioc;
242} 233}
243 234EXPORT_SYMBOL(create_io_context_slowpath);
244/**
245 * current_io_context - get io_context of %current
246 * @gfp_flags: allocation flags, used if allocation is necessary
247 * @node: allocation node, used if allocation is necessary
248 *
249 * Return io_context of %current. If it doesn't exist, it is created with
250 * @gfp_flags and @node. The returned io_context does NOT have its
251 * reference count incremented. Because io_context is exited only on task
252 * exit, %current can be sure that the returned io_context is valid and
253 * alive as long as it is executing.
254 */
255struct io_context *current_io_context(gfp_t gfp_flags, int node)
256{
257 might_sleep_if(gfp_flags & __GFP_WAIT);
258
259 if (current->io_context)
260 return current->io_context;
261
262 return create_task_io_context(current, gfp_flags, node, false);
263}
264EXPORT_SYMBOL(current_io_context);
265 235
266/** 236/**
267 * get_task_io_context - get io_context of a task 237 * get_task_io_context - get io_context of a task
@@ -274,7 +244,7 @@ EXPORT_SYMBOL(current_io_context);
274 * incremented. 244 * incremented.
275 * 245 *
276 * This function always goes through task_lock() and it's better to use 246 * This function always goes through task_lock() and it's better to use
277 * current_io_context() + get_io_context() for %current. 247 * %current->io_context + get_io_context() for %current.
278 */ 248 */
279struct io_context *get_task_io_context(struct task_struct *task, 249struct io_context *get_task_io_context(struct task_struct *task,
280 gfp_t gfp_flags, int node) 250 gfp_t gfp_flags, int node)
@@ -283,16 +253,18 @@ struct io_context *get_task_io_context(struct task_struct *task,
283 253
284 might_sleep_if(gfp_flags & __GFP_WAIT); 254 might_sleep_if(gfp_flags & __GFP_WAIT);
285 255
286 task_lock(task); 256 do {
287 ioc = task->io_context; 257 task_lock(task);
288 if (likely(ioc)) { 258 ioc = task->io_context;
289 get_io_context(ioc); 259 if (likely(ioc)) {
260 get_io_context(ioc);
261 task_unlock(task);
262 return ioc;
263 }
290 task_unlock(task); 264 task_unlock(task);
291 return ioc; 265 } while (create_io_context(task, gfp_flags, node));
292 }
293 task_unlock(task);
294 266
295 return create_task_io_context(task, gfp_flags, node, true); 267 return NULL;
296} 268}
297EXPORT_SYMBOL(get_task_io_context); 269EXPORT_SYMBOL(get_task_io_context);
298 270
diff --git a/block/blk.h b/block/blk.h
index 8d421156fefb..5bca2668e1bf 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -127,9 +127,6 @@ static inline int blk_should_fake_timeout(struct request_queue *q)
127} 127}
128#endif 128#endif
129 129
130void get_io_context(struct io_context *ioc);
131struct io_context *current_io_context(gfp_t gfp_flags, int node);
132
133int ll_back_merge_fn(struct request_queue *q, struct request *req, 130int ll_back_merge_fn(struct request_queue *q, struct request *req,
134 struct bio *bio); 131 struct bio *bio);
135int ll_front_merge_fn(struct request_queue *q, struct request *req, 132int ll_front_merge_fn(struct request_queue *q, struct request *req,
@@ -198,6 +195,39 @@ static inline int blk_do_io_stat(struct request *rq)
198 (rq->cmd_flags & REQ_DISCARD)); 195 (rq->cmd_flags & REQ_DISCARD));
199} 196}
200 197
198/*
199 * Internal io_context interface
200 */
201void get_io_context(struct io_context *ioc);
202
203void create_io_context_slowpath(struct task_struct *task, gfp_t gfp_mask,
204 int node);
205
206/**
207 * create_io_context - try to create task->io_context
208 * @task: target task
209 * @gfp_mask: allocation mask
210 * @node: allocation node
211 *
212 * If @task->io_context is %NULL, allocate a new io_context and install it.
213 * Returns the current @task->io_context which may be %NULL if allocation
214 * failed.
215 *
216 * Note that this function can't be called with IRQ disabled because
217 * task_lock which protects @task->io_context is IRQ-unsafe.
218 */
219static inline struct io_context *create_io_context(struct task_struct *task,
220 gfp_t gfp_mask, int node)
221{
222 WARN_ON_ONCE(irqs_disabled());
223 if (unlikely(!task->io_context))
224 create_io_context_slowpath(task, gfp_mask, node);
225 return task->io_context;
226}
227
228/*
229 * Internal throttling interface
230 */
201#ifdef CONFIG_BLK_DEV_THROTTLING 231#ifdef CONFIG_BLK_DEV_THROTTLING
202extern bool blk_throtl_bio(struct request_queue *q, struct bio *bio); 232extern bool blk_throtl_bio(struct request_queue *q, struct bio *bio);
203extern void blk_throtl_drain(struct request_queue *q); 233extern void blk_throtl_drain(struct request_queue *q);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 3b07ce168780..5f7e4d161404 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -3012,7 +3012,7 @@ static int cfq_create_cic(struct cfq_data *cfqd, gfp_t gfp_mask)
3012 might_sleep_if(gfp_mask & __GFP_WAIT); 3012 might_sleep_if(gfp_mask & __GFP_WAIT);
3013 3013
3014 /* allocate stuff */ 3014 /* allocate stuff */
3015 ioc = current_io_context(gfp_mask, q->node); 3015 ioc = create_io_context(current, gfp_mask, q->node);
3016 if (!ioc) 3016 if (!ioc)
3017 goto out; 3017 goto out;
3018 3018