xfs: Check for extent overflow when trivally adding a new extent
[xfstests-dev.git] / tests / xfs / 432
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2017, Oracle and/or its affiliates.  All Rights Reserved.
4 #
5 # FS QA Test No. 432
6 #
7 # Ensure that metadump copies large directory extents
8 #
9 # Metadump helpfully discards directory (and xattr) extents that are
10 # longer than 1000 blocks.  This is a little silly since a hardlink farm
11 # can easily create such a monster.
12 #
13 # Now that we've upped metadump's default too-long-extent discard
14 # threshold to 2^21 blocks, make sure we never do that again.
15 #
16 seq=`basename "$0"`
17 seqres="$RESULT_DIR/$seq"
18 echo "QA output created by $seq"
19
20 here=`pwd`
21 tmp=/tmp/$$
22 status=1    # failure is the default!
23 trap "_cleanup; exit \$status" 0 1 2 3 15
24
25 _cleanup()
26 {
27         cd /
28         rm -f "$tmp".* $metadump_file $metadump_img
29 }
30
31 # get standard environment, filters and checks
32 . ./common/rc
33 . ./common/filter
34
35 # real QA test starts here
36 _supported_fs xfs
37 _require_scratch
38
39 rm -f "$seqres.full"
40
41 echo "Format and mount"
42 # We need to create a directory with a huuuge extent record.  Normally
43 # a rapidly expanding directory gets its blocks allocated in lockstep --
44 # physically we end up writing (a couple of dir data blocks) followed by
45 # (a da btree block) over and over.
46 #
47 # Therefore, we crank the directory block size up to maximum and the
48 # filesystem down to minimum so that we have to allocate 64 blocks at
49 # a time, trying to end up with the result that we have > 1000 blocks
50 # allocated in a single extent.
51 #
52 # In theory the math works out here -- ~65500 bytes for a da leaf block /
53 # 8 bytes per da leaf entry == ~8187 hash entries for a da node.  65500
54 # bytes for a dir data block / 264 bytes per dirent == ~248 dirents per
55 # block.  8187 hashes/dablk / 248 dirents/dirblock = ~33 dirblocks per
56 # dablock.  33 dirblocks * 64k mean that we can expand a directory by
57 # 2112k before we have to allocate another da btree block.
58 _scratch_mkfs -b size=1k -n size=64k > "$seqres.full" 2>&1
59 _scratch_mount >> "$seqres.full" 2>&1
60
61 metadump_file="$TEST_DIR/meta-$seq"
62 metadump_img="$TEST_DIR/img-$seq"
63 rm -f $metadump_file $metadump_img
64 testdir="$SCRATCH_MNT/test-$seq"
65 max_fname_len=255
66 blksz=$(_get_block_size $SCRATCH_MNT)
67
68 # Try to create a directory w/ extents
69 blocks=1050
70 names=$((blocks * (blksz / max_fname_len)))
71 echo "Create huge dir"
72 mkdir -p $testdir
73 touch $SCRATCH_MNT/a
74 seq 0 $names | while read f; do
75         name="$testdir/$(printf "%0${max_fname_len}d" $f)"
76         ln $SCRATCH_MNT/a $name
77 done
78 dir_inum=$(stat -c %i $testdir)
79
80 echo "Check for > 1000 block extent?"
81 _scratch_unmount
82 check_for_long_extent() {
83         inum=$1
84
85         _scratch_xfs_db -x -c "inode $dir_inum" -c bmap | \
86                 sed -e 's/^.*count \([0-9]*\) flag.*$/\1/g' | \
87                 awk '{if ($1 > 1000) { printf("yes, %d\n", $1); } }'
88 }
89 extlen="$(check_for_long_extent $dir_inum)"
90 echo "qualifying extent: $extlen blocks" >> $seqres.full
91 test -n "$extlen" || _notrun "could not create dir extent > 1000 blocks"
92
93 echo "Try to metadump"
94 _scratch_xfs_metadump $metadump_file -w
95 xfs_mdrestore $metadump_file $metadump_img
96
97 echo "Check restored metadump image"
98 $XFS_REPAIR_PROG -n $metadump_img >> $seqres.full 2>&1
99
100 # success, all done
101 status=0
102 exit