]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ext4: consolidate fsverity_info lookup
authorChristoph Hellwig <hch@lst.de>
Mon, 2 Feb 2026 06:06:37 +0000 (07:06 +0100)
committerEric Biggers <ebiggers@kernel.org>
Wed, 4 Feb 2026 19:27:54 +0000 (11:27 -0800)
Look up the fsverity_info once in ext4_mpage_readpages, and then use it
for the readahead, local verification of holes and pass it along to the
I/O completion workqueue in struct bio_post_read_ctx.

This amortizes the lookup better once it becomes less efficient.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Link: https://lore.kernel.org/r/20260202060754.270269-9-hch@lst.de
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
fs/ext4/readpage.c

index b0a3c923636829c670e523fff3ed9076316d0d65..04fcb7b8f2a73206a732d0a9f3cd57ec2a142708 100644 (file)
@@ -62,6 +62,7 @@ enum bio_post_read_step {
 
 struct bio_post_read_ctx {
        struct bio *bio;
+       struct fsverity_info *vi;
        struct work_struct work;
        unsigned int cur_step;
        unsigned int enabled_steps;
@@ -97,7 +98,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;
+       struct fsverity_info *vi = ctx->vi;
 
        /*
         * fsverity_verify_bio() may call readahead() again, and although verity
@@ -110,7 +111,7 @@ static void verity_work(struct work_struct *work)
        mempool_free(ctx, bio_post_read_ctx_pool);
        bio->bi_private = NULL;
 
-       fsverity_verify_bio(*fsverity_info_addr(inode), bio);
+       fsverity_verify_bio(vi, bio);
 
        __read_end_io(bio);
 }
@@ -174,22 +175,16 @@ static void mpage_end_io(struct bio *bio)
        __read_end_io(bio);
 }
 
-static inline bool ext4_need_verity(const struct inode *inode, pgoff_t idx)
-{
-       return fsverity_active(inode) &&
-              idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE);
-}
-
 static void ext4_set_bio_post_read_ctx(struct bio *bio,
                                       const struct inode *inode,
-                                      pgoff_t first_idx)
+                                      struct fsverity_info *vi)
 {
        unsigned int post_read_steps = 0;
 
        if (fscrypt_inode_uses_fs_layer_crypto(inode))
                post_read_steps |= 1 << STEP_DECRYPT;
 
-       if (ext4_need_verity(inode, first_idx))
+       if (vi)
                post_read_steps |= 1 << STEP_VERITY;
 
        if (post_read_steps) {
@@ -198,6 +193,7 @@ static void ext4_set_bio_post_read_ctx(struct bio *bio,
                        mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
 
                ctx->bio = bio;
+               ctx->vi = vi;
                ctx->enabled_steps = post_read_steps;
                bio->bi_private = ctx;
        }
@@ -211,7 +207,7 @@ static inline loff_t ext4_readpage_limit(struct inode *inode)
        return i_size_read(inode);
 }
 
-static int ext4_mpage_readpages(struct inode *inode,
+static int ext4_mpage_readpages(struct inode *inode, struct fsverity_info *vi,
                struct readahead_control *rac, struct folio *folio)
 {
        struct bio *bio = NULL;
@@ -331,10 +327,7 @@ static int ext4_mpage_readpages(struct inode *inode,
                        folio_zero_segment(folio, first_hole << blkbits,
                                          folio_size(folio));
                        if (first_hole == 0) {
-                               if (ext4_need_verity(inode, folio->index) &&
-                                   !fsverity_verify_folio(
-                                               *fsverity_info_addr(inode),
-                                               folio))
+                               if (vi && !fsverity_verify_folio(vi, folio))
                                        goto set_error_page;
                                folio_end_read(folio, true);
                                continue;
@@ -362,7 +355,7 @@ static int ext4_mpage_readpages(struct inode *inode,
                                        REQ_OP_READ, GFP_KERNEL);
                        fscrypt_set_bio_crypt_ctx(bio, inode, next_block,
                                                  GFP_KERNEL);
-                       ext4_set_bio_post_read_ctx(bio, inode, folio->index);
+                       ext4_set_bio_post_read_ctx(bio, inode, vi);
                        bio->bi_iter.bi_sector = first_block << (blkbits - 9);
                        bio->bi_end_io = mpage_end_io;
                        if (rac)
@@ -401,6 +394,7 @@ next_page:
 int ext4_read_folio(struct file *file, struct folio *folio)
 {
        struct inode *inode = folio->mapping->host;
+       struct fsverity_info *vi = NULL;
        int ret;
 
        trace_ext4_read_folio(inode, folio);
@@ -411,24 +405,28 @@ int ext4_read_folio(struct file *file, struct folio *folio)
                        return ret;
        }
 
-       if (ext4_need_verity(inode, folio->index))
-               fsverity_readahead(*fsverity_info_addr(inode), folio->index,
-                                  folio_nr_pages(folio));
-       return ext4_mpage_readpages(inode, NULL, folio);
+       if (folio->index < DIV_ROUND_UP(inode->i_size, PAGE_SIZE))
+               vi = fsverity_get_info(inode);
+       if (vi)
+               fsverity_readahead(vi, folio->index, folio_nr_pages(folio));
+       return ext4_mpage_readpages(inode, vi, NULL, folio);
 }
 
 void ext4_readahead(struct readahead_control *rac)
 {
        struct inode *inode = rac->mapping->host;
+       struct fsverity_info *vi = NULL;
 
        /* If the file has inline data, no need to do readahead. */
        if (ext4_has_inline_data(inode))
                return;
 
-       if (ext4_need_verity(inode, readahead_index(rac)))
-               fsverity_readahead(*fsverity_info_addr(inode),
-                                  readahead_index(rac), readahead_count(rac));
-       ext4_mpage_readpages(inode, rac, NULL);
+       if (readahead_index(rac) < DIV_ROUND_UP(inode->i_size, PAGE_SIZE))
+               vi = fsverity_get_info(inode);
+       if (vi)
+               fsverity_readahead(vi, readahead_index(rac),
+                                  readahead_count(rac));
+       ext4_mpage_readpages(inode, vi, rac, NULL);
 }
 
 int __init ext4_init_post_read_processing(void)