From: Darrick J. Wong <djwong@xxxxxxxxxx> Before we let fsverity begin writing merkle tree blocks to the file, let's perform a minor effort to clean up any stale metadata from a previous attempt to enable fsverity. This can only happen if the system crashes /and/ the file shrinks, which is unlikely. But we could do a better job of cleaning up anyway. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/xfs_verity.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_verity.c b/fs/xfs/xfs_verity.c index c19fa47d1f76..db43e017f10e 100644 --- a/fs/xfs/xfs_verity.c +++ b/fs/xfs/xfs_verity.c @@ -413,6 +413,44 @@ xfs_verity_get_descriptor( return args.valuelen; } +/* + * Clear out old fsverity metadata before we start building a new one. This + * could happen if, say, we crashed while building fsverity data. + */ +static int +xfs_verity_drop_old_metadata( + struct xfs_inode *ip, + u64 new_tree_size, + unsigned int tree_blocksize) +{ + struct xfs_verity_merkle_key name; + struct xfs_da_args args = { + .dp = ip, + .whichfork = XFS_ATTR_FORK, + .attr_filter = XFS_ATTR_VERITY, + .op_flags = XFS_DA_OP_REMOVE, + .name = (const uint8_t *)&name, + .namelen = sizeof(struct xfs_verity_merkle_key), + /* NULL value make xfs_attr_set remove the attr */ + .value = NULL, + }; + u64 offset; + int error = 0; + + /* + * Delete as many merkle tree blocks in increasing blkno order until we + * don't find any more. That ought to be good enough for avoiding + * dead bloat without excessive runtime. + */ + for (offset = new_tree_size; !error; offset += tree_blocksize) { + xfs_verity_merkle_key_to_disk(&name, offset); + error = xfs_attr_set(&args); + } + if (error == -ENOATTR) + return 0; + return error; +} + static int xfs_verity_begin_enable( struct file *filp, @@ -421,7 +459,6 @@ xfs_verity_begin_enable( { struct inode *inode = file_inode(filp); struct xfs_inode *ip = XFS_I(inode); - int error = 0; xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL); @@ -431,7 +468,8 @@ xfs_verity_begin_enable( if (xfs_iflags_test_and_set(ip, XFS_VERITY_CONSTRUCTION)) return -EBUSY; - return error; + return xfs_verity_drop_old_metadata(ip, merkle_tree_size, + tree_blocksize); } static int