Commit 96fcef0a authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] boot-time selectable log buffer size

From: Andrea Arcangeli <andrea@suse.de>

Allow the printk log buffer size to be selected with a __setup parameter,
`log_buf_len=N', where N must be a power-of-two.

The default, initial statically allocated buffer size is still determined via
kernel config.
parent cedc5632
...@@ -460,6 +460,10 @@ running once the system is up. ...@@ -460,6 +460,10 @@ running once the system is up.
logibm_irq= [HW,MOUSE] Logitech Bus Mouse Driver logibm_irq= [HW,MOUSE] Logitech Bus Mouse Driver
Format: <irq> Format: <irq>
log_buf_len=n Sets the size of the printk ring buffer, in bytes.
Format is n, nk, nM. n must be a power of two. The
default is set in kernel config.
lp=0 [LP] Specify parallel ports to use, e.g, lp=0 [LP] Specify parallel ports to use, e.g,
lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses lp=port[,port...] lp=none,parport0 (lp0 not configured, lp1 uses
lp=reset first parallel port). 'lp=0' disables the lp=reset first parallel port). 'lp=0' disables the
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/security.h> #include <linux/security.h>
#include <linux/bootmem.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
#define LOG_BUF_MASK (LOG_BUF_LEN-1)
/* printk's without a loglevel use this.. */ /* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
...@@ -68,11 +68,15 @@ struct console *console_drivers; ...@@ -68,11 +68,15 @@ struct console *console_drivers;
*/ */
static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED; static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
static char log_buf[LOG_BUF_LEN]; static char __log_buf[__LOG_BUF_LEN];
static char *log_buf = __log_buf;
static int log_buf_len = __LOG_BUF_LEN;
#define LOG_BUF_MASK (log_buf_len-1)
#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
/* /*
* The indices into log_buf are not constrained to LOG_BUF_LEN - they * The indices into log_buf are not constrained to log_buf_len - they
* must be masked before subscripting * must be masked before subscripting
*/ */
static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */ static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
...@@ -141,6 +145,45 @@ static int __init console_setup(char *str) ...@@ -141,6 +145,45 @@ static int __init console_setup(char *str)
__setup("console=", console_setup); __setup("console=", console_setup);
static int __init log_buf_len_setup(char *str)
{
unsigned long size = memparse(str, &str);
if (size > log_buf_len) {
unsigned long start, dest_idx, offset;
char * new_log_buf;
new_log_buf = alloc_bootmem(size);
if (!new_log_buf) {
printk("log_buf_len: allocation failed\n");
goto out;
}
spin_lock_irq(&logbuf_lock);
log_buf_len = size;
log_buf = new_log_buf;
offset = start = min(con_start, log_start);
dest_idx = 0;
while (start != log_end) {
log_buf[dest_idx] = __log_buf[start & (__LOG_BUF_LEN - 1)];
start++;
dest_idx++;
}
log_start -= offset;
con_start -= offset;
log_end -= offset;
spin_unlock_irq(&logbuf_lock);
printk("log_buf_len: %d\n", log_buf_len);
}
out:
return 1;
}
__setup("log_buf_len=", log_buf_len_setup);
/* /*
* Commands to do_syslog: * Commands to do_syslog:
* *
...@@ -213,8 +256,8 @@ int do_syslog(int type, char __user * buf, int len) ...@@ -213,8 +256,8 @@ int do_syslog(int type, char __user * buf, int len)
if (error) if (error)
goto out; goto out;
count = len; count = len;
if (count > LOG_BUF_LEN) if (count > log_buf_len)
count = LOG_BUF_LEN; count = log_buf_len;
spin_lock_irq(&logbuf_lock); spin_lock_irq(&logbuf_lock);
if (count > logged_chars) if (count > logged_chars)
count = logged_chars; count = logged_chars;
...@@ -229,7 +272,7 @@ int do_syslog(int type, char __user * buf, int len) ...@@ -229,7 +272,7 @@ int do_syslog(int type, char __user * buf, int len)
*/ */
for(i = 0; i < count && !error; i++) { for(i = 0; i < count && !error; i++) {
j = limit-1-i; j = limit-1-i;
if (j+LOG_BUF_LEN < log_end) if (j + log_buf_len < log_end)
break; break;
c = LOG_BUF(j); c = LOG_BUF(j);
spin_unlock_irq(&logbuf_lock); spin_unlock_irq(&logbuf_lock);
...@@ -302,12 +345,15 @@ static void __call_console_drivers(unsigned long start, unsigned long end) ...@@ -302,12 +345,15 @@ static void __call_console_drivers(unsigned long start, unsigned long end)
/* /*
* Write out chars from start to end - 1 inclusive * Write out chars from start to end - 1 inclusive
*/ */
static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level) static void _call_console_drivers(unsigned long start,
unsigned long end, int msg_log_level)
{ {
if (msg_log_level < console_loglevel && console_drivers && start != end) { if (msg_log_level < console_loglevel &&
console_drivers && start != end) {
if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) { if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
/* wrapped write */ /* wrapped write */
__call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN); __call_console_drivers(start & LOG_BUF_MASK,
log_buf_len);
__call_console_drivers(0, end & LOG_BUF_MASK); __call_console_drivers(0, end & LOG_BUF_MASK);
} else { } else {
__call_console_drivers(start, end); __call_console_drivers(start, end);
...@@ -370,11 +416,11 @@ static void emit_log_char(char c) ...@@ -370,11 +416,11 @@ static void emit_log_char(char c)
{ {
LOG_BUF(log_end) = c; LOG_BUF(log_end) = c;
log_end++; log_end++;
if (log_end - log_start > LOG_BUF_LEN) if (log_end - log_start > log_buf_len)
log_start = log_end - LOG_BUF_LEN; log_start = log_end - log_buf_len;
if (log_end - con_start > LOG_BUF_LEN) if (log_end - con_start > log_buf_len)
con_start = log_end - LOG_BUF_LEN; con_start = log_end - log_buf_len;
if (logged_chars < LOG_BUF_LEN) if (logged_chars < log_buf_len)
logged_chars++; logged_chars++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment