Re: [PATCH 03/10] ext4: Remove EA inode entry from mbcache on inode eviction

Ritesh Harjani
2022-06-16T15:01:28Z

On 22/06/14 06:05PM, Jan Kara wrote:
> Currently we remove EA inode from mbcache as soon as its xattr refcount
> drops to zero. However there can be pending attempts to reuse the inode
> and thus refcount handling code has to handle the situation when
> refcount increases from zero anyway. So save some work and just keep EA
> inode in mbcache until it is getting evicted. At that moment we are sure
> following iget() of EA inode will fail anyway (or wait for eviction to
> finish and load things from the disk again) and so removing mbcache
> entry at that moment is fine and simplifies the code a bit.
>
> CC: stable@vger.kernel.org
> Fixes: 82939d7999df ("ext4: convert to mbcache2")
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
> fs/ext4/inode.c | 2 ++
> fs/ext4/xattr.c | 24 ++++++++----------------
> fs/ext4/xattr.h | 1 +
> 3 files changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 3dce7d058985..7450ee734262 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -177,6 +177,8 @@ void ext4_evict_inode(struct inode *inode)
>
> trace_ext4_evict_inode(inode);
>
> + if (EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL)
> + ext4_evict_ea_inode(inode);
> if (inode->i_nlink) {
> /*
> * When journalling data dirty buffers are tracked only in the
> diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
> index 042325349098..7fc40fb1e6b3 100644
> --- a/fs/ext4/xattr.c
> +++ b/fs/ext4/xattr.c
> @@ -436,6 +436,14 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
> return err;
> }
>
> +/* Remove entry from mbcache when EA inode is getting evicted */
> +void ext4_evict_ea_inode(struct inode *inode)
> +{
> + if (EA_INODE_CACHE(inode))
> + mb_cache_entry_delete(EA_INODE_CACHE(inode),
> + ext4_xattr_inode_get_hash(inode), inode->i_ino);
> +}
> +
> static int
> ext4_xattr_inode_verify_hashes(struct inode *ea_inode,
> struct ext4_xattr_entry *entry, void *buffer,
> @@ -976,10 +984,8 @@ int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode,
> static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
> int ref_change)
> {
> - struct mb_cache *ea_inode_cache = EA_INODE_CACHE(ea_inode);
> struct ext4_iloc iloc;
> s64 ref_count;
> - u32 hash;
> int ret;
>
> inode_lock(ea_inode);
> @@ -1002,14 +1008,6 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
>
> set_nlink(ea_inode, 1);
> ext4_orphan_del(handle, ea_inode);
> -
> - if (ea_inode_cache) {
> - hash = ext4_xattr_inode_get_hash(ea_inode);
> - mb_cache_entry_create(ea_inode_cache,
> - GFP_NOFS, hash,
> - ea_inode->i_ino,
> - true /* reusable */);
> - }

Ok, so if I understand this correctly, since we are not immediately removing the
ea_inode_cache entry when the recount reaches 0, hence when the refcount is
reaches 1 from 0, we need not create mb_cache entry is it?
Is this since the entry never got deleted in the first place?

But what happens when the entry is created the very first time?
I might need to study xattr code to understand how this condition is taken care.

-ritesh

> }
> } else {
> WARN_ONCE(ref_count < 0, "EA inode %lu ref_count=%lld",
> @@ -1022,12 +1020,6 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
>
> clear_nlink(ea_inode);
> ext4_orphan_add(handle, ea_inode);
> -
> - if (ea_inode_cache) {
> - hash = ext4_xattr_inode_get_hash(ea_inode);
> - mb_cache_entry_delete(ea_inode_cache, hash,
> - ea_inode->i_ino);
> - }
> }
> }
>
> diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
> index 77efb9a627ad..060b7a2f485c 100644
> --- a/fs/ext4/xattr.h
> +++ b/fs/ext4/xattr.h
> @@ -178,6 +178,7 @@ extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);
>
> extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
> struct ext4_inode *raw_inode, handle_t *handle);
> +extern void ext4_evict_ea_inode(struct inode *inode);
>
> extern const struct xattr_handler *ext4_xattr_handlers[];
>
> --
> 2.35.3
>