Skip to content

Commit 6607ce3

Browse files
fdmananakdave
authored andcommitted
btrfs: use btrfs_record_snapshot_destroy() during rmdir
We are setting the parent directory's last_unlink_trans directly which may result in a concurrent task starting to log the directory not see the update and therefore can log the directory after we removed a child directory which had a snapshot within instead of falling back to a transaction commit. Replaying such a log tree would result in a mount failure since we can't currently delete snapshots (and subvolumes) during log replay. This is the type of failure described in commit 1ec9a1a ("Btrfs: fix unreplayable log after snapshot delete + parent dir fsync"). Fix this by using btrfs_record_snapshot_destroy() which updates the last_unlink_trans field while holding the inode's log_mutex lock. Fixes: 44f714d ("Btrfs: improve performance on fsync against new inode after rename/unlink") Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 255265e commit 6607ce3

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

fs/btrfs/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4747,7 +4747,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
47474747
* deletes for directory foo.
47484748
*/
47494749
if (BTRFS_I(inode)->last_unlink_trans >= trans->transid)
4750-
BTRFS_I(dir)->last_unlink_trans = BTRFS_I(inode)->last_unlink_trans;
4750+
btrfs_record_snapshot_destroy(trans, BTRFS_I(dir));
47514751

47524752
if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
47534753
ret = btrfs_unlink_subvol(trans, BTRFS_I(dir), dentry);

0 commit comments

Comments
 (0)