#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2017 Red Hat, Inc. All Rights Reserved. # # FS QA Test 294 # # Test readdir on fragmented multi-fsb dir blocks # # If the readahead map ends with a partial multi-fsb dir # block, the loop at the end of xfs_dir2_leaf_readbuf() may # walk off the end of the mapping array, read garbage, # corrupt the loop control counter, and never return. # # Failure is a hang; KASAN should also catch this. # . ./common/preamble _begin_fstest auto dir metadata # Import common functions. . ./common/filter # real QA test starts here # Modify as appropriate. _supported_fs xfs _require_scratch _require_test_program "punch-alternating" _require_xfs_io_command "falloc" _require_xfs_io_command "fpunch" # We want to mkfs with a very specific geometry MKFS_OPTIONS="" _scratch_mkfs "-d size=512m -n size=8192 -i size=1024" >> $seqres.full 2>&1 \ || _fail "mkfs failed" _scratch_mount # Make a ton of mostly-empty inode clusters so we can always # make more inodes mkdir $SCRATCH_MNT/tmp for I in `seq 1 10000`; do touch $SCRATCH_MNT/tmp/$I; done # These mostly-empty clusters will live here: mkdir $SCRATCH_MNT/clusters for I in `seq 1 32 10000`; do mv $SCRATCH_MNT/tmp/$I $SCRATCH_MNT/clusters; done rm -rf $SCRATCH_MNT/tmp # Make our test dir with a couple blocks, should be contiguous mkdir $SCRATCH_MNT/testdir # roughly 20 chars per file for I in `seq 1 100`; do touch $SCRATCH_MNT/testdir/12345678901234567890$I; done # File to fragment: $XFS_IO_PROG -f -c "falloc 0 70m" $SCRATCH_MNT/fragfile || _fail "Could not allocate space" # Now completely fragment freespace. # Consume most of it: space=$(stat -f -c '%f * %S * 95 / 100' $SCRATCH_MNT | $BC_PROG) $XFS_IO_PROG -f -c "falloc 0 $space" $SCRATCH_MNT/fillfile || _fail "Could not allocate space" df -h $SCRATCH_MNT >> $seqres.full 2>&1 # Fill remaining space; let this run to failure dd if=/dev/zero of=$SCRATCH_MNT/spacefile1 oflag=direct >> $seqres.full 2>&1 # Fragment our all-consuming file $here/src/punch-alternating $SCRATCH_MNT/fragfile >> $seqres.full 2>&1 # Punching might have freed up large-ish swaths of metadata # Consume hopefully any remaining contiguous freespace # (and then some for good measure) dd conv=fsync if=/dev/zero of=$SCRATCH_MNT/spacefile2 bs=1M count=64 >> $seqres.full 2>&1 # Now populate the directory so that it must allocate these # fragmented blocks for I in `seq 1 1400`; do touch $SCRATCH_MNT/testdir/12345678901234567890$I; done # Now traverse that ugly thing! find $SCRATCH_MNT/testdir | sort | _filter_scratch | md5sum status=0 exit