[PATCH] btrfs: do not insert dir index if there is a conflicting dir item name
Qu Wenruo <[email protected]>
| Newsgroups | org.kernel.vger.linux-btrfs |
|---|---|
| Message-ID | <3cc8583892db7e3d03c0e252a31a8b0565ae2d30.1786680299.git.wqu@suse.com> |
Inside btrfs_insert_dir_item(), if we hit an -EEXIST error from
insert_with_overflow(), we continue to second_insert label, which will
insert the corresponding dir index.
However insert_with_overflow() does not return -EEXIST just because there
is a hash conflict, but only when there is a completely same name in the
existing dir item.
So when we got -EEXIST insert_with_overflow(), it really means there is
an conflicting name, and we should not continue.
If we continue to the second_insert label, we will create another dir
index for an existing name, which will corrupt the fs.
For the existing callers, the btrfs_add_link() is already properly
handling the -EEXIST error without aborting (unless the inode ref is
unable to be reverted).
The only call site that aborts is from create_pending_snapshot(), but
that's the expected behavior as we have no way to revert the created
subvolume.
This bug is reported by Sashiko while reviewing a patch touching code
around the offending location.
But since it's an existing bug, it's not shown in the summary page.
Link: https://sashiko.dev/#/patchset/20260811-btrfs-enomem-v3-0-46a993fc3fe5%40kernel.org
Fixes: e06afa839e72 ("Btrfs: rename")
Signed-off-by: Qu Wenruo <[email protected]>
---
fs/btrfs/dir-item.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index 30ddafaf8d3d..a6bd69be522b 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -149,8 +149,6 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,
name->name, name->len);
if (IS_ERR(dir_item)) {
ret = PTR_ERR(dir_item);
- if (ret == -EEXIST)
- goto second_insert;
goto out_free_prealloc;
}
@@ -167,7 +165,6 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,
write_extent_buffer(leaf, name->name, name_ptr, name->len);
-second_insert:
if (!need_delayed_index) {
ret = 0;
goto out_free_prealloc;
--
2.54.0