Skip to content

Commit

Permalink
blk-mq: don't disallow request merges for req->special being set
Browse files Browse the repository at this point in the history
For blk-mq, if a driver has requested per-request payload data
to carry command structures, they are stuffed into req->special.
For an old style request based driver, req->special is used
for the same purpose but indicates that a per-driver request
structure has been prepared for the request already. So for the
old style driver, we do not merge such requests.

As most/all blk-mq drivers will use the payload feature, and
since we have no problem merging on these, make this check
dependent on whether it's a blk-mq enabled driver or not.

Reported-by: Shaohua Li <[email protected]>
Signed-off-by: Jens Axboe <[email protected]>
  • Loading branch information
axboe committed Oct 29, 2013
1 parent 92f399c commit e7e2450
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions block/blk-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,17 @@ int ll_front_merge_fn(struct request_queue *q, struct request *req,
return ll_new_hw_segment(q, req, bio);
}

/*
* blk-mq uses req->special to carry normal driver per-request payload, it
* does not indicate a prepared command that we cannot merge with.
*/
static bool req_no_special_merge(struct request *req)
{
struct request_queue *q = req->q;

return !q->mq_ops && req->special;
}

static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
struct request *next)
{
Expand All @@ -319,7 +330,7 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
* First check if the either of the requests are re-queued
* requests. Can't merge them if they are.
*/
if (req->special || next->special)
if (req_no_special_merge(req) || req_no_special_merge(next))
return 0;

/*
Expand Down Expand Up @@ -416,7 +427,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,

if (rq_data_dir(req) != rq_data_dir(next)
|| req->rq_disk != next->rq_disk
|| next->special)
|| req_no_special_merge(next))
return 0;

if (req->cmd_flags & REQ_WRITE_SAME &&
Expand Down Expand Up @@ -515,7 +526,7 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
return false;

/* must be same device and not a special request */
if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special)
if (rq->rq_disk != bio->bi_bdev->bd_disk || req_no_special_merge(rq))
return false;

/* only merge integrity protected bio into ditto rq */
Expand Down

0 comments on commit e7e2450

Please sign in to comment.