aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSweet Tea Dorminy <[email protected]>2022-04-08 13:15:07 -0400
committerDavid Sterba <[email protected]>2022-05-16 17:03:09 +0200
commit6c3636ebe39270b85ba8ad75435be4f563d9b1b7 (patch)
tree5f8eab1bd2efcd9669d3928824dd5f88284d3bce
parentcaae78e032343df525b8d05c58b462827f10b2a3 (diff)
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: Omar Sandoval <[email protected]> Reported-by: Naohiro Aota <[email protected]> Signed-off-by: Sweet Tea Dorminy <[email protected]> Signed-off-by: David Sterba <[email protected]>
-rw-r--r--fs/btrfs/inode.c74
1 files changed, 37 insertions, 37 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index dbf059926141..31ccb82157c2 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6207,43 +6207,6 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
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
* 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,
btrfs_mark_buffer_dirty(path->nodes[0]);
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);
trace_btrfs_inode_new(inode);