]>
Commit | Line | Data |
---|---|---|
1 | Add two new functions for reading the kernel log buffer. Their intention | |
2 | is to be used by recovery/dump/debug code so the kernel log can be easily | |
3 | retrieved/parsed in a crash scenario, but they are generic enough for other | |
4 | people to dream up other fun uses. | |
5 | ||
6 | Signed-off-by: Mike Frysinger <vapier@gentoo.org> | |
7 | --- | |
8 | diff --git a/include/linux/kernel.h b/include/linux/kernel.h | |
9 | index 4300bb4..8d5b6c7 100644 | |
10 | --- a/include/linux/kernel.h | |
11 | +++ b/include/linux/kernel.h | |
12 | @@ -156,6 +156,9 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |
13 | __attribute__ ((format (printf, 1, 0))); | |
14 | asmlinkage int printk(const char * fmt, ...) | |
15 | __attribute__ ((format (printf, 1, 2))) __cold; | |
16 | +extern int log_buf_get_len(void); | |
17 | +extern int log_buf_read(int idx); | |
18 | +extern int log_buf_copy(char *dest, int idx, int len); | |
19 | #else | |
20 | static inline int vprintk(const char *s, va_list args) | |
21 | __attribute__ ((format (printf, 1, 0))); | |
22 | @@ -163,6 +166,9 @@ static inline int vprintk(const char *s, va_list args) { return 0; } | |
23 | static inline int printk(const char *s, ...) | |
24 | __attribute__ ((format (printf, 1, 2))); | |
25 | static inline int __cold printk(const char *s, ...) { return 0; } | |
26 | +static inline int log_buf_get_len(void) { return 0; } | |
27 | +static inline int log_buf_read(int idx); { return 0; } | |
28 | +static inline int log_buf_copy(char *dest, int idx, int len) { return 0; } | |
29 | #endif | |
30 | ||
31 | unsigned long int_sqrt(unsigned long); | |
32 | diff --git a/kernel/printk.c b/kernel/printk.c | |
33 | index 051d27e..35b231a 100644 | |
34 | --- a/kernel/printk.c | |
35 | +++ b/kernel/printk.c | |
36 | @@ -163,6 +163,55 @@ out: | |
37 | __setup("log_buf_len=", log_buf_len_setup); | |
38 | ||
39 | /* | |
40 | + * Return the number of unread characters in the log buffer. | |
41 | + */ | |
42 | +int log_buf_get_len(void) | |
43 | +{ | |
44 | + return log_end - log_start; | |
45 | +} | |
46 | + | |
47 | +/* | |
48 | + * Copy a range of characters from the log buffer. | |
49 | + */ | |
50 | +int log_buf_copy(char *dest, int idx, int len) | |
51 | +{ | |
52 | + int ret, max; | |
53 | + | |
54 | + if (!oops_in_progress) | |
55 | + spin_lock_irq(&logbuf_lock); | |
56 | + | |
57 | + max = log_buf_get_len(); | |
58 | + if (idx < 0 || idx >= max) | |
59 | + ret = -1; | |
60 | + else { | |
61 | + if (len > max) | |
62 | + len = max; | |
63 | + ret = len; | |
64 | + while (len-- > 0) { | |
65 | + *dest = LOG_BUF(idx++); | |
66 | + ++dest; | |
67 | + } | |
68 | + } | |
69 | + | |
70 | + if (!oops_in_progress) | |
71 | + spin_unlock_irq(&logbuf_lock); | |
72 | + | |
73 | + return ret; | |
74 | +} | |
75 | + | |
76 | +/* | |
77 | + * Extract a single character from the log buffer. | |
78 | + */ | |
79 | +int log_buf_read(int idx) | |
80 | +{ | |
81 | + char ret; | |
82 | + if (log_buf_copy(&ret, idx, 1) == 1) | |
83 | + return ret; | |
84 | + else | |
85 | + return -1; | |
86 | +} | |
87 | + | |
88 | +/* | |
89 | * Commands to do_syslog: | |
90 | * | |
91 | * 0 -- Close the log. Currently a NOP. |