From: Darrick J. Wong <djwong@xxxxxxxxxx> When running this test on an XFS filesystem with a 64k block size, I see this error: generic/275 - output mismatch (see /var/tmp/fstests/generic/275.out.bad) --- tests/generic/275.out 2021-05-13 11:47:55.694860280 -0700 +++ /var/tmp/fstests/generic/275.out.bad 2022-07-19 10:38:41.840000000 -0700 @@ -2,4 +2,7 @@ ------------------------------ write until ENOSPC test ------------------------------ +du: cannot access '/opt/tmp1': No such file or directory +stat: cannot statx '/opt/tmp1': No such file or directory +/tmp/fstests/tests/generic/275: line 74: [: -lt: unary operator expected done ... (Run 'diff -u /tmp/fstests/tests/generic/275.out /var/tmp/fstests/generic/275.out.bad' to see the entire diff) The 275.full file indicates that the test was unable to recreate the $SCRATCH_MNT/tmp1 file after we freed all but the last 256K of free space in the filesystem. I mounted the scratch fs, and df reported exactly 256K of free space available, which means there are 4 blocks left in the filesystem for user programs to use. Unfortunately for this test, xfs_create requires sufficient free blocks in the filesystem to handle full inode btree splits and the maximal directory expansion for a new dirent. In other words, there must be enough free space to handle the worst case space consumption. That quantity is 26 blocks, hence the last dd in the test fails with ENOSPC, which makes the test fail. Fix all this by creating the file that we use to test the low-space file write *before* we drain the free space down to 256K. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- tests/generic/275 | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/generic/275 b/tests/generic/275 index 6189edca..f3b05409 100755 --- a/tests/generic/275 +++ b/tests/generic/275 @@ -37,6 +37,15 @@ _scratch_unmount 2>/dev/null _scratch_mkfs_sized $((2 * 1024 * 1024 * 1024)) >>$seqres.full 2>&1 _scratch_mount +# Certain filesystems such as XFS require sufficient free blocks to handle the +# worst-case directory expansion as a result of a creat() call. If the fs +# block size is very large (e.g. 64k) then the number of blocks required for +# the creat() call can represent far more free space than the 256K left at the +# end of this test. Therefore, create the file that the last dd will write to +# now when we know there's enough free blocks. +later_file=$SCRATCH_MNT/later +touch $later_file + # this file will get removed to create 256k of free space after ENOSPC # conditions are created. dd if=/dev/zero of=$SCRATCH_MNT/tmp1 bs=256K count=1 >>$seqres.full 2>&1 @@ -63,12 +72,12 @@ _freespace=`$DF_PROG -k $SCRATCH_MNT | tail -n 1 | awk '{print $5}'` # Try to write more than available space in chunks that will allow at least one # full write to succeed. -dd if=/dev/zero of=$SCRATCH_MNT/tmp1 bs=128k count=8 >>$seqres.full 2>&1 +dd if=/dev/zero of=$later_file bs=128k count=8 >>$seqres.full 2>&1 echo "Bytes written until ENOSPC:" >>$seqres.full -du $SCRATCH_MNT/tmp1 >>$seqres.full +du $later_file >>$seqres.full # And at least some of it should succeed. -_filesize=`_get_filesize $SCRATCH_MNT/tmp1` +_filesize=`_get_filesize $later_file` [ $_filesize -lt $((128 * 1024)) ] && \ _fail "Partial write until enospc failed; wrote $_filesize bytes."