diff -up linux-2.6.26.noarch/arch/x86/kernel/i386_ksyms_32.c.orig linux-2.6.26.noarch/arch/x86/kernel/i386_ksyms_32.c --- linux-2.6.26.noarch/arch/x86/kernel/i386_ksyms_32.c.orig 2008-07-28 08:11:20.000000000 -0400 +++ linux-2.6.26.noarch/arch/x86/kernel/i386_ksyms_32.c 2008-07-28 08:13:02.000000000 -0400 @@ -1,4 +1,5 @@ #include +#include #include #include @@ -13,6 +14,8 @@ EXPORT_SYMBOL(mcount); /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_generic); +EXPORT_SYMBOL_GPL(klogger); + EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); diff -up linux-2.6.26.noarch/arch/x86/kernel/x8664_ksyms_64.c.orig linux-2.6.26.noarch/arch/x86/kernel/x8664_ksyms_64.c --- linux-2.6.26.noarch/arch/x86/kernel/x8664_ksyms_64.c.orig 2008-07-28 08:11:20.000000000 -0400 +++ linux-2.6.26.noarch/arch/x86/kernel/x8664_ksyms_64.c 2008-07-28 08:13:02.000000000 -0400 @@ -2,6 +2,7 @@ All C exports should go in the respective C files. */ #include +#include #include #include @@ -19,6 +20,8 @@ EXPORT_SYMBOL(mcount); EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL_GPL(klogger); + EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); diff -up /dev/null linux-2.6.26.noarch/include/linux/klogger.h --- /dev/null 2008-07-28 02:14:19.451006833 -0400 +++ linux-2.6.26.noarch/include/linux/klogger.h 2008-07-28 08:13:02.000000000 -0400 @@ -0,0 +1,75 @@ +#ifndef _KLOGGER_H +#define _KLOGGER_H + +#ifdef MODULE +#define KLOGGER_SIZE (PAGE_SIZE * 10240) /* 1024 pages */ +#else +#define KLOGGER_SIZE (PAGE_SIZE * 256) /* 256 pages */ +#endif +#define KLOGGER_STOP 0x0 +#define KLOGGER_START 0x1 +#define KLOGGER_RESTART 0x2 + +#define KLOGGER_ON 0x1 +#define KLOGGER_OFF 0x0 + +/* + * klog format types + */ +#define KLOGGER_UNFMT 0x0 /* no format */ +#define KLOGGER_TSTAMPS 0x1 /* time stamps on every line*/ +#define KLOGGER_ISTAMPS 0x2 /* time stamp intervals */ + +enum { + CTL_KLOGGER_CMD=1, + CTL_KLOGGER_STATE, + CTL_KLOGGER_SZ, + CTL_KLOGGER_FMT, + CTL_KLOGGER_CONS, + CTL_KLOGGER_BYTES +}; + +#ifdef __KERNEL__ +extern void klogger(char *, ...); +extern void vklogger(char *fmt, va_list vp); +extern void klogger_unfmt(char *, ...); +extern void klogger_timestamp(char *, ...); +extern void klogger_intervals(char *, ...); + +extern int klogger_pause(void); +extern void klogger_restart(void); + +#if 0 +inline static int +klogger_pause() +{ + int laststate; + + spin_lock_irq(&klogger_lock); + laststate = klogger_state; + klogger_state = KLOGGER_OFF; + spin_unlock_irq(&klogger_lock); + + return laststate; +} +static inline void +klogger_restart() +{ + spin_lock_irq(&klogger_lock); + klogger_state = KLOGGER_ON; + spin_unlock_irq(&klogger_lock); +} +#endif + +#if 0 +#ifdef MODULE +#ifdef dfprintk +#undef dfprintk +#endif +#define dfprintk(fac, args...) \ + do { ifdebug(fac) klogger_timestamp(args); } while(0) +#endif +#endif +#endif + +#endif /* _KLOGGER_H */ diff -up linux-2.6.26.noarch/include/linux/sysctl.h.orig linux-2.6.26.noarch/include/linux/sysctl.h --- linux-2.6.26.noarch/include/linux/sysctl.h.orig 2008-07-28 08:11:28.000000000 -0400 +++ linux-2.6.26.noarch/include/linux/sysctl.h 2008-07-28 08:13:02.000000000 -0400 @@ -72,6 +72,7 @@ enum CTL_ARLAN=254, /* arlan wireless driver */ CTL_S390DBF=5677, /* s390 debug */ CTL_SUNRPC=7249, /* sunrpc debug */ + CTL_KLOGGER=7300, /* klogger debug */ CTL_PM=9899, /* frv power management */ CTL_FRV=9898, /* frv specific sysctls */ }; diff -up /dev/null linux-2.6.26.noarch/kernel/kernel_logger.c --- /dev/null 2008-07-28 02:14:19.451006833 -0400 +++ linux-2.6.26.noarch/kernel/kernel_logger.c 2008-07-28 08:14:26.000000000 -0400 @@ -0,0 +1,787 @@ +/* + * klogger is an in-kernel logging facility. The features are: + * + * * klogger will have very little effect on timing of + * execution (unlike printks). + * + * * Entries can be retrieved from either a live system or cores dumps. + * + * * There are three ways to set time stamps on a log entry: + * - None. + * - Time stamp every entry + * - Time stamp every event. Meaning if numerous entries + * occurs during the same time interval, only the first + * entry will have the time stamp. + * + * * The log has the following controls: + * start - allows entries to be entered in to the log and if needed + * allocates the memory used by the log. + * stop - stop entries from being added to the log. + * restart - stop and restarts the logging. + * + * * The user command, klogger, can be used to + * - Retrieve entries. + * - Set time stamps + * - Control log. + * - Set the size of the log. + */ + +#include +#ifdef MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef MODULE +#include "klogger.h" +#else +#include +#endif + +//#define KLOGGER_ON 0x1 +//#define KLOGGER_OFF 0x0 +static unsigned int klogger_state = 0; + +#if 0 +static char *klogger_bufsize = NULL; +#endif +static char *klogger_bufend = NULL; +static unsigned long klogger_end, klogger_curr; +static int klogger_console = 0; +static int klogger_format=KLOGGER_TSTAMPS; +static unsigned long klogger_size = PAGE_ALIGN(KLOGGER_SIZE); +// +//static char *klogger_buf = NULL; +static char klogger_buf[PAGE_ALIGN(KLOGGER_SIZE)]; +static unsigned long klogger_bytes; + +static spinlock_t klogger_lock; + +#define KLOGGER_MAXLOG_ENTRY 128 /* max size of an log entry */ +#define KBYTES(x) ((x) * (1024)) +#define MEGABYTES(x) ((x) * (1048576)) +#define GIGABYTES(x) ((x) * (1073741824)) + +static inline int klogger_alloc(void); +static inline int klogger_start(void); +#if 0 +static inline int klogger_pause(void); +static inline void klogger_restart(void); +#endif +int klogger_procfs_open(void); +void klogger_procfs_close(void); +static inline void klogger_destroy(void); + +static char * +klogger_num2str(unsigned long bytes, char *outbuf) +{ + static char myoutbuf[64]; + unsigned long num; + unsigned long pcnt; + + if (outbuf == NULL) + outbuf = myoutbuf; + + if ((num = (bytes/GIGABYTES(1)))) { + if (bytes % GIGABYTES(1)) { + pcnt = bytes/1073741824; + sprintf(outbuf, "%luG", pcnt); + } else { + sprintf(outbuf, "%luG", num); + } + } else if ((num = (bytes/MEGABYTES(1)))) { + if (bytes % MEGABYTES(1)) { + pcnt = bytes/1048576; + //sprintf(outbuf, "%.2fM", pcnt); + sprintf(outbuf, "~%luM", num); + } else { + sprintf(outbuf, "%luM", num); + } + } else { + if (bytes % KBYTES(1)) { + //pcnt = bytes/1024; + sprintf(outbuf, "%luK", (bytes/1024)); + } else { + sprintf(outbuf, "%luK", (bytes/KBYTES(1))); + } + } + return(outbuf); +} + + +/* + * Put a number (base <= 16) in a buffer in reverse order; return an + * optional length and a pointer to the NULL terminated (preceded?) + * buffer. + */ +static const char hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +#define hex2ascii(hex) (hex2ascii_data[hex]) +static __inline void +ksprintn( + register u_long ul, + register int len, + register int base, + register char *p) +{ /* A long in base 8, plus NULL. */ + + do { + p[len - 1] = hex2ascii(ul % base); + ul /= base ; + } while (--len); +} + +static void +kernel_log(int type, char *fmt, va_list vp) +{ + struct timeval tv; + static int lastmsec = 0 ; + static int lastsec = 0 ; + int secs ; + int msecs ; + int bytes=0; + unsigned long resid, bufend; + char *p ; + + //if (klogger_buf == NULL || (klogger_state & KLOGGER_ON) == 0) + if ((klogger_state & KLOGGER_ON) == 0) + return; + + spin_lock_irq(&klogger_lock); + if ((klogger_state & KLOGGER_ON) == 0) { + spin_unlock_irq(&klogger_lock); + return; + } + + //resid = (klogger_size - klogger_curr) -1; + resid = (klogger_size - klogger_curr); + if (resid <= KLOGGER_MAXLOG_ENTRY) { + klogger_end = klogger_curr; + klogger_curr = 0; + } + p = &klogger_buf[klogger_curr]; + + if (klogger_format && (type & (KLOGGER_ISTAMPS|KLOGGER_TSTAMPS))) { + tv.tv_sec = tv.tv_usec = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18) + get_fast_time(&tv); +#else + do_gettimeofday(&tv); +#endif + + secs = tv.tv_sec % 1000 ; + msecs = tv.tv_usec / 1000 ; + if (klogger_format == KLOGGER_TSTAMPS) { + if (fmt[1] != '\0' && (fmt[0] != '\n' || fmt[0] != ' ')) + ksprintn(secs, 3, 10, p) ; + p[3] = '.' ; + ksprintn(msecs, 3, 10, p + 4) ; + p[7] = ' '; + bytes = 8 ; + } else if (secs != lastsec || msecs != lastmsec) { + ksprintn(secs, 3, 10, p) ; + p[3] = '.' ; + ksprintn(msecs, 3, 10, p + 4) ; + p[7] = '\t' ; + lastsec = secs ; + lastmsec = msecs ; + bytes = 8 ; + } else { + p[0] = '\t'; + bytes++; + } + } +#ifdef CONFIG_SMP +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + bytes += sprintf((p + bytes), "%d:%d:", task_cpu(current), current->pid); +#else + bytes += sprintf((p + bytes), "%d:%d:", current->cpu, current->pid); +#endif +#else + bytes += sprintf((p + bytes), "%d:", current->pid); +#endif + bufend = (klogger_bufend - (p + bytes)) - 1; + if (bufend >= (unsigned long)klogger_bufend) + bufend = (unsigned long)klogger_bufend; + bytes += vsnprintf(p + bytes, bufend, fmt, vp); + if (klogger_console) + printk("%s", p); + klogger_curr += bytes; + klogger_bytes += bytes; + + if (klogger_end < klogger_curr) + klogger_end = klogger_curr; + + spin_unlock_irq(&klogger_lock); +} +void +klogger(char *fmt, ...) +{ + va_list vp; + + va_start(vp, fmt); + kernel_log(klogger_format, fmt, vp); + va_end(vp); +} + +void +vklogger(char *fmt, va_list vp) +{ + kernel_log(klogger_format, fmt, vp); +} +void +klogger_unfmt(char *fmt, ...) +{ + va_list vp; + + va_start(vp, fmt); + kernel_log(KLOGGER_UNFMT, fmt, vp); + va_end(vp); +} +void +klogger_timestamp(char *fmt, ...) +{ + va_list vp; + + va_start(vp, fmt); + kernel_log(KLOGGER_TSTAMPS, fmt, vp); + va_end(vp); +} +void +klogger_intervals(char *fmt, ...) +{ + va_list vp; + + va_start(vp, fmt); + kernel_log(KLOGGER_ISTAMPS, fmt, vp); + va_end(vp); +} + +#if 0 +static int +klogger_alloc() +{ + char *tmp; + spin_lock(&klogger_lock); + + if (klogger_buf) { + spin_unlock(&klogger_lock); + return(EEXIST); + } + if (klogger_size <= 0) { + spin_unlock(&klogger_lock); + return(EINVAL); + } + + /* + * Don't go to sleep holding a spinlock + */ + spin_unlock(&klogger_lock); + tmp = kmalloc(klogger_size, GFP_KERNEL); + if (tmp == NULL) { + printk("klogger_alloc: Unable to allocate %ld bytes of memory\n", + klogger_size); + return(ENOMEM); + } + /* + * Make sure someone else didn't allocate + * the memory while we were away + */ + spin_lock(&klogger_lock); + if (klogger_buf == NULL) { + klogger_buf = tmp; + tmp = NULL; + klogger_end = klogger_curr = 0; + klogger_bufend = (klogger_buf + klogger_size); + klogger_state = KLOGGER_START; + } + + /* + * If tmp != NULL we lost the race + */ + if (tmp != NULL) + kfree(tmp); + return(0); +} +#endif +#define KLOGGER_CMDBUF_SZ 65 +static char klogger_cmdbuf[KLOGGER_CMDBUF_SZ]; + +static inline void +klogger_setstate(int state) +{ + spin_lock_irq(&klogger_lock); + klogger_state = state; + spin_unlock_irq(&klogger_lock); + return; +} + + +static inline int +klogger_alloc(void) +{ + spin_lock_irq(&klogger_lock); + klogger_end = klogger_curr = 0; + klogger_bufend = (klogger_buf + klogger_size); + klogger_state = KLOGGER_START; + spin_unlock_irq(&klogger_lock); + + return(0); +} + + +static inline int +klogger_start(void) +{ + int cc; + + strcpy(klogger_cmdbuf, "start"); + cc = klogger_alloc(); + klogger_bytes = 0; + return cc; +} +int +klogger_pause(void) +{ + int laststate; + + spin_lock_irq(&klogger_lock); + laststate = klogger_state; + klogger_state = KLOGGER_OFF; + spin_unlock_irq(&klogger_lock); + + return laststate; +} +void +klogger_restart(void) +{ + spin_lock_irq(&klogger_lock); + klogger_state = KLOGGER_ON; + spin_unlock_irq(&klogger_lock); +} + + +static inline void +klogger_destroy(void) +{ +#if 0 + spin_lock_irq(&klogger_lock); + if (klogger_buf) { + kfree(klogger_buf); + klogger_buf = NULL; + } + spin_unlock_irq(&klogger_lock); +#endif +} + +static int +klogger_strategy(struct ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen) +{ + return 1; +} +static int +klogger_sysctl( + ctl_table *ctl, + int write, + struct file *filp, + void __user *buffer, + size_t *lenp, + loff_t *ppos) +{ + int cc = 0; + int read = (write == 0); + static char tmp[64]; + void *ptr; + + switch(ctl->ctl_name) { + case CTL_KLOGGER_CMD: + cc = proc_dostring(ctl, write, filp, buffer, lenp, ppos); + if (write) { + ptr = ctl->data; + if (strncmp(ptr, "start", strlen("start")) == 0){ + klogger_start(); + } else if (strncmp(ptr, "stop", strlen("stop")) == 0){ + klogger_destroy(); + } else if (strncmp(ptr, "pause", strlen("pause")) == 0){ + klogger_pause(); + } else if (strncmp(ptr, "restart", strlen("restart")) == 0){ + klogger_restart(); + } else if (strncmp(ptr, "off", strlen("off")) == 0){ + klogger_destroy(); + } + } + break; + case CTL_KLOGGER_STATE: + if (read) { + int *saveptr, savemaxlen; + + switch(klogger_state) { + case KLOGGER_ON: + strcpy(tmp, "On"); + break; + case KLOGGER_OFF: + strcpy(tmp, "Off"); + break; + default: + sprintf(tmp, "Bad State: 0x%x", klogger_state); + break; + } + + saveptr = ctl->data; + savemaxlen = ctl->maxlen; + ctl->data = (int *)tmp; + ctl->maxlen = strlen((char *)ctl->data); + + cc = proc_dostring(ctl, write, filp, buffer, lenp, ppos); + + ctl->data = saveptr; + ctl->maxlen = savemaxlen; + + break; + } + break; + case CTL_KLOGGER_SZ: + case CTL_KLOGGER_BYTES: + case CTL_KLOGGER_FMT: + if (read) { + int *saveptr, savemaxlen; + + if (ctl->ctl_name == CTL_KLOGGER_SZ) { + sprintf(tmp, "%ld (%s or %ld pages)", + klogger_size, klogger_num2str(klogger_size, NULL), + (klogger_size/PAGE_SIZE)); + } else if (ctl->ctl_name == CTL_KLOGGER_BYTES) { + sprintf(tmp, "%ld (%s)", + klogger_size, klogger_num2str(klogger_size, NULL)); + } else { /* KLOGGER_FMT */ + switch(klogger_format) { + case KLOGGER_UNFMT: + strcpy(tmp, "Unformated"); + break; + case KLOGGER_TSTAMPS: + strcpy(tmp, "TimeStamped"); + break; + case KLOGGER_ISTAMPS: + strcpy(tmp, "Intervals"); + break; + default: + sprintf(tmp, "Invalid Format: %d", klogger_format); + } + } + saveptr = ctl->data; + savemaxlen = ctl->maxlen; + ctl->data = (int *)tmp; + ctl->maxlen = strlen((char *)ctl->data); + + cc = proc_dostring(ctl, write, filp, buffer, lenp, ppos); + + ctl->data = saveptr; + ctl->maxlen = savemaxlen; + break; + } + cc = proc_dointvec(ctl, write, filp, buffer, lenp, ppos); + break; + } + + return cc; +} + +static struct ctl_table_header *sysctl_table; +static ctl_table klogger_tab[] = { +{ + .ctl_name = CTL_KLOGGER_CMD, + .procname = "cmd", + .data = klogger_cmdbuf, + .maxlen = KLOGGER_CMDBUF_SZ, + .mode = 0666, + .proc_handler = &klogger_sysctl, + .strategy = &klogger_strategy +}, +{ + .ctl_name = CTL_KLOGGER_STATE, + .procname = "state", + .data = &klogger_state, + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &klogger_sysctl, + .strategy = &klogger_strategy +}, +{ + .ctl_name = CTL_KLOGGER_SZ, + .procname = "size", + .data = &klogger_size, + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &klogger_sysctl, + .strategy = &klogger_strategy +}, +{ + .ctl_name = CTL_KLOGGER_FMT, + .procname = "format", + .data = &klogger_format, + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &klogger_sysctl, + .strategy = &klogger_strategy +}, +{ + .ctl_name = CTL_KLOGGER_CONS, + .procname = "toconsole", + .data = &klogger_console, + .maxlen = sizeof(int), + .mode = 0666, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec +}, +{ + .ctl_name = CTL_KLOGGER_BYTES, + .procname = "totalbytes", + .data = &klogger_bytes, + .maxlen = sizeof(unsigned long), + .mode = 0666, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec +}, + { .ctl_name = 0 } +}; +static ctl_table klogger_table[] = { +{ + .ctl_name = CTL_KLOGGER, + .procname= "klogger", + .mode = 0555, + .child = klogger_tab +}, + {.ctl_name = 0} +}; + +#if 0 +static void +klogger_setbufsize(char *arg) +{ + char *ch; + unsigned long factor = 0L; + unsigned long num; + + ch = &arg[strlen(arg)-1]; + switch(*ch) { + case 'k': + case 'K': + factor = KBYTES(1); + *ch = '\0'; + break; + case 'm': + case 'M': + factor = MEGABYTES(1); + *ch = '\0'; + break; + case 'g': + case 'G': + factor = GIGABYTES(1); + *ch = '\0'; + break; + } + num = simple_strtol(arg, (char **)NULL, 0); + if (num > 0) { + if (factor) + num *= factor; + klogger_size = PAGE_ALIGN(num); + printk("Setting klogger_size to %ld (%s)\n", + klogger_size, klogger_num2str(klogger_size, NULL)); + } + return; +} +#endif +static int +klogger_procfs_read( + char *page, + char **start, + off_t offset, + int count, + int *eof, + void *data) +{ + static unsigned long firstpart, secondpart, lastbytes; + static int laststate; + int cc =0; + + if (offset == 0) { + laststate = klogger_pause(); + + secondpart = lastbytes = 0; + firstpart = klogger_end - klogger_curr; + if (firstpart) { + *start = klogger_buf + klogger_curr; + cc = min(count, (int)firstpart); + firstpart -= cc; + } + if (klogger_curr > 0) { + secondpart = &klogger_buf[klogger_curr] - &klogger_buf[0]; + if (firstpart == 0) { + *start = klogger_buf; + cc = min(count, (int)secondpart); + secondpart -= cc; + lastbytes = cc; + } + } + if (cc == 0) + klogger_setstate(laststate); + return cc; + } + if (firstpart) { + *start = klogger_buf + (klogger_curr+offset); + firstpart = &klogger_buf[klogger_end] - *start; + cc = min(count, (int)firstpart); + firstpart -= cc; + } else if (secondpart) { + *start = klogger_buf + lastbytes; + secondpart = &klogger_buf[klogger_curr] - *start; + cc = min(count, (int)secondpart); + secondpart -= cc; + lastbytes += cc; + } else { + *eof = 1; + klogger_setstate(laststate); + } + + return cc; +} +static ssize_t +klogger_file_read( + struct file *file, + char __user *buf, + size_t nbytes, + loff_t *ppos) +{ + int eof = 0; + char *start = NULL; + ssize_t retval=0, n; + + while ((nbytes > 0) && !eof) { + n = klogger_procfs_read(NULL, &start, *ppos, nbytes, &eof, NULL); + if (n == 0) + break; /* End of file */ + if (n < 0) { + if (retval == 0) + retval = n; + break; + } + n -= copy_to_user(buf, start, n); + if (n == 0) { + if (retval == 0) + retval = -EFAULT; + break; + } + *ppos += n; + nbytes -= n; + buf += n; + retval += n; + } + return retval; +} +static struct file_operations klogger_fops; +int +klogger_procfs_open(void) +{ + struct proc_dir_entry *klogger_fp; + + klogger_fp = create_proc_entry("klogger", 0444, NULL); + if (klogger_fp == NULL) { + printk("Unable to create /proc/klogger\n"); + return 1; + } + klogger_fp->read_proc = klogger_procfs_read; + /* + * So we can read more that PROC_BLOCK_SIZE + * we need to replace the proc_file_read() + * routine with our own. + */ + memcpy(&klogger_fops, klogger_fp->proc_fops, sizeof(klogger_fops)); + klogger_fops.read = klogger_file_read; + klogger_fp->proc_fops = &klogger_fops; + + return 0; +} +void +klogger_procfs_close(void) +{ + remove_proc_entry("klogger", NULL); + + return; +} +static int __init +klogger_init(void) +{ + int cc; + + spin_lock_init(&klogger_lock); + + sysctl_table = register_sysctl_table(klogger_table); + if (sysctl_table == NULL) { + printk("klogger: Unable to register sysctl entries\n"); + return(1); + } + + if (klogger_procfs_open()) { + unregister_sysctl_table(sysctl_table); + sysctl_table = NULL; + return(1); + } + + if ((cc = klogger_start())) { + printk("klogger: Unable to start : errno %d\n", cc); + klogger_procfs_close(); + unregister_sysctl_table(sysctl_table); + sysctl_table = NULL; + return(cc); + } + + return 0; +} + +postcore_initcall(klogger_init); + +#ifdef MODULE +MODULE_LICENSE ("GPL"); +MODULE_DESCRIPTION ("In-kernel logging facility"); +#if 0 +MODULE_PARM_DESC(klogger_bufsize, "Buffer size [0x]Number"); +MODULE_PARM(klogger_bufsize, "s"); +#endif +int +init_module() +{ + return klogger_init(); +} +void +cleanup_module() +{ + klogger_destroy(); + + if (sysctl_table) { + unregister_sysctl_table(sysctl_table); + sysctl_table = NULL; + } + klogger_procfs_close(); + + return; +} + +EXPORT_SYMBOL_GPL(klogger); +EXPORT_SYMBOL_GPL(klogger_unfmt); +EXPORT_SYMBOL_GPL(klogger_timestamp); +EXPORT_SYMBOL_GPL(klogger_intervals); +EXPORT_SYMBOL_GPL(klogger_pause); +EXPORT_SYMBOL_GPL(klogger_restart); + +#endif /* MODULE */ + diff -up linux-2.6.26.noarch/kernel/Makefile.orig linux-2.6.26.noarch/kernel/Makefile --- linux-2.6.26.noarch/kernel/Makefile.orig 2008-07-28 08:11:31.000000000 -0400 +++ linux-2.6.26.noarch/kernel/Makefile 2008-07-28 08:13:02.000000000 -0400 @@ -5,7 +5,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ cpu.o exit.o itimer.o time.o softirq.o resource.o \ sysctl.o capability.o ptrace.o timer.o user.o \ - signal.o sys.o kmod.o workqueue.o pid.o \ + signal.o sys.o kmod.o workqueue.o pid.o kernel_logger.o \ rcupdate.o extable.o params.o posix-timers.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ diff -up linux-2.6.26.noarch/kernel/sysctl_check.c.orig linux-2.6.26.noarch/kernel/sysctl_check.c --- linux-2.6.26.noarch/kernel/sysctl_check.c.orig 2008-07-28 08:11:28.000000000 -0400 +++ linux-2.6.26.noarch/kernel/sysctl_check.c 2008-07-28 08:13:02.000000000 -0400 @@ -2,6 +2,7 @@ #include #include "../fs/xfs/linux-2.6/xfs_sysctl.h" #include +#include #include #include @@ -1203,6 +1204,16 @@ static const struct trans_ctl_table tran {} }; +static struct trans_ctl_table trans_klogger_table[] = { + { CTL_KLOGGER_CMD, "cmd" }, + { CTL_KLOGGER_STATE, "state" }, + { CTL_KLOGGER_SZ, "size" }, + { CTL_KLOGGER_FMT, "format" }, + { CTL_KLOGGER_CONS, "toconsole" }, + { CTL_KLOGGER_BYTES, "totalbytes" }, + {} +}; + static const struct trans_ctl_table trans_pm_table[] = { { 1 /* CTL_PM_SUSPEND */, "suspend" }, { 2 /* CTL_PM_CMODE */, "cmode" }, @@ -1231,6 +1242,7 @@ static const struct trans_ctl_table tran { CTL_ARLAN, "arlan", trans_arlan_table }, { CTL_S390DBF, "s390dbf", trans_s390dbf_table }, { CTL_SUNRPC, "sunrpc", trans_sunrpc_table }, + { CTL_KLOGGER, "klogger", trans_klogger_table }, { CTL_PM, "pm", trans_pm_table }, { CTL_FRV, "frv", trans_frv_table }, {}