[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <eb9bf3d88a2cd2162d69ad477d6649256f1b59be.1351135989.git.joe@perches.com>
Date: Wed, 24 Oct 2012 20:43:57 -0700
From: Joe Perches <joe@...ches.com>
To: Andrew Morton <akpm@...ux-foundation.org>
Cc: Kay Sievers <kay@...y.org>, Yuanhan Liu <yuanhan.liu@...el.com>,
linux-kernel@...r.kernel.org
Subject: [PATCH V2 22/23] printk: Add printk_syslog.c and .h
Move syslog functions to a separate file.
Add compilation unit to Makefile.
Add missing #include <linux/uaccess.h>
Reported-by: Yuanhan Liu <yuanhan.liu@...el.com>
Signed-off-by: Joe Perches <joe@...ches.com>
---
kernel/printk/Makefile | 1 +
kernel/printk/printk.c | 351 +----------------------------------------
kernel/printk/printk_syslog.c | 355 +++++++++++++++++++++++++++++++++++++++++
kernel/printk/printk_syslog.h | 13 ++
4 files changed, 373 insertions(+), 347 deletions(-)
create mode 100644 kernel/printk/printk_syslog.c
create mode 100644 kernel/printk/printk_syslog.h
diff --git a/kernel/printk/Makefile b/kernel/printk/Makefile
index bda335f..7947661 100644
--- a/kernel/printk/Makefile
+++ b/kernel/printk/Makefile
@@ -1,4 +1,5 @@
obj-y = printk.o
obj-y += printk_log.o
obj-y += devkmsg.o
+obj-y += printk_syslog.o
obj-$(CONFIG_A11Y_BRAILLE_CONSOLE) += braille.o
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 0c6042a..bed0e7d 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -30,12 +30,10 @@
#include <linux/security.h>
#include <linux/bootmem.h>
#include <linux/memblock.h>
-#include <linux/syscalls.h>
#include <linux/kexec.h>
#include <linux/kdb.h>
#include <linux/ratelimit.h>
#include <linux/kmsg_dump.h>
-#include <linux/syslog.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/rculist.h>
@@ -49,6 +47,7 @@
#include "console_cmdline.h"
#include "braille.h"
#include "printk_log.h"
+#include "printk_syslog.h"
/*
* Architectures can override it:
@@ -122,11 +121,6 @@ EXPORT_SYMBOL(console_set_on_cmdline);
static int console_may_schedule;
#ifdef CONFIG_PRINTK
-/* the next printk record to read by syslog(READ) or /proc/kmsg */
-static u64 syslog_seq;
-static u32 syslog_idx;
-static enum printk_log_flags syslog_prev;
-static size_t syslog_partial;
/* the next printk record to write to the console */
static u64 console_seq;
@@ -272,340 +266,6 @@ static inline void boot_delay_msec(void)
}
#endif
-#ifdef CONFIG_SECURITY_DMESG_RESTRICT
-int dmesg_restrict = 1;
-#else
-int dmesg_restrict;
-#endif
-
-static int syslog_action_restricted(int type)
-{
- if (dmesg_restrict)
- return 1;
- /* Unless restricted, we allow "read all" and "get buffer size" for everybody */
- return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
-}
-
-static int check_syslog_permissions(int type, bool from_file)
-{
- /*
- * If this is from /proc/kmsg and we've already opened it, then we've
- * already done the capabilities checks at open time.
- */
- if (from_file && type != SYSLOG_ACTION_OPEN)
- return 0;
-
- if (syslog_action_restricted(type)) {
- if (capable(CAP_SYSLOG))
- return 0;
- /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
- if (capable(CAP_SYS_ADMIN)) {
- printk_once(KERN_WARNING "%s (%d): "
- "Attempt to access syslog with CAP_SYS_ADMIN "
- "but no CAP_SYSLOG (deprecated).\n",
- current->comm, task_pid_nr(current));
- return 0;
- }
- return -EPERM;
- }
- return 0;
-}
-
-static int syslog_print(char __user *buf, int size)
-{
- char *text;
- struct printk_log *msg;
- int len = 0;
-
- text = kmalloc(PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX, GFP_KERNEL);
- if (!text)
- return -ENOMEM;
-
- while (size > 0) {
- size_t n;
- size_t skip;
-
- raw_spin_lock_irq(&printk_logbuf_lock);
- if (syslog_seq < printk_log_first_seq) {
- /* messages are gone, move to first one */
- syslog_seq = printk_log_first_seq;
- syslog_idx = printk_log_first_idx;
- syslog_prev = 0;
- syslog_partial = 0;
- }
- if (syslog_seq == printk_log_next_seq) {
- raw_spin_unlock_irq(&printk_logbuf_lock);
- break;
- }
-
- skip = syslog_partial;
- msg = printk_log_from_idx(syslog_idx);
- n = printk_msg_print_text(msg, syslog_prev, true, text,
- PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX);
- if (n - syslog_partial <= size) {
- /* message fits into buffer, move forward */
- syslog_idx = printk_log_next(syslog_idx);
- syslog_seq++;
- syslog_prev = msg->flags;
- n -= syslog_partial;
- syslog_partial = 0;
- } else if (!len){
- /* partial read(), remember position */
- n = size;
- syslog_partial += n;
- } else
- n = 0;
- raw_spin_unlock_irq(&printk_logbuf_lock);
-
- if (!n)
- break;
-
- if (copy_to_user(buf, text + skip, n)) {
- if (!len)
- len = -EFAULT;
- break;
- }
-
- len += n;
- size -= n;
- buf += n;
- }
-
- kfree(text);
- return len;
-}
-
-static int syslog_print_all(char __user *buf, int size, bool clear)
-{
- char *text;
- int len = 0;
-
- text = kmalloc(PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX, GFP_KERNEL);
- if (!text)
- return -ENOMEM;
-
- raw_spin_lock_irq(&printk_logbuf_lock);
- if (buf) {
- u64 next_seq;
- u64 seq;
- u32 idx;
- enum printk_log_flags prev;
-
- if (printk_log_clear_seq < printk_log_first_seq) {
- /* messages are gone, move to first available one */
- printk_log_clear_seq = printk_log_first_seq;
- printk_log_clear_idx = printk_log_first_idx;
- }
-
- /*
- * Find first record that fits, including all following records,
- * into the user-provided buffer for this dump.
- */
- seq = printk_log_clear_seq;
- idx = printk_log_clear_idx;
- prev = 0;
- while (seq < printk_log_next_seq) {
- struct printk_log *msg = printk_log_from_idx(idx);
-
- len += printk_msg_print_text(msg, prev, true, NULL, 0);
- prev = msg->flags;
- idx = printk_log_next(idx);
- seq++;
- }
-
- /* move first record forward until length fits into the buffer */
- seq = printk_log_clear_seq;
- idx = printk_log_clear_idx;
- prev = 0;
- while (len > size && seq < printk_log_next_seq) {
- struct printk_log *msg = printk_log_from_idx(idx);
-
- len -= printk_msg_print_text(msg, prev, true, NULL, 0);
- prev = msg->flags;
- idx = printk_log_next(idx);
- seq++;
- }
-
- /* last message fitting into this dump */
- next_seq = printk_log_next_seq;
-
- len = 0;
- prev = 0;
- while (len >= 0 && seq < next_seq) {
- struct printk_log *msg = printk_log_from_idx(idx);
- int textlen;
-
- textlen = printk_msg_print_text(msg, prev, true, text,
- PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX);
- if (textlen < 0) {
- len = textlen;
- break;
- }
- idx = printk_log_next(idx);
- seq++;
- prev = msg->flags;
-
- raw_spin_unlock_irq(&printk_logbuf_lock);
- if (copy_to_user(buf + len, text, textlen))
- len = -EFAULT;
- else
- len += textlen;
- raw_spin_lock_irq(&printk_logbuf_lock);
-
- if (seq < printk_log_first_seq) {
- /* messages are gone, move to next one */
- seq = printk_log_first_seq;
- idx = printk_log_first_idx;
- prev = 0;
- }
- }
- }
-
- if (clear) {
- printk_log_clear_seq = printk_log_next_seq;
- printk_log_clear_idx = printk_log_next_idx;
- }
- raw_spin_unlock_irq(&printk_logbuf_lock);
-
- kfree(text);
- return len;
-}
-
-int do_syslog(int type, char __user *buf, int len, bool from_file)
-{
- bool clear = false;
- static int saved_console_loglevel = -1;
- int error;
-
- error = check_syslog_permissions(type, from_file);
- if (error)
- goto out;
-
- error = security_syslog(type);
- if (error)
- return error;
-
- switch (type) {
- case SYSLOG_ACTION_CLOSE: /* Close log */
- break;
- case SYSLOG_ACTION_OPEN: /* Open log */
- break;
- case SYSLOG_ACTION_READ: /* Read from log */
- error = -EINVAL;
- if (!buf || len < 0)
- goto out;
- error = 0;
- if (!len)
- goto out;
- if (!access_ok(VERIFY_WRITE, buf, len)) {
- error = -EFAULT;
- goto out;
- }
- error = wait_event_interruptible(printk_log_wait,
- syslog_seq != printk_log_next_seq);
- if (error)
- goto out;
- error = syslog_print(buf, len);
- break;
- /* Read/clear last kernel messages */
- case SYSLOG_ACTION_READ_CLEAR:
- clear = true;
- /* FALL THRU */
- /* Read last kernel messages */
- case SYSLOG_ACTION_READ_ALL:
- error = -EINVAL;
- if (!buf || len < 0)
- goto out;
- error = 0;
- if (!len)
- goto out;
- if (!access_ok(VERIFY_WRITE, buf, len)) {
- error = -EFAULT;
- goto out;
- }
- error = syslog_print_all(buf, len, clear);
- break;
- /* Clear ring buffer */
- case SYSLOG_ACTION_CLEAR:
- syslog_print_all(NULL, 0, true);
- break;
- /* Disable logging to console */
- case SYSLOG_ACTION_CONSOLE_OFF:
- if (saved_console_loglevel == -1)
- saved_console_loglevel = console_loglevel;
- console_loglevel = minimum_console_loglevel;
- break;
- /* Enable logging to console */
- case SYSLOG_ACTION_CONSOLE_ON:
- if (saved_console_loglevel != -1) {
- console_loglevel = saved_console_loglevel;
- saved_console_loglevel = -1;
- }
- break;
- /* Set level of messages printed to console */
- case SYSLOG_ACTION_CONSOLE_LEVEL:
- error = -EINVAL;
- if (len < 1 || len > 8)
- goto out;
- if (len < minimum_console_loglevel)
- len = minimum_console_loglevel;
- console_loglevel = len;
- /* Implicitly re-enable logging to console */
- saved_console_loglevel = -1;
- error = 0;
- break;
- /* Number of chars in the log buffer */
- case SYSLOG_ACTION_SIZE_UNREAD:
- raw_spin_lock_irq(&printk_logbuf_lock);
- if (syslog_seq < printk_log_first_seq) {
- /* messages are gone, move to first one */
- syslog_seq = printk_log_first_seq;
- syslog_idx = printk_log_first_idx;
- syslog_prev = 0;
- syslog_partial = 0;
- }
- if (from_file) {
- /*
- * Short-cut for poll(/"proc/kmsg") which simply checks
- * for pending data, not the size; return the count of
- * records, not the length.
- */
- error = printk_log_next_idx - syslog_idx;
- } else {
- u64 seq = syslog_seq;
- u32 idx = syslog_idx;
- enum printk_log_flags prev = syslog_prev;
-
- error = 0;
- while (seq < printk_log_next_seq) {
- struct printk_log *msg = printk_log_from_idx(idx);
-
- error += printk_msg_print_text(msg, prev, true, NULL, 0);
- idx = printk_log_next(idx);
- seq++;
- prev = msg->flags;
- }
- error -= syslog_partial;
- }
- raw_spin_unlock_irq(&printk_logbuf_lock);
- break;
- /* Size of the log buffer */
- case SYSLOG_ACTION_SIZE_BUFFER:
- error = printk_log_buf_len;
- break;
- default:
- error = -EINVAL;
- break;
- }
-out:
- return error;
-}
-
-SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
-{
- return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
-}
-
static bool __read_mostly ignore_loglevel;
static int __init ignore_loglevel_setup(char *str)
@@ -1061,11 +721,8 @@ EXPORT_SYMBOL(printk);
#else /* CONFIG_PRINTK */
-static u64 syslog_seq;
-static u32 syslog_idx;
static u64 console_seq;
static u32 console_idx;
-static enum printk_log_flags syslog_prev;
u64 printk_log_first_seq;
u32 printk_log_first_idx;
u64 printk_log_next_seq;
@@ -1701,9 +1358,9 @@ void register_console(struct console *newcon)
* for us.
*/
raw_spin_lock_irqsave(&printk_logbuf_lock, flags);
- console_seq = syslog_seq;
- console_idx = syslog_idx;
- console_prev = syslog_prev;
+ console_seq = printk_syslog_seq;
+ console_idx = printk_syslog_idx;
+ console_prev = printk_syslog_prev;
raw_spin_unlock_irqrestore(&printk_logbuf_lock, flags);
/*
* We're about to replay the log buffer. Only do this to the
diff --git a/kernel/printk/printk_syslog.c b/kernel/printk/printk_syslog.c
new file mode 100644
index 0000000..b5135b0
--- /dev/null
+++ b/kernel/printk/printk_syslog.c
@@ -0,0 +1,355 @@
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/security.h>
+#include <linux/syscalls.h>
+#include <linux/syslog.h>
+#include <linux/uaccess.h>
+
+#include "printk_log.h"
+#include "printk_syslog.h"
+
+/* the next printk record to read by syslog(READ) or /proc/kmsg */
+u64 printk_syslog_seq;
+u32 printk_syslog_idx;
+enum printk_log_flags printk_syslog_prev;
+
+#ifdef CONFIG_PRINTK
+
+static size_t printk_syslog_partial;
+
+#ifdef CONFIG_SECURITY_DMESG_RESTRICT
+int dmesg_restrict = 1;
+#else
+int dmesg_restrict;
+#endif
+
+static int printk_syslog_action_restricted(int type)
+{
+ if (dmesg_restrict)
+ return 1;
+ /* Unless restricted, we allow "read all" and "get buffer size" for everybody */
+ return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER;
+}
+
+static int check_syslog_permissions(int type, bool from_file)
+{
+ /*
+ * If this is from /proc/kmsg and we've already opened it, then we've
+ * already done the capabilities checks at open time.
+ */
+ if (from_file && type != SYSLOG_ACTION_OPEN)
+ return 0;
+
+ if (printk_syslog_action_restricted(type)) {
+ if (capable(CAP_SYSLOG))
+ return 0;
+ /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
+ if (capable(CAP_SYS_ADMIN)) {
+ printk_once(KERN_WARNING "%s (%d): "
+ "Attempt to access syslog with CAP_SYS_ADMIN "
+ "but no CAP_SYSLOG (deprecated).\n",
+ current->comm, task_pid_nr(current));
+ return 0;
+ }
+ return -EPERM;
+ }
+ return 0;
+}
+
+static int printk_syslog_print(char __user *buf, int size)
+{
+ char *text;
+ struct printk_log *msg;
+ int len = 0;
+
+ text = kmalloc(PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX, GFP_KERNEL);
+ if (!text)
+ return -ENOMEM;
+
+ while (size > 0) {
+ size_t n;
+ size_t skip;
+
+ raw_spin_lock_irq(&printk_logbuf_lock);
+ if (printk_syslog_seq < printk_log_first_seq) {
+ /* messages are gone, move to first one */
+ printk_syslog_seq = printk_log_first_seq;
+ printk_syslog_idx = printk_log_first_idx;
+ printk_syslog_prev = 0;
+ printk_syslog_partial = 0;
+ }
+ if (printk_syslog_seq == printk_log_next_seq) {
+ raw_spin_unlock_irq(&printk_logbuf_lock);
+ break;
+ }
+
+ skip = printk_syslog_partial;
+ msg = printk_log_from_idx(printk_syslog_idx);
+ n = printk_msg_print_text(msg, printk_syslog_prev, true, text,
+ PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX);
+ if (n - printk_syslog_partial <= size) {
+ /* message fits into buffer, move forward */
+ printk_syslog_idx = printk_log_next(printk_syslog_idx);
+ printk_syslog_seq++;
+ printk_syslog_prev = msg->flags;
+ n -= printk_syslog_partial;
+ printk_syslog_partial = 0;
+ } else if (!len){
+ /* partial read(), remember position */
+ n = size;
+ printk_syslog_partial += n;
+ } else
+ n = 0;
+ raw_spin_unlock_irq(&printk_logbuf_lock);
+
+ if (!n)
+ break;
+
+ if (copy_to_user(buf, text + skip, n)) {
+ if (!len)
+ len = -EFAULT;
+ break;
+ }
+
+ len += n;
+ size -= n;
+ buf += n;
+ }
+
+ kfree(text);
+ return len;
+}
+
+static int printk_syslog_print_all(char __user *buf, int size, bool clear)
+{
+ char *text;
+ int len = 0;
+
+ text = kmalloc(PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX, GFP_KERNEL);
+ if (!text)
+ return -ENOMEM;
+
+ raw_spin_lock_irq(&printk_logbuf_lock);
+ if (buf) {
+ u64 next_seq;
+ u64 seq;
+ u32 idx;
+ enum printk_log_flags prev;
+
+ if (printk_log_clear_seq < printk_log_first_seq) {
+ /* messages are gone, move to first available one */
+ printk_log_clear_seq = printk_log_first_seq;
+ printk_log_clear_idx = printk_log_first_idx;
+ }
+
+ /*
+ * Find first record that fits, including all following records,
+ * into the user-provided buffer for this dump.
+ */
+ seq = printk_log_clear_seq;
+ idx = printk_log_clear_idx;
+ prev = 0;
+ while (seq < printk_log_next_seq) {
+ struct printk_log *msg = printk_log_from_idx(idx);
+
+ len += printk_msg_print_text(msg, prev, true, NULL, 0);
+ prev = msg->flags;
+ idx = printk_log_next(idx);
+ seq++;
+ }
+
+ /* move first record forward until length fits into the buffer */
+ seq = printk_log_clear_seq;
+ idx = printk_log_clear_idx;
+ prev = 0;
+ while (len > size && seq < printk_log_next_seq) {
+ struct printk_log *msg = printk_log_from_idx(idx);
+
+ len -= printk_msg_print_text(msg, prev, true, NULL, 0);
+ prev = msg->flags;
+ idx = printk_log_next(idx);
+ seq++;
+ }
+
+ /* last message fitting into this dump */
+ next_seq = printk_log_next_seq;
+
+ len = 0;
+ prev = 0;
+ while (len >= 0 && seq < next_seq) {
+ struct printk_log *msg = printk_log_from_idx(idx);
+ int textlen;
+
+ textlen = printk_msg_print_text(msg, prev, true, text,
+ PRINTK_LOG_LINE_MAX + PRINTK_PREFIX_MAX);
+ if (textlen < 0) {
+ len = textlen;
+ break;
+ }
+ idx = printk_log_next(idx);
+ seq++;
+ prev = msg->flags;
+
+ raw_spin_unlock_irq(&printk_logbuf_lock);
+ if (copy_to_user(buf + len, text, textlen))
+ len = -EFAULT;
+ else
+ len += textlen;
+ raw_spin_lock_irq(&printk_logbuf_lock);
+
+ if (seq < printk_log_first_seq) {
+ /* messages are gone, move to next one */
+ seq = printk_log_first_seq;
+ idx = printk_log_first_idx;
+ prev = 0;
+ }
+ }
+ }
+
+ if (clear) {
+ printk_log_clear_seq = printk_log_next_seq;
+ printk_log_clear_idx = printk_log_next_idx;
+ }
+ raw_spin_unlock_irq(&printk_logbuf_lock);
+
+ kfree(text);
+ return len;
+}
+
+int do_syslog(int type, char __user *buf, int len, bool from_file)
+{
+ bool clear = false;
+ static int saved_console_loglevel = -1;
+ int error;
+
+ error = check_syslog_permissions(type, from_file);
+ if (error)
+ goto out;
+
+ error = security_syslog(type);
+ if (error)
+ return error;
+
+ switch (type) {
+ case SYSLOG_ACTION_CLOSE: /* Close log */
+ break;
+ case SYSLOG_ACTION_OPEN: /* Open log */
+ break;
+ case SYSLOG_ACTION_READ: /* Read from log */
+ error = -EINVAL;
+ if (!buf || len < 0)
+ goto out;
+ error = 0;
+ if (!len)
+ goto out;
+ if (!access_ok(VERIFY_WRITE, buf, len)) {
+ error = -EFAULT;
+ goto out;
+ }
+ error = wait_event_interruptible(printk_log_wait,
+ printk_syslog_seq != printk_log_next_seq);
+ if (error)
+ goto out;
+ error = printk_syslog_print(buf, len);
+ break;
+ /* Read/clear last kernel messages */
+ case SYSLOG_ACTION_READ_CLEAR:
+ clear = true;
+ /* FALL THRU */
+ /* Read last kernel messages */
+ case SYSLOG_ACTION_READ_ALL:
+ error = -EINVAL;
+ if (!buf || len < 0)
+ goto out;
+ error = 0;
+ if (!len)
+ goto out;
+ if (!access_ok(VERIFY_WRITE, buf, len)) {
+ error = -EFAULT;
+ goto out;
+ }
+ error = printk_syslog_print_all(buf, len, clear);
+ break;
+ /* Clear ring buffer */
+ case SYSLOG_ACTION_CLEAR:
+ printk_syslog_print_all(NULL, 0, true);
+ break;
+ /* Disable logging to console */
+ case SYSLOG_ACTION_CONSOLE_OFF:
+ if (saved_console_loglevel == -1)
+ saved_console_loglevel = console_loglevel;
+ console_loglevel = minimum_console_loglevel;
+ break;
+ /* Enable logging to console */
+ case SYSLOG_ACTION_CONSOLE_ON:
+ if (saved_console_loglevel != -1) {
+ console_loglevel = saved_console_loglevel;
+ saved_console_loglevel = -1;
+ }
+ break;
+ /* Set level of messages printed to console */
+ case SYSLOG_ACTION_CONSOLE_LEVEL:
+ error = -EINVAL;
+ if (len < 1 || len > 8)
+ goto out;
+ if (len < minimum_console_loglevel)
+ len = minimum_console_loglevel;
+ console_loglevel = len;
+ /* Implicitly re-enable logging to console */
+ saved_console_loglevel = -1;
+ error = 0;
+ break;
+ /* Number of chars in the log buffer */
+ case SYSLOG_ACTION_SIZE_UNREAD:
+ raw_spin_lock_irq(&printk_logbuf_lock);
+ if (printk_syslog_seq < printk_log_first_seq) {
+ /* messages are gone, move to first one */
+ printk_syslog_seq = printk_log_first_seq;
+ printk_syslog_idx = printk_log_first_idx;
+ printk_syslog_prev = 0;
+ printk_syslog_partial = 0;
+ }
+ if (from_file) {
+ /*
+ * Short-cut for poll(/"proc/kmsg") which simply checks
+ * for pending data, not the size; return the count of
+ * records, not the length.
+ */
+ error = printk_log_next_idx - printk_syslog_idx;
+ } else {
+ u64 seq = printk_syslog_seq;
+ u32 idx = printk_syslog_idx;
+ enum printk_log_flags prev = printk_syslog_prev;
+
+ error = 0;
+ while (seq < printk_log_next_seq) {
+ struct printk_log *msg = printk_log_from_idx(idx);
+
+ error += printk_msg_print_text(msg, prev, true, NULL, 0);
+ idx = printk_log_next(idx);
+ seq++;
+ prev = msg->flags;
+ }
+ error -= printk_syslog_partial;
+ }
+ raw_spin_unlock_irq(&printk_logbuf_lock);
+ break;
+ /* Size of the log buffer */
+ case SYSLOG_ACTION_SIZE_BUFFER:
+ error = printk_log_buf_len;
+ break;
+ default:
+ error = -EINVAL;
+ break;
+ }
+out:
+ return error;
+}
+
+SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
+{
+ return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
+}
+
+#endif
diff --git a/kernel/printk/printk_syslog.h b/kernel/printk/printk_syslog.h
new file mode 100644
index 0000000..187ffdd
--- /dev/null
+++ b/kernel/printk/printk_syslog.h
@@ -0,0 +1,13 @@
+#ifndef _PRINTK_SYSLOG_H
+#define _PRINTK_SYSLOG_H
+
+#include <linux/syscalls.h>
+#include <linux/syslog.h>
+#include "printk_log.h"
+
+/* the next printk record to read by syslog(READ) or /proc/kmsg */
+extern u64 printk_syslog_seq;
+extern u32 printk_syslog_idx;
+extern enum printk_log_flags printk_syslog_prev;
+
+#endif
--
1.7.8.112.g3fd21
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists