[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230307105309.xddxh3tqtzsqxjuz@quack3>
Date: Tue, 7 Mar 2023 11:53:09 +0100
From: Jan Kara <jack@...e.cz>
To: Eric Whitney <enwlinux@...il.com>
Cc: linux-ext4@...r.kernel.org, tytso@....edu
Subject: Re: [PATCH] ext4: fix RENAME_WHITEOUT handling for inline directories
On Fri 10-02-23 12:32:44, Eric Whitney wrote:
> A significant number of xfstests can cause ext4 to log one or more
> warning messages when they are run on a test file system where the
> inline_data feature has been enabled. An example:
>
> "EXT4-fs warning (device vdc): ext4_dirblock_csum_set:425: inode
> #16385: comm fsstress: No space for directory leaf checksum. Please
> run e2fsck -D."
>
> The xfstests include: ext4/057, 058, and 307; generic/013, 051, 068,
> 070, 076, 078, 083, 232, 269, 270, 390, 461, 475, 476, 482, 579, 585,
> 589, 626, 631, and 650.
>
> In this situation, the warning message indicates a bug in the code that
> performs the RENAME_WHITEOUT operation on a directory entry that has
> been stored inline. It doesn't detect that the directory is stored
> inline, and incorrectly attempts to compute a dirent block checksum on
> the whiteout inode when creating it. This attempt fails as a result
> of the integrity checking in get_dirent_tail (usually due to a failure
> to match the EXT4_FT_DIR_CSUM magic cookie), and the warning message
> is then emitted.
>
> Fix this by simply collecting the inlined data state at the time the
> search for the source directory entry is performed. Existing code
> handles the rest, and this is sufficient to eliminate all spurious
> warning messages produced by the tests above. Go one step further
> and do the same in the code that resets the source directory entry in
> the event of failure. The inlined state should be present in the
> "old" struct, but given the possibility of a race there's no harm
> in taking a conservative approach and getting that information again
> since the directory entry is being reread anyway.
>
> Fixes: b7ff91fd030d ("ext4: find old entry again if failed to rename whiteout")
>
> Signed-off-by: Eric Whitney <enwlinux@...il.com>
Looks good to me. Feel free to add:
Reviewed-by: Jan Kara <jack@...e.cz>
Honza
> ---
> fs/ext4/namei.c | 13 +++++++------
> 1 file changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
> index dd28453d6ea3..924e16b239e0 100644
> --- a/fs/ext4/namei.c
> +++ b/fs/ext4/namei.c
> @@ -1595,11 +1595,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
> int has_inline_data = 1;
> ret = ext4_find_inline_entry(dir, fname, res_dir,
> &has_inline_data);
> - if (has_inline_data) {
> - if (inlined)
> - *inlined = 1;
> + if (inlined)
> + *inlined = has_inline_data;
> + if (has_inline_data)
> goto cleanup_and_exit;
> - }
> }
>
> if ((namelen <= 2) && (name[0] == '.') &&
> @@ -3646,7 +3645,8 @@ static void ext4_resetent(handle_t *handle, struct ext4_renament *ent,
> * so the old->de may no longer valid and need to find it again
> * before reset old inode info.
> */
> - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
> + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de,
> + &old.inlined);
> if (IS_ERR(old.bh))
> retval = PTR_ERR(old.bh);
> if (!old.bh)
> @@ -3813,7 +3813,8 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
> return retval;
> }
>
> - old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
> + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de,
> + &old.inlined);
> if (IS_ERR(old.bh))
> return PTR_ERR(old.bh);
> /*
> --
> 2.30.2
>
--
Jan Kara <jack@...e.com>
SUSE Labs, CR
Powered by blists - more mailing lists