aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2014-09-25 11:23:43 -0400
committerJens Axboe <axboe@fb.com>2014-09-25 17:22:40 -0400
commit7c94e1c157a227837b04f02f5edeff8301410ba2 (patch)
tree3b592095b0204ebad61dd22b77aa1e72595dbc3a /block
parent7ddab5de5b80d3111f9e6765714e728b2c4f1c07 (diff)
block: introduce blk_flush_queue to drive flush machinery
This patch introduces 'struct blk_flush_queue' and puts all flush machinery related fields into this structure, so that - flush implementation details aren't exposed to driver - it is easy to convert to per dispatch-queue flush machinery This patch is basically a mechanical replacement. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ming Lei <ming.lei@canonical.com> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-core.c4
-rw-r--r--block/blk-flush.c109
-rw-r--r--block/blk-mq.c10
-rw-r--r--block/blk.h22
4 files changed, 97 insertions, 48 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 222fe84d6ac4..cfaca8ca6cc4 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -390,11 +390,13 @@ static void __blk_drain_queue(struct request_queue *q, bool drain_all)
390 * be drained. Check all the queues and counters. 390 * be drained. Check all the queues and counters.
391 */ 391 */
392 if (drain_all) { 392 if (drain_all) {
393 struct blk_flush_queue *fq = blk_get_flush_queue(q);
393 drain |= !list_empty(&q->queue_head); 394 drain |= !list_empty(&q->queue_head);
394 for (i = 0; i < 2; i++) { 395 for (i = 0; i < 2; i++) {
395 drain |= q->nr_rqs[i]; 396 drain |= q->nr_rqs[i];
396 drain |= q->in_flight[i]; 397 drain |= q->in_flight[i];
397 drain |= !list_empty(&q->flush_queue[i]); 398 if (fq)
399 drain |= !list_empty(&fq->flush_queue[i]);
398 } 400 }
399 } 401 }
400 402
diff --git a/block/blk-flush.c b/block/blk-flush.c
index caf44756d329..b01a86d6bf86 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -28,7 +28,7 @@
28 * 28 *
29 * The actual execution of flush is double buffered. Whenever a request 29 * The actual execution of flush is double buffered. Whenever a request
30 * needs to execute PRE or POSTFLUSH, it queues at 30 * needs to execute PRE or POSTFLUSH, it queues at
31 * q->flush_queue[q->flush_pending_idx]. Once certain criteria are met, a 31 * fq->flush_queue[fq->flush_pending_idx]. Once certain criteria are met, a
32 * flush is issued and the pending_idx is toggled. When the flush 32 * flush is issued and the pending_idx is toggled. When the flush
33 * completes, all the requests which were pending are proceeded to the next 33 * completes, all the requests which were pending are proceeded to the next
34 * step. This allows arbitrary merging of different types of FLUSH/FUA 34 * step. This allows arbitrary merging of different types of FLUSH/FUA
@@ -155,7 +155,7 @@ static bool blk_flush_queue_rq(struct request *rq, bool add_front)
155 * completion and trigger the next step. 155 * completion and trigger the next step.
156 * 156 *
157 * CONTEXT: 157 * CONTEXT:
158 * spin_lock_irq(q->queue_lock or q->mq_flush_lock) 158 * spin_lock_irq(q->queue_lock or fq->mq_flush_lock)
159 * 159 *
160 * RETURNS: 160 * RETURNS:
161 * %true if requests were added to the dispatch queue, %false otherwise. 161 * %true if requests were added to the dispatch queue, %false otherwise.
@@ -164,7 +164,8 @@ static bool blk_flush_complete_seq(struct request *rq, unsigned int seq,
164 int error) 164 int error)
165{ 165{
166 struct request_queue *q = rq->q; 166 struct request_queue *q = rq->q;
167 struct list_head *pending = &q->flush_queue[q->flush_pending_idx]; 167 struct blk_flush_queue *fq = blk_get_flush_queue(q);
168 struct list_head *pending = &fq->flush_queue[fq->flush_pending_idx];
168 bool queued = false, kicked; 169 bool queued = false, kicked;
169 170
170 BUG_ON(rq->flush.seq & seq); 171 BUG_ON(rq->flush.seq & seq);
@@ -180,12 +181,12 @@ static bool blk_flush_complete_seq(struct request *rq, unsigned int seq,
180 case REQ_FSEQ_POSTFLUSH: 181 case REQ_FSEQ_POSTFLUSH:
181 /* queue for flush */ 182 /* queue for flush */
182 if (list_empty(pending)) 183 if (list_empty(pending))
183 q->flush_pending_since = jiffies; 184 fq->flush_pending_since = jiffies;
184 list_move_tail(&rq->flush.list, pending); 185 list_move_tail(&rq->flush.list, pending);
185 break; 186 break;
186 187
187 case REQ_FSEQ_DATA: 188 case REQ_FSEQ_DATA:
188 list_move_tail(&rq->flush.list, &q->flush_data_in_flight); 189 list_move_tail(&rq->flush.list, &fq->flush_data_in_flight);
189 queued = blk_flush_queue_rq(rq, true); 190 queued = blk_flush_queue_rq(rq, true);
190 break; 191 break;
191 192
@@ -220,17 +221,18 @@ static void flush_end_io(struct request *flush_rq, int error)
220 bool queued = false; 221 bool queued = false;
221 struct request *rq, *n; 222 struct request *rq, *n;
222 unsigned long flags = 0; 223 unsigned long flags = 0;
224 struct blk_flush_queue *fq = blk_get_flush_queue(q);
223 225
224 if (q->mq_ops) { 226 if (q->mq_ops) {
225 spin_lock_irqsave(&q->mq_flush_lock, flags); 227 spin_lock_irqsave(&fq->mq_flush_lock, flags);
226 flush_rq->tag = -1; 228 flush_rq->tag = -1;
227 } 229 }
228 230
229 running = &q->flush_queue[q->flush_running_idx]; 231 running = &fq->flush_queue[fq->flush_running_idx];
230 BUG_ON(q->flush_pending_idx == q->flush_running_idx); 232 BUG_ON(fq->flush_pending_idx == fq->flush_running_idx);
231 233
232 /* account completion of the flush request */ 234 /* account completion of the flush request */
233 q->flush_running_idx ^= 1; 235 fq->flush_running_idx ^= 1;
234 236
235 if (!q->mq_ops) 237 if (!q->mq_ops)
236 elv_completed_request(q, flush_rq); 238 elv_completed_request(q, flush_rq);
@@ -254,13 +256,13 @@ static void flush_end_io(struct request *flush_rq, int error)
254 * directly into request_fn may confuse the driver. Always use 256 * directly into request_fn may confuse the driver. Always use
255 * kblockd. 257 * kblockd.
256 */ 258 */
257 if (queued || q->flush_queue_delayed) { 259 if (queued || fq->flush_queue_delayed) {
258 WARN_ON(q->mq_ops); 260 WARN_ON(q->mq_ops);
259 blk_run_queue_async(q); 261 blk_run_queue_async(q);
260 } 262 }
261 q->flush_queue_delayed = 0; 263 fq->flush_queue_delayed = 0;
262 if (q->mq_ops) 264 if (q->mq_ops)
263 spin_unlock_irqrestore(&q->mq_flush_lock, flags); 265 spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
264} 266}
265 267
266/** 268/**
@@ -271,33 +273,34 @@ static void flush_end_io(struct request *flush_rq, int error)
271 * Please read the comment at the top of this file for more info. 273 * Please read the comment at the top of this file for more info.
272 * 274 *
273 * CONTEXT: 275 * CONTEXT:
274 * spin_lock_irq(q->queue_lock or q->mq_flush_lock) 276 * spin_lock_irq(q->queue_lock or fq->mq_flush_lock)
275 * 277 *
276 * RETURNS: 278 * RETURNS:
277 * %true if flush was issued, %false otherwise. 279 * %true if flush was issued, %false otherwise.
278 */ 280 */
279static bool blk_kick_flush(struct request_queue *q) 281static bool blk_kick_flush(struct request_queue *q)
280{ 282{
281 struct list_head *pending = &q->flush_queue[q->flush_pending_idx]; 283 struct blk_flush_queue *fq = blk_get_flush_queue(q);
284 struct list_head *pending = &fq->flush_queue[fq->flush_pending_idx];
282 struct request *first_rq = 285 struct request *first_rq =
283 list_first_entry(pending, struct request, flush.list); 286 list_first_entry(pending, struct request, flush.list);
284 struct request *flush_rq = q->flush_rq; 287 struct request *flush_rq = fq->flush_rq;
285 288
286 /* C1 described at the top of this file */ 289 /* C1 described at the top of this file */
287 if (q->flush_pending_idx != q->flush_running_idx || list_empty(pending)) 290 if (fq->flush_pending_idx != fq->flush_running_idx || list_empty(pending))
288 return false; 291 return false;
289 292
290 /* C2 and C3 */ 293 /* C2 and C3 */
291 if (!list_empty(&q->flush_data_in_flight) && 294 if (!list_empty(&fq->flush_data_in_flight) &&
292 time_before(jiffies, 295 time_before(jiffies,
293 q->flush_pending_since + FLUSH_PENDING_TIMEOUT)) 296 fq->flush_pending_since + FLUSH_PENDING_TIMEOUT))
294 return false; 297 return false;
295 298
296 /* 299 /*
297 * Issue flush and toggle pending_idx. This makes pending_idx 300 * Issue flush and toggle pending_idx. This makes pending_idx
298 * different from running_idx, which means flush is in flight. 301 * different from running_idx, which means flush is in flight.
299 */ 302 */
300 q->flush_pending_idx ^= 1; 303 fq->flush_pending_idx ^= 1;
301 304
302 blk_rq_init(q, flush_rq); 305 blk_rq_init(q, flush_rq);
303 if (q->mq_ops) 306 if (q->mq_ops)
@@ -329,6 +332,7 @@ static void mq_flush_data_end_io(struct request *rq, int error)
329 struct blk_mq_hw_ctx *hctx; 332 struct blk_mq_hw_ctx *hctx;
330 struct blk_mq_ctx *ctx; 333 struct blk_mq_ctx *ctx;
331 unsigned long flags; 334 unsigned long flags;
335 struct blk_flush_queue *fq = blk_get_flush_queue(q);
332 336
333 ctx = rq->mq_ctx; 337 ctx = rq->mq_ctx;
334 hctx = q->mq_ops->map_queue(q, ctx->cpu); 338 hctx = q->mq_ops->map_queue(q, ctx->cpu);
@@ -337,10 +341,10 @@ static void mq_flush_data_end_io(struct request *rq, int error)
337 * After populating an empty queue, kick it to avoid stall. Read 341 * After populating an empty queue, kick it to avoid stall. Read
338 * the comment in flush_end_io(). 342 * the comment in flush_end_io().
339 */ 343 */
340 spin_lock_irqsave(&q->mq_flush_lock, flags); 344 spin_lock_irqsave(&fq->mq_flush_lock, flags);
341 if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error)) 345 if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error))
342 blk_mq_run_hw_queue(hctx, true); 346 blk_mq_run_hw_queue(hctx, true);
343 spin_unlock_irqrestore(&q->mq_flush_lock, flags); 347 spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
344} 348}
345 349
346/** 350/**
@@ -408,11 +412,13 @@ void blk_insert_flush(struct request *rq)
408 rq->cmd_flags |= REQ_FLUSH_SEQ; 412 rq->cmd_flags |= REQ_FLUSH_SEQ;
409 rq->flush.saved_end_io = rq->end_io; /* Usually NULL */ 413 rq->flush.saved_end_io = rq->end_io; /* Usually NULL */
410 if (q->mq_ops) { 414 if (q->mq_ops) {
415 struct blk_flush_queue *fq = blk_get_flush_queue(q);
416
411 rq->end_io = mq_flush_data_end_io; 417 rq->end_io = mq_flush_data_end_io;
412 418
413 spin_lock_irq(&q->mq_flush_lock); 419 spin_lock_irq(&fq->mq_flush_lock);
414 blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0); 420 blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0);
415 spin_unlock_irq(&q->mq_flush_lock); 421 spin_unlock_irq(&fq->mq_flush_lock);
416 return; 422 return;
417 } 423 }
418 rq->end_io = flush_data_end_io; 424 rq->end_io = flush_data_end_io;
@@ -473,31 +479,52 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
473} 479}
474EXPORT_SYMBOL(blkdev_issue_flush); 480EXPORT_SYMBOL(blkdev_issue_flush);
475 481
476static int blk_mq_init_flush(struct request_queue *q) 482static struct blk_flush_queue *blk_alloc_flush_queue(
483 struct request_queue *q)
477{ 484{
478 struct blk_mq_tag_set *set = q->tag_set; 485 struct blk_flush_queue *fq;
486 int rq_sz = sizeof(struct request);
479 487
480 spin_lock_init(&q->mq_flush_lock); 488 fq = kzalloc(sizeof(*fq), GFP_KERNEL);
489 if (!fq)
490 goto fail;
481 491
482 q->flush_rq = kzalloc(round_up(sizeof(struct request) + 492 if (q->mq_ops) {
483 set->cmd_size, cache_line_size()), 493 spin_lock_init(&fq->mq_flush_lock);
484 GFP_KERNEL); 494 rq_sz = round_up(rq_sz + q->tag_set->cmd_size,
485 if (!q->flush_rq) 495 cache_line_size());
486 return -ENOMEM; 496 }
487 return 0; 497
498 fq->flush_rq = kzalloc(rq_sz, GFP_KERNEL);
499 if (!fq->flush_rq)
500 goto fail_rq;
501
502 INIT_LIST_HEAD(&fq->flush_queue[0]);
503 INIT_LIST_HEAD(&fq->flush_queue[1]);
504 INIT_LIST_HEAD(&fq->flush_data_in_flight);
505
506 return fq;
507
508 fail_rq:
509 kfree(fq);
510 fail:
511 return NULL;
488} 512}
489 513
490int blk_init_flush(struct request_queue *q) 514static void blk_free_flush_queue(struct blk_flush_queue *fq)
491{ 515{
492 INIT_LIST_HEAD(&q->flush_queue[0]); 516 /* bio based request queue hasn't flush queue */
493 INIT_LIST_HEAD(&q->flush_queue[1]); 517 if (!fq)
494 INIT_LIST_HEAD(&q->flush_data_in_flight); 518 return;
495 519
496 if (q->mq_ops) 520 kfree(fq->flush_rq);
497 return blk_mq_init_flush(q); 521 kfree(fq);
522}
498 523
499 q->flush_rq = kzalloc(sizeof(struct request), GFP_KERNEL); 524int blk_init_flush(struct request_queue *q)
500 if (!q->flush_rq) 525{
526 q->fq = blk_alloc_flush_queue(q);
527 if (!q->fq)
501 return -ENOMEM; 528 return -ENOMEM;
502 529
503 return 0; 530 return 0;
@@ -505,5 +532,5 @@ int blk_init_flush(struct request_queue *q)
505 532
506void blk_exit_flush(struct request_queue *q) 533void blk_exit_flush(struct request_queue *q)
507{ 534{
508 kfree(q->flush_rq); 535 blk_free_flush_queue(q->fq);
509} 536}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 2758cdf2de94..d39e8a5eaeaa 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -508,20 +508,22 @@ void blk_mq_kick_requeue_list(struct request_queue *q)
508} 508}
509EXPORT_SYMBOL(blk_mq_kick_requeue_list); 509EXPORT_SYMBOL(blk_mq_kick_requeue_list);
510 510
511static inline bool is_flush_request(struct request *rq, unsigned int tag) 511static inline bool is_flush_request(struct request *rq,
512 struct blk_flush_queue *fq, unsigned int tag)
512{ 513{
513 return ((rq->cmd_flags & REQ_FLUSH_SEQ) && 514 return ((rq->cmd_flags & REQ_FLUSH_SEQ) &&
514 rq->q->flush_rq->tag == tag); 515 fq->flush_rq->tag == tag);
515} 516}
516 517
517struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag) 518struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag)
518{ 519{
519 struct request *rq = tags->rqs[tag]; 520 struct request *rq = tags->rqs[tag];
521 struct blk_flush_queue *fq = blk_get_flush_queue(rq->q);
520 522
521 if (!is_flush_request(rq, tag)) 523 if (!is_flush_request(rq, fq, tag))
522 return rq; 524 return rq;
523 525
524 return rq->q->flush_rq; 526 return fq->flush_rq;
525} 527}
526EXPORT_SYMBOL(blk_mq_tag_to_rq); 528EXPORT_SYMBOL(blk_mq_tag_to_rq);
527 529
diff --git a/block/blk.h b/block/blk.h
index c6fa3d4c6a89..833c4ac6c4eb 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -12,11 +12,28 @@
12/* Max future timer expiry for timeouts */ 12/* Max future timer expiry for timeouts */
13#define BLK_MAX_TIMEOUT (5 * HZ) 13#define BLK_MAX_TIMEOUT (5 * HZ)
14 14
15struct blk_flush_queue {
16 unsigned int flush_queue_delayed:1;
17 unsigned int flush_pending_idx:1;
18 unsigned int flush_running_idx:1;
19 unsigned long flush_pending_since;
20 struct list_head flush_queue[2];
21 struct list_head flush_data_in_flight;
22 struct request *flush_rq;
23 spinlock_t mq_flush_lock;
24};
25
15extern struct kmem_cache *blk_requestq_cachep; 26extern struct kmem_cache *blk_requestq_cachep;
16extern struct kmem_cache *request_cachep; 27extern struct kmem_cache *request_cachep;
17extern struct kobj_type blk_queue_ktype; 28extern struct kobj_type blk_queue_ktype;
18extern struct ida blk_queue_ida; 29extern struct ida blk_queue_ida;
19 30
31static inline struct blk_flush_queue *blk_get_flush_queue(
32 struct request_queue *q)
33{
34 return q->fq;
35}
36
20static inline void __blk_get_queue(struct request_queue *q) 37static inline void __blk_get_queue(struct request_queue *q)
21{ 38{
22 kobject_get(&q->kobj); 39 kobject_get(&q->kobj);
@@ -89,6 +106,7 @@ void blk_insert_flush(struct request *rq);
89static inline struct request *__elv_next_request(struct request_queue *q) 106static inline struct request *__elv_next_request(struct request_queue *q)
90{ 107{
91 struct request *rq; 108 struct request *rq;
109 struct blk_flush_queue *fq = blk_get_flush_queue(q);
92 110
93 while (1) { 111 while (1) {
94 if (!list_empty(&q->queue_head)) { 112 if (!list_empty(&q->queue_head)) {
@@ -111,9 +129,9 @@ static inline struct request *__elv_next_request(struct request_queue *q)
111 * should be restarted later. Please see flush_end_io() for 129 * should be restarted later. Please see flush_end_io() for
112 * details. 130 * details.
113 */ 131 */
114 if (q->flush_pending_idx != q->flush_running_idx && 132 if (fq->flush_pending_idx != fq->flush_running_idx &&
115 !queue_flush_queueable(q)) { 133 !queue_flush_queueable(q)) {
116 q->flush_queue_delayed = 1; 134 fq->flush_queue_delayed = 1;
117 return NULL; 135 return NULL;
118 } 136 }
119 if (unlikely(blk_queue_bypass(q)) || 137 if (unlikely(blk_queue_bypass(q)) ||