]> git.pld-linux.org Git - packages/kernel.git/blob - evlog-2.6.8-PLD.patch
- replaced by linux-2.4-sfq.patch
[packages/kernel.git] / evlog-2.6.8-PLD.patch
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
4 @@ -21,6 +21,7 @@
5  #include <linux/pm.h>
6  #include <asm/semaphore.h>
7  #include <asm/atomic.h>
8 +#include <linux/printkat.h>
9  
10  #define DEVICE_NAME_SIZE       50
11  #define DEVICE_NAME_HALF       __stringify(20) /* Less than half to accommodate slop */
12 @@ -401,7 +402,8 @@
13  
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__)
19  
20  #ifdef DEBUG
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
25 @@ -0,0 +1,134 @@
26 +/*
27 + * Linux Event Logging
28 + * Copyright (C) International Business Machines Corp., 2001
29 + *
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.
34 + *
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.
39 + *
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.
43 + *
44 + *  Please send e-mail to kenistoj@users.sourceforge.net if you have
45 + *  questions or comments.
46 + *
47 + *  Project Website:  http://evlog.sourceforge.net/
48 + */
49 +
50 +#ifndef _LINUX_EVLOG_H
51 +#define _LINUX_EVLOG_H
52 +
53 +#include <stdarg.h>
54 +#include <linux/types.h>
55 +#include <asm/types.h>
56 +
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. */
66 +
67 +/* Formats for optional portion of record. */
68 +#define EVL_NODATA    0
69 +#define EVL_BINARY    1
70 +#define EVL_STRING    2
71 +#define EVL_PRINTF    3
72 +
73 +/* Maximum length of variable portion of record */
74 +#define EVL_ENTRY_MAXLEN (8 * 1024)
75 +
76 +/* Facility (e.g., driver) names are truncated to 15+null. */
77 +#define FACILITY_MAXLEN 16
78 +
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... */
92 +       gid_t   log_gid;
93 +       pid_t   log_pid;
94 +       pid_t   log_pgrp;
95 +       char    log_facility[FACILITY_MAXLEN];  /* e.g., driver name */
96 +}; 
97 +
98 +#define LOGREC_KMAGIC  0x7af8
99 +#define LOGREC_KVERSION        3
100 +
101 +/* Reserved Event Types */
102 +#define EVL_BUFFER_OVERRUN     0x6
103 +
104 +#ifdef __KERNEL__
105 +/*
106 + * severities, AKA priorities
107 + */
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 */
116 +
117 +/*
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.
120 + */
121 +struct evl_recbuf {
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 */
127 +};
128 +
129 +#ifdef CONFIG_EVLOG
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);
136 +
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 */
156 +
157 +#endif /* __KERNEL__ */
158 +
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
163 @@ -37,6 +37,7 @@
164  #include <linux/config.h>
165  #include <linux/device.h>
166  #include <linux/percpu.h>
167 +#include <linux/printkat.h>
168  
169  struct divert_blk;
170  struct vlan_group;
171 @@ -477,6 +478,9 @@
172         struct divert_blk       *divert;
173  #endif /* CONFIG_NET_DIVERT */
174  
175 +       /* NETIF_MSG_* flags to control the types of events we log */
176 +       int msg_enable;
177 +
178         /* class/net/name entry */
179         struct class_device     class_dev;
180         struct net_device_stats* (*last_stats)(struct net_device *);
181 @@ -778,6 +782,7 @@
182         NETIF_MSG_PKTDATA       = 0x1000,
183         NETIF_MSG_HW            = 0x2000,
184         NETIF_MSG_WOL           = 0x4000,
185 +       NETIF_MSG_ALL           = -1,           /* always log message */
186  };
187  
188  #define netif_msg_drv(p)       ((p)->msg_enable & NETIF_MSG_DRV)
189 @@ -946,6 +951,49 @@
190  extern char *net_sysctl_strdup(const char *s);
191  #endif
192  
193 +/* debugging and troubleshooting/diagnostic helpers. */
194 +/**
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
203 + */
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...)      \
207 +do {                                                                   \
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__);                             \
216 +       }                                                               \
217 +} while (0)
218 +#ifdef DEBUG
219 +#define netdev_dbg(netdev, msglevel, format, arg...)           \
220 +       netdev_printk(KERN_DEBUG , netdev , msglevel , format , ## arg)
221 +#else
222 +#define netdev_dbg(netdev, msglevel, format, arg...) do {} while (0)
223 +#endif
224 +
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)
231 +
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)
235 +
236  #endif /* __KERNEL__ */
237  
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
242 @@ -0,0 +1,98 @@
243 +/*
244 + * Linux Event Logging for the Enterprise
245 + * Copyright (C) International Business Machines Corp., 2002
246 + *
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.
251 + *
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.
256 + *
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.
260 + *
261 + *  Please send e-mail to kenistoj@users.sourceforge.net if you have
262 + *  questions or comments.
263 + *
264 + *  Project Website:  http://evlog.sourceforge.net/
265 + */
266 +
267 +#ifndef _LINUX_PRINTKAT_H
268 +#define _LINUX_PRINTKAT_H
269 +
270 +extern int __printkat(const char *facname, int call_printk,
271 +       const char *fmt, ...);
272 +
273 +#ifndef CONFIG_EVLOG
274 +
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)
278 +
279 +#else  /* CONFIG_EVLOG */
280 +
281 +#include <linux/stringify.h>
282 +#include <linux/kernel.h>
283 +#include <linux/evlog.h>
284 +
285 +/*
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.
290 + *
291 + * In a device driver, EVL_FACILITY_NAME should be the driver name (without
292 + * quotes).
293 + */
294 +#ifndef EVL_FACILITY_NAME
295 +#ifdef KBUILD_MODNAME
296 +#define EVL_FACILITY_NAME KBUILD_MODNAME
297 +#else
298 +#define EVL_FACILITY_NAME kern
299 +#endif
300 +#endif
301 +
302 +/* Bloat doesn't matter: this doesn't end up in vmlinux. */
303 +struct log_position {
304 +   int line;
305 +   char function[64 - sizeof(int)];
306 +   char file[128];
307 +};
308 +
309 +#define _LOG_POS { __LINE__, __FUNCTION__, __FILE__ }
310 +
311 +/*
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.
316 + */
317 +struct log_info {
318 +   char format[128+64];
319 +   char facility[64];
320 +   struct log_position pos;
321 +};
322 +
323 +#define printkat(fmt, arg...) \
324 +({ \
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); \
328 +})
329 +
330 +/* Same as printkat, but don't call printk. */
331 +#define printkat_noprintk(fmt, arg...) \
332 +({ \
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); \
336 +})
337 +
338 +#endif /* CONFIG_EVLOG */
339 +
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
344 @@ -197,6 +197,19 @@
345           agent" (/sbin/hotplug) to load modules and set up software needed
346           to use devices as you hotplug them.
347  
348 +config EVLOG
349 +       bool "Event logging support"
350 +       ---help---
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.
356 +
357 +         For more information see http://evlog.sourceforge.net
358 +
359 +         If you don't know what to do here, say N.
360 +
361  config IKCONFIG
362         bool "Kernel .config support"
363         ---help---
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
367 @@ -20,6 +20,7 @@
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
378 @@ -0,0 +1,499 @@
379 +/*
380 + * Linux Event Logging
381 + * Copyright (C) International Business Machines Corp., 2003
382 + *
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.
387 + *
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.
392 + *
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.
396 + *
397 + *  Please send e-mail to kenistoj@users.sourceforge.net if you have
398 + *  questions or comments.
399 + *
400 + *  Project Website:  http://evlog.sourceforge.net/
401 + */
402 +
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>
411 +
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);
417 +
418 +/**
419 + * evl_write() - write header + optional buffer to event handler
420 + *
421 + * @buf: optional variable-length data
422 + * other args as per evl_mk_rechdr()
423 + */
424 +int
425 +evl_write(const char *facility, int event_type, int severity, const void *buf,
426 +       size_t size, uint flags, int format)
427 +{
428 +       struct kern_log_entry hdr;
429 +
430 +       evl_mk_rechdr(&hdr, facility, event_type, severity, size, flags,
431 +               format);
432 +       return evl_writeh(&hdr, buf);
433 +}
434 +
435 +void
436 +evl_init_recbuf(struct evl_recbuf *b, char *buf, size_t size)
437 +{
438 +       b->b_buf = buf;
439 +       b->b_tail = buf;
440 +       b->b_end = buf + size;
441 +       b->b_zapped_nl = NULL;
442 +       b->b_argsz = NULL;
443 +}
444 +
445 +/**
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
450 + */
451 +void
452 +evl_put(struct evl_recbuf *b, const void *data, size_t datasz)
453 +{
454 +       ptrdiff_t room = b->b_end - b->b_tail;
455 +       if (room > 0) {
456 +               (void) memcpy(b->b_tail, data, min(datasz, (size_t)room));
457 +       }
458 +       b->b_tail += datasz;
459 +}
460 +
461 +/**
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.
466 + *
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
470 + */
471 +void
472 +evl_puts(struct evl_recbuf *b, const char *s, int null)
473 +{
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';
478 +       }
479 +}
480 +
481 +/**
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.
487 + */
488 +void
489 +evl_zap_newline(struct evl_recbuf *b)
490 +{
491 +       char *nl = b->b_tail - 2;
492 +       if (b->b_buf <= nl && nl < b->b_end && *nl == '\n') {
493 +               *nl = '\0';
494 +               b->b_tail--;
495 +               b->b_zapped_nl = nl;
496 +       }
497 +}
498 +
499 +/**
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.
503 + */
504 +void
505 +evl_unzap_newline(struct evl_recbuf *b)
506 +{
507 +       if (b->b_zapped_nl) {
508 +               b->b_zapped_nl[0] = '\n';
509 +               b->b_zapped_nl[1] = '\0';
510 +       }
511 +}
512 +
513 +/**
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.
517 + */
518 +void
519 +evl_end_fmt(struct evl_recbuf *b)
520 +{
521 +       int argsz = 0;
522 +       b->b_argsz = b->b_tail;
523 +       evl_put(b, &argsz, sizeof(int));
524 +}
525 +
526 +/**
527 + * evl_end_args() - For EVL_PRINTF record, store the argsz.
528 + * Called after the args have been copied in.
529 + */
530 +void
531 +evl_end_args(struct evl_recbuf *b)
532 +{
533 +       char *args;
534 +       int argsz;
535 +
536 +       if (! b->b_argsz) {
537 +               /* Nobody called evl_end_fmt(). */
538 +               return;
539 +       }
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. */
543 +               return;
544 +       }
545 +       argsz = b->b_tail - args;
546 +       memcpy(b->b_argsz, &argsz, sizeof(int));
547 +}
548 +
549 +static inline void
550 +skip_atoi(const char **s)
551 +{
552 +       while (isdigit(**s)) {
553 +               (*s)++;
554 +       }
555 +}
556 +
557 +/**
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
565 + *      %*.2lx
566 + * *pqualifier is set to 'l', *wp is set to 0x1, and a pointer to the 'x'
567 + * is returned.
568 + *
569 + * Note: This function is derived from vsnprintf() (see lib/vsprintf.c),
570 + * and should be kept in sync with that function.
571 + *
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 '*'.
575 + */
576 +const char *
577 +parse_printf_fmt(const char *fmt, int *pqualifier, int *wp)
578 +{
579 +       int qualifier = -1;
580 +       *wp = 0;
581 +
582 +       /* process flags */
583 +       repeat:
584 +               ++fmt;          /* this also skips first '%' */
585 +               switch (*fmt) {
586 +                       case '-':
587 +                       case '+':
588 +                       case ' ':
589 +                       case '#':
590 +                       case '0':
591 +                               goto repeat;
592 +               }
593 +
594 +       /* get field width */
595 +       if (isdigit(*fmt))
596 +               skip_atoi(&fmt);
597 +       else if (*fmt == '*') {
598 +               ++fmt;
599 +               /* it's the next argument */
600 +               *wp |= 0x1;
601 +       }
602 +
603 +       /* get the precision */
604 +       if (*fmt == '.') {
605 +               ++fmt;
606 +               if (isdigit(*fmt))
607 +                       skip_atoi(&fmt);
608 +               else if (*fmt == '*') {
609 +                       ++fmt;
610 +                       /* it's the next argument */
611 +                       *wp |= 0x2;
612 +               }
613 +       }
614 +
615 +       /* get the conversion qualifier */
616 +       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
617 +           *fmt == 'Z' || *fmt == 'z') {
618 +               qualifier = *fmt;
619 +               ++fmt;
620 +               if (qualifier == 'l' && *fmt == 'l') {
621 +                       qualifier = 'L';
622 +                       ++fmt;
623 +               }
624 +       }
625 +
626 +       *pqualifier = qualifier;
627 +       return fmt;
628 +}
629 +
630 +/**
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.
634 + *
635 + * @b - describes buffer; updated to reflect data added
636 + * @fmt - printf/printk-style format string
637 + * @args - values to be packed into buffer
638 + */
639 +void
640 +evl_pack_args(struct evl_recbuf *b, const char *fmt, va_list args)
641 +{
642 +#define COPYARG(type) \
643 +    do { type v=va_arg(args,type); evl_put(b,&v,sizeof(v)); } while(0)
644 +
645 +       const char *s;
646 +       int qualifier;
647 +
648 +       for (; *fmt ; ++fmt) {
649 +               int wp = 0x0;
650 +               if (*fmt != '%') {
651 +                       continue;
652 +               }
653 +
654 +               fmt = parse_printf_fmt(fmt, &qualifier, &wp);
655 +               if (wp & 0x1) {
656 +                       /* width is '*' (next arg) */
657 +                       COPYARG(int);
658 +               }
659 +               if (wp & 0x2) {
660 +                       /* ditto precision */
661 +                       COPYARG(int);
662 +               }
663 +
664 +               switch (*fmt) {
665 +                       case 'c':
666 +                               COPYARG(int);
667 +                               continue;
668 +
669 +                       case 's':
670 +                               s = va_arg(args, char *);
671 +                               evl_puts(b, s, 1);
672 +                               continue;
673 +
674 +                       case 'p':
675 +                               COPYARG(void*);
676 +                               continue;
677 +
678 +                       case 'n':
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 *);
684 +                               } else {
685 +                                       (void) va_arg(args, int *);
686 +                               }
687 +                               continue;
688 +
689 +                       case '%':
690 +                               continue;
691 +
692 +                               /* integer number formats - handle outside switch */
693 +                       case 'o':
694 +                       case 'X':
695 +                       case 'x':
696 +                       case 'd':
697 +                       case 'i':
698 +                       case 'u':
699 +                               break;
700 +
701 +                       default:
702 +                               /* Bogus conversion.  Pass thru unchanged. */
703 +                               if (*fmt == '\0')
704 +                                       --fmt;
705 +                               continue;
706 +               }
707 +               if (qualifier == 'L') {
708 +                       COPYARG(long long);
709 +               } else if (qualifier == 'l') {
710 +                       COPYARG(long);
711 +               } else if (qualifier == 'Z' || qualifier == 'z') {
712 +                       COPYARG(size_t);
713 +               } else if (qualifier == 'h') {
714 +                       COPYARG(int);
715 +               } else {
716 +                       COPYARG(int);
717 +               }
718 +       }
719 +}
720 +
721 +/*
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.
725 + */
726 +static spinlock_t msgbuf_lock = SPIN_LOCK_UNLOCKED;
727 +static char msgbuf[EVL_ENTRY_MAXLEN];
728 +
729 +/**
730 + * evl_send_printf() - Format and log a PRINTF-format message.
731 + * Create and log a PRINTF-format event record whose contents are:
732 + *     format string
733 + *     int containing args size
734 + *     args
735 + * @hdr - pre-constructed record header, which we adjust as needed
736 + * @fmt - format string
737 + * @args - arg list
738 + */
739 +static int
740 +evl_send_printf(struct kern_log_entry *hdr, const char *fmt, va_list args)
741 +{
742 +       int ret;
743 +       struct evl_recbuf b;
744 +       unsigned long iflags;
745 +
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);
750 +       evl_end_fmt(&b);
751 +       evl_pack_args(&b, fmt, args);
752 +       evl_end_args(&b);
753 +
754 +       hdr->log_size = b.b_tail - b.b_buf;
755 +       /* Note: If size > EVL_ENTRY_MAXLEN, evl_writeh() will handle it. */
756 +       
757 +       ret = evl_writeh(hdr, b.b_buf);
758 +       spin_unlock_irqrestore(&msgbuf_lock, iflags);
759 +       return ret;
760 +}
761 +
762 +/**
763 + * evl_vprintk() - Format and log a PRINTF-format record.
764 + * @fmt - format string
765 + * @args - arg list
766 + * other args as per evl_mk_rechdr().  If event_type == 0, set flag to
767 + *     request that recipient set event type.
768 + */
769 +int
770 +evl_vprintk(const char *facility, int event_type, int severity,
771 +       const char *fmt, va_list args)
772 +{
773 +       struct kern_log_entry hdr;
774 +       unsigned int flags = 0;
775 +       if (event_type == 0) {
776 +               flags |= EVL_EVTYCRC;
777 +       }
778 +       evl_mk_rechdr(&hdr, facility, event_type, severity, 1 /*size TBD*/,
779 +               flags, EVL_PRINTF);
780 +       
781 +       return evl_send_printf(&hdr, fmt, args);
782 +}
783 +
784 +/**
785 + * evl_printk() - Format and log a PRINTF-format record.
786 + * @fmt - format string
787 + * other args as per evl_mk_rechdr()
788 + */
789 +int
790 +evl_printk(const char *facility, int event_type, int severity,
791 +       const char *fmt, ...)
792 +{
793 +       va_list args;
794 +       int ret;
795 +       va_start(args, fmt);
796 +       ret = evl_vprintk(facility, event_type, severity, fmt, args);
797 +       va_end(args);
798 +       return ret;
799 +}
800 +
801 +/*** printkat support ***/
802 +
803 +static int
804 +try_extract_severity(const char *msg)
805 +{
806 +       if (msg[0] == '<'
807 +           && msg[1] >= '0' && msg[1] <= '7'
808 +           && msg[2] == '>') {
809 +               return msg[1] - '0';
810 +       }
811 +       return -1;
812 +}
813 +
814 +static int
815 +extract_severity(const char *fmt, va_list args)
816 +{
817 +       int sev = try_extract_severity(fmt);
818 +       if (sev == -1 && (fmt[0] == '<' || fmt[0] == '%')) {
819 +               /* Handle stuff like "<%d>..." and "%s..." */
820 +               char prefix[4];
821 +               (void) vsnprintf(prefix, 4, fmt, args);
822 +               sev = try_extract_severity(prefix);
823 +       }
824 +       return sev;
825 +}
826 +
827 +/**
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
833 + *     evl_unbrace().
834 + * other args as per printk()
835 + * 
836 + * On return, buf contains the format string, purged of {id} constructs
837 + * and the "{{" trailer, if any.
838 + */
839 +int
840 +evl_printkat(const char *facility, char *buf, size_t buflen, const char *fmt,
841 +       va_list args)
842 +{
843 +       int ret;
844 +       int severity;
845 +       struct evl_recbuf b;
846 +       struct kern_log_entry hdr;
847 +
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);
852 +       evl_end_fmt(&b);
853 +
854 +       evl_pack_args(&b, fmt, args);
855 +       evl_end_args(&b);
856 +
857 +       severity = extract_severity(b.b_buf, args);
858 +       if (severity < 0) {
859 +               /* See kernel.h and printk.c */
860 +               severity = default_message_loglevel;
861 +       }
862 +
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. */
866 +       
867 +       ret = evl_writeh(&hdr, b.b_buf);
868 +
869 +       /* Put the newline back in case caller calls printk(). */
870 +       evl_unzap_newline(&b);
871 +       return ret;
872 +}
873 +
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
881 @@ -0,0 +1,523 @@
882 +/*
883 + * Linux Event Logging
884 + * Copyright (C) International Business Machines Corp., 2003
885 + *
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.
890 + *
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.
895 + *
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.
899 + *
900 + *  Please send e-mail to kenistoj@users.sourceforge.net if you have
901 + *  questions or comments.
902 + *
903 + *  Project Website:  http://evlog.sourceforge.net/
904 + */
905 +
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>
919 +
920 +#define REC_HDR_SIZE sizeof(struct kern_log_entry)
921 +
922 +extern struct timezone sys_tz;
923 +
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)
927 +#undef EVL_BUF_SIZE
928 +#define EVL_BUF_SIZE (2*EVL_ENTRY_MAXLEN)
929 +#endif
930 +
931 +/*
932 + * After buffer overflows, require at most this much free space before
933 + * logging events again.
934 + */
935 +#define EVL_BUF_DRAINAGE (16*1024U)
936 +
937 +/*
938 + * This data structure describes the circular buffer that is written into
939 + * by evl_writeh() and drained by evl_kbufread().
940 + *
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.
943 + *
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.
947 + * By convention:
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.
952 + *
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.
957 + */
958 +struct cbuf {
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 */
965 +};
966
967 +static char evl_buffer[EVL_BUF_SIZE + sizeof(long)];
968 +
969 +static struct cbuf ebuf = {
970 +       evl_buffer,
971 +       EVL_BUF_SIZE,
972 +       0,
973 +       evl_buffer, 
974 +       evl_buffer,
975 +       evl_buffer + EVL_BUF_SIZE
976 +};
977 +
978 +/*
979 + * evl_read_sem serializes reads of the evlog buffer into user space (although
980 + * only the logging daemon should be running evl_kbufread()).
981 + *
982 + * readq allows the reader to sleep until there's at least one record in
983 + * the buffer to read.
984 + *
985 + * ebuf_lock serializes writes to the evlog buffer.
986 + */
987 +static DECLARE_MUTEX(evl_read_sem);
988 +static DECLARE_WAIT_QUEUE_HEAD(readq);
989 +static spinlock_t ebuf_lock = SPIN_LOCK_UNLOCKED;
990 +
991 +/*
992 + * A region of the evlog circular buffer, possibly split into 2 chunks
993 + * due to wraparound.
994 + */
995 +struct cbregion {
996 +       char    *rg_head;
997 +       char    *rg_tail;
998 +       size_t  rg_chunk1;
999 +       size_t  rg_chunk2;
1000 +};
1001 +
1002 +/**
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.
1008 + *
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
1013 + */
1014 +static void
1015 +set_region(struct cbregion *rg, char *head, size_t nbytes)
1016 +{
1017 +       if (head >= ebuf.bf_end) {
1018 +               head -= ebuf.bf_len;
1019 +       }
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;
1026 +       } else {
1027 +               rg->rg_chunk1 = nbytes;
1028 +               rg->rg_chunk2 = 0;
1029 +       }
1030 +}
1031 +
1032 +static void
1033 +copy_from_cbuf(const struct cbregion *rg, char *dest)
1034 +{
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);
1038 +       }
1039 +}
1040 +
1041 +static int
1042 +copy_cbuf_to_user(const struct cbregion *rg, char *ubuf)
1043 +{
1044 +       int status;
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,
1048 +                       rg->rg_chunk2);
1049 +       }
1050 +       return status;
1051 +}
1052 +
1053 +static void
1054 +copy_to_cbuf(const struct cbregion *rg, const char *src)
1055 +{
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);
1059 +       }
1060 +}
1061 +
1062 +/**
1063 + * copy_rec_to_cbuf() - Log event (hdr + vardata) to buffer.
1064 + * Caller has verified that there's enough room.
1065 + */
1066 +static void
1067 +copy_rec_to_cbuf(const struct kern_log_entry *hdr, const char *vardata)
1068 +{
1069 +       struct cbregion rg;
1070 +       char *tail = ebuf.bf_tail;
1071 +
1072 +       set_region(&rg, tail, REC_HDR_SIZE);
1073 +       copy_to_cbuf(&rg, (const char*) hdr);
1074 +
1075 +       if (hdr->log_size != 0) {
1076 +               set_region(&rg, tail + REC_HDR_SIZE, hdr->log_size);
1077 +               copy_to_cbuf(&rg, vardata);
1078 +       }
1079 +
1080 +       ebuf.bf_tail = rg.rg_tail;
1081 +}
1082 +
1083 +/**
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)
1092 + */
1093 +void
1094 +evl_mk_rechdr(struct kern_log_entry *rec_hdr,
1095 +               const char *facility,
1096 +               int     event_type,
1097 +               int     severity,
1098 +               size_t  size,
1099 +               uint    flags,
1100 +               int     format)
1101 +{
1102 +       struct timespec ts;
1103 +
1104 +       flags |= EVL_KERNEL_EVENT;
1105 +       if (in_interrupt()) {
1106 +               flags |= EVL_INTERRUPT;
1107 +       }
1108 +
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();
1121 +
1122 +       strlcpy(rec_hdr->log_facility, facility, FACILITY_MAXLEN);
1123 +
1124 +       if (get_seconds() == 0) {
1125 +               rec_hdr->log_flags |= EVL_INITIAL_BOOT_EVENT;
1126 +       } else {
1127 +#if defined(__i386__)
1128 +               if (sys_tz.tz_minuteswest == 0) {
1129 +                       /* localtime */
1130 +                       rec_hdr->log_flags |= EVL_KERNTIME_LOCAL;
1131 +               }
1132 +#endif
1133 +       }
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;
1137 +}
1138 +
1139 +/**
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.
1143 + */
1144 +static void
1145 +normalize_header(struct kern_log_entry *hdr, const void *vardata)
1146 +{
1147 +       if (hdr->log_severity < 0 || hdr->log_severity > LOG_DEBUG) {
1148 +               hdr->log_severity = LOG_WARNING;
1149 +       }
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;
1155 +       }
1156 +       if (hdr->log_size > EVL_ENTRY_MAXLEN) {
1157 +               hdr->log_size = EVL_ENTRY_MAXLEN;
1158 +               hdr->log_flags |= EVL_TRUNCATE;
1159 +       }
1160 +}
1161 +
1162 +/**
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.
1168 + */
1169 +static void
1170 +log_dropped_recs_event(void)
1171 +{
1172 +#define DROP_MSG_SIZE 80
1173 +       char sbuf[DROP_MSG_SIZE];
1174 +       struct kern_log_entry drechdr;
1175 +
1176 +       snprintf(sbuf, DROP_MSG_SIZE,
1177 +               "%d event records dropped due to EVL buffer overflow.", 
1178 +               ebuf.bf_dropped);
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);
1183 +}
1184 +
1185 +/**
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.
1189 + *
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.
1197 + *
1198 + * @hdr: The header of the record caller intends to log.
1199 + */
1200 +static int
1201 +evl_check_buf(const struct kern_log_entry *hdr)
1202 +{
1203 +       char *head, *tail;
1204 +       size_t water_mark, avail, recsize;
1205 +
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)) :
1211 +                 (head - tail);
1212 +
1213 +       if (ebuf.bf_dropped != 0) {
1214 +               /*
1215 +                * Still recovering from buffer overflow.
1216 +                * Apply the low water mark.
1217 +                */
1218 +               water_mark = min(EVL_BUF_DRAINAGE, ebuf.bf_len / 2);
1219 +               /*
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"
1223 +                * message.
1224 +                */
1225 +               water_mark = max(water_mark,
1226 +                       recsize + REC_HDR_SIZE + DROP_MSG_SIZE);
1227 +       } else {
1228 +               /* +1 because bf_tail must never catch up with bf_head. */
1229 +               water_mark = recsize + 1;
1230 +       }
1231 +
1232 +       if (avail < water_mark) {
1233 +               return -1;
1234 +       }
1235 +
1236 +       /* There's enough free buffer space.  Return success. */
1237 +       if (ebuf.bf_dropped != 0) {
1238 +               log_dropped_recs_event();
1239 +       }
1240 +       return 0;
1241 +}
1242 +
1243 +/**
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.
1247 + *
1248 + * @retbuf: pointer to the buffer to be filled with the event records
1249 + * @bufsize: length, in bytes, of retbuf
1250 + */
1251 +int
1252 +evl_kbufread(char *retbuf, size_t bufsize)
1253 +{
1254 +       char *rec;
1255 +       size_t rec_size;
1256 +       int error = 0;
1257 +       int retbuflen = 0;
1258 +       char *tail, *buf = retbuf;
1259 +
1260 +       if (bufsize < REC_HDR_SIZE) {
1261 +               return -EINVAL;
1262 +       }
1263 +
1264 +       if (ebuf.bf_head == ebuf.bf_tail && ebuf.bf_dropped != 0) {
1265 +               /*
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.
1271 +                */
1272 +               unsigned long iflags;
1273 +               spin_lock_irqsave(&ebuf_lock, iflags);
1274 +               log_dropped_recs_event();
1275 +               spin_unlock_irqrestore(&ebuf_lock, iflags);
1276 +       }
1277 +
1278 +       /* 
1279 +        * We expect that only the logging daemon will be running here,
1280 +        * but serialize access just in case.
1281 +        */
1282 +       error = down_interruptible(&evl_read_sem);
1283 +       if (error == -EINTR) {
1284 +               return -EINTR;
1285 +       }
1286 +       /* Go to sleep if the buffer is empty.  */
1287 +       error = wait_event_interruptible(readq, 
1288 +               (ebuf.bf_head != ebuf.bf_tail));
1289 +       if (error) {
1290 +               up(&evl_read_sem);
1291 +               return error;
1292 +       }
1293 +       /*
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).
1302 +        *
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.
1306 +        */
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. */
1311 +               error = -EFAULT;
1312 +               goto out;
1313 +       }
1314 +
1315 +       do {
1316 +               struct cbregion rg;
1317 +               __u16 vardata_size;     /* type must match rec.log_size */
1318 +
1319 +               if (bufsize < REC_HDR_SIZE) {
1320 +                       break;
1321 +               }
1322 +
1323 +               /*
1324 +                * Extract log_size from header, which could be split due to
1325 +                * wraparound, or misaligned.
1326 +                */
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;
1331 +
1332 +               if (bufsize < rec_size) {
1333 +                       /* 
1334 +                        * Copyout only the header 'cause user buffer can't
1335 +                        * hold full record.
1336 +                        */
1337 +                       set_region(&rg, rec, REC_HDR_SIZE);
1338 +                       error = copy_cbuf_to_user(&rg, buf);
1339 +                       if (error) {
1340 +                               error = -EFAULT;
1341 +                               break;
1342 +                       }
1343 +                       bufsize -= REC_HDR_SIZE;
1344 +                       retbuflen += REC_HDR_SIZE;
1345 +                       break;
1346 +               }
1347 +               set_region(&rg, rec, rec_size);
1348 +               error = copy_cbuf_to_user(&rg, buf);
1349 +               if (error) {
1350 +                       error = -EFAULT;
1351 +                       break;
1352 +               }
1353 +               rec = rg.rg_tail;
1354 +               buf += rec_size;
1355 +               bufsize -= rec_size;
1356 +               retbuflen += rec_size;
1357 +       } while (rec != tail);
1358 +
1359 +       if (error == 0) {
1360 +               ebuf.bf_head = rec;
1361 +               error = retbuflen;
1362 +       }
1363 +
1364 +out:
1365 +       up(&evl_read_sem);
1366 +       return(error);
1367 +}
1368 +
1369 +/**
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.
1373 + */
1374 +int
1375 +evl_writeh(struct kern_log_entry *hdr, const char *vardata)
1376 +{
1377 +       char *oldtail = ebuf.bf_tail;
1378 +       unsigned long iflags;   /* for spin_lock_irqsave() */
1379 +
1380 +       normalize_header(hdr, vardata);
1381 +       
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);
1386 +               return -ENOSPC;
1387 +       }
1388 +
1389 +       copy_rec_to_cbuf(hdr, vardata);
1390 +       /*
1391 +        * If the variable portion is a truncated string, make sure it
1392 +        * ends with a null character.
1393 +        */
1394 +       if ((hdr->log_flags & EVL_TRUNCATE) && hdr->log_format == EVL_STRING) {
1395 +               *(ebuf.bf_tail - 1) = '\0';
1396 +       }
1397 +
1398 +       if ((ebuf.bf_head == oldtail) &&
1399 +           (ebuf.bf_head != ebuf.bf_tail)) {
1400 +               wake_up_interruptible(&readq);
1401 +       }
1402 +       spin_unlock_irqrestore(&ebuf_lock, iflags);
1403 +       return 0;
1404 +}
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
1408 @@ -34,6 +34,16 @@
1409  
1410  #include <asm/uaccess.h>
1411  
1412 +#include <string.h>
1413 +#include <ctype.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
1418 +#else
1419 +#define PRINTKAT_BUFLEN 512
1420 +#endif
1421 +
1422  #define __LOG_BUF_LEN  (1 << CONFIG_LOG_BUF_SHIFT)
1423  
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;
1428  
1429 +#ifdef CONFIG_EVLOG
1430 +extern int evl_kbufread(char *, size_t);
1431 +#endif
1432 +
1433  /* Flag: console code may call schedule() */
1434  static int console_may_schedule;
1435  
1436 @@ -242,6 +256,7 @@
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
1441   */
1442  int do_syslog(int type, char __user * buf, int len)
1443  {
1444 @@ -366,6 +381,17 @@
1445         case 9:         /* Number of chars in the log buffer */
1446                 error = log_end - log_start;
1447                 break;
1448 +       case 20:
1449 +#ifdef CONFIG_EVLOG
1450 +               error = verify_area(VERIFY_WRITE, buf, len);
1451 +               if (error) {
1452 +                       goto out;
1453 +               }
1454 +               error = evl_kbufread(buf, len);
1455 +#else
1456 +               error = -EIO;
1457 +#endif
1458 +               break;
1459         case 10:        /* Size of the log buffer */
1460                 error = log_buf_len;
1461                 break;
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.
1465   */
1466 +int vprintk(const char *fmt, va_list args);
1467 +
1468  asmlinkage int printk(const char *fmt, ...)
1469  {
1470 +       int status;
1471         va_list args;
1472 +       va_start(args, fmt);
1473 +       status = vprintk(fmt, args);
1474 +       va_end(args);
1475 +       return status;
1476 +}
1477 +
1478 +int vprintk(const char *fmt, va_list args)
1479 +{
1480         unsigned long flags;
1481         int printed_len;
1482         char *p;
1483 @@ -527,9 +564,7 @@
1484         spin_lock_irqsave(&logbuf_lock, flags);
1485  
1486         /* Emit the output into the temporary buffer */
1487 -       va_start(args, fmt);
1488         printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
1489 -       va_end(args);
1490  
1491         /*
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);
1496  }
1497 +
1498 +static char printkat_buf[PRINTKAT_BUFLEN];
1499 +static spinlock_t printkat_lock = SPIN_LOCK_UNLOCKED;
1500 +
1501 +/*
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.
1505 + */
1506 +void evl_unbrace(char *dest, const char *src, int bufsz)
1507 +{
1508 +       const char *copy_this = src, *scan_this = src;
1509 +       const char *c, *lcb, *rcb, *cut_here;
1510 +       int copy_len, dlen = 0;
1511 +
1512 +       cut_here = strstr(src, "{{");
1513 +       dest[0] = '\0';
1514 +       for (;;) {
1515 +               lcb = strchr(scan_this, '{');
1516 +               if (!lcb) {
1517 +                       goto done;
1518 +               }
1519 +               rcb = strstr(lcb+2, "}%");
1520 +               if (!rcb) {
1521 +                       goto done;
1522 +               }
1523 +               if (cut_here && cut_here < rcb) {
1524 +                       goto done;
1525 +               }
1526 +               /* Is it a valid identifier between the { and } ? */
1527 +               c = lcb+1;
1528 +               if (*c != '_' && !isalpha(*c)) {
1529 +                       goto scan_again;
1530 +               }
1531 +               for (c++; c < rcb; c++) {
1532 +                       if (*c != '_' && !isalnum(*c)) {
1533 +                               goto scan_again;
1534 +                       }
1535 +               }
1536 +               copy_len = min(lcb - copy_this, bufsz-(dlen+1));
1537 +               strncat(dest + dlen, copy_this, copy_len);
1538 +               dlen += copy_len;
1539 +               copy_this = rcb+1;
1540 +scan_again:
1541 +               scan_this = rcb+2;
1542 +       }
1543 +done:
1544 +       if (cut_here) {
1545 +               copy_len = min(cut_here - copy_this, bufsz-(dlen+1));
1546 +       } else {
1547 +               copy_len = bufsz-(dlen+1);
1548 +       }
1549 +       strncat(dest + dlen, copy_this, copy_len);
1550 +       return;
1551 +}
1552 +
1553 +/**
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 "{{".
1561 + */
1562 +/*ARGSUSED*/
1563 +int __printkat(const char *facname, int call_printk,  const char *fmt, ...)
1564 +{
1565 +       int status;
1566 +       unsigned long flags;
1567 +       va_list args;
1568 +
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,
1573 +               args);
1574 +       if (call_printk) {
1575 +               (void) vprintk(printkat_buf, args);
1576 +       }
1577 +       spin_unlock_irqrestore(&printkat_lock, flags);
1578 +#else
1579 +       /* EVLOG disabled.  Just call printk, stripping {id}s as needed. */
1580 +       if (!call_printk) {
1581 +               return 0;
1582 +       }
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);
1588 +       } else {
1589 +               status = vprintk(fmt, args);
1590 +       }
1591 +#endif
1592 +       va_end(args);
1593 +
1594 +       return status;
1595 +}
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 @@
1602  
1603  subsys_initcall(net_dev_init);
1604  
1605 +static spinlock_t netdev_printk_lock = SPIN_LOCK_UNLOCKED;
1606 +/**
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
1615 + *
1616 + * Does the work for the netdev_printk macro.
1617 + * For a lot of network drivers, the probe function looks like
1618 + *     ...
1619 + *     netdev = alloc_netdev(...);     // or alloc_etherdev(...)
1620 + *     SET_NETDEV_DEV(netdev, dev);
1621 + *     ...
1622 + *     register_netdev(netdev);
1623 + *     ...
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".
1630 + *
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.
1635 + *
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..."
1639 + *
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
1643 + * identified.
1644 + *
1645 + * Returns:
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
1649 + *     0 on success
1650 + */
1651 +int __netdev_printk(const char *sevlevel, const struct net_device *netdev,
1652 +       int msglevel, const char *format, ...)
1653 +{
1654 +       int ret = 1;    /* not logged */
1655 +       if (!netdev || !format) {
1656 +               return -EINVAL;
1657 +       }
1658 +       if (msglevel == NETIF_MSG_ALL || (netdev->msg_enable & msglevel)) {
1659 +               static char msg[512];   /* protected by netdev_printk_lock */
1660 +               unsigned long flags;
1661 +               va_list args;
1662 +               struct device *dev = netdev->class_dev.dev;
1663 +               
1664 +               spin_lock_irqsave(&netdev_printk_lock, flags);
1665 +               va_start(args, format);
1666 +               vsnprintf(msg, 512, format, args);
1667 +               va_end(args);
1668 +
1669 +               if (!sevlevel) {
1670 +                       sevlevel = "";
1671 +               }
1672 +
1673 +               if (netdev->reg_state == NETREG_REGISTERED || !dev) {
1674 +                       printk("%s%s: %s", sevlevel, netdev->name, msg);
1675 +               } else {
1676 +                       printk("%s%s (%s %s): %s", sevlevel, netdev->name,
1677 +                               dev->driver->name, dev->bus_id, msg);
1678 +               }
1679 +               spin_unlock_irqrestore(&netdev_printk_lock, flags);
1680 +               ret = dev ? 0 : 2;
1681 +       }
1682 +       return ret;
1683 +}
1684 +
1685 +EXPORT_SYMBOL(__netdev_printk);
1686  EXPORT_SYMBOL(__dev_get);
1687  EXPORT_SYMBOL(__dev_get_by_flags);
1688  EXPORT_SYMBOL(__dev_get_by_index);
This page took 0.180523 seconds and 3 git commands to generate.