xref: /illumos-gate/usr/src/uts/common/os/logsubr.c (revision b210e777)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
505b96de2Smjnelson  * Common Development and Distribution License (the "License").
605b96de2Smjnelson  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2105b96de2Smjnelson 
227c478bd9Sstevel@tonic-gate /*
236112cec5SJoshua M. Clulow  * Copyright 2020 Oxide Computer Company
24ba91f08bSGary Mills  * Copyright (c) 2013 Gary Mills
25861a9162SJohn Beck  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/param.h>
307c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
317c478bd9Sstevel@tonic-gate #include <sys/systm.h>
327c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
337c478bd9Sstevel@tonic-gate #include <sys/stream.h>
347c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
357c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
377c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
387c478bd9Sstevel@tonic-gate #include <sys/log.h>
397c478bd9Sstevel@tonic-gate #include <sys/spl.h>
407c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
417c478bd9Sstevel@tonic-gate #include <sys/console.h>
427c478bd9Sstevel@tonic-gate #include <sys/debug.h>
437c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
447c478bd9Sstevel@tonic-gate #include <sys/id_space.h>
457c478bd9Sstevel@tonic-gate #include <sys/zone.h>
466112cec5SJoshua M. Clulow #include <sys/bootbanner.h>
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate log_zone_t log_global;
497c478bd9Sstevel@tonic-gate queue_t *log_consq;
507c478bd9Sstevel@tonic-gate queue_t *log_backlogq;
517c478bd9Sstevel@tonic-gate queue_t *log_intrq;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #define	LOG_PRISIZE	8	/* max priority size: 7 characters + null */
547c478bd9Sstevel@tonic-gate #define	LOG_FACSIZE	9	/* max priority size: 8 characters + null */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate static krwlock_t log_rwlock;
577c478bd9Sstevel@tonic-gate static int log_rwlock_depth;
587c478bd9Sstevel@tonic-gate static int log_seq_no[SL_CONSOLE + 1];
597c478bd9Sstevel@tonic-gate static stdata_t log_fakestr;
607c478bd9Sstevel@tonic-gate static id_space_t *log_minorspace;
617c478bd9Sstevel@tonic-gate static log_t log_backlog;
62068ccd7aSns static struct kmem_cache *log_cons_cache;	/* log_t cache */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate static queue_t *log_recentq;
657c478bd9Sstevel@tonic-gate static queue_t *log_freeq;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate static zone_key_t log_zone_key;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate static char log_overflow_msg[] = "message overflow on /dev/log minor #%d%s\n";
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static char log_pri[LOG_PRIMASK + 1][LOG_PRISIZE] = {
727c478bd9Sstevel@tonic-gate 	"emerg",	"alert",	"crit",		"error",
737c478bd9Sstevel@tonic-gate 	"warning",	"notice",	"info",		"debug"
747c478bd9Sstevel@tonic-gate };
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static char log_fac[LOG_NFACILITIES + 1][LOG_FACSIZE] = {
777c478bd9Sstevel@tonic-gate 	"kern",		"user",		"mail",		"daemon",
787c478bd9Sstevel@tonic-gate 	"auth",		"syslog",	"lpr",		"news",
79ba91f08bSGary Mills 	"uucp",		"altcron",	"authpriv",	"ftp",
80ba91f08bSGary Mills 	"ntp",		"audit",	"console",	"cron",
817c478bd9Sstevel@tonic-gate 	"local0",	"local1",	"local2",	"local3",
827c478bd9Sstevel@tonic-gate 	"local4",	"local5",	"local6",	"local7",
837c478bd9Sstevel@tonic-gate 	"unknown"
847c478bd9Sstevel@tonic-gate };
85068ccd7aSns static int log_cons_constructor(void *, void *, int);
86068ccd7aSns static void log_cons_destructor(void *, void *);
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Get exclusive access to the logging system; this includes all minor
907c478bd9Sstevel@tonic-gate  * devices.  We use an rwlock rather than a mutex because hold times
917c478bd9Sstevel@tonic-gate  * are potentially long, so we don't want to waste cycles in adaptive mutex
927c478bd9Sstevel@tonic-gate  * spin (rwlocks always block when contended).  Note that we explicitly
937c478bd9Sstevel@tonic-gate  * support recursive calls (e.g. printf() calls foo() calls printf()).
947c478bd9Sstevel@tonic-gate  *
957c478bd9Sstevel@tonic-gate  * Clients may use log_enter() / log_exit() to guarantee that a group
967c478bd9Sstevel@tonic-gate  * of messages is treated atomically (i.e. they appear in order and are
977c478bd9Sstevel@tonic-gate  * not interspersed with any other messages), e.g. for multiline printf().
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * This could probably be changed to a per-zone lock if contention becomes
1007c478bd9Sstevel@tonic-gate  * an issue.
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate void
log_enter(void)1037c478bd9Sstevel@tonic-gate log_enter(void)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	if (rw_owner(&log_rwlock) != curthread)
1067c478bd9Sstevel@tonic-gate 		rw_enter(&log_rwlock, RW_WRITER);
1077c478bd9Sstevel@tonic-gate 	log_rwlock_depth++;
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate void
log_exit(void)1117c478bd9Sstevel@tonic-gate log_exit(void)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 	if (--log_rwlock_depth == 0)
1147c478bd9Sstevel@tonic-gate 		rw_exit(&log_rwlock);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate void
log_flushq(queue_t * q)1187c478bd9Sstevel@tonic-gate log_flushq(queue_t *q)
1197c478bd9Sstevel@tonic-gate {
1207c478bd9Sstevel@tonic-gate 	mblk_t *mp;
1217c478bd9Sstevel@tonic-gate 	log_t *lp = (log_t *)q->q_ptr;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	/* lp will be NULL if the queue was created via log_makeq */
124301ce41fSja 	while ((mp = getq_noenab(q, 0)) != NULL)
1257c478bd9Sstevel@tonic-gate 		log_sendmsg(mp, lp == NULL ? GLOBAL_ZONEID : lp->log_zoneid);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate /*
1297c478bd9Sstevel@tonic-gate  * Create a minimal queue with just enough fields filled in to support
1307c478bd9Sstevel@tonic-gate  * canput(9F), putq(9F), and getq_noenab(9F).  We set QNOENB to ensure
1317c478bd9Sstevel@tonic-gate  * that the queue will never be enabled.
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate static queue_t *
log_makeq(size_t lowat,size_t hiwat,void * ibc)1347c478bd9Sstevel@tonic-gate log_makeq(size_t lowat, size_t hiwat, void *ibc)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	queue_t *q;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	q = kmem_zalloc(sizeof (queue_t), KM_SLEEP);
1397c478bd9Sstevel@tonic-gate 	q->q_stream = &log_fakestr;
1407c478bd9Sstevel@tonic-gate 	q->q_flag = QISDRV | QMTSAFE | QNOENB | QREADR | QUSE;
1417c478bd9Sstevel@tonic-gate 	q->q_nfsrv = q;
1427c478bd9Sstevel@tonic-gate 	q->q_lowat = lowat;
1437c478bd9Sstevel@tonic-gate 	q->q_hiwat = hiwat;
1447c478bd9Sstevel@tonic-gate 	mutex_init(QLOCK(q), NULL, MUTEX_DRIVER, ibc);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	return (q);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * Initialize the log structure for a new zone.
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate static void *
log_zoneinit(zoneid_t zoneid)1537c478bd9Sstevel@tonic-gate log_zoneinit(zoneid_t zoneid)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	int i;
1567c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID)
1597c478bd9Sstevel@tonic-gate 		lzp = &log_global;	/* use statically allocated struct */
1607c478bd9Sstevel@tonic-gate 	else
1617c478bd9Sstevel@tonic-gate 		lzp = kmem_zalloc(sizeof (log_zone_t), KM_SLEEP);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NUMCLONES; i++) {
1647c478bd9Sstevel@tonic-gate 		lzp->lz_clones[i].log_minor =
1657c478bd9Sstevel@tonic-gate 		    (minor_t)id_alloc(log_minorspace);
1667c478bd9Sstevel@tonic-gate 		lzp->lz_clones[i].log_zoneid = zoneid;
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 	return (lzp);
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1727c478bd9Sstevel@tonic-gate static void
log_zonefree(zoneid_t zoneid,void * arg)1737c478bd9Sstevel@tonic-gate log_zonefree(zoneid_t zoneid, void *arg)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	log_zone_t *lzp = arg;
1767c478bd9Sstevel@tonic-gate 	int i;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	ASSERT(lzp != &log_global && zoneid != GLOBAL_ZONEID);
1797c478bd9Sstevel@tonic-gate 	if (lzp == NULL)
1807c478bd9Sstevel@tonic-gate 		return;
1817c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NUMCLONES; i++)
1827c478bd9Sstevel@tonic-gate 		id_free(log_minorspace, lzp->lz_clones[i].log_minor);
1837c478bd9Sstevel@tonic-gate 	kmem_free(lzp, sizeof (log_zone_t));
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1866112cec5SJoshua M. Clulow static void
log_bootbanner_print(const char * line,uint_t num)1876112cec5SJoshua M. Clulow log_bootbanner_print(const char *line, uint_t num)
1886112cec5SJoshua M. Clulow {
1896112cec5SJoshua M. Clulow 	const char *pfx = (num == 0) ? "\r" : "";
1906112cec5SJoshua M. Clulow 
1916112cec5SJoshua M. Clulow 	printf("%s%s\n", pfx, line);
1926112cec5SJoshua M. Clulow }
1936112cec5SJoshua M. Clulow 
1947c478bd9Sstevel@tonic-gate void
log_init(void)1957c478bd9Sstevel@tonic-gate log_init(void)
1967c478bd9Sstevel@tonic-gate {
1977c478bd9Sstevel@tonic-gate 	int log_maxzones;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	/*
2007c478bd9Sstevel@tonic-gate 	 * Create a backlog queue to consume console messages during periods
201bbf21555SRichard Lowe 	 * when there is no console reader (e.g. before syslogd(8) starts).
2027c478bd9Sstevel@tonic-gate 	 */
2037c478bd9Sstevel@tonic-gate 	log_backlogq = log_consq = log_makeq(0, LOG_HIWAT, NULL);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	/*
2067c478bd9Sstevel@tonic-gate 	 * Create a queue to hold free message of size <= LOG_MSGSIZE.
2077c478bd9Sstevel@tonic-gate 	 * Calls from high-level interrupt handlers will do a getq_noenab()
2087c478bd9Sstevel@tonic-gate 	 * from this queue, so its q_lock must be a maximum SPL spin lock.
2097c478bd9Sstevel@tonic-gate 	 */
2107c478bd9Sstevel@tonic-gate 	log_freeq = log_makeq(LOG_MINFREE, LOG_MAXFREE, (void *)ipltospl(SPL8));
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	/*
2137c478bd9Sstevel@tonic-gate 	 * Create a queue for messages from high-level interrupt context.
2147c478bd9Sstevel@tonic-gate 	 * These messages are drained via softcall, or explicitly by panic().
2157c478bd9Sstevel@tonic-gate 	 */
2167c478bd9Sstevel@tonic-gate 	log_intrq = log_makeq(0, LOG_HIWAT, (void *)ipltospl(SPL8));
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/*
21964b8fdd9SNick Ewins 	 * Create a queue to hold the most recent 64K of console messages.
2207c478bd9Sstevel@tonic-gate 	 * Useful for debugging.  Required by the "$<msgbuf" adb macro.
2217c478bd9Sstevel@tonic-gate 	 */
2227c478bd9Sstevel@tonic-gate 	log_recentq = log_makeq(0, LOG_RECENTSIZE, NULL);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	/*
2257c478bd9Sstevel@tonic-gate 	 * Create an id space for clone devices opened via /dev/log.
2267c478bd9Sstevel@tonic-gate 	 * Need to limit the number of zones to avoid exceeding the
2277c478bd9Sstevel@tonic-gate 	 * available minor number space.
2287c478bd9Sstevel@tonic-gate 	 */
2297c478bd9Sstevel@tonic-gate 	log_maxzones = (L_MAXMIN32 - LOG_LOGMIN) / LOG_NUMCLONES - 1;
2307c478bd9Sstevel@tonic-gate 	if (log_maxzones < maxzones)
2317c478bd9Sstevel@tonic-gate 		maxzones = log_maxzones;
2327c478bd9Sstevel@tonic-gate 	log_minorspace = id_space_create("logminor_space", LOG_LOGMIN + 1,
2337c478bd9Sstevel@tonic-gate 	    L_MAXMIN32);
2347c478bd9Sstevel@tonic-gate 	/*
2357c478bd9Sstevel@tonic-gate 	 * Put ourselves on the ZSD list.  Note that zones have not been
2367c478bd9Sstevel@tonic-gate 	 * initialized yet, but our constructor will be called on the global
2377c478bd9Sstevel@tonic-gate 	 * zone when they are.
2387c478bd9Sstevel@tonic-gate 	 */
2397c478bd9Sstevel@tonic-gate 	zone_key_create(&log_zone_key, log_zoneinit, NULL, log_zonefree);
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/*
2427c478bd9Sstevel@tonic-gate 	 * Initialize backlog structure.
2437c478bd9Sstevel@tonic-gate 	 */
2447c478bd9Sstevel@tonic-gate 	log_backlog.log_zoneid = GLOBAL_ZONEID;
2457c478bd9Sstevel@tonic-gate 	log_backlog.log_minor = LOG_BACKLOG;
2467c478bd9Sstevel@tonic-gate 
247068ccd7aSns 	/* Allocate kmem cache for conslog's log structures */
248068ccd7aSns 	log_cons_cache = kmem_cache_create("log_cons_cache",
249068ccd7aSns 	    sizeof (struct log), 0, log_cons_constructor, log_cons_destructor,
250068ccd7aSns 	    NULL, NULL, NULL, 0);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/*
2537c478bd9Sstevel@tonic-gate 	 * Let the logging begin.
2547c478bd9Sstevel@tonic-gate 	 */
2557c478bd9Sstevel@tonic-gate 	log_update(&log_backlog, log_backlogq, SL_CONSOLE, log_console);
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	/*
2586112cec5SJoshua M. Clulow 	 * Now that logging is enabled, emit the boot banner.
2597c478bd9Sstevel@tonic-gate 	 */
2606112cec5SJoshua M. Clulow #ifdef	LEGACY_BANNER
2617c478bd9Sstevel@tonic-gate 	printf("\rSunOS Release %s Version %s %u-bit\n",
2627c478bd9Sstevel@tonic-gate 	    utsname.release, utsname.version, NBBY * (uint_t)sizeof (void *));
263861a9162SJohn Beck 	printf("Copyright (c) 1983, 2010, Oracle and/or its affiliates. "
264861a9162SJohn Beck 	    "All rights reserved.\n");
2656112cec5SJoshua M. Clulow #else
266*b210e777SJoshua M. Clulow 	bootbanner_print(log_bootbanner_print);
2676112cec5SJoshua M. Clulow #endif
2687c478bd9Sstevel@tonic-gate #ifdef DEBUG
2697c478bd9Sstevel@tonic-gate 	printf("DEBUG enabled\n");
2707c478bd9Sstevel@tonic-gate #endif
2717c478bd9Sstevel@tonic-gate }
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate /*
274068ccd7aSns  * Allocate a log device corresponding to supplied device type.
275068ccd7aSns  * Both devices are clonable. /dev/log devices are allocated per zone.
276068ccd7aSns  * /dev/conslog devices are allocated from kmem cache.
2777c478bd9Sstevel@tonic-gate  */
2787c478bd9Sstevel@tonic-gate log_t *
log_alloc(minor_t type)2797c478bd9Sstevel@tonic-gate log_alloc(minor_t type)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate 	zone_t *zptr = curproc->p_zone;
2827c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
2837c478bd9Sstevel@tonic-gate 	log_t *lp;
2847c478bd9Sstevel@tonic-gate 	int i;
285068ccd7aSns 	minor_t minor;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	if (type == LOG_CONSMIN) {
2887c478bd9Sstevel@tonic-gate 
289068ccd7aSns 		/*
290068ccd7aSns 		 * Return a write-only /dev/conslog device.
291068ccd7aSns 		 * No point allocating log_t until there's a free minor number.
292068ccd7aSns 		 */
293068ccd7aSns 		minor = (minor_t)id_alloc(log_minorspace);
294068ccd7aSns 		lp = kmem_cache_alloc(log_cons_cache, KM_SLEEP);
295068ccd7aSns 		lp->log_minor = minor;
296068ccd7aSns 		return (lp);
297068ccd7aSns 	} else {
298068ccd7aSns 		ASSERT(type == LOG_LOGMIN);
2997c478bd9Sstevel@tonic-gate 
300068ccd7aSns 		lzp = zone_getspecific(log_zone_key, zptr);
301068ccd7aSns 		ASSERT(lzp != NULL);
3027c478bd9Sstevel@tonic-gate 
303068ccd7aSns 		/* search for an available /dev/log device for the zone */
304068ccd7aSns 		for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) {
305068ccd7aSns 			lp = &lzp->lz_clones[i];
306068ccd7aSns 			if (lp->log_inuse == 0)
307068ccd7aSns 				break;
308068ccd7aSns 		}
309068ccd7aSns 		if (i > LOG_LOGMAXIDX)
310068ccd7aSns 			lp = NULL;
311068ccd7aSns 		else
312068ccd7aSns 			/* Indicate which device type */
313068ccd7aSns 			lp->log_major = LOG_LOGMIN;
314068ccd7aSns 		return (lp);
3157c478bd9Sstevel@tonic-gate 	}
316068ccd7aSns }
317068ccd7aSns 
318068ccd7aSns void
log_free(log_t * lp)319068ccd7aSns log_free(log_t *lp)
320068ccd7aSns {
321068ccd7aSns 	id_free(log_minorspace, lp->log_minor);
322068ccd7aSns 	kmem_cache_free(log_cons_cache, lp);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate  * Move console messages from src to dst.  The time of day isn't known
3277c478bd9Sstevel@tonic-gate  * early in boot, so fix up the message timestamps if necessary.
3287c478bd9Sstevel@tonic-gate  */
3297c478bd9Sstevel@tonic-gate static void
log_conswitch(log_t * src,log_t * dst)3307c478bd9Sstevel@tonic-gate log_conswitch(log_t *src, log_t *dst)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	mblk_t *mp;
3337c478bd9Sstevel@tonic-gate 	mblk_t *hmp = NULL;
3347c478bd9Sstevel@tonic-gate 	mblk_t *tmp = NULL;
3357c478bd9Sstevel@tonic-gate 	log_ctl_t *hlc;
3367c478bd9Sstevel@tonic-gate 
337301ce41fSja 	while ((mp = getq_noenab(src->log_q, 0)) != NULL) {
3387c478bd9Sstevel@tonic-gate 		log_ctl_t *lc = (log_ctl_t *)mp->b_rptr;
3397c478bd9Sstevel@tonic-gate 		lc->flags |= SL_LOGONLY;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate 		/*
3423348528fSdm 		 * The ttime is written with 0 in log_sensmsg() only when
3438cff005aSkk 		 * good gethrestime_sec() data is not available to store in
3448cff005aSkk 		 * the log_ctl_t in the early boot phase.
3457c478bd9Sstevel@tonic-gate 		 */
3468cff005aSkk 		if (lc->ttime == 0) {
3477c478bd9Sstevel@tonic-gate 			/*
3487c478bd9Sstevel@tonic-gate 			 * Look ahead to first early boot message with time.
3497c478bd9Sstevel@tonic-gate 			 */
3507c478bd9Sstevel@tonic-gate 			if (hmp) {
3517c478bd9Sstevel@tonic-gate 				tmp->b_next = mp;
3527c478bd9Sstevel@tonic-gate 				tmp = mp;
3537c478bd9Sstevel@tonic-gate 			} else
3547c478bd9Sstevel@tonic-gate 				hmp = tmp = mp;
3557c478bd9Sstevel@tonic-gate 			continue;
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 		while (hmp) {
3597c478bd9Sstevel@tonic-gate 			tmp = hmp->b_next;
3607c478bd9Sstevel@tonic-gate 			hmp->b_next = NULL;
3617c478bd9Sstevel@tonic-gate 			hlc = (log_ctl_t *)hmp->b_rptr;
3627c478bd9Sstevel@tonic-gate 			/*
3637c478bd9Sstevel@tonic-gate 			 * Calculate hrestime for an early log message with
3647c478bd9Sstevel@tonic-gate 			 * an invalid time stamp. We know:
3657c478bd9Sstevel@tonic-gate 			 *  - the lbolt of the invalid time stamp.
3667c478bd9Sstevel@tonic-gate 			 *  - the hrestime and lbolt of the first valid
3677c478bd9Sstevel@tonic-gate 			 *    time stamp.
3687c478bd9Sstevel@tonic-gate 			 */
3697c478bd9Sstevel@tonic-gate 			hlc->ttime = lc->ttime - (lc->ltime - hlc->ltime) / hz;
3707c478bd9Sstevel@tonic-gate 			(void) putq(dst->log_q, hmp);
3717c478bd9Sstevel@tonic-gate 			hmp = tmp;
3727c478bd9Sstevel@tonic-gate 		}
3737c478bd9Sstevel@tonic-gate 		(void) putq(dst->log_q, mp);
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 	while (hmp) {
3767c478bd9Sstevel@tonic-gate 		tmp = hmp->b_next;
3777c478bd9Sstevel@tonic-gate 		hmp->b_next = NULL;
3787c478bd9Sstevel@tonic-gate 		hlc = (log_ctl_t *)hmp->b_rptr;
379d3d50737SRafael Vanoni 		hlc->ttime = gethrestime_sec() -
380d3d50737SRafael Vanoni 		    (ddi_get_lbolt() - hlc->ltime) / hz;
3817c478bd9Sstevel@tonic-gate 		(void) putq(dst->log_q, hmp);
3827c478bd9Sstevel@tonic-gate 		hmp = tmp;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 	dst->log_overflow = src->log_overflow;
3857c478bd9Sstevel@tonic-gate 	src->log_flags = 0;
3867c478bd9Sstevel@tonic-gate 	dst->log_flags = SL_CONSOLE;
3877c478bd9Sstevel@tonic-gate 	log_consq = dst->log_q;
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate /*
3917c478bd9Sstevel@tonic-gate  * Set the fields in the 'target' clone to the specified values.
3927c478bd9Sstevel@tonic-gate  * Then, look at all clones to determine which message types are
3937c478bd9Sstevel@tonic-gate  * currently active and which clone is the primary console queue.
3947c478bd9Sstevel@tonic-gate  * If the primary console queue changes to or from the backlog
3957c478bd9Sstevel@tonic-gate  * queue, copy all messages from backlog to primary or vice versa.
3967c478bd9Sstevel@tonic-gate  */
3977c478bd9Sstevel@tonic-gate void
log_update(log_t * target,queue_t * q,short flags,log_filter_t * filter)3987c478bd9Sstevel@tonic-gate log_update(log_t *target, queue_t *q, short flags, log_filter_t *filter)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate 	log_t *lp;
4017c478bd9Sstevel@tonic-gate 	short active = SL_CONSOLE;
4027c478bd9Sstevel@tonic-gate 	zone_t *zptr = NULL;
4037c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
4047c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = target->log_zoneid;
4057c478bd9Sstevel@tonic-gate 	int i;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	log_enter();
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	if (q != NULL)
4107c478bd9Sstevel@tonic-gate 		target->log_q = q;
4117c478bd9Sstevel@tonic-gate 	target->log_wanted = filter;
4127c478bd9Sstevel@tonic-gate 	target->log_flags = flags;
4137c478bd9Sstevel@tonic-gate 	target->log_overflow = 0;
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/*
4167c478bd9Sstevel@tonic-gate 	 * Need to special case the global zone here since this may be
4177c478bd9Sstevel@tonic-gate 	 * called before zone_init.
4187c478bd9Sstevel@tonic-gate 	 */
4197c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID) {
4207c478bd9Sstevel@tonic-gate 		lzp = &log_global;
4217c478bd9Sstevel@tonic-gate 	} else if ((zptr = zone_find_by_id(zoneid)) == NULL) {
4227c478bd9Sstevel@tonic-gate 		log_exit();
4237c478bd9Sstevel@tonic-gate 		return;		/* zone is being destroyed, ignore update */
4247c478bd9Sstevel@tonic-gate 	} else {
4257c478bd9Sstevel@tonic-gate 		lzp = zone_getspecific(log_zone_key, zptr);
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate 	ASSERT(lzp != NULL);
4287c478bd9Sstevel@tonic-gate 	for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) {
4297c478bd9Sstevel@tonic-gate 		lp = &lzp->lz_clones[i];
4307c478bd9Sstevel@tonic-gate 		if (zoneid == GLOBAL_ZONEID && (lp->log_flags & SL_CONSOLE))
4317c478bd9Sstevel@tonic-gate 			log_consq = lp->log_q;
4327c478bd9Sstevel@tonic-gate 		active |= lp->log_flags;
4337c478bd9Sstevel@tonic-gate 	}
4347c478bd9Sstevel@tonic-gate 	lzp->lz_active = active;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	if (zptr)
4377c478bd9Sstevel@tonic-gate 		zone_rele(zptr);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	if (log_consq == target->log_q) {
4407c478bd9Sstevel@tonic-gate 		if (flags & SL_CONSOLE)
4417c478bd9Sstevel@tonic-gate 			log_conswitch(&log_backlog, target);
4427c478bd9Sstevel@tonic-gate 		else
4437c478bd9Sstevel@tonic-gate 			log_conswitch(target, &log_backlog);
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate 	target->log_q = q;
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 	log_exit();
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4517c478bd9Sstevel@tonic-gate int
log_error(log_t * lp,log_ctl_t * lc)4527c478bd9Sstevel@tonic-gate log_error(log_t *lp, log_ctl_t *lc)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate 	if ((lc->pri & LOG_FACMASK) == LOG_KERN)
4557c478bd9Sstevel@tonic-gate 		lc->pri = LOG_KERN | LOG_ERR;
4567c478bd9Sstevel@tonic-gate 	return (1);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate int
log_trace(log_t * lp,log_ctl_t * lc)4607c478bd9Sstevel@tonic-gate log_trace(log_t *lp, log_ctl_t *lc)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate 	trace_ids_t *tid = (trace_ids_t *)lp->log_data->b_rptr;
4637c478bd9Sstevel@tonic-gate 	trace_ids_t *tidend = (trace_ids_t *)lp->log_data->b_wptr;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	/*
4667c478bd9Sstevel@tonic-gate 	 * We use `tid + 1 <= tidend' here rather than the more traditional
4677c478bd9Sstevel@tonic-gate 	 * `tid < tidend', since the former ensures that there's at least
4687c478bd9Sstevel@tonic-gate 	 * `sizeof (trace_ids_t)' bytes available before executing the
4697c478bd9Sstevel@tonic-gate 	 * loop, whereas the latter only ensures that there's a single byte.
4707c478bd9Sstevel@tonic-gate 	 */
4717c478bd9Sstevel@tonic-gate 	for (; tid + 1 <= tidend; tid++) {
4727c478bd9Sstevel@tonic-gate 		if (tid->ti_level < lc->level && tid->ti_level >= 0)
4737c478bd9Sstevel@tonic-gate 			continue;
4747c478bd9Sstevel@tonic-gate 		if (tid->ti_mid != lc->mid && tid->ti_mid >= 0)
4757c478bd9Sstevel@tonic-gate 			continue;
4767c478bd9Sstevel@tonic-gate 		if (tid->ti_sid != lc->sid && tid->ti_sid >= 0)
4777c478bd9Sstevel@tonic-gate 			continue;
4787c478bd9Sstevel@tonic-gate 		if ((lc->pri & LOG_FACMASK) == LOG_KERN)
4797c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_DEBUG;
4807c478bd9Sstevel@tonic-gate 		return (1);
4817c478bd9Sstevel@tonic-gate 	}
4827c478bd9Sstevel@tonic-gate 	return (0);
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4867c478bd9Sstevel@tonic-gate int
log_console(log_t * lp,log_ctl_t * lc)4877c478bd9Sstevel@tonic-gate log_console(log_t *lp, log_ctl_t *lc)
4887c478bd9Sstevel@tonic-gate {
4897c478bd9Sstevel@tonic-gate 	if ((lc->pri & LOG_FACMASK) == LOG_KERN) {
4907c478bd9Sstevel@tonic-gate 		if (lc->flags & SL_FATAL)
4917c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_CRIT;
4927c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_ERROR)
4937c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_ERR;
4947c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_WARN)
4957c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_WARNING;
4967c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_NOTE)
4977c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_NOTICE;
4987c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_TRACE)
4997c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_DEBUG;
5007c478bd9Sstevel@tonic-gate 		else
5017c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_INFO;
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 	return (1);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate mblk_t *
log_makemsg(int mid,int sid,int level,int sl,int pri,void * msg,size_t size,int on_intr)5077c478bd9Sstevel@tonic-gate log_makemsg(int mid, int sid, int level, int sl, int pri, void *msg,
5086112cec5SJoshua M. Clulow     size_t size, int on_intr)
5097c478bd9Sstevel@tonic-gate {
5107c478bd9Sstevel@tonic-gate 	mblk_t *mp = NULL;
5117c478bd9Sstevel@tonic-gate 	mblk_t *mp2;
5127c478bd9Sstevel@tonic-gate 	log_ctl_t *lc;
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if (size <= LOG_MSGSIZE &&
5157c478bd9Sstevel@tonic-gate 	    (on_intr || log_freeq->q_count > log_freeq->q_lowat))
516301ce41fSja 		mp = getq_noenab(log_freeq, 0);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (mp == NULL) {
5197c478bd9Sstevel@tonic-gate 		if (on_intr ||
5207c478bd9Sstevel@tonic-gate 		    (mp = allocb(sizeof (log_ctl_t), BPRI_HI)) == NULL ||
5217c478bd9Sstevel@tonic-gate 		    (mp2 = allocb(MAX(size, LOG_MSGSIZE), BPRI_HI)) == NULL) {
5227c478bd9Sstevel@tonic-gate 			freemsg(mp);
5237c478bd9Sstevel@tonic-gate 			return (NULL);
5247c478bd9Sstevel@tonic-gate 		}
5257c478bd9Sstevel@tonic-gate 		DB_TYPE(mp) = M_PROTO;
5267c478bd9Sstevel@tonic-gate 		mp->b_wptr += sizeof (log_ctl_t);
5277c478bd9Sstevel@tonic-gate 		mp->b_cont = mp2;
5287c478bd9Sstevel@tonic-gate 	} else {
5297c478bd9Sstevel@tonic-gate 		mp2 = mp->b_cont;
5307c478bd9Sstevel@tonic-gate 		mp2->b_wptr = mp2->b_rptr;
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	lc = (log_ctl_t *)mp->b_rptr;
5347c478bd9Sstevel@tonic-gate 	lc->mid = mid;
5357c478bd9Sstevel@tonic-gate 	lc->sid = sid;
5367c478bd9Sstevel@tonic-gate 	lc->level = level;
5377c478bd9Sstevel@tonic-gate 	lc->flags = sl;
5387c478bd9Sstevel@tonic-gate 	lc->pri = pri;
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	bcopy(msg, mp2->b_wptr, size - 1);
5417c478bd9Sstevel@tonic-gate 	mp2->b_wptr[size - 1] = '\0';
5427c478bd9Sstevel@tonic-gate 	mp2->b_wptr += strlen((char *)mp2->b_wptr) + 1;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 	return (mp);
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate void
log_freemsg(mblk_t * mp)5487c478bd9Sstevel@tonic-gate log_freemsg(mblk_t *mp)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate 	mblk_t *mp2 = mp->b_cont;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	ASSERT(MBLKL(mp) == sizeof (log_ctl_t));
5537c478bd9Sstevel@tonic-gate 	ASSERT(mp2->b_rptr == mp2->b_datap->db_base);
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	if ((log_freeq->q_flag & QFULL) == 0 &&
5567c478bd9Sstevel@tonic-gate 	    MBLKL(mp2) <= LOG_MSGSIZE && MBLKSIZE(mp2) >= LOG_MSGSIZE)
5577c478bd9Sstevel@tonic-gate 		(void) putq(log_freeq, mp);
5587c478bd9Sstevel@tonic-gate 	else
5597c478bd9Sstevel@tonic-gate 		freemsg(mp);
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate void
log_sendmsg(mblk_t * mp,zoneid_t zoneid)5637c478bd9Sstevel@tonic-gate log_sendmsg(mblk_t *mp, zoneid_t zoneid)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	log_t *lp;
5667c478bd9Sstevel@tonic-gate 	char *src, *dst;
5677c478bd9Sstevel@tonic-gate 	mblk_t *mp2 = mp->b_cont;
5687c478bd9Sstevel@tonic-gate 	log_ctl_t *lc = (log_ctl_t *)mp->b_rptr;
5697c478bd9Sstevel@tonic-gate 	int flags, fac;
5707c478bd9Sstevel@tonic-gate 	off_t facility = 0;
5717c478bd9Sstevel@tonic-gate 	off_t body = 0;
5727c478bd9Sstevel@tonic-gate 	zone_t *zptr = NULL;
5737c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
5747c478bd9Sstevel@tonic-gate 	int i;
5757c478bd9Sstevel@tonic-gate 	int backlog;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	/*
5787c478bd9Sstevel@tonic-gate 	 * Need to special case the global zone here since this may be
5797c478bd9Sstevel@tonic-gate 	 * called before zone_init.
5807c478bd9Sstevel@tonic-gate 	 */
5817c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID) {
5827c478bd9Sstevel@tonic-gate 		lzp = &log_global;
5837c478bd9Sstevel@tonic-gate 	} else if ((zptr = zone_find_by_id(zoneid)) == NULL) {
5847c478bd9Sstevel@tonic-gate 		/* specified zone doesn't exist, free message and return */
5857c478bd9Sstevel@tonic-gate 		log_freemsg(mp);
5867c478bd9Sstevel@tonic-gate 		return;
5877c478bd9Sstevel@tonic-gate 	} else {
5887c478bd9Sstevel@tonic-gate 		lzp = zone_getspecific(log_zone_key, zptr);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 	ASSERT(lzp != NULL);
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	if ((lc->flags & lzp->lz_active) == 0) {
5937c478bd9Sstevel@tonic-gate 		if (zptr)
5947c478bd9Sstevel@tonic-gate 			zone_rele(zptr);
5957c478bd9Sstevel@tonic-gate 		log_freemsg(mp);
5967c478bd9Sstevel@tonic-gate 		return;
5977c478bd9Sstevel@tonic-gate 	}
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	if (panicstr) {
6007c478bd9Sstevel@tonic-gate 		/*
6017c478bd9Sstevel@tonic-gate 		 * Raise the console queue's q_hiwat to ensure that we
6027c478bd9Sstevel@tonic-gate 		 * capture all panic messages.
6037c478bd9Sstevel@tonic-gate 		 */
6047c478bd9Sstevel@tonic-gate 		log_consq->q_hiwat = 2 * LOG_HIWAT;
6057c478bd9Sstevel@tonic-gate 		log_consq->q_flag &= ~QFULL;
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 		/* Message was created while panicking. */
6087c478bd9Sstevel@tonic-gate 		lc->flags |= SL_PANICMSG;
6097c478bd9Sstevel@tonic-gate 	}
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	src = (char *)mp2->b_rptr;
6127c478bd9Sstevel@tonic-gate 	dst = strstr(src, "FACILITY_AND_PRIORITY] ");
6137c478bd9Sstevel@tonic-gate 	if (dst != NULL) {
6147c478bd9Sstevel@tonic-gate 		facility = dst - src;
6157c478bd9Sstevel@tonic-gate 		body = facility + 23; /* strlen("FACILITY_AND_PRIORITY] ") */
6167c478bd9Sstevel@tonic-gate 	}
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	log_enter();
6197c478bd9Sstevel@tonic-gate 
6208cff005aSkk 	/*
6213348528fSdm 	 * In the early boot phase hrestime is invalid, then timechanged is 0.
6223348528fSdm 	 * If hrestime is not valid, the ttime is set to 0 here and the correct
6233348528fSdm 	 * ttime is calculated in log_conswitch() later. The log_conswitch()
6243348528fSdm 	 * calculation to determine the correct ttime does not use ttime data
6253348528fSdm 	 * from these log_ctl_t structures; it only uses ttime from log_ctl_t's
6263348528fSdm 	 * that contain good data.
6273348528fSdm 	 *
6288cff005aSkk 	 */
629d3d50737SRafael Vanoni 	lc->ltime = ddi_get_lbolt();
6303348528fSdm 	if (timechanged) {
6318cff005aSkk 		lc->ttime = gethrestime_sec();
6328cff005aSkk 	} else {
6338cff005aSkk 		lc->ttime = 0;
6348cff005aSkk 	}
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate 	flags = lc->flags & lzp->lz_active;
6377c478bd9Sstevel@tonic-gate 	log_seq_no[flags & SL_ERROR]++;
6387c478bd9Sstevel@tonic-gate 	log_seq_no[flags & SL_TRACE]++;
6397c478bd9Sstevel@tonic-gate 	log_seq_no[flags & SL_CONSOLE]++;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	/*
6427c478bd9Sstevel@tonic-gate 	 * If this is in the global zone, start with the backlog, then
6437c478bd9Sstevel@tonic-gate 	 * walk through the clone logs.  If not, just do the clone logs.
6447c478bd9Sstevel@tonic-gate 	 */
6457c478bd9Sstevel@tonic-gate 	backlog = (zoneid == GLOBAL_ZONEID);
6467c478bd9Sstevel@tonic-gate 	i = LOG_LOGMINIDX;
6477c478bd9Sstevel@tonic-gate 	while (i <= LOG_LOGMAXIDX) {
6487c478bd9Sstevel@tonic-gate 		if (backlog) {
6497c478bd9Sstevel@tonic-gate 			/*
6507c478bd9Sstevel@tonic-gate 			 * Do the backlog this time, then start on the
6517c478bd9Sstevel@tonic-gate 			 * others.
6527c478bd9Sstevel@tonic-gate 			 */
6537c478bd9Sstevel@tonic-gate 			backlog = 0;
6547c478bd9Sstevel@tonic-gate 			lp = &log_backlog;
6557c478bd9Sstevel@tonic-gate 		} else {
6567c478bd9Sstevel@tonic-gate 			lp = &lzp->lz_clones[i++];
6577c478bd9Sstevel@tonic-gate 		}
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate 		if ((lp->log_flags & flags) && lp->log_wanted(lp, lc)) {
6607c478bd9Sstevel@tonic-gate 			if (canput(lp->log_q)) {
6617c478bd9Sstevel@tonic-gate 				lp->log_overflow = 0;
6627c478bd9Sstevel@tonic-gate 				lc->seq_no = log_seq_no[lp->log_flags];
6637c478bd9Sstevel@tonic-gate 				if ((mp2 = copymsg(mp)) == NULL)
6647c478bd9Sstevel@tonic-gate 					break;
6657c478bd9Sstevel@tonic-gate 				if (facility != 0) {
6667c478bd9Sstevel@tonic-gate 					src = (char *)mp2->b_cont->b_rptr;
6677c478bd9Sstevel@tonic-gate 					dst = src + facility;
6687c478bd9Sstevel@tonic-gate 					fac = (lc->pri & LOG_FACMASK) >> 3;
6697c478bd9Sstevel@tonic-gate 					dst += snprintf(dst,
6707c478bd9Sstevel@tonic-gate 					    LOG_FACSIZE + LOG_PRISIZE, "%s.%s",
6717c478bd9Sstevel@tonic-gate 					    log_fac[MIN(fac, LOG_NFACILITIES)],
6727c478bd9Sstevel@tonic-gate 					    log_pri[lc->pri & LOG_PRIMASK]);
6737c478bd9Sstevel@tonic-gate 					src += body - 2; /* copy "] " too */
6747c478bd9Sstevel@tonic-gate 					while (*src != '\0')
6757c478bd9Sstevel@tonic-gate 						*dst++ = *src++;
6767c478bd9Sstevel@tonic-gate 					*dst++ = '\0';
6777c478bd9Sstevel@tonic-gate 					mp2->b_cont->b_wptr = (uchar_t *)dst;
6787c478bd9Sstevel@tonic-gate 				}
6797c478bd9Sstevel@tonic-gate 				(void) putq(lp->log_q, mp2);
6807c478bd9Sstevel@tonic-gate 			} else if (++lp->log_overflow == 1) {
6817c478bd9Sstevel@tonic-gate 				if (lp->log_q == log_consq) {
6827c478bd9Sstevel@tonic-gate 					console_printf(log_overflow_msg,
6837c478bd9Sstevel@tonic-gate 					    lp->log_minor,
684bbf21555SRichard Lowe 					    " -- is syslogd(8) running?");
6857c478bd9Sstevel@tonic-gate 				} else {
6867c478bd9Sstevel@tonic-gate 					printf(log_overflow_msg,
6877c478bd9Sstevel@tonic-gate 					    lp->log_minor, "");
6887c478bd9Sstevel@tonic-gate 				}
6897c478bd9Sstevel@tonic-gate 			}
6907c478bd9Sstevel@tonic-gate 		}
6917c478bd9Sstevel@tonic-gate 	}
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	if (zptr)
6947c478bd9Sstevel@tonic-gate 		zone_rele(zptr);
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	if ((flags & SL_CONSOLE) && (lc->pri & LOG_FACMASK) == LOG_KERN) {
6977c478bd9Sstevel@tonic-gate 		if ((mp2 == NULL || log_consq == log_backlogq || panicstr) &&
6987c478bd9Sstevel@tonic-gate 		    (lc->flags & SL_LOGONLY) == 0)
6997c478bd9Sstevel@tonic-gate 			console_printf("%s", (char *)mp->b_cont->b_rptr + body);
7007c478bd9Sstevel@tonic-gate 		if ((lc->flags & SL_CONSONLY) == 0 &&
7017c478bd9Sstevel@tonic-gate 		    (mp2 = copymsg(mp)) != NULL) {
7027c478bd9Sstevel@tonic-gate 			mp2->b_cont->b_rptr += body;
7037c478bd9Sstevel@tonic-gate 			if (log_recentq->q_flag & QFULL)
704301ce41fSja 				freemsg(getq_noenab(log_recentq, 0));
7057c478bd9Sstevel@tonic-gate 			(void) putq(log_recentq, mp2);
7067c478bd9Sstevel@tonic-gate 		}
7077c478bd9Sstevel@tonic-gate 	}
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	log_freemsg(mp);
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 	log_exit();
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate  * Print queued messages to console.
7167c478bd9Sstevel@tonic-gate  */
7177c478bd9Sstevel@tonic-gate void
log_printq(queue_t * qfirst)7187c478bd9Sstevel@tonic-gate log_printq(queue_t *qfirst)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate 	mblk_t *mp;
7217c478bd9Sstevel@tonic-gate 	queue_t *q, *qlast;
7227c478bd9Sstevel@tonic-gate 	char *cp, *msgp;
7237c478bd9Sstevel@tonic-gate 	log_ctl_t *lc;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	/*
7267c478bd9Sstevel@tonic-gate 	 * Look ahead to first queued message in the stream.
7277c478bd9Sstevel@tonic-gate 	 */
7287c478bd9Sstevel@tonic-gate 	qlast = NULL;
7297c478bd9Sstevel@tonic-gate 	do {
7307c478bd9Sstevel@tonic-gate 		for (q = qfirst; q->q_next != qlast; q = q->q_next)
7317c478bd9Sstevel@tonic-gate 			continue;
7327c478bd9Sstevel@tonic-gate 		for (mp = q->q_first; mp != NULL; mp = mp->b_next) {
7337c478bd9Sstevel@tonic-gate 			lc = (log_ctl_t *)mp->b_rptr;
7347c478bd9Sstevel@tonic-gate 			/*
7357c478bd9Sstevel@tonic-gate 			 * Check if message is already displayed at
7367c478bd9Sstevel@tonic-gate 			 * /dev/console.
7377c478bd9Sstevel@tonic-gate 			 */
7387c478bd9Sstevel@tonic-gate 			if (lc->flags & SL_PANICMSG)
7397c478bd9Sstevel@tonic-gate 				continue;
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 			cp = (char *)mp->b_cont->b_rptr;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 			/* Strip off the message ID. */
7447c478bd9Sstevel@tonic-gate 			if ((msgp = strstr(cp, "[ID ")) != NULL &&
7457c478bd9Sstevel@tonic-gate 			    (msgp = strstr(msgp,  "] ")) != NULL) {
7467c478bd9Sstevel@tonic-gate 				cp = msgp + 2;
7477c478bd9Sstevel@tonic-gate 			}
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 			/*
7507c478bd9Sstevel@tonic-gate 			 * Using console_printf instead of printf to avoid
7517c478bd9Sstevel@tonic-gate 			 * queueing messages to log_consq.
7527c478bd9Sstevel@tonic-gate 			 */
7537c478bd9Sstevel@tonic-gate 			console_printf("%s", cp);
7547c478bd9Sstevel@tonic-gate 		}
7557c478bd9Sstevel@tonic-gate 	} while ((qlast = q) != qfirst);
7567c478bd9Sstevel@tonic-gate }
757068ccd7aSns 
758068ccd7aSns /* ARGSUSED */
759068ccd7aSns static int
log_cons_constructor(void * buf,void * cdrarg,int kmflags)760068ccd7aSns log_cons_constructor(void *buf, void *cdrarg, int kmflags)
761068ccd7aSns {
762068ccd7aSns 	struct log *lp = buf;
763068ccd7aSns 
764068ccd7aSns 	lp->log_zoneid = GLOBAL_ZONEID;
765068ccd7aSns 	lp->log_major = LOG_CONSMIN;	/* Indicate which device type */
766068ccd7aSns 	lp->log_data = NULL;
767068ccd7aSns 	return (0);
768068ccd7aSns }
769068ccd7aSns 
770068ccd7aSns /* ARGSUSED */
771068ccd7aSns static void
log_cons_destructor(void * buf,void * cdrarg)772068ccd7aSns log_cons_destructor(void *buf, void *cdrarg)
773068ccd7aSns {
774068ccd7aSns 	struct log *lp = buf;
775068ccd7aSns 
776068ccd7aSns 	ASSERT(lp->log_zoneid == GLOBAL_ZONEID);
777068ccd7aSns 	ASSERT(lp->log_major == LOG_CONSMIN);
778068ccd7aSns 	ASSERT(lp->log_data == NULL);
779068ccd7aSns }
780