All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 4a801b22 authored by David Johnson's avatar David Johnson

Move emergency_restart call out of bh in Linux ipod module on aarch64/powerpc64.

Calling emergency_restart directly from the softirq/bh ipod icmp handler
has a history of causing panics prior to the intended shutdown on both
aarch64 and powerpc64.  The panics didn't inhibit the intended reboot,
but on OPAL-booted ppc64le, were very noisy, because each "hyperthread"
cpu attempted a dealloc of the irq handler from within the handler, so
the console got a noisy stack trace for each thread.

So now if IPOD_QUEUE_RESTART is defined (and it is by default on aarch64
and powerpc64), we move the call to emergency_restart into a dedicated,
preallocated workqueue thread, whose sole purpose is to (eventually)
reboot the machine.  Wasteful, but we don't want to need to initialize
anything, or use a shared workqueue, if an IPOD is really necessary, at
IPOD time.
parent f8533dad
/*
* Copyright (c) 2000-2018 University of Utah and the Flux Group.
* Copyright (c) 2000-2019 University of Utah and the Flux Group.
*
* {{{EMULAB-LICENSE
*
......@@ -41,7 +41,25 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Flux Research Group");
MODULE_VERSION("3.0.0");
MODULE_VERSION("3.1.0");
#if defined(__aarch64__) || defined(__powerpc64__)
#define IPOD_QUEUE_RESTART
#endif
#ifdef IPOD_QUEUE_RESTART
#include <linux/workqueue.h>
static struct workqueue_struct *restart_queue;
static void restart_work_func(struct work_struct *work)
{
printk(KERN_CRIT "IPOD: restarting (delayed)...\n");
emergency_restart();
}
DECLARE_WORK(restart_work,restart_work_func);
#endif
#define IPOD_ICMP_TYPE 6
#define IPOD_ICMP_CODE 6
......@@ -245,7 +263,11 @@ static unsigned int ipod_hook_fn(
if (doit) {
sysctl_ipod_enabled = 0;
printk(KERN_CRIT "IPOD: reboot forced by %pI4...\n",&iph->saddr);
#ifdef IPOD_QUEUE_RESTART
queue_work(restart_queue,&restart_work);
#else
emergency_restart();
#endif
return NF_DROP;
}
else {
......@@ -288,11 +310,21 @@ static int __init ipod_init_module(void) {
return -1;
}
#ifdef IPOD_QUEUE_RESTART
restart_queue = create_singlethread_workqueue("ipod_restart_queue");
#endif
return 0;
}
static void __exit ipod_cleanup_module(void) {
printk(KERN_INFO "removing IPOD\n");
#ifdef IPOD_QUEUE_RESTART
cancel_work_sync(&restart_work);
destroy_workqueue(restart_queue);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)
nf_unregister_net_hook(&init_net,&ipod_hook_ops);
#else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment