linux-block.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* bio_add_pc_page cleanups
@ 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
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Christoph Hellwig @ 2019-07-03 13:00 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] 9+ messages in thread

* [PATCH 1/3] block: improve the gap check in __bio_add_pc_page
  2019-07-03 13:00 bio_add_pc_page cleanups Christoph Hellwig
@ 2019-07-03 13:00 ` Christoph Hellwig
  2019-07-03 14:40   ` Johannes Thumshirn
  2019-07-03 13:00 ` [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page Christoph Hellwig
  2019-07-03 13:00 ` [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers Christoph Hellwig
  2 siblings, 1 reply; 9+ 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 related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page
  2019-07-03 13:00 bio_add_pc_page cleanups 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 13:00 ` Christoph Hellwig
  2019-07-03 13:34   ` Johannes Thumshirn
  2019-07-03 13:00 ` [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers Christoph Hellwig
  2 siblings, 1 reply; 9+ messages in thread
From: Christoph Hellwig @ 2019-07-03 13:00 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 6be22b8477ce..1db626f99bcb 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -645,25 +645,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);
 }
 
 /**
@@ -699,26 +694,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;
 	}
@@ -734,7 +721,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 related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers
  2019-07-03 13:00 bio_add_pc_page cleanups 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 13:00 ` [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page Christoph Hellwig
@ 2019-07-03 13:00 ` Christoph Hellwig
  2 siblings, 0 replies; 9+ messages in thread
From: Christoph Hellwig @ 2019-07-03 13:00 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 1db626f99bcb..631b590a479f 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -668,7 +668,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
@@ -679,10 +679,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
@@ -694,12 +693,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
@@ -728,7 +723,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);
 
@@ -1369,13 +1365,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 related	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page
  2019-07-03 13:00 ` [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page Christoph Hellwig
@ 2019-07-03 13:34   ` Johannes Thumshirn
  2019-07-03 14:34     ` Christoph Hellwig
  0 siblings, 1 reply; 9+ messages in thread
From: Johannes Thumshirn @ 2019-07-03 13:34 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Jens Axboe, linux-block

On Wed, Jul 03, 2019 at 06:00:35AM -0700, Christoph Hellwig wrote:
[snip]
>  	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);
>  }

That's a lot of spurious whitespace changes here.

-- 
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] 9+ messages in thread

* Re: [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page
  2019-07-03 13:34   ` Johannes Thumshirn
@ 2019-07-03 14:34     ` Christoph Hellwig
  2019-07-03 14:40       ` Johannes Thumshirn
  0 siblings, 1 reply; 9+ messages in thread
From: Christoph Hellwig @ 2019-07-03 14:34 UTC (permalink / raw)
  To: Johannes Thumshirn; +Cc: Christoph Hellwig, Jens Axboe, linux-block

On Wed, Jul 03, 2019 at 03:34:55PM +0200, Johannes Thumshirn wrote:
> On Wed, Jul 03, 2019 at 06:00:35AM -0700, Christoph Hellwig wrote:
> [snip]
> >  	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);
> >  }
> 
> That's a lot of spurious whitespace changes here.

Really just an empty line going away outside the directly touched code.
I think it is more effective to boundle that here rather than having
an extra patch for that..

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

* Re: [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page
  2019-07-03 14:34     ` Christoph Hellwig
@ 2019-07-03 14:40       ` Johannes Thumshirn
  0 siblings, 0 replies; 9+ messages in thread
From: Johannes Thumshirn @ 2019-07-03 14:40 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Jens Axboe, linux-block

On Wed, Jul 03, 2019 at 04:34:59PM +0200, Christoph Hellwig wrote:
> Really just an empty line going away outside the directly touched code.
> I think it is more effective to boundle that here rather than having
> an extra patch for that..

I'm not a fan of stuff glued together, but admittedly that's pure bikeshedding
here.

-- 
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] 9+ 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; 9+ 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] 9+ 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
  0 siblings, 0 replies; 9+ 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 related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-08-12 15:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-03 13:00 bio_add_pc_page cleanups 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
2019-07-03 13:00 ` [PATCH 2/3] block: create bio_try_merge_pc_page helper __bio_add_pc_page Christoph Hellwig
2019-07-03 13:34   ` Johannes Thumshirn
2019-07-03 14:34     ` Christoph Hellwig
2019-07-03 14:40       ` Johannes Thumshirn
2019-07-03 13:00 ` [PATCH 3/3] block: move same page handling from __bio_add_pc_page to the callers Christoph Hellwig
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).