xref: /onnv-gate/usr/src/uts/common/os/logsubr.c (revision 12041:03c4bd206296)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51401Smjnelson  * Common Development and Distribution License (the "License").
61401Smjnelson  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211401Smjnelson 
220Sstevel@tonic-gate /*
23*12041SJohn.Beck@Sun.COM  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <sys/types.h>
270Sstevel@tonic-gate #include <sys/param.h>
280Sstevel@tonic-gate #include <sys/varargs.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/cmn_err.h>
310Sstevel@tonic-gate #include <sys/stream.h>
320Sstevel@tonic-gate #include <sys/strsubr.h>
330Sstevel@tonic-gate #include <sys/strsun.h>
340Sstevel@tonic-gate #include <sys/sysmacros.h>
350Sstevel@tonic-gate #include <sys/kmem.h>
360Sstevel@tonic-gate #include <sys/log.h>
370Sstevel@tonic-gate #include <sys/spl.h>
380Sstevel@tonic-gate #include <sys/syslog.h>
390Sstevel@tonic-gate #include <sys/console.h>
400Sstevel@tonic-gate #include <sys/debug.h>
410Sstevel@tonic-gate #include <sys/utsname.h>
420Sstevel@tonic-gate #include <sys/id_space.h>
430Sstevel@tonic-gate #include <sys/zone.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate log_zone_t log_global;
460Sstevel@tonic-gate queue_t *log_consq;
470Sstevel@tonic-gate queue_t *log_backlogq;
480Sstevel@tonic-gate queue_t *log_intrq;
490Sstevel@tonic-gate 
500Sstevel@tonic-gate #define	LOG_PRISIZE	8	/* max priority size: 7 characters + null */
510Sstevel@tonic-gate #define	LOG_FACSIZE	9	/* max priority size: 8 characters + null */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate static krwlock_t log_rwlock;
540Sstevel@tonic-gate static int log_rwlock_depth;
550Sstevel@tonic-gate static int log_seq_no[SL_CONSOLE + 1];
560Sstevel@tonic-gate static stdata_t log_fakestr;
570Sstevel@tonic-gate static id_space_t *log_minorspace;
580Sstevel@tonic-gate static log_t log_backlog;
591259Sns92644 static struct kmem_cache *log_cons_cache;	/* log_t cache */
600Sstevel@tonic-gate 
610Sstevel@tonic-gate static queue_t *log_recentq;
620Sstevel@tonic-gate static queue_t *log_freeq;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static zone_key_t log_zone_key;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static char log_overflow_msg[] = "message overflow on /dev/log minor #%d%s\n";
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static char log_pri[LOG_PRIMASK + 1][LOG_PRISIZE] = {
690Sstevel@tonic-gate 	"emerg",	"alert",	"crit",		"error",
700Sstevel@tonic-gate 	"warning",	"notice",	"info",		"debug"
710Sstevel@tonic-gate };
720Sstevel@tonic-gate 
730Sstevel@tonic-gate static char log_fac[LOG_NFACILITIES + 1][LOG_FACSIZE] = {
740Sstevel@tonic-gate 	"kern",		"user",		"mail",		"daemon",
750Sstevel@tonic-gate 	"auth",		"syslog",	"lpr",		"news",
760Sstevel@tonic-gate 	"uucp",		"resv9",	"resv10",	"resv11",
770Sstevel@tonic-gate 	"resv12",	"audit",	"resv14",	"cron",
780Sstevel@tonic-gate 	"local0",	"local1",	"local2",	"local3",
790Sstevel@tonic-gate 	"local4",	"local5",	"local6",	"local7",
800Sstevel@tonic-gate 	"unknown"
810Sstevel@tonic-gate };
821259Sns92644 static int log_cons_constructor(void *, void *, int);
831259Sns92644 static void log_cons_destructor(void *, void *);
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate  * Get exclusive access to the logging system; this includes all minor
870Sstevel@tonic-gate  * devices.  We use an rwlock rather than a mutex because hold times
880Sstevel@tonic-gate  * are potentially long, so we don't want to waste cycles in adaptive mutex
890Sstevel@tonic-gate  * spin (rwlocks always block when contended).  Note that we explicitly
900Sstevel@tonic-gate  * support recursive calls (e.g. printf() calls foo() calls printf()).
910Sstevel@tonic-gate  *
920Sstevel@tonic-gate  * Clients may use log_enter() / log_exit() to guarantee that a group
930Sstevel@tonic-gate  * of messages is treated atomically (i.e. they appear in order and are
940Sstevel@tonic-gate  * not interspersed with any other messages), e.g. for multiline printf().
950Sstevel@tonic-gate  *
960Sstevel@tonic-gate  * This could probably be changed to a per-zone lock if contention becomes
970Sstevel@tonic-gate  * an issue.
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate void
log_enter(void)1000Sstevel@tonic-gate log_enter(void)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	if (rw_owner(&log_rwlock) != curthread)
1030Sstevel@tonic-gate 		rw_enter(&log_rwlock, RW_WRITER);
1040Sstevel@tonic-gate 	log_rwlock_depth++;
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate void
log_exit(void)1080Sstevel@tonic-gate log_exit(void)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	if (--log_rwlock_depth == 0)
1110Sstevel@tonic-gate 		rw_exit(&log_rwlock);
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate void
log_flushq(queue_t * q)1150Sstevel@tonic-gate log_flushq(queue_t *q)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	mblk_t *mp;
1180Sstevel@tonic-gate 	log_t *lp = (log_t *)q->q_ptr;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	/* lp will be NULL if the queue was created via log_makeq */
1216769Sja97890 	while ((mp = getq_noenab(q, 0)) != NULL)
1220Sstevel@tonic-gate 		log_sendmsg(mp, lp == NULL ? GLOBAL_ZONEID : lp->log_zoneid);
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate  * Create a minimal queue with just enough fields filled in to support
1270Sstevel@tonic-gate  * canput(9F), putq(9F), and getq_noenab(9F).  We set QNOENB to ensure
1280Sstevel@tonic-gate  * that the queue will never be enabled.
1290Sstevel@tonic-gate  */
1300Sstevel@tonic-gate static queue_t *
log_makeq(size_t lowat,size_t hiwat,void * ibc)1310Sstevel@tonic-gate log_makeq(size_t lowat, size_t hiwat, void *ibc)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate 	queue_t *q;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	q = kmem_zalloc(sizeof (queue_t), KM_SLEEP);
1360Sstevel@tonic-gate 	q->q_stream = &log_fakestr;
1370Sstevel@tonic-gate 	q->q_flag = QISDRV | QMTSAFE | QNOENB | QREADR | QUSE;
1380Sstevel@tonic-gate 	q->q_nfsrv = q;
1390Sstevel@tonic-gate 	q->q_lowat = lowat;
1400Sstevel@tonic-gate 	q->q_hiwat = hiwat;
1410Sstevel@tonic-gate 	mutex_init(QLOCK(q), NULL, MUTEX_DRIVER, ibc);
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	return (q);
1440Sstevel@tonic-gate }
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate  * Initialize the log structure for a new zone.
1480Sstevel@tonic-gate  */
1490Sstevel@tonic-gate static void *
log_zoneinit(zoneid_t zoneid)1500Sstevel@tonic-gate log_zoneinit(zoneid_t zoneid)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	int i;
1530Sstevel@tonic-gate 	log_zone_t *lzp;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID)
1560Sstevel@tonic-gate 		lzp = &log_global;	/* use statically allocated struct */
1570Sstevel@tonic-gate 	else
1580Sstevel@tonic-gate 		lzp = kmem_zalloc(sizeof (log_zone_t), KM_SLEEP);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	for (i = 0; i < LOG_NUMCLONES; i++) {
1610Sstevel@tonic-gate 		lzp->lz_clones[i].log_minor =
1620Sstevel@tonic-gate 		    (minor_t)id_alloc(log_minorspace);
1630Sstevel@tonic-gate 		lzp->lz_clones[i].log_zoneid = zoneid;
1640Sstevel@tonic-gate 	}
1650Sstevel@tonic-gate 	return (lzp);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate /*ARGSUSED*/
1690Sstevel@tonic-gate static void
log_zonefree(zoneid_t zoneid,void * arg)1700Sstevel@tonic-gate log_zonefree(zoneid_t zoneid, void *arg)
1710Sstevel@tonic-gate {
1720Sstevel@tonic-gate 	log_zone_t *lzp = arg;
1730Sstevel@tonic-gate 	int i;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	ASSERT(lzp != &log_global && zoneid != GLOBAL_ZONEID);
1760Sstevel@tonic-gate 	if (lzp == NULL)
1770Sstevel@tonic-gate 		return;
1780Sstevel@tonic-gate 	for (i = 0; i < LOG_NUMCLONES; i++)
1790Sstevel@tonic-gate 		id_free(log_minorspace, lzp->lz_clones[i].log_minor);
1800Sstevel@tonic-gate 	kmem_free(lzp, sizeof (log_zone_t));
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate void
log_init(void)1840Sstevel@tonic-gate log_init(void)
1850Sstevel@tonic-gate {
1860Sstevel@tonic-gate 	int log_maxzones;
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate 	/*
1890Sstevel@tonic-gate 	 * Create a backlog queue to consume console messages during periods
1900Sstevel@tonic-gate 	 * when there is no console reader (e.g. before syslogd(1M) starts).
1910Sstevel@tonic-gate 	 */
1920Sstevel@tonic-gate 	log_backlogq = log_consq = log_makeq(0, LOG_HIWAT, NULL);
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	/*
1950Sstevel@tonic-gate 	 * Create a queue to hold free message of size <= LOG_MSGSIZE.
1960Sstevel@tonic-gate 	 * Calls from high-level interrupt handlers will do a getq_noenab()
1970Sstevel@tonic-gate 	 * from this queue, so its q_lock must be a maximum SPL spin lock.
1980Sstevel@tonic-gate 	 */
1990Sstevel@tonic-gate 	log_freeq = log_makeq(LOG_MINFREE, LOG_MAXFREE, (void *)ipltospl(SPL8));
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	/*
2020Sstevel@tonic-gate 	 * Create a queue for messages from high-level interrupt context.
2030Sstevel@tonic-gate 	 * These messages are drained via softcall, or explicitly by panic().
2040Sstevel@tonic-gate 	 */
2050Sstevel@tonic-gate 	log_intrq = log_makeq(0, LOG_HIWAT, (void *)ipltospl(SPL8));
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/*
2080Sstevel@tonic-gate 	 * Create a queue to hold the most recent 8K of console messages.
2090Sstevel@tonic-gate 	 * Useful for debugging.  Required by the "$<msgbuf" adb macro.
2100Sstevel@tonic-gate 	 */
2110Sstevel@tonic-gate 	log_recentq = log_makeq(0, LOG_RECENTSIZE, NULL);
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	/*
2140Sstevel@tonic-gate 	 * Create an id space for clone devices opened via /dev/log.
2150Sstevel@tonic-gate 	 * Need to limit the number of zones to avoid exceeding the
2160Sstevel@tonic-gate 	 * available minor number space.
2170Sstevel@tonic-gate 	 */
2180Sstevel@tonic-gate 	log_maxzones = (L_MAXMIN32 - LOG_LOGMIN) / LOG_NUMCLONES - 1;
2190Sstevel@tonic-gate 	if (log_maxzones < maxzones)
2200Sstevel@tonic-gate 		maxzones = log_maxzones;
2210Sstevel@tonic-gate 	log_minorspace = id_space_create("logminor_space", LOG_LOGMIN + 1,
2220Sstevel@tonic-gate 	    L_MAXMIN32);
2230Sstevel@tonic-gate 	/*
2240Sstevel@tonic-gate 	 * Put ourselves on the ZSD list.  Note that zones have not been
2250Sstevel@tonic-gate 	 * initialized yet, but our constructor will be called on the global
2260Sstevel@tonic-gate 	 * zone when they are.
2270Sstevel@tonic-gate 	 */
2280Sstevel@tonic-gate 	zone_key_create(&log_zone_key, log_zoneinit, NULL, log_zonefree);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	/*
2310Sstevel@tonic-gate 	 * Initialize backlog structure.
2320Sstevel@tonic-gate 	 */
2330Sstevel@tonic-gate 	log_backlog.log_zoneid = GLOBAL_ZONEID;
2340Sstevel@tonic-gate 	log_backlog.log_minor = LOG_BACKLOG;
2350Sstevel@tonic-gate 
2361259Sns92644 	/* Allocate kmem cache for conslog's log structures */
2371259Sns92644 	log_cons_cache = kmem_cache_create("log_cons_cache",
2381259Sns92644 	    sizeof (struct log), 0, log_cons_constructor, log_cons_destructor,
2391259Sns92644 	    NULL, NULL, NULL, 0);
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	/*
2420Sstevel@tonic-gate 	 * Let the logging begin.
2430Sstevel@tonic-gate 	 */
2440Sstevel@tonic-gate 	log_update(&log_backlog, log_backlogq, SL_CONSOLE, log_console);
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	/*
2470Sstevel@tonic-gate 	 * Now that logging is enabled, emit the SunOS banner.
2480Sstevel@tonic-gate 	 */
2490Sstevel@tonic-gate 	printf("\rSunOS Release %s Version %s %u-bit\n",
2500Sstevel@tonic-gate 	    utsname.release, utsname.version, NBBY * (uint_t)sizeof (void *));
251*12041SJohn.Beck@Sun.COM 	printf("Copyright (c) 1983, 2010, Oracle and/or its affiliates. "
252*12041SJohn.Beck@Sun.COM 	    "All rights reserved.\n");
2530Sstevel@tonic-gate #ifdef DEBUG
2540Sstevel@tonic-gate 	printf("DEBUG enabled\n");
2550Sstevel@tonic-gate #endif
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /*
2591259Sns92644  * Allocate a log device corresponding to supplied device type.
2601259Sns92644  * Both devices are clonable. /dev/log devices are allocated per zone.
2611259Sns92644  * /dev/conslog devices are allocated from kmem cache.
2620Sstevel@tonic-gate  */
2630Sstevel@tonic-gate log_t *
log_alloc(minor_t type)2640Sstevel@tonic-gate log_alloc(minor_t type)
2650Sstevel@tonic-gate {
2660Sstevel@tonic-gate 	zone_t *zptr = curproc->p_zone;
2670Sstevel@tonic-gate 	log_zone_t *lzp;
2680Sstevel@tonic-gate 	log_t *lp;
2690Sstevel@tonic-gate 	int i;
2701259Sns92644 	minor_t minor;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	if (type == LOG_CONSMIN) {
2730Sstevel@tonic-gate 
2741259Sns92644 		/*
2751259Sns92644 		 * Return a write-only /dev/conslog device.
2761259Sns92644 		 * No point allocating log_t until there's a free minor number.
2771259Sns92644 		 */
2781259Sns92644 		minor = (minor_t)id_alloc(log_minorspace);
2791259Sns92644 		lp = kmem_cache_alloc(log_cons_cache, KM_SLEEP);
2801259Sns92644 		lp->log_minor = minor;
2811259Sns92644 		return (lp);
2821259Sns92644 	} else {
2831259Sns92644 		ASSERT(type == LOG_LOGMIN);
2840Sstevel@tonic-gate 
2851259Sns92644 		lzp = zone_getspecific(log_zone_key, zptr);
2861259Sns92644 		ASSERT(lzp != NULL);
2870Sstevel@tonic-gate 
2881259Sns92644 		/* search for an available /dev/log device for the zone */
2891259Sns92644 		for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) {
2901259Sns92644 			lp = &lzp->lz_clones[i];
2911259Sns92644 			if (lp->log_inuse == 0)
2921259Sns92644 				break;
2931259Sns92644 		}
2941259Sns92644 		if (i > LOG_LOGMAXIDX)
2951259Sns92644 			lp = NULL;
2961259Sns92644 		else
2971259Sns92644 			/* Indicate which device type */
2981259Sns92644 			lp->log_major = LOG_LOGMIN;
2991259Sns92644 		return (lp);
3000Sstevel@tonic-gate 	}
3011259Sns92644 }
3021259Sns92644 
3031259Sns92644 void
log_free(log_t * lp)3041259Sns92644 log_free(log_t *lp)
3051259Sns92644 {
3061259Sns92644 	id_free(log_minorspace, lp->log_minor);
3071259Sns92644 	kmem_cache_free(log_cons_cache, lp);
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate /*
3110Sstevel@tonic-gate  * Move console messages from src to dst.  The time of day isn't known
3120Sstevel@tonic-gate  * early in boot, so fix up the message timestamps if necessary.
3130Sstevel@tonic-gate  */
3140Sstevel@tonic-gate static void
log_conswitch(log_t * src,log_t * dst)3150Sstevel@tonic-gate log_conswitch(log_t *src, log_t *dst)
3160Sstevel@tonic-gate {
3170Sstevel@tonic-gate 	mblk_t *mp;
3180Sstevel@tonic-gate 	mblk_t *hmp = NULL;
3190Sstevel@tonic-gate 	mblk_t *tmp = NULL;
3200Sstevel@tonic-gate 	log_ctl_t *hlc;
3210Sstevel@tonic-gate 
3226769Sja97890 	while ((mp = getq_noenab(src->log_q, 0)) != NULL) {
3230Sstevel@tonic-gate 		log_ctl_t *lc = (log_ctl_t *)mp->b_rptr;
3240Sstevel@tonic-gate 		lc->flags |= SL_LOGONLY;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		/*
3274123Sdm120769 		 * The ttime is written with 0 in log_sensmsg() only when
3282771Skk112340 		 * good gethrestime_sec() data is not available to store in
3292771Skk112340 		 * the log_ctl_t in the early boot phase.
3300Sstevel@tonic-gate 		 */
3312771Skk112340 		if (lc->ttime == 0) {
3320Sstevel@tonic-gate 			/*
3330Sstevel@tonic-gate 			 * Look ahead to first early boot message with time.
3340Sstevel@tonic-gate 			 */
3350Sstevel@tonic-gate 			if (hmp) {
3360Sstevel@tonic-gate 				tmp->b_next = mp;
3370Sstevel@tonic-gate 				tmp = mp;
3380Sstevel@tonic-gate 			} else
3390Sstevel@tonic-gate 				hmp = tmp = mp;
3400Sstevel@tonic-gate 			continue;
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 		while (hmp) {
3440Sstevel@tonic-gate 			tmp = hmp->b_next;
3450Sstevel@tonic-gate 			hmp->b_next = NULL;
3460Sstevel@tonic-gate 			hlc = (log_ctl_t *)hmp->b_rptr;
3470Sstevel@tonic-gate 			/*
3480Sstevel@tonic-gate 			 * Calculate hrestime for an early log message with
3490Sstevel@tonic-gate 			 * an invalid time stamp. We know:
3500Sstevel@tonic-gate 			 *  - the lbolt of the invalid time stamp.
3510Sstevel@tonic-gate 			 *  - the hrestime and lbolt of the first valid
3520Sstevel@tonic-gate 			 *    time stamp.
3530Sstevel@tonic-gate 			 */
3540Sstevel@tonic-gate 			hlc->ttime = lc->ttime - (lc->ltime - hlc->ltime) / hz;
3550Sstevel@tonic-gate 			(void) putq(dst->log_q, hmp);
3560Sstevel@tonic-gate 			hmp = tmp;
3570Sstevel@tonic-gate 		}
3580Sstevel@tonic-gate 		(void) putq(dst->log_q, mp);
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 	while (hmp) {
3610Sstevel@tonic-gate 		tmp = hmp->b_next;
3620Sstevel@tonic-gate 		hmp->b_next = NULL;
3630Sstevel@tonic-gate 		hlc = (log_ctl_t *)hmp->b_rptr;
36411066Srafael.vanoni@sun.com 		hlc->ttime = gethrestime_sec() -
36511066Srafael.vanoni@sun.com 		    (ddi_get_lbolt() - hlc->ltime) / hz;
3660Sstevel@tonic-gate 		(void) putq(dst->log_q, hmp);
3670Sstevel@tonic-gate 		hmp = tmp;
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 	dst->log_overflow = src->log_overflow;
3700Sstevel@tonic-gate 	src->log_flags = 0;
3710Sstevel@tonic-gate 	dst->log_flags = SL_CONSOLE;
3720Sstevel@tonic-gate 	log_consq = dst->log_q;
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate /*
3760Sstevel@tonic-gate  * Set the fields in the 'target' clone to the specified values.
3770Sstevel@tonic-gate  * Then, look at all clones to determine which message types are
3780Sstevel@tonic-gate  * currently active and which clone is the primary console queue.
3790Sstevel@tonic-gate  * If the primary console queue changes to or from the backlog
3800Sstevel@tonic-gate  * queue, copy all messages from backlog to primary or vice versa.
3810Sstevel@tonic-gate  */
3820Sstevel@tonic-gate void
log_update(log_t * target,queue_t * q,short flags,log_filter_t * filter)3830Sstevel@tonic-gate log_update(log_t *target, queue_t *q, short flags, log_filter_t *filter)
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	log_t *lp;
3860Sstevel@tonic-gate 	short active = SL_CONSOLE;
3870Sstevel@tonic-gate 	zone_t *zptr = NULL;
3880Sstevel@tonic-gate 	log_zone_t *lzp;
3890Sstevel@tonic-gate 	zoneid_t zoneid = target->log_zoneid;
3900Sstevel@tonic-gate 	int i;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	log_enter();
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	if (q != NULL)
3950Sstevel@tonic-gate 		target->log_q = q;
3960Sstevel@tonic-gate 	target->log_wanted = filter;
3970Sstevel@tonic-gate 	target->log_flags = flags;
3980Sstevel@tonic-gate 	target->log_overflow = 0;
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/*
4010Sstevel@tonic-gate 	 * Need to special case the global zone here since this may be
4020Sstevel@tonic-gate 	 * called before zone_init.
4030Sstevel@tonic-gate 	 */
4040Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID) {
4050Sstevel@tonic-gate 		lzp = &log_global;
4060Sstevel@tonic-gate 	} else if ((zptr = zone_find_by_id(zoneid)) == NULL) {
4070Sstevel@tonic-gate 		log_exit();
4080Sstevel@tonic-gate 		return;		/* zone is being destroyed, ignore update */
4090Sstevel@tonic-gate 	} else {
4100Sstevel@tonic-gate 		lzp = zone_getspecific(log_zone_key, zptr);
4110Sstevel@tonic-gate 	}
4120Sstevel@tonic-gate 	ASSERT(lzp != NULL);
4130Sstevel@tonic-gate 	for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) {
4140Sstevel@tonic-gate 		lp = &lzp->lz_clones[i];
4150Sstevel@tonic-gate 		if (zoneid == GLOBAL_ZONEID && (lp->log_flags & SL_CONSOLE))
4160Sstevel@tonic-gate 			log_consq = lp->log_q;
4170Sstevel@tonic-gate 		active |= lp->log_flags;
4180Sstevel@tonic-gate 	}
4190Sstevel@tonic-gate 	lzp->lz_active = active;
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	if (zptr)
4220Sstevel@tonic-gate 		zone_rele(zptr);
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	if (log_consq == target->log_q) {
4250Sstevel@tonic-gate 		if (flags & SL_CONSOLE)
4260Sstevel@tonic-gate 			log_conswitch(&log_backlog, target);
4270Sstevel@tonic-gate 		else
4280Sstevel@tonic-gate 			log_conswitch(target, &log_backlog);
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 	target->log_q = q;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	log_exit();
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate /*ARGSUSED*/
4360Sstevel@tonic-gate int
log_error(log_t * lp,log_ctl_t * lc)4370Sstevel@tonic-gate log_error(log_t *lp, log_ctl_t *lc)
4380Sstevel@tonic-gate {
4390Sstevel@tonic-gate 	if ((lc->pri & LOG_FACMASK) == LOG_KERN)
4400Sstevel@tonic-gate 		lc->pri = LOG_KERN | LOG_ERR;
4410Sstevel@tonic-gate 	return (1);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate int
log_trace(log_t * lp,log_ctl_t * lc)4450Sstevel@tonic-gate log_trace(log_t *lp, log_ctl_t *lc)
4460Sstevel@tonic-gate {
4470Sstevel@tonic-gate 	trace_ids_t *tid = (trace_ids_t *)lp->log_data->b_rptr;
4480Sstevel@tonic-gate 	trace_ids_t *tidend = (trace_ids_t *)lp->log_data->b_wptr;
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	/*
4510Sstevel@tonic-gate 	 * We use `tid + 1 <= tidend' here rather than the more traditional
4520Sstevel@tonic-gate 	 * `tid < tidend', since the former ensures that there's at least
4530Sstevel@tonic-gate 	 * `sizeof (trace_ids_t)' bytes available before executing the
4540Sstevel@tonic-gate 	 * loop, whereas the latter only ensures that there's a single byte.
4550Sstevel@tonic-gate 	 */
4560Sstevel@tonic-gate 	for (; tid + 1 <= tidend; tid++) {
4570Sstevel@tonic-gate 		if (tid->ti_level < lc->level && tid->ti_level >= 0)
4580Sstevel@tonic-gate 			continue;
4590Sstevel@tonic-gate 		if (tid->ti_mid != lc->mid && tid->ti_mid >= 0)
4600Sstevel@tonic-gate 			continue;
4610Sstevel@tonic-gate 		if (tid->ti_sid != lc->sid && tid->ti_sid >= 0)
4620Sstevel@tonic-gate 			continue;
4630Sstevel@tonic-gate 		if ((lc->pri & LOG_FACMASK) == LOG_KERN)
4640Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_DEBUG;
4650Sstevel@tonic-gate 		return (1);
4660Sstevel@tonic-gate 	}
4670Sstevel@tonic-gate 	return (0);
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate /*ARGSUSED*/
4710Sstevel@tonic-gate int
log_console(log_t * lp,log_ctl_t * lc)4720Sstevel@tonic-gate log_console(log_t *lp, log_ctl_t *lc)
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate 	if ((lc->pri & LOG_FACMASK) == LOG_KERN) {
4750Sstevel@tonic-gate 		if (lc->flags & SL_FATAL)
4760Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_CRIT;
4770Sstevel@tonic-gate 		else if (lc->flags & SL_ERROR)
4780Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_ERR;
4790Sstevel@tonic-gate 		else if (lc->flags & SL_WARN)
4800Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_WARNING;
4810Sstevel@tonic-gate 		else if (lc->flags & SL_NOTE)
4820Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_NOTICE;
4830Sstevel@tonic-gate 		else if (lc->flags & SL_TRACE)
4840Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_DEBUG;
4850Sstevel@tonic-gate 		else
4860Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_INFO;
4870Sstevel@tonic-gate 	}
4880Sstevel@tonic-gate 	return (1);
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate mblk_t *
log_makemsg(int mid,int sid,int level,int sl,int pri,void * msg,size_t size,int on_intr)4920Sstevel@tonic-gate log_makemsg(int mid, int sid, int level, int sl, int pri, void *msg,
4930Sstevel@tonic-gate 	size_t size, int on_intr)
4940Sstevel@tonic-gate {
4950Sstevel@tonic-gate 	mblk_t *mp = NULL;
4960Sstevel@tonic-gate 	mblk_t *mp2;
4970Sstevel@tonic-gate 	log_ctl_t *lc;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	if (size <= LOG_MSGSIZE &&
5000Sstevel@tonic-gate 	    (on_intr || log_freeq->q_count > log_freeq->q_lowat))
5016769Sja97890 		mp = getq_noenab(log_freeq, 0);
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	if (mp == NULL) {
5040Sstevel@tonic-gate 		if (on_intr ||
5050Sstevel@tonic-gate 		    (mp = allocb(sizeof (log_ctl_t), BPRI_HI)) == NULL ||
5060Sstevel@tonic-gate 		    (mp2 = allocb(MAX(size, LOG_MSGSIZE), BPRI_HI)) == NULL) {
5070Sstevel@tonic-gate 			freemsg(mp);
5080Sstevel@tonic-gate 			return (NULL);
5090Sstevel@tonic-gate 		}
5100Sstevel@tonic-gate 		DB_TYPE(mp) = M_PROTO;
5110Sstevel@tonic-gate 		mp->b_wptr += sizeof (log_ctl_t);
5120Sstevel@tonic-gate 		mp->b_cont = mp2;
5130Sstevel@tonic-gate 	} else {
5140Sstevel@tonic-gate 		mp2 = mp->b_cont;
5150Sstevel@tonic-gate 		mp2->b_wptr = mp2->b_rptr;
5160Sstevel@tonic-gate 	}
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	lc = (log_ctl_t *)mp->b_rptr;
5190Sstevel@tonic-gate 	lc->mid = mid;
5200Sstevel@tonic-gate 	lc->sid = sid;
5210Sstevel@tonic-gate 	lc->level = level;
5220Sstevel@tonic-gate 	lc->flags = sl;
5230Sstevel@tonic-gate 	lc->pri = pri;
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 	bcopy(msg, mp2->b_wptr, size - 1);
5260Sstevel@tonic-gate 	mp2->b_wptr[size - 1] = '\0';
5270Sstevel@tonic-gate 	mp2->b_wptr += strlen((char *)mp2->b_wptr) + 1;
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	return (mp);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate void
log_freemsg(mblk_t * mp)5330Sstevel@tonic-gate log_freemsg(mblk_t *mp)
5340Sstevel@tonic-gate {
5350Sstevel@tonic-gate 	mblk_t *mp2 = mp->b_cont;
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	ASSERT(MBLKL(mp) == sizeof (log_ctl_t));
5380Sstevel@tonic-gate 	ASSERT(mp2->b_rptr == mp2->b_datap->db_base);
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	if ((log_freeq->q_flag & QFULL) == 0 &&
5410Sstevel@tonic-gate 	    MBLKL(mp2) <= LOG_MSGSIZE && MBLKSIZE(mp2) >= LOG_MSGSIZE)
5420Sstevel@tonic-gate 		(void) putq(log_freeq, mp);
5430Sstevel@tonic-gate 	else
5440Sstevel@tonic-gate 		freemsg(mp);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate void
log_sendmsg(mblk_t * mp,zoneid_t zoneid)5480Sstevel@tonic-gate log_sendmsg(mblk_t *mp, zoneid_t zoneid)
5490Sstevel@tonic-gate {
5500Sstevel@tonic-gate 	log_t *lp;
5510Sstevel@tonic-gate 	char *src, *dst;
5520Sstevel@tonic-gate 	mblk_t *mp2 = mp->b_cont;
5530Sstevel@tonic-gate 	log_ctl_t *lc = (log_ctl_t *)mp->b_rptr;
5540Sstevel@tonic-gate 	int flags, fac;
5550Sstevel@tonic-gate 	off_t facility = 0;
5560Sstevel@tonic-gate 	off_t body = 0;
5570Sstevel@tonic-gate 	zone_t *zptr = NULL;
5580Sstevel@tonic-gate 	log_zone_t *lzp;
5590Sstevel@tonic-gate 	int i;
5600Sstevel@tonic-gate 	int backlog;
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	/*
5630Sstevel@tonic-gate 	 * Need to special case the global zone here since this may be
5640Sstevel@tonic-gate 	 * called before zone_init.
5650Sstevel@tonic-gate 	 */
5660Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID) {
5670Sstevel@tonic-gate 		lzp = &log_global;
5680Sstevel@tonic-gate 	} else if ((zptr = zone_find_by_id(zoneid)) == NULL) {
5690Sstevel@tonic-gate 		/* specified zone doesn't exist, free message and return */
5700Sstevel@tonic-gate 		log_freemsg(mp);
5710Sstevel@tonic-gate 		return;
5720Sstevel@tonic-gate 	} else {
5730Sstevel@tonic-gate 		lzp = zone_getspecific(log_zone_key, zptr);
5740Sstevel@tonic-gate 	}
5750Sstevel@tonic-gate 	ASSERT(lzp != NULL);
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	if ((lc->flags & lzp->lz_active) == 0) {
5780Sstevel@tonic-gate 		if (zptr)
5790Sstevel@tonic-gate 			zone_rele(zptr);
5800Sstevel@tonic-gate 		log_freemsg(mp);
5810Sstevel@tonic-gate 		return;
5820Sstevel@tonic-gate 	}
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	if (panicstr) {
5850Sstevel@tonic-gate 		/*
5860Sstevel@tonic-gate 		 * Raise the console queue's q_hiwat to ensure that we
5870Sstevel@tonic-gate 		 * capture all panic messages.
5880Sstevel@tonic-gate 		 */
5890Sstevel@tonic-gate 		log_consq->q_hiwat = 2 * LOG_HIWAT;
5900Sstevel@tonic-gate 		log_consq->q_flag &= ~QFULL;
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 		/* Message was created while panicking. */
5930Sstevel@tonic-gate 		lc->flags |= SL_PANICMSG;
5940Sstevel@tonic-gate 	}
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	src = (char *)mp2->b_rptr;
5970Sstevel@tonic-gate 	dst = strstr(src, "FACILITY_AND_PRIORITY] ");
5980Sstevel@tonic-gate 	if (dst != NULL) {
5990Sstevel@tonic-gate 		facility = dst - src;
6000Sstevel@tonic-gate 		body = facility + 23; /* strlen("FACILITY_AND_PRIORITY] ") */
6010Sstevel@tonic-gate 	}
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	log_enter();
6040Sstevel@tonic-gate 
6052771Skk112340 	/*
6064123Sdm120769 	 * In the early boot phase hrestime is invalid, then timechanged is 0.
6074123Sdm120769 	 * If hrestime is not valid, the ttime is set to 0 here and the correct
6084123Sdm120769 	 * ttime is calculated in log_conswitch() later. The log_conswitch()
6094123Sdm120769 	 * calculation to determine the correct ttime does not use ttime data
6104123Sdm120769 	 * from these log_ctl_t structures; it only uses ttime from log_ctl_t's
6114123Sdm120769 	 * that contain good data.
6124123Sdm120769 	 *
6132771Skk112340 	 */
61411066Srafael.vanoni@sun.com 	lc->ltime = ddi_get_lbolt();
6154123Sdm120769 	if (timechanged) {
6162771Skk112340 		lc->ttime = gethrestime_sec();
6172771Skk112340 	} else {
6182771Skk112340 		lc->ttime = 0;
6192771Skk112340 	}
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 	flags = lc->flags & lzp->lz_active;
6220Sstevel@tonic-gate 	log_seq_no[flags & SL_ERROR]++;
6230Sstevel@tonic-gate 	log_seq_no[flags & SL_TRACE]++;
6240Sstevel@tonic-gate 	log_seq_no[flags & SL_CONSOLE]++;
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	/*
6270Sstevel@tonic-gate 	 * If this is in the global zone, start with the backlog, then
6280Sstevel@tonic-gate 	 * walk through the clone logs.  If not, just do the clone logs.
6290Sstevel@tonic-gate 	 */
6300Sstevel@tonic-gate 	backlog = (zoneid == GLOBAL_ZONEID);
6310Sstevel@tonic-gate 	i = LOG_LOGMINIDX;
6320Sstevel@tonic-gate 	while (i <= LOG_LOGMAXIDX) {
6330Sstevel@tonic-gate 		if (backlog) {
6340Sstevel@tonic-gate 			/*
6350Sstevel@tonic-gate 			 * Do the backlog this time, then start on the
6360Sstevel@tonic-gate 			 * others.
6370Sstevel@tonic-gate 			 */
6380Sstevel@tonic-gate 			backlog = 0;
6390Sstevel@tonic-gate 			lp = &log_backlog;
6400Sstevel@tonic-gate 		} else {
6410Sstevel@tonic-gate 			lp = &lzp->lz_clones[i++];
6420Sstevel@tonic-gate 		}
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 		if ((lp->log_flags & flags) && lp->log_wanted(lp, lc)) {
6450Sstevel@tonic-gate 			if (canput(lp->log_q)) {
6460Sstevel@tonic-gate 				lp->log_overflow = 0;
6470Sstevel@tonic-gate 				lc->seq_no = log_seq_no[lp->log_flags];
6480Sstevel@tonic-gate 				if ((mp2 = copymsg(mp)) == NULL)
6490Sstevel@tonic-gate 					break;
6500Sstevel@tonic-gate 				if (facility != 0) {
6510Sstevel@tonic-gate 					src = (char *)mp2->b_cont->b_rptr;
6520Sstevel@tonic-gate 					dst = src + facility;
6530Sstevel@tonic-gate 					fac = (lc->pri & LOG_FACMASK) >> 3;
6540Sstevel@tonic-gate 					dst += snprintf(dst,
6550Sstevel@tonic-gate 					    LOG_FACSIZE + LOG_PRISIZE, "%s.%s",
6560Sstevel@tonic-gate 					    log_fac[MIN(fac, LOG_NFACILITIES)],
6570Sstevel@tonic-gate 					    log_pri[lc->pri & LOG_PRIMASK]);
6580Sstevel@tonic-gate 					src += body - 2; /* copy "] " too */
6590Sstevel@tonic-gate 					while (*src != '\0')
6600Sstevel@tonic-gate 						*dst++ = *src++;
6610Sstevel@tonic-gate 					*dst++ = '\0';
6620Sstevel@tonic-gate 					mp2->b_cont->b_wptr = (uchar_t *)dst;
6630Sstevel@tonic-gate 				}
6640Sstevel@tonic-gate 				(void) putq(lp->log_q, mp2);
6650Sstevel@tonic-gate 			} else if (++lp->log_overflow == 1) {
6660Sstevel@tonic-gate 				if (lp->log_q == log_consq) {
6670Sstevel@tonic-gate 					console_printf(log_overflow_msg,
6680Sstevel@tonic-gate 					    lp->log_minor,
6690Sstevel@tonic-gate 					    " -- is syslogd(1M) running?");
6700Sstevel@tonic-gate 				} else {
6710Sstevel@tonic-gate 					printf(log_overflow_msg,
6720Sstevel@tonic-gate 					    lp->log_minor, "");
6730Sstevel@tonic-gate 				}
6740Sstevel@tonic-gate 			}
6750Sstevel@tonic-gate 		}
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 	if (zptr)
6790Sstevel@tonic-gate 		zone_rele(zptr);
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	if ((flags & SL_CONSOLE) && (lc->pri & LOG_FACMASK) == LOG_KERN) {
6820Sstevel@tonic-gate 		if ((mp2 == NULL || log_consq == log_backlogq || panicstr) &&
6830Sstevel@tonic-gate 		    (lc->flags & SL_LOGONLY) == 0)
6840Sstevel@tonic-gate 			console_printf("%s", (char *)mp->b_cont->b_rptr + body);
6850Sstevel@tonic-gate 		if ((lc->flags & SL_CONSONLY) == 0 &&
6860Sstevel@tonic-gate 		    (mp2 = copymsg(mp)) != NULL) {
6870Sstevel@tonic-gate 			mp2->b_cont->b_rptr += body;
6880Sstevel@tonic-gate 			if (log_recentq->q_flag & QFULL)
6896769Sja97890 				freemsg(getq_noenab(log_recentq, 0));
6900Sstevel@tonic-gate 			(void) putq(log_recentq, mp2);
6910Sstevel@tonic-gate 		}
6920Sstevel@tonic-gate 	}
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 	log_freemsg(mp);
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	log_exit();
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate  * Print queued messages to console.
7010Sstevel@tonic-gate  */
7020Sstevel@tonic-gate void
log_printq(queue_t * qfirst)7030Sstevel@tonic-gate log_printq(queue_t *qfirst)
7040Sstevel@tonic-gate {
7050Sstevel@tonic-gate 	mblk_t *mp;
7060Sstevel@tonic-gate 	queue_t *q, *qlast;
7070Sstevel@tonic-gate 	char *cp, *msgp;
7080Sstevel@tonic-gate 	log_ctl_t *lc;
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate 	/*
7110Sstevel@tonic-gate 	 * Look ahead to first queued message in the stream.
7120Sstevel@tonic-gate 	 */
7130Sstevel@tonic-gate 	qlast = NULL;
7140Sstevel@tonic-gate 	do {
7150Sstevel@tonic-gate 		for (q = qfirst; q->q_next != qlast; q = q->q_next)
7160Sstevel@tonic-gate 			continue;
7170Sstevel@tonic-gate 		for (mp = q->q_first; mp != NULL; mp = mp->b_next) {
7180Sstevel@tonic-gate 			lc = (log_ctl_t *)mp->b_rptr;
7190Sstevel@tonic-gate 			/*
7200Sstevel@tonic-gate 			 * Check if message is already displayed at
7210Sstevel@tonic-gate 			 * /dev/console.
7220Sstevel@tonic-gate 			 */
7230Sstevel@tonic-gate 			if (lc->flags & SL_PANICMSG)
7240Sstevel@tonic-gate 				continue;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 			cp = (char *)mp->b_cont->b_rptr;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 			/* Strip off the message ID. */
7290Sstevel@tonic-gate 			if ((msgp = strstr(cp, "[ID ")) != NULL &&
7300Sstevel@tonic-gate 			    (msgp = strstr(msgp,  "] ")) != NULL) {
7310Sstevel@tonic-gate 				cp = msgp + 2;
7320Sstevel@tonic-gate 			}
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 			/*
7350Sstevel@tonic-gate 			 * Using console_printf instead of printf to avoid
7360Sstevel@tonic-gate 			 * queueing messages to log_consq.
7370Sstevel@tonic-gate 			 */
7380Sstevel@tonic-gate 			console_printf("%s", cp);
7390Sstevel@tonic-gate 		}
7400Sstevel@tonic-gate 	} while ((qlast = q) != qfirst);
7410Sstevel@tonic-gate }
7421259Sns92644 
7431259Sns92644 /* ARGSUSED */
7441259Sns92644 static int
log_cons_constructor(void * buf,void * cdrarg,int kmflags)7451259Sns92644 log_cons_constructor(void *buf, void *cdrarg, int kmflags)
7461259Sns92644 {
7471259Sns92644 	struct log *lp = buf;
7481259Sns92644 
7491259Sns92644 	lp->log_zoneid = GLOBAL_ZONEID;
7501259Sns92644 	lp->log_major = LOG_CONSMIN;	/* Indicate which device type */
7511259Sns92644 	lp->log_data = NULL;
7521259Sns92644 	return (0);
7531259Sns92644 }
7541259Sns92644 
7551259Sns92644 /* ARGSUSED */
7561259Sns92644 static void
log_cons_destructor(void * buf,void * cdrarg)7571259Sns92644 log_cons_destructor(void *buf, void *cdrarg)
7581259Sns92644 {
7591259Sns92644 	struct log *lp = buf;
7601259Sns92644 
7611259Sns92644 	ASSERT(lp->log_zoneid == GLOBAL_ZONEID);
7621259Sns92644 	ASSERT(lp->log_major == LOG_CONSMIN);
7631259Sns92644 	ASSERT(lp->log_data == NULL);
7641259Sns92644 }
765