logsubr.c revision 281888b30170d9201cff6510aa98cb0a7151b09e
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <sys/id_space.h>
static krwlock_t log_rwlock;
static int log_rwlock_depth;
static stdata_t log_fakestr;
static id_space_t *log_minorspace;
static log_t log_backlog;
static queue_t *log_recentq;
static zone_key_t log_zone_key;
static char log_overflow_msg[] = "message overflow on /dev/log minor #%d%s\n";
"emerg", "alert", "crit", "error",
"warning", "notice", "info", "debug"
};
"kern", "user", "mail", "daemon",
"auth", "syslog", "lpr", "news",
"uucp", "resv9", "resv10", "resv11",
"resv12", "audit", "resv14", "cron",
"local0", "local1", "local2", "local3",
"local4", "local5", "local6", "local7",
"unknown"
};
static int log_cons_constructor(void *, void *, int);
static void log_cons_destructor(void *, void *);
/*
* Get exclusive access to the logging system; this includes all minor
* devices. We use an rwlock rather than a mutex because hold times
* are potentially long, so we don't want to waste cycles in adaptive mutex
* spin (rwlocks always block when contended). Note that we explicitly
* support recursive calls (e.g. printf() calls foo() calls printf()).
*
* Clients may use log_enter() / log_exit() to guarantee that a group
* of messages is treated atomically (i.e. they appear in order and are
* not interspersed with any other messages), e.g. for multiline printf().
*
* This could probably be changed to a per-zone lock if contention becomes
* an issue.
*/
void
log_enter(void)
{
}
void
log_exit(void)
{
if (--log_rwlock_depth == 0)
}
void
log_flushq(queue_t *q)
{
/* lp will be NULL if the queue was created via log_makeq */
}
/*
* Create a minimal queue with just enough fields filled in to support
* canput(9F), putq(9F), and getq_noenab(9F). We set QNOENB to ensure
* that the queue will never be enabled.
*/
static queue_t *
{
queue_t *q;
q->q_stream = &log_fakestr;
q->q_nfsrv = q;
return (q);
}
/*
* Initialize the log structure for a new zone.
*/
static void *
{
int i;
if (zoneid == GLOBAL_ZONEID)
else
for (i = 0; i < LOG_NUMCLONES; i++) {
}
return (lzp);
}
/*ARGSUSED*/
static void
{
int i;
return;
for (i = 0; i < LOG_NUMCLONES; i++)
}
void
log_init(void)
{
int log_maxzones;
/*
* Create a backlog queue to consume console messages during periods
* when there is no console reader (e.g. before syslogd(1M) starts).
*/
/*
* Create a queue to hold free message of size <= LOG_MSGSIZE.
* Calls from high-level interrupt handlers will do a getq_noenab()
* from this queue, so its q_lock must be a maximum SPL spin lock.
*/
/*
* Create a queue for messages from high-level interrupt context.
* These messages are drained via softcall, or explicitly by panic().
*/
/*
* Create a queue to hold the most recent 8K of console messages.
* Useful for debugging. Required by the "$<msgbuf" adb macro.
*/
/*
* Need to limit the number of zones to avoid exceeding the
* available minor number space.
*/
if (log_maxzones < maxzones)
/*
* Put ourselves on the ZSD list. Note that zones have not been
* initialized yet, but our constructor will be called on the global
* zone when they are.
*/
/*
* Initialize backlog structure.
*/
/* Allocate kmem cache for conslog's log structures */
/*
* Let the logging begin.
*/
/*
* Now that logging is enabled, emit the SunOS banner.
*/
printf("\rSunOS Release %s Version %s %u-bit\n",
printf("Copyright 1983-2007 Sun Microsystems, Inc. "
"All rights reserved.\nUse is subject to license terms.\n");
#ifdef DEBUG
printf("DEBUG enabled\n");
#endif
}
/*
* Allocate a log device corresponding to supplied device type.
*/
log_t *
{
int i;
if (type == LOG_CONSMIN) {
/*
* No point allocating log_t until there's a free minor number.
*/
return (lp);
} else {
for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) {
break;
}
if (i > LOG_LOGMAXIDX)
else
/* Indicate which device type */
return (lp);
}
}
void
{
}
/*
* Move console messages from src to dst. The time of day isn't known
* early in boot, so fix up the message timestamps if necessary.
*/
static void
{
/*
* The ttime is written with 0 in log_sensmsg() only when
* good gethrestime_sec() data is not available to store in
* the log_ctl_t in the early boot phase.
*/
/*
* Look ahead to first early boot message with time.
*/
if (hmp) {
} else
continue;
}
while (hmp) {
/*
* Calculate hrestime for an early log message with
* an invalid time stamp. We know:
* - the lbolt of the invalid time stamp.
* - the hrestime and lbolt of the first valid
* time stamp.
*/
}
}
while (hmp) {
}
}
/*
* Set the fields in the 'target' clone to the specified values.
* Then, look at all clones to determine which message types are
* currently active and which clone is the primary console queue.
* If the primary console queue changes to or from the backlog
* queue, copy all messages from backlog to primary or vice versa.
*/
void
{
short active = SL_CONSOLE;
int i;
log_enter();
if (q != NULL)
target->log_overflow = 0;
/*
* Need to special case the global zone here since this may be
* called before zone_init.
*/
if (zoneid == GLOBAL_ZONEID) {
lzp = &log_global;
log_exit();
return; /* zone is being destroyed, ignore update */
} else {
}
for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) {
}
if (zptr)
if (flags & SL_CONSOLE)
else
}
log_exit();
}
/*ARGSUSED*/
int
{
return (1);
}
int
{
/*
* We use `tid + 1 <= tidend' here rather than the more traditional
* `tid < tidend', since the former ensures that there's at least
* `sizeof (trace_ids_t)' bytes available before executing the
* loop, whereas the latter only ensures that there's a single byte.
*/
continue;
continue;
continue;
return (1);
}
return (0);
}
/*ARGSUSED*/
int
{
else
}
return (1);
}
mblk_t *
{
if (size <= LOG_MSGSIZE &&
if (on_intr ||
return (NULL);
}
} else {
}
return (mp);
}
void
{
else
}
void
{
int i;
int backlog;
/*
* Need to special case the global zone here since this may be
* called before zone_init.
*/
if (zoneid == GLOBAL_ZONEID) {
lzp = &log_global;
/* specified zone doesn't exist, free message and return */
return;
} else {
}
if (zptr)
return;
}
if (panicstr) {
/*
* Raise the console queue's q_hiwat to ensure that we
* capture all panic messages.
*/
/* Message was created while panicking. */
}
}
log_enter();
/*
* In the early boot phase hrestime is invalid, then timechanged is 0.
* If hrestime is not valid, the ttime is set to 0 here and the correct
* ttime is calculated in log_conswitch() later. The log_conswitch()
* calculation to determine the correct ttime does not use ttime data
* from these log_ctl_t structures; it only uses ttime from log_ctl_t's
* that contain good data.
*
*/
if (timechanged) {
} else {
}
/*
* If this is in the global zone, start with the backlog, then
* walk through the clone logs. If not, just do the clone logs.
*/
i = LOG_LOGMINIDX;
while (i <= LOG_LOGMAXIDX) {
if (backlog) {
/*
* Do the backlog this time, then start on the
* others.
*/
backlog = 0;
lp = &log_backlog;
} else {
}
lp->log_overflow = 0;
break;
if (facility != 0) {
while (*src != '\0')
*dst++ = '\0';
}
" -- is syslogd(1M) running?");
} else {
}
}
}
}
if (zptr)
}
}
log_exit();
}
/*
* Print queued messages to console.
*/
void
{
/*
* Look ahead to first queued message in the stream.
*/
do {
continue;
/*
* Check if message is already displayed at
*/
continue;
/* Strip off the message ID. */
}
/*
* Using console_printf instead of printf to avoid
* queueing messages to log_consq.
*/
}
}
/* ARGSUSED */
static int
{
return (0);
}
/* ARGSUSED */
static void
{
}