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

fsverity: use a hashtable to find the fsverity_info



Use the kernel's resizable hash table (rhashtable) to find the
fsverity_info.  This way file systems that want to support fsverity don't
have to bloat every inode in the system with an extra pointer.  The
trade-off is that looking up the fsverity_info is a bit more expensive
now, but the main operations are still dominated by I/O and hashing
overhead.

The rhashtable implementations requires no external synchronization, and
the _fast versions of the APIs provide the RCU critical sections required
by the implementation.  Because struct fsverity_info is only removed on
inode eviction and does not contain a reference count, there is no need
for an extended critical section to grab a reference or validate the
object state.  The file open path uses rhashtable_lookup_get_insert_fast,
which can either find an existing object for the hash key or insert a
new one in a single atomic operation, so that concurrent opens never
instantiate duplicate fsverity_info structure.  FS_IOC_ENABLE_VERITY must
already be synchronized by a combination of i_rwsem and file system flags
and uses rhashtable_lookup_insert_fast, which errors out on an existing
object for the hash key as an additional safety check.

Because insertion into the hash table now happens before S_VERITY is set,
fsverity just becomes a barrier and a flag check and doesn't have to look
up the fsverity_info at all, so there is only a single lookup per
->read_folio or ->readahead invocation.  For btrfs there is an additional
one for each bio completion, while for ext4 and f2fs the fsverity_info
is stored in the per-I/O context and reused for the completion workqueue.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Link: https://lore.kernel.org/r/20260202060754.270269-12-hch@lst.de


[EB: folded in fix for missing fsverity_free_info()]
Signed-off-by: default avatarEric Biggers <ebiggers@kernel.org>
parent b0160e45
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -339,10 +339,6 @@ struct btrfs_inode {

	struct rw_semaphore i_mmap_lock;

#ifdef CONFIG_FS_VERITY
	struct fsverity_info *i_verity_info;
#endif

	struct inode vfs_inode;
};

+0 −3
Original line number Diff line number Diff line
@@ -8097,9 +8097,6 @@ static void init_once(void *foo)
	struct btrfs_inode *ei = foo;

	inode_init_once(&ei->vfs_inode);
#ifdef CONFIG_FS_VERITY
	ei->i_verity_info = NULL;
#endif
}

void __cold btrfs_destroy_cachep(void)
+0 −2
Original line number Diff line number Diff line
@@ -795,8 +795,6 @@ static int btrfs_write_merkle_tree_block(struct file *file, const void *buf,
}

const struct fsverity_operations btrfs_verityops = {
	.inode_info_offs         = (int)offsetof(struct btrfs_inode, i_verity_info) -
				   (int)offsetof(struct btrfs_inode, vfs_inode),
	.begin_enable_verity     = btrfs_begin_enable_verity,
	.end_enable_verity       = btrfs_end_enable_verity,
	.get_verity_descriptor   = btrfs_get_verity_descriptor,
+0 −4
Original line number Diff line number Diff line
@@ -1205,10 +1205,6 @@ struct ext4_inode_info {
#ifdef CONFIG_FS_ENCRYPTION
	struct fscrypt_inode_info *i_crypt_info;
#endif

#ifdef CONFIG_FS_VERITY
	struct fsverity_info *i_verity_info;
#endif
};

/*
+0 −3
Original line number Diff line number Diff line
@@ -1484,9 +1484,6 @@ static void init_once(void *foo)
#ifdef CONFIG_FS_ENCRYPTION
	ei->i_crypt_info = NULL;
#endif
#ifdef CONFIG_FS_VERITY
	ei->i_verity_info = NULL;
#endif
}

static int __init init_inodecache(void)
Loading