#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2022-2024 Oracle. All Rights Reserved. # # FS QA Test No. 607 # # This is a regression test for "xfs: Fix false ENOSPC when performing direct # write on a delalloc extent in cow fork". If there is a lot of free space but # it is very fragmented, it's possible that a very large delalloc reservation # could be created in the CoW fork by a buffered write. If a directio write # tries to convert the delalloc reservation to a real extent, it's possible # that the allocation will succeed but fail to convert even the first block of # the directio write range. In this case, XFS will return ENOSPC even though # all it needed to do was to keep converting until the allocator returns ENOSPC # or the first block of the direct write got some space. # . ./common/preamble _begin_fstest auto quick clone _cleanup() { cd / rm -f $file1 $file2 $fragmentedfile } # Import common functions. . ./common/reflink . ./common/inject # real QA test starts here _fixed_by_kernel_commit d62113303d69 \ "xfs: Fix false ENOSPC when performing direct write on a delalloc extent in cow fork" # Modify as appropriate. _supported_fs xfs _require_test_program "punch-alternating" _require_test_reflink _require_xfs_io_error_injection "bmap_alloc_minlen_extent" _require_test_delalloc file1=$TEST_DIR/file1.$seq file2=$TEST_DIR/file2.$seq fragmentedfile=$TEST_DIR/fragmentedfile.$seq rm -f $file1 $file2 $fragmentedfile # COW operates on pages, so we must not perform operations in units smaller # than a page. blksz=$(_get_file_block_size $TEST_DIR) pagesz=$(_get_page_size) if (( $blksz < $pagesz )); then blksz=$pagesz fi echo "Create source file" $XFS_IO_PROG -f -c "pwrite 0 $((blksz * 256))" $file1 >> $seqres.full sync echo "Create Reflinked file" _cp_reflink $file1 $file2 >> $seqres.full echo "Set cowextsize" $XFS_IO_PROG -c "cowextsize $((blksz * 128))" -c stat $file1 >> $seqres.full echo "Fragment FS" $XFS_IO_PROG -f -c "pwrite 0 $((blksz * 512))" $fragmentedfile >> $seqres.full sync $here/src/punch-alternating $fragmentedfile echo "Allocate block sized extent from now onwards" _test_inject_error bmap_alloc_minlen_extent 1 echo "Create big delalloc extent in CoW fork" $XFS_IO_PROG -c "pwrite 0 $blksz" $file1 >> $seqres.full sync $XFS_IO_PROG -c 'bmap -elpv' -c 'bmap -celpv' $file1 &>> $seqres.full echo "Direct I/O write at offset 3FSB" $XFS_IO_PROG -d -c "pwrite $((blksz * 3)) $((blksz * 2))" $file1 >> $seqres.full # success, all done status=0 exit