On 5/8/20 3:01 PM, Zorro Lang wrote: > Set different block & inode grace timers for user, group and project > quotas, then test softlimit enforcement timeout, make sure different > grace timers as expected. > > Signed-off-by: Zorro Lang <zlang@xxxxxxxxxx> > --- > > Hi, > > Thanks Eric found the overlapping quota timer issue. I set user, group and > project quota grace time together, then test them one by one. That cause > the user quota test is affected by group/project timers. This v3 patch fix > this issue. > > But there's still a failure on XFS, about xfs group and project quota > always return ENOSPC to instead of EDQUOT, e.g: > > -pwrite: Disk quota exceeded > +pwrite: No space left on device > > Should I expect ENOSPC or EDQUOT both in this case? Yep, this will somehow need to account for the differences between ext4 and xfs. Or, we could commit the ENOSPC version and tell ext4 that they did project quotas wrong. ;) > And there's another weird thing is -- why ext4 test passed when there's > the overlapping quota timer issue in this case ... That'll take more investigation, don't know yet ... Thanks for working on this, -Eric > Thanks, > Zorro > > common/quota | 4 + > tests/generic/597 | 187 ++++++++++++++++++++++++++++++++++++++++++ > tests/generic/597.out | 41 +++++++++ > tests/generic/group | 1 + > 4 files changed, 233 insertions(+) > create mode 100755 tests/generic/597 > create mode 100644 tests/generic/597.out > > diff --git a/common/quota b/common/quota > index 240e0bbc..1437d5f7 100644 > --- a/common/quota > +++ b/common/quota > @@ -217,6 +217,10 @@ _qmount() > if [ "$FSTYP" != "xfs" ]; then > quotacheck -ug $SCRATCH_MNT >>$seqres.full 2>&1 > quotaon -ug $SCRATCH_MNT >>$seqres.full 2>&1 > + # try to turn on project quota if it's supported > + if quotaon --help 2>&1 | grep -q '\-\-project'; then > + quotaon --project $SCRATCH_MNT >>$seqres.full 2>&1 > + fi > fi > chmod ugo+rwx $SCRATCH_MNT > } > diff --git a/tests/generic/597 b/tests/generic/597 > new file mode 100755 > index 00000000..f87a7dc7 > --- /dev/null > +++ b/tests/generic/597 > @@ -0,0 +1,187 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) 2020 Red Hat, Inc. All Rights Reserved. > +# > +# FS QA Test No. 597 > +# > +# Test per-type(user, group and project) filesystem quota timers, make sure > +# enforcement > +# > +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() > +{ > + restore_project > + cd / > + rm -f $tmp.* > +} > + > +# get standard environment, filters and checks > +. ./common/rc > +. ./common/filter > +. ./common/quota > + > +# remove previous $seqres.full before test > +rm -f $seqres.full > + > +require_project() > +{ > + rm -f $tmp.projects $tmp.projid > + if [ -f /etc/projects ];then > + cat /etc/projects > $tmp.projects > + fi > + if [ -f /etc/projid ];then > + cat /etc/projid > $tmp.projid > + fi > + > + cat >/etc/projects <<EOF > +100:$SCRATCH_MNT/t > +EOF > + cat >/etc/projid <<EOF > +$qa_user:100 > +EOF > + PROJECT_CHANGED=1 > +} > + > +restore_project() > +{ > + if [ "$PROJECT_CHANGED" = "1" ];then > + rm -f /etc/projects /etc/projid > + if [ -f $tmp.projects ];then > + cat $tmp.projects > /etc/projects > + fi > + if [ -f $tmp.projid ];then > + cat $tmp.projid > /etc/projid > + fi > + fi > +} > + > +init_files() > +{ > + local dir=$1 > + > + echo "### Initialize files, and their mode and ownership" > + touch $dir/file{1,2} 2>/dev/null > + chown $qa_user $dir/file{1,2} 2>/dev/null > + chgrp $qa_user $dir/file{1,2} 2>/dev/null > + chmod 777 $dir 2>/dev/null > +} > + > +cleanup_files() > +{ > + echo "### Remove all files" > + rm -f ${1}/file{1,2,3,4,5,6} > +} > + > +test_grace() > +{ > + local type=$1 > + local dir=$2 > + local bgrace=$3 > + local igrace=$4 > + > + init_files $dir > + echo "--- Test block quota ---" > + # Firstly fit below block soft limit > + echo "Write 225 blocks..." > + su $qa_user -c "$XFS_IO_PROG -c 'pwrite 0 $((225 * $BLOCK_SIZE))' \ > + -c fsync $dir/file1" 2>&1 >>$seqres.full | \ > + _filter_xfs_io_error | tee -a $seqres.full > + repquota -v -$type $SCRATCH_MNT | grep -v "^root" >>$seqres.full 2>&1 > + # Secondly overcome block soft limit > + echo "Rewrite 250 blocks plus 1 byte, over the block softlimit..." > + su $qa_user -c "$XFS_IO_PROG -c 'pwrite 0 $((250 * $BLOCK_SIZE + 1))' \ > + -c fsync $dir/file1" 2>&1 >>$seqres.full | \ > + _filter_xfs_io_error | tee -a $seqres.full > + repquota -v -$type $SCRATCH_MNT | grep -v "^root" >>$seqres.full 2>&1 > + # Reset grace time here, make below grace time test more accurate > + setquota -$type $qa_user -T $bgrace $igrace $SCRATCH_MNT 2>/dev/null > + # Now sleep enough grace time and check that softlimit got enforced > + sleep $((bgrace + 1)) > + echo "Try to write 1 one more block after grace..." > + su $qa_user -c "$XFS_IO_PROG -c 'truncate 0' -c 'pwrite 0 $BLOCK_SIZE' \ > + $dir/file2" 2>&1 >>$seqres.full | _filter_xfs_io_error | \ > + tee -a $seqres.full > + repquota -v -$type $SCRATCH_MNT | grep -v "^root" >>$seqres.full 2>&1 > + echo "--- Test inode quota ---" > + # And now the softlimit test for inodes > + # First reset space limits so that we don't have problems with > + # space reservations on XFS > + setquota -$type $qa_user 0 0 3 100 $SCRATCH_MNT > + echo "Create 2 more files, over the inode softlimit..." > + su $qa_user -c "touch $dir/file3 $dir/file4" 2>&1 >>$seqres.full | \ > + _filter_scratch | tee -a $seqres.full > + repquota -v -$type $SCRATCH_MNT | grep -v "^root" >>$seqres.full 2>&1 > + # Reset grace time here, make below grace time test more accurate > + setquota -$type $qa_user -T $bgrace $igrace $SCRATCH_MNT 2>/dev/null > + # Wait and check grace time enforcement > + sleep $((igrace+1)) > + echo "Try to create one more inode after grace..." > + su $qa_user -c "touch $dir/file5" 2>&1 >>$seqres.full | > + _filter_scratch | tee -a $seqres.full > + repquota -v -$type $SCRATCH_MNT | grep -v "^root" >>$seqres.full 2>&1 > + cleanup_files $dir > +} > + > +# real QA test starts here > +_supported_fs generic > +_supported_os Linux > +_require_scratch > +_require_setquota_project > +_require_quota > +_require_user > +_require_group > + > +_scratch_mkfs >$seqres.full 2>&1 > +_scratch_enable_pquota > +_qmount_option "usrquota,grpquota,prjquota" > +_qmount > +_require_prjquota $SCRATCH_DEV > +BLOCK_SIZE=$(_get_file_block_size $SCRATCH_MNT) > +rm -rf $SCRATCH_MNT/t > +mkdir $SCRATCH_MNT/t > +$XFS_IO_PROG -r -c "chproj 100" -c "chattr +P" $SCRATCH_MNT/t > +require_project > + > +echo "### Set up different grace timers to each type of quota" > +UBGRACE=12 > +UIGRACE=10 > +GBGRACE=4 > +GIGRACE=2 > +PBGRACE=8 > +PIGRACE=6 > + > +setquota -u $qa_user $((250 * $BLOCK_SIZE / 1024)) \ > + $((1000 * $BLOCK_SIZE / 1024)) 3 100 $SCRATCH_MNT > +setquota -u -t $UBGRACE $UIGRACE $SCRATCH_MNT > +echo; echo "### Test user quota softlimit and grace time" > +test_grace u $SCRATCH_MNT $UBGRACE $UIGRACE > +# Reset the user quota space & inode limits, avoid it affect later test > +setquota -u $qa_user 0 0 0 0 $SCRATCH_MNT > + > +setquota -g $qa_user $((250 * $BLOCK_SIZE / 1024)) \ > + $((1000 * $BLOCK_SIZE / 1024)) 3 100 $SCRATCH_MNT > +setquota -g -t $GBGRACE $GIGRACE $SCRATCH_MNT > +echo; echo "### Test group quota softlimit and grace time" > +test_grace g $SCRATCH_MNT $GBGRACE $GIGRACE > +# Reset the group quota space & inode limits, avoid it affect later test > +setquota -g $qa_user 0 0 0 0 $SCRATCH_MNT > + > +setquota -P $qa_user $((250 * $BLOCK_SIZE / 1024)) \ > + $((1000 * $BLOCK_SIZE / 1024)) 3 100 $SCRATCH_MNT > +setquota -P -t $PBGRACE $PIGRACE $SCRATCH_MNT > +echo; echo "### Test project quota softlimit and grace time" > +test_grace P $SCRATCH_MNT/t $PBGRACE $PIGRACE > +# Reset the project quota space & inode limits > +setquota -P $qa_user 0 0 0 0 $SCRATCH_MNT > + > +# success, all done > +status=0 > +exit > diff --git a/tests/generic/597.out b/tests/generic/597.out > new file mode 100644 > index 00000000..57a68ee1 > --- /dev/null > +++ b/tests/generic/597.out > @@ -0,0 +1,41 @@ > +QA output created by 597 > +### Set up different grace timers to each type of quota > + > +### Test user quota softlimit and grace time > +### Initialize files, and their mode and ownership > +--- Test block quota --- > +Write 225 blocks... > +Rewrite 250 blocks plus 1 byte, over the block softlimit... > +Try to write 1 one more block after grace... > +pwrite: Disk quota exceeded > +--- Test inode quota --- > +Create 2 more files, over the inode softlimit... > +Try to create one more inode after grace... > +touch: cannot touch 'SCRATCH_MNT/file5': Disk quota exceeded > +### Remove all files > + > +### Test group quota softlimit and grace time > +### Initialize files, and their mode and ownership > +--- Test block quota --- > +Write 225 blocks... > +Rewrite 250 blocks plus 1 byte, over the block softlimit... > +Try to write 1 one more block after grace... > +pwrite: Disk quota exceeded > +--- Test inode quota --- > +Create 2 more files, over the inode softlimit... > +Try to create one more inode after grace... > +touch: cannot touch 'SCRATCH_MNT/file5': Disk quota exceeded > +### Remove all files > + > +### Test project quota softlimit and grace time > +### Initialize files, and their mode and ownership > +--- Test block quota --- > +Write 225 blocks... > +Rewrite 250 blocks plus 1 byte, over the block softlimit... > +Try to write 1 one more block after grace... > +pwrite: Disk quota exceeded > +--- Test inode quota --- > +Create 2 more files, over the inode softlimit... > +Try to create one more inode after grace... > +touch: cannot touch 'SCRATCH_MNT/t/file5': Disk quota exceeded > +### Remove all files > diff --git a/tests/generic/group b/tests/generic/group > index 718575ba..10af4c41 100644 > --- a/tests/generic/group > +++ b/tests/generic/group > @@ -598,3 +598,4 @@ > 594 auto quick quota > 595 auto quick encrypt > 596 auto quick > +597 auto quick quota >