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