diff mbox series

btrfs: restore inode creation before xattr setting

Message ID 8a60e54c02d8951cf5650cc8452ae583c130bbf7.1649437335.git.sweettea-kernel@dorminy.me (mailing list archive)
State New, archived
Headers show
Series btrfs: restore inode creation before xattr setting | expand

Commit Message

Sweet Tea Dorminy April 8, 2022, 5:15 p.m. UTC
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 <osandov@osandov.com>
Reported-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
This should apply on top of osandov's patch at
 https://lore.kernel.org/linux-btrfs/da6cfa1b8e42db5c8954680cac1ca322d463b880.1647306546.git.osandov@fb.com/

It's survived a good dose of fstests, and several iterations of specific
tests that were failing, e.g. generic/650.

David: I don't know if you'd rather roll this into osandov's original
patch, or whether you'd like me or osandov to resend the patch linked
above with this addition rolled into it, or whether you'd like to apply
it separately. 

---
 fs/btrfs/inode.c | 74 ++++++++++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 37 deletions(-)

Comments

David Sterba April 8, 2022, 6:37 p.m. UTC | #1
On Fri, Apr 08, 2022 at 01:15:07PM -0400, Sweet Tea Dorminy wrote:
> 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 <osandov@osandov.com>
> Reported-by: Naohiro Aota <naohiro.aota@wdc.com>
> Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
> ---
> This should apply on top of osandov's patch at
>  https://lore.kernel.org/linux-btrfs/da6cfa1b8e42db5c8954680cac1ca322d463b880.1647306546.git.osandov@fb.com/
> 
> It's survived a good dose of fstests, and several iterations of specific
> tests that were failing, e.g. generic/650.

Thanks.

> David: I don't know if you'd rather roll this into osandov's original
> patch, or whether you'd like me or osandov to resend the patch linked
> above with this addition rolled into it, or whether you'd like to apply
> it separately.

For simple fixups sent as replies I can apply it manually but sometimes
it's better for me to do the review instead of trying to figure out what
was the real intention.

So patch applied cleanly and now pushed to misc-next, thanks.
diff mbox series

Patch

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 2f4935649555..213e7048d911 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6213,43 +6213,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
@@ -6327,6 +6290,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);