Look up the fsverity_info once in f2fs_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.  Do the same
thing in f2fs_get_read_data_folio for reads that come from garbage
collection and other background activities.

This amortizes the lookup better once it becomes less efficient.

Signed-off-by: Christoph Hellwig <[email protected]>
---
 fs/f2fs/compress.c |  9 +++---
 fs/f2fs/data.c     | 73 +++++++++++++++++++++++++---------------------
 fs/f2fs/f2fs.h     |  9 ++----
 3 files changed, 46 insertions(+), 45 deletions(-)

diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 0c269b875e0c..285f5b4bb2fc 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -1181,6 +1181,7 @@ int f2fs_prepare_compress_overwrite(struct inode *inode,
                .cluster_idx = index >> F2FS_I(inode)->i_log_cluster_size,
                .rpages = NULL,
                .nr_rpages = 0,
+               .vi = NULL, /* can't write to fsverity files */
        };
 
        return prepare_compress_overwrite(&cc, pagep, index, fsdata);
@@ -1716,7 +1717,7 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct 
compress_ctx *cc)
        dic->nr_cpages = cc->nr_cpages;
        refcount_set(&dic->refcnt, 1);
        dic->failed = false;
-       dic->need_verity = f2fs_need_verity(cc->inode, start_idx);
+       dic->vi = cc->vi;
 
        for (i = 0; i < dic->cluster_size; i++)
                dic->rpages[i] = cc->rpages[i];
@@ -1814,9 +1815,7 @@ static void f2fs_verify_cluster(struct work_struct *work)
                if (!rpage)
                        continue;
 
-               if (fsverity_verify_page(
-                               *fsverity_info_addr(rpage->mapping->host),
-                               rpage))
+               if (fsverity_verify_page(dic->vi, rpage))
                        SetPageUptodate(rpage);
                else
                        ClearPageUptodate(rpage);
