diff options
author | Kay Sievers <kay@vrfy.org> | 2012-07-07 22:09:24 +0200 |
---|---|---|
committer | Kay Sievers <kay@vrfy.org> | 2012-07-07 22:09:24 +0200 |
commit | 84086010c19ee24301fd8924875bf618da231edf (patch) | |
tree | da63ad695e3f96438f12747ab6d6d0dab6a2adc1 | |
parent | 24342b8926c01991984ecd82c91a1f45dedb9d3f (diff) | |
download | patches-84086010c19ee24301fd8924875bf618da231edf.tar.gz |
remove merged patches, add cont merge fix
-rw-r--r-- | 00-kmsg-spinlock_irq.patch | 113 | ||||
-rw-r--r-- | 01-kmsg-escape.patch | 36 | ||||
-rw-r--r-- | 02-kmsg-facility-len.patch | 45 | ||||
-rw-r--r-- | 03-kmsg-nonblock-race.patch | 62 | ||||
-rw-r--r-- | 04-kmsg-cons-fix.patch | 30 | ||||
-rw-r--r-- | kmsg-merge-cont.patch | 381 | ||||
-rw-r--r-- | series | 6 |
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; @@ -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 |