Commit d0b57f09 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Eric Biggers
Browse files

ext4: consolidate fsverity_info lookup



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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Link: https://lore.kernel.org/r/20260202060754.270269-9-hch@lst.de


Signed-off-by: default avatarEric Biggers <ebiggers@kernel.org>
parent f6ae956d
Loading
Loading
Loading
Loading
+22 −24
Original line number Diff line number Diff line
@@ -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 @@ static int ext4_mpage_readpages(struct inode *inode,
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)