]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fsverity: push out fsverity_info lookup
authorChristoph Hellwig <hch@lst.de>
Mon, 2 Feb 2026 06:06:35 +0000 (07:06 +0100)
committerEric Biggers <ebiggers@kernel.org>
Tue, 3 Feb 2026 01:15:26 +0000 (17:15 -0800)
Pass a struct fsverity_info to the verification and readahead helpers,
and push the lookup into the callers.  Right now this is a very dumb
almost mechanic move that open codes a lot of fsverity_info_addr() calls
in the file systems.  The subsequent patches will clean this up.

This prepares for reducing the number of fsverity_info lookups, which
will allow to amortize them better when using a more expensive lookup
method.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Acked-by: David Sterba <dsterba@suse.com> # btrfs
Link: https://lore.kernel.org/r/20260202060754.270269-7-hch@lst.de
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
fs/btrfs/extent_io.c
fs/buffer.c
fs/ext4/readpage.c
fs/f2fs/compress.c
fs/f2fs/data.c
fs/verity/verify.c
include/linux/fsverity.h

index a4b74023618d309e221200cbca767a10e9325531..21430b7d8f27c6edf97ee4aacec9abc891b6ced1 100644 (file)
@@ -484,7 +484,8 @@ static bool btrfs_verify_folio(struct folio *folio, u64 start, u32 len)
            btrfs_folio_test_uptodate(fs_info, folio, start, len) ||
            start >= i_size_read(folio->mapping->host))
                return true;
-       return fsverity_verify_folio(folio);
+       return fsverity_verify_folio(*fsverity_info_addr(folio->mapping->host),
+                       folio);
 }
 
 static void end_folio_read(struct folio *folio, bool uptodate, u64 start, u32 len)
index 838c0c5710229e42f5b3334a7b5d67bb912af91b..3982253b6805e296241aa09015beac25cc14e8fd 100644 (file)
@@ -309,9 +309,11 @@ static void verify_bh(struct work_struct *work)
        struct postprocess_bh_ctx *ctx =
                container_of(work, struct postprocess_bh_ctx, work);
        struct buffer_head *bh = ctx->bh;
+       struct inode *inode = bh->b_folio->mapping->host;
        bool valid;
 
-       valid = fsverity_verify_blocks(bh->b_folio, bh->b_size, bh_offset(bh));
+       valid = fsverity_verify_blocks(*fsverity_info_addr(inode), bh->b_folio,
+                                      bh->b_size, bh_offset(bh));
        end_buffer_async_read(bh, valid);
        kfree(ctx);
 }
index 3049a66a05c86477010d4e739b0f7586eb8a943b..b0a3c923636829c670e523fff3ed9076316d0d65 100644 (file)
@@ -97,6 +97,7 @@ static void verity_work(struct work_struct *work)
        struct bio_post_read_ctx *ctx =
                container_of(work, struct bio_post_read_ctx, work);
        struct bio *bio = ctx->bio;
