On Wed, Jul 16, 2025 at 04:10:30PM +0200, Christoph Hellwig wrote: > On Wed, Jul 16, 2025 at 03:08:53PM +0100, Matthew Wilcox wrote: > > struct filemap_inode { > > struct inode inode; > > struct address_space i_mapping; > > struct fscrypt_struct i_fscrypt; > > struct fsverity_struct i_fsverity; > > struct quota_struct i_quota; > > }; > > > > struct ext4_inode { > > struct filemap_inode inode; > > ... > > }; > > > > saves any messing with i_ops and offsets. > > I still wastest a lot of space for XFS which only needs inode > and i_mapping of those. As would most ext4 file systems.. We can do a hybrid approach: diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 2bc6a3ac2b8e..dda45b3f2122 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1198,9 +1198,7 @@ struct ext4_inode_info { kprojid_t i_projid; -#ifdef CONFIG_FS_ENCRYPTION - struct fscrypt_inode_info *i_fscrypt_info; -#endif + struct vfs_inode_adjunct i_adjunct; /* Adjunct data for inode */ }; /* diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 676d33a7d842..f257ac048f3b 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -981,17 +981,19 @@ const struct file_operations ext4_file_operations = { }; const struct inode_operations ext4_file_inode_operations = { - .setattr = ext4_setattr, - .getattr = ext4_file_getattr, - .listxattr = ext4_listxattr, - .get_inode_acl = ext4_get_acl, - .set_acl = ext4_set_acl, - .fiemap = ext4_fiemap, - .fileattr_get = ext4_fileattr_get, - .fileattr_set = ext4_fileattr_set, + .i_adjunct_offset = offsetof(struct ext4_inode_info, vfs_inode) - + offsetof(struct ext4_inode_info, i_adjunct), + .setattr = ext4_setattr, + .getattr = ext4_file_getattr, + .listxattr = ext4_listxattr, + .get_inode_acl = ext4_get_acl, + .set_acl = ext4_set_acl, + .fiemap = ext4_fiemap, + .fileattr_get = ext4_fileattr_get, + .fileattr_set = ext4_fileattr_set, #ifdef CONFIG_FS_ENCRYPTION - .get_fscrypt = ext4_get_fscrypt, - .set_fscrypt = ext4_set_fscrypt, + .get_fscrypt = ext4_get_fscrypt, + .set_fscrypt = ext4_set_fscrypt, #endif }; diff --git a/include/linux/fs.h b/include/linux/fs.h index d8f242a2f431..c4752c80710e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -789,6 +789,12 @@ struct inode { void *i_private; /* fs or device private pointer */ } __randomize_layout; +struct vfs_inode_adjunct { +#ifdef CONFIG_FS_ENCRYPTION + struct fscrypt_inode_info *i_fscrypt_info; +#endif +}; + static inline void inode_set_cached_link(struct inode *inode, char *link, int linklen) { VFS_WARN_ON_INODE(strlen(link) != linklen, inode); @@ -2217,6 +2223,7 @@ int wrap_directory_iterator(struct file *, struct dir_context *, { return wrap_directory_iterator(file, ctx, x); } struct inode_operations { + ptrdiff_t i_adjunct_offset; struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); int (*permission) (struct mnt_idmap *, struct inode *, int); diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 1aa474232fa7..fa0080869dc1 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -195,6 +195,12 @@ struct fscrypt_operations { int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name, struct dentry *dentry, unsigned int flags); +static inline struct fscrypt_inode_info *CRYPT_I(struct inode *inode) +{ + struct vfs_inode_adjunct *p = ((void *)inode) - inode->i_op->i_adjunct_offset; + return p->i_fscrypt_info; +} + static inline int vfs_fscrypt_inode_set(struct fscrypt_inode_info *crypt_info, struct fscrypt_inode_info **p) {