* [PATCH] block: Add bvec_folio()
@ 2026-05-22 18:21 Matthew Wilcox (Oracle)
2026-05-25 6:06 ` Christoph Hellwig
0 siblings, 1 reply; 5+ messages in thread
From: Matthew Wilcox (Oracle) @ 2026-05-22 18:21 UTC (permalink / raw)
To: Jens Axboe
Cc: Matthew Wilcox (Oracle), linux-block, linux-kernel, io-uring,
linux-mm, Leon Romanovsky
This is a simple helper which replaces page_folio(bvec->bv_page).
Minor improvement in readability, but the real motivation is to reduce
the number of references to bvec->bv_page so that it can be changed
with less work.
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Leon Romanovsky <leon@kernel.org>
---
Hi Jens,
I have a pile of other patches which depend on this one, but they're
spread all over the kernel and don't really have anything in common
with each other. Getting this in the next merge window will let me send
those patches next cycle.
block/bio.c | 6 +++---
include/linux/bio.h | 2 +-
include/linux/bvec.h | 13 +++++++++++++
io_uring/rsrc.c | 2 +-
mm/page_io.c | 4 ++--
5 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/block/bio.c b/block/bio.c
index 5f10900b3f42..85aab3140909 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1300,7 +1300,7 @@ static void bio_free_folios(struct bio *bio)
int i;
bio_for_each_bvec_all(bv, bio, i) {
- struct folio *folio = page_folio(bv->bv_page);
+ struct folio *folio = bvec_folio(bv);
if (!is_zero_folio(folio))
folio_put(folio);
@@ -1409,7 +1409,7 @@ int bio_iov_iter_bounce(struct bio *bio, struct iov_iter *iter, size_t maxlen,
static void bvec_unpin(struct bio_vec *bv, bool mark_dirty)
{
- struct folio *folio = page_folio(bv->bv_page);
+ struct folio *folio = bvec_folio(bv);
size_t nr_pages = (bv->bv_offset + bv->bv_len - 1) / PAGE_SIZE -
bv->bv_offset / PAGE_SIZE + 1;
@@ -1443,7 +1443,7 @@ static void bio_iov_iter_unbounce_read(struct bio *bio, bool is_error,
bvec_unpin(&bio->bi_io_vec[1 + i], mark_dirty);
}
- folio_put(page_folio(bio->bi_io_vec[0].bv_page));
+ folio_put(bvec_folio(&bio->bi_io_vec[0]));
}
/**
diff --git a/include/linux/bio.h b/include/linux/bio.h
index dc17780d6c1e..6613ab4519bd 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -283,7 +283,7 @@ static inline void bio_first_folio(struct folio_iter *fi, struct bio *bio,
return;
}
- fi->folio = page_folio(bvec->bv_page);
+ fi->folio = bvec_folio(bvec);
fi->offset = bvec->bv_offset +
PAGE_SIZE * folio_page_idx(fi->folio, bvec->bv_page);
fi->_seg_count = bvec->bv_len;
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index d36dd476feda..32846079b853 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -74,6 +74,19 @@ static inline void bvec_set_virt(struct bio_vec *bv, void *vaddr,
bvec_set_page(bv, virt_to_page(vaddr), len, offset_in_page(vaddr));
}
+/**
+ * bvec_folio - Return the first folio referenced by this bvec
+ * @bv: bvec to access
+ *
+ * bvecs can span multiple folios. Unless you know that this
+ * bvec does not, you may be better off using something like
+ * bio_for_each_folio_all() which iterates over all folios.
+ */
+static inline struct folio *bvec_folio(const struct bio_vec *bv)
+{
+ return page_folio(bv->bv_page);
+}
+
struct bvec_iter {
/*
* Current device address in 512 byte sectors. Only updated by the bio
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 650303626be6..5d792f70ec1e 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -102,7 +102,7 @@ static void io_release_ubuf(void *priv)
unsigned int i;
for (i = 0; i < imu->nr_bvecs; i++) {
- struct folio *folio = page_folio(imu->bvec[i].bv_page);
+ struct folio *folio = bvec_folio(&imu->bvec[i]);
unpin_user_folio(folio, 1);
}
diff --git a/mm/page_io.c b/mm/page_io.c
index 70cea9e24d2f..a59b73f8bdd9 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -490,7 +490,7 @@ static void sio_read_complete(struct kiocb *iocb, long ret)
if (ret == sio->len) {
for (p = 0; p < sio->pages; p++) {
- struct folio *folio = page_folio(sio->bvec[p].bv_page);
+ struct folio *folio = bvec_folio(&sio->bvec[p]);
count_mthp_stat(folio_order(folio), MTHP_STAT_SWPIN);
count_memcg_folio_events(folio, PSWPIN, folio_nr_pages(folio));
@@ -500,7 +500,7 @@ static void sio_read_complete(struct kiocb *iocb, long ret)
count_vm_events(PSWPIN, sio->len >> PAGE_SHIFT);
} else {
for (p = 0; p < sio->pages; p++) {
- struct folio *folio = page_folio(sio->bvec[p].bv_page);
+ struct folio *folio = bvec_folio(&sio->bvec[p]);
folio_unlock(folio);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] block: Add bvec_folio()
2026-05-22 18:21 [PATCH] block: Add bvec_folio() Matthew Wilcox (Oracle)
@ 2026-05-25 6:06 ` Christoph Hellwig
2026-05-25 13:29 ` Matthew Wilcox
0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2026-05-25 6:06 UTC (permalink / raw)
To: Matthew Wilcox (Oracle)
Cc: Jens Axboe, linux-block, linux-kernel, io-uring, linux-mm,
Leon Romanovsky
> +/**
> + * bvec_folio - Return the first folio referenced by this bvec
> + * @bv: bvec to access
> + *
> + * bvecs can span multiple folios. Unless you know that this
> + * bvec does not, you may be better off using something like
> + * bio_for_each_folio_all() which iterates over all folios.
> + */
> +static inline struct folio *bvec_folio(const struct bio_vec *bv)
> +{
> + return page_folio(bv->bv_page);
> +}
The comment here is confusing. bio_for_each_folio_all is a helper that
only works in the submitter side, and not for anything using the
bvec_iter required for drivers or anything else sitting below a
potential bio clone/split or using bvecs from an upper layer (like
ITER_BVEC direct I/O). Additionally bv_page can be a different
page than the fist page due to large bv_offset on split bios.
So I'm not against the function per se, but the documentation must
explain the minefields it is stepping into a bit better.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] block: Add bvec_folio()
2026-05-25 6:06 ` Christoph Hellwig
@ 2026-05-25 13:29 ` Matthew Wilcox
2026-05-26 6:43 ` Christoph Hellwig
0 siblings, 1 reply; 5+ messages in thread
From: Matthew Wilcox @ 2026-05-25 13:29 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, linux-block, linux-kernel, io-uring, linux-mm,
Leon Romanovsky
On Sun, May 24, 2026 at 11:06:26PM -0700, Christoph Hellwig wrote:
> > +/**
> > + * bvec_folio - Return the first folio referenced by this bvec
> > + * @bv: bvec to access
> > + *
> > + * bvecs can span multiple folios. Unless you know that this
> > + * bvec does not, you may be better off using something like
> > + * bio_for_each_folio_all() which iterates over all folios.
> > + */
> > +static inline struct folio *bvec_folio(const struct bio_vec *bv)
> > +{
> > + return page_folio(bv->bv_page);
> > +}
>
> The comment here is confusing. bio_for_each_folio_all is a helper that
> only works in the submitter side, and not for anything using the
> bvec_iter required for drivers or anything else sitting below a
> potential bio clone/split or using bvecs from an upper layer (like
> ITER_BVEC direct I/O). Additionally bv_page can be a different
> page than the fist page due to large bv_offset on split bios.
>
> So I'm not against the function per se, but the documentation must
> explain the minefields it is stepping into a bit better.
Lower level drivers shouldn't be concerning themselves with folios.
For a start, we can put non-folios (eg slab memory) into bvecs.
I'm happy to clarify this comment further, but I don't understand
who's going to look at this function and need to have more explanation.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] block: Add bvec_folio()
2026-05-25 13:29 ` Matthew Wilcox
@ 2026-05-26 6:43 ` Christoph Hellwig
2026-05-26 17:47 ` Matthew Wilcox
0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2026-05-26 6:43 UTC (permalink / raw)
To: Matthew Wilcox
Cc: Christoph Hellwig, Jens Axboe, linux-block, linux-kernel,
io-uring, linux-mm, Leon Romanovsky
On Mon, May 25, 2026 at 02:29:27PM +0100, Matthew Wilcox wrote:
> > So I'm not against the function per se, but the documentation must
> > explain the minefields it is stepping into a bit better.
>
> Lower level drivers shouldn't be concerning themselves with folios.
> For a start, we can put non-folios (eg slab memory) into bvecs.
Well, that is a very good thing to put into the comment. We can also
put them into high-level bvecs, so framing this as 'only use if you
know the memory is folios, which you can't unless you are the entity
who filled the bio' might be a good choice.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] block: Add bvec_folio()
2026-05-26 6:43 ` Christoph Hellwig
@ 2026-05-26 17:47 ` Matthew Wilcox
0 siblings, 0 replies; 5+ messages in thread
From: Matthew Wilcox @ 2026-05-26 17:47 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jens Axboe, linux-block, linux-kernel, io-uring, linux-mm,
Leon Romanovsky
On Mon, May 25, 2026 at 11:43:22PM -0700, Christoph Hellwig wrote:
> On Mon, May 25, 2026 at 02:29:27PM +0100, Matthew Wilcox wrote:
> > > So I'm not against the function per se, but the documentation must
> > > explain the minefields it is stepping into a bit better.
> >
> > Lower level drivers shouldn't be concerning themselves with folios.
> > For a start, we can put non-folios (eg slab memory) into bvecs.
>
> Well, that is a very good thing to put into the comment. We can also
> put them into high-level bvecs, so framing this as 'only use if you
> know the memory is folios, which you can't unless you are the entity
> who filled the bio' might be a good choice.
How about:
/**
* bvec_folio - Return the first folio referenced by this bvec
* @bv: bvec to access
*
* bvecs can contain non-folio memory, so this should only be called by
* the creator of the bvec; drivers have no business looking at the owner
* of the memory. It may not even be the right interface for the caller
* to use as bvecs can span multiple folios. You may be better off using
* something like bio_for_each_folio_all() which iterates over all folios.
*/
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-05-26 17:47 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-22 18:21 [PATCH] block: Add bvec_folio() Matthew Wilcox (Oracle)
2026-05-25 6:06 ` Christoph Hellwig
2026-05-25 13:29 ` Matthew Wilcox
2026-05-26 6:43 ` Christoph Hellwig
2026-05-26 17:47 ` Matthew Wilcox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox