This adds a swap test for tiny discontiguous swapfile. This was causing a kernel crash on XFS with kernel <= v4.18 and could cause a invalid huge swapfile to get registered on latest kernel which may lead to random corruption later. (This happens only on bs < ps configuration) More details about the kernel issue could be found in commit msg of the fix at [1]. [1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=5808fecc572391867fcd929662b29c12e6d08d81 Signed-off-by: Ritesh Harjani <riteshh@xxxxxxxxxxxxx> --- tests/generic/639 | 78 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/639.out | 2 ++ tests/generic/group | 1 + 3 files changed, 81 insertions(+) create mode 100755 tests/generic/639 create mode 100644 tests/generic/639.out diff --git a/tests/generic/639 b/tests/generic/639 new file mode 100755 index 00000000..3c6d8f1b --- /dev/null +++ b/tests/generic/639 @@ -0,0 +1,78 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2021 YOUR NAME HERE. All Rights Reserved. +# +# FS QA Test 639 +# +# Test tiny swapfile with discontiguity. This was causing a kernel crash on XFS +# with kernel version <= v4.18. And/or could cause a invalid swapfilesize to get +# registered, which could cause some corruption later in the running kernel. +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=0 # success is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + rm -f $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter + +# remove previous $seqres.full before test +rm -f $seqres.full + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_require_test +_require_xfs_io_command "fcollapse" +_require_test_program mkswap +_require_test_program swapon +_require_scratch_swapfile + +_scratch_mkfs >>$seqres.full 2>&1 +_scratch_mount >>$seqres.full 2>&1 + +SWAPFILE=$SCRATCH_MNT/swapscratch-$seq +PS=$(get_page_size) +BS=$(_get_block_size $SCRATCH_MNT) + +if [ $BS -gt $(($PS / 4)) ]; then + _notrun "This test requires blocksize atleast less or equal to pagesize/4, bs=$BS, ps=$PS" +fi + +# create a swapfile +$XFS_IO_PROG -f -c "pwrite 0 $(($PS + $PS + $BS + $BS))" -c fsync $SWAPFILE >> $seqres.full +$XFS_IO_PROG -c "fcollapse $(($PS - $BS)) $BS" $SWAPFILE >> $seqres.full +$XFS_IO_PROG -c "fcollapse $(($PS*2 - $BS*2)) $BS" $SWAPFILE >> $seqres.full +$CHATTR_PROG +C $SWAPFILE >> $seqres.full 2>&1 +"$here/src/mkswap" $SWAPFILE + +"$here/src/swapon" $SWAPFILE >> $seqres.full 2>&1 +ret=$? +if [ $ret -eq 0 ]; then + swapsize_kb=$(cat /proc/swaps |grep $SWAPFILE |awk '{print $3}') + swapsize=$(($swapsize_kb * 1024)) + filesize=$(_get_filesize $SWAPFILE) + + # error case + if [ $swapsize -gt $filesize ]; then + status=1 + echo "Allocated swap size($swapsize) cannot be greater than swapfile size($filesize)" + fi +fi +swapoff $SWAPFILE >> $seqres.full 2>&1 + +echo "Silence is golden" +exit diff --git a/tests/generic/639.out b/tests/generic/639.out new file mode 100644 index 00000000..62c66537 --- /dev/null +++ b/tests/generic/639.out @@ -0,0 +1,2 @@ +QA output created by 639 +Silence is golden diff --git a/tests/generic/group b/tests/generic/group index 9a636b23..48ffa3c7 100644 --- a/tests/generic/group +++ b/tests/generic/group @@ -641,3 +641,4 @@ 636 auto quick swap 637 auto quick dir 638 auto quick rw +639 auto quick swap -- 2.31.1