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 /* 23*ba91f08bSGary Mills * Copyright (c) 2013 Gary Mills 24861a9162SJohn Beck * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/param.h> 297c478bd9Sstevel@tonic-gate #include <sys/varargs.h> 307c478bd9Sstevel@tonic-gate #include <sys/systm.h> 317c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 327c478bd9Sstevel@tonic-gate #include <sys/stream.h> 337c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 347c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 357c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 367c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 377c478bd9Sstevel@tonic-gate #include <sys/log.h> 387c478bd9Sstevel@tonic-gate #include <sys/spl.h> 397c478bd9Sstevel@tonic-gate #include <sys/syslog.h> 407c478bd9Sstevel@tonic-gate #include <sys/console.h> 417c478bd9Sstevel@tonic-gate #include <sys/debug.h> 427c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 437c478bd9Sstevel@tonic-gate #include <sys/id_space.h> 447c478bd9Sstevel@tonic-gate #include <sys/zone.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate log_zone_t log_global; 477c478bd9Sstevel@tonic-gate queue_t *log_consq; 487c478bd9Sstevel@tonic-gate queue_t *log_backlogq; 497c478bd9Sstevel@tonic-gate queue_t *log_intrq; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #define LOG_PRISIZE 8 /* max priority size: 7 characters + null */ 527c478bd9Sstevel@tonic-gate #define LOG_FACSIZE 9 /* max priority size: 8 characters + null */ 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static krwlock_t log_rwlock; 557c478bd9Sstevel@tonic-gate static int log_rwlock_depth; 567c478bd9Sstevel@tonic-gate static int log_seq_no[SL_CONSOLE + 1]; 577c478bd9Sstevel@tonic-gate static stdata_t log_fakestr; 587c478bd9Sstevel@tonic-gate static id_space_t *log_minorspace; 597c478bd9Sstevel@tonic-gate static log_t log_backlog; 60068ccd7aSns92644 static struct kmem_cache *log_cons_cache; /* log_t cache */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate static queue_t *log_recentq; 637c478bd9Sstevel@tonic-gate static queue_t *log_freeq; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static zone_key_t log_zone_key; 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate static char log_overflow_msg[] = "message overflow on /dev/log minor #%d%s\n"; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate static char log_pri[LOG_PRIMASK + 1][LOG_PRISIZE] = { 707c478bd9Sstevel@tonic-gate "emerg", "alert", "crit", "error", 717c478bd9Sstevel@tonic-gate "warning", "notice", "info", "debug" 727c478bd9Sstevel@tonic-gate }; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static char log_fac[LOG_NFACILITIES + 1][LOG_FACSIZE] = { 757c478bd9Sstevel@tonic-gate "kern", "user", "mail", "daemon", 767c478bd9Sstevel@tonic-gate "auth", "syslog", "lpr", "news", 77*ba91f08bSGary Mills "uucp", "altcron", "authpriv", "ftp", 78*ba91f08bSGary Mills "ntp", "audit", "console", "cron", 797c478bd9Sstevel@tonic-gate "local0", "local1", "local2", "local3", 807c478bd9Sstevel@tonic-gate "local4", "local5", "local6", "local7", 817c478bd9Sstevel@tonic-gate "unknown" 827c478bd9Sstevel@tonic-gate }; 83068ccd7aSns92644 static int log_cons_constructor(void *, void *, int); 84068ccd7aSns92644 static void log_cons_destructor(void *, void *); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* 877c478bd9Sstevel@tonic-gate * Get exclusive access to the logging system; this includes all minor 887c478bd9Sstevel@tonic-gate * devices. We use an rwlock rather than a mutex because hold times 897c478bd9Sstevel@tonic-gate * are potentially long, so we don't want to waste cycles in adaptive mutex 907c478bd9Sstevel@tonic-gate * spin (rwlocks always block when contended). Note that we explicitly 917c478bd9Sstevel@tonic-gate * support recursive calls (e.g. printf() calls foo() calls printf()). 927c478bd9Sstevel@tonic-gate * 937c478bd9Sstevel@tonic-gate * Clients may use log_enter() / log_exit() to guarantee that a group 947c478bd9Sstevel@tonic-gate * of messages is treated atomically (i.e. they appear in order and are 957c478bd9Sstevel@tonic-gate * not interspersed with any other messages), e.g. for multiline printf(). 967c478bd9Sstevel@tonic-gate * 977c478bd9Sstevel@tonic-gate * This could probably be changed to a per-zone lock if contention becomes 987c478bd9Sstevel@tonic-gate * an issue. 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate void 1017c478bd9Sstevel@tonic-gate log_enter(void) 1027c478bd9Sstevel@tonic-gate { 1037c478bd9Sstevel@tonic-gate if (rw_owner(&log_rwlock) != curthread) 1047c478bd9Sstevel@tonic-gate rw_enter(&log_rwlock, RW_WRITER); 1057c478bd9Sstevel@tonic-gate log_rwlock_depth++; 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate void 1097c478bd9Sstevel@tonic-gate log_exit(void) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate if (--log_rwlock_depth == 0) 1127c478bd9Sstevel@tonic-gate rw_exit(&log_rwlock); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate void 1167c478bd9Sstevel@tonic-gate log_flushq(queue_t *q) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate mblk_t *mp; 1197c478bd9Sstevel@tonic-gate log_t *lp = (log_t *)q->q_ptr; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* lp will be NULL if the queue was created via log_makeq */ 122301ce41fSja97890 while ((mp = getq_noenab(q, 0)) != NULL) 1237c478bd9Sstevel@tonic-gate log_sendmsg(mp, lp == NULL ? GLOBAL_ZONEID : lp->log_zoneid); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Create a minimal queue with just enough fields filled in to support 1287c478bd9Sstevel@tonic-gate * canput(9F), putq(9F), and getq_noenab(9F). We set QNOENB to ensure 1297c478bd9Sstevel@tonic-gate * that the queue will never be enabled. 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate static queue_t * 1327c478bd9Sstevel@tonic-gate log_makeq(size_t lowat, size_t hiwat, void *ibc) 1337c478bd9Sstevel@tonic-gate { 1347c478bd9Sstevel@tonic-gate queue_t *q; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate q = kmem_zalloc(sizeof (queue_t), KM_SLEEP); 1377c478bd9Sstevel@tonic-gate q->q_stream = &log_fakestr; 1387c478bd9Sstevel@tonic-gate q->q_flag = QISDRV | QMTSAFE | QNOENB | QREADR | QUSE; 1397c478bd9Sstevel@tonic-gate q->q_nfsrv = q; 1407c478bd9Sstevel@tonic-gate q->q_lowat = lowat; 1417c478bd9Sstevel@tonic-gate q->q_hiwat = hiwat; 1427c478bd9Sstevel@tonic-gate mutex_init(QLOCK(q), NULL, MUTEX_DRIVER, ibc); 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate return (q); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * Initialize the log structure for a new zone. 1497c478bd9Sstevel@tonic-gate */ 1507c478bd9Sstevel@tonic-gate static void * 1517c478bd9Sstevel@tonic-gate log_zoneinit(zoneid_t zoneid) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate int i; 1547c478bd9Sstevel@tonic-gate log_zone_t *lzp; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (zoneid == GLOBAL_ZONEID) 1577c478bd9Sstevel@tonic-gate lzp = &log_global; /* use statically allocated struct */ 1587c478bd9Sstevel@tonic-gate else 1597c478bd9Sstevel@tonic-gate lzp = kmem_zalloc(sizeof (log_zone_t), KM_SLEEP); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NUMCLONES; i++) { 1627c478bd9Sstevel@tonic-gate lzp->lz_clones[i].log_minor = 1637c478bd9Sstevel@tonic-gate (minor_t)id_alloc(log_minorspace); 1647c478bd9Sstevel@tonic-gate lzp->lz_clones[i].log_zoneid = zoneid; 1657c478bd9Sstevel@tonic-gate } 1667c478bd9Sstevel@tonic-gate return (lzp); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1707c478bd9Sstevel@tonic-gate static void 1717c478bd9Sstevel@tonic-gate log_zonefree(zoneid_t zoneid, void *arg) 1727c478bd9Sstevel@tonic-gate { 1737c478bd9Sstevel@tonic-gate log_zone_t *lzp = arg; 1747c478bd9Sstevel@tonic-gate int i; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate ASSERT(lzp != &log_global && zoneid != GLOBAL_ZONEID); 1777c478bd9Sstevel@tonic-gate if (lzp == NULL) 1787c478bd9Sstevel@tonic-gate return; 1797c478bd9Sstevel@tonic-gate for (i = 0; i < LOG_NUMCLONES; i++) 1807c478bd9Sstevel@tonic-gate id_free(log_minorspace, lzp->lz_clones[i].log_minor); 1817c478bd9Sstevel@tonic-gate kmem_free(lzp, sizeof (log_zone_t)); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate void 1857c478bd9Sstevel@tonic-gate log_init(void) 1867c478bd9Sstevel@tonic-gate { 1877c478bd9Sstevel@tonic-gate int log_maxzones; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * Create a backlog queue to consume console messages during periods 1917c478bd9Sstevel@tonic-gate * when there is no console reader (e.g. before syslogd(1M) starts). 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate log_backlogq = log_consq = log_makeq(0, LOG_HIWAT, NULL); 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * Create a queue to hold free message of size <= LOG_MSGSIZE. 1977c478bd9Sstevel@tonic-gate * Calls from high-level interrupt handlers will do a getq_noenab() 1987c478bd9Sstevel@tonic-gate * from this queue, so its q_lock must be a maximum SPL spin lock. 1997c478bd9Sstevel@tonic-gate */ 2007c478bd9Sstevel@tonic-gate log_freeq = log_makeq(LOG_MINFREE, LOG_MAXFREE, (void *)ipltospl(SPL8)); 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Create a queue for messages from high-level interrupt context. 2047c478bd9Sstevel@tonic-gate * These messages are drained via softcall, or explicitly by panic(). 2057c478bd9Sstevel@tonic-gate */ 2067c478bd9Sstevel@tonic-gate log_intrq = log_makeq(0, LOG_HIWAT, (void *)ipltospl(SPL8)); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Create a queue to hold the most recent 8K of console messages. 2107c478bd9Sstevel@tonic-gate * Useful for debugging. Required by the "$<msgbuf" adb macro. 2117c478bd9Sstevel@tonic-gate */ 2127c478bd9Sstevel@tonic-gate log_recentq = log_makeq(0, LOG_RECENTSIZE, NULL); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Create an id space for clone devices opened via /dev/log. 2167c478bd9Sstevel@tonic-gate * Need to limit the number of zones to avoid exceeding the 2177c478bd9Sstevel@tonic-gate * available minor number space. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate log_maxzones = (L_MAXMIN32 - LOG_LOGMIN) / LOG_NUMCLONES - 1; 2207c478bd9Sstevel@tonic-gate if (log_maxzones < maxzones) 2217c478bd9Sstevel@tonic-gate maxzones = log_maxzones; 2227c478bd9Sstevel@tonic-gate log_minorspace = id_space_create("logminor_space", LOG_LOGMIN + 1, 2237c478bd9Sstevel@tonic-gate L_MAXMIN32); 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Put ourselves on the ZSD list. Note that zones have not been 2267c478bd9Sstevel@tonic-gate * initialized yet, but our constructor will be called on the global 2277c478bd9Sstevel@tonic-gate * zone when they are. 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate zone_key_create(&log_zone_key, log_zoneinit, NULL, log_zonefree); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * Initialize backlog structure. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate log_backlog.log_zoneid = GLOBAL_ZONEID; 2357c478bd9Sstevel@tonic-gate log_backlog.log_minor = LOG_BACKLOG; 2367c478bd9Sstevel@tonic-gate 237068ccd7aSns92644 /* Allocate kmem cache for conslog's log structures */ 238068ccd7aSns92644 log_cons_cache = kmem_cache_create("log_cons_cache", 239068ccd7aSns92644 sizeof (struct log), 0, log_cons_constructor, log_cons_destructor, 240068ccd7aSns92644 NULL, NULL, NULL, 0); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Let the logging begin. 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate log_update(&log_backlog, log_backlogq, SL_CONSOLE, log_console); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * Now that logging is enabled, emit the SunOS banner. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate printf("\rSunOS Release %s Version %s %u-bit\n", 2517c478bd9Sstevel@tonic-gate utsname.release, utsname.version, NBBY * (uint_t)sizeof (void *)); 252861a9162SJohn Beck printf("Copyright (c) 1983, 2010, Oracle and/or its affiliates. " 253861a9162SJohn Beck "All rights reserved.\n"); 2547c478bd9Sstevel@tonic-gate #ifdef DEBUG 2557c478bd9Sstevel@tonic-gate printf("DEBUG enabled\n"); 2567c478bd9Sstevel@tonic-gate #endif 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 260068ccd7aSns92644 * Allocate a log device corresponding to supplied device type. 261068ccd7aSns92644 * Both devices are clonable. /dev/log devices are allocated per zone. 262068ccd7aSns92644 * /dev/conslog devices are allocated from kmem cache. 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate log_t * 2657c478bd9Sstevel@tonic-gate log_alloc(minor_t type) 2667c478bd9Sstevel@tonic-gate { 2677c478bd9Sstevel@tonic-gate zone_t *zptr = curproc->p_zone; 2687c478bd9Sstevel@tonic-gate log_zone_t *lzp; 2697c478bd9Sstevel@tonic-gate log_t *lp; 2707c478bd9Sstevel@tonic-gate int i; 271068ccd7aSns92644 minor_t minor; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate if (type == LOG_CONSMIN) { 2747c478bd9Sstevel@tonic-gate 275068ccd7aSns92644 /* 276068ccd7aSns92644 * Return a write-only /dev/conslog device. 277068ccd7aSns92644 * No point allocating log_t until there's a free minor number. 278068ccd7aSns92644 */ 279068ccd7aSns92644 minor = (minor_t)id_alloc(log_minorspace); 280068ccd7aSns92644 lp = kmem_cache_alloc(log_cons_cache, KM_SLEEP); 281068ccd7aSns92644 lp->log_minor = minor; 282068ccd7aSns92644 return (lp); 283068ccd7aSns92644 } else { 2847c478bd9Sstevel@tonic-gate ASSERT(type == LOG_LOGMIN); 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate lzp = zone_getspecific(log_zone_key, zptr); 2877c478bd9Sstevel@tonic-gate ASSERT(lzp != NULL); 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* search for an available /dev/log device for the zone */ 2907c478bd9Sstevel@tonic-gate for (i = LOG_LOGMINIDX; i <= LOG_LOGMAXIDX; i++) { 2917c478bd9Sstevel@tonic-gate lp = &lzp->lz_clones[i]; 2927c478bd9Sstevel@tonic-gate if (lp->log_inuse == 0) 2937c478bd9Sstevel@tonic-gate break; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate if (i > LOG_LOGMAXIDX) 2967c478bd9Sstevel@tonic-gate lp = NULL; 297068ccd7aSns92644 else 298068ccd7aSns92644 /* Indicate which device type */ 299068ccd7aSns92644 lp->log_major = LOG_LOGMIN; 3007c478bd9Sstevel@tonic-gate return (lp); 3017c478bd9Sstevel@tonic-gate } 302068ccd7aSns92644 } 303068ccd7aSns92644 304068ccd7aSns92644 void 305068ccd7aSns92644 log_free(log_t *lp) 306068ccd7aSns92644 { 307068ccd7aSns92644 id_free(log_minorspace, lp->log_minor); 308068ccd7aSns92644 kmem_cache_free(log_cons_cache, lp); 309068ccd7aSns92644 } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* 3127c478bd9Sstevel@tonic-gate * Move console messages from src to dst. The time of day isn't known 3137c478bd9Sstevel@tonic-gate * early in boot, so fix up the message timestamps if necessary. 3147c478bd9Sstevel@tonic-gate */ 3157c478bd9Sstevel@tonic-gate static void 3167c478bd9Sstevel@tonic-gate log_conswitch(log_t *src, log_t *dst) 3177c478bd9Sstevel@tonic-gate { 3187c478bd9Sstevel@tonic-gate mblk_t *mp; 3197c478bd9Sstevel@tonic-gate mblk_t *hmp = NULL; 3207c478bd9Sstevel@tonic-gate mblk_t *tmp = NULL; 3217c478bd9Sstevel@tonic-gate log_ctl_t *hlc; 3227c478bd9Sstevel@tonic-gate 323301ce41fSja97890 while ((mp = getq_noenab(src->log_q, 0)) != NULL) { 3247c478bd9Sstevel@tonic-gate log_ctl_t *lc = (log_ctl_t *)mp->b_rptr; 3257c478bd9Sstevel@tonic-gate lc->flags |= SL_LOGONLY; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate /* 3283348528fSdm120769 * The ttime is written with 0 in log_sensmsg() only when 3298cff005aSkk112340 * good gethrestime_sec() data is not available to store in 3308cff005aSkk112340 * the log_ctl_t in the early boot phase. 3317c478bd9Sstevel@tonic-gate */ 3328cff005aSkk112340 if (lc->ttime == 0) { 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * Look ahead to first early boot message with time. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate if (hmp) { 3377c478bd9Sstevel@tonic-gate tmp->b_next = mp; 3387c478bd9Sstevel@tonic-gate tmp = mp; 3397c478bd9Sstevel@tonic-gate } else 3407c478bd9Sstevel@tonic-gate hmp = tmp = mp; 3417c478bd9Sstevel@tonic-gate continue; 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate while (hmp) { 3457c478bd9Sstevel@tonic-gate tmp = hmp->b_next; 3467c478bd9Sstevel@tonic-gate hmp->b_next = NULL; 3477c478bd9Sstevel@tonic-gate hlc = (log_ctl_t *)hmp->b_rptr; 3487c478bd9Sstevel@tonic-gate /* 3497c478bd9Sstevel@tonic-gate * Calculate hrestime for an early log message with 3507c478bd9Sstevel@tonic-gate * an invalid time stamp. We know: 3517c478bd9Sstevel@tonic-gate * - the lbolt of the invalid time stamp. 3527c478bd9Sstevel@tonic-gate * - the hrestime and lbolt of the first valid 3537c478bd9Sstevel@tonic-gate * time stamp. 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate hlc->ttime = lc->ttime - (lc->ltime - hlc->ltime) / hz; 3567c478bd9Sstevel@tonic-gate (void) putq(dst->log_q, hmp); 3577c478bd9Sstevel@tonic-gate hmp = tmp; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate (void) putq(dst->log_q, mp); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate while (hmp) { 3627c478bd9Sstevel@tonic-gate tmp = hmp->b_next; 3637c478bd9Sstevel@tonic-gate hmp->b_next = NULL; 3647c478bd9Sstevel@tonic-gate hlc = (log_ctl_t *)hmp->b_rptr; 365d3d50737SRafael Vanoni hlc->ttime = gethrestime_sec() - 366d3d50737SRafael Vanoni (ddi_get_lbolt() - hlc->ltime) / hz; 3677c478bd9Sstevel@tonic-gate (void) putq(dst->log_q, hmp); 3687c478bd9Sstevel@tonic-gate hmp = tmp; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate dst->log_overflow = src->log_overflow; 3717c478bd9Sstevel@tonic-gate src->log_flags = 0; 3727c478bd9Sstevel@tonic-gate dst->log_flags = SL_CONSOLE; 3737c478bd9Sstevel@tonic-gate log_consq = dst->log_q; 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate 3767c478bd9Sstevel@tonic-gate /* 3777c478bd9Sstevel@tonic-gate * Set the fields in the 'target' clone to the specified values. 3787c478bd9Sstevel@tonic-gate * Then, look at all clones to determine which message types are 3797c478bd9Sstevel@tonic-gate * currently active and which clone is the primary console queue. 3807c478bd9Sstevel@tonic-gate * If the primary console queue changes to or from the backlog 3817c478bd9Sstevel@tonic-gate * queue, copy all messages from backlog to primary or vice versa. 3827c478bd9Sstevel@tonic-gate */ 3837c478bd9Sstevel@tonic-gate void 3847c478bd9Sstevel@tonic-gate log_update(log_t *target, queue_t *q, short flags, log_filter_t *filter) 3857c478bd9Sstevel@tonic-gate { 3867c478bd9Sstevel@tonic-gate log_t *lp; 3877c478bd9Sstevel@tonic-gate short active = SL_CONSOLE; 3887c478bd9Sstevel@tonic-gate zone_t *zptr = NULL; 3897c478bd9Sstevel@tonic-gate log_zone_t *lzp; 3907c478bd9Sstevel@tonic-gate zoneid_t zoneid = target->log_zoneid; 3917c478bd9Sstevel@tonic-gate int i; 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate log_enter(); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate if (q != NULL) 3967c478bd9Sstevel@tonic-gate target->log_q = q; 3977c478bd9Sstevel@tonic-gate target->log_wanted = filter; 3987c478bd9Sstevel@tonic-gate target->log_flags = flags; 3997c478bd9Sstevel@tonic-gate target->log_overflow = 0; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Need to special case the global zone here since this may be 4037c478bd9Sstevel@tonic-gate * called before zone_init. 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate if (zoneid == GLOBAL_ZONEID) { 4067c478bd9Sstevel@tonic-gate lzp = &log_global; 4077c478bd9Sstevel@tonic-gate } else if ((zptr = zone_find_by_id(zoneid)) == NULL) { 4087c478bd9Sstevel@tonic-gate log_exit(); 4097c478bd9Sstevel@tonic-gate return; /* zone is being destroyed, ignore update */ 4107c478bd9Sstevel@tonic-gate } else { 4117c478bd9Sstevel@tonic-gate lzp = zone_getspecific(log_zone_key, zptr); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate ASSERT(lzp != NULL); 4147c478bd9Sstevel@tonic-gate for (i = LOG_LOGMAXIDX; i >= LOG_LOGMINIDX; i--) { 4157c478bd9Sstevel@tonic-gate lp = &lzp->lz_clones[i]; 4167c478bd9Sstevel@tonic-gate if (zoneid == GLOBAL_ZONEID && (lp->log_flags & SL_CONSOLE)) 4177c478bd9Sstevel@tonic-gate log_consq = lp->log_q; 4187c478bd9Sstevel@tonic-gate active |= lp->log_flags; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate lzp->lz_active = active; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate if (zptr) 4237c478bd9Sstevel@tonic-gate zone_rele(zptr); 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate if (log_consq == target->log_q) { 4267c478bd9Sstevel@tonic-gate if (flags & SL_CONSOLE) 4277c478bd9Sstevel@tonic-gate log_conswitch(&log_backlog, target); 4287c478bd9Sstevel@tonic-gate else 4297c478bd9Sstevel@tonic-gate log_conswitch(target, &log_backlog); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate target->log_q = q; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate log_exit(); 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4377c478bd9Sstevel@tonic-gate int 4387c478bd9Sstevel@tonic-gate log_error(log_t *lp, log_ctl_t *lc) 4397c478bd9Sstevel@tonic-gate { 4407c478bd9Sstevel@tonic-gate if ((lc->pri & LOG_FACMASK) == LOG_KERN) 4417c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_ERR; 4427c478bd9Sstevel@tonic-gate return (1); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate int 4467c478bd9Sstevel@tonic-gate log_trace(log_t *lp, log_ctl_t *lc) 4477c478bd9Sstevel@tonic-gate { 4487c478bd9Sstevel@tonic-gate trace_ids_t *tid = (trace_ids_t *)lp->log_data->b_rptr; 4497c478bd9Sstevel@tonic-gate trace_ids_t *tidend = (trace_ids_t *)lp->log_data->b_wptr; 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate /* 4527c478bd9Sstevel@tonic-gate * We use `tid + 1 <= tidend' here rather than the more traditional 4537c478bd9Sstevel@tonic-gate * `tid < tidend', since the former ensures that there's at least 4547c478bd9Sstevel@tonic-gate * `sizeof (trace_ids_t)' bytes available before executing the 4557c478bd9Sstevel@tonic-gate * loop, whereas the latter only ensures that there's a single byte. 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate for (; tid + 1 <= tidend; tid++) { 4587c478bd9Sstevel@tonic-gate if (tid->ti_level < lc->level && tid->ti_level >= 0) 4597c478bd9Sstevel@tonic-gate continue; 4607c478bd9Sstevel@tonic-gate if (tid->ti_mid != lc->mid && tid->ti_mid >= 0) 4617c478bd9Sstevel@tonic-gate continue; 4627c478bd9Sstevel@tonic-gate if (tid->ti_sid != lc->sid && tid->ti_sid >= 0) 4637c478bd9Sstevel@tonic-gate continue; 4647c478bd9Sstevel@tonic-gate if ((lc->pri & LOG_FACMASK) == LOG_KERN) 4657c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_DEBUG; 4667c478bd9Sstevel@tonic-gate return (1); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate return (0); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4727c478bd9Sstevel@tonic-gate int 4737c478bd9Sstevel@tonic-gate log_console(log_t *lp, log_ctl_t *lc) 4747c478bd9Sstevel@tonic-gate { 4757c478bd9Sstevel@tonic-gate if ((lc->pri & LOG_FACMASK) == LOG_KERN) { 4767c478bd9Sstevel@tonic-gate if (lc->flags & SL_FATAL) 4777c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_CRIT; 4787c478bd9Sstevel@tonic-gate else if (lc->flags & SL_ERROR) 4797c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_ERR; 4807c478bd9Sstevel@tonic-gate else if (lc->flags & SL_WARN) 4817c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_WARNING; 4827c478bd9Sstevel@tonic-gate else if (lc->flags & SL_NOTE) 4837c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_NOTICE; 4847c478bd9Sstevel@tonic-gate else if (lc->flags & SL_TRACE) 4857c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_DEBUG; 4867c478bd9Sstevel@tonic-gate else 4877c478bd9Sstevel@tonic-gate lc->pri = LOG_KERN | LOG_INFO; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate return (1); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate mblk_t * 4937c478bd9Sstevel@tonic-gate log_makemsg(int mid, int sid, int level, int sl, int pri, void *msg, 4947c478bd9Sstevel@tonic-gate size_t size, int on_intr) 4957c478bd9Sstevel@tonic-gate { 4967c478bd9Sstevel@tonic-gate mblk_t *mp = NULL; 4977c478bd9Sstevel@tonic-gate mblk_t *mp2; 4987c478bd9Sstevel@tonic-gate log_ctl_t *lc; 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate if (size <= LOG_MSGSIZE && 5017c478bd9Sstevel@tonic-gate (on_intr || log_freeq->q_count > log_freeq->q_lowat)) 502301ce41fSja97890 mp = getq_noenab(log_freeq, 0); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate if (mp == NULL) { 5057c478bd9Sstevel@tonic-gate if (on_intr || 5067c478bd9Sstevel@tonic-gate (mp = allocb(sizeof (log_ctl_t), BPRI_HI)) == NULL || 5077c478bd9Sstevel@tonic-gate (mp2 = allocb(MAX(size, LOG_MSGSIZE), BPRI_HI)) == NULL) { 5087c478bd9Sstevel@tonic-gate freemsg(mp); 5097c478bd9Sstevel@tonic-gate return (NULL); 5107c478bd9Sstevel@tonic-gate } 5117c478bd9Sstevel@tonic-gate DB_TYPE(mp) = M_PROTO; 5127c478bd9Sstevel@tonic-gate mp->b_wptr += sizeof (log_ctl_t); 5137c478bd9Sstevel@tonic-gate mp->b_cont = mp2; 5147c478bd9Sstevel@tonic-gate } else { 5157c478bd9Sstevel@tonic-gate mp2 = mp->b_cont; 5167c478bd9Sstevel@tonic-gate mp2->b_wptr = mp2->b_rptr; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate lc = (log_ctl_t *)mp->b_rptr; 5207c478bd9Sstevel@tonic-gate lc->mid = mid; 5217c478bd9Sstevel@tonic-gate lc->sid = sid; 5227c478bd9Sstevel@tonic-gate lc->level = level; 5237c478bd9Sstevel@tonic-gate lc->flags = sl; 5247c478bd9Sstevel@tonic-gate lc->pri = pri; 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate bcopy(msg, mp2->b_wptr, size - 1); 5277c478bd9Sstevel@tonic-gate mp2->b_wptr[size - 1] = '\0'; 5287c478bd9Sstevel@tonic-gate mp2->b_wptr += strlen((char *)mp2->b_wptr) + 1; 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate return (mp); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate void 5347c478bd9Sstevel@tonic-gate log_freemsg(mblk_t *mp) 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate mblk_t *mp2 = mp->b_cont; 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate ASSERT(MBLKL(mp) == sizeof (log_ctl_t)); 5397c478bd9Sstevel@tonic-gate ASSERT(mp2->b_rptr == mp2->b_datap->db_base); 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if ((log_freeq->q_flag & QFULL) == 0 && 5427c478bd9Sstevel@tonic-gate MBLKL(mp2) <= LOG_MSGSIZE && MBLKSIZE(mp2) >= LOG_MSGSIZE) 5437c478bd9Sstevel@tonic-gate (void) putq(log_freeq, mp); 5447c478bd9Sstevel@tonic-gate else 5457c478bd9Sstevel@tonic-gate freemsg(mp); 5467c478bd9Sstevel@tonic-gate } 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate void 5497c478bd9Sstevel@tonic-gate log_sendmsg(mblk_t *mp, zoneid_t zoneid) 5507c478bd9Sstevel@tonic-gate { 5517c478bd9Sstevel@tonic-gate log_t *lp; 5527c478bd9Sstevel@tonic-gate char *src, *dst; 5537c478bd9Sstevel@tonic-gate mblk_t *mp2 = mp->b_cont; 5547c478bd9Sstevel@tonic-gate log_ctl_t *lc = (log_ctl_t *)mp->b_rptr; 5557c478bd9Sstevel@tonic-gate int flags, fac; 5567c478bd9Sstevel@tonic-gate off_t facility = 0; 5577c478bd9Sstevel@tonic-gate off_t body = 0; 5587c478bd9Sstevel@tonic-gate zone_t *zptr = NULL; 5597c478bd9Sstevel@tonic-gate log_zone_t *lzp; 5607c478bd9Sstevel@tonic-gate int i; 5617c478bd9Sstevel@tonic-gate int backlog; 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * Need to special case the global zone here since this may be 5657c478bd9Sstevel@tonic-gate * called before zone_init. 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate if (zoneid == GLOBAL_ZONEID) { 5687c478bd9Sstevel@tonic-gate lzp = &log_global; 5697c478bd9Sstevel@tonic-gate } else if ((zptr = zone_find_by_id(zoneid)) == NULL) { 5707c478bd9Sstevel@tonic-gate /* specified zone doesn't exist, free message and return */ 5717c478bd9Sstevel@tonic-gate log_freemsg(mp); 5727c478bd9Sstevel@tonic-gate return; 5737c478bd9Sstevel@tonic-gate } else { 5747c478bd9Sstevel@tonic-gate lzp = zone_getspecific(log_zone_key, zptr); 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate ASSERT(lzp != NULL); 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if ((lc->flags & lzp->lz_active) == 0) { 5797c478bd9Sstevel@tonic-gate if (zptr) 5807c478bd9Sstevel@tonic-gate zone_rele(zptr); 5817c478bd9Sstevel@tonic-gate log_freemsg(mp); 5827c478bd9Sstevel@tonic-gate return; 5837c478bd9Sstevel@tonic-gate } 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate if (panicstr) { 5867c478bd9Sstevel@tonic-gate /* 5877c478bd9Sstevel@tonic-gate * Raise the console queue's q_hiwat to ensure that we 5887c478bd9Sstevel@tonic-gate * capture all panic messages. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate log_consq->q_hiwat = 2 * LOG_HIWAT; 5917c478bd9Sstevel@tonic-gate log_consq->q_flag &= ~QFULL; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate /* Message was created while panicking. */ 5947c478bd9Sstevel@tonic-gate lc->flags |= SL_PANICMSG; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate src = (char *)mp2->b_rptr; 5987c478bd9Sstevel@tonic-gate dst = strstr(src, "FACILITY_AND_PRIORITY] "); 5997c478bd9Sstevel@tonic-gate if (dst != NULL) { 6007c478bd9Sstevel@tonic-gate facility = dst - src; 6017c478bd9Sstevel@tonic-gate body = facility + 23; /* strlen("FACILITY_AND_PRIORITY] ") */ 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate log_enter(); 6057c478bd9Sstevel@tonic-gate 6068cff005aSkk112340 /* 6073348528fSdm120769 * In the early boot phase hrestime is invalid, then timechanged is 0. 6083348528fSdm120769 * If hrestime is not valid, the ttime is set to 0 here and the correct 6093348528fSdm120769 * ttime is calculated in log_conswitch() later. The log_conswitch() 6103348528fSdm120769 * calculation to determine the correct ttime does not use ttime data 6113348528fSdm120769 * from these log_ctl_t structures; it only uses ttime from log_ctl_t's 6123348528fSdm120769 * that contain good data. 6133348528fSdm120769 * 6148cff005aSkk112340 */ 615d3d50737SRafael Vanoni lc->ltime = ddi_get_lbolt(); 6163348528fSdm120769 if (timechanged) { 6177c478bd9Sstevel@tonic-gate lc->ttime = gethrestime_sec(); 6188cff005aSkk112340 } else { 6198cff005aSkk112340 lc->ttime = 0; 6208cff005aSkk112340 } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate flags = lc->flags & lzp->lz_active; 6237c478bd9Sstevel@tonic-gate log_seq_no[flags & SL_ERROR]++; 6247c478bd9Sstevel@tonic-gate log_seq_no[flags & SL_TRACE]++; 6257c478bd9Sstevel@tonic-gate log_seq_no[flags & SL_CONSOLE]++; 6267c478bd9Sstevel@tonic-gate 6277c478bd9Sstevel@tonic-gate /* 6287c478bd9Sstevel@tonic-gate * If this is in the global zone, start with the backlog, then 6297c478bd9Sstevel@tonic-gate * walk through the clone logs. If not, just do the clone logs. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate backlog = (zoneid == GLOBAL_ZONEID); 6327c478bd9Sstevel@tonic-gate i = LOG_LOGMINIDX; 6337c478bd9Sstevel@tonic-gate while (i <= LOG_LOGMAXIDX) { 6347c478bd9Sstevel@tonic-gate if (backlog) { 6357c478bd9Sstevel@tonic-gate /* 6367c478bd9Sstevel@tonic-gate * Do the backlog this time, then start on the 6377c478bd9Sstevel@tonic-gate * others. 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate backlog = 0; 6407c478bd9Sstevel@tonic-gate lp = &log_backlog; 6417c478bd9Sstevel@tonic-gate } else { 6427c478bd9Sstevel@tonic-gate lp = &lzp->lz_clones[i++]; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate if ((lp->log_flags & flags) && lp->log_wanted(lp, lc)) { 6467c478bd9Sstevel@tonic-gate if (canput(lp->log_q)) { 6477c478bd9Sstevel@tonic-gate lp->log_overflow = 0; 6487c478bd9Sstevel@tonic-gate lc->seq_no = log_seq_no[lp->log_flags]; 6497c478bd9Sstevel@tonic-gate if ((mp2 = copymsg(mp)) == NULL) 6507c478bd9Sstevel@tonic-gate break; 6517c478bd9Sstevel@tonic-gate if (facility != 0) { 6527c478bd9Sstevel@tonic-gate src = (char *)mp2->b_cont->b_rptr; 6537c478bd9Sstevel@tonic-gate dst = src + facility; 6547c478bd9Sstevel@tonic-gate fac = (lc->pri & LOG_FACMASK) >> 3; 6557c478bd9Sstevel@tonic-gate dst += snprintf(dst, 6567c478bd9Sstevel@tonic-gate LOG_FACSIZE + LOG_PRISIZE, "%s.%s", 6577c478bd9Sstevel@tonic-gate log_fac[MIN(fac, LOG_NFACILITIES)], 6587c478bd9Sstevel@tonic-gate log_pri[lc->pri & LOG_PRIMASK]); 6597c478bd9Sstevel@tonic-gate src += body - 2; /* copy "] " too */ 6607c478bd9Sstevel@tonic-gate while (*src != '\0') 6617c478bd9Sstevel@tonic-gate *dst++ = *src++; 6627c478bd9Sstevel@tonic-gate *dst++ = '\0'; 6637c478bd9Sstevel@tonic-gate mp2->b_cont->b_wptr = (uchar_t *)dst; 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate (void) putq(lp->log_q, mp2); 6667c478bd9Sstevel@tonic-gate } else if (++lp->log_overflow == 1) { 6677c478bd9Sstevel@tonic-gate if (lp->log_q == log_consq) { 6687c478bd9Sstevel@tonic-gate console_printf(log_overflow_msg, 6697c478bd9Sstevel@tonic-gate lp->log_minor, 6707c478bd9Sstevel@tonic-gate " -- is syslogd(1M) running?"); 6717c478bd9Sstevel@tonic-gate } else { 6727c478bd9Sstevel@tonic-gate printf(log_overflow_msg, 6737c478bd9Sstevel@tonic-gate lp->log_minor, ""); 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate if (zptr) 6807c478bd9Sstevel@tonic-gate zone_rele(zptr); 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if ((flags & SL_CONSOLE) && (lc->pri & LOG_FACMASK) == LOG_KERN) { 6837c478bd9Sstevel@tonic-gate if ((mp2 == NULL || log_consq == log_backlogq || panicstr) && 6847c478bd9Sstevel@tonic-gate (lc->flags & SL_LOGONLY) == 0) 6857c478bd9Sstevel@tonic-gate console_printf("%s", (char *)mp->b_cont->b_rptr + body); 6867c478bd9Sstevel@tonic-gate if ((lc->flags & SL_CONSONLY) == 0 && 6877c478bd9Sstevel@tonic-gate (mp2 = copymsg(mp)) != NULL) { 6887c478bd9Sstevel@tonic-gate mp2->b_cont->b_rptr += body; 6897c478bd9Sstevel@tonic-gate if (log_recentq->q_flag & QFULL) 690301ce41fSja97890 freemsg(getq_noenab(log_recentq, 0)); 6917c478bd9Sstevel@tonic-gate (void) putq(log_recentq, mp2); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate log_freemsg(mp); 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate log_exit(); 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate /* 7017c478bd9Sstevel@tonic-gate * Print queued messages to console. 7027c478bd9Sstevel@tonic-gate */ 7037c478bd9Sstevel@tonic-gate void 7047c478bd9Sstevel@tonic-gate log_printq(queue_t *qfirst) 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate mblk_t *mp; 7077c478bd9Sstevel@tonic-gate queue_t *q, *qlast; 7087c478bd9Sstevel@tonic-gate char *cp, *msgp; 7097c478bd9Sstevel@tonic-gate log_ctl_t *lc; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate /* 7127c478bd9Sstevel@tonic-gate * Look ahead to first queued message in the stream. 7137c478bd9Sstevel@tonic-gate */ 7147c478bd9Sstevel@tonic-gate qlast = NULL; 7157c478bd9Sstevel@tonic-gate do { 7167c478bd9Sstevel@tonic-gate for (q = qfirst; q->q_next != qlast; q = q->q_next) 7177c478bd9Sstevel@tonic-gate continue; 7187c478bd9Sstevel@tonic-gate for (mp = q->q_first; mp != NULL; mp = mp->b_next) { 7197c478bd9Sstevel@tonic-gate lc = (log_ctl_t *)mp->b_rptr; 7207c478bd9Sstevel@tonic-gate /* 7217c478bd9Sstevel@tonic-gate * Check if message is already displayed at 7227c478bd9Sstevel@tonic-gate * /dev/console. 7237c478bd9Sstevel@tonic-gate */ 7247c478bd9Sstevel@tonic-gate if (lc->flags & SL_PANICMSG) 7257c478bd9Sstevel@tonic-gate continue; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate cp = (char *)mp->b_cont->b_rptr; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* Strip off the message ID. */ 7307c478bd9Sstevel@tonic-gate if ((msgp = strstr(cp, "[ID ")) != NULL && 7317c478bd9Sstevel@tonic-gate (msgp = strstr(msgp, "] ")) != NULL) { 7327c478bd9Sstevel@tonic-gate cp = msgp + 2; 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate 7357c478bd9Sstevel@tonic-gate /* 7367c478bd9Sstevel@tonic-gate * Using console_printf instead of printf to avoid 7377c478bd9Sstevel@tonic-gate * queueing messages to log_consq. 7387c478bd9Sstevel@tonic-gate */ 7397c478bd9Sstevel@tonic-gate console_printf("%s", cp); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate } while ((qlast = q) != qfirst); 7427c478bd9Sstevel@tonic-gate } 743068ccd7aSns92644 744068ccd7aSns92644 /* ARGSUSED */ 745068ccd7aSns92644 static int 746068ccd7aSns92644 log_cons_constructor(void *buf, void *cdrarg, int kmflags) 747068ccd7aSns92644 { 748068ccd7aSns92644 struct log *lp = buf; 749068ccd7aSns92644 750068ccd7aSns92644 lp->log_zoneid = GLOBAL_ZONEID; 751068ccd7aSns92644 lp->log_major = LOG_CONSMIN; /* Indicate which device type */ 752068ccd7aSns92644 lp->log_data = NULL; 753068ccd7aSns92644 return (0); 754068ccd7aSns92644 } 755068ccd7aSns92644 756068ccd7aSns92644 /* ARGSUSED */ 757068ccd7aSns92644 static void 758068ccd7aSns92644 log_cons_destructor(void *buf, void *cdrarg) 759068ccd7aSns92644 { 760068ccd7aSns92644 struct log *lp = buf; 761068ccd7aSns92644 762068ccd7aSns92644 ASSERT(lp->log_zoneid == GLOBAL_ZONEID); 763068ccd7aSns92644 ASSERT(lp->log_major == LOG_CONSMIN); 764068ccd7aSns92644 ASSERT(lp->log_data == NULL); 765068ccd7aSns92644 } 766