mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
69eb6281a9
Previously _scratch_mount didn't check the mount status and most tests continue to run even if the mount failed (unless test checks for the mount status explicitly). This would result in running tests on the underlying filesystem (usually rootfs) and implicit test failures, and such failures can be annoying and are usually hard to debug. Now _fail test by default if _scratch_mount failed and introduce _try_scratch_mount for tests that need to check mount results themselves. Suggested-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Eryu Guan <eguan@redhat.com>
319 lines
9.1 KiB
Plaintext
319 lines
9.1 KiB
Plaintext
##/bin/bash
|
|
#
|
|
# Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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
|
|
#
|
|
#
|
|
# Functions useful for quota tests
|
|
#
|
|
|
|
#
|
|
# checks that the generic quota support in the kernel is enabled
|
|
# and that we have valid quota user tools installed.
|
|
#
|
|
_require_quota()
|
|
{
|
|
[ -n "$QUOTA_PROG" ] || _notrun "Quota user tools not installed"
|
|
|
|
case $FSTYP in
|
|
ext2|ext3|ext4|ext4dev|reiserfs)
|
|
if [ ! -d /proc/sys/fs/quota ]; then
|
|
_notrun "Installed kernel does not support quotas"
|
|
fi
|
|
;;
|
|
gfs2|ocfs2)
|
|
;;
|
|
xfs)
|
|
if [ ! -f /proc/fs/xfs/xqmstat ]; then
|
|
_notrun "Installed kernel does not support XFS quotas"
|
|
fi
|
|
if [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ]; then
|
|
_notrun "Quotas not supported on realtime test device"
|
|
fi
|
|
if [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ]; then
|
|
_notrun "Quotas not supported on realtime scratch device"
|
|
fi
|
|
;;
|
|
*)
|
|
_notrun "disk quotas not supported by this filesystem type: $FSTYP"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#
|
|
# checks that the XFS quota support in the kernel is enabled
|
|
# and that we have valid quota user tools installed.
|
|
#
|
|
_require_xfs_quota()
|
|
{
|
|
src/feature -q $TEST_DEV
|
|
[ $? -ne 0 ] && _notrun "Installed kernel does not support XFS quota"
|
|
if [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_RTDEV" ]; then
|
|
_notrun "Quotas not supported on realtime test device"
|
|
fi
|
|
if [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_RTDEV" ]; then
|
|
_notrun "Quotas not supported on realtime scratch device"
|
|
fi
|
|
[ -n "$XFS_QUOTA_PROG" ] || _notrun "XFS quota user tools not installed"
|
|
}
|
|
|
|
#
|
|
# checks that xfs_quota can operate on foreign (non-xfs) filesystems
|
|
# Skips check on xfs filesystems, old xfs_quota is fine there.
|
|
# Appends "-f" to enable foreign behavior on non-xfs filesystems if available.
|
|
#
|
|
_require_xfs_quota_foreign()
|
|
{
|
|
if [ "$FSTYP" != "xfs" ]; then
|
|
$XFS_QUOTA_PROG -f -V &>/dev/null || \
|
|
_notrun "xfs_quota binary does not support foreign filesystems"
|
|
XFS_QUOTA_PROG="$XFS_QUOTA_PROG -f"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# checks that the project quota support in the kernel is enabled.
|
|
#
|
|
_require_prjquota()
|
|
{
|
|
[ -n "$1" ] && _dev="$1" || _dev="$TEST_DEV"
|
|
if [ "$FSTYP" == "ext4" ]; then
|
|
dumpe2fs -h $_dev 2>&1 | grep -qw project || \
|
|
_notrun "Project quota not available on this ext4"
|
|
fi
|
|
src/feature -P $_dev
|
|
[ $? -ne 0 ] && _notrun "Installed kernel does not support project quotas"
|
|
if [ "$USE_EXTERNAL" = yes -a ! -z "$_dev" ]; then
|
|
_notrun "Project quotas not supported on realtime filesystem"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Do we have GETNEXTQUOTA? Querying ID 0 should work.
|
|
#
|
|
_require_getnextquota()
|
|
{
|
|
_require_test_program "test-nextquota"
|
|
$here/src/test-nextquota -i 0 -u -d $SCRATCH_DEV &> $seqres.full || \
|
|
_notrun "No GETNEXTQUOTA support"
|
|
}
|
|
|
|
#
|
|
# ext4 (for now) is unique in that we must enable the project quota feature
|
|
# prior to mount. This is a relatively new feature ...
|
|
_scratch_enable_pquota()
|
|
{
|
|
[ "$FSTYP" != "ext4" ] && return
|
|
|
|
tune2fs -O quota,project $SCRATCH_DEV >>$seqres.full 2>&1
|
|
_try_scratch_mount >/dev/null 2>&1 \
|
|
|| _notrun "kernel doesn't support project feature on $FSTYP"
|
|
_scratch_unmount
|
|
}
|
|
|
|
#
|
|
# checks for user nobody in /etc/passwd and /etc/group.
|
|
#
|
|
_require_nobody()
|
|
{
|
|
_cat_passwd | grep -q '^nobody'
|
|
[ $? -ne 0 ] && _notrun "password file does not contain user nobody."
|
|
|
|
_cat_group | egrep -q '^no(body|group)'
|
|
[ $? -ne 0 ] && _notrun "group file does not contain nobody/nogroup."
|
|
}
|
|
|
|
# create a file as a specific user (uid)
|
|
# takes filename, id, type (u/g/p), blocksize, blockcount
|
|
#
|
|
_file_as_id()
|
|
{
|
|
[ $# != 5 ] && _fail "broken call to _file_as_id in test $seq"
|
|
|
|
parent=`dirname $1`
|
|
if [ $3 = p ]; then
|
|
echo PARENT: $XFS_IO_PROG -r -c "chproj $2" -c "chattr +P" $parent >>$seqres.full
|
|
$XFS_IO_PROG -r -c "chproj $2" -c "chattr +P" $parent >>$seqres.full 2>&1
|
|
magik='$>' # (irrelevent, above set projid-inherit-on-parent)
|
|
elif [ $3 = u ]; then
|
|
magik='$>' # perlspeak for effective uid
|
|
elif [ $3 = g ]; then
|
|
magik='$)' # perlspeak for effective gid
|
|
else
|
|
_notrun "broken type in call to _file_as_id in test $seq"
|
|
fi
|
|
|
|
perl <<EOF >>$seqres.full 2>&1
|
|
\$| = 1;
|
|
$magik = $2;
|
|
if ($5 == 0) {
|
|
print "touch $1";
|
|
exec "touch $1";
|
|
} else {
|
|
print "dd if=/dev/zero of=$1 bs=$4 count=$5";
|
|
exec "dd if=/dev/zero of=$1 bs=$4 count=$5";
|
|
}
|
|
EOF
|
|
# for debugging the above euid change, try... [need write in cwd]
|
|
# exec "dd if=/dev/zero of=$1 bs=$4 count=$5 >>$seqres.full 2>&1";
|
|
|
|
if [ $3 = p ]; then
|
|
echo PARENT: $XFS_IO_PROG -r -c "chproj 0" -c "chattr -P" $parent >>$seqres.full
|
|
$XFS_IO_PROG -r -c "chproj 0" -c "chattr -P" $parent >>$seqres.full 2>&1
|
|
fi
|
|
}
|
|
|
|
_choose_uid()
|
|
{
|
|
_cat_passwd | grep '^nobody' | perl -ne '@a = split(/:/); END { printf "id=%d name=%s\n", $a[2],$a[0] }'
|
|
}
|
|
|
|
_choose_gid()
|
|
{
|
|
_cat_group | egrep '^no(body|group)' | perl -ne '@a = split(/:/); END { printf "id=%d name=%s\n", $a[2],$a[0] }'
|
|
}
|
|
|
|
_choose_prid()
|
|
{
|
|
if [ "X$projid_file" == "X" ]; then
|
|
projid_file=/etc/projid
|
|
fi
|
|
if [ ! -f $projid_file ]; then
|
|
echo 0
|
|
return
|
|
fi
|
|
perl -ne '@a = split(/:/); END { printf "id=%d name=%s\n", $a[1],$a[0] }' \
|
|
$projid_file
|
|
}
|
|
|
|
_qmount()
|
|
{
|
|
_scratch_unmount >/dev/null 2>&1
|
|
_try_scratch_mount || _fail "qmount failed"
|
|
# xfs doesn't need these setups and quotacheck even fails on xfs
|
|
# redirect the output to $seqres.full for debug purpose and ignore results
|
|
if [ "$FSTYP" != "xfs" ]; then
|
|
quotacheck -ug $SCRATCH_MNT >>$seqres.full 2>&1
|
|
quotaon -ug $SCRATCH_MNT >>$seqres.full 2>&1
|
|
fi
|
|
chmod ugo+rwx $SCRATCH_MNT
|
|
}
|
|
|
|
#
|
|
# Ensures only the given quota mount option is used
|
|
#
|
|
_qmount_option()
|
|
{
|
|
OPTS=$1
|
|
|
|
# Replace any user defined quota options
|
|
# with the quota option that we want.
|
|
# Simplest to do this rather than delete existing ones first because
|
|
# of the variety of commas and spaces and multiple -o's
|
|
# that we'd have to cater for. Doesn't matter if we have duplicates.
|
|
# Use "QUOTA" string so that we don't have any substring confusion
|
|
# thanks to "quota" which will match with "uquota" and "gquota" etc.
|
|
export MOUNT_OPTIONS=`echo $MOUNT_OPTIONS \
|
|
| sed -e 's/uquota/QUOTA/g' \
|
|
-e 's/usrquota/QUOTA/g' \
|
|
-e 's/gquota/QUOTA/g' \
|
|
-e 's/grpquota/QUOTA/g' \
|
|
-e 's/\bpquota/QUOTA/g' \
|
|
-e 's/prjquota/QUOTA/g' \
|
|
-e 's/quota/QUOTA/g' \
|
|
-e 's/uqnoenforce/QUOTA/g' \
|
|
-e 's/gqnoenforce/QUOTA/g' \
|
|
-e 's/pqnoenforce/QUOTA/g' \
|
|
-e 's/qnoenforce/QUOTA/g' \
|
|
-e "s/QUOTA/$OPTS/g"`
|
|
|
|
# ext4 doesn't _do_ "-o pquota/prjquota" because reasons
|
|
# Switch it to "quota" to enable mkfs-time pquota
|
|
if [ "$FSTYP" == "ext4" ]; then
|
|
OPTS=`echo $OPTS \
|
|
| sed -e 's/\bpquota/quota/g' \
|
|
-e 's/prjquota/quota/g'`
|
|
fi
|
|
# Ensure we have the given quota option - duplicates are fine
|
|
export MOUNT_OPTIONS="$MOUNT_OPTIONS -o $OPTS"
|
|
echo "MOUNT_OPTIONS = $MOUNT_OPTIONS" >>$seqres.full
|
|
}
|
|
|
|
_check_quota_usage()
|
|
{
|
|
# Sync to get delalloc to disk
|
|
sync
|
|
|
|
# kill caches to guarantee removal speculative delalloc
|
|
# XXX: really need an ioctl instead of this big hammer
|
|
echo 3 > /proc/sys/vm/drop_caches
|
|
|
|
VFS_QUOTA=0
|
|
case $FSTYP in
|
|
ext2|ext3|ext4|ext4dev|reiserfs|gfs2)
|
|
VFS_QUOTA=1
|
|
quotaon -f -u -g $SCRATCH_MNT 2>/dev/null
|
|
;;
|
|
xfs)
|
|
# Clear out speculative preallocations to eliminate them
|
|
# as a source of intermittent orig/checked differences.
|
|
test -x "$XFS_SPACEMAN_PROG" && \
|
|
"$XFS_SPACEMAN_PROG" -c 'prealloc -s' $SCRATCH_MNT
|
|
;;
|
|
*)
|
|
;;
|
|
esac
|
|
repquota -u -n $SCRATCH_MNT | grep -v "^#0" | _filter_scratch |
|
|
sort >$tmp.user.orig
|
|
repquota -g -n $SCRATCH_MNT | grep -v "^#0" | _filter_scratch |
|
|
sort >$tmp.group.orig
|
|
if [ $VFS_QUOTA -eq 1 ]; then
|
|
quotacheck -u -g $SCRATCH_MNT 2>/dev/null
|
|
else
|
|
# use XFS method to force quotacheck
|
|
xfs_quota -x -c "off -ug" $SCRATCH_MNT
|
|
_scratch_unmount
|
|
_scratch_mount "-o usrquota,grpquota"
|
|
fi
|
|
repquota -u -n $SCRATCH_MNT | grep -v "^#0" | _filter_scratch |
|
|
sort >$tmp.user.checked
|
|
repquota -g -n $SCRATCH_MNT | grep -v "^#0" | _filter_scratch |
|
|
sort >$tmp.group.checked
|
|
if [ $VFS_QUOTA -eq 1 ]; then
|
|
quotaon -u -g $SCRATCH_MNT 2>/dev/null
|
|
fi
|
|
{
|
|
echo "Comparing user usage"
|
|
diff $tmp.user.orig $tmp.user.checked
|
|
} && {
|
|
echo "Comparing group usage"
|
|
diff $tmp.group.orig $tmp.group.checked
|
|
}
|
|
}
|
|
|
|
# Report the block usage of root, $qa_user, and nobody
|
|
_report_quota_blocks() {
|
|
repquota $1 | egrep "^($qa_user|root|nobody)" | awk '{print $1, $3, $4, $5}'
|
|
}
|
|
|
|
# Report the inode usage of root, $qa_user, and nobody
|
|
_report_quota_inodes() {
|
|
repquota $1 | egrep "^($qa_user|root|nobody)" | awk '{print $1, $6, $7, $8}'
|
|
}
|
|
|
|
# make sure this script returns success
|
|
/bin/true
|