generic: test MADV_POPULATE_READ with IO errors
[xfstests-dev.git] / tests / xfs / 294
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2017 Red Hat, Inc.  All Rights Reserved.
4 #
5 # FS QA Test 294
6 #
7 # Test readdir on fragmented multi-fsb dir blocks
8 #
9 # If the readahead map ends with a partial multi-fsb dir
10 # block, the loop at the end of xfs_dir2_leaf_readbuf() may
11 # walk off the end of the mapping array, read garbage,
12 # corrupt the loop control counter, and never return.
13 #
14 # Failure is a hang; KASAN should also catch this.
15 #
16 . ./common/preamble
17 _begin_fstest auto dir metadata
18
19 # Import common functions.
20 . ./common/filter
21
22 # real QA test starts here
23
24 # Modify as appropriate.
25 _supported_fs xfs
26 _require_scratch
27 _require_test_program "punch-alternating"
28 _require_xfs_io_command "falloc"
29 _require_xfs_io_command "fpunch"
30
31 # We want to mkfs with a very specific geometry
32 MKFS_OPTIONS=""
33 _scratch_mkfs "-d size=512m -n size=8192 -i size=1024" >> $seqres.full 2>&1 \
34         || _fail "mkfs failed"
35 _scratch_mount
36
37 # Make a ton of mostly-empty inode clusters so we can always
38 # make more inodes
39 mkdir $SCRATCH_MNT/tmp
40 for I in `seq 1 10000`; do touch $SCRATCH_MNT/tmp/$I; done
41
42 # These mostly-empty clusters will live here:
43 mkdir $SCRATCH_MNT/clusters
44 for I in `seq 1 32 10000`; do
45         mv $SCRATCH_MNT/tmp/$I $SCRATCH_MNT/clusters;
46 done
47 rm -rf $SCRATCH_MNT/tmp
48
49 # Make our test dir with a couple blocks, should be contiguous
50 mkdir $SCRATCH_MNT/testdir
51 # roughly 20 chars per file
52 for I in `seq 1 100`; do
53         touch $SCRATCH_MNT/testdir/12345678901234567890$I;
54 done
55
56 # File to fragment:
57 $XFS_IO_PROG -f -c "falloc 0 70m" $SCRATCH_MNT/fragfile ||
58         _fail "Could not allocate space"
59
60 # Now completely fragment freespace.
61 # Consume most of it:
62 space=$(stat -f -c '%f * %S * 95 / 100' $SCRATCH_MNT | $BC_PROG)
63 $XFS_IO_PROG -f -c "falloc 0 $space" $SCRATCH_MNT/fillfile ||
64         _fail "Could not allocate space"
65
66 df -h $SCRATCH_MNT >> $seqres.full 2>&1
67
68 # Fill remaining space; let this run to failure
69 dd if=/dev/zero of=$SCRATCH_MNT/spacefile1 oflag=direct >> $seqres.full 2>&1
70 # Fragment our all-consuming file
71 $here/src/punch-alternating $SCRATCH_MNT/fragfile >> $seqres.full 2>&1
72
73 # Punching might have freed up large-ish swaths of metadata
74 # Consume hopefully any remaining contiguous freespace
75 # (and then some for good measure)
76 dd conv=fsync if=/dev/zero of=$SCRATCH_MNT/spacefile2 bs=1M count=64 >> $seqres.full 2>&1
77
78 # Now populate the directory so that it must allocate these
79 # fragmented blocks
80 for I in `seq 1 1400`; do
81         touch $SCRATCH_MNT/testdir/12345678901234567890$I;
82 done
83
84 # Now traverse that ugly thing!
85 find $SCRATCH_MNT/testdir | sort | _filter_scratch | md5sum
86
87 status=0
88 exit