| #!/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 <lczerner@redhat.com> | |
| # | |
| # 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_scratch | |
| _scratch_mkfs >/dev/null 2>&1 | |
| _scratch_mount | |
| FSTRIM="$here/src/fstrim" | |
| "$FSTRIM" -l 10M $SCRATCH_MNT &> /dev/null || _notrun "FSTRIM is not supported" | |
| 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)" | |
| "$FSTRIM" -s $beyond_eofs $SCRATCH_MNT | |
| [ $? -eq 0 ] && status=1 | |
| echo "[+] Start beyond the end of fs with len set (should fail)" | |
| "$FSTRIM" -s $beyond_eofs -l1M $SCRATCH_MNT | |
| [ $? -eq 0 ] && status=1 | |
| echo "[+] Start = 2^64-1 (should fail)" | |
| "$FSTRIM" -s $max_64bit $SCRATCH_MNT | |
| [ $? -eq 0 ] && status=1 | |
| echo "[+] Start = 2^64-1 and len is set (should fail)" | |
| "$FSTRIM" -s $max_64bit -l1M $SCRATCH_MNT | |
| [ $? -eq 0 ] && status=1 | |
| _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" $SCRATCH_MNT | |
| [ $? -ne 0 ] && status=1 | |
| echo "[+] Default length with start set (should succeed)" | |
| "$FSTRIM" -s10M $SCRATCH_MNT | |
| [ $? -ne 0 ] && status=1 | |
| echo "[+] Length beyond the end of fs (should succeed)" | |
| "$FSTRIM" -l $beyond_eofs $SCRATCH_MNT | |
| [ $? -ne 0 ] && status=1 | |
| echo "[+] Length beyond the end of fs with start set (should succeed)" | |
| "$FSTRIM" -s10M -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" -v -s10M $SCRATCH_MNT) | |
| bytes=${out%% *} | |
| 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" -s$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" -v -l$len $SCRATCH_MNT) | |
| bytes=${out%% *} | |
| 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 |