@@ -1835,7 +1834,7 @@ void f2fs_decompress_end_io(struct decompress_io_ctx 
*dic, bool failed,
 {
        int i;
 
-       if (!failed && dic->need_verity) {
+       if (!failed && dic->vi) {
                /*
                 * Note that to avoid deadlocks, the verity work can't be done
                 * on the decompression workqueue.  This is because verifying
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index bca1e34d327a..2e0900d0673a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -109,6 +109,7 @@ enum bio_post_read_step {
 struct bio_post_read_ctx {
        struct bio *bio;
        struct f2fs_sb_info *sbi;
+       struct fsverity_info *vi;
        struct work_struct work;
        unsigned int enabled_steps;
        /*
@@ -165,6 +166,7 @@ static void f2fs_verify_bio(struct work_struct *work)
                container_of(work, struct bio_post_read_ctx, work);
        struct bio *bio = ctx->bio;
        bool may_have_compressed_pages = (ctx->enabled_steps & STEP_DECOMPRESS);
+       struct fsverity_info *vi = ctx->vi;
 
        /*
         * fsverity_verify_bio() may call readahead() again, and while verity
@@ -185,8 +187,6 @@ 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(vi, &folio->page)) {
@@ -195,9 +195,8 @@ static void f2fs_verify_bio(struct work_struct *work)
                        }
                }
        } else {
-               struct inode *inode = bio_first_folio_all(bio)->mapping->host;
 
-               fsverity_verify_bio(*fsverity_info_addr(inode), bio);
+               fsverity_verify_bio(vi, bio);
        }
 
        f2fs_finish_read_bio(bio, true);
@@ -1040,9 +1039,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
        f2fs_up_write(&io->io_rwsem);
 }
 
-static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
-                                     unsigned nr_pages, blk_opf_t op_flag,
-                                     pgoff_t first_idx, bool for_write)
+static struct bio *f2fs_grab_read_bio(struct inode *inode,
+               struct fsverity_info *vi, block_t blkaddr, unsigned nr_pages,
+               blk_opf_t op_flag, pgoff_t first_idx, bool for_write)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct bio *bio;
@@ -1061,7 +1060,7 @@ static struct bio *f2fs_grab_read_bio(struct inode 
*inode, block_t blkaddr,
        if (fscrypt_inode_uses_fs_layer_crypto(inode))
                post_read_steps |= STEP_DECRYPT;
 
-       if (f2fs_need_verity(inode, first_idx))
+       if (vi)
                post_read_steps |= STEP_VERITY;
 
        /*
@@ -1076,6 +1075,7 @@ static struct bio *f2fs_grab_read_bio(struct inode 
*inode, block_t blkaddr,
                ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
                ctx->bio = bio;
                ctx->sbi = sbi;
+               ctx->vi = vi;
                ctx->enabled_steps = post_read_steps;
                ctx->fs_blkaddr = blkaddr;
                ctx->decompression_attempted = false;
@@ -1087,15 +1087,15 @@ static struct bio *f2fs_grab_read_bio(struct inode 
*inode, block_t blkaddr,
 }
 
 /* This can handle encryption stuffs */
-static void f2fs_submit_page_read(struct inode *inode, struct folio *folio,
-                                block_t blkaddr, blk_opf_t op_flags,
-                                bool for_write)
+static void f2fs_submit_page_read(struct inode *inode, struct fsverity_info 
*vi,
+               struct folio *folio, block_t blkaddr, blk_opf_t op_flags,
+               bool for_write)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct bio *bio;
 
-       bio = f2fs_grab_read_bio(inode, blkaddr, 1, op_flags,
-                                       folio->index, for_write);
+       bio = f2fs_grab_read_bio(inode, vi, blkaddr, 1, op_flags, folio->index,
+                       for_write);
 
        /* wait for GCed page writeback via META_MAPPING */
        f2fs_wait_on_block_writeback(inode, blkaddr);
@@ -1197,6 +1197,14 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t 
index)
        return err;
 }
 
+static inline struct fsverity_info *f2fs_need_verity(const struct inode *inode,
+               pgoff_t idx)
+{
+       if (idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE))
+               return fsverity_get_info(inode);
+       return NULL;
+}
+
 struct folio *f2fs_get_read_data_folio(struct inode *inode, pgoff_t index,
                blk_opf_t op_flags, bool for_write, pgoff_t *next_pgofs)
 {
@@ -1262,8 +1270,8 @@ struct folio *f2fs_get_read_data_folio(struct inode 
*inode, pgoff_t index,
                return folio;
        }
 
-       f2fs_submit_page_read(inode, folio, dn.data_blkaddr,
-                                               op_flags, for_write);
+       f2fs_submit_page_read(inode, f2fs_need_verity(inode, folio->index),
+                       folio, dn.data_blkaddr, op_flags, for_write);
        return folio;
 
 put_err:
@@ -2067,12 +2075,10 @@ static inline blk_opf_t f2fs_ra_op_flags(struct 
readahead_control *rac)
        return rac ? REQ_RAHEAD : 0;
 }
 
-static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
-                                       unsigned nr_pages,
-                                       struct f2fs_map_blocks *map,
-                                       struct bio **bio_ret,
-                                       sector_t *last_block_in_bio,
-                                       struct readahead_control *rac)
+static int f2fs_read_single_page(struct inode *inode, struct fsverity_info *vi,
+               struct folio *folio, unsigned nr_pages,
+               struct f2fs_map_blocks *map, struct bio **bio_ret,
+               sector_t *last_block_in_bio, struct readahead_control *rac)
 {
        struct bio *bio = *bio_ret;
        const unsigned int blocksize = F2FS_BLKSIZE;
@@ -2124,10 +2130,7 @@ static int f2fs_read_single_page(struct inode *inode, 
struct folio *folio,
        } else {
 zero_out:
                folio_zero_segment(folio, 0, folio_size(folio));
-               if (f2fs_need_verity(inode, index) &&
-                   !fsverity_verify_folio(
-                               *fsverity_info_addr(folio->mapping->host),
-                               folio)) {
+               if (vi && !fsverity_verify_folio(vi, folio)) {
                        ret = -EIO;
                        goto out;
                }
@@ -2149,7 +2152,7 @@ static int f2fs_read_single_page(struct inode *inode, 
struct folio *folio,
                bio = NULL;
        }
        if (bio == NULL)
-               bio = f2fs_grab_read_bio(inode, block_nr, nr_pages,
+               bio = f2fs_grab_read_bio(inode, vi, block_nr, nr_pages,
                                f2fs_ra_op_flags(rac), index,
                                false);
 
@@ -2301,8 +2304,8 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct 
bio **bio_ret,
                }
 
                if (!bio)
-                       bio = f2fs_grab_read_bio(inode, blkaddr, nr_pages - i,
-                                       f2fs_ra_op_flags(rac),
+                       bio = f2fs_grab_read_bio(inode, cc->vi, blkaddr,
+                                       nr_pages - i, f2fs_ra_op_flags(rac),
                                        folio->index, for_write);
 
                if (!bio_add_folio(bio, folio, blocksize, 0))
@@ -2364,6 +2367,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
 #endif
        unsigned nr_pages = rac ? readahead_count(rac) : 1;
        unsigned max_nr_pages = nr_pages;
+       struct fsverity_info *vi = NULL;
        int ret = 0;
        bool first_folio = true;
 
@@ -2391,9 +2395,9 @@ static int f2fs_mpage_readpages(struct inode *inode,
                }
 
                if (first_folio) {
-                       if (f2fs_need_verity(inode, folio->index))
-                               fsverity_readahead(*fsverity_info_addr(inode),
-                                               folio, nr_pages);
+                       vi = f2fs_need_verity(inode, folio->index);
+                       if (vi)
+                               fsverity_readahead(vi, folio, nr_pages);
                        first_folio = false;
                }
 
@@ -2405,6 +2409,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
 
                /* there are remained compressed pages, submit them */
                if (!f2fs_cluster_can_merge_page(&cc, index)) {
+                       cc.vi = vi;
                        ret = f2fs_read_multi_pages(&cc, &bio,
                                                max_nr_pages,
                                                &last_block_in_bio,
@@ -2438,8 +2443,8 @@ static int f2fs_mpage_readpages(struct inode *inode,
 read_single_page:
 #endif
 
-               ret = f2fs_read_single_page(inode, folio, max_nr_pages, &map,
-                                       &bio, &last_block_in_bio, rac);
+               ret = f2fs_read_single_page(inode, vi, folio, max_nr_pages,
+                                       &map, &bio, &last_block_in_bio, rac);
                if (ret) {
 #ifdef CONFIG_F2FS_FS_COMPRESSION
 set_error_page:
@@ -2455,6 +2460,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
                if (f2fs_compressed_file(inode)) {
                        /* last page */
                        if (nr_pages == 1 && !f2fs_cluster_is_empty(&cc)) {
+                               cc.vi = vi;
                                ret = f2fs_read_multi_pages(&cc, &bio,
                                                        max_nr_pages,
                                                        &last_block_in_bio,
@@ -3653,6 +3659,7 @@ static int f2fs_write_begin(const struct kiocb *iocb,
                }
                f2fs_submit_page_read(use_cow ?
                                F2FS_I(inode)->cow_inode : inode,
+                               NULL, /* can't write to fsverity files */
                                folio, blkaddr, 0, true);
 
                folio_lock(folio);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 20edbb99b814..f2fcadc7a6fe 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1603,6 +1603,7 @@ struct compress_ctx {
        size_t clen;                    /* valid data length in cbuf */
        void *private;                  /* payload buffer for specified 
compression algorithm */
        void *private2;                 /* extra payload buffer */
+       struct fsverity_info *vi;       /* verity info if needed */
 };
 
 /* compress context for write IO path */
@@ -1658,7 +1659,7 @@ struct decompress_io_ctx {
        refcount_t refcnt;
 
        bool failed;                    /* IO error occurred before 
decompression? */
-       bool need_verity;               /* need fs-verity verification after 
decompression? */
+       struct fsverity_info *vi;       /* fs-verity context if needed */
        unsigned char compress_algorithm;       /* backup algorithm type */
        void *private;                  /* payload buffer for specified 
decompression algorithm */
        void *private2;                 /* extra payload buffer */
@@ -4886,12 +4887,6 @@ static inline bool f2fs_allow_multi_device_dio(struct 
f2fs_sb_info *sbi,
        return sbi->aligned_blksize;
 }
 
-static inline bool f2fs_need_verity(const struct inode *inode, pgoff_t idx)
-{
-       return fsverity_active(inode) &&
-              idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE);
-}
-
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 extern int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
                                        unsigned long type, enum fault_option 
fo);
-- 
2.47.3



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to