. common/config
-BC=$(which bc 2> /dev/null) || BC=
-
-# Some tests are not relevant or functional when testing XFS realtime
-# subvolumes along with the rtinherit=1 mkfs option. In these cases,
-# this test will opt-out of the test.
-_require_no_rtinherit()
-{
- [ "$FSTYP" = "xfs" ] && echo "$MKFS_OPTIONS" |
- egrep -q "rtinherit([^=]|=1|$)" && \
- _notrun "rtinherit mkfs option is not supported by this test."
-}
+BC="$(type -P bc)" || BC=
_require_math()
{
dd()
{
- if [ "$HOSTOS" == "Linux" ]
- then
command dd --help 2>&1 | grep noxfer >/dev/null
-
if [ "$?" -eq 0 ]
then
command dd status=noxfer $@
else
command dd $@
- fi
- else
- command dd $@
- fi
+ fi
}
# Prints the md5 checksum of a given file
9p)
;;
ceph)
+ . ./common/ceph
;;
glusterfs)
;;
local params="$*"
local last_index=$(( $# - 1 ))
- #get mount point to handle dmapi mtpt option correctly
[ $last_index -gt 0 ] && shift $last_index
local fs_escaped=$1
- echo $params | sed -e 's/dmapi/dmi/' \
- | $PERL_PROG -ne "s#mtpt=[^,|^\n|^\s]*#mtpt=$fs_escaped\1\2#; print;"
+ echo $params | \
+ $PERL_PROG -ne "s#mtpt=[^,|^\n|^\s]*#mtpt=$fs_escaped\1\2#; print;"
}
# mount scratch device with given options and _fail if mount fails
_scratch_mount()
{
- _try_scratch_mount $* || _fail "mount failed"
+ _try_scratch_mount $* || _fail "mount $(_scratch_mount_options $*) failed"
+}
+
+_scratch_mount_idmapped()
+{
+ local type="$1"
+ local id="$2"
+
+ if [ "$type" = "u" ]; then
+ # This means root will be able to create files as uid %id in
+ # the underlying filesystem by going through the idmapped mount.
+ $here/src/idmapped-mounts/mount-idmapped --map-mount u:0:$id:1 \
+ --map-mount u:$id:0:1 \
+ --map-mount g:0:0:1 \
+ "$SCRATCH_MNT" "$SCRATCH_MNT" || _fail "mount-idmapped failed"
+ elif [ "$type" = "g" ]; then
+ # This means root will be able to create files as gid %id in
+ # the underlying filesystem by going through the idmapped mount.
+ $here/src/idmapped-mounts/mount-idmapped --map-mount g:0:$id:1 \
+ --map-mount g:$id:0:1 \
+ --map-mount u:0:0:1 \
+ "$SCRATCH_MNT" "$SCRATCH_MNT" || _fail "mount-idmapped failed"
+ elif [ "$type" = "b" ]; then
+ # This means root will be able to create files as uid and gid
+ # %id in the underlying filesystem by going through the idmapped mount.
+ $here/src/idmapped-mounts/mount-idmapped --map-mount b:0:$id:1 \
+ --map-mount b:$id:0:1 \
+ "$SCRATCH_MNT" "$SCRATCH_MNT" || _fail "mount-idmapped failed"
+ else
+ _fail "usage: either \"u\" (uid), \"g\" (gid), or \"b\" (uid and gid) must be specified "
+ fi
}
_scratch_unmount()
esac
}
+_scratch_umount_idmapped()
+{
+ $UMOUNT_PROG $SCRATCH_MNT
+}
+
_scratch_remount()
{
local opts="$1"
return $mkfs_status
}
-_scratch_metadump()
-{
- local dumpfile=$1
- shift
- local options=
-
- [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \
- options="-l $SCRATCH_LOGDEV"
-
- xfs_metadump $options "$@" $SCRATCH_DEV $dumpfile
-}
-
_setup_large_ext4_fs()
{
local fs_size=$1
return $mkfs_status
}
+_ext4_metadump()
+{
+ local device="$1"
+ local dumpfile="$2"
+ local compressopt="$3"
+
+ test -n "$E2IMAGE_PROG" || _fail "e2image not installed"
+ $E2IMAGE_PROG -Q "$device" "$dumpfile"
+ [ "$compressopt" = "compress" ] && [ -n "$DUMP_COMPRESSOR" ] &&
+ $DUMP_COMPRESSOR -f "$dumpfile" &>> "$seqres.full"
+}
+
+# Capture the metadata of a filesystem in a dump file for offline analysis.
+# This is not supported by all filesystem types, so this function should only
+# be used after a test has already failed.
+_metadump_dev() {
+ local device="$1"
+ local dumpfile="$2"
+ local compressopt="$3"
+
+ test "$DUMP_CORRUPT_FS" = 1 || return 0
+
+ case "$FSTYP" in
+ ext*)
+ _ext4_metadump $device $dumpfile $compressopt
+ ;;
+ xfs)
+ _xfs_metadump $dumpfile $device none $compressopt
+ ;;
+ *)
+ echo "Don't know how to metadump $FSTYP"
+ return 1
+ ;;
+ esac
+}
+
_test_mkfs()
{
case $FSTYP in
_fail "Usage: _scratch_dev_pool_get ndevs"
fi
- local test_ndevs=$1
- local config_ndevs=`echo $SCRATCH_DEV_POOL| wc -w`
- local -a devs="( $SCRATCH_DEV_POOL )"
-
- typeset -p config_ndevs >/dev/null 2>&1
+ typeset -p SCRATCH_DEV_POOL >/dev/null 2>&1
if [ $? -ne 0 ]; then
_fail "Bug: cant find SCRATCH_DEV_POOL ndevs"
fi
+ local test_ndevs=$1
+ local config_ndevs=`echo $SCRATCH_DEV_POOL| wc -w`
+ local -a devs="( $SCRATCH_DEV_POOL )"
+
if [ $config_ndevs -lt $test_ndevs ]; then
_notrun "Need at least test requested number of ndevs $test_ndevs"
fi
fi
}
+_check_minimal_fs_size()
+{
+ local fssize=$1
+
+ if [ -n "$MIN_FSSIZE" ]; then
+ [ $MIN_FSSIZE -gt "$fssize" ] &&
+ _notrun "specified filesystem size is too small"
+ fi
+}
+
# Create fs of certain size on scratch device
# _scratch_mkfs_sized <size in bytes> [optional blocksize]
_scratch_mkfs_sized()
{
- local fssize=$1
- local blocksize=$2
- local def_blksz
+ local fssize=$1
+ local blocksize=$2
+ local def_blksz
- case $FSTYP in
- xfs)
- def_blksz=`echo $MKFS_OPTIONS|sed -rn 's/.*-b ?size= ?+([0-9]+).*/\1/p'`
- ;;
- ext2|ext3|ext4|ext4dev|udf|btrfs|reiser4|ocfs2|reiserfs)
- def_blksz=`echo $MKFS_OPTIONS| sed -rn 's/.*-b ?+([0-9]+).*/\1/p'`
- ;;
- jfs)
- def_blksz=4096
- ;;
- esac
-
- [ -n "$def_blksz" ] && blocksize=$def_blksz
- [ -z "$blocksize" ] && blocksize=4096
+ case $FSTYP in
+ xfs)
+ def_blksz=`echo $MKFS_OPTIONS | sed -rn 's/.*-b ?size= ?+([0-9]+).*/\1/p'`
+ ;;
+ btrfs)
+ def_blksz=`echo $MKFS_OPTIONS | sed -rn 's/.*-s ?+([0-9]+).*/\1/p'`
+ ;;
+ ext2|ext3|ext4|ext4dev|udf|reiser4|ocfs2|reiserfs)
+ def_blksz=`echo $MKFS_OPTIONS | sed -rn 's/.*-b ?+([0-9]+).*/\1/p'`
+ ;;
+ jfs)
+ def_blksz=4096
+ ;;
+ esac
+ [ -n "$def_blksz" ] && blocksize=$def_blksz
+ [ -z "$blocksize" ] && blocksize=4096
- local re='^[0-9]+$'
- if ! [[ $fssize =~ $re ]] ; then
- _notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
- fi
- if ! [[ $blocksize =~ $re ]] ; then
- _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
- fi
+ local re='^[0-9]+$'
+ if ! [[ $fssize =~ $re ]] ; then
+ _notrun "error: _scratch_mkfs_sized: fs size \"$fssize\" not an integer."
+ fi
+ if ! [[ $blocksize =~ $re ]] ; then
+ _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
+ fi
- local blocks=`expr $fssize / $blocksize`
+ local blocks=`expr $fssize / $blocksize`
- if [ "$HOSTOS" == "Linux" -a -b "$SCRATCH_DEV" ]; then
- local devsize=`blockdev --getsize64 $SCRATCH_DEV`
- [ "$fssize" -gt "$devsize" ] && _notrun "Scratch device too small"
- fi
+ _check_minimal_fs_size $fssize
- case $FSTYP in
- xfs)
- # don't override MKFS_OPTIONS that set a block size.
- echo $MKFS_OPTIONS |egrep -q "b?size="
- if [ $? -eq 0 ]; then
- _scratch_mkfs_xfs -d size=$fssize
- else
- _scratch_mkfs_xfs -d size=$fssize -b size=$blocksize
+ if [ -b "$SCRATCH_DEV" ]; then
+ local devsize=`blockdev --getsize64 $SCRATCH_DEV`
+ [ "$fssize" -gt "$devsize" ] && _notrun "Scratch device too small"
fi
- ;;
- ext2|ext3|ext4|ext4dev)
- ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
- ;;
- gfs2)
- # mkfs.gfs2 doesn't automatically shrink journal files on small
- # filesystems, so the journal files may end up being bigger than the
- # filesystem, which will cause mkfs.gfs2 to fail. Until that's fixed,
- # shrink the journal size to at most one eigth of the filesystem and at
- # least 8 MiB, the minimum size allowed.
- local min_journal_size=8
- local default_journal_size=128
- if (( fssize/8 / (1024*1024) < default_journal_size )); then
- local journal_size=$(( fssize/8 / (1024*1024) ))
- (( journal_size >= min_journal_size )) || journal_size=$min_journal_size
- MKFS_OPTIONS="-J $journal_size $MKFS_OPTIONS"
- fi
- ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV $blocks
- ;;
- ocfs2)
- yes | ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
- ;;
- udf)
- $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
- ;;
- btrfs)
- local mixed_opt=
- # minimum size that's needed without the mixed option.
- # Ref: btrfs-prog: btrfs_min_dev_size()
- # Non mixed mode is also the default option.
- (( fssize < $((256 * 1024 *1024)) )) && mixed_opt='--mixed'
- $MKFS_BTRFS_PROG $MKFS_OPTIONS $mixed_opt -b $fssize $SCRATCH_DEV
- ;;
- jfs)
- ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS $SCRATCH_DEV $blocks
- ;;
- reiserfs)
- ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
- ;;
- reiser4)
- # mkfs.resier4 requires size in KB as input for creating filesystem
- $MKFS_REISER4_PROG $MKFS_OPTIONS -y -b $blocksize $SCRATCH_DEV \
- `expr $fssize / 1024`
- ;;
- f2fs)
- # mkfs.f2fs requires # of sectors as an input for the size
- local sector_size=`blockdev --getss $SCRATCH_DEV`
- $MKFS_F2FS_PROG $MKFS_OPTIONS $SCRATCH_DEV `expr $fssize / $sector_size`
- ;;
- tmpfs)
- local free_mem=`_free_memory_bytes`
- if [ "$free_mem" -lt "$fssize" ] ; then
- _notrun "Not enough memory ($free_mem) for tmpfs with $fssize bytes"
+
+ if [ "$FSTYP" = "xfs" ] && [ -b "$SCRATCH_RTDEV" ]; then
+ local rtdevsize=`blockdev --getsize64 $SCRATCH_RTDEV`
+ [ "$fssize" -gt "$rtdevsize" ] && _notrun "Scratch rt device too small"
+ rt_ops="-r size=$fssize"
fi
- export MOUNT_OPTIONS="-o size=$fssize $TMPFS_MOUNT_OPTIONS"
- ;;
- *)
- _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
- ;;
- esac
+
+ case $FSTYP in
+ xfs)
+ # don't override MKFS_OPTIONS that set a block size.
+ echo $MKFS_OPTIONS |egrep -q "b?size="
+ if [ $? -eq 0 ]; then
+ _scratch_mkfs_xfs -d size=$fssize $rt_ops
+ else
+ _scratch_mkfs_xfs -d size=$fssize $rt_ops -b size=$blocksize
+ fi
+ ;;
+ ext2|ext3|ext4|ext4dev)
+ ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+ ;;
+ gfs2)
+ # mkfs.gfs2 doesn't automatically shrink journal files on small
+ # filesystems, so the journal files may end up being bigger than the
+ # filesystem, which will cause mkfs.gfs2 to fail. Until that's fixed,
+ # shrink the journal size to at most one eigth of the filesystem and at
+ # least 8 MiB, the minimum size allowed.
+ local min_journal_size=8
+ local default_journal_size=128
+ if (( fssize/8 / (1024*1024) < default_journal_size )); then
+ local journal_size=$(( fssize/8 / (1024*1024) ))
+ (( journal_size >= min_journal_size )) || journal_size=$min_journal_size
+ MKFS_OPTIONS="-J $journal_size $MKFS_OPTIONS"
+ fi
+ ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV $blocks
+ ;;
+ ocfs2)
+ yes | ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+ ;;
+ udf)
+ $MKFS_UDF_PROG $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+ ;;
+ btrfs)
+ local mixed_opt=
+ # minimum size that's needed without the mixed option.
+ # Ref: btrfs-prog: btrfs_min_dev_size()
+ # Non mixed mode is also the default option.
+ (( fssize < $((256 * 1024 *1024)) )) && mixed_opt='--mixed'
+ $MKFS_BTRFS_PROG $MKFS_OPTIONS $mixed_opt -b $fssize $SCRATCH_DEV
+ ;;
+ jfs)
+ ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS $SCRATCH_DEV $blocks
+ ;;
+ reiserfs)
+ ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV $blocks
+ ;;
+ reiser4)
+ # mkfs.resier4 requires size in KB as input for creating filesystem
+ $MKFS_REISER4_PROG $MKFS_OPTIONS -y -b $blocksize $SCRATCH_DEV \
+ `expr $fssize / 1024`
+ ;;
+ f2fs)
+ # mkfs.f2fs requires # of sectors as an input for the size
+ local sector_size=`blockdev --getss $SCRATCH_DEV`
+ $MKFS_F2FS_PROG $MKFS_OPTIONS $SCRATCH_DEV `expr $fssize / $sector_size`
+ ;;
+ tmpfs)
+ local free_mem=`_free_memory_bytes`
+ if [ "$free_mem" -lt "$fssize" ] ; then
+ _notrun "Not enough memory ($free_mem) for tmpfs with $fssize bytes"
+ fi
+ export MOUNT_OPTIONS="-o size=$fssize $TMPFS_MOUNT_OPTIONS"
+ ;;
+ bcachefs)
+ $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS --fs_size=$fssize --block_size=$blocksize $SCRATCH_DEV
+ ;;
+ *)
+ _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
+ ;;
+ esac
}
# Emulate an N-data-disk stripe w/ various stripe units
case $FSTYP in
xfs)
if echo "$MKFS_OPTIONS" | egrep -q "b?size="; then
- MKFS_OPTIONS=$(echo "$MKFS_OPTIONS" | sed -r "s/(b?size=)[0-9]+/\1$blocksize/")
+ MKFS_OPTIONS=$(echo "$MKFS_OPTIONS" | sed -r "s/(b?size=)[0-9]+k?/\1$blocksize/")
else
MKFS_OPTIONS+=" -b size=$blocksize"
fi
# _scratch_mkfs_blocksized blocksize
_scratch_mkfs_blocksized()
{
- local blocksize=$1
+ local blocksize=$1
- local re='^[0-9]+$'
- if ! [[ $blocksize =~ $re ]] ; then
- _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
- fi
+ local re='^[0-9]+$'
+ if ! [[ $blocksize =~ $re ]] ; then
+ _notrun "error: _scratch_mkfs_sized: block size \"$blocksize\" not an integer."
+ fi
- case $FSTYP in
- xfs)
- _scratch_mkfs_xfs $MKFS_OPTIONS -b size=$blocksize
- ;;
- ext2|ext3|ext4)
- ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV
- ;;
- gfs2)
- ${MKFS_PROG}.$FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV
- ;;
- ocfs2)
- yes | ${MKFS_PROG}.$FSTYP -F $MKFS_OPTIONS -b $blocksize -C $blocksize $SCRATCH_DEV
- ;;
- *)
- _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
- ;;
- esac
+ case $FSTYP in
+ btrfs)
+ test -f /sys/fs/btrfs/features/supported_sectorsizes || \
+ _notrun "Subpage sectorsize support is not found in $FSTYP"
+
+ grep -wq $blocksize /sys/fs/btrfs/features/supported_sectorsizes || \
+ _notrun "$FSTYP does not support sectorsize=$blocksize yet"
+
+ _scratch_mkfs --sectorsize=$blocksize
+ ;;
+ xfs)
+ _scratch_mkfs_xfs $MKFS_OPTIONS -b size=$blocksize
+ ;;
+ ext2|ext3|ext4)
+ ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize $SCRATCH_DEV
+ ;;
+ gfs2)
+ ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS -O -b $blocksize $SCRATCH_DEV
+ ;;
+ ocfs2)
+ yes | ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize \
+ -C $blocksize $SCRATCH_DEV
+ ;;
+ bcachefs)
+ ${MKFS_PROG} -t $FSTYP $MKFS_OPTIONS --block_size=$blocksize \
+ $SCRATCH_DEV
+ ;;
+ *)
+ _notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
+ ;;
+ esac
}
_scratch_resvblks()
fi
return $res
;;
+ bcachefs)
+ # With bcachefs, if fsck detects any errors we consider it a bug and we
+ # want the test to fail:
+ _check_scratch_fs
+ ;;
*)
local dev=$SCRATCH_DEV
local fstyp=$FSTYP
_notrun "not suitable for this filesystem type: $FSTYP"
}
-
-# tests whether $FSTYP is one of the supported OSes for a test
-#
-_supported_os()
-{
- local h
-
- for h
- do
- if [ "$h" = "$HOSTOS" ]
- then
- return
- fi
- done
-
- _notrun "not suitable for this OS: $HOSTOS"
-}
-
# check if a FS on a device is mounted
# if so, verify that it is mounted on mount point
# if fstype is given as argument, verify that it is also
_notrun "this test requires a valid \$SCRATCH_MNT"
fi
;;
- nfs*|ceph)
+ nfs*)
echo $SCRATCH_DEV | grep -q ":/" > /dev/null 2>&1
if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
_notrun "this test requires a valid \$SCRATCH_DEV"
_notrun "this test requires a valid \$SCRATCH_MNT"
fi
;;
+ ceph)
+ echo $SCRATCH_DEV | grep -qE "=/|:/" > /dev/null 2>&1
+ if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
+ _notrun "this test requires a valid \$SCRATCH_DEV"
+ fi
+ if [ ! -d "$SCRATCH_MNT" ]; then
+ _notrun "this test requires a valid \$SCRATCH_MNT"
+ fi
+ ;;
pvfs2)
echo $SCRATCH_DEV | grep -q "://" > /dev/null 2>&1
if [ -z "$SCRATCH_DEV" -o "$?" != "0" ]; then
tmpfs)
if [ -z "$SCRATCH_DEV" -o ! -d "$SCRATCH_MNT" ];
then
- _notrun "this test requires a valid \$SCRATCH_MNT and unique $SCRATCH_DEV"
+ _notrun "this test requires a valid \$SCRATCH_MNT and unique \$SCRATCH_DEV"
fi
;;
ubifs)
rm -f ${RESULT_DIR}/require_scratch
}
+# we need the scratch device and it needs to not be an lvm device
+_require_scratch_nolvm()
+{
+ _require_scratch_nocheck
+
+ # This works if we don't have LVM, all we want is to skip if the scratch
+ # device is an lvm device.
+ $LVM_PROG lvdisplay $SCRATCH_DEV > /dev/null 2>&1
+ [ $? -eq 0 ] && _notrun "test requires a non-lvm scratch device"
+}
+
+_require_no_compress()
+{
+ case "$FSTYP" in
+ btrfs)
+ _require_btrfs_no_compress
+ ;;
+ *)
+ ;;
+ esac
+}
+
# we need the scratch device and it should be checked post test.
_require_scratch()
{
[ $devsize -lt $1 ] && _notrun "scratch dev too small"
}
+# require a scratch dev of a minimum size (in kb) and should not be checked
+# post test
+_require_scratch_size_nocheck()
+{
+ [ $# -eq 1 ] || _fail "_require_scratch_size: expected size param"
+
+ _require_scratch_nocheck
+ local devsize=`_get_device_size $SCRATCH_DEV`
+ [ $devsize -lt $1 ] && _notrun "scratch dev too small"
+}
+
+# Require scratch fs which supports >16T of filesystem size.
+# _require_scratch must be called before this function is called.
+_require_scratch_16T_support()
+{
+ case $FSTYP in
+ ext2|ext3|f2fs)
+ _notrun "$FSTYP doesn't support >16T filesystem"
+ ;;
+ ext4)
+ _scratch_mkfs >> $seqres.full 2>&1
+ _scratch_mount
+ local blocksize=$(_get_block_size $SCRATCH_MNT)
+ if [ $blocksize -lt 4096 ]; then
+ _notrun "This test requires >16T fs support"
+ fi
+ _scratch_unmount
+ ;;
+ *)
+ ;;
+ esac
+}
+
+# Require scratch fs supports delay allocation.
+_require_scratch_delalloc()
+{
+ _require_command "$FILEFRAG_PROG" filefrag
+
+ _scratch_mkfs > $seqres.full
+ _scratch_mount
+ $XFS_IO_PROG -f -c 'pwrite 0 64k' $SCRATCH_MNT/testy &> /dev/null
+ $FILEFRAG_PROG -v $SCRATCH_MNT/testy 2>&1 | grep -q delalloc || \
+ _notrun "test requires delayed allocation buffered writes"
+ _scratch_unmount
+}
# this test needs a test partition - check we're ok & mount it
#
_notrun "this test requires a valid \$TEST_DIR"
fi
;;
- nfs*|ceph)
+ nfs*)
echo $TEST_DEV | grep -q ":/" > /dev/null 2>&1
if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
_notrun "this test requires a valid \$TEST_DEV"
_notrun "this test requires a valid \$TEST_DIR"
fi
;;
+ ceph)
+ echo $TEST_DEV | grep -qE "=/|:/" > /dev/null 2>&1
+ if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
+ _notrun "this test requires a valid \$TEST_DEV"
+ fi
+ if [ ! -d "$TEST_DIR" ]; then
+ _notrun "this test requires a valid \$TEST_DIR"
+ fi
+ ;;
cifs)
echo $TEST_DEV | grep -q "//" > /dev/null 2>&1
if [ -z "$TEST_DEV" -o "$?" != "0" ]; then
#
_require_loop()
{
- if [ "$HOSTOS" != "Linux" ]
- then
- _notrun "This test requires linux for loopback device support"
- fi
-
modprobe loop >/dev/null 2>&1
if grep loop /proc/devices >/dev/null 2>&1
then
else
_notrun "This test requires loopback device support"
fi
-}
-
-# this test requires ext2 filesystem support
-#
-_require_ext2()
-{
- if [ "$HOSTOS" != "Linux" ]
- then
- _notrun "This test requires linux for ext2 filesystem support"
- fi
- modprobe ext2 >/dev/null 2>&1
- if grep ext2 /proc/filesystems >/dev/null 2>&1
- then
- :
- else
- _notrun "This test requires ext2 filesystem support"
- fi
+ # loop device does not handle zone information
+ _require_non_zoned_device ${TEST_DEV}
}
-# this test requires tmpfs filesystem support
+# this test requires kernel support for a secondary filesystem
#
-_require_tmpfs()
+_require_extra_fs()
{
- modprobe tmpfs >/dev/null 2>&1
- grep -q tmpfs /proc/filesystems ||
- _notrun "this test requires tmpfs support"
+ modprobe "$1" >/dev/null 2>&1
+ grep -q -w "$1" /proc/filesystems ||
+ _notrun "this test requires $1 support"
}
# this test requires that (large) loopback device files are not in use
fi
}
+# Decide if the scratch filesystem is likely to be mounted in fsdax mode.
+# It goes 3 ways based on mount options::
+# 1. "dax" or "dax=always" means always test using DAX
+# 2. "dax=never" means we'll never use DAX
+# 3. "dax=inode" or nothing means "use scratch dev capability" to
+# determine whether DAX is going to be used.
+#
+# Returns 0 if DAX will be used, 1 if DAX is not going to be used.
+__scratch_uses_fsdax()
+{
+ local ops=$(_normalize_mount_options "$MOUNT_OPTIONS")
+
+ echo $ops | egrep -qw "dax(=always| |$)" && return 0
+ echo $ops | grep -qw "dax=never" && return 1
+
+ local sysfs="/sys/block/$(_short_dev $SCRATCH_DEV)"
+ test -e "${sysfs}/dax" && return 0
+ test "$(cat "${sysfs}/queue/dax" 2>/dev/null)" = "1" && return 0
+ return 1
+}
+
# this test requires a specific device mapper target
_require_dm_target()
{
local target=$1
+ local fsdax
+ local bdevdax
# require SCRATCH_DEV to be a valid block device with sane BLKFLSBUF
# behaviour
_require_sane_bdev_flush $SCRATCH_DEV
_require_command "$DMSETUP_PROG" dmsetup
- echo $MOUNT_OPTIONS | grep -q dax
- if [ $? -eq 0 ]; then
+ if __scratch_uses_fsdax; then
case $target in
stripe|linear|log-writes)
;;
if [ $? -ne 0 ]; then
_notrun "This test requires dm $target support"
fi
+
+ # dm-error cannot handle the zone information
+ #
+ # dm-snapshot and dm-thin-pool cannot ensure sequential writes on
+ # the backing device
+ case $target in
+ error|snapshot|thin-pool)
+ _require_non_zoned_device ${SCRATCH_DEV}
+ ;;
+ esac
+}
+
+_zone_type()
+{
+ local target=$1
+ if [ -z $target ]; then
+ echo "Usage: _zone_type <device>"
+ exit 1
+ fi
+ local sdev=`_short_dev $target`
+
+ if [ -e /sys/block/${sdev}/queue/zoned ]; then
+ cat /sys/block/${sdev}/queue/zoned
+ else
+ echo none
+ fi
+}
+
+_require_zoned_device()
+{
+ local target=$1
+ if [ -z $target ]; then
+ echo "Usage: _require_zoned_device <device>"
+ exit 1
+ fi
+
+ local type=`_zone_type ${target}`
+ if [ "${type}" = "none" ]; then
+ _notrun "this test require zoned block device"
+ fi
+}
+
+_require_non_zoned_device()
+{
+ local target=$1
+ if [ -z $target ]; then
+ echo "Usage: _require_non_zoned_device <device>"
+ exit 1
+ fi
+
+ local type=`_zone_type ${target}`
+ if [ "${type}" != "none" ]; then
+ _notrun "this test require non-zoned block device"
+ fi
}
# this test requires the ext4 kernel support crc feature on scratch device
_require_odirect
}
+# this test requires that the kernel supports IO_URING
+_require_io_uring()
+{
+ $here/src/feature -R
+ case $? in
+ 0)
+ ;;
+ 1)
+ _notrun "kernel does not support IO_URING"
+ ;;
+ *)
+ _fail "unexpected error testing for IO_URING support"
+ ;;
+ esac
+}
+
+# test whether the mount_setattr syscall is available
+_require_mount_setattr()
+{
+ $here/src/feature -r
+ case $? in
+ 0)
+ ;;
+ 1)
+ _notrun "kernel does not support mount_setattr syscall"
+ ;;
+ *)
+ _fail "unexpected error testing for mount_setattr support"
+ ;;
+ esac
+}
+
+# test whether idmapped mounts are supported
+_require_idmapped_mounts()
+{
+ IDMAPPED_MOUNTS_TEST=$here/src/idmapped-mounts/idmapped-mounts
+ [ -x $IDMAPPED_MOUNTS_TEST ] || _notrun "idmapped-mounts utilities required"
+
+ _require_mount_setattr
+
+ $here/src/idmapped-mounts/idmapped-mounts --supported \
+ --device "$TEST_DEV" \
+ --mount "$TEST_DIR" \
+ --fstype "$FSTYP"
+
+ if [ $? -ne 0 ]; then
+ _notrun "idmapped-mounts not support by $FSTYP"
+ fi
+}
+
# this test requires that a test program exists under src/
# $1 - command (require)
#
echo "0 $u32max"
;;
xfs)
- echo "$s32min $s32max"
+ _xfs_timestamp_range "$device"
;;
btrfs)
echo "$s64min $s64max"
cat /etc/group
}
-# check for a user on the machine, fsgqa as default
+# check if a user exists in the system
+#
+_require_user_exists()
+{
+ local user=$1
+ _cat_passwd | grep -q "^$user:"
+ [ "$?" == "0" ] || _notrun "$user user not defined."
+}
+
+# check if a user exists and is able to execute commands.
+# Uses 'fsgqa' user as default.
#
_require_user()
{
- qa_user=fsgqa
- if [ -n "$1" ];then
- qa_user=$1
- fi
- _cat_passwd | grep -q $qa_user
- [ "$?" == "0" ] || _notrun "$qa_user user not defined."
- echo /bin/true | su $qa_user
- [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
+ qa_user=fsgqa
+ if [ -n "$1" ];then
+ qa_user=$1
+ fi
+ _require_user_exists $qa_user
+ echo /bin/true | su $qa_user
+ [ "$?" == "0" ] || _notrun "$qa_user cannot execute commands."
+}
+
+# check for a chown support
+#
+_require_chown()
+{
+ local rnd_uid=4242
+ local file="$TEST_DIR/chown_testfile"
+
+ rm -f $file
+ touch $file
+ chown ${rnd_uid}:${rnd_uid} $file >/dev/null 2>&1 \
+ || _notrun "chown is not supported ${FSTYP}"
+}
+
+
+# check for a chmod support
+# Since chmod sometimes fails silently actual functionality test is done
+#
+_require_chmod()
+{
+ local file="$TEST_DIR/chmod_testfile"
+
+ rm -f $file
+ touch $file
+
+ # get original file mode
+ local mode=`stat --format="0%a" $file`
+ # flip the user's read bit
+ let mode^=0400
+ chmod `printf '%o' "$mode"` $file
+ # check that the chmod actually flipped the bit
+ [ `stat --format="0%a" $file` == `printf '0%o' "$mode"` ] \
+ || _notrun "chmod is not supported ${FSTYP}"
}
# check for a group on the machine, fsgqa as default
local param="$*"
local param_checked=""
local opts=""
+ local attr_info=""
local testfile=$TEST_DIR/$$.xfs_io
local testio
case $command in
+ "lsattr")
+ # Test xfs_io lsattr support and filesystem FS_IOC_FSSETXATTR
+ # support.
+ testio=`$XFS_IO_PROG -F -f -c "lsattr $param" $testfile 2>&1`
+ param_checked="$param"
+ ;;
"chattr")
+ local testdir=$TEST_DIR/$$.attr_dir
+ mkdir $TEST_DIR/$$.attr_dir
if [ -z "$param" ]; then
param=s
fi
# Test xfs_io chattr support AND
# filesystem FS_IOC_FSSETXATTR support
- testio=`$XFS_IO_PROG -F -f -c "chattr +$param" $testfile 2>&1`
- $XFS_IO_PROG -F -f -r -c "chattr -$param" $testfile 2>&1
+ # 'tPnE' flags are only valid for a directory so check them on a directory.
+ if echo "$param" | egrep -q 't|P|n|E'; then
+ testio=`$XFS_IO_PROG -F -c "chattr +$param" $testdir 2>&1`
+ attr_info=`$XFS_IO_PROG -F -r -c "lsattr" $testdir | awk '{print $1}'`
+ $XFS_IO_PROG -F -r -c "chattr -$param" $testdir 2>&1
+ else
+ testio=`$XFS_IO_PROG -F -f -c "chattr +$param" $testfile 2>&1`
+ attr_info=`$XFS_IO_PROG -F -r -c "lsattr" $testfile | awk '{print $1}'`
+ $XFS_IO_PROG -F -r -c "chattr -$param" $testfile 2>&1
+ fi
param_checked="+$param"
+ rm -rf $testdir 2>&1 > /dev/null
;;
"chproj")
testio=`$XFS_IO_PROG -F -f -c "chproj 0" $testfile 2>&1`
echo $testio | grep -q "\(invalid option\|not supported\)" && \
_notrun "xfs_io $command doesn't support $param"
fi
+
+ # On XFS, ioctl(FSSETXATTR)(called by xfs_io -c "chattr") maskes off unsupported
+ # or invalid flags silently so need to check these flags by extra ioctl(FSGETXATTR)
+ # (called by xfs_io -c "lsattr").
+ # The following URL explains why we don't change the behavior of XFS.
+ # https://www.spinics.net/lists/linux-xfs/msg44725.html
+ if [ -n "$attr_info" -a "$FSTYP" = "xfs" ]; then
+ local num=${#param}
+ for i in $(seq 0 $((num-1))); do
+ echo $attr_info | grep -q "${param:$i:1}" || \
+ _notrun "xfs_io $command +${param:$i:1} support is missing (unknown flag in kernel)"
+ done
+ fi
}
# check that kernel and filesystem support direct I/O
rm -f $testfile 2>&1 > /dev/null
}
+# Format a swapfile and return its size in bytes
_format_swapfile() {
local fname="$1"
local sz="$2"
+ local swap_log=""
rm -f "$fname"
touch "$fname"
# Swap files must be nocow on Btrfs.
$CHATTR_PROG +C "$fname" > /dev/null 2>&1
_pwrite_byte 0x61 0 "$sz" "$fname" >> $seqres.full
- $MKSWAP_PROG "$fname" >> $seqres.full
+ # Ignore permission complaints on filesystems that don't support perms
+ swap_log=$($MKSWAP_PROG "$fname" 2>&1 | grep -v "insecure permission")
+ echo $swap_log >> $seqres.full
+
+ echo $swap_log | grep -oP '\w+(?= bytes)'
+}
+
+_swapon_file() {
+ local fname="$1"
+
+ # Ignore permission complaints on filesystems that don't support perms
+ $(swapon "$fname" 2> >(grep -v "insecure permissions" >&2))
}
# Check that the filesystem supports swapfiles
_scratch_mount
# Minimum size for mkswap is 10 pages
- _format_swapfile "$SCRATCH_MNT/swap" $(($(get_page_size) * 10))
+ _format_swapfile "$SCRATCH_MNT/swap" $(($(get_page_size) * 10)) > /dev/null
- if ! swapon "$SCRATCH_MNT/swap" >/dev/null 2>&1; then
- _scratch_unmount
- _notrun "swapfiles are not supported"
- fi
+ # ext* has supported all variants of swap files since their
+ # introduction, so swapon should not fail.
+ case "$FSTYP" in
+ ext2|ext3|ext4)
+ if ! swapon "$SCRATCH_MNT/swap" >/dev/null 2>&1; then
+ if _check_s_dax "$SCRATCH_MNT/swap" 1 >/dev/null; then
+ _scratch_unmount
+ _notrun "swapfiles are not supported"
+ else
+ _scratch_unmount
+ _fail "swapon failed for $FSTYP"
+ fi
+ fi
+ ;;
+ *)
+ if ! swapon "$SCRATCH_MNT/swap" >/dev/null 2>&1; then
+ _scratch_unmount
+ _notrun "swapfiles are not supported"
+ fi
+ ;;
+ esac
swapoff "$SCRATCH_MNT/swap" >/dev/null 2>&1
_scratch_unmount
return 0
;;
nfs*)
- # NFSv2 and NFSv3 only support default behavior of SEEK_HOLE,
- # while NFSv4 supports non-default behavior
- local nfsvers=`_df_device $TEST_DEV | $AWK_PROG '{ print $2 }'`
- [ "$nfsvers" = "nfs4" ]
+ # NFSv2, NFSv3, and NFSv4.0/4.1 only support default behavior of SEEK_HOLE,
+ # while NFSv4.2 supports non-default behavior
+ local nfsvers=`_mount() | grep $TEST_DEV | sed -n 's/^.*vers=\([0-9.]*\).*$/\1/p'`
+ [ "$nfsvers" = "4.2" ]
return $?
;;
overlay)
fi
rm -f $tmp.fsck
+ if [ $ok -eq 0 ] && [ -n "$DUMP_CORRUPT_FS" ]; then
+ case "$FSTYP" in
+ ext*)
+ local flatdev="$(basename "$device")"
+ _ext4_metadump "$seqres.$flatdev.check.qcow2" "$device" compress
+ ;;
+ esac
+ fi
+
if [ $ok -eq 0 ]
then
echo "*** mount output ***" >>$seqres.full
_scratch_unmount
}
+_check_s_dax()
+{
+ local target=$1
+ local exp_s_dax=$2
+ local ret=0
+
+ local attributes=$($XFS_IO_PROG -c 'statx -r' $target | awk '/stat.attributes / { print $3 }')
+
+ # The original attribute bit value, STATX_ATTR_DAX (0x2000), conflicted
+ # with STATX_ATTR_MOUNT_ROOT. Therefore, STATX_ATTR_DAX was changed to
+ # 0x00200000.
+ #
+ # Because DAX tests do not run on root mounts, STATX_ATTR_MOUNT_ROOT
+ # should always be 0. Check for the old flag and fail the test if that
+ # occurs.
+
+ if [ $(( attributes & 0x2000 )) -ne 0 ]; then
+ echo "$target has an unexpected STATX_ATTR_MOUNT_ROOT flag set"
+ echo "which used to be STATX_ATTR_DAX"
+ echo " This test should not be running on the root inode..."
+ echo " Does the kernel have the following patch?"
+ echo " 72d1249e2ffd uapi: fix statx attribute value overlap for DAX & MOUNT_ROOT"
+ fi
+
+ if [ $exp_s_dax -eq 0 ]; then
+ if (( attributes & 0x00200000 )); then
+ echo "$target has unexpected S_DAX flag"
+ ret=1
+ fi
+ else
+ if ! (( attributes & 0x00200000 )); then
+ echo "$target doesn't have expected S_DAX flag"
+ ret=2
+ fi
+ fi
+ return $ret
+}
+
+_check_xflag()
+{
+ local target=$1
+ local exp_xflag=$2
+
+ if [ $exp_xflag -eq 0 ]; then
+ _test_inode_flag dax $target && echo "$target has unexpected FS_XFLAG_DAX flag"
+ else
+ _test_inode_flag dax $target || echo "$target doesn't have expected FS_XFLAG_DAX flag"
+ fi
+}
+
# Check if dax mount options are supported
#
# $1 can be either 'dax=always' or 'dax'
fi
case "$FSTYP" in
- ext2|vfat|msdos|udf|exfat)
+ ext2|vfat|msdos|udf|exfat|tmpfs)
echo "$FSTYP does not support metadata journaling"
return 1
;;
return 1
}
# ext4 might not load a journal
- if _normalize_mount_options | grep -qw "noload"; then
+ if _normalize_mount_options "$MOUNT_OPTIONS" | grep -qw "noload"; then
echo "mount option \"noload\" not allowed in this test"
return 1
fi
_notrun "cloner binary not present at $CLONER_PROG"
}
-# Normalize mount options from global $MOUNT_OPTIONS
-# Convert options like "-o opt1,opt2 -oopt3" to
-# "opt1 opt2 opt3"
+# Normalize mount options from the option string in $1
+# Convert options like "-o opt1,opt2 -oopt3" to "opt1 opt2 opt3"
_normalize_mount_options()
{
- echo $MOUNT_OPTIONS | sed -n 's/-o\s*\(\S*\)/\1/gp'| sed 's/,/ /g'
+ echo "$1" | sed -n 's/-o\s*\(\S*\)/\1/gp'| sed 's/,/ /g'
}
-# skip test if MOUNT_OPTIONS contains the given strings
-_exclude_scratch_mount_option()
+# skip test if $1 contains the given strings in trailing arguments
+# Both dax and dax=always are excluded if dax or dax=always is passed
+_exclude_mount_option()
{
- local mnt_opts=$(_normalize_mount_options)
+ local mnt_opts=$(_normalize_mount_options "$1")
+ shift
while [ $# -gt 0 ]; do
- if echo $mnt_opts | grep -qw "$1"; then
+ local pattern=$1
+ echo "$pattern" | egrep -q "dax(=always|$)" && \
+ pattern="dax(=always| |$)"
+ if echo $mnt_opts | egrep -q "$pattern"; then
_notrun "mount option \"$1\" not allowed in this test"
fi
shift
done
}
+_exclude_scratch_mount_option()
+{
+ _exclude_mount_option "$MOUNT_OPTIONS" $@
+}
+
+_exclude_test_mount_option()
+{
+ _exclude_mount_option "$TEST_FS_MOUNT_OPTS" $@
+}
+
_require_atime()
{
_exclude_scratch_mount_option "noatime"
case $FSTYP in
- nfs|cifs)
+ nfs|cifs|virtiofs)
_notrun "atime related mount options have no effect on $FSTYP"
;;
esac
{
local file=$1 dev
dev=`losetup -f --show $file` || _fail "Cannot assign $file to a loop device"
+
+ # Try to enable asynchronous directio mode on the loopback device so
+ # that writeback started by a filesystem mounted on the loop device
+ # won't be throttled by buffered writes to the lower filesystem. This
+ # is a performance optimization for tests that want to write a lot of
+ # data, so it isn't required to work.
+ test -b "$dev" && losetup --direct-io=on $dev 2> /dev/null
+
echo $dev
}
_require_test_program "locktest"
touch $TEST_DIR/setlease_testfile
$here/src/locktest -t $TEST_DIR/setlease_testfile >/dev/null 2>&1
- [ $? -eq 22 ] && _notrun "Require fcntl setlease support"
+ local ret=$?
+ [ $ret -eq 22 ] && _notrun "Require fcntl setlease support"
+ [ "$FSTYP" == "nfs" -a $ret -eq 11 ] && \
+ _notrun "NFS requires delegation before setlease"
}
_require_ofd_locks()
# return device size in kb
_get_device_size()
{
- grep -w `_short_dev $1` /proc/partitions | awk '{print $3}'
+ echo $(($(blockdev --getsz $1) >> 1))
}
# Make sure we actually have dmesg checking set up.
echo "Missing mount point argument for _get_file_block_size"
exit 1
fi
- if [ "$FSTYP" = "ocfs2" ]; then
+
+ case "$FSTYP" in
+ "ocfs2")
stat -c '%o' $1
- else
+ ;;
+ "xfs")
+ _xfs_get_file_block_size $1
+ ;;
+ *)
_get_block_size $1
- fi
+ ;;
+ esac
}
# Get the minimum block size of an fs.
stat -f -c %S $1
}
+# Require that the fundamental allocation unit of a file is the same as the
+# filesystem block size. The sole parameter must be the root dir of a
+# filesystem.
+_require_file_block_size_equals_fs_block_size()
+{
+ local file_alloc_unit="$(_get_file_block_size $1)"
+ local fs_block_size="$(_get_block_size $1)"
+ test "$file_alloc_unit" != "$fs_block_size" && \
+ _notrun "File allocation unit is larger than a filesystem block"
+}
+
get_page_size()
{
echo $(getconf PAGE_SIZE)
_require_fs_sysfs()
{
local attr=$1
- local dname=$(_short_dev $TEST_DEV)
+ local dname
+
+ case "$FSTYP" in
+ btrfs)
+ dname=$(findmnt -n -o UUID $TEST_DEV) ;;
+ *)
+ dname=$(_short_dev $TEST_DEV) ;;
+ esac
if [ -z "$attr" -o -z "$dname" ];then
_fail "Usage: _require_fs_sysfs <sysfs_attr_path>"
_fail "Usage: _set_fs_sysfs_attr <mounted_device> <attr> <content>"
fi
- local dname=$(_short_dev $dev)
+ local dname
+ case "$FSTYP" in
+ btrfs)
+ dname=$(findmnt -n -o UUID ${dev}) ;;
+ *)
+ dname=$(_short_dev $dev) ;;
+ esac
+
echo "$content" > /sys/fs/${FSTYP}/${dname}/${attr}
}
_fail "Usage: _get_fs_sysfs_attr <mounted_device> <attr>"
fi
- local dname=$(_short_dev $dev)
+ local dname
+ case "$FSTYP" in
+ btrfs)
+ dname=$(findmnt -n -o UUID ${dev}) ;;
+ *)
+ dname=$(_short_dev $dev) ;;
+ esac
+
cat /sys/fs/${FSTYP}/${dname}/${attr}
}
_supports_xfs_scrub "${mount}" "${dev}" || return 1
- # We only care if xfs_scrub has unicode string support...
- if ! type ldd > /dev/null 2>&1 || \
- ! ldd "${XFS_SCRUB_PROG}" | grep -q libicui18n; then
- return 1
+ # If the xfs_scrub binary contains the string "Unicode name.*%s", then
+ # we know that it has the ability to complain about improper Unicode
+ # names.
+ if strings "${XFS_SCRUB_PROG}" | grep -q 'Unicode name.*%s'; then
+ return 0
fi
- return 0
+ # If the xfs_scrub binary is linked against the libicui18n Unicode
+ # library, then we surmise that it contains the Unicode name checker.
+ if type ldd > /dev/null 2>&1 && \
+ ldd "${XFS_SCRUB_PROG}" 2> /dev/null | grep -q libicui18n; then
+ return 0
+ fi
+
+ # We could not establish that xfs_scrub supports unicode names.
+ return 1
}
# exfat timestamps start at 1980 and cannot be prior to epoch
rm -f $TEST_DIR/$seq.null
}
+_getcap()
+{
+ $GETCAP_PROG "$@" | _filter_getcap
+ return ${PIPESTATUS[0]}
+}
+
+_require_od_endian_flag()
+{
+ od --endian=little < /dev/null > /dev/null 2>&1 || \
+ _notrun "od does not support endian flag"
+}
+
+# Skip this test unless the filesystem treats names (directory entries,
+# fs labels, and extended attribute names) as raw byte sequences.
+_require_names_are_bytes() {
+ case "$FSTYP" in
+ ext2|ext3|ext4|f2fs|xfs|btrfs)
+ # do nothing
+ ;;
+ *)
+ _notrun "$FSTYP does not allow unrestricted byte streams for names"
+ ;;
+ esac
+}
+
+_has_kernel_config()
+{
+ local option=$1
+ local uname=$(uname -r)
+ local config_list="$KCONFIG_PATH
+ /proc/config.gz
+ /lib/modules/$uname/build/.config
+ /boot/config-$uname
+ /lib/kernel/config-$uname"
+
+ for config in $config_list; do
+ [ ! -f $config ] && continue
+ [ $config = "/proc/config.gz" ] && break
+ grep -qE "^${option}=[my]" $config
+ return
+ done
+
+ [ ! -f $config ] && _notrun "Could not locate kernel config file"
+
+ # We can only get here with /proc/config.gz
+ _require_command "$GZIP_PROG" gzip
+ $GZIP_PROG -cd $config | grep -qE "^${option}=[my]"
+}
+
+_require_kernel_config()
+{
+ _has_kernel_config $1 || _notrun "Installed kernel not built with $1"
+}
+
init_rc
################################################################################