提交 410e0283 编写于 作者: F Filipe Manana 提交者: Zheng Zengkai

btrfs: add missing run of delayed items after unlink during log replay

stable inclusion
from stable-v5.10.104
commit 292e1c88b8a5616ada179f1f4f14c799571217af
bugzilla: https://gitee.com/openeuler/kernel/issues/I56XAC

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=292e1c88b8a5616ada179f1f4f14c799571217af

--------------------------------

commit 4751dc99 upstream.

During log replay, whenever we need to check if a name (dentry) exists in
a directory we do searches on the subvolume tree for inode references or
or directory entries (BTRFS_DIR_INDEX_KEY keys, and BTRFS_DIR_ITEM_KEY
keys as well, before kernel 5.17). However when during log replay we
unlink a name, through btrfs_unlink_inode(), we may not delete inode
references and dir index keys from a subvolume tree and instead just add
the deletions to the delayed inode's delayed items, which will only be
run when we commit the transaction used for log replay. This means that
after an unlink operation during log replay, if we attempt to search for
the same name during log replay, we will not see that the name was already
deleted, since the deletion is recorded only on the delayed items.

We run delayed items after every unlink operation during log replay,
except at unlink_old_inode_refs() and at add_inode_ref(). This was due
to an overlook, as delayed items should be run after evert unlink, for
the reasons stated above.

So fix those two cases.

Fixes: 0d836392 ("Btrfs: fix mount failure after fsync due to hard link recreation")
Fixes: 1f250e92 ("Btrfs: fix log replay failure after unlink and link combination")
CC: stable@vger.kernel.org # 4.19+
Signed-off-by: NFilipe Manana <fdmanana@suse.com>
Signed-off-by: NDavid Sterba <dsterba@suse.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NYu Liao <liaoyu15@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 e82484d2
...@@ -1286,6 +1286,15 @@ static int unlink_old_inode_refs(struct btrfs_trans_handle *trans, ...@@ -1286,6 +1286,15 @@ static int unlink_old_inode_refs(struct btrfs_trans_handle *trans,
inode, name, namelen); inode, name, namelen);
kfree(name); kfree(name);
iput(dir); iput(dir);
/*
* Whenever we need to check if a name exists or not, we
* check the subvolume tree. So after an unlink we must
* run delayed items, so that future checks for a name
* during log replay see that the name does not exists
* anymore.
*/
if (!ret)
ret = btrfs_run_delayed_items(trans);
if (ret) if (ret)
goto out; goto out;
goto again; goto again;
...@@ -1537,6 +1546,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ...@@ -1537,6 +1546,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
*/ */
if (!ret && inode->i_nlink == 0) if (!ret && inode->i_nlink == 0)
inc_nlink(inode); inc_nlink(inode);
/*
* Whenever we need to check if a name exists or
* not, we check the subvolume tree. So after an
* unlink we must run delayed items, so that future
* checks for a name during log replay see that the
* name does not exists anymore.
*/
if (!ret)
ret = btrfs_run_delayed_items(trans);
} }
if (ret < 0) if (ret < 0)
goto out; goto out;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册