Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_shutdown.c
Show First 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Variable panicstr contains argument to first call to panic; used as flag | * Variable panicstr contains argument to first call to panic; used as flag | ||||
* to indicate that the kernel has already called panic. | * to indicate that the kernel has already called panic. | ||||
*/ | */ | ||||
const char *panicstr; | const char *panicstr; | ||||
int dumping; /* system is dumping */ | int dumping; /* system is dumping */ | ||||
int rebooting; /* system is rebooting */ | int rebooting; /* system is rebooting */ | ||||
#ifdef VIMAGE | |||||
VPS_DEFINE(int, vrebooting); /* vps is rebooting */ | |||||
#define V_vrebooting VPS(vrebooting) | |||||
#endif | |||||
static struct dumperinfo dumper; /* our selected dumper */ | static struct dumperinfo dumper; /* our selected dumper */ | ||||
/* Context information for dump-debuggers. */ | /* Context information for dump-debuggers. */ | ||||
static struct pcb dumppcb; /* Registers. */ | static struct pcb dumppcb; /* Registers. */ | ||||
lwpid_t dumptid; /* Thread ID. */ | lwpid_t dumptid; /* Thread ID. */ | ||||
static struct cdevsw reroot_cdevsw = { | static struct cdevsw reroot_cdevsw = { | ||||
.d_version = D_VERSION, | .d_version = D_VERSION, | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | |||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_system_check_reboot(td->td_ucred, uap->opt); | error = mac_system_check_reboot(td->td_ucred, uap->opt); | ||||
#endif | #endif | ||||
if (error == 0) | if (error == 0) | ||||
error = priv_check(td, PRIV_REBOOT); | error = priv_check(td, PRIV_REBOOT); | ||||
if (error == 0) { | if (error == 0) { | ||||
if (uap->opt & RB_REROOT) | if (uap->opt & RB_REROOT) | ||||
error = kern_reroot(); | error = kern_reroot(); | ||||
else | else { | ||||
#ifdef VIMAGE | |||||
/* XXX Can argue that we should never make it here. */ | |||||
/* Init will want to _exit() in this case. */ | |||||
if (!IS_DEFAULT_VPS(TD_TO_VPS(curthread))) { | |||||
V_vrebooting = 1; | |||||
return (error); | |||||
} | |||||
#endif | |||||
kern_reboot(uap->opt); | kern_reboot(uap->opt); | ||||
} | } | ||||
} | |||||
return (error); | return (error); | ||||
} | } | ||||
static VPS_DEFINE(int, vhowto); | |||||
#define V_vhowto VPS(vhowto) | |||||
static void | static void | ||||
shutdown_nice_task_fn(void *arg, int pending __unused) | shutdown_nice_task_fn(void *arg, int pending __unused) | ||||
{ | { | ||||
int howto; | |||||
howto = (uintptr_t)arg; | CURVPS_SET((struct vps *)arg); | ||||
/* Send a signal to init(8) and have it shutdown the world. */ | /* Send a signal to init(8) and have it shutdown the world. */ | ||||
PROC_LOCK(initproc); | PROC_LOCK(V_initproc); | ||||
if (howto & RB_POWEROFF) | if (V_vhowto & RB_POWEROFF) | ||||
kern_psignal(initproc, SIGUSR2); | kern_psignal(V_initproc, SIGUSR2); | ||||
else if (howto & RB_POWERCYCLE) | else if (V_vhowto & RB_POWERCYCLE) | ||||
kern_psignal(initproc, SIGWINCH); | kern_psignal(V_initproc, SIGWINCH); | ||||
else if (howto & RB_HALT) | else if (V_vhowto & RB_HALT) | ||||
kern_psignal(initproc, SIGUSR1); | kern_psignal(V_initproc, SIGUSR1); | ||||
else | else | ||||
kern_psignal(initproc, SIGINT); | kern_psignal(V_initproc, SIGINT); | ||||
PROC_UNLOCK(initproc); | PROC_UNLOCK(V_initproc); | ||||
V_vhowto = 0; | |||||
CURVPS_RESTORE(); | |||||
} | } | ||||
static struct task shutdown_nice_task = TASK_INITIALIZER(0, | static struct task shutdown_nice_task = TASK_INITIALIZER(0, | ||||
&shutdown_nice_task_fn, NULL); | &shutdown_nice_task_fn, NULL); | ||||
/* | /* | ||||
* Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC | * Called by events that want to shut down.. e.g <CTL><ALT><DEL> on a PC | ||||
*/ | */ | ||||
void | void | ||||
shutdown_nice(int howto) | shutdown_nice(int howto) | ||||
{ | { | ||||
if (initproc != NULL && !SCHEDULER_STOPPED()) { | if (V_initproc != NULL && !SCHEDULER_STOPPED()) { | ||||
shutdown_nice_task.ta_context = (void *)(uintptr_t)howto; | |||||
KASSERT(V_vhowto == 0, ("%s: vps %p howto not 0: %d\n", | |||||
__func__, curvps, V_vhowto)); | |||||
V_vhowto = howto; | |||||
shutdown_nice_task.ta_context = (void *)curvps; | |||||
taskqueue_enqueue(taskqueue_fast, &shutdown_nice_task); | taskqueue_enqueue(taskqueue_fast, &shutdown_nice_task); | ||||
} else { | } else { | ||||
#ifdef VIMAGE | |||||
/* XXX Can argue that we should never make it here. */ | |||||
/* Init will want to _exit() in this case. */ | |||||
if (!IS_DEFAULT_VPS(TD_TO_VPS(curthread))) { | |||||
V_vrebooting = 1; | |||||
return; | |||||
} | |||||
#endif | |||||
/* | /* | ||||
* No init(8) running, or scheduler would not allow it | * No init(8) running, or scheduler would not allow it | ||||
* to run, so simply reboot. | * to run, so simply reboot. | ||||
*/ | */ | ||||
kern_reboot(howto | RB_NOSYNC); | kern_reboot(howto | RB_NOSYNC); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
kern_reroot(void) | kern_reroot(void) | ||||
{ | { | ||||
struct vnode *oldrootvnode, *vp; | struct vnode *oldrootvnode, *vp; | ||||
struct mount *mp, *devmp; | struct mount *mp, *devmp; | ||||
int error; | int error; | ||||
if (curproc != initproc) | if (curproc != V_initproc) | ||||
return (EPERM); | return (EPERM); | ||||
/* | /* | ||||
* Mark the filesystem containing currently-running executable | * Mark the filesystem containing currently-running executable | ||||
* (the temporary copy of init(8)) busy. | * (the temporary copy of init(8)) busy. | ||||
*/ | */ | ||||
vp = curproc->p_textvp; | vp = curproc->p_textvp; | ||||
error = vn_lock(vp, LK_SHARED); | error = vn_lock(vp, LK_SHARED); | ||||
▲ Show 20 Lines • Show All 1,098 Lines • Show Last 20 Lines |