mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
generic: ENOSPC regression test in a multi-threaded scenario
Test allocation strategies of the file system and validate space anomalies as reported by the system versus the allocated by the program. The test is motivated by a bug in ext4 systems where-in ENOSPC is reported by the file system even though enough space for allocations is available[1]. [1]: https://patchwork.ozlabs.org/patch/1294003 Linux kernel patch series that fixes the above regression: 53f86b170dfa ("ext4: mballoc: add blocks to PA list under same spinlock after allocating blocks") cf5e2ca6c990 ("ext4: mballoc: refactor ext4_mb_discard_preallocations()") 07b5b8e1ac40 ("ext4: mballoc: introduce pcpu seqcnt for freeing PA to improve ENOSPC handling") 8ef123fe02ca ("ext4: mballoc: refactor ext4_mb_good_group()") 993778306e79 ("ext4: mballoc: use lock for checking free blocks while retrying") Suggested-by: Ritesh Harjani <riteshh@linux.ibm.com> Co-authored-by: Sourabh Jain <sourabhjain@linux.ibm.com> Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com> Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com> Reviewed-by: Eryu Guan <guaneryu@gmail.com> Signed-off-by: Eryu Guan <guaneryu@gmail.com>
This commit is contained in:
committed by
Eryu Guan
parent
445cbd798b
commit
8b4f7e207c
Executable
+207
@@ -0,0 +1,207 @@
|
||||
#! /bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (c) 2020 IBM Corporation. All Rights Reserved.
|
||||
#
|
||||
# FS QA Test 619
|
||||
#
|
||||
# ENOSPC regression test in a multi-threaded scenario. Test allocation
|
||||
# strategies of the file system and validate space anomalies as reported by
|
||||
# the system versus the allocated by the program.
|
||||
#
|
||||
# The test is motivated by a bug in ext4 systems where-in ENOSPC is
|
||||
# reported by the file system even though enough space for allocations is
|
||||
# available[1].
|
||||
# [1]: https://patchwork.ozlabs.org/patch/1294003
|
||||
#
|
||||
# Linux kernel patch series that fixes the above regression:
|
||||
# 53f86b170dfa ("ext4: mballoc: add blocks to PA list under same spinlock
|
||||
# after allocating blocks")
|
||||
# cf5e2ca6c990 ("ext4: mballoc: refactor ext4_mb_discard_preallocations()")
|
||||
# 07b5b8e1ac40 ("ext4: mballoc: introduce pcpu seqcnt for freeing PA to
|
||||
# improve ENOSPC handling")
|
||||
# 8ef123fe02ca ("ext4: mballoc: refactor ext4_mb_good_group()")
|
||||
# 993778306e79 ("ext4: mballoc: use lock for checking free blocks while
|
||||
# retrying")
|
||||
#
|
||||
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
|
||||
|
||||
FS_SIZE=$((240*1024*1024)) # 240MB
|
||||
DEBUG=1 # set to 0 to disable debug statements in shell and c-prog
|
||||
FACT=0.7
|
||||
|
||||
# Disk allocation methods
|
||||
FALLOCATE=1
|
||||
FTRUNCATE=2
|
||||
|
||||
# Helps to build TEST_VECTORS
|
||||
SMALL_FILE_SIZE=$((512 * 1024)) # in Bytes
|
||||
BIG_FILE_SIZE=$((1536 * 1024)) # in Bytes
|
||||
MIX_FILE_SIZE=$((2048 * 1024)) # (BIG + SMALL small file size)
|
||||
|
||||
_cleanup()
|
||||
{
|
||||
cd /
|
||||
rm -f $tmp.*
|
||||
}
|
||||
|
||||
# get standard environment, filters and checks
|
||||
. ./common/rc
|
||||
. ./common/filter
|
||||
|
||||
# remove previous $seqres.full before test
|
||||
rm -f $seqres.full
|
||||
|
||||
# Modify as appropriate.
|
||||
_supported_fs generic
|
||||
_require_scratch
|
||||
_require_test_program "t_enospc"
|
||||
_require_xfs_io_command "falloc"
|
||||
|
||||
debug()
|
||||
{
|
||||
if [ $DEBUG -eq 1 ]; then
|
||||
echo "$1" >> $seqres.full
|
||||
fi
|
||||
}
|
||||
|
||||
# Calculate the number of threads needed to fill the disk space
|
||||
# Arguments
|
||||
# $1: the size of a file
|
||||
# $2: ratio in which $1 file should be split into multiple files.
|
||||
# $3: percentage of the disk space should be used during the test
|
||||
# Calculate the number of threads needed to fill the disk space
|
||||
calc_thread_cnt()
|
||||
{
|
||||
local file_ratio_unit=$1
|
||||
local file_ratio=$2
|
||||
local disk_saturation=$3
|
||||
local tot_avail_size
|
||||
local avail_size
|
||||
local thread_cnt
|
||||
|
||||
IFS=',' read -ra fratio <<< $file_ratio
|
||||
file_ratio_cnt=${#fratio[@]}
|
||||
|
||||
tot_avail_size=$($DF_PROG --block-size=1 $SCRATCH_DEV | awk 'FNR == 2 { print $5 }')
|
||||
avail_size=$(echo $tot_avail_size*$disk_saturation | $BC_PROG)
|
||||
thread_cnt=$(echo "$file_ratio_cnt*($avail_size/$file_ratio_unit)" | $BC_PROG)
|
||||
|
||||
debug "Total available size: $tot_avail_size"
|
||||
debug "Available size: $avail_size"
|
||||
debug "Thread count: $thread_cnt"
|
||||
|
||||
echo ${thread_cnt}
|
||||
}
|
||||
|
||||
# Arguments
|
||||
# $1: a string containing test configuration separated by a colon.
|
||||
# $1 is treated as an array of arguments to the function.
|
||||
# Description of each array element is given below.
|
||||
#
|
||||
# @1: name of the test
|
||||
# @2: thread in t_enospec exerciser will allocate file of @2 size
|
||||
# @3: defines the proportion in which the file size defined in @2
|
||||
# should be divided into two files.
|
||||
# (valid @3: more than two values are not allowed)
|
||||
# values should be comma separated)
|
||||
# sum of all values must be 1)
|
||||
# @4: define the percentage of available memory should be used to
|
||||
# during the test.
|
||||
# @5: defines the disk allocation method (fallocate/ftruncate)
|
||||
# @6: number of the test should run
|
||||
run_testcase()
|
||||
{
|
||||
IFS=':' read -ra args <<< $1
|
||||
local test_name=${args[0]}
|
||||
local file_ratio_unit=${args[1]}
|
||||
local file_ratio=${args[2]}
|
||||
local disk_saturation=${args[3]}
|
||||
local disk_alloc_method=${args[4]}
|
||||
local test_iteration_cnt=${args[5]}
|
||||
local extra_args=""
|
||||
local thread_cnt
|
||||
|
||||
if [ "$disk_alloc_method" == "$FALLOCATE" ]; then
|
||||
extra_args="$extra_args -f"
|
||||
fi
|
||||
|
||||
# enable the debug statements in c program
|
||||
if [ "$DEBUG" -eq 1 ]; then
|
||||
extra_args="$extra_args -v"
|
||||
fi
|
||||
|
||||
debug "============ Test details start ============"
|
||||
debug "Test name: $test_name"
|
||||
debug "File ratio unit: $file_ratio_unit"
|
||||
debug "File ratio: $file_ratio"
|
||||
debug "Disk saturation $disk_saturation"
|
||||
debug "Disk alloc method $disk_alloc_method"
|
||||
debug "Test iteration count: $test_iteration_cnt"
|
||||
debug "Extra arg: $extra_args"
|
||||
|
||||
for i in $(eval echo "{1..$test_iteration_cnt}"); do
|
||||
# Setup the device
|
||||
_scratch_mkfs_sized $FS_SIZE >> $seqres.full 2>&1
|
||||
_scratch_mount
|
||||
|
||||
debug "===== Test: $test_name iteration: $i starts ====="
|
||||
thread_cnt=$(calc_thread_cnt $file_ratio_unit $file_ratio $disk_saturation)
|
||||
|
||||
# Start the test
|
||||
$here/src/t_enospc -t $thread_cnt -s $file_ratio_unit -r $file_ratio -p $SCRATCH_MNT $extra_args >> $seqres.full
|
||||
|
||||
status=$(echo $?)
|
||||
if [ $status -ne 0 ]; then
|
||||
use_per=$($DF_PROG -h | grep $SCRATCH_MNT | awk '{print substr($6, 1, length($6)-1)}' | $BC_PROG)
|
||||
alloc_per=$(echo "$FACT * 100" | $BC_PROG)
|
||||
# We are here since t_enospc failed with an error code.
|
||||
# If the used filesystem space is still < available space - that means
|
||||
# the test failed due to FS wrongly reported ENOSPC.
|
||||
if [ $(echo "$use_per < $alloc_per" | $BC_PROG) -ne 0 ]; then
|
||||
if [ $status -eq 134 ]; then
|
||||
# SIGABRT asserted exit code = 134
|
||||
echo "FAIL: Aborted assertion faliure"
|
||||
elif [ $status -eq 7 ]; then
|
||||
# SIGBUS asserted exit code = 7
|
||||
echo "FAIL: ENOSPC BUS faliure"
|
||||
fi
|
||||
echo "$test_name failed at iteration count: $i"
|
||||
echo "$($DF_PROG -h $SCRATCH_MNT)"
|
||||
echo "Allocated: $alloc_per% Used: $use_per%"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make space for other tests
|
||||
_scratch_unmount
|
||||
|
||||
debug "===== Test: $test_name iteration: $i ends ====="
|
||||
done
|
||||
debug "============ Test details end ============="
|
||||
}
|
||||
|
||||
declare -a TEST_VECTORS=(
|
||||
# test-name:file-ratio-unit:file-ratio:disk-saturation:disk-alloc-method:test-iteration-cnt
|
||||
"Small-file-fallocate-test:$SMALL_FILE_SIZE:1:$FACT:$FALLOCATE:3"
|
||||
"Big-file-fallocate-test:$BIG_FILE_SIZE:1:$FACT:$FALLOCATE:3"
|
||||
"Mix-file-fallocate-test:$MIX_FILE_SIZE:0.75,0.25:$FACT:$FALLOCATE:3"
|
||||
"Small-file-ftruncate-test:$SMALL_FILE_SIZE:1:$FACT:$FTRUNCATE:3"
|
||||
"Big-file-ftruncate-test:$BIG_FILE_SIZE:1:$FACT:$FTRUNCATE:3"
|
||||
"Mix-file-ftruncate-test:$MIX_FILE_SIZE:0.75,0.25:$FACT:$FTRUNCATE:3"
|
||||
)
|
||||
|
||||
# real QA test starts here
|
||||
for i in "${TEST_VECTORS[@]}"; do
|
||||
run_testcase $i
|
||||
done
|
||||
|
||||
echo "Silence is golden"
|
||||
status=0
|
||||
exit
|
||||
@@ -0,0 +1,2 @@
|
||||
QA output created by 619
|
||||
Silence is golden
|
||||
@@ -621,3 +621,4 @@
|
||||
616 auto rw io_uring stress
|
||||
617 auto rw io_uring stress
|
||||
618 auto quick attr
|
||||
619 auto rw enospc
|
||||
|
||||
Reference in New Issue
Block a user