diff mbox series

[1/3] common/populate: fix btree-format xattr creation on xfs

Message ID 168065021529.494608.15409038797376185356.stgit@frogsfrogsfrogs (mailing list archive)
State New, archived
Headers show
Series populate: tweaks to the filesystems created | expand

Commit Message

Darrick J. Wong April 4, 2023, 11:16 p.m. UTC
From: Darrick J. Wong <djwong@kernel.org>

Currently, we set a large number of extended attributes when trying to
force the attr fork to be in BTREE format.  This doesn't work reliably
because userspace has no control over where xattr leaf and dabtree
blocks are mapped, and contiguous mappings can prevent the file from
having a btree format attr fork.

However, we /do/ have one small knob for controlling attr fork mappings
in the form of creating remote value xattrs and then deleting them to
leave holes in the mappings.  Create a separate helper function that
exploits this property to try to create a sparse attr fork with enough
mappings to give us the btree attr fork that we want.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 common/populate |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/common/populate b/common/populate
index b6f510f396..144a3f5186 100644
--- a/common/populate
+++ b/common/populate
@@ -155,6 +155,57 @@  __populate_create_attr() {
 	done
 }
 
+# Create an extended attr structure and ensure that the fork is btree format
+__populate_xfs_create_btree_attr() {
+	local name="$1"
+	local isize="$2"
+	local dblksz="$3"
+	local icore_size="$(_xfs_get_inode_core_bytes $SCRATCH_MNT)"
+	# We need enough extents to guarantee that the attr fork is in btree
+	# format.  Cycling the mount to use xfs_db is too slow, so watch for
+	# when the number of holes that we can punch in the attr fork by
+	# deleting remote xattrs exceeds the number of extent mappings that can
+	# fit in the inode core.
+	local max_nextents="$(((isize - icore_size) / 16))"
+	local nr
+	local i
+	local incr
+	local bigval
+
+	# Add about one block's worth of attrs in betweeen creating punchable
+	# remote value blocks.
+	incr=$(( (dblksz / 16) / 100 * 100 ))
+	bigval="$(perl -e "print \"@\" x $dblksz;")"
+
+	touch "${name}"
+
+	# We cannot control the mapping behaviors of the attr fork leaf and
+	# dabtree blocks, but we do know that remote values are stored in a
+	# single extent, and that those mappings are removed if the xattr is
+	# deleted.
+	#
+	# The extended attribute structure tends to grow from offset zero
+	# upwards, so we try to set up a sparse attr fork mapping by
+	# iteratively creating at least one leaf block's worth of local attrs,
+	# and then one remote attr, until the number of remote xattrs exceeds
+	# the number of mappings that fit in the inode core...
+	for ((nr = 0; nr < (incr * max_nextents); nr += incr)); do
+		# Simulate a getfattr dump file so we can bulk-add attrs.
+		(
+			echo "# file: ${name}";
+			seq --format "user.%08g=\"abcdefgh\"" "${nr}" "$((nr + incr + 1))"
+			echo "user.v$(printf "%.08d" "$nr")=\"${bigval}\""
+			echo
+		) | setfattr --restore -
+	done
+
+	# ... and in the second loop we delete all the remote attrs to
+	# fragment the attr fork mappings.
+	for ((i = 0; i < nr; i += incr)); do
+		setfattr -x "user.v$(printf "%.08d" "$i")" "${name}"
+	done
+}
+
 # Fill up some percentage of the remaining free space
 __populate_fill_fs() {
 	dir="$1"
@@ -327,7 +378,7 @@  _scratch_xfs_populate() {
 
 	# BTREE
 	echo "+ btree attr"
-	__populate_create_attr "${SCRATCH_MNT}/ATTR.FMT_BTREE" "$((64 * blksz / 40))" true
+	__populate_xfs_create_btree_attr "${SCRATCH_MNT}/ATTR.FMT_BTREE" "$isize" "$dblksz"
 
 	# trusted namespace
 	touch ${SCRATCH_MNT}/ATTR.TRUSTED