# # ext4 specific common functions # __generate_ext4_report_vars() { __generate_blockdev_report_vars TEST_LOGDEV __generate_blockdev_report_vars SCRATCH_LOGDEV } _setup_large_ext4_fs() { local fs_size=$1 local tmp_dir=/tmp/ [ "$LARGE_SCRATCH_DEV" != yes ] && return 0 [ -z "$SCRATCH_DEV_EMPTY_SPACE" ] && SCRATCH_DEV_EMPTY_SPACE=0 [ $SCRATCH_DEV_EMPTY_SPACE -ge $fs_size ] && return 0 # Default free space in the FS is 50GB, but you can specify more via # SCRATCH_DEV_EMPTY_SPACE local space_to_consume=$(($fs_size - 50*1024*1024*1024 - $SCRATCH_DEV_EMPTY_SPACE)) # mount the filesystem and create 16TB - 4KB files until we consume # all the necessary space. _try_scratch_mount 2>&1 >$tmp_dir/mnt.err local status=$? if [ $status -ne 0 ]; then echo "mount failed" cat $tmp_dir/mnt.err >&2 rm -f $tmp_dir/mnt.err return $status fi rm -f $tmp_dir/mnt.err local file_size=$((16*1024*1024*1024*1024 - 4096)) local nfiles=0 while [ $space_to_consume -gt $file_size ]; do xfs_io -F -f \ -c "truncate $file_size" \ -c "falloc -k 0 $file_size" \ $SCRATCH_MNT/.use_space.$nfiles 2>&1 status=$? if [ $status -ne 0 ]; then break; fi space_to_consume=$(( $space_to_consume - $file_size )) nfiles=$(($nfiles + 1)) done # consume the remaining space. if [ $space_to_consume -gt 0 ]; then xfs_io -F -f \ -c "truncate $space_to_consume" \ -c "falloc -k 0 $space_to_consume" \ $SCRATCH_MNT/.use_space.$nfiles 2>&1 status=$? fi export NUM_SPACE_FILES=$nfiles _scratch_unmount if [ $status -ne 0 ]; then echo "large file prealloc failed" cat $tmp_dir/mnt.err >&2 return $status fi return 0 } _scratch_mkfs_ext4_opts() { mkfs_opts=$* _scratch_options mkfs echo "$MKFS_EXT4_PROG $SCRATCH_OPTIONS $mkfs_opts" } _scratch_mkfs_ext4() { local mkfs_cmd="`_scratch_mkfs_ext4_opts`" local mkfs_filter="grep -v -e ^Warning: -e \"^mke2fs \" | grep -v \"^$\"" local tmp=`mktemp -u` local mkfs_status if [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ]; then $MKFS_EXT4_PROG -F -O journal_dev $MKFS_OPTIONS $* $SCRATCH_LOGDEV 2>$tmp.mkfserr 1>$tmp.mkfsstd mkjournal_status=$? if [ $mkjournal_status -ne 0 ]; then cat $tmp.mkfsstd cat $tmp.mkfserr >&2 return $mkjournal_status fi fi _scratch_do_mkfs "$mkfs_cmd" "$mkfs_filter" $* 2>$tmp.mkfserr 1>$tmp.mkfsstd mkfs_status=$? if [ $mkfs_status -eq 0 -a "$LARGE_SCRATCH_DEV" = yes ]; then # manually parse the mkfs output to get the fs size in bytes local fs_size=`cat $tmp.mkfsstd | awk ' \ /^Block size/ { split($2, a, "="); bs = a[2] ; } \ / inodes, / { blks = $3 } \ /reserved for the super user/ { resv = $1 } \ END { fssize = bs * blks - resv; print fssize }'` _setup_large_ext4_fs $fs_size mkfs_status=$? fi # output mkfs stdout and stderr cat $tmp.mkfsstd cat $tmp.mkfserr >&2 rm -f $tmp.mkfserr $tmp.mkfsstd 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" } _ext4_mdrestore() { local metadump="$1" local device="$2" shift; shift local options="$@" # If we're configured for compressed dumps and there isn't already an # uncompressed dump, see if we can use DUMP_COMPRESSOR to decompress # something. if [ ! -e "$metadump" ] && [ -n "$DUMP_COMPRESSOR" ]; then for compr in "$metadump".*; do [ -e "$compr" ] && $DUMP_COMPRESSOR -d -f -k "$compr" && break done fi test -r "$metadump" || return 1 $E2IMAGE_PROG $options -r "${metadump}" "${SCRATCH_DEV}" } # this test requires the ext4 kernel support crc feature on scratch device # _require_scratch_ext4_crc() { _scratch_mkfs_ext4 >/dev/null 2>&1 dumpe2fs -h $SCRATCH_DEV 2> /dev/null | grep -q metadata_csum || _notrun "metadata_csum not supported by this filesystem" _try_scratch_mount >/dev/null 2>&1 \ || _notrun "Kernel doesn't support metadata_csum feature" _scratch_unmount } # Check whether the specified feature whether it is supported by # mkfs.ext4 and the kernel. _require_scratch_ext4_feature() { if [ -z "$1" ]; then echo "Usage: _require_scratch_ext4_feature feature" exit 1 fi $MKFS_EXT4_PROG -F $MKFS_OPTIONS -O "$1" \ $SCRATCH_DEV 512m >/dev/null 2>&1 \ || _notrun "mkfs.ext4 doesn't support $1 feature" _try_scratch_mount >/dev/null 2>&1 \ || _notrun "Kernel doesn't support the ext4 feature(s): $1" _scratch_unmount } # Disable extent zeroing for ext4 on the given device _ext4_disable_extent_zeroout() { local dev=${1:-$TEST_DEV} local sdev=`_short_dev $dev` [ -f /sys/fs/ext4/$sdev/extent_max_zeroout_kb ] && \ echo 0 >/sys/fs/ext4/$sdev/extent_max_zeroout_kb } _scratch_ext4_options() { local type=$1 local log_opt="" case $type in mkfs) SCRATCH_OPTIONS="$SCRATCH_OPTIONS -F" log_opt="-J device=$SCRATCH_LOGDEV" ;; mount) # As of kernel 5.19, the kernel mount option path parser only # accepts direct paths to block devices--the final path # component cannot be a symlink. log_opt="-o journal_path=$(realpath -q "$SCRATCH_LOGDEV")" ;; esac [ "$USE_EXTERNAL" = yes -a ! -z "$SCRATCH_LOGDEV" ] && \ SCRATCH_OPTIONS="$SCRATCH_OPTIONS ${log_opt}" } # Get the inode flags for a particular inode number _ext4_get_inum_iflags() { local dev="$1" local inumber="$2" debugfs -R "stat <${inumber}>" "${dev}" 2> /dev/null | \ sed -n 's/^.*Flags: \([0-9a-fx]*\).*$/\1/p' }