All of lore.kernel.org
 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ 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; 8+ 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] 8+ messages in thread

end of thread, other threads:[~2019-07-03 14:40 UTC | newest]

Thread overview: 8+ 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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.