[PATCHv2 1/2] block: Merge discard requests as a special case

Keith Busch keith.busch at intel.com
Thu Feb 1 12:31:57 PST 2018


Discard requests operate under different constraints than other operations
and have different rules for merging. This patch will handle such requests
as a special case, using the same criteria and segment accounting used
for merging a discard bio into a reqseut.

Signed-off-by: Keith Busch <keith.busch at intel.com>
---
 block/blk-merge.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/block/blk-merge.c b/block/blk-merge.c
index 8452fc7164cc..e36462bc90f3 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -550,6 +550,25 @@ static bool req_no_special_merge(struct request *req)
 	return !q->mq_ops && req->special;
 }
 
+static int req_attempt_discard_merge(struct request_queue *q, struct request *req,
+		struct request *next)
+{
+	unsigned short segments = blk_rq_nr_discard_segments(req);
+
+	if (segments >= queue_max_discard_segments(q))
+		goto no_merge;
+	if (blk_rq_sectors(req) + bio_sectors(next->bio) >
+	    blk_rq_get_max_sectors(req, blk_rq_pos(req)))
+		goto no_merge;
+
+	req->nr_phys_segments = segments + blk_rq_nr_discard_segments(next);
+	return 1;
+
+no_merge:
+	req_set_nomerge(q, req);
+	return 0;
+}
+
 static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
 				struct request *next)
 {
@@ -564,6 +583,13 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
 	if (req_no_special_merge(req) || req_no_special_merge(next))
 		return 0;
 
+	/*
+	 * Merging discard requests use different constraints than other
+	 * operations.
+	 */
+	if (req_op(req) == REQ_OP_DISCARD)
+		return req_attempt_discard_merge(q, req, next);
+
 	if (req_gap_back_merge(req, next->bio))
 		return 0;
 
@@ -715,7 +741,8 @@ static struct request *attempt_merge(struct request_queue *q,
 
 	req->__data_len += blk_rq_bytes(next);
 
-	elv_merge_requests(q, req, next);
+	if (req_op(req) != REQ_OP_DISCARD)
+		elv_merge_requests(q, req, next);
 
 	/*
 	 * 'next' is going away, so update stats accordingly
-- 
2.14.3




More information about the Linux-nvme mailing list