Skip to content

Commit 4aef4c9

Browse files
fdmananagregkh
authored andcommitted
btrfs: add missing run of delayed items after unlink during log replay
commit 4751dc9 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: 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 34146bb commit 4aef4c9

1 file changed

Lines changed: 18 additions & 0 deletions

File tree

fs/btrfs/tree-log.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,15 @@ static int unlink_old_inode_refs(struct btrfs_trans_handle *trans,
13291329
inode, name, namelen);
13301330
kfree(name);
13311331
iput(dir);
1332+
/*
1333+
* Whenever we need to check if a name exists or not, we
1334+
* check the subvolume tree. So after an unlink we must
1335+
* run delayed items, so that future checks for a name
1336+
* during log replay see that the name does not exists
1337+
* anymore.
1338+
*/
1339+
if (!ret)
1340+
ret = btrfs_run_delayed_items(trans);
13321341
if (ret)
13331342
goto out;
13341343
goto again;
@@ -1580,6 +1589,15 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
15801589
*/
15811590
if (!ret && inode->i_nlink == 0)
15821591
inc_nlink(inode);
1592+
/*
1593+
* Whenever we need to check if a name exists or
1594+
* not, we check the subvolume tree. So after an
1595+
* unlink we must run delayed items, so that future
1596+
* checks for a name during log replay see that the
1597+
* name does not exists anymore.
1598+
*/
1599+
if (!ret)
1600+
ret = btrfs_run_delayed_items(trans);
15831601
}
15841602
if (ret < 0)
15851603
goto out;

0 commit comments

Comments
 (0)