On Tue, Jul 19, 2022 at 02:37:13PM -0700, Darrick J. Wong wrote: > 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 Make sense to me, Reviewed-by: Zorro Lang <zlang@xxxxxxxxxx> > + > # 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." > >