Linux-Block Archive on lore.kernel.org
 help / color / Atom feed
* bio_add_pc_page cleanups
@ 2019-08-12 15:39 Christoph Hellwig
  2019-08-12 15:39 ` [PATCH 1/3] block: improve the gap check in __bio_add_pc_page Christoph Hellwig
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Christoph Hellwig @ 2019-08-12 15:39 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Hi Jens,

this series cleans up the bio_add_pc_page code and reuses more code
from the regular bio path.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] block: improve the gap check in __bio_add_pc_page
  2019-08-12 15:39 bio_add_pc_page cleanups Christoph Hellwig
@ 2019-08-12 15:39 ` Christoph Hellwig
  2019-08-12 15:39 ` [PATCH 2/3] block: create a bio_try_merge_pc_page helper Christoph Hellwig
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2019-08-12 15:39 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block, Johannes Thumshirn

If we can add more data into an existing segment we do not create a gap
per definition, so move the check for a gap after the attempt to merge
into the segment.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
---
 block/bio.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 24a496f5d2e2..9f80bf4531b3 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -710,18 +710,18 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 			goto done;
 		}
 
-		/*
-		 * If the queue doesn't support SG gaps and adding this
-		 * offset would create a gap, disallow it.
-		 */
-		if (bvec_gap_to_prev(q, bvec, offset))
-			return 0;
-
 		if (page_is_mergeable(bvec, page, len, offset, &same_page) &&
 		    can_add_page_to_seg(q, bvec, page, len, offset)) {
 			bvec->bv_len += len;
 			goto done;
 		}
+
+		/*
+		 * If the queue doesn't support SG gaps and adding this segment
+		 * would create a gap, disallow it.
+		 */
+		if (bvec_gap_to_prev(q, bvec, offset))
+			return 0;
 	}
 
 	if (bio_full(bio, len))
-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/3] block: create a bio_try_merge_pc_page helper
  2019-08-12 15:39 bio_add_pc_page cleanups Christoph Hellwig
  2019-08-12 15:39 ` [PATCH 1/3] block: improve the gap check in __bio_add_pc_page Christoph Hellwig
@ 2019-08-12 15:39 ` Christoph Hellwig
  2019-08-12 15:39 ` [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers Christoph Hellwig
  2019-08-22  1:00 ` bio_add_pc_page cleanups Christoph Hellwig
  3 siblings, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2019-08-12 15:39 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Passsthrough bio handling should be the same as normal bio handling,
except that we need to take hardware limitations into account.  Thus
use the common try_merge implementation after checking the hardware
limits.  This changes behavior in that we now also check segment
and dma boundary settings for same page merges, which is a little
more work but has no effect as those need to be larger than the
page size.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c | 34 ++++++++++------------------------
 1 file changed, 10 insertions(+), 24 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 9f80bf4531b3..6ea4b9257667 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -646,25 +646,20 @@ 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)
+static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio,
+		struct page *page, unsigned len, unsigned offset,
+		bool *same_page)
 {
+	struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
 	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;
+	return __bio_try_merge_page(bio, page, len, offset, same_page);
 }
 
 /**
@@ -700,26 +695,18 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 		return 0;
 
 	if (bio->bi_vcnt > 0) {
-		bvec = &bio->bi_io_vec[bio->bi_vcnt - 1];
-
-		if (page == bvec->bv_page &&
-		    offset == bvec->bv_offset + bvec->bv_len) {
-			if (put_same_page)
+		if (bio_try_merge_pc_page(q, bio, page, len, offset,
+				&same_page)) {
+			if (put_same_page && same_page)
 				put_page(page);
-			bvec->bv_len += len;
-			goto done;
-		}
-
-		if (page_is_mergeable(bvec, page, len, offset, &same_page) &&
-		    can_add_page_to_seg(q, bvec, page, len, offset)) {
-			bvec->bv_len += len;
-			goto done;
+			return len;
 		}
 
 		/*
 		 * If the queue doesn't support SG gaps and adding this segment
 		 * would create a gap, disallow it.
 		 */
+		bvec = &bio->bi_io_vec[bio->bi_vcnt - 1];
 		if (bvec_gap_to_prev(q, bvec, offset))
 			return 0;
 	}
@@ -735,7 +722,6 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 	bvec->bv_len = len;
 	bvec->bv_offset = offset;
 	bio->bi_vcnt++;
- done:
 	bio->bi_iter.bi_size += len;
 	return len;
 }
-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers
  2019-08-12 15:39 bio_add_pc_page cleanups Christoph Hellwig
  2019-08-12 15:39 ` [PATCH 1/3] block: improve the gap check in __bio_add_pc_page Christoph Hellwig
  2019-08-12 15:39 ` [PATCH 2/3] block: create a bio_try_merge_pc_page helper Christoph Hellwig
@ 2019-08-12 15:39 ` Christoph Hellwig
  2019-08-22  1:00 ` bio_add_pc_page cleanups Christoph Hellwig
  3 siblings, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2019-08-12 15:39 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

Hiding page refcount manipulation inside a low-level bio helper is
somewhat awkward.  Instead return the same page information to the
callers, where it fits in much better.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 6ea4b9257667..11aa6738ed62 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -669,7 +669,7 @@ static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio,
  *	@page: page to add
  *	@len: vec entry length
  *	@offset: vec entry offset
- *	@put_same_page: put the page if it is same with last added page
+ *	@same_page: return if the merge happen inside the same page
  *
  *	Attempt to add a page to the bio_vec maplist. This can fail for a
  *	number of reasons, such as the bio being full or target block device
@@ -680,10 +680,9 @@ static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio,
  */
 static 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)
+		bool *same_page)
 {
 	struct bio_vec *bvec;
-	bool same_page = false;
 
 	/*
 	 * cloned bio must not modify vec list
@@ -695,12 +694,8 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 		return 0;
 
 	if (bio->bi_vcnt > 0) {
-		if (bio_try_merge_pc_page(q, bio, page, len, offset,
-				&same_page)) {
-			if (put_same_page && same_page)
-				put_page(page);
+		if (bio_try_merge_pc_page(q, bio, page, len, offset, same_page))
 			return len;
-		}
 
 		/*
 		 * If the queue doesn't support SG gaps and adding this segment
@@ -729,7 +724,8 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 int bio_add_pc_page(struct request_queue *q, struct bio *bio,
 		struct page *page, unsigned int len, unsigned int offset)
 {
-	return __bio_add_pc_page(q, bio, page, len, offset, false);
+	bool same_page = false;
+	return __bio_add_pc_page(q, bio, page, len, offset, &same_page);
 }
 EXPORT_SYMBOL(bio_add_pc_page);
 
@@ -1370,13 +1366,17 @@ struct bio *bio_map_user_iov(struct request_queue *q,
 			for (j = 0; j < npages; j++) {
 				struct page *page = pages[j];
 				unsigned int n = PAGE_SIZE - offs;
+				bool same_page = false;
 
 				if (n > bytes)
 					n = bytes;
 
 				if (!__bio_add_pc_page(q, bio, page, n, offs,
-							true))
+						&same_page)) {
+					if (same_page)
+						put_page(page);
 					break;
+				}
 
 				added += n;
 				bytes -= n;
-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: bio_add_pc_page cleanups
  2019-08-12 15:39 bio_add_pc_page cleanups Christoph Hellwig
                   ` (2 preceding siblings ...)
  2019-08-12 15:39 ` [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers Christoph Hellwig
@ 2019-08-22  1:00 ` Christoph Hellwig
  3 siblings, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2019-08-22  1:00 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

On Mon, Aug 12, 2019 at 05:39:55PM +0200, Christoph Hellwig wrote:
> Hi Jens,
> 
> this series cleans up the bio_add_pc_page code and reuses more code
> from the regular bio path.

ping?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] block: improve the gap check in __bio_add_pc_page
  2019-07-03 13:00 ` [PATCH 1/3] block: improve the gap check in __bio_add_pc_page Christoph Hellwig
@ 2019-07-03 14:40   ` Johannes Thumshirn
  0 siblings, 0 replies; 7+ messages in thread
From: Johannes Thumshirn @ 2019-07-03 14:40 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Jens Axboe, linux-block

Looks good,
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
-- 
Johannes Thumshirn                            SUSE Labs Filesystems
jthumshirn@suse.de                                +49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] block: improve the gap check in __bio_add_pc_page
  2019-07-03 13:00 Christoph Hellwig
@ 2019-07-03 13:00 ` Christoph Hellwig
  2019-07-03 14:40   ` Johannes Thumshirn
  0 siblings, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2019-07-03 13:00 UTC (permalink / raw)
  To: Jens Axboe; +Cc: linux-block

If we can add more data into an existing segment we do not create a gap
per definition, so move the check for a gap after the attempt to merge
into the segment.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index 29cd6cf4da51..6be22b8477ce 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -709,18 +709,18 @@ static int __bio_add_pc_page(struct request_queue *q, struct bio *bio,
 			goto done;
 		}
 
-		/*
-		 * If the queue doesn't support SG gaps and adding this
-		 * offset would create a gap, disallow it.
-		 */
-		if (bvec_gap_to_prev(q, bvec, offset))
-			return 0;
-
 		if (page_is_mergeable(bvec, page, len, offset, &same_page) &&
 		    can_add_page_to_seg(q, bvec, page, len, offset)) {
 			bvec->bv_len += len;
 			goto done;
 		}
+
+		/*
+		 * If the queue doesn't support SG gaps and adding this segment
+		 * would create a gap, disallow it.
+		 */
+		if (bvec_gap_to_prev(q, bvec, offset))
+			return 0;
 	}
 
 	if (bio_full(bio, len))
-- 
2.20.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, back to index

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-12 15:39 bio_add_pc_page cleanups Christoph Hellwig
2019-08-12 15:39 ` [PATCH 1/3] block: improve the gap check in __bio_add_pc_page Christoph Hellwig
2019-08-12 15:39 ` [PATCH 2/3] block: create a bio_try_merge_pc_page helper Christoph Hellwig
2019-08-12 15:39 ` [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers Christoph Hellwig
2019-08-22  1:00 ` bio_add_pc_page cleanups Christoph Hellwig
  -- strict thread matches above, loose matches on Subject: below --
2019-07-03 13:00 Christoph Hellwig
2019-07-03 13:00 ` [PATCH 1/3] block: improve the gap check in __bio_add_pc_page Christoph Hellwig
2019-07-03 14:40   ` Johannes Thumshirn

Linux-Block Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-block/0 linux-block/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-block linux-block/ https://lore.kernel.org/linux-block \
		linux-block@vger.kernel.org linux-block@archiver.kernel.org
	public-inbox-index linux-block


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-block


AGPL code for this site: git clone https://public-inbox.org/ public-inbox