Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsverity: add support for info in fs-specific part of inode

Add an inode_info_offs field to struct fsverity_operations, and update
fs/verity/ to support it. When set to a nonzero value, it specifies the
offset to the fsverity_info pointer within the filesystem-specific part
of the inode structure, to be used instead of inode::i_verity_info.

Since this makes inode::i_verity_info no longer necessarily used, update
comments that mentioned it.

This is a prerequisite for a later commit that removes
inode::i_verity_info, saving memory and improving cache efficiency on
filesystems that don't support fsverity.

Co-developed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Link: https://lore.kernel.org/20250810075706.172910-9-ebiggers@kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Eric Biggers and committed by
Christian Brauner
2a7349ad ab90c2d2

+55 -29
+3 -3
fs/verity/enable.c
··· 284 284 /* Successfully enabled verity */ 285 285 286 286 /* 287 - * Readers can start using ->i_verity_info immediately, so it 288 - * can't be rolled back once set. So don't set it until just 289 - * after the filesystem has successfully enabled verity. 287 + * Readers can start using the inode's verity info immediately, 288 + * so it can't be rolled back once set. So don't set it until 289 + * just after the filesystem has successfully enabled verity. 290 290 */ 291 291 fsverity_set_info(inode, vi); 292 292 }
+5 -4
fs/verity/fsverity_private.h
··· 63 63 * fsverity_info - cached verity metadata for an inode 64 64 * 65 65 * When a verity file is first opened, an instance of this struct is allocated 66 - * and stored in ->i_verity_info; it remains until the inode is evicted. It 67 - * caches information about the Merkle tree that's needed to efficiently verify 68 - * data read from the file. It also caches the file digest. The Merkle tree 69 - * pages themselves are not cached here, but the filesystem may cache them. 66 + * and a pointer to it is stored in the file's in-memory inode. It remains 67 + * until the inode is evicted. It caches information about the Merkle tree 68 + * that's needed to efficiently verify data read from the file. It also caches 69 + * the file digest. The Merkle tree pages themselves are not cached here, but 70 + * the filesystem may cache them. 70 71 */ 71 72 struct fsverity_info { 72 73 struct merkle_tree_params tree_params;
+12 -11
fs/verity/open.c
··· 244 244 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi) 245 245 { 246 246 /* 247 - * Multiple tasks may race to set ->i_verity_info, so use 248 - * cmpxchg_release(). This pairs with the smp_load_acquire() in 249 - * fsverity_get_info(). I.e., here we publish ->i_verity_info with a 250 - * RELEASE barrier so that other tasks can ACQUIRE it. 247 + * Multiple tasks may race to set the inode's verity info pointer, so 248 + * use cmpxchg_release(). This pairs with the smp_load_acquire() in 249 + * fsverity_get_info(). I.e., publish the pointer with a RELEASE 250 + * barrier so that other tasks can ACQUIRE it. 251 251 */ 252 - if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) { 253 - /* Lost the race, so free the fsverity_info we allocated. */ 252 + if (cmpxchg_release(fsverity_info_addr(inode), NULL, vi) != NULL) { 253 + /* Lost the race, so free the verity info we allocated. */ 254 254 fsverity_free_info(vi); 255 255 /* 256 - * Afterwards, the caller may access ->i_verity_info directly, 257 - * so make sure to ACQUIRE the winning fsverity_info. 256 + * Afterwards, the caller may access the inode's verity info 257 + * directly, so make sure to ACQUIRE the winning verity info. 258 258 */ 259 259 (void)fsverity_get_info(inode); 260 260 } ··· 350 350 return 0; 351 351 } 352 352 353 - /* Ensure the inode has an ->i_verity_info */ 354 353 static int ensure_verity_info(struct inode *inode) 355 354 { 356 355 struct fsverity_info *vi = fsverity_get_info(inode); ··· 394 395 395 396 void __fsverity_cleanup_inode(struct inode *inode) 396 397 { 397 - fsverity_free_info(inode->i_verity_info); 398 - inode->i_verity_info = NULL; 398 + struct fsverity_info **vi_addr = fsverity_info_addr(inode); 399 + 400 + fsverity_free_info(*vi_addr); 401 + *vi_addr = NULL; 399 402 } 400 403 EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode); 401 404
+1 -1
fs/verity/verify.c
··· 245 245 unsigned long max_ra_pages) 246 246 { 247 247 struct inode *inode = data_folio->mapping->host; 248 - struct fsverity_info *vi = inode->i_verity_info; 248 + struct fsverity_info *vi = *fsverity_info_addr(inode); 249 249 const unsigned int block_size = vi->tree_params.block_size; 250 250 u64 pos = (u64)data_folio->index << PAGE_SHIFT; 251 251
+34 -10
include/linux/fsverity.h
··· 28 28 29 29 /* Verity operations for filesystems */ 30 30 struct fsverity_operations { 31 + /** 32 + * The offset of the pointer to struct fsverity_info in the 33 + * filesystem-specific part of the inode, relative to the beginning of 34 + * the common part of the inode (the 'struct inode'). 35 + */ 36 + ptrdiff_t inode_info_offs; 31 37 32 38 /** 33 39 * Begin enabling verity on the given file. ··· 130 124 131 125 #ifdef CONFIG_FS_VERITY 132 126 127 + static inline struct fsverity_info ** 128 + fsverity_info_addr(const struct inode *inode) 129 + { 130 + if (inode->i_sb->s_vop->inode_info_offs == 0) 131 + return (struct fsverity_info **)&inode->i_verity_info; 132 + return (void *)inode + inode->i_sb->s_vop->inode_info_offs; 133 + } 134 + 133 135 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) 134 136 { 135 137 /* 136 - * Pairs with the cmpxchg_release() in fsverity_set_info(). 137 - * I.e., another task may publish ->i_verity_info concurrently, 138 - * executing a RELEASE barrier. We need to use smp_load_acquire() here 139 - * to safely ACQUIRE the memory the other task published. 138 + * Since this function can be called on inodes belonging to filesystems 139 + * that don't support fsverity at all, and fsverity_info_addr() doesn't 140 + * work on such filesystems, we have to start with an IS_VERITY() check. 141 + * Checking IS_VERITY() here is also useful to minimize the overhead of 142 + * fsverity_active() on non-verity files. 140 143 */ 141 - return smp_load_acquire(&inode->i_verity_info); 144 + if (!IS_VERITY(inode)) 145 + return NULL; 146 + 147 + /* 148 + * Pairs with the cmpxchg_release() in fsverity_set_info(). I.e., 149 + * another task may publish the inode's verity info concurrently, 150 + * executing a RELEASE barrier. Use smp_load_acquire() here to safely 151 + * ACQUIRE the memory the other task published. 152 + */ 153 + return smp_load_acquire(fsverity_info_addr(inode)); 142 154 } 143 155 144 156 /* enable.c */ ··· 180 156 * fsverity_cleanup_inode() - free the inode's verity info, if present 181 157 * @inode: an inode being evicted 182 158 * 183 - * Filesystems must call this on inode eviction to free ->i_verity_info. 159 + * Filesystems must call this on inode eviction to free the inode's verity info. 184 160 */ 185 161 static inline void fsverity_cleanup_inode(struct inode *inode) 186 162 { 187 - if (inode->i_verity_info) 163 + if (*fsverity_info_addr(inode)) 188 164 __fsverity_cleanup_inode(inode); 189 165 } 190 166 ··· 291 267 * fsverity_active() - do reads from the inode need to go through fs-verity? 292 268 * @inode: inode to check 293 269 * 294 - * This checks whether ->i_verity_info has been set. 270 + * This checks whether the inode's verity info has been set. 295 271 * 296 272 * Filesystems call this from ->readahead() to check whether the pages need to 297 273 * be verified or not. Don't use IS_VERITY() for this purpose; it's subject to 298 274 * a race condition where the file is being read concurrently with 299 - * FS_IOC_ENABLE_VERITY completing. (S_VERITY is set before ->i_verity_info.) 275 + * FS_IOC_ENABLE_VERITY completing. (S_VERITY is set before the verity info.) 300 276 * 301 277 * Return: true if reads need to go through fs-verity, otherwise false 302 278 */ ··· 311 287 * @filp: the struct file being set up 312 288 * 313 289 * When opening a verity file, deny the open if it is for writing. Otherwise, 314 - * set up the inode's ->i_verity_info if not already done. 290 + * set up the inode's verity info if not already done. 315 291 * 316 292 * When combined with fscrypt, this must be called after fscrypt_file_open(). 317 293 * Otherwise, we won't have the key set up to decrypt the verity metadata.