]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
block: Add bvec_folio()
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 28 May 2026 17:59:03 +0000 (18:59 +0100)
committerJens Axboe <axboe@kernel.dk>
Fri, 29 May 2026 11:34:24 +0000 (05:34 -0600)
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>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: William Kucharski <william.kucharski@linux.dev>
Link: https://patch.msgid.link/20260528175905.1102280-2-willy@infradead.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/bio.c
include/linux/bio.h
include/linux/bvec.h
io_uring/rsrc.c
mm/page_io.c

index e9944dab0132706609b789764aa3458cbb4c393f..c3d0a00a27f150dc3bfe05b3ad237c962d020dd5 100644 (file)
@@ -1299,7 +1299,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);
@@ -1406,7 +1406,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;
 
@@ -1440,7 +1440,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]));
 }
 
 /**
index 97f993d4d914e1d52739274105d8a19963460d9b..26ebfff93a16dbab83ce2bfc3cff7e1f8dbd9072 100644 (file)
@@ -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;
index f4c7ec282ac9cb00141b9cb3e4df9c310704c178..c939f2b3be87fcd7c381d7646890a64528422e95 100644 (file)
@@ -74,6 +74,21 @@ 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
+ *
+ * A bvec 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 a bvec can span multiple folios.  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
index 650303626be6ed54d661ac88cd942095a79a2603..5d792f70ec1ed6213f70d914393a582c3de7e595 100644 (file)
@@ -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);
        }
index 70cea9e24d2fd3fd9bd2763d19dc10985497f88c..a59b73f8bdd9d1eb0730752d3261f2a122b1a52c 100644 (file)
@@ -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);
                }