#!/bin/bash # FS QA Test No. 260 # # Purpose of this test is to check FITRIM argument handling to make sure # that the argument processing is right and that it does not overflow. # #----------------------------------------------------------------------- # Copyright 2011 (C) Red Hat, Inc., Lukas Czerner # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write the Free Software Foundation, # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #----------------------------------------------------------------------- owner=lczerner@redhat.com seq=`basename $0` echo "QA output created by $seq" here=`pwd` tmp=`mktemp -d` status=0 trap "exit \$status" 0 1 2 3 15 chpid=0 mypid=$$ # get standard environment, filters and checks . ./common.rc . ./common.filter # real QA test starts here _supported_fs generic _supported_os Linux _require_math _require_fstrim _require_scratch _scratch_mkfs >/dev/null 2>&1 _scratch_mount _test_batched_discard $SCRATCH_MNT || _notrun "FITRIM not supported on $SCRATCH_DEV" fssize=$(df -k | grep "$SCRATCH_MNT" | grep "$SCRATCH_DEV" | awk '{print $2}') beyond_eofs=$(_math "$fssize*2048") max_64bit=$(_math "2^64 - 1") # All these tests should return EINVAL # since the start is beyond the end of # the file system echo "[+] Start beyond the end of fs (should fail)" out=$($FSTRIM_PROG -o $beyond_eofs $SCRATCH_MNT 2>&1) [ $? -eq 0 ] && status=1 echo $out | _filter_scratch echo "[+] Start beyond the end of fs with len set (should fail)" out=$($FSTRIM_PROG -o $beyond_eofs -l1M $SCRATCH_MNT 2>&1) [ $? -eq 0 ] && status=1 echo $out | _filter_scratch echo "[+] Start = 2^64-1 (should fail)" out=$($FSTRIM_PROG -o $max_64bit $SCRATCH_MNT 2>&1) [ $? -eq 0 ] && status=1 echo $out | _filter_scratch echo "[+] Start = 2^64-1 and len is set (should fail)" out=$($FSTRIM_PROG -o $max_64bit -l1M $SCRATCH_MNT 2>&1) [ $? -eq 0 ] && status=1 echo $out | _filter_scratch _scratch_unmount _scratch_mkfs >/dev/null 2>&1 _scratch_mount # All these tests should succeed # since the length should be truncated echo "[+] Default length (should succeed)" $FSTRIM_PROG $SCRATCH_MNT [ $? -ne 0 ] && status=1 echo "[+] Default length with start set (should succeed)" $FSTRIM_PROG -o10M $SCRATCH_MNT [ $? -ne 0 ] && status=1 echo "[+] Length beyond the end of fs (should succeed)" $FSTRIM_PROG -l $beyond_eofs $SCRATCH_MNT [ $? -ne 0 ] && status=1 echo "[+] Length beyond the end of fs with start set (should succeed)" $FSTRIM_PROG -o10M -l $beyond_eofs $SCRATCH_MNT [ $? -ne 0 ] && status=1 _scratch_unmount _scratch_mkfs >/dev/null 2>&1 _scratch_mount # This is a bit fuzzy, but since the file system is fresh # there should be at least (fssize/2) free space to trim. # This is supposed to catch wrong FITRIM argument handling out=$($FSTRIM_PROG -v -o10M $SCRATCH_MNT) nopref=${out##*: } bytes=${nopref%% *} if [ $bytes -gt $(_math "$fssize*1024") ]; then status=1 echo "After the full fs discard $bytes bytes were discarded"\ "however the file system is $(_math "$fssize*1024") bytes long." fi # Btrfs is special and this test does not apply to it # It is because btrfs does not have not-yet-used parts of the device # mapped and since we got here right after the mkfs, there is not # enough free extents in the root tree. if [ $bytes -le $(_math "$fssize*512") ] && [ $FSTYP != "btrfs" ]; then status=1 echo "After the full fs discard $bytes bytes were discarded"\ "however the file system is $(_math "$fssize*1024") bytes long." fi # Now to catch overflows due to fsblk->allocation group number conversion # This is different for every file system and it also apply just to some of # them. In order to add check specific for file system you're interested in # compute the arguments as you need and make the file system with proper # alignment # (2^32-1) + 2 (this is set to overflow 32bit variable by 2) base=$(_math "2^32+1") case $FSTYP in ext[34]) agsize=32768 bsize=4096 start=$(_math "$base*$agsize*$bsize") len=$start export MKFS_OPTIONS="-F -b $bsize -g $agsize" ;; xfs) agsize=65538 bsize=4096 start=$(_math "$base*$agsize*$bsize") len=$start export MKFS_OPTIONS="-f -d agsize=$(_math "$agsize*$bsize") -b size=$bsize" ;; *) # (2^32-1) * 4096 * 65536 == 32bit max size * block size * ag size start=$(_math "(2^32 - 1) * 4096 * 65536") len=$start ;; esac _scratch_unmount _scratch_mkfs >/dev/null 2>&1 _scratch_mount # It should fail since $start is beyond the end of file system $FSTRIM_PROG -o$start -l10M $SCRATCH_MNT &> /dev/null if [ $? -eq 0 ]; then status=1 echo "It seems that fs logic handling start"\ "argument overflows" fi _scratch_unmount _scratch_mkfs >/dev/null 2>&1 _scratch_mount # len should be big enough to cover the whole file system, so if the # number of discarded bytes is smaller than file system size/2 then it # most likely overflowed # Btrfs is special and this test does not apply to it # It is because btrfs does not have not-yet-used parts of the device # mapped and since we got here right after the mkfs, there is not # enough free extents in the root tree. out=$($FSTRIM_PROG -v -l$len $SCRATCH_MNT) nopref=${out##*: } bytes=${nopref%% *} if [ $bytes -le $(_math "$fssize*512") ] && [ $FSTYP != "btrfs" ]; then status=1 echo "It seems that fs logic handling len argument overflows" fi echo "Test done" exit