xref: /titanic_53/usr/src/uts/common/os/logsubr.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/log.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/spl.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/syslog.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/console.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/id_space.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/zone.h>
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate log_zone_t log_global;
49*7c478bd9Sstevel@tonic-gate queue_t *log_consq;
50*7c478bd9Sstevel@tonic-gate queue_t *log_backlogq;
51*7c478bd9Sstevel@tonic-gate queue_t *log_intrq;
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #define	LOG_PRISIZE	8	/* max priority size: 7 characters + null */
54*7c478bd9Sstevel@tonic-gate #define	LOG_FACSIZE	9	/* max priority size: 8 characters + null */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate static krwlock_t log_rwlock;
57*7c478bd9Sstevel@tonic-gate static int log_rwlock_depth;
58*7c478bd9Sstevel@tonic-gate static int log_seq_no[SL_CONSOLE + 1];
59*7c478bd9Sstevel@tonic-gate static stdata_t log_fakestr;
60*7c478bd9Sstevel@tonic-gate static id_space_t *log_minorspace;
61*7c478bd9Sstevel@tonic-gate static log_t log_backlog;
62*7c478bd9Sstevel@tonic-gate static log_t log_conslog;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static queue_t *log_recentq;
65*7c478bd9Sstevel@tonic-gate static queue_t *log_freeq;
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate static zone_key_t log_zone_key;
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate static char log_overflow_msg[] = "message overflow on /dev/log minor #%d%s\n";
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate static char log_pri[LOG_PRIMASK + 1][LOG_PRISIZE] = {
72*7c478bd9Sstevel@tonic-gate 	"emerg",	"alert",	"crit",		"error",
73*7c478bd9Sstevel@tonic-gate 	"warning",	"notice",	"info",		"debug"
74*7c478bd9Sstevel@tonic-gate };
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate static char log_fac[LOG_NFACILITIES + 1][LOG_FACSIZE] = {
77*7c478bd9Sstevel@tonic-gate 	"kern",		"user",		"mail",		"daemon",
78*7c478bd9Sstevel@tonic-gate 	"auth",		"syslog",	"lpr",		"news",
79*7c478bd9Sstevel@tonic-gate 	"uucp",		"resv9",	"resv10",	"resv11",
80*7c478bd9Sstevel@tonic-gate 	"resv12",	"audit",	"resv14",	"cron",
81*7c478bd9Sstevel@tonic-gate 	"local0",	"local1",	"local2",	"local3",
82*7c478bd9Sstevel@tonic-gate 	"local4",	"local5",	"local6",	"local7",
83*7c478bd9Sstevel@tonic-gate 	"unknown"
84*7c478bd9Sstevel@tonic-gate };
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate /*
87*7c478bd9Sstevel@tonic-gate  * Get exclusive access to the logging system; this includes all minor
88*7c478bd9Sstevel@tonic-gate  * devices.  We use an rwlock rather than a mutex because hold times
89*7c478bd9Sstevel@tonic-gate  * are potentially long, so we don't want to waste cycles in adaptive mutex
90*7c478bd9Sstevel@tonic-gate  * spin (rwlocks always block when contended).  Note that we explicitly
91*7c478bd9Sstevel@tonic-gate  * support recursive calls (e.g. printf() calls foo() calls printf()).
92*7c478bd9Sstevel@tonic-gate  *
93*7c478bd9Sstevel@tonic-gate  * Clients may use log_enter() / log_exit() to guarantee that a group
94*7c478bd9Sstevel@tonic-gate  * of messages is treated atomically (i.e. they appear in order and are
95*7c478bd9Sstevel@tonic-gate  * not interspersed with any other messages), e.g. for multiline printf().
96*7c478bd9Sstevel@tonic-gate  *
97*7c478bd9Sstevel@tonic-gate  * This could probably be changed to a per-zone lock if contention becomes
98*7c478bd9Sstevel@tonic-gate  * an issue.
99*7c478bd9Sstevel@tonic-gate  */
100*7c478bd9Sstevel@tonic-gate void
101*7c478bd9Sstevel@tonic-gate log_enter(void)
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate 	if (rw_owner(&log_rwlock) != curthread)
104*7c478bd9Sstevel@tonic-gate 		rw_enter(&log_rwlock, RW_WRITER);
105*7c478bd9Sstevel@tonic-gate 	log_rwlock_depth++;
106*7c478bd9Sstevel@tonic-gate }
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate void
109*7c478bd9Sstevel@tonic-gate log_exit(void)
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	if (--log_rwlock_depth == 0)
112*7c478bd9Sstevel@tonic-gate 		rw_exit(&log_rwlock);
113*7c478bd9Sstevel@tonic-gate }
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate void
116*7c478bd9Sstevel@tonic-gate log_flushq(queue_t *q)
117*7c478bd9Sstevel@tonic-gate {
118*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
119*7c478bd9Sstevel@tonic-gate 	log_t *lp = (log_t *)q->q_ptr;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/* lp will be NULL if the queue was created via log_makeq */
122*7c478bd9Sstevel@tonic-gate 	while ((mp = getq_noenab(q)) != NULL)
123*7c478bd9Sstevel@tonic-gate 		log_sendmsg(mp, lp == NULL ? GLOBAL_ZONEID : lp->log_zoneid);
124*7c478bd9Sstevel@tonic-gate }
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate /*
127*7c478bd9Sstevel@tonic-gate  * Create a minimal queue with just enough fields filled in to support
128*7c478bd9Sstevel@tonic-gate  * canput(9F), putq(9F), and getq_noenab(9F).  We set QNOENB to ensure
129*7c478bd9Sstevel@tonic-gate  * that the queue will never be enabled.
130*7c478bd9Sstevel@tonic-gate  */
131*7c478bd9Sstevel@tonic-gate static queue_t *
132*7c478bd9Sstevel@tonic-gate log_makeq(size_t lowat, size_t hiwat, void *ibc)
133*7c478bd9Sstevel@tonic-gate {
134*7c478bd9Sstevel@tonic-gate 	queue_t *q;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	q = kmem_zalloc(sizeof (queue_t), KM_SLEEP);
137*7c478bd9Sstevel@tonic-gate 	q->q_stream = &log_fakestr;
138*7c478bd9Sstevel@tonic-gate 	q->q_flag = QISDRV | QMTSAFE | QNOENB | QREADR | QUSE;
139*7c478bd9Sstevel@tonic-gate 	q->q_nfsrv = q;
140*7c478bd9Sstevel@tonic-gate 	q->q_lowat = lowat;
141*7c478bd9Sstevel@tonic-gate 	q->q_hiwat = hiwat;
142*7c478bd9Sstevel@tonic-gate 	mutex_init(QLOCK(q), NULL, MUTEX_DRIVER, ibc);
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	return (q);
145*7c478bd9Sstevel@tonic-gate }
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate /*
148*7c478bd9Sstevel@tonic-gate  * Initialize the log structure for a new zone.
149*7c478bd9Sstevel@tonic-gate  */
150*7c478bd9Sstevel@tonic-gate static void *
151*7c478bd9Sstevel@tonic-gate log_zoneinit(zoneid_t zoneid)
152*7c478bd9Sstevel@tonic-gate {
153*7c478bd9Sstevel@tonic-gate 	int i;
154*7c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID)
157*7c478bd9Sstevel@tonic-gate 		lzp = &log_global;	/* use statically allocated struct */
158*7c478bd9Sstevel@tonic-gate 	else
159*7c478bd9Sstevel@tonic-gate 		lzp = kmem_zalloc(sizeof (log_zone_t), KM_SLEEP);
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NUMCLONES; i++) {
162*7c478bd9Sstevel@tonic-gate 		lzp->lz_clones[i].log_minor =
163*7c478bd9Sstevel@tonic-gate 		    (minor_t)id_alloc(log_minorspace);
164*7c478bd9Sstevel@tonic-gate 		lzp->lz_clones[i].log_zoneid = zoneid;
165*7c478bd9Sstevel@tonic-gate 	}
166*7c478bd9Sstevel@tonic-gate 	return (lzp);
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
170*7c478bd9Sstevel@tonic-gate static void
171*7c478bd9Sstevel@tonic-gate log_zonefree(zoneid_t zoneid, void *arg)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	log_zone_t *lzp = arg;
174*7c478bd9Sstevel@tonic-gate 	int i;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	ASSERT(lzp != &log_global && zoneid != GLOBAL_ZONEID);
177*7c478bd9Sstevel@tonic-gate 	if (lzp == NULL)
178*7c478bd9Sstevel@tonic-gate 		return;
179*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < LOG_NUMCLONES; i++)
180*7c478bd9Sstevel@tonic-gate 		id_free(log_minorspace, lzp->lz_clones[i].log_minor);
181*7c478bd9Sstevel@tonic-gate 	kmem_free(lzp, sizeof (log_zone_t));
182*7c478bd9Sstevel@tonic-gate }
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate void
185*7c478bd9Sstevel@tonic-gate log_init(void)
186*7c478bd9Sstevel@tonic-gate {
187*7c478bd9Sstevel@tonic-gate 	int log_maxzones;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	/*
190*7c478bd9Sstevel@tonic-gate 	 * Create a backlog queue to consume console messages during periods
191*7c478bd9Sstevel@tonic-gate 	 * when there is no console reader (e.g. before syslogd(1M) starts).
192*7c478bd9Sstevel@tonic-gate 	 */
193*7c478bd9Sstevel@tonic-gate 	log_backlogq = log_consq = log_makeq(0, LOG_HIWAT, NULL);
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	/*
196*7c478bd9Sstevel@tonic-gate 	 * Create a queue to hold free message of size <= LOG_MSGSIZE.
197*7c478bd9Sstevel@tonic-gate 	 * Calls from high-level interrupt handlers will do a getq_noenab()
198*7c478bd9Sstevel@tonic-gate 	 * from this queue, so its q_lock must be a maximum SPL spin lock.
199*7c478bd9Sstevel@tonic-gate 	 */
200*7c478bd9Sstevel@tonic-gate 	log_freeq = log_makeq(LOG_MINFREE, LOG_MAXFREE, (void *)ipltospl(SPL8));
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	/*
203*7c478bd9Sstevel@tonic-gate 	 * Create a queue for messages from high-level interrupt context.
204*7c478bd9Sstevel@tonic-gate 	 * These messages are drained via softcall, or explicitly by panic().
205*7c478bd9Sstevel@tonic-gate 	 */
206*7c478bd9Sstevel@tonic-gate 	log_intrq = log_makeq(0, LOG_HIWAT, (void *)ipltospl(SPL8));
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	/*
209*7c478bd9Sstevel@tonic-gate 	 * Create a queue to hold the most recent 8K of console messages.
210*7c478bd9Sstevel@tonic-gate 	 * Useful for debugging.  Required by the "$<msgbuf" adb macro.
211*7c478bd9Sstevel@tonic-gate 	 */
212*7c478bd9Sstevel@tonic-gate 	log_recentq = log_makeq(0, LOG_RECENTSIZE, NULL);
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	/*
215*7c478bd9Sstevel@tonic-gate 	 * Create an id space for clone devices opened via /dev/log.
216*7c478bd9Sstevel@tonic-gate 	 * Need to limit the number of zones to avoid exceeding the
217*7c478bd9Sstevel@tonic-gate 	 * available minor number space.
218*7c478bd9Sstevel@tonic-gate 	 */
219*7c478bd9Sstevel@tonic-gate 	log_maxzones = (L_MAXMIN32 - LOG_LOGMIN) / LOG_NUMCLONES - 1;
220*7c478bd9Sstevel@tonic-gate 	if (log_maxzones < maxzones)
221*7c478bd9Sstevel@tonic-gate 		maxzones = log_maxzones;
222*7c478bd9Sstevel@tonic-gate 	log_minorspace = id_space_create("logminor_space", LOG_LOGMIN + 1,
223*7c478bd9Sstevel@tonic-gate 	    L_MAXMIN32);
224*7c478bd9Sstevel@tonic-gate 	/*
225*7c478bd9Sstevel@tonic-gate 	 * Put ourselves on the ZSD list.  Note that zones have not been
226*7c478bd9Sstevel@tonic-gate 	 * initialized yet, but our constructor will be called on the global
227*7c478bd9Sstevel@tonic-gate 	 * zone when they are.
228*7c478bd9Sstevel@tonic-gate 	 */
229*7c478bd9Sstevel@tonic-gate 	zone_key_create(&log_zone_key, log_zoneinit, NULL, log_zonefree);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	/*
232*7c478bd9Sstevel@tonic-gate 	 * Initialize backlog structure.
233*7c478bd9Sstevel@tonic-gate 	 */
234*7c478bd9Sstevel@tonic-gate 	log_backlog.log_zoneid = GLOBAL_ZONEID;
235*7c478bd9Sstevel@tonic-gate 	log_backlog.log_minor = LOG_BACKLOG;
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	/*
238*7c478bd9Sstevel@tonic-gate 	 * Initialize conslog structure.
239*7c478bd9Sstevel@tonic-gate 	 */
240*7c478bd9Sstevel@tonic-gate 	log_conslog.log_zoneid = GLOBAL_ZONEID;
241*7c478bd9Sstevel@tonic-gate 	log_conslog.log_minor = LOG_CONSMIN;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	/*
244*7c478bd9Sstevel@tonic-gate 	 * Let the logging begin.
245*7c478bd9Sstevel@tonic-gate 	 */
246*7c478bd9Sstevel@tonic-gate 	log_update(&log_backlog, log_backlogq, SL_CONSOLE, log_console);
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	/*
249*7c478bd9Sstevel@tonic-gate 	 * Now that logging is enabled, emit the SunOS banner.
250*7c478bd9Sstevel@tonic-gate 	 */
251*7c478bd9Sstevel@tonic-gate 	printf("\rSunOS Release %s Version %s %u-bit\n",
252*7c478bd9Sstevel@tonic-gate 	    utsname.release, utsname.version, NBBY * (uint_t)sizeof (void *));
253*7c478bd9Sstevel@tonic-gate 	printf("Copyright 1983-2005 Sun Microsystems, Inc.  "
254*7c478bd9Sstevel@tonic-gate 		"All rights reserved.\nUse is subject to license terms.\n");
255*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
256*7c478bd9Sstevel@tonic-gate 	printf("DEBUG enabled\n");
257*7c478bd9Sstevel@tonic-gate #endif
258*7c478bd9Sstevel@tonic-gate }
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate /*
261*7c478bd9Sstevel@tonic-gate  * Allocate a log device corresponding to supplied device type.  All
262*7c478bd9Sstevel@tonic-gate  * processes within a given zone that open /dev/conslog share the same
263*7c478bd9Sstevel@tonic-gate  * device; processes opening /dev/log get distinct devices (if
264*7c478bd9Sstevel@tonic-gate  * available).
265*7c478bd9Sstevel@tonic-gate  */
266*7c478bd9Sstevel@tonic-gate log_t *
267*7c478bd9Sstevel@tonic-gate log_alloc(minor_t type)
268*7c478bd9Sstevel@tonic-gate {
269*7c478bd9Sstevel@tonic-gate 	zone_t *zptr = curproc->p_zone;
270*7c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
271*7c478bd9Sstevel@tonic-gate 	log_t *lp;
272*7c478bd9Sstevel@tonic-gate 	int i;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	if (type == LOG_CONSMIN) {
275*7c478bd9Sstevel@tonic-gate 		/* return the dedicated /dev/conslog device */
276*7c478bd9Sstevel@tonic-gate 		return (&log_conslog);
277*7c478bd9Sstevel@tonic-gate 	}
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	ASSERT(type == LOG_LOGMIN);
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	lzp = zone_getspecific(log_zone_key, zptr);
282*7c478bd9Sstevel@tonic-gate 	ASSERT(lzp != NULL);
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	/* search for an available /dev/log device for the zone */
285*7c478bd9Sstevel@tonic-gate 	for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) {
286*7c478bd9Sstevel@tonic-gate 		lp = &lzp->lz_clones[i];
287*7c478bd9Sstevel@tonic-gate 		if (lp->log_inuse == 0)
288*7c478bd9Sstevel@tonic-gate 			break;
289*7c478bd9Sstevel@tonic-gate 	}
290*7c478bd9Sstevel@tonic-gate 	if (i > LOG_LOGMAXIDX)
291*7c478bd9Sstevel@tonic-gate 		lp = NULL;
292*7c478bd9Sstevel@tonic-gate 	return (lp);
293*7c478bd9Sstevel@tonic-gate }
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate /*
296*7c478bd9Sstevel@tonic-gate  * Move console messages from src to dst.  The time of day isn't known
297*7c478bd9Sstevel@tonic-gate  * early in boot, so fix up the message timestamps if necessary.
298*7c478bd9Sstevel@tonic-gate  */
299*7c478bd9Sstevel@tonic-gate static void
300*7c478bd9Sstevel@tonic-gate log_conswitch(log_t *src, log_t *dst)
301*7c478bd9Sstevel@tonic-gate {
302*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
303*7c478bd9Sstevel@tonic-gate 	mblk_t *hmp = NULL;
304*7c478bd9Sstevel@tonic-gate 	mblk_t *tmp = NULL;
305*7c478bd9Sstevel@tonic-gate 	log_ctl_t *hlc;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	while ((mp = getq_noenab(src->log_q)) != NULL) {
308*7c478bd9Sstevel@tonic-gate 		log_ctl_t *lc = (log_ctl_t *)mp->b_rptr;
309*7c478bd9Sstevel@tonic-gate 		lc->flags |= SL_LOGONLY;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 		/*
312*7c478bd9Sstevel@tonic-gate 		 * In the early boot phase hrestime is invalid.
313*7c478bd9Sstevel@tonic-gate 		 * hrestime becomes valid when clock() runs for the first time.
314*7c478bd9Sstevel@tonic-gate 		 * At this time is lbolt == 1. log_sendmsg() saves the lbolt
315*7c478bd9Sstevel@tonic-gate 		 * value in ltime.
316*7c478bd9Sstevel@tonic-gate 		 */
317*7c478bd9Sstevel@tonic-gate 		if (lc->ltime < 2) {
318*7c478bd9Sstevel@tonic-gate 			/*
319*7c478bd9Sstevel@tonic-gate 			 * Look ahead to first early boot message with time.
320*7c478bd9Sstevel@tonic-gate 			 */
321*7c478bd9Sstevel@tonic-gate 			if (hmp) {
322*7c478bd9Sstevel@tonic-gate 				tmp->b_next = mp;
323*7c478bd9Sstevel@tonic-gate 				tmp = mp;
324*7c478bd9Sstevel@tonic-gate 			} else
325*7c478bd9Sstevel@tonic-gate 				hmp = tmp = mp;
326*7c478bd9Sstevel@tonic-gate 			continue;
327*7c478bd9Sstevel@tonic-gate 		}
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 		while (hmp) {
330*7c478bd9Sstevel@tonic-gate 			tmp = hmp->b_next;
331*7c478bd9Sstevel@tonic-gate 			hmp->b_next = NULL;
332*7c478bd9Sstevel@tonic-gate 			hlc = (log_ctl_t *)hmp->b_rptr;
333*7c478bd9Sstevel@tonic-gate 			/*
334*7c478bd9Sstevel@tonic-gate 			 * Calculate hrestime for an early log message with
335*7c478bd9Sstevel@tonic-gate 			 * an invalid time stamp. We know:
336*7c478bd9Sstevel@tonic-gate 			 *  - the lbolt of the invalid time stamp.
337*7c478bd9Sstevel@tonic-gate 			 *  - the hrestime and lbolt of the first valid
338*7c478bd9Sstevel@tonic-gate 			 *    time stamp.
339*7c478bd9Sstevel@tonic-gate 			 */
340*7c478bd9Sstevel@tonic-gate 			hlc->ttime = lc->ttime - (lc->ltime - hlc->ltime) / hz;
341*7c478bd9Sstevel@tonic-gate 			(void) putq(dst->log_q, hmp);
342*7c478bd9Sstevel@tonic-gate 			hmp = tmp;
343*7c478bd9Sstevel@tonic-gate 		}
344*7c478bd9Sstevel@tonic-gate 		(void) putq(dst->log_q, mp);
345*7c478bd9Sstevel@tonic-gate 	}
346*7c478bd9Sstevel@tonic-gate 	while (hmp) {
347*7c478bd9Sstevel@tonic-gate 		tmp = hmp->b_next;
348*7c478bd9Sstevel@tonic-gate 		hmp->b_next = NULL;
349*7c478bd9Sstevel@tonic-gate 		hlc = (log_ctl_t *)hmp->b_rptr;
350*7c478bd9Sstevel@tonic-gate 		hlc->ttime = gethrestime_sec() - (lbolt - hlc->ltime) / hz;
351*7c478bd9Sstevel@tonic-gate 		(void) putq(dst->log_q, hmp);
352*7c478bd9Sstevel@tonic-gate 		hmp = tmp;
353*7c478bd9Sstevel@tonic-gate 	}
354*7c478bd9Sstevel@tonic-gate 	dst->log_overflow = src->log_overflow;
355*7c478bd9Sstevel@tonic-gate 	src->log_flags = 0;
356*7c478bd9Sstevel@tonic-gate 	dst->log_flags = SL_CONSOLE;
357*7c478bd9Sstevel@tonic-gate 	log_consq = dst->log_q;
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate /*
361*7c478bd9Sstevel@tonic-gate  * Set the fields in the 'target' clone to the specified values.
362*7c478bd9Sstevel@tonic-gate  * Then, look at all clones to determine which message types are
363*7c478bd9Sstevel@tonic-gate  * currently active and which clone is the primary console queue.
364*7c478bd9Sstevel@tonic-gate  * If the primary console queue changes to or from the backlog
365*7c478bd9Sstevel@tonic-gate  * queue, copy all messages from backlog to primary or vice versa.
366*7c478bd9Sstevel@tonic-gate  */
367*7c478bd9Sstevel@tonic-gate void
368*7c478bd9Sstevel@tonic-gate log_update(log_t *target, queue_t *q, short flags, log_filter_t *filter)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	log_t *lp;
371*7c478bd9Sstevel@tonic-gate 	short active = SL_CONSOLE;
372*7c478bd9Sstevel@tonic-gate 	zone_t *zptr = NULL;
373*7c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
374*7c478bd9Sstevel@tonic-gate 	zoneid_t zoneid = target->log_zoneid;
375*7c478bd9Sstevel@tonic-gate 	int i;
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 	log_enter();
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	if (q != NULL)
380*7c478bd9Sstevel@tonic-gate 		target->log_q = q;
381*7c478bd9Sstevel@tonic-gate 	target->log_wanted = filter;
382*7c478bd9Sstevel@tonic-gate 	target->log_flags = flags;
383*7c478bd9Sstevel@tonic-gate 	target->log_overflow = 0;
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate 	/*
386*7c478bd9Sstevel@tonic-gate 	 * Need to special case the global zone here since this may be
387*7c478bd9Sstevel@tonic-gate 	 * called before zone_init.
388*7c478bd9Sstevel@tonic-gate 	 */
389*7c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID) {
390*7c478bd9Sstevel@tonic-gate 		lzp = &log_global;
391*7c478bd9Sstevel@tonic-gate 	} else if ((zptr = zone_find_by_id(zoneid)) == NULL) {
392*7c478bd9Sstevel@tonic-gate 		log_exit();
393*7c478bd9Sstevel@tonic-gate 		return;		/* zone is being destroyed, ignore update */
394*7c478bd9Sstevel@tonic-gate 	} else {
395*7c478bd9Sstevel@tonic-gate 		lzp = zone_getspecific(log_zone_key, zptr);
396*7c478bd9Sstevel@tonic-gate 	}
397*7c478bd9Sstevel@tonic-gate 	ASSERT(lzp != NULL);
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) {
400*7c478bd9Sstevel@tonic-gate 		lp = &lzp->lz_clones[i];
401*7c478bd9Sstevel@tonic-gate 		if (zoneid == GLOBAL_ZONEID && (lp->log_flags & SL_CONSOLE))
402*7c478bd9Sstevel@tonic-gate 			log_consq = lp->log_q;
403*7c478bd9Sstevel@tonic-gate 		active |= lp->log_flags;
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate 	lzp->lz_active = active;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 	if (zptr)
408*7c478bd9Sstevel@tonic-gate 		zone_rele(zptr);
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	if (log_consq == target->log_q) {
411*7c478bd9Sstevel@tonic-gate 		if (flags & SL_CONSOLE)
412*7c478bd9Sstevel@tonic-gate 			log_conswitch(&log_backlog, target);
413*7c478bd9Sstevel@tonic-gate 		else
414*7c478bd9Sstevel@tonic-gate 			log_conswitch(target, &log_backlog);
415*7c478bd9Sstevel@tonic-gate 	}
416*7c478bd9Sstevel@tonic-gate 	target->log_q = q;
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	log_exit();
419*7c478bd9Sstevel@tonic-gate }
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
422*7c478bd9Sstevel@tonic-gate int
423*7c478bd9Sstevel@tonic-gate log_error(log_t *lp, log_ctl_t *lc)
424*7c478bd9Sstevel@tonic-gate {
425*7c478bd9Sstevel@tonic-gate 	if ((lc->pri & LOG_FACMASK) == LOG_KERN)
426*7c478bd9Sstevel@tonic-gate 		lc->pri = LOG_KERN | LOG_ERR;
427*7c478bd9Sstevel@tonic-gate 	return (1);
428*7c478bd9Sstevel@tonic-gate }
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate int
431*7c478bd9Sstevel@tonic-gate log_trace(log_t *lp, log_ctl_t *lc)
432*7c478bd9Sstevel@tonic-gate {
433*7c478bd9Sstevel@tonic-gate 	trace_ids_t *tid = (trace_ids_t *)lp->log_data->b_rptr;
434*7c478bd9Sstevel@tonic-gate 	trace_ids_t *tidend = (trace_ids_t *)lp->log_data->b_wptr;
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 	/*
437*7c478bd9Sstevel@tonic-gate 	 * We use `tid + 1 <= tidend' here rather than the more traditional
438*7c478bd9Sstevel@tonic-gate 	 * `tid < tidend', since the former ensures that there's at least
439*7c478bd9Sstevel@tonic-gate 	 * `sizeof (trace_ids_t)' bytes available before executing the
440*7c478bd9Sstevel@tonic-gate 	 * loop, whereas the latter only ensures that there's a single byte.
441*7c478bd9Sstevel@tonic-gate 	 */
442*7c478bd9Sstevel@tonic-gate 	for (; tid + 1 <= tidend; tid++) {
443*7c478bd9Sstevel@tonic-gate 		if (tid->ti_level < lc->level && tid->ti_level >= 0)
444*7c478bd9Sstevel@tonic-gate 			continue;
445*7c478bd9Sstevel@tonic-gate 		if (tid->ti_mid != lc->mid && tid->ti_mid >= 0)
446*7c478bd9Sstevel@tonic-gate 			continue;
447*7c478bd9Sstevel@tonic-gate 		if (tid->ti_sid != lc->sid && tid->ti_sid >= 0)
448*7c478bd9Sstevel@tonic-gate 			continue;
449*7c478bd9Sstevel@tonic-gate 		if ((lc->pri & LOG_FACMASK) == LOG_KERN)
450*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_DEBUG;
451*7c478bd9Sstevel@tonic-gate 		return (1);
452*7c478bd9Sstevel@tonic-gate 	}
453*7c478bd9Sstevel@tonic-gate 	return (0);
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
457*7c478bd9Sstevel@tonic-gate int
458*7c478bd9Sstevel@tonic-gate log_console(log_t *lp, log_ctl_t *lc)
459*7c478bd9Sstevel@tonic-gate {
460*7c478bd9Sstevel@tonic-gate 	if ((lc->pri & LOG_FACMASK) == LOG_KERN) {
461*7c478bd9Sstevel@tonic-gate 		if (lc->flags & SL_FATAL)
462*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_CRIT;
463*7c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_ERROR)
464*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_ERR;
465*7c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_WARN)
466*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_WARNING;
467*7c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_NOTE)
468*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_NOTICE;
469*7c478bd9Sstevel@tonic-gate 		else if (lc->flags & SL_TRACE)
470*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_DEBUG;
471*7c478bd9Sstevel@tonic-gate 		else
472*7c478bd9Sstevel@tonic-gate 			lc->pri = LOG_KERN | LOG_INFO;
473*7c478bd9Sstevel@tonic-gate 	}
474*7c478bd9Sstevel@tonic-gate 	return (1);
475*7c478bd9Sstevel@tonic-gate }
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate mblk_t *
478*7c478bd9Sstevel@tonic-gate log_makemsg(int mid, int sid, int level, int sl, int pri, void *msg,
479*7c478bd9Sstevel@tonic-gate 	size_t size, int on_intr)
480*7c478bd9Sstevel@tonic-gate {
481*7c478bd9Sstevel@tonic-gate 	mblk_t *mp = NULL;
482*7c478bd9Sstevel@tonic-gate 	mblk_t *mp2;
483*7c478bd9Sstevel@tonic-gate 	log_ctl_t *lc;
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if (size <= LOG_MSGSIZE &&
486*7c478bd9Sstevel@tonic-gate 	    (on_intr || log_freeq->q_count > log_freeq->q_lowat))
487*7c478bd9Sstevel@tonic-gate 		mp = getq_noenab(log_freeq);
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	if (mp == NULL) {
490*7c478bd9Sstevel@tonic-gate 		if (on_intr ||
491*7c478bd9Sstevel@tonic-gate 		    (mp = allocb(sizeof (log_ctl_t), BPRI_HI)) == NULL ||
492*7c478bd9Sstevel@tonic-gate 		    (mp2 = allocb(MAX(size, LOG_MSGSIZE), BPRI_HI)) == NULL) {
493*7c478bd9Sstevel@tonic-gate 			freemsg(mp);
494*7c478bd9Sstevel@tonic-gate 			return (NULL);
495*7c478bd9Sstevel@tonic-gate 		}
496*7c478bd9Sstevel@tonic-gate 		DB_TYPE(mp) = M_PROTO;
497*7c478bd9Sstevel@tonic-gate 		mp->b_wptr += sizeof (log_ctl_t);
498*7c478bd9Sstevel@tonic-gate 		mp->b_cont = mp2;
499*7c478bd9Sstevel@tonic-gate 	} else {
500*7c478bd9Sstevel@tonic-gate 		mp2 = mp->b_cont;
501*7c478bd9Sstevel@tonic-gate 		mp2->b_wptr = mp2->b_rptr;
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	lc = (log_ctl_t *)mp->b_rptr;
505*7c478bd9Sstevel@tonic-gate 	lc->mid = mid;
506*7c478bd9Sstevel@tonic-gate 	lc->sid = sid;
507*7c478bd9Sstevel@tonic-gate 	lc->level = level;
508*7c478bd9Sstevel@tonic-gate 	lc->flags = sl;
509*7c478bd9Sstevel@tonic-gate 	lc->pri = pri;
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 	bcopy(msg, mp2->b_wptr, size - 1);
512*7c478bd9Sstevel@tonic-gate 	mp2->b_wptr[size - 1] = '\0';
513*7c478bd9Sstevel@tonic-gate 	mp2->b_wptr += strlen((char *)mp2->b_wptr) + 1;
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 	return (mp);
516*7c478bd9Sstevel@tonic-gate }
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate void
519*7c478bd9Sstevel@tonic-gate log_freemsg(mblk_t *mp)
520*7c478bd9Sstevel@tonic-gate {
521*7c478bd9Sstevel@tonic-gate 	mblk_t *mp2 = mp->b_cont;
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	ASSERT(MBLKL(mp) == sizeof (log_ctl_t));
524*7c478bd9Sstevel@tonic-gate 	ASSERT(mp2->b_rptr == mp2->b_datap->db_base);
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	if ((log_freeq->q_flag & QFULL) == 0 &&
527*7c478bd9Sstevel@tonic-gate 	    MBLKL(mp2) <= LOG_MSGSIZE && MBLKSIZE(mp2) >= LOG_MSGSIZE)
528*7c478bd9Sstevel@tonic-gate 		(void) putq(log_freeq, mp);
529*7c478bd9Sstevel@tonic-gate 	else
530*7c478bd9Sstevel@tonic-gate 		freemsg(mp);
531*7c478bd9Sstevel@tonic-gate }
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate void
534*7c478bd9Sstevel@tonic-gate log_sendmsg(mblk_t *mp, zoneid_t zoneid)
535*7c478bd9Sstevel@tonic-gate {
536*7c478bd9Sstevel@tonic-gate 	log_t *lp;
537*7c478bd9Sstevel@tonic-gate 	char *src, *dst;
538*7c478bd9Sstevel@tonic-gate 	mblk_t *mp2 = mp->b_cont;
539*7c478bd9Sstevel@tonic-gate 	log_ctl_t *lc = (log_ctl_t *)mp->b_rptr;
540*7c478bd9Sstevel@tonic-gate 	int flags, fac;
541*7c478bd9Sstevel@tonic-gate 	off_t facility = 0;
542*7c478bd9Sstevel@tonic-gate 	off_t body = 0;
543*7c478bd9Sstevel@tonic-gate 	zone_t *zptr = NULL;
544*7c478bd9Sstevel@tonic-gate 	log_zone_t *lzp;
545*7c478bd9Sstevel@tonic-gate 	int i;
546*7c478bd9Sstevel@tonic-gate 	int backlog;
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 	/*
549*7c478bd9Sstevel@tonic-gate 	 * Need to special case the global zone here since this may be
550*7c478bd9Sstevel@tonic-gate 	 * called before zone_init.
551*7c478bd9Sstevel@tonic-gate 	 */
552*7c478bd9Sstevel@tonic-gate 	if (zoneid == GLOBAL_ZONEID) {
553*7c478bd9Sstevel@tonic-gate 		lzp = &log_global;
554*7c478bd9Sstevel@tonic-gate 	} else if ((zptr = zone_find_by_id(zoneid)) == NULL) {
555*7c478bd9Sstevel@tonic-gate 		/* specified zone doesn't exist, free message and return */
556*7c478bd9Sstevel@tonic-gate 		log_freemsg(mp);
557*7c478bd9Sstevel@tonic-gate 		return;
558*7c478bd9Sstevel@tonic-gate 	} else {
559*7c478bd9Sstevel@tonic-gate 		lzp = zone_getspecific(log_zone_key, zptr);
560*7c478bd9Sstevel@tonic-gate 	}
561*7c478bd9Sstevel@tonic-gate 	ASSERT(lzp != NULL);
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	if ((lc->flags & lzp->lz_active) == 0) {
564*7c478bd9Sstevel@tonic-gate 		if (zptr)
565*7c478bd9Sstevel@tonic-gate 			zone_rele(zptr);
566*7c478bd9Sstevel@tonic-gate 		log_freemsg(mp);
567*7c478bd9Sstevel@tonic-gate 		return;
568*7c478bd9Sstevel@tonic-gate 	}
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	if (panicstr) {
571*7c478bd9Sstevel@tonic-gate 		/*
572*7c478bd9Sstevel@tonic-gate 		 * Raise the console queue's q_hiwat to ensure that we
573*7c478bd9Sstevel@tonic-gate 		 * capture all panic messages.
574*7c478bd9Sstevel@tonic-gate 		 */
575*7c478bd9Sstevel@tonic-gate 		log_consq->q_hiwat = 2 * LOG_HIWAT;
576*7c478bd9Sstevel@tonic-gate 		log_consq->q_flag &= ~QFULL;
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 		/* Message was created while panicking. */
579*7c478bd9Sstevel@tonic-gate 		lc->flags |= SL_PANICMSG;
580*7c478bd9Sstevel@tonic-gate 	}
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	src = (char *)mp2->b_rptr;
583*7c478bd9Sstevel@tonic-gate 	dst = strstr(src, "FACILITY_AND_PRIORITY] ");
584*7c478bd9Sstevel@tonic-gate 	if (dst != NULL) {
585*7c478bd9Sstevel@tonic-gate 		facility = dst - src;
586*7c478bd9Sstevel@tonic-gate 		body = facility + 23; /* strlen("FACILITY_AND_PRIORITY] ") */
587*7c478bd9Sstevel@tonic-gate 	}
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 	log_enter();
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 	lc->ltime = lbolt;
592*7c478bd9Sstevel@tonic-gate 	lc->ttime = gethrestime_sec();
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	flags = lc->flags & lzp->lz_active;
595*7c478bd9Sstevel@tonic-gate 	log_seq_no[flags & SL_ERROR]++;
596*7c478bd9Sstevel@tonic-gate 	log_seq_no[flags & SL_TRACE]++;
597*7c478bd9Sstevel@tonic-gate 	log_seq_no[flags & SL_CONSOLE]++;
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 	/*
600*7c478bd9Sstevel@tonic-gate 	 * If this is in the global zone, start with the backlog, then
601*7c478bd9Sstevel@tonic-gate 	 * walk through the clone logs.  If not, just do the clone logs.
602*7c478bd9Sstevel@tonic-gate 	 */
603*7c478bd9Sstevel@tonic-gate 	backlog = (zoneid == GLOBAL_ZONEID);
604*7c478bd9Sstevel@tonic-gate 	i = LOG_LOGMINIDX;
605*7c478bd9Sstevel@tonic-gate 	while (i <= LOG_LOGMAXIDX) {
606*7c478bd9Sstevel@tonic-gate 		if (backlog) {
607*7c478bd9Sstevel@tonic-gate 			/*
608*7c478bd9Sstevel@tonic-gate 			 * Do the backlog this time, then start on the
609*7c478bd9Sstevel@tonic-gate 			 * others.
610*7c478bd9Sstevel@tonic-gate 			 */
611*7c478bd9Sstevel@tonic-gate 			backlog = 0;
612*7c478bd9Sstevel@tonic-gate 			lp = &log_backlog;
613*7c478bd9Sstevel@tonic-gate 		} else {
614*7c478bd9Sstevel@tonic-gate 			lp = &lzp->lz_clones[i++];
615*7c478bd9Sstevel@tonic-gate 		}
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 		if ((lp->log_flags & flags) && lp->log_wanted(lp, lc)) {
618*7c478bd9Sstevel@tonic-gate 			if (canput(lp->log_q)) {
619*7c478bd9Sstevel@tonic-gate 				lp->log_overflow = 0;
620*7c478bd9Sstevel@tonic-gate 				lc->seq_no = log_seq_no[lp->log_flags];
621*7c478bd9Sstevel@tonic-gate 				if ((mp2 = copymsg(mp)) == NULL)
622*7c478bd9Sstevel@tonic-gate 					break;
623*7c478bd9Sstevel@tonic-gate 				if (facility != 0) {
624*7c478bd9Sstevel@tonic-gate 					src = (char *)mp2->b_cont->b_rptr;
625*7c478bd9Sstevel@tonic-gate 					dst = src + facility;
626*7c478bd9Sstevel@tonic-gate 					fac = (lc->pri & LOG_FACMASK) >> 3;
627*7c478bd9Sstevel@tonic-gate 					dst += snprintf(dst,
628*7c478bd9Sstevel@tonic-gate 					    LOG_FACSIZE + LOG_PRISIZE, "%s.%s",
629*7c478bd9Sstevel@tonic-gate 					    log_fac[MIN(fac, LOG_NFACILITIES)],
630*7c478bd9Sstevel@tonic-gate 					    log_pri[lc->pri & LOG_PRIMASK]);
631*7c478bd9Sstevel@tonic-gate 					src += body - 2; /* copy "] " too */
632*7c478bd9Sstevel@tonic-gate 					while (*src != '\0')
633*7c478bd9Sstevel@tonic-gate 						*dst++ = *src++;
634*7c478bd9Sstevel@tonic-gate 					*dst++ = '\0';
635*7c478bd9Sstevel@tonic-gate 					mp2->b_cont->b_wptr = (uchar_t *)dst;
636*7c478bd9Sstevel@tonic-gate 				}
637*7c478bd9Sstevel@tonic-gate 				(void) putq(lp->log_q, mp2);
638*7c478bd9Sstevel@tonic-gate 			} else if (++lp->log_overflow == 1) {
639*7c478bd9Sstevel@tonic-gate 				if (lp->log_q == log_consq) {
640*7c478bd9Sstevel@tonic-gate 					console_printf(log_overflow_msg,
641*7c478bd9Sstevel@tonic-gate 					    lp->log_minor,
642*7c478bd9Sstevel@tonic-gate 					    " -- is syslogd(1M) running?");
643*7c478bd9Sstevel@tonic-gate 				} else {
644*7c478bd9Sstevel@tonic-gate 					printf(log_overflow_msg,
645*7c478bd9Sstevel@tonic-gate 					    lp->log_minor, "");
646*7c478bd9Sstevel@tonic-gate 				}
647*7c478bd9Sstevel@tonic-gate 			}
648*7c478bd9Sstevel@tonic-gate 		}
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	if (zptr)
652*7c478bd9Sstevel@tonic-gate 		zone_rele(zptr);
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 	if ((flags & SL_CONSOLE) && (lc->pri & LOG_FACMASK) == LOG_KERN) {
655*7c478bd9Sstevel@tonic-gate 		if ((mp2 == NULL || log_consq == log_backlogq || panicstr) &&
656*7c478bd9Sstevel@tonic-gate 		    (lc->flags & SL_LOGONLY) == 0)
657*7c478bd9Sstevel@tonic-gate 			console_printf("%s", (char *)mp->b_cont->b_rptr + body);
658*7c478bd9Sstevel@tonic-gate 		if ((lc->flags & SL_CONSONLY) == 0 &&
659*7c478bd9Sstevel@tonic-gate 		    (mp2 = copymsg(mp)) != NULL) {
660*7c478bd9Sstevel@tonic-gate 			mp2->b_cont->b_rptr += body;
661*7c478bd9Sstevel@tonic-gate 			if (log_recentq->q_flag & QFULL)
662*7c478bd9Sstevel@tonic-gate 				freemsg(getq_noenab(log_recentq));
663*7c478bd9Sstevel@tonic-gate 			(void) putq(log_recentq, mp2);
664*7c478bd9Sstevel@tonic-gate 		}
665*7c478bd9Sstevel@tonic-gate 	}
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	log_freemsg(mp);
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	log_exit();
670*7c478bd9Sstevel@tonic-gate }
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate /*
673*7c478bd9Sstevel@tonic-gate  * Print queued messages to console.
674*7c478bd9Sstevel@tonic-gate  */
675*7c478bd9Sstevel@tonic-gate void
676*7c478bd9Sstevel@tonic-gate log_printq(queue_t *qfirst)
677*7c478bd9Sstevel@tonic-gate {
678*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
679*7c478bd9Sstevel@tonic-gate 	queue_t *q, *qlast;
680*7c478bd9Sstevel@tonic-gate 	char *cp, *msgp;
681*7c478bd9Sstevel@tonic-gate 	log_ctl_t *lc;
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	/*
684*7c478bd9Sstevel@tonic-gate 	 * Look ahead to first queued message in the stream.
685*7c478bd9Sstevel@tonic-gate 	 */
686*7c478bd9Sstevel@tonic-gate 	qlast = NULL;
687*7c478bd9Sstevel@tonic-gate 	do {
688*7c478bd9Sstevel@tonic-gate 		for (q = qfirst; q->q_next != qlast; q = q->q_next)
689*7c478bd9Sstevel@tonic-gate 			continue;
690*7c478bd9Sstevel@tonic-gate 		for (mp = q->q_first; mp != NULL; mp = mp->b_next) {
691*7c478bd9Sstevel@tonic-gate 			lc = (log_ctl_t *)mp->b_rptr;
692*7c478bd9Sstevel@tonic-gate 			/*
693*7c478bd9Sstevel@tonic-gate 			 * Check if message is already displayed at
694*7c478bd9Sstevel@tonic-gate 			 * /dev/console.
695*7c478bd9Sstevel@tonic-gate 			 */
696*7c478bd9Sstevel@tonic-gate 			if (lc->flags & SL_PANICMSG)
697*7c478bd9Sstevel@tonic-gate 				continue;
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 			cp = (char *)mp->b_cont->b_rptr;
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 			/* Strip off the message ID. */
702*7c478bd9Sstevel@tonic-gate 			if ((msgp = strstr(cp, "[ID ")) != NULL &&
703*7c478bd9Sstevel@tonic-gate 			    (msgp = strstr(msgp,  "] ")) != NULL) {
704*7c478bd9Sstevel@tonic-gate 				cp = msgp + 2;
705*7c478bd9Sstevel@tonic-gate 			}
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 			/*
708*7c478bd9Sstevel@tonic-gate 			 * Using console_printf instead of printf to avoid
709*7c478bd9Sstevel@tonic-gate 			 * queueing messages to log_consq.
710*7c478bd9Sstevel@tonic-gate 			 */
711*7c478bd9Sstevel@tonic-gate 			console_printf("%s", cp);
712*7c478bd9Sstevel@tonic-gate 		}
713*7c478bd9Sstevel@tonic-gate 	} while ((qlast = q) != qfirst);
714*7c478bd9Sstevel@tonic-gate }
715