]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commit
f2fs: reduce the scope of setting fsck tag when de->name_len is zero
authorYangtao Li <frank.li@vivo.com>
Wed, 4 Aug 2021 03:29:46 +0000 (11:29 +0800)
committerStefan Bader <stefan.bader@canonical.com>
Fri, 5 Nov 2021 09:17:57 +0000 (10:17 +0100)
commit8b980365f32b9eb2062d8e4aba605cea00baa0b1
treea28ddfdf9543125726d273414ea8bfac3419f8d2
parent0fb6d8db035ea411022a68e56564e95d57b74c1c
f2fs: reduce the scope of setting fsck tag when de->name_len is zero

BugLink: https://bugs.launchpad.net/bugs/1947781
[ Upstream commit d4bf15a7ce172d186d400d606adf4f34a59130d6 ]

I recently found a case where de->name_len is 0 in f2fs_fill_dentries()
easily reproduced, and finally set the fsck flag.

Thread A Thread B
- f2fs_readdir
 - f2fs_read_inline_dir
  - ctx->pos = d.max
- f2fs_add_dentry
 - f2fs_add_inline_entry
  - do_convert_inline_dir
 - f2fs_add_regular_entry
- f2fs_readdir
 - f2fs_fill_dentries
  - set_sbi_flag(sbi, SBI_NEED_FSCK)

Process A opens the folder, and has been reading without closing it.
During this period, Process B created a file under the folder (occupying
multiple f2fs_dir_entry, exceeding the d.max of the inline dir). After
creation, process A uses the d.max of inline dir to read it again, and
it will read that de->name_len is 0.

And Chao pointed out that w/o inline conversion, the race condition still
can happen as below:

dir_entry1: A
dir_entry2: B
dir_entry3: C
free slot: _
ctx->pos: ^

Thread A is traversing directory,
ctx-pos moves to below position after readdir() by thread A:
AAAABBBB___
        ^

Then thread B delete dir_entry2, and create dir_entry3.

Thread A calls readdir() to lookup dirents starting from middle
of new dirent slots as below:
AAAACCCCCC_
        ^
In these scenarios, the file system is not damaged, and it's hard to
avoid it. But we can bypass tagging FSCK flag if:
a) bit_pos (:= ctx->pos % d->max) is non-zero and
b) before bit_pos moves to first valid dir_entry.

Fixes: ddf06b753a85 ("f2fs: fix to trigger fsck if dirent.name_len is zero")
Signed-off-by: Yangtao Li <frank.li@vivo.com>
[Chao: clean up description]
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kelsey Skunberg <kelsey.skunberg@canonical.com>
fs/f2fs/dir.c