On Tue, 2025-07-15 at 16:35 +0200, Christian Brauner wrote: > struct inode is bloated as everyone is aware and we should try and > shrink it as that's potentially a lot of memory savings. I've already > freed up around 8 bytes but we can probably do better. > > There's a bunch of stuff that got shoved into struct inode that I don't > think deserves a spot in there. There are two members I'm currently > particularly interested in: > > (1) #ifdef CONFIG_FS_ENCRYPTION > struct fscrypt_inode_info *i_crypt_info; > #endif > > ceph, ext4, f2fs, ubifs > > (2) #ifdef CONFIG_FS_VERITY > struct fsverity_info *i_verity_info; > #endif > > btrfs, ext4, f2fs > > So we have 4 users for fscrypt and 3 users for fsverity with both > features having been around for a decent amount of time. > > For all other filesystems the 16 bytes are just wasted bloating inodes > for every pseudo filesystem and most other regular filesystems. > > We should be able to move both of these out of struct inode by adding > inode operations and making it the filesystem's responsibility to > accommodate the information in their respective inodes. > > Unless there are severe performance penalties for the extra pointer > dereferences getting our hands on 16 bytes is a good reason to at least > consider doing this. > > I've drafted one way of doing this using ext4 as my victim^wexample. I'd > like to hear some early feedback whether this is something we would want > to pursue. > > Build failures very much expected! > > Not-Signed-off-by: Christian Brauner <brauner@xxxxxxxxxx> > --- > fs/crypto/bio.c | 2 +- > fs/crypto/crypto.c | 8 ++++---- > fs/crypto/fname.c | 8 ++++---- > fs/crypto/fscrypt_private.h | 3 +-- > fs/crypto/hooks.c | 2 +- > fs/crypto/inline_crypt.c | 10 +++++----- > fs/crypto/keysetup.c | 21 ++++---------------- > fs/crypto/policy.c | 8 ++++---- > fs/ext4/ext4.h | 9 +++++++++ > fs/ext4/file.c | 4 ++++ > fs/ext4/namei.c | 22 +++++++++++++++++++++ > fs/ext4/super.c | 6 +++++- > fs/ext4/symlink.c | 12 ++++++++++++ > include/linux/fs.h | 9 +++++---- > include/linux/fscrypt.h | 47 ++++++++++++++++++++++++++++++--------------- > 15 files changed, 112 insertions(+), 59 deletions(-) > > diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c > index 0ad8c30b8fa5..f541e6b3a9cc 100644 > --- a/fs/crypto/bio.c > +++ b/fs/crypto/bio.c > @@ -111,7 +111,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode, > int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, > sector_t pblk, unsigned int len) > { > - const struct fscrypt_inode_info *ci = inode->i_crypt_info; > + const struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > const unsigned int du_bits = ci->ci_data_unit_bits; > const unsigned int du_size = 1U << du_bits; > const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits; > diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c > index b74b5937e695..c480f6867101 100644 > --- a/fs/crypto/crypto.c > +++ b/fs/crypto/crypto.c > @@ -181,7 +181,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio, > size_t len, size_t offs, gfp_t gfp_flags) > { > const struct inode *inode = folio->mapping->host; > - const struct fscrypt_inode_info *ci = inode->i_crypt_info; > + const struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > const unsigned int du_bits = ci->ci_data_unit_bits; > const unsigned int du_size = 1U << du_bits; > struct page *ciphertext_page; > @@ -241,7 +241,7 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page, > { > if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units)) > return -EOPNOTSUPP; > - return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT, > + return fscrypt_crypt_data_unit(inode->i_op->get_fscrypt(inode), FS_ENCRYPT, > lblk_num, page, page, len, offs, > gfp_flags); > } > @@ -265,7 +265,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len, > size_t offs) > { > const struct inode *inode = folio->mapping->host; > - const struct fscrypt_inode_info *ci = inode->i_crypt_info; > + const struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > const unsigned int du_bits = ci->ci_data_unit_bits; > const unsigned int du_size = 1U << du_bits; > u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) + > @@ -316,7 +316,7 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page, > { > if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units)) > return -EOPNOTSUPP; > - return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT, > + return fscrypt_crypt_data_unit(inode->i_op->get_fscrypt(inode), FS_DECRYPT, > lblk_num, page, page, len, offs, > GFP_NOFS); > } > diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c > index 010f9c0a4c2f..a0317df113a9 100644 > --- a/fs/crypto/fname.c > +++ b/fs/crypto/fname.c > @@ -94,7 +94,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, > { > struct skcipher_request *req = NULL; > DECLARE_CRYPTO_WAIT(wait); > - const struct fscrypt_inode_info *ci = inode->i_crypt_info; > + const struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > struct crypto_skcipher *tfm = ci->ci_enc_key.tfm; > union fscrypt_iv iv; > struct scatterlist sg; > @@ -151,7 +151,7 @@ static int fname_decrypt(const struct inode *inode, > struct skcipher_request *req = NULL; > DECLARE_CRYPTO_WAIT(wait); > struct scatterlist src_sg, dst_sg; > - const struct fscrypt_inode_info *ci = inode->i_crypt_info; > + const struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > struct crypto_skcipher *tfm = ci->ci_enc_key.tfm; > union fscrypt_iv iv; > int res; > @@ -293,7 +293,7 @@ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy, > bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, > u32 max_len, u32 *encrypted_len_ret) > { > - return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy, > + return __fscrypt_fname_encrypted_size(&inode->i_op->get_fscrypt(inode)->ci_policy, > orig_len, max_len, > encrypted_len_ret); > } > @@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name); > */ > u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name) > { > - const struct fscrypt_inode_info *ci = dir->i_crypt_info; > + const struct fscrypt_inode_info *ci = dir->i_op->get_fscrypt(dir); > > WARN_ON_ONCE(!ci->ci_dirhash_key_initialized); > > diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h > index c1d92074b65c..ddc3c86494cf 100644 > --- a/fs/crypto/fscrypt_private.h > +++ b/fs/crypto/fscrypt_private.h > @@ -231,8 +231,7 @@ struct fscrypt_prepared_key { > * fscrypt_inode_info - the "encryption key" for an inode > * > * When an encrypted file's key is made available, an instance of this struct is > - * allocated and stored in ->i_crypt_info. Once created, it remains until the > - * inode is evicted. > + * allocated and stored. Once created, it remains until the inode is evicted. > */ > struct fscrypt_inode_info { > > diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c > index d8d5049b8fe1..a45763da352e 100644 > --- a/fs/crypto/hooks.c > +++ b/fs/crypto/hooks.c > @@ -197,7 +197,7 @@ int fscrypt_prepare_setflags(struct inode *inode, > err = fscrypt_require_key(inode); > if (err) > return err; > - ci = inode->i_crypt_info; > + ci = inode->i_op->get_fscrypt(inode); > if (ci->ci_policy.version != FSCRYPT_POLICY_V2) > return -EINVAL; > mk = ci->ci_master_key; > diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c > index 1d008c440cb6..f5a6560a9c2e 100644 > --- a/fs/crypto/inline_crypt.c > +++ b/fs/crypto/inline_crypt.c > @@ -262,7 +262,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb, > > bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) > { > - return inode->i_crypt_info->ci_inlinecrypt; > + return inode->i_op->get_fscrypt(inode)->ci_inlinecrypt; > } > EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto); > > @@ -306,7 +306,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, > > if (!fscrypt_inode_uses_inline_crypto(inode)) > return; > - ci = inode->i_crypt_info; > + ci = inode->i_op->get_fscrypt(inode); > > fscrypt_generate_dun(ci, first_lblk, dun); > bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask); > @@ -396,10 +396,10 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, > * uses the same pointer. I.e., there's currently no need to support > * merging requests where the keys are the same but the pointers differ. > */ > - if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key) > + if (bc->bc_key != inode->i_op->get_fscrypt(inode)->ci_enc_key.blk_key) > return false; > > - fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun); > + fscrypt_generate_dun(inode->i_op->get_fscrypt(inode), next_lblk, next_dun); > return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); > } > EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); > @@ -501,7 +501,7 @@ u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks) > if (nr_blocks <= 1) > return nr_blocks; > > - ci = inode->i_crypt_info; > + ci = inode->i_op->get_fscrypt(inode); > if (!(fscrypt_policy_flags(&ci->ci_policy) & > FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) > return nr_blocks; > diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c > index 0d71843af946..90e1ea83c573 100644 > --- a/fs/crypto/keysetup.c > +++ b/fs/crypto/keysetup.c > @@ -568,7 +568,7 @@ static int setup_file_encryption_key(struct fscrypt_inode_info *ci, > return err; > } > > -static void put_crypt_info(struct fscrypt_inode_info *ci) > +void put_crypt_info(struct fscrypt_inode_info *ci) > { > struct fscrypt_master_key *mk; > > @@ -597,6 +597,7 @@ static void put_crypt_info(struct fscrypt_inode_info *ci) > memzero_explicit(ci, sizeof(*ci)); > kmem_cache_free(fscrypt_inode_info_cachep, ci); > } > +EXPORT_SYMBOL(put_crypt_info); > > static int > fscrypt_setup_encryption_info(struct inode *inode, > @@ -644,7 +645,7 @@ fscrypt_setup_encryption_info(struct inode *inode, > * fscrypt_get_inode_info(). I.e., here we publish ->i_crypt_info with > * a RELEASE barrier so that other tasks can ACQUIRE it. > */ > - if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) { > + if (!inode->i_op->set_fscrypt(crypt_info, inode)) { > /* > * We won the race and set ->i_crypt_info to our crypt_info. > * Now link it into the master key's inode list. > @@ -788,20 +789,6 @@ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, > } > EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode); > > -/** > - * fscrypt_put_encryption_info() - free most of an inode's fscrypt data > - * @inode: an inode being evicted > - * > - * Free the inode's fscrypt_inode_info. Filesystems must call this when the > - * inode is being evicted. An RCU grace period need not have elapsed yet. > - */ > -void fscrypt_put_encryption_info(struct inode *inode) > -{ > - put_crypt_info(inode->i_crypt_info); > - inode->i_crypt_info = NULL; > -} > -EXPORT_SYMBOL(fscrypt_put_encryption_info); > - > /** > * fscrypt_free_inode() - free an inode's fscrypt data requiring RCU delay > * @inode: an inode being freed > @@ -830,7 +817,7 @@ EXPORT_SYMBOL(fscrypt_free_inode); > */ > int fscrypt_drop_inode(struct inode *inode) > { > - const struct fscrypt_inode_info *ci = fscrypt_get_inode_info(inode); > + const struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > > /* > * If ci is NULL, then the inode doesn't have an encryption key set up > diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c > index 701259991277..694d1ed26eeb 100644 > --- a/fs/crypto/policy.c > +++ b/fs/crypto/policy.c > @@ -436,7 +436,7 @@ static int fscrypt_get_policy(struct inode *inode, union fscrypt_policy *policy) > union fscrypt_context ctx; > int ret; > > - ci = fscrypt_get_inode_info(inode); > + ci = inode->i_op->get_fscrypt(inode); > if (ci) { > /* key available, use the cached policy */ > *policy = ci->ci_policy; > @@ -725,7 +725,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir) > err = fscrypt_require_key(dir); > if (err) > return ERR_PTR(err); > - return &dir->i_crypt_info->ci_policy; > + return &dir->i_op->get_fscrypt(dir)->ci_policy; > } > > return fscrypt_get_dummy_policy(dir->i_sb); > @@ -744,7 +744,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir) > */ > int fscrypt_context_for_new_inode(void *ctx, struct inode *inode) > { > - struct fscrypt_inode_info *ci = inode->i_crypt_info; > + struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > > BUILD_BUG_ON(sizeof(union fscrypt_context) != > FSCRYPT_SET_CONTEXT_MAX_SIZE); > @@ -769,7 +769,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode); > */ > int fscrypt_set_context(struct inode *inode, void *fs_data) > { > - struct fscrypt_inode_info *ci = inode->i_crypt_info; > + struct fscrypt_inode_info *ci = inode->i_op->get_fscrypt(inode); > union fscrypt_context ctx; > int ctxsize; > > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h > index 18373de980f2..34685eec6245 100644 > --- a/fs/ext4/ext4.h > +++ b/fs/ext4/ext4.h > @@ -1197,6 +1197,10 @@ struct ext4_inode_info { > __u32 i_csum_seed; > > kprojid_t i_projid; > + > +#ifdef CONFIG_FS_ENCRYPTION > + struct fscrypt_inode_info *i_fscrypt_info; > +#endif > }; > > /* > @@ -3904,6 +3908,11 @@ static inline bool ext4_inode_can_atomic_write(struct inode *inode) > extern int ext4_block_write_begin(handle_t *handle, struct folio *folio, > loff_t pos, unsigned len, > get_block_t *get_block); > +#ifdef CONFIG_FS_ENCRYPTION > +struct fscrypt_inode_info *ext4_get_fscrypt(const struct inode *inode); > +int ext4_set_fscrypt(struct fscrypt_inode_info *fscrypt_info,struct inode *inode); > +#endif > + > #endif /* __KERNEL__ */ > > #define EFSBADCRC EBADMSG /* Bad CRC detected */ > diff --git a/fs/ext4/file.c b/fs/ext4/file.c > index 21df81347147..676d33a7d842 100644 > --- a/fs/ext4/file.c > +++ b/fs/ext4/file.c > @@ -989,5 +989,9 @@ const struct inode_operations ext4_file_inode_operations = { > .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, > +#endif > }; > > diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c > index a178ac229489..a27c5925c836 100644 > --- a/fs/ext4/namei.c > +++ b/fs/ext4/namei.c > @@ -4203,6 +4203,20 @@ static int ext4_rename2(struct mnt_idmap *idmap, > return ext4_rename(idmap, old_dir, old_dentry, new_dir, new_dentry, flags); > } > > +#ifdef CONFIG_FS_ENCRYPTION > +struct fscrypt_inode_info *ext4_get_fscrypt(const struct inode *inode) > +{ > + struct ext4_inode_info *ei = EXT4_I(inode); > + return fscrypt_inode_info_get(&ei->i_fscrypt_info); > +} > + > +int ext4_set_fscrypt(struct fscrypt_inode_info *fscrypt_info, struct inode *inode) > +{ > + struct ext4_inode_info *ei = EXT4_I(inode); > + return fscrypt_inode_info_set(fscrypt_info, &ei->i_fscrypt_info); > +} > +#endif > + > /* > * directories can handle most operations... > */ > @@ -4225,6 +4239,10 @@ const struct inode_operations ext4_dir_inode_operations = { > .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, > +#endif > }; > > const struct inode_operations ext4_special_inode_operations = { > @@ -4233,4 +4251,8 @@ const struct inode_operations ext4_special_inode_operations = { > .listxattr = ext4_listxattr, > .get_inode_acl = ext4_get_acl, > .set_acl = ext4_set_acl, > +#ifdef CONFIG_FS_ENCRYPTION > + .get_fscrypt = ext4_get_fscrypt, > + .set_fscrypt = ext4_set_fscrypt, > +#endif > }; > diff --git a/fs/ext4/super.c b/fs/ext4/super.c > index c7d39da7e733..972b057b0d00 100644 > --- a/fs/ext4/super.c > +++ b/fs/ext4/super.c > @@ -1412,6 +1412,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) > INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work); > ext4_fc_init_inode(&ei->vfs_inode); > spin_lock_init(&ei->i_fc_lock); > +#ifdef CONFIG_FS_ENCRYPTION > + ei->i_fscrypt_info = NULL; > +#endif > return &ei->vfs_inode; > } > > @@ -1509,7 +1512,8 @@ void ext4_clear_inode(struct inode *inode) > jbd2_free_inode(EXT4_I(inode)->jinode); > EXT4_I(inode)->jinode = NULL; > } > - fscrypt_put_encryption_info(inode); > + put_crypt_info(EXT4_I(inode)->i_fscrypt_info); > + EXT4_I(inode)->i_fscrypt_info = NULL; > fsverity_cleanup_inode(inode); > } > > diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c > index 645240cc0229..ee3f71e406ce 100644 > --- a/fs/ext4/symlink.c > +++ b/fs/ext4/symlink.c > @@ -119,6 +119,10 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = { > .setattr = ext4_setattr, > .getattr = ext4_encrypted_symlink_getattr, > .listxattr = ext4_listxattr, > +#ifdef CONFIG_FS_ENCRYPTION > + .get_fscrypt = ext4_get_fscrypt, > + .set_fscrypt = ext4_set_fscrypt, > +#endif > }; > > const struct inode_operations ext4_symlink_inode_operations = { > @@ -126,6 +130,10 @@ const struct inode_operations ext4_symlink_inode_operations = { > .setattr = ext4_setattr, > .getattr = ext4_getattr, > .listxattr = ext4_listxattr, > +#ifdef CONFIG_FS_ENCRYPTION > + .get_fscrypt = ext4_get_fscrypt, > + .set_fscrypt = ext4_set_fscrypt, > +#endif > }; > > const struct inode_operations ext4_fast_symlink_inode_operations = { > @@ -133,4 +141,8 @@ const struct inode_operations ext4_fast_symlink_inode_operations = { > .setattr = ext4_setattr, > .getattr = ext4_getattr, > .listxattr = ext4_listxattr, > +#ifdef CONFIG_FS_ENCRYPTION > + .get_fscrypt = ext4_get_fscrypt, > + .set_fscrypt = ext4_set_fscrypt, > +#endif > }; > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 96c7925a6551..600b878f41ab 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -778,10 +778,6 @@ struct inode { > struct fsnotify_mark_connector __rcu *i_fsnotify_marks; > #endif > > -#ifdef CONFIG_FS_ENCRYPTION > - struct fscrypt_inode_info *i_crypt_info; > -#endif > - > #ifdef CONFIG_FS_VERITY > struct fsverity_info *i_verity_info; > #endif > @@ -2257,6 +2253,11 @@ struct inode_operations { > struct dentry *dentry, struct fileattr *fa); > int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa); > struct offset_ctx *(*get_offset_ctx)(struct inode *inode); > +#ifdef CONFIG_FS_ENCRYPTION > + struct fscrypt_inode_info *(*get_fscrypt)(const struct inode *inode); > + int (*set_fscrypt)(struct fscrypt_inode_info *fscrypt_info, > + struct inode *inode); > +#endif > } ____cacheline_aligned; > > /* Did the driver provide valid mmap hook configuration? */ > diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h > index 56fad33043d5..7ac612fec6bb 100644 > --- a/include/linux/fscrypt.h > +++ b/include/linux/fscrypt.h > @@ -195,18 +195,6 @@ 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 * > -fscrypt_get_inode_info(const struct inode *inode) > -{ > - /* > - * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info(). > - * I.e., another task may publish ->i_crypt_info concurrently, executing > - * a RELEASE barrier. We need to use smp_load_acquire() here to safely > - * ACQUIRE the memory the other task published. > - */ > - return smp_load_acquire(&inode->i_crypt_info); > -} > - > /** > * fscrypt_needs_contents_encryption() - check whether an inode needs > * contents encryption > @@ -385,7 +373,7 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *arg); > /* keysetup.c */ > int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, > bool *encrypt_ret); > -void fscrypt_put_encryption_info(struct inode *inode); > +void put_crypt_info(struct fscrypt_inode_info *ci); > void fscrypt_free_inode(struct inode *inode); > int fscrypt_drop_inode(struct inode *inode); > > @@ -446,10 +434,37 @@ static inline void fscrypt_set_ops(struct super_block *sb, > { > sb->s_cop = s_cop; > } > + > +static inline int fscrypt_inode_info_set(struct fscrypt_inode_info *crypt_info, > + struct fscrypt_inode_info **p) > +{ > + if (cmpxchg_release(p, NULL, crypt_info) != NULL) > + return -EEXIST; > + return 0; > +} > + > +static inline struct fscrypt_inode_info * > +fscrypt_inode_info_get(struct fscrypt_inode_info **crypt_info) > +{ > + /* > + * Pairs with the cmpxchg_release() in fscrypt_inode_info_set(). I.e., > + * another task may publish crypt_info concurrently, executing a > + * RELEASE barrier. We need to use smp_load_acquire() here to safely > + * ACQUIRE the memory the other task published (could be a READ_ONCE() > + * really). > + */ > + return smp_load_acquire(crypt_info); > +} > #else /* !CONFIG_FS_ENCRYPTION */ > > +static inline int fscrypt_inode_info_set(struct fscrypt_inode_info *crypt_info, > + struct fscrypt_inode_info **p) > +{ > + return 0; > +} > + > static inline struct fscrypt_inode_info * > -fscrypt_get_inode_info(const struct inode *inode) > +fscrypt_inode_info_get(const struct fscrypt_inode_info **crypt_info) > { > return NULL; > } > @@ -639,7 +654,7 @@ static inline int fscrypt_prepare_new_inode(struct inode *dir, > return 0; > } > > -static inline void fscrypt_put_encryption_info(struct inode *inode) > +static inline void put_crypt_info(struct fscrypt_inode_info *ci) > { > return; > } > @@ -930,7 +945,7 @@ static inline bool fscrypt_inode_uses_fs_layer_crypto(const struct inode *inode) > */ > static inline bool fscrypt_has_encryption_key(const struct inode *inode) > { > - return fscrypt_get_inode_info(inode) != NULL; > + return inode->i_op->get_fscrypt(inode) != NULL; > } > > /** > > --- > base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494 > change-id: 20250715-work-inode-fscrypt-2b63b276e793 I like the concept. Debloating struct inode is a great goal, IMO. Fields that are not generally useful should be in the fs-specific inodes. I do wish it weren't quite so cumbersome with having to define _get/_set operations, but I think it's a reasonable tradeoff to get these fields out of struct inode. Cheers! -- Jeff Layton <jlayton@xxxxxxxxxx>