1 diff -Nur linux-2.6.8.1.org/include/linux/device.h linux-2.6.8.1/include/linux/device.h
2 --- linux-2.6.8.1.org/include/linux/device.h 2005-03-02 12:00:34.158312680 +0100
3 +++ linux-2.6.8.1/include/linux/device.h 2005-03-02 13:17:48.124842688 +0100
6 #include <asm/semaphore.h>
7 #include <asm/atomic.h>
8 +#include <linux/printkat.h>
10 #define DEVICE_NAME_SIZE 50
11 #define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */
14 /* debugging and troubleshooting/diagnostic helpers. */
15 #define dev_printk(level, dev, format, arg...) \
16 - printk(level "%s %s: " format , (dev)->driver ? (dev)->driver->name : "" , (dev)->bus_id , ## arg)
17 + printkat(level "{driver}%s {busid}%s: " format "{{line}%d}" , \
18 + (dev)->driver->name , (dev)->bus_id , ## arg , __LINE__)
21 #define dev_dbg(dev, format, arg...) \
22 diff -Nur linux-2.6.8.1.org/include/linux/evlog.h linux-2.6.8.1/include/linux/evlog.h
23 --- linux-2.6.8.1.org/include/linux/evlog.h 1970-01-01 01:00:00.000000000 +0100
24 +++ linux-2.6.8.1/include/linux/evlog.h 2005-03-02 13:11:31.855044392 +0100
27 + * Linux Event Logging
28 + * Copyright (C) International Business Machines Corp., 2001
30 + * This program is free software; you can redistribute it and/or modify
31 + * it under the terms of the GNU General Public License as published by
32 + * the Free Software Foundation; either version 2 of the License, or
33 + * (at your option) any later version.
35 + * This program is distributed in the hope that it will be useful,
36 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 + * GNU General Public License for more details.
40 + * You should have received a copy of the GNU General Public License
41 + * along with this program; if not, write to the Free Software
42 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 + * Please send e-mail to kenistoj@users.sourceforge.net if you have
45 + * questions or comments.
47 + * Project Website: http://evlog.sourceforge.net/
50 +#ifndef _LINUX_EVLOG_H
51 +#define _LINUX_EVLOG_H
54 +#include <linux/types.h>
55 +#include <asm/types.h>
57 +/* Values for log_flags member */
58 +#define EVL_TRUNCATE 0x1
59 +#define EVL_KERNEL_EVENT 0x2
60 +#define EVL_INITIAL_BOOT_EVENT 0x4
61 +#define EVL_KERNTIME_LOCAL 0x8
62 +#define EVL_INTERRUPT 0x10 /* Logged from interrupt context */
63 +#define EVL_PRINTK 0x20 /* Strip leading <n> when formatting */
64 +#define EVL_EVTYCRC 0x40 /* Daemon will set event type = CRC */
65 + /* of format string. */
67 +/* Formats for optional portion of record. */
73 +/* Maximum length of variable portion of record */
74 +#define EVL_ENTRY_MAXLEN (8 * 1024)
76 +/* Facility (e.g., driver) names are truncated to 15+null. */
77 +#define FACILITY_MAXLEN 16
79 +/* struct kern_log_entry - kernel record header */
80 +struct kern_log_entry {
81 + __u16 log_kmagic; /* always LOGREC_KMAGIC */
82 + __u16 log_kversion; /* which version of this struct? */
83 + __u16 log_size; /* # bytes in variable part of record */
84 + __s8 log_format; /* BINARY, STRING, PRINTF, NODATA */
85 + __s8 log_severity; /* DEBUG, INFO, NOTICE, WARN, etc. */
86 + __s32 log_event_type; /* facility-specific event ID */
87 + __u32 log_flags; /* EVL_TRUNCATE, etc. */
88 + __s32 log_processor; /* CPU ID */
89 + time_t log_time_sec;
90 + __s32 log_time_nsec;
91 + uid_t log_uid; /* event context... */
95 + char log_facility[FACILITY_MAXLEN]; /* e.g., driver name */
98 +#define LOGREC_KMAGIC 0x7af8
99 +#define LOGREC_KVERSION 3
101 +/* Reserved Event Types */
102 +#define EVL_BUFFER_OVERRUN 0x6
106 + * severities, AKA priorities
108 +#define LOG_EMERG 0 /* system is unusable */
109 +#define LOG_ALERT 1 /* action must be taken immediately */
110 +#define LOG_CRIT 2 /* critical conditions */
111 +#define LOG_ERR 3 /* error conditions */
112 +#define LOG_WARNING 4 /* warning conditions */
113 +#define LOG_NOTICE 5 /* normal but significant condition */
114 +#define LOG_INFO 6 /* informational */
115 +#define LOG_DEBUG 7 /* debug-level messages */
118 + * A buffer to pack with data, one value at a time. By convention, b_tail
119 + * reflects the total amount you've attempted to add, and so may be past b_end.
122 + char *b_buf; /* start of buffer */
123 + char *b_tail; /* add next data here */
124 + char *b_end; /* b_buf + buffer size */
125 + char *b_argsz; /* points to argsz word in EVL_PRINTF-format record */
126 + char *b_zapped_nl; /* where terminating newline was */
130 +extern int evl_write(const char *facility, int event_type,
131 + int severity, const void *buf, size_t len, uint flags, int format);
132 +extern int evl_printk(const char *facility, int event_type, int sev,
133 + const char *fmt, ...);
134 +extern int evl_vprintk(const char *facility, int event_type, int sev,
135 + const char *fmt, va_list args);
137 +/* Functions for hand-constructing event records */
138 +extern void evl_init_recbuf(struct evl_recbuf *b, char *buf, size_t size);
139 +extern void evl_put(struct evl_recbuf *b, const void *data, size_t datasz);
140 +extern void evl_puts(struct evl_recbuf *b, const char *s, int null);
141 +extern void evl_zap_newline(struct evl_recbuf *b);
142 +extern void evl_end_fmt(struct evl_recbuf *b);
143 +extern void evl_pack_args(struct evl_recbuf *b, const char *fmt, va_list args);
144 +extern void evl_end_args(struct evl_recbuf *b);
145 +#else /* ! CONFIG_EVLOG */
146 +static inline int evl_write(const char *facility, int event_type,
147 + int severity, const void *buf, size_t len, uint flags, int format)
148 + { return -ENOSYS; }
149 +static inline int evl_printk(const char *facility, int event_type, int sev,
150 + const char *fmt, ...);
151 + { return -ENOSYS; }
152 +static inline int evl_vprintk(const char *facility, int event_type, int sev,
153 + const char *fmt, va_list args)
154 + { return -ENOSYS; }
155 +#endif /* CONFIG_EVLOG */
157 +#endif /* __KERNEL__ */
159 +#endif /* _LINUX_EVLOG_H */
160 diff -Nur linux-2.6.8.1.org/include/linux/netdevice.h linux-2.6.8.1/include/linux/netdevice.h
161 --- linux-2.6.8.1.org/include/linux/netdevice.h 2004-08-14 12:56:22.000000000 +0200
162 +++ linux-2.6.8.1/include/linux/netdevice.h 2005-03-02 13:18:28.970633184 +0100
164 #include <linux/config.h>
165 #include <linux/device.h>
166 #include <linux/percpu.h>
167 +#include <linux/printkat.h>
172 struct divert_blk *divert;
173 #endif /* CONFIG_NET_DIVERT */
175 + /* NETIF_MSG_* flags to control the types of events we log */
178 /* class/net/name entry */
179 struct class_device class_dev;
180 struct net_device_stats* (*last_stats)(struct net_device *);
182 NETIF_MSG_PKTDATA = 0x1000,
183 NETIF_MSG_HW = 0x2000,
184 NETIF_MSG_WOL = 0x4000,
185 + NETIF_MSG_ALL = -1, /* always log message */
188 #define netif_msg_drv(p) ((p)->msg_enable & NETIF_MSG_DRV)
190 extern char *net_sysctl_strdup(const char *s);
193 +/* debugging and troubleshooting/diagnostic helpers. */
195 + * netdev_printk() - Log message with interface name, gated by message level
196 + * @sevlevel: severity level -- e.g., KERN_INFO
197 + * @netdev: net_device pointer
198 + * @msglevel: a standard message-level flag with the NETIF_MSG_ prefix removed.
199 + * Unless msglevel is ALL, log the message only if that flag is set in
200 + * netdev->msg_enable.
201 + * @format: as with printk
202 + * @args: as with printk
204 +extern int __netdev_printk(const char *sevlevel,
205 + const struct net_device *netdev, int msglevel, const char *format, ...);
206 +#define netdev_printk(sevlevel, netdev, msglevel, format, arg...) \
208 + if (__netdev_printk(sevlevel , netdev , NETIF_MSG_##msglevel , \
209 + format , ## arg) == 0) { \
210 + printkat_noprintk(sevlevel \
211 + "{netdev}%s ({driver}%s {busid}%s) {msglvl}%s: "\
212 + format "{{line}%d}" , netdev->name , \
213 + netdev->class_dev.dev->driver->name , \
214 + netdev->class_dev.dev->bus_id , #msglevel , \
215 + ## arg , __LINE__); \
219 +#define netdev_dbg(netdev, msglevel, format, arg...) \
220 + netdev_printk(KERN_DEBUG , netdev , msglevel , format , ## arg)
222 +#define netdev_dbg(netdev, msglevel, format, arg...) do {} while (0)
225 +#define netdev_err(netdev, msglevel, format, arg...) \
226 + netdev_printk(KERN_ERR , netdev , msglevel , format , ## arg)
227 +#define netdev_info(netdev, msglevel, format, arg...) \
228 + netdev_printk(KERN_INFO , netdev , msglevel , format , ## arg)
229 +#define netdev_warn(netdev, msglevel, format, arg...) \
230 + netdev_printk(KERN_WARNING , netdev , msglevel , format , ## arg)
232 +/* report fatal error unconditionally; msglevel ignored for now */
233 +#define netdev_fatal(netdev, msglevel, format, arg...) \
234 + netdev_printk(KERN_ERR , netdev , ALL , format , ## arg)
236 #endif /* __KERNEL__ */
238 #endif /* _LINUX_DEV_H */
239 diff -Nur linux-2.6.8.1.org/include/linux/printkat.h linux-2.6.8.1/include/linux/printkat.h
240 --- linux-2.6.8.1.org/include/linux/printkat.h 1970-01-01 01:00:00.000000000 +0100
241 +++ linux-2.6.8.1/include/linux/printkat.h 2005-03-02 13:18:40.092942336 +0100
244 + * Linux Event Logging for the Enterprise
245 + * Copyright (C) International Business Machines Corp., 2002
247 + * This program is free software; you can redistribute it and/or modify
248 + * it under the terms of the GNU General Public License as published by
249 + * the Free Software Foundation; either version 2 of the License, or
250 + * (at your option) any later version.
252 + * This program is distributed in the hope that it will be useful,
253 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
254 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
255 + * GNU General Public License for more details.
257 + * You should have received a copy of the GNU General Public License
258 + * along with this program; if not, write to the Free Software
259 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
261 + * Please send e-mail to kenistoj@users.sourceforge.net if you have
262 + * questions or comments.
264 + * Project Website: http://evlog.sourceforge.net/
267 +#ifndef _LINUX_PRINTKAT_H
268 +#define _LINUX_PRINTKAT_H
270 +extern int __printkat(const char *facname, int call_printk,
271 + const char *fmt, ...);
273 +#ifndef CONFIG_EVLOG
275 +/* Just strip {id} constructs and call printk. */
276 +#define printkat(fmt, arg...) __printkat((const char*)0, 1, fmt, ## arg)
277 +#define printkat_noprintk(fmt, arg...) do {} while(0)
279 +#else /* CONFIG_EVLOG */
281 +#include <linux/stringify.h>
282 +#include <linux/kernel.h>
283 +#include <linux/evlog.h>
286 + * Facility name defaults to the name of the module, as set in the kernel
287 + * build, or to kern (the kernel default) if the module name is not set.
288 + * Define EVL_FACILITY_NAME before including this file (or redefine it
289 + * before calling printkat) if that's unsatisfactory.
291 + * In a device driver, EVL_FACILITY_NAME should be the driver name (without
294 +#ifndef EVL_FACILITY_NAME
295 +#ifdef KBUILD_MODNAME
296 +#define EVL_FACILITY_NAME KBUILD_MODNAME
298 +#define EVL_FACILITY_NAME kern
302 +/* Bloat doesn't matter: this doesn't end up in vmlinux. */
303 +struct log_position {
305 + char function[64 - sizeof(int)];
309 +#define _LOG_POS { __LINE__, __FUNCTION__, __FILE__ }
312 + * Information about a printkat() message.
313 + * Again, bloat doesn't matter: this doesn't end up in vmlinux.
314 + * Note that, because of default alignment in the .log section,
315 + * sizeof(struct log_info) should be a multiple of 32.
318 + char format[128+64];
320 + struct log_position pos;
323 +#define printkat(fmt, arg...) \
325 + static struct log_info __attribute__((section(".log"),unused)) ___ \
326 + = { fmt, __stringify(EVL_FACILITY_NAME), _LOG_POS }; \
327 + __printkat(__stringify(EVL_FACILITY_NAME) , 1, fmt , ## arg); \
330 +/* Same as printkat, but don't call printk. */
331 +#define printkat_noprintk(fmt, arg...) \
333 + static struct log_info __attribute__((section(".log"),unused)) ___ \
334 + = { fmt, __stringify(EVL_FACILITY_NAME), _LOG_POS }; \
335 + __printkat(__stringify(EVL_FACILITY_NAME) , 0, fmt , ## arg); \
338 +#endif /* CONFIG_EVLOG */
340 +#endif /*_LINUX_PRINTKAT_H*/
341 diff -Nur linux-2.6.8.1.org/init/Kconfig linux-2.6.8.1/init/Kconfig
342 --- linux-2.6.8.1.org/init/Kconfig 2005-03-02 12:00:38.994577456 +0100
343 +++ linux-2.6.8.1/init/Kconfig 2005-03-02 13:11:31.857044088 +0100
345 agent" (/sbin/hotplug) to load modules and set up software needed
346 to use devices as you hotplug them.
349 + bool "Event logging support"
351 + This enables support for event logging based upon the draft
352 + POSIX 1003.25 standard. Enabling this feature does not
353 + affect the operation of the klog/syslog package in any way.
354 + In order to fully utilize this feature, user must also install
355 + the companion evlog package in user-space.
357 + For more information see http://evlog.sourceforge.net
359 + If you don't know what to do here, say N.
362 bool "Kernel .config support"
364 diff -Nur linux-2.6.8.1.org/kernel/Makefile linux-2.6.8.1/kernel/Makefile
365 --- linux-2.6.8.1.org/kernel/Makefile 2005-03-02 12:00:29.913957920 +0100
366 +++ linux-2.6.8.1/kernel/Makefile 2005-03-02 13:13:03.103172568 +0100
368 obj-$(CONFIG_COMPAT) += compat.o
369 obj-$(CONFIG_IKCONFIG) += configs.o
370 obj-$(CONFIG_IKCONFIG_PROC) += configs.o
371 +obj-$(CONFIG_EVLOG) += evlbuf.o evlapi.o
372 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
373 obj-$(CONFIG_AUDIT) += audit.o
374 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
375 diff -Nur linux-2.6.8.1.org/kernel/evlapi.c linux-2.6.8.1/kernel/evlapi.c
376 --- linux-2.6.8.1.org/kernel/evlapi.c 1970-01-01 01:00:00.000000000 +0100
377 +++ linux-2.6.8.1/kernel/evlapi.c 2005-03-02 13:18:40.093942184 +0100
380 + * Linux Event Logging
381 + * Copyright (C) International Business Machines Corp., 2003
383 + * This program is free software; you can redistribute it and/or modify
384 + * it under the terms of the GNU General Public License as published by
385 + * the Free Software Foundation; either version 2 of the License, or
386 + * (at your option) any later version.
388 + * This program is distributed in the hope that it will be useful,
389 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
390 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
391 + * GNU General Public License for more details.
393 + * You should have received a copy of the GNU General Public License
394 + * along with this program; if not, write to the Free Software
395 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
397 + * Please send e-mail to kenistoj@users.sourceforge.net if you have
398 + * questions or comments.
400 + * Project Website: http://evlog.sourceforge.net/
403 +#include <linux/config.h>
404 +#include <linux/kernel.h>
405 +#include <linux/module.h>
406 +#include <linux/stddef.h>
407 +#include <linux/spinlock.h>
408 +#include <linux/string.h>
409 +#include <linux/ctype.h>
410 +#include <linux/evlog.h>
412 +extern void evl_mk_rechdr(struct kern_log_entry *hdr,
413 + const char *facility, int event_type, int severity, size_t size,
414 + uint flags, int format);
415 +extern int evl_writeh(struct kern_log_entry *hdr, const char *vardata);
416 +extern void evl_unbrace(char *dest, const char *src, int bufsz);
419 + * evl_write() - write header + optional buffer to event handler
421 + * @buf: optional variable-length data
422 + * other args as per evl_mk_rechdr()
425 +evl_write(const char *facility, int event_type, int severity, const void *buf,
426 + size_t size, uint flags, int format)
428 + struct kern_log_entry hdr;
430 + evl_mk_rechdr(&hdr, facility, event_type, severity, size, flags,
432 + return evl_writeh(&hdr, buf);
436 +evl_init_recbuf(struct evl_recbuf *b, char *buf, size_t size)
440 + b->b_end = buf + size;
441 + b->b_zapped_nl = NULL;
446 + * evl_put() - Append data to buffer; handle overflow.
447 + * @b - describes buffer; updated to reflect data appended
448 + * @data - data to append
449 + * @datasz - data length in bytes
452 +evl_put(struct evl_recbuf *b, const void *data, size_t datasz)
454 + ptrdiff_t room = b->b_end - b->b_tail;
456 + (void) memcpy(b->b_tail, data, min(datasz, (size_t)room));
458 + b->b_tail += datasz;
462 + * evl_puts() - Append string to buffer; handle overflow.
463 + * Append a string to the buffer. If null == 1, we include the terminating
464 + * null. If the string extends over the end of the buffer, terminate the
465 + * buffer with a null.
467 + * @b - describes buffer; updated to reflect data appended
468 + * @s - null-terminated string
469 + * @null - 1 if we append the terminating null, 0 otherwise
472 +evl_puts(struct evl_recbuf *b, const char *s, int null)
474 + char *old_tail = b->b_tail;
475 + evl_put(b, s, strlen(s) + null);
476 + if (b->b_tail > b->b_end && old_tail < b->b_end) {
477 + *(b->b_end - 1) = '\0';
482 + * evl_zap_newline() - Delete newline at end of format string.
483 + * Called after the format string has been copied into b.
484 + * If the format ends in a newline, remove it. We remove the
485 + * terminating newline to increase flexibility when formatting
486 + * the record for viewing.
489 +evl_zap_newline(struct evl_recbuf *b)
491 + char *nl = b->b_tail - 2;
492 + if (b->b_buf <= nl && nl < b->b_end && *nl == '\n') {
495 + b->b_zapped_nl = nl;
500 + * evl_unzap_newline() - Replace previously zapped newline.
501 + * NOTE: Replacing the newline (and advancing the terminating null)
502 + * renders useless the contents of the record beyond the format string.
505 +evl_unzap_newline(struct evl_recbuf *b)
507 + if (b->b_zapped_nl) {
508 + b->b_zapped_nl[0] = '\n';
509 + b->b_zapped_nl[1] = '\0';
514 + * evl_end_fmt() - Make and remember room for argsz word in EVL_PRINTF rec.
515 + * Called after the format string has been copied in, but before the args.
516 + * Store zero for now; evl_end_args() will store the actual size later.
519 +evl_end_fmt(struct evl_recbuf *b)
522 + b->b_argsz = b->b_tail;
523 + evl_put(b, &argsz, sizeof(int));
527 + * evl_end_args() - For EVL_PRINTF record, store the argsz.
528 + * Called after the args have been copied in.
531 +evl_end_args(struct evl_recbuf *b)
536 + if (! b->b_argsz) {
537 + /* Nobody called evl_end_fmt(). */
540 + args = b->b_argsz + sizeof(int);
541 + if (args > b->b_end) {
542 + /* VERY long format string: even argsz is off end of record. */
545 + argsz = b->b_tail - args;
546 + memcpy(b->b_argsz, &argsz, sizeof(int));
550 +skip_atoi(const char **s)
552 + while (isdigit(**s)) {
558 + * parse_printf_fmt() - Parse printf/printk conversion spec.
559 + * fmt points to the '%' in a printk conversion specification. Advance
560 + * fmt past any flags, width and/or precision specifiers, and qualifiers
561 + * such as 'l' and 'L'. Return a pointer to the conversion character.
562 + * Stores the qualifier character (or -1, if there is none) at *pqualifier.
563 + * *wp is set to flags indicating whether the width and/or precision are '*'.
564 + * For example, given
566 + * *pqualifier is set to 'l', *wp is set to 0x1, and a pointer to the 'x'
569 + * Note: This function is derived from vsnprintf() (see lib/vsprintf.c),
570 + * and should be kept in sync with that function.
572 + * @fmt - points to '%' in conversion spec
573 + * @pqualifier - *pqualifier is set to conversion spec's qualifier, or -1.
574 + * @wp - Bits in *wp are set if the width or/and precision are '*'.
577 +parse_printf_fmt(const char *fmt, int *pqualifier, int *wp)
579 + int qualifier = -1;
582 + /* process flags */
584 + ++fmt; /* this also skips first '%' */
594 + /* get field width */
597 + else if (*fmt == '*') {
599 + /* it's the next argument */
603 + /* get the precision */
608 + else if (*fmt == '*') {
610 + /* it's the next argument */
615 + /* get the conversion qualifier */
616 + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
617 + *fmt == 'Z' || *fmt == 'z') {
620 + if (qualifier == 'l' && *fmt == 'l') {
626 + *pqualifier = qualifier;
631 + * evl_pack_args() - Pack args into buffer, guided by format string.
632 + * b describes a buffer. fmt and args are as passed to vsnprintf(). Using
633 + * fmt as a guide, copy the args into b's buffer.
635 + * @b - describes buffer; updated to reflect data added
636 + * @fmt - printf/printk-style format string
637 + * @args - values to be packed into buffer
640 +evl_pack_args(struct evl_recbuf *b, const char *fmt, va_list args)
642 +#define COPYARG(type) \
643 + do { type v=va_arg(args,type); evl_put(b,&v,sizeof(v)); } while(0)
648 + for (; *fmt ; ++fmt) {
654 + fmt = parse_printf_fmt(fmt, &qualifier, &wp);
656 + /* width is '*' (next arg) */
660 + /* ditto precision */
670 + s = va_arg(args, char *);
679 + /* Skip over the %n arg. */
680 + if (qualifier == 'l') {
681 + (void) va_arg(args, long *);
682 + } else if (qualifier == 'Z' || qualifier == 'z') {
683 + (void) va_arg(args, size_t *);
685 + (void) va_arg(args, int *);
692 + /* integer number formats - handle outside switch */
702 + /* Bogus conversion. Pass thru unchanged. */
707 + if (qualifier == 'L') {
708 + COPYARG(long long);
709 + } else if (qualifier == 'l') {
711 + } else if (qualifier == 'Z' || qualifier == 'z') {
713 + } else if (qualifier == 'h') {
722 + * Scratch buffer for constructing event records. This is static because
723 + * (1) we want events to be logged even in low-memory situations; and
724 + * (2) the buffer is too big to be an auto variable.
726 +static spinlock_t msgbuf_lock = SPIN_LOCK_UNLOCKED;
727 +static char msgbuf[EVL_ENTRY_MAXLEN];
730 + * evl_send_printf() - Format and log a PRINTF-format message.
731 + * Create and log a PRINTF-format event record whose contents are:
733 + * int containing args size
735 + * @hdr - pre-constructed record header, which we adjust as needed
736 + * @fmt - format string
740 +evl_send_printf(struct kern_log_entry *hdr, const char *fmt, va_list args)
743 + struct evl_recbuf b;
744 + unsigned long iflags;
746 + spin_lock_irqsave(&msgbuf_lock, iflags);
747 + evl_init_recbuf(&b, msgbuf, EVL_ENTRY_MAXLEN);
748 + evl_puts(&b, fmt, 1);
749 + evl_zap_newline(&b);
751 + evl_pack_args(&b, fmt, args);
754 + hdr->log_size = b.b_tail - b.b_buf;
755 + /* Note: If size > EVL_ENTRY_MAXLEN, evl_writeh() will handle it. */
757 + ret = evl_writeh(hdr, b.b_buf);
758 + spin_unlock_irqrestore(&msgbuf_lock, iflags);
763 + * evl_vprintk() - Format and log a PRINTF-format record.
764 + * @fmt - format string
766 + * other args as per evl_mk_rechdr(). If event_type == 0, set flag to
767 + * request that recipient set event type.
770 +evl_vprintk(const char *facility, int event_type, int severity,
771 + const char *fmt, va_list args)
773 + struct kern_log_entry hdr;
774 + unsigned int flags = 0;
775 + if (event_type == 0) {
776 + flags |= EVL_EVTYCRC;
778 + evl_mk_rechdr(&hdr, facility, event_type, severity, 1 /*size TBD*/,
779 + flags, EVL_PRINTF);
781 + return evl_send_printf(&hdr, fmt, args);
785 + * evl_printk() - Format and log a PRINTF-format record.
786 + * @fmt - format string
787 + * other args as per evl_mk_rechdr()
790 +evl_printk(const char *facility, int event_type, int severity,
791 + const char *fmt, ...)
795 + va_start(args, fmt);
796 + ret = evl_vprintk(facility, event_type, severity, fmt, args);
801 +/*** printkat support ***/
804 +try_extract_severity(const char *msg)
807 + && msg[1] >= '0' && msg[1] <= '7'
808 + && msg[2] == '>') {
809 + return msg[1] - '0';
815 +extract_severity(const char *fmt, va_list args)
817 + int sev = try_extract_severity(fmt);
818 + if (sev == -1 && (fmt[0] == '<' || fmt[0] == '%')) {
819 + /* Handle stuff like "<%d>..." and "%s..." */
821 + (void) vsnprintf(prefix, 4, fmt, args);
822 + sev = try_extract_severity(prefix);
828 + * evl_printkat() - Log a PRINTF-format record, stripping attribute names.
829 + * @facility: facility name (e.g., "kern", driver name)
830 + * @buf, @buflen: a scratch buffer in which we construct the record
831 + * @fmt: format string, possibly including severity-level prefix.
832 + * Any attribute names in curly braces will be stripped out by
834 + * other args as per printk()
836 + * On return, buf contains the format string, purged of {id} constructs
837 + * and the "{{" trailer, if any.
840 +evl_printkat(const char *facility, char *buf, size_t buflen, const char *fmt,
845 + struct evl_recbuf b;
846 + struct kern_log_entry hdr;
848 + evl_init_recbuf(&b, buf, buflen);
849 + evl_unbrace(b.b_buf, fmt, (int) buflen);
850 + b.b_tail = b.b_buf + strlen(b.b_buf) + 1;
851 + evl_zap_newline(&b);
854 + evl_pack_args(&b, fmt, args);
857 + severity = extract_severity(b.b_buf, args);
858 + if (severity < 0) {
859 + /* See kernel.h and printk.c */
860 + severity = default_message_loglevel;
863 + evl_mk_rechdr(&hdr, facility, 0, severity, b.b_tail - b.b_buf,
864 + EVL_EVTYCRC, EVL_PRINTF);
865 + /* Note: If size > EVL_ENTRY_MAXLEN, evl_writeh() will handle it. */
867 + ret = evl_writeh(&hdr, b.b_buf);
869 + /* Put the newline back in case caller calls printk(). */
870 + evl_unzap_newline(&b);
874 +EXPORT_SYMBOL(evl_write);
875 +EXPORT_SYMBOL(evl_printk);
876 +EXPORT_SYMBOL(evl_vprintk);
877 +EXPORT_SYMBOL(evl_printkat);
878 diff -Nur linux-2.6.8.1.org/kernel/evlbuf.c linux-2.6.8.1/kernel/evlbuf.c
879 --- linux-2.6.8.1.org/kernel/evlbuf.c 1970-01-01 01:00:00.000000000 +0100
880 +++ linux-2.6.8.1/kernel/evlbuf.c 2005-03-02 13:11:31.861043480 +0100
883 + * Linux Event Logging
884 + * Copyright (C) International Business Machines Corp., 2003
886 + * This program is free software; you can redistribute it and/or modify
887 + * it under the terms of the GNU General Public License as published by
888 + * the Free Software Foundation; either version 2 of the License, or
889 + * (at your option) any later version.
891 + * This program is distributed in the hope that it will be useful,
892 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
893 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
894 + * GNU General Public License for more details.
896 + * You should have received a copy of the GNU General Public License
897 + * along with this program; if not, write to the Free Software
898 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
900 + * Please send e-mail to kenistoj@users.sourceforge.net if you have
901 + * questions or comments.
903 + * Project Website: http://evlog.sourceforge.net/
906 +#include <linux/config.h>
907 +#include <linux/kernel.h>
908 +#include <linux/stddef.h>
909 +#include <linux/spinlock.h>
910 +#include <linux/time.h>
911 +#include <linux/smp.h>
912 +#include <linux/string.h>
913 +#include <linux/interrupt.h>
914 +#include <asm/uaccess.h>
915 +#include <asm/semaphore.h>
916 +#include <linux/module.h>
917 +#include <linux/ctype.h>
918 +#include <linux/evlog.h>
920 +#define REC_HDR_SIZE sizeof(struct kern_log_entry)
922 +extern struct timezone sys_tz;
924 +/* Use same buffer size as printk's, but at least 2x the max rec length. */
925 +#define EVL_BUF_SIZE (1 << CONFIG_LOG_BUF_SHIFT)
926 +#if (EVL_BUF_SIZE < 2*EVL_ENTRY_MAXLEN)
928 +#define EVL_BUF_SIZE (2*EVL_ENTRY_MAXLEN)
932 + * After buffer overflows, require at most this much free space before
933 + * logging events again.
935 +#define EVL_BUF_DRAINAGE (16*1024U)
938 + * This data structure describes the circular buffer that is written into
939 + * by evl_writeh() and drained by evl_kbufread().
941 + * bf_buf, bf_len, and bf_end are the start, length, and end of the buffer,
942 + * and in the current implementation these remain constant.
944 + * bf_tail advances as event records are logged to the buffer, and bf_head
945 + * advances as records are drained from the buffer. bf_dropped maintains
946 + * a count of records that have been dropped due to buffer overrun.
948 + * - (bf_head == bf_tail) indicates an empty buffer.
949 + * - bf_head can take any value from bf_buf through bf_end.
950 + * - bf_tail starts out equal to bf_buf, but once the first record is written
951 + * to the buffer, bf_tail never equals bf_buf. It can equal bf_end.
953 + * It is possible for one task to be draining the buffer while another
954 + * is writing to it. Only evl_kbufread() advances bf_head, and only
955 + * copy_rec_to_cbuf() advances bf_tail. Each advances its respective
956 + * pointer only after completing its operation.
959 + char *bf_buf; /* base buffer address */
960 + unsigned int bf_len; /* buffer length */
961 + unsigned int bf_dropped; /* (internal) dropped count */
962 + char *bf_head; /* head-pointer for circ. buf */
963 + char *bf_tail; /* tail-pointer for circ. buf */
964 + char *bf_end; /* end buffer address */
967 +static char evl_buffer[EVL_BUF_SIZE + sizeof(long)];
969 +static struct cbuf ebuf = {
975 + evl_buffer + EVL_BUF_SIZE
979 + * evl_read_sem serializes reads of the evlog buffer into user space (although
980 + * only the logging daemon should be running evl_kbufread()).
982 + * readq allows the reader to sleep until there's at least one record in
983 + * the buffer to read.
985 + * ebuf_lock serializes writes to the evlog buffer.
987 +static DECLARE_MUTEX(evl_read_sem);
988 +static DECLARE_WAIT_QUEUE_HEAD(readq);
989 +static spinlock_t ebuf_lock = SPIN_LOCK_UNLOCKED;
992 + * A region of the evlog circular buffer, possibly split into 2 chunks
993 + * due to wraparound.
1003 + * set_region() - Establish region to be written to or read from.
1004 + * Caller wants to write to or read from an nbytes-byte region (of the
1005 + * evlog circular buffer) starting at head. Figure out whether the
1006 + * region needs to be 1 chunk (typical) or 2 (due to wraparound),
1007 + * and populate the region struct accordingly.
1009 + * @rg: region struct to be populated
1010 + * @head: beginning of region to be read/written. If this is beyond the
1011 + * end of the buffer, wrap it around to the beginning.
1012 + * @nbytes: size of region
1015 +set_region(struct cbregion *rg, char *head, size_t nbytes)
1017 + if (head >= ebuf.bf_end) {
1018 + head -= ebuf.bf_len;
1020 + rg->rg_head = head;
1021 + rg->rg_tail = head + nbytes;
1022 + if (rg->rg_tail > ebuf.bf_end) {
1023 + rg->rg_chunk1 = ebuf.bf_end - head;
1024 + rg->rg_chunk2 = nbytes - rg->rg_chunk1;
1025 + rg->rg_tail = ebuf.bf_buf + rg->rg_chunk2;
1027 + rg->rg_chunk1 = nbytes;
1028 + rg->rg_chunk2 = 0;
1033 +copy_from_cbuf(const struct cbregion *rg, char *dest)
1035 + memcpy(dest, rg->rg_head, rg->rg_chunk1);
1036 + if (rg->rg_chunk2 != 0) {
1037 + memcpy(dest + rg->rg_chunk1, ebuf.bf_buf, rg->rg_chunk2);
1042 +copy_cbuf_to_user(const struct cbregion *rg, char *ubuf)
1045 + status = copy_to_user(ubuf, rg->rg_head, rg->rg_chunk1);
1046 + if (rg->rg_chunk2 != 0 && status == 0) {
1047 + status = copy_to_user(ubuf + rg->rg_chunk1, ebuf.bf_buf,
1054 +copy_to_cbuf(const struct cbregion *rg, const char *src)
1056 + memcpy(rg->rg_head, src, rg->rg_chunk1);
1057 + if (rg->rg_chunk2 != 0) {
1058 + memcpy(ebuf.bf_buf, src + rg->rg_chunk1, rg->rg_chunk2);
1063 + * copy_rec_to_cbuf() - Log event (hdr + vardata) to buffer.
1064 + * Caller has verified that there's enough room.
1067 +copy_rec_to_cbuf(const struct kern_log_entry *hdr, const char *vardata)
1069 + struct cbregion rg;
1070 + char *tail = ebuf.bf_tail;
1072 + set_region(&rg, tail, REC_HDR_SIZE);
1073 + copy_to_cbuf(&rg, (const char*) hdr);
1075 + if (hdr->log_size != 0) {
1076 + set_region(&rg, tail + REC_HDR_SIZE, hdr->log_size);
1077 + copy_to_cbuf(&rg, vardata);
1080 + ebuf.bf_tail = rg.rg_tail;
1084 + * evl_mk_rechdr() - Populate evlog record header.
1085 + * @facility: facility name (e.g., "kern", driver name)
1086 + * @event_type: event type (event ID assigned by programmer; may also be
1087 + * computed by recipient -- e.g., CRC of format string)
1088 + * @severity: severity level (e.g., LOG_INFO)
1089 + * @size: length, in bytes, of variable data
1090 + * @flags: event flags (e.g., EVL_TRUNCATE, EVL_EVTYCRC)
1091 + * @format: format of variable data (e.g., EVL_STRING)
1094 +evl_mk_rechdr(struct kern_log_entry *rec_hdr,
1095 + const char *facility,
1102 + struct timespec ts;
1104 + flags |= EVL_KERNEL_EVENT;
1105 + if (in_interrupt()) {
1106 + flags |= EVL_INTERRUPT;
1109 + rec_hdr->log_kmagic = LOGREC_KMAGIC;
1110 + rec_hdr->log_kversion = LOGREC_KVERSION;
1111 + rec_hdr->log_size = (__u16) size;
1112 + rec_hdr->log_format = (__s8) format;
1113 + rec_hdr->log_event_type = (__s32) event_type;
1114 + rec_hdr->log_severity = (__s8) severity;
1115 + rec_hdr->log_uid = current->uid;
1116 + rec_hdr->log_gid = current->gid;
1117 + rec_hdr->log_pid = current->pid;
1118 + rec_hdr->log_pgrp = process_group(current);
1119 + rec_hdr->log_flags = (__u32) flags;
1120 + rec_hdr->log_processor = (__s32) smp_processor_id();
1122 + strlcpy(rec_hdr->log_facility, facility, FACILITY_MAXLEN);
1124 + if (get_seconds() == 0) {
1125 + rec_hdr->log_flags |= EVL_INITIAL_BOOT_EVENT;
1127 +#if defined(__i386__)
1128 + if (sys_tz.tz_minuteswest == 0) {
1130 + rec_hdr->log_flags |= EVL_KERNTIME_LOCAL;
1134 + ts = CURRENT_TIME;
1135 + rec_hdr->log_time_sec = (time_t) ts.tv_sec;
1136 + rec_hdr->log_time_nsec = (__s32) ts.tv_nsec;
1140 + * normalize_header() - Fix up rec header, handling overflow, null vardata, etc.
1141 + * In case of sloppiness on the part of the caller, we clean it up rather
1142 + * than failing, since the caller is unlikely to handle failure.
1145 +normalize_header(struct kern_log_entry *hdr, const void *vardata)
1147 + if (hdr->log_severity < 0 || hdr->log_severity > LOG_DEBUG) {
1148 + hdr->log_severity = LOG_WARNING;
1150 + if (vardata == NULL
1151 + || hdr->log_size == 0
1152 + || hdr->log_format == EVL_NODATA) {
1153 + hdr->log_size = 0;
1154 + hdr->log_format = EVL_NODATA;
1156 + if (hdr->log_size > EVL_ENTRY_MAXLEN) {
1157 + hdr->log_size = EVL_ENTRY_MAXLEN;
1158 + hdr->log_flags |= EVL_TRUNCATE;
1163 + * log_dropped_recs_event() - Log message about previously dropped records.
1164 + * The evlog circular buffer had been full and caused later records to be
1165 + * dropped. Now the buffer has some free space again. Log an event reporting
1166 + * the number of records dropped. Caller has verified that there's at least
1167 + * enough room for this event record.
1170 +log_dropped_recs_event(void)
1172 +#define DROP_MSG_SIZE 80
1173 + char sbuf[DROP_MSG_SIZE];
1174 + struct kern_log_entry drechdr;
1176 + snprintf(sbuf, DROP_MSG_SIZE,
1177 + "%d event records dropped due to EVL buffer overflow.",
1179 + ebuf.bf_dropped = 0;
1180 + evl_mk_rechdr(&drechdr, "kern", EVL_BUFFER_OVERRUN, LOG_INFO,
1181 + strlen(sbuf) + 1, 0, EVL_STRING);
1182 + copy_rec_to_cbuf(&drechdr, sbuf);
1186 + * evl_check_buf() - Check for space in evlog buffer.
1187 + * If buffer free space is sufficient to log the indicated record,
1188 + * return 0. If not, return -1.
1190 + * Once the buffer becomes full and one or more messages are discarded,
1191 + * a significant portion of the buffer must be drained before we permit
1192 + * messages to be buffered again. We count the number of discards
1193 + * in the meantime and report them when we resume logging events.
1194 + * If we resumed logging with a nearly full buffer, then there could
1195 + * be a thrashing of stops and starts, making the discarded-message
1196 + * reporting annoying.
1198 + * @hdr: The header of the record caller intends to log.
1201 +evl_check_buf(const struct kern_log_entry *hdr)
1203 + char *head, *tail;
1204 + size_t water_mark, avail, recsize;
1206 + recsize = REC_HDR_SIZE + hdr->log_size;
1207 + head = ebuf.bf_head;
1208 + tail = ebuf.bf_tail;
1209 + avail = (head <= tail) ?
1210 + (ebuf.bf_len - (tail - head)) :
1213 + if (ebuf.bf_dropped != 0) {
1215 + * Still recovering from buffer overflow.
1216 + * Apply the low water mark.
1218 + water_mark = min(EVL_BUF_DRAINAGE, ebuf.bf_len / 2);
1220 + * Just in case recsize is huge and/or somebody cranks the
1221 + * buffer size and/or EVL_BUF_DRAINAGE way down, make
1222 + * sure we have room for this record AND the "records dropped"
1225 + water_mark = max(water_mark,
1226 + recsize + REC_HDR_SIZE + DROP_MSG_SIZE);
1228 + /* +1 because bf_tail must never catch up with bf_head. */
1229 + water_mark = recsize + 1;
1232 + if (avail < water_mark) {
1236 + /* There's enough free buffer space. Return success. */
1237 + if (ebuf.bf_dropped != 0) {
1238 + log_dropped_recs_event();
1244 + * evl_kbufread() - Copy records from evlog circular buffer into user space.
1245 + * If successful, returns the number of bytes copied; else returns a
1246 + * negative error code.
1248 + * @retbuf: pointer to the buffer to be filled with the event records
1249 + * @bufsize: length, in bytes, of retbuf
1252 +evl_kbufread(char *retbuf, size_t bufsize)
1257 + int retbuflen = 0;
1258 + char *tail, *buf = retbuf;
1260 + if (bufsize < REC_HDR_SIZE) {
1264 + if (ebuf.bf_head == ebuf.bf_tail && ebuf.bf_dropped != 0) {
1266 + * Probable scenario:
1267 + * 1. Somebody logged a huge burst of events and overflowed
1268 + * the buffer. At this point, there was no room for the
1269 + * "records dropped" message.
1270 + * 2. evlogd drained the buffer, and is now back for more.
1272 + unsigned long iflags;
1273 + spin_lock_irqsave(&ebuf_lock, iflags);
1274 + log_dropped_recs_event();
1275 + spin_unlock_irqrestore(&ebuf_lock, iflags);
1279 + * We expect that only the logging daemon will be running here,
1280 + * but serialize access just in case.
1282 + error = down_interruptible(&evl_read_sem);
1283 + if (error == -EINTR) {
1286 + /* Go to sleep if the buffer is empty. */
1287 + error = wait_event_interruptible(readq,
1288 + (ebuf.bf_head != ebuf.bf_tail));
1290 + up(&evl_read_sem);
1294 + * Assemble message(s) into the user buffer, as many as will
1295 + * fit. On running out of space in the buffer, try to copy
1296 + * the header for the overflowing message. This means that
1297 + * there will always be at least a header returned. The caller
1298 + * must compare the numbers of bytes returned (remaining) with
1299 + * the length of the message to see if the entire message is
1300 + * present. A subsequent read will get the entire message,
1301 + * including the header (again).
1303 + * For simplicity, take a snapshot of bf_tail, and don't read
1304 + * past that even if evl_writeh() pours in more records while
1305 + * we're draining. We'll get those new records next time around.
1307 + tail = ebuf.bf_tail;
1308 + rec = ebuf.bf_head;
1309 + if (rec == tail) {
1310 + /* Should not happen. Buffer must have at least one record. */
1316 + struct cbregion rg;
1317 + __u16 vardata_size; /* type must match rec.log_size */
1319 + if (bufsize < REC_HDR_SIZE) {
1324 + * Extract log_size from header, which could be split due to
1325 + * wraparound, or misaligned.
1327 + set_region(&rg, rec+offsetof(struct kern_log_entry, log_size),
1328 + sizeof(vardata_size));
1329 + copy_from_cbuf(&rg, (char*) &vardata_size);
1330 + rec_size = REC_HDR_SIZE + vardata_size;
1332 + if (bufsize < rec_size) {
1334 + * Copyout only the header 'cause user buffer can't
1335 + * hold full record.
1337 + set_region(&rg, rec, REC_HDR_SIZE);
1338 + error = copy_cbuf_to_user(&rg, buf);
1343 + bufsize -= REC_HDR_SIZE;
1344 + retbuflen += REC_HDR_SIZE;
1347 + set_region(&rg, rec, rec_size);
1348 + error = copy_cbuf_to_user(&rg, buf);
1355 + bufsize -= rec_size;
1356 + retbuflen += rec_size;
1357 + } while (rec != tail);
1360 + ebuf.bf_head = rec;
1361 + error = retbuflen;
1365 + up(&evl_read_sem);
1370 + * evl_writeh() - Log event, given a pre-constructed header.
1371 + * Returns 0 on success, or a negative error code otherwise.
1372 + * For caller's convenience, we normalize the header as needed.
1375 +evl_writeh(struct kern_log_entry *hdr, const char *vardata)
1377 + char *oldtail = ebuf.bf_tail;
1378 + unsigned long iflags; /* for spin_lock_irqsave() */
1380 + normalize_header(hdr, vardata);
1382 + spin_lock_irqsave(&ebuf_lock, iflags);
1383 + if (evl_check_buf(hdr) < 0) {
1384 + ebuf.bf_dropped++;
1385 + spin_unlock_irqrestore(&ebuf_lock, iflags);
1389 + copy_rec_to_cbuf(hdr, vardata);
1391 + * If the variable portion is a truncated string, make sure it
1392 + * ends with a null character.
1394 + if ((hdr->log_flags & EVL_TRUNCATE) && hdr->log_format == EVL_STRING) {
1395 + *(ebuf.bf_tail - 1) = '\0';
1398 + if ((ebuf.bf_head == oldtail) &&
1399 + (ebuf.bf_head != ebuf.bf_tail)) {
1400 + wake_up_interruptible(&readq);
1402 + spin_unlock_irqrestore(&ebuf_lock, iflags);
1405 diff -Nur linux-2.6.8.1.org/kernel/printk.c linux-2.6.8.1/kernel/printk.c
1406 --- linux-2.6.8.1.org/kernel/printk.c 2005-03-02 12:00:39.012574720 +0100
1407 +++ linux-2.6.8.1/kernel/printk.c 2005-03-02 13:25:03.524651856 +0100
1410 #include <asm/uaccess.h>
1412 +#include <string.h>
1414 +#ifdef CONFIG_EVLOG
1415 +#include <linux/evlog.h>
1416 +extern int evl_printkat(const char *facname, char *buf, size_t buflen, const char *fmt, va_list args);
1417 +#define PRINTKAT_BUFLEN EVL_ENTRY_MAXLEN
1419 +#define PRINTKAT_BUFLEN 512
1422 #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
1424 /* printk's without a loglevel use this.. */
1425 @@ -111,6 +121,10 @@
1426 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
1427 static int preferred_console = -1;
1429 +#ifdef CONFIG_EVLOG
1430 +extern int evl_kbufread(char *, size_t);
1433 /* Flag: console code may call schedule() */
1434 static int console_may_schedule;
1437 * 8 -- Set level of messages printed to console
1438 * 9 -- Return number of unread characters in the log buffer
1439 * 10 -- Return size of the log buffer
1440 + * 20 -- Read from event logging buffer
1442 int do_syslog(int type, char __user * buf, int len)
1444 @@ -366,6 +381,17 @@
1445 case 9: /* Number of chars in the log buffer */
1446 error = log_end - log_start;
1449 +#ifdef CONFIG_EVLOG
1450 + error = verify_area(VERIFY_WRITE, buf, len);
1454 + error = evl_kbufread(buf, len);
1459 case 10: /* Size of the log buffer */
1460 error = log_buf_len;
1462 @@ -511,9 +537,20 @@
1463 * then changes console_loglevel may break. This is because console_loglevel
1464 * is inspected when the actual printing occurs.
1466 +int vprintk(const char *fmt, va_list args);
1468 asmlinkage int printk(const char *fmt, ...)
1472 + va_start(args, fmt);
1473 + status = vprintk(fmt, args);
1478 +int vprintk(const char *fmt, va_list args)
1480 unsigned long flags;
1484 spin_lock_irqsave(&logbuf_lock, flags);
1486 /* Emit the output into the temporary buffer */
1487 - va_start(args, fmt);
1488 printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
1492 * Copy the output into log_buf. If the caller didn't provide
1493 @@ -900,4 +935,104 @@
1494 return __printk_ratelimit(printk_ratelimit_jiffies,
1495 printk_ratelimit_burst);
1498 +static char printkat_buf[PRINTKAT_BUFLEN];
1499 +static spinlock_t printkat_lock = SPIN_LOCK_UNLOCKED;
1502 + * Copy src to dest, replacing strings of the form "{id}%" with "%".
1503 + * If src contains "{{", strip out that and anything beyond it.
1504 + * dest is a buffer of size bufsz. Make sure we don't overflow it.
1506 +void evl_unbrace(char *dest, const char *src, int bufsz)
1508 + const char *copy_this = src, *scan_this = src;
1509 + const char *c, *lcb, *rcb, *cut_here;
1510 + int copy_len, dlen = 0;
1512 + cut_here = strstr(src, "{{");
1515 + lcb = strchr(scan_this, '{');
1519 + rcb = strstr(lcb+2, "}%");
1523 + if (cut_here && cut_here < rcb) {
1526 + /* Is it a valid identifier between the { and } ? */
1528 + if (*c != '_' && !isalpha(*c)) {
1531 + for (c++; c < rcb; c++) {
1532 + if (*c != '_' && !isalnum(*c)) {
1536 + copy_len = min(lcb - copy_this, bufsz-(dlen+1));
1537 + strncat(dest + dlen, copy_this, copy_len);
1539 + copy_this = rcb+1;
1541 + scan_this = rcb+2;
1545 + copy_len = min(cut_here - copy_this, bufsz-(dlen+1));
1547 + copy_len = bufsz-(dlen+1);
1549 + strncat(dest + dlen, copy_this, copy_len);
1554 + * printkat - Log message to printk and/or evlog, stripping {id}s.
1555 + * @facname: facility name (e.g., driver name) for evlog event
1556 + * @call_printk: 0 -> don't call printk
1557 + * fmt and subsequent args are as with printk. Log the message to printk
1558 + * (via vprintk), and (if EVLOG is configured) also to evlog as an
1559 + * EVL_PRINTF-format record. Strip {id}s from the message, and also
1560 + * anything following "{{".
1563 +int __printkat(const char *facname, int call_printk, const char *fmt, ...)
1566 + unsigned long flags;
1569 + va_start(args, fmt);
1570 +#ifdef CONFIG_EVLOG
1571 + spin_lock_irqsave(&printkat_lock, flags);
1572 + status = evl_printkat(facname, printkat_buf, PRINTKAT_BUFLEN, fmt,
1574 + if (call_printk) {
1575 + (void) vprintk(printkat_buf, args);
1577 + spin_unlock_irqrestore(&printkat_lock, flags);
1579 + /* EVLOG disabled. Just call printk, stripping {id}s as needed. */
1580 + if (!call_printk) {
1583 + if (strstr(fmt, "}%") || strstr(fmt, "{{")) {
1584 + spin_lock_irqsave(&printkat_lock, flags);
1585 + evl_unbrace(printkat_buf, fmt, PRINTKAT_BUFLEN);
1586 + status = vprintk(printkat_buf, args);
1587 + spin_unlock_irqrestore(&printkat_lock, flags);
1589 + status = vprintk(fmt, args);
1596 +EXPORT_SYMBOL(__printkat);
1597 EXPORT_SYMBOL(printk_ratelimit);
1598 diff -Nur linux-2.6.8.1.org/net/core/dev.c linux-2.6.8.1/net/core/dev.c
1599 --- linux-2.6.8.1.org/net/core/dev.c 2005-03-02 12:00:34.020333656 +0100
1600 +++ linux-2.6.8.1/net/core/dev.c 2005-03-02 13:18:28.973632728 +0100
1601 @@ -3337,6 +3337,87 @@
1603 subsys_initcall(net_dev_init);
1605 +static spinlock_t netdev_printk_lock = SPIN_LOCK_UNLOCKED;
1607 + * __netdev_printk() - Log message with interface name, gated by message level
1608 + * @sevlevel: severity level -- e.g., KERN_INFO
1609 + * @netdev: net_device pointer
1610 + * @msglevel: a standard message-level flag such as NETIF_MSG_PROBE.
1611 + * Unless msglevel is NETIF_MSG_ALL, log the message only if
1612 + * that flag is set in netdev->msg_enable.
1613 + * @format: as with printk
1614 + * @args: as with printk
1616 + * Does the work for the netdev_printk macro.
1617 + * For a lot of network drivers, the probe function looks like
1619 + * netdev = alloc_netdev(...); // or alloc_etherdev(...)
1620 + * SET_NETDEV_DEV(netdev, dev);
1622 + * register_netdev(netdev);
1624 + * netdev_printk and its wrappers (e.g., netdev_err) can be used as
1625 + * soon as you have a valid net_device pointer -- e.g., from alloc_netdev,
1626 + * alloc_etherdev, or init_etherdev. (Before that, use dev_printk and
1627 + * its wrappers to report device errors.) It's common for an interface to
1628 + * have a name like "eth%d" until the device is successfully configured,
1629 + * and the call to register_netdev changes it to a "real" name like "eth0".
1631 + * If the interface's reg_state is NETREG_REGISTERED, we assume that it has
1632 + * been successfully set up in sysfs, and we prepend only the interface name
1633 + * to the message -- e.g., "eth0: NIC Link is Down". The interface
1634 + * name can be used to find eth0's driver, bus ID, etc. in sysfs.
1636 + * For any other value of reg_state, we prepend the driver name and bus ID
1637 + * as well as the (possibly incomplete) interface name -- e.g.,
1638 + * "eth%d (e100 0000:00:03.0): Failed to map PCI address..."
1640 + * Probe functions that alloc and register in one step (via init_etherdev),
1641 + * or otherwise register the device before the probe completes successfully,
1642 + * may need to take other steps to ensure that the failing device is clearly
1646 + * negative number on error
1647 + * 1 if we didn't log the event because of the msglevel
1648 + * 2 if we logged the message but the struct device pointer is null
1651 +int __netdev_printk(const char *sevlevel, const struct net_device *netdev,
1652 + int msglevel, const char *format, ...)
1654 + int ret = 1; /* not logged */
1655 + if (!netdev || !format) {
1658 + if (msglevel == NETIF_MSG_ALL || (netdev->msg_enable & msglevel)) {
1659 + static char msg[512]; /* protected by netdev_printk_lock */
1660 + unsigned long flags;
1662 + struct device *dev = netdev->class_dev.dev;
1664 + spin_lock_irqsave(&netdev_printk_lock, flags);
1665 + va_start(args, format);
1666 + vsnprintf(msg, 512, format, args);
1673 + if (netdev->reg_state == NETREG_REGISTERED || !dev) {
1674 + printk("%s%s: %s", sevlevel, netdev->name, msg);
1676 + printk("%s%s (%s %s): %s", sevlevel, netdev->name,
1677 + dev->driver->name, dev->bus_id, msg);
1679 + spin_unlock_irqrestore(&netdev_printk_lock, flags);
1680 + ret = dev ? 0 : 2;
1685 +EXPORT_SYMBOL(__netdev_printk);
1686 EXPORT_SYMBOL(__dev_get);
1687 EXPORT_SYMBOL(__dev_get_by_flags);
1688 EXPORT_SYMBOL(__dev_get_by_index);