xfs: quotas on idmapped mounts
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 12 Apr 2021 11:57:08 +0000 (13:57 +0200)
committerEryu Guan <guaneryu@gmail.com>
Sun, 18 Apr 2021 12:53:53 +0000 (20:53 +0800)
This is basically a re-implementation of xfs/050 but each file creation
call is done through an idmapped mount which verifies that the semantics
are identical even when the mount is idmapped.

Cc: Eryu Guan <guan@eryu.me>
Cc: Darrick J. Wong <djwong@kernel.org>
Cc: fstests@vger.kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Eryu Guan <guaneryu@gmail.com>
tests/xfs/153 [new file with mode: 0755]
tests/xfs/153.out [new file with mode: 0644]
tests/xfs/group

diff --git a/tests/xfs/153 b/tests/xfs/153
new file mode 100755 (executable)
index 0000000..ab2469d
--- /dev/null
@@ -0,0 +1,212 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2021 Christian Brauner <christian.brauner@ubuntu.com>
+# All Rights Reserved.
+#
+# FS QA Test No. 153
+#
+# Exercises basic XFS quota functionality
+#       uquota, gquota, uqnoenforce, gqnoenforce
+#
+seq=`basename $0`
+seqres=$RESULT_DIR/$seq
+echo "QA output created by $seq"
+
+here=`pwd`
+tmp=/tmp/$$
+status=1       # failure is the default!
+
+# get standard environment, filters and checks
+. ./common/rc
+. ./common/filter
+. ./common/quota
+
+_cleanup()
+{
+       cd /
+       _scratch_unmount 2>/dev/null
+       rm -f $tmp.*
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# real QA test starts here
+_supported_fs xfs
+
+cp /dev/null $seqres.full
+chmod a+rwx $seqres.full       # arbitrary users will write here
+
+_require_scratch
+_require_xfs_quota
+_require_user fsgqa
+_require_test_program "idmapped-mounts/mount-idmapped"
+
+_scratch_mkfs >/dev/null 2>&1
+_scratch_mount
+bsize=$(_get_file_block_size $SCRATCH_MNT)
+_scratch_unmount
+
+bsoft=$(( 200 * $bsize ))
+bhard=$(( 1000 * $bsize ))
+isoft=4
+ihard=10
+
+# The actual point at which limit enforcement takes place for the
+# hard block limit is variable depending on filesystem blocksize,
+# and iosize.  What we want to test is that the limit is enforced
+# (ie. blksize less than limit but not unduly less - ~85% is kind)
+# nowadays we actually get much closer to the limit before EDQUOT.
+#
+_filter_and_check_blks()
+{
+       perl -npe '
+               if (/^\#'$id'\s+(\d+)/ && '$enforce') {
+                       $maximum = '$bhard';
+                       $minimum = '$bhard' * 85/100;
+                       $used = $1 * 1024;
+                       if (($used < $minimum || $used > $maximum) && '$noextsz') {
+                               printf(" URK %d: %d is out of range! [%d,%d]\n",
+                                       '$id', $used, $minimum, $maximum);
+                       }
+                       s/^(\#'$id'\s+)(\d+)/\1 =OK=/g;
+               }
+       ' | _filter_quota_report
+}
+
+run_tests()
+{
+       _scratch_mkfs_xfs | _filter_mkfs 2>$tmp.mkfs
+       cat $tmp.mkfs >>$seqres.full
+
+       # keep the blocksize and data size for dd later
+       . $tmp.mkfs
+
+       _qmount
+
+       # Figure out whether we're doing large allocations
+       # (bail out if they're so large they stuff the test up)
+       _test_inode_flag extsz-inherit $SCRATCH_MNT
+       noextsz=$?
+       extsize=`_test_inode_extsz $SCRATCH_MNT`
+       [ $extsize -ge 512000 ] && \
+               _notrun "Extent size hint is too large ($extsize bytes)"
+
+       _qsetup $1
+
+       echo "Using type=$type id=$id" >>$seqres.full
+
+       $XFS_QUOTA_PROG -x -c "warn -$type 65535 -d" $SCRATCH_DEV
+
+       echo
+       echo "*** report no quota settings" | tee -a $seqres.full
+       $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
+               -c "repquota -birnN -$type" $SCRATCH_DEV |
+               _filter_quota_report | LC_COLLATE=POSIX sort -ru
+
+       echo
+       echo "*** report initial settings" | tee -a $seqres.full
+       _scratch_mount_idmapped $type $id
+       _file_as_id $SCRATCH_MNT/initme 0 $type 1024 0
+       _scratch_umount_idmapped
+       echo "ls -l $SCRATCH_MNT" >>$seqres.full
+       ls -l $SCRATCH_MNT >>$seqres.full
+       $XFS_QUOTA_PROG -D $tmp.projects -P $temp.projid -x \
+               -c "limit -$type bsoft=${bsoft} bhard=${bhard} $id" \
+               -c "limit -$type isoft=$isoft ihard=$ihard $id" \
+               $SCRATCH_DEV
+       $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
+               -c "repquota -birnN -$type" $SCRATCH_DEV |
+               _filter_quota_report | LC_COLLATE=POSIX sort -ru
+
+       echo
+       echo "*** push past the soft inode limit" | tee -a $seqres.full
+       _scratch_mount_idmapped $type $id
+       _file_as_id $SCRATCH_MNT/softie1 0 $type 1024 0
+       _file_as_id $SCRATCH_MNT/softie2 0 $type 1024 0
+       _file_as_id $SCRATCH_MNT/softie3 0 $type 1024 0
+       _file_as_id $SCRATCH_MNT/softie4 0 $type 1024 0
+       _scratch_umount_idmapped
+       _qmount
+       $XFS_QUOTA_PROG -x -c "warn -i -$type 0 $id" $SCRATCH_DEV
+       $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
+               -c "repquota -birnN -$type" $SCRATCH_DEV |
+               _filter_quota_report | LC_COLLATE=POSIX sort -ru
+
+       echo
+       echo "*** push past the soft block limit" | tee -a $seqres.full
+       _scratch_mount_idmapped $type $id
+       _file_as_id $SCRATCH_MNT/softie 0 $type $bsize 300
+       _scratch_umount_idmapped
+       _qmount
+       $XFS_QUOTA_PROG -x -c "warn -i -$type 0 $id" \
+               -c "warn -b -$type 0 $id" $SCRATCH_DEV
+       $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
+               -c "repquota -birnN -$type" $SCRATCH_DEV |
+               _filter_quota_report | LC_COLLATE=POSIX sort -ru
+
+       echo
+       # Note: for quota accounting (not enforcement), EDQUOT is not expected
+       echo "*** push past the hard inode limit (expect EDQUOT)" | tee -a $seqres.full
+       for i in 1 2 3 4 5 6 7 8 9 10 11 12
+       do
+               _scratch_mount_idmapped $type $id
+               _file_as_id $SCRATCH_MNT/hard$i 0 $type 1024 0
+               _scratch_umount_idmapped
+       done
+       _qmount
+       $XFS_QUOTA_PROG -x  -c "warn -b -$type 0 $id" \
+               -c "warn -i -$type 0 $id" $SCRATCH_DEV
+       $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
+               -c "repquota -birnN -$type" $SCRATCH_DEV |
+               _filter_quota_report | LC_COLLATE=POSIX sort -ru
+
+       echo
+       # Note: for quota accounting (not enforcement), EDQUOT is not expected
+       echo "*** push past the hard block limit (expect EDQUOT)" | tee -a $seqres.full
+       _scratch_mount_idmapped $type $id
+       _file_as_id $SCRATCH_MNT/softie 0 $type $bsize 1200
+       _scratch_umount_idmapped
+       echo "ls -l $SCRATCH_MNT" >>$seqres.full
+       ls -l $SCRATCH_MNT >>$seqres.full
+       _qmount
+       $XFS_QUOTA_PROG -x -c "warn -b -$type 0 $id" $SCRATCH_DEV
+       $XFS_QUOTA_PROG -D $tmp.projects -P $tmp.projid -x \
+               -c "repquota -birnN -$type" $SCRATCH_DEV |
+               _filter_and_check_blks | LC_COLLATE=POSIX sort -ru
+
+       echo
+       echo "*** unmount"
+       _scratch_unmount
+
+}
+
+cat >$tmp.projects <<EOF
+1:$SCRATCH_MNT
+EOF
+
+cat >$tmp.projid <<EOF
+root:0
+scrach:1
+EOF
+
+projid_file="$tmp.projid"
+
+echo "*** user"
+_qmount_option "uquota"
+run_tests u
+
+echo "*** group"
+_qmount_option "gquota"
+run_tests g
+
+echo "*** uqnoenforce"
+_qmount_option "uqnoenforce"
+run_tests uno
+
+echo "*** gqnoenforce"
+_qmount_option "gqnoenforce"
+run_tests gno
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/153.out b/tests/xfs/153.out
new file mode 100644 (file)
index 0000000..9202475
--- /dev/null
@@ -0,0 +1,129 @@
+QA output created by 153
+*** user
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+*** report no quota settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+
+*** report initial settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 1 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the soft inode limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 5 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** push past the soft block limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [7 days] 6 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** push past the hard inode limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [7 days] 10 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** push past the hard block limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] =OK= 200 1000 0 [7 days] 10 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** unmount
+*** group
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+*** report no quota settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+
+*** report initial settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 1 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the soft inode limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 5 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** push past the soft block limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [7 days] 6 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** push past the hard inode limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [7 days] 10 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** push past the hard block limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] =OK= 200 1000 0 [7 days] 10 4 10 00 [7 days] 0 0 0 00 [--------]
+
+*** unmount
+*** uqnoenforce
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+*** report no quota settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+
+*** report initial settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 1 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the soft inode limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 5 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the soft block limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [--------] 6 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the hard inode limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [--------] 18 4 10 00 [--none--] 0 0 0 00 [--------]
+
+*** push past the hard block limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 1200 200 1000 00 [--none--] 18 4 10 00 [--none--] 0 0 0 00 [--------]
+
+*** unmount
+*** gqnoenforce
+meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
+data     = bsize=XXX blocks=XXX, imaxpct=PCT
+         = sunit=XXX swidth=XXX, unwritten=X
+naming   =VERN bsize=XXX
+log      =LDEV bsize=XXX blocks=XXX
+realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
+
+*** report no quota settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+
+*** report initial settings
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 1 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the soft inode limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 0 200 1000 00 [--------] 5 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the soft block limit
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [--------] 6 4 10 00 [--------] 0 0 0 00 [--------]
+
+*** push past the hard inode limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 300 200 1000 00 [--------] 18 4 10 00 [--none--] 0 0 0 00 [--------]
+
+*** push past the hard block limit (expect EDQUOT)
+[ROOT] 0 0 0 00 [--------] 3 0 0 00 [--------] 0 0 0 00 [--------]
+[NAME] 1200 200 1000 00 [--none--] 18 4 10 00 [--none--] 0 0 0 00 [--------]
+
+*** unmount
index caf7bb7c71077adf9eeaccf13c47d4080c3178ff..d1b1456b19c4a4110adb0591efef2480a5f634c6 100644 (file)
 150 auto quick db
 151 auto quick db
 152 auto quick quota idmapped
 150 auto quick db
 151 auto quick db
 152 auto quick quota idmapped
+153 auto quick quota idmapped
 164 rw pattern auto prealloc quick
 165 rw pattern auto prealloc quick
 166 rw metadata auto quick
 164 rw pattern auto prealloc quick
 165 rw pattern auto prealloc quick
 166 rw metadata auto quick