| #! /bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (C) 2019 SUSE Linux Products GmbH. All Rights Reserved. |
| # |
| # FS QA Test 192 |
| # |
| # Test btrfs consistency after each FUA for a workload with snapshot creation |
| # and removal |
| # |
| seq=`basename $0` |
| seqres=$RESULT_DIR/$seq |
| echo "QA output created by $seq" |
| |
| here=`pwd` |
| tmp=/tmp/$$ |
| status=1 # failure is the default! |
| trap "_cleanup; exit \$status" 0 1 2 3 15 |
| |
| _cleanup() |
| { |
| cd / |
| kill -q $pid1 &> /dev/null |
| kill -q $pid2 &> /dev/null |
| "$KILLALL_PROG" -q $FSSTRESS_PROG &> /dev/null |
| wait |
| _log_writes_cleanup &> /dev/null |
| rm -f $tmp.* |
| } |
| |
| # get standard environment, filters and checks |
| . ./common/rc |
| . ./common/filter |
| . ./common/attr |
| . ./common/dmlogwrites |
| |
| # remove previous $seqres.full before test |
| rm -f $seqres.full |
| |
| # real QA test starts here |
| |
| # Modify as appropriate. |
| _supported_fs btrfs |
| |
| _require_command "$KILLALL_PROG" killall |
| _require_command "$BLKDISCARD_PROG" blkdiscard |
| _require_btrfs_fs_feature "no_holes" |
| _require_btrfs_mkfs_feature "no-holes" |
| _require_log_writes |
| _require_scratch |
| _require_attrs |
| |
| # We require a 4K nodesize to ensure the test isn't too slow |
| if [ $(get_page_size) -ne 4096 ]; then |
| _notrun "This test doesn't support non-4K page size yet" |
| fi |
| |
| runtime=30 |
| nr_cpus=$("$here/src/feature" -o) |
| # cap nr_cpus to 8 to avoid spending too much time on hosts with many cpus |
| if [ $nr_cpus -gt 8 ]; then |
| nr_cpus=8 |
| fi |
| fsstress_args=$(_scale_fsstress_args -w -d $SCRATCH_MNT -n 99999 -p $nr_cpus \ |
| $FSSTRESS_AVOID) |
| _log_writes_init $SCRATCH_DEV |
| |
| # Discard the whole devices so when some tree pointer is wrong, it won't point |
| # to some older valid tree blocks, so we can detect it. |
| $BLKDISCARD_PROG $LOGWRITES_DMDEV > /dev/null 2>&1 |
| |
| # Use no-holes to avoid warnings of missing file extent items (expected |
| # for holes due to mix of buffered and direct IO writes). |
| # And use 4K nodesize to bump tree height. |
| _log_writes_mkfs -O no-holes -n 4k >> $seqres.full |
| _log_writes_mount |
| |
| $BTRFS_UTIL_PROG subvolume create $SCRATCH_MNT/src > /dev/null |
| mkdir -p $SCRATCH_MNT/snapshots |
| mkdir -p $SCRATCH_MNT/src/padding |
| |
| random_file() |
| { |
| local basedir=$1 |
| echo "$basedir/$(ls $basedir | sort -R | tail -1)" |
| } |
| |
| snapshot_workload() |
| { |
| trap "wait; exit" SIGTERM |
| |
| local i=0 |
| while true; do |
| $BTRFS_UTIL_PROG subvolume snapshot \ |
| $SCRATCH_MNT/src $SCRATCH_MNT/snapshots/$i \ |
| > /dev/null |
| # Do something small to make snapshots different |
| rm -f "$(random_file $SCRATCH_MNT/src/padding)" |
| rm -f "$(random_file $SCRATCH_MNT/src/padding)" |
| touch "$(random_file $SCRATCH_MNT/src/padding)" |
| touch "$SCRATCH_MNT/src/padding/random_$RANDOM" |
| |
| i=$(($i + 1)) |
| sleep 1 |
| done |
| } |
| |
| delete_workload() |
| { |
| trap "wait; exit" SIGTERM |
| |
| while true; do |
| sleep 2 |
| $BTRFS_UTIL_PROG subvolume delete \ |
| "$(random_file $SCRATCH_MNT/snapshots)" \ |
| > /dev/null 2>&1 |
| done |
| } |
| |
| # Replay and check each fua/flush (specified by $2) point. |
| # |
| # Since dm-log-writes records bio sequentially, even just replaying a range |
| # still needs to iterate all records before the end point. |
| # When number of records grows, it will be unacceptably slow, thus we need |
| # to use relay-log itself to trigger fsck, avoid unnecessary seek. |
| log_writes_fast_replay_check() |
| { |
| local check_point=$1 |
| local blkdev=$2 |
| local fsck_command="$BTRFS_UTIL_PROG check $blkdev" |
| local ret |
| |
| [ -z "$check_point" -o -z "$blkdev" ] && _fail \ |
| "check_point and blkdev must be specified for log_writes_fast_replay_check" |
| |
| $here/src/log-writes/replay-log --log $LOGWRITES_DEV \ |
| --replay $blkdev --check $check_point --fsck "$fsck_command" \ |
| &> $tmp.full_fsck |
| ret=$? |
| tail -n 150 $tmp.full_fsck > $seqres.full |
| [ $ret -ne 0 ] && _fail "fsck failed during replay" |
| } |
| |
| xattr_value=$(printf '%0.sX' $(seq 1 3800)) |
| |
| # Bumping tree height to level 2. |
| for ((i = 0; i < 64; i++)); do |
| touch "$SCRATCH_MNT/src/padding/$i" |
| $SETFATTR_PROG -n 'user.x1' -v $xattr_value "$SCRATCH_MNT/src/padding/$i" |
| done |
| |
| _log_writes_mark prepare |
| |
| snapshot_workload & |
| pid1=$! |
| delete_workload & |
| pid2=$! |
| |
| "$FSSTRESS_PROG" $fsstress_args > /dev/null & |
| sleep $runtime |
| |
| "$KILLALL_PROG" -q "$FSSTRESS_PROG" &> /dev/null |
| kill $pid1 &> /dev/null |
| kill $pid2 &> /dev/null |
| wait |
| _log_writes_unmount |
| _log_writes_remove |
| |
| log_writes_fast_replay_check fua "$SCRATCH_DEV" |
| |
| echo "Silence is golden" |
| |
| # success, all done |
| status=0 |
| exit |