Skip to content

Commit bf5bcf9

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") Reviewed-by: Johannes Thumshirn <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 5f61b96 commit bf5bcf9

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
@@ -7447,6 +7447,8 @@ void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans,
74477447
* full log sync.
74487448
* Also we don't need to worry with renames, since btrfs_rename() marks the log
74497449
* for full commit when renaming a subvolume.
7450+
*
7451+
* Must be called before creating the subvolume entry in its parent directory.
74507452
*/
74517453
void btrfs_record_new_subvolume(const struct btrfs_trans_handle *trans,
74527454
struct btrfs_inode *dir)

0 commit comments

Comments
 (0)