Quoting Rui Xiang (leo.ruixiang@xxxxxxxxx): > From: Libo Chen <clbchenlibo.chen@xxxxxxxxxx> > > 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@xxxxxxxxxx> > Signed-off-by: Xiang Rui <rui.xiang@xxxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxxxxxxxxxxxxx > https://lists.linuxfoundation.org/mailman/listinfo/containers _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/containers