fstests: move test group info to test files
[xfstests-dev.git] / tests / xfs / 076
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2015 Red Hat, Inc.  All Rights Reserved.
4 #
5 # FS QA Test No. xfs/076
6 #
7 # Verify that a filesystem with sparse inode support can allocate inodes in the
8 # event of free space fragmentation. This test is generic in nature but
9 # primarily relevant to filesystems that implement dynamic inode allocation
10 # (e.g., XFS).
11 #
12 # The test is inspired by inode allocation limitations on XFS when available
13 # free space is fragmented. XFS allocates inodes 64 at a time and thus requires
14 # an extent of length that depends on inode size (64 * isize / blksize).
15 #
16 # The test creates a small, sparse inode enabled filesystem. It fragments free
17 # space, allocates inodes to ENOSPC and then verifies that most of the available
18 # inodes (.i.e., free space) have been consumed.
19 #
20 . ./common/preamble
21 _begin_fstest auto enospc punch
22
23 # Import common functions.
24 . ./common/filter
25
26 # Override the default cleanup function.
27 _cleanup()
28 {
29         cd /
30         _scratch_unmount 2>/dev/null
31         rm -f $tmp.*
32 }
33
34 _consume_freesp()
35 {
36         file=$1
37
38         # consume nearly all available space (leave ~1MB)
39         avail=`_get_available_space $SCRATCH_MNT`
40         filesizemb=$((avail / 1024 / 1024 - 1))
41         $XFS_IO_PROG -fc "falloc 0 ${filesizemb}m" $file
42 }
43
44 # Allocate inodes in a directory until failure.
45 _alloc_inodes()
46 {
47         dir=$1
48
49         i=0
50         while [ true ]; do
51                 touch $dir/$i 2>> $seqres.full || break
52                 i=$((i + 1))
53         done
54 }
55
56 # real QA test starts here
57
58 _require_scratch
59 _require_xfs_io_command "falloc"
60 _require_xfs_io_command "fpunch"
61 _require_xfs_sparse_inodes
62
63 _scratch_mkfs "-d size=50m -m crc=1 -i sparse" |
64         _filter_mkfs > /dev/null 2> $tmp.mkfs
65 . $tmp.mkfs     # for isize
66
67 _scratch_mount
68
69 # Calculate the fs inode chunk size based on the inode size and fixed 64-inode
70 # record. This value is used as the target level of free space fragmentation
71 # induced by the test (i.e., max size of free extents). We don't need to go
72 # smaller than a full chunk because the XFS block allocator tacks on alignment
73 # requirements to the size of the requested allocation. In other words, a chunk
74 # sized free chunk is not enough to guarantee a successful chunk sized
75 # allocation.
76 CHUNK_SIZE=$((isize * 64))
77
78 _consume_freesp $SCRATCH_MNT/spc
79
80 # Now that the fs is nearly full, punch holes in every other $CHUNK_SIZE range
81 # of the space consumer file. This should ensure that most freed extents are not
82 # contiguous with any others and thus sufficiently fragment free space. After
83 # each hole punch, allocate as many inodes as possible into the newly freed
84 # space. Note that we start at the end of the file and work backwards as a
85 # reverse allocation pattern increases the chances of both left and right sparse
86 # record merges.
87 offset=`_get_filesize $SCRATCH_MNT/spc`
88 offset=$((offset - $CHUNK_SIZE * 2))
89 while [ $offset -ge 0 ]; do
90         $XFS_IO_PROG -c "fpunch $offset $CHUNK_SIZE" $SCRATCH_MNT/spc \
91                 2>> $seqres.full || _fail "fpunch failed"
92
93         # allocate as many inodes as possible
94         mkdir -p $SCRATCH_MNT/offset.$offset > /dev/null 2>&1
95         _alloc_inodes $SCRATCH_MNT/offset.$offset
96
97         offset=$((offset - $CHUNK_SIZE * 2))
98 done
99
100 # check that we've hit at least 95% inode usage
101 iusepct=`_get_used_inode_percent $SCRATCH_MNT`
102 _within_tolerance "iusepct" $iusepct 100 5 0 -v
103
104 status=0
105 exit