mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-02 02:19:54 -04:00
fsverity: push out fsverity_info lookup
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>
This commit is contained in:
committed by
Eric Biggers
parent
7e36e04495
commit
47bc2ac9b6
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 @@ static int f2fs_read_single_page(struct inode *inode, struct folio *folio,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@ static bool verify_data_block(struct fsverity_info *vi,
|
||||
|
||||
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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user