diff options
author | Jens Axboe <axboe@fb.com> | 2017-02-03 09:49:05 -0700 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-02-03 09:49:05 -0700 |
commit | f0fe98610d92134ce0b00e0cd6bd94835d02a8e9 (patch) | |
tree | 24e672fb0292d984cca8cabeee848b913e61a0d4 /block | |
parent | f0c35c1e77830355eb2ef552db912de9a5b8c16e (diff) | |
parent | e4d750c97794ea2bab793d4c518b1f4006364588 (diff) |
Merge branch 'for-4.11/next' into for-next
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 12 | ||||
-rw-r--r-- | block/blk-merge.c | 44 | ||||
-rw-r--r-- | block/blk-mq-sched.c | 9 | ||||
-rw-r--r-- | block/blk-mq-sched.h | 3 | ||||
-rw-r--r-- | block/blk.h | 4 | ||||
-rw-r--r-- | block/mq-deadline.c | 8 |
6 files changed, 52 insertions, 28 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 4b3b11a51a79..d161d4ab7052 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1598,7 +1598,7 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) { struct blk_plug *plug; int el_ret, where = ELEVATOR_INSERT_SORT; - struct request *req; + struct request *req, *free; unsigned int request_count = 0; unsigned int wb_acct; @@ -1639,15 +1639,21 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) if (el_ret == ELEVATOR_BACK_MERGE) { if (bio_attempt_back_merge(q, req, bio)) { elv_bio_merged(q, req, bio); - if (!attempt_back_merge(q, req)) + free = attempt_back_merge(q, req); + if (!free) elv_merged_request(q, req, el_ret); + else + __blk_put_request(q, free); goto out_unlock; } } else if (el_ret == ELEVATOR_FRONT_MERGE) { if (bio_attempt_front_merge(q, req, bio)) { elv_bio_merged(q, req, bio); - if (!attempt_front_merge(q, req)) + free = attempt_front_merge(q, req); + if (!free) elv_merged_request(q, req, el_ret); + else + __blk_put_request(q, free); goto out_unlock; } } diff --git a/block/blk-merge.c b/block/blk-merge.c index 6aa43dec5af4..a373416dbc9a 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -659,31 +659,32 @@ static void blk_account_io_merge(struct request *req) } /* - * Has to be called with the request spinlock acquired + * For non-mq, this has to be called with the request spinlock acquired. + * For mq with scheduling, the appropriate queue wide lock should be held. */ -static int attempt_merge(struct request_queue *q, struct request *req, - struct request *next) +static struct request *attempt_merge(struct request_queue *q, + struct request *req, struct request *next) { if (!rq_mergeable(req) || !rq_mergeable(next)) - return 0; + return NULL; if (req_op(req) != req_op(next)) - return 0; + return NULL; /* * not contiguous */ if (blk_rq_pos(req) + blk_rq_sectors(req) != blk_rq_pos(next)) - return 0; + return NULL; if (rq_data_dir(req) != rq_data_dir(next) || req->rq_disk != next->rq_disk || req_no_special_merge(next)) - return 0; + return NULL; if (req_op(req) == REQ_OP_WRITE_SAME && !blk_write_same_mergeable(req->bio, next->bio)) - return 0; + return NULL; /* * If we are allowed to merge, then append bio list @@ -692,7 +693,7 @@ static int attempt_merge(struct request_queue *q, struct request *req, * counts here. */ if (!ll_merge_requests_fn(q, req, next)) - return 0; + return NULL; /* * If failfast settings disagree or any of the two is already @@ -732,42 +733,51 @@ static int attempt_merge(struct request_queue *q, struct request *req, if (blk_rq_cpu_valid(next)) req->cpu = next->cpu; - /* owner-ship of bio passed from next to req */ + /* + * ownership of bio passed from next to req, return 'next' for + * the caller to free + */ next->bio = NULL; - __blk_put_request(q, next); - return 1; + return next; } -int attempt_back_merge(struct request_queue *q, struct request *rq) +struct request *attempt_back_merge(struct request_queue *q, struct request *rq) { struct request *next = elv_latter_request(q, rq); if (next) return attempt_merge(q, rq, next); - return 0; + return NULL; } -int attempt_front_merge(struct request_queue *q, struct request *rq) +struct request *attempt_front_merge(struct request_queue *q, struct request *rq) { struct request *prev = elv_former_request(q, rq); if (prev) return attempt_merge(q, prev, rq); - return 0; + return NULL; } int blk_attempt_req_merge(struct request_queue *q, struct request *rq, struct request *next) { struct elevator_queue *e = q->elevator; + struct request *free; if (!e->uses_mq && e->type->ops.sq.elevator_allow_rq_merge_fn) if (!e->type->ops.sq.elevator_allow_rq_merge_fn(q, rq, next)) return 0; - return attempt_merge(q, rq, next); + free = attempt_merge(q, rq, next); + if (free) { + __blk_put_request(q, free); + return 1; + } + + return 0; } bool blk_rq_merge_ok(struct request *rq, struct bio *bio) diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c index 3ec52f494094..ee455e7cf9d8 100644 --- a/block/blk-mq-sched.c +++ b/block/blk-mq-sched.c @@ -234,7 +234,8 @@ void blk_mq_sched_move_to_dispatch(struct blk_mq_hw_ctx *hctx, } EXPORT_SYMBOL_GPL(blk_mq_sched_move_to_dispatch); -bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio) +bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio, + struct request **merged_request) { struct request *rq; int ret; @@ -244,7 +245,8 @@ bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio) if (!blk_mq_sched_allow_merge(q, rq, bio)) return false; if (bio_attempt_back_merge(q, rq, bio)) { - if (!attempt_back_merge(q, rq)) + *merged_request = attempt_back_merge(q, rq); + if (!*merged_request) elv_merged_request(q, rq, ret); return true; } @@ -252,7 +254,8 @@ bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio) if (!blk_mq_sched_allow_merge(q, rq, bio)) return false; if (bio_attempt_front_merge(q, rq, bio)) { - if (!attempt_front_merge(q, rq)) + *merged_request = attempt_front_merge(q, rq); + if (!*merged_request) elv_merged_request(q, rq, ret); return true; } diff --git a/block/blk-mq-sched.h b/block/blk-mq-sched.h index add5f090a8cd..5954859c8670 100644 --- a/block/blk-mq-sched.h +++ b/block/blk-mq-sched.h @@ -15,7 +15,8 @@ struct request *blk_mq_sched_get_request(struct request_queue *q, struct bio *bi void blk_mq_sched_put_request(struct request *rq); void blk_mq_sched_request_inserted(struct request *rq); -bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio); +bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio, + struct request **merged_request); bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio); bool blk_mq_sched_try_insert_merge(struct request_queue *q, struct request *rq); void blk_mq_sched_restart_queues(struct blk_mq_hw_ctx *hctx); diff --git a/block/blk.h b/block/blk.h index 6aa53a4aad88..4972b98d47e1 100644 --- a/block/blk.h +++ b/block/blk.h @@ -208,8 +208,8 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *bio); int ll_front_merge_fn(struct request_queue *q, struct request *req, struct bio *bio); -int attempt_back_merge(struct request_queue *q, struct request *rq); -int attempt_front_merge(struct request_queue *q, struct request *rq); +struct request *attempt_back_merge(struct request_queue *q, struct request *rq); +struct request *attempt_front_merge(struct request_queue *q, struct request *rq); int blk_attempt_req_merge(struct request_queue *q, struct request *rq, struct request *next); void blk_recalc_rq_segments(struct request *rq); diff --git a/block/mq-deadline.c b/block/mq-deadline.c index 8f91f21e8663..d68d9c273a66 100644 --- a/block/mq-deadline.c +++ b/block/mq-deadline.c @@ -371,12 +371,16 @@ static bool dd_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio) { struct request_queue *q = hctx->queue; struct deadline_data *dd = q->elevator->elevator_data; - int ret; + struct request *free = NULL; + bool ret; spin_lock(&dd->lock); - ret = blk_mq_sched_try_merge(q, bio); + ret = blk_mq_sched_try_merge(q, bio, &free); spin_unlock(&dd->lock); + if (free) + blk_mq_free_request(free); + return ret; } |