4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2013 Joyent, Inc. All rights reserved.
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/sysmacros.h>
31 #include <sys/systm.h>
32 #include <sys/errno.h>
34 #include <sys/vnode.h>
39 #include <sys/uadmin.h>
40 #include <sys/signal.h>
42 #include <vm/seg_kmem.h>
43 #include <sys/modctl.h>
44 #include <sys/callb.h>
45 #include <sys/dumphdr.h>
46 #include <sys/debug.h>
47 #include <sys/ftrace.h>
48 #include <sys/cmn_err.h>
49 #include <sys/panic.h>
51 #include <sys/ddi_periodic.h>
52 #include <sys/sunddi.h>
53 #include <sys/policy.h>
55 #include <sys/condvar.h>
56 #include <sys/thread.h>
60 * Administrivia system call. We provide this in two flavors: one for calling
61 * from the system call path (uadmin), and the other for calling from elsewhere
62 * within the kernel (kadmin). Callers must beware that certain uadmin cmd
63 * values (specifically A_SWAPCTL) are only supported by uadmin and not kadmin.
66 extern ksema_t fsflush_sema
;
69 kthread_t
*ua_shutdown_thread
= NULL
;
72 volatile int fastreboot_dryrun
= 0;
75 * Kill all user processes in said zone. A special argument of ALL_ZONES is
76 * passed in when the system as a whole is shutting down. The lack of per-zone
77 * process lists is likely to make the following a performance bottleneck on a
78 * system with many zones.
81 killall(zoneid_t zoneid
)
85 ASSERT(zoneid
!= GLOBAL_ZONEID
);
87 * Kill all processes except kernel daemons and ourself.
88 * Make a first pass to stop all processes so they won't
89 * be trying to restart children as we kill them.
91 mutex_enter(&pidlock
);
92 for (p
= practive
; p
!= NULL
; p
= p
->p_next
) {
93 if ((zoneid
== ALL_ZONES
|| p
->p_zone
->zone_id
== zoneid
) &&
94 p
->p_exec
!= NULLVP
&& /* kernel daemons */
97 mutex_enter(&p
->p_lock
);
99 sigtoproc(p
, NULL
, SIGSTOP
);
100 mutex_exit(&p
->p_lock
);
105 if ((zoneid
== ALL_ZONES
|| p
->p_zone
->zone_id
== zoneid
) &&
106 p
->p_exec
!= NULLVP
&& /* kernel daemons */
109 p
->p_stat
!= SZOMB
) {
110 mutex_enter(&p
->p_lock
);
111 if (sigismember(&p
->p_sig
, SIGKILL
)) {
112 mutex_exit(&p
->p_lock
);
115 sigtoproc(p
, NULL
, SIGKILL
);
116 mutex_exit(&p
->p_lock
);
117 (void) cv_reltimedwait(&p
->p_srwchan_cv
,
118 &pidlock
, hz
, TR_CLOCK_TICK
);
125 mutex_exit(&pidlock
);
129 kadmin(int cmd
, int fcn
, void *mdep
, cred_t
*credp
)
134 boolean_t invoke_cb
= B_FALSE
;
137 * We might be called directly by the kernel's fault-handling code, so
138 * we can't assert that the caller is in the global zone.
142 * Make sure that cmd is one of the valid <sys/uadmin.h> command codes
143 * and that we have appropriate privileges for this action.
154 if (secpolicy_sys_config(credp
, B_FALSE
) != 0)
163 * Serialize these operations on ualock. If it is held, the
164 * system should shutdown, reboot, or remount shortly, unless there is
165 * an error. We need a cv rather than just a mutex because proper
166 * functioning of A_REBOOT relies on being able to interrupt blocked
169 * We only clear ua_shutdown_thread after A_REMOUNT or A_CONFIG.
170 * Other commands should never return.
172 if (cmd
== A_SHUTDOWN
|| cmd
== A_REBOOT
|| cmd
== A_REMOUNT
||
174 mutex_enter(&ualock
);
175 while (ua_shutdown_thread
!= NULL
) {
176 if (cv_wait_sig(&uacond
, &ualock
) == 0) {
178 * If we were interrupted, leave, and handle
179 * the signal (or exit, depending on what
186 ua_shutdown_thread
= curthread
;
193 proc_t
*p
= ttoproc(curthread
);
196 * Release (almost) all of our own resources if we are called
197 * from a user context, however if we are calling kadmin() from
198 * a kernel context then we do not release these resources.
202 if ((error
= exitlwps(0)) != 0) {
204 * Another thread in this process also called
207 mutex_enter(&ualock
);
208 ua_shutdown_thread
= NULL
;
213 mutex_enter(&p
->p_lock
);
214 p
->p_flag
|= SNOWAIT
;
215 sigfillset(&p
->p_ignore
);
216 curthread
->t_lwp
->lwp_cursig
= 0;
217 curthread
->t_lwp
->lwp_extsig
= 0;
219 vnode_t
*exec_vp
= p
->p_exec
;
221 mutex_exit(&p
->p_lock
);
224 mutex_exit(&p
->p_lock
);
228 closeall(P_FINFO(curproc
));
233 * Reset t_cred if not set because much of the
234 * filesystem code depends on CRED() being valid.
236 if (curthread
->t_cred
== NULL
)
237 curthread
->t_cred
= kcred
;
240 /* indicate shutdown in progress */
244 * Communcate that init shouldn't be restarted.
246 zone_shutdown_global();
250 * If we are calling kadmin() from a kernel context then we
251 * do not release these resources.
253 if (ttoproc(curthread
) != &p0
) {
254 VN_RELE(PTOU(curproc
)->u_cdir
);
255 if (PTOU(curproc
)->u_rdir
)
256 VN_RELE(PTOU(curproc
)->u_rdir
);
257 if (PTOU(curproc
)->u_cwd
)
258 refstr_rele(PTOU(curproc
)->u_cwd
);
260 PTOU(curproc
)->u_cdir
= rootdir
;
261 PTOU(curproc
)->u_rdir
= NULL
;
262 PTOU(curproc
)->u_cwd
= NULL
;
266 * Allow the reboot/halt/poweroff code a chance to do
267 * anything it needs to whilst we still have filesystems
268 * mounted, like loading any modules necessary for later
269 * performing the actual poweroff.
271 if ((mdep
!= NULL
) && (*(char *)mdep
== '/')) {
272 buf
= i_convert_boot_device_name(mdep
, NULL
, &buflen
);
273 mdpreboot(cmd
, fcn
, buf
);
275 mdpreboot(cmd
, fcn
, mdep
);
278 * Allow fsflush to finish running and then prevent it
279 * from ever running again so that vfs_unmountall() and
280 * vfs_syncall() can acquire the vfs locks they need.
282 sema_p(&fsflush_sema
);
283 (void) callb_execute_class(CB_CL_UADMIN_PRE_VFS
, 0);
286 (void) VFS_MOUNTROOT(rootvfs
, ROOT_UNMOUNT
);
290 * Check for (and unregister) any DDI periodic handlers that
291 * still exist, as they most likely constitute resource leaks:
304 if ((mdep
!= NULL
) && (*(char *)mdep
== '/')) {
305 buf
= i_convert_boot_device_name(mdep
, NULL
, &buflen
);
306 mdboot(cmd
, fcn
, buf
, invoke_cb
);
308 mdboot(cmd
, fcn
, mdep
, invoke_cb
);
309 /* no return expected */
314 case AD_UPDATE_BOOT_CONFIG
:
316 extern void fastboot_update_config(const char *);
318 fastboot_update_config(mdep
);
323 /* Let other threads enter the shutdown path now */
324 mutex_enter(&ualock
);
325 ua_shutdown_thread
= NULL
;
331 (void) VFS_MOUNTROOT(rootvfs
, ROOT_REMOUNT
);
332 /* Let other threads enter the shutdown path now */
333 mutex_enter(&ualock
);
334 ua_shutdown_thread
= NULL
;
342 * This is the entrypoint for all suspend/resume actions.
344 extern int cpr(int, void *);
346 if (modload("misc", "cpr") == -1)
348 /* Let the CPR module decide what to do with mdep */
349 error
= cpr(fcn
, mdep
);
356 case AD_FTRACE_START
:
357 (void) FTRACE_START();
360 (void) FTRACE_STOP();
370 if (fcn
== AD_NOSYNC
) {
378 if ((mdep
!= NULL
) && (*(char *)mdep
== '/')) {
379 panic_bootstr
= i_convert_boot_device_name(mdep
,
382 panic_bootstr
= mdep
;
384 extern void fastboot_update_and_load(int, char *);
386 fastboot_update_and_load(fcn
, mdep
);
388 panic("forced crash dump initiated at user request");
394 DTRACE_PROBE7(test
, int, 1, int, 2, int, 3, int, 4, int, 5,
407 uadmin(int cmd
, int fcn
, uintptr_t mdep
)
409 int error
= 0, rv
= 0;
411 cred_t
*credp
= CRED();
412 char *bootargs
= NULL
;
413 int reset_status
= 0;
415 if (cmd
== A_SHUTDOWN
&& fcn
== AD_FASTREBOOT_DRYRUN
) {
416 ddi_walk_devs(ddi_root_node(), check_driver_quiesce
,
418 if (reset_status
!= 0)
425 * The swapctl system call doesn't have its own entry point: it uses
426 * uadmin as a wrapper so we just call it directly from here.
428 if (cmd
== A_SWAPCTL
) {
429 if (get_udatamodel() == DATAMODEL_NATIVE
)
430 error
= swapctl(fcn
, (void *)mdep
, &rv
);
431 #if defined(_SYSCALL32_IMPL)
433 error
= swapctl32(fcn
, (void *)mdep
, &rv
);
434 #endif /* _SYSCALL32_IMPL */
435 return (error
? set_errno(error
) : rv
);
439 * Certain subcommands intepret a non-NULL mdep value as a pointer to
440 * a boot string. We pull that in as bootargs, if applicable.
442 if (mdep
!= (uintptr_t)NULL
&&
443 (cmd
== A_SHUTDOWN
|| cmd
== A_REBOOT
|| cmd
== A_DUMP
||
444 cmd
== A_FREEZE
|| cmd
== A_CONFIG
)) {
445 bootargs
= kmem_zalloc(BOOTARGS_MAX
, KM_SLEEP
);
446 if ((error
= copyinstr((const char *)mdep
, bootargs
,
447 BOOTARGS_MAX
, &nbytes
)) != 0) {
448 kmem_free(bootargs
, BOOTARGS_MAX
);
449 return (set_errno(error
));
454 * Invoke the appropriate kadmin() routine.
456 if (getzoneid() != GLOBAL_ZONEID
)
457 error
= zone_kadmin(cmd
, fcn
, bootargs
, credp
);
459 error
= kadmin(cmd
, fcn
, bootargs
, credp
);
461 if (bootargs
!= NULL
)
462 kmem_free(bootargs
, BOOTARGS_MAX
);
463 return (error
? set_errno(error
) : 0);