Thread (13 messages) 13 messages, 3 authors, 2011-02-18

Re: [PATCH 5/5] printk: Allocate kernel log buffer earlier

From: Yinghai Lu <yinghai@kernel.org>
Date: 2011-02-17 23:21:41
Also in: lkml

On Thu, Feb 17, 2011 at 10:51 AM, Mike Travis [off-list ref] wrote:
quoted hunk ↗ jump to hunk
On larger systems, because of the numerous ACPI, Bootmem and EFI
messages, the static log buffer overflows before the larger one
specified by the log_buf_len param is allocated.  Minimize the
overflow by allocating the new log buffer as soon as possible.

All arch's are covered by the "setup_log_buf" in start_kernel().
The x86 arch allocates it right after bootmem is created.

v1: Added pertinent __init & __initdata specifiers.
v2: updated to apply to x86-tip

Signed-off-by: Mike Travis <redacted>
Reviewed-by: Jack Steiner <redacted>
Reviewed-by: Robin Holt <redacted>
---
 arch/x86/kernel/setup.c |    5 ++
 include/linux/printk.h  |    4 ++
 init/main.c             |    1
 kernel/printk.c         |   81 +++++++++++++++++++++++++++++-------------------
 4 files changed, 60 insertions(+), 31 deletions(-)
--- linux.orig/arch/x86/kernel/setup.c
+++ linux/arch/x86/kernel/setup.c
@@ -1007,6 +1007,11 @@ void __init setup_arch(char **cmdline_p)
       memblock_find_dma_reserve();
       dma32_reserve_bootmem();

+       /*
+        * Allocate bigger log buffer as early as possible
+        */
+       setup_log_buf();
+
 #ifdef CONFIG_KVM_CLOCK
       kvmclock_init();
 #endif
--- linux.orig/include/linux/printk.h
+++ linux/include/linux/printk.h
@@ -1,6 +1,8 @@
 #ifndef __KERNEL_PRINTK__
 #define __KERNEL_PRINTK__

+#include <linux/init.h>
+
 extern const char linux_banner[];
 extern const char linux_proc_banner[];
@@ -89,6 +91,8 @@ int no_printk(const char *fmt, ...)
 extern asmlinkage __attribute__ ((format (printf, 1, 2)))
 void early_printk(const char *fmt, ...);

+void __init setup_log_buf(void);
+
 extern int printk_needs_cpu(int cpu);
 extern void printk_tick(void);
--- linux.orig/init/main.c
+++ linux/init/main.c
@@ -592,6 +592,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();
--- linux.orig/kernel/printk.c
+++ linux/kernel/printk.c
@@ -162,46 +162,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));
use x86_memblock_find_range in x86 code?

you can do that much earlier before SRAT etc is parsed.

Thanks

Yinghai
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help