new file mode 100755
@@ -0,0 +1,478 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2020 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com>.
+#
+# FS QA Test 002
+#
+# Sanity check of ext4 mount options
+#
+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()
+{
+ cd /
+ $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
+ if [ -n "$LOOP_LOGDEV" ];then
+ _destroy_loop_device $LOOP_LOGDEV 2>/dev/null
+ fi
+ 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
+
+echo "Silence is golden."
+
+_supported_fs generic
+_supported_os Linux
+_require_scratch
+_require_quota
+_require_loop
+
+LOG=""
+print_log() {
+ LOG="$LOG $@"
+}
+
+KERNEL_VERSION=`uname -r | cut -d'.' -f1,2`
+kernel_gte() {
+ gte=`echo "$KERNEL_VERSION >= $1" | $BC_PROG`
+ [ $gte -eq 1 ] && return 0
+ return 1
+}
+
+# This test is only relevant for the newer kernel
+kernel_gte 4.19 || _notrun "This test is only relevant for kernel versions 5.7 and higher"
+
+IGNORED="remount,defaults,ignored,removed"
+CHECK_MINFO="lazytime"
+ERR=0
+
+test_mnt() {
+ findmnt -n $SCRATCH_DEV > /dev/null 2>&1
+ [ $? -ne 0 ] && return $?
+
+ if [ $# -eq 1 ]; then
+ OPTS=$1
+ elif [ $# -eq 2 ]; then
+ OPTS=$2
+ else
+ return 0
+ fi
+
+ print_log "checking \"$OPTS\" "
+ # test options in /proc/fs/ext4/dev/options
+ (
+ ret=0
+ IFS=','
+ for option in $OPTS; do
+ if echo $IGNORED | grep -w $option; then
+ continue
+ fi
+
+ [ $option = "noload" ] && option="norecovery"
+
+ if [[ $option = ^* ]]; then
+ expected=1
+ else
+ expected=0
+ fi
+ option=${option#^}
+
+ if echo $CHECK_MINFO | grep -w $option; then
+ findmnt -n -o OPTIONS $SCRATCH_DEV | grep $option
+ ret=$?
+ else
+ grep $option /proc/fs/ext4/$(basename $SCRATCH_DEV)/options
+ ret=$?
+ fi
+
+ if [ $ret -ne $expected ]; then
+ exit 1
+ fi
+ done
+ ) > /dev/null 2>&1
+ return $?
+}
+
+fail() {
+ print_log " FAILED"
+ ERR=$((ERR+1))
+ echo $LOG | tee -a $seqres.full
+ LOG=""
+}
+
+ok() {
+ print_log " OK"
+ echo $LOG >> $seqres.full
+ LOG=""
+}
+
+simple_mount() {
+ _mount $* >> $seqres.full 2>&1
+}
+
+# $1 - can hold -n option, if it does argumetns are shifted
+# $1 - options to test
+# $2 - if provided it's the option string to check for
+do_mnt() {
+ device=$SCRATCH_DEV
+ # If -n argument is provided do not specify $SCRATCH_DEV
+ # usefull for remount
+ if [ "$1" == "-n" ]; then
+ unset device
+ shift
+ fi
+
+ if [ -z "$1" ]; then
+ simple_mount $device $SCRATCH_MNT
+ ret=$?
+ else
+ simple_mount -o $1 $device $SCRATCH_MNT
+ ret=$?
+ fi
+ if [ $ret -eq 0 ]; then
+ test_mnt $1 $2
+ ret=$?
+ [ $ret -ne 0 ] && print_log "(not found)"
+ else
+ print_log "(failed mount)"
+ fi
+
+ return $ret
+}
+
+not_mnt() {
+ print_log "SHOULD FAIL mounting \"$1\" "
+ do_mnt $@
+ if [ $? -eq 0 ]; then
+ fail
+ else
+ ok
+ fi
+ $UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+}
+
+_mnt() {
+ print_log "mounting \"$1\" "
+ do_mnt $@
+ if [ $? -ne 0 ]; then
+ fail
+ else
+ ok
+ fi
+}
+
+mnt() {
+ _mnt $*
+ $UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+}
+
+# $1 - options to mount with
+# $2 - options to remount with
+remount() {
+ # First do this specifying both dev and mnt
+ print_log "mounting \"$1\" "
+ do_mnt $1
+ [ $? -ne 0 ] && fail && return
+ print_log "remounting \"$2\" "
+ do_mnt remount,$2 $3
+ if [ $? -ne 0 ]; then
+ fail
+ $UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+ return
+ else
+ ok
+ fi
+ $UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+
+ # Now just specify mnt
+ print_log "mounting \"$1\" "
+ do_mnt $1
+ [ $? -ne 0 ] && fail && return
+ print_log "remounting (MNT ONLY) \"$2\" "
+ do_mnt -n remount,$2 $3
+ if [ $? -ne 0 ]; then
+ fail
+ else
+ ok
+ fi
+
+ $UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+}
+
+# $1 - options to mount with, or -r argument
+# $2 - options to remount with
+_not_remount() {
+ remount_only=0
+ # If -r is specified we're going to do remount only
+ if [ "$1" == "-r" ]; then
+ remount_only=1
+ # Dont need shift since first argument would
+ # have been consumed by mount anyway
+ fi
+
+ if [ $remount_only -eq 0 ]; then
+ print_log "mounting \"$1\" "
+ do_mnt $1
+ [ $? -ne 0 ] && fail && return
+ fi
+ print_log "SHOULD FAIL remounting \"$2\" "
+ do_mnt remount,$2 $3
+ if [ $? -eq 0 ]; then
+ fail
+ else
+ ok
+ fi
+
+ # Now just specify mnt
+ print_log "SHOULD FAIL remounting (MNT ONLY) \"$2\" "
+ do_mnt -n remount,$2 $3
+ if [ $? -eq 0 ]; then
+ fail
+ else
+ ok
+ fi
+}
+
+not_remount() {
+ _not_remount $*
+ $UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+}
+
+
+do_mkfs() {
+ $MKFS_EXT4_PROG -Fq $* >> $seqres.full 2>&1 ||
+ _fail "mkfs failed - $MKFS_EXT4_PROG -Fq $* $SCRATCH_DEV"
+}
+
+$UMOUNT_PROG $SCRATCH_MNT 2> /dev/null
+$UMOUNT_PROG $SCRATCH_DEV 2> /dev/null
+
+do_mkfs $SCRATCH_DEV
+
+not_mnt failme
+mnt
+mnt bsddf
+mnt minixdf
+mnt grpid
+mnt bsdgroups grpid
+mnt nogrpid
+mnt sysvgroups nogrpid
+mnt resgid=1001
+mnt resuid=1001
+mnt sb=131072
+mnt errors=continue
+mnt errors=panic
+mnt errors=remount-ro
+mnt nouid32
+mnt debug
+mnt oldalloc removed
+mnt orlov removed
+mnt user_xattr
+mnt nouser_xattr
+mnt noload norecovery
+mnt bh removed
+mnt nobh removed
+mnt commit=7
+mnt min_batch_time=200
+mnt max_batch_time=10000
+mnt journal_checksum
+mnt nojournal_checksum
+mnt journal_async_commit,data=writeback
+mnt abort ignored
+mnt data=journal
+mnt data=ordered
+mnt data=writeback
+mnt data_err=abort
+mnt data_err=ignore ignored
+mnt usrjquota=aquota.user,jqfmt=vfsv0
+not_mnt usrjquota=aquota.user # should fail
+mnt usrjquota= ignored
+mnt grpjquota=aquota.group,jqfmt=vfsv0
+not_mnt grpjquota=aquota.group # should fail
+mnt grpjquota= ignored
+mnt jqfmt=vfsold
+mnt jqfmt=vfsv0
+mnt jqfmt=vfsv1
+mnt grpquota
+mnt quota
+mnt noquota
+mnt usrquota
+mnt grpquota
+mnt barrier
+mnt barrier=0 nobarrier
+mnt barrier=1 barrier
+mnt barrier=99 barrier
+mnt nobarrier
+mnt i_version
+#mnt dax
+mnt stripe=512
+mnt delalloc
+mnt nodelalloc
+mnt warn_on_error
+mnt nowarn_on_error
+mnt lazytime
+mnt nolazytime ^lazytime
+not_mnt debug_want_extra_isize=512
+mnt debug_want_extra_isize=32 ignored
+mnt mblk_io_submit removed
+mnt nomblk_io_submit removed
+mnt block_validity
+mnt noblock_validity
+mnt inode_readahead_blks=16
+mnt journal_ioprio=6 ignored
+mnt auto_da_alloc=0 noauto_da_alloc
+mnt auto_da_alloc=1 auto_da_alloc
+mnt auto_da_alloc=95 auto_da_alloc
+mnt auto_da_alloc
+mnt noauto_da_alloc
+mnt dioread_nolock
+kernel_gte 5.6 && mnt nodioread_nolock
+kernel_gte 5.6 && mnt dioread_lock nodioread_nolock
+mnt discard
+mnt nodiscard
+mnt init_itable=20
+mnt init_itable
+mnt init_itable=0
+mnt noinit_itable
+mnt max_dir_size_kb=4096
+mnt test_dummy_encryption
+mnt nombcache
+mnt no_mbcache nombcache
+mnt check=none removed
+mnt nocheck removed
+mnt reservation removed
+mnt noreservation removed
+not_mnt journal=20
+not_mnt nonsenseoption
+not_mnt nonsenseoption=value
+
+# generic remount check
+remount barrier nobarrier
+remount nobarrier barrier
+remount discard nodiscard
+remount nodiscard discard
+
+# Quota remount check
+remount grpquota usrquota
+remount usrquota quota
+remount usrquota usrjquota=q.u,jqfmt=vfsv0
+remount grpquota grpjquota=q.g,jqfmt=vfsv0
+
+not_remount usrquota grpjquota=q.g,jqfmt=vfsv0
+not_remount grpquota usrjquota=q.u,jqfmt=vfsv0
+
+remount quota usrjquota=q.u,jqfmt=vfsv0
+not_remount quota grpjquota=q.g,jqfmt=vfsv0
+
+remount usrjquota=q.u,jqfmt=vfsv0 grpjquota=q.g
+not_remount usrjquota=q.u,jqfmt=vfsv0 usrjquota=q.ua
+not_remount grpjquota=q.g,jqfmt=vfsv0 grpjquota=q.ga
+
+remount usrjquota=q.u,jqfmt=vfsv0 usrquota usrjquota=q.u,jqfmt=vfsv0
+remount grpjquota=q.g,jqfmt=vfsv0 grpquota grpjquota=q.g,jqfmt=vfsv0
+not_remount usrjquota=q.u,jqfmt=vfsv0 grpquota
+not_remount grpjquota=q.g,jqfmt=vfsv0 usrquota
+
+remount grpjquota=q.g,jqfmt=vfsv0 grpjquota= ^grpjquota=
+remount usrjquota=q.u,jqfmt=vfsv0 usrjquota= ^usrjquota=
+remount grpjquota=q.g,usrjquota=q.u,jqfmt=vfsv0 grpjquota=,usrjquota= ^grpjquota=,^usrjquota=
+
+remount jqfmt=vfsv0 grpjquota=q.g
+remount jqfmt=vfsv0 usrjquota=q.u
+
+remount noload data=journal norecovery
+not_remount data=ordered data=journal
+not_remount data=journal data=writeback
+not_remount data=writeback data=ordered
+
+# Create logdev for external journal
+LOOP_IMG=$tmp.logdev
+truncate -s 100M $LOOP_IMG
+LOOP_LOGDEV=`_create_loop_device $LOOP_IMG`
+majmin=`stat -c "%t:%T" $LOOP_LOGDEV`
+LOGDEV_DEVNUM=`echo "${majmin%:*}*2^8 + ${majmin#*:}" | bc`
+
+do_mkfs -O journal_dev $LOOP_LOGDEV
+do_mkfs -J device=$LOOP_LOGDEV $SCRATCH_DEV
+mnt defaults
+mnt journal_path=$LOOP_LOGDEV ignored
+mnt journal_dev=$LOGDEV_DEVNUM ignored
+not_mnt journal_path=${LOOP_LOGDEV}_nonexistent ignored
+not_mnt journal_dev=123456 ignored
+not_mnt journal_dev=999999999999999 ignored
+
+do_mkfs -E quotatype=prjquota $SCRATCH_DEV
+mnt prjquota
+
+# test clearing/changing journalled quota when enabled
+echo "== Testing active journalled quota" >> $seqres.full
+_mnt prjquota,grpjquota=aquota.group,usrjquota=aquota.user,jqfmt=vfsv0
+
+# Prepare and enable quota
+#quotaoff -f $SCRATCH_MNT >> $seqres.full 2>&1
+quotacheck -vugm $SCRATCH_MNT >> $seqres.full 2>&1
+quotaon -vug $SCRATCH_MNT >> $seqres.full 2>&1
+
+_not_remount -r grpjquota=
+_not_remount -r usrjquota=aaquota.user
+_not_remount -r grpjquota=aaquota.group
+_not_remount -r jqfmt=vfsv1
+_not_remount -r noquota
+_mnt remount,usrquota,grpquota ^usrquota,^grpquota
+$UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
+
+# test clearing/changing quota when enabled
+do_mkfs -E quotatype=^prjquota $SCRATCH_DEV
+not_mnt prjquota
+echo "== Testing active non-journalled quota" >> $seqres.full
+_mnt grpquota,usrquota
+
+# Prepare and enable quota
+#quotaoff -f $SCRATCH_MNT >> $seqres.full 2>&1
+quotacheck -vugm $SCRATCH_MNT >> $seqres.full 2>&1
+quotaon -vug $SCRATCH_MNT >> $seqres.full 2>&1
+
+_not_remount -r noquota
+_not_remount -r usrjquota=aquota.user
+_not_remount -r grpjquota=aquota.group
+_not_remount -r jqfmt=vfsv1
+_mnt remount,grpjquota= grpquota,^grpjquota
+_mnt remount,usrjquota= usrquota,^usrjquota
+_mnt remount,usrquota,grpquota usrquota,grpquota
+quotaoff -f $SCRATCH_MNT >> $seqres.full 2>&1
+_mnt remount,noquota ^usrquota,^grpquota,quota
+$UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
+
+# Quota feature
+echo "== Testing quota feature " >> $seqres.full
+do_mkfs -O quota -E quotatype=prjquota $SCRATCH_DEV
+mnt usrjquota=aquota.user,jqfmt=vfsv0 ^usrjquota=
+mnt grpjquota=aquota.user,jqfmt=vfsv0 ^grpjquota=
+mnt jqfmt=vfsv1 ^jqfmt=
+mnt prjquota
+mnt usrquota
+mnt grpquota
+not_remount defaults usrjquota=aquota.user
+not_remount defaults grpjquota=aquota.user
+not_remount defaults jqfmt=vfsv1
+remount defaults grpjquota=,usrjquota= ignored
+
+$UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1
+echo "$ERR errors encountered" >> $seqres.full
+
+status=$ERR
+exit
new file mode 100644
@@ -0,0 +1,2 @@
+QA output created by 002
+Silence is golden.
@@ -4,6 +4,7 @@
# - comment line before each group is "new" description
#
001 auto prealloc quick zero
+002 auto mount
003 auto quick
004 auto dump
005 auto quick metadata ioctl rw
Add test to validate that the ext4 mount options are properly recognized, validated and applied to avoid regression as ext4 moves to the new mount API. Signed-off-by: Lukas Czerner <lczerner@redhat.com> --- tests/ext4/002 | 478 +++++++++++++++++++++++++++++++++++++++++++++ tests/ext4/002.out | 2 + tests/ext4/group | 1 + 3 files changed, 481 insertions(+) create mode 100755 tests/ext4/002 create mode 100644 tests/ext4/002.out