Message ID | 201708310859.v7V8xDaT012246@finist_ce7.work |
---|---|
State | New |
Series | "block: Check for gaps on front and back merges" |
Headers | show |
diff --git a/block/blk-merge.c b/block/blk-merge.c index b0ce46d..0e8b7f2 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -294,6 +294,8 @@ static inline int ll_new_hw_segment(struct request_queue *q, int ll_back_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) { + if (req_gap_back_merge(req, bio)) + return 0; if (blk_rq_sectors(req) + bio_sectors(bio) > blk_rq_get_max_sectors(req)) { req->cmd_flags |= REQ_NOMERGE; @@ -312,6 +314,8 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, int ll_front_merge_fn(struct request_queue *q, struct request *req, struct bio *bio) { + if (req_gap_front_merge(req, bio)) + return 0; if (blk_rq_sectors(req) + bio_sectors(bio) > blk_rq_get_max_sectors(req)) { req->cmd_flags |= REQ_NOMERGE; @@ -338,14 +342,6 @@ static bool req_no_special_merge(struct request *req) return !q->mq_ops && req->special; } -static int req_gap_to_prev(struct request *req, struct bio *next) -{ - struct bio *prev = req->biotail; - - return bvec_gap_to_prev(req->q, &prev->bi_io_vec[prev->bi_vcnt - 1], - next->bi_io_vec[0].bv_offset); -} - static int ll_merge_requests_fn(struct request_queue *q, struct request *req, struct request *next) { @@ -360,7 +356,7 @@ 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; - if (req_gap_to_prev(req, next->bio)) + if (req_gap_back_merge(req, next->bio)) return 0; /* @@ -568,10 +564,6 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) !blk_write_same_mergeable(rq->bio, bio)) return false; - /* Only check gaps if the bio carries data */ - if (bio_has_data(bio) && req_gap_to_prev(rq, bio)) - return false; - return true; } diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e1662f9..2b9bc88 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1493,6 +1493,26 @@ static inline bool bvec_gap_to_prev(struct request_queue *q, ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q)); } +static inline bool bio_will_gap(struct request_queue *q, struct bio *prev, + struct bio *next) +{ + if (!bio_has_data(prev)) + return false; + + return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1], + next->bi_io_vec[0].bv_offset); +} + +static inline bool req_gap_back_merge(struct request *req, struct bio *bio) +{ + return bio_will_gap(req->q, req->biotail, bio); +} + +static inline bool req_gap_front_merge(struct request *req, struct bio *bio) +{ + return bio_will_gap(req->q, bio, req->bio); +} + struct work_struct; int kblockd_schedule_work(struct work_struct *work); int kblockd_schedule_delayed_work(struct delayed_work *dwork, unsigned long delay);
Please consider to release a RK patch for it. https://readykernel.com/ -- Best regards, Konstantin Khorenko, Virtuozzo Linux Kernel Team On 08/31/2017 11:59 AM, Konstantin Khorenko wrote: > The commit is pushed to "branch-rh7-3.10.0-514.26.1.vz7.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git > after rh7-3.10.0-514.26.1.vz7.35.5 > ------> > commit 36178f3003689a99f0b58b6c12e235186952d9a9 > Author: Maxim Patlasov <mpatlasov@virtuozzo.com> > Date: Thu Aug 31 11:59:13 2017 +0300 > > ms/block: Check for gaps on front and back merges > > Backport 5e7c4274a70aa2d6f485996d0ca1dad52d0039ca from ml. Before the patch, > front merge incorrectly used the same req_gap_to_prev() as back merge. > Original patch description: > > block: Check for gaps on front and back merges > > We are checking for gaps to previous bio_vec, which can > only detect back merges gaps. Moreover, at the point where > we check for a gap, we don't know if we will attempt a back > or a front merge. Thus, check for gap to prev in a back merge > attempt and check for a gap to next in a front merge attempt. > > Signed-off-by: Jens Axboe <axboe@fb.com> > [sagig: Minor rename change] > Signed-off-by: Sagi Grimberg <sagig@mellanox.com> > > https://jira.sw.ru/browse/PSBM-70321 > Signed-off-by: Maxim Patlasov <mpatlasov@virtuozzo.com> > --- > block/blk-merge.c | 18 +++++------------- > include/linux/blkdev.h | 20 ++++++++++++++++++++ > 2 files changed, 25 insertions(+), 13 deletions(-) > > diff --git a/block/blk-merge.c b/block/blk-merge.c > index b0ce46d..0e8b7f2 100644 > --- a/block/blk-merge.c > +++ b/block/blk-merge.c > @@ -294,6 +294,8 @@ static inline int ll_new_hw_segment(struct request_queue *q, > int ll_back_merge_fn(struct request_queue *q, struct request *req, > struct bio *bio) > { > + if (req_gap_back_merge(req, bio)) > + return 0; > if (blk_rq_sectors(req) + bio_sectors(bio) > > blk_rq_get_max_sectors(req)) { > req->cmd_flags |= REQ_NOMERGE; > @@ -312,6 +314,8 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req, > int ll_front_merge_fn(struct request_queue *q, struct request *req, > struct bio *bio) > { > + if (req_gap_front_merge(req, bio)) > + return 0; > if (blk_rq_sectors(req) + bio_sectors(bio) > > blk_rq_get_max_sectors(req)) { > req->cmd_flags |= REQ_NOMERGE; > @@ -338,14 +342,6 @@ static bool req_no_special_merge(struct request *req) > return !q->mq_ops && req->special; > } > > -static int req_gap_to_prev(struct request *req, struct bio *next) > -{ > - struct bio *prev = req->biotail; > - > - return bvec_gap_to_prev(req->q, &prev->bi_io_vec[prev->bi_vcnt - 1], > - next->bi_io_vec[0].bv_offset); > -} > - > static int ll_merge_requests_fn(struct request_queue *q, struct request *req, > struct request *next) > { > @@ -360,7 +356,7 @@ 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; > > - if (req_gap_to_prev(req, next->bio)) > + if (req_gap_back_merge(req, next->bio)) > return 0; > > /* > @@ -568,10 +564,6 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) > !blk_write_same_mergeable(rq->bio, bio)) > return false; > > - /* Only check gaps if the bio carries data */ > - if (bio_has_data(bio) && req_gap_to_prev(rq, bio)) > - return false; > - > return true; > } > > diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h > index e1662f9..2b9bc88 100644 > --- a/include/linux/blkdev.h > +++ b/include/linux/blkdev.h > @@ -1493,6 +1493,26 @@ static inline bool bvec_gap_to_prev(struct request_queue *q, > ((bprv->bv_offset + bprv->bv_len) & queue_virt_boundary(q)); > } > > +static inline bool bio_will_gap(struct request_queue *q, struct bio *prev, > + struct bio *next) > +{ > + if (!bio_has_data(prev)) > + return false; > + > + return bvec_gap_to_prev(q, &prev->bi_io_vec[prev->bi_vcnt - 1], > + next->bi_io_vec[0].bv_offset); > +} > + > +static inline bool req_gap_back_merge(struct request *req, struct bio *bio) > +{ > + return bio_will_gap(req->q, req->biotail, bio); > +} > + > +static inline bool req_gap_front_merge(struct request *req, struct bio *bio) > +{ > + return bio_will_gap(req->q, bio, req->bio); > +} > + > struct work_struct; > int kblockd_schedule_work(struct work_struct *work); > int kblockd_schedule_delayed_work(struct delayed_work *dwork, unsigned long delay); > . >