* [PATCHSET 0/3] fstests: direct specification of looping test duration
@ 2023-04-11 18:13 Darrick J. Wong
2023-04-11 18:13 ` [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test Darrick J. Wong
` (3 more replies)
0 siblings, 4 replies; 16+ messages in thread
From: Darrick J. Wong @ 2023-04-11 18:13 UTC (permalink / raw)
To: djwong, zlang; +Cc: linux-xfs, fstests, guan
Hi all,
One of the things that I do as a maintainer is to designate a handful of
VMs to run fstests for unusually long periods of time. This practice I
call long term soak testing. There are actually three separate fleets
for this -- one runs alongside the nightly builds, one runs alongside
weekly rebases, and the last one runs stable releases.
My interactions with all three fleets is pretty much the same -- load
current builds of software, and try to run the exerciser tests for a
duration of time -- 12 hours, 6.5 days, 30 days, etc. TIME_FACTOR does
not work well for this usage model, because it is difficult to guess
the correct time factor given that the VMs are hetergeneous and the IO
completion rate is not perfectly predictable.
Worse yet, if you want to run (say) all the recoveryloop tests on one VM
(because recoveryloop is prone to crashing), it's impossible to set a
TIME_FACTOR so that each loop test gets equal runtime. That can be
hacked around with config sections, but that doesn't solve the first
problem.
This series introduces a new configuration variable, SOAK_DURATION, that
allows test runners to control directly various long soak and looping
recovery tests. This is intended to be an alternative to TIME_FACTOR,
since that variable usually adjusts operation counts, which are
proportional to runtime but otherwise not a direct measure of time.
With this override in place, I can configure the long soak fleet to run
for exactly as long as I want them to, and they actually hit the time
budget targets. The recoveryloop fleet now divides looping-test time
equally among the four that are in that group so that they all get ~3
hours of coverage every night.
There are more tests that could use this than I actually modified here,
but I've done enough to show this off as a proof of concept.
If you're going to start using this mess, you probably ought to just
pull from my git trees, which are linked below.
This is an extraordinary way to destroy everything. Enjoy!
Comments and questions are, as always, welcome.
--D
fstests git tree:
https://git.kernel.org/cgit/linux/kernel/git/djwong/xfstests-dev.git/log/?h=soak-duration
---
check | 14 +++++++++
common/config | 7 ++++
common/fuzzy | 7 ++++
common/rc | 34 +++++++++++++++++++++
common/report | 1 +
ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++--
ltp/fsx.c | 50 +++++++++++++++++++++++++++++++
src/soak_duration.awk | 23 ++++++++++++++
tests/generic/019 | 1 +
tests/generic/388 | 2 +
tests/generic/475 | 2 +
tests/generic/476 | 7 +++-
tests/generic/482 | 5 +++
tests/generic/521 | 1 +
tests/generic/522 | 1 +
tests/generic/642 | 1 +
tests/generic/648 | 8 +++--
17 files changed, 229 insertions(+), 13 deletions(-)
create mode 100644 src/soak_duration.awk
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test 2023-04-11 18:13 [PATCHSET 0/3] fstests: direct specification of looping test duration Darrick J. Wong @ 2023-04-11 18:13 ` Darrick J. Wong 2023-04-22 8:24 ` Zorro Lang 2023-04-11 18:13 ` [PATCH 2/3] misc: add duration for long soak tests Darrick J. Wong ` (2 subsequent siblings) 3 siblings, 1 reply; 16+ messages in thread From: Darrick J. Wong @ 2023-04-11 18:13 UTC (permalink / raw) To: djwong, zlang; +Cc: linux-xfs, fstests, guan From: Darrick J. Wong <djwong@kernel.org> This test is a long(ish) running stress test, so add it to those groups. Signed-off-by: Darrick J. Wong <djwong@kernel.org> --- tests/generic/476 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/generic/476 b/tests/generic/476 index 212373d17c..edb0be7b50 100755 --- a/tests/generic/476 +++ b/tests/generic/476 @@ -8,7 +8,7 @@ # bugs in the write path. # . ./common/preamble -_begin_fstest auto rw +_begin_fstest auto rw soak long_rw stress # Override the default cleanup function. _cleanup() ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test 2023-04-11 18:13 ` [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test Darrick J. Wong @ 2023-04-22 8:24 ` Zorro Lang 2023-04-24 18:17 ` Darrick J. Wong 0 siblings, 1 reply; 16+ messages in thread From: Zorro Lang @ 2023-04-22 8:24 UTC (permalink / raw) To: Darrick J. Wong; +Cc: linux-xfs, fstests, guan On Tue, Apr 11, 2023 at 11:13:52AM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@kernel.org> > > This test is a long(ish) running stress test, so add it to those groups. > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > --- > tests/generic/476 | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > > diff --git a/tests/generic/476 b/tests/generic/476 > index 212373d17c..edb0be7b50 100755 > --- a/tests/generic/476 > +++ b/tests/generic/476 > @@ -8,7 +8,7 @@ > # bugs in the write path. > # > . ./common/preamble > -_begin_fstest auto rw > +_begin_fstest auto rw soak long_rw stress Sorry for late reviewing. I thought a bit more about this change. I think the "soak", "long_rw" and "stress" tags are a bit overlap. If the "stress" group means "fsstress", then I think the fsstress test can be in soak group too, and currently the test cases in "soak" group are same with the "long_rw" group [1]. So I think we can give the "soak" tag to more test cases with random I/Os (fsstress or fsx or others). And rename "long_rw" to "long_soak" for those soak group cases which need long soaking time. Then we have two group tags for random loading/stress test cases, the testers can (decide to) run these random load test cases seperately with more time or loop count. Anyway, above things can be done in another patchset, I just speak out to get more talking:) For this patch: Reviewed-by: Zorro Lang <zlang@redhat.com> Thanks, Zorro [1] # ./check -n -g soak SECTION -- simpledev FSTYP -- xfs (non-debug) PLATFORM -- Linux/x86_64 MKFS_OPTIONS -- -f -m rmapbt=1 /dev/sda3 MOUNT_OPTIONS -- -o context=system_u:object_r:root_t:s0 /dev/sda3 /mnt/scratch generic/521 generic/522 generic/642 # ./check -n -g long_rw SECTION -- simpledev FSTYP -- xfs (non-debug) PLATFORM -- Linux/x86_64 MKFS_OPTIONS -- -f -m rmapbt=1 /dev/sda3 MOUNT_OPTIONS -- -o context=system_u:object_r:root_t:s0 /dev/sda3 /mnt/scratch generic/521 generic/522 generic/642 > > # Override the default cleanup function. > _cleanup() > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test 2023-04-22 8:24 ` Zorro Lang @ 2023-04-24 18:17 ` Darrick J. Wong 2023-04-25 4:50 ` Zorro Lang 0 siblings, 1 reply; 16+ messages in thread From: Darrick J. Wong @ 2023-04-24 18:17 UTC (permalink / raw) To: Zorro Lang; +Cc: linux-xfs, fstests, guan On Sat, Apr 22, 2023 at 04:24:56PM +0800, Zorro Lang wrote: > On Tue, Apr 11, 2023 at 11:13:52AM -0700, Darrick J. Wong wrote: > > From: Darrick J. Wong <djwong@kernel.org> > > > > This test is a long(ish) running stress test, so add it to those groups. > > > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > > --- > > tests/generic/476 | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > > > diff --git a/tests/generic/476 b/tests/generic/476 > > index 212373d17c..edb0be7b50 100755 > > --- a/tests/generic/476 > > +++ b/tests/generic/476 > > @@ -8,7 +8,7 @@ > > # bugs in the write path. > > # > > . ./common/preamble > > -_begin_fstest auto rw > > +_begin_fstest auto rw soak long_rw stress > > Sorry for late reviewing. I thought a bit more about this change. I think > the "soak", "long_rw" and "stress" tags are a bit overlap. If the "stress" > group means "fsstress", then I think the fsstress test can be in soak > group too, and currently the test cases in "soak" group are same with the > "long_rw" group [1]. Hm. Given the current definitions of each group: long_rw long-soak read write IO path exercisers rw read/write IO tests soak long running soak tests of any kind stress fsstress filesystem exerciser I think these all can apply to generic/476 -- it's definitely a read-write IO test; it's definitely one that does RW for a long time; and it uses fsstress. > So I think we can give the "soak" tag to more test cases with random I/Os > (fsstress or fsx or others). And rename "long_rw" to "long_soak" for those > soak group cases which need long soaking time. Then we have two group tags > for random loading/stress test cases, the testers can (decide to) run these > random load test cases seperately with more time or loop count. I have a counterproposal -- what do you think about redefining 'soak' to mean "all tests where SOAK_DURATION can be used to control the test runtime directly"? This shouldn't break anyone's scripts, since the only members of 'soak' are the ones that get modified by this patchset. --D > Anyway, above things can be done in another patchset, I just speak out to > get more talking:) For this patch: > > Reviewed-by: Zorro Lang <zlang@redhat.com> > > > > Thanks, > Zorro > > [1] > # ./check -n -g soak > SECTION -- simpledev > FSTYP -- xfs (non-debug) > PLATFORM -- Linux/x86_64 > MKFS_OPTIONS -- -f -m rmapbt=1 /dev/sda3 > MOUNT_OPTIONS -- -o context=system_u:object_r:root_t:s0 /dev/sda3 /mnt/scratch > > generic/521 > generic/522 > generic/642 > > # ./check -n -g long_rw > SECTION -- simpledev > FSTYP -- xfs (non-debug) > PLATFORM -- Linux/x86_64 > MKFS_OPTIONS -- -f -m rmapbt=1 /dev/sda3 > MOUNT_OPTIONS -- -o context=system_u:object_r:root_t:s0 /dev/sda3 /mnt/scratch > > generic/521 > generic/522 > generic/642 > > > > > > # Override the default cleanup function. > > _cleanup() > > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test 2023-04-24 18:17 ` Darrick J. Wong @ 2023-04-25 4:50 ` Zorro Lang 0 siblings, 0 replies; 16+ messages in thread From: Zorro Lang @ 2023-04-25 4:50 UTC (permalink / raw) To: Darrick J. Wong; +Cc: linux-xfs, fstests On Mon, Apr 24, 2023 at 11:17:25AM -0700, Darrick J. Wong wrote: > On Sat, Apr 22, 2023 at 04:24:56PM +0800, Zorro Lang wrote: > > On Tue, Apr 11, 2023 at 11:13:52AM -0700, Darrick J. Wong wrote: > > > From: Darrick J. Wong <djwong@kernel.org> > > > > > > This test is a long(ish) running stress test, so add it to those groups. > > > > > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > > > --- > > > tests/generic/476 | 2 +- > > > 1 file changed, 1 insertion(+), 1 deletion(-) > > > > > > > > > diff --git a/tests/generic/476 b/tests/generic/476 > > > index 212373d17c..edb0be7b50 100755 > > > --- a/tests/generic/476 > > > +++ b/tests/generic/476 > > > @@ -8,7 +8,7 @@ > > > # bugs in the write path. > > > # > > > . ./common/preamble > > > -_begin_fstest auto rw > > > +_begin_fstest auto rw soak long_rw stress > > > > Sorry for late reviewing. I thought a bit more about this change. I think > > the "soak", "long_rw" and "stress" tags are a bit overlap. If the "stress" > > group means "fsstress", then I think the fsstress test can be in soak > > group too, and currently the test cases in "soak" group are same with the > > "long_rw" group [1]. > > Hm. Given the current definitions of each group: > > long_rw long-soak read write IO path exercisers > rw read/write IO tests > soak long running soak tests of any kind > stress fsstress filesystem exerciser > > I think these all can apply to generic/476 -- it's definitely a > read-write IO test; it's definitely one that does RW for a long time; > and it uses fsstress. > > > So I think we can give the "soak" tag to more test cases with random I/Os > > (fsstress or fsx or others). And rename "long_rw" to "long_soak" for those > > soak group cases which need long soaking time. Then we have two group tags > > for random loading/stress test cases, the testers can (decide to) run these > > random load test cases seperately with more time or loop count. > > I have a counterproposal -- what do you think about redefining 'soak' to > mean "all tests where SOAK_DURATION can be used to control the test > runtime directly"? This shouldn't break anyone's scripts, since the > only members of 'soak' are the ones that get modified by this patchset. Sure, we can check if more cases can use the SOAK_DURATION later, then we add them to soak group. Thanks, Zorro > > --D > > > Anyway, above things can be done in another patchset, I just speak out to > > get more talking:) For this patch: > > > > Reviewed-by: Zorro Lang <zlang@redhat.com> > > > > > > > > Thanks, > > Zorro > > > > [1] > > # ./check -n -g soak > > SECTION -- simpledev > > FSTYP -- xfs (non-debug) > > PLATFORM -- Linux/x86_64 > > MKFS_OPTIONS -- -f -m rmapbt=1 /dev/sda3 > > MOUNT_OPTIONS -- -o context=system_u:object_r:root_t:s0 /dev/sda3 /mnt/scratch > > > > generic/521 > > generic/522 > > generic/642 > > > > # ./check -n -g long_rw > > SECTION -- simpledev > > FSTYP -- xfs (non-debug) > > PLATFORM -- Linux/x86_64 > > MKFS_OPTIONS -- -f -m rmapbt=1 /dev/sda3 > > MOUNT_OPTIONS -- -o context=system_u:object_r:root_t:s0 /dev/sda3 /mnt/scratch > > > > generic/521 > > generic/522 > > generic/642 > > > > > > > > > > # Override the default cleanup function. > > > _cleanup() > > > > > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 2/3] misc: add duration for long soak tests 2023-04-11 18:13 [PATCHSET 0/3] fstests: direct specification of looping test duration Darrick J. Wong 2023-04-11 18:13 ` [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test Darrick J. Wong @ 2023-04-11 18:13 ` Darrick J. Wong 2023-04-15 0:29 ` [PATCH v2 " Darrick J. Wong 2023-04-11 18:14 ` [PATCH 3/3] misc: add duration for recovery loop tests Darrick J. Wong 2023-04-13 10:48 ` [PATCHSET 0/3] fstests: direct specification of looping test duration Andrey Albershteyn 3 siblings, 1 reply; 16+ messages in thread From: Darrick J. Wong @ 2023-04-11 18:13 UTC (permalink / raw) To: djwong, zlang; +Cc: linux-xfs, fstests, guan From: Darrick J. Wong <djwong@kernel.org> Make it so that test runners can schedule long soak stress test programs for an exact number of seconds by setting the STRESS_DURATION config variable. Signed-off-by: Darrick J. Wong <djwong@kernel.org> --- check | 14 +++++++++ common/config | 7 ++++ common/fuzzy | 7 ++++ common/report | 1 + ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- ltp/fsx.c | 50 +++++++++++++++++++++++++++++++ src/soak_duration.awk | 23 ++++++++++++++ tests/generic/476 | 5 +++ tests/generic/521 | 1 + tests/generic/522 | 1 + tests/generic/642 | 1 + 11 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 src/soak_duration.awk diff --git a/check b/check index 1a58a2b269..b065277287 100755 --- a/check +++ b/check @@ -366,6 +366,20 @@ if ! . ./common/rc; then exit 1 fi +# If the test config specified a soak test duration, see if there are any +# unit suffixes that need converting to an integer seconds count. +if [ -n "$SOAK_DURATION" ]; then + SOAK_DURATION="$(echo "$SOAK_DURATION" | \ + sed -e 's/^\([.0-9]*\)\([a-z]\)*/\1 \2/g' | \ + $AWK_PROG -f $here/src/soak_duration.awk)" + if [ $? -ne 0 ]; then + echo "$SOAK_DURATION" + status=1 + exit 1 + fi + export SOAK_DURATION +fi + if [ -n "$subdir_xfile" ]; then for d in $SRC_GROUPS $FSTYP; do [ -f $SRC_DIR/$d/$subdir_xfile ] || continue diff --git a/common/config b/common/config index 6c8cb3a5ba..fdd0aadbeb 100644 --- a/common/config +++ b/common/config @@ -57,6 +57,13 @@ export SOAK_PROC=3 # -p option to fsstress export SOAK_STRESS=10000 # -n option to fsstress export SOAK_PASSES=-1 # count of repetitions of fsstress (while soaking) export EMAIL=root@localhost # where auto-qa will send its status messages + +# For certain tests that run in tight loops, setting this variable allows the +# test runner to specify exactly how long the test should continue looping. +# This is independent of TIME_FACTOR. Floating point numbers are allowed, and +# the unit suffixes m(inutes), h(ours), d(ays), and w(eeks) are supported. +export SOAK_DURATION=${SOAK_DURATION:=} + export HOST_OPTIONS=${HOST_OPTIONS:=local.config} export CHECK_OPTIONS=${CHECK_OPTIONS:="-g auto"} export BENCH_PASSES=${BENCH_PASSES:=5} diff --git a/common/fuzzy b/common/fuzzy index 961bedc717..4365e7343e 100644 --- a/common/fuzzy +++ b/common/fuzzy @@ -1351,7 +1351,12 @@ _scratch_xfs_stress_scrub() { fi local start="$(date +%s)" - local end="$((start + (30 * TIME_FACTOR) ))" + local end + if [ -n "$SOAK_DURATION" ]; then + end="$((start + SOAK_DURATION))" + else + end="$((start + (30 * TIME_FACTOR) ))" + fi local scrub_startat="$((start + scrub_delay))" test "$scrub_startat" -gt "$((end - 10))" && scrub_startat="$((end - 10))" diff --git a/common/report b/common/report index be930e0b06..9bfa09ecce 100644 --- a/common/report +++ b/common/report @@ -67,6 +67,7 @@ __generate_report_vars() { REPORT_VARS["CPUS"]="$(getconf _NPROCESSORS_ONLN 2>/dev/null)" REPORT_VARS["MEM_KB"]="$(grep MemTotal: /proc/meminfo | awk '{print $2}')" REPORT_VARS["SWAP_KB"]="$(grep SwapTotal: /proc/meminfo | awk '{print $2}')" + test -n "$SOAK_DURATION" && REPORT_VARS["SOAK_DURATION"]="$SOAK_DURATION" test -e /sys/devices/system/node/possible && \ REPORT_VARS["NUMA_NODES"]="$(cat /sys/devices/system/node/possible 2>/dev/null)" diff --git a/ltp/fsstress.c b/ltp/fsstress.c index e60f2da929..0dc6545448 100644 --- a/ltp/fsstress.c +++ b/ltp/fsstress.c @@ -386,6 +386,8 @@ char *execute_cmd = NULL; int execute_freq = 1; struct print_string flag_str = {0}; +struct timespec deadline = { 0 }; + void add_to_flist(int, int, int, int); void append_pathname(pathname_t *, char *); int attr_list_path(pathname_t *, char *, const int); @@ -459,6 +461,34 @@ void sg_handler(int signum) } } +bool +keep_looping(int i, int loops) +{ + int ret; + + if (deadline.tv_nsec) { + struct timespec now; + + ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret) { + perror("CLOCK_MONOTONIC"); + return false; + } + + return now.tv_sec <= deadline.tv_sec; + } + + if (!loops) + return true; + + return i < loops; +} + +static struct option longopts[] = { + {"duration", optional_argument, 0, 256}, + { } +}; + int main(int argc, char **argv) { char buf[10]; @@ -478,13 +508,14 @@ int main(int argc, char **argv) struct sigaction action; int loops = 1; const char *allopts = "cd:e:f:i:l:m:M:n:o:p:rRs:S:vVwx:X:zH"; + long long duration; errrange = errtag = 0; umask(0); nops = sizeof(ops) / sizeof(ops[0]); ops_end = &ops[nops]; myprog = argv[0]; - while ((c = getopt(argc, argv, allopts)) != -1) { + while ((c = getopt_long(argc, argv, allopts, longopts, NULL)) != -1) { switch (c) { case 'c': cleanup = 1; @@ -579,6 +610,26 @@ int main(int argc, char **argv) case 'X': execute_freq = strtoul(optarg, NULL, 0); break; + case 256: /* --duration */ + if (!optarg) { + fprintf(stderr, "Specify time with --duration=\n"); + exit(87); + } + duration = strtoll(optarg, NULL, 0); + if (duration < 1) { + fprintf(stderr, "%lld: invalid duration\n", duration); + exit(88); + } + + i = clock_gettime(CLOCK_MONOTONIC, &deadline); + if (i) { + perror("CLOCK_MONOTONIC"); + exit(89); + } + + deadline.tv_sec += duration; + deadline.tv_nsec = 1; + break; case '?': fprintf(stderr, "%s - invalid parameters\n", myprog); @@ -721,7 +772,7 @@ int main(int argc, char **argv) } } #endif - for (i = 0; !loops || (i < loops); i++) + for (i = 0; keep_looping(i, loops); i++) doproc(); #ifdef AIO if(io_destroy(io_ctx) != 0) { @@ -1121,6 +1172,26 @@ dirid_to_fent(int dirid) return NULL; } +bool +keep_running(opnum_t opno, opnum_t operations) +{ + int ret; + + if (deadline.tv_nsec) { + struct timespec now; + + ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret) { + perror("CLOCK_MONOTONIC"); + return false; + } + + return now.tv_sec <= deadline.tv_sec; + } + + return opno < operations; +} + void doproc(void) { @@ -1149,7 +1220,7 @@ doproc(void) srandom(seed); if (namerand) namerand = random(); - for (opno = 0; opno < operations; opno++) { + for (opno = 0; keep_running(opno, operations); opno++) { if (execute_cmd && opno && opno % dividend == 0) { if (verbose) printf("%lld: execute command %s\n", opno, @@ -1935,6 +2006,7 @@ usage(void) printf(" -V specifies verifiable logging mode (omitting inode numbers)\n"); printf(" -X ncmd number of calls to the -x command (default 1)\n"); printf(" -H prints usage and exits\n"); + printf(" --duration=s run for this many seconds\n"); } void diff --git a/ltp/fsx.c b/ltp/fsx.c index ee4b8fe45d..761d5e467f 100644 --- a/ltp/fsx.c +++ b/ltp/fsx.c @@ -193,6 +193,8 @@ int fsx_rw(int rw, int fd, char *buf, unsigned len, unsigned offset); #define fsxread(a,b,c,d) fsx_rw(READ, a,b,c,d) #define fsxwrite(a,b,c,d) fsx_rw(WRITE, a,b,c,d) +struct timespec deadline; + const char *replayops = NULL; const char *recordops = NULL; FILE * fsxlogf = NULL; @@ -2457,6 +2459,7 @@ usage(void) -Z: O_DIRECT (use -R, -W, -r and -w too)\n\ --replay-ops opsfile: replay ops from recorded .fsxops file\n\ --record-ops[=opsfile]: dump ops file also on success. optionally specify ops file name\n\ + --duration=seconds: run for this many seconds\n\ fname: this filename is REQUIRED (no default)\n"); exit(90); } @@ -2739,9 +2742,33 @@ __test_fallocate(int mode, const char *mode_str) #endif } +bool +keep_running(void) +{ + int ret; + + if (deadline.tv_nsec) { + struct timespec now; + + ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret) { + perror("CLOCK_MONOTONIC"); + return false; + } + + return now.tv_sec <= deadline.tv_sec; + } + + if (numops == -1) + return true; + + return numops-- != 0; +} + static struct option longopts[] = { {"replay-ops", required_argument, 0, 256}, {"record-ops", optional_argument, 0, 255}, + {"duration", optional_argument, 0, 254}, { } }; @@ -2753,6 +2780,7 @@ main(int argc, char **argv) char logfile[PATH_MAX]; struct stat statbuf; int o_flags = O_RDWR|O_CREAT|O_TRUNC; + long long duration; logfile[0] = 0; dname[0] = 0; @@ -2950,6 +2978,26 @@ main(int argc, char **argv) o_direct = O_DIRECT; o_flags |= O_DIRECT; break; + case 254: /* --duration */ + if (!optarg) { + fprintf(stderr, "Specify time with --duration=\n"); + exit(87); + } + duration = strtoll(optarg, NULL, 0); + if (duration < 1) { + fprintf(stderr, "%lld: invalid duration\n", duration); + exit(88); + } + + i = clock_gettime(CLOCK_MONOTONIC, &deadline); + if (i) { + perror("CLOCK_MONOTONIC"); + exit(89); + } + + deadline.tv_sec += duration; + deadline.tv_nsec = 1; + break; case 255: /* --record-ops */ if (optarg) snprintf(opsfile, sizeof(opsfile), "%s", optarg); @@ -3145,7 +3193,7 @@ main(int argc, char **argv) if (xchg_range_calls) xchg_range_calls = test_xchg_range(); - while (numops == -1 || numops--) + while (keep_running()) if (!test()) break; diff --git a/src/soak_duration.awk b/src/soak_duration.awk new file mode 100644 index 0000000000..6c38d09b39 --- /dev/null +++ b/src/soak_duration.awk @@ -0,0 +1,23 @@ +#!/usr/bin/awk +# +# Convert time interval specifications with suffixes to an integer number of +# seconds. +{ + nr = $1; + if ($2 == "" || $2 ~ /s/) # seconds + ; + else if ($2 ~ /m/) # minutes + nr *= 60; + else if ($2 ~ /h/) # hours + nr *= 3600; + else if ($2 ~ /d/) # days + nr *= 86400; + else if ($2 ~ /w/) # weeks + nr *= 604800; + else { + printf("%s: unknown suffix\n", $2); + exit 1; + } + + printf("%d\n", nr); +} diff --git a/tests/generic/476 b/tests/generic/476 index edb0be7b50..a162cda6b1 100755 --- a/tests/generic/476 +++ b/tests/generic/476 @@ -33,7 +33,10 @@ _scratch_mount >> $seqres.full 2>&1 nr_cpus=$((LOAD_FACTOR * 4)) nr_ops=$((25000 * nr_cpus * TIME_FACTOR)) -$FSSTRESS_PROG $FSSTRESS_AVOID -w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full +fsstress_args=(-w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus) +test -n "$SOAK_DURATION" && fsstress_args+=(--duration="$SOAK_DURATION") + +$FSSTRESS_PROG $FSSTRESS_AVOID "${fsstress_args[@]}" >> $seqres.full # success, all done status=0 diff --git a/tests/generic/521 b/tests/generic/521 index cde9d44775..22dd31a8ec 100755 --- a/tests/generic/521 +++ b/tests/generic/521 @@ -35,6 +35,7 @@ fsx_args+=(-r $min_dio_sz) fsx_args+=(-t $min_dio_sz) fsx_args+=(-w $min_dio_sz) fsx_args+=(-Z) +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' diff --git a/tests/generic/522 b/tests/generic/522 index ae84fe04bb..f0cbcb245c 100755 --- a/tests/generic/522 +++ b/tests/generic/522 @@ -29,6 +29,7 @@ fsx_args+=(-N $nr_ops) fsx_args+=(-p $((nr_ops / 100))) fsx_args+=(-o $op_sz) fsx_args+=(-l $file_sz) +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' diff --git a/tests/generic/642 b/tests/generic/642 index c0e274d843..eba90903a3 100755 --- a/tests/generic/642 +++ b/tests/generic/642 @@ -49,6 +49,7 @@ for verb in attr_remove removefattr; do done args+=('-f' "setfattr=20") args+=('-f' "attr_set=60") # sets larger xattrs +test -n "$DURATION" && args+=(--duration="$DURATION") $FSSTRESS_PROG "${args[@]}" $FSSTRESS_AVOID -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 2/3] misc: add duration for long soak tests 2023-04-11 18:13 ` [PATCH 2/3] misc: add duration for long soak tests Darrick J. Wong @ 2023-04-15 0:29 ` Darrick J. Wong 2023-04-22 13:33 ` Zorro Lang 0 siblings, 1 reply; 16+ messages in thread From: Darrick J. Wong @ 2023-04-15 0:29 UTC (permalink / raw) To: zlang; +Cc: linux-xfs, fstests, guan From: Darrick J. Wong <djwong@kernel.org> Make it so that test runners can schedule long soak stress test programs for an exact number of seconds by setting the SOAK_DURATION config variable. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com> --- v2: fix commit message --- check | 14 +++++++++ common/config | 7 ++++ common/fuzzy | 7 ++++ common/report | 1 + ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- ltp/fsx.c | 50 +++++++++++++++++++++++++++++++ src/soak_duration.awk | 23 ++++++++++++++ tests/generic/476 | 5 +++ tests/generic/521 | 1 + tests/generic/522 | 1 + tests/generic/642 | 1 + 11 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 src/soak_duration.awk diff --git a/check b/check index e32b70d301..1d78cf27f4 100755 --- a/check +++ b/check @@ -366,6 +366,20 @@ if ! . ./common/rc; then exit 1 fi +# If the test config specified a soak test duration, see if there are any +# unit suffixes that need converting to an integer seconds count. +if [ -n "$SOAK_DURATION" ]; then + SOAK_DURATION="$(echo "$SOAK_DURATION" | \ + sed -e 's/^\([.0-9]*\)\([a-z]\)*/\1 \2/g' | \ + $AWK_PROG -f $here/src/soak_duration.awk)" + if [ $? -ne 0 ]; then + echo "$SOAK_DURATION" + status=1 + exit 1 + fi + export SOAK_DURATION +fi + if [ -n "$subdir_xfile" ]; then for d in $SRC_GROUPS $FSTYP; do [ -f $SRC_DIR/$d/$subdir_xfile ] || continue diff --git a/common/config b/common/config index 6c8cb3a5ba..fdd0aadbeb 100644 --- a/common/config +++ b/common/config @@ -57,6 +57,13 @@ export SOAK_PROC=3 # -p option to fsstress export SOAK_STRESS=10000 # -n option to fsstress export SOAK_PASSES=-1 # count of repetitions of fsstress (while soaking) export EMAIL=root@localhost # where auto-qa will send its status messages + +# For certain tests that run in tight loops, setting this variable allows the +# test runner to specify exactly how long the test should continue looping. +# This is independent of TIME_FACTOR. Floating point numbers are allowed, and +# the unit suffixes m(inutes), h(ours), d(ays), and w(eeks) are supported. +export SOAK_DURATION=${SOAK_DURATION:=} + export HOST_OPTIONS=${HOST_OPTIONS:=local.config} export CHECK_OPTIONS=${CHECK_OPTIONS:="-g auto"} export BENCH_PASSES=${BENCH_PASSES:=5} diff --git a/common/fuzzy b/common/fuzzy index 744d9ed65d..9c04bb5318 100644 --- a/common/fuzzy +++ b/common/fuzzy @@ -1360,7 +1360,12 @@ _scratch_xfs_stress_scrub() { fi local start="$(date +%s)" - local end="$((start + (30 * TIME_FACTOR) ))" + local end + if [ -n "$SOAK_DURATION" ]; then + end="$((start + SOAK_DURATION))" + else + end="$((start + (30 * TIME_FACTOR) ))" + fi local scrub_startat="$((start + scrub_delay))" test "$scrub_startat" -gt "$((end - 10))" && scrub_startat="$((end - 10))" diff --git a/common/report b/common/report index be930e0b06..9bfa09ecce 100644 --- a/common/report +++ b/common/report @@ -67,6 +67,7 @@ __generate_report_vars() { REPORT_VARS["CPUS"]="$(getconf _NPROCESSORS_ONLN 2>/dev/null)" REPORT_VARS["MEM_KB"]="$(grep MemTotal: /proc/meminfo | awk '{print $2}')" REPORT_VARS["SWAP_KB"]="$(grep SwapTotal: /proc/meminfo | awk '{print $2}')" + test -n "$SOAK_DURATION" && REPORT_VARS["SOAK_DURATION"]="$SOAK_DURATION" test -e /sys/devices/system/node/possible && \ REPORT_VARS["NUMA_NODES"]="$(cat /sys/devices/system/node/possible 2>/dev/null)" diff --git a/ltp/fsstress.c b/ltp/fsstress.c index e60f2da929..0dc6545448 100644 --- a/ltp/fsstress.c +++ b/ltp/fsstress.c @@ -386,6 +386,8 @@ char *execute_cmd = NULL; int execute_freq = 1; struct print_string flag_str = {0}; +struct timespec deadline = { 0 }; + void add_to_flist(int, int, int, int); void append_pathname(pathname_t *, char *); int attr_list_path(pathname_t *, char *, const int); @@ -459,6 +461,34 @@ void sg_handler(int signum) } } +bool +keep_looping(int i, int loops) +{ + int ret; + + if (deadline.tv_nsec) { + struct timespec now; + + ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret) { + perror("CLOCK_MONOTONIC"); + return false; + } + + return now.tv_sec <= deadline.tv_sec; + } + + if (!loops) + return true; + + return i < loops; +} + +static struct option longopts[] = { + {"duration", optional_argument, 0, 256}, + { } +}; + int main(int argc, char **argv) { char buf[10]; @@ -478,13 +508,14 @@ int main(int argc, char **argv) struct sigaction action; int loops = 1; const char *allopts = "cd:e:f:i:l:m:M:n:o:p:rRs:S:vVwx:X:zH"; + long long duration; errrange = errtag = 0; umask(0); nops = sizeof(ops) / sizeof(ops[0]); ops_end = &ops[nops]; myprog = argv[0]; - while ((c = getopt(argc, argv, allopts)) != -1) { + while ((c = getopt_long(argc, argv, allopts, longopts, NULL)) != -1) { switch (c) { case 'c': cleanup = 1; @@ -579,6 +610,26 @@ int main(int argc, char **argv) case 'X': execute_freq = strtoul(optarg, NULL, 0); break; + case 256: /* --duration */ + if (!optarg) { + fprintf(stderr, "Specify time with --duration=\n"); + exit(87); + } + duration = strtoll(optarg, NULL, 0); + if (duration < 1) { + fprintf(stderr, "%lld: invalid duration\n", duration); + exit(88); + } + + i = clock_gettime(CLOCK_MONOTONIC, &deadline); + if (i) { + perror("CLOCK_MONOTONIC"); + exit(89); + } + + deadline.tv_sec += duration; + deadline.tv_nsec = 1; + break; case '?': fprintf(stderr, "%s - invalid parameters\n", myprog); @@ -721,7 +772,7 @@ int main(int argc, char **argv) } } #endif - for (i = 0; !loops || (i < loops); i++) + for (i = 0; keep_looping(i, loops); i++) doproc(); #ifdef AIO if(io_destroy(io_ctx) != 0) { @@ -1121,6 +1172,26 @@ dirid_to_fent(int dirid) return NULL; } +bool +keep_running(opnum_t opno, opnum_t operations) +{ + int ret; + + if (deadline.tv_nsec) { + struct timespec now; + + ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret) { + perror("CLOCK_MONOTONIC"); + return false; + } + + return now.tv_sec <= deadline.tv_sec; + } + + return opno < operations; +} + void doproc(void) { @@ -1149,7 +1220,7 @@ doproc(void) srandom(seed); if (namerand) namerand = random(); - for (opno = 0; opno < operations; opno++) { + for (opno = 0; keep_running(opno, operations); opno++) { if (execute_cmd && opno && opno % dividend == 0) { if (verbose) printf("%lld: execute command %s\n", opno, @@ -1935,6 +2006,7 @@ usage(void) printf(" -V specifies verifiable logging mode (omitting inode numbers)\n"); printf(" -X ncmd number of calls to the -x command (default 1)\n"); printf(" -H prints usage and exits\n"); + printf(" --duration=s run for this many seconds\n"); } void diff --git a/ltp/fsx.c b/ltp/fsx.c index ee4b8fe45d..761d5e467f 100644 --- a/ltp/fsx.c +++ b/ltp/fsx.c @@ -193,6 +193,8 @@ int fsx_rw(int rw, int fd, char *buf, unsigned len, unsigned offset); #define fsxread(a,b,c,d) fsx_rw(READ, a,b,c,d) #define fsxwrite(a,b,c,d) fsx_rw(WRITE, a,b,c,d) +struct timespec deadline; + const char *replayops = NULL; const char *recordops = NULL; FILE * fsxlogf = NULL; @@ -2457,6 +2459,7 @@ usage(void) -Z: O_DIRECT (use -R, -W, -r and -w too)\n\ --replay-ops opsfile: replay ops from recorded .fsxops file\n\ --record-ops[=opsfile]: dump ops file also on success. optionally specify ops file name\n\ + --duration=seconds: run for this many seconds\n\ fname: this filename is REQUIRED (no default)\n"); exit(90); } @@ -2739,9 +2742,33 @@ __test_fallocate(int mode, const char *mode_str) #endif } +bool +keep_running(void) +{ + int ret; + + if (deadline.tv_nsec) { + struct timespec now; + + ret = clock_gettime(CLOCK_MONOTONIC, &now); + if (ret) { + perror("CLOCK_MONOTONIC"); + return false; + } + + return now.tv_sec <= deadline.tv_sec; + } + + if (numops == -1) + return true; + + return numops-- != 0; +} + static struct option longopts[] = { {"replay-ops", required_argument, 0, 256}, {"record-ops", optional_argument, 0, 255}, + {"duration", optional_argument, 0, 254}, { } }; @@ -2753,6 +2780,7 @@ main(int argc, char **argv) char logfile[PATH_MAX]; struct stat statbuf; int o_flags = O_RDWR|O_CREAT|O_TRUNC; + long long duration; logfile[0] = 0; dname[0] = 0; @@ -2950,6 +2978,26 @@ main(int argc, char **argv) o_direct = O_DIRECT; o_flags |= O_DIRECT; break; + case 254: /* --duration */ + if (!optarg) { + fprintf(stderr, "Specify time with --duration=\n"); + exit(87); + } + duration = strtoll(optarg, NULL, 0); + if (duration < 1) { + fprintf(stderr, "%lld: invalid duration\n", duration); + exit(88); + } + + i = clock_gettime(CLOCK_MONOTONIC, &deadline); + if (i) { + perror("CLOCK_MONOTONIC"); + exit(89); + } + + deadline.tv_sec += duration; + deadline.tv_nsec = 1; + break; case 255: /* --record-ops */ if (optarg) snprintf(opsfile, sizeof(opsfile), "%s", optarg); @@ -3145,7 +3193,7 @@ main(int argc, char **argv) if (xchg_range_calls) xchg_range_calls = test_xchg_range(); - while (numops == -1 || numops--) + while (keep_running()) if (!test()) break; diff --git a/src/soak_duration.awk b/src/soak_duration.awk new file mode 100644 index 0000000000..6c38d09b39 --- /dev/null +++ b/src/soak_duration.awk @@ -0,0 +1,23 @@ +#!/usr/bin/awk +# +# Convert time interval specifications with suffixes to an integer number of +# seconds. +{ + nr = $1; + if ($2 == "" || $2 ~ /s/) # seconds + ; + else if ($2 ~ /m/) # minutes + nr *= 60; + else if ($2 ~ /h/) # hours + nr *= 3600; + else if ($2 ~ /d/) # days + nr *= 86400; + else if ($2 ~ /w/) # weeks + nr *= 604800; + else { + printf("%s: unknown suffix\n", $2); + exit 1; + } + + printf("%d\n", nr); +} diff --git a/tests/generic/476 b/tests/generic/476 index edb0be7b50..a162cda6b1 100755 --- a/tests/generic/476 +++ b/tests/generic/476 @@ -33,7 +33,10 @@ _scratch_mount >> $seqres.full 2>&1 nr_cpus=$((LOAD_FACTOR * 4)) nr_ops=$((25000 * nr_cpus * TIME_FACTOR)) -$FSSTRESS_PROG $FSSTRESS_AVOID -w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full +fsstress_args=(-w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus) +test -n "$SOAK_DURATION" && fsstress_args+=(--duration="$SOAK_DURATION") + +$FSSTRESS_PROG $FSSTRESS_AVOID "${fsstress_args[@]}" >> $seqres.full # success, all done status=0 diff --git a/tests/generic/521 b/tests/generic/521 index cde9d44775..22dd31a8ec 100755 --- a/tests/generic/521 +++ b/tests/generic/521 @@ -35,6 +35,7 @@ fsx_args+=(-r $min_dio_sz) fsx_args+=(-t $min_dio_sz) fsx_args+=(-w $min_dio_sz) fsx_args+=(-Z) +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' diff --git a/tests/generic/522 b/tests/generic/522 index ae84fe04bb..f0cbcb245c 100755 --- a/tests/generic/522 +++ b/tests/generic/522 @@ -29,6 +29,7 @@ fsx_args+=(-N $nr_ops) fsx_args+=(-p $((nr_ops / 100))) fsx_args+=(-o $op_sz) fsx_args+=(-l $file_sz) +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' diff --git a/tests/generic/642 b/tests/generic/642 index c0e274d843..eba90903a3 100755 --- a/tests/generic/642 +++ b/tests/generic/642 @@ -49,6 +49,7 @@ for verb in attr_remove removefattr; do done args+=('-f' "setfattr=20") args+=('-f' "attr_set=60") # sets larger xattrs +test -n "$DURATION" && args+=(--duration="$DURATION") $FSSTRESS_PROG "${args[@]}" $FSSTRESS_AVOID -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] misc: add duration for long soak tests 2023-04-15 0:29 ` [PATCH v2 " Darrick J. Wong @ 2023-04-22 13:33 ` Zorro Lang 2023-04-24 18:27 ` Darrick J. Wong 0 siblings, 1 reply; 16+ messages in thread From: Zorro Lang @ 2023-04-22 13:33 UTC (permalink / raw) To: Darrick J. Wong; +Cc: linux-xfs, fstests, guan On Fri, Apr 14, 2023 at 05:29:49PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@kernel.org> > > Make it so that test runners can schedule long soak stress test programs > for an exact number of seconds by setting the SOAK_DURATION config > variable. > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com> > --- > v2: fix commit message > --- > check | 14 +++++++++ > common/config | 7 ++++ > common/fuzzy | 7 ++++ > common/report | 1 + > ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- > ltp/fsx.c | 50 +++++++++++++++++++++++++++++++ > src/soak_duration.awk | 23 ++++++++++++++ > tests/generic/476 | 5 +++ > tests/generic/521 | 1 + > tests/generic/522 | 1 + > tests/generic/642 | 1 + > 11 files changed, 182 insertions(+), 6 deletions(-) > create mode 100644 src/soak_duration.awk > > diff --git a/check b/check > index e32b70d301..1d78cf27f4 100755 > --- a/check > +++ b/check > @@ -366,6 +366,20 @@ if ! . ./common/rc; then > exit 1 > fi > > +# If the test config specified a soak test duration, see if there are any > +# unit suffixes that need converting to an integer seconds count. > +if [ -n "$SOAK_DURATION" ]; then > + SOAK_DURATION="$(echo "$SOAK_DURATION" | \ > + sed -e 's/^\([.0-9]*\)\([a-z]\)*/\1 \2/g' | \ > + $AWK_PROG -f $here/src/soak_duration.awk)" > + if [ $? -ne 0 ]; then > + echo "$SOAK_DURATION" echo SOAK_DURATION=$SOAK_DURATION ? > + status=1 > + exit 1 > + fi > + export SOAK_DURATION Is this necessary? As you've exported SOAK_DURATION in common/config: export SOAK_DURATION=${SOAK_DURATION:=} > +fi > + > if [ -n "$subdir_xfile" ]; then > for d in $SRC_GROUPS $FSTYP; do > [ -f $SRC_DIR/$d/$subdir_xfile ] || continue > diff --git a/common/config b/common/config > index 6c8cb3a5ba..fdd0aadbeb 100644 > --- a/common/config > +++ b/common/config > @@ -57,6 +57,13 @@ export SOAK_PROC=3 # -p option to fsstress > export SOAK_STRESS=10000 # -n option to fsstress > export SOAK_PASSES=-1 # count of repetitions of fsstress (while soaking) > export EMAIL=root@localhost # where auto-qa will send its status messages > + > +# For certain tests that run in tight loops, setting this variable allows the > +# test runner to specify exactly how long the test should continue looping. > +# This is independent of TIME_FACTOR. Floating point numbers are allowed, and > +# the unit suffixes m(inutes), h(ours), d(ays), and w(eeks) are supported. > +export SOAK_DURATION=${SOAK_DURATION:=} Better to describe more about the SOAK_DURATION (and TIME/LOAD_FACTOR) in documentation (README?). To clarify the relationship of SOAK_DURATION with other related parameters, and how the SOAK_DURATION works/be used. > + > export HOST_OPTIONS=${HOST_OPTIONS:=local.config} > export CHECK_OPTIONS=${CHECK_OPTIONS:="-g auto"} > export BENCH_PASSES=${BENCH_PASSES:=5} > diff --git a/common/fuzzy b/common/fuzzy > index 744d9ed65d..9c04bb5318 100644 > --- a/common/fuzzy > +++ b/common/fuzzy > @@ -1360,7 +1360,12 @@ _scratch_xfs_stress_scrub() { > fi > > local start="$(date +%s)" > - local end="$((start + (30 * TIME_FACTOR) ))" > + local end > + if [ -n "$SOAK_DURATION" ]; then > + end="$((start + SOAK_DURATION))" > + else > + end="$((start + (30 * TIME_FACTOR) ))" > + fi > local scrub_startat="$((start + scrub_delay))" > test "$scrub_startat" -gt "$((end - 10))" && > scrub_startat="$((end - 10))" > diff --git a/common/report b/common/report > index be930e0b06..9bfa09ecce 100644 > --- a/common/report > +++ b/common/report > @@ -67,6 +67,7 @@ __generate_report_vars() { > REPORT_VARS["CPUS"]="$(getconf _NPROCESSORS_ONLN 2>/dev/null)" > REPORT_VARS["MEM_KB"]="$(grep MemTotal: /proc/meminfo | awk '{print $2}')" > REPORT_VARS["SWAP_KB"]="$(grep SwapTotal: /proc/meminfo | awk '{print $2}')" > + test -n "$SOAK_DURATION" && REPORT_VARS["SOAK_DURATION"]="$SOAK_DURATION" > > test -e /sys/devices/system/node/possible && \ > REPORT_VARS["NUMA_NODES"]="$(cat /sys/devices/system/node/possible 2>/dev/null)" > diff --git a/ltp/fsstress.c b/ltp/fsstress.c > index e60f2da929..0dc6545448 100644 > --- a/ltp/fsstress.c > +++ b/ltp/fsstress.c > @@ -386,6 +386,8 @@ char *execute_cmd = NULL; > int execute_freq = 1; > struct print_string flag_str = {0}; > > +struct timespec deadline = { 0 }; > + > void add_to_flist(int, int, int, int); > void append_pathname(pathname_t *, char *); > int attr_list_path(pathname_t *, char *, const int); > @@ -459,6 +461,34 @@ void sg_handler(int signum) > } > } > > +bool > +keep_looping(int i, int loops) > +{ > + int ret; > + > + if (deadline.tv_nsec) { > + struct timespec now; > + > + ret = clock_gettime(CLOCK_MONOTONIC, &now); > + if (ret) { > + perror("CLOCK_MONOTONIC"); > + return false; > + } > + > + return now.tv_sec <= deadline.tv_sec; > + } > + > + if (!loops) > + return true; > + > + return i < loops; > +} > + > +static struct option longopts[] = { > + {"duration", optional_argument, 0, 256}, OK, we'd better to check those test cases use fsstress "-n" later, think about if some of them should be replaced by "--duration". Thanks, Zorro > + { } > +}; > + > int main(int argc, char **argv) > { > char buf[10]; > @@ -478,13 +508,14 @@ int main(int argc, char **argv) > struct sigaction action; > int loops = 1; > const char *allopts = "cd:e:f:i:l:m:M:n:o:p:rRs:S:vVwx:X:zH"; > + long long duration; > > errrange = errtag = 0; > umask(0); > nops = sizeof(ops) / sizeof(ops[0]); > ops_end = &ops[nops]; > myprog = argv[0]; > - while ((c = getopt(argc, argv, allopts)) != -1) { > + while ((c = getopt_long(argc, argv, allopts, longopts, NULL)) != -1) { > switch (c) { > case 'c': > cleanup = 1; > @@ -579,6 +610,26 @@ int main(int argc, char **argv) > case 'X': > execute_freq = strtoul(optarg, NULL, 0); > break; > + case 256: /* --duration */ > + if (!optarg) { > + fprintf(stderr, "Specify time with --duration=\n"); > + exit(87); > + } > + duration = strtoll(optarg, NULL, 0); > + if (duration < 1) { > + fprintf(stderr, "%lld: invalid duration\n", duration); > + exit(88); > + } > + > + i = clock_gettime(CLOCK_MONOTONIC, &deadline); > + if (i) { > + perror("CLOCK_MONOTONIC"); > + exit(89); > + } > + > + deadline.tv_sec += duration; > + deadline.tv_nsec = 1; > + break; > case '?': > fprintf(stderr, "%s - invalid parameters\n", > myprog); > @@ -721,7 +772,7 @@ int main(int argc, char **argv) > } > } > #endif > - for (i = 0; !loops || (i < loops); i++) > + for (i = 0; keep_looping(i, loops); i++) > doproc(); > #ifdef AIO > if(io_destroy(io_ctx) != 0) { > @@ -1121,6 +1172,26 @@ dirid_to_fent(int dirid) > return NULL; > } > > +bool > +keep_running(opnum_t opno, opnum_t operations) > +{ > + int ret; > + > + if (deadline.tv_nsec) { > + struct timespec now; > + > + ret = clock_gettime(CLOCK_MONOTONIC, &now); > + if (ret) { > + perror("CLOCK_MONOTONIC"); > + return false; > + } > + > + return now.tv_sec <= deadline.tv_sec; > + } > + > + return opno < operations; > +} > + > void > doproc(void) > { > @@ -1149,7 +1220,7 @@ doproc(void) > srandom(seed); > if (namerand) > namerand = random(); > - for (opno = 0; opno < operations; opno++) { > + for (opno = 0; keep_running(opno, operations); opno++) { > if (execute_cmd && opno && opno % dividend == 0) { > if (verbose) > printf("%lld: execute command %s\n", opno, > @@ -1935,6 +2006,7 @@ usage(void) > printf(" -V specifies verifiable logging mode (omitting inode numbers)\n"); > printf(" -X ncmd number of calls to the -x command (default 1)\n"); > printf(" -H prints usage and exits\n"); > + printf(" --duration=s run for this many seconds\n"); > } > > void > diff --git a/ltp/fsx.c b/ltp/fsx.c > index ee4b8fe45d..761d5e467f 100644 > --- a/ltp/fsx.c > +++ b/ltp/fsx.c > @@ -193,6 +193,8 @@ int fsx_rw(int rw, int fd, char *buf, unsigned len, unsigned offset); > #define fsxread(a,b,c,d) fsx_rw(READ, a,b,c,d) > #define fsxwrite(a,b,c,d) fsx_rw(WRITE, a,b,c,d) > > +struct timespec deadline; > + > const char *replayops = NULL; > const char *recordops = NULL; > FILE * fsxlogf = NULL; > @@ -2457,6 +2459,7 @@ usage(void) > -Z: O_DIRECT (use -R, -W, -r and -w too)\n\ > --replay-ops opsfile: replay ops from recorded .fsxops file\n\ > --record-ops[=opsfile]: dump ops file also on success. optionally specify ops file name\n\ > + --duration=seconds: run for this many seconds\n\ > fname: this filename is REQUIRED (no default)\n"); > exit(90); > } > @@ -2739,9 +2742,33 @@ __test_fallocate(int mode, const char *mode_str) > #endif > } > > +bool > +keep_running(void) > +{ > + int ret; > + > + if (deadline.tv_nsec) { > + struct timespec now; > + > + ret = clock_gettime(CLOCK_MONOTONIC, &now); > + if (ret) { > + perror("CLOCK_MONOTONIC"); > + return false; > + } > + > + return now.tv_sec <= deadline.tv_sec; > + } > + > + if (numops == -1) > + return true; > + > + return numops-- != 0; > +} > + > static struct option longopts[] = { > {"replay-ops", required_argument, 0, 256}, > {"record-ops", optional_argument, 0, 255}, > + {"duration", optional_argument, 0, 254}, > { } > }; > > @@ -2753,6 +2780,7 @@ main(int argc, char **argv) > char logfile[PATH_MAX]; > struct stat statbuf; > int o_flags = O_RDWR|O_CREAT|O_TRUNC; > + long long duration; > > logfile[0] = 0; > dname[0] = 0; > @@ -2950,6 +2978,26 @@ main(int argc, char **argv) > o_direct = O_DIRECT; > o_flags |= O_DIRECT; > break; > + case 254: /* --duration */ > + if (!optarg) { > + fprintf(stderr, "Specify time with --duration=\n"); > + exit(87); > + } > + duration = strtoll(optarg, NULL, 0); > + if (duration < 1) { > + fprintf(stderr, "%lld: invalid duration\n", duration); > + exit(88); > + } > + > + i = clock_gettime(CLOCK_MONOTONIC, &deadline); > + if (i) { > + perror("CLOCK_MONOTONIC"); > + exit(89); > + } > + > + deadline.tv_sec += duration; > + deadline.tv_nsec = 1; > + break; > case 255: /* --record-ops */ > if (optarg) > snprintf(opsfile, sizeof(opsfile), "%s", optarg); > @@ -3145,7 +3193,7 @@ main(int argc, char **argv) > if (xchg_range_calls) > xchg_range_calls = test_xchg_range(); > > - while (numops == -1 || numops--) > + while (keep_running()) > if (!test()) > break; > > diff --git a/src/soak_duration.awk b/src/soak_duration.awk > new file mode 100644 > index 0000000000..6c38d09b39 > --- /dev/null > +++ b/src/soak_duration.awk > @@ -0,0 +1,23 @@ > +#!/usr/bin/awk > +# > +# Convert time interval specifications with suffixes to an integer number of > +# seconds. > +{ > + nr = $1; > + if ($2 == "" || $2 ~ /s/) # seconds > + ; > + else if ($2 ~ /m/) # minutes > + nr *= 60; > + else if ($2 ~ /h/) # hours > + nr *= 3600; > + else if ($2 ~ /d/) # days > + nr *= 86400; > + else if ($2 ~ /w/) # weeks > + nr *= 604800; > + else { > + printf("%s: unknown suffix\n", $2); > + exit 1; > + } > + > + printf("%d\n", nr); > +} > diff --git a/tests/generic/476 b/tests/generic/476 > index edb0be7b50..a162cda6b1 100755 > --- a/tests/generic/476 > +++ b/tests/generic/476 > @@ -33,7 +33,10 @@ _scratch_mount >> $seqres.full 2>&1 > > nr_cpus=$((LOAD_FACTOR * 4)) > nr_ops=$((25000 * nr_cpus * TIME_FACTOR)) > -$FSSTRESS_PROG $FSSTRESS_AVOID -w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full > +fsstress_args=(-w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus) > +test -n "$SOAK_DURATION" && fsstress_args+=(--duration="$SOAK_DURATION") > + > +$FSSTRESS_PROG $FSSTRESS_AVOID "${fsstress_args[@]}" >> $seqres.full > > # success, all done > status=0 > diff --git a/tests/generic/521 b/tests/generic/521 > index cde9d44775..22dd31a8ec 100755 > --- a/tests/generic/521 > +++ b/tests/generic/521 > @@ -35,6 +35,7 @@ fsx_args+=(-r $min_dio_sz) > fsx_args+=(-t $min_dio_sz) > fsx_args+=(-w $min_dio_sz) > fsx_args+=(-Z) > +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") > > run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' > > diff --git a/tests/generic/522 b/tests/generic/522 > index ae84fe04bb..f0cbcb245c 100755 > --- a/tests/generic/522 > +++ b/tests/generic/522 > @@ -29,6 +29,7 @@ fsx_args+=(-N $nr_ops) > fsx_args+=(-p $((nr_ops / 100))) > fsx_args+=(-o $op_sz) > fsx_args+=(-l $file_sz) > +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") > > run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' > > diff --git a/tests/generic/642 b/tests/generic/642 > index c0e274d843..eba90903a3 100755 > --- a/tests/generic/642 > +++ b/tests/generic/642 > @@ -49,6 +49,7 @@ for verb in attr_remove removefattr; do > done > args+=('-f' "setfattr=20") > args+=('-f' "attr_set=60") # sets larger xattrs > +test -n "$DURATION" && args+=(--duration="$DURATION") > > $FSSTRESS_PROG "${args[@]}" $FSSTRESS_AVOID -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] misc: add duration for long soak tests 2023-04-22 13:33 ` Zorro Lang @ 2023-04-24 18:27 ` Darrick J. Wong 0 siblings, 0 replies; 16+ messages in thread From: Darrick J. Wong @ 2023-04-24 18:27 UTC (permalink / raw) To: Zorro Lang; +Cc: linux-xfs, fstests, guan On Sat, Apr 22, 2023 at 09:33:16PM +0800, Zorro Lang wrote: > On Fri, Apr 14, 2023 at 05:29:49PM -0700, Darrick J. Wong wrote: > > From: Darrick J. Wong <djwong@kernel.org> > > > > Make it so that test runners can schedule long soak stress test programs > > for an exact number of seconds by setting the SOAK_DURATION config > > variable. > > > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > > Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com> > > --- > > v2: fix commit message > > --- > > check | 14 +++++++++ > > common/config | 7 ++++ > > common/fuzzy | 7 ++++ > > common/report | 1 + > > ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- > > ltp/fsx.c | 50 +++++++++++++++++++++++++++++++ > > src/soak_duration.awk | 23 ++++++++++++++ > > tests/generic/476 | 5 +++ > > tests/generic/521 | 1 + > > tests/generic/522 | 1 + > > tests/generic/642 | 1 + > > 11 files changed, 182 insertions(+), 6 deletions(-) > > create mode 100644 src/soak_duration.awk > > > > diff --git a/check b/check > > index e32b70d301..1d78cf27f4 100755 > > --- a/check > > +++ b/check > > @@ -366,6 +366,20 @@ if ! . ./common/rc; then > > exit 1 > > fi > > > > +# If the test config specified a soak test duration, see if there are any > > +# unit suffixes that need converting to an integer seconds count. > > +if [ -n "$SOAK_DURATION" ]; then > > + SOAK_DURATION="$(echo "$SOAK_DURATION" | \ > > + sed -e 's/^\([.0-9]*\)\([a-z]\)*/\1 \2/g' | \ > > + $AWK_PROG -f $here/src/soak_duration.awk)" > > + if [ $? -ne 0 ]; then > > + echo "$SOAK_DURATION" > > echo SOAK_DURATION=$SOAK_DURATION ? Hmm. On nonzero return, the awk script already specified the reason that the input was rejected, so I think this line can go away. > > + status=1 > > + exit 1 > > + fi > > + export SOAK_DURATION > > Is this necessary? As you've exported SOAK_DURATION in common/config: > > export SOAK_DURATION=${SOAK_DURATION:=} You're correct, it does not need to be re-exported. > > +fi > > + > > if [ -n "$subdir_xfile" ]; then > > for d in $SRC_GROUPS $FSTYP; do > > [ -f $SRC_DIR/$d/$subdir_xfile ] || continue > > diff --git a/common/config b/common/config > > index 6c8cb3a5ba..fdd0aadbeb 100644 > > --- a/common/config > > +++ b/common/config > > @@ -57,6 +57,13 @@ export SOAK_PROC=3 # -p option to fsstress > > export SOAK_STRESS=10000 # -n option to fsstress > > export SOAK_PASSES=-1 # count of repetitions of fsstress (while soaking) > > export EMAIL=root@localhost # where auto-qa will send its status messages > > + > > +# For certain tests that run in tight loops, setting this variable allows the > > +# test runner to specify exactly how long the test should continue looping. > > +# This is independent of TIME_FACTOR. Floating point numbers are allowed, and > > +# the unit suffixes m(inutes), h(ours), d(ays), and w(eeks) are supported. > > +export SOAK_DURATION=${SOAK_DURATION:=} > > Better to describe more about the SOAK_DURATION (and TIME/LOAD_FACTOR) in > documentation (README?). To clarify the relationship of SOAK_DURATION with > other related parameters, and how the SOAK_DURATION works/be used. TIME_FACTOR is not documented in the README. I'll add another patch to do that... > > + > > export HOST_OPTIONS=${HOST_OPTIONS:=local.config} > > export CHECK_OPTIONS=${CHECK_OPTIONS:="-g auto"} > > export BENCH_PASSES=${BENCH_PASSES:=5} > > diff --git a/common/fuzzy b/common/fuzzy > > index 744d9ed65d..9c04bb5318 100644 > > --- a/common/fuzzy > > +++ b/common/fuzzy > > @@ -1360,7 +1360,12 @@ _scratch_xfs_stress_scrub() { > > fi > > > > local start="$(date +%s)" > > - local end="$((start + (30 * TIME_FACTOR) ))" > > + local end > > + if [ -n "$SOAK_DURATION" ]; then > > + end="$((start + SOAK_DURATION))" > > + else > > + end="$((start + (30 * TIME_FACTOR) ))" > > + fi > > local scrub_startat="$((start + scrub_delay))" > > test "$scrub_startat" -gt "$((end - 10))" && > > scrub_startat="$((end - 10))" > > diff --git a/common/report b/common/report > > index be930e0b06..9bfa09ecce 100644 > > --- a/common/report > > +++ b/common/report > > @@ -67,6 +67,7 @@ __generate_report_vars() { > > REPORT_VARS["CPUS"]="$(getconf _NPROCESSORS_ONLN 2>/dev/null)" > > REPORT_VARS["MEM_KB"]="$(grep MemTotal: /proc/meminfo | awk '{print $2}')" > > REPORT_VARS["SWAP_KB"]="$(grep SwapTotal: /proc/meminfo | awk '{print $2}')" > > + test -n "$SOAK_DURATION" && REPORT_VARS["SOAK_DURATION"]="$SOAK_DURATION" > > > > test -e /sys/devices/system/node/possible && \ > > REPORT_VARS["NUMA_NODES"]="$(cat /sys/devices/system/node/possible 2>/dev/null)" > > diff --git a/ltp/fsstress.c b/ltp/fsstress.c > > index e60f2da929..0dc6545448 100644 > > --- a/ltp/fsstress.c > > +++ b/ltp/fsstress.c > > @@ -386,6 +386,8 @@ char *execute_cmd = NULL; > > int execute_freq = 1; > > struct print_string flag_str = {0}; > > > > +struct timespec deadline = { 0 }; > > + > > void add_to_flist(int, int, int, int); > > void append_pathname(pathname_t *, char *); > > int attr_list_path(pathname_t *, char *, const int); > > @@ -459,6 +461,34 @@ void sg_handler(int signum) > > } > > } > > > > +bool > > +keep_looping(int i, int loops) > > +{ > > + int ret; > > + > > + if (deadline.tv_nsec) { > > + struct timespec now; > > + > > + ret = clock_gettime(CLOCK_MONOTONIC, &now); > > + if (ret) { > > + perror("CLOCK_MONOTONIC"); > > + return false; > > + } > > + > > + return now.tv_sec <= deadline.tv_sec; > > + } > > + > > + if (!loops) > > + return true; > > + > > + return i < loops; > > +} > > + > > +static struct option longopts[] = { > > + {"duration", optional_argument, 0, 256}, > > OK, we'd better to check those test cases use fsstress "-n" later, think about > if some of them should be replaced by "--duration". <nod> I'll update the fsstress/fsx --help screens to state that --duration overrides -n/-N. --D > Thanks, > Zorro > > > + { } > > +}; > > + > > int main(int argc, char **argv) > > { > > char buf[10]; > > @@ -478,13 +508,14 @@ int main(int argc, char **argv) > > struct sigaction action; > > int loops = 1; > > const char *allopts = "cd:e:f:i:l:m:M:n:o:p:rRs:S:vVwx:X:zH"; > > + long long duration; > > > > errrange = errtag = 0; > > umask(0); > > nops = sizeof(ops) / sizeof(ops[0]); > > ops_end = &ops[nops]; > > myprog = argv[0]; > > - while ((c = getopt(argc, argv, allopts)) != -1) { > > + while ((c = getopt_long(argc, argv, allopts, longopts, NULL)) != -1) { > > switch (c) { > > case 'c': > > cleanup = 1; > > @@ -579,6 +610,26 @@ int main(int argc, char **argv) > > case 'X': > > execute_freq = strtoul(optarg, NULL, 0); > > break; > > + case 256: /* --duration */ > > + if (!optarg) { > > + fprintf(stderr, "Specify time with --duration=\n"); > > + exit(87); > > + } > > + duration = strtoll(optarg, NULL, 0); > > + if (duration < 1) { > > + fprintf(stderr, "%lld: invalid duration\n", duration); > > + exit(88); > > + } > > + > > + i = clock_gettime(CLOCK_MONOTONIC, &deadline); > > + if (i) { > > + perror("CLOCK_MONOTONIC"); > > + exit(89); > > + } > > + > > + deadline.tv_sec += duration; > > + deadline.tv_nsec = 1; > > + break; > > case '?': > > fprintf(stderr, "%s - invalid parameters\n", > > myprog); > > @@ -721,7 +772,7 @@ int main(int argc, char **argv) > > } > > } > > #endif > > - for (i = 0; !loops || (i < loops); i++) > > + for (i = 0; keep_looping(i, loops); i++) > > doproc(); > > #ifdef AIO > > if(io_destroy(io_ctx) != 0) { > > @@ -1121,6 +1172,26 @@ dirid_to_fent(int dirid) > > return NULL; > > } > > > > +bool > > +keep_running(opnum_t opno, opnum_t operations) > > +{ > > + int ret; > > + > > + if (deadline.tv_nsec) { > > + struct timespec now; > > + > > + ret = clock_gettime(CLOCK_MONOTONIC, &now); > > + if (ret) { > > + perror("CLOCK_MONOTONIC"); > > + return false; > > + } > > + > > + return now.tv_sec <= deadline.tv_sec; > > + } > > + > > + return opno < operations; > > +} > > + > > void > > doproc(void) > > { > > @@ -1149,7 +1220,7 @@ doproc(void) > > srandom(seed); > > if (namerand) > > namerand = random(); > > - for (opno = 0; opno < operations; opno++) { > > + for (opno = 0; keep_running(opno, operations); opno++) { > > if (execute_cmd && opno && opno % dividend == 0) { > > if (verbose) > > printf("%lld: execute command %s\n", opno, > > @@ -1935,6 +2006,7 @@ usage(void) > > printf(" -V specifies verifiable logging mode (omitting inode numbers)\n"); > > printf(" -X ncmd number of calls to the -x command (default 1)\n"); > > printf(" -H prints usage and exits\n"); > > + printf(" --duration=s run for this many seconds\n"); > > } > > > > void > > diff --git a/ltp/fsx.c b/ltp/fsx.c > > index ee4b8fe45d..761d5e467f 100644 > > --- a/ltp/fsx.c > > +++ b/ltp/fsx.c > > @@ -193,6 +193,8 @@ int fsx_rw(int rw, int fd, char *buf, unsigned len, unsigned offset); > > #define fsxread(a,b,c,d) fsx_rw(READ, a,b,c,d) > > #define fsxwrite(a,b,c,d) fsx_rw(WRITE, a,b,c,d) > > > > +struct timespec deadline; > > + > > const char *replayops = NULL; > > const char *recordops = NULL; > > FILE * fsxlogf = NULL; > > @@ -2457,6 +2459,7 @@ usage(void) > > -Z: O_DIRECT (use -R, -W, -r and -w too)\n\ > > --replay-ops opsfile: replay ops from recorded .fsxops file\n\ > > --record-ops[=opsfile]: dump ops file also on success. optionally specify ops file name\n\ > > + --duration=seconds: run for this many seconds\n\ > > fname: this filename is REQUIRED (no default)\n"); > > exit(90); > > } > > @@ -2739,9 +2742,33 @@ __test_fallocate(int mode, const char *mode_str) > > #endif > > } > > > > +bool > > +keep_running(void) > > +{ > > + int ret; > > + > > + if (deadline.tv_nsec) { > > + struct timespec now; > > + > > + ret = clock_gettime(CLOCK_MONOTONIC, &now); > > + if (ret) { > > + perror("CLOCK_MONOTONIC"); > > + return false; > > + } > > + > > + return now.tv_sec <= deadline.tv_sec; > > + } > > + > > + if (numops == -1) > > + return true; > > + > > + return numops-- != 0; > > +} > > + > > static struct option longopts[] = { > > {"replay-ops", required_argument, 0, 256}, > > {"record-ops", optional_argument, 0, 255}, > > + {"duration", optional_argument, 0, 254}, > > { } > > }; > > > > @@ -2753,6 +2780,7 @@ main(int argc, char **argv) > > char logfile[PATH_MAX]; > > struct stat statbuf; > > int o_flags = O_RDWR|O_CREAT|O_TRUNC; > > + long long duration; > > > > logfile[0] = 0; > > dname[0] = 0; > > @@ -2950,6 +2978,26 @@ main(int argc, char **argv) > > o_direct = O_DIRECT; > > o_flags |= O_DIRECT; > > break; > > + case 254: /* --duration */ > > + if (!optarg) { > > + fprintf(stderr, "Specify time with --duration=\n"); > > + exit(87); > > + } > > + duration = strtoll(optarg, NULL, 0); > > + if (duration < 1) { > > + fprintf(stderr, "%lld: invalid duration\n", duration); > > + exit(88); > > + } > > + > > + i = clock_gettime(CLOCK_MONOTONIC, &deadline); > > + if (i) { > > + perror("CLOCK_MONOTONIC"); > > + exit(89); > > + } > > + > > + deadline.tv_sec += duration; > > + deadline.tv_nsec = 1; > > + break; > > case 255: /* --record-ops */ > > if (optarg) > > snprintf(opsfile, sizeof(opsfile), "%s", optarg); > > @@ -3145,7 +3193,7 @@ main(int argc, char **argv) > > if (xchg_range_calls) > > xchg_range_calls = test_xchg_range(); > > > > - while (numops == -1 || numops--) > > + while (keep_running()) > > if (!test()) > > break; > > > > diff --git a/src/soak_duration.awk b/src/soak_duration.awk > > new file mode 100644 > > index 0000000000..6c38d09b39 > > --- /dev/null > > +++ b/src/soak_duration.awk > > @@ -0,0 +1,23 @@ > > +#!/usr/bin/awk > > +# > > +# Convert time interval specifications with suffixes to an integer number of > > +# seconds. > > +{ > > + nr = $1; > > + if ($2 == "" || $2 ~ /s/) # seconds > > + ; > > + else if ($2 ~ /m/) # minutes > > + nr *= 60; > > + else if ($2 ~ /h/) # hours > > + nr *= 3600; > > + else if ($2 ~ /d/) # days > > + nr *= 86400; > > + else if ($2 ~ /w/) # weeks > > + nr *= 604800; > > + else { > > + printf("%s: unknown suffix\n", $2); > > + exit 1; > > + } > > + > > + printf("%d\n", nr); > > +} > > diff --git a/tests/generic/476 b/tests/generic/476 > > index edb0be7b50..a162cda6b1 100755 > > --- a/tests/generic/476 > > +++ b/tests/generic/476 > > @@ -33,7 +33,10 @@ _scratch_mount >> $seqres.full 2>&1 > > > > nr_cpus=$((LOAD_FACTOR * 4)) > > nr_ops=$((25000 * nr_cpus * TIME_FACTOR)) > > -$FSSTRESS_PROG $FSSTRESS_AVOID -w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full > > +fsstress_args=(-w -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus) > > +test -n "$SOAK_DURATION" && fsstress_args+=(--duration="$SOAK_DURATION") > > + > > +$FSSTRESS_PROG $FSSTRESS_AVOID "${fsstress_args[@]}" >> $seqres.full > > > > # success, all done > > status=0 > > diff --git a/tests/generic/521 b/tests/generic/521 > > index cde9d44775..22dd31a8ec 100755 > > --- a/tests/generic/521 > > +++ b/tests/generic/521 > > @@ -35,6 +35,7 @@ fsx_args+=(-r $min_dio_sz) > > fsx_args+=(-t $min_dio_sz) > > fsx_args+=(-w $min_dio_sz) > > fsx_args+=(-Z) > > +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") > > > > run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' > > > > diff --git a/tests/generic/522 b/tests/generic/522 > > index ae84fe04bb..f0cbcb245c 100755 > > --- a/tests/generic/522 > > +++ b/tests/generic/522 > > @@ -29,6 +29,7 @@ fsx_args+=(-N $nr_ops) > > fsx_args+=(-p $((nr_ops / 100))) > > fsx_args+=(-o $op_sz) > > fsx_args+=(-l $file_sz) > > +test -n "$SOAK_DURATION" && fsx_args+=(--duration="$SOAK_DURATION") > > > > run_fsx "${fsx_args[@]}" | sed -e '/^fsx.*/d' > > > > diff --git a/tests/generic/642 b/tests/generic/642 > > index c0e274d843..eba90903a3 100755 > > --- a/tests/generic/642 > > +++ b/tests/generic/642 > > @@ -49,6 +49,7 @@ for verb in attr_remove removefattr; do > > done > > args+=('-f' "setfattr=20") > > args+=('-f' "attr_set=60") # sets larger xattrs > > +test -n "$DURATION" && args+=(--duration="$DURATION") > > > > $FSSTRESS_PROG "${args[@]}" $FSSTRESS_AVOID -d $SCRATCH_MNT -n $nr_ops -p $nr_cpus >> $seqres.full > > > > > ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 3/3] misc: add duration for recovery loop tests 2023-04-11 18:13 [PATCHSET 0/3] fstests: direct specification of looping test duration Darrick J. Wong 2023-04-11 18:13 ` [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test Darrick J. Wong 2023-04-11 18:13 ` [PATCH 2/3] misc: add duration for long soak tests Darrick J. Wong @ 2023-04-11 18:14 ` Darrick J. Wong 2023-04-23 15:09 ` Zorro Lang 2023-04-13 10:48 ` [PATCHSET 0/3] fstests: direct specification of looping test duration Andrey Albershteyn 3 siblings, 1 reply; 16+ messages in thread From: Darrick J. Wong @ 2023-04-11 18:14 UTC (permalink / raw) To: djwong, zlang; +Cc: linux-xfs, fstests, guan From: Darrick J. Wong <djwong@kernel.org> Make it so that we can run recovery loop tests for an exact number of seconds. Signed-off-by: Darrick J. Wong <djwong@kernel.org> --- common/rc | 34 ++++++++++++++++++++++++++++++++++ tests/generic/019 | 1 + tests/generic/388 | 2 +- tests/generic/475 | 2 +- tests/generic/482 | 5 +++++ tests/generic/648 | 8 ++++---- 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/common/rc b/common/rc index e89b0a3794..090f3d4938 100644 --- a/common/rc +++ b/common/rc @@ -5078,6 +5078,40 @@ _save_coredump() $COREDUMP_COMPRESSOR -f "$out_file" } +# Decide if a soak test should continue looping. The sole parameter is the +# number of soak loops that the test wants to run by default. The actual +# loop iteration number is stored in SOAK_LOOPIDX until the loop completes. +# +# If the test runner set a SOAK_DURATION value, this predicate will keep +# looping until it has run for at least that long. +_soak_loop_running() { + local max_soak_loops="$1" + + test -z "$SOAK_LOOPIDX" && SOAK_LOOPIDX=1 + + if [ -n "$SOAK_DURATION" ]; then + if [ -z "$SOAK_DEADLINE" ]; then + SOAK_DEADLINE="$(( $(date +%s) + SOAK_DURATION))" + fi + + local now="$(date +%s)" + if [ "$now" -gt "$SOAK_DEADLINE" ]; then + unset SOAK_DEADLINE + unset SOAK_LOOPIDX + return 1 + fi + SOAK_LOOPIDX=$((SOAK_LOOPIDX + 1)) + return 0 + fi + + if [ "$SOAK_LOOPIDX" -gt "$max_soak_loops" ]; then + unset SOAK_LOOPIDX + return 1 + fi + SOAK_LOOPIDX=$((SOAK_LOOPIDX + 1)) + return 0 +} + init_rc ################################################################################ diff --git a/tests/generic/019 b/tests/generic/019 index b68dd90c0d..b81c1d17ba 100755 --- a/tests/generic/019 +++ b/tests/generic/019 @@ -30,6 +30,7 @@ _cleanup() } RUN_TIME=$((20+10*$TIME_FACTOR)) +test -n "$SOAK_DURATION" && RUN_TIME="$SOAK_DURATION" NUM_JOBS=$((4*LOAD_FACTOR)) BLK_DEV_SIZE=`blockdev --getsz $SCRATCH_DEV` FILE_SIZE=$((BLK_DEV_SIZE * 512)) diff --git a/tests/generic/388 b/tests/generic/388 index 9cd737e8eb..4a5be6698c 100755 --- a/tests/generic/388 +++ b/tests/generic/388 @@ -42,7 +42,7 @@ _scratch_mkfs >> $seqres.full 2>&1 _require_metadata_journaling $SCRATCH_DEV _scratch_mount -for i in $(seq 1 $((50 * TIME_FACTOR)) ); do +while _soak_loop_running $((50 * TIME_FACTOR)); do ($FSSTRESS_PROG $FSSTRESS_AVOID -d $SCRATCH_MNT -n 999999 -p 4 >> $seqres.full &) \ > /dev/null 2>&1 diff --git a/tests/generic/475 b/tests/generic/475 index c426402ede..0cbf5131c2 100755 --- a/tests/generic/475 +++ b/tests/generic/475 @@ -41,7 +41,7 @@ _require_metadata_journaling $SCRATCH_DEV _dmerror_init _dmerror_mount -for i in $(seq 1 $((50 * TIME_FACTOR)) ); do +while _soak_loop_running $((50 * TIME_FACTOR)); do ($FSSTRESS_PROG $FSSTRESS_AVOID -d $SCRATCH_MNT -n 999999 -p $((LOAD_FACTOR * 4)) >> $seqres.full &) \ > /dev/null 2>&1 diff --git a/tests/generic/482 b/tests/generic/482 index 28c83a232e..b980826b14 100755 --- a/tests/generic/482 +++ b/tests/generic/482 @@ -62,8 +62,13 @@ nr_cpus=$("$here/src/feature" -o) if [ $nr_cpus -gt 8 ]; then nr_cpus=8 fi + fsstress_args=$(_scale_fsstress_args -w -d $SCRATCH_MNT -n 512 -p $nr_cpus \ $FSSTRESS_AVOID) + +# XXX dm-logwrites pins kernel memory for every write! +# test -n "$SOAK_DURATION" && fsstress_args="$fsstress_args --duration=$SOAK_DURATION" + devsize=$((1024*1024*200 / 512)) # 200m phys/virt size csize=$((1024*64 / 512)) # 64k cluster size lowspace=$((1024*1024 / 512)) # 1m low space threshold diff --git a/tests/generic/648 b/tests/generic/648 index d7bf5697e1..3b3544ff49 100755 --- a/tests/generic/648 +++ b/tests/generic/648 @@ -74,14 +74,14 @@ snap_loop_fs() { fsstress=($FSSTRESS_PROG $FSSTRESS_AVOID -d "$loopmnt" -n 999999 -p "$((LOAD_FACTOR * 4))") -for i in $(seq 1 $((25 * TIME_FACTOR)) ); do +while _soak_loop_running $((25 * TIME_FACTOR)); do touch $scratch_aliveflag snap_loop_fs >> $seqres.full 2>&1 & if ! _mount $loopimg $loopmnt -o loop; then rm -f $scratch_aliveflag _metadump_dev $loopimg $seqres.loop.$i.md - _fail "iteration $i loopimg mount failed" + _fail "iteration $SOAK_LOOPIDX loopimg mount failed" break fi @@ -126,12 +126,12 @@ for i in $(seq 1 $((25 * TIME_FACTOR)) ); do done if [ $is_unmounted -ne 0 ];then cat $tmp.unmount.err - _fail "iteration $i scratch unmount failed" + _fail "iteration $SOAK_LOOPIDX scratch unmount failed" fi _dmerror_load_working_table if ! _dmerror_mount; then _metadump_dev $DMERROR_DEV $seqres.scratch.$i.md - _fail "iteration $i scratch mount failed" + _fail "iteration $SOAK_LOOPIDX scratch mount failed" fi done ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 3/3] misc: add duration for recovery loop tests 2023-04-11 18:14 ` [PATCH 3/3] misc: add duration for recovery loop tests Darrick J. Wong @ 2023-04-23 15:09 ` Zorro Lang 2023-04-24 17:57 ` Darrick J. Wong 0 siblings, 1 reply; 16+ messages in thread From: Zorro Lang @ 2023-04-23 15:09 UTC (permalink / raw) To: Darrick J. Wong; +Cc: linux-xfs, fstests On Tue, Apr 11, 2023 at 11:14:03AM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <djwong@kernel.org> > > Make it so that we can run recovery loop tests for an exact number of > seconds. > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > --- > common/rc | 34 ++++++++++++++++++++++++++++++++++ > tests/generic/019 | 1 + > tests/generic/388 | 2 +- > tests/generic/475 | 2 +- > tests/generic/482 | 5 +++++ > tests/generic/648 | 8 ++++---- > 6 files changed, 46 insertions(+), 6 deletions(-) > > > diff --git a/common/rc b/common/rc > index e89b0a3794..090f3d4938 100644 > --- a/common/rc > +++ b/common/rc > @@ -5078,6 +5078,40 @@ _save_coredump() > $COREDUMP_COMPRESSOR -f "$out_file" > } > > +# Decide if a soak test should continue looping. The sole parameter is the > +# number of soak loops that the test wants to run by default. The actual > +# loop iteration number is stored in SOAK_LOOPIDX until the loop completes. > +# > +# If the test runner set a SOAK_DURATION value, this predicate will keep > +# looping until it has run for at least that long. > +_soak_loop_running() { > + local max_soak_loops="$1" > + > + test -z "$SOAK_LOOPIDX" && SOAK_LOOPIDX=1 > + > + if [ -n "$SOAK_DURATION" ]; then > + if [ -z "$SOAK_DEADLINE" ]; then > + SOAK_DEADLINE="$(( $(date +%s) + SOAK_DURATION))" > + fi > + > + local now="$(date +%s)" > + if [ "$now" -gt "$SOAK_DEADLINE" ]; then > + unset SOAK_DEADLINE > + unset SOAK_LOOPIDX > + return 1 > + fi > + SOAK_LOOPIDX=$((SOAK_LOOPIDX + 1)) > + return 0 > + fi > + > + if [ "$SOAK_LOOPIDX" -gt "$max_soak_loops" ]; then > + unset SOAK_LOOPIDX > + return 1 > + fi > + SOAK_LOOPIDX=$((SOAK_LOOPIDX + 1)) > + return 0 > +} > + > init_rc > > ################################################################################ > diff --git a/tests/generic/019 b/tests/generic/019 > index b68dd90c0d..b81c1d17ba 100755 > --- a/tests/generic/019 > +++ b/tests/generic/019 > @@ -30,6 +30,7 @@ _cleanup() > } > > RUN_TIME=$((20+10*$TIME_FACTOR)) > +test -n "$SOAK_DURATION" && RUN_TIME="$SOAK_DURATION" > NUM_JOBS=$((4*LOAD_FACTOR)) > BLK_DEV_SIZE=`blockdev --getsz $SCRATCH_DEV` > FILE_SIZE=$((BLK_DEV_SIZE * 512)) > diff --git a/tests/generic/388 b/tests/generic/388 > index 9cd737e8eb..4a5be6698c 100755 > --- a/tests/generic/388 > +++ b/tests/generic/388 > @@ -42,7 +42,7 @@ _scratch_mkfs >> $seqres.full 2>&1 > _require_metadata_journaling $SCRATCH_DEV > _scratch_mount > > -for i in $(seq 1 $((50 * TIME_FACTOR)) ); do > +while _soak_loop_running $((50 * TIME_FACTOR)); do > ($FSSTRESS_PROG $FSSTRESS_AVOID -d $SCRATCH_MNT -n 999999 -p 4 >> $seqres.full &) \ > > /dev/null 2>&1 > > diff --git a/tests/generic/475 b/tests/generic/475 > index c426402ede..0cbf5131c2 100755 > --- a/tests/generic/475 > +++ b/tests/generic/475 > @@ -41,7 +41,7 @@ _require_metadata_journaling $SCRATCH_DEV > _dmerror_init > _dmerror_mount > > -for i in $(seq 1 $((50 * TIME_FACTOR)) ); do > +while _soak_loop_running $((50 * TIME_FACTOR)); do > ($FSSTRESS_PROG $FSSTRESS_AVOID -d $SCRATCH_MNT -n 999999 -p $((LOAD_FACTOR * 4)) >> $seqres.full &) \ > > /dev/null 2>&1 > > diff --git a/tests/generic/482 b/tests/generic/482 > index 28c83a232e..b980826b14 100755 > --- a/tests/generic/482 > +++ b/tests/generic/482 > @@ -62,8 +62,13 @@ nr_cpus=$("$here/src/feature" -o) > if [ $nr_cpus -gt 8 ]; then > nr_cpus=8 > fi > + > fsstress_args=$(_scale_fsstress_args -w -d $SCRATCH_MNT -n 512 -p $nr_cpus \ > $FSSTRESS_AVOID) > + > +# XXX dm-logwrites pins kernel memory for every write! > +# test -n "$SOAK_DURATION" && fsstress_args="$fsstress_args --duration=$SOAK_DURATION" Do you expect the second comment is a comment? Others looks good to me. I'll test V2 and merge it if no regression from it. Thanks, Zorro ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/3] misc: add duration for recovery loop tests 2023-04-23 15:09 ` Zorro Lang @ 2023-04-24 17:57 ` Darrick J. Wong 0 siblings, 0 replies; 16+ messages in thread From: Darrick J. Wong @ 2023-04-24 17:57 UTC (permalink / raw) To: Zorro Lang; +Cc: linux-xfs, fstests On Sun, Apr 23, 2023 at 11:09:59PM +0800, Zorro Lang wrote: > On Tue, Apr 11, 2023 at 11:14:03AM -0700, Darrick J. Wong wrote: > > From: Darrick J. Wong <djwong@kernel.org> > > > > Make it so that we can run recovery loop tests for an exact number of > > seconds. > > > > Signed-off-by: Darrick J. Wong <djwong@kernel.org> > > --- > > common/rc | 34 ++++++++++++++++++++++++++++++++++ > > tests/generic/019 | 1 + > > tests/generic/388 | 2 +- > > tests/generic/475 | 2 +- > > tests/generic/482 | 5 +++++ > > tests/generic/648 | 8 ++++---- > > 6 files changed, 46 insertions(+), 6 deletions(-) > > > > > > diff --git a/common/rc b/common/rc > > index e89b0a3794..090f3d4938 100644 > > --- a/common/rc > > +++ b/common/rc > > @@ -5078,6 +5078,40 @@ _save_coredump() > > $COREDUMP_COMPRESSOR -f "$out_file" > > } > > > > +# Decide if a soak test should continue looping. The sole parameter is the > > +# number of soak loops that the test wants to run by default. The actual > > +# loop iteration number is stored in SOAK_LOOPIDX until the loop completes. > > +# > > +# If the test runner set a SOAK_DURATION value, this predicate will keep > > +# looping until it has run for at least that long. > > +_soak_loop_running() { > > + local max_soak_loops="$1" > > + > > + test -z "$SOAK_LOOPIDX" && SOAK_LOOPIDX=1 > > + > > + if [ -n "$SOAK_DURATION" ]; then > > + if [ -z "$SOAK_DEADLINE" ]; then > > + SOAK_DEADLINE="$(( $(date +%s) + SOAK_DURATION))" > > + fi > > + > > + local now="$(date +%s)" > > + if [ "$now" -gt "$SOAK_DEADLINE" ]; then > > + unset SOAK_DEADLINE > > + unset SOAK_LOOPIDX > > + return 1 > > + fi > > + SOAK_LOOPIDX=$((SOAK_LOOPIDX + 1)) > > + return 0 > > + fi > > + > > + if [ "$SOAK_LOOPIDX" -gt "$max_soak_loops" ]; then > > + unset SOAK_LOOPIDX > > + return 1 > > + fi > > + SOAK_LOOPIDX=$((SOAK_LOOPIDX + 1)) > > + return 0 > > +} > > + > > init_rc > > > > ################################################################################ > > diff --git a/tests/generic/019 b/tests/generic/019 > > index b68dd90c0d..b81c1d17ba 100755 > > --- a/tests/generic/019 > > +++ b/tests/generic/019 > > @@ -30,6 +30,7 @@ _cleanup() > > } > > > > RUN_TIME=$((20+10*$TIME_FACTOR)) > > +test -n "$SOAK_DURATION" && RUN_TIME="$SOAK_DURATION" > > NUM_JOBS=$((4*LOAD_FACTOR)) > > BLK_DEV_SIZE=`blockdev --getsz $SCRATCH_DEV` > > FILE_SIZE=$((BLK_DEV_SIZE * 512)) > > diff --git a/tests/generic/388 b/tests/generic/388 > > index 9cd737e8eb..4a5be6698c 100755 > > --- a/tests/generic/388 > > +++ b/tests/generic/388 > > @@ -42,7 +42,7 @@ _scratch_mkfs >> $seqres.full 2>&1 > > _require_metadata_journaling $SCRATCH_DEV > > _scratch_mount > > > > -for i in $(seq 1 $((50 * TIME_FACTOR)) ); do > > +while _soak_loop_running $((50 * TIME_FACTOR)); do > > ($FSSTRESS_PROG $FSSTRESS_AVOID -d $SCRATCH_MNT -n 999999 -p 4 >> $seqres.full &) \ > > > /dev/null 2>&1 > > > > diff --git a/tests/generic/475 b/tests/generic/475 > > index c426402ede..0cbf5131c2 100755 > > --- a/tests/generic/475 > > +++ b/tests/generic/475 > > @@ -41,7 +41,7 @@ _require_metadata_journaling $SCRATCH_DEV > > _dmerror_init > > _dmerror_mount > > > > -for i in $(seq 1 $((50 * TIME_FACTOR)) ); do > > +while _soak_loop_running $((50 * TIME_FACTOR)); do > > ($FSSTRESS_PROG $FSSTRESS_AVOID -d $SCRATCH_MNT -n 999999 -p $((LOAD_FACTOR * 4)) >> $seqres.full &) \ > > > /dev/null 2>&1 > > > > diff --git a/tests/generic/482 b/tests/generic/482 > > index 28c83a232e..b980826b14 100755 > > --- a/tests/generic/482 > > +++ b/tests/generic/482 > > @@ -62,8 +62,13 @@ nr_cpus=$("$here/src/feature" -o) > > if [ $nr_cpus -gt 8 ]; then > > nr_cpus=8 > > fi > > + > > fsstress_args=$(_scale_fsstress_args -w -d $SCRATCH_MNT -n 512 -p $nr_cpus \ > > $FSSTRESS_AVOID) > > + > > +# XXX dm-logwrites pins kernel memory for every write! > > +# test -n "$SOAK_DURATION" && fsstress_args="$fsstress_args --duration=$SOAK_DURATION" > > Do you expect the second comment is a comment? Actually... I'd like to withdraw this chunk so that people aren't tempted to uncomment it. I had previously wanted generic/482 to be a SOAK_DURATION controllable test, but all that does is increase kernel memory usage until the VM OOMs, and it OOMs pretty quickly if you don't provision it with the same amount of RAM as the fs is writing to disk. I'll repost this without the changes to g/482. --D > Others looks good to me. I'll test V2 and merge it if no regression from it. > > Thanks, > Zorro > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCHSET 0/3] fstests: direct specification of looping test duration 2023-04-11 18:13 [PATCHSET 0/3] fstests: direct specification of looping test duration Darrick J. Wong ` (2 preceding siblings ...) 2023-04-11 18:14 ` [PATCH 3/3] misc: add duration for recovery loop tests Darrick J. Wong @ 2023-04-13 10:48 ` Andrey Albershteyn 2023-04-13 14:47 ` Darrick J. Wong 3 siblings, 1 reply; 16+ messages in thread From: Andrey Albershteyn @ 2023-04-13 10:48 UTC (permalink / raw) To: Darrick J. Wong; +Cc: zlang, linux-xfs, fstests, guan On Tue, Apr 11, 2023 at 11:13:46AM -0700, Darrick J. Wong wrote: > Hi all, > > One of the things that I do as a maintainer is to designate a handful of > VMs to run fstests for unusually long periods of time. This practice I > call long term soak testing. There are actually three separate fleets > for this -- one runs alongside the nightly builds, one runs alongside > weekly rebases, and the last one runs stable releases. > > My interactions with all three fleets is pretty much the same -- load > current builds of software, and try to run the exerciser tests for a > duration of time -- 12 hours, 6.5 days, 30 days, etc. TIME_FACTOR does > not work well for this usage model, because it is difficult to guess > the correct time factor given that the VMs are hetergeneous and the IO > completion rate is not perfectly predictable. > > Worse yet, if you want to run (say) all the recoveryloop tests on one VM > (because recoveryloop is prone to crashing), it's impossible to set a > TIME_FACTOR so that each loop test gets equal runtime. That can be > hacked around with config sections, but that doesn't solve the first > problem. > > This series introduces a new configuration variable, SOAK_DURATION, that > allows test runners to control directly various long soak and looping > recovery tests. This is intended to be an alternative to TIME_FACTOR, > since that variable usually adjusts operation counts, which are > proportional to runtime but otherwise not a direct measure of time. > > With this override in place, I can configure the long soak fleet to run > for exactly as long as I want them to, and they actually hit the time > budget targets. The recoveryloop fleet now divides looping-test time > equally among the four that are in that group so that they all get ~3 > hours of coverage every night. > > There are more tests that could use this than I actually modified here, > but I've done enough to show this off as a proof of concept. > > If you're going to start using this mess, you probably ought to just > pull from my git trees, which are linked below. > > This is an extraordinary way to destroy everything. Enjoy! > Comments and questions are, as always, welcome. > > --D > > fstests git tree: > https://git.kernel.org/cgit/linux/kernel/git/djwong/xfstests-dev.git/log/?h=soak-duration > --- > check | 14 +++++++++ > common/config | 7 ++++ > common/fuzzy | 7 ++++ > common/rc | 34 +++++++++++++++++++++ > common/report | 1 + > ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- > ltp/fsx.c | 50 +++++++++++++++++++++++++++++++ > src/soak_duration.awk | 23 ++++++++++++++ > tests/generic/019 | 1 + > tests/generic/388 | 2 + > tests/generic/475 | 2 + > tests/generic/476 | 7 +++- > tests/generic/482 | 5 +++ > tests/generic/521 | 1 + > tests/generic/522 | 1 + > tests/generic/642 | 1 + > tests/generic/648 | 8 +++-- > 17 files changed, 229 insertions(+), 13 deletions(-) > create mode 100644 src/soak_duration.awk > The set looks good to me (the second commit has different var name, but fine by me) Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com> -- - Andrey ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCHSET 0/3] fstests: direct specification of looping test duration 2023-04-13 10:48 ` [PATCHSET 0/3] fstests: direct specification of looping test duration Andrey Albershteyn @ 2023-04-13 14:47 ` Darrick J. Wong 2023-04-13 15:43 ` Andrey Albershteyn 0 siblings, 1 reply; 16+ messages in thread From: Darrick J. Wong @ 2023-04-13 14:47 UTC (permalink / raw) To: Andrey Albershteyn; +Cc: zlang, linux-xfs, fstests, guan On Thu, Apr 13, 2023 at 12:48:36PM +0200, Andrey Albershteyn wrote: > On Tue, Apr 11, 2023 at 11:13:46AM -0700, Darrick J. Wong wrote: > > Hi all, > > > > One of the things that I do as a maintainer is to designate a handful of > > VMs to run fstests for unusually long periods of time. This practice I > > call long term soak testing. There are actually three separate fleets > > for this -- one runs alongside the nightly builds, one runs alongside > > weekly rebases, and the last one runs stable releases. > > > > My interactions with all three fleets is pretty much the same -- load > > current builds of software, and try to run the exerciser tests for a > > duration of time -- 12 hours, 6.5 days, 30 days, etc. TIME_FACTOR does > > not work well for this usage model, because it is difficult to guess > > the correct time factor given that the VMs are hetergeneous and the IO > > completion rate is not perfectly predictable. > > > > Worse yet, if you want to run (say) all the recoveryloop tests on one VM > > (because recoveryloop is prone to crashing), it's impossible to set a > > TIME_FACTOR so that each loop test gets equal runtime. That can be > > hacked around with config sections, but that doesn't solve the first > > problem. > > > > This series introduces a new configuration variable, SOAK_DURATION, that > > allows test runners to control directly various long soak and looping > > recovery tests. This is intended to be an alternative to TIME_FACTOR, > > since that variable usually adjusts operation counts, which are > > proportional to runtime but otherwise not a direct measure of time. > > > > With this override in place, I can configure the long soak fleet to run > > for exactly as long as I want them to, and they actually hit the time > > budget targets. The recoveryloop fleet now divides looping-test time > > equally among the four that are in that group so that they all get ~3 > > hours of coverage every night. > > > > There are more tests that could use this than I actually modified here, > > but I've done enough to show this off as a proof of concept. > > > > If you're going to start using this mess, you probably ought to just > > pull from my git trees, which are linked below. > > > > This is an extraordinary way to destroy everything. Enjoy! > > Comments and questions are, as always, welcome. > > > > --D > > > > fstests git tree: > > https://git.kernel.org/cgit/linux/kernel/git/djwong/xfstests-dev.git/log/?h=soak-duration > > --- > > check | 14 +++++++++ > > common/config | 7 ++++ > > common/fuzzy | 7 ++++ > > common/rc | 34 +++++++++++++++++++++ > > common/report | 1 + > > ltp/fsstress.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- > > ltp/fsx.c | 50 +++++++++++++++++++++++++++++++ > > src/soak_duration.awk | 23 ++++++++++++++ > > tests/generic/019 | 1 + > > tests/generic/388 | 2 + > > tests/generic/475 | 2 + > > tests/generic/476 | 7 +++- > > tests/generic/482 | 5 +++ > > tests/generic/521 | 1 + > > tests/generic/522 | 1 + > > tests/generic/642 | 1 + > > tests/generic/648 | 8 +++-- > > 17 files changed, 229 insertions(+), 13 deletions(-) > > create mode 100644 src/soak_duration.awk > > > > The set looks good to me (the second commit has different var name, > but fine by me) Which variable name, specifically? --D > Reviewed-by: Andrey Albershteyn <aalbersh@redhat.com> > > -- > - Andrey > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCHSET 0/3] fstests: direct specification of looping test duration 2023-04-13 14:47 ` Darrick J. Wong @ 2023-04-13 15:43 ` Andrey Albershteyn 2023-04-15 0:28 ` Darrick J. Wong 0 siblings, 1 reply; 16+ messages in thread From: Andrey Albershteyn @ 2023-04-13 15:43 UTC (permalink / raw) To: Darrick J. Wong; +Cc: zlang, linux-xfs, fstests, guan On Thu, Apr 13, 2023 at 07:47:08AM -0700, Darrick J. Wong wrote: > On Thu, Apr 13, 2023 at 12:48:36PM +0200, Andrey Albershteyn wrote: > > > tests/generic/648 | 8 +++-- > > > 17 files changed, 229 insertions(+), 13 deletions(-) > > > create mode 100644 src/soak_duration.awk > > > > > > > The set looks good to me (the second commit has different var name, > > but fine by me) > > Which variable name, specifically? STRESS_DURATION in the commit message -- - Andrey ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCHSET 0/3] fstests: direct specification of looping test duration 2023-04-13 15:43 ` Andrey Albershteyn @ 2023-04-15 0:28 ` Darrick J. Wong 0 siblings, 0 replies; 16+ messages in thread From: Darrick J. Wong @ 2023-04-15 0:28 UTC (permalink / raw) To: Andrey Albershteyn; +Cc: zlang, linux-xfs, fstests, guan On Thu, Apr 13, 2023 at 05:43:52PM +0200, Andrey Albershteyn wrote: > On Thu, Apr 13, 2023 at 07:47:08AM -0700, Darrick J. Wong wrote: > > On Thu, Apr 13, 2023 at 12:48:36PM +0200, Andrey Albershteyn wrote: > > > > tests/generic/648 | 8 +++-- > > > > 17 files changed, 229 insertions(+), 13 deletions(-) > > > > create mode 100644 src/soak_duration.awk > > > > > > > > > > The set looks good to me (the second commit has different var name, > > > but fine by me) > > > > Which variable name, specifically? > > STRESS_DURATION in the commit message Ah, will fix and resend. Thanks for noticing! --D > -- > - Andrey > ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2023-04-25 4:51 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-04-11 18:13 [PATCHSET 0/3] fstests: direct specification of looping test duration Darrick J. Wong 2023-04-11 18:13 ` [PATCH 1/3] generic/476: reclassify this test as a long running soak stress test Darrick J. Wong 2023-04-22 8:24 ` Zorro Lang 2023-04-24 18:17 ` Darrick J. Wong 2023-04-25 4:50 ` Zorro Lang 2023-04-11 18:13 ` [PATCH 2/3] misc: add duration for long soak tests Darrick J. Wong 2023-04-15 0:29 ` [PATCH v2 " Darrick J. Wong 2023-04-22 13:33 ` Zorro Lang 2023-04-24 18:27 ` Darrick J. Wong 2023-04-11 18:14 ` [PATCH 3/3] misc: add duration for recovery loop tests Darrick J. Wong 2023-04-23 15:09 ` Zorro Lang 2023-04-24 17:57 ` Darrick J. Wong 2023-04-13 10:48 ` [PATCHSET 0/3] fstests: direct specification of looping test duration Andrey Albershteyn 2023-04-13 14:47 ` Darrick J. Wong 2023-04-13 15:43 ` Andrey Albershteyn 2023-04-15 0:28 ` Darrick J. Wong
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox