summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-07-07 22:09:24 +0200
committerKay Sievers <kay@vrfy.org>2012-07-07 22:09:24 +0200
commit84086010c19ee24301fd8924875bf618da231edf (patch)
treeda63ad695e3f96438f12747ab6d6d0dab6a2adc1
parent24342b8926c01991984ecd82c91a1f45dedb9d3f (diff)
downloadpatches-84086010c19ee24301fd8924875bf618da231edf.tar.gz
remove merged patches, add cont merge fix
-rw-r--r--00-kmsg-spinlock_irq.patch113
-rw-r--r--01-kmsg-escape.patch36
-rw-r--r--02-kmsg-facility-len.patch45
-rw-r--r--03-kmsg-nonblock-race.patch62
-rw-r--r--04-kmsg-cons-fix.patch30
-rw-r--r--kmsg-merge-cont.patch381
-rw-r--r--series6
7 files changed, 382 insertions, 291 deletions
diff --git a/00-kmsg-spinlock_irq.patch b/00-kmsg-spinlock_irq.patch
deleted file mode 100644
index 7043be8..0000000
--- a/00-kmsg-spinlock_irq.patch
+++ /dev/null
@@ -1,113 +0,0 @@
-From: liu chuansheng <chuansheng.liu@intel.com>
-Subject: [PATCH] printk: replacing the raw_spin_lock/unlock with raw_spin_lock/unlock_irq
-
-In function devkmsg_read/writev/llseek/poll/open()..., the function
-raw_spin_lock/unlock is used, there is potential deadlock case happening.
-CPU1: thread1 doing the cat /dev/kmsg:
- raw_spin_lock(&logbuf_lock);
- while (user->seq == log_next_seq) {
-when thread1 run here, at this time one interrupt is coming on CPU1 and running
-based on this thread,if the interrupt handle called the printk which need the
-logbuf_lock spin also, it will cause deadlock.
-
-So we should use raw_spin_lock/unlock_irq here.
-
-Acked-by: Kay Sievers <kay@vrfy.org>
-Signed-off-by: liu chuansheng <chuansheng.liu@intel.com>
----
- kernel/printk.c | 24 ++++++++++++------------
- 1 file changed, 12 insertions(+), 12 deletions(-)
-
---- a/kernel/printk.c
-+++ b/kernel/printk.c
-@@ -430,20 +430,20 @@ static ssize_t devkmsg_read(struct file
- ret = mutex_lock_interruptible(&user->lock);
- if (ret)
- return ret;
-- raw_spin_lock(&logbuf_lock);
-+ raw_spin_lock_irq(&logbuf_lock);
- while (user->seq == log_next_seq) {
- if (file->f_flags & O_NONBLOCK) {
- ret = -EAGAIN;
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
- goto out;
- }
-
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
- ret = wait_event_interruptible(log_wait,
- user->seq != log_next_seq);
- if (ret)
- goto out;
-- raw_spin_lock(&logbuf_lock);
-+ raw_spin_lock_irq(&logbuf_lock);
- }
-
- if (user->seq < log_first_seq) {
-@@ -451,7 +451,7 @@ static ssize_t devkmsg_read(struct file
- user->idx = log_first_idx;
- user->seq = log_first_seq;
- ret = -EPIPE;
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
- goto out;
- }
-
-@@ -501,7 +501,7 @@ static ssize_t devkmsg_read(struct file
-
- user->idx = log_next(user->idx);
- user->seq++;
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
-
- if (len > count) {
- ret = -EINVAL;
-@@ -528,7 +528,7 @@ static loff_t devkmsg_llseek(struct file
- if (offset)
- return -ESPIPE;
-
-- raw_spin_lock(&logbuf_lock);
-+ raw_spin_lock_irq(&logbuf_lock);
- switch (whence) {
- case SEEK_SET:
- /* the first record */
-@@ -552,7 +552,7 @@ static loff_t devkmsg_llseek(struct file
- default:
- ret = -EINVAL;
- }
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
- return ret;
- }
-
-@@ -566,14 +566,14 @@ static unsigned int devkmsg_poll(struct
-
- poll_wait(file, &log_wait, wait);
-
-- raw_spin_lock(&logbuf_lock);
-+ raw_spin_lock_irq(&logbuf_lock);
- if (user->seq < log_next_seq) {
- /* return error when data has vanished underneath us */
- if (user->seq < log_first_seq)
- ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI;
- ret = POLLIN|POLLRDNORM;
- }
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
-
- return ret;
- }
-@@ -597,10 +597,10 @@ static int devkmsg_open(struct inode *in
-
- mutex_init(&user->lock);
-
-- raw_spin_lock(&logbuf_lock);
-+ raw_spin_lock_irq(&logbuf_lock);
- user->idx = log_first_idx;
- user->seq = log_first_seq;
-- raw_spin_unlock(&logbuf_lock);
-+ raw_spin_unlock_irq(&logbuf_lock);
-
- file->private_data = user;
- return 0;
diff --git a/01-kmsg-escape.patch b/01-kmsg-escape.patch
deleted file mode 100644
index 7a01496..0000000
--- a/01-kmsg-escape.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From: Kay Sievers <kay@vrfy.org>
-Subject: kmsg: escape the backslash character while exporting data
-
-Non-printable characters in the log data are hex-escaped to ensure safe
-post processing. We need to escape a backslash we find in the data, to be
-able to distinguish it from a backslash we add for the escaping.
-
-Also escape the non-printable character 127.
-
-Thanks to Miloslav Trmac for the heads up.
-
-Signed-off-by: Kay Sievers <kay@vrfy.org>
----
- kernel/printk.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/kernel/printk.c
-+++ b/kernel/printk.c
-@@ -465,7 +465,7 @@ static ssize_t devkmsg_read(struct file
- for (i = 0; i < msg->text_len; i++) {
- unsigned char c = log_text(msg)[i];
-
-- if (c < ' ' || c >= 128)
-+ if (c < ' ' || c >= 127 || c == '\\')
- len += sprintf(user->buf + len, "\\x%02x", c);
- else
- user->buf[len++] = c;
-@@ -489,7 +489,7 @@ static ssize_t devkmsg_read(struct file
- continue;
- }
-
-- if (c < ' ' || c >= 128) {
-+ if (c < ' ' || c >= 127 || c == '\\') {
- len += sprintf(user->buf + len, "\\x%02x", c);
- continue;
- }
diff --git a/02-kmsg-facility-len.patch b/02-kmsg-facility-len.patch
deleted file mode 100644
index 2ed06c7..0000000
--- a/02-kmsg-facility-len.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-From: Kay Sievers <kay@vrfy.org>
-Subject: kmsg: add the facility number to the syslog prefix
-
-After the recent split of facility and level into separate variables,
-we miss the facility value (always 0 for kernel-originated messages)
-in the syslog prefix.
-
-On Tue, Jul 3, 2012 at 12:45 PM, Dan Carpenter <dan.carpenter@oracle.com> wrote:
-> Static checkers complain about the impossible condition here.
->
-> In 084681d14e ('printk: flush continuation lines immediately to
-> console'), we changed msg->level from being a u16 to being an unsigned
-> 3 bit bitfield.
-
-Cc: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Kay Sievers <kay@vrfy.org>
----
- kernel/printk.c | 11 +++++++----
- 1 file changed, 7 insertions(+), 4 deletions(-)
-
---- a/kernel/printk.c
-+++ b/kernel/printk.c
-@@ -818,15 +818,18 @@ static size_t print_time(u64 ts, char *b
- static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
- {
- size_t len = 0;
-+ unsigned int prefix = (msg->facility << 3) | msg->level;
-
- if (syslog) {
- if (buf) {
-- len += sprintf(buf, "<%u>", msg->level);
-+ len += sprintf(buf, "<%u>", prefix);
- } else {
- len += 3;
-- if (msg->level > 9)
-- len++;
-- if (msg->level > 99)
-+ if (prefix > 999)
-+ len += 3;
-+ else if (prefix > 99)
-+ len += 2;
-+ else if (prefix > 9)
- len++;
- }
- }
diff --git a/03-kmsg-nonblock-race.patch b/03-kmsg-nonblock-race.patch
deleted file mode 100644
index 0135227..0000000
--- a/03-kmsg-nonblock-race.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From: Kay Sievers <kay@vrfy.org>
-Subject: kmsg: properly handle concurrent non-blocking read() from /proc/kmsg
-
-The /proc/kmsg read() interface is internally simply wired up to a sequence
-of syslog() syscalls, which might are racy between their checks and actions,
-regarding concurrency.
-
-In the (very uncommon) case of concurrent readers of /dev/kmsg, relying on
-usual O_NONBLOCK behavior, the recently introduced mutex might block an
-O_NONBLOCK reader in read(), when poll() returns for it, but another process
-has already read the data in the meantime. We've seen that while running
-artificial test setups and tools that "fight" about /proc/kmsg data.
-
-This restores the original /proc/kmsg behavior, where in case of concurrent
-read()s, poll() might wake up but the read() syscall will just return 0 to
-the caller, while another process has "stolen" the data.
-
-This is in the general case not the expected behavior, but it is the exact
-same one, that can easily be triggered with a 3.4 kernel, and some tools
-might just rely on it.
-
-The mutex is not needed, the original integrity issue which introduced it,
-is in the meantime covered by:
- "fill buffer with more than a single message for SYSLOG_ACTION_READ"
- 116e90b23f74d303e8d607c7a7d54f60f14ab9f2
-
-Cc: Yuanhan Liu <yuanhan.liu@linux.intel.com>
-Acked-by: Jan Beulich <jbeulich@suse.com>
-Signed-off-by: Kay Sievers <kay@vrfy.org>
----
- kernel/printk.c | 9 +--------
- 1 file changed, 1 insertion(+), 8 deletions(-)
-
---- a/kernel/printk.c
-+++ b/kernel/printk.c
-@@ -1021,7 +1021,6 @@ int do_syslog(int type, char __user *buf
- {
- bool clear = false;
- static int saved_console_loglevel = -1;
-- static DEFINE_MUTEX(syslog_mutex);
- int error;
-
- error = check_syslog_permissions(type, from_file);
-@@ -1048,17 +1047,11 @@ int do_syslog(int type, char __user *buf
- error = -EFAULT;
- goto out;
- }
-- error = mutex_lock_interruptible(&syslog_mutex);
-- if (error)
-- goto out;
- error = wait_event_interruptible(log_wait,
- syslog_seq != log_next_seq);
-- if (error) {
-- mutex_unlock(&syslog_mutex);
-+ if (error)
- goto out;
-- }
- error = syslog_print(buf, len);
-- mutex_unlock(&syslog_mutex);
- break;
- /* Read/clear last kernel messages */
- case SYSLOG_ACTION_READ_CLEAR:
diff --git a/04-kmsg-cons-fix.patch b/04-kmsg-cons-fix.patch
deleted file mode 100644
index 113d3d7..0000000
--- a/04-kmsg-cons-fix.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From: Kay Sievers <kay@vrfy.org>
-Subject: kmsg: make sure all messages reach a newly registered boot console
-
-We suppress printing kmsg records to the console, which are already printed
-immediately while we have received their fragments.
-
-Newly registered boot consoles print the entire kmsg buffer during
-registration. Clear the console-suppress flag after we skipped the record
-during its first storage, so any later print will see these records as usual.
-
-Signed-off-by: Kay Sievers <kay@vrfy.org>
----
- kernel/printk.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/kernel/printk.c
-+++ b/kernel/printk.c
-@@ -1953,6 +1953,12 @@ skip:
- */
- console_idx = log_next(console_idx);
- 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;
- goto skip;
- }
-
diff --git a/kmsg-merge-cont.patch b/kmsg-merge-cont.patch
new file mode 100644
index 0000000..98e4914
--- /dev/null
+++ b/kmsg-merge-cont.patch
@@ -0,0 +1,381 @@
+diff --git a/kernel/printk.c b/kernel/printk.c
+index f02f1f5..fe9fd52 100644
+--- a/kernel/printk.c
++++ b/kernel/printk.c
+@@ -194,8 +194,10 @@ static int console_may_schedule;
+ */
+
+ enum log_flags {
+- LOG_DEFAULT = 0,
+- LOG_NOCONS = 1, /* already flushed, do not print to console */
++ LOG_NOCONS = 1, /* already flushed, do not print to console */
++ LOG_NEWLINE = 2, /* text ended with a newline */
++ LOG_PREFIX = 4, /* text started with a prefix */
++ LOG_CONT = 8, /* text is part of continuation line */
+ };
+
+ struct log {
+@@ -838,8 +840,8 @@ static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
+ return len;
+ }
+
+-static size_t msg_print_text(const struct log *msg, bool syslog,
+- char *buf, size_t size)
++static size_t msg_print_text(const struct log *msg, enum log_flags prev,
++ bool syslog, char *buf, size_t size)
+ {
+ const char *text = log_text(msg);
+ size_t text_size = msg->text_len;
+@@ -848,6 +850,8 @@ static size_t msg_print_text(const struct log *msg, bool syslog,
+ do {
+ const char *next = memchr(text, '\n', text_size);
+ size_t text_len;
++ bool prefix = true;
++ bool newline = true;
+
+ if (next) {
+ text_len = next - text;
+@@ -857,19 +861,35 @@ static size_t msg_print_text(const struct log *msg, bool syslog,
+ text_len = text_size;
+ }
+
++ if ((prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))
++ prefix = false;
++
++ if (msg->flags & LOG_CONT) {
++ if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE))
++ prefix = false;
++
++ if (!(msg->flags & LOG_NEWLINE))
++ newline = false;
++ }
++
+ if (buf) {
+ if (print_prefix(msg, syslog, NULL) +
+ text_len + 1>= size - len)
+ break;
+
+- len += print_prefix(msg, syslog, buf + len);
++ if (prefix)
++ len += print_prefix(msg, syslog, buf + len);
+ memcpy(buf + len, text, text_len);
+ len += text_len;
+- buf[len++] = '\n';
++ if (newline)
++ buf[len++] = '\n';
+ } else {
+ /* SYSLOG_ACTION_* buffer size only calculation */
+- len += print_prefix(msg, syslog, NULL);
+- len += text_len + 1;
++ if (prefix)
++ len += print_prefix(msg, syslog, NULL);
++ len += text_len;
++ if (newline)
++ len++;
+ }
+
+ text = next;
+@@ -882,6 +902,7 @@ static int syslog_print(char __user *buf, int size)
+ {
+ char *text;
+ struct log *msg;
++ enum log_flags prev = 0;
+ int len = 0;
+
+ text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+@@ -896,16 +917,18 @@ static int syslog_print(char __user *buf, int size)
+ /* messages are gone, move to first one */
+ syslog_seq = log_first_seq;
+ syslog_idx = log_first_idx;
++ prev = 0;
+ }
+ if (syslog_seq == log_next_seq) {
+ raw_spin_unlock_irq(&logbuf_lock);
+ break;
+ }
+ msg = log_from_idx(syslog_idx);
+- n = msg_print_text(msg, true, text, LOG_LINE_MAX);
++ n = msg_print_text(msg, prev, true, text, LOG_LINE_MAX);
+ if (n <= size) {
+ syslog_idx = log_next(syslog_idx);
+ syslog_seq++;
++ prev = msg->flags;
+ } else
+ n = 0;
+ raw_spin_unlock_irq(&logbuf_lock);
+@@ -944,6 +967,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
+ u64 next_seq;
+ u64 seq;
+ u32 idx;
++ enum log_flags prev;
+
+ if (clear_seq < log_first_seq) {
+ /* messages are gone, move to first available one */
+@@ -957,10 +981,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
+ */
+ seq = clear_seq;
+ idx = clear_idx;
++ prev = 0;
+ while (seq < log_next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+- len += msg_print_text(msg, true, NULL, 0);
++ len += msg_print_text(msg, prev, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
+ }
+@@ -968,10 +993,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
+ /* move first record forward until length fits into the buffer */
+ seq = clear_seq;
+ idx = clear_idx;
++ prev = 0;
+ while (len > size && seq < log_next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+- len -= msg_print_text(msg, true, NULL, 0);
++ len -= msg_print_text(msg, prev, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
+ }
+@@ -980,17 +1006,19 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
+ next_seq = log_next_seq;
+
+ len = 0;
++ prev = 0;
+ while (len >= 0 && seq < next_seq) {
+ struct log *msg = log_from_idx(idx);
+ int textlen;
+
+- textlen = msg_print_text(msg, true, text, LOG_LINE_MAX);
++ textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX);
+ if (textlen < 0) {
+ len = textlen;
+ break;
+ }
+ idx = log_next(idx);
+ seq++;
++ prev = msg->flags;
+
+ raw_spin_unlock_irq(&logbuf_lock);
+ if (copy_to_user(buf + len, text, textlen))
+@@ -1003,6 +1031,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
+ /* messages are gone, move to next one */
+ seq = log_first_seq;
+ idx = log_first_idx;
++ prev = 0;
+ }
+ }
+ }
+@@ -1116,18 +1145,18 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
+ */
+ error = log_next_idx - syslog_idx;
+ } else {
+- u64 seq;
+- u32 idx;
++ u64 seq = syslog_seq;
++ u32 idx = syslog_idx;
++ enum log_flags prev = 0;
+
+ error = 0;
+- seq = syslog_seq;
+- idx = syslog_idx;
+ while (seq < log_next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+- error += msg_print_text(msg, true, NULL, 0);
++ error += msg_print_text(msg, prev, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
++ prev = msg->flags;
+ }
+ }
+ raw_spin_unlock_irq(&logbuf_lock);
+@@ -1396,10 +1425,9 @@ asmlinkage int vprintk_emit(int facility, int level,
+ static char textbuf[LOG_LINE_MAX];
+ char *text = textbuf;
+ size_t text_len;
++ enum log_flags lflags = 0;
+ unsigned long flags;
+ int this_cpu;
+- bool newline = false;
+- bool prefix = false;
+ int printed_len = 0;
+
+ boot_delay_msec();
+@@ -1438,7 +1466,7 @@ asmlinkage int vprintk_emit(int facility, int level,
+ recursion_bug = 0;
+ printed_len += strlen(recursion_msg);
+ /* emit KERN_CRIT message */
+- log_store(0, 2, LOG_DEFAULT, 0,
++ log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
+ NULL, 0, recursion_msg, printed_len);
+ }
+
+@@ -1451,7 +1479,7 @@ asmlinkage int vprintk_emit(int facility, int level,
+ /* mark and strip a trailing newline */
+ if (text_len && text[text_len-1] == '\n') {
+ text_len--;
+- newline = true;
++ lflags |= LOG_NEWLINE;
+ }
+
+ /* strip syslog prefix and extract log level or control flags */
+@@ -1461,7 +1489,7 @@ asmlinkage int vprintk_emit(int facility, int level,
+ if (level == -1)
+ level = text[1] - '0';
+ case 'd': /* KERN_DEFAULT */
+- prefix = true;
++ lflags |= LOG_PREFIX;
+ case 'c': /* KERN_CONT */
+ text += 3;
+ text_len -= 3;
+@@ -1471,22 +1499,20 @@ asmlinkage int vprintk_emit(int facility, int level,
+ if (level == -1)
+ level = default_message_loglevel;
+
+- if (dict) {
+- prefix = true;
+- newline = true;
+- }
++ if (dict)
++ lflags |= LOG_PREFIX|LOG_NEWLINE;
+
+- if (!newline) {
++ if (!(lflags & LOG_NEWLINE)) {
+ /*
+ * Flush the conflicting buffer. An earlier newline was missing,
+ * or another task also prints continuation lines.
+ */
+- if (cont.len && (prefix || cont.owner != current))
++ if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
+ cont_flush();
+
+ /* buffer line if possible, otherwise store it right away */
+ if (!cont_add(facility, level, text, text_len))
+- log_store(facility, level, LOG_DEFAULT, 0,
++ log_store(facility, level, lflags | LOG_CONT, 0,
+ dict, dictlen, text, text_len);
+ } else {
+ bool stored = false;
+@@ -1498,13 +1524,13 @@ asmlinkage int vprintk_emit(int facility, int level,
+ * flush it out and store this line separately.
+ */
+ if (cont.len && cont.owner == current) {
+- if (!prefix)
++ if (!(lflags & LOG_PREFIX))
+ stored = cont_add(facility, level, text, text_len);
+ cont_flush();
+ }
+
+ if (!stored)
+- log_store(facility, level, LOG_DEFAULT, 0,
++ log_store(facility, level, lflags, 0,
+ dict, dictlen, text, text_len);
+ }
+ printed_len += text_len;
+@@ -1603,8 +1629,8 @@ static struct cont {
+ static struct log *log_from_idx(u32 idx) { return NULL; }
+ static u32 log_next(u32 idx) { return 0; }
+ static void call_console_drivers(int level, const char *text, size_t len) {}
+-static size_t msg_print_text(const struct log *msg, bool syslog,
+- char *buf, size_t size) { return 0; }
++static size_t msg_print_text(const struct log *msg, enum log_flags prev,
++ bool syslog, char *buf, size_t size) { return 0; }
+ static size_t cont_print_text(char *text, size_t size) { return 0; }
+
+ #endif /* CONFIG_PRINTK */
+@@ -1901,6 +1927,7 @@ void console_unlock(void)
+ static u64 seen_seq;
+ unsigned long flags;
+ bool wake_klogd = false;
++ enum log_flags prev = 0;
+ bool retry;
+
+ if (console_suspended) {
+@@ -1940,6 +1967,7 @@ again:
+ /* messages are gone, move to first one */
+ console_seq = log_first_seq;
+ console_idx = log_first_idx;
++ prev = 0;
+ }
+ skip:
+ if (console_seq == log_next_seq)
+@@ -1963,10 +1991,11 @@ skip:
+ }
+
+ level = msg->level;
+- len = msg_print_text(msg, false, text, sizeof(text));
++ len = msg_print_text(msg, prev, false, text, sizeof(text));
+
+ console_idx = log_next(console_idx);
+ console_seq++;
++ prev = msg->flags;
+ raw_spin_unlock(&logbuf_lock);
+
+ stop_critical_timings(); /* don't trace print latency */
+@@ -2522,8 +2551,7 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+ }
+
+ msg = log_from_idx(dumper->cur_idx);
+- l = msg_print_text(msg, syslog,
+- line, size);
++ l = msg_print_text(msg, 0, syslog, line, size);
+
+ dumper->cur_idx = log_next(dumper->cur_idx);
+ dumper->cur_seq++;
+@@ -2563,6 +2591,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+ u32 idx;
+ u64 next_seq;
+ u32 next_idx;
++ enum log_flags prev;
+ size_t l = 0;
+ bool ret = false;
+
+@@ -2585,23 +2614,27 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+ /* calculate length of entire buffer */
+ seq = dumper->cur_seq;
+ idx = dumper->cur_idx;
++ prev = 0;
+ while (seq < dumper->next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+- l += msg_print_text(msg, true, NULL, 0);
++ l += msg_print_text(msg, prev, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
++ prev = msg->flags;
+ }
+
+ /* move first record forward until length fits into the buffer */
+ seq = dumper->cur_seq;
+ idx = dumper->cur_idx;
++ prev = 0;
+ while (l > size && seq < dumper->next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+- l -= msg_print_text(msg, true, NULL, 0);
++ l -= msg_print_text(msg, prev, true, NULL, 0);
+ idx = log_next(idx);
+ seq++;
++ prev = msg->flags;
+ }
+
+ /* last message in next interation */
+@@ -2609,14 +2642,16 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+ next_idx = idx;
+
+ l = 0;
++ prev = 0;
+ while (seq < dumper->next_seq) {
+ struct log *msg = log_from_idx(idx);
+
+- l += msg_print_text(msg, syslog,
++ l += msg_print_text(msg, prev, syslog,
+ buf + l, size - l);
+
+ idx = log_next(idx);
+ seq++;
++ prev = msg->flags;
+ }
+
+ dumper->next_seq = next_seq;
diff --git a/series b/series
index fb9a0a1..64bf3f7 100644
--- a/series
+++ b/series
@@ -1,6 +1,2 @@
#test-modules.patch
-00-kmsg-spinlock_irq.patch
-01-kmsg-escape.patch
-02-kmsg-facility-len.patch
-03-kmsg-nonblock-race.patch
-04-kmsg-cons-fix.patch
+kmsg-merge-cont.patch