2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2021 Chandan Babu R. All Rights Reserved.
7 # Verify that XFS does not cause inode fork's extent count to overflow when
8 # adding/removing directory entries.
10 seqres=$RESULT_DIR/$seq
11 echo "QA output created by $seq"
15 status=1 # failure is the default!
16 trap "_cleanup; exit \$status" 0 1 2 3 15
24 # get standard environment, filters and checks
30 # remove previous $seqres.full before test
33 # real QA test starts here
38 _require_test_program "punch-alternating"
39 _require_xfs_io_error_injection "reduce_max_iextents"
40 _require_xfs_io_error_injection "bmap_alloc_minlen_extent"
42 _scratch_mkfs_sized $((1024 * 1024 * 1024)) | _filter_mkfs >> $seqres.full 2> $tmp.mkfs
45 # Filesystems with directory block size greater than one FSB will not be tested,
46 # since "7 (i.e. XFS_DA_NODE_MAXDEPTH + 1 data block + 1 free block) * 2 (fsb
47 # count) = 14" is greater than the pseudo max extent count limit of 10.
48 # Extending the pseudo max limit won't help either. Consider the case where 1
49 # FSB is 1k in size and 1 dir block is 64k in size (i.e. fsb count = 64). In
50 # this case, the pseudo max limit has to be greater than 7 * 64 = 448 extents.
51 if (( $dirbsize > $dbsize )); then
52 _notrun "Directory block size ($dirbsize) is larger than FSB size ($dbsize)"
55 echo "Format and mount fs"
56 _scratch_mkfs_sized $((1024 * 1024 * 1024)) >> $seqres.full
57 _scratch_mount >> $seqres.full
59 # Disable realtime inherit flag (if any) on root directory so that space on data
60 # device gets fragmented rather than realtime device.
61 $XFS_IO_PROG -c 'chattr -t' $SCRATCH_MNT
63 echo "Consume free space"
64 fillerdir=$SCRATCH_MNT/fillerdir
65 nr_free_blks=$(stat -f -c '%f' $SCRATCH_MNT)
66 nr_free_blks=$((nr_free_blks * 90 / 100))
68 _fill_fs $((dbsize * nr_free_blks)) $fillerdir $dbsize 0 >> $seqres.full 2>&1
70 echo "Create fragmented filesystem"
71 for dentry in $(ls -1 $fillerdir/); do
72 $here/src/punch-alternating $fillerdir/$dentry >> $seqres.full
75 echo "Inject reduce_max_iextents error tag"
76 _scratch_inject_error reduce_max_iextents 1
78 echo "Inject bmap_alloc_minlen_extent error tag"
79 _scratch_inject_error bmap_alloc_minlen_extent 1
83 echo "* Create directory entries"
85 testdir=$SCRATCH_MNT/testdir
88 nr_dents=$((dbsize * 20 / dent_len))
89 for i in $(seq 1 $nr_dents); do
90 dentry="$(printf "%0255d" $i)"
91 touch ${testdir}/$dentry >> $seqres.full 2>&1 || break
94 echo "Verify directory's extent count"
95 nextents=$(_xfs_get_fsxattr nextents $testdir)
96 if (( $nextents > 10 )); then
97 echo "Extent count overflow check failed: nextents = $nextents"
103 echo "* Rename: Populate destination directory"
105 dstdir=$SCRATCH_MNT/dstdir
108 nr_dents=$((dirbsize * 20 / dent_len))
110 echo "Populate \$dstdir by moving new directory entries"
111 for i in $(seq 1 $nr_dents); do
112 dentry="$(printf "%0255d" $i)"
113 dentry=${SCRATCH_MNT}/${dentry}
114 touch $dentry || break
115 mv $dentry $dstdir >> $seqres.full 2>&1 || break
120 echo "Verify \$dstdir's extent count"
122 nextents=$(_xfs_get_fsxattr nextents $dstdir)
123 if (( $nextents > 10 )); then
124 echo "Extent count overflow check failed: nextents = $nextents"
130 echo "* Create multiple hard links to a single file"
132 testdir=$SCRATCH_MNT/testdir
135 testfile=$SCRATCH_MNT/testfile
138 nr_dents=$((dirbsize * 20 / dent_len))
140 echo "Create multiple hardlinks"
141 for i in $(seq 1 $nr_dents); do
142 dentry="$(printf "%0255d" $i)"
143 ln $testfile ${testdir}/${dentry} >> $seqres.full 2>&1 || break
148 echo "Verify directory's extent count"
149 nextents=$(_xfs_get_fsxattr nextents $testdir)
150 if (( $nextents > 10 )); then
151 echo "Extent count overflow check failed: nextents = $nextents"
157 echo "* Create multiple symbolic links to a single file"
159 testdir=$SCRATCH_MNT/testdir
162 testfile=$SCRATCH_MNT/testfile
165 nr_dents=$((dirbsize * 20 / dent_len))
167 echo "Create multiple symbolic links"
168 for i in $(seq 1 $nr_dents); do
169 dentry="$(printf "%0255d" $i)"
170 ln -s $testfile ${testdir}/${dentry} >> $seqres.full 2>&1 || break;
175 echo "Verify directory's extent count"
176 nextents=$(_xfs_get_fsxattr nextents $testdir)
177 if (( $nextents > 10 )); then
178 echo "Extent count overflow check failed: nextents = $nextents"