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