Skip to content

Commit 4751dc9

Browse files
fdmananakdave
authored andcommitted
btrfs: add missing run of delayed items after unlink during log replay
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: 0d83639 ("Btrfs: fix mount failure after fsync due to hard link recreation") Fixes: 1f250e9 ("Btrfs: fix log replay failure after unlink and link combination") CC: stable@vger.kernel.org # 4.19+ Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent d4aef1e commit 4751dc9

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

fs/btrfs/tree-log.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,15 @@ static int unlink_old_inode_refs(struct btrfs_trans_handle *trans,
13621362
inode, name, namelen);
13631363
kfree(name);
13641364
iput(dir);
1365+
/*
1366+
* Whenever we need to check if a name exists or not, we
1367+
* check the subvolume tree. So after an unlink we must
1368+
* run delayed items, so that future checks for a name
1369+
* during log replay see that the name does not exists
1370+
* anymore.
1371+
*/
1372+
if (!ret)
1373+
ret = btrfs_run_delayed_items(trans);
13651374
if (ret)
13661375
goto out;
13671376
goto again;
@@ -1614,6 +1623,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
16141623
*/
16151624
if (!ret && inode->i_nlink == 0)
16161625
inc_nlink(inode);
1626+
/*
1627+
* Whenever we need to check if a name exists or
1628+
* not, we check the subvolume tree. So after an
1629+
* unlink we must run delayed items, so that future
1630+
* checks for a name during log replay see that the
1631+
* name does not exists anymore.
1632+
*/
1633+
if (!ret)
1634+
ret = btrfs_run_delayed_items(trans);
16171635
}
16181636
if (ret < 0)
16191637
goto out;

0 commit comments

Comments
 (0)