+       struct inode *inode = bio_first_folio_all(bio)->mapping->host;
 
        /*
         * fsverity_verify_bio() may call readahead() again, and although verity
@@ -109,7 +110,7 @@ static void verity_work(struct work_struct *work)
        mempool_free(ctx, bio_post_read_ctx_pool);
        bio->bi_private = NULL;
 
-       fsverity_verify_bio(bio);
+       fsverity_verify_bio(*fsverity_info_addr(inode), bio);
 
        __read_end_io(bio);
 }
@@ -331,7 +332,9 @@ static int ext4_mpage_readpages(struct inode *inode,
                                          folio_size(folio));
                        if (first_hole == 0) {
                                if (ext4_need_verity(inode, folio->index) &&
-                                   !fsverity_verify_folio(folio))
+                                   !fsverity_verify_folio(
+                                               *fsverity_info_addr(inode),
+                                               folio))
                                        goto set_error_page;
                                folio_end_read(folio, true);
                                continue;
@@ -409,7 +412,8 @@ int ext4_read_folio(struct file *file, struct folio *folio)
        }
 
        if (ext4_need_verity(inode, folio->index))
-               fsverity_readahead(inode, folio->index, folio_nr_pages(folio));
+               fsverity_readahead(*fsverity_info_addr(inode), folio->index,
+                                  folio_nr_pages(folio));
        return ext4_mpage_readpages(inode, NULL, folio);
 }
 
@@ -422,8 +426,8 @@ void ext4_readahead(struct readahead_control *rac)
                return;
 
        if (ext4_need_verity(inode, readahead_index(rac)))
-               fsverity_readahead(inode, readahead_index(rac),
-                                  readahead_count(rac));
+               fsverity_readahead(*fsverity_info_addr(inode),
+                                  readahead_index(rac), readahead_count(rac));
        ext4_mpage_readpages(inode, rac, NULL);
 }
 
index 40a62f1dee4d45be42796fa5586ec0fc3e8b4f88..3de4a7e669590342dfcf7773964f7d6912d98941 100644 (file)
@@ -1814,7 +1814,9 @@ static void f2fs_verify_cluster(struct work_struct *work)
                if (!rpage)
                        continue;
 
-               if (fsverity_verify_page(rpage))
+               if (fsverity_verify_page(
+                               *fsverity_info_addr(rpage->mapping->host),
+                               rpage))
                        SetPageUptodate(rpage);
                else
                        ClearPageUptodate(rpage);
index 58d8a311ef2c3b191bcfe89f23e3c5aff8428587..3593208c99db54c2ff2ec13f306fd9253f8df5bd 100644 (file)
@@ -185,15 +185,19 @@ static void f2fs_verify_bio(struct work_struct *work)
 
                bio_for_each_folio_all(fi, bio) {
                        struct folio *folio = fi.folio;
+                       struct fsverity_info *vi =
+                               *fsverity_info_addr(folio->mapping->host);
 
                        if (!f2fs_is_compressed_page(folio) &&
-                           !fsverity_verify_page(&folio->page)) {
+                           !fsverity_verify_page(vi, &folio->page)) {
                                bio->bi_status = BLK_STS_IOERR;
                                break;
                        }
                }
        } else {
-               fsverity_verify_bio(bio);
+               struct inode *inode = bio_first_folio_all(bio)->mapping->host;
+
+               fsverity_verify_bio(*fsverity_info_addr(inode), bio);
        }
 
        f2fs_finish_read_bio(bio, true);
@@ -2121,7 +2125,9 @@ got_it:
 zero_out:
                folio_zero_segment(folio, 0, folio_size(folio));
                if (f2fs_need_verity(inode, index) &&
-                   !fsverity_verify_folio(folio)) {
+                   !fsverity_verify_folio(
+                               *fsverity_info_addr(folio->mapping->host),
+                               folio)) {
                        ret = -EIO;
                        goto out;
                }
@@ -2475,7 +2481,8 @@ static int f2fs_read_data_folio(struct file *file, struct folio *folio)
        }
 
        if (f2fs_need_verity(inode, folio->index))
-               fsverity_readahead(inode, folio->index, folio_nr_pages(folio));
+               fsverity_readahead(*fsverity_info_addr(inode), folio->index,
+                                  folio_nr_pages(folio));
        return f2fs_mpage_readpages(inode, NULL, folio);
 }
 
@@ -2493,8 +2500,8 @@ static void f2fs_readahead(struct readahead_control *rac)
                return;
 
        if (f2fs_need_verity(inode, readahead_index(rac)))
-               fsverity_readahead(inode, readahead_index(rac),
-                                  readahead_count(rac));
+               fsverity_readahead(*fsverity_info_addr(inode),
+                                  readahead_index(rac), readahead_count(rac));
        f2fs_mpage_readpages(inode, rac, NULL);
 }
 
index 31045d83ace4743836d6d8cea6371d1db6cfd6db..37e000f01c180455936fbef8e00f611c0ce5dd00 100644 (file)
@@ -38,7 +38,7 @@ static struct workqueue_struct *fsverity_read_workqueue;
 
 /**
  * fsverity_readahead() - kick off readahead on fsverity hashes
- * @inode:             inode that is being read
+ * @vi:                        fsverity_info for the inode to be read
  * @index:             first file data page index that is being read
  * @nr_pages:          number of file data pages to be read
  *
@@ -49,10 +49,10 @@ static struct workqueue_struct *fsverity_read_workqueue;
  * ensure that the hashes are already cached on completion of the file data
  * read if possible.
  */
-void fsverity_readahead(struct inode *inode, pgoff_t index,
+void fsverity_readahead(struct fsverity_info *vi, pgoff_t index,
                        unsigned long nr_pages)
 {
-       const struct fsverity_info *vi = *fsverity_info_addr(inode);
+       struct inode *inode = vi->inode;
        const struct merkle_tree_params *params = &vi->tree_params;
        u64 start_hidx = (u64)index << params->log_blocks_per_page;
        u64 end_hidx =
@@ -314,11 +314,9 @@ error:
 
 static void
 fsverity_init_verification_context(struct fsverity_verification_context *ctx,
-                                  struct inode *inode)
+                                  struct fsverity_info *vi)
 {
-       struct fsverity_info *vi = *fsverity_info_addr(inode);
-
-       ctx->inode = inode;
+       ctx->inode = vi->inode;
        ctx->vi = vi;
        ctx->num_pending = 0;
        if (vi->tree_params.hash_alg->algo_id == HASH_ALGO_SHA256 &&
@@ -398,6 +396,7 @@ static bool fsverity_add_data_blocks(struct fsverity_verification_context *ctx,
 
 /**
  * fsverity_verify_blocks() - verify data in a folio
+ * @vi: fsverity_info for the inode to be read
  * @folio: the folio containing the data to verify
  * @len: the length of the data to verify in the folio
  * @offset: the offset of the data to verify in the folio
@@ -408,11 +407,12 @@ static bool fsverity_add_data_blocks(struct fsverity_verification_context *ctx,
  *
  * Return: %true if the data is valid, else %false.
  */
-bool fsverity_verify_blocks(struct folio *folio, size_t len, size_t offset)
+bool fsverity_verify_blocks(struct fsverity_info *vi, struct folio *folio,
+                           size_t len, size_t offset)
 {
        struct fsverity_verification_context ctx;
 
-       fsverity_init_verification_context(&ctx, folio->mapping->host);
+       fsverity_init_verification_context(&ctx, vi);
 
        if (fsverity_add_data_blocks(&ctx, folio, len, offset) &&
            fsverity_verify_pending_blocks(&ctx))
@@ -425,6 +425,7 @@ EXPORT_SYMBOL_GPL(fsverity_verify_blocks);
 #ifdef CONFIG_BLOCK
 /**
  * fsverity_verify_bio() - verify a 'read' bio that has just completed
+ * @vi: fsverity_info for the inode to be read
  * @bio: the bio to verify
  *
  * Verify the bio's data against the file's Merkle tree.  All bio data segments
@@ -437,13 +438,12 @@ EXPORT_SYMBOL_GPL(fsverity_verify_blocks);
  * filesystems) must instead call fsverity_verify_page() directly on each page.
  * All filesystems must also call fsverity_verify_page() on holes.
  */
-void fsverity_verify_bio(struct bio *bio)
+void fsverity_verify_bio(struct fsverity_info *vi, struct bio *bio)
 {
-       struct inode *inode = bio_first_folio_all(bio)->mapping->host;
        struct fsverity_verification_context ctx;
        struct folio_iter fi;
 
-       fsverity_init_verification_context(&ctx, inode);
+       fsverity_init_verification_context(&ctx, vi);
 
        bio_for_each_folio_all(fi, bio) {
                if (!fsverity_add_data_blocks(&ctx, fi.folio, fi.length,
index 722a42754a86c2855582b1939753abde973cdf06..076228a9fd12af9f83cbb9dc63b4851a68d78588 100644 (file)
@@ -197,12 +197,20 @@ int fsverity_ioctl_read_metadata(struct file *filp, const void __user *uarg);
 
 /* verify.c */
 
-bool fsverity_verify_blocks(struct folio *folio, size_t len, size_t offset);
-void fsverity_verify_bio(struct bio *bio);
+bool fsverity_verify_blocks(struct fsverity_info *vi, struct folio *folio,
+                           size_t len, size_t offset);
+void fsverity_verify_bio(struct fsverity_info *vi, struct bio *bio);
 void fsverity_enqueue_verify_work(struct work_struct *work);
 
 #else /* !CONFIG_FS_VERITY */
 
+/*
+ * Provide a stub to allow code using this to compile.  All callsites should be
+ * guarded by compiler dead code elimination, and this forces a link error if
+ * not.
+ */
+struct fsverity_info **fsverity_info_addr(const struct inode *inode);
+
 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
        return NULL;
@@ -251,14 +259,16 @@ static inline int fsverity_ioctl_read_metadata(struct file *filp,
 
 /* verify.c */
 
-static inline bool fsverity_verify_blocks(struct folio *folio, size_t len,
+static inline bool fsverity_verify_blocks(struct fsverity_info *vi,
+                                         struct folio *folio, size_t len,
                                          size_t offset)
 {
        WARN_ON_ONCE(1);
        return false;
 }
 
-static inline void fsverity_verify_bio(struct bio *bio)
+static inline void fsverity_verify_bio(struct fsverity_info *vi,
+                                      struct bio *bio)
 {
        WARN_ON_ONCE(1);
 }
@@ -270,14 +280,16 @@ static inline void fsverity_enqueue_verify_work(struct work_struct *work)
 
 #endif /* !CONFIG_FS_VERITY */
 
-static inline bool fsverity_verify_folio(struct folio *folio)
+static inline bool fsverity_verify_folio(struct fsverity_info *vi,
+                                        struct folio *folio)
 {
-       return fsverity_verify_blocks(folio, folio_size(folio), 0);
+       return fsverity_verify_blocks(vi, folio, folio_size(folio), 0);
 }
 
-static inline bool fsverity_verify_page(struct page *page)
+static inline bool fsverity_verify_page(struct fsverity_info *vi,
+                                       struct page *page)
 {
-       return fsverity_verify_blocks(page_folio(page), PAGE_SIZE, 0);
+       return fsverity_verify_blocks(vi, page_folio(page), PAGE_SIZE, 0);
 }
 
 /**
@@ -319,7 +331,7 @@ static inline int fsverity_file_open(struct inode *inode, struct file *filp)
 }
 
 void fsverity_cleanup_inode(struct inode *inode);
-void fsverity_readahead(struct inode *inode, pgoff_t index,
+void fsverity_readahead(struct fsverity_info *vi, pgoff_t index,
                        unsigned long nr_pages);
 
 struct page *generic_read_merkle_tree_page(struct inode *inode, pgoff_t index);