Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1674698

[PATCH v2 51/51] block: bio: pass segments to bio if bio_add_page() is bypassed

From Ming Lei <ming.lei@redhat.com>
Newsgroups linux.kernel
Subject [PATCH v2 51/51] block: bio: pass segments to bio if bio_add_page() is bypassed
Date 2017-06-26 14:30 +0200
Message-ID <tWBjs-2iS-15@gated-at.bofh.it> (permalink)
References <tWB9L-2fr-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


Under some situations, such as block direct I/O, we can't use
bio_add_page() for merging pages into multipage bvec, so
a new function is implemented for converting page array into one
segment array, then these cases can benefit from multipage bvec
too.

Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
 block/bio.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 436305cde045..e2bcbb842982 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -876,6 +876,41 @@ int bio_add_page(struct bio *bio, struct page *page,
 }
 EXPORT_SYMBOL(bio_add_page);
 
+static unsigned convert_to_segs(struct bio* bio, struct page **pages,
+				unsigned char *page_cnt,
+				unsigned nr_pages)
+{
+
+	unsigned idx;
+	unsigned nr_seg = 0;
+	struct request_queue *q = NULL;
+
+	if (bio->bi_bdev)
+		q = bdev_get_queue(bio->bi_bdev);
+
+	if (!q || !blk_queue_cluster(q)) {
+		memset(page_cnt, 0, nr_pages);
+		return nr_pages;
+	}
+
+	page_cnt[nr_seg] = 0;
+	for (idx = 1; idx < nr_pages; idx++) {
+		struct page *pg_s = pages[nr_seg];
+		struct page *pg = pages[idx];
+
+		if (page_to_pfn(pg_s) + page_cnt[nr_seg] + 1 ==
+		    page_to_pfn(pg)) {
+			page_cnt[nr_seg]++;
+		} else {
+			page_cnt[++nr_seg] = 0;
+			if (nr_seg < idx)
+				pages[nr_seg] = pg;
+		}
+	}
+
+	return nr_seg + 1;
+}
+
 /**
  * bio_iov_iter_get_pages - pin user or kernel pages and add them to a bio
  * @bio: bio to add pages to
@@ -895,6 +930,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
 	struct page **pages = (struct page **)bv;
 	size_t offset, diff;
 	ssize_t size;
+	unsigned short nr_segs;
+	unsigned char page_cnt[nr_pages];	/* at most 256 pages */
 
 	size = iov_iter_get_pages(iter, pages, LONG_MAX, nr_pages, &offset);
 	if (unlikely(size <= 0))
@@ -910,13 +947,18 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
 	 * need to be reflected here as well.
 	 */
 	bio->bi_iter.bi_size += size;
-	bio->bi_vcnt += nr_pages;
-
 	diff = (nr_pages * PAGE_SIZE - offset) - size;
-	while (nr_pages--) {
-		bv[nr_pages].bv_page = pages[nr_pages];
-		bv[nr_pages].bv_len = PAGE_SIZE;
-		bv[nr_pages].bv_offset = 0;
+
+	/* convert into segments */
+	nr_segs = convert_to_segs(bio, pages, page_cnt, nr_pages);
+	bio->bi_vcnt += nr_segs;
+
+	while (nr_segs--) {
+		unsigned cnt = (unsigned)page_cnt[nr_segs] + 1;
+
+		bv[nr_segs].bv_page = pages[nr_segs];
+		bv[nr_segs].bv_len = PAGE_SIZE * cnt;
+		bv[nr_segs].bv_offset = 0;
 	}
 
 	bv[0].bv_offset += offset;
-- 
2.9.4

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH v2 00/51] block: support multipage bvec Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:20 +0200
  [PATCH v2 29/51] block: bio: introduce single/multi page version of bio_for_each_segment_all() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:20 +0200
  [PATCH v2 43/51] xfs: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 22/51] block: introduce bio_for_each_segment_mp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 18/51] block: bounce: don't access bio->bi_io_vec in copy_to_high_bio_irq Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 20/51] block: introduce multipage/single page bvec helpers Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 51/51] block: bio: pass segments to bio if bio_add_page() is bypassed Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 32/51] btrfs: use bvec_get_last_page to get bio's last page Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 41/51] fs/iomap: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 14/51] btrfs: avoid to access bvec table directly for a cloned bio Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
    Re: [PATCH v2 14/51] btrfs: avoid to access bvec table directly for  a cloned bio Liu Bo <bo.li.liu@oracle.com> - 2017-06-26 20:10 +0200
  [PATCH v2 46/51] exofs: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 49/51] fs/direct-io: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 39/51] fs/mpage: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 40/51] fs/block: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 37/51] dm-crypt: don't clear bvec->bv_page in crypt_free_buffer_pages() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 47/51] fs: crypto: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 44/51] gfs2: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 45/51] f2fs: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 50/51] block: enable multipage bvecs Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 48/51] fs/btrfs: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 33/51] block: deal with dirtying pages for multipage bvec Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 36/51] md: raid1: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  [PATCH v2 42/51] ext4: convert to bio_for_each_segment_all_sp() Ming Lei <ming.lei@redhat.com> - 2017-06-26 14:30 +0200
  Re: [PATCH v2 00/51] block: support multipage bvec David Sterba <dsterba@suse.cz> - 2017-06-26 18:50 +0200
  Re: [PATCH v2 00/51] block: support multipage bvec Jens Axboe <axboe@kernel.dk> - 2017-06-26 18:50 +0200

csiph-web