[PATCH 26/29] xfs: better reporting and error handling in xfs_drop_merkle_tree

Darrick J. Wong
2024-03-13T17:59:21Z

From: Darrick J. Wong <djwong@kernel.org>

xfs_drop_merkle_tree is responsible for removing the fsverity metadata
after a failed attempt to enable fsverity for a file. However, if the
enablement process fails before the verity descriptor is written to the
file, the cleanup function will trip the WARN_ON. The error code in
that case is ENOATTR, which isn't worth logging about.

Fix that return code handling, fix the tree block removal loop not to
return early with ENOATTR, and improve the logging so that we actually
capture what kind of error occurred.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
fs/xfs/xfs_verity.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/fs/xfs/xfs_verity.c b/fs/xfs/xfs_verity.c
index cfa50534bfc4..3dcc2af084fc 100644
--- a/fs/xfs/xfs_verity.c
+++ b/fs/xfs/xfs_verity.c
@@ -481,15 +481,14 @@ xfs_verity_begin_enable(
tree_blocksize);
}

+/* Try to remove all the fsverity metadata after a failed enablement. */
static int
-xfs_drop_merkle_tree(
+xfs_verity_drop_incomplete_tree(
struct xfs_inode *ip,
u64 merkle_tree_size,
unsigned int tree_blocksize)
{
struct xfs_fsverity_merkle_key name;
- int error = 0;
- u64 offset = 0;
struct xfs_da_args args = {
.dp = ip,
.whichfork = XFS_ATTR_FORK,
@@ -500,6 +499,8 @@ xfs_drop_merkle_tree(
/* NULL value make xfs_attr_set remove the attr */
.value = NULL,
};
+ u64 offset;
+ int error;

if (!merkle_tree_size)
return 0;
@@ -507,6 +508,8 @@ xfs_drop_merkle_tree(
for (offset = 0; offset < merkle_tree_size; offset += tree_blocksize) {
xfs_fsverity_merkle_key_to_disk(&name, offset);
error = xfs_attr_set(&args);
+ if (error == -ENOATTR)
+ error = 0;
if (error)
return error;
}
@@ -514,7 +517,8 @@ xfs_drop_merkle_tree(
args.name = (const uint8_t *)XFS_VERITY_DESCRIPTOR_NAME;
args.namelen = XFS_VERITY_DESCRIPTOR_NAME_LEN;
error = xfs_attr_set(&args);
-
+ if (error == -ENOATTR)
+ return 0;
return error;
}

@@ -573,9 +577,16 @@ xfs_verity_end_enable(
inode->i_flags |= S_VERITY;

out:
- if (error)
- WARN_ON_ONCE(xfs_drop_merkle_tree(ip, merkle_tree_size,
- tree_blocksize));
+ if (error) {
+ int error2;
+
+ error2 = xfs_verity_drop_incomplete_tree(ip, merkle_tree_size,
+ tree_blocksize);
+ if (error2)
+ xfs_alert(ip->i_mount,
+ "ino 0x%llx failed to clean up new fsverity metadata, err %d",
+ ip->i_ino, error2);
+ }

xfs_iflags_clear(ip, XFS_VERITY_CONSTRUCTION);
return error;