FITRIM is a bizarre ioctl. Callers are allowed to pass in "start" and
"length" parameters, which are clearly some kind of range argument. No
means is provided to discover the minimum or maximum range. Although
regular userspace programs default to (start=0, length=-1ULL), this test
tries to exercise different parameters.
However, the test assumes that the "size" column returned by the df
command is the maximum value supported by the FITRIM command, and is
surprised if the number of bytes trimmed by (start=0, length=-1ULL) is
larger than this size quantity.
This is completely wrong on XFS with realtime volumes, because the
statfs output (which is what df reports) will reflect the realtime
volume if the directory argument is a realtime file or a directory
flagged with rtinherit. This is trivially reproducible by configuring a
rt volume that is much larger than the data volume, setting rtinherit on
the root dir at mkfs time, and running either of these tests.
Refactor the open-coded df logic so that we can determine the value
programmatically for XFS.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Zorro Lang <zlang@kernel.org>
fi
}
+# Given a mountpoint and the device associated with that mountpoint, return the
+# maximum start offset that the FITRIM command will accept, in units of 1024
+# byte blocks.
+_discard_max_offset_kb()
+{
+ case "$FSTYP" in
+ xfs)
+ _xfs_discard_max_offset_kb "$1"
+ ;;
+ *)
+ $DF_PROG -k | awk -v dev="$2" -v mnt="$1" '$1 == dev && $7 == mnt { print $3 }'
+ ;;
+ esac
+}
+
_require_dumpe2fs()
{
if [ -z "$DUMPE2FS_PROG" ]; then
_notrun "atomicswap dependencies not supported by scratch filesystem type: $FSTYP"
_scratch_unmount
}
+
+# Return the maximum start offset that the FITRIM command will accept, in units
+# of 1024 byte blocks.
+_xfs_discard_max_offset_kb()
+{
+ $XFS_IO_PROG -c 'statfs' "$1" | \
+ awk '{g[$1] = $3} END {print (g["geom.bsize"] * g["geom.datablocks"] / 1024)}'
+}
fstrim_loop()
{
trap "_destroy_fstrim; exit \$status" 2 15
- fsize=$($DF_PROG | grep $SCRATCH_MNT | grep $SCRATCH_DEV | awk '{print $3}')
+ fsize=$(_discard_max_offset_kb "$SCRATCH_MNT" "$SCRATCH_DEV")
mmlen=$(_guess_max_minlen)
while true ; do
_require_batched_discard $SCRATCH_MNT
-fssize=$($DF_PROG -k | grep "$SCRATCH_MNT" | grep "$SCRATCH_DEV" | awk '{print $3}')
+fssize=$(_discard_max_offset_kb "$SCRATCH_MNT" "$SCRATCH_DEV")
beyond_eofs=$(_math "$fssize*2048")
max_64bit=$(_math "2^64 - 1")