From: Ming Lei <ming.lei@redhat.com>
To: Jens Axboe <axboe@kernel.dk>
Cc: linux-block@vger.kernel.org, Ming Lei <ming.lei@redhat.com>,
Omar Sandoval <osandov@fb.com>, Christoph Hellwig <hch@lst.de>
Subject: [PATCH V3 07/10] block: enable multi-page bvec for passthrough IO
Date: Fri, 29 Mar 2019 15:08:00 +0800 [thread overview]
Message-ID: <20190329070803.10958-8-ming.lei@redhat.com> (raw)
In-Reply-To: <20190329070803.10958-1-ming.lei@redhat.com>
Now block IO stack is basically ready for supporting multi-page bvec,
however it isn't enabled on passthrough IO.
One reason is that passthrough IO is dispatched to LLD directly and bio
split is bypassed, so the bio has to be built correctly for dispatch to
LLD from the beginning.
Implement multi-page support for passthrough IO by limitting each bvec
as block device's segment and applying all kinds of queue limit in
blk_add_pc_page(). Then we don't need to calculate segments any more for
passthrough IO any more, turns out code is simplified much.
Cc: Omar Sandoval <osandov@fb.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
block/bio.c | 60 +++++++++++++++++++++++++++++++-----------------------------
1 file changed, 31 insertions(+), 29 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index 26853e072cd7..8d516d508ae3 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -665,6 +665,27 @@ static inline bool page_is_mergeable(const struct bio_vec *bv,
return true;
}
+/*
+ * Check if the @page can be added to the current segment(@bv), and make
+ * sure to call it only if page_is_mergeable(@bv, @page) is true
+ */
+static bool can_add_page_to_seg(struct request_queue *q,
+ struct bio_vec *bv, struct page *page, unsigned len,
+ unsigned offset)
+{
+ unsigned long mask = queue_segment_boundary(q);
+ phys_addr_t addr1 = page_to_phys(bv->bv_page) + bv->bv_offset;
+ phys_addr_t addr2 = page_to_phys(page) + offset + len - 1;
+
+ if ((addr1 | mask) != (addr2 | mask))
+ return false;
+
+ if (bv->bv_len + len > queue_max_segment_size(q))
+ return false;
+
+ return true;
+}
+
/**
* __bio_add_pc_page - attempt to add page to passthrough bio
* @q: the target queue
@@ -685,7 +706,6 @@ int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
struct page *page, unsigned int len, unsigned int offset,
bool put_same_page)
{
- int retried_segments = 0;
struct bio_vec *bvec;
/*
@@ -709,6 +729,7 @@ int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
offset == bvec->bv_offset + bvec->bv_len) {
if (put_same_page)
put_page(page);
+ bvec_merge:
bvec->bv_len += len;
bio->bi_iter.bi_size += len;
goto done;
@@ -720,11 +741,18 @@ int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
*/
if (bvec_gap_to_prev(q, bvec, offset))
return 0;
+
+ if (page_is_mergeable(bvec, page, len, offset, false) &&
+ can_add_page_to_seg(q, bvec, page, len, offset))
+ goto bvec_merge;
}
if (bio_full(bio))
return 0;
+ if (bio->bi_phys_segments >= queue_max_segments(q))
+ return 0;
+
/*
* setup the new entry, we might clear it again later if we
* cannot add the page
@@ -734,38 +762,12 @@ int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
bvec->bv_len = len;
bvec->bv_offset = offset;
bio->bi_vcnt++;
- bio->bi_phys_segments++;
bio->bi_iter.bi_size += len;
- /*
- * Perform a recount if the number of segments is greater
- * than queue_max_segments(q).
- */
-
- while (bio->bi_phys_segments > queue_max_segments(q)) {
-
- if (retried_segments)
- goto failed;
-
- retried_segments = 1;
- blk_recount_segments(q, bio);
- }
-
- /* If we may be able to merge these biovecs, force a recount */
- if (bio->bi_vcnt > 1 && biovec_phys_mergeable(q, bvec - 1, bvec))
- bio_clear_flag(bio, BIO_SEG_VALID);
-
done:
+ bio->bi_phys_segments = bio->bi_vcnt;
+ bio_set_flag(bio, BIO_SEG_VALID);
return len;
-
- failed:
- bvec->bv_page = NULL;
- bvec->bv_len = 0;
- bvec->bv_offset = 0;
- bio->bi_vcnt--;
- bio->bi_iter.bi_size -= len;
- blk_recount_segments(q, bio);
- return 0;
}
EXPORT_SYMBOL(__bio_add_pc_page);
--
2.9.5
next prev parent reply other threads:[~2019-03-29 7:08 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-29 7:07 [PATCH V3 00/10] block: enable multi-page bvec for passthrough IO Ming Lei
2019-03-29 7:07 ` [PATCH V3 01/10] block: pass page to xen_biovec_phys_mergeable Ming Lei
2019-03-29 7:07 ` [PATCH V3 02/10] block: avoid to break XEN by multi-page bvec Ming Lei
2019-03-29 7:07 ` [PATCH V3 03/10] block: don't merge adjacent bvecs to one segment in bio blk_queue_split Ming Lei
2019-03-29 7:07 ` [PATCH V3 04/10] block: cleanup bio_add_pc_page Ming Lei
2019-03-29 7:07 ` [PATCH V3 05/10] block: check if page is mergeable in one helper Ming Lei
2019-03-29 7:07 ` [PATCH V3 06/10] block: put the same page when adding it to bio Ming Lei
2019-03-29 7:08 ` Ming Lei [this message]
2019-03-29 7:08 ` [PATCH V3 08/10] block: remove argument of 'request_queue' from __blk_bvec_map_sg Ming Lei
2019-03-29 7:08 ` [PATCH V3 09/10] block: reuse __blk_bvec_map_sg() for mapping page sized bvec Ming Lei
2019-03-29 7:08 ` [PATCH V3 10/10] block: don't check if adjacent bvecs in one bio can be mergeable Ming Lei
2019-03-29 14:20 ` [PATCH V3 00/10] block: enable multi-page bvec for passthrough IO Jens Axboe
2019-03-29 14:22 ` Jens Axboe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190329070803.10958-8-ming.lei@redhat.com \
--to=ming.lei@redhat.com \
--cc=axboe@kernel.dk \
--cc=hch@lst.de \
--cc=linux-block@vger.kernel.org \
--cc=osandov@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox