[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20121119142926.GB4453@mail.hallyn.com>
Date: Mon, 19 Nov 2012 14:29:26 +0000
From: "Serge E. Hallyn" <serge@...lyn.com>
To: Rui Xiang <leo.ruixiang@...il.com>
Cc: serge.hallyn@...onical.com, containers@...ts.linux-foundation.org,
netdev@...r.kernel.org, "Eric W. Biederman" <ebiederm@...ssion.com>
Subject: Re: [PATCH RFC 3/5] printk: modify printk interface for
syslog_namespace
Quoting Rui Xiang (leo.ruixiang@...il.com):
> From: Libo Chen <clbchenlibo.chen@...wei.com>
>
> We re-implement printk by additional syslog_ns.
>
> The function include printk, /dev/kmsg, do_syslog and kmsg_dump should be modifyed
> for syslog_ns. Previous identifier *** such as log_first_seq should be replaced
> by syslog_ns->***.
>
> Signed-off-by: Libo Chen <clbchenlibo.chen@...wei.com>
> Signed-off-by: Xiang Rui <rui.xiang@...wei.com>
> ---
> drivers/base/core.c | 4 +-
> include/linux/printk.h | 4 +-
> kernel/printk.c | 609 +++++++++++++++++++++++++++++-------------------
> 3 files changed, 372 insertions(+), 245 deletions(-)
>
> diff --git a/drivers/base/core.c b/drivers/base/core.c
> index abea76c..665c2f7 100644
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -26,6 +26,7 @@
> #include <linux/async.h>
> #include <linux/pm_runtime.h>
> #include <linux/netdevice.h>
> +#include <linux/syslog_namespace.h>
>
> #include "base.h"
> #include "power/power.h"
> @@ -1922,7 +1923,8 @@ int dev_vprintk_emit(int level, const struct device *dev,
>
> hdrlen = create_syslog_header(dev, hdr, sizeof(hdr));
>
> - return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args);
> + return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen,
> + fmt, args, current_syslog_ns());
> }
> EXPORT_SYMBOL(dev_vprintk_emit);
>
> diff --git a/include/linux/printk.h b/include/linux/printk.h
> index 9afc01e..e0c60d9 100644
> --- a/include/linux/printk.h
> +++ b/include/linux/printk.h
> @@ -7,6 +7,7 @@
> extern const char linux_banner[];
> extern const char linux_proc_banner[];
>
> +struct syslog_namespace;
> static inline int printk_get_level(const char *buffer)
> {
> if (buffer[0] == KERN_SOH_ASCII && buffer[1]) {
> @@ -105,7 +106,8 @@ extern void printk_tick(void);
> asmlinkage __printf(5, 0)
> int vprintk_emit(int facility, int level,
> const char *dict, size_t dictlen,
> - const char *fmt, va_list args);
> + const char *fmt, va_list args,
> + struct syslog_namespace *syslog_ns);
>
> asmlinkage __printf(1, 0)
> int vprintk(const char *fmt, va_list args);
> diff --git a/kernel/printk.c b/kernel/printk.c
> index 2d607f4..2ef9c46 100644
> --- a/kernel/printk.c
> +++ b/kernel/printk.c
> @@ -42,6 +42,7 @@
> #include <linux/notifier.h>
> #include <linux/rculist.h>
> #include <linux/poll.h>
> +#include <linux/syslog_namespace.h>
>
> #include <asm/uaccess.h>
>
> @@ -214,46 +215,14 @@ struct log {
> * The logbuf_lock protects kmsg buffer, indices, counters. It is also
> * used in interesting ways to provide interlocking in console_unlock();
> */
> -static DEFINE_RAW_SPINLOCK(logbuf_lock);
>
> #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 log_flags syslog_prev;
> -static size_t syslog_partial;
> -
> -/* index and sequence number of the first record stored in the buffer */
> -static u64 log_first_seq;
> -static u32 log_first_idx;
> -
> -/* index and sequence number of the next record to store in the buffer */
> -static u64 log_next_seq;
> -static u32 log_next_idx;
>
> -/* the next printk record to write to the console */
> -static u64 console_seq;
> -static u32 console_idx;
> static enum log_flags console_prev;
>
> -/* the next printk record to read after the last 'clear' command */
> -static u64 clear_seq;
> -static u32 clear_idx;
> -
> #define PREFIX_MAX 32
> #define LOG_LINE_MAX 1024 - PREFIX_MAX
>
> -/* record buffer */
> -#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
> -#define LOG_ALIGN 4
> -#else
> -#define LOG_ALIGN __alignof__(struct log)
> -#endif
> -#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
> -static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
> -static char *log_buf = __log_buf;
> -static u32 log_buf_len = __LOG_BUF_LEN;
> -
> /* cpu currently holding logbuf_lock */
> static volatile unsigned int logbuf_cpu = UINT_MAX;
>
> @@ -270,23 +239,23 @@ static char *log_dict(const struct log *msg)
> }
>
> /* get record by index; idx must point to valid msg */
> -static struct log *log_from_idx(u32 idx)
> +static struct log *log_from_idx(u32 idx, struct syslog_namespace *syslog_ns)
> {
> - struct log *msg = (struct log *)(log_buf + idx);
> + struct log *msg = (struct log *)(syslog_ns->log_buf + idx);
>
> /*
> * A length == 0 record is the end of buffer marker. Wrap around and
> * read the message at the start of the buffer.
> */
> if (!msg->len)
> - return (struct log *)log_buf;
> + return (struct log *)syslog_ns->log_buf;
> return msg;
> }
>
> /* get next record; idx must point to valid msg */
> -static u32 log_next(u32 idx)
> +static u32 log_next(u32 idx, struct syslog_namespace *syslog_ns)
> {
> - struct log *msg = (struct log *)(log_buf + idx);
> + struct log *msg = (struct log *)(syslog_ns->log_buf + idx);
>
> /* length == 0 indicates the end of the buffer; wrap */
> /*
> @@ -295,7 +264,7 @@ static u32 log_next(u32 idx)
> * return the one after that.
> */
> if (!msg->len) {
> - msg = (struct log *)log_buf;
> + msg = (struct log *)syslog_ns->log_buf;
> return msg->len;
> }
> return idx + msg->len;
> @@ -305,7 +274,8 @@ static u32 log_next(u32 idx)
> static void log_store(int facility, int level,
> enum log_flags flags, u64 ts_nsec,
> const char *dict, u16 dict_len,
> - const char *text, u16 text_len)
> + const char *text, u16 text_len,
> + struct syslog_namespace *syslog_ns)
> {
> struct log *msg;
> u32 size, pad_len;
> @@ -315,34 +285,40 @@ static void log_store(int facility, int level,
> pad_len = (-size) & (LOG_ALIGN - 1);
> size += pad_len;
>
> - while (log_first_seq < log_next_seq) {
> + while (syslog_ns->log_first_seq < syslog_ns->log_next_seq) {
> u32 free;
>
> - if (log_next_idx > log_first_idx)
> - free = max(log_buf_len - log_next_idx, log_first_idx);
> + if (syslog_ns->log_next_idx > syslog_ns->log_first_idx)
> + free = max(syslog_ns->log_buf_len -
> + syslog_ns->log_next_idx,
> + syslog_ns->log_first_idx);
> else
> - free = log_first_idx - log_next_idx;
> + free = syslog_ns->log_first_idx -
> + syslog_ns->log_next_idx;
>
> if (free > size + sizeof(struct log))
> break;
>
> /* drop old messages until we have enough contiuous space */
> - log_first_idx = log_next(log_first_idx);
> - log_first_seq++;
> + syslog_ns->log_first_idx =
> + log_next(syslog_ns->log_first_idx, syslog_ns);
> + syslog_ns->log_first_seq++;
> }
>
> - if (log_next_idx + size + sizeof(struct log) >= log_buf_len) {
> + if (syslog_ns->log_next_idx + size + sizeof(struct log) >=
> + syslog_ns->log_buf_len) {
> /*
> * This message + an additional empty header does not fit
> * at the end of the buffer. Add an empty header with len == 0
> * to signify a wrap around.
> */
> - memset(log_buf + log_next_idx, 0, sizeof(struct log));
> - log_next_idx = 0;
> + memset(syslog_ns->log_buf + syslog_ns->log_next_idx,
> + 0, sizeof(struct log));
> + syslog_ns->log_next_idx = 0;
> }
>
> /* fill message */
> - msg = (struct log *)(log_buf + log_next_idx);
> + msg = (struct log *)(syslog_ns->log_buf + syslog_ns->log_next_idx);
> memcpy(log_text(msg), text, text_len);
> msg->text_len = text_len;
> memcpy(log_dict(msg), dict, dict_len);
> @@ -358,8 +334,8 @@ static void log_store(int facility, int level,
> msg->len = sizeof(struct log) + text_len + dict_len + pad_len;
>
> /* insert message */
> - log_next_idx += msg->len;
> - log_next_seq++;
> + syslog_ns->log_next_idx += msg->len;
> + syslog_ns->log_next_seq++;
> }
>
> /* /dev/kmsg - userspace message inject/listen interface */
> @@ -368,6 +344,7 @@ struct devkmsg_user {
> u32 idx;
> enum log_flags prev;
> struct mutex lock;
> + struct syslog_namespace *syslog_ns;
> char buf[8192];
> };
>
> @@ -431,6 +408,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
> size_t count, loff_t *ppos)
> {
> struct devkmsg_user *user = file->private_data;
> + struct syslog_namespace *syslog_ns = user->syslog_ns;
> struct log *msg;
> u64 ts_usec;
> size_t i;
> @@ -444,32 +422,32 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
> ret = mutex_lock_interruptible(&user->lock);
> if (ret)
> return ret;
> - raw_spin_lock_irq(&logbuf_lock);
> - while (user->seq == log_next_seq) {
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> + while (user->seq == syslog_ns->log_next_seq) {
> if (file->f_flags & O_NONBLOCK) {
> ret = -EAGAIN;
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> goto out;
> }
>
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> ret = wait_event_interruptible(log_wait,
> - user->seq != log_next_seq);
> + user->seq != syslog_ns->log_next_seq);
> if (ret)
> goto out;
> - raw_spin_lock_irq(&logbuf_lock);
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> }
>
> - if (user->seq < log_first_seq) {
> + if (user->seq < syslog_ns->log_first_seq) {
> /* our last seen message is gone, return error and reset */
> - user->idx = log_first_idx;
> - user->seq = log_first_seq;
> + user->idx = syslog_ns->log_first_idx;
> + user->seq = syslog_ns->log_first_seq;
> ret = -EPIPE;
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> goto out;
> }
>
> - msg = log_from_idx(user->idx);
> + msg = log_from_idx(user->idx, syslog_ns);
> ts_usec = msg->ts_nsec;
> do_div(ts_usec, 1000);
>
> @@ -530,9 +508,9 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
> user->buf[len++] = '\n';
> }
>
> - user->idx = log_next(user->idx);
> + user->idx = log_next(user->idx, syslog_ns);
> user->seq++;
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
>
> if (len > count) {
> ret = -EINVAL;
> @@ -552,6 +530,7 @@ out:
> static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
> {
> struct devkmsg_user *user = file->private_data;
> + struct syslog_namespace *syslog_ns = user->syslog_ns;
> loff_t ret = 0;
>
> if (!user)
> @@ -559,12 +538,12 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
> if (offset)
> return -ESPIPE;
>
> - raw_spin_lock_irq(&logbuf_lock);
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> switch (whence) {
> case SEEK_SET:
> /* the first record */
> - user->idx = log_first_idx;
> - user->seq = log_first_seq;
> + user->idx = syslog_ns->log_first_idx;
> + user->seq = syslog_ns->log_first_seq;
> break;
> case SEEK_DATA:
> /*
> @@ -572,24 +551,25 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
> * like issued by 'dmesg -c'. Reading /dev/kmsg itself
> * changes no global state, and does not clear anything.
> */
> - user->idx = clear_idx;
> - user->seq = clear_seq;
> + user->idx = syslog_ns->clear_idx;
> + user->seq = syslog_ns->clear_seq;
> break;
> case SEEK_END:
> /* after the last record */
> - user->idx = log_next_idx;
> - user->seq = log_next_seq;
> + user->idx = syslog_ns->log_next_idx;
> + user->seq = syslog_ns->log_next_seq;
> break;
> default:
> ret = -EINVAL;
> }
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> return ret;
> }
>
> static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
> {
> struct devkmsg_user *user = file->private_data;
> + struct syslog_namespace *syslog_ns = user->syslog_ns;
> int ret = 0;
>
> if (!user)
> @@ -597,20 +577,21 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
>
> poll_wait(file, &log_wait, wait);
>
> - raw_spin_lock_irq(&logbuf_lock);
> - if (user->seq < log_next_seq) {
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> + if (user->seq < syslog_ns->log_next_seq) {
> /* return error when data has vanished underneath us */
> - if (user->seq < log_first_seq)
> + if (user->seq < syslog_ns->log_first_seq)
> ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI;
> ret = POLLIN|POLLRDNORM;
> }
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
>
> return ret;
> }
>
> static int devkmsg_open(struct inode *inode, struct file *file)
> {
> + struct syslog_namespace *syslog_ns;
> struct devkmsg_user *user;
> int err;
>
> @@ -628,10 +609,11 @@ static int devkmsg_open(struct inode *inode, struct file *file)
>
> mutex_init(&user->lock);
>
> - raw_spin_lock_irq(&logbuf_lock);
> - user->idx = log_first_idx;
> - user->seq = log_first_seq;
> - raw_spin_unlock_irq(&logbuf_lock);
> + user->syslog_ns = current_syslog_ns();
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> + user->idx = syslog_ns->log_first_idx;
> + user->seq = syslog_ns->log_first_seq;
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
>
> file->private_data = user;
> return 0;
> @@ -669,10 +651,12 @@ const struct file_operations kmsg_fops = {
> */
> void log_buf_kexec_setup(void)
> {
> - VMCOREINFO_SYMBOL(log_buf);
> - VMCOREINFO_SYMBOL(log_buf_len);
> - VMCOREINFO_SYMBOL(log_first_idx);
> - VMCOREINFO_SYMBOL(log_next_idx);
> + struct syslog_namespace *syslog_ns = current_syslog_ns();
> +
> + VMCOREINFO_SYMBOL(syslog_ns->log_buf);
> + VMCOREINFO_SYMBOL(syslog_ns->log_buf_len);
> + VMCOREINFO_SYMBOL(syslog_ns->log_first_idx);
> + VMCOREINFO_SYMBOL(syslog_ns->log_next_idx);
> /*
> * Export struct log size and field offsets. User space tools can
> * parse it and detect any changes to structure down the line.
> @@ -692,10 +676,11 @@ static unsigned long __initdata new_log_buf_len;
> static int __init log_buf_len_setup(char *str)
> {
> unsigned size = memparse(str, &str);
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
>
> if (size)
> size = roundup_pow_of_two(size);
> - if (size > log_buf_len)
> + if (size > syslog_ns->log_buf_len)
> new_log_buf_len = size;
>
> return 0;
> @@ -707,6 +692,7 @@ void __init setup_log_buf(int early)
> unsigned long flags;
> char *new_log_buf;
> int free;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
>
> if (!new_log_buf_len)
> return;
> @@ -728,15 +714,15 @@ void __init setup_log_buf(int early)
> return;
> }
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> - log_buf_len = new_log_buf_len;
> - log_buf = new_log_buf;
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
> + memcpy(new_log_buf, syslog_ns->log_buf, __LOG_BUF_LEN);
> + syslog_ns->log_buf_len = new_log_buf_len;
> + syslog_ns->log_buf = new_log_buf;
> new_log_buf_len = 0;
> - free = __LOG_BUF_LEN - log_next_idx;
> - memcpy(log_buf, __log_buf, __LOG_BUF_LEN);
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + free = __LOG_BUF_LEN - syslog_ns->log_next_idx;
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
>
> - pr_info("log_buf_len: %d\n", log_buf_len);
> + pr_info("log_buf_len: %d\n", syslog_ns->log_buf_len);
> pr_info("early log buf free: %d(%d%%)\n",
> free, (free * 100) / __LOG_BUF_LEN);
> }
> @@ -937,7 +923,8 @@ static size_t msg_print_text(const struct log *msg, enum log_flags prev,
> return len;
> }
>
> -static int syslog_print(char __user *buf, int size)
> +static int syslog_print(char __user *buf, int size,
> + struct syslog_namespace *syslog_ns)
> {
> char *text;
> struct log *msg;
> @@ -951,37 +938,38 @@ static int syslog_print(char __user *buf, int size)
> size_t n;
> size_t skip;
>
> - raw_spin_lock_irq(&logbuf_lock);
> - if (syslog_seq < log_first_seq) {
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> + if (syslog_ns->syslog_seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to first one */
> - syslog_seq = log_first_seq;
> - syslog_idx = log_first_idx;
> - syslog_prev = 0;
> - syslog_partial = 0;
> + syslog_ns->syslog_seq = syslog_ns->log_first_seq;
> + syslog_ns->syslog_idx = syslog_ns->log_first_idx;
> + syslog_ns->syslog_prev = 0;
> + syslog_ns->syslog_partial = 0;
> }
> - if (syslog_seq == log_next_seq) {
> - raw_spin_unlock_irq(&logbuf_lock);
> + if (syslog_ns->syslog_seq == syslog_ns->log_next_seq) {
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> break;
> }
>
> - skip = syslog_partial;
> - msg = log_from_idx(syslog_idx);
> - n = msg_print_text(msg, syslog_prev, true, text,
> + skip = syslog_ns->syslog_partial;
> + msg = log_from_idx(syslog_ns->syslog_idx, syslog_ns);
> + n = msg_print_text(msg, syslog_ns->syslog_prev, true, text,
> LOG_LINE_MAX + PREFIX_MAX);
> - if (n - syslog_partial <= size) {
> + if (n - syslog_ns->syslog_partial <= size) {
> /* message fits into buffer, move forward */
> - syslog_idx = log_next(syslog_idx);
> - syslog_seq++;
> - syslog_prev = msg->flags;
> - n -= syslog_partial;
> - syslog_partial = 0;
> + syslog_ns->syslog_idx =
> + log_next(syslog_ns->syslog_idx, syslog_ns);
> + syslog_ns->syslog_seq++;
> + syslog_ns->syslog_prev = msg->flags;
> + n -= syslog_ns->syslog_partial;
> + syslog_ns->syslog_partial = 0;
> } else if (!len){
> /* partial read(), remember position */
> n = size;
> - syslog_partial += n;
> + syslog_ns->syslog_partial += n;
> } else
> n = 0;
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
>
> if (!n)
> break;
> @@ -1001,7 +989,8 @@ static int syslog_print(char __user *buf, int size)
> return len;
> }
>
> -static int syslog_print_all(char __user *buf, int size, bool clear)
> +static int syslog_print_all(char __user *buf, int size, bool clear,
> + struct syslog_namespace *syslog_ns)
> {
> char *text;
> int len = 0;
> @@ -1010,55 +999,55 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
> if (!text)
> return -ENOMEM;
>
> - raw_spin_lock_irq(&logbuf_lock);
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> if (buf) {
> u64 next_seq;
> u64 seq;
> u32 idx;
> enum log_flags prev;
>
> - if (clear_seq < log_first_seq) {
> + if (syslog_ns->clear_seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to first available one */
> - clear_seq = log_first_seq;
> - clear_idx = log_first_idx;
> + syslog_ns->clear_seq = syslog_ns->log_first_seq;
> + syslog_ns->clear_idx = syslog_ns->log_first_idx;
> }
>
> /*
> * Find first record that fits, including all following records,
> * into the user-provided buffer for this dump.
> */
> - seq = clear_seq;
> - idx = clear_idx;
> + seq = syslog_ns->clear_seq;
> + idx = syslog_ns->clear_idx;
> prev = 0;
> - while (seq < log_next_seq) {
> - struct log *msg = log_from_idx(idx);
> + while (seq < syslog_ns->log_next_seq) {
> + struct log *msg = log_from_idx(idx, syslog_ns);
>
> len += msg_print_text(msg, prev, true, NULL, 0);
> prev = msg->flags;
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> }
>
> /* move first record forward until length fits into the buffer */
> - seq = clear_seq;
> - idx = clear_idx;
> + seq = syslog_ns->clear_seq;
> + idx = syslog_ns->clear_idx;
> prev = 0;
> - while (len > size && seq < log_next_seq) {
> - struct log *msg = log_from_idx(idx);
> + while (len > size && seq < syslog_ns->log_next_seq) {
> + struct log *msg = log_from_idx(idx, syslog_ns);
>
> len -= msg_print_text(msg, prev, true, NULL, 0);
> prev = msg->flags;
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> }
>
> /* last message fitting into this dump */
> - next_seq = log_next_seq;
> + next_seq = syslog_ns->log_next_seq;
>
> len = 0;
> prev = 0;
> while (len >= 0 && seq < next_seq) {
> - struct log *msg = log_from_idx(idx);
> + struct log *msg = log_from_idx(idx, syslog_ns);
> int textlen;
>
> textlen = msg_print_text(msg, prev, true, text,
> @@ -1067,31 +1056,31 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
> len = textlen;
> break;
> }
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> prev = msg->flags;
>
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> if (copy_to_user(buf + len, text, textlen))
> len = -EFAULT;
> else
> len += textlen;
> - raw_spin_lock_irq(&logbuf_lock);
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
>
> - if (seq < log_first_seq) {
> + if (seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to next one */
> - seq = log_first_seq;
> - idx = log_first_idx;
> + seq = syslog_ns->log_first_seq;
> + idx = syslog_ns->log_first_idx;
> prev = 0;
> }
> }
> }
>
> if (clear) {
> - clear_seq = log_next_seq;
> - clear_idx = log_next_idx;
> + syslog_ns->clear_seq = syslog_ns->log_next_seq;
> + syslog_ns->clear_idx = syslog_ns->log_next_idx;
> }
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
>
> kfree(text);
> return len;
> @@ -1102,6 +1091,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
> bool clear = false;
> static int saved_console_loglevel = -1;
> int error;
> + struct syslog_namespace *syslog_ns = current_syslog_ns();
>
> error = check_syslog_permissions(type, from_file);
> if (error)
> @@ -1128,10 +1118,10 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
> goto out;
> }
> error = wait_event_interruptible(log_wait,
> - syslog_seq != log_next_seq);
> + syslog_ns->syslog_seq != syslog_ns->log_next_seq);
> if (error)
> goto out;
> - error = syslog_print(buf, len);
> + error = syslog_print(buf, len, syslog_ns);
> break;
> /* Read/clear last kernel messages */
> case SYSLOG_ACTION_READ_CLEAR:
> @@ -1149,11 +1139,11 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
> error = -EFAULT;
> goto out;
> }
> - error = syslog_print_all(buf, len, clear);
> + error = syslog_print_all(buf, len, clear, syslog_ns);
> break;
> /* Clear ring buffer */
> case SYSLOG_ACTION_CLEAR:
> - syslog_print_all(NULL, 0, true);
> + syslog_print_all(NULL, 0, true, syslog_ns);
> break;
> /* Disable logging to console */
> case SYSLOG_ACTION_CONSOLE_OFF:
> @@ -1182,13 +1172,13 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
> break;
> /* Number of chars in the log buffer */
> case SYSLOG_ACTION_SIZE_UNREAD:
> - raw_spin_lock_irq(&logbuf_lock);
> - if (syslog_seq < log_first_seq) {
> + raw_spin_lock_irq(&syslog_ns->logbuf_lock);
> + if (syslog_ns->syslog_seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to first one */
> - syslog_seq = log_first_seq;
> - syslog_idx = log_first_idx;
> - syslog_prev = 0;
> - syslog_partial = 0;
> + syslog_ns->syslog_seq = syslog_ns->log_first_seq;
> + syslog_ns->syslog_idx = syslog_ns->log_first_idx;
> + syslog_ns->syslog_prev = 0;
> + syslog_ns->syslog_partial = 0;
> }
> if (from_file) {
> /*
> @@ -1196,28 +1186,28 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
> * for pending data, not the size; return the count of
> * records, not the length.
> */
> - error = log_next_idx - syslog_idx;
> + error = syslog_ns->log_next_idx - syslog_ns->syslog_idx;
> } else {
> - u64 seq = syslog_seq;
> - u32 idx = syslog_idx;
> - enum log_flags prev = syslog_prev;
> + u64 seq = syslog_ns->syslog_seq;
> + u32 idx = syslog_ns->syslog_idx;
> + enum log_flags prev = syslog_ns->syslog_prev;
>
> error = 0;
> - while (seq < log_next_seq) {
> - struct log *msg = log_from_idx(idx);
> + while (seq < syslog_ns->log_next_seq) {
> + struct log *msg = log_from_idx(idx, syslog_ns);
>
> error += msg_print_text(msg, prev, true, NULL, 0);
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> prev = msg->flags;
> }
> - error -= syslog_partial;
> + error -= syslog_ns->syslog_partial;
> }
> - raw_spin_unlock_irq(&logbuf_lock);
> + raw_spin_unlock_irq(&syslog_ns->logbuf_lock);
> break;
> /* Size of the log buffer */
> case SYSLOG_ACTION_SIZE_BUFFER:
> - error = log_buf_len;
> + error = syslog_ns->log_buf_len;
> break;
> default:
> error = -EINVAL;
> @@ -1282,7 +1272,7 @@ static void call_console_drivers(int level, const char *text, size_t len)
> * every 10 seconds, to leave time for slow consoles to print a
> * full oops.
> */
> -static void zap_locks(void)
> +static void zap_locks(struct syslog_namespace *syslog_ns)
> {
> static unsigned long oops_timestamp;
>
> @@ -1294,7 +1284,7 @@ static void zap_locks(void)
>
> debug_locks_off();
> /* If a crash is occurring, make sure we can't deadlock */
> - raw_spin_lock_init(&logbuf_lock);
> + raw_spin_lock_init(&syslog_ns->logbuf_lock);
> /* And make sure that we print immediately */
> sema_init(&console_sem, 1);
> }
> @@ -1334,8 +1324,9 @@ static inline int can_use_console(unsigned int cpu)
> * interrupts disabled. It should return with 'lockbuf_lock'
> * released but interrupts still disabled.
> */
> -static int console_trylock_for_printk(unsigned int cpu)
> - __releases(&logbuf_lock)
> +static int console_trylock_for_printk(unsigned int cpu,
> + struct syslog_namespace *syslog_ns)
> + __releases(&syslog_ns->logbuf_lock)
> {
> int retval = 0, wake = 0;
>
> @@ -1357,7 +1348,7 @@ static int console_trylock_for_printk(unsigned int cpu)
> logbuf_cpu = UINT_MAX;
> if (wake)
> up(&console_sem);
> - raw_spin_unlock(&logbuf_lock);
> + raw_spin_unlock(&syslog_ns->logbuf_lock);
> return retval;
> }
>
> @@ -1393,7 +1384,7 @@ static struct cont {
> bool flushed:1; /* buffer sealed and committed */
> } cont;
>
> -static void cont_flush(enum log_flags flags)
> +static void cont_flush(enum log_flags flags, struct syslog_namespace *syslog_ns)
> {
> if (cont.flushed)
> return;
> @@ -1407,7 +1398,7 @@ static void cont_flush(enum log_flags flags)
> * line. LOG_NOCONS suppresses a duplicated output.
> */
> log_store(cont.facility, cont.level, flags | LOG_NOCONS,
> - cont.ts_nsec, NULL, 0, cont.buf, cont.len);
> + cont.ts_nsec, NULL, 0, cont.buf, cont.len, syslog_ns);
> cont.flags = flags;
> cont.flushed = true;
> } else {
> @@ -1416,19 +1407,20 @@ static void cont_flush(enum log_flags flags)
> * just submit it to the store and free the buffer.
> */
> log_store(cont.facility, cont.level, flags, 0,
> - NULL, 0, cont.buf, cont.len);
> + NULL, 0, cont.buf, cont.len, syslog_ns);
> cont.len = 0;
> }
> }
>
> -static bool cont_add(int facility, int level, const char *text, size_t len)
> +static bool cont_add(int facility, int level, const char *text, size_t len,
> + struct syslog_namespace *syslog_ns)
> {
> if (cont.len && cont.flushed)
> return false;
>
> if (cont.len + len > sizeof(cont.buf)) {
> /* the line gets too long, split it up in separate records */
> - cont_flush(LOG_CONT);
> + cont_flush(LOG_CONT, syslog_ns);
> return false;
> }
>
> @@ -1446,7 +1438,7 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
> cont.len += len;
>
> if (cont.len > (sizeof(cont.buf) * 80) / 100)
> - cont_flush(LOG_CONT);
> + cont_flush(LOG_CONT, syslog_ns);
>
> return true;
> }
> @@ -1481,7 +1473,8 @@ static size_t cont_print_text(char *text, size_t size)
>
> asmlinkage int vprintk_emit(int facility, int level,
> const char *dict, size_t dictlen,
> - const char *fmt, va_list args)
> + const char *fmt, va_list args,
> + struct syslog_namespace *syslog_ns)
> {
> static int recursion_bug;
> static char textbuf[LOG_LINE_MAX];
> @@ -1514,11 +1507,11 @@ asmlinkage int vprintk_emit(int facility, int level,
> recursion_bug = 1;
> goto out_restore_irqs;
> }
> - zap_locks();
> + zap_locks(syslog_ns);
> }
>
> lockdep_off();
> - raw_spin_lock(&logbuf_lock);
> + raw_spin_lock(&syslog_ns->logbuf_lock);
> logbuf_cpu = this_cpu;
>
> if (recursion_bug) {
> @@ -1529,7 +1522,7 @@ asmlinkage int vprintk_emit(int facility, int level,
> printed_len += strlen(recursion_msg);
> /* emit KERN_CRIT message */
> log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
> - NULL, 0, recursion_msg, printed_len);
> + NULL, 0, recursion_msg, printed_len, syslog_ns);
> }
>
> /*
> @@ -1576,12 +1569,12 @@ asmlinkage int vprintk_emit(int facility, int level,
> * or another task also prints continuation lines.
> */
> if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
> - cont_flush(LOG_NEWLINE);
> + cont_flush(LOG_NEWLINE, syslog_ns);
>
> /* buffer line if possible, otherwise store it right away */
> - if (!cont_add(facility, level, text, text_len))
> + if (!cont_add(facility, level, text, text_len, syslog_ns))
> log_store(facility, level, lflags | LOG_CONT, 0,
> - dict, dictlen, text, text_len);
> + dict, dictlen, text, text_len, syslog_ns);
> } else {
> bool stored = false;
>
> @@ -1593,13 +1586,14 @@ asmlinkage int vprintk_emit(int facility, int level,
> */
> if (cont.len && cont.owner == current) {
> if (!(lflags & LOG_PREFIX))
> - stored = cont_add(facility, level, text, text_len);
> - cont_flush(LOG_NEWLINE);
> + stored = cont_add(facility, level, text,
> + text_len, syslog_ns);
> + cont_flush(LOG_NEWLINE, syslog_ns);
> }
>
> if (!stored)
> log_store(facility, level, lflags, 0,
> - dict, dictlen, text, text_len);
> + dict, dictlen, text, text_len, syslog_ns);
> }
> printed_len += text_len;
>
> @@ -1611,7 +1605,7 @@ asmlinkage int vprintk_emit(int facility, int level,
> * The console_trylock_for_printk() function will release 'logbuf_lock'
> * regardless of whether it actually gets the console semaphore or not.
> */
> - if (console_trylock_for_printk(this_cpu))
> + if (console_trylock_for_printk(this_cpu, syslog_ns))
> console_unlock();
>
> lockdep_on();
> @@ -1624,7 +1618,8 @@ EXPORT_SYMBOL(vprintk_emit);
>
> asmlinkage int vprintk(const char *fmt, va_list args)
> {
> - return vprintk_emit(0, -1, NULL, 0, fmt, args);
> + return vprintk_emit(0, -1, NULL, 0, fmt, args,
> + current_syslog_ns());
> }
> EXPORT_SYMBOL(vprintk);
>
> @@ -1636,7 +1631,8 @@ asmlinkage int printk_emit(int facility, int level,
> int r;
>
> va_start(args, fmt);
> - r = vprintk_emit(facility, level, dict, dictlen, fmt, args);
> + r = vprintk_emit(facility, level, dict, dictlen, fmt, args,
> + current_syslog_ns());
> va_end(args);
>
> return r;
> @@ -1678,7 +1674,7 @@ asmlinkage int printk(const char *fmt, ...)
> }
> #endif
> va_start(args, fmt);
> - r = vprintk_emit(0, -1, NULL, 0, fmt, args);
> + r = vprintk_emit(0, -1, NULL, 0, fmt, args, current_syslog_ns());
Current is meaningless here. The default should be using init_syslog_ns.
> va_end(args);
>
> return r;
> @@ -1981,12 +1977,13 @@ void wake_up_klogd(void)
> this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
> }
>
> -static void console_cont_flush(char *text, size_t size)
> +static void console_cont_flush(char *text, size_t size,
> + struct syslog_namespace *syslog_ns)
> {
> unsigned long flags;
> size_t len;
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
>
> if (!cont.len)
> goto out;
> @@ -1996,18 +1993,131 @@ static void console_cont_flush(char *text, size_t size)
> * busy. The earlier ones need to be printed before this one, we
> * did not flush any fragment so far, so just let it queue up.
> */
> - if (console_seq < log_next_seq && !cont.cons)
> + if (syslog_ns->console_seq < syslog_ns->log_next_seq && !cont.cons)
> goto out;
>
> len = cont_print_text(text, size);
> - raw_spin_unlock(&logbuf_lock);
> + raw_spin_unlock(&syslog_ns->logbuf_lock);
> stop_critical_timings();
> call_console_drivers(cont.level, text, len);
> start_critical_timings();
> local_irq_restore(flags);
> return;
> out:
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
> +}
> +
> +/**
> + * syslog_console_unlock - unlock the console system for syslog_namespace
> + *
> + * Releases the console_lock which the caller holds on the console system
> + * and the console driver list.
> + *
> + * While the console_lock was held, console output may have been buffered
> + * by printk(). If this is the case, syslog_console_unlock(); emits
> + * the output prior to releasing the lock.
> + *
> + * If there is output waiting, we wake /dev/kmsg and syslog() users.
> + *
> + * syslog_console_unlock(); may be called from any context.
> + */
> +void syslog_console_unlock(struct syslog_namespace *syslog_ns)
> +{
> + static char text[LOG_LINE_MAX + PREFIX_MAX];
> + static u64 seen_seq;
> + unsigned long flags;
> + bool wake_klogd = false;
> + bool retry;
> +
> + if (console_suspended) {
> + up(&console_sem);
> + return;
> + }
> +
> + console_may_schedule = 0;
> +
> + /* flush buffered message fragment immediately to console */
> + console_cont_flush(text, sizeof(text), syslog_ns);
> +again:
> + for (;;) {
> + struct log *msg;
> + size_t len;
> + int level;
> +
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
> + if (seen_seq != syslog_ns->log_next_seq) {
> + wake_klogd = true;
> + seen_seq = syslog_ns->log_next_seq;
> + }
> +
> + if (syslog_ns->console_seq < syslog_ns->log_first_seq) {
> + /* messages are gone, move to first one */
> + syslog_ns->console_seq = syslog_ns->log_first_seq;
> + syslog_ns->console_idx = syslog_ns->log_first_idx;
> + console_prev = 0;
> + }
> +skip:
> + if (syslog_ns->console_seq == syslog_ns->log_next_seq)
> + break;
> +
> + msg = log_from_idx(syslog_ns->console_idx, syslog_ns);
> + if (msg->flags & LOG_NOCONS) {
> + /*
> + * Skip record we have buffered and already printed
> + * directly to the console when we received it.
> + */
> + syslog_ns->console_idx =
> + log_next(syslog_ns->console_idx, syslog_ns);
> + syslog_ns->console_seq++;
> + /*
> + * We will get here again when we register a new
> + * CON_PRINTBUFFER console. Clear the flag so we
> + * will properly dump everything later.
> + */
> + msg->flags &= ~LOG_NOCONS;
> + console_prev = msg->flags;
> + goto skip;
> + }
> +
> + level = msg->level;
> + len = msg_print_text(msg, console_prev, false,
> + text, sizeof(text));
> + syslog_ns->console_idx =
> + log_next(syslog_ns->console_idx, syslog_ns);
> + syslog_ns->console_seq++;
> + console_prev = msg->flags;
> + raw_spin_unlock(&syslog_ns->logbuf_lock);
> +
> + stop_critical_timings(); /* don't trace print latency */
> + call_console_drivers(level, text, len);
> + start_critical_timings();
> + local_irq_restore(flags);
> + }
> + console_locked = 0;
> +
> + /* Release the exclusive_console once it is used */
> + if (unlikely(exclusive_console))
> + exclusive_console = NULL;
> +
> + raw_spin_unlock(&syslog_ns->logbuf_lock);
> +
> + up(&console_sem);
> +
> + /*
> + * Someone could have filled up the buffer again, so re-check if there's
> + * something to flush. In case we cannot trylock the console_sem again,
> + * there's a new owner and the console_unlock() from them will do the
> + * flush, no worries.
> + */
> + raw_spin_lock(&syslog_ns->logbuf_lock);
> + retry = syslog_ns->console_seq != syslog_ns->log_next_seq;
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
> +
> + if (retry && console_trylock())
> + goto again;
> +
> + if (wake_klogd)
> + wake_up_klogd();
> }
>
> /**
> @@ -2027,6 +2137,7 @@ out:
> void console_unlock(void)
> {
> static char text[LOG_LINE_MAX + PREFIX_MAX];
> + struct syslog_namespace *syslog_ns = current_syslog_ns();
> static u64 seen_seq;
> unsigned long flags;
> bool wake_klogd = false;
> @@ -2040,37 +2151,38 @@ void console_unlock(void)
> console_may_schedule = 0;
>
> /* flush buffered message fragment immediately to console */
> - console_cont_flush(text, sizeof(text));
> + console_cont_flush(text, sizeof(text), syslog_ns);
> again:
> for (;;) {
> struct log *msg;
> size_t len;
> int level;
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> - if (seen_seq != log_next_seq) {
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
> + if (seen_seq != syslog_ns->log_next_seq) {
> wake_klogd = true;
> - seen_seq = log_next_seq;
> + seen_seq = syslog_ns->log_next_seq;
> }
>
> - if (console_seq < log_first_seq) {
> + if (syslog_ns->console_seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to first one */
> - console_seq = log_first_seq;
> - console_idx = log_first_idx;
> + syslog_ns->console_seq = syslog_ns->log_first_seq;
> + syslog_ns->console_idx = syslog_ns->log_first_idx;
> console_prev = 0;
> }
> skip:
> - if (console_seq == log_next_seq)
> + if (syslog_ns->console_seq == syslog_ns->log_next_seq)
> break;
>
> - msg = log_from_idx(console_idx);
> + msg = log_from_idx(syslog_ns->console_idx, syslog_ns);
> if (msg->flags & LOG_NOCONS) {
> /*
> * Skip record we have buffered and already printed
> * directly to the console when we received it.
> */
> - console_idx = log_next(console_idx);
> - console_seq++;
> + syslog_ns->console_idx =
> + log_next(syslog_ns->console_idx, syslog_ns);
> + syslog_ns->console_seq++;
> /*
> * We will get here again when we register a new
> * CON_PRINTBUFFER console. Clear the flag so we
> @@ -2084,10 +2196,11 @@ skip:
> level = msg->level;
> len = msg_print_text(msg, console_prev, false,
> text, sizeof(text));
> - console_idx = log_next(console_idx);
> - console_seq++;
> + syslog_ns->console_idx =
> + log_next(syslog_ns->console_idx, syslog_ns);
> + syslog_ns->console_seq++;
> console_prev = msg->flags;
> - raw_spin_unlock(&logbuf_lock);
> + raw_spin_unlock(&syslog_ns->logbuf_lock);
>
> stop_critical_timings(); /* don't trace print latency */
> call_console_drivers(level, text, len);
> @@ -2100,7 +2213,7 @@ skip:
> if (unlikely(exclusive_console))
> exclusive_console = NULL;
>
> - raw_spin_unlock(&logbuf_lock);
> + raw_spin_unlock(&syslog_ns->logbuf_lock);
>
> up(&console_sem);
>
> @@ -2110,9 +2223,9 @@ skip:
> * there's a new owner and the console_unlock() from them will do the
> * flush, no worries.
> */
> - raw_spin_lock(&logbuf_lock);
> - retry = console_seq != log_next_seq;
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_lock(&syslog_ns->logbuf_lock);
> + retry = syslog_ns->console_seq != syslog_ns->log_next_seq;
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
>
> if (retry && console_trylock())
> goto again;
> @@ -2237,6 +2350,7 @@ void register_console(struct console *newcon)
> int i;
> unsigned long flags;
> struct console *bcon = NULL;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
>
> /*
> * before we register a new CON_BOOT console, make sure we don't
> @@ -2346,11 +2460,11 @@ void register_console(struct console *newcon)
> * console_unlock(); will print out the buffered messages
> * for us.
> */
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> - console_seq = syslog_seq;
> - console_idx = syslog_idx;
> - console_prev = syslog_prev;
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
> + syslog_ns->console_seq = syslog_ns->syslog_seq;
> + syslog_ns->console_idx = syslog_ns->syslog_idx;
> + console_prev = syslog_ns->syslog_prev;
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
> /*
> * We're about to replay the log buffer. Only do this to the
> * just-registered console to avoid excessive message spam to
> @@ -2573,6 +2687,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
> {
> struct kmsg_dumper *dumper;
> unsigned long flags;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
>
> if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
> return;
> @@ -2585,12 +2700,12 @@ void kmsg_dump(enum kmsg_dump_reason reason)
> /* initialize iterator with data about the stored records */
> dumper->active = true;
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> - dumper->cur_seq = clear_seq;
> - dumper->cur_idx = clear_idx;
> - dumper->next_seq = log_next_seq;
> - dumper->next_idx = log_next_idx;
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
> + dumper->cur_seq = syslog_ns->clear_seq;
> + dumper->cur_idx = syslog_ns->clear_idx;
> + dumper->next_seq = syslog_ns->log_next_seq;
> + dumper->next_idx = syslog_ns->log_next_idx;
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
>
> /* invoke dumper which will iterate over records */
> dumper->dump(dumper, reason);
> @@ -2626,24 +2741,25 @@ bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
> struct log *msg;
> size_t l = 0;
> bool ret = false;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
>
> if (!dumper->active)
> goto out;
>
> - if (dumper->cur_seq < log_first_seq) {
> + if (dumper->cur_seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to first available one */
> - dumper->cur_seq = log_first_seq;
> - dumper->cur_idx = log_first_idx;
> + dumper->cur_seq = syslog_ns->log_first_seq;
> + dumper->cur_idx = syslog_ns->log_first_idx;
> }
>
> /* last entry */
> - if (dumper->cur_seq >= log_next_seq)
> + if (dumper->cur_seq >= syslog_ns->log_next_seq)
> goto out;
>
> - msg = log_from_idx(dumper->cur_idx);
> + msg = log_from_idx(dumper->cur_idx, syslog_ns);
> l = msg_print_text(msg, 0, syslog, line, size);
>
> - dumper->cur_idx = log_next(dumper->cur_idx);
> + dumper->cur_idx = log_next(dumper->cur_idx, syslog_ns);
> dumper->cur_seq++;
> ret = true;
> out:
> @@ -2674,10 +2790,12 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
> {
> unsigned long flags;
> bool ret;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
> +
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len);
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
>
> return ret;
> }
> @@ -2713,20 +2831,21 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
> enum log_flags prev;
> size_t l = 0;
> bool ret = false;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
>
> if (!dumper->active)
> goto out;
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> - if (dumper->cur_seq < log_first_seq) {
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
> + if (dumper->cur_seq < syslog_ns->log_first_seq) {
> /* messages are gone, move to first available one */
> - dumper->cur_seq = log_first_seq;
> - dumper->cur_idx = log_first_idx;
> + dumper->cur_seq = syslog_ns->log_first_seq;
> + dumper->cur_idx = syslog_ns->log_first_idx;
> }
>
> /* last entry */
> if (dumper->cur_seq >= dumper->next_seq) {
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
> goto out;
> }
>
> @@ -2735,10 +2854,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
> idx = dumper->cur_idx;
> prev = 0;
> while (seq < dumper->next_seq) {
> - struct log *msg = log_from_idx(idx);
> + struct log *msg = log_from_idx(idx, syslog_ns);
>
> l += msg_print_text(msg, prev, true, NULL, 0);
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> prev = msg->flags;
> }
> @@ -2748,10 +2867,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
> idx = dumper->cur_idx;
> prev = 0;
> while (l > size && seq < dumper->next_seq) {
> - struct log *msg = log_from_idx(idx);
> + struct log *msg = log_from_idx(idx, syslog_ns);
>
> l -= msg_print_text(msg, prev, true, NULL, 0);
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> prev = msg->flags;
> }
> @@ -2763,10 +2882,10 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
> l = 0;
> prev = 0;
> while (seq < dumper->next_seq) {
> - struct log *msg = log_from_idx(idx);
> + struct log *msg = log_from_idx(idx, syslog_ns);
>
> l += msg_print_text(msg, prev, syslog, buf + l, size - l);
> - idx = log_next(idx);
> + idx = log_next(idx, syslog_ns);
> seq++;
> prev = msg->flags;
> }
> @@ -2774,7 +2893,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
> dumper->next_seq = next_seq;
> dumper->next_idx = next_idx;
> ret = true;
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
> out:
> if (len)
> *len = l;
> @@ -2794,10 +2913,12 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
> */
> void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
> {
> - dumper->cur_seq = clear_seq;
> - dumper->cur_idx = clear_idx;
> - dumper->next_seq = log_next_seq;
> - dumper->next_idx = log_next_idx;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
> +
> + dumper->cur_seq = syslog_ns->clear_seq;
> + dumper->cur_idx = syslog_ns->clear_idx;
> + dumper->next_seq = syslog_ns->log_next_seq;
> + dumper->next_idx = syslog_ns->log_next_idx;
> }
>
> /**
> @@ -2811,10 +2932,12 @@ void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
> void kmsg_dump_rewind(struct kmsg_dumper *dumper)
> {
> unsigned long flags;
> + struct syslog_namespace *syslog_ns = &init_syslog_ns;
> +
> + raw_spin_lock_irqsave(&syslog_ns->logbuf_lock, flags);
>
> - raw_spin_lock_irqsave(&logbuf_lock, flags);
> kmsg_dump_rewind_nolock(dumper);
> - raw_spin_unlock_irqrestore(&logbuf_lock, flags);
> + raw_spin_unlock_irqrestore(&syslog_ns->logbuf_lock, flags);
> }
> EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
> #endif
> --
> 1.7.1
>
> _______________________________________________
> Containers mailing list
> Containers@...ts.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/containers
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists