refscale: Ditch ref_scale_shutdown in favor of torture_shutdown_init()

The torture_shutdown_init() function spawns a shutdown kthread in
a manner very similar to that implemented by ref_scale_shutdown().
This commit therefore re-implements ref_scale_shutdown in terms of
torture_shutdown_init().

The initial draft of this patch was generated by version 2.1.16 of the
Claude AI/LLM, but trained and configured for use by my employer, and
prompted to refer to Linux-kernel source code.  This initial draft failed
to provide a forward reference to ref_scale_cleanup(), passed zero to
torture_shutdown_init() for an unwelcome insta-shutdown, and failed to
pass the kvm.sh --duration argument in as a refscale module parameter.
On the other hand, it did catch the need to NULL main_task on the
post-test self-shutdown code path, which I might well have forgotten
to do.

This version of the patch fixes those problems, and in fact very little
of the initial draft remains.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
This commit is contained in:
Paul E. McKenney 2026-02-05 13:43:32 -08:00 committed by Joel Fernandes
parent df6e6ae18f
commit b0c8dd5097
2 changed files with 15 additions and 38 deletions

View File

@ -92,15 +92,9 @@ torture_param(int, nreaders, -1, "Number of readers, -1 for 75% of CPUs.");
torture_param(int, nruns, 30, "Number of experiments to run.");
// Reader delay in nanoseconds, 0 for no delay.
torture_param(int, readdelay, 0, "Read-side delay in nanoseconds.");
#ifdef MODULE
# define REFSCALE_SHUTDOWN 0
#else
# define REFSCALE_SHUTDOWN 1
#endif
torture_param(bool, shutdown, REFSCALE_SHUTDOWN,
"Shutdown at end of scalability tests.");
// Maximum shutdown delay in seconds, or zero for no shutdown.
torture_param(int, shutdown_secs, !IS_MODULE(CONFIG_REPRO_TEST) * 300,
"Shutdown at end of scalability tests or at specified timeout (s).");
struct reader_task {
struct task_struct *task;
@ -109,12 +103,8 @@ struct reader_task {
u64 last_duration_ns;
};
static struct task_struct *shutdown_task;
static wait_queue_head_t shutdown_wq;
static struct task_struct *main_task;
static wait_queue_head_t main_wq;
static int shutdown_start;
static struct reader_task *reader_tasks;
@ -1357,6 +1347,8 @@ static u64 process_durations(int n)
return sum;
}
static void ref_scale_cleanup(void);
// The main_func is the main orchestrator, it performs a bunch of
// experiments. For every experiment, it orders all the readers
// involved to start and waits for them to finish the experiment. It
@ -1443,9 +1435,10 @@ static int main_func(void *arg)
oom_exit:
// This will shutdown everything including us.
if (shutdown) {
shutdown_start = 1;
wake_up(&shutdown_wq);
if (shutdown_secs) {
main_task = NULL; // Avoid self-kill deadlock.
ref_scale_cleanup();
kernel_power_off();
}
// Wait for torture to stop us
@ -1463,8 +1456,8 @@ static void
ref_scale_print_module_parms(const struct ref_scale_ops *cur_ops, const char *tag)
{
pr_alert("%s" SCALE_FLAG
"--- %s: verbose=%d verbose_batched=%d shutdown=%d holdoff=%d lookup_instances=%ld loops=%d nreaders=%d nruns=%d readdelay=%d\n", scale_type, tag,
verbose, verbose_batched, shutdown, holdoff, lookup_instances, loops, nreaders, nruns, readdelay);
"--- %s: verbose=%d verbose_batched=%d shutdown_secs=%d holdoff=%d lookup_instances=%ld loops=%d nreaders=%d nruns=%d readdelay=%d\n", scale_type, tag,
verbose, verbose_batched, shutdown_secs, holdoff, lookup_instances, loops, nreaders, nruns, readdelay);
}
static void
@ -1497,19 +1490,6 @@ ref_scale_cleanup(void)
torture_cleanup_end();
}
// Shutdown kthread. Just waits to be awakened, then shuts down system.
static int
ref_scale_shutdown(void *arg)
{
wait_event_idle(shutdown_wq, shutdown_start);
smp_mb(); // Wake before output.
ref_scale_cleanup();
kernel_power_off();
return -EINVAL;
}
static int __init
ref_scale_init(void)
{
@ -1553,13 +1533,10 @@ ref_scale_init(void)
ref_scale_print_module_parms(cur_ops, "Start of test");
// Shutdown task
if (shutdown) {
init_waitqueue_head(&shutdown_wq);
firsterr = torture_create_kthread(ref_scale_shutdown, NULL,
shutdown_task);
if (shutdown_secs) {
firsterr = torture_shutdown_init(shutdown_secs, ref_scale_cleanup);
if (torture_init_error(firsterr))
goto unwind;
schedule_timeout_uninterruptible(1);
}
// Reader tasks (default to ~75% of online CPUs).
@ -1604,7 +1581,7 @@ ref_scale_init(void)
unwind:
torture_init_end();
ref_scale_cleanup();
if (shutdown) {
if (shutdown_secs) {
WARN_ON(!IS_MODULE(CONFIG_RCU_REF_SCALE_TEST));
kernel_power_off();
}

View File

@ -11,7 +11,7 @@
#
# Adds per-version torture-module parameters to kernels supporting them.
per_version_boot_params () {
echo refscale.shutdown=1 \
echo refscale.shutdown_secs=$3 \
refscale.verbose=0 \
$1
}