2 # FS QA Test No. xfs/076
4 # Verify that a filesystem with sparse inode support can allocate inodes in the
5 # event of free space fragmentation. This test is generic in nature but
6 # primarily relevant to filesystems that implement dynamic inode allocation
9 # The test is inspired by inode allocation limitations on XFS when available
10 # free space is fragmented. XFS allocates inodes 64 at a time and thus requires
11 # an extent of length that depends on inode size (64 * isize / blksize).
13 # The test creates a small, sparse inode enabled filesystem. It fragments free
14 # space, allocates inodes to ENOSPC and then verifies that most of the available
15 # inodes (.i.e., free space) have been consumed.
17 #-----------------------------------------------------------------------
18 # Copyright (c) 2015 Red Hat, Inc. All Rights Reserved.
20 # This program is free software; you can redistribute it and/or
21 # modify it under the terms of the GNU General Public License as
22 # published by the Free Software Foundation.
24 # This program is distributed in the hope that it would be useful,
25 # but WITHOUT ANY WARRANTY; without even the implied warranty of
26 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 # GNU General Public License for more details.
29 # You should have received a copy of the GNU General Public License
30 # along with this program; if not, write the Free Software Foundation,
31 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #-----------------------------------------------------------------------
37 seqres=$RESULT_DIR/$seq
38 echo "QA output created by $seq"
42 status=1 # failure is the default!
44 # get standard environment, filters and checks
51 _scratch_unmount 2>/dev/null
54 trap "_cleanup; exit \$status" 0 1 2 3 15
60 # consume nearly all available space (leave ~1MB)
61 avail=`_get_available_space $SCRATCH_MNT`
62 filesizemb=$((avail / 1024 / 1024 - 1))
63 $XFS_IO_PROG -fc "falloc 0 ${filesizemb}m" $file
66 # Allocate inodes in a directory until failure.
73 touch $dir/$i 2>> $seqres.full || break
78 # real QA test starts here
82 _require_xfs_io_command "falloc"
83 _require_xfs_io_command "fpunch"
84 _require_xfs_sparse_inodes
88 _scratch_mkfs "-d size=50m -m crc=1 -i sparse" |
89 _filter_mkfs > /dev/null 2> $tmp.mkfs
90 . $tmp.mkfs # for isize
94 # Calculate the fs inode chunk size based on the inode size and fixed 64-inode
95 # record. This value is used as the target level of free space fragmentation
96 # induced by the test (i.e., max size of free extents). We don't need to go
97 # smaller than a full chunk because the XFS block allocator tacks on alignment
98 # requirements to the size of the requested allocation. In other words, a chunk
99 # sized free chunk is not enough to guarantee a successful chunk sized
101 CHUNK_SIZE=$((isize * 64))
103 _consume_freesp $SCRATCH_MNT/spc
105 # Now that the fs is nearly full, punch holes in every other $CHUNK_SIZE range
106 # of the space consumer file. This should ensure that most freed extents are not
107 # contiguous with any others and thus sufficiently fragment free space. After
108 # each hole punch, allocate as many inodes as possible into the newly freed
109 # space. Note that we start at the end of the file and work backwards as a
110 # reverse allocation pattern increases the chances of both left and right sparse
112 offset=`stat -c "%s" $SCRATCH_MNT/spc`
113 offset=$((offset - $CHUNK_SIZE * 2))
114 while [ $offset -ge 0 ]; do
115 $XFS_IO_PROG -c "fpunch $offset $CHUNK_SIZE" $SCRATCH_MNT/spc \
116 2>> $seqres.full || _fail "fpunch failed"
118 # allocate as many inodes as possible
119 mkdir -p $SCRATCH_MNT/offset.$offset > /dev/null 2>&1
120 _alloc_inodes $SCRATCH_MNT/offset.$offset
122 offset=$((offset - $CHUNK_SIZE * 2))
125 # check that we've hit at least 95% inode usage
126 iusepct=`_get_used_inode_percent $SCRATCH_MNT`
127 _within_tolerance "iusepct" $iusepct 100 5 0 -v