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