Skip to content

Commit 2b6f3e4

Browse files
fdmananakdave
authored andcommitted
btrfs: record new subvolume in parent dir earlier to avoid dir logging races
Instead of recording that a new subvolume was created in a directory after we add the entry do the directory, record it before adding the entry. This is to avoid races where after creating the entry and before recording the new subvolume in the directory (the call to btrfs_record_new_subvolume()), another task logs the directory, so we end up with a log tree where we logged a directory that has an entry pointing to a root that was not yet committed, resulting in an invalid entry if the log is persisted and replayed later due to a power failure or crash. Also state this requirement in the function comment for btrfs_record_new_subvolume(), similar to what we do for the btrfs_record_unlink_dir() and btrfs_record_snapshot_destroy(). Fixes: 45c4102 ("btrfs: avoid transaction commit on any fsync after subvolume creation") Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 9fbec87 commit 2b6f3e4

File tree

2 files changed

+4
-2
lines changed

2 files changed

+4
-2
lines changed

fs/btrfs/ioctl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,14 +666,14 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
666666
goto out;
667667
}
668668

669+
btrfs_record_new_subvolume(trans, BTRFS_I(dir));
670+
669671
ret = btrfs_create_new_inode(trans, &new_inode_args);
670672
if (ret) {
671673
btrfs_abort_transaction(trans, ret);
672674
goto out;
673675
}
674676

675-
btrfs_record_new_subvolume(trans, BTRFS_I(dir));
676-
677677
d_instantiate_new(dentry, new_inode_args.inode);
678678
new_inode_args.inode = NULL;
679679

fs/btrfs/tree-log.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7454,6 +7454,8 @@ void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans,
74547454
* full log sync.
74557455
* Also we don't need to worry with renames, since btrfs_rename() marks the log
74567456
* for full commit when renaming a subvolume.
7457+
*
7458+
* Must be called before creating the subvolume entry in its parent directory.
74577459
*/
74587460
void btrfs_record_new_subvolume(const struct btrfs_trans_handle *trans,
74597461
struct btrfs_inode *dir)

0 commit comments

Comments
 (0)