generic: fixes for different allocation behaviours
cover generic: fixes for different allocation behaviours
Hi folks,
These 3 patches address failures I found when testing the XFS DAX functionality. DAX disables delayed allocation on XFS, so the size of the buffer in the write() call determines the size of the allocation that is done. Hence tests that expect a specific extent layout need to do IO in buffers as large as the extent size they expect to be created.
The other side of this is that some tests also expect partial writes to occur, which happened as a side effect of buffered writes being broken down into PAGE_SIZE chunks. With DAX, that does not happen - the writes tend to either succeed or fail completely, especially if it is an ENOSPC condition that is ocurring.
HEnce these patches address these test assumptions, and now they work correctly and pass on both DAX and non-DAX filesystems.
Cheers,
Dave.
PATCH 1/3 generic/018: use xfs_io and larger buffers for writes
From: Dave Chinner <[email protected]>
The test currently uses 'dd' directly for writing to files; instead we should be using the xfs_io pwrite command.
Also, when we have a configuration that does not do delayed allocation (e.g. dax), there is no guarantee that the files will be allocated in the pattern expected, so do all the writes from a single buffer so the kernel can allocate extents in the manner the test expects as much as possible.
--- tests/generic/018 | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
tests/generic/018 +12 -7
@@ -57,6 +57,7 @@ fragfile=$SCRATCH_MNT/fragfile.$$ rm -f $fragfile # Craft some fragmented files, defrag them, check the result. +bsize=4096 echo "zero-length file:" | tee -a $seqres.full touch $fragfile
@@ -67,24 +68,28 @@ $XFS_IO_PROG -f -c "truncate 1m" $fragfile _defrag --before 0 --after 0 $fragfile echo "Contiguous file:" | tee -a $seqres.full -dd if=/dev/zero of=$fragfile bs=4k count=4 &>/dev/null +$XFS_IO_PROG -f -c "pwrite -b $((4 * bsize)) 0 $((4 * bsize))" $fragfile \ + > /dev/null _defrag --before 1 --after 1 $fragfile echo "Write backwards sync, but contiguous - should defrag to 1 extent" | tee -a $seqres.full -for I in `seq 9 -1 0`; do - dd if=/dev/zero of=$fragfile bs=4k count=1 conv=notrunc seek=$I oflag=sync &>/dev/null +for i in `seq 9 -1 0`; do + $XFS_IO_PROG -fs -c "pwrite $((i * bsize)) $bsize" $fragfile \ + > /dev/null done _defrag --before 10 --after 1 $fragfile echo "Write backwards sync leaving holes - defrag should do nothing" | tee -a $seqres.full -for I in `seq 31 -2 0`; do - dd if=/dev/zero of=$fragfile bs=4k count=1 conv=notrunc seek=$I oflag=sync &>/dev/null +for i in `seq 31 -2 0`; do + $XFS_IO_PROG -fs -c "pwrite $((i * bsize)) $bsize" $fragfile \ + > /dev/null done _defrag --before 16 --after 16 $fragfile echo "Write forwards sync leaving holes - defrag should do nothing" | tee -a $seqres.full -for I in `seq 0 2 31`; do - dd if=/dev/zero of=$fragfile bs=4k count=1 conv=notrunc seek=$I oflag=sync &>/dev/null +for i in `seq 0 2 31`; do + $XFS_IO_PROG -fs -c "pwrite $((i * bsize)) $bsize" $fragfile \ + > /dev/null done _defrag --before 16 --after 16 $fragfile
Signature · 1 line
2.0.0
PATCH 2/3 generic/223, xfs/203: IO is not well aligned
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
On certain configurations (e.g. MOUNT_OPTIONS="-o dax") we get different allocation patterns due to the writes being done in multiple pwrite() calls. e.g. the write is 8k, but the buffer size is 4k, and so the filesystem sees 4k writes. If the filesytem is not using delayed allocation, then the allocation context is a 4k write rather than an 8k write and so they don't get appropriately aligned.
Fix this by making the write buffer the same size and the writes being done.
--- tests/generic/223 | 2 +- tests/xfs/203 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
tests/generic/223 +1 -1
@@ -69,7 +69,7 @@ for SUNIT_K in 8 16 32 64 128; do $XFS_IO_PROG -f -c "falloc 0 $SIZE" \ $SCRATCH_MNT/file-$FILE-$SIZE-falloc \ >> $seqres.full 2>&1 - $XFS_IO_PROG -f -c "pwrite 0 $SIZE" \ + $XFS_IO_PROG -f -c "pwrite -b $SIZE 0 $SIZE" \ $SCRATCH_MNT/file-$FILE-$SIZE-write \ >> $seqres.full 2>&1 src/t_stripealign $SCRATCH_MNT/file-$FILE-$SIZE-falloc \
tests/xfs/203 +2 -2
@@ -38,11 +38,11 @@ _write_holes() let fsize=$(($writes * 0x100000)) # prevent EOF preallocation from affecting results - xfs_io -f $file -c "truncate $fsize" + $XFS_IO_PROG -f $file -c "truncate $fsize" offset=0 for i in `seq 0 $writes`; do - xfs_io -f $file -c "pwrite -q $offset 64k" + $XFS_IO_PROG -f $file -c "pwrite -b 64k -q $offset 64k" let offset=$offset+0x100000 done }
Signature · 1 line
2.0.0
PATCH 3/3 generic/275: writes may not partially succeed
In reply to Dave ChinnerFrom: Dave Chinner <[email protected]>
When a large IO is done as a single buffer, there is no guarantee that it will partially succeed when close to ENOSPC. The test assumes that the kernel is going to break the write down into smaller chunks (i.e. buffered IO breaking it down into PAGE_SIZE allocations), but certain configurations will not do this. e.g. extent size hints are set or DAX is being used) and hence the large write fails completely as there is not space for the entire allocation to be made.
Hence break the final write in the test up into multiple small writes, thereby acheiving the same effect - ensuring that we can write more data after removing some space....
--- tests/generic/275 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
tests/generic/275 +7 -3
@@ -57,6 +57,8 @@ umount $SCRATCH_DEV 2>/dev/null _scratch_mkfs_sized $((2 * 1024 * 1024 * 1024)) >>$seqres.full 2>&1 _scratch_mount +# 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 [ $? -ne 0 ] && _fail "Error creating file"
@@ -79,14 +81,16 @@ $DF_PROG $SCRATCH_MNT >>$seqres.full 2>&1 _freespace=`$DF_PROG -k $SCRATCH_MNT | tail -n 1 | awk '{print $5}'` [ $_freespace -gt 1024 ] && _fail "could not sufficiently fill filesystem" -# Try a write larger than available space -dd if=/dev/zero of=$SCRATCH_MNT/tmp1 bs=1M count=1 >>$seqres.full 2>&1 +# 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 echo "Bytes written until ENOSPC:" >>$seqres.full du $SCRATCH_MNT/tmp1 >>$seqres.full # And at least some of it should succeed. _filesize=`ls -l $SCRATCH_MNT/tmp1 | awk '{print $5}'` -[ $_filesize -eq 0 ] && _fail "write file err: Partial write until enospc failed; wrote 0 bytes." +[ $_filesize -lt $((128 * 1024)) ] && \ + _fail "Partial write until enospc failed; wrote $_filesize bytes." echo "done" status=0
Signature · 1 line
2.0.0
Quoted 9 lines · Dave Chinner
Hi folks,
These 3 patches address failures I found when testing the XFS DAX functionality. DAX disables delayed allocation on XFS, so the size of the buffer in the
write()call determines the size of the allocation that is done. Hence tests that expect a specific extent layout need to do IO in buffers as large as the extent size they expect to be created.
Quoted 9 lines
The other side of this is that some tests also expect partial writes to occur, which happened as a side effect of buffered writes being broken down into
PAGE_SIZEchunks. With DAX, that does not happen - the writes tend to either succeed or fail completely, especially if it is an ENOSPC condition that is ocurring.HEnce these patches address these test assumptions, and now they work correctly and pass on both DAX and non-DAX filesystems.
All look fine to me:
Quoted 7 lines
Cheers,
Dave.
--
To unsubscribe from this list: send the line "unsubscribe fstests" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html