@@ -966,6 +966,11 @@ void __init setup_arch(char **cmdline_p)
initmem_init(0, max_pfn);
+ /*
+ * Allocate bigger log buffer as early as possible
+ */
+ setup_log_buf();
+
#ifdef CONFIG_ACPI_SLEEP
/*
* Reserve low memory region for sleep support.
@@ -17,6 +17,7 @@
#include <linux/typecheck.h>
#include <linux/ratelimit.h>
#include <linux/dynamic_debug.h>
+#include <linux/init.h>
#include <asm/byteorder.h>
#include <asm/bug.h>
@@ -281,6 +282,8 @@ static inline void log_buf_kexec_setup(v
}
#endif
+void __init setup_log_buf(void);
+
extern int printk_needs_cpu(int cpu);
extern void printk_tick(void);
@@ -589,6 +589,7 @@ asmlinkage void __init start_kernel(void
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
+ setup_log_buf();
pidhash_init();
vfs_caches_init_early();
sort_main_extable();
@@ -167,46 +167,65 @@ void log_buf_kexec_setup(void)
}
#endif
+static unsigned long __initdata new_log_buf_len;
static int __init log_buf_len_setup(char *str)
{
unsigned size = memparse(str, &str);
- unsigned long flags;
if (size)
size = roundup_pow_of_two(size);
- if (size > log_buf_len) {
- unsigned start, dest_idx, offset;
- char *new_log_buf;
-
- new_log_buf = alloc_bootmem(size);
- if (!new_log_buf) {
- printk(KERN_WARNING "log_buf_len: allocation failed\n");
- goto out;
- }
-
- spin_lock_irqsave(&logbuf_lock, flags);
- 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_irqrestore(&logbuf_lock, flags);
+ if (size > log_buf_len)
+ new_log_buf_len = size;
- printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);
- }
-out:
- return 1;
+ return 0;
}
+early_param("log_buf_len", log_buf_len_setup);
-__setup("log_buf_len=", log_buf_len_setup);
+void __init setup_log_buf(void)
+{
+ unsigned long flags;
+ unsigned start, dest_idx, offset;
+ char *new_log_buf;
+ char first_line[64], *first_nl;
+
+ if (!new_log_buf_len)
+ return;
+
+ new_log_buf = alloc_bootmem(new_log_buf_len);
+ memset(first_line, 0, sizeof(first_line));
+
+ spin_lock_irqsave(&logbuf_lock, flags);
+ log_buf_len = new_log_buf_len;
+ log_buf = new_log_buf;
+ new_log_buf_len = 0;
+
+ offset = start = min(con_start, log_start);
+ dest_idx = 0;
+ while (start != log_end) {
+ unsigned log_idx_mask = start & (__LOG_BUF_LEN - 1);
+
+ log_buf[dest_idx] = __log_buf[log_idx_mask];
+ if (dest_idx < sizeof(first_line) - 1)
+ first_line[dest_idx] = __log_buf[log_idx_mask];
+ start++;
+ dest_idx++;
+ }
+ log_start -= offset;
+ con_start -= offset;
+ log_end -= offset;
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ first_nl = strchr(first_line, '\n');
+ if (first_nl)
+ *first_nl = '\0';
+
+ pr_info("log_buf_len: %d, first line: %s\n",
+ log_buf_len, first_line);
+
+ pr_debug("bu: %d/%d (%d%%)\n",
+ dest_idx, __LOG_BUF_LEN - dest_idx,
+ (dest_idx * 100) / __LOG_BUF_LEN);
+}
#ifdef CONFIG_BOOT_PRINTK_DELAY