Re: [PATCH RFC DRAFT DOESNOTBUILD] inode: free up more space

Jan Kara
2025-07-17T10:54:51Z

On Thu 17-07-25 10:32:07, Christian Brauner wrote:
> 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 */
> };

Well, but if we moved also fsverity & quota & what not into
vfs_inode_adjunct the benefit of such structure would be diminishing? Or
am I misunderstanding the proposal? I think that the new method should
strive for each filesystem inode to store only the info it needs and not
waste space for things it isn't interested in.

Honza

> 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)
> {
--
Jan Kara <jack@suse.com>
SUSE Labs, CR