diff options
-rw-r--r-- | block/blk-core.c | 15 | ||||
-rw-r--r-- | block/blk-mq.c | 14 | ||||
-rw-r--r-- | block/blk.h | 3 |
3 files changed, 23 insertions, 9 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 9dcfb8ec554b..f0be754c7781 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1522,7 +1522,8 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req, | |||
1522 | * Caller must ensure !blk_queue_nomerges(q) beforehand. | 1522 | * Caller must ensure !blk_queue_nomerges(q) beforehand. |
1523 | */ | 1523 | */ |
1524 | bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, | 1524 | bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, |
1525 | unsigned int *request_count) | 1525 | unsigned int *request_count, |
1526 | struct request **same_queue_rq) | ||
1526 | { | 1527 | { |
1527 | struct blk_plug *plug; | 1528 | struct blk_plug *plug; |
1528 | struct request *rq; | 1529 | struct request *rq; |
@@ -1542,8 +1543,16 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, | |||
1542 | list_for_each_entry_reverse(rq, plug_list, queuelist) { | 1543 | list_for_each_entry_reverse(rq, plug_list, queuelist) { |
1543 | int el_ret; | 1544 | int el_ret; |
1544 | 1545 | ||
1545 | if (rq->q == q) | 1546 | if (rq->q == q) { |
1546 | (*request_count)++; | 1547 | (*request_count)++; |
1548 | /* | ||
1549 | * Only blk-mq multiple hardware queues case checks the | ||
1550 | * rq in the same queue, there should be only one such | ||
1551 | * rq in a queue | ||
1552 | **/ | ||
1553 | if (same_queue_rq) | ||
1554 | *same_queue_rq = rq; | ||
1555 | } | ||
1547 | 1556 | ||
1548 | if (rq->q != q || !blk_rq_merge_ok(rq, bio)) | 1557 | if (rq->q != q || !blk_rq_merge_ok(rq, bio)) |
1549 | continue; | 1558 | continue; |
@@ -1608,7 +1617,7 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio) | |||
1608 | * any locks. | 1617 | * any locks. |
1609 | */ | 1618 | */ |
1610 | if (!blk_queue_nomerges(q) && | 1619 | if (!blk_queue_nomerges(q) && |
1611 | blk_attempt_plug_merge(q, bio, &request_count)) | 1620 | blk_attempt_plug_merge(q, bio, &request_count, NULL)) |
1612 | return; | 1621 | return; |
1613 | 1622 | ||
1614 | spin_lock_irq(q->queue_lock); | 1623 | spin_lock_irq(q->queue_lock); |
diff --git a/block/blk-mq.c b/block/blk-mq.c index 902c2eb9a0e7..31df47443699 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
@@ -1269,6 +1269,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) | |||
1269 | struct request *rq; | 1269 | struct request *rq; |
1270 | unsigned int request_count = 0; | 1270 | unsigned int request_count = 0; |
1271 | struct blk_plug *plug; | 1271 | struct blk_plug *plug; |
1272 | struct request *same_queue_rq = NULL; | ||
1272 | 1273 | ||
1273 | blk_queue_bounce(q, &bio); | 1274 | blk_queue_bounce(q, &bio); |
1274 | 1275 | ||
@@ -1278,7 +1279,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) | |||
1278 | } | 1279 | } |
1279 | 1280 | ||
1280 | if (!is_flush_fua && !blk_queue_nomerges(q) && | 1281 | if (!is_flush_fua && !blk_queue_nomerges(q) && |
1281 | blk_attempt_plug_merge(q, bio, &request_count)) | 1282 | blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq)) |
1282 | return; | 1283 | return; |
1283 | 1284 | ||
1284 | rq = blk_mq_map_request(q, bio, &data); | 1285 | rq = blk_mq_map_request(q, bio, &data); |
@@ -1309,9 +1310,12 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) | |||
1309 | * issued. So the plug list will have one request at most | 1310 | * issued. So the plug list will have one request at most |
1310 | */ | 1311 | */ |
1311 | if (plug) { | 1312 | if (plug) { |
1312 | if (!list_empty(&plug->mq_list)) { | 1313 | /* |
1313 | old_rq = list_first_entry(&plug->mq_list, | 1314 | * The plug list might get flushed before this. If that |
1314 | struct request, queuelist); | 1315 | * happens, same_queue_rq is invalid and plug list is empty |
1316 | **/ | ||
1317 | if (same_queue_rq && !list_empty(&plug->mq_list)) { | ||
1318 | old_rq = same_queue_rq; | ||
1315 | list_del_init(&old_rq->queuelist); | 1319 | list_del_init(&old_rq->queuelist); |
1316 | } | 1320 | } |
1317 | list_add_tail(&rq->queuelist, &plug->mq_list); | 1321 | list_add_tail(&rq->queuelist, &plug->mq_list); |
@@ -1360,7 +1364,7 @@ static void blk_sq_make_request(struct request_queue *q, struct bio *bio) | |||
1360 | } | 1364 | } |
1361 | 1365 | ||
1362 | if (!is_flush_fua && !blk_queue_nomerges(q) && | 1366 | if (!is_flush_fua && !blk_queue_nomerges(q) && |
1363 | blk_attempt_plug_merge(q, bio, &request_count)) | 1367 | blk_attempt_plug_merge(q, bio, &request_count, NULL)) |
1364 | return; | 1368 | return; |
1365 | 1369 | ||
1366 | rq = blk_mq_map_request(q, bio, &data); | 1370 | rq = blk_mq_map_request(q, bio, &data); |
diff --git a/block/blk.h b/block/blk.h index 4b48d55e588e..026d9594142b 100644 --- a/block/blk.h +++ b/block/blk.h | |||
@@ -78,7 +78,8 @@ bool bio_attempt_front_merge(struct request_queue *q, struct request *req, | |||
78 | bool bio_attempt_back_merge(struct request_queue *q, struct request *req, | 78 | bool bio_attempt_back_merge(struct request_queue *q, struct request *req, |
79 | struct bio *bio); | 79 | struct bio *bio); |
80 | bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, | 80 | bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio, |
81 | unsigned int *request_count); | 81 | unsigned int *request_count, |
82 | struct request **same_queue_rq); | ||
82 | 83 | ||
83 | void blk_account_io_start(struct request *req, bool new_io); | 84 | void blk_account_io_start(struct request *req, bool new_io); |
84 | void blk_account_io_completion(struct request *req, unsigned int bytes); | 85 | void blk_account_io_completion(struct request *req, unsigned int bytes); |