uadmin.c revision edc40228913a9349b362a899c05648e6bdc23167
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <vm/seg_kmem.h>
/*
* Administrivia system call. We provide this in two flavors: one for calling
* from the system call path (uadmin), and the other for calling from elsewhere
* within the kernel (kadmin). Callers must beware that certain uadmin cmd
* values (specifically A_SWAPCTL) are only supported by uadmin and not kadmin.
*/
extern ksema_t fsflush_sema;
/*
* Kill all user processes in said zone. A special argument of ALL_ZONES is
* passed in when the system as a whole is shutting down. The lack of per-zone
* process lists is likely to make the following a performance bottleneck on a
* system with many zones.
*/
void
{
proc_t *p;
/*
* Kill all processes except kernel daemons and ourself.
* Make a first pass to stop all processes so they won't
* be trying to restart children as we kill them.
*/
mutex_enter(&p->p_lock);
mutex_exit(&p->p_lock);
}
}
p = practive;
while (p != NULL) {
mutex_enter(&p->p_lock);
mutex_exit(&p->p_lock);
p = p->p_next;
} else {
mutex_exit(&p->p_lock);
(void) cv_timedwait(&p->p_srwchan_cv,
p = practive;
}
} else {
p = p->p_next;
}
}
}
int
{
int error = 0;
int locked = 0;
char *buf;
/*
* We might be called directly by the kernel's fault-handling code, so
* we can't assert that the caller is in the global zone.
*/
/*
* and that we have appropriate privileges for this action.
*/
switch (cmd) {
case A_FTRACE:
case A_SHUTDOWN:
case A_REBOOT:
case A_REMOUNT:
case A_FREEZE:
case A_DUMP:
return (EPERM);
break;
default:
return (EINVAL);
}
/*
* Serialize these operations on ualock. If it is held, just return
* as if successful since the system will soon reset or remount.
*/
if (!mutex_tryenter(&ualock))
return (0);
locked = 1;
}
switch (cmd) {
case A_SHUTDOWN:
{
/*
* Release (almost) all of our own resources if we are called
* from a user context, however if we are calling kadmin() from
* a kernel context then we do not release these resources.
*/
return (error);
mutex_enter(&p->p_lock);
sigfillset(&p->p_ignore);
if (p->p_exec) {
mutex_exit(&p->p_lock);
} else {
mutex_exit(&p->p_lock);
}
pollcleanup();
relvm();
} else {
/*
* Reset t_cred if not set because much of the
* filesystem code depends on CRED() being valid.
*/
}
/*
* Communcate that init shouldn't be restarted.
*/
/*
* If we are calling kadmin() from a kernel context then we
* do not release these resources.
*/
if (u.u_rdir)
if (u.u_cwd)
refstr_rele(u.u_cwd);
}
/*
* anything it needs to whilst we still have filesystems
* mounted, like loading any modules necessary for later
* performing the actual poweroff.
*/
} else
/*
* Allow fsflush to finish running and then prevent it
* from ever running again so that vfs_unmountall() and
* vfs_syncall() can acquire the vfs locks they need.
*/
vfs_syncall();
/* FALLTHROUGH */
}
case A_REBOOT:
} else
/* no return expected */
break;
case A_REMOUNT:
break;
case A_FREEZE:
{
/* XXX: declare in some header file */
extern int cpr(int);
return (ENOTSUP);
break;
}
case A_FTRACE:
{
switch (fcn) {
case AD_FTRACE_START:
(void) FTRACE_START();
break;
case AD_FTRACE_STOP:
(void) FTRACE_STOP();
break;
default:
}
break;
}
case A_DUMP:
{
in_sync = 1;
break;
}
panic_bootfcn = fcn;
panic_forced = 1;
} else
panic("forced crash dump initiated at user request");
/*NOTREACHED*/
}
default:
}
if (locked)
mutex_exit(&ualock);
return (error);
}
int
{
char buf[257];
/*
* The swapctl system call doesn't have its own entry point: it uses
* uadmin as a wrapper so we just call it directly from here.
*/
if (get_udatamodel() == DATAMODEL_NATIVE)
#if defined(_SYSCALL32_IMPL)
else
#endif /* _SYSCALL32_IMPL */
}
/*
* Handle zones.
*/
if (getzoneid() != GLOBAL_ZONEID) {
}
/*
* Certain subcommands intepret a non-NULL mdep value as a pointer to
* a boot string. Attempt to copy it in now, or reset mdep to NULL.
*/
} else
}
return (0);
}