Commit 6c3636eb authored by Sweet Tea Dorminy's avatar Sweet Tea Dorminy Committed by David Sterba

btrfs: restore inode creation before xattr setting

According to the tree checker, "all xattrs with a given objectid follow
the inode with that objectid in the tree" is an invariant. This was
broken by the recent change "btrfs: move common inode creation code into
btrfs_create_new_inode()", which moved acl creation and property
inheritance (stored in xattrs) to before inode insertion into the tree.
As a result, under certain timings, the xattrs could be written to the
tree before the inode, causing the tree checker to report violation of
the invariant.

Move property inheritance and acl creation back to their old ordering
after the inode insertion.
Suggested-by: default avatarOmar Sandoval <osandov@osandov.com>
Reported-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: default avatarSweet Tea Dorminy <sweettea-kernel@dorminy.me>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent caae78e0
...@@ -6207,43 +6207,6 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans, ...@@ -6207,43 +6207,6 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
goto out; goto out;
} }
if (args->subvol) {
struct inode *parent;
/*
* Subvolumes inherit properties from their parent subvolume,
* not the directory they were created in.
*/
parent = btrfs_iget(fs_info->sb, BTRFS_FIRST_FREE_OBJECTID,
BTRFS_I(dir)->root);
if (IS_ERR(parent)) {
ret = PTR_ERR(parent);
} else {
ret = btrfs_inode_inherit_props(trans, inode, parent);
iput(parent);
}
} else {
ret = btrfs_inode_inherit_props(trans, inode, dir);
}
if (ret) {
btrfs_err(fs_info,
"error inheriting props for ino %llu (root %llu): %d",
btrfs_ino(BTRFS_I(inode)), root->root_key.objectid,
ret);
}
/*
* Subvolumes don't inherit ACLs or get passed to the LSM. This is
* probably a bug.
*/
if (!args->subvol) {
ret = btrfs_init_inode_security(trans, args);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto discard;
}
}
/* /*
* We could have gotten an inode number from somebody who was fsynced * We could have gotten an inode number from somebody who was fsynced
* and then removed in this same transaction, so let's just set full * and then removed in this same transaction, so let's just set full
...@@ -6321,6 +6284,43 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans, ...@@ -6321,6 +6284,43 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(path->nodes[0]);
btrfs_release_path(path); btrfs_release_path(path);
if (args->subvol) {
struct inode *parent;
/*
* Subvolumes inherit properties from their parent subvolume,
* not the directory they were created in.
*/
parent = btrfs_iget(fs_info->sb, BTRFS_FIRST_FREE_OBJECTID,
BTRFS_I(dir)->root);
if (IS_ERR(parent)) {
ret = PTR_ERR(parent);
} else {
ret = btrfs_inode_inherit_props(trans, inode, parent);
iput(parent);
}
} else {
ret = btrfs_inode_inherit_props(trans, inode, dir);
}
if (ret) {
btrfs_err(fs_info,
"error inheriting props for ino %llu (root %llu): %d",
btrfs_ino(BTRFS_I(inode)), root->root_key.objectid,
ret);
}
/*
* Subvolumes don't inherit ACLs or get passed to the LSM. This is
* probably a bug.
*/
if (!args->subvol) {
ret = btrfs_init_inode_security(trans, args);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto discard;
}
}
inode_tree_add(inode); inode_tree_add(inode);
trace_btrfs_inode_new(inode); trace_btrfs_inode_new(inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment