linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
@ 2012-05-03  0:29 Kay Sievers
  2012-05-03 19:48 ` Peter Zijlstra
                   ` (3 more replies)
  0 siblings, 4 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-03  0:29 UTC (permalink / raw)
  To: Greg Kroah-Hartmann; +Cc: Linus Torvalds, Ingo Molnar, linux-kernel

From: Kay Sievers <kay@vrfy.org>
Subject: printk: convert byte-buffer to variable-length record buffer

- Record-based stream instead of the traditional byte stream
  buffer. All records carry a 64 bit timestamp, the syslog facility
  and priority in the record header.

- Records consume almost the same amount, sometimes less memory than
  the traditional byte stream buffer (if printk_time is enabled). The record
  header is 16 bytes long, plus some padding bytes at the end if needed.
  The byte-stream buffer needed 3 chars for the syslog prefix, 15 char for
  the timestamp and a newline.

- Buffer management is based on message sequence numbers. When records
  need to be discarded, the reading heads move on to the next full
  record. Unlike the byte-stream buffer, no old logged lines get
  truncated or partly overwritten by new ones. Sequence numbers also
  allow consumers of the log stream to get notified if any message in
  the stream they are about to read gets discarded during the time
  of reading.

- Better buffered IO support for KERN_CONT continuation lines, when printk()
  is called multiple times for a single line. The use of KERN_CONT is now
  mandatory to use continuation; a few places in the kernel need trivial fixes
  here. The buffering could possibly be extended to per-cpu variables to allow
  better thread-safety for multiple printk() invocations for a single line.

- Full-featured syslog facility value support. Different facilities
  can tag their messages. All userspace-injected messages enforce a
  facility value > 0 now, to be able to reliably distinguish them from
  the kernel-generated messages. Independent subsystems like a
  baseband processor running its own firmware, or a kernel-related
  userspace process can use their own unique facility values. Multiple
  independent log streams can co-exist that way in the same
  buffer. All share the same global sequence number counter to ensure
  proper ordering (and interleaving) and to allow the consumers of the
  log to reliably correlate the events from different facilities.

Tested-by: William Douglas <william.douglas@intel.com>
Signed-off-by: Kay Sievers <kay@vrfy.org>
---
 drivers/char/mem.c     |   55 +-
 include/linux/printk.h |   11 
 kernel/printk.c        | 1020 ++++++++++++++++++++++++++++---------------------
 3 files changed, 642 insertions(+), 444 deletions(-)

--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -810,33 +810,54 @@ static const struct file_operations oldm
 static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
 			   unsigned long count, loff_t pos)
 {
-	char *line, *p;
+	char *buf, *line;
 	int i;
-	ssize_t ret = -EFAULT;
+	int level = default_message_loglevel;
+	int facility = 1;	/* LOG_USER */
 	size_t len = iov_length(iv, count);
+	ssize_t ret = len;
 
-	line = kmalloc(len + 1, GFP_KERNEL);
-	if (line == NULL)
+	if (len > 1024)
+		return -EINVAL;
+	buf = kmalloc(len+1, GFP_KERNEL);
+	if (buf == NULL)
 		return -ENOMEM;
 
-	/*
-	 * copy all vectors into a single string, to ensure we do
-	 * not interleave our log line with other printk calls
-	 */
-	p = line;
+	line = buf;
 	for (i = 0; i < count; i++) {
-		if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len))
+		if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len))
 			goto out;
-		p += iv[i].iov_len;
+		line += iv[i].iov_len;
+	}
+
+	/*
+	 * Extract and skip the syslog prefix <[0-9]*>. Coming from userspace
+	 * the decimal value represents 32bit, the lower 3 bit are the log
+	 * level, the rest are the log facility.
+	 *
+	 * If no prefix or no userspace facility is specified, we
+	 * enforce LOG_USER, to be able to reliably distinguish
+	 * kernel-generated messages from userspace-injected ones.
+	 */
+	line = buf;
+	if (line[0] == '<') {
+		char *endp = NULL;
+
+		i = simple_strtoul(line+1, &endp, 10);
+		if (endp && endp[0] == '>') {
+			level = i & 7;
+			if (i >> 3)
+				facility = i >> 3;
+			endp++;
+			len -= endp - line;
+			line = endp;
+		}
 	}
-	p[0] = '\0';
+	line[len] = '\0';
 
-	ret = printk("%s", line);
-	/* printk can add a prefix */
-	if (ret > len)
-		ret = len;
+	printk_emit(facility, level, NULL, 0, "%s", line);
 out:
-	kfree(line);
+	kfree(buf);
 	return ret;
 }
 
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -95,8 +95,19 @@ extern int printk_needs_cpu(int cpu);
 extern void printk_tick(void);
 
 #ifdef CONFIG_PRINTK
+asmlinkage __printf(5, 0)
+int vprintk_emit(int facility, int level,
+		 const char *dict, size_t dictlen,
+		 const char *fmt, va_list args);
+
 asmlinkage __printf(1, 0)
 int vprintk(const char *fmt, va_list args);
+
+asmlinkage __printf(5, 6) __cold
+asmlinkage int printk_emit(int facility, int level,
+			   const char *dict, size_t dictlen,
+			   const char *fmt, ...);
+
 asmlinkage __printf(1, 2) __cold
 int printk(const char *fmt, ...);
 
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,8 +54,6 @@ void asmlinkage __attribute__((weak)) ea
 {
 }
 
-#define __LOG_BUF_LEN	(1 << CONFIG_LOG_BUF_SHIFT)
-
 /* printk's without a loglevel use this.. */
 #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
 
@@ -99,24 +97,6 @@ EXPORT_SYMBOL_GPL(console_drivers);
 static int console_locked, console_suspended;
 
 /*
- * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
- * It is also used in interesting ways to provide interlocking in
- * console_unlock();.
- */
-static DEFINE_RAW_SPINLOCK(logbuf_lock);
-
-#define LOG_BUF_MASK (log_buf_len-1)
-#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
-
-/*
- * The indices into log_buf are not constrained to log_buf_len - they
- * must be masked before subscripting
- */
-static unsigned log_start;	/* Index into log_buf: next char to be read by syslog() */
-static unsigned con_start;	/* Index into log_buf: next char to be sent to consoles */
-static unsigned log_end;	/* Index into log_buf: most-recently-written-char + 1 */
-
-/*
  * If exclusive_console is non-NULL then only this console is to be printed to.
  */
 static struct console *exclusive_console;
@@ -146,12 +126,176 @@ EXPORT_SYMBOL(console_set_on_cmdline);
 static int console_may_schedule;
 
 #ifdef CONFIG_PRINTK
+/*
+ * The printk log buffer consists of a chain of concatenated variable
+ * length records. Every record starts with a record header, containing
+ * the overall length of the record.
+ *
+ * The heads to the first and last entry in the buffer, as well as the
+ * sequence numbers of these both entries are maintained when messages
+ * are stored..
+ *
+ * If the heads indicate available messages, the length in the header
+ * tells the start next message. A length == 0 for the next message
+ * indicates a wrap-around to the beginning of the buffer.
+ *
+ * Every record carries the monotonic timestamp in microseconds, as well as
+ * the standard userspace syslog level and syslog facility. The usual
+ * kernel messages use LOG_KERN; userspace-injected messages always carry
+ * a matching syslog facility, by default LOG_USER. The origin of every
+ * message can be reliably determined that way.
+ *
+ * The human readable log message directly follows the message header. The
+ * length of the message text is stored in the header, the stored message
+ * is not terminated.
+ *
+ */
+
+struct log {
+	u64 ts_nsec;		/* timestamp in nanoseconds */
+	u16 len;		/* length of entire record */
+	u16 text_len;		/* length of text buffer */
+	u16 dict_len;		/* length of dictionary buffer */
+	u16 level;		/* syslog level + facility */
+};
+
+/*
+ * 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);
+
+/* cpu currently holding logbuf_lock */
+static volatile unsigned int logbuf_cpu = UINT_MAX;
+
+#define LOG_LINE_MAX 1024
 
+/* record buffer */
+#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
 static char __log_buf[__LOG_BUF_LEN];
 static char *log_buf = __log_buf;
-static int log_buf_len = __LOG_BUF_LEN;
-static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
-static int saved_console_loglevel = -1;
+static u32 log_buf_len = __LOG_BUF_LEN;
+
+/* 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 read after the last 'clear' command */
+static u64 clear_seq;
+static u32 clear_idx;
+
+/* the next printk record to read by syslog(READ) or /proc/kmsg */
+static u64 syslog_seq;
+static u32 syslog_idx;
+
+/* human readable text of the record */
+static char *log_text(const struct log *msg)
+{
+	return (char *)msg + sizeof(struct log);
+}
+
+/* optional key/value pair dictionary attached to the record */
+static char *log_dict(const struct log *msg)
+{
+	return (char *)msg + sizeof(struct log) + msg->text_len;
+}
+
+/* get record by index; idx must point to valid msg */
+static struct log *log_from_idx(u32 idx)
+{
+	struct log *msg = (struct log *)(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 msg;
+}
+
+/* get next record; idx must point to valid msg */
+static u32 log_next(u32 idx)
+{
+	struct log *msg = (struct log *)(log_buf + idx);
+
+	/* length == 0 indicates the end of the buffer; wrap */
+	/*
+	 * A length == 0 record is the end of buffer marker. Wrap around and
+	 * read the message at the start of the buffer as *this* one, and
+	 * return the one after that.
+	 */
+	if (!msg->len) {
+		msg = (struct log *)log_buf;
+		return msg->len;
+	}
+	return idx + msg->len;
+}
+
+#if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+#define LOG_ALIGN 4
+#else
+#define LOG_ALIGN 8
+#endif
+
+/* insert record into the buffer, discard old ones, update heads */
+static void log_store(int facility, int level,
+		      const char *dict, u16 dict_len,
+		      const char *text, u16 text_len)
+{
+	struct log *msg;
+	u32 size, pad_len;
+
+	/* number of '\0' padding bytes to next message */
+	size = sizeof(struct log) + text_len + dict_len;
+	pad_len = (-size) & (LOG_ALIGN - 1);
+	size += pad_len;
+
+	while (log_first_seq < log_next_seq) {
+		u32 free;
+
+		if (log_next_idx > log_first_idx)
+			free = max(log_buf_len - log_next_idx, log_first_idx);
+		else
+			free = log_first_idx - 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++;
+	}
+
+	if (log_next_idx + size + sizeof(struct log) >= 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;
+	}
+
+	/* fill message */
+	msg = (struct log *)(log_buf + log_next_idx);
+	memcpy(log_text(msg), text, text_len);
+	msg->text_len = text_len;
+	memcpy(log_dict(msg), dict, dict_len);
+	msg->dict_len = dict_len;
+	msg->level = (facility << 3) | (level & 7);
+	msg->ts_nsec = local_clock();
+	memset(log_dict(msg) + dict_len, 0, pad_len);
+	msg->len = sizeof(struct log) + text_len + dict_len + pad_len;
+
+	/* insert message */
+	log_next_idx += msg->len;
+	log_next_seq++;
+}
 
 #ifdef CONFIG_KEXEC
 /*
@@ -165,9 +309,9 @@ static int saved_console_loglevel = -1;
 void log_buf_kexec_setup(void)
 {
 	VMCOREINFO_SYMBOL(log_buf);
-	VMCOREINFO_SYMBOL(log_end);
 	VMCOREINFO_SYMBOL(log_buf_len);
-	VMCOREINFO_SYMBOL(logged_chars);
+	VMCOREINFO_SYMBOL(log_first_idx);
+	VMCOREINFO_SYMBOL(log_next_idx);
 }
 #endif
 
@@ -191,7 +335,6 @@ early_param("log_buf_len", log_buf_len_s
 void __init setup_log_buf(int early)
 {
 	unsigned long flags;
-	unsigned start, dest_idx, offset;
 	char *new_log_buf;
 	int free;
 
@@ -219,20 +362,8 @@ void __init setup_log_buf(int early)
 	log_buf_len = new_log_buf_len;
 	log_buf = new_log_buf;
 	new_log_buf_len = 0;
-	free = __LOG_BUF_LEN - log_end;
-
-	offset = start = min(con_start, log_start);
-	dest_idx = 0;
-	while (start != log_end) {
-		unsigned log_idx_mask = start & (__LOG_BUF_LEN - 1);
-
-		log_buf[dest_idx] = __log_buf[log_idx_mask];
-		start++;
-		dest_idx++;
-	}
-	log_start -= offset;
-	con_start -= offset;
-	log_end -= offset;
+	free = __LOG_BUF_LEN - log_next_idx;
+	memcpy(log_buf, __log_buf, __LOG_BUF_LEN);
 	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 
 	pr_info("log_buf_len: %d\n", log_buf_len);
@@ -332,11 +463,165 @@ static int check_syslog_permissions(int
 	return 0;
 }
 
+#if defined(CONFIG_PRINTK_TIME)
+static bool printk_time = 1;
+#else
+static bool printk_time;
+#endif
+module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
+
+static int syslog_print_line(u32 idx, char *text, size_t size)
+{
+	struct log *msg;
+	size_t len;
+
+	msg = log_from_idx(idx);
+	if (!text) {
+		/* calculate length only */
+		len = 3;
+
+		if (msg->level > 9)
+			len++;
+		if (msg->level > 99)
+			len++;
+
+		if (printk_time)
+			len += 15;
+
+		len += msg->text_len;
+		len++;
+		return len;
+	}
+
+	len = sprintf(text, "<%u>", msg->level);
+
+	if (printk_time) {
+		unsigned long long t = msg->ts_nsec;
+		unsigned long rem_ns = do_div(t, 1000000000);
+
+		len += sprintf(text + len, "[%5lu.%06lu] ",
+				   (unsigned long) t, rem_ns / 1000);
+	}
+
+	if (len + msg->text_len > size)
+		return -EINVAL;
+	memcpy(text + len, log_text(msg), msg->text_len);
+	len += msg->text_len;
+	text[len++] = '\n';
+	return len;
+}
+
+static int syslog_print(char __user *buf, int size)
+{
+	char *text;
+	int len;
+
+	text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+	if (!text)
+		return -ENOMEM;
+
+	raw_spin_lock_irq(&logbuf_lock);
+	if (syslog_seq < log_first_seq) {
+		/* messages are gone, move to first one */
+		syslog_seq = log_first_seq;
+		syslog_idx = log_first_idx;
+	}
+	len = syslog_print_line(syslog_idx, text, LOG_LINE_MAX);
+	syslog_idx = log_next(syslog_idx);
+	syslog_seq++;
+	raw_spin_unlock_irq(&logbuf_lock);
+
+	if (len > 0 && copy_to_user(buf, text, len))
+		len = -EFAULT;
+
+	kfree(text);
+	return len;
+}
+
+static int syslog_print_all(char __user *buf, int size, bool clear)
+{
+	char *text;
+	int len = 0;
+
+	text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+	if (!text)
+		return -ENOMEM;
+
+	raw_spin_lock_irq(&logbuf_lock);
+	if (buf) {
+		u64 next_seq;
+		u64 seq;
+		u32 idx;
+
+		if (clear_seq < log_first_seq) {
+			/* messages are gone, move to first available one */
+			clear_seq = log_first_seq;
+			clear_idx = 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;
+		while (seq < log_next_seq) {
+			len += syslog_print_line(idx, NULL, 0);
+			idx = log_next(idx);
+			seq++;
+		}
+		seq = clear_seq;
+		idx = clear_idx;
+		while (len > size && seq < log_next_seq) {
+			len -= syslog_print_line(idx, NULL, 0);
+			idx = log_next(idx);
+			seq++;
+		}
+
+		/* last message in this dump */
+		next_seq = log_next_seq;
+
+		len = 0;
+		while (len >= 0 && seq < next_seq) {
+			int textlen;
+
+			textlen = syslog_print_line(idx, text, LOG_LINE_MAX);
+			if (textlen < 0) {
+				len = textlen;
+				break;
+			}
+			idx = log_next(idx);
+			seq++;
+
+			raw_spin_unlock_irq(&logbuf_lock);
+			if (copy_to_user(buf + len, text, textlen))
+				len = -EFAULT;
+			else
+				len += textlen;
+			raw_spin_lock_irq(&logbuf_lock);
+
+			if (seq < log_first_seq) {
+				/* messages are gone, move to next one */
+				seq = log_first_seq;
+				idx = log_first_idx;
+			}
+		}
+	}
+
+	if (clear) {
+		clear_seq = log_next_seq;
+		clear_idx = log_next_idx;
+	}
+	raw_spin_unlock_irq(&logbuf_lock);
+
+	kfree(text);
+	return len;
+}
+
 int do_syslog(int type, char __user *buf, int len, bool from_file)
 {
-	unsigned i, j, limit, count;
-	int do_clear = 0;
-	char c;
+	bool clear = false;
+	static int saved_console_loglevel = -1;
 	int error;
 
 	error = check_syslog_permissions(type, from_file);
@@ -364,28 +649,14 @@ int do_syslog(int type, char __user *buf
 			goto out;
 		}
 		error = wait_event_interruptible(log_wait,
-							(log_start - log_end));
+						 syslog_seq != log_next_seq);
 		if (error)
 			goto out;
-		i = 0;
-		raw_spin_lock_irq(&logbuf_lock);
-		while (!error && (log_start != log_end) && i < len) {
-			c = LOG_BUF(log_start);
-			log_start++;
-			raw_spin_unlock_irq(&logbuf_lock);
-			error = __put_user(c,buf);
-			buf++;
-			i++;
-			cond_resched();
-			raw_spin_lock_irq(&logbuf_lock);
-		}
-		raw_spin_unlock_irq(&logbuf_lock);
-		if (!error)
-			error = i;
+		error = syslog_print(buf, len);
 		break;
 	/* Read/clear last kernel messages */
 	case SYSLOG_ACTION_READ_CLEAR:
-		do_clear = 1;
+		clear = true;
 		/* FALL THRU */
 	/* Read last kernel messages */
 	case SYSLOG_ACTION_READ_ALL:
@@ -399,52 +670,11 @@ int do_syslog(int type, char __user *buf
 			error = -EFAULT;
 			goto out;
 		}
-		count = len;
-		if (count > log_buf_len)
-			count = log_buf_len;
-		raw_spin_lock_irq(&logbuf_lock);
-		if (count > logged_chars)
-			count = logged_chars;
-		if (do_clear)
-			logged_chars = 0;
-		limit = log_end;
-		/*
-		 * __put_user() could sleep, and while we sleep
-		 * printk() could overwrite the messages
-		 * we try to copy to user space. Therefore
-		 * the messages are copied in reverse. <manfreds>
-		 */
-		for (i = 0; i < count && !error; i++) {
-			j = limit-1-i;
-			if (j + log_buf_len < log_end)
-				break;
-			c = LOG_BUF(j);
-			raw_spin_unlock_irq(&logbuf_lock);
-			error = __put_user(c,&buf[count-1-i]);
-			cond_resched();
-			raw_spin_lock_irq(&logbuf_lock);
-		}
-		raw_spin_unlock_irq(&logbuf_lock);
-		if (error)
-			break;
-		error = i;
-		if (i != count) {
-			int offset = count-error;
-			/* buffer overflow during copy, correct user buffer. */
-			for (i = 0; i < error; i++) {
-				if (__get_user(c,&buf[i+offset]) ||
-				    __put_user(c,&buf[i])) {
-					error = -EFAULT;
-					break;
-				}
-				cond_resched();
-			}
-		}
+		error = syslog_print_all(buf, len, clear);
 		break;
 	/* Clear ring buffer */
 	case SYSLOG_ACTION_CLEAR:
-		logged_chars = 0;
-		break;
+		syslog_print_all(NULL, 0, true);
 	/* Disable logging to console */
 	case SYSLOG_ACTION_CONSOLE_OFF:
 		if (saved_console_loglevel == -1)
@@ -472,7 +702,33 @@ int do_syslog(int type, char __user *buf
 		break;
 	/* Number of chars in the log buffer */
 	case SYSLOG_ACTION_SIZE_UNREAD:
-		error = log_end - log_start;
+		raw_spin_lock_irq(&logbuf_lock);
+		if (syslog_seq < log_first_seq) {
+			/* messages are gone, move to first one */
+			syslog_seq = log_first_seq;
+			syslog_idx = log_first_idx;
+		}
+		if (from_file) {
+			/*
+			 * Short-cut for poll(/"proc/kmsg") which simply checks
+			 * for pending data, not the size; return the count of
+			 * records, not the length.
+			 */
+			error = log_next_idx - syslog_idx;
+		} else {
+			u64 seq;
+			u32 idx;
+
+			error = 0;
+			seq = syslog_seq;
+			idx = syslog_idx;
+			while (seq < log_next_seq) {
+				error += syslog_print_line(idx, NULL, 0);
+				idx = log_next(idx);
+				seq++;
+			}
+		}
+		raw_spin_unlock_irq(&logbuf_lock);
 		break;
 	/* Size of the log buffer */
 	case SYSLOG_ACTION_SIZE_BUFFER:
@@ -501,29 +757,11 @@ void kdb_syslog_data(char *syslog_data[4
 {
 	syslog_data[0] = log_buf;
 	syslog_data[1] = log_buf + log_buf_len;
-	syslog_data[2] = log_buf + log_end -
-		(logged_chars < log_buf_len ? logged_chars : log_buf_len);
-	syslog_data[3] = log_buf + log_end;
+	syslog_data[2] = log_buf + log_first_idx;
+	syslog_data[3] = log_buf + log_next_idx;
 }
 #endif	/* CONFIG_KGDB_KDB */
 
-/*
- * Call the console drivers on a range of log_buf
- */
-static void __call_console_drivers(unsigned start, unsigned end)
-{
-	struct console *con;
-
-	for_each_console(con) {
-		if (exclusive_console && con != exclusive_console)
-			continue;
-		if ((con->flags & CON_ENABLED) && con->write &&
-				(cpu_online(smp_processor_id()) ||
-				(con->flags & CON_ANYTIME)))
-			con->write(con, &LOG_BUF(start), end - start);
-	}
-}
-
 static bool __read_mostly ignore_loglevel;
 
 static int __init ignore_loglevel_setup(char *str)
@@ -540,142 +778,33 @@ MODULE_PARM_DESC(ignore_loglevel, "ignor
 	"print all kernel messages to the console.");
 
 /*
- * Write out chars from start to end - 1 inclusive
- */
-static void _call_console_drivers(unsigned start,
-				unsigned end, int msg_log_level)
-{
-	trace_console(&LOG_BUF(0), start, end, log_buf_len);
-
-	if ((msg_log_level < console_loglevel || ignore_loglevel) &&
-			console_drivers && start != end) {
-		if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
-			/* wrapped write */
-			__call_console_drivers(start & LOG_BUF_MASK,
-						log_buf_len);
-			__call_console_drivers(0, end & LOG_BUF_MASK);
-		} else {
-			__call_console_drivers(start, end);
-		}
-	}
-}
-
-/*
- * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the
- * lower 3 bit are the log level, the rest are the log facility. In case
- * userspace passes usual userspace syslog messages to /dev/kmsg or
- * /dev/ttyprintk, the log prefix might contain the facility. Printk needs
- * to extract the correct log level for in-kernel processing, and not mangle
- * the original value.
- *
- * If a prefix is found, the length of the prefix is returned. If 'level' is
- * passed, it will be filled in with the log level without a possible facility
- * value. If 'special' is passed, the special printk prefix chars are accepted
- * and returned. If no valid header is found, 0 is returned and the passed
- * variables are not touched.
- */
-static size_t log_prefix(const char *p, unsigned int *level, char *special)
-{
-	unsigned int lev = 0;
-	char sp = '\0';
-	size_t len;
-
-	if (p[0] != '<' || !p[1])
-		return 0;
-	if (p[2] == '>') {
-		/* usual single digit level number or special char */
-		switch (p[1]) {
-		case '0' ... '7':
-			lev = p[1] - '0';
-			break;
-		case 'c': /* KERN_CONT */
-		case 'd': /* KERN_DEFAULT */
-			sp = p[1];
-			break;
-		default:
-			return 0;
-		}
-		len = 3;
-	} else {
-		/* multi digit including the level and facility number */
-		char *endp = NULL;
-
-		lev = (simple_strtoul(&p[1], &endp, 10) & 7);
-		if (endp == NULL || endp[0] != '>')
-			return 0;
-		len = (endp + 1) - p;
-	}
-
-	/* do not accept special char if not asked for */
-	if (sp && !special)
-		return 0;
-
-	if (special) {
-		*special = sp;
-		/* return special char, do not touch level */
-		if (sp)
-			return len;
-	}
-
-	if (level)
-		*level = lev;
-	return len;
-}
-
-/*
  * Call the console drivers, asking them to write out
  * log_buf[start] to log_buf[end - 1].
  * The console_lock must be held.
  */
-static void call_console_drivers(unsigned start, unsigned end)
+static void call_console_drivers(int level, const char *text, size_t len)
 {
-	unsigned cur_index, start_print;
-	static int msg_level = -1;
+	struct console *con;
 
-	BUG_ON(((int)(start - end)) > 0);
+	trace_console(text, 0, len, len);
 
-	cur_index = start;
-	start_print = start;
-	while (cur_index != end) {
-		if (msg_level < 0 && ((end - cur_index) > 2)) {
-			/* strip log prefix */
-			cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL);
-			start_print = cur_index;
-		}
-		while (cur_index != end) {
-			char c = LOG_BUF(cur_index);
-
-			cur_index++;
-			if (c == '\n') {
-				if (msg_level < 0) {
-					/*
-					 * printk() has already given us loglevel tags in
-					 * the buffer.  This code is here in case the
-					 * log buffer has wrapped right round and scribbled
-					 * on those tags
-					 */
-					msg_level = default_message_loglevel;
-				}
-				_call_console_drivers(start_print, cur_index, msg_level);
-				msg_level = -1;
-				start_print = cur_index;
-				break;
-			}
-		}
-	}
-	_call_console_drivers(start_print, end, msg_level);
-}
+	if (level >= console_loglevel && !ignore_loglevel)
+		return;
+	if (!console_drivers)
+		return;
 
-static void emit_log_char(char c)
-{
-	LOG_BUF(log_end) = c;
-	log_end++;
-	if (log_end - log_start > log_buf_len)
-		log_start = log_end - log_buf_len;
-	if (log_end - con_start > log_buf_len)
-		con_start = log_end - log_buf_len;
-	if (logged_chars < log_buf_len)
-		logged_chars++;
+	for_each_console(con) {
+		if (exclusive_console && con != exclusive_console)
+			continue;
+		if (!(con->flags & CON_ENABLED))
+			continue;
+		if (!con->write)
+			continue;
+		if (!cpu_online(smp_processor_id()) &&
+		    !(con->flags & CON_ANYTIME))
+			continue;
+		con->write(con, text, len);
+	}
 }
 
 /*
@@ -700,16 +829,6 @@ static void zap_locks(void)
 	sema_init(&console_sem, 1);
 }
 
-#if defined(CONFIG_PRINTK_TIME)
-static bool printk_time = 1;
-#else
-static bool printk_time = 0;
-#endif
-module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
-
-static bool always_kmsg_dump;
-module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR);
-
 /* Check if we have any console registered that can be called early in boot. */
 static int have_callable_console(void)
 {
@@ -722,51 +841,6 @@ static int have_callable_console(void)
 	return 0;
 }
 
-/**
- * printk - print a kernel message
- * @fmt: format string
- *
- * This is printk().  It can be called from any context.  We want it to work.
- *
- * We try to grab the console_lock.  If we succeed, it's easy - we log the output and
- * call the console drivers.  If we fail to get the semaphore we place the output
- * into the log buffer and return.  The current holder of the console_sem will
- * notice the new output in console_unlock(); and will send it to the
- * consoles before releasing the lock.
- *
- * One effect of this deferred printing is that code which calls printk() and
- * then changes console_loglevel may break. This is because console_loglevel
- * is inspected when the actual printing occurs.
- *
- * See also:
- * printf(3)
- *
- * See the vsnprintf() documentation for format string extensions over C99.
- */
-
-asmlinkage int printk(const char *fmt, ...)
-{
-	va_list args;
-	int r;
-
-#ifdef CONFIG_KGDB_KDB
-	if (unlikely(kdb_trap_printk)) {
-		va_start(args, fmt);
-		r = vkdb_printf(fmt, args);
-		va_end(args);
-		return r;
-	}
-#endif
-	va_start(args, fmt);
-	r = vprintk(fmt, args);
-	va_end(args);
-
-	return r;
-}
-
-/* cpu currently holding logbuf_lock */
-static volatile unsigned int printk_cpu = UINT_MAX;
-
 /*
  * Can we actually use the console at this time on this cpu?
  *
@@ -810,17 +884,12 @@ static int console_trylock_for_printk(un
 			retval = 0;
 		}
 	}
-	printk_cpu = UINT_MAX;
+	logbuf_cpu = UINT_MAX;
 	if (wake)
 		up(&console_sem);
 	raw_spin_unlock(&logbuf_lock);
 	return retval;
 }
-static const char recursion_bug_msg [] =
-		KERN_CRIT "BUG: recent printk recursion!\n";
-static int recursion_bug;
-static int new_text_line = 1;
-static char printk_buf[1024];
 
 int printk_delay_msec __read_mostly;
 
@@ -836,15 +905,22 @@ static inline void printk_delay(void)
 	}
 }
 
-asmlinkage int vprintk(const char *fmt, va_list args)
-{
-	int printed_len = 0;
-	int current_log_level = default_message_loglevel;
+asmlinkage int vprintk_emit(int facility, int level,
+			    const char *dict, size_t dictlen,
+			    const char *fmt, va_list args)
+{
+	static int recursion_bug;
+	static char buf[LOG_LINE_MAX];
+	static size_t buflen;
+	static int buflevel;
+	static char textbuf[LOG_LINE_MAX];
+	char *text = textbuf;
+	size_t textlen;
 	unsigned long flags;
 	int this_cpu;
-	char *p;
-	size_t plen;
-	char special;
+	bool newline = false;
+	bool cont = false;
+	int printed_len = 0;
 
 	boot_delay_msec();
 	printk_delay();
@@ -856,7 +932,7 @@ asmlinkage int vprintk(const char *fmt,
 	/*
 	 * Ouch, printk recursed into itself!
 	 */
-	if (unlikely(printk_cpu == this_cpu)) {
+	if (unlikely(logbuf_cpu == this_cpu)) {
 		/*
 		 * If a crash is occurring during printk() on this CPU,
 		 * then try to get the crash message out but make sure
@@ -873,97 +949,92 @@ asmlinkage int vprintk(const char *fmt,
 
 	lockdep_off();
 	raw_spin_lock(&logbuf_lock);
-	printk_cpu = this_cpu;
+	logbuf_cpu = this_cpu;
 
 	if (recursion_bug) {
+		static const char recursion_msg[] =
+			"BUG: recent printk recursion!";
+
 		recursion_bug = 0;
-		strcpy(printk_buf, recursion_bug_msg);
-		printed_len = strlen(recursion_bug_msg);
-	}
-	/* Emit the output into the temporary buffer */
-	printed_len += vscnprintf(printk_buf + printed_len,
-				  sizeof(printk_buf) - printed_len, fmt, args);
-
-	p = printk_buf;
-
-	/* Read log level and handle special printk prefix */
-	plen = log_prefix(p, &current_log_level, &special);
-	if (plen) {
-		p += plen;
-
-		switch (special) {
-		case 'c': /* Strip <c> KERN_CONT, continue line */
-			plen = 0;
-			break;
-		case 'd': /* Strip <d> KERN_DEFAULT, start new line */
-			plen = 0;
-		default:
-			if (!new_text_line) {
-				emit_log_char('\n');
-				new_text_line = 1;
-			}
-		}
+		printed_len += strlen(recursion_msg);
+		/* emit KERN_CRIT message */
+		log_store(0, 2, NULL, 0, recursion_msg, printed_len);
 	}
 
 	/*
-	 * Copy the output into log_buf. If the caller didn't provide
-	 * the appropriate log prefix, we insert them here
+	 * The printf needs to come first; we need the syslog
+	 * prefix which might be passed-in as a parameter.
 	 */
-	for (; *p; p++) {
-		if (new_text_line) {
-			new_text_line = 0;
-
-			if (plen) {
-				/* Copy original log prefix */
-				int i;
-
-				for (i = 0; i < plen; i++)
-					emit_log_char(printk_buf[i]);
-				printed_len += plen;
-			} else {
-				/* Add log prefix */
-				emit_log_char('<');
-				emit_log_char(current_log_level + '0');
-				emit_log_char('>');
-				printed_len += 3;
-			}
+	textlen = vscnprintf(text, sizeof(textbuf), fmt, args);
 
-			if (printk_time) {
-				/* Add the current time stamp */
-				char tbuf[50], *tp;
-				unsigned tlen;
-				unsigned long long t;
-				unsigned long nanosec_rem;
-
-				t = cpu_clock(printk_cpu);
-				nanosec_rem = do_div(t, 1000000000);
-				tlen = sprintf(tbuf, "[%5lu.%06lu] ",
-						(unsigned long) t,
-						nanosec_rem / 1000);
-
-				for (tp = tbuf; tp < tbuf + tlen; tp++)
-					emit_log_char(*tp);
-				printed_len += tlen;
-			}
+	/* mark and strip a trailing newline */
+	if (textlen && text[textlen-1] == '\n') {
+		textlen--;
+		newline = true;
+	}
 
-			if (!*p)
-				break;
+	/* strip syslog prefix and extract log level or flags */
+	if (text[0] == '<' && text[1] && text[2] == '>') {
+		switch (text[1]) {
+		case '0' ... '7':
+			if (level == -1)
+				level = text[1] - '0';
+			text += 3;
+			textlen -= 3;
+			break;
+		case 'c':	/* KERN_CONT */
+			cont = true;
+		case 'd':	/* KERN_DEFAULT */
+			text += 3;
+			textlen -= 3;
+			break;
 		}
+	}
 
-		emit_log_char(*p);
-		if (*p == '\n')
-			new_text_line = 1;
+	if (buflen && (!cont || dict)) {
+		/* no continuation; flush existing buffer */
+		log_store(facility, buflevel, NULL, 0, buf, buflen);
+		printed_len += buflen;
+		buflen = 0;
+	}
+
+	if (buflen == 0) {
+		/* remember level for first message in the buffer */
+		if (level == -1)
+			buflevel = default_message_loglevel;
+		else
+			buflevel = level;
+	}
+
+	if (buflen || !newline) {
+		/* append to existing buffer, or buffer until next message */
+		if (buflen + textlen > sizeof(buf))
+			textlen = sizeof(buf) - buflen;
+		memcpy(buf + buflen, text, textlen);
+		buflen += textlen;
+	}
+
+	if (newline) {
+		/* end of line; flush buffer */
+		if (buflen) {
+			log_store(facility, buflevel,
+				  dict, dictlen, buf, buflen);
+			printed_len += buflen;
+			buflen = 0;
+		} else {
+			log_store(facility, buflevel,
+				  dict, dictlen, text, textlen);
+			printed_len += textlen;
+		}
 	}
 
 	/*
-	 * Try to acquire and then immediately release the
-	 * console semaphore. The release will do all the
-	 * actual magic (print out buffers, wake up klogd,
-	 * etc). 
+	 * Try to acquire and then immediately release the console semaphore.
+	 * The release will print out buffers and wake up /dev/kmsg and syslog()
+	 * users.
 	 *
-	 * The console_trylock_for_printk() function
-	 * will release 'logbuf_lock' regardless of whether it
-	 * actually gets the semaphore or not.
+	 * 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))
 		console_unlock();
@@ -974,12 +1045,73 @@ out_restore_irqs:
 
 	return printed_len;
 }
-EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(vprintk_emit);
+
+asmlinkage int vprintk(const char *fmt, va_list args)
+{
+	return vprintk_emit(0, -1, NULL, 0, fmt, args);
+}
 EXPORT_SYMBOL(vprintk);
 
+asmlinkage int printk_emit(int facility, int level,
+			   const char *dict, size_t dictlen,
+			   const char *fmt, ...)
+{
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+	r = vprintk_emit(facility, level, dict, dictlen, fmt, args);
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(printk_emit);
+
+/**
+ * printk - print a kernel message
+ * @fmt: format string
+ *
+ * This is printk(). It can be called from any context. We want it to work.
+ *
+ * We try to grab the console_lock. If we succeed, it's easy - we log the
+ * output and call the console drivers.  If we fail to get the semaphore, we
+ * place the output into the log buffer and return. The current holder of
+ * the console_sem will notice the new output in console_unlock(); and will
+ * send it to the consoles before releasing the lock.
+ *
+ * One effect of this deferred printing is that code which calls printk() and
+ * then changes console_loglevel may break. This is because console_loglevel
+ * is inspected when the actual printing occurs.
+ *
+ * See also:
+ * printf(3)
+ *
+ * See the vsnprintf() documentation for format string extensions over C99.
+ */
+asmlinkage int printk(const char *fmt, ...)
+{
+	va_list args;
+	int r;
+
+#ifdef CONFIG_KGDB_KDB
+	if (unlikely(kdb_trap_printk)) {
+		va_start(args, fmt);
+		r = vkdb_printf(fmt, args);
+		va_end(args);
+		return r;
+	}
+#endif
+	va_start(args, fmt);
+	r = vprintk_emit(0, -1, NULL, 0, fmt, args);
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(printk);
 #else
 
-static void call_console_drivers(unsigned start, unsigned end)
+static void call_console_drivers(int level, const char *text, size_t len)
 {
 }
 
@@ -1217,7 +1349,7 @@ int is_console_locked(void)
 }
 
 /*
- * Delayed printk facility, for scheduler-internal messages:
+ * Delayed printk version, for scheduler-internal messages:
  */
 #define PRINTK_BUF_SIZE		512
 
@@ -1253,6 +1385,10 @@ void wake_up_klogd(void)
 		this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
 }
 
+/* the next printk record to write to the console */
+static u64 console_seq;
+static u32 console_idx;
+
 /**
  * console_unlock - unlock the console system
  *
@@ -1263,15 +1399,16 @@ void wake_up_klogd(void)
  * by printk().  If this is the case, console_unlock(); emits
  * the output prior to releasing the lock.
  *
- * If there is output waiting for klogd, we wake it up.
+ * If there is output waiting, we wake it /dev/kmsg and syslog() users.
  *
  * console_unlock(); may be called from any context.
  */
 void console_unlock(void)
 {
+	static u64 seen_seq;
 	unsigned long flags;
-	unsigned _con_start, _log_end;
-	unsigned wake_klogd = 0, retry = 0;
+	bool wake_klogd = false;
+	bool retry;
 
 	if (console_suspended) {
 		up(&console_sem);
@@ -1281,17 +1418,41 @@ void console_unlock(void)
 	console_may_schedule = 0;
 
 again:
-	for ( ; ; ) {
+	for (;;) {
+		struct log *msg;
+		static char text[LOG_LINE_MAX];
+		size_t len;
+		int level;
+
 		raw_spin_lock_irqsave(&logbuf_lock, flags);
-		wake_klogd |= log_start - log_end;
-		if (con_start == log_end)
-			break;			/* Nothing to print */
-		_con_start = con_start;
-		_log_end = log_end;
-		con_start = log_end;		/* Flush */
+		if (seen_seq != log_next_seq) {
+			wake_klogd = true;
+			seen_seq = log_next_seq;
+		}
+
+		if (console_seq < log_first_seq) {
+			/* messages are gone, move to first one */
+			console_seq = log_first_seq;
+			console_idx = log_first_idx;
+		}
+
+		if (console_seq == log_next_seq)
+			break;
+
+		msg = log_from_idx(console_idx);
+		level = msg->level & 7;
+		len = msg->text_len;
+		if (len+1 >= sizeof(text))
+			len = sizeof(text)-1;
+		memcpy(text, log_text(msg), len);
+		text[len++] = '\n';
+
+		console_idx = log_next(console_idx);
+		console_seq++;
 		raw_spin_unlock(&logbuf_lock);
+
 		stop_critical_timings();	/* don't trace print latency */
-		call_console_drivers(_con_start, _log_end);
+		call_console_drivers(level, text, len);
 		start_critical_timings();
 		local_irq_restore(flags);
 	}
@@ -1312,8 +1473,7 @@ again:
 	 * flush, no worries.
 	 */
 	raw_spin_lock(&logbuf_lock);
-	if (con_start != log_end)
-		retry = 1;
+	retry = console_seq != log_next_seq;
 	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 
 	if (retry && console_trylock())
@@ -1549,7 +1709,8 @@ void register_console(struct console *ne
 		 * for us.
 		 */
 		raw_spin_lock_irqsave(&logbuf_lock, flags);
-		con_start = log_start;
+		console_seq = syslog_seq;
+		console_idx = syslog_idx;
 		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 		/*
 		 * We're about to replay the log buffer.  Only do this to the
@@ -1758,6 +1919,9 @@ int kmsg_dump_unregister(struct kmsg_dum
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
 
+static bool always_kmsg_dump;
+module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR);
+
 /**
  * kmsg_dump - dump kernel log to kernel message dumpers.
  * @reason: the reason (oops, panic etc) for dumping
@@ -1767,8 +1931,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
  */
 void kmsg_dump(enum kmsg_dump_reason reason)
 {
-	unsigned long end;
-	unsigned chars;
+	u64 idx;
 	struct kmsg_dumper *dumper;
 	const char *s1, *s2;
 	unsigned long l1, l2;
@@ -1780,24 +1943,27 @@ void kmsg_dump(enum kmsg_dump_reason rea
 	/* Theoretically, the log could move on after we do this, but
 	   there's not a lot we can do about that. The new messages
 	   will overwrite the start of what we dump. */
-	raw_spin_lock_irqsave(&logbuf_lock, flags);
-	end = log_end & LOG_BUF_MASK;
-	chars = logged_chars;
-	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 
-	if (chars > end) {
-		s1 = log_buf + log_buf_len - chars + end;
-		l1 = chars - end;
+	raw_spin_lock_irqsave(&logbuf_lock, flags);
+	if (syslog_seq < log_first_seq)
+		idx = syslog_idx;
+	else
+		idx = log_first_idx;
+
+	if (idx > log_next_idx) {
+		s1 = log_buf;
+		l1 = log_next_idx;
 
-		s2 = log_buf;
-		l2 = end;
+		s2 = log_buf + idx;
+		l2 = log_buf_len - idx;
 	} else {
 		s1 = "";
 		l1 = 0;
 
-		s2 = log_buf + end - chars;
-		l2 = chars;
+		s2 = log_buf + idx;
+		l2 = log_next_idx - idx;
 	}
+	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(dumper, &dump_list, list)



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03  0:29 [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer Kay Sievers
@ 2012-05-03 19:48 ` Peter Zijlstra
  2012-05-03 19:54   ` Kay Sievers
  2012-05-03 19:56   ` Linus Torvalds
  2012-05-08  8:48 ` Sasha Levin
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 100+ messages in thread
From: Peter Zijlstra @ 2012-05-03 19:48 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Thu, 2012-05-03 at 02:29 +0200, Kay Sievers wrote:
> + * This is printk(). It can be called from any context. We want it to work.

This is not true..

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 19:48 ` Peter Zijlstra
@ 2012-05-03 19:54   ` Kay Sievers
  2012-05-03 19:55     ` Peter Zijlstra
  2012-05-03 19:56   ` Linus Torvalds
  1 sibling, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-03 19:54 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Thu, May 3, 2012 at 9:48 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Thu, 2012-05-03 at 02:29 +0200, Kay Sievers wrote:
>> + * This is printk(). It can be called from any context. We want it to work.
>
> This is not true..

I did not add that, it's just 'diff' that moves this hunk while adding
stuff before it. It's the same text as in the current code:

  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=kernel/printk.c;h=b663c2c95d3922e4c080e8974c09c6ce99b4355f;hb=HEAD#l729

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 19:54   ` Kay Sievers
@ 2012-05-03 19:55     ` Peter Zijlstra
  0 siblings, 0 replies; 100+ messages in thread
From: Peter Zijlstra @ 2012-05-03 19:55 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Thu, 2012-05-03 at 21:54 +0200, Kay Sievers wrote:
> On Thu, May 3, 2012 at 9:48 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> > On Thu, 2012-05-03 at 02:29 +0200, Kay Sievers wrote:
> >> + * This is printk(). It can be called from any context. We want it to work.
> >
> > This is not true..
> 
> I did not add that, it's just 'diff' that moves this hunk while adding
> stuff before it. It's the same text as in the current code:

Sure, but its still not true.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 19:48 ` Peter Zijlstra
  2012-05-03 19:54   ` Kay Sievers
@ 2012-05-03 19:56   ` Linus Torvalds
  2012-05-03 20:02     ` Peter Zijlstra
  1 sibling, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-03 19:56 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Thu, May 3, 2012 at 12:48 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> On Thu, 2012-05-03 at 02:29 +0200, Kay Sievers wrote:
>> + * This is printk(). It can be called from any context. We want it to work.
>
> This is not true..

Well, it is very very nearly true, and people should basically expect it to be.

There are exceptions, but they are ridiculously specific
 - no NMI context
 - we've had trouble with the percpu runqueue lock (due to the stupid wakeup)
 - for similar reasons, we've had trouble with printk called from
within some terminal locks.

But basically, it damn well should be considered a hard rule that you
can printk from pretty much anything. The few cases where that is not
true are big problems, and should be considered to be real problems,
not "oh, you can't printk from here".

                     Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 19:56   ` Linus Torvalds
@ 2012-05-03 20:02     ` Peter Zijlstra
  2012-05-03 20:09       ` Linus Torvalds
  0 siblings, 1 reply; 100+ messages in thread
From: Peter Zijlstra @ 2012-05-03 20:02 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Thu, 2012-05-03 at 12:56 -0700, Linus Torvalds wrote:
> On Thu, May 3, 2012 at 12:48 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> > On Thu, 2012-05-03 at 02:29 +0200, Kay Sievers wrote:
> >> + * This is printk(). It can be called from any context. We want it to work.
> >
> > This is not true..
> 
> Well, it is very very nearly true, and people should basically expect it to be.
> 
> There are exceptions, but they are ridiculously specific
>  - no NMI context

With the new record design you could actually make the thing lockless
and allow writing to it from NMI context. IIRC vsnprintf() doesn't do
any allocations/locks.

>  - we've had trouble with the percpu runqueue lock (due to the stupid wakeup)

Yep :-(

>  - for similar reasons, we've had trouble with printk called from
> within some terminal locks.
> 
> But basically, it damn well should be considered a hard rule that you
> can printk from pretty much anything. The few cases where that is not
> true are big problems, and should be considered to be real problems,
> not "oh, you can't printk from here".

Thing is, with bonkers stuff like usb-console and kms/drm that's a _lot_
of code running under the logbuf/console locks.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 20:02     ` Peter Zijlstra
@ 2012-05-03 20:09       ` Linus Torvalds
  2012-05-03 20:11         ` Peter Zijlstra
  0 siblings, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-03 20:09 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Thu, May 3, 2012 at 1:02 PM, Peter Zijlstra <peterz@infradead.org> wrote:
>
> Thing is, with bonkers stuff like usb-console and kms/drm that's a _lot_
> of code running under the logbuf/console locks.

The top-level console lock shouldn't be a problem - we use trylock and
delay if it is held.

It's the lower-level driver-specific locks that screw us up. And quite
frankly, I am *not* willing to say that that is a printk() problem.
That is purely a "USB serial console is damn well broken" issue, and
should not be considered a limitation of printk.

                  Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 20:09       ` Linus Torvalds
@ 2012-05-03 20:11         ` Peter Zijlstra
  2012-05-03 20:18           ` Greg Kroah-Hartmann
  0 siblings, 1 reply; 100+ messages in thread
From: Peter Zijlstra @ 2012-05-03 20:11 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Thu, 2012-05-03 at 13:09 -0700, Linus Torvalds wrote:
> On Thu, May 3, 2012 at 1:02 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > Thing is, with bonkers stuff like usb-console and kms/drm that's a _lot_
> > of code running under the logbuf/console locks.
> 
> The top-level console lock shouldn't be a problem - we use trylock and
> delay if it is held.
> 
> It's the lower-level driver-specific locks that screw us up. And quite
> frankly, I am *not* willing to say that that is a printk() problem.
> That is purely a "USB serial console is damn well broken" issue, and
> should not be considered a limitation of printk.

I'm happy to call all that broken ;-)

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03 20:11         ` Peter Zijlstra
@ 2012-05-03 20:18           ` Greg Kroah-Hartmann
  0 siblings, 0 replies; 100+ messages in thread
From: Greg Kroah-Hartmann @ 2012-05-03 20:18 UTC (permalink / raw)
  To: Peter Zijlstra; +Cc: Linus Torvalds, Kay Sievers, Ingo Molnar, linux-kernel

On Thu, May 03, 2012 at 10:11:02PM +0200, Peter Zijlstra wrote:
> On Thu, 2012-05-03 at 13:09 -0700, Linus Torvalds wrote:
> > On Thu, May 3, 2012 at 1:02 PM, Peter Zijlstra <peterz@infradead.org> wrote:
> > >
> > > Thing is, with bonkers stuff like usb-console and kms/drm that's a _lot_
> > > of code running under the logbuf/console locks.
> > 
> > The top-level console lock shouldn't be a problem - we use trylock and
> > delay if it is held.
> > 
> > It's the lower-level driver-specific locks that screw us up. And quite
> > frankly, I am *not* willing to say that that is a printk() problem.
> > That is purely a "USB serial console is damn well broken" issue, and
> > should not be considered a limitation of printk.
> 
> I'm happy to call all that broken ;-)

USB serial console was a drunken bet gone wrong.  I'm amazed that it
even works at times, and it should never be considered critical enough
to affect any core kernel code.

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03  0:29 [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer Kay Sievers
  2012-05-03 19:48 ` Peter Zijlstra
@ 2012-05-08  8:48 ` Sasha Levin
  2012-05-08 11:14   ` Kay Sievers
  2012-05-26 11:11 ` Anton Vorontsov
  2012-11-28 13:33 ` Michael Kerrisk
  3 siblings, 1 reply; 100+ messages in thread
From: Sasha Levin @ 2012-05-08  8:48 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

Hi Kay,

On Thu, May 3, 2012 at 2:29 AM, Kay Sievers <kay@vrfy.org> wrote:
> From: Kay Sievers <kay@vrfy.org>
> Subject: printk: convert byte-buffer to variable-length record buffer

This patch was included in today's linux-next, and it looks like it
broke printk on my configuration.

It's a bit hard to describe exactly what's wrong, but here are the main points:

1. PRINTK_TIME timing information is gone.
2. Newline issues. It appears to be adding newlines where it
shouldn't. For example:

Before:
[   10.110626] parport0: PC-style at 0x378, irq 7 [PCSPP,TRISTATE]

After:
parport0: PC-style at 0x378
, irq 7
 [
PCSPP
,TRISTATE
]

3. Things are not properly aligned, such as stack traces.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08  8:48 ` Sasha Levin
@ 2012-05-08 11:14   ` Kay Sievers
  2012-05-08 13:33     ` Sasha Levin
  2012-05-09  3:52     ` Linus Torvalds
  0 siblings, 2 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-08 11:14 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Tue, 2012-05-08 at 10:48 +0200, Sasha Levin wrote:
> This patch was included in today's linux-next, and it looks like it
> broke printk on my configuration.
> 
> It's a bit hard to describe exactly what's wrong, but here are the main points:
> 
> 1. PRINTK_TIME timing information is gone.

It's always unconditionally recorded now. It looks fine in 'dmesg'
output, right?

> 2. Newline issues. It appears to be adding newlines where it
> shouldn't.

> parport0: PC-style at 0x378
> , irq 7
>  [
> PCSPP

Yeah, we need to make sure, we never merge the (always racy)
continuation printk() users with (non-racy) non-continuation users.
Therefore KERN_CONT is required to suppress the newline and to merge the
content with the earlier non-newline-terminated printk() line. 

I 'm sure, I have signed up for the job to fix what's needed here. :)

Patch for parport is below.

> 3. Things are not properly aligned, such as stack traces.

Mind sending the entire output of your 'dmesg', which shows it?

We recently just needed to fix the "<%u>" in the dump, which got
recognized as syslog prority prefixes. There might be a few more
KERN_CONT missing ...

Thanks,
Kay


From: Kay Sievers <kay@vrfy.org>
Subject: parport: use KERN_CONT in printk() continuation lines

On Tue, May 8, 2012 at 10:48 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
> Before:
> [   10.110626] parport0: PC-style at 0x378, irq 7 [PCSPP,TRISTATE]
>
> After:
> parport0: PC-style at 0x378
> , irq 7
>  [
> PCSPP
> ,TRISTATE
> ]

Reported-By: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Kay Sievers <kay@vrfy.org>
---
 drivers/parport/parport_pc.c |   16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2351,7 +2351,7 @@ struct parport *parport_pc_probe_port(un
 
 	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
 	if (p->base_hi && priv->ecr)
-		printk(" (0x%lx)", p->base_hi);
+		printk(KERN_CONT " (0x%lx)", p->base_hi);
 	if (p->irq == PARPORT_IRQ_AUTO) {
 		p->irq = PARPORT_IRQ_NONE;
 		parport_irq_probe(p);
@@ -2362,7 +2362,7 @@ struct parport *parport_pc_probe_port(un
 		p->irq = PARPORT_IRQ_NONE;
 	}
 	if (p->irq != PARPORT_IRQ_NONE) {
-		printk(", irq %d", p->irq);
+		printk(KERN_CONT ", irq %d", p->irq);
 		priv->ctr_writable |= 0x10;
 
 		if (p->dma == PARPORT_DMA_AUTO) {
@@ -2386,21 +2386,21 @@ struct parport *parport_pc_probe_port(un
 		/* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */
 #endif /* IEEE 1284 support */
 		if (p->dma != PARPORT_DMA_NONE) {
-			printk(", dma %d", p->dma);
+			printk(KERN_CONT ", dma %d", p->dma);
 			p->modes |= PARPORT_MODE_DMA;
 		} else
-			printk(", using FIFO");
+			printk(KERN_CONT ", using FIFO");
 	} else
 		/* We can't use the DMA channel after all. */
 		p->dma = PARPORT_DMA_NONE;
 #endif /* Allowed to use FIFO/DMA */
 
-	printk(" [");
+	printk(KERN_CONT " [");
 
 #define printmode(x) \
 	{\
 		if (p->modes & PARPORT_MODE_##x) {\
-			printk("%s%s", f ? "," : "", #x);\
+			printk(KERN_CONT "%s%s", f ? "," : "", #x);\
 			f++;\
 		} \
 	}
@@ -2416,9 +2416,9 @@ struct parport *parport_pc_probe_port(un
 	}
 #undef printmode
 #ifndef CONFIG_PARPORT_1284
-	printk("(,...)");
+	printk(KERN_CONT "(,...)");
 #endif /* CONFIG_PARPORT_1284 */
-	printk("]\n");
+	printk(KERN_CONT "]\n");
 	if (probedirq != PARPORT_IRQ_NONE)
 		printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
 



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 11:14   ` Kay Sievers
@ 2012-05-08 13:33     ` Sasha Levin
  2012-05-08 14:29       ` Kay Sievers
  2012-05-09  3:52     ` Linus Torvalds
  1 sibling, 1 reply; 100+ messages in thread
From: Sasha Levin @ 2012-05-08 13:33 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1682 bytes --]

On Tue, May 8, 2012 at 1:14 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Tue, 2012-05-08 at 10:48 +0200, Sasha Levin wrote:
>> This patch was included in today's linux-next, and it looks like it
>> broke printk on my configuration.
>>
>> It's a bit hard to describe exactly what's wrong, but here are the main points:
>>
>> 1. PRINTK_TIME timing information is gone.
>
> It's always unconditionally recorded now. It looks fine in 'dmesg'
> output, right?

Yup. Is there no intention to show it in the console output though? it
was quite handy there.

>
>> 2. Newline issues. It appears to be adding newlines where it
>> shouldn't.
>
>> parport0: PC-style at 0x378
>> , irq 7
>>  [
>> PCSPP
>
> Yeah, we need to make sure, we never merge the (always racy)
> continuation printk() users with (non-racy) non-continuation users.
> Therefore KERN_CONT is required to suppress the newline and to merge the
> content with the earlier non-newline-terminated printk() line.
>
> I 'm sure, I have signed up for the job to fix what's needed here. :)
>
> Patch for parport is below.
>
>> 3. Things are not properly aligned, such as stack traces.
>
> Mind sending the entire output of your 'dmesg', which shows it?
>
> We recently just needed to fix the "<%u>" in the dump, which got
> recognized as syslog prority prefixes. There might be a few more
> KERN_CONT missing ...

The 3rd one actually looks like the KERN_CONT problem now that you've
explained it. You can see it in the 'saved trace' test in the boot
log.

I've attached the boot log which shows several other places with this
issue, if you're ok with it I can try patching those myself.

[-- Attachment #2: log.txt --]
[-- Type: text/plain, Size: 73182 bytes --]

Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 3.4.0-rc6-next-20120508-sasha-00001-g8de7752-dirty (sasha@ksplice-shell2) (gcc version 4.4.5 (Debian 4.4.5-8) ) #178 SMP PREEMPT Tue May 8 04:27:40 EDT 2012
Command line: init=virt/init console=ttyS0 sched_debug slub_debug=FZPU rw numa=fake=10 root=/dev/vda
KERNEL supported cpus:
  Intel GenuineIntel
  AMD AuthenticAMD
  Centaur CentaurHauls
e820: BIOS-provided physical RAM map:
BIOS-e820: [mem 0x0000000000000000-0x000000000009dbff] usable
BIOS-e820: [mem 0x000000000009dc00-0x000000000009ffff] reserved
BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
BIOS-e820: [mem 0x0000000000100000-0x000000007fffcfff] usable
BIOS-e820: [mem 0x000000007fffd000-0x000000007fffffff] reserved
BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved
BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
NX (Execute Disable) protection: active
DMI 2.4 present.
No AGP bridge found
e820: last_pfn = 0x7fffd max_arch_pfn = 0x400000000
x86 PAT enabled: cpu 0, old 0x70406, new 0x7010600070106
found SMP MP-table at [mem 0x000fd5d0-0x000fd5df] mapped at [ffff8800000fd5d0]
init_memory_mapping: [mem 0x00000000-0x7fffcfff]
ACPI: RSDP 00000000000fd3f0 00014 (v00 BOCHS )
ACPI: RSDT 000000007fffd660 00034 (v01 BOCHS  BXPCRSDT 00000001 BXPC 00000001)
ACPI: FACP 000000007fffff80 00074 (v01 BOCHS  BXPCFACP 00000001 BXPC 00000001)
ACPI: DSDT 000000007fffd9b0 02589 (v01   BXPC   BXDSDT 00000001 INTL 20100528)
ACPI: FACS 000000007fffff40 00040
ACPI: SSDT 000000007fffd7e0 001C1 (v01 BOCHS  BXPCSSDT 00000001 BXPC 00000001)
ACPI: APIC 000000007fffd6e0 0008A (v01 BOCHS  BXPCAPIC 00000001 BXPC 00000001)
ACPI: HPET 000000007fffd6a0 00038 (v01 BOCHS  BXPCHPET 00000001 BXPC 00000001)
No NUMA configuration found
Faking a node at [mem 0x0000000000000000-0x000000007fffcfff]
Faking node 0 at [mem 0x0000000000000000-0x000000000dffffff] (224MB)
Faking node 1 at [mem 0x000000000e000000-0x000000001bffffff] (224MB)
Faking node 2 at [mem 0x000000001c000000-0x0000000029ffffff] (224MB)
Faking node 3 at [mem 0x000000002a000000-0x0000000035ffffff] (192MB)
Faking node 4 at [mem 0x0000000036000000-0x0000000041ffffff] (192MB)
Faking node 5 at [mem 0x0000000042000000-0x000000004dffffff] (192MB)
Faking node 6 at [mem 0x000000004e000000-0x0000000059ffffff] (192MB)
Faking node 7 at [mem 0x000000005a000000-0x0000000065ffffff] (192MB)
Faking node 8 at [mem 0x0000000066000000-0x0000000071ffffff] (192MB)
Faking node 9 at [mem 0x0000000072000000-0x000000007fffcfff] (223MB)
Initmem setup node 0 [mem 0x00000000-0x0dffffff]
  NODE_DATA [mem 0x0dfcf000-0x0dffffff]
Initmem setup node 1 [mem 0x0e000000-0x1bffffff]
  NODE_DATA [mem 0x1bfcf000-0x1bffffff]
Initmem setup node 2 [mem 0x1c000000-0x29ffffff]
  NODE_DATA [mem 0x29fcf000-0x29ffffff]
Initmem setup node 3 [mem 0x2a000000-0x35ffffff]
  NODE_DATA [mem 0x35fcf000-0x35ffffff]
Initmem setup node 4 [mem 0x36000000-0x41ffffff]
  NODE_DATA [mem 0x41fcf000-0x41ffffff]
Initmem setup node 5 [mem 0x42000000-0x4dffffff]
  NODE_DATA [mem 0x4dfcf000-0x4dffffff]
Initmem setup node 6 [mem 0x4e000000-0x59ffffff]
  NODE_DATA [mem 0x59fcf000-0x59ffffff]
Initmem setup node 7 [mem 0x5a000000-0x65ffffff]
  NODE_DATA [mem 0x65fcf000-0x65ffffff]
Initmem setup node 8 [mem 0x66000000-0x71ffffff]
  NODE_DATA [mem 0x71fcf000-0x71ffffff]
Initmem setup node 9 [mem 0x72000000-0x7fffcfff]
  NODE_DATA [mem 0x7ffcb000-0x7fffbfff]
kvm-clock: Using msrs 4b564d01 and 4b564d00
kvm-clock: cpu 0, msr 0:41d7841, boot clock
Zone ranges:
  DMA      
[mem 0x00010000-0x00ffffff]
  DMA32    
[mem 0x01000000-0xffffffff]
  Normal   
empty
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x00010000-0x0009cfff]
  node   0: [mem 0x00100000-0x0dffffff]
  node   1: [mem 0x0e000000-0x1bffffff]
  node   2: [mem 0x1c000000-0x29ffffff]
  node   3: [mem 0x2a000000-0x35ffffff]
  node   4: [mem 0x36000000-0x41ffffff]
  node   5: [mem 0x42000000-0x4dffffff]
  node   6: [mem 0x4e000000-0x59ffffff]
  node   7: [mem 0x5a000000-0x65ffffff]
  node   8: [mem 0x66000000-0x71ffffff]
  node   9: [mem 0x72000000-0x7fffcfff]
ACPI: PM-Timer IO Port: 0xb008
ACPI: LAPIC (acpi_id[0x00] lapic_id[0x00] enabled)
ACPI: LAPIC (acpi_id[0x01] lapic_id[0x01] enabled)
ACPI: LAPIC (acpi_id[0x02] lapic_id[0x02] enabled)
ACPI: LAPIC (acpi_id[0x03] lapic_id[0x03] enabled)
ACPI: IOAPIC (id[0x04] address[0xfec00000] gsi_base[0])
IOAPIC[0]: apic_id 4, version 17, address 0xfec00000, GSI 0-23
ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl)
ACPI: INT_SRC_OVR (bus 0 bus_irq 5 global_irq 5 high level)
ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 high level)
ACPI: INT_SRC_OVR (bus 0 bus_irq 10 global_irq 10 high level)
ACPI: INT_SRC_OVR (bus 0 bus_irq 11 global_irq 11 high level)
Using ACPI (MADT) for SMP configuration information
ACPI: HPET id: 0x8086a201 base: 0xfed00000
SMP: Allowing 4 CPUs, 0 hotplug CPUs
PM: Registered nosave memory: 000000000009d000 - 000000000009e000
PM: Registered nosave memory: 000000000009e000 - 00000000000a0000
PM: Registered nosave memory: 00000000000a0000 - 00000000000f0000
PM: Registered nosave memory: 00000000000f0000 - 0000000000100000
e820: [mem 0x80000000-0xfeffbfff] available for PCI devices
Booting paravirtualized kernel on KVM
setup_percpu: NR_CPUS:4096 nr_cpumask_bits:4 nr_cpu_ids:4 nr_node_ids:10
PERCPU: Embedded 475 pages/cpu @ffff88000d800000 s1923672 r0 d21928 u2097152

[0] 
0 
[1] 
1 
[2] 
2 
[3] 
3 

kvm-clock: cpu 0, msr 0:d9d4841, primary cpu clock
KVM setup async PF for cpu 0
kvm-stealtime: cpu 0, msr d80f0c0
Built 10 zonelists in Node order, mobility grouping on.  Total pages: 515973
Policy zone: DMA32
Kernel command line: init=virt/init console=ttyS0 sched_debug slub_debug=FZPU rw numa=fake=10 root=/dev/vda
PID hash table entries: 4096 (order: 3, 32768 bytes)
__ex_table already sorted, skipping sort
xsave/xrstor: enabled xstate_bv 0x7, cntxt size 0x340
Checking aperture...
No AGP bridge found
Memory: 1978372k/2097140k available (30279k kernel code, 460k absent, 118308k reserved, 18880k data, 3380k init)
kmemleak: Kernel memory leak detector disabled
SLUB: Genslabs=15, HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=10
Preemptible hierarchical RCU implementation.
	RCU debugfs-based tracing is enabled.
	RCU dyntick-idle grace-period acceleration is enabled.
	RCU lockdep checking is enabled.
	RCU torture testing starts during boot.
	Additional per-CPU info printed with stalls.
NR_IRQS:262400 nr_irqs:712 16
Console: colour VGA+ 80x25
console [ttyS0] enabled
Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
... MAX_LOCKDEP_SUBCLASSES:  8
... MAX_LOCK_DEPTH:          48
... MAX_LOCKDEP_KEYS:        8191
... CLASSHASH_SIZE:          4096
... MAX_LOCKDEP_ENTRIES:     16384
... MAX_LOCKDEP_CHAINS:      32768
... CHAINHASH_SIZE:          16384
 memory used by lock dependency info: 6367 kB
 per task-struct memory footprint: 2688 bytes
------------------------
| Locking API testsuite:
----------------------------------------------------------------------------
                                 | spin |wlock |rlock |mutex | wsem | rsem |
  --------------------------------------------------------------------------
                     A-A deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

                 A-B-B-A deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

             A-B-B-C-C-A deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

             A-B-C-A-B-C deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

         A-B-B-C-C-D-D-A deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

         A-B-C-D-B-D-D-A deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

         A-B-C-D-B-C-D-A deadlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

                    double unlock:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

                  initialize held:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

                 bad unlock order:
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |
  ok  |

  --------------------------------------------------------------------------
              recursive read-lock:
             |
  ok  |
             |
  ok  |

           recursive read-lock #2:
             |
  ok  |
             |
  ok  |

            mixed read-write-lock:
             |
  ok  |
             |
  ok  |

            mixed write-read-lock:
             |
  ok  |
             |
  ok  |

  --------------------------------------------------------------------------
     hard-irqs-on + irq-safe-A/12:
  ok  |
  ok  |
  ok  |

     soft-irqs-on + irq-safe-A/12:
  ok  |
  ok  |
  ok  |

     hard-irqs-on + irq-safe-A/21:
  ok  |
  ok  |
  ok  |

     soft-irqs-on + irq-safe-A/21:
  ok  |
  ok  |
  ok  |

       sirq-safe-A => hirqs-on/12:
  ok  |
  ok  |
  ok  |

       sirq-safe-A => hirqs-on/21:
  ok  |
  ok  |
  ok  |

         hard-safe-A + irqs-on/12:
  ok  |
  ok  |
  ok  |

         soft-safe-A + irqs-on/12:
  ok  |
  ok  |
  ok  |

         hard-safe-A + irqs-on/21:
  ok  |
  ok  |
  ok  |

         soft-safe-A + irqs-on/21:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #1/123:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #1/123:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #1/132:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #1/132:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #1/213:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #1/213:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #1/231:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #1/231:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #1/312:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #1/312:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #1/321:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #1/321:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #2/123:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #2/123:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #2/132:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #2/132:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #2/213:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #2/213:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #2/231:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #2/231:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #2/312:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #2/312:
  ok  |
  ok  |
  ok  |

    hard-safe-A + unsafe-B #2/321:
  ok  |
  ok  |
  ok  |

    soft-safe-A + unsafe-B #2/321:
  ok  |
  ok  |
  ok  |

      hard-irq lock-inversion/123:
  ok  |
  ok  |
  ok  |

      soft-irq lock-inversion/123:
  ok  |
  ok  |
  ok  |

      hard-irq lock-inversion/132:
  ok  |
  ok  |
  ok  |

      soft-irq lock-inversion/132:
  ok  |
  ok  |
  ok  |

      hard-irq lock-inversion/213:
  ok  |
  ok  |
  ok  |

      soft-irq lock-inversion/213:
  ok  |
  ok  |
  ok  |

      hard-irq lock-inversion/231:
  ok  |
  ok  |
  ok  |

      soft-irq lock-inversion/231:
  ok  |
  ok  |
  ok  |

      hard-irq lock-inversion/312:
  ok  |
  ok  |
  ok  |

      soft-irq lock-inversion/312:
  ok  |
  ok  |
  ok  |

      hard-irq lock-inversion/321:
  ok  |
  ok  |
  ok  |

      soft-irq lock-inversion/321:
  ok  |
  ok  |
  ok  |

      hard-irq read-recursion/123:
  ok  |

      soft-irq read-recursion/123:
  ok  |

      hard-irq read-recursion/132:
  ok  |

      soft-irq read-recursion/132:
  ok  |

      hard-irq read-recursion/213:
  ok  |

      soft-irq read-recursion/213:
  ok  |

      hard-irq read-recursion/231:
  ok  |

      soft-irq read-recursion/231:
  ok  |

      hard-irq read-recursion/312:
  ok  |

      soft-irq read-recursion/312:
  ok  |

      hard-irq read-recursion/321:
  ok  |

      soft-irq read-recursion/321:
  ok  |

-------------------------------------------------------
Good, all 218 testcases passed! |
---------------------------------
kmemleak: Early log buffer exceeded (1254), please increase DEBUG_KMEMLEAK_EARLY_LOG_SIZE
Detected 2491.820 MHz processor.
Calibrating delay loop (skipped) preset value.. 4983.64 BogoMIPS (lpj=2491820)
pid_max: default: 32768 minimum: 301
Security Framework initialized
AppArmor: AppArmor disabled by boot time parameter
Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes)
Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes)
Mount-cache hash table entries: 256
Initializing cgroup subsys debug
Initializing cgroup subsys cpuacct
Initializing cgroup subsys devices
Initializing cgroup subsys freezer
Initializing cgroup subsys net_cls
Initializing cgroup subsys blkio
Initializing cgroup subsys perf_event
Initializing cgroup subsys net_prio
mce: CPU supports 10 MCE banks
ACPI: Core revision 20120320
..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1
CPU0: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz stepping 07
Performance Events: 16-deep LBR, SandyBridge events, Intel PMU driver.
PEBS disabled due to CPU errata.
... version:                2
... bit width:              48
... generic registers:      4
... value mask:             0000ffffffffffff
... max period:             000000007fffffff
... fixed-purpose events:   3
... event mask:             000000070000000f
NMI watchdog: enabled, takes one hw-pmu counter.
lockdep: fixing up alternatives.
Booting Node   1, Processors  #1
kvm-clock: cpu 1, msr 0:1b9d4841, secondary cpu clock
KVM setup async PF for cpu 1
kvm-stealtime: cpu 1, msr 1b80f0c0
NMI watchdog: enabled, takes one hw-pmu counter.
lockdep: fixing up alternatives.
 Ok.
Booting Node   2, Processors  #2
kvm-clock: cpu 2, msr 0:299d4841, secondary cpu clock
KVM setup async PF for cpu 2
kvm-stealtime: cpu 2, msr 2980f0c0
NMI watchdog: enabled, takes one hw-pmu counter.
lockdep: fixing up alternatives.
 Ok.
Booting Node   3, Processors  #3 Ok.
kvm-clock: cpu 3, msr 0:35bd4841, secondary cpu clock
KVM setup async PF for cpu 3
kvm-stealtime: cpu 3, msr 35a0f0c0
NMI watchdog: enabled, takes one hw-pmu counter.
Brought up 4 CPUs
----------------
| NMI testsuite:
--------------------
  remote IPI:
  ok  |

   local IPI:
  ok  |

--------------------
Good, all   2 testcases passed! |
---------------------------------
Total of 4 processors activated (19934.56 BogoMIPS).
devtmpfs: initialized
initlevel:0=early, 5 registered initcalls
EVM: security.selinux
EVM: security.SMACK64
EVM: security.capability
initlevel:1=core, 36 registered initcalls
xor: automatically using best checksumming function:
   avx       : 15648.000 MB/sec
atomic64 test passed for x86-64 platform with CX8 and with SSE
kworker/u:0 (34) used greatest stack depth: 4952 bytes left
kworker/u:0 (36) used greatest stack depth: 4488 bytes left
dummy: 
RTC time: 13:27:18, date: 05/08/12
NET: Registered protocol family 16
initlevel:2=postcore, 20 registered initcalls
initlevel:3=arch, 12 registered initcalls
ACPI: bus type pci registered
PCI: Using configuration type 1 for base access
initlevel:4=subsys, 96 registered initcalls
bio: create slab <bio-0> at 0
raid6: sse2x1    6890 MB/s
raid6: sse2x2    9812 MB/s
raid6: sse2x4   11179 MB/s
raid6: using algorithm sse2x4 (11179 MB/s)
raid6: using ssse3x2 recovery algorithm
ACPI: Added _OSI(Module Device)
ACPI: Added _OSI(Processor Device)
ACPI: Added _OSI(3.0 _SCP Extensions)
ACPI: Added _OSI(Processor Aggregator Device)
ACPI: Interpreter enabled
ACPI: (supports S0
 S3
 S4
 S5
)
ACPI: Using IOAPIC for interrupt routing
ACPI: No dock devices found.
PCI: Ignoring host bridge windows from ACPI; if necessary, use "pci=use_crs" and report a bug
ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
PCI host bridge to bus 0000:00
pci_bus 0000:00: root bus resource [io  0x0000-0xffff]
pci_bus 0000:00: root bus resource [mem 0x00000000-0xffffffffff]
pci 0000:00:01.3: quirk: [io  0xb000-0xb03f] claimed by PIIX4 ACPI
pci 0000:00:01.3: quirk: [io  0xb100-0xb10f] claimed by PIIX4 SMB
 pci0000:00: Unable to request _OSC control (_OSC support mask: 0x1e)
ACPI: PCI Interrupt Link [LNKA] (IRQs
 5
 *10
 11
)

ACPI: PCI Interrupt Link [LNKB] (IRQs
 5
 *10
 11
)

ACPI: PCI Interrupt Link [LNKC] (IRQs
 5
 10
 *11
)

ACPI: PCI Interrupt Link [LNKD] (IRQs
 5
 10
 *11
)

ACPI: PCI Interrupt Link [LNKS] (IRQs
 9
)
 *0

vgaarb: device added: PCI:0000:00:02.0,decodes=io+mem,owns=io+mem,locks=none
vgaarb: loaded
vgaarb: bridge control possible 0000:00:02.0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Linux media interface: v0.10
Linux video capture interface: v2.00
pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
PTP clock support registered
wmi: Mapper loaded
Advanced Linux Sound Architecture Driver Version 1.0.25.
PCI: Using ACPI for IRQ routing
Sangoma WANPIPE Router v1.1 (c) 1995-2000 Sangoma Technologies Inc.
NET: Registered protocol family 23
Bluetooth: Core ver 2.16
NET: Registered protocol family 31
Bluetooth: HCI device and connection manager initialized
Bluetooth: HCI socket layer initialized
Bluetooth: L2CAP socket layer initialized
Bluetooth: SCO socket layer initialized
NET: Registered protocol family 8
NET: Registered protocol family 20
------------[ cut here ]------------
WARNING: at net/wireless/reg.c:396 regulatory_init+0xce/0x144()
Hardware name: Bochs
db.txt is empty, you should update it...
Pid: 1, comm: swapper/0 Not tainted 3.4.0-rc6-next-20120508-sasha-00001-g8de7752-dirty #178
Call Trace:
 [<ffffffff810b6ca7>] warn_slowpath_common+0x87/0xb0
 [<ffffffff8425fb55>] ? sctp_snmp_proc_init+0x31/0x31
 [<ffffffff810b6d71>] warn_slowpath_fmt+0x41/0x50
 [<ffffffff8189c208>] ? __raw_spin_lock_init+0x38/0x70
 [<ffffffff8425fcf0>] regulatory_init+0xce/0x144
 [<ffffffff8425fbba>] cfg80211_init+0x65/0xcd
 [<ffffffff841d9639>] do_one_initcall+0x7a/0x155
 [<ffffffff841d9807>] do_basic_setup+0xc8/0xed
 [<ffffffff841d982c>] ? do_basic_setup+0xed/0xed
 [<ffffffff841f7ff7>] ? smp_init+0x85/0x8d
 [<ffffffff841d9a85>] kernel_init+0x1fe/0x280
 [<ffffffff810e7f0e>] ? sub_preempt_count+0xae/0xf0
 [<ffffffff82d8ca74>] kernel_thread_helper+0x4/0x10
 [<ffffffff810e884d>] ? finish_task_switch+0x8d/0x110
 [<ffffffff82d8ad74>] ? retint_restore_args+0x13/0x13
 [<ffffffff841d9887>] ? repair_env_string+0x5b/0x5b
 [<ffffffff82d8ca70>] ? gs_change+0x13/0x13
---[ end trace 44593438a59a9533 ]---
NetLabel: Initializing
NetLabel:  domain hash size = 128
NetLabel:  protocols = UNLABELED CIPSOv4
NetLabel:  unlabeled traffic allowed by default
cfg80211: Calling CRDA to update world regulatory domain
nfc: nfc_init: NFC Core ver 0.1
NET: Registered protocol family 39
initlevel:5=fs, 35 registered initcalls
HPET: 3 timers in total, 0 timers will be used for per-cpu timer
hpet0: at MMIO 0xfed00000, IRQs 2, 8, 0
hpet0: 3 comparators, 64-bit 100.000000 MHz counter
Switching to clocksource kvm-clock
FS-Cache: Loaded
CacheFiles: Loaded
pnp: PnP ACPI init
ACPI: bus type pnp registered
pnp: PnP ACPI: found 8 devices
ACPI: ACPI bus type pnp unregistered
NET: Registered protocol family 2
IP route cache hash table entries: 65536 (order: 7, 524288 bytes)
TCP established hash table entries: 262144 (order: 10, 4194304 bytes)
TCP bind hash table entries: 65536 (order: 10, 5242880 bytes)
TCP: Hash tables configured (established 262144 bind 65536)
TCP: reno registered
UDP hash table entries: 1024 (order: 5, 196608 bytes)
UDP-Lite hash table entries: 1024 (order: 5, 196608 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
pci 0000:00:00.0: Limiting direct PCI/PCI transfers
pci 0000:00:01.0: PIIX3: Enabling Passive Release
pci 0000:00:01.0: Activating ISA DMA hang workarounds
DMA-API: preallocated 32768 debug entries
DMA-API: debugging enabled by kernel config
initlevel:6=device, 1764 registered initcalls
kvm: no hardware support
has_svm: not amd
kvm: no hardware support
Machine check injector initialized
microcode: CPU0 sig=0x206a7, pf=0x1, revision=0x1
microcode: CPU1 sig=0x206a7, pf=0x1, revision=0x1
microcode: CPU2 sig=0x206a7, pf=0x1, revision=0x1
microcode: CPU3 sig=0x206a7, pf=0x1, revision=0x1
microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba
sha1_ssse3: Using AVX optimized SHA-1 implementation
Initializing RT-Tester: OK
====[ backtrace testing ]===========
Testing a backtrace from process context.
The following trace is a kernel self test and not a bug!
Pid: 1, comm: swapper/0 Tainted: G        W    3.4.0-rc6-next-20120508-sasha-00001-g8de7752-dirty #178
Call Trace:
 [<ffffffff8112a850>] ? backtrace_test_irq_callback+0x20/0x20
 [<ffffffff8112a888>] backtrace_regression_test+0x38/0x110
 [<ffffffff841f80bf>] ? kallsyms_init+0x25/0x25
 [<ffffffff8119c5db>] ? __alloc_percpu+0xb/0x10
 [<ffffffff841d9639>] do_one_initcall+0x7a/0x155
 [<ffffffff841d9807>] do_basic_setup+0xc8/0xed
 [<ffffffff841d982c>] ? do_basic_setup+0xed/0xed
 [<ffffffff841f7ff7>] ? smp_init+0x85/0x8d
 [<ffffffff841d9a85>] kernel_init+0x1fe/0x280
 [<ffffffff810e7f0e>] ? sub_preempt_count+0xae/0xf0
 [<ffffffff82d8ca74>] kernel_thread_helper+0x4/0x10
 [<ffffffff810e884d>] ? finish_task_switch+0x8d/0x110
 [<ffffffff82d8ad74>] ? retint_restore_args+0x13/0x13
 [<ffffffff841d9887>] ? repair_env_string+0x5b/0x5b
 [<ffffffff82d8ca70>] ? gs_change+0x13/0x13
Testing a backtrace from irq context.
The following trace is a kernel self test and not a bug!
Pid: 16, comm: ksoftirqd/1 Tainted: G        W    3.4.0-rc6-next-20120508-sasha-00001-g8de7752-dirty #178
Call Trace:
 [<ffffffff8112a839>] backtrace_test_irq_callback+0x9/0x20
 [<ffffffff810be141>] tasklet_action+0xb1/0x130
 [<ffffffff810be8e8>] __do_softirq+0xc8/0x1c0
 [<ffffffff810beadd>] run_ksoftirqd+0xfd/0x230
 [<ffffffff810be9e0>] ? __do_softirq+0x1c0/0x1c0
 [<ffffffff810dad02>] kthread+0xb2/0xc0
 [<ffffffff82d8ca74>] kernel_thread_helper+0x4/0x10
 [<ffffffff810e884d>] ? finish_task_switch+0x8d/0x110
 [<ffffffff82d8ad74>] ? retint_restore_args+0x13/0x13
 [<ffffffff810dac50>] ? __init_kthread_worker+0x70/0x70
 [<ffffffff82d8ca70>] ? gs_change+0x13/0x13
Testing a saved backtrace.
The following trace is a kernel self test and not a bug!
 
[<ffffffff8105d1fa>] save_stack_trace+0x2a/0x50
 
[<ffffffff8112a934>] backtrace_regression_test+0xe4/0x110
 
[<ffffffff841d9639>] do_one_initcall+0x7a/0x155
 
[<ffffffff841d9807>] do_basic_setup+0xc8/0xed
 
[<ffffffff841d9a85>] kernel_init+0x1fe/0x280
 
[<ffffffff82d8ca74>] kernel_thread_helper+0x4/0x10
 
[<ffffffffffffffff>] 0xffffffffffffffff
====[ end of backtrace testing ]====
audit: initializing netlink socket (disabled)
type=2000 audit(1336483646.153:1): initialized
rcu-torture:--- Start of test: nreaders=8 nfakewriters=4 stat_interval=0 verbose=0 test_no_idle_hz=0 shuffle_interval=3 stutter=5 irqreader=1 fqs_duration=0 fqs_holdoff=0 fqs_stutter=3 test_boost=1/0 test_boost_interval=7 test_boost_duration=4 shutdown_secs=0 onoff_interval=0 onoff_holdoff=0
HugeTLB registered 2 MB page size, pre-allocated 0 pages
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
DLM installed
squashfs: version 4.0 (2009/01/31) Phillip Lougher
NFS: Registering the id_resolver key type
FS-Cache: Netfs 'nfs' registered for caching
nfs4filelayout_init: NFSv4 File Layout Driver Registering...
NFS: objlayout_init: Registered OSD pNFS Layout Driver
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
FS-Cache: Netfs 'cifs' registered for caching
NTFS driver 2.1.30 [Flags: R/W DEBUG].
EFS: 1.0a - http://aeschi.ch.eu.org/efs/
jffs2: version 2.2. (NAND) (SUMMARY)  © 2001-2006 Red Hat, Inc.
ROMFS MTD (C) 2007 Red Hat, Inc.
QNX4 filesystem 0.2.3 registered.
QNX6 filesystem 1.0.0 registered.
fuse init (API version 7.19)
JFS: nTxBlock = 8192, nTxLock = 65536
SGI XFS with ACLs, security attributes, realtime, large block/inode numbers, debug enabled
9p: Installing v9fs 9p2000 file system support
FS-Cache: Netfs '9p' registered for caching
NILFS version 2 loaded
BeFS version: 0.9.3
OCFS2 1.5.0
ocfs2: Registered cluster interface o2cb
ocfs2: Registered cluster interface user
OCFS2 DLMFS 1.5.0
OCFS2 User DLM kernel interface loaded
OCFS2 Node Manager 1.5.0
OCFS2 DLM 1.5.0
Btrfs loaded
GFS2 installed
ceph: loaded (mds proto 32)
msgmni has been set to 3864
NET: Registered protocol family 38
async_tx: api initialized (async)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 249)
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
start plist test
end plist test
crc32: CRC_LE_BITS = 64, CRC_BE BITS = 64
crc32: self tests passed, processed 225944 bytes in 171576 nsec
crc32c: CRC_LE_BITS = 64
crc32c: self tests passed, processed 225944 bytes in 87453 nsec
xz_dec_test: module loaded
xz_dec_test: Create a device node with 'mknod xz_dec_test c 248 0' and write .xz files to it.
pci_hotplug: PCI Hot Plug PCI Core version: 0.5
pciehp: PCI Express Hot Plug Controller Driver version: 0.4
cpcihp_zt5550: ZT5550 CompactPCI Hot Plug Driver version: 0.2
cpcihp_generic: Generic port I/O CompactPCI Hot Plug Driver version: 0.1
cpcihp_generic: not configured, disabling.
shpchp: Standard Hot Plug PCI Controller Driver version: 0.4
acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5
acpiphp: Slot [1] registered
acpiphp: Slot [2] registered
acpiphp: Slot [3] registered
acpiphp: Slot [4] registered
acpiphp: Slot [5] registered
acpiphp: Slot [6] registered
acpiphp: Slot [7] registered
acpiphp: Slot [8] registered
acpiphp: Slot [9] registered
acpiphp: Slot [10] registered
acpiphp: Slot [11] registered
acpiphp: Slot [12] registered
acpiphp: Slot [13] registered
acpiphp: Slot [14] registered
acpiphp: Slot [15] registered
acpiphp: Slot [16] registered
acpiphp: Slot [17] registered
acpiphp: Slot [18] registered
acpiphp: Slot [19] registered
acpiphp: Slot [20] registered
acpiphp: Slot [21] registered
acpiphp: Slot [22] registered
acpiphp: Slot [23] registered
acpiphp: Slot [24] registered
acpiphp: Slot [25] registered
acpiphp: Slot [26] registered
acpiphp: Slot [27] registered
acpiphp: Slot [28] registered
acpiphp: Slot [29] registered
acpiphp: Slot [30] registered
Refined TSC clocksource calibration: 2491.904 MHz.
acpiphp: Slot [31] registered
acpiphp_ibm: ibm_acpiphp_init: acpi_walk_namespace failed
ALI M7101 PMU not found.
INTEL CARILLO RANCH LPC not found.
Carillo Ranch Backlight Driver Initialized.
i2c-core: driver [adp8860_bl] using legacy suspend method
i2c-core: driver [adp8860_bl] using legacy resume method
i2c-core: driver [adp8870_bl] using legacy suspend method
i2c-core: driver [adp8870_bl] using legacy resume method
rivafb_setup START
nvidiafb_setup START
VIA Graphics Integration Chipset framebuffer 2.4 initializing
Could not find Carillo Ranch MCH device.
no IO addresses supplied
hgafb: HGA card not detected.
hgafb: probe of hgafb.0 failed with error -22
cirrusfb 0000:00:02.0: Cirrus Logic chipset on PCI bus, RAM (4096 kB) at 0xfc000000
fbcon: CL Picasso4 (fb0) is primary device
Console: switching 
to colour frame buffer device 80x30
usbcore: registered new interface driver udlfb
usbcore: registered new interface driver smscufx
uvesafb: failed to execute /sbin/v86d
uvesafb: make sure that the v86d helper is installed and executable
uvesafb: Getting VBE info block failed (eax=0x4f00, err=-2)
uvesafb: vbe_init() failed with -22
uvesafb: probe of uvesafb.0 failed with error -22
vga16fb: mapped to 0xffff8800000a0000
fb1: VGA16 VGA frame buffer device
input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
ACPI: Power Button [PWRF]
GHES: HEST is not enabled!
ERST DBG: ERST support is disabled.
ACPI: PCI Interrupt Link [LNKD] enabled at IRQ 11
ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 10
XENFS: not registering filesystem on non-xen platform
Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
ÿserial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
00:06: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A
Initializing Nozomi driver 2.1d
lp: driver loaded but no devices found
Non-volatile memory driver v1.3
ppdev: user-space parallel port driver
Linux agpgart interface v0.103
ipmi message handler version 39.2
ipmi device interface
IPMI System Interface driver.
ipmi_si: Adding default-specified kcs state machine
ipmi_si: Trying default-specified kcs state machine at i/o address 0xca2, slave address 0x0, irq 0
ipmi_si: Interface detection failed
ipmi_si: Adding default-specified smic state machine
ipmi_si: Trying default-specified smic state machine at i/o address 0xca9, slave address 0x0, irq 0
ipmi_si: Interface detection failed
ipmi_si: Adding default-specified bt state machine
ipmi_si: Trying default-specified bt state machine at i/o address 0xe4, slave address 0x0, irq 0
ipmi_si: Interface detection failed
ipmi_si: Unable to find any System Interface(s)
IPMI Watchdog: driver initialized
Copyright (C) 2004 MontaVista Software - IPMI Powerdown via sys_reboot.
Hangcheck: starting hangcheck timer 0.9.1 (tick is 180 seconds, margin is 60 seconds).
Hangcheck: Using getrawmonotonic().
ramoops: platform device not found, using module parameters
ramoops: The memory size and the record size must be non-zero
ramoops: probe of ramoops failed with error -22
[drm] Initialized drm 1.1.0 20060810
[drm] radeon defaulting to kernel modesetting.
[drm] radeon kernel modesetting enabled.
[drm:i915_init] *ERROR* drm/i915 can't work without intel_agp module!
usbcore: registered new interface driver udl
i2c-core: driver [ch7006] using legacy suspend method
i2c-core: driver [ch7006] using legacy resume method
parport_pc 00:05: reported by Plug and Play ACPI
parport0: PC-style at 0x378
, irq 7
 [
PCSPP
,TRISTATE
]
lp0: using parport0 (interrupt-driven).
lp0: console ready
FDC 0 is a S82078B
brd: module loaded
loop: module loaded
Compaq SMART2 Driver (v 2.6.0)
HP CISS Driver (v 3.6.26)
MM: desc_per_page = 128
nbd: registered device at major 43
 vda: unknown partition table
'Low Performance USB Block' driver is deprecated. Please switch to usb-storage
usbcore: registered new interface driver ub
drbd: initialized. Version: 8.3.11 (api:88/proto:86-96)
drbd: built-in
drbd: registered as block device major 147
drbd: minor_table @ 0xffff880070805da8
rbd: loaded rbd (rados block device)
mtip32xx Version 1.2.6os3
ibmasm: IBM ASM Service Processor Driver version 1.0 loaded
lkdtm: No crash points registered, enable through debugfs
Phantom Linux Driver, version n0.9.8, init OK
i2c-core: driver [apds9802als] using legacy suspend method
i2c-core: driver [apds9802als] using legacy resume method
i2c-core: driver [isl29003] using legacy suspend method
i2c-core: driver [isl29003] using legacy resume method
i2c-core: driver [tsl2550] using legacy suspend method
i2c-core: driver [tsl2550] using legacy resume method
Silicon Labs C2 port support v. 0.51.0 - (C) 2007 Rodolfo Giometti
c2port c2port0: C2 port uc added
c2port c2port0: uc flash has 30 blocks x 512 bytes (15360 bytes total)
i2c-core: driver [fsa9480] using legacy suspend method
i2c-core: driver [fsa9480] using legacy resume method
usbcore: registered new interface driver pn533
Uniform Multi-Platform E-IDE driver
piix 0000:00:01.1: IDE controller (0x8086:0x7010 rev 0x00)
piix 0000:00:01.1: not 100% native mode: will probe irqs later
    ide0: BM-DMA at 0xc180-0xc187
    ide1: BM-DMA at 0xc188-0xc18f
hdc: QEMU DVD-ROM, ATAPI CD/DVD-ROM drive
hdc: MWDMA2 mode selected
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
ide1 at 0x170-0x177,0x376 on irq 15
ide_generic: please use "probe_mask=0x3f" module parameter for probing all legacy ISA IDE ports
ide-gd driver 1.18
ide-cd driver 5.00
ide-cd: hdc: ATAPI 4X DVD-ROM drive, 512kB Cache
cdrom: Uniform CD-ROM driver Revision: 3.20
Loading iSCSI transport class v2.0-870.
fnic: Cisco FCoE HBA Driver, ver 1.5.0.2
bnx2fc: Broadcom NetXtreme II FCoE Driver bnx2fc v1.0.10 (Jan 22, 2011)
iscsi: registered transport (tcp)
Loading Adaptec I2O RAID: Version 2.4 Build 5go
Detecting Adaptec I2O RAID controllers...
Adaptec aacraid driver 1.2-0[28900]-ms
aic94xx: Adaptec aic94xx SAS/SATA driver version 1.0.3 loaded
isci: Intel(R) C600 SAS Controller Driver - version 1.1.0
scsi: <fdomain> Detection failed (no card)
qla2xxx [0000:00:00.0]-0005: : QLogic Fibre Channel HBA Driver: 8.03.07.13-k.
iscsi: registered transport (qla4xxx)
QLogic iSCSI HBA Driver
Emulex LightPulse Fibre Channel SCSI driver 8.3.30
Copyright(c) 2004-2009 Emulex.  All rights reserved.
Brocade BFA FC/FCOE SCSI driver - version: 3.0.23.0
DC390: clustering now enabled by default. If you get problems load
       with "disable_clustering=1" and report to maintainers
megaraid cmm: 2.20.2.7 (Release Date: Sun Jul 16 00:01:03 EST 2006)
megaraid: 2.20.5.1 (Release Date: Thu Nov 16 15:32:35 EST 2006)
megasas: 00.00.06.15-rc1 Mon. Mar. 19 17:00:00 PDT 2012
mpt2sas version 13.100.00.00 loaded
GDT-HA: Storage RAID Controller Driver. Version: 3.05
3ware Storage Controller device driver for Linux v1.26.02.003.
3ware 9000 Storage Controller device driver for Linux v2.26.02.014.
LSI 3ware SAS/SATA-RAID Controller device driver for Linux v3.26.02.000.
ppa: Version 2.07 (for Linux 2.4.x)
imm: Version 2.05 (for Linux 2.4.0)
ipr: IBM Power RAID SCSI Device Driver version: 2.5.3 (March 10, 2012)
RocketRAID 3xxx/4xxx Controller driver v1.6 (090910)
stex: Promise SuperTrak EX Driver version: 4.6.0000.4
libcxgbi:libcxgbi_init_module: tag itt 0x1fff, 13 bits, age 0xf, 4 bits.
libcxgbi:ddp_setup_host_page_size: system PAGE 4096, ddp idx 0.
Chelsio T3 iSCSI Driver cxgb3i v2.0.0 (Jun. 2010)
iscsi: registered transport (cxgb3i)
Chelsio T4 iSCSI Driver cxgb4i v0.9.1 (Aug. 2010)
iscsi: registered transport (cxgb4i)
Broadcom NetXtreme II iSCSI Driver bnx2i v2.7.0.3 (Jun 15, 2011)
iscsi: registered transport (bnx2i)
iscsi: registered transport (be2iscsi)
VMware PVSCSI driver - version 1.0.2.0-k
hv_vmbus: registering driver hv_storvsc
st: Version 20101219, fixed bufsize 32768, s/g segs 256
osst :I: Tape driver with OnStream support version 0.99.4
osst :I: $Id: osst.c,v 1.73 2005/01/01 21:13:34 wriede Exp $
SCSI Media Changer driver v0.25 
osd: LOADED open-osd 0.2.1
scsi_debug: host protection
scsi0 : scsi_debug, version 1.82 [20100324], dev_size_mb=8, opts=0x0
scsi 0:0:0:0: Direct-Access     Linux    scsi_debug       0004 PQ: 0 ANSI: 5
sd 0:0:0:0: [sda] 16384 512-byte logical blocks: (8.38 MB/8.00 MiB)
sd 0:0:0:0: Attached scsi generic sg0 type 0
scsi_scan_0 (3479) used greatest stack depth: 3768 bytes left
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, supports DPO and FUA
 sda: unknown partition table
sd 0:0:0:0: [sda] Attached SCSI disk
Error: Driver 'pata_platform' is already registered, aborting...
Rounding down aligned max_sectors from 4294967295 to 8388600
SSFDC read-only Flash Translation layer
mtdoops: mtd device (mtddev=name/number) must be supplied
physmap-flash.0: failed to claim resource 0
Generic platform RAM MTD, (c) 2004 Simtec Electronics
slram: not enough parameters.
ftl_cs: FTL header not found.
onenand_wait: timeout! ctrl=0x0000 intr=0x0000
OneNAND 16MB 1.8V 16-bit (0x04)
OneNAND version = 0x001e
Scanning device for bad blocks
Creating 1 MTD partitions on "OneNAND simulator":
0x000000000000-0x000001000000 : "OneNAND simulator partition"
ftl_cs: FTL header not found.
HSI/SSI char device loaded
bonding: Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
eql: Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)
Micrel KS8995 Ethernet switch SPI driver version 0.1.1
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <maxk@qualcomm.com>
arcnet loaded.
arcnet: RFC1201 "standard" (`a') encapsulation support loaded.
arcnet: RFC1051 "simple standard" (`s') encapsulation support loaded.
arcnet: raw mode (`r') encapsulation support loaded.
arcnet: cap mode (`c') encapsulation support loaded.
arcnet: COM90xx chipset support
S1: No ARCnet cards found.
arcnet: COM90xx IO-mapped mode support (by David Woodhouse et el.)
E-mail me if you actually test this driver, please!
 arc%d: No autoprobe for IO mapped cards; you must specify the base address!
arcnet: RIM I (entirely mem-mapped) support
E-mail me if you actually test the RIM I driver, please!
Given: node 00h, shmem 0h, irq 0
No autoprobe for RIM I; you must specify the shmem and irq!
arcnet: COM20020 PCI support
ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>
ipddp0: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>
vcan: Virtual CAN interface driver
slcan: serial line CAN interface driver
slcan: 10 dynamic interface channels.
CAN device driver interface
usbcore: registered new interface driver peak_usb
cnic: Broadcom NetXtreme II CNIC Driver cnic v2.5.10 (March 21, 2012)
e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI
e1000: Copyright (c) 1999-2006 Intel Corporation.
e1000e: Intel(R) PRO/1000 Network Driver - 2.0.0-k
e1000e: Copyright(c) 1999 - 2012 Intel Corporation.
igb: Intel(R) Gigabit Ethernet Network Driver - version 3.4.7-k
igb: Copyright (c) 2007-2012 Intel Corporation.
igbvf: Intel(R) Gigabit Virtual Function Network Driver - version 2.0.1-k
igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
mkiss: AX.25 Multikiss, Hans Albas PE1AYX
AX.25: 6pack driver, Revision: 0.3.0
YAM driver version 0.8 by F1OAT/F6FBB
AX.25: bpqether driver version 004
baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA
baycom_ser_fdx: version 0.10
hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA
hdlcdrv: version 0.8
baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA
baycom_ser_hdx: version 0.10
baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA
baycom_par: version 0.9
NET3 PLIP version 2.4-parport gniibe@mri.co.jp
plip0: Parallel port at 0x378, using IRQ 7.
PPP generic driver version 2.4.2
PPP BSD Compression module registered
PPP Deflate Compression module registered
PPP MPPE Compression module registered
NET: Registered protocol family 24
PPTP driver version 0.8.5
SLIP: version 0.8.4-NET3.019-NEWTTY (dynamic channels, max=256) (6 bit encapsulation enabled).
CSLIP: code copyright 1989 Regents of the University of California.
SLIP linefill/keepalive option.
iwlwifi: Intel(R) Wireless WiFi Link AGN driver for Linux, in-tree:d
iwlwifi: Copyright(c) 2003-2012 Intel Corporation
iwl4965: Intel(R) Wireless WiFi 4965 driver for Linux, in-tree:
iwl4965: Copyright(c) 2003-2011 Intel Corporation
iwl3945: Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux, in-tree:s
iwl3945: Copyright(c) 2003-2011 Intel Corporation
VMware vmxnet3 virtual NIC driver - version 1.1.29.0-k-NAPI
usbcore: registered new interface driver asix
usbcore: registered new interface driver cdc_ether
usbcore: registered new interface driver cdc_eem
usbcore: registered new interface driver net1080
usbcore: registered new interface driver cdc_subset
usbcore: registered new interface driver zaurus
usbcore: registered new interface driver sierra_net
usbcore: registered new interface driver cdc_ncm
usbcore: registered new interface driver qmi_wwan
adummy: version 1.0
I2O subsystem v1.325
i2o: max drivers = 8
I2O Configuration OSM v1.323
I2O Bus Adapter OSM v1.317
I2O Block Device OSM v1.325
I2O SCSI Peripheral OSM v1.316
I2O ProcFS OSM v1.316
Fusion MPT base driver 3.04.20
Copyright (c) 1999-2008 LSI Corporation
Fusion MPT SPI Host driver 3.04.20
Fusion MPT FC Host driver 3.04.20
Fusion MPT SAS Host driver 3.04.20
Fusion MPT misc device (ioctl) driver 3.04.20
mptctl: Registered with Fusion MPT base driver
mptctl: /dev/mptctl @ (major,minor=10,220)
Fusion MPT LAN driver 3.04.20
Generic UIO driver for PCI 2.3 devices version: 0.01.0
ks0108: ERROR: parport didn't register new device
cfag12864b: ERROR: ks0108 is not initialized
cfag12864bfb: ERROR: cfag12864b is not initialized
aoe: AoE v47 initialised.
paride: aten registered as protocol 0
paride: bpck registered as protocol 1
paride: comm registered as protocol 2
paride: dstr registered as protocol 3
paride: k951 registered as protocol 4
paride: k971 registered as protocol 5
paride: epat registered as protocol 6
paride: epia registered as protocol 7
paride: frpw registered as protocol 8
paride: friq registered as protocol 9
paride: fit2 registered as protocol 10
paride: fit3 registered as protocol 11
paride: on20 registered as protocol 12
paride: on26 registered as protocol 13
paride: ktti registered as protocol 14
pd: pd version 1.05, major 45, cluster 64, nice 0
pda: Autoprobe failed
pd: no valid drive found
pcd: pcd version 1.07, major 46, nice 0
pcd0: Autoprobe failed
pcd: No CD-ROM drive found
pf: pf version 1.04, major 47, cluster 64, nice 0
pf: No ATAPI disk detected
pt: pt version 1.04, major 96
pt0: Autoprobe failed
pt: No ATAPI tape drive detected
pg: pg version 1.02, major 97
pga: Autoprobe failed
pg: No ATAPI device detected
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
uhci_hcd: USB Universal Host Controller Interface driver
usbcore: registered new interface driver cdc_wdm
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
usbcore: registered new interface driver libusual
i8042: PNP: PS/2 Controller [PNP0303:KBD,PNP0f13:MOU] at 0x60,0x64 irq 1,12
serio: i8042 KBD port at 0x60,0x64 irq 1
serio: i8042 AUX port at 0x60,0x64 irq 12
mousedev: PS/2 mouse device common for all mice
input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input1
usbcore: registered new interface driver synaptics_usb
rtc_cmos 00:01: RTC can wake from S4
rtc_cmos 00:01: rtc core: registered rtc_cmos as rtc0
rtc0: alarms up to one day, 114 bytes nvram, hpet irqs
rtc-test rtc-test.0: rtc core: registered test as rtc1
rtc-test rtc-test.1: rtc core: registered test as rtc2
i2c /dev entries driver
lirc_dev: IR Remote Control driver registered, major 232 
IR NEC protocol handler initialized
IR RC5(x) protocol handler initialized
IR RC6 protocol handler initialized
IR JVC protocol handler initialized
IR Sony protocol handler initialized
IR RC5 (streamzap) protocol handler initialized
IR SANYO protocol handler initialized
IR MCE Keyboard/mouse protocol handler initialized
IR LIRC bridge handler initialized
gspca_main: v2.14.0 registered
usbcore: registered new interface driver jl2005bcd
vivi-000: V4L2 device registered as video0
Video Technology Magazine Virtual Video Capture Board ver 0.8.1 successfully loaded.
pps pps0: new PPS source ktimer
pps pps0: ktimer PPS source registered
pps_ldisc: PPS line discipline registered
pps_parport: parallel port PPS client
pps_parport: couldn't register with parport0
Driver for 1-wire Dallas network protocol.
usbcore: registered new interface driver DS9490R
DS1WM w1 busmaster driver - (c) 2004 Szabolcs Gyurko
1-Wire driver for the DS2760 battery monitor  chip  - (c) 2004-2005, Szabolcs Gyurko
i2c-core: driver [sbs-battery] using legacy suspend method
md: linear personality registered for level -1
md: raid0 personality registered for level 0
md: raid1 personality registered for level 1
md: raid10 personality registered for level 10
md: raid6 personality registered for level 6
md: raid5 personality registered for level 5
md: raid4 personality registered for level 4
md: multipath personality registered for level -4
md: faulty personality registered for level -5
device-mapper: uevent: version 1.0.3
device-mapper: ioctl: 4.22.0-ioctl (2011-10-19) initialised: dm-devel@redhat.com
device-mapper: multipath: version 1.3.0 loaded
device-mapper: multipath round-robin: version 1.0.0 loaded
device-mapper: multipath queue-length: version 0.1.0 loaded
device-mapper: multipath service-time: version 0.2.0 loaded
device-mapper: dm-log-userspace: version 1.1.0 loaded
Bluetooth: Virtual HCI driver ver 1.3
Bluetooth: HCI UART driver ver 2.2
Bluetooth: HCI H4 protocol initialized
Bluetooth: HCI BCSP protocol initialized
Bluetooth: HCILL protocol initialized
Bluetooth: HCIATH3K protocol initialized
usbcore: registered new interface driver btusb
Bluetooth: Generic Bluetooth SDIO driver ver 0.1
usbcore: registered new interface driver ath3k
ISDN subsystem Rev: 1.1.2.3/
1.1.2.2/
1.1.2.3/
1.1.2.2/
1.1.2.2

PPP BSD Compression module registered
CAPI 2.0 started up with major 68 (middleware)
Modular ISDN core version 1.1.28
NET: Registered protocol family 34
DSP module 2.0
mISDN_dsp: DSP clocks every 64 samples. This equals 8 jiffies.
mISDN: Layer-1-over-IP driver Rev. 2.00
0 virtual devices registered
dss1_divert module successfully installed
gigaset: Driver for Gigaset 307x (debug build)
gigaset: Kernel CAPI interface
usbcore: registered new interface driver usb_gigaset
usb_gigaset: USB Driver for Gigaset 307x using M105
usbcore: registered new interface driver bas_gigaset
bas_gigaset: USB Driver for Gigaset 307x
EDAC MC: Ver: 2.1.0
AMD64 EDAC driver v3.4.0
cpuidle: using governor ladder
cpuidle: using governor menu
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
usbcore: registered new interface driver ushc
sdhci-pltfm: SDHCI platform and OF driver helper
user_mad: couldn't register device number
iscsi: registered transport (iser)
EFI Variables Facility v0.08 2004-May-17
dcdbas dcdbas: Dell Systems Management Base Driver (version 5.6.0-3.2)
No iBFT detected.
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
usbcore: registered new interface driver Abilis Systems as10x usb driver
usbip_core: usbip_core_init:814: USB/IP Core v1.0.0
usbcore: registered new interface driver usbip-host
usbip_host: usbip_host_init:270: USB/IP Host Driver v1.0.0
usbcore: registered new interface driver w35und
usbcore: registered new interface driver prism2_usb
usbcore: registered new interface driver asus-oled
input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input2
Panel driver version 0.9.5 registered on parport0 (io=0x378).
usbcore: registered new interface driver r8712u
usbcore: registered new interface driver tranzport
usbcore: registered new interface driver alphatrack
VME User Space Access Driver
vme_user: No cards, skipping registration
zram: num_devices not specified. Using default: 1
zram: Creating 1 devices ...
Loading crystalhd 0.9.27
beceem: Beceem Communications Inc. WiMAX driver, 5.2.45
Copyright 2010. Beceem Communications Inc
usbcore: registered new interface driver usbbcm
usbcore: registered new interface driver ft1000usb
input: Speakup as /devices/virtual/input/input3
initialized device: /dev/synth, node (MAJOR 10, MINOR 25)
speakup 3.1.6: initialized
synth name on entry is: (null)
i2c-core: driver [cptm1217] using legacy suspend method
i2c-core: driver [cptm1217] using legacy resume method
Linux telephony interface: v1.00
ixj driver initialized.
ozwpan ozwpan: Ozmo Devices WPAN
ozwpan ozwpan: new USB bus registered, assigned bus number 1
usb usb1: New USB device found, idVendor=1d6b, idProduct=0001
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: Ozmo Devices WPAN
usb usb1: Manufacturer: Linux 3.4.0-rc6-next-20120508-sasha-00001-g8de7752-dirty Ozmo WPAN
usb usb1: SerialNumber: ozwpan
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 8 ports detected
asus_wmi: Asus Management GUID not found
asus_wmi: Management GUID not found
asus_wmi: Management GUID not found
msi_laptop: driver 0.5 successfully loaded
compal_laptop: Motherboard not recognized (You could try the module's force-parameter)
acerhdf: Acer Aspire One Fan driver, v.0.5.26
acerhdf: unknown (unsupported) BIOS version Bochs/Bochs/Bochs, please report, aborting!
hp_accel: driver loaded
hdaps: supported laptop not found!
hdaps: driver init failed (ret=-19)!
fujitsu_laptop: driver 0.6.0 successfully loaded
fujitsu_tablet: Unknown (using defaults)
msi_wmi: This machine doesn't have MSI-hotkeys through WMI
topstar_laptop: ACPI extras driver loaded
intel_oaktrail: Platform not recognized (You could try the module's force-parameter)
hv_utils: Registering HyperV Utility Driver
hv_vmbus: registering driver hv_util
Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98
aedsp16: I/O, IRQ and DMA are mandatory
pss: mss_io, mss_dma, mss_irq and pss_io must be set.
ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996
ad1848: No ISAPnP cards found, trying standard ones...
MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996
I/O, IRQ, DMA and type are mandatory
Pro Audio Spectrum driver Copyright (C) by Hannu Savolainen 1993-1996
I/O, IRQ, DMA and type are mandatory
sb: Init: Starting Probe...
sb: Init: Done
Cyrix Kahlua VSA1 XpressAudio support (c) Copyright 2003 Red Hat Inc
uart6850: irq and io must be set.
YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996
MIDI Loopback device driver
ALSA sound/core/seq/oss/seq_oss.c:236 can't register device seq
ALSA sound/core/oss/pcm_oss.c:3009 unable to register OSS PCM device 0:0
no UART detected at 0x1
ALSA sound/drivers/mtpav.c:589 MTVAP port 0x378 is busy
snd_mtpav: probe of snd_mtpav failed with error -16
snd_mts64: probe of snd_mts64.0 failed with error -5
snd_portman2x4: probe of snd_portman2x4.0 failed with error -5
input: PC Speaker as /devices/platform/pcspkr/input/input4
PCSP: CONFIG_DEBUG_PAGEALLOC is enabled, which may make the sound noisy.
usbcore: registered new interface driver snd-usb-audio
usbcore: registered new interface driver snd-ua101
usbcore: registered new interface driver snd-usb-usx2y
usbcore: registered new interface driver snd-usb-us122l
usbcore: registered new interface driver snd-usb-caiaq
usbcore: registered new interface driver snd-usb-6fire
oprofile: using NMI interrupt.
pktgen: Packet Generator for packet performance testing. Version: 2.74
GACT probability on
Mirror/redirect action on
Simple TC action Loaded
netem: version 1.3
u32 classifier
    Performance counters on
    input device check on
    Actions configured
Netfilter messages via NETLINK v0.30.
nfnl_acct: registering with nfnetlink.
nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
ctnetlink v0.93: registering with nfnetlink.
NF_TPROXY: Transparent proxy support initialized, version 4.1.0
NF_TPROXY: Copyright (c) 2006-2007 BalaBit IT Ltd.
xt_time: kernel timezone is -0000
ip_set: protocol 6
IPVS: Registered protocols (TCP, UDP, SCTP, AH, ESP)
IPVS: Connection hash table configured (size=4096, memory=64Kbytes)
IPVS: Creating netns size=3104 id=0
IPVS: ipvs loaded.
IPVS: [rr] scheduler registered.
IPVS: [wrr] scheduler registered.
IPVS: [lc] scheduler registered.
IPVS: [wlc] scheduler registered.
IPVS: [lblc] scheduler registered.
IPVS: [lblcr] scheduler registered.
IPVS: [dh] scheduler registered.
IPVS: [sh] scheduler registered.
IPVS: [sed] scheduler registered.
IPVS: [nq] scheduler registered.
IPVS: ftp: loaded support on port[0] = 21
IPVS: [sip] pe registered.
IPv4 over IPv4 tunneling driver
gre: GRE over IPv4 demultiplexor driver
ip_gre: GRE over IPv4 tunneling driver
ip_tables: (C) 2000-2006 Netfilter Core Team
ipt_CLUSTERIP: ClusterIP Version 0.8 loaded successfully
arp_tables: (C) 2002 David S. Miller
TCP: cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 10
Mobile IPv6
ip6_tables: (C) 2000-2006 Netfilter Core Team
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
NET: Registered protocol family 15
Bridge firewalling registered
Ebtables v2.0 registered
NET: Registered protocol family 4
NET: Registered protocol family 5
NET: Registered protocol family 9
X.25 for Linux Version 0.2
NET: Registered protocol family 6
NET: Registered protocol family 11
NET: Registered protocol family 3
can: controller area network core (rev 20090105 abi 8)
NET: Registered protocol family 29
can: raw protocol (rev 20090105)
can: broadcast manager protocol (rev 20090105 t)
can: netlink gateway (rev 20101209)
IrCOMM protocol (Dag Brattli)
Bluetooth: RFCOMM TTY layer initialized
Bluetooth: RFCOMM socket layer initialized
Bluetooth: RFCOMM ver 1.11
Bluetooth: BNEP (Ethernet Emulation) ver 1.3
Bluetooth: BNEP filters: protocol multicast
Bluetooth: CMTP (CAPI Emulation) ver 1.0
Bluetooth: HIDP (Human Interface Emulation) ver 1.2
RPC: Registered rdma transport module.
NET: Registered protocol family 33
RxRPC: Registered security type 2 'rxkad'
lec:lane_module_init: lec.c: initialized
mpoa:atm_mpoa_init: mpc.c: initialized
L2TP core driver, V2.0
PPPoL2TP kernel driver, V2.0
L2TP IP encapsulation support (L2TPv3)
L2TP netlink interface
L2TP ethernet pseudowire support (L2TPv3)
L2TP debugfs support
L2TP IP encapsulation support for IPv6 (L2TPv3)
NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team
DECnet: Routing cache hash table of 1024 buckets, 80Kbytes
NET: Registered protocol family 12
NET: Registered protocol family 19
NET: Registered protocol family 35
8021q: 802.1Q VLAN Support v1.8
DCCP: Activated CCID 2 (TCP-like)
DCCP: Activated CCID 3 (TCP-Friendly Rate Control)
sctp: Hash tables configured (established 26214 bind 26214)
NET: Registered protocol family 21
Registered RDS/iwarp transport
Registered RDS/infiniband transport
Registered RDS/tcp transport
lib80211: common routines for IEEE802.11 drivers
TIPC: Activated (version 2.0.0)
NET: Registered protocol family 30
TIPC: Started in single node mode
9pnet: Installing 9P2000 support
NET: Registered protocol family 37
NET: Registered protocol family 36
Registering the dns_resolver key type
libceph: loaded (mon/osd proto 15/24, osdmap 5/6 5/6)
batman_adv: B.A.T.M.A.N. advanced 2012.1.0 (compatibility version 14) loaded
openvswitch: Open vSwitch switching datapath
initlevel:7=late, 60 registered initcalls
registered taskstats version 1
kAFS: Red Hat AFS client v0.1 registering.
FS-Cache: Netfs 'afs' registered for caching
IMA: No TPM chip found, activating TPM-bypass!
raid6test: testing the 4-disk case...
raid6test: test_disks(0, 1): faila=  0(D)  failb=  1(D)  OK
CPA self-test:
raid6test: test_disks(0, 2): faila=  0(D)  failb=  2(P)  OK
raid6test: test_disks(0, 3): faila=  0(D)  failb=  3(Q)  OK
raid6test: test_disks(1, 2): faila=  1(D)  failb=  2(P)  OK
raid6test: test_disks(1, 3): faila=  1(D)  failb=  3(Q)  OK
 4k 524285 large 0 gb 0 x 262144[ffff880000000000-ffff88003ffff000] miss 0
raid6test: test_disks(2, 3): faila=  2(P)  failb=  3(Q)  OK
raid6test: testing the 5-disk case...
raid6test: test_disks(0, 1): faila=  0(D)  failb=  1(D)  OK
raid6test: test_disks(0, 2): faila=  0(D)  failb=  2(D)  OK
raid6test: test_disks(0, 3): faila=  0(D)  failb=  3(P)  OK
raid6test: test_disks(0, 4): faila=  0(D)  failb=  4(Q)  OK
raid6test: test_disks(1, 2): faila=  1(D)  failb=  2(D)  OK
raid6test: test_disks(1, 3): faila=  1(D)  failb=  3(P)  OK
raid6test: test_disks(1, 4): faila=  1(D)  failb=  4(Q)  OK
raid6test: test_disks(2, 3): faila=  2(D)  failb=  3(P)  OK
raid6test: test_disks(2, 4): faila=  2(D)  failb=  4(Q)  OK
raid6test: test_disks(3, 4): faila=  3(P)  failb=  4(Q)  OK
raid6test: testing the 11-disk case...
raid6test: test_disks(0, 1): faila=  0(D)  failb=  1(D)  OK
raid6test: test_disks(0, 2): faila=  0(D)  failb=  2(D)  OK
raid6test: test_disks(0, 3): faila=  0(D)  failb=  3(D)  OK
raid6test: test_disks(0, 4): faila=  0(D)  failb=  4(D)  OK
raid6test: test_disks(0, 5): faila=  0(D)  failb=  5(D)  OK
raid6test: test_disks(0, 6): faila=  0(D)  failb=  6(D)  OK
raid6test: test_disks(0, 7): faila=  0(D)  failb=  7(D)  OK
raid6test: test_disks(0, 8): faila=  0(D)  failb=  8(D)  OK
raid6test: test_disks(0, 9): faila=  0(D)  failb=  9(P)  OK
raid6test: test_disks(0, 10): faila=  0(D)  failb= 10(Q)  OK
raid6test: test_disks(1, 2): faila=  1(D)  failb=  2(D)  OK
raid6test: test_disks(1, 3): faila=  1(D)  failb=  3(D)  OK
raid6test: test_disks(1, 4): faila=  1(D)  failb=  4(D)  OK
raid6test: test_disks(1, 5): faila=  1(D)  failb=  5(D)  OK
raid6test: test_disks(1, 6): faila=  1(D)  failb=  6(D)  OK
raid6test: test_disks(1, 7): faila=  1(D)  failb=  7(D)  OK
raid6test: test_disks(1, 8): faila=  1(D)  failb=  8(D)  OK
raid6test: test_disks(1, 9): faila=  1(D)  failb=  9(P)  OK
raid6test: test_disks(1, 10): faila=  1(D)  failb= 10(Q)  OK
raid6test: test_disks(2, 3): faila=  2(D)  failb=  3(D)  OK
raid6test: test_disks(2, 4): faila=  2(D)  failb=  4(D)  OK
raid6test: test_disks(2, 5): faila=  2(D)  failb=  5(D)  OK
raid6test: test_disks(2, 6): faila=  2(D)  failb=  6(D)  OK
raid6test: test_disks(2, 7): faila=  2(D)  failb=  7(D)  OK
raid6test: test_disks(2, 8): faila=  2(D)  failb=  8(D)  OK
raid6test: test_disks(2, 9): faila=  2(D)  failb=  9(P)  OK
raid6test: test_disks(2, 10): faila=  2(D)  failb= 10(Q)  OK
raid6test: test_disks(3, 4): faila=  3(D)  failb=  4(D)  OK
raid6test: test_disks(3, 5): faila=  3(D)  failb=  5(D)  OK
raid6test: test_disks(3, 6): faila=  3(D)  failb=  6(D)  OK
raid6test: test_disks(3, 7): faila=  3(D)  failb=  7(D)  OK
raid6test: test_disks(3, 8): faila=  3(D)  failb=  8(D)  OK
raid6test: test_disks(3, 9): faila=  3(D)  failb=  9(P)  OK
raid6test: test_disks(3, 10): faila=  3(D)  failb= 10(Q)  OK
raid6test: test_disks(4, 5): faila=  4(D)  failb=  5(D)  OK
raid6test: test_disks(4, 6): faila=  4(D)  failb=  6(D)  OK
raid6test: test_disks(4, 7): faila=  4(D)  failb=  7(D)  OK
raid6test: test_disks(4, 8): faila=  4(D)  failb=  8(D)  OK
raid6test: test_disks(4, 9): faila=  4(D)  failb=  9(P)  OK
raid6test: test_disks(4, 10): faila=  4(D)  failb= 10(Q)  OK
raid6test: test_disks(5, 6): faila=  5(D)  failb=  6(D)  OK
raid6test: test_disks(5, 7): faila=  5(D)  failb=  7(D)  OK
raid6test: test_disks(5, 8): faila=  5(D)  failb=  8(D)  OK
raid6test: test_disks(5, 9): faila=  5(D)  failb=  9(P)  OK
raid6test: test_disks(5, 10): faila=  5(D)  failb= 10(Q)  OK
raid6test: test_disks(6, 7): faila=  6(D)  failb=  7(D)  OK
raid6test: test_disks(6, 8): faila=  6(D)  failb=  8(D)  OK
raid6test: test_disks(6, 9): faila=  6(D)  failb=  9(P)  OK
raid6test: test_disks(6, 10): faila=  6(D)  failb= 10(Q)  OK
raid6test: test_disks(7, 8): faila=  7(D)  failb=  8(D)  OK
raid6test: test_disks(7, 9): faila=  7(D)  failb=  9(P)  OK
raid6test: test_disks(7, 10): faila=  7(D)  failb= 10(Q)  OK
raid6test: test_disks(8, 9): faila=  8(D)  failb=  9(P)  OK
raid6test: test_disks(8, 10): faila=  8(D)  failb= 10(Q)  OK
raid6test: test_disks(9, 10): faila=  9(P)  failb= 10(Q)  OK
raid6test: testing the 12-disk case...
raid6test: test_disks(0, 1): faila=  0(D)  failb=  1(D)  OK
raid6test: test_disks(0, 2): faila=  0(D)  failb=  2(D)  OK
raid6test: test_disks(0, 3): faila=  0(D)  failb=  3(D)  OK
raid6test: test_disks(0, 4): faila=  0(D)  failb=  4(D)  OK
raid6test: test_disks(0, 5): faila=  0(D)  failb=  5(D)  OK
raid6test: test_disks(0, 6): faila=  0(D)  failb=  6(D)  OK
raid6test: test_disks(0, 7): faila=  0(D)  failb=  7(D)  OK
raid6test: test_disks(0, 8): faila=  0(D)  failb=  8(D)  OK
raid6test: test_disks(0, 9): faila=  0(D)  failb=  9(D)  OK
raid6test: test_disks(0, 10): faila=  0(D)  failb= 10(P)  OK
raid6test: test_disks(0, 11): faila=  0(D)  failb= 11(Q)  OK
raid6test: test_disks(1, 2): faila=  1(D)  failb=  2(D)  OK
raid6test: test_disks(1, 3): faila=  1(D)  failb=  3(D)  OK
raid6test: test_disks(1, 4): faila=  1(D)  failb=  4(D)  OK
raid6test: test_disks(1, 5): faila=  1(D)  failb=  5(D)  OK
raid6test: test_disks(1, 6): faila=  1(D)  failb=  6(D)  OK
raid6test: test_disks(1, 7): faila=  1(D)  failb=  7(D)  OK
raid6test: test_disks(1, 8): faila=  1(D)  failb=  8(D)  OK
raid6test: test_disks(1, 9): faila=  1(D)  failb=  9(D)  OK
raid6test: test_disks(1, 10): faila=  1(D)  failb= 10(P)  OK
raid6test: test_disks(1, 11): faila=  1(D)  failb= 11(Q)  OK
raid6test: test_disks(2, 3): faila=  2(D)  failb=  3(D)  OK
raid6test: test_disks(2, 4): faila=  2(D)  failb=  4(D)  OK
raid6test: test_disks(2, 5): faila=  2(D)  failb=  5(D)  OK
raid6test: test_disks(2, 6): faila=  2(D)  failb=  6(D)  OK
raid6test: test_disks(2, 7): faila=  2(D)  failb=  7(D)  OK
raid6test: test_disks(2, 8): faila=  2(D)  failb=  8(D)  OK
raid6test: test_disks(2, 9): faila=  2(D)  failb=  9(D)  OK
raid6test: test_disks(2, 10): faila=  2(D)  failb= 10(P)  OK
raid6test: test_disks(2, 11): faila=  2(D)  failb= 11(Q)  OK
raid6test: test_disks(3, 4): faila=  3(D)  failb=  4(D)  OK
raid6test: test_disks(3, 5): faila=  3(D)  failb=  5(D)  OK
raid6test: test_disks(3, 6): faila=  3(D)  failb=  6(D)  OK
raid6test: test_disks(3, 7): faila=  3(D)  failb=  7(D)  OK
raid6test: test_disks(3, 8): faila=  3(D)  failb=  8(D)  OK
raid6test: test_disks(3, 9): faila=  3(D)  failb=  9(D)  OK
raid6test: test_disks(3, 10): faila=  3(D)  failb= 10(P)  OK
raid6test: test_disks(3, 11): faila=  3(D)  failb= 11(Q)  OK
raid6test: test_disks(4, 5): faila=  4(D)  failb=  5(D)  OK
raid6test: test_disks(4, 6): faila=  4(D)  failb=  6(D)  OK
raid6test: test_disks(4, 7): faila=  4(D)  failb=  7(D)  OK
raid6test: test_disks(4, 8): faila=  4(D)  failb=  8(D)  OK
raid6test: test_disks(4, 9): faila=  4(D)  failb=  9(D)  OK
raid6test: test_disks(4, 10): faila=  4(D)  failb= 10(P)  OK
raid6test: test_disks(4, 11): faila=  4(D)  failb= 11(Q)  OK
raid6test: test_disks(5, 6): faila=  5(D)  failb=  6(D)  OK
raid6test: test_disks(5, 7): faila=  5(D)  failb=  7(D)  OK
raid6test: test_disks(5, 8): faila=  5(D)  failb=  8(D)  OK
raid6test: test_disks(5, 9): faila=  5(D)  failb=  9(D)  OK
raid6test: test_disks(5, 10): faila=  5(D)  failb= 10(P)  OK
raid6test: test_disks(5, 11): faila=  5(D)  failb= 11(Q)  OK
raid6test: test_disks(6, 7): faila=  6(D)  failb=  7(D)  OK
raid6test: test_disks(6, 8): faila=  6(D)  failb=  8(D)  OK
raid6test: test_disks(6, 9): faila=  6(D)  failb=  9(D)  OK
raid6test: test_disks(6, 10): faila=  6(D)  failb= 10(P)  OK
raid6test: test_disks(6, 11): faila=  6(D)  failb= 11(Q)  OK
raid6test: test_disks(7, 8): faila=  7(D)  failb=  8(D)  OK
raid6test: test_disks(7, 9): faila=  7(D)  failb=  9(D)  OK
raid6test: test_disks(7, 10): faila=  7(D)  failb= 10(P)  OK
raid6test: test_disks(7, 11): faila=  7(D)  failb= 11(Q)  OK
raid6test: test_disks(8, 9): faila=  8(D)  failb=  9(D)  OK
raid6test: test_disks(8, 10): faila=  8(D)  failb= 10(P)  OK
raid6test: test_disks(8, 11): faila=  8(D)  failb= 11(Q)  OK
raid6test: test_disks(9, 10): faila=  9(D)  failb= 10(P)  OK
raid6test: test_disks(9, 11): faila=  9(D)  failb= 11(Q)  OK
raid6test: test_disks(10, 11): faila= 10(P)  failb= 11(Q)  OK
raid6test: testing the 16-disk case...
raid6test: test_disks(0, 1): faila=  0(D)  failb=  1(D)  OK
raid6test: test_disks(0, 2): faila=  0(D)  failb=  2(D)  OK
raid6test: test_disks(0, 3): faila=  0(D)  failb=  3(D)  OK
raid6test: test_disks(0, 4): faila=  0(D)  failb=  4(D)  OK
raid6test: test_disks(0, 5): faila=  0(D)  failb=  5(D)  OK
raid6test: test_disks(0, 6): faila=  0(D)  failb=  6(D)  OK
raid6test: test_disks(0, 7): faila=  0(D)  failb=  7(D)  OK
raid6test: test_disks(0, 8): faila=  0(D)  failb=  8(D)  OK
raid6test: test_disks(0, 9): faila=  0(D)  failb=  9(D)  OK
raid6test: test_disks(0, 10): faila=  0(D)  failb= 10(D)  OK
raid6test: test_disks(0, 11): faila=  0(D)  failb= 11(D)  OK
raid6test: test_disks(0, 12): faila=  0(D)  failb= 12(D)  OK
raid6test: test_disks(0, 13): faila=  0(D)  failb= 13(D)  OK
raid6test: test_disks(0, 14): faila=  0(D)  failb= 14(P)  OK
raid6test: test_disks(0, 15): faila=  0(D)  failb= 15(Q)  OK
raid6test: test_disks(1, 2): faila=  1(D)  failb=  2(D)  OK
raid6test: test_disks(1, 3): faila=  1(D)  failb=  3(D)  OK
raid6test: test_disks(1, 4): faila=  1(D)  failb=  4(D)  OK
raid6test: test_disks(1, 5): faila=  1(D)  failb=  5(D)  OK
raid6test: test_disks(1, 6): faila=  1(D)  failb=  6(D)  OK
raid6test: test_disks(1, 7): faila=  1(D)  failb=  7(D)  OK
raid6test: test_disks(1, 8): faila=  1(D)  failb=  8(D)  OK
raid6test: test_disks(1, 9): faila=  1(D)  failb=  9(D)  OK
raid6test: test_disks(1, 10): faila=  1(D)  failb= 10(D)  OK
raid6test: test_disks(1, 11): faila=  1(D)  failb= 11(D)  OK
raid6test: test_disks(1, 12): faila=  1(D)  failb= 12(D)  OK
raid6test: test_disks(1, 13): faila=  1(D)  failb= 13(D)  OK
raid6test: test_disks(1, 14): faila=  1(D)  failb= 14(P)  OK
raid6test: test_disks(1, 15): faila=  1(D)  failb= 15(Q)  OK
raid6test: test_disks(2, 3): faila=  2(D)  failb=  3(D)  OK
raid6test: test_disks(2, 4): faila=  2(D)  failb=  4(D)  OK
raid6test: test_disks(2, 5): faila=  2(D)  failb=  5(D)  OK
raid6test: test_disks(2, 6): faila=  2(D)  failb=  6(D)  OK
raid6test: test_disks(2, 7): faila=  2(D)  failb=  7(D)  OK
raid6test: test_disks(2, 8): faila=  2(D)  failb=  8(D)  OK
raid6test: test_disks(2, 9): faila=  2(D)  failb=  9(D)  OK
raid6test: test_disks(2, 10): faila=  2(D)  failb= 10(D)  OK
raid6test: test_disks(2, 11): faila=  2(D)  failb= 11(D)  OK
raid6test: test_disks(2, 12): faila=  2(D)  failb= 12(D)  OK
raid6test: test_disks(2, 13): faila=  2(D)  failb= 13(D)  OK
raid6test: test_disks(2, 14): faila=  2(D)  failb= 14(P)  OK
raid6test: test_disks(2, 15): faila=  2(D)  failb= 15(Q)  OK
raid6test: test_disks(3, 4): faila=  3(D)  failb=  4(D)  OK
raid6test: test_disks(3, 5): faila=  3(D)  failb=  5(D)  OK
raid6test: test_disks(3, 6): faila=  3(D)  failb=  6(D)  OK
raid6test: test_disks(3, 7): faila=  3(D)  failb=  7(D)  OK
raid6test: test_disks(3, 8): faila=  3(D)  failb=  8(D)  OK
raid6test: test_disks(3, 9): faila=  3(D)  failb=  9(D)  OK
raid6test: test_disks(3, 10): faila=  3(D)  failb= 10(D)  OK
raid6test: test_disks(3, 11): faila=  3(D)  failb= 11(D)  OK
raid6test: test_disks(3, 12): faila=  3(D)  failb= 12(D)  OK
raid6test: test_disks(3, 13): faila=  3(D)  failb= 13(D)  OK
raid6test: test_disks(3, 14): faila=  3(D)  failb= 14(P)  OK
raid6test: test_disks(3, 15): faila=  3(D)  failb= 15(Q)  OK
raid6test: test_disks(4, 5): faila=  4(D)  failb=  5(D)  OK
raid6test: test_disks(4, 6): faila=  4(D)  failb=  6(D)  OK
raid6test: test_disks(4, 7): faila=  4(D)  failb=  7(D)  OK
raid6test: test_disks(4, 8): faila=  4(D)  failb=  8(D)  OK
raid6test: test_disks(4, 9): faila=  4(D)  failb=  9(D)  OK
raid6test: test_disks(4, 10): faila=  4(D)  failb= 10(D)  OK
raid6test: test_disks(4, 11): faila=  4(D)  failb= 11(D)  OK
raid6test: test_disks(4, 12): faila=  4(D)  failb= 12(D)  OK
raid6test: test_disks(4, 13): faila=  4(D)  failb= 13(D)  OK
raid6test: test_disks(4, 14): faila=  4(D)  failb= 14(P)  OK
raid6test: test_disks(4, 15): faila=  4(D)  failb= 15(Q)  OK
raid6test: test_disks(5, 6): faila=  5(D)  failb=  6(D)  OK
raid6test: test_disks(5, 7): faila=  5(D)  failb=  7(D)  OK
raid6test: test_disks(5, 8): faila=  5(D)  failb=  8(D)  OK
raid6test: test_disks(5, 9): faila=  5(D)  failb=  9(D)  OK
raid6test: test_disks(5, 10): faila=  5(D)  failb= 10(D)  OK
raid6test: test_disks(5, 11): faila=  5(D)  failb= 11(D)  OK
raid6test: test_disks(5, 12): faila=  5(D)  failb= 12(D)  OK
raid6test: test_disks(5, 13): faila=  5(D)  failb= 13(D)  OK
raid6test: test_disks(5, 14): faila=  5(D)  failb= 14(P)  OK
raid6test: test_disks(5, 15): faila=  5(D)  failb= 15(Q)  OK
raid6test: test_disks(6, 7): faila=  6(D)  failb=  7(D)  OK
raid6test: test_disks(6, 8): faila=  6(D)  failb=  8(D)  OK
raid6test: test_disks(6, 9): faila=  6(D)  failb=  9(D)  OK
raid6test: test_disks(6, 10): faila=  6(D)  failb= 10(D)  OK
raid6test: test_disks(6, 11): faila=  6(D)  failb= 11(D)  OK
raid6test: test_disks(6, 12): faila=  6(D)  failb= 12(D)  OK
raid6test: test_disks(6, 13): faila=  6(D)  failb= 13(D)  OK
raid6test: test_disks(6, 14): faila=  6(D)  failb= 14(P)  OK
raid6test: test_disks(6, 15): faila=  6(D)  failb= 15(Q)  OK
raid6test: test_disks(7, 8): faila=  7(D)  failb=  8(D)  OK
raid6test: test_disks(7, 9): faila=  7(D)  failb=  9(D)  OK
raid6test: test_disks(7, 10): faila=  7(D)  failb= 10(D)  OK
raid6test: test_disks(7, 11): faila=  7(D)  failb= 11(D)  OK
raid6test: test_disks(7, 12): faila=  7(D)  failb= 12(D)  OK
raid6test: test_disks(7, 13): faila=  7(D)  failb= 13(D)  OK
raid6test: test_disks(7, 14): faila=  7(D)  failb= 14(P)  OK
raid6test: test_disks(7, 15): faila=  7(D)  failb= 15(Q)  OK
raid6test: test_disks(8, 9): faila=  8(D)  failb=  9(D)  OK
raid6test: test_disks(8, 10): faila=  8(D)  failb= 10(D)  OK
raid6test: test_disks(8, 11): faila=  8(D)  failb= 11(D)  OK
raid6test: test_disks(8, 12): faila=  8(D)  failb= 12(D)  OK
raid6test: test_disks(8, 13): faila=  8(D)  failb= 13(D)  OK
raid6test: test_disks(8, 14): faila=  8(D)  failb= 14(P)  OK
raid6test: test_disks(8, 15): faila=  8(D)  failb= 15(Q)  OK
raid6test: test_disks(9, 10): faila=  9(D)  failb= 10(D)  OK
raid6test: test_disks(9, 11): faila=  9(D)  failb= 11(D)  OK
raid6test: test_disks(9, 12): faila=  9(D)  failb= 12(D)  OK
raid6test: test_disks(9, 13): faila=  9(D)  failb= 13(D)  OK
raid6test: test_disks(9, 14): faila=  9(D)  failb= 14(P)  OK
raid6test: test_disks(9, 15): faila=  9(D)  failb= 15(Q)  OK
raid6test: test_disks(10, 11): faila= 10(D)  failb= 11(D)  OK
raid6test: test_disks(10, 12): faila= 10(D)  failb= 12(D)  OK
raid6test: test_disks(10, 13): faila= 10(D)  failb= 13(D)  OK
raid6test: test_disks(10, 14): faila= 10(D)  failb= 14(P)  OK
raid6test: test_disks(10, 15): faila= 10(D)  failb= 15(Q)  OK
raid6test: test_disks(11, 12): faila= 11(D)  failb= 12(D)  OK
raid6test: test_disks(11, 13): faila= 11(D)  failb= 13(D)  OK
raid6test: test_disks(11, 14): faila= 11(D)  failb= 14(P)  OK
raid6test: test_disks(11, 15): faila= 11(D)  failb= 15(Q)  OK
raid6test: test_disks(12, 13): faila= 12(D)  failb= 13(D)  OK
raid6test: test_disks(12, 14): faila= 12(D)  failb= 14(P)  OK
raid6test: test_disks(12, 15): faila= 12(D)  failb= 15(Q)  OK
raid6test: test_disks(13, 14): faila= 13(D)  failb= 14(P)  OK
raid6test: test_disks(13, 15): faila= 13(D)  failb= 15(Q)  OK
raid6test: test_disks(14, 15): faila= 14(P)  failb= 15(Q)  OK
raid6test: 
raid6test: complete (257 tests, 0 failures)
  Magic number: 12:896:482
sound pcmC0D0c: hash matches
register_blkdev: cannot get major 3 for hd
 4k 524285 large 0 gb 0 x 262144[ffff880000000000-ffff88003ffff000] miss 0
 4k 524285 large 0 gb 0 x 262144[ffff880000000000-ffff88003ffff000] miss 0
ok.
console [netcon0] enabled
netconsole: network logging started
rtc_cmos 00:01: setting system clock to 2012-05-08 13:27:56 UTC (1336483676)
BIOS EDD facility v0.16 2004-Jun-25, 1 devices found
ALSA device list:
  #0: Dummy 1
  #1: Loopback 1
  #2: Virtual MIDI Card 1
  #3: Internal PC-Speaker at port 0x61
md: Waiting for all devices to be available before autodetect
md: If you don't use raid, use raid=noautodetect
md: Autodetecting RAID arrays.
md: Scanned 0 and added 0 devices.
md: autorun ...
md: ... autorun DONE.
kjournald starting.  Commit interval 5 seconds
EXT3-fs (vda): using internal journal
EXT3-fs (vda): recovery complete
EXT3-fs (vda): mounted filesystem with ordered data mode
VFS: Mounted root (ext3 filesystem) on device 250:0.
devtmpfs: mounted
debug: unmapping init [mem 0xffffffff84003000-0xffffffff8434ffff]
Write protecting the kernel read-only data: 43008k
Testing CPA: undo ffffffff81000000-ffffffff83a00000
Testing CPA: again
debug: unmapping init [mem 0xffff880002d96000-0xffff880002dfffff]
debug: unmapping init [mem 0xffff8800039e5000-0xffff8800039fffff]
Mounting...
sh-4.2# hrtimer: interrupt took 4472708 ns
xQEMU: Terminated
\r

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 13:33     ` Sasha Levin
@ 2012-05-08 14:29       ` Kay Sievers
  2012-05-08 15:33         ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-08 14:29 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Tue, May 8, 2012 at 3:33 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
> On Tue, May 8, 2012 at 1:14 PM, Kay Sievers <kay@vrfy.org> wrote:

> The 3rd one actually looks like the KERN_CONT problem now that you've
> explained it. You can see it in the 'saved trace' test in the boot
> log.
>
> I've attached the boot log which shows several other places with this
> issue,

The percpu stuff should be pending (thought it was in -next already):
  https://lkml.org/lkml/2012/3/29/317

The ACPI stuff was fixed here:
  https://lkml.org/lkml/2012/4/2/532

But only the vt and hpet things got merged so far:
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commitdiff;h=5da527aafed2834852fc4fe21daeaeadf7c61af3

I'll respin the ACPI parts now.

> if you're ok with it I can try patching those myself.

That would be awesome. If you decide otherwise, please let me know,
and I'll take care of them.

Even if we decide to relax the current strict behaviour later, we
should fix all stuff we run into. Userspace really relies on proper
messages, and not partial or mixed up things to guess what they mean.

The nice thing with the currently strict logic is that only two
instances of KERN_CONT running at the same time can race against each
other and mix their own messages. Unlike the old kmsg behaviour, users
which log a single proper terminated line, will never get interleaved
with the KERN_CONT users. This reduces the "risk" of garbled messages
to the users which actually decided to take this "risk".

Thanks,
Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 14:29       ` Kay Sievers
@ 2012-05-08 15:33         ` Kay Sievers
  2012-05-08 15:57           ` Sasha Levin
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-08 15:33 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Tue, May 8, 2012 at 4:29 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Tue, May 8, 2012 at 3:33 PM, Sasha Levin <levinsasha928@gmail.com> wrote:

>> if you're ok with it I can try patching those myself.
>
> That would be awesome. If you decide otherwise, please let me know,
> and I'll take care of them.

Sent the rest out, which got lost a while ago. Here's the already
fixed and pending stuff, so you can check what's not covered and still
missing on your box.

percpu:
  http://thread.gmane.org/gmane.linux.kernel/1274450

mm:
  http://thread.gmane.org/gmane.linux.kernel/1293437

acpi:
  http://thread.gmane.org/gmane.linux.kernel/1293438

Thanks,
Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 15:33         ` Kay Sievers
@ 2012-05-08 15:57           ` Sasha Levin
  2012-05-08 16:27             ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Sasha Levin @ 2012-05-08 15:57 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Tue, May 8, 2012 at 5:33 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Tue, May 8, 2012 at 4:29 PM, Kay Sievers <kay@vrfy.org> wrote:
>> On Tue, May 8, 2012 at 3:33 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
>
>>> if you're ok with it I can try patching those myself.
>>
>> That would be awesome. If you decide otherwise, please let me know,
>> and I'll take care of them.
>
> Sent the rest out, which got lost a while ago. Here's the already
> fixed and pending stuff, so you can check what's not covered and still
> missing on your box.

> mm:
>  http://thread.gmane.org/gmane.linux.kernel/1293437

Woops, look like I've did this one all over.


What about PRINTK_TIME? Are there plans to enable it on console output?

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 15:57           ` Sasha Levin
@ 2012-05-08 16:27             ` Kay Sievers
  2012-05-08 22:57               ` Greg Kroah-Hartmann
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-08 16:27 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel,
	Karel Zak

On Tue, May 8, 2012 at 5:57 PM, Sasha Levin <levinsasha928@gmail.com> wrote:

> What about PRINTK_TIME? Are there plans to enable it on console output?

Yeah, we should restore the old behaviour. The timestamp is always
stored internally, regardless of the CONFIG_PRINTK_TIME or tunable
setting. At the moment, seems they are only (conditionally) added to
the syslog() output and (unconditionally) to the /dev/kmsg export.

I guess we just re-define CONFIG_PRINTK_TIME and the tunable as: "show
time in syslog() and on the console output".

Karel will likely extend dmesg(1) to use /dev/kmsg instead of syslog()
when it's readable and dmesg(1) can still show the time stamps read
from /dev/kmsg, even when CONFIG_PRINTK_TIME is not set, so the old
tunable basically becomes a "show timestamps on the console" flag. :)

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 16:27             ` Kay Sievers
@ 2012-05-08 22:57               ` Greg Kroah-Hartmann
  0 siblings, 0 replies; 100+ messages in thread
From: Greg Kroah-Hartmann @ 2012-05-08 22:57 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Sasha Levin, Linus Torvalds, Ingo Molnar, linux-kernel, Karel Zak

On Tue, May 08, 2012 at 06:27:42PM +0200, Kay Sievers wrote:
> On Tue, May 8, 2012 at 5:57 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
> 
> > What about PRINTK_TIME? Are there plans to enable it on console output?
> 
> Yeah, we should restore the old behaviour. The timestamp is always
> stored internally, regardless of the CONFIG_PRINTK_TIME or tunable
> setting. At the moment, seems they are only (conditionally) added to
> the syslog() output and (unconditionally) to the /dev/kmsg export.
> 
> I guess we just re-define CONFIG_PRINTK_TIME and the tunable as: "show
> time in syslog() and on the console output".

That would be good to put back, can you do that?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-08 11:14   ` Kay Sievers
  2012-05-08 13:33     ` Sasha Levin
@ 2012-05-09  3:52     ` Linus Torvalds
  2012-05-09  4:06       ` Joe Perches
                         ` (2 more replies)
  1 sibling, 3 replies; 100+ messages in thread
From: Linus Torvalds @ 2012-05-09  3:52 UTC (permalink / raw)
  To: Kay Sievers; +Cc: Sasha Levin, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Tue, May 8, 2012 at 4:14 AM, Kay Sievers <kay@vrfy.org> wrote:
>
> Yeah, we need to make sure, we never merge the (always racy)
> continuation printk() users with (non-racy) non-continuation users.
> Therefore KERN_CONT is required to suppress the newline and to merge the
> content with the earlier non-newline-terminated printk() line.

Why?

I really think this is just a bug in the new code.

KERN_CONT should not be needed if the previous printk didn't have a final "\n".

We made it easier to use printk for a reason a few months ago. The new
rules are:

 - If you have a KERN_<loglevel>, it *always* starts a new line, the
obvious exception being KERN_CONT

 - the loglevels *only* matter at the start of the printk - so if you
have '\n' embedded in a single printk, that changes nothing
what-so-ever. It's not line-based.

 - if you didn't have a '\n', and don't have a loglevel, KERN_CONT is implied.

Quite frankly, those three rules (a) make sense and (b) make things easy.

Breaking them now is a bug. Please don't go adding ugly KERN_CONT when
there really isn't any reason for it. Just fix the printk code you
broke.

                  Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  3:52     ` Linus Torvalds
@ 2012-05-09  4:06       ` Joe Perches
  2012-05-09  4:11       ` Sasha Levin
  2012-05-09  9:38       ` Kay Sievers
  2 siblings, 0 replies; 100+ messages in thread
From: Joe Perches @ 2012-05-09  4:06 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Sasha Levin, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Tue, 2012-05-08 at 20:52 -0700, Linus Torvalds wrote:
> On Tue, May 8, 2012 at 4:14 AM, Kay Sievers <kay@vrfy.org> wrote:
> > Yeah, we need to make sure, we never merge the (always racy)
> > continuation printk() users with (non-racy) non-continuation users.
> > Therefore KERN_CONT is required to suppress the newline and to merge the
> > content with the earlier non-newline-terminated printk() line.
> 
> Please don't go adding ugly KERN_CONT when
> there really isn't any reason for it. Just fix the printk code you
> broke.

Thanks for making that clear.


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  3:52     ` Linus Torvalds
  2012-05-09  4:06       ` Joe Perches
@ 2012-05-09  4:11       ` Sasha Levin
  2012-05-09  4:27         ` Linus Torvalds
  2012-05-09  9:38       ` Kay Sievers
  2 siblings, 1 reply; 100+ messages in thread
From: Sasha Levin @ 2012-05-09  4:11 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Wed, May 9, 2012 at 5:52 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> KERN_CONT should not be needed if the previous printk didn't have a final "\n".
>
> We made it easier to use printk for a reason a few months ago. The new
> rules are:
>
>  - If you have a KERN_<loglevel>, it *always* starts a new line, the
> obvious exception being KERN_CONT
>
>  - the loglevels *only* matter at the start of the printk - so if you
> have '\n' embedded in a single printk, that changes nothing
> what-so-ever. It's not line-based.
>
>  - if you didn't have a '\n', and don't have a loglevel, KERN_CONT is implied.
>
> Quite frankly, those three rules (a) make sense and (b) make things easy.

Is there a reason to keep KERN_CONT under this set of rules at all?

I'm guessing that there are very few places that have a final '\n' but
still want to use KERN_CONT, and even in that case it should be
trivially easy to fix them up.

Besides that, from what I understand, KERN_CONT isn't really needed.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  4:11       ` Sasha Levin
@ 2012-05-09  4:27         ` Linus Torvalds
  2012-05-09  4:36           ` Linus Torvalds
  0 siblings, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-09  4:27 UTC (permalink / raw)
  To: Sasha Levin; +Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Tue, May 8, 2012 at 9:11 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
>
> Is there a reason to keep KERN_CONT under this set of rules at all?

Yes, a very subtle and rare one.

If you want to print out a string that starts with "<%d>", you *have*
to use a prefix, in order to not make printk think that the "<*>" is
the prefix itself.

And if you don't want to start a new line, you need to use KERN_CONT.

So there is *one* case, and one case only, where KERN_CONT is useful,
and it's when the string you are printing out could otherwise be
mistaken for a prefix itself (the "<%d>" thing isn't the only such
string, of course - it could be a "%s" where the string has those
characters in it.

So think of KERN_CONT as a "quoting safety" thing. And in 99% of all
cases it is obviously not actually needed. So in general, KERN_CONT is
useless and should not be used, but that doesn't mean that it can be
removed as a _concept_.

               Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  4:27         ` Linus Torvalds
@ 2012-05-09  4:36           ` Linus Torvalds
  2012-05-09  7:07             ` Ingo Molnar
  0 siblings, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-09  4:36 UTC (permalink / raw)
  To: Sasha Levin; +Cc: Kay Sievers, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Tue, May 8, 2012 at 9:27 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> So think of KERN_CONT as a "quoting safety" thing. And in 99% of all
> cases it is obviously not actually needed. So in general, KERN_CONT is
> useless and should not be used, but that doesn't mean that it can be
> removed as a _concept_.

Btw, KERN_DEFAULT is the exact same thing for the "I start a new line,
but I don't really have a special priority level".

And it's *way* overused. At one point we used to have the policy that
all new printk()'s should have a priority level, presumably so that we
at some point could have just made it a real argument instead (ie
'printk(prio, "fmt", arg)').

However, that turned out to be just stupid (the same way encouraging
people to always use KERN_CONT was/is stupid). It turns out that a lot
of printk's really don't have a good priority level, there's no reason
to force them to use KERN_DEFAULT, and it doesn't actually add *any*
value what-so-ever.

But again, it can be useful for the special case where you start a new
printk() with a string that could be mistaken for the priority marker.
So exactly like KERN_CONT, KERN_DEFAULT can be used for "quoting"
purposes.

Of course, if you print out random strings with odd random crap in the
first few characters, you're probably doing something really really
wrong. So 99% of the time, you should never need KERN_DEFAULT or
KERN_CONT. They exist for the rare exceptional case, and they do
*need* to exist, but they should not generally need to be *used*.

So it's like a defibrillator: it is good to *have* one, but it's
really bad to have to *use* one.

                       Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  4:36           ` Linus Torvalds
@ 2012-05-09  7:07             ` Ingo Molnar
  2012-05-09 13:21               ` Kay Sievers
  2012-05-09 13:29               ` Kay Sievers
  0 siblings, 2 replies; 100+ messages in thread
From: Ingo Molnar @ 2012-05-09  7:07 UTC (permalink / raw)
  To: Linus Torvalds, Jonathan Corbet
  Cc: Sasha Levin, Kay Sievers, Greg Kroah-Hartmann, linux-kernel


* Linus Torvalds <torvalds@linux-foundation.org> wrote:

> [...]
> 
> So it's like a defibrillator: it is good to *have* one, but 
> it's really bad to have to *use* one.

/me nominates this for LWN quote of the week!

Thanks for bringing sanity into printk,

	Ingo

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  3:52     ` Linus Torvalds
  2012-05-09  4:06       ` Joe Perches
  2012-05-09  4:11       ` Sasha Levin
@ 2012-05-09  9:38       ` Kay Sievers
  2012-05-09 13:50         ` Joe Perches
  2 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-09  9:38 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Sasha Levin, Greg Kroah-Hartmann, Ingo Molnar, linux-kernel

On Wed, May 9, 2012 at 5:52 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Tue, May 8, 2012 at 4:14 AM, Kay Sievers <kay@vrfy.org> wrote:
>>
>> Yeah, we need to make sure, we never merge the (always racy)
>> continuation printk() users with (non-racy) non-continuation users.
>> Therefore KERN_CONT is required to suppress the newline and to merge the
>> content with the earlier non-newline-terminated printk() line.
>
> Why?

The idea was: Prefixes are not used that often, but not using a prefix
should not expose the user to wrongly get appended to an earlier
non-terminated line of another thread.

The point was to limit the "risk" of wrong merges to users of
continuation, and not to users which send ordinary "atomic" lines.

> I really think this is just a bug in the new code.
>
> KERN_CONT should not be needed if the previous printk didn't have a final "\n".

It significantly limits wrong merges, especially for users which can
rightfully expect not to get a wrong merge.

> We made it easier to use printk for a reason a few months ago. The new
> rules are:
>
>  - If you have a KERN_<loglevel>, it *always* starts a new line, the
> obvious exception being KERN_CONT
>
>  - the loglevels *only* matter at the start of the printk - so if you
> have '\n' embedded in a single printk, that changes nothing
> what-so-ever. It's not line-based.

It is a different behaviour. "Innocent" users are not exposed to "risky" users.

>  - if you didn't have a '\n', and don't have a loglevel, KERN_CONT is implied.

But a lot of stuff which does not look for continuation, has no
prefix, hasn't it? I rather make the "I want to be appended" explicit,
instead giving the "I don't care about the log level" any meaning.

I think continuation is special, and ideally should not be much used.
We should not "optimize" for it, and not accept breakage introduced to
ordinary users that way.

> Quite frankly, those three rules (a) make sense and (b) make things easy.

It's true, it's much easier, but it's also much less reliable.

> Breaking them now is a bug. Please don't go adding ugly KERN_CONT when
> there really isn't any reason for it. Just fix the printk code you
> broke.

I can do this, I just don't think it's the right thing to do.

I surely would prefer reliability over rather weird heuristics for
special cases. Today, we should be able to trust at least
non-continuation printk users, which we can't, if we do expose them to
the very real problems of continuation.

Still not convinced? :)

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  7:07             ` Ingo Molnar
@ 2012-05-09 13:21               ` Kay Sievers
  2012-05-09 13:29               ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-09 13:21 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Linus Torvalds, Jonathan Corbet, Sasha Levin,
	Greg Kroah-Hartmann, linux-kernel

On Wed, May 9, 2012 at 9:07 AM, Ingo Molnar <mingo@kernel.org> wrote:
> * Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
>> [...]
>>
>> So it's like a defibrillator: it is good to *have* one, but
>> it's really bad to have to *use* one.

I rather teach the people with known heart problems to only slap their
shocks at people who wear a sign that they are prepared to get
treated, instead of just letting them "help" the healthy random next
guy. :)

> /me nominates this for LWN quote of the week!
>
> Thanks for bringing sanity into printk,

Sounds like the view of sanity of the guys with heart problems, not so
much of the healthy guys. :)

In other words:
Isolation of risk-takers from non-risk-takers is usually a good thing.

Explicit annotation of exceptions almost every time beats expressions
which need heuristics to construct the context.

We use typed pointer instead of void too, even when we don't need it
most of the time. :)

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  7:07             ` Ingo Molnar
  2012-05-09 13:21               ` Kay Sievers
@ 2012-05-09 13:29               ` Kay Sievers
  2012-05-10  0:54                 ` Kay Sievers
  1 sibling, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-09 13:29 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Linus Torvalds, Jonathan Corbet, Sasha Levin,
	Greg Kroah-Hartmann, linux-kernel

On Wed, May 9, 2012 at 9:07 AM, Ingo Molnar <mingo@kernel.org> wrote:

> Thanks for bringing sanity into printk,

Just to check all the options we have, and I have no good idea how
they would work out. It's just an idea, without giving much thought
about possible side effects:

Can we somehow store the PID of the printk() thread that has left the
un-terminated line behind in the buffer, and flush it out when the
next printk() is from a differnt PID? That could prevent the mangling
of "atomic" printk()s by continuation users, and merging unrelated
continuation users together.

Would it make sense to make the printk line buffer per CPU, so they
are not shared between threads, and continuation could work more
reliable?

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09  9:38       ` Kay Sievers
@ 2012-05-09 13:50         ` Joe Perches
  2012-05-09 14:37           ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Joe Perches @ 2012-05-09 13:50 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Linus Torvalds, Sasha Levin, Greg Kroah-Hartmann, Ingo Molnar,
	linux-kernel

On Wed, 2012-05-09 at 11:38 +0200, Kay Sievers wrote:
> On Wed, May 9, 2012 at 5:52 AM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> > On Tue, May 8, 2012 at 4:14 AM, Kay Sievers <kay@vrfy.org> wrote:
> >>
> >> Yeah, we need to make sure, we never merge the (always racy)
> >> continuation printk() users with (non-racy) non-continuation users.
> >> Therefore KERN_CONT is required to suppress the newline and to merge the
> >> content with the earlier non-newline-terminated printk() line.
> >
> > Why?
> 
> The idea was: Prefixes are not used that often, but not using a prefix
> should not expose the user to wrongly get appended to an earlier
> non-terminated line of another thread.
> 
> The point was to limit the "risk" of wrong merges to users of
> continuation, and not to users which send ordinary "atomic" lines.

I think your premise is wrong for a couple of reasons.

1: printk content is not guaranteed to be stable.

   printk content should not be guaranteed to be stable.
   It'd make it difficult to simply add a new message
   or extend or correct an existing one.

2: There are _thousands_ of printks without prefix levels.

   KERN_CONT was always kind of a half-stupid idea.
   It's only real purpose is to designate message
   continuations but it never gave enough information to
   correctly coalesce the messages.

I think you need to give up on the idea that printk
output can be made to be machine readable.

If you really want to have users get complete and
not-interleaved messages you need to buffer partial
messages,  Whether or not printk message coalescing
needs to have a cookie or can be done well enough by
using call tree information as suggested by Andrew
Morton is tbd.

Changing printk semantics and trying to stabilize
printk message content are bad ideas though.

I think printk_emit is an OK idea.  Having a
per-subsystem notification mechanism, something
like an expanded ethtool is certainly useful.

Making the new additional content of printk_emit
discoverable would be useful.

Converting log_buf from circular to record oriented
and adding another binary header/descriptor to it
is a good idea too.

cheers, Joe


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09 13:50         ` Joe Perches
@ 2012-05-09 14:37           ` Kay Sievers
  2012-05-09 23:02             ` Yinghai Lu
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-09 14:37 UTC (permalink / raw)
  To: Joe Perches
  Cc: Linus Torvalds, Sasha Levin, Greg Kroah-Hartmann, Ingo Molnar,
	linux-kernel

On Wed, May 9, 2012 at 3:50 PM, Joe Perches <joe@perches.com> wrote:
> On Wed, 2012-05-09 at 11:38 +0200, Kay Sievers wrote:

> I think your premise is wrong for a couple of reasons.
>
> 1: printk content is not guaranteed to be stable.

Nobody talks about the content of the strings.

>   printk content should not be guaranteed to be stable.
>   It'd make it difficult to simply add a new message
>   or extend or correct an existing one.

Again, that's only what you make out of it.

My point is reliable log _storage_ and with that properly working, the
output _format_ gets as _reliable_ as possible. Continuation printk()
today is entirely unreliable, not only for the continuation users,
also for everybody else, because we merge randomly with atomic
printk() users.

We have (stupid ) scripts that diff dmesg after
supposed-to-be-harmless kernel changes to automatically spot problems.
You can see all the broken merges of continuation lines, and they also
affect lines which do simple and proper atomic printk()s. This is not
useful, and again it's the broken _logic_ of storage not the _content_
of the message.

> 2: There are _thousands_ of printks without prefix levels.

Right, and nobody is crazy enough to think we want to touch them all.

>   KERN_CONT was always kind of a half-stupid idea.
>   It's only real purpose is to designate message
>   continuations but it never gave enough information to
>   correctly coalesce the messages.

Right, it's the annotation of an exception; not nice, but pretty
well-defined, and can be isolated from the non-exception by software
instead of a human.

> I think you need to give up on the idea that printk
> output can be made to be machine readable.

Nobody talks about that in this very context. It is all about better
_reliability_ of the facility not about _content_.

The structured data, possibly attached to the log message, which
uniquely identifies the kernel device, is surely meant to be machine
readable, and no, I'm absolutely not giving up on that approach.

> If you really want to have users get complete and
> not-interleaved messages you need to buffer partial
> messages,  Whether or not printk message coalescing
> needs to have a cookie or can be done well enough by
> using call tree information as suggested by Andrew
> Morton is tbd.

I'm convinced, that we need something simpler than a new cookie logic.
It can work sure, but I doubt we really wants to change the code flow
of all the stuff.

> Changing printk semantics and trying to stabilize
> printk message content are bad ideas though.

Again, nobody talks about content of here.

But reliable context-aware facilities are almost never a bad idea. We
can certainly make printk() better without changing the whole source
tree.

You might not oppose to the heuristics and the "throw it all in a bag
an let's find out later" strategy, I certainly don't like it and think
it's very broken.

> I think printk_emit is an OK idea.  Having a
> per-subsystem notification mechanism, something
> like an expanded ethtool is certainly useful.
>
> Making the new additional content of printk_emit
> discoverable would be useful.

It is all available through /dev/kmsg,

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09 14:37           ` Kay Sievers
@ 2012-05-09 23:02             ` Yinghai Lu
  2012-05-09 23:06               ` Greg Kroah-Hartmann
  0 siblings, 1 reply; 100+ messages in thread
From: Yinghai Lu @ 2012-05-09 23:02 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Joe Perches, Linus Torvalds, Sasha Levin, Greg Kroah-Hartmann,
	Ingo Molnar, linux-kernel

On Wed, May 9, 2012 at 7:37 AM, Kay Sievers <kay@vrfy.org> wrote:
>
>> Changing printk semantics and trying to stabilize
>> printk message content are bad ideas though.
>
> Again, nobody talks about content of here.

printk_time=1 does not work anymore with this patch on serial console.

but dmesg still have that time printout.

Yinghai

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09 23:02             ` Yinghai Lu
@ 2012-05-09 23:06               ` Greg Kroah-Hartmann
  2012-05-10  2:30                 ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Greg Kroah-Hartmann @ 2012-05-09 23:06 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: Kay Sievers, Joe Perches, Linus Torvalds, Sasha Levin,
	Ingo Molnar, linux-kernel

On Wed, May 09, 2012 at 04:02:40PM -0700, Yinghai Lu wrote:
> On Wed, May 9, 2012 at 7:37 AM, Kay Sievers <kay@vrfy.org> wrote:
> >
> >> Changing printk semantics and trying to stabilize
> >> printk message content are bad ideas though.
> >
> > Again, nobody talks about content of here.
> 
> printk_time=1 does not work anymore with this patch on serial console.

Known issue, I think Kay is working on the solution for this right
now...

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09 13:29               ` Kay Sievers
@ 2012-05-10  0:54                 ` Kay Sievers
  2012-05-10  1:18                   ` Linus Torvalds
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-10  0:54 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Linus Torvalds, Jonathan Corbet, Sasha Levin,
	Greg Kroah-Hartmann, linux-kernel

On Wed, 2012-05-09 at 15:29 +0200, Kay Sievers wrote:

> Can we somehow store the PID of the printk() thread that has left the
> un-terminated line behind in the buffer, and flush it out when the
> next printk() is from a differnt PID? That could prevent the mangling
> of "atomic" printk()s by continuation users, and merging unrelated
> continuation users together.

How about this? It relaxes the need for KERN_CONT, but it limits
continuation lines to repeated calls of the same thread.

If things race against each other, the lines are separated and not
wrongly mixed with the data from other users.

I would be happy with that, as it protects the "atomic" users of
printk() from getting mixed up with continuation users.

Thanks,
Kay


From: Kay Sievers <kay@vrfy.org>
Subject: printk() - do not merge continuation lines of different threads

Signed-off-by: Kay Sievers <kay@vrfy.org>---
---

 kernel/printk.c |   18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility
 	static size_t buflen;
 	static int buflevel;
 	static char textbuf[LOG_LINE_MAX];
+	static struct task_struct *cont;
 	char *text = textbuf;
 	size_t textlen;
 	unsigned long flags;
 	int this_cpu;
 	bool newline = false;
-	bool cont = false;
+	bool prefix = false;
 	int printed_len = 0;
 
 	boot_delay_msec();
@@ -1295,20 +1296,17 @@ asmlinkage int vprintk_emit(int facility
 		case '0' ... '7':
 			if (level == -1)
 				level = text[1] - '0';
-			text += 3;
-			textlen -= 3;
-			break;
 		case 'c':	/* KERN_CONT */
-			cont = true;
 		case 'd':	/* KERN_DEFAULT */
+			if (text[1] != 'c')
+				prefix = true;
 			text += 3;
 			textlen -= 3;
-			break;
 		}
 	}
 
-	if (buflen && (!cont || dict)) {
-		/* no continuation; flush existing buffer */
+	if (buflen && (prefix || dict || cont != current)) {
+		/* flush existing buffer */
 		log_store(facility, buflevel, NULL, 0, buf, buflen);
 		printed_len += buflen;
 		buflen = 0;
@@ -1342,6 +1340,10 @@ asmlinkage int vprintk_emit(int facility
 				  dict, dictlen, text, textlen);
 			printed_len += textlen;
 		}
+		cont = NULL;
+	} else {
+		/* remember thread which filled the buffer */
+		cont = current;
 	}
 
 	/*



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10  0:54                 ` Kay Sievers
@ 2012-05-10  1:18                   ` Linus Torvalds
  2012-05-10  2:32                     ` Kay Sievers
  2012-05-10 16:39                     ` Kay Sievers
  0 siblings, 2 replies; 100+ messages in thread
From: Linus Torvalds @ 2012-05-10  1:18 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Ingo Molnar, Jonathan Corbet, Sasha Levin, Greg Kroah-Hartmann,
	linux-kernel

On Wed, May 9, 2012 at 5:54 PM, Kay Sievers <kay@vrfy.org> wrote:
>
> How about this? It relaxes the need for KERN_CONT, but it limits
> continuation lines to repeated calls of the same thread.

Fair enough, looks reasonable.

Except your case-statement sucks. Having a "case 'c':" that basically
then immediately has an "if (it was not 'c')" is just disturbing. Just
move the code that is common to all the cases outside the case
statement entirely, and make the 'c' case not do anything at all, and
remove that crazy extraneous if-statement.

                  Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-09 23:06               ` Greg Kroah-Hartmann
@ 2012-05-10  2:30                 ` Kay Sievers
  2012-05-11 10:35                   ` Sasha Levin
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-10  2:30 UTC (permalink / raw)
  To: Greg Kroah-Hartmann
  Cc: Yinghai Lu, Joe Perches, Linus Torvalds, Sasha Levin,
	Ingo Molnar, linux-kernel

On Wed, 2012-05-09 at 16:06 -0700, Greg Kroah-Hartmann wrote:
> On Wed, May 09, 2012 at 04:02:40PM -0700, Yinghai Lu wrote:
> > On Wed, May 9, 2012 at 7:37 AM, Kay Sievers <kay@vrfy.org> wrote:
> > >
> > >> Changing printk semantics and trying to stabilize
> > >> printk message content are bad ideas though.
> > >
> > > Again, nobody talks about content of here.
> > 
> > printk_time=1 does not work anymore with this patch on serial console.
> 
> Known issue, I think Kay is working on the solution for this right
> now...

Sure, and this seems to work for me.

Thanks,
Kay


From: Kay Sievers <kay@vrfy.org>
Subject: printk() - restore timestamp printing at console output

The output of the timestamps got lost with the conversion of the
kmsg buffer to records; restore the old behavior.

Document, that CONFIG_PRINTK_TIME now only controls the output of
the timestamps in the syslog() system call and on the console, and
not the recording of the timestamps.

Signed-off-by: Kay Sievers <kay@vrfy.org>
---

 kernel/printk.c   |   43 ++++++++++++++++++++++++++-----------------
 lib/Kconfig.debug |   16 ++++++++++------
 2 files changed, 36 insertions(+), 23 deletions(-)

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -786,6 +786,22 @@ static bool printk_time;
 #endif
 module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
 
+static size_t prepend_timestamp(unsigned long long t, char *buf)
+{
+	unsigned long rem_ns;
+
+	if (!printk_time)
+		return 0;
+
+	if (!buf)
+		return 15;
+
+	rem_ns = do_div(t, 1000000000);
+
+	return sprintf(buf, "[%5lu.%06lu] ",
+		       (unsigned long) t, rem_ns / 1000);
+}
+
 static int syslog_print_line(u32 idx, char *text, size_t size)
 {
 	struct log *msg;
@@ -800,9 +816,7 @@ static int syslog_print_line(u32 idx, ch
 			len++;
 		if (msg->level > 99)
 			len++;
-
-		if (printk_time)
-			len += 15;
+		len += prepend_timestamp(0, NULL);
 
 		len += msg->text_len;
 		len++;
@@ -810,15 +824,7 @@ static int syslog_print_line(u32 idx, ch
 	}
 
 	len = sprintf(text, "<%u>", msg->level);
-
-	if (printk_time) {
-		unsigned long long t = msg->ts_nsec;
-		unsigned long rem_ns = do_div(t, 1000000000);
-
-		len += sprintf(text + len, "[%5lu.%06lu] ",
-				   (unsigned long) t, rem_ns / 1000);
-	}
-
+	len += prepend_timestamp(msg->ts_nsec, text + len);
 	if (len + msg->text_len > size)
 		return -EINVAL;
 	memcpy(text + len, log_text(msg), msg->text_len);
@@ -1741,7 +1747,7 @@ again:
 	for (;;) {
 		struct log *msg;
 		static char text[LOG_LINE_MAX];
-		size_t len;
+		size_t len, l;
 		int level;
 
 		raw_spin_lock_irqsave(&logbuf_lock, flags);
@@ -1761,10 +1767,13 @@ again:
 
 		msg = log_from_idx(console_idx);
 		level = msg->level & 7;
-		len = msg->text_len;
-		if (len+1 >= sizeof(text))
-			len = sizeof(text)-1;
-		memcpy(text, log_text(msg), len);
+
+		len = prepend_timestamp(msg->ts_nsec, text);
+		l = msg->text_len;
+		if (len + l + 1 >= sizeof(text))
+			l = sizeof(text) - len - 1;
+		memcpy(text + len, log_text(msg), l);
+		len += l;
 		text[len++] = '\n';
 
 		console_idx = log_next(console_idx);
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3,12 +3,16 @@ config PRINTK_TIME
 	bool "Show timing information on printks"
 	depends on PRINTK
 	help
-	  Selecting this option causes timing information to be
-	  included in printk output.  This allows you to measure
-	  the interval between kernel operations, including bootup
-	  operations.  This is useful for identifying long delays
-	  in kernel startup.  Or add printk.time=1 at boot-time.
-	  See Documentation/kernel-parameters.txt
+	  Selecting this option causes time stamps of the printk()
+	  messages to be added to the output of the syslog() system
+	  call and at the console.
+
+	  The timestamp is always recorded internally, and exported
+	  to /dev/kmsg. This flag just specifies if the timestamp should
+	  be included, not that the timestamp is recorded.
+
+	  The behavior is also controlled by the kernel command line
+	  parameter printk.time=1. See Documentation/kernel-parameters.txt
 
 config DEFAULT_MESSAGE_LOGLEVEL
 	int "Default message log level (1-7)"



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10  1:18                   ` Linus Torvalds
@ 2012-05-10  2:32                     ` Kay Sievers
  2012-05-10  2:46                       ` Joe Perches
  2012-05-10 16:39                     ` Kay Sievers
  1 sibling, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-10  2:32 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Ingo Molnar, Jonathan Corbet, Sasha Levin, Greg Kroah-Hartmann,
	linux-kernel

On Wed, 2012-05-09 at 18:18 -0700, Linus Torvalds wrote:
> On Wed, May 9, 2012 at 5:54 PM, Kay Sievers <kay@vrfy.org> wrote:
> >
> > How about this? It relaxes the need for KERN_CONT, but it limits
> > continuation lines to repeated calls of the same thread.
> 
> Fair enough, looks reasonable.
> 
> Except your case-statement sucks. Having a "case 'c':" that basically
> then immediately has an "if (it was not 'c')" is just disturbing. Just
> move the code that is common to all the cases outside the case
> statement entirely, and make the 'c' case not do anything at all, and
> remove that crazy extraneous if-statement.


From: Kay Sievers <kay@vrfy.org>
Subject: printk() - do not merge continuation lines of different threads

This prevents the merging of printk() continuation lines of different
threads, in the case they race against each other.

It should properly isolate "atomic" single-line printk() users from
continuation users, to make sure the single-line users will never be
merged with the racy continuation ones.

Signed-off-by: Kay Sievers <kay@vrfy.org>
---

 kernel/printk.c |   19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1230,12 +1230,13 @@ asmlinkage int vprintk_emit(int facility
 	static size_t buflen;
 	static int buflevel;
 	static char textbuf[LOG_LINE_MAX];
+	static struct task_struct *cont;
 	char *text = textbuf;
 	size_t textlen;
 	unsigned long flags;
 	int this_cpu;
 	bool newline = false;
-	bool cont = false;
+	bool prefix = false;
 	int printed_len = 0;
 
 	boot_delay_msec();
@@ -1295,20 +1296,16 @@ asmlinkage int vprintk_emit(int facility
 		case '0' ... '7':
 			if (level == -1)
 				level = text[1] - '0';
-			text += 3;
-			textlen -= 3;
-			break;
-		case 'c':	/* KERN_CONT */
-			cont = true;
 		case 'd':	/* KERN_DEFAULT */
+			prefix = true;
+		case 'c':	/* KERN_CONT */
 			text += 3;
 			textlen -= 3;
-			break;
 		}
 	}
 
-	if (buflen && (!cont || dict)) {
-		/* no continuation; flush existing buffer */
+	if (buflen && (prefix || dict || cont != current)) {
+		/* flush existing buffer */
 		log_store(facility, buflevel, NULL, 0, buf, buflen);
 		printed_len += buflen;
 		buflen = 0;
@@ -1342,6 +1339,10 @@ asmlinkage int vprintk_emit(int facility
 				  dict, dictlen, text, textlen);
 			printed_len += textlen;
 		}
+		cont = NULL;
+	} else {
+		/* remember thread which filled the buffer */
+		cont = current;
 	}
 
 	/*



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10  2:32                     ` Kay Sievers
@ 2012-05-10  2:46                       ` Joe Perches
  0 siblings, 0 replies; 100+ messages in thread
From: Joe Perches @ 2012-05-10  2:46 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Linus Torvalds, Ingo Molnar, Jonathan Corbet, Sasha Levin,
	Greg Kroah-Hartmann, linux-kernel

On Thu, 2012-05-10 at 04:32 +0200, Kay Sievers wrote:
> --- a/kernel/printk.c
[]
> @@ -1295,20 +1296,16 @@ asmlinkage int vprintk_emit(int facility
>  		case '0' ... '7':
>  			if (level == -1)
>  				level = text[1] - '0';
> -			text += 3;
> -			textlen -= 3;
> -			break;
> -		case 'c':	/* KERN_CONT */
> -			cont = true;
>  		case 'd':	/* KERN_DEFAULT */
> +			prefix = true;
> +		case 'c':	/* KERN_CONT */

trivia:

Please add /* fallthrough */ comment lines
so it shows the "missing" breaks are intentional.



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10  1:18                   ` Linus Torvalds
  2012-05-10  2:32                     ` Kay Sievers
@ 2012-05-10 16:39                     ` Kay Sievers
  2012-05-10 16:47                       ` Linus Torvalds
  1 sibling, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-10 16:39 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Ingo Molnar, Jonathan Corbet, Sasha Levin, Greg Kroah-Hartmann,
	linux-kernel

On Wed, 2012-05-09 at 18:18 -0700, Linus Torvalds wrote:
> On Wed, May 9, 2012 at 5:54 PM, Kay Sievers <kay@vrfy.org> wrote:
> >
> > How about this? It relaxes the need for KERN_CONT, but it limits
> > continuation lines to repeated calls of the same thread.
> 
> Fair enough, looks reasonable.

Here is something which might make sense, and could become be the most
reliable and fail-tolerant version so far. It is also the least
restrictive one regarding the input format, and takes the same amount of
resources as the current implementation.

We fully isolate continuation users from non-continuation users. If a
continuation user gets interrupted by a an ordinary non-continuation
user, we will no longer touch the buffer of the continuation user, we
just emit the ordinary message.

When the same thread comes back and continues printing, we still append
to the earlier buffer we stored.

The only case where printk() still gets messed up now, is when multiple
threads use continuation at the same time, which is way less likely than
mixing with ordinary users.

We will also never merge two racing continuation users into one line;
the worst thing that can happen now, is that they end split up into more
than the intended single line.

Note: In this version, the KERN_* prefixes have all no further meaning
anymore, besides that they carry the priority, or prevent they the
content of the line to be parsed for a priority.

All the special rules are gone. KERN_CONT is the same as KERN_DEFAULT
now.

Even continuation users could use prefixes now, if they wanted to. We
should be context-aware enough now, with remembering the owner (task) of
the buffered data, that we might be able to relax all the special rules
regarding the prefixes.

Any ideas about that?

Thanks,
Kay



From: Kay Sievers <kay@vrfy.org>
Subject: printk() - fully separate continuation line users from ordinary ones
---

 printk.c |   86 ++++++++++++++++++++++++++++++---------------------------------
 1 file changed, 41 insertions(+), 45 deletions(-)

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1232,17 +1232,16 @@ asmlinkage int vprintk_emit(int facility, int level,
 			    const char *fmt, va_list args)
 {
 	static int recursion_bug;
-	static char buf[LOG_LINE_MAX];
-	static size_t buflen;
-	static int buflevel;
+	static char cont_buf[LOG_LINE_MAX];
+	static size_t cont_len;
+	static int cont_level;
+	static struct task_struct *cont_task;
 	static char textbuf[LOG_LINE_MAX];
-	static struct task_struct *cont;
 	char *text = textbuf;
-	size_t textlen;
+	size_t text_len;
 	unsigned long flags;
 	int this_cpu;
 	bool newline = false;
-	bool prefix = false;
 	int printed_len = 0;
 
 	boot_delay_msec();
@@ -1288,11 +1287,11 @@ asmlinkage int vprintk_emit(int facility, int level,
 	 * The printf needs to come first; we need the syslog
 	 * prefix which might be passed-in as a parameter.
 	 */
-	textlen = vscnprintf(text, sizeof(textbuf), fmt, args);
+	text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
 
 	/* mark and strip a trailing newline */
-	if (textlen && text[textlen-1] == '\n') {
-		textlen--;
+	if (text_len && text[text_len-1] == '\n') {
+		text_len--;
 		newline = true;
 	}
 
@@ -1303,52 +1302,49 @@ asmlinkage int vprintk_emit(int facility, int level,
 			if (level == -1)
 				level = text[1] - '0';
 		case 'd':	/* KERN_DEFAULT */
-			prefix = true;
 		case 'c':	/* KERN_CONT */
 			text += 3;
-			textlen -= 3;
+			text_len -= 3;
 		}
 	}
 
-	if (buflen && (prefix || dict || cont != current)) {
-		/* flush existing buffer */
-		log_store(facility, buflevel, NULL, 0, buf, buflen);
-		printed_len += buflen;
-		buflen = 0;
-	}
+	if (level == -1)
+		level = default_message_loglevel;
 
-	if (buflen == 0) {
-		/* remember level for first message in the buffer */
-		if (level == -1)
-			buflevel = default_message_loglevel;
-		else
-			buflevel = level;
-	}
+	if (!newline) {
+		if (cont_len && cont_task != current) {
+			/* flush earlier buffer from different thread */
+			log_store(facility, cont_level, NULL, 0, cont_buf, cont_len);
+			cont_len = 0;
+		}
 
-	if (buflen || !newline) {
-		/* append to existing buffer, or buffer until next message */
-		if (buflen + textlen > sizeof(buf))
-			textlen = sizeof(buf) - buflen;
-		memcpy(buf + buflen, text, textlen);
-		buflen += textlen;
-	}
+		if (!cont_len) {
+			cont_level = level;
+			cont_task = current;
+		}
 
-	if (newline) {
-		/* end of line; flush buffer */
-		if (buflen) {
-			log_store(facility, buflevel,
-				  dict, dictlen, buf, buflen);
-			printed_len += buflen;
-			buflen = 0;
+		/* buffer, or append to earlier buffer from same thread */
+		if (cont_len + text_len > sizeof(cont_buf))
+			text_len = sizeof(cont_buf) - cont_len;
+		memcpy(cont_buf + cont_len, text, text_len);
+		cont_len += text_len;
+	} else {
+		if (cont_len && cont_task == current) {
+			/* append to earlier buffer and flush */
+			if (cont_len + text_len > sizeof(cont_buf))
+				text_len = sizeof(cont_buf) - cont_len;
+			memcpy(cont_buf + cont_len, text, text_len);
+			cont_len += text_len;
+			log_store(facility, cont_level,
+				  NULL, 0, cont_buf, cont_len);
+			cont_len = 0;
+			cont_task = NULL;
+			printed_len = cont_len;
 		} else {
-			log_store(facility, buflevel,
-				  dict, dictlen, text, textlen);
-			printed_len += textlen;
+			log_store(facility, level,
+				  dict, dictlen, text, text_len);
+			printed_len = text_len;
 		}
-		cont = NULL;
-	} else {
-		/* remember thread which filled the buffer */
-		cont = current;
 	}
 
 	/*



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 16:39                     ` Kay Sievers
@ 2012-05-10 16:47                       ` Linus Torvalds
  2012-05-10 18:49                         ` Tony Luck
  2012-05-10 19:09                         ` Kay Sievers
  0 siblings, 2 replies; 100+ messages in thread
From: Linus Torvalds @ 2012-05-10 16:47 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Ingo Molnar, Jonathan Corbet, Sasha Levin, Greg Kroah-Hartmann,
	linux-kernel

On Thu, May 10, 2012 at 9:39 AM, Kay Sievers <kay@vrfy.org> wrote:
>
> All the special rules are gone. KERN_CONT is the same as KERN_DEFAULT
> now.

That's wrong.

Key, KERN_CONT and KERN_DEFAULT really are different and have
fundamentally different semantics. The fact that you think they aren't
shows that you don't understand it.

Your "current" check doesn't change anything.

There are two main and important differences:

 - people can avoid using '\n' if they know the next printk will have
a KERN_xxx marker (xxx != CONT).

   This is often useful for having loops that print out individual
entries all on the same line - print all of them without the '\n'.

   The printk afterwards will automatically start a new line if it has
KERN_DEFAULT.

   If you make KERN_CONT and KERN_DEFAULT the same, it is a BUG. Don't do it.

 - You don't seem to realize that interrupts are threaded events too,
but they will happen with the same task-struct.

   An interrupt that prints out with KERN_DEFAULT had better not act
the same way as KERN_CONT.

So dammit, just stop trying to get rid of KERN_CONT or KERN_DEFAULT.
They are both real, and they are both *different*. If you think they
are the same, you are WRONG.

Don't try to change the rules because you think you are "clever".
You're only making things worse.

                       Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 16:47                       ` Linus Torvalds
@ 2012-05-10 18:49                         ` Tony Luck
  2012-05-10 19:09                         ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Tony Luck @ 2012-05-10 18:49 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Ingo Molnar, Jonathan Corbet, Sasha Levin,
	Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 9:47 AM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>   This is often useful for having loops that print out individual
> entries all on the same line - print all of them without the '\n'.

Though it is a pain when people do this and the output from each iteration
of the loop gets interleaved with other printk() output.  Perhaps it is OK to
do multiple printk() calls in initialization code where it kernel is
mostly single
threaded. But it should be avoided in "oh dear, something bad happened" bits
of code (in case the badness isn't localized and all the other cpus are spitting
out partial messages too).

-Tony

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 16:47                       ` Linus Torvalds
  2012-05-10 18:49                         ` Tony Luck
@ 2012-05-10 19:09                         ` Kay Sievers
  2012-05-10 20:14                           ` Ted Ts'o
  1 sibling, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-10 19:09 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Ingo Molnar, Jonathan Corbet, Sasha Levin, Greg Kroah-Hartmann,
	linux-kernel

On Thu, 2012-05-10 at 09:47 -0700, Linus Torvalds wrote:
> On Thu, May 10, 2012 at 9:39 AM, Kay Sievers <kay@vrfy.org> wrote:

>  An interrupt that prints out with KERN_DEFAULT had better not act
>  the same way as KERN_CONT.

Good point, understood, and adapted to the new logic.


Here is a new RFC version. I think it's slightly better than the
currently implemented logic in Greg's tree:

We fully isolate continuation users from non-continuation users. If a
continuation user gets interrupted by an ordinary non-continuation
user, we will not touch the continuation buffer, we just emit the
ordinary message. When the same thread comes back and continues its
printing, we still append to the earlier buffer we stored.

The only case where printk() still gets messed up now, is when multiple
threads (or interrupts) race against each other.

We will also never wrongly merge two racing continuation users into one
line.


Current intended behavior, and general rules:
printk() starting with KERN_* (not KERN_CONT) and ending with '\n' will
*always* logged as single line, *never* be merged with anything else. 

printk() not starting with any KERN_* might get merged with an earlier
line buffered by the *same* thread.

printk() not ending with '\n' will be buffered.

Buffered lines will be flushed when a different thread emits a printk()
that needs to be buffered --> race.

Buffered line will be flushed, when the same thread emits a printk()
with a KERN_* (not KERN_CONT) --> newline missing.

Buffered line will be joined, when the same thread emits a printk()
without any KERN_* or with KERN_CONT.

Does that sounds correct? Anything to add or adjust?

Thanks,
Kay

---

  printk.c |   97 +++++++++++++++++++++++++++++++++++----------------------------
  1 file changed, 54 insertions(+), 43 deletions(-)

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1232,13 +1232,13 @@ asmlinkage int vprintk_emit(int facility, int level,
 			    const char *fmt, va_list args)
 {
 	static int recursion_bug;
-	static char buf[LOG_LINE_MAX];
-	static size_t buflen;
-	static int buflevel;
+	static char cont_buf[LOG_LINE_MAX];
+	static size_t cont_len;
+	static int cont_level;
+	static struct task_struct *cont_task;
 	static char textbuf[LOG_LINE_MAX];
-	static struct task_struct *cont;
 	char *text = textbuf;
-	size_t textlen;
+	size_t text_len;
 	unsigned long flags;
 	int this_cpu;
 	bool newline = false;
@@ -1288,11 +1288,11 @@ asmlinkage int vprintk_emit(int facility, int level,
 	 * The printf needs to come first; we need the syslog
 	 * prefix which might be passed-in as a parameter.
 	 */
-	textlen = vscnprintf(text, sizeof(textbuf), fmt, args);
+	text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
 
 	/* mark and strip a trailing newline */
-	if (textlen && text[textlen-1] == '\n') {
-		textlen--;
+	if (text_len && text[text_len-1] == '\n') {
+		text_len--;
 		newline = true;
 	}
 
@@ -1306,49 +1306,60 @@ asmlinkage int vprintk_emit(int facility, int level,
 			prefix = true;
 		case 'c':	/* KERN_CONT */
 			text += 3;
-			textlen -= 3;
+			text_len -= 3;
 		}
 	}
 
-	if (buflen && (prefix || dict || cont != current)) {
-		/* flush existing buffer */
-		log_store(facility, buflevel, NULL, 0, buf, buflen);
-		printed_len += buflen;
-		buflen = 0;
-	}
+	if (level == -1)
+		level = default_message_loglevel;
 
-	if (buflen == 0) {
-		/* remember level for first message in the buffer */
-		if (level == -1)
-			buflevel = default_message_loglevel;
-		else
-			buflevel = level;
-	}
+	if (!newline) {
+		if (cont_len && (prefix || cont_task != current)) {
+			/*
+			 * Flush earlier buffer, either from a different
+			 * thread, or when we've seen a new prefix.
+			 */
+			log_store(facility, cont_level, NULL, 0, cont_buf, cont_len);
+			cont_len = 0;
+		}
 
-	if (buflen || !newline) {
-		/* append to existing buffer, or buffer until next message */
-		if (buflen + textlen > sizeof(buf))
-			textlen = sizeof(buf) - buflen;
-		memcpy(buf + buflen, text, textlen);
-		buflen += textlen;
-	}
+		if (!cont_len) {
+			cont_level = level;
+			cont_task = current;
+		}
+
+		/* buffer/append to earlier buffer from same thread */
+		if (cont_len + text_len > sizeof(cont_buf))
+			text_len = sizeof(cont_buf) - cont_len;
+		memcpy(cont_buf + cont_len, text, text_len);
+		cont_len += text_len;
+	} else {
+		if (cont_len && cont_task == current) {
+			if (prefix) {
+				/*
+				 * New prefix in same thread; flush. Either
+				 * no earlier newline, or in an interrupt.
+				 */
+				log_store(facility, cont_level,
+					  NULL, 0, cont_buf, cont_len);
+				cont_len = 0;
+			}
 
-	if (newline) {
-		/* end of line; flush buffer */
-		if (buflen) {
-			log_store(facility, buflevel,
-				  dict, dictlen, buf, buflen);
-			printed_len += buflen;
-			buflen = 0;
+			/* append to earlier buffer and flush */
+			if (cont_len + text_len > sizeof(cont_buf))
+				text_len = sizeof(cont_buf) - cont_len;
+			memcpy(cont_buf + cont_len, text, text_len);
+			cont_len += text_len;
+			log_store(facility, cont_level,
+				  NULL, 0, cont_buf, cont_len);
+			cont_len = 0;
+			cont_task = NULL;
+			printed_len = cont_len;
 		} else {
-			log_store(facility, buflevel,
-				  dict, dictlen, text, textlen);
-			printed_len += textlen;
+			log_store(facility, level,
+				  dict, dictlen, text, text_len);
+			printed_len = text_len;
 		}
-		cont = NULL;
-	} else {
-		/* remember thread which filled the buffer */
-		cont = current;
 	}
 
 	/*



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 19:09                         ` Kay Sievers
@ 2012-05-10 20:14                           ` Ted Ts'o
  2012-05-10 20:37                             ` Joe Perches
  2012-05-10 20:38                             ` Kay Sievers
  0 siblings, 2 replies; 100+ messages in thread
From: Ted Ts'o @ 2012-05-10 20:14 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Linus Torvalds, Ingo Molnar, Jonathan Corbet, Sasha Levin,
	Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 09:09:46PM +0200, Kay Sievers wrote:
> We fully isolate continuation users from non-continuation users. If a
> continuation user gets interrupted by an ordinary non-continuation
> user, we will not touch the continuation buffer, we just emit the
> ordinary message. When the same thread comes back and continues its
> printing, we still append to the earlier buffer we stored.

It's not necessarily a matter of "thread comes back", although that
situation can happen too.  You can get this situation quite simply if
you have two processes in foreground kernel mode on two different
CPU's sending continuation printk's at the same time.

> We will also never wrongly merge two racing continuation users into one
> line.

I'm not sure how you guarantee this?  The only way you *could*
guarantee this is if you used a continuation buffer in the task_struct
for foreground kernel code, and a per-CPU continuation buffer for
interrupt code.

> Buffered line will be joined, when the same thread emits a printk()
> without any KERN_* or with KERN_CONT.

Is there any difference in any of the cases in terms of how printk's
that are prefixed with KERN_CONT versus a printk that does not have
any KERN_* prefix?  If so, is there value in keeping KERN_CONT?

    	   	       	      	    	     - Ted

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:14                           ` Ted Ts'o
@ 2012-05-10 20:37                             ` Joe Perches
  2012-05-10 20:39                               ` Kay Sievers
  2012-05-10 20:38                             ` Kay Sievers
  1 sibling, 1 reply; 100+ messages in thread
From: Joe Perches @ 2012-05-10 20:37 UTC (permalink / raw)
  To: Ted Ts'o
  Cc: Kay Sievers, Linus Torvalds, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, 2012-05-10 at 16:14 -0400, Ted Ts'o wrote:
> Is there any difference in any of the cases in terms of how printk's
> that are prefixed with KERN_CONT versus a printk that does not have
> any KERN_* prefix?  If so, is there value in keeping KERN_CONT?

As far as I know, no.

It is a useful marker to show where prints
are actually continued.

#define KERN_CONT ""

would save a small amount of text.



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:14                           ` Ted Ts'o
  2012-05-10 20:37                             ` Joe Perches
@ 2012-05-10 20:38                             ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-10 20:38 UTC (permalink / raw)
  To: Ted Ts'o, Kay Sievers, Linus Torvalds, Ingo Molnar,
	Jonathan Corbet, Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 10:14 PM, Ted Ts'o <tytso@mit.edu> wrote:
> On Thu, May 10, 2012 at 09:09:46PM +0200, Kay Sievers wrote:
>> We fully isolate continuation users from non-continuation users. If a
>> continuation user gets interrupted by an ordinary non-continuation
>> user, we will not touch the continuation buffer, we just emit the
>> ordinary message. When the same thread comes back and continues its
>> printing, we still append to the earlier buffer we stored.
>
> It's not necessarily a matter of "thread comes back", although that
> situation can happen too.  You can get this situation quite simply if
> you have two processes in foreground kernel mode on two different
> CPU's sending continuation printk's at the same time.

The access to printk is fully serialized. If only one thread does
continuation (needs buffering), it will still own the continuation
buffer. We record the "owner" (pointer to the task) of the data.

>> We will also never wrongly merge two racing continuation users into one
>> line.
>
> I'm not sure how you guarantee this?  The only way you *could*
> guarantee this is if you used a continuation buffer in the task_struct
> for foreground kernel code, and a per-CPU continuation buffer for
> interrupt code.

Yeah adding it to struct task would reliably work. :) But as we record
the "owner" of the continuation buffer, we should be able to flush the
content of the earlier buffer, instead of wrongly merging it. The same
struct task and interrupts could go wrong, that's true.

>> Buffered line will be joined, when the same thread emits a printk()
>> without any KERN_* or with KERN_CONT.
>
> Is there any difference in any of the cases in terms of how printk's
> that are prefixed with KERN_CONT versus a printk that does not have
> any KERN_* prefix?  If so, is there value in keeping KERN_CONT?

Yeah, it is. It will instruct to merge with the buffer, but also tell
not the parse the prefix, in case you want to log stuff like "<7>" as
real data and not as a prefix.

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:37                             ` Joe Perches
@ 2012-05-10 20:39                               ` Kay Sievers
  2012-05-10 20:46                                 ` Joe Perches
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-10 20:39 UTC (permalink / raw)
  To: Joe Perches
  Cc: Ted Ts'o, Linus Torvalds, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 10:37 PM, Joe Perches <joe@perches.com> wrote:
> On Thu, 2012-05-10 at 16:14 -0400, Ted Ts'o wrote:
>> Is there any difference in any of the cases in terms of how printk's
>> that are prefixed with KERN_CONT versus a printk that does not have
>> any KERN_* prefix?  If so, is there value in keeping KERN_CONT?
>
> As far as I know, no.
>
> It is a useful marker to show where prints
> are actually continued.
>
> #define KERN_CONT ""
>
> would save a small amount of text.

Nah, we can't do that. We need it to tell "here is your non-prefix to
parse, leave the data behind alone".

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:39                               ` Kay Sievers
@ 2012-05-10 20:46                                 ` Joe Perches
  2012-05-10 20:52                                   ` Linus Torvalds
  2012-05-10 21:01                                   ` Kay Sievers
  0 siblings, 2 replies; 100+ messages in thread
From: Joe Perches @ 2012-05-10 20:46 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Ted Ts'o, Linus Torvalds, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, 2012-05-10 at 22:39 +0200, Kay Sievers wrote:
> On Thu, May 10, 2012 at 10:37 PM, Joe Perches <joe@perches.com> wrote:
> > On Thu, 2012-05-10 at 16:14 -0400, Ted Ts'o wrote:
> >> Is there any difference in any of the cases in terms of how printk's
> >> that are prefixed with KERN_CONT versus a printk that does not have
> >> any KERN_* prefix?  If so, is there value in keeping KERN_CONT?
> >
> > As far as I know, no.
> >
> > It is a useful marker to show where prints
> > are actually continued.
> >
> > #define KERN_CONT ""
> >
> > would save a small amount of text.
> 
> Nah, we can't do that. We need it to tell "here is your non-prefix to
> parse, leave the data behind alone".

That's where I think you're still a bit
uncertain how the _current_ printk system
works.  Your _new_ printk system should
have identical behavior.  Though if you
manage to use the call tree and current to
coalesce complete messages more correctly,
that'd be great.



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:46                                 ` Joe Perches
@ 2012-05-10 20:52                                   ` Linus Torvalds
  2012-05-10 21:11                                     ` Joe Perches
  2012-05-11  0:38                                     ` Kay Sievers
  2012-05-10 21:01                                   ` Kay Sievers
  1 sibling, 2 replies; 100+ messages in thread
From: Linus Torvalds @ 2012-05-10 20:52 UTC (permalink / raw)
  To: Joe Perches
  Cc: Kay Sievers, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 1:46 PM, Joe Perches <joe@perches.com> wrote:
>
> That's where I think you're still a bit
> uncertain how the _current_ printk system
> works.

No, you are. Read my answer from two days ago in this thread.

KERN_CONT is *not* the same as "". Not now, not ever. If you make it
the same, you're broken.

The reason is simple: KERN_CONT "<3>" should print out the string
"<3>". If you make KERN_CONT be "", it will do the wrong thing, and
think that the <3> is a priority marker.

Please people, this is subtle, and current code does things RIGHT. Any
code that changes it to do something else is almost certainly buggy.
The new semantics had better be the same as the old one.

The change to verify that 'current' matches the previous printout is
so far the *only* sane semantic change I've seen in this thread.
Everything else has been pure garbage.

                    Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:46                                 ` Joe Perches
  2012-05-10 20:52                                   ` Linus Torvalds
@ 2012-05-10 21:01                                   ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-10 21:01 UTC (permalink / raw)
  To: Joe Perches
  Cc: Ted Ts'o, Linus Torvalds, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 10:46 PM, Joe Perches <joe@perches.com> wrote:
> On Thu, 2012-05-10 at 22:39 +0200, Kay Sievers wrote:

>> Nah, we can't do that. We need it to tell "here is your non-prefix to
>> parse, leave the data behind alone".
>
> That's where I think you're still a bit
> uncertain how the _current_ printk system
> works.
> Your _new_ printk system should
> have identical behavior.

We must be at least as good as we are, sure.

But the aim is to be *better* not to be *identical*, especially when
things go wrong, and they do go wrong far too often in the current
code. What we have today is really not good enough. We have a lot of
context during logging (like the thread), and we should use it to make
the best out of it _before_ we log the stuff away.

>  Though if you
> manage to use the call tree and current to
> coalesce complete messages more correctly,
> that'd be great.

That's what we try. We just need to get all the details out of the
peoples heads, which are nowhere written down, to make it happen. It's
a bit of a painful process sometimes. :)

The conversion from the "put all bytes in a bag and let's find out
later what happened"-buffer to a real separated record buffer imposed
some changes to the logic, and we need to restore/adapt some useful
rules now, which could't be preserved 1:1. But I'm confident that we
manage to get a better overall picture in the end.

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:52                                   ` Linus Torvalds
@ 2012-05-10 21:11                                     ` Joe Perches
  2012-05-10 21:15                                       ` Kay Sievers
  2012-05-10 21:58                                       ` Linus Torvalds
  2012-05-11  0:38                                     ` Kay Sievers
  1 sibling, 2 replies; 100+ messages in thread
From: Joe Perches @ 2012-05-10 21:11 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, 2012-05-10 at 13:52 -0700, Linus Torvalds wrote:
> On Thu, May 10, 2012 at 1:46 PM, Joe Perches <joe@perches.com> wrote:
> >
> > That's where I think you're still a bit
> > uncertain how the _current_ printk system
> > works.
> 
> No, you are. Read my answer from two days ago in this thread.
> 
> KERN_CONT is *not* the same as "". Not now, not ever. If you make it
> the same, you're broken.
> 
> The reason is simple: KERN_CONT "<3>" should print out the string
> "<3>".

I think it's a distinction without a difference for,
as fas as I know, that's a case that doesn't exist
in the current kernel.

$ grep -rP --include=*.[ch] "\bpr_cont\s*\(\s*\"<" *
$ grep -rP --include=*.[ch] "\bprintk\s*\(\s*KERN_CONT\s*\"<" *
arch/x86/kernel/dumpstack_32.c:				printk(KERN_CONT "<%02x> ", c);
arch/x86/kernel/dumpstack_64.c:				printk(KERN_CONT "<%02x> ", c);
arch/powerpc/kernel/process.c:				printk(KERN_CONT "<%08x> ", instr);
drivers/media/video/tm6000/tm6000-core.c:			printk(KERN_CONT "<<< ");
drivers/media/video/cx231xx/cx231xx-core.c:			printk(KERN_CONT "<<<");



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 21:11                                     ` Joe Perches
@ 2012-05-10 21:15                                       ` Kay Sievers
  2012-05-10 21:58                                       ` Linus Torvalds
  1 sibling, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-10 21:15 UTC (permalink / raw)
  To: Joe Perches
  Cc: Linus Torvalds, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 11:11 PM, Joe Perches <joe@perches.com> wrote:
> On Thu, 2012-05-10 at 13:52 -0700, Linus Torvalds wrote:
>> On Thu, May 10, 2012 at 1:46 PM, Joe Perches <joe@perches.com> wrote:
>> >
>> > That's where I think you're still a bit
>> > uncertain how the _current_ printk system
>> > works.
>>
>> No, you are. Read my answer from two days ago in this thread.
>>
>> KERN_CONT is *not* the same as "". Not now, not ever. If you make it
>> the same, you're broken.
>>
>> The reason is simple: KERN_CONT "<3>" should print out the string
>> "<3>".
>
> I think it's a distinction without a difference for,
> as fas as I know, that's a case that doesn't exist
> in the current kernel.
>
> $ grep -rP --include=*.[ch] "\bpr_cont\s*\(\s*\"<" *
> $ grep -rP --include=*.[ch] "\bprintk\s*\(\s*KERN_CONT\s*\"<" *
> arch/x86/kernel/dumpstack_32.c:                         printk(KERN_CONT "<%02x> ", c);
> arch/x86/kernel/dumpstack_64.c:                         printk(KERN_CONT "<%02x> ", c);
> arch/powerpc/kernel/process.c:                          printk(KERN_CONT "<%08x> ", instr);
> drivers/media/video/tm6000/tm6000-core.c:                       printk(KERN_CONT "<<< ");
> drivers/media/video/cx231xx/cx231xx-core.c:                     printk(KERN_CONT "<<<");

It surely does, and we needed to add KERN_CONT in the past because
stuff got eaten by the prefix parser.
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=40c8cefaaf12734327db7199a56e60058d98e7b6
  http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=13f541c10b30fc6529200d7f9a0073217709622f

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 21:11                                     ` Joe Perches
  2012-05-10 21:15                                       ` Kay Sievers
@ 2012-05-10 21:58                                       ` Linus Torvalds
  2012-05-11  0:13                                         ` Joe Perches
  1 sibling, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-10 21:58 UTC (permalink / raw)
  To: Joe Perches
  Cc: Kay Sievers, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 2:11 PM, Joe Perches <joe@perches.com> wrote:
>
> I think it's a distinction without a difference for,
> as fas as I know, that's a case that doesn't exist
> in the current kernel.

So? Even if we hadn't had this bug before (we have), your argument is
utter crap. Even if we weren't to have that patter right *now*, that
doesn't mean that it cannot happen.

Your grep is also not at all exhaustive. What if somebody does

   printk("%s.."

how are you going to prove that '%s' doesn't contain a level marker
thing? It's much easier to just say "use a KERN_CONT" (or more
commonly KERN_DEFAULT) to avoid the problem.

We do need an escape model. The current KERN_CONT does that. Stop
arguing for crap.

                 Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 21:58                                       ` Linus Torvalds
@ 2012-05-11  0:13                                         ` Joe Perches
  0 siblings, 0 replies; 100+ messages in thread
From: Joe Perches @ 2012-05-11  0:13 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, 2012-05-10 at 14:58 -0700, Linus Torvalds wrote:
> On Thu, May 10, 2012 at 2:11 PM, Joe Perches <joe@perches.com> wrote:
> >
> > I think it's a distinction without a difference for,
> > as fas as I know, that's a case that doesn't exist
> > in the current kernel.
> 
> So? Even if we hadn't had this bug before (we have),

True.  I've fixed the ones you've introduced when you
changed printk semantics in the past.

> your argument is utter crap.

What happened to the pragmatic Linus Torvalds?
Did the dogmatic one replace him again temporarily?

> Even if we weren't to have that patter right *now*, that
> doesn't mean that it cannot happen.

Not what I said.

> Your grep is also not at all exhaustive.

I believe I know the printk subsystem and its uses
as well as anyone.  I don't think there is a case
today.

> We do need an escape model.

Or an agreement to not to emit "<[0-7cd]>"
as the first 3 bytes after a newline or as
the start of a new printk.  It could just
as easily be an escape is a required leading
non "<" character.

I think that's not onerous.

> The current KERN_CONT does that. Stop
> arguing for crap.

Correctness in all cases can be a good thing.
Simplicity may be better because complexity
is reduced.

cheers, Joe


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10 20:52                                   ` Linus Torvalds
  2012-05-10 21:11                                     ` Joe Perches
@ 2012-05-11  0:38                                     ` Kay Sievers
  2012-05-11  1:23                                       ` Kay Sievers
  1 sibling, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-11  0:38 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Joe Perches, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Thu, May 10, 2012 at 10:52 PM, Linus Torvalds <torvalds@linux-foundation.org> wrote:

> The change to verify that 'current' matches the previous printout is
> so far the *only* sane semantic change I've seen in this thread.
> Everything else has been pure garbage.

Ok, let's continue with sane things then. :)

Here is a stupid kernel module which creates 3 racy printk() loops, 2 of
them do continuation, one does an atomic print. The continuation one
prints one char per printk.
  http://people.freedesktop.org/~kay/printk-race/printk-race.c

The lines all try to look like:
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
  (XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)

Every loop has it's own uppercase character. The line enclosed in '()'.
'A' is the atomic one, the cont ones are 'C' and 'X'.

Our current kernel look like:
[   99.056806] XC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   99.059772] XC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   99.062168] XCCX(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   99.066479] CXXC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   99.070063] XC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   99.073081] XCCXCXCXCXCXCXCXCXCXCXCXCXCXCXCCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXC)
[   99.148325] (CCXCXCX)
[   99.155468] (XXCXCXCXCCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXCXXCXCXCXCXCXCXCXCXC)
[   99.277357] (CCXCXCXCX)
  http://people.freedesktop.org/~kay/printk-race/printk-out-before.txt


The kernel with the record buffer, and the 'current' who owns the cont buffer
looks like:
[   78.080866] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   78.082790] (CC
[   78.084152] (XX
[   78.084497] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   78.085494] C
[   78.086125] X
[   78.087188] C
[   78.088669] X
[   78.089803] C
[   78.091510] X
[   78.091924] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   78.094112] CC
[   78.096171] X
  http://people.freedesktop.org/~kay/printk-race/printk-out-after.txt

Thanks,
Kay


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11  0:38                                     ` Kay Sievers
@ 2012-05-11  1:23                                       ` Kay Sievers
  2012-05-14 18:46                                         ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-11  1:23 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Joe Perches, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Fri, 2012-05-11 at 02:38 +0200, Kay Sievers wrote:
> On Thu, May 10, 2012 at 10:52 PM, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> 
> > The change to verify that 'current' matches the previous printout is
> > so far the *only* sane semantic change I've seen in this thread.
> > Everything else has been pure garbage.
> 
> Ok, let's continue with sane things then. :)
> 
> Here is a stupid kernel module which creates 3 racy printk() loops, 2 of
> them do continuation, one does an atomic print. The continuation one
> prints one char per printk.
>   http://people.freedesktop.org/~kay/printk-race/printk-race.c
> 
> The lines all try to look like:
>   (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
>   (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
>   (XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
> 
> Every loop has it's own uppercase character. The line enclosed in '()'.
> 'A' is the atomic one, the cont ones are 'C' and 'X'.

Having only one continuation user racing against an atomic printk user
looks like this:

Current kernel:
[   54.062900] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.068200] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.071698] (CC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.074103] C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.076052] C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.078116] C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.080096] C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.082060] CC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   54.086121] C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  http://people.freedesktop.org/~kay/printk-race/printk-out-before-2.txt

Record buffer, with cont buffer owner:
[   33.431129] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.435112] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.439131] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.441820] (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
[   33.445292] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.450131] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.453127] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.456084] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.459143] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.462161] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
[   33.465165] (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  http://people.freedesktop.org/~kay/printk-race/printk-out-after-2.txt

Kay


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-10  2:30                 ` Kay Sievers
@ 2012-05-11 10:35                   ` Sasha Levin
  2012-05-11 15:19                     ` Greg KH
  2012-05-13 21:30                     ` Kay Sievers
  0 siblings, 2 replies; 100+ messages in thread
From: Sasha Levin @ 2012-05-11 10:35 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Yinghai Lu, Joe Perches, Linus Torvalds,
	Ingo Molnar, linux-kernel

On Thu, May 10, 2012 at 4:30 AM, Kay Sievers <kay@vrfy.org> wrote:
> On Wed, 2012-05-09 at 16:06 -0700, Greg Kroah-Hartmann wrote:
>> On Wed, May 09, 2012 at 04:02:40PM -0700, Yinghai Lu wrote:
>> > On Wed, May 9, 2012 at 7:37 AM, Kay Sievers <kay@vrfy.org> wrote:
>> > >
>> > >> Changing printk semantics and trying to stabilize
>> > >> printk message content are bad ideas though.
>> > >
>> > > Again, nobody talks about content of here.
>> >
>> > printk_time=1 does not work anymore with this patch on serial console.
>>
>> Known issue, I think Kay is working on the solution for this right
>> now...
>
> Sure, and this seems to work for me.
>
> Thanks,
> Kay
>
>
> From: Kay Sievers <kay@vrfy.org>
> Subject: printk() - restore timestamp printing at console output
>
> The output of the timestamps got lost with the conversion of the
> kmsg buffer to records; restore the old behavior.
>
> Document, that CONFIG_PRINTK_TIME now only controls the output of
> the timestamps in the syslog() system call and on the console, and
> not the recording of the timestamps.
>
> Signed-off-by: Kay Sievers <kay@vrfy.org>
> ---

This has a small issue with the way timing is printed compared to how
it worked previously.

Consider the following case:

    printk("\n foo \n bar \n zoot")

Previously, you would see timing on each line of the print, but now
you see it only on the first.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 10:35                   ` Sasha Levin
@ 2012-05-11 15:19                     ` Greg KH
  2012-05-11 15:22                       ` Sasha Levin
  2012-05-11 15:35                       ` Linus Torvalds
  2012-05-13 21:30                     ` Kay Sievers
  1 sibling, 2 replies; 100+ messages in thread
From: Greg KH @ 2012-05-11 15:19 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Kay Sievers, Yinghai Lu, Joe Perches, Linus Torvalds,
	Ingo Molnar, linux-kernel

On Fri, May 11, 2012 at 12:35:07PM +0200, Sasha Levin wrote:
> On Thu, May 10, 2012 at 4:30 AM, Kay Sievers <kay@vrfy.org> wrote:
> > On Wed, 2012-05-09 at 16:06 -0700, Greg Kroah-Hartmann wrote:
> >> On Wed, May 09, 2012 at 04:02:40PM -0700, Yinghai Lu wrote:
> >> > On Wed, May 9, 2012 at 7:37 AM, Kay Sievers <kay@vrfy.org> wrote:
> >> > >
> >> > >> Changing printk semantics and trying to stabilize
> >> > >> printk message content are bad ideas though.
> >> > >
> >> > > Again, nobody talks about content of here.
> >> >
> >> > printk_time=1 does not work anymore with this patch on serial console.
> >>
> >> Known issue, I think Kay is working on the solution for this right
> >> now...
> >
> > Sure, and this seems to work for me.
> >
> > Thanks,
> > Kay
> >
> >
> > From: Kay Sievers <kay@vrfy.org>
> > Subject: printk() - restore timestamp printing at console output
> >
> > The output of the timestamps got lost with the conversion of the
> > kmsg buffer to records; restore the old behavior.
> >
> > Document, that CONFIG_PRINTK_TIME now only controls the output of
> > the timestamps in the syslog() system call and on the console, and
> > not the recording of the timestamps.
> >
> > Signed-off-by: Kay Sievers <kay@vrfy.org>
> > ---
> 
> This has a small issue with the way timing is printed compared to how
> it worked previously.
> 
> Consider the following case:
> 
>     printk("\n foo \n bar \n zoot")
> 
> Previously, you would see timing on each line of the print, but now
> you see it only on the first.

What code does this?  Shouldn't those be individual printk lines?  I
didn't think that type of line would ever work properly in the past.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 15:19                     ` Greg KH
@ 2012-05-11 15:22                       ` Sasha Levin
  2012-05-11 15:35                       ` Linus Torvalds
  1 sibling, 0 replies; 100+ messages in thread
From: Sasha Levin @ 2012-05-11 15:22 UTC (permalink / raw)
  To: Greg KH
  Cc: Kay Sievers, Yinghai Lu, Joe Perches, Linus Torvalds,
	Ingo Molnar, linux-kernel

On Fri, May 11, 2012 at 5:19 PM, Greg KH <gregkh@linuxfoundation.org> wrote:
> On Fri, May 11, 2012 at 12:35:07PM +0200, Sasha Levin wrote:
>> This has a small issue with the way timing is printed compared to how
>> it worked previously.
>>
>> Consider the following case:
>>
>>     printk("\n foo \n bar \n zoot")
>>
>> Previously, you would see timing on each line of the print, but now
>> you see it only on the first.
>
> What code does this?  Shouldn't those be individual printk lines?  I
> didn't think that type of line would ever work properly in the past.

At least the lockdep code, in several places:

        __print_lock_name(safe_class);
        printk(");\n");
        printk("\n *** DEADLOCK ***\n\n");

Which has looked fine before.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 15:19                     ` Greg KH
  2012-05-11 15:22                       ` Sasha Levin
@ 2012-05-11 15:35                       ` Linus Torvalds
  2012-05-11 15:40                         ` Kay Sievers
  1 sibling, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-11 15:35 UTC (permalink / raw)
  To: Greg KH
  Cc: Sasha Levin, Kay Sievers, Yinghai Lu, Joe Perches, Ingo Molnar,
	linux-kernel

On Fri, May 11, 2012 at 8:19 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
>
> What code does this?  Shouldn't those be individual printk lines?  I
> didn't think that type of line would ever work properly in the past.

We've *always* supported multiple lines, Greg. And it has always
worked. It's very inconvenient to have to use multiple printk's when
one would do.

That said, I think it would be interesting if the timing values were
just not printed at all when they match the last one, which would
happen with this kind of setup (and also happens if your time source
sucks).

You'd still want the lines to line up, though.

                       Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 15:35                       ` Linus Torvalds
@ 2012-05-11 15:40                         ` Kay Sievers
  2012-05-11 15:47                           ` Linus Torvalds
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-11 15:40 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Greg KH, Sasha Levin, Yinghai Lu, Joe Perches, Ingo Molnar, linux-kernel

On Fri, May 11, 2012 at 5:35 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Fri, May 11, 2012 at 8:19 AM, Greg KH <gregkh@linuxfoundation.org> wrote:
>>
>> What code does this?  Shouldn't those be individual printk lines?  I
>> didn't think that type of line would ever work properly in the past.
>
> We've *always* supported multiple lines, Greg. And it has always
> worked. It's very inconvenient to have to use multiple printk's when
> one would do.
>
> That said, I think it would be interesting if the timing values were
> just not printed at all when they match the last one, which would
> happen with this kind of setup (and also happens if your time source
> sucks).
>
> You'd still want the lines to line up, though.

Should we just pad the multi-newline-in-one-record output with 15
spaces when printk_time is on?

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 15:40                         ` Kay Sievers
@ 2012-05-11 15:47                           ` Linus Torvalds
  2012-05-11 19:51                             ` Mark Lord
  2012-05-12  7:43                             ` Sasha Levin
  0 siblings, 2 replies; 100+ messages in thread
From: Linus Torvalds @ 2012-05-11 15:47 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg KH, Sasha Levin, Yinghai Lu, Joe Perches, Ingo Molnar, linux-kernel

On Fri, May 11, 2012 at 8:40 AM, Kay Sievers <kay@vrfy.org> wrote:
>
> Should we just pad the multi-newline-in-one-record output with 15
> spaces when printk_time is on?

Yeah, I think that would be the nicest thing.

Btw, I'd also *love* to see some model (eventually - not necessarily
now) where we could have the option of the time printouts being a bit
different (rather than just on/off). It would be very nice if we had
"relative" time printouts for events close together, so the rule could
be something like:

 - if time is same as last line, pad with empty

 - if time is more than a minute from last one, show an absolute value
of dd hh:mm:ss

 - otherwise, show a relative value of +ss.mmmmmm

So the on/off choice could be on/off/relative.

Hmm?

             Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 15:47                           ` Linus Torvalds
@ 2012-05-11 19:51                             ` Mark Lord
  2012-05-11 20:02                               ` Linus Torvalds
  2012-05-12  7:43                             ` Sasha Levin
  1 sibling, 1 reply; 100+ messages in thread
From: Mark Lord @ 2012-05-11 19:51 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Greg KH, Sasha Levin, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On 12-05-11 11:47 AM, Linus Torvalds wrote:
> On Fri, May 11, 2012 at 8:40 AM, Kay Sievers <kay@vrfy.org> wrote:
>>
>> Should we just pad the multi-newline-in-one-record output with 15
>> spaces when printk_time is on?
> 
> Yeah, I think that would be the nicest thing.
> 
> Btw, I'd also *love* to see some model (eventually - not necessarily
> now) where we could have the option of the time printouts being a bit
> different (rather than just on/off). It would be very nice if we had
> "relative" time printouts for events close together, so the rule could
> be something like:
> 
>  - if time is same as last line, pad with empty
> 
>  - if time is more than a minute from last one, show an absolute value
> of dd hh:mm:ss
> 
>  - otherwise, show a relative value of +ss.mmmmmm
> 
> So the on/off choice could be on/off/relative.
> 
> Hmm?

Breaks the "grep for specific messages" case.


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 19:51                             ` Mark Lord
@ 2012-05-11 20:02                               ` Linus Torvalds
  2012-05-12 18:04                                 ` Mark Lord
  0 siblings, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-11 20:02 UTC (permalink / raw)
  To: Mark Lord
  Cc: Kay Sievers, Greg KH, Sasha Levin, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On Fri, May 11, 2012 at 12:51 PM, Mark Lord <kernel@teksavvy.com> wrote:
>
> Breaks the "grep for specific messages" case.

Why?

Sure, if you grep for times, you'd not want to enable the relative
time. But why would you grep for a time anyway? Regardless, it would
be your choice.

Generally, relative times are much more useful - the absolute time seldom is.

                       Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 15:47                           ` Linus Torvalds
  2012-05-11 19:51                             ` Mark Lord
@ 2012-05-12  7:43                             ` Sasha Levin
  2012-05-12 18:35                               ` Linus Torvalds
  2012-05-13 21:48                               ` Kay Sievers
  1 sibling, 2 replies; 100+ messages in thread
From: Sasha Levin @ 2012-05-12  7:43 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Greg KH, Yinghai Lu, Joe Perches, Ingo Molnar, linux-kernel

On Fri, May 11, 2012 at 5:47 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> Btw, I'd also *love* to see some model (eventually - not necessarily
> now) where we could have the option of the time printouts being a bit
> different (rather than just on/off). It would be very nice if we had
> "relative" time printouts for events close together, so the rule could
> be something like:
>
>  - if time is same as last line, pad with empty
>
>  - if time is more than a minute from last one, show an absolute value
> of dd hh:mm:ss
>
>  - otherwise, show a relative value of +ss.mmmmmm
>
> So the on/off choice could be on/off/relative.
>
> Hmm?

So I got something like this:

# sleep 61 ; echo foo > /dev/kmsg ; sleep 61 ; echo bar > /dev/kmsg ;
sleep 5 ; echo zoot > /dev/kmsg ; sleep 10 ; echo foo > /dev/kmsg ;
echo bar > /dev/kmsg ; sleep 61 ; echo zoot > /dev/kmsg ; echo foo >
/dev/kmsg

[  673.222632] foo
[  734.315249] bar
[   +5.077527] zoot
[  +10.235225] foo
[   +0.002971] bar
[  810.883085] zoot
[   +0.003081] foo

If that looks right, I can send a patch once this printf overhaul is
stable, unless Kay already plans on doing it as part of his work.

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 20:02                               ` Linus Torvalds
@ 2012-05-12 18:04                                 ` Mark Lord
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Lord @ 2012-05-12 18:04 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Kay Sievers, Greg KH, Sasha Levin, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On 12-05-11 04:02 PM, Linus Torvalds wrote:
> On Fri, May 11, 2012 at 12:51 PM, Mark Lord <kernel@teksavvy.com> wrote:
>>
>> Breaks the "grep for specific messages" case.
> 
> Why?
> 
> Sure, if you grep for times, you'd not want to enable the relative
> time. But why would you grep for a time anyway? Regardless, it would
> be your choice.


I'd be grepping for specific message content, not times.
But I'd want to see the times for the messages,
to know if they're related events or not.

Relative times are great, no problem there.
But relative to what?  The previous message?

That's no good unless viewing all messages,
rather than a grep'd subset.

But with a choice, we do get the best of both, so no problemo.

Cheers

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-12  7:43                             ` Sasha Levin
@ 2012-05-12 18:35                               ` Linus Torvalds
  2012-05-13 11:08                                 ` Kay Sievers
                                                   ` (2 more replies)
  2012-05-13 21:48                               ` Kay Sievers
  1 sibling, 3 replies; 100+ messages in thread
From: Linus Torvalds @ 2012-05-12 18:35 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Kay Sievers, Greg KH, Yinghai Lu, Joe Perches, Ingo Molnar, linux-kernel

On Sat, May 12, 2012 at 12:43 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
>
> So I got something like this:
>
> # sleep 61 ; echo foo > /dev/kmsg ; sleep 61 ; echo bar > /dev/kmsg ;
> sleep 5 ; echo zoot > /dev/kmsg ; sleep 10 ; echo foo > /dev/kmsg ;
> echo bar > /dev/kmsg ; sleep 61 ; echo zoot > /dev/kmsg ; echo foo >
> /dev/kmsg
>
> [  673.222632] foo
> [  734.315249] bar
> [   +5.077527] zoot
> [  +10.235225] foo
> [   +0.002971] bar
> [  810.883085] zoot
> [   +0.003081] foo
>
> If that looks right, I can send a patch once this printf overhaul is
> stable, unless Kay already plans on doing it as part of his work.

So judging by my own use, I really think that

 (a) the microseconds are *totally* useless for the absolute time. In
fact, they are worse than useless: they take up space and are actively
distracting.

      If the last message was over a minute ago, *nobody* cares about
the microsecond. The microseconds are useful when there are multiple
messages and you see that "oh, those events happened within a couple
of ms of each other", but for the absolute time they are just bad.

     Even the *seconds* are probably not that interesting.

 (b) The one thing I have often wanted is not "after how many seconds
of boot", but "when". So it would actually be nice if the absolute
time was converted into local time. The kernel can actually do that,
so I suspect that the best format for the relative timestamps would
really be something like

   > [May12 11:27] foo
   > [May12 11:28] bar
   > [  +5.077527] zoot
   > [ +10.235225] foo
   > [  +0.002971] bar
   > [May12 11:29] zoot
   > [  +0.003081] foo

because that would be really useful sometimes.

(And no, never mind the year. If you log those things long-term, the
year will be in the full log, so logging the year in the dmesg is just
pointless.)

I dunno. The above is what I would have liked to see quite often. I
look at dmesg, and notice that I had an WARN_ON_ONCE in it, and I have
no idea when it happened, because the "seconds since boot" is totally
useless information for me, as I'm too lazy to try to use /proc/uptime
to calculate what it is.

                    Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-12 18:35                               ` Linus Torvalds
@ 2012-05-13 11:08                                 ` Kay Sievers
  2012-05-13 13:22                                 ` Mark Lord
  2012-05-17  3:44                                 ` H. Peter Anvin
  2 siblings, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-13 11:08 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Sasha Levin, Greg KH, Yinghai Lu, Joe Perches, Ingo Molnar, linux-kernel

On Sat, May 12, 2012 at 8:35 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Sat, May 12, 2012 at 12:43 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
>>
>> So I got something like this:
>>
>> # sleep 61 ; echo foo > /dev/kmsg ; sleep 61 ; echo bar > /dev/kmsg ;
>> sleep 5 ; echo zoot > /dev/kmsg ; sleep 10 ; echo foo > /dev/kmsg ;
>> echo bar > /dev/kmsg ; sleep 61 ; echo zoot > /dev/kmsg ; echo foo >
>> /dev/kmsg
>>
>> [  673.222632] foo
>> [  734.315249] bar
>> [   +5.077527] zoot
>> [  +10.235225] foo
>> [   +0.002971] bar
>> [  810.883085] zoot
>> [   +0.003081] foo
>>
>> If that looks right, I can send a patch once this printf overhaul is
>> stable, unless Kay already plans on doing it as part of his work.
>
> So judging by my own use, I really think that
>
>  (a) the microseconds are *totally* useless for the absolute time. In
> fact, they are worse than useless: they take up space and are actively
> distracting.
>
>      If the last message was over a minute ago, *nobody* cares about
> the microsecond. The microseconds are useful when there are multiple
> messages and you see that "oh, those events happened within a couple
> of ms of each other", but for the absolute time they are just bad.
>
>     Even the *seconds* are probably not that interesting.
>
>  (b) The one thing I have often wanted is not "after how many seconds
> of boot", but "when". So it would actually be nice if the absolute
> time was converted into local time. The kernel can actually do that,
> so I suspect that the best format for the relative timestamps would
> really be something like
>
>   > [May12 11:27] foo
>   > [May12 11:28] bar
>   > [  +5.077527] zoot
>   > [ +10.235225] foo
>   > [  +0.002971] bar
>   > [May12 11:29] zoot
>   > [  +0.003081] foo
>
> because that would be really useful sometimes.
>
> (And no, never mind the year. If you log those things long-term, the
> year will be in the full log, so logging the year in the dmesg is just
> pointless.)
>
> I dunno. The above is what I would have liked to see quite often. I
> look at dmesg, and notice that I had an WARN_ON_ONCE in it, and I have
> no idea when it happened, because the "seconds since boot" is totally
> useless information for me, as I'm too lazy to try to use /proc/uptime
> to calculate what it is.

Yeah, that looks generally more useful.

"dmesg -T" tries to translate that to wall clock time too. At the
moment, it can't really do that reliable at the point of reading the
timestamps though, because the monotonic time used does not include
the time spent in suspend.

One other problem with the current logic is that the timestamp we get
at the moment is not guaranteed to monotonic, log lines from different
CPUs at the same time can jump forth and back, so the relative-time
calculation could, with the current code, show negative values.

Not sure what options we have to use a more better clock source, if
things are expected to work in NMIs and IRQs.

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-12 18:35                               ` Linus Torvalds
  2012-05-13 11:08                                 ` Kay Sievers
@ 2012-05-13 13:22                                 ` Mark Lord
  2012-05-13 18:01                                   ` Linus Torvalds
  2012-05-14 16:40                                   ` valdis.kletnieks
  2012-05-17  3:44                                 ` H. Peter Anvin
  2 siblings, 2 replies; 100+ messages in thread
From: Mark Lord @ 2012-05-13 13:22 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Sasha Levin, Kay Sievers, Greg KH, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On 12-05-12 02:35 PM, Linus Torvalds wrote:
>
>  (b) The one thing I have often wanted is not "after how many seconds
> of boot", but "when". So it would actually be nice if the absolute
> time was converted into local time. The kernel can actually do that,
> so I suspect that the best format for the relative timestamps would
> really be something like
> 
>    > [May12 11:27] foo
>    > [May12 11:28] bar
>    > [  +5.077527] zoot
>    > [ +10.235225] foo
>    > [  +0.002971] bar
>    > [May12 11:29] zoot
>    > [  +0.003081] foo
> 
> because that would be really useful sometimes.
> 
> (And no, never mind the year. If you log those things long-term, the
> year will be in the full log, so logging the year in the dmesg is just
> pointless.)
> 
> I dunno. The above is what I would have liked to see quite often. I
> look at dmesg, and notice that I had an WARN_ON_ONCE in it, and I have
> no idea when it happened, because the "seconds since boot" is totally
> useless information for me, as I'm too lazy to try to use /proc/uptime
> to calculate what it is.


Look in syslog ?


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-13 13:22                                 ` Mark Lord
@ 2012-05-13 18:01                                   ` Linus Torvalds
  2012-05-13 22:19                                     ` Mark Lord
  2012-05-14 16:40                                   ` valdis.kletnieks
  1 sibling, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-05-13 18:01 UTC (permalink / raw)
  To: Mark Lord
  Cc: Sasha Levin, Kay Sievers, Greg KH, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On Sun, May 13, 2012 at 6:22 AM, Mark Lord <kernel@teksavvy.com> wrote:
>
> Look in syslog ?

That usually requires root permission, so it's an extra (annoying)
step. It also gives all kinds or other mostly irrelevant information
for a kernel person.

Besides, according to the same argument, dmesg shouldn't have times
*at*all*. So the "look in your syslog" is pointless for discussing the
dmesg timestamp.

                   Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11 10:35                   ` Sasha Levin
  2012-05-11 15:19                     ` Greg KH
@ 2012-05-13 21:30                     ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-13 21:30 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Greg Kroah-Hartmann, Yinghai Lu, Joe Perches, Linus Torvalds,
	Ingo Molnar, linux-kernel

On Fri, 2012-05-11 at 12:35 +0200, Sasha Levin wrote:
> On Thu, May 10, 2012 at 4:30 AM, Kay Sievers <kay@vrfy.org> wrote:
> > On Wed, 2012-05-09 at 16:06 -0700, Greg Kroah-Hartmann wrote:
> >> On Wed, May 09, 2012 at 04:02:40PM -0700, Yinghai Lu wrote:
> >> > On Wed, May 9, 2012 at 7:37 AM, Kay Sievers <kay@vrfy.org> wrote:
> >> > >
> >> > >> Changing printk semantics and trying to stabilize
> >> > >> printk message content are bad ideas though.
> >> > >
> >> > > Again, nobody talks about content of here.
> >> >
> >> > printk_time=1 does not work anymore with this patch on serial console.
> >>
> >> Known issue, I think Kay is working on the solution for this right
> >> now...
> >
> > Sure, and this seems to work for me.
> >
> > Thanks,
> > Kay
> >
> >
> > From: Kay Sievers <kay@vrfy.org>
> > Subject: printk() - restore timestamp printing at console output
> >
> > The output of the timestamps got lost with the conversion of the
> > kmsg buffer to records; restore the old behavior.
> >
> > Document, that CONFIG_PRINTK_TIME now only controls the output of
> > the timestamps in the syslog() system call and on the console, and
> > not the recording of the timestamps.
> >
> > Signed-off-by: Kay Sievers <kay@vrfy.org>
> > ---
> 
> This has a small issue with the way timing is printed compared to how
> it worked previously.
> 
> Consider the following case:
> 
>     printk("\n foo \n bar \n zoot")
> 
> Previously, you would see timing on each line of the print, but now
> you see it only on the first.

Does this fix it for you? It should fully restore the current behavior
for multi-line printing.

Thanks,
Kay



From: Kay Sievers <kay@vrfy.org>
Subject: printk() - restore prefix/timestamp printing for multi-newline strings

Calls like:
  printk("\n *** DEADLOCK ***\n\n");
will print 3 properly indented, separated, syslog + timestamp prefixed lines in
the log output.


Reported-By: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Kay Sievers <kay@vrfy.org>
---

 printk.c |  127 +++++++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 76 insertions(+), 51 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index c42faf9..ee312c7 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -448,7 +448,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
 
 	/* escape non-printable characters */
 	for (i = 0; i < msg->text_len; i++) {
-		char c = log_text(msg)[i];
+		unsigned char c = log_text(msg)[i];
 
 		if (c < ' ' || c >= 128)
 			len += sprintf(user->buf + len, "\\x%02x", c);
@@ -461,7 +461,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
 		bool line = true;
 
 		for (i = 0; i < msg->dict_len; i++) {
-			char c = log_dict(msg)[i];
+			unsigned char c = log_dict(msg)[i];
 
 			if (line) {
 				user->buf[len++] = ' ';
@@ -785,56 +791,81 @@ static bool printk_time;
 #endif
 module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
 
-static size_t prepend_timestamp(unsigned long long t, char *buf)
+static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
 {
-	unsigned long rem_ns;
+	size_t len = 0;
 
-	if (!printk_time)
-		return 0;
+	if (syslog) {
+		if (buf) {
+			len += sprintf(buf, "<%u>", msg->level);
+		} else {
+			len += 3;
+			if (msg->level > 9)
+				len++;
+			if (msg->level > 99)
+				len++;
+		}
+	}
 
-	if (!buf)
-		return 15;
+	if (printk_time) {
+		if (buf) {
+			unsigned long long ts = msg->ts_nsec;
+			unsigned long rem_nsec = do_div(ts, 1000000000);
 
-	rem_ns = do_div(t, 1000000000);
+			len += sprintf(buf + len, "[%5lu.%06lu] ",
+					 (unsigned long) ts, rem_nsec / 1000);
+		} else {
+			len += 15;
+		}
+	}
 
-	return sprintf(buf, "[%5lu.%06lu] ",
-		       (unsigned long) t, rem_ns / 1000);
+	return len;
 }
 
-static int syslog_print_line(u32 idx, char *text, size_t size)
+static size_t msg_print_text(const struct log *msg, bool syslog,
+			     char *buf, size_t size)
 {
-	struct log *msg;
-	size_t len;
+	const char *text = log_text(msg);
+	size_t text_size = msg->text_len;
+	size_t len = 0;
 
-	msg = log_from_idx(idx);
-	if (!text) {
-		/* calculate length only */
-		len = 3;
+	do {
+		const char *next = memchr(text, '\n', text_size);
+		size_t text_len;
 
-		if (msg->level > 9)
-			len++;
-		if (msg->level > 99)
-			len++;
-		len += prepend_timestamp(0, NULL);
+		if (next) {
+			text_len = next - text;
+			next++;
+			text_size -= next - text;
+		} else {
+			text_len = text_size;
+		}
 
-		len += msg->text_len;
-		len++;
-		return len;
-	}
+		if (buf) {
+			if (print_prefix(msg, syslog, NULL) +
+			    text_len + 1>= size - len)
+				break;
+
+			len += print_prefix(msg, syslog, buf + len);
+			memcpy(buf + len, text, text_len);
+			len += text_len;
+			buf[len++] = '\n';
+		} else {
+			/* SYSLOG_ACTION_* buffer size only calculation */
+			len += print_prefix(msg, syslog, NULL);
+			len += text_len + 1;
+		}
+
+		text = next;
+	} while (text);
 
-	len = sprintf(text, "<%u>", msg->level);
-	len += prepend_timestamp(msg->ts_nsec, text + len);
-	if (len + msg->text_len > size)
-		return -EINVAL;
-	memcpy(text + len, log_text(msg), msg->text_len);
-	len += msg->text_len;
-	text[len++] = '\n';
 	return len;
 }
 
 static int syslog_print(char __user *buf, int size)
 {
 	char *text;
+	struct log *msg;
 	int len;
 
 	text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
@@ -847,7 +878,8 @@ static int syslog_print(char __user *buf, int size)
 		syslog_seq = log_first_seq;
 		syslog_idx = log_first_idx;
 	}
-	len = syslog_print_line(syslog_idx, text, LOG_LINE_MAX);
+	msg = log_from_idx(syslog_idx);
+	len = msg_print_text(msg, true, text, LOG_LINE_MAX);
 	syslog_idx = log_next(syslog_idx);
 	syslog_seq++;
 	raw_spin_unlock_irq(&logbuf_lock);
@@ -887,14 +919,18 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
 		seq = clear_seq;
 		idx = clear_idx;
 		while (seq < log_next_seq) {
-			len += syslog_print_line(idx, NULL, 0);
+			struct log *msg = log_from_idx(idx);
+
+			len += msg_print_text(msg, true, NULL, 0);
 			idx = log_next(idx);
 			seq++;
 		}
 		seq = clear_seq;
 		idx = clear_idx;
 		while (len > size && seq < log_next_seq) {
-			len -= syslog_print_line(idx, NULL, 0);
+			struct log *msg = log_from_idx(idx);
+
+			len -= msg_print_text(msg, true, NULL, 0);
 			idx = log_next(idx);
 			seq++;
 		}
@@ -904,9 +940,10 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
 
 		len = 0;
 		while (len >= 0 && seq < next_seq) {
+			struct log *msg = log_from_idx(idx);
 			int textlen;
 
-			textlen = syslog_print_line(idx, text, LOG_LINE_MAX);
+			textlen = msg_print_text(msg, true, text, LOG_LINE_MAX);
 			if (textlen < 0) {
 				len = textlen;
 				break;
@@ -1044,7 +1081,9 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 			seq = syslog_seq;
 			idx = syslog_idx;
 			while (seq < log_next_seq) {
-				error += syslog_print_line(idx, NULL, 0);
+				struct log *msg = log_from_idx(idx);
+
+				error += msg_print_text(msg, true, NULL, 0);
 				idx = log_next(idx);
 				seq++;
 			}
@@ -1439,10 +1478,8 @@ static struct log *log_from_idx(u32 idx) { return NULL; }
 static u32 log_next(u32 idx) { return 0; }
 static char *log_text(const struct log *msg) { return NULL; }
 static void call_console_drivers(int level, const char *text, size_t len) {}
-static size_t prepend_timestamp(unsigned long long t, char *buf)
-{
-	return 0;
-}
+static size_t msg_print_text(const struct log *msg, bool syslog,
+			     char *buf, size_t size) { return 0; }
 
 #endif /* CONFIG_PRINTK */
 
@@ -1750,7 +1787,7 @@ again:
 	for (;;) {
 		struct log *msg;
 		static char text[LOG_LINE_MAX];
-		size_t len, l;
+		size_t len;
 		int level;
 
 		raw_spin_lock_irqsave(&logbuf_lock, flags);
@@ -1771,13 +1808,7 @@ again:
 		msg = log_from_idx(console_idx);
 		level = msg->level & 7;
 
-		len = prepend_timestamp(msg->ts_nsec, text);
-		l = msg->text_len;
-		if (len + l + 1 >= sizeof(text))
-			l = sizeof(text) - len - 1;
-		memcpy(text + len, log_text(msg), l);
-		len += l;
-		text[len++] = '\n';
+		len = msg_print_text(msg, false, text, sizeof(text));
 
 		console_idx = log_next(console_idx);
 		console_seq++;



^ permalink raw reply related	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-12  7:43                             ` Sasha Levin
  2012-05-12 18:35                               ` Linus Torvalds
@ 2012-05-13 21:48                               ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-13 21:48 UTC (permalink / raw)
  To: Sasha Levin
  Cc: Linus Torvalds, Greg KH, Yinghai Lu, Joe Perches, Ingo Molnar,
	linux-kernel

On Sat, May 12, 2012 at 9:43 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
> On Fri, May 11, 2012 at 5:47 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
>> Btw, I'd also *love* to see some model (eventually - not necessarily
>> now) where we could have the option of the time printouts being a bit
>> different (rather than just on/off). It would be very nice if we had
>> "relative" time printouts for events close together, so the rule could
>> be something like:
>>
>>  - if time is same as last line, pad with empty
>>
>>  - if time is more than a minute from last one, show an absolute value
>> of dd hh:mm:ss
>>
>>  - otherwise, show a relative value of +ss.mmmmmm
>>
>> So the on/off choice could be on/off/relative.
>>
>> Hmm?
>
> So I got something like this:
>
> # sleep 61 ; echo foo > /dev/kmsg ; sleep 61 ; echo bar > /dev/kmsg ;
> sleep 5 ; echo zoot > /dev/kmsg ; sleep 10 ; echo foo > /dev/kmsg ;
> echo bar > /dev/kmsg ; sleep 61 ; echo zoot > /dev/kmsg ; echo foo >
> /dev/kmsg
>
> [  673.222632] foo
> [  734.315249] bar
> [   +5.077527] zoot
> [  +10.235225] foo
> [   +0.002971] bar
> [  810.883085] zoot
> [   +0.003081] foo
>
> If that looks right,
> I can send a patch once this printf overhaul is
> stable

I just sent out the fix to restore the original multi-line behaviour,
I have nothing else queued in that area at the moment.

> unless Kay already plans on doing it as part of his work.

I'm busy making the prink() output look the same as it was before but
without the wrong continuation merges. New features need to wait a
little bit, so go ahead. :)

But I want to express, that I'm very interested in finding out if we
could switch to a 'better' clock source as we have today, which can
safely be translated to wall clock time not leaving the suspend time
out, and not jumping forth and back in time between logs from
different CPUs. I think that would be very useful for your patch too.

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-13 18:01                                   ` Linus Torvalds
@ 2012-05-13 22:19                                     ` Mark Lord
  0 siblings, 0 replies; 100+ messages in thread
From: Mark Lord @ 2012-05-13 22:19 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Sasha Levin, Kay Sievers, Greg KH, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On 12-05-13 02:01 PM, Linus Torvalds wrote:
> On Sun, May 13, 2012 at 6:22 AM, Mark Lord <kernel@teksavvy.com> wrote:
>>
>> Look in syslog ?
> 
> That usually requires root permission, so it's an extra (annoying)
> step. It also gives all kinds or other mostly irrelevant information
> for a kernel person.
> 
> Besides, according to the same argument, dmesg shouldn't have times
> *at*all*. So the "look in your syslog" is pointless for discussing the
> dmesg timestamp.

It's good for dates.  Not as good for times.
I figure anyone trying to diagnose a kernel issue
already has access to /var/log/ as well.  :)

But it's good as you propose with an option.

Cheers

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-13 13:22                                 ` Mark Lord
  2012-05-13 18:01                                   ` Linus Torvalds
@ 2012-05-14 16:40                                   ` valdis.kletnieks
  1 sibling, 0 replies; 100+ messages in thread
From: valdis.kletnieks @ 2012-05-14 16:40 UTC (permalink / raw)
  To: Mark Lord
  Cc: Linus Torvalds, Sasha Levin, Kay Sievers, Greg KH, Yinghai Lu,
	Joe Perches, Ingo Molnar, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 616 bytes --]

On Sun, 13 May 2012 09:22:04 -0400, Mark Lord said:
> On 12-05-12 02:35 PM, Linus Torvalds wrote:
> > I dunno. The above is what I would have liked to see quite often. I
> > look at dmesg, and notice that I had an WARN_ON_ONCE in it, and I have
> > no idea when it happened, because the "seconds since boot" is totally
> > useless information for me, as I'm too lazy to try to use /proc/uptime
> > to calculate what it is.

> Look in syslog ?

Oddly enough, just yesterday I was looking in dmesg on one of my servers, trying to
find a hint of why syslog and a number of other things had failed to start at boot...



[-- Attachment #2: Type: application/pgp-signature, Size: 865 bytes --]

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-11  1:23                                       ` Kay Sievers
@ 2012-05-14 18:46                                         ` Kay Sievers
  0 siblings, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-14 18:46 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Joe Perches, Ted Ts'o, Ingo Molnar, Jonathan Corbet,
	Sasha Levin, Greg Kroah-Hartmann, linux-kernel

On Fri, 2012-05-11 at 03:23 +0200, Kay Sievers wrote:
> On Fri, 2012-05-11 at 02:38 +0200, Kay Sievers wrote:
> > On Thu, May 10, 2012 at 10:52 PM, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> > 
> > > The change to verify that 'current' matches the previous printout is
> > > so far the *only* sane semantic change I've seen in this thread.
> > > Everything else has been pure garbage.
> > 
> > Ok, let's continue with sane things then. :)
> > 
> > Here is a stupid kernel module which creates 3 racy printk() loops, 2 of
> > them do continuation, one does an atomic print. The continuation one
> > prints one char per printk.
> >   http://people.freedesktop.org/~kay/printk-race/printk-race.c
> > 
> > The lines all try to look like:
> >   (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
> >   (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
> >   (XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
> > 
> > Every loop has it's own uppercase character. The line enclosed in '()'.
> > 'A' is the atomic one, the cont ones are 'C' and 'X'.
> 
> Having only one continuation user racing against an atomic printk user
> looks like this:

This seems to work significantly better for me than all earlier
versions. The single line users like dev_printk() should be reliable
now.

Thanks,
Kay


From: Kay Sievers <kay@vrfy.org>
Subject: printk() - isolate KERN_CONT users from ordinary complete lines

Arrange the continuation printk() buffering to be fully separated from the
ordinary full line users.

Limit the exposure to races and wrong printk() line merges to users of
continuation only. Ordinary full line users racing against continuation
users will no longer affect each other.

Multiple continuation users from different threads, racing against each
other will not wrongly be merged into a single line, but printed as
separate lines.

Test output of a kernel module which starts two separate threads which
race against each other, one of them printing a single full terminated
line:
  printk("(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)\n");

The other one printing the line, every character separate in a
continuation loop:
  printk("(C");
  for (i = 0; i < 58; i++)
          printk(KERN_CONT "C");
  printk(KERN_CONT "C)\n");

Behavior of single and non-thread-aware printk() buffer:
  # modprobe printk-race
  printk test init
  (CC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  CC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  CC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  CC(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  C(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
  (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)

New behavior with separate and thread-aware continuation buffer:
  # modprobe printk-race
  printk test init
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)
  (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)
  (CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC)

Signed-off-by: Kay Sievers <kay@vrfy.org>
---

 kernel/printk.c |  113 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 65 insertions(+), 48 deletions(-)

--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1264,13 +1264,13 @@ asmlinkage int vprintk_emit(int facility
 			    const char *fmt, va_list args)
 {
 	static int recursion_bug;
-	static char buf[LOG_LINE_MAX];
-	static size_t buflen;
-	static int buflevel;
+	static char cont_buf[LOG_LINE_MAX];
+	static size_t cont_len;
+	static int cont_level;
+	static struct task_struct *cont_task;
 	static char textbuf[LOG_LINE_MAX];
-	static struct task_struct *cont;
 	char *text = textbuf;
-	size_t textlen;
+	size_t text_len;
 	unsigned long flags;
 	int this_cpu;
 	bool newline = false;
@@ -1320,15 +1320,15 @@ asmlinkage int vprintk_emit(int facility
 	 * The printf needs to come first; we need the syslog
 	 * prefix which might be passed-in as a parameter.
 	 */
-	textlen = vscnprintf(text, sizeof(textbuf), fmt, args);
+	text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
 
 	/* mark and strip a trailing newline */
-	if (textlen && text[textlen-1] == '\n') {
-		textlen--;
+	if (text_len && text[text_len-1] == '\n') {
+		text_len--;
 		newline = true;
 	}
 
-	/* strip syslog prefix and extract log level or flags */
+	/* strip syslog prefix and extract log level or control flags */
 	if (text[0] == '<' && text[1] && text[2] == '>') {
 		switch (text[1]) {
 		case '0' ... '7':
@@ -1338,49 +1338,67 @@ asmlinkage int vprintk_emit(int facility
 			prefix = true;
 		case 'c':	/* KERN_CONT */
 			text += 3;
-			textlen -= 3;
+			text_len -= 3;
 		}
 	}
 
-	if (buflen && (prefix || dict || cont != current)) {
-		/* flush existing buffer */
-		log_store(facility, buflevel, NULL, 0, buf, buflen);
-		printed_len += buflen;
-		buflen = 0;
-	}
-
-	if (buflen == 0) {
-		/* remember level for first message in the buffer */
-		if (level == -1)
-			buflevel = default_message_loglevel;
-		else
-			buflevel = level;
-	}
-
-	if (buflen || !newline) {
-		/* append to existing buffer, or buffer until next message */
-		if (buflen + textlen > sizeof(buf))
-			textlen = sizeof(buf) - buflen;
-		memcpy(buf + buflen, text, textlen);
-		buflen += textlen;
-	}
-
-	if (newline) {
-		/* end of line; flush buffer */
-		if (buflen) {
-			log_store(facility, buflevel,
-				  dict, dictlen, buf, buflen);
-			printed_len += buflen;
-			buflen = 0;
-		} else {
-			log_store(facility, buflevel,
-				  dict, dictlen, text, textlen);
-			printed_len += textlen;
+	if (level == -1)
+		level = default_message_loglevel;
+
+	if (dict) {
+		prefix = true;
+		newline = true;
+	}
+
+	if (!newline) {
+		if (cont_len && (prefix || cont_task != current)) {
+			/*
+			 * Flush earlier buffer, which is either from a
+			 * different thread, or when we got a new prefix.
+			 */
+			log_store(facility, cont_level, NULL, 0, cont_buf, cont_len);
+			cont_len = 0;
 		}
-		cont = NULL;
+
+		if (!cont_len) {
+			cont_level = level;
+			cont_task = current;
+		}
+
+		/* buffer or append to earlier buffer from the same thread */
+		if (cont_len + text_len > sizeof(cont_buf))
+			text_len = sizeof(cont_buf) - cont_len;
+		memcpy(cont_buf + cont_len, text, text_len);
+		cont_len += text_len;
 	} else {
-		/* remember thread which filled the buffer */
-		cont = current;
+		if (cont_len && cont_task == current) {
+			if (prefix) {
+				/*
+				 * New prefix from the same thread; flush. We
+				 * either got no earlier newline, or we race
+				 * with an interrupt.
+				 */
+				log_store(facility, cont_level,
+					  NULL, 0, cont_buf, cont_len);
+				cont_len = 0;
+			}
+
+			/* append to the earlier buffer and flush */
+			if (cont_len + text_len > sizeof(cont_buf))
+				text_len = sizeof(cont_buf) - cont_len;
+			memcpy(cont_buf + cont_len, text, text_len);
+			cont_len += text_len;
+			log_store(facility, cont_level,
+				  NULL, 0, cont_buf, cont_len);
+			cont_len = 0;
+			cont_task = NULL;
+			printed_len = cont_len;
+		} else {
+			/* ordinary single and terminated line */
+			log_store(facility, level,
+				  dict, dictlen, text, text_len);
+			printed_len = text_len;
+		}
 	}
 
 	/*
@@ -1470,7 +1488,6 @@ EXPORT_SYMBOL(printk);
 #define LOG_LINE_MAX 0
 static struct log *log_from_idx(u32 idx) { return NULL; }
 static u32 log_next(u32 idx) { return 0; }
-static char *log_text(const struct log *msg) { return NULL; }
 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; }



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-12 18:35                               ` Linus Torvalds
  2012-05-13 11:08                                 ` Kay Sievers
  2012-05-13 13:22                                 ` Mark Lord
@ 2012-05-17  3:44                                 ` H. Peter Anvin
  2 siblings, 0 replies; 100+ messages in thread
From: H. Peter Anvin @ 2012-05-17  3:44 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Sasha Levin, Kay Sievers, Greg KH, Yinghai Lu, Joe Perches,
	Ingo Molnar, linux-kernel

On 05/12/2012 11:35 AM, Linus Torvalds wrote:
> 
>  (b) The one thing I have often wanted is not "after how many seconds
> of boot", but "when". So it would actually be nice if the absolute
> time was converted into local time. The kernel can actually do that,
> so I suspect that the best format for the relative timestamps would
> really be something like
> 
>    > [May12 11:27] foo
>    > [May12 11:28] bar
>    > [  +5.077527] zoot
>    > [ +10.235225] foo
>    > [  +0.002971] bar
>    > [May12 11:29] zoot
>    > [  +0.003081] foo
> 
> because that would be really useful sometimes.
> 
> (And no, never mind the year. If you log those things long-term, the
> year will be in the full log, so logging the year in the dmesg is just
> pointless.)

I would like to give a +1 on absolute time, and -1 on local timezone and
a -$LARGE_NUMBER on low resolution.

Why?  Getting events accurately timed across multiple hosts can be
really useful when trying to reconstruct, ahem, "network events".

Getting UTC time at some fairly high resolution is useful for that.  I
would say the useful resolution is probably milliseconds.

	-hpa


^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03  0:29 [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer Kay Sievers
  2012-05-03 19:48 ` Peter Zijlstra
  2012-05-08  8:48 ` Sasha Levin
@ 2012-05-26 11:11 ` Anton Vorontsov
  2012-05-27 14:23   ` Kay Sievers
  2012-11-28 13:33 ` Michael Kerrisk
  3 siblings, 1 reply; 100+ messages in thread
From: Anton Vorontsov @ 2012-05-26 11:11 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

Hello Kay,

On Thu, May 03, 2012 at 02:29:13AM +0200, Kay Sievers wrote:
> From: Kay Sievers <kay@vrfy.org>
> Subject: printk: convert byte-buffer to variable-length record buffer

Bad news, this patch breaks all kmsg_dump users.

Per current printk.c:

 * The 'struct log' buffer header must never be directly exported to
 * userspace, it is a kernel-private implementation detail that might
 * need to be changed in the future, when the requirements change.

But kmsg_dump users get the raw log, not text. Some users may even
use strlen() on the buffers, e.g. ramoops module was using it just
recently, before persistent_ram rework.

So, starting from this patch every kmsg_dump user is getting the
binary stuff, which is barely usable, and breaks a longstanding
user-visible ABIs (e.g. mtdoops, oops dumping into nvram on PowerPC,
and ramoops of course).

I'm not sure how we can fix this without allocating a huge buffer
(and thus wasting memory), or reworking the whole kmsg_dump concept
and its users.

Ideas?

p.s. And, btw, during HW bring-up, when there's even no serial
console usable, I somewhat liked to directly print log_buf memory
from a JTAG debugger, and thus see the kernel logs. Now that'll
look ugly. Heh. :-)

-- 
Anton Vorontsov
Email: cbouatmailru@gmail.com

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-26 11:11 ` Anton Vorontsov
@ 2012-05-27 14:23   ` Kay Sievers
  2012-05-29 16:07     ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-27 14:23 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

On Sat, May 26, 2012 at 1:11 PM, Anton Vorontsov
<anton.vorontsov@linaro.org> wrote:

>> Subject: printk: convert byte-buffer to variable-length record buffer
>
> Bad news, this patch breaks all kmsg_dump users.
>
> Per current printk.c:
>
>  * The 'struct log' buffer header must never be directly exported to
>  * userspace, it is a kernel-private implementation detail that might
>  * need to be changed in the future, when the requirements change.
>
> But kmsg_dump users get the raw log, not text. Some users may even
> use strlen() on the buffers, e.g. ramoops module was using it just
> recently, before persistent_ram rework.
>
> So, starting from this patch every kmsg_dump user is getting the
> binary stuff, which is barely usable, and breaks a longstanding
> user-visible ABIs (e.g. mtdoops, oops dumping into nvram on PowerPC,
> and ramoops of course).

These cases export their own format, it's just that the dump routines
could copy the buffer in only two steps (beginning and end of the ring
buffer), while in the future their code would need an update to copy
it record for record now. The exported format in the dump does not
necessarily need to change.

It should be possible to convert them pretty easily to do that, they
operate on their own allocated buffers already. Some of them seem to
mangle the line-buffer already, so they should be able to copy
record-by-record either.

> I'm not sure how we can fix this without allocating a huge buffer
> (and thus wasting memory), or reworking the whole kmsg_dump concept
> and its users.

I think an iterator in the dumper code is nicer and simpler. It will
even provide structured data to the dumper, if the dumper wants to
make use of it in the future. The prefix mangling of the text in the
nvram dumper could surely benefit from that.

The iterator would basically work similar to the printing of the whole
buffer at a newly registered boot console, which was doing a similar
logic as the dumper does.

> p.s. And, btw, during HW bring-up, when there's even no serial
> console usable, I somewhat liked to directly print log_buf memory
> from a JTAG debugger, and thus see the kernel logs. Now that'll
> look ugly. Heh. :-)

Yeah, that probably does not look pretty anymore, but it still all
works, right? Doesn't have he debugger a strings(1)-like output to
print of a memory area?

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-27 14:23   ` Kay Sievers
@ 2012-05-29 16:07     ` Kay Sievers
  2012-05-29 16:14       ` Joe Perches
                         ` (3 more replies)
  0 siblings, 4 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-29 16:07 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

On Sun, 2012-05-27 at 16:23 +0200, Kay Sievers wrote:
> On Sat, May 26, 2012 at 1:11 PM, Anton Vorontsov <anton.vorontsov@linaro.org> wrote:

> > So, starting from this patch every kmsg_dump user is getting the
> > binary stuff, which is barely usable, and breaks a longstanding
> > user-visible ABIs (e.g. mtdoops, oops dumping into nvram on PowerPC,
> > and ramoops of course).
> 
> These cases export their own format, it's just that the dump routines
> could copy the buffer in only two steps (beginning and end of the ring
> buffer), while in the future their code would need an update to copy
> it record for record now. The exported format in the dump does not
> necessarily need to change.

Here is an untested patch, which should restore the old plain text
export format of the kmsg buffer. I adds an iterator to the dumper
routine, which can be used by the dumper to properly copy the data out
of the kmsg record buffer. All current users are converted in the same
patch.

Any feedback/help in testing/updating and getting this thing into a
mergeable state would be greatly appreciated.

There are two versions of the iterator:
kmsg_dump_get_line() starts with the oldest records. With the next call,
the iterator retrieves one line after the other. Useful for cases like
printing to a console or any other stream device.

kmsg_dump_get_buffer() fills a buffer with as many of the youngest
records as fit into it. With the next call, the iterator retrieves the
next block of older messages. Useful to dump the entire buffer with one
shot, or chunk the data into blocks and store them, with the youngest
messages being the most important, retrieved first.

Unlike the old logic, there are no stale pointers handed out to the
dumper, if case things get overwritten while a dump is in progress,
lines are not truncated or overwritten.

Thanks,
Kay

---
 arch/powerpc/platforms/pseries/nvram.c     |   60 +---------
 arch/x86/platform/mrst/early_printk_mrst.c |   13 --
 drivers/mtd/mtdoops.c                      |   22 ---
 fs/pstore/platform.c                       |   34 ++---
 include/linux/kmsg_dump.h                  |   39 +++++-
 kernel/printk.c                            |  173 ++++++++++++++++++++++++-----
 6 files changed, 204 insertions(+), 137 deletions(-)

--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -68,9 +68,7 @@ static const char *pseries_nvram_os_part
 };
 
 static void oops_to_nvram(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason,
-		const char *old_msgs, unsigned long old_len,
-		const char *new_msgs, unsigned long new_len);
+			  enum kmsg_dump_reason reason);
 
 static struct kmsg_dumper nvram_kmsg_dumper = {
 	.dump = oops_to_nvram
@@ -504,28 +502,6 @@ int __init pSeries_nvram_init(void)
 }
 
 /*
- * Try to capture the last capture_len bytes of the printk buffer.  Return
- * the amount actually captured.
- */
-static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
-				const char *new_msgs, size_t new_len,
-				char *captured, size_t capture_len)
-{
-	if (new_len >= capture_len) {
-		memcpy(captured, new_msgs + (new_len - capture_len),
-								capture_len);
-		return capture_len;
-	} else {
-		/* Grab the end of old_msgs. */
-		size_t old_tail_len = min(old_len, capture_len - new_len);
-		memcpy(captured, old_msgs + (old_len - old_tail_len),
-								old_tail_len);
-		memcpy(captured + old_tail_len, new_msgs, new_len);
-		return old_tail_len + new_len;
-	}
-}
-
-/*
  * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
  * would logging this oops/panic overwrite an RTAS event that rtas_errd
  * hasn't had a chance to read and process?  Return 1 if so, else 0.
@@ -541,27 +517,6 @@ static int clobbering_unread_rtas_event(
 						NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* Squeeze out each line's <n> severity prefix. */
-static size_t elide_severities(char *buf, size_t len)
-{
-	char *in, *out, *buf_end = buf + len;
-	/* Assume a <n> at the very beginning marks the start of a line. */
-	int newline = 1;
-
-	in = out = buf;
-	while (in < buf_end) {
-		if (newline && in+3 <= buf_end &&
-				*in == '<' && isdigit(in[1]) && in[2] == '>') {
-			in += 3;
-			newline = 0;
-		} else {
-			newline = (*in == '\n');
-			*out++ = *in++;
-		}
-	}
-	return out - buf;
-}
-
 /* Derived from logfs_compress() */
 static int nvram_compress(const void *in, void *out, size_t inlen,
 							size_t outlen)
@@ -619,9 +574,7 @@ static int zip_oops(size_t text_len)
  * partition.  If that's too much, go back and capture uncompressed text.
  */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason,
-		const char *old_msgs, unsigned long old_len,
-		const char *new_msgs, unsigned long new_len)
+			  enum kmsg_dump_reason reason)
 {
 	static unsigned int oops_count = 0;
 	static bool panicking = false;
@@ -660,14 +613,13 @@ static void oops_to_nvram(struct kmsg_du
 		return;
 
 	if (big_oops_buf) {
-		text_len = capture_last_msgs(old_msgs, old_len,
-			new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
-		text_len = elide_severities(big_oops_buf, text_len);
+		kmsg_dump_get_buffer(dumper, false,
+				     big_oops_buf, big_oops_buf_sz, &text_len);
 		rc = zip_oops(text_len);
 	}
 	if (rc != 0) {
-		text_len = capture_last_msgs(old_msgs, old_len,
-				new_msgs, new_len, oops_data, oops_data_sz);
+		kmsg_dump_get_buffer(dumper, true,
+				     oops_data, oops_data_sz, &text_len);
 		err_type = ERR_TYPE_KERNEL_PANIC;
 		*oops_len = (u16) text_len;
 	}
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/mrst/early_printk_mrst.c
@@ -110,19 +110,16 @@ static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
 
 static void dw_kmsg_dump(struct kmsg_dumper *dumper,
-			enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2)
+			 enum kmsg_dump_reason reason)
 {
-	int i;
+	static char line[1024];
+	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
 	mrst_early_console_init();
 
-	for (i = 0; i < l1; i++)
-		early_mrst_console.write(&early_mrst_console, s1 + i, 1);
-	for (i = 0; i < l2; i++)
-		early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
+		early_mrst_console.write(&early_mrst_console, line, len);
 }
 
 /* Set the ratio rate to 115200, 8n1, IRQ disabled */
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -304,32 +304,17 @@ static void find_next_position(struct mt
 }
 
 static void mtdoops_do_dump(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
-		const char *s2, unsigned long l2)
+			    enum kmsg_dump_reason reason)
 {
 	struct mtdoops_context *cxt = container_of(dumper,
 			struct mtdoops_context, dump);
-	unsigned long s1_start, s2_start;
-	unsigned long l1_cpy, l2_cpy;
-	char *dst;
-
-	if (reason != KMSG_DUMP_OOPS &&
-	    reason != KMSG_DUMP_PANIC)
-		return;
 
 	/* Only dump oopses if dump_oops is set */
 	if (reason == KMSG_DUMP_OOPS && !dump_oops)
 		return;
 
-	dst = cxt->oops_buf + MTDOOPS_HEADER_SIZE; /* Skip the header */
-	l2_cpy = min(l2, record_size - MTDOOPS_HEADER_SIZE);
-	l1_cpy = min(l1, record_size - MTDOOPS_HEADER_SIZE - l2_cpy);
-
-	s2_start = l2 - l2_cpy;
-	s1_start = l1 - l1_cpy;
-
-	memcpy(dst, s1 + s1_start, l1_cpy);
-	memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
+	kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
+			     record_size - MTDOOPS_HEADER_SIZE, NULL);
 
 	/* Panics must be written immediately */
 	if (reason != KMSG_DUMP_OOPS)
@@ -375,6 +360,7 @@ static void mtdoops_notify_add(struct mt
 		return;
 	}
 
+	cxt->dump.max_reason = KMSG_DUMP_OOPS;
 	cxt->dump.dump = mtdoops_do_dump;
 	err = kmsg_dump_register(&cxt->dump);
 	if (err) {
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -94,20 +94,15 @@ static const char *get_reason_str(enum k
  * as we can from the end of the buffer.
  */
 static void pstore_dump(struct kmsg_dumper *dumper,
-	    enum kmsg_dump_reason reason,
-	    const char *s1, unsigned long l1,
-	    const char *s2, unsigned long l2)
+			enum kmsg_dump_reason reason)
 {
-	unsigned long	s1_start, s2_start;
-	unsigned long	l1_cpy, l2_cpy;
-	unsigned long	size, total = 0;
-	char		*dst;
+	unsigned long	total = 0;
 	const char	*why;
 	u64		id;
-	int		hsize, ret;
 	unsigned int	part = 1;
 	unsigned long	flags = 0;
 	int		is_locked = 0;
+	int		ret;
 
 	why = get_reason_str(reason);
 
@@ -119,30 +114,25 @@ static void pstore_dump(struct kmsg_dump
 		spin_lock_irqsave(&psinfo->buf_lock, flags);
 	oopscount++;
 	while (total < kmsg_bytes) {
+		char *dst;
+		unsigned long size;
+		int hsize;
+		size_t len;
+
 		dst = psinfo->buf;
 		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
 		size = psinfo->bufsize - hsize;
 		dst += hsize;
 
-		l2_cpy = min(l2, size);
-		l1_cpy = min(l1, size - l2_cpy);
-
-		if (l1_cpy + l2_cpy == 0)
+		if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
 			break;
 
-		s2_start = l2 - l2_cpy;
-		s1_start = l1 - l1_cpy;
-
-		memcpy(dst, s1 + s1_start, l1_cpy);
-		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
-
 		ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
-				   hsize + l1_cpy + l2_cpy, psinfo);
+				    hsize + len, psinfo);
 		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 			pstore_new_entry = 1;
-		l1 -= l1_cpy;
-		l2 -= l2_cpy;
-		total += l1_cpy + l2_cpy;
+
+		total += hsize + len;
 		part++;
 	}
 	if (in_nmi()) {
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -21,6 +21,7 @@
  * is passed to the kernel.
  */
 enum kmsg_dump_reason {
+	KMSG_DUMP_UNDEF,
 	KMSG_DUMP_PANIC,
 	KMSG_DUMP_OOPS,
 	KMSG_DUMP_EMERG,
@@ -31,23 +32,35 @@ enum kmsg_dump_reason {
 
 /**
  * struct kmsg_dumper - kernel crash message dumper structure
- * @dump:	The callback which gets called on crashes. The buffer is passed
- * 		as two sections, where s1 (length l1) contains the older
- * 		messages and s2 (length l2) contains the newer.
  * @list:	Entry in the dumper list (private)
+ * @dump:	Call into dumping code which will retrieve the data with
+ * 		through the record iterator
+ * @max_reason:	filter for highest reason number that should be dumped
  * @registered:	Flag that specifies if this is already registered
  */
 struct kmsg_dumper {
-	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2);
 	struct list_head list;
-	int registered;
+	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+	enum kmsg_dump_reason max_reason;
+	bool active;
+	bool registered;
+
+	/* private state of the kmsg iterator */
+	u32 cur_idx;
+	u32 next_idx;
+	u64 cur_seq;
+	u64 next_seq;
 };
 
 #ifdef CONFIG_PRINTK
 void kmsg_dump(enum kmsg_dump_reason reason);
 
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			  char *line, size_t size, size_t *len);
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			  char *buf, size_t size, size_t *len);
+
 int kmsg_dump_register(struct kmsg_dumper *dumper);
 
 int kmsg_dump_unregister(struct kmsg_dumper *dumper);
@@ -56,6 +69,18 @@ static inline void kmsg_dump(enum kmsg_d
 {
 }
 
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			  const char *line, size_t size, size_t *len)
+{
+	return false
+}
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			    char *buf, size_t size, size_t *len)
+{
+	return false;
+}
+
 static inline int kmsg_dump_register(struct kmsg_dumper *dumper)
 {
 	return -EINVAL;
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -909,7 +909,7 @@ static int syslog_print_all(char __user
 		/*
 		 * Find first record that fits, including all following records,
 		 * into the user-provided buffer for this dump.
-		*/
+		 */
 		seq = clear_seq;
 		idx = clear_idx;
 		while (seq < log_next_seq) {
@@ -919,6 +919,8 @@ static int syslog_print_all(char __user
 			idx = log_next(idx);
 			seq++;
 		}
+
+		/* move first record forward until length fits into the buffer */
 		seq = clear_seq;
 		idx = clear_idx;
 		while (len > size && seq < log_next_seq) {
@@ -929,7 +931,7 @@ static int syslog_print_all(char __user
 			seq++;
 		}
 
-		/* last message in this dump */
+		/* last message fitting into this dump */
 		next_seq = log_next_seq;
 
 		len = 0;
@@ -2305,43 +2307,158 @@ module_param_named(always_kmsg_dump, alw
  */
 void kmsg_dump(enum kmsg_dump_reason reason)
 {
-	u64 idx;
 	struct kmsg_dumper *dumper;
-	const char *s1, *s2;
-	unsigned long l1, l2;
 	unsigned long flags;
 
 	if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
 		return;
 
-	/* Theoretically, the log could move on after we do this, but
-	   there's not a lot we can do about that. The new messages
-	   will overwrite the start of what we dump. */
+	rcu_read_lock();
+	list_for_each_entry_rcu(dumper, &dump_list, list) {
+		if (dumper->max_reason && reason > dumper->max_reason)
+			continue;
 
-	raw_spin_lock_irqsave(&logbuf_lock, flags);
-	if (syslog_seq < log_first_seq)
-		idx = syslog_idx;
-	else
-		idx = log_first_idx;
-
-	if (idx > log_next_idx) {
-		s1 = log_buf;
-		l1 = log_next_idx;
+		/* initialize iterator with data about the stored records */
+		dumper->active = true;
 
-		s2 = log_buf + idx;
-		l2 = log_buf_len - idx;
-	} else {
-		s1 = "";
-		l1 = 0;
+		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);
 
-		s2 = log_buf + idx;
-		l2 = log_next_idx - idx;
+		/* invoke dumper which will iterate over records */
+		dumper->dump(dumper, reason);
+
+		/* reset iterator */
+		dumper->active = false;
 	}
+	rcu_read_unlock();
+}
+
+/*
+ * Start at the *oldest* kmsg record, and print one line into the provided
+ * buffer. Repeated calls will return the next record. A return value of
+ * FALSE indicates that all records are read including the youngest one.
+ */
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			char *line, size_t size, size_t *len)
+{
+	unsigned long flags;
+	struct log *msg;
+	size_t l = 0;
+	bool ret = false;
+
+	if (!dumper->active)
+		goto out;
+
+	raw_spin_lock_irqsave(&logbuf_lock, flags);
+	if (dumper->cur_seq < log_first_seq) {
+		/* messages are gone, move to first available one */
+		dumper->cur_seq = log_first_seq;
+		dumper->cur_idx = log_first_idx;
+	}
+
+	/* last entry */
+	if (dumper->cur_seq >= log_next_seq) {
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
+
+	msg = log_from_idx(dumper->cur_idx);
+	l = msg_print_text(msg, syslog,
+			      line, size);
+
+	dumper->cur_idx = log_next(dumper->cur_idx);
+	dumper->cur_seq++;
+	ret = true;
 	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+	if (len)
+		*len = l;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(dumper, &dump_list, list)
-		dumper->dump(dumper, reason, s1, l1, s2, l2);
-	rcu_read_unlock();
+/*
+ * Fill the provided buffer with as many of the the *youngest* kmsg records
+ * that fit into it. Repeated calls will fill the buffer with the next block
+ * of older records, not including the former ones. A return value of FALSE
+ * indicate that all records are read, including the oldest one.
+ */
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			  char *buf, size_t size, size_t *len)
+{
+	unsigned long flags;
+	u64 seq;
+	u32 idx;
+	u64 next_seq;
+	u32 next_idx;
+	size_t l = 0;
+	bool ret = false;
+
+	if (!dumper->active)
+		goto out;
+
+	raw_spin_lock_irqsave(&logbuf_lock, flags);
+	if (dumper->cur_seq < log_first_seq) {
+		/* messages are gone, move to first available one */
+		dumper->cur_seq = log_first_seq;
+		dumper->cur_idx = log_first_idx;
+	}
+
+	/* last entry */
+	if (dumper->cur_seq >= dumper->next_seq) {
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
+
+	/* calculate length of entire buffer */
+	seq = dumper->cur_seq;
+	idx = dumper->cur_idx;
+	while (seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l += msg_print_text(msg, true, NULL, 0);
+		idx = log_next(idx);
+		seq++;
+	}
+
+	/* move first record forward until length fits into the buffer */
+	seq = dumper->cur_seq;
+	idx = dumper->cur_idx;
+	while (l > size && seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l -= msg_print_text(msg, true, NULL, 0);
+		idx = log_next(idx);
+		seq++;
+	}
+
+	/* last message in next interation */
+	next_seq = seq;
+	next_idx = idx;
+
+	l = 0;
+	while (seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l += msg_print_text(msg, syslog,
+				    buf + l, size - l);
+
+		idx = log_next(idx);
+		seq++;
+	}
+
+	dumper->next_seq = next_seq;
+	dumper->next_idx = next_idx;
+	ret = true;
+	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+	if (len)
+		*len = l;
+	return ret;
 }
+EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
 #endif



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 16:07     ` Kay Sievers
@ 2012-05-29 16:14       ` Joe Perches
  2012-05-29 16:34         ` Kay Sievers
  2012-05-29 17:11       ` Luck, Tony
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 100+ messages in thread
From: Joe Perches @ 2012-05-29 16:14 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Anton Vorontsov, Greg Kroah-Hartmann, Linus Torvalds,
	Ingo Molnar, linux-kernel, Kees Cook, Colin Cross, Tony Luck,
	John Stultz

On Tue, 2012-05-29 at 18:07 +0200, Kay Sievers wrote:
[]
> --- a/include/linux/kmsg_dump.h
> +++ b/include/linux/kmsg_dump.h
[]
> @@ -56,6 +69,18 @@ static inline void kmsg_dump(enum kmsg_d
>  {
>  }
>  
> +bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
> +			  const char *line, size_t size, size_t *len)
> +{
> +	return false
> +}

uncompilable.




^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 16:14       ` Joe Perches
@ 2012-05-29 16:34         ` Kay Sievers
  2012-05-29 16:51           ` Joe Perches
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-29 16:34 UTC (permalink / raw)
  To: Joe Perches
  Cc: Anton Vorontsov, Greg Kroah-Hartmann, Linus Torvalds,
	Ingo Molnar, linux-kernel, Kees Cook, Colin Cross, Tony Luck,
	John Stultz

On Tue, May 29, 2012 at 6:14 PM, Joe Perches <joe@perches.com> wrote:
> On Tue, 2012-05-29 at 18:07 +0200, Kay Sievers wrote:

>> +bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
>> +                       const char *line, size_t size, size_t *len)
>> +{
>> +     return false
>> +}
>
> uncompilable.

The damn !CONFIG_PRINTK case. :) Fixed!
  http://git.kernel.org/?p=linux/kernel/git/kay/patches.git;a=commitdiff;h=607b6e8fa7ca61dd385d632fe51c6afc5f5374b7

Thanks,
Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 16:34         ` Kay Sievers
@ 2012-05-29 16:51           ` Joe Perches
  0 siblings, 0 replies; 100+ messages in thread
From: Joe Perches @ 2012-05-29 16:51 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Anton Vorontsov, Greg Kroah-Hartmann, Linus Torvalds,
	Ingo Molnar, linux-kernel, Kees Cook, Colin Cross, Tony Luck,
	John Stultz

On Tue, 2012-05-29 at 18:34 +0200, Kay Sievers wrote:
> The damn !CONFIG_PRINTK case. :) Fixed!

Maybe more appropriate is a ;)  Thanks.

When you get a chance, could you comment on the
RFC patch to convert the <.> in KERN_<LEVEL>
to an ascii SOH.

https://lkml.org/lkml/2012/5/24/350

It doesn't / shouldn't affect any output anywhere
as vprintk_emit converts it back to <.> for the
actual output, it saves some space, and it makes
KERN_CONT/pr_cont unnecessary as anything other
than a notational marker.


^ permalink raw reply	[flat|nested] 100+ messages in thread

* RE: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 16:07     ` Kay Sievers
  2012-05-29 16:14       ` Joe Perches
@ 2012-05-29 17:11       ` Luck, Tony
  2012-05-29 17:22         ` Kay Sievers
  2012-06-06  6:33       ` Greg Kroah-Hartmann
  2012-06-15  0:04       ` Greg KH
  3 siblings, 1 reply; 100+ messages in thread
From: Luck, Tony @ 2012-05-29 17:11 UTC (permalink / raw)
  To: Kay Sievers, Anton Vorontsov
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, John Stultz

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 960 bytes --]

+/*
+ * Fill the provided buffer with as many of the the *youngest* kmsg records
+ * that fit into it. Repeated calls will fill the buffer with the next block
+ * of older records, not including the former ones. A return value of FALSE
+ * indicate that all records are read, including the oldest one.
+ */

I confess to not reading all of this ... but does this handle the pstore/OOPS
case? We'll use this call to pull as many records as will fit in the pstore
error record ... but almost certainly won't pull all of the console log, so
we won't see the FALSE return.

The system keeps on running.

Now another OOPS happens and pstore wants to grab the new "youngest" records,
it doesn't want to continue stepping to older records from the place it got
to on the first OOPS.  Will that work?

-Tony
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 17:11       ` Luck, Tony
@ 2012-05-29 17:22         ` Kay Sievers
  2012-05-30 11:29           ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-05-29 17:22 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Anton Vorontsov, Greg Kroah-Hartmann, Linus Torvalds,
	Ingo Molnar, linux-kernel, Kees Cook, Colin Cross, John Stultz

On Tue, May 29, 2012 at 7:11 PM, Luck, Tony <tony.luck@intel.com> wrote:
> +/*
> + * Fill the provided buffer with as many of the the *youngest* kmsg records
> + * that fit into it. Repeated calls will fill the buffer with the next block
> + * of older records, not including the former ones. A return value of FALSE
> + * indicate that all records are read, including the oldest one.
> + */
>
> I confess to not reading all of this ... but does this handle the pstore/OOPS
> case? We'll use this call to pull as many records as will fit in the pstore
> error record ... but almost certainly won't pull all of the console log, so
> we won't see the FALSE return.

The loop in pstore gets the newest messages first, then another chunk
of the older messages with every call; pstore stops to iterate when
the defined limit it wants to store is reached, or when no messages
are available anymore.

> The system keeps on running.
>
> Now another OOPS happens and pstore wants to grab the new "youngest" records,
> it doesn't want to continue stepping to older records from the place it got
> to on the first OOPS.  Will that work?

A new oops will init the iterator again, so it will start at the end
with the new messages that happened in the meantime.

The iterator is only valid while used from dump(), it will return an
error if used outside of it.

The logic *should* work; at least it should be easy to make it work if
it doesn't. :)

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 17:22         ` Kay Sievers
@ 2012-05-30 11:29           ` Kay Sievers
  0 siblings, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-05-30 11:29 UTC (permalink / raw)
  To: Luck, Tony
  Cc: Anton Vorontsov, Greg Kroah-Hartmann, Linus Torvalds,
	Ingo Molnar, linux-kernel, Kees Cook, Colin Cross, John Stultz

On Tue, 2012-05-29 at 19:22 +0200, Kay Sievers wrote:
> On Tue, May 29, 2012 at 7:11 PM, Luck, Tony <tony.luck@intel.com> wrote:
> > +/*
> > + * Fill the provided buffer with as many of the the *youngest* kmsg records
> > + * that fit into it. Repeated calls will fill the buffer with the next block
> > + * of older records, not including the former ones. A return value of FALSE
> > + * indicate that all records are read, including the oldest one.
> > + */
> >
> > I confess to not reading all of this ... but does this handle the pstore/OOPS
> > case? We'll use this call to pull as many records as will fit in the pstore
> > error record ... but almost certainly won't pull all of the console log, so
> > we won't see the FALSE return.
> 
> The loop in pstore gets the newest messages first, then another chunk
> of the older messages with every call; pstore stops to iterate when
> the defined limit it wants to store is reached, or when no messages
> are available anymore.
> 
> > The system keeps on running.
> >
> > Now another OOPS happens and pstore wants to grab the new "youngest" records,
> > it doesn't want to continue stepping to older records from the place it got
> > to on the first OOPS.  Will that work?
> 
> A new oops will init the iterator again, so it will start at the end
> with the new messages that happened in the meantime.
> 
> The iterator is only valid while used from dump(), it will return an
> error if used outside of it.
> 
> The logic *should* work; at least it should be easy to make it work if
> it doesn't. :)

Updated patch with proper kerneldoc headers, to clarify the iterator's
interface and behavior.

Tony, could you possibly give it a try with your pstore dumper, if it
behaves as expected, or what we need to fix?

Thanks,
Kay

---
 arch/powerpc/platforms/pseries/nvram.c     |   61 -------
 arch/x86/platform/mrst/early_printk_mrst.c |   13 -
 drivers/mtd/mtdoops.c                      |   22 --
 fs/pstore/platform.c                       |   34 +---
 include/linux/kmsg_dump.h                  |   45 ++++-
 kernel/printk.c                            |  222 +++++++++++++++++++++++++----
 6 files changed, 259 insertions(+), 138 deletions(-)

--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -68,9 +68,7 @@ static const char *pseries_nvram_os_part
 };
 
 static void oops_to_nvram(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason,
-		const char *old_msgs, unsigned long old_len,
-		const char *new_msgs, unsigned long new_len);
+			  enum kmsg_dump_reason reason);
 
 static struct kmsg_dumper nvram_kmsg_dumper = {
 	.dump = oops_to_nvram
@@ -504,28 +502,6 @@ int __init pSeries_nvram_init(void)
 }
 
 /*
- * Try to capture the last capture_len bytes of the printk buffer.  Return
- * the amount actually captured.
- */
-static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
-				const char *new_msgs, size_t new_len,
-				char *captured, size_t capture_len)
-{
-	if (new_len >= capture_len) {
-		memcpy(captured, new_msgs + (new_len - capture_len),
-								capture_len);
-		return capture_len;
-	} else {
-		/* Grab the end of old_msgs. */
-		size_t old_tail_len = min(old_len, capture_len - new_len);
-		memcpy(captured, old_msgs + (old_len - old_tail_len),
-								old_tail_len);
-		memcpy(captured + old_tail_len, new_msgs, new_len);
-		return old_tail_len + new_len;
-	}
-}
-
-/*
  * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
  * would logging this oops/panic overwrite an RTAS event that rtas_errd
  * hasn't had a chance to read and process?  Return 1 if so, else 0.
@@ -541,27 +517,6 @@ static int clobbering_unread_rtas_event(
 						NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* Squeeze out each line's <n> severity prefix. */
-static size_t elide_severities(char *buf, size_t len)
-{
-	char *in, *out, *buf_end = buf + len;
-	/* Assume a <n> at the very beginning marks the start of a line. */
-	int newline = 1;
-
-	in = out = buf;
-	while (in < buf_end) {
-		if (newline && in+3 <= buf_end &&
-				*in == '<' && isdigit(in[1]) && in[2] == '>') {
-			in += 3;
-			newline = 0;
-		} else {
-			newline = (*in == '\n');
-			*out++ = *in++;
-		}
-	}
-	return out - buf;
-}
-
 /* Derived from logfs_compress() */
 static int nvram_compress(const void *in, void *out, size_t inlen,
 							size_t outlen)
@@ -619,9 +574,7 @@ static int zip_oops(size_t text_len)
  * partition.  If that's too much, go back and capture uncompressed text.
  */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason,
-		const char *old_msgs, unsigned long old_len,
-		const char *new_msgs, unsigned long new_len)
+			  enum kmsg_dump_reason reason)
 {
 	static unsigned int oops_count = 0;
 	static bool panicking = false;
@@ -660,14 +613,14 @@ static void oops_to_nvram(struct kmsg_du
 		return;
 
 	if (big_oops_buf) {
-		text_len = capture_last_msgs(old_msgs, old_len,
-			new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
-		text_len = elide_severities(big_oops_buf, text_len);
+		kmsg_dump_get_buffer(dumper, false,
+				     big_oops_buf, big_oops_buf_sz, &text_len);
 		rc = zip_oops(text_len);
 	}
 	if (rc != 0) {
-		text_len = capture_last_msgs(old_msgs, old_len,
-				new_msgs, new_len, oops_data, oops_data_sz);
+		kmsg_dump_rewind(dumper);
+		kmsg_dump_get_buffer(dumper, true,
+				     oops_data, oops_data_sz, &text_len);
 		err_type = ERR_TYPE_KERNEL_PANIC;
 		*oops_len = (u16) text_len;
 	}
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/mrst/early_printk_mrst.c
@@ -110,19 +110,16 @@ static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
 
 static void dw_kmsg_dump(struct kmsg_dumper *dumper,
-			enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2)
+			 enum kmsg_dump_reason reason)
 {
-	int i;
+	static char line[1024];
+	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
 	mrst_early_console_init();
 
-	for (i = 0; i < l1; i++)
-		early_mrst_console.write(&early_mrst_console, s1 + i, 1);
-	for (i = 0; i < l2; i++)
-		early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
+		early_mrst_console.write(&early_mrst_console, line, len);
 }
 
 /* Set the ratio rate to 115200, 8n1, IRQ disabled */
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -304,32 +304,17 @@ static void find_next_position(struct mt
 }
 
 static void mtdoops_do_dump(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
-		const char *s2, unsigned long l2)
+			    enum kmsg_dump_reason reason)
 {
 	struct mtdoops_context *cxt = container_of(dumper,
 			struct mtdoops_context, dump);
-	unsigned long s1_start, s2_start;
-	unsigned long l1_cpy, l2_cpy;
-	char *dst;
-
-	if (reason != KMSG_DUMP_OOPS &&
-	    reason != KMSG_DUMP_PANIC)
-		return;
 
 	/* Only dump oopses if dump_oops is set */
 	if (reason == KMSG_DUMP_OOPS && !dump_oops)
 		return;
 
-	dst = cxt->oops_buf + MTDOOPS_HEADER_SIZE; /* Skip the header */
-	l2_cpy = min(l2, record_size - MTDOOPS_HEADER_SIZE);
-	l1_cpy = min(l1, record_size - MTDOOPS_HEADER_SIZE - l2_cpy);
-
-	s2_start = l2 - l2_cpy;
-	s1_start = l1 - l1_cpy;
-
-	memcpy(dst, s1 + s1_start, l1_cpy);
-	memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
+	kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
+			     record_size - MTDOOPS_HEADER_SIZE, NULL);
 
 	/* Panics must be written immediately */
 	if (reason != KMSG_DUMP_OOPS)
@@ -375,6 +360,7 @@ static void mtdoops_notify_add(struct mt
 		return;
 	}
 
+	cxt->dump.max_reason = KMSG_DUMP_OOPS;
 	cxt->dump.dump = mtdoops_do_dump;
 	err = kmsg_dump_register(&cxt->dump);
 	if (err) {
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -94,20 +94,15 @@ static const char *get_reason_str(enum k
  * as we can from the end of the buffer.
  */
 static void pstore_dump(struct kmsg_dumper *dumper,
-	    enum kmsg_dump_reason reason,
-	    const char *s1, unsigned long l1,
-	    const char *s2, unsigned long l2)
+			enum kmsg_dump_reason reason)
 {
-	unsigned long	s1_start, s2_start;
-	unsigned long	l1_cpy, l2_cpy;
-	unsigned long	size, total = 0;
-	char		*dst;
+	unsigned long	total = 0;
 	const char	*why;
 	u64		id;
-	int		hsize, ret;
 	unsigned int	part = 1;
 	unsigned long	flags = 0;
 	int		is_locked = 0;
+	int		ret;
 
 	why = get_reason_str(reason);
 
@@ -119,30 +114,25 @@ static void pstore_dump(struct kmsg_dump
 		spin_lock_irqsave(&psinfo->buf_lock, flags);
 	oopscount++;
 	while (total < kmsg_bytes) {
+		char *dst;
+		unsigned long size;
+		int hsize;
+		size_t len;
+
 		dst = psinfo->buf;
 		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
 		size = psinfo->bufsize - hsize;
 		dst += hsize;
 
-		l2_cpy = min(l2, size);
-		l1_cpy = min(l1, size - l2_cpy);
-
-		if (l1_cpy + l2_cpy == 0)
+		if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
 			break;
 
-		s2_start = l2 - l2_cpy;
-		s1_start = l1 - l1_cpy;
-
-		memcpy(dst, s1 + s1_start, l1_cpy);
-		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
-
 		ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
-				   hsize + l1_cpy + l2_cpy, psinfo);
+				    hsize + len, psinfo);
 		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 			pstore_new_entry = 1;
-		l1 -= l1_cpy;
-		l2 -= l2_cpy;
-		total += l1_cpy + l2_cpy;
+
+		total += hsize + len;
 		part++;
 	}
 	if (in_nmi()) {
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -21,6 +21,7 @@
  * is passed to the kernel.
  */
 enum kmsg_dump_reason {
+	KMSG_DUMP_UNDEF,
 	KMSG_DUMP_PANIC,
 	KMSG_DUMP_OOPS,
 	KMSG_DUMP_EMERG,
@@ -31,23 +32,37 @@ enum kmsg_dump_reason {
 
 /**
  * struct kmsg_dumper - kernel crash message dumper structure
- * @dump:	The callback which gets called on crashes. The buffer is passed
- * 		as two sections, where s1 (length l1) contains the older
- * 		messages and s2 (length l2) contains the newer.
  * @list:	Entry in the dumper list (private)
+ * @dump:	Call into dumping code which will retrieve the data with
+ * 		through the record iterator
+ * @max_reason:	filter for highest reason number that should be dumped
  * @registered:	Flag that specifies if this is already registered
  */
 struct kmsg_dumper {
-	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2);
 	struct list_head list;
-	int registered;
+	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+	enum kmsg_dump_reason max_reason;
+	bool active;
+	bool registered;
+
+	/* private state of the kmsg iterator */
+	u32 cur_idx;
+	u32 next_idx;
+	u64 cur_seq;
+	u64 next_seq;
 };
 
 #ifdef CONFIG_PRINTK
 void kmsg_dump(enum kmsg_dump_reason reason);
 
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			char *line, size_t size, size_t *len);
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			  char *buf, size_t size, size_t *len);
+
+void kmsg_dump_rewind(struct kmsg_dumper *dumper);
+
 int kmsg_dump_register(struct kmsg_dumper *dumper);
 
 int kmsg_dump_unregister(struct kmsg_dumper *dumper);
@@ -56,6 +71,22 @@ static inline void kmsg_dump(enum kmsg_d
 {
 }
 
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			  const char *line, size_t size, size_t *len)
+{
+	return false;
+}
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			    char *buf, size_t size, size_t *len)
+{
+	return false;
+}
+
+void kmsg_dump_rewind(struct kmsg_dumper *dumper)
+{
+}
+
 static inline int kmsg_dump_register(struct kmsg_dumper *dumper)
 {
 	return -EINVAL;
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -909,7 +909,7 @@ static int syslog_print_all(char __user
 		/*
 		 * Find first record that fits, including all following records,
 		 * into the user-provided buffer for this dump.
-		*/
+		 */
 		seq = clear_seq;
 		idx = clear_idx;
 		while (seq < log_next_seq) {
@@ -919,6 +919,8 @@ static int syslog_print_all(char __user
 			idx = log_next(idx);
 			seq++;
 		}
+
+		/* move first record forward until length fits into the buffer */
 		seq = clear_seq;
 		idx = clear_idx;
 		while (len > size && seq < log_next_seq) {
@@ -929,7 +931,7 @@ static int syslog_print_all(char __user
 			seq++;
 		}
 
-		/* last message in this dump */
+		/* last message fitting into this dump */
 		next_seq = log_next_seq;
 
 		len = 0;
@@ -2300,48 +2302,210 @@ module_param_named(always_kmsg_dump, alw
  * kmsg_dump - dump kernel log to kernel message dumpers.
  * @reason: the reason (oops, panic etc) for dumping
  *
- * Iterate through each of the dump devices and call the oops/panic
- * callbacks with the log buffer.
+ * Call each of the registered dumper's dump() callback, which can
+ * retrieve the kmsg records with kmsg_dump_get_line() or
+ * kmsg_dump_get_buffer().
  */
 void kmsg_dump(enum kmsg_dump_reason reason)
 {
-	u64 idx;
 	struct kmsg_dumper *dumper;
-	const char *s1, *s2;
-	unsigned long l1, l2;
 	unsigned long flags;
 
 	if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
 		return;
 
-	/* Theoretically, the log could move on after we do this, but
-	   there's not a lot we can do about that. The new messages
-	   will overwrite the start of what we dump. */
+	rcu_read_lock();
+	list_for_each_entry_rcu(dumper, &dump_list, list) {
+		if (dumper->max_reason && reason > dumper->max_reason)
+			continue;
+
+		/* 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);
+
+		/* invoke dumper which will iterate over records */
+		dumper->dump(dumper, reason);
+
+		/* reset iterator */
+		dumper->active = false;
+	}
+	rcu_read_unlock();
+}
+
+/**
+ * kmsg_dump_get_line - retrieve one kmsg log line
+ * @dumper: registered kmsg dumper
+ * @syslog: include the "<4>" prefixes
+ * @line: buffer to copy the line to
+ * @size: maximum size of the buffer
+ * @len: length of line placed into buffer
+ *
+ * Start at the beginning of the kmsg buffer, with the oldest kmsg
+ * record, and copy one record into the provided buffer.
+ *
+ * Consecutive calls will return the next available record moving
+ * towards the end of the buffer with the youngest messages.
+ *
+ * A return value of FALSE indicate that there are no more records to
+ * read.
+ */
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			char *line, size_t size, size_t *len)
+{
+	unsigned long flags;
+	struct log *msg;
+	size_t l = 0;
+	bool ret = false;
+
+	if (!dumper->active)
+		goto out;
 
 	raw_spin_lock_irqsave(&logbuf_lock, flags);
-	if (syslog_seq < log_first_seq)
-		idx = syslog_idx;
-	else
-		idx = log_first_idx;
-
-	if (idx > log_next_idx) {
-		s1 = log_buf;
-		l1 = log_next_idx;
+	if (dumper->cur_seq < log_first_seq) {
+		/* messages are gone, move to first available one */
+		dumper->cur_seq = log_first_seq;
+		dumper->cur_idx = log_first_idx;
+	}
 
-		s2 = log_buf + idx;
-		l2 = log_buf_len - idx;
-	} else {
-		s1 = "";
-		l1 = 0;
+	/* last entry */
+	if (dumper->cur_seq >= log_next_seq) {
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
 
-		s2 = log_buf + idx;
-		l2 = log_next_idx - idx;
+	msg = log_from_idx(dumper->cur_idx);
+	l = msg_print_text(msg, syslog,
+			      line, size);
+
+	dumper->cur_idx = log_next(dumper->cur_idx);
+	dumper->cur_seq++;
+	ret = true;
+	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+	if (len)
+		*len = l;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
+
+/**
+ * kmsg_dump_get_buffer - copy kmsg log lines
+ * @dumper: registered kmsg dumper
+ * @syslog: include the "<4>" prefixes
+ * @line: buffer to copy the line to
+ * @size: maximum size of the buffer
+ * @len: length of line placed into buffer
+ *
+ * Start at the end of the kmsg buffer and fill the provided buffer
+ * with as many of the the *youngest* kmsg records that fit into it.
+ * If the buffer is large enough, all available kmsg records will be
+ * copied with a single call.
+ *
+ * Consecutive calls will fill the buffer with the next block of
+ * available older records, not including the earlier retrieved ones.
+ *
+ * A return value of FALSE indicate that there are no more records to
+ * read.
+ */
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			  char *buf, size_t size, size_t *len)
+{
+	unsigned long flags;
+	u64 seq;
+	u32 idx;
+	u64 next_seq;
+	u32 next_idx;
+	size_t l = 0;
+	bool ret = false;
+
+	if (!dumper->active)
+		goto out;
+
+	raw_spin_lock_irqsave(&logbuf_lock, flags);
+	if (dumper->cur_seq < log_first_seq) {
+		/* messages are gone, move to first available one */
+		dumper->cur_seq = log_first_seq;
+		dumper->cur_idx = log_first_idx;
+	}
+
+	/* last entry */
+	if (dumper->cur_seq >= dumper->next_seq) {
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
+
+	/* calculate length of entire buffer */
+	seq = dumper->cur_seq;
+	idx = dumper->cur_idx;
+	while (seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l += msg_print_text(msg, true, NULL, 0);
+		idx = log_next(idx);
+		seq++;
+	}
+
+	/* move first record forward until length fits into the buffer */
+	seq = dumper->cur_seq;
+	idx = dumper->cur_idx;
+	while (l > size && seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l -= msg_print_text(msg, true, NULL, 0);
+		idx = log_next(idx);
+		seq++;
+	}
+
+	/* last message in next interation */
+	next_seq = seq;
+	next_idx = idx;
+
+	l = 0;
+	while (seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l += msg_print_text(msg, syslog,
+				    buf + l, size - l);
+
+		idx = log_next(idx);
+		seq++;
 	}
+
+	dumper->next_seq = next_seq;
+	dumper->next_idx = next_idx;
+	ret = true;
 	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+	if (len)
+		*len = l;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(dumper, &dump_list, list)
-		dumper->dump(dumper, reason, s1, l1, s2, l2);
-	rcu_read_unlock();
+/**
+ * kmsg_dump_rewind - reset the interator
+ * @dumper: registered kmsg dumper
+ *
+ * Reset the dumper's iterator so that kmsg_dump_get_line() and
+ * kmsg_dump_get_buffer() can be called again and used multiple
+ * times within the same dumper.dump() callback.
+ */
+void kmsg_dump_rewind(struct kmsg_dumper *dumper)
+{
+	unsigned long flags;
+
+	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);
 }
+EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
 #endif



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 16:07     ` Kay Sievers
  2012-05-29 16:14       ` Joe Perches
  2012-05-29 17:11       ` Luck, Tony
@ 2012-06-06  6:33       ` Greg Kroah-Hartmann
  2012-06-15  0:04       ` Greg KH
  3 siblings, 0 replies; 100+ messages in thread
From: Greg Kroah-Hartmann @ 2012-06-06  6:33 UTC (permalink / raw)
  To: Anton Vorontsov
  Cc: Linus Torvalds, Ingo Molnar, linux-kernel, Kees Cook,
	Colin Cross, Tony Luck, John Stultz, Kay Sievers

On Tue, May 29, 2012 at 06:07:00PM +0200, Kay Sievers wrote:
> On Sun, 2012-05-27 at 16:23 +0200, Kay Sievers wrote:
> > On Sat, May 26, 2012 at 1:11 PM, Anton Vorontsov <anton.vorontsov@linaro.org> wrote:
> 
> > > So, starting from this patch every kmsg_dump user is getting the
> > > binary stuff, which is barely usable, and breaks a longstanding
> > > user-visible ABIs (e.g. mtdoops, oops dumping into nvram on PowerPC,
> > > and ramoops of course).
> > 
> > These cases export their own format, it's just that the dump routines
> > could copy the buffer in only two steps (beginning and end of the ring
> > buffer), while in the future their code would need an update to copy
> > it record for record now. The exported format in the dump does not
> > necessarily need to change.
> 
> Here is an untested patch, which should restore the old plain text
> export format of the kmsg buffer. I adds an iterator to the dumper
> routine, which can be used by the dumper to properly copy the data out
> of the kmsg record buffer. All current users are converted in the same
> patch.
> 
> Any feedback/help in testing/updating and getting this thing into a
> mergeable state would be greatly appreciated.

Any comments on this patch?  Did anyone try it out?  I want to merge it
now, so unless someone objects, will do so soon.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-29 16:07     ` Kay Sievers
                         ` (2 preceding siblings ...)
  2012-06-06  6:33       ` Greg Kroah-Hartmann
@ 2012-06-15  0:04       ` Greg KH
  2012-06-15  1:31         ` Anton Vorontsov
  2012-06-15 12:07         ` Kay Sievers
  3 siblings, 2 replies; 100+ messages in thread
From: Greg KH @ 2012-06-15  0:04 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Anton Vorontsov, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

On Tue, May 29, 2012 at 06:07:00PM +0200, Kay Sievers wrote:
> On Sun, 2012-05-27 at 16:23 +0200, Kay Sievers wrote:
> > On Sat, May 26, 2012 at 1:11 PM, Anton Vorontsov <anton.vorontsov@linaro.org> wrote:
> 
> > > So, starting from this patch every kmsg_dump user is getting the
> > > binary stuff, which is barely usable, and breaks a longstanding
> > > user-visible ABIs (e.g. mtdoops, oops dumping into nvram on PowerPC,
> > > and ramoops of course).
> > 
> > These cases export their own format, it's just that the dump routines
> > could copy the buffer in only two steps (beginning and end of the ring
> > buffer), while in the future their code would need an update to copy
> > it record for record now. The exported format in the dump does not
> > necessarily need to change.
> 
> Here is an untested patch, which should restore the old plain text
> export format of the kmsg buffer. I adds an iterator to the dumper
> routine, which can be used by the dumper to properly copy the data out
> of the kmsg record buffer. All current users are converted in the same
> patch.
> 
> Any feedback/help in testing/updating and getting this thing into a
> mergeable state would be greatly appreciated.
> 
> There are two versions of the iterator:
> kmsg_dump_get_line() starts with the oldest records. With the next call,
> the iterator retrieves one line after the other. Useful for cases like
> printing to a console or any other stream device.
> 
> kmsg_dump_get_buffer() fills a buffer with as many of the youngest
> records as fit into it. With the next call, the iterator retrieves the
> next block of older messages. Useful to dump the entire buffer with one
> shot, or chunk the data into blocks and store them, with the youngest
> messages being the most important, retrieved first.
> 
> Unlike the old logic, there are no stale pointers handed out to the
> dumper, if case things get overwritten while a dump is in progress,
> lines are not truncated or overwritten.

As no one seems to have responded, care to resend this with a
signed-off-by so I can queue it up for 3.6?  If people complain, it can
still go to 3.5, but given that no one is saying anything, I guess no
one cares...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-06-15  0:04       ` Greg KH
@ 2012-06-15  1:31         ` Anton Vorontsov
  2012-06-15 12:07         ` Kay Sievers
  1 sibling, 0 replies; 100+ messages in thread
From: Anton Vorontsov @ 2012-06-15  1:31 UTC (permalink / raw)
  To: Greg KH
  Cc: Kay Sievers, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

On Thu, Jun 14, 2012 at 05:04:22PM -0700, Greg KH wrote:
[...]
> > Unlike the old logic, there are no stale pointers handed out to the
> > dumper, if case things get overwritten while a dump is in progress,
> > lines are not truncated or overwritten.
> 
> As no one seems to have responded, care to resend this with a
> signed-off-by so I can queue it up for 3.6?  If people complain, it can
> still go to 3.5, but given that no one is saying anything, I guess no
> one cares...

Well, I do care. Just didn't find time to test it. I'll try to speed
myself up.

Thanks,

-- 
Anton Vorontsov
Email: cbouatmailru@gmail.com

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-06-15  0:04       ` Greg KH
  2012-06-15  1:31         ` Anton Vorontsov
@ 2012-06-15 12:07         ` Kay Sievers
  2012-06-15 12:23           ` Ingo Molnar
                             ` (2 more replies)
  1 sibling, 3 replies; 100+ messages in thread
From: Kay Sievers @ 2012-06-15 12:07 UTC (permalink / raw)
  To: Greg KH
  Cc: Anton Vorontsov, Linus Torvalds, Ingo Molnar, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

On Thu, 2012-06-14 at 17:04 -0700, Greg KH wrote:

> As no one seems to have responded, care to resend this with a
> signed-off-by so I can queue it up for 3.6?  If people complain, it can
> still go to 3.5, but given that no one is saying anything, I guess no
> one cares...

Sounds like a good plan. Here it is.

Thanks,
Kay


From: Kay Sievers <kay@vrfy.org>
Subject: kmsg - kmsg_dump() use iterator to receice log buffer content

Provide an iterator to receive the log buffer content, and convert all
kmsg_dump() user to it.

The structured data in the kmsg buffer now contains binary data, which
should no longer be copied verbatim to the kmsg_dump() users.

The iterator should provide reliable access to the buffer data, and also
supports proper log line-aware chunking of data while iterating.

Signed-off-by: Kay Sievers <kay@vrfy.org>
---
 arch/powerpc/platforms/pseries/nvram.c     |   61 -------
 arch/x86/platform/mrst/early_printk_mrst.c |   13 -
 drivers/mtd/mtdoops.c                      |   22 --
 fs/pstore/platform.c                       |   34 +---
 include/linux/kmsg_dump.h                  |   45 ++++-
 kernel/printk.c                            |  222 +++++++++++++++++++++++++----
 6 files changed, 259 insertions(+), 138 deletions(-)

--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -68,9 +68,7 @@ static const char *pseries_nvram_os_part
 };
 
 static void oops_to_nvram(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason,
-		const char *old_msgs, unsigned long old_len,
-		const char *new_msgs, unsigned long new_len);
+			  enum kmsg_dump_reason reason);
 
 static struct kmsg_dumper nvram_kmsg_dumper = {
 	.dump = oops_to_nvram
@@ -504,28 +502,6 @@ int __init pSeries_nvram_init(void)
 }
 
 /*
- * Try to capture the last capture_len bytes of the printk buffer.  Return
- * the amount actually captured.
- */
-static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
-				const char *new_msgs, size_t new_len,
-				char *captured, size_t capture_len)
-{
-	if (new_len >= capture_len) {
-		memcpy(captured, new_msgs + (new_len - capture_len),
-								capture_len);
-		return capture_len;
-	} else {
-		/* Grab the end of old_msgs. */
-		size_t old_tail_len = min(old_len, capture_len - new_len);
-		memcpy(captured, old_msgs + (old_len - old_tail_len),
-								old_tail_len);
-		memcpy(captured + old_tail_len, new_msgs, new_len);
-		return old_tail_len + new_len;
-	}
-}
-
-/*
  * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
  * would logging this oops/panic overwrite an RTAS event that rtas_errd
  * hasn't had a chance to read and process?  Return 1 if so, else 0.
@@ -541,27 +517,6 @@ static int clobbering_unread_rtas_event(
 						NVRAM_RTAS_READ_TIMEOUT);
 }
 
-/* Squeeze out each line's <n> severity prefix. */
-static size_t elide_severities(char *buf, size_t len)
-{
-	char *in, *out, *buf_end = buf + len;
-	/* Assume a <n> at the very beginning marks the start of a line. */
-	int newline = 1;
-
-	in = out = buf;
-	while (in < buf_end) {
-		if (newline && in+3 <= buf_end &&
-				*in == '<' && isdigit(in[1]) && in[2] == '>') {
-			in += 3;
-			newline = 0;
-		} else {
-			newline = (*in == '\n');
-			*out++ = *in++;
-		}
-	}
-	return out - buf;
-}
-
 /* Derived from logfs_compress() */
 static int nvram_compress(const void *in, void *out, size_t inlen,
 							size_t outlen)
@@ -619,9 +574,7 @@ static int zip_oops(size_t text_len)
  * partition.  If that's too much, go back and capture uncompressed text.
  */
 static void oops_to_nvram(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason,
-		const char *old_msgs, unsigned long old_len,
-		const char *new_msgs, unsigned long new_len)
+			  enum kmsg_dump_reason reason)
 {
 	static unsigned int oops_count = 0;
 	static bool panicking = false;
@@ -660,14 +613,14 @@ static void oops_to_nvram(struct kmsg_du
 		return;
 
 	if (big_oops_buf) {
-		text_len = capture_last_msgs(old_msgs, old_len,
-			new_msgs, new_len, big_oops_buf, big_oops_buf_sz);
-		text_len = elide_severities(big_oops_buf, text_len);
+		kmsg_dump_get_buffer(dumper, false,
+				     big_oops_buf, big_oops_buf_sz, &text_len);
 		rc = zip_oops(text_len);
 	}
 	if (rc != 0) {
-		text_len = capture_last_msgs(old_msgs, old_len,
-				new_msgs, new_len, oops_data, oops_data_sz);
+		kmsg_dump_rewind(dumper);
+		kmsg_dump_get_buffer(dumper, true,
+				     oops_data, oops_data_sz, &text_len);
 		err_type = ERR_TYPE_KERNEL_PANIC;
 		*oops_len = (u16) text_len;
 	}
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/mrst/early_printk_mrst.c
@@ -110,19 +110,16 @@ static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
 
 static void dw_kmsg_dump(struct kmsg_dumper *dumper,
-			enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2)
+			 enum kmsg_dump_reason reason)
 {
-	int i;
+	static char line[1024];
+	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
 	mrst_early_console_init();
 
-	for (i = 0; i < l1; i++)
-		early_mrst_console.write(&early_mrst_console, s1 + i, 1);
-	for (i = 0; i < l2; i++)
-		early_mrst_console.write(&early_mrst_console, s2 + i, 1);
+	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
+		early_mrst_console.write(&early_mrst_console, line, len);
 }
 
 /* Set the ratio rate to 115200, 8n1, IRQ disabled */
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -304,32 +304,17 @@ static void find_next_position(struct mt
 }
 
 static void mtdoops_do_dump(struct kmsg_dumper *dumper,
-		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
-		const char *s2, unsigned long l2)
+			    enum kmsg_dump_reason reason)
 {
 	struct mtdoops_context *cxt = container_of(dumper,
 			struct mtdoops_context, dump);
-	unsigned long s1_start, s2_start;
-	unsigned long l1_cpy, l2_cpy;
-	char *dst;
-
-	if (reason != KMSG_DUMP_OOPS &&
-	    reason != KMSG_DUMP_PANIC)
-		return;
 
 	/* Only dump oopses if dump_oops is set */
 	if (reason == KMSG_DUMP_OOPS && !dump_oops)
 		return;
 
-	dst = cxt->oops_buf + MTDOOPS_HEADER_SIZE; /* Skip the header */
-	l2_cpy = min(l2, record_size - MTDOOPS_HEADER_SIZE);
-	l1_cpy = min(l1, record_size - MTDOOPS_HEADER_SIZE - l2_cpy);
-
-	s2_start = l2 - l2_cpy;
-	s1_start = l1 - l1_cpy;
-
-	memcpy(dst, s1 + s1_start, l1_cpy);
-	memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
+	kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
+			     record_size - MTDOOPS_HEADER_SIZE, NULL);
 
 	/* Panics must be written immediately */
 	if (reason != KMSG_DUMP_OOPS)
@@ -375,6 +360,7 @@ static void mtdoops_notify_add(struct mt
 		return;
 	}
 
+	cxt->dump.max_reason = KMSG_DUMP_OOPS;
 	cxt->dump.dump = mtdoops_do_dump;
 	err = kmsg_dump_register(&cxt->dump);
 	if (err) {
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -94,20 +94,15 @@ static const char *get_reason_str(enum k
  * as we can from the end of the buffer.
  */
 static void pstore_dump(struct kmsg_dumper *dumper,
-	    enum kmsg_dump_reason reason,
-	    const char *s1, unsigned long l1,
-	    const char *s2, unsigned long l2)
+			enum kmsg_dump_reason reason)
 {
-	unsigned long	s1_start, s2_start;
-	unsigned long	l1_cpy, l2_cpy;
-	unsigned long	size, total = 0;
-	char		*dst;
+	unsigned long	total = 0;
 	const char	*why;
 	u64		id;
-	int		hsize, ret;
 	unsigned int	part = 1;
 	unsigned long	flags = 0;
 	int		is_locked = 0;
+	int		ret;
 
 	why = get_reason_str(reason);
 
@@ -119,30 +114,25 @@ static void pstore_dump(struct kmsg_dump
 		spin_lock_irqsave(&psinfo->buf_lock, flags);
 	oopscount++;
 	while (total < kmsg_bytes) {
+		char *dst;
+		unsigned long size;
+		int hsize;
+		size_t len;
+
 		dst = psinfo->buf;
 		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
 		size = psinfo->bufsize - hsize;
 		dst += hsize;
 
-		l2_cpy = min(l2, size);
-		l1_cpy = min(l1, size - l2_cpy);
-
-		if (l1_cpy + l2_cpy == 0)
+		if (!kmsg_dump_get_buffer(dumper, true, dst, size, &len))
 			break;
 
-		s2_start = l2 - l2_cpy;
-		s1_start = l1 - l1_cpy;
-
-		memcpy(dst, s1 + s1_start, l1_cpy);
-		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
-
 		ret = psinfo->write(PSTORE_TYPE_DMESG, reason, &id, part,
-				   hsize + l1_cpy + l2_cpy, psinfo);
+				    hsize + len, psinfo);
 		if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 			pstore_new_entry = 1;
-		l1 -= l1_cpy;
-		l2 -= l2_cpy;
-		total += l1_cpy + l2_cpy;
+
+		total += hsize + len;
 		part++;
 	}
 	if (in_nmi()) {
--- a/include/linux/kmsg_dump.h
+++ b/include/linux/kmsg_dump.h
@@ -21,6 +21,7 @@
  * is passed to the kernel.
  */
 enum kmsg_dump_reason {
+	KMSG_DUMP_UNDEF,
 	KMSG_DUMP_PANIC,
 	KMSG_DUMP_OOPS,
 	KMSG_DUMP_EMERG,
@@ -31,23 +32,37 @@ enum kmsg_dump_reason {
 
 /**
  * struct kmsg_dumper - kernel crash message dumper structure
- * @dump:	The callback which gets called on crashes. The buffer is passed
- * 		as two sections, where s1 (length l1) contains the older
- * 		messages and s2 (length l2) contains the newer.
  * @list:	Entry in the dumper list (private)
+ * @dump:	Call into dumping code which will retrieve the data with
+ * 		through the record iterator
+ * @max_reason:	filter for highest reason number that should be dumped
  * @registered:	Flag that specifies if this is already registered
  */
 struct kmsg_dumper {
-	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason,
-			const char *s1, unsigned long l1,
-			const char *s2, unsigned long l2);
 	struct list_head list;
-	int registered;
+	void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+	enum kmsg_dump_reason max_reason;
+	bool active;
+	bool registered;
+
+	/* private state of the kmsg iterator */
+	u32 cur_idx;
+	u32 next_idx;
+	u64 cur_seq;
+	u64 next_seq;
 };
 
 #ifdef CONFIG_PRINTK
 void kmsg_dump(enum kmsg_dump_reason reason);
 
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			char *line, size_t size, size_t *len);
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			  char *buf, size_t size, size_t *len);
+
+void kmsg_dump_rewind(struct kmsg_dumper *dumper);
+
 int kmsg_dump_register(struct kmsg_dumper *dumper);
 
 int kmsg_dump_unregister(struct kmsg_dumper *dumper);
@@ -56,6 +71,22 @@ static inline void kmsg_dump(enum kmsg_d
 {
 }
 
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			  const char *line, size_t size, size_t *len)
+{
+	return false;
+}
+
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			    char *buf, size_t size, size_t *len)
+{
+	return false;
+}
+
+void kmsg_dump_rewind(struct kmsg_dumper *dumper)
+{
+}
+
 static inline int kmsg_dump_register(struct kmsg_dumper *dumper)
 {
 	return -EINVAL;
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -909,7 +909,7 @@ static int syslog_print_all(char __user
 		/*
 		 * Find first record that fits, including all following records,
 		 * into the user-provided buffer for this dump.
-		*/
+		 */
 		seq = clear_seq;
 		idx = clear_idx;
 		while (seq < log_next_seq) {
@@ -919,6 +919,8 @@ static int syslog_print_all(char __user
 			idx = log_next(idx);
 			seq++;
 		}
+
+		/* move first record forward until length fits into the buffer */
 		seq = clear_seq;
 		idx = clear_idx;
 		while (len > size && seq < log_next_seq) {
@@ -929,7 +931,7 @@ static int syslog_print_all(char __user
 			seq++;
 		}
 
-		/* last message in this dump */
+		/* last message fitting into this dump */
 		next_seq = log_next_seq;
 
 		len = 0;
@@ -2300,48 +2302,210 @@ module_param_named(always_kmsg_dump, alw
  * kmsg_dump - dump kernel log to kernel message dumpers.
  * @reason: the reason (oops, panic etc) for dumping
  *
- * Iterate through each of the dump devices and call the oops/panic
- * callbacks with the log buffer.
+ * Call each of the registered dumper's dump() callback, which can
+ * retrieve the kmsg records with kmsg_dump_get_line() or
+ * kmsg_dump_get_buffer().
  */
 void kmsg_dump(enum kmsg_dump_reason reason)
 {
-	u64 idx;
 	struct kmsg_dumper *dumper;
-	const char *s1, *s2;
-	unsigned long l1, l2;
 	unsigned long flags;
 
 	if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
 		return;
 
-	/* Theoretically, the log could move on after we do this, but
-	   there's not a lot we can do about that. The new messages
-	   will overwrite the start of what we dump. */
+	rcu_read_lock();
+	list_for_each_entry_rcu(dumper, &dump_list, list) {
+		if (dumper->max_reason && reason > dumper->max_reason)
+			continue;
+
+		/* 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);
+
+		/* invoke dumper which will iterate over records */
+		dumper->dump(dumper, reason);
+
+		/* reset iterator */
+		dumper->active = false;
+	}
+	rcu_read_unlock();
+}
+
+/**
+ * kmsg_dump_get_line - retrieve one kmsg log line
+ * @dumper: registered kmsg dumper
+ * @syslog: include the "<4>" prefixes
+ * @line: buffer to copy the line to
+ * @size: maximum size of the buffer
+ * @len: length of line placed into buffer
+ *
+ * Start at the beginning of the kmsg buffer, with the oldest kmsg
+ * record, and copy one record into the provided buffer.
+ *
+ * Consecutive calls will return the next available record moving
+ * towards the end of the buffer with the youngest messages.
+ *
+ * A return value of FALSE indicate that there are no more records to
+ * read.
+ */
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+			char *line, size_t size, size_t *len)
+{
+	unsigned long flags;
+	struct log *msg;
+	size_t l = 0;
+	bool ret = false;
+
+	if (!dumper->active)
+		goto out;
 
 	raw_spin_lock_irqsave(&logbuf_lock, flags);
-	if (syslog_seq < log_first_seq)
-		idx = syslog_idx;
-	else
-		idx = log_first_idx;
-
-	if (idx > log_next_idx) {
-		s1 = log_buf;
-		l1 = log_next_idx;
+	if (dumper->cur_seq < log_first_seq) {
+		/* messages are gone, move to first available one */
+		dumper->cur_seq = log_first_seq;
+		dumper->cur_idx = log_first_idx;
+	}
 
-		s2 = log_buf + idx;
-		l2 = log_buf_len - idx;
-	} else {
-		s1 = "";
-		l1 = 0;
+	/* last entry */
+	if (dumper->cur_seq >= log_next_seq) {
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
 
-		s2 = log_buf + idx;
-		l2 = log_next_idx - idx;
+	msg = log_from_idx(dumper->cur_idx);
+	l = msg_print_text(msg, syslog,
+			      line, size);
+
+	dumper->cur_idx = log_next(dumper->cur_idx);
+	dumper->cur_seq++;
+	ret = true;
+	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+	if (len)
+		*len = l;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
+
+/**
+ * kmsg_dump_get_buffer - copy kmsg log lines
+ * @dumper: registered kmsg dumper
+ * @syslog: include the "<4>" prefixes
+ * @line: buffer to copy the line to
+ * @size: maximum size of the buffer
+ * @len: length of line placed into buffer
+ *
+ * Start at the end of the kmsg buffer and fill the provided buffer
+ * with as many of the the *youngest* kmsg records that fit into it.
+ * If the buffer is large enough, all available kmsg records will be
+ * copied with a single call.
+ *
+ * Consecutive calls will fill the buffer with the next block of
+ * available older records, not including the earlier retrieved ones.
+ *
+ * A return value of FALSE indicate that there are no more records to
+ * read.
+ */
+bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
+			  char *buf, size_t size, size_t *len)
+{
+	unsigned long flags;
+	u64 seq;
+	u32 idx;
+	u64 next_seq;
+	u32 next_idx;
+	size_t l = 0;
+	bool ret = false;
+
+	if (!dumper->active)
+		goto out;
+
+	raw_spin_lock_irqsave(&logbuf_lock, flags);
+	if (dumper->cur_seq < log_first_seq) {
+		/* messages are gone, move to first available one */
+		dumper->cur_seq = log_first_seq;
+		dumper->cur_idx = log_first_idx;
+	}
+
+	/* last entry */
+	if (dumper->cur_seq >= dumper->next_seq) {
+		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
+
+	/* calculate length of entire buffer */
+	seq = dumper->cur_seq;
+	idx = dumper->cur_idx;
+	while (seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l += msg_print_text(msg, true, NULL, 0);
+		idx = log_next(idx);
+		seq++;
+	}
+
+	/* move first record forward until length fits into the buffer */
+	seq = dumper->cur_seq;
+	idx = dumper->cur_idx;
+	while (l > size && seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l -= msg_print_text(msg, true, NULL, 0);
+		idx = log_next(idx);
+		seq++;
+	}
+
+	/* last message in next interation */
+	next_seq = seq;
+	next_idx = idx;
+
+	l = 0;
+	while (seq < dumper->next_seq) {
+		struct log *msg = log_from_idx(idx);
+
+		l += msg_print_text(msg, syslog,
+				    buf + l, size - l);
+
+		idx = log_next(idx);
+		seq++;
 	}
+
+	dumper->next_seq = next_seq;
+	dumper->next_idx = next_idx;
+	ret = true;
 	raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+out:
+	if (len)
+		*len = l;
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(dumper, &dump_list, list)
-		dumper->dump(dumper, reason, s1, l1, s2, l2);
-	rcu_read_unlock();
+/**
+ * kmsg_dump_rewind - reset the interator
+ * @dumper: registered kmsg dumper
+ *
+ * Reset the dumper's iterator so that kmsg_dump_get_line() and
+ * kmsg_dump_get_buffer() can be called again and used multiple
+ * times within the same dumper.dump() callback.
+ */
+void kmsg_dump_rewind(struct kmsg_dumper *dumper)
+{
+	unsigned long flags;
+
+	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);
 }
+EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
 #endif



^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-06-15 12:07         ` Kay Sievers
@ 2012-06-15 12:23           ` Ingo Molnar
  2012-06-15 21:53             ` Greg KH
  2012-06-15 12:23           ` Anton Vorontsov
  2012-06-15 20:54           ` Tony Luck
  2 siblings, 1 reply; 100+ messages in thread
From: Ingo Molnar @ 2012-06-15 12:23 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg KH, Anton Vorontsov, Linus Torvalds, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz


* Kay Sievers <kay@vrfy.org> wrote:

> On Thu, 2012-06-14 at 17:04 -0700, Greg KH wrote:
> 
> > As no one seems to have responded, care to resend this with a
> > signed-off-by so I can queue it up for 3.6?  If people complain, it can
> > still go to 3.5, but given that no one is saying anything, I guess no
> > one cares...
> 
> Sounds like a good plan. Here it is.
> 
> Thanks,
> Kay
> 
> 
> From: Kay Sievers <kay@vrfy.org>
> Subject: kmsg - kmsg_dump() use iterator to receice log buffer content

typo.

> 
> Provide an iterator to receive the log buffer content, and convert all
> kmsg_dump() user to it.

typo.

> +/**
> + * kmsg_dump_get_line - retrieve one kmsg log line
> + * @dumper: registered kmsg dumper
> + * @syslog: include the "<4>" prefixes
> + * @line: buffer to copy the line to
> + * @size: maximum size of the buffer
> + * @len: length of line placed into buffer
> + *
> + * Start at the beginning of the kmsg buffer, with the oldest kmsg
> + * record, and copy one record into the provided buffer.
> + *
> + * Consecutive calls will return the next available record moving
> + * towards the end of the buffer with the youngest messages.
> + *
> + * A return value of FALSE indicate that there are no more records to
> + * read.

typo.

> + *
> + * Start at the end of the kmsg buffer and fill the provided buffer
> + * with as many of the the *youngest* kmsg records that fit into it.
> + * If the buffer is large enough, all available kmsg records will be
> + * copied with a single call.
> + *
> + * Consecutive calls will fill the buffer with the next block of
> + * available older records, not including the earlier retrieved ones.
> + *
> + * A return value of FALSE indicate that there are no more records to
> + * read.

typo.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-06-15 12:07         ` Kay Sievers
  2012-06-15 12:23           ` Ingo Molnar
@ 2012-06-15 12:23           ` Anton Vorontsov
  2012-06-15 20:54           ` Tony Luck
  2 siblings, 0 replies; 100+ messages in thread
From: Anton Vorontsov @ 2012-06-15 12:23 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg KH, Linus Torvalds, Ingo Molnar, linux-kernel, Kees Cook,
	Colin Cross, Tony Luck, John Stultz

On Fri, Jun 15, 2012 at 02:07:51PM +0200, Kay Sievers wrote:
[...]
> From: Kay Sievers <kay@vrfy.org>
> Subject: kmsg - kmsg_dump() use iterator to receice log buffer content
> 
> Provide an iterator to receive the log buffer content, and convert all
> kmsg_dump() user to it.
> 
> The structured data in the kmsg buffer now contains binary data, which
> should no longer be copied verbatim to the kmsg_dump() users.
> 
> The iterator should provide reliable access to the buffer data, and also
> supports proper log line-aware chunking of data while iterating.
> 
> Signed-off-by: Kay Sievers <kay@vrfy.org>

Thanks Kay, it works!

Reported-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Tested-by: Anton Vorontsov <anton.vorontsov@linaro.org>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-06-15 12:07         ` Kay Sievers
  2012-06-15 12:23           ` Ingo Molnar
  2012-06-15 12:23           ` Anton Vorontsov
@ 2012-06-15 20:54           ` Tony Luck
  2 siblings, 0 replies; 100+ messages in thread
From: Tony Luck @ 2012-06-15 20:54 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg KH, Anton Vorontsov, Linus Torvalds, Ingo Molnar,
	linux-kernel, Kees Cook, Colin Cross, John Stultz

On Fri, Jun 15, 2012 at 5:07 AM, Kay Sievers <kay@vrfy.org> wrote:
> On Thu, 2012-06-14 at 17:04 -0700, Greg KH wrote:
>
>> As no one seems to have responded, care to resend this with a
>> signed-off-by so I can queue it up for 3.6?  If people complain, it can
>> still go to 3.5, but given that no one is saying anything, I guess no
>> one cares...
>
> Sounds like a good plan. Here it is.

This got squeezed out of my TODO list ... sorry.  pstore bits work fine. I'd
like to see this go into 3.5.

Thanks

Tested-by: Tony Luck <tony.luck@intel.com>

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-06-15 12:23           ` Ingo Molnar
@ 2012-06-15 21:53             ` Greg KH
  0 siblings, 0 replies; 100+ messages in thread
From: Greg KH @ 2012-06-15 21:53 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Kay Sievers, Anton Vorontsov, Linus Torvalds, linux-kernel,
	Kees Cook, Colin Cross, Tony Luck, John Stultz

On Fri, Jun 15, 2012 at 02:23:11PM +0200, Ingo Molnar wrote:
> 
> * Kay Sievers <kay@vrfy.org> wrote:
> 
> > On Thu, 2012-06-14 at 17:04 -0700, Greg KH wrote:
> > 
> > > As no one seems to have responded, care to resend this with a
> > > signed-off-by so I can queue it up for 3.6?  If people complain, it can
> > > still go to 3.5, but given that no one is saying anything, I guess no
> > > one cares...
> > 
> > Sounds like a good plan. Here it is.
> > 
> > Thanks,
> > Kay
> > 
> > 
> > From: Kay Sievers <kay@vrfy.org>
> > Subject: kmsg - kmsg_dump() use iterator to receice log buffer content
> 
> typo.
> 
> > 
> > Provide an iterator to receive the log buffer content, and convert all
> > kmsg_dump() user to it.
> 
> typo.

<snip>

Thanks, I've fixed up all of these typos in the patch before I applied
it.

We need a "Proofread-by:" tag :)

greg k-h

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-05-03  0:29 [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer Kay Sievers
                   ` (2 preceding siblings ...)
  2012-05-26 11:11 ` Anton Vorontsov
@ 2012-11-28 13:33 ` Michael Kerrisk
  2012-11-28 16:22   ` Kay Sievers
  3 siblings, 1 reply; 100+ messages in thread
From: Michael Kerrisk @ 2012-11-28 13:33 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel,
	Michael Kerrisk

Hi Kay,

On Thu, May 3, 2012 at 2:29 AM, Kay Sievers <kay@vrfy.org> wrote:
> From: Kay Sievers <kay@vrfy.org>
[...]
>         case SYSLOG_ACTION_SIZE_UNREAD:
> -               error = log_end - log_start;
> +               raw_spin_lock_irq(&logbuf_lock);
> +               if (syslog_seq < log_first_seq) {
> +                       /* messages are gone, move to first one */
> +                       syslog_seq = log_first_seq;
> +                       syslog_idx = log_first_idx;
> +               }
> +               if (from_file) {
> +                       /*
> +                        * Short-cut for poll(/"proc/kmsg") which simply checks
> +                        * for pending data, not the size; return the count of
> +                        * records, not the length.
> +                        */
> +                       error = log_next_idx - syslog_idx;
> +               } else {
> +                       u64 seq;
> +                       u32 idx;
> +
> +                       error = 0;
> +                       seq = syslog_seq;
> +                       idx = syslog_idx;
> +                       while (seq < log_next_seq) {
> +                               error += syslog_print_line(idx, NULL, 0);
> +                               idx = log_next(idx);
> +                               seq++;
> +                       }
> +               }
> +               raw_spin_unlock_irq(&logbuf_lock);
>                 break;
[...]

It looks as though the changes here have broken SYSLOG_ACTION_SIZE_UNREAD.

On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
SYSLOG_ACTION_SIZE_UNREAD returns 0.

On 3.5, immediately after SYSLOG_ACTION_READ_CLEAR, the value returned
by SYSLOG_ACTION_SIZE_UNREAD is unchanged (i.e., assuming that the
value returned was non-zero before SYSLOG_ACTION_SIZE_UNREAD, it is
still nonzero afterward), even though a subsequent
SYSLOG_ACTION_READ_CLEAR indicates that there are zero bytes to read.

(All tests conducted with (r)syslogd stopped.)

Cheers,

Michael


-- 
Michael Kerrisk Linux man-pages maintainer;
http://www.kernel.org/doc/man-pages/

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-28 13:33 ` Michael Kerrisk
@ 2012-11-28 16:22   ` Kay Sievers
  2012-11-28 16:37     ` Linus Torvalds
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-11-28 16:22 UTC (permalink / raw)
  To: Michael Kerrisk
  Cc: Greg Kroah-Hartmann, Linus Torvalds, Ingo Molnar, linux-kernel

On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
> On Thu, May 3, 2012 at 2:29 AM, Kay Sievers <kay@vrfy.org> wrote:
>> From: Kay Sievers <kay@vrfy.org>
> [...]
>>         case SYSLOG_ACTION_SIZE_UNREAD:
>> -               error = log_end - log_start;
>> +               raw_spin_lock_irq(&logbuf_lock);
>> +               if (syslog_seq < log_first_seq) {
>> +                       /* messages are gone, move to first one */
>> +                       syslog_seq = log_first_seq;
>> +                       syslog_idx = log_first_idx;
>> +               }
>> +               if (from_file) {
>> +                       /*
>> +                        * Short-cut for poll(/"proc/kmsg") which simply checks
>> +                        * for pending data, not the size; return the count of
>> +                        * records, not the length.
>> +                        */
>> +                       error = log_next_idx - syslog_idx;
>> +               } else {
>> +                       u64 seq;
>> +                       u32 idx;
>> +
>> +                       error = 0;
>> +                       seq = syslog_seq;
>> +                       idx = syslog_idx;
>> +                       while (seq < log_next_seq) {
>> +                               error += syslog_print_line(idx, NULL, 0);
>> +                               idx = log_next(idx);
>> +                               seq++;
>> +                       }
>> +               }
>> +               raw_spin_unlock_irq(&logbuf_lock);
>>                 break;
> [...]
>
> It looks as though the changes here have broken SYSLOG_ACTION_SIZE_UNREAD.

Any specifics that it causes actual problems we need to address?

> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
> SYSLOG_ACTION_SIZE_UNREAD returns 0.

Hmm, sounds like the right thing to do.

We have read everything, even cleared the buffer for later queries. So
there is nothing to read anymore for later calls, and they will
actually never return anything if they are called, so returning 0 here
sounds like the right thing. The current SYSLOG_ACTION_SIZE_UNREAD
seems to match properly the expectations one can make for
SYSLOG_ACTION_READ_ALL.

> On 3.5, immediately after SYSLOG_ACTION_READ_CLEAR, the value returned
> by SYSLOG_ACTION_SIZE_UNREAD is unchanged
>
> (i.e., assuming that the
> value returned was non-zero before SYSLOG_ACTION_SIZE_UNREAD, it is
> still nonzero afterward), even though a subsequent
> SYSLOG_ACTION_READ_CLEAR indicates that there are zero bytes to read.

Which sounds at least like weird behaviour, if not "broken".

Any indication that we need to restore the old behaviour to fix some
weird assumptions? To me the current one sounds like the better and
more correct option, and what one would expect from it. But maybe we
cannot get away with it ...

(I hope I understood what you explained correctly, I'm a bit confused
by the issue.)


Thanks,
Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-28 16:22   ` Kay Sievers
@ 2012-11-28 16:37     ` Linus Torvalds
  2012-11-28 16:49       ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Linus Torvalds @ 2012-11-28 16:37 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Michael Kerrisk, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, Nov 28, 2012 at 8:22 AM, Kay Sievers <kay@vrfy.org> wrote:
> On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>
>> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
>> SYSLOG_ACTION_SIZE_UNREAD returns 0.
>
> Hmm, sounds like the right thing to do.

Right.

And that's the *OLD* behavior (2.6.31).

>> On 3.5, immediately after SYSLOG_ACTION_READ_CLEAR, the value returned
>> by SYSLOG_ACTION_SIZE_UNREAD is unchanged

And this is the *NEW* behavior, and as you say:

> Which sounds at least like weird behaviour, if not "broken".

So the new behavior is insane and different. Let's fix it.

It looks like it is because the new SYSLOG_ACTION_SIZE_UNREAD code
does not take the new clear_seq code into account. Hmm?

                 Linus

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-28 16:37     ` Linus Torvalds
@ 2012-11-28 16:49       ` Kay Sievers
  2012-11-28 17:51         ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-11-28 16:49 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Michael Kerrisk, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, Nov 28, 2012 at 5:37 PM, Linus Torvalds
<torvalds@linux-foundation.org> wrote:
> On Wed, Nov 28, 2012 at 8:22 AM, Kay Sievers <kay@vrfy.org> wrote:
>> On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>>
>>> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
>>> SYSLOG_ACTION_SIZE_UNREAD returns 0.
>>
>> Hmm, sounds like the right thing to do.
>
> Right.
>
> And that's the *OLD* behavior (2.6.31).

Ah, hmm, I read 2.6... as 3.6... :)

> So the new behavior is insane and different. Let's fix it.

Yeah.

> It looks like it is because the new SYSLOG_ACTION_SIZE_UNREAD code
> does not take the new clear_seq code into account. Hmm?

Right, something like that. I'll take a look now ...

Thanks,
Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-28 16:49       ` Kay Sievers
@ 2012-11-28 17:51         ` Kay Sievers
  2012-11-29 13:18           ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-11-28 17:51 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Michael Kerrisk, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, 2012-11-28 at 17:49 +0100, Kay Sievers wrote:
> On Wed, Nov 28, 2012 at 5:37 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> > On Wed, Nov 28, 2012 at 8:22 AM, Kay Sievers <kay@vrfy.org> wrote:
> >> On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
> >>
> >>> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
> >>> SYSLOG_ACTION_SIZE_UNREAD returns 0.
> >>
> >> Hmm, sounds like the right thing to do.
> >
> > Right.
> >
> > And that's the *OLD* behavior (2.6.31).
> 
> Ah, hmm, I read 2.6... as 3.6... :)
> 
> > So the new behavior is insane and different. Let's fix it.
> 
> Yeah.
> 
> > It looks like it is because the new SYSLOG_ACTION_SIZE_UNREAD code
> > does not take the new clear_seq code into account. Hmm?
> 
> Right, something like that. I'll take a look now ...

From: Kay Sievers <kay@vrfy.org>
Subject: printk: respect SYSLOG_ACTION_READ_CLEAR for SYSLOG_ACTION_SIZE_UNREAD

On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
> It looks as though the changes here have broken SYSLOG_ACTION_SIZE_UNREAD.
> 
> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
> SYSLOG_ACTION_SIZE_UNREAD returns 0.
> 
> On 3.5, immediately after SYSLOG_ACTION_READ_CLEAR, the value returned
> by SYSLOG_ACTION_SIZE_UNREAD is unchanged (i.e., assuming that the
> value returned was non-zero before SYSLOG_ACTION_SIZE_UNREAD, it is
> still nonzero afterward), even though a subsequent
> SYSLOG_ACTION_READ_CLEAR indicates that there are zero bytes to read.

Fix SYSLOG_ACTION_SIZE_UNREAD to return the amount of available
characters by starting to count at the first available record after
the last SYSLOG_ACTION_READ_CLEAR, instead of the first message
record for SYSLOG_ACTION_READ.

Before:
  syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
  syslog(SYSLOG_ACTION_READ_CLEAR, "<12>"..., 1000000) = 24000
  syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965

After:
  syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 90402
  syslog(SYSLOG_ACTION_READ_CLEAR, "<5>"..., 1000000) = 90402
  syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 0

Reported-By: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-Off-By: Kay Sievers <kay@vrfy.org>
---
 printk.c |   15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index 2d607f4..35a7f4f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1183,12 +1183,10 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 	/* Number of chars in the log buffer */
 	case SYSLOG_ACTION_SIZE_UNREAD:
 		raw_spin_lock_irq(&logbuf_lock);
-		if (syslog_seq < log_first_seq) {
+		if (clear_seq < 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;
+			clear_seq = log_first_seq;
+			clear_idx = log_first_idx;
 		}
 		if (from_file) {
 			/*
@@ -1198,9 +1196,9 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 			 */
 			error = log_next_idx - syslog_idx;
 		} else {
-			u64 seq = syslog_seq;
-			u32 idx = syslog_idx;
-			enum log_flags prev = syslog_prev;
+			u64 seq = clear_seq;
+			u32 idx = clear_idx;
+			enum log_flags prev = 0;
 
 			error = 0;
 			while (seq < log_next_seq) {
@@ -1211,7 +1209,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 				seq++;
 				prev = msg->flags;
 			}
-			error -= syslog_partial;
 		}
 		raw_spin_unlock_irq(&logbuf_lock);
 		break;



^ permalink raw reply related	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-28 17:51         ` Kay Sievers
@ 2012-11-29 13:18           ` Michael Kerrisk (man-pages)
  2012-11-29 13:28             ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Michael Kerrisk (man-pages) @ 2012-11-29 13:18 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Linus Torvalds, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, Nov 28, 2012 at 6:51 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Wed, 2012-11-28 at 17:49 +0100, Kay Sievers wrote:
>> On Wed, Nov 28, 2012 at 5:37 PM, Linus Torvalds
>> <torvalds@linux-foundation.org> wrote:
>> > On Wed, Nov 28, 2012 at 8:22 AM, Kay Sievers <kay@vrfy.org> wrote:
>> >> On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>> >>
>> >>> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
>> >>> SYSLOG_ACTION_SIZE_UNREAD returns 0.
>> >>
>> >> Hmm, sounds like the right thing to do.
>> >
>> > Right.
>> >
>> > And that's the *OLD* behavior (2.6.31).
>>
>> Ah, hmm, I read 2.6... as 3.6... :)
>>
>> > So the new behavior is insane and different. Let's fix it.
>>
>> Yeah.
>>
>> > It looks like it is because the new SYSLOG_ACTION_SIZE_UNREAD code
>> > does not take the new clear_seq code into account. Hmm?
>>
>> Right, something like that. I'll take a look now ...
>
> From: Kay Sievers <kay@vrfy.org>
> Subject: printk: respect SYSLOG_ACTION_READ_CLEAR for SYSLOG_ACTION_SIZE_UNREAD
>
> On Wed, Nov 28, 2012 at 2:33 PM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>> It looks as though the changes here have broken SYSLOG_ACTION_SIZE_UNREAD.
>>
>> On a 2.6.31 system, immediately after SYSLOG_ACTION_READ_CLEAR, a
>> SYSLOG_ACTION_SIZE_UNREAD returns 0.
>>
>> On 3.5, immediately after SYSLOG_ACTION_READ_CLEAR, the value returned
>> by SYSLOG_ACTION_SIZE_UNREAD is unchanged (i.e., assuming that the
>> value returned was non-zero before SYSLOG_ACTION_SIZE_UNREAD, it is
>> still nonzero afterward), even though a subsequent
>> SYSLOG_ACTION_READ_CLEAR indicates that there are zero bytes to read.
>
> Fix SYSLOG_ACTION_SIZE_UNREAD to return the amount of available
> characters by starting to count at the first available record after
> the last SYSLOG_ACTION_READ_CLEAR, instead of the first message
> record for SYSLOG_ACTION_READ.
>
> Before:
>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>   syslog(SYSLOG_ACTION_READ_CLEAR, "<12>"..., 1000000) = 24000
>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>
> After:
>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 90402
>   syslog(SYSLOG_ACTION_READ_CLEAR, "<5>"..., 1000000) = 90402
>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 0
>
> Reported-By: Michael Kerrisk <mtk.manpages@gmail.com>
> Signed-Off-By: Kay Sievers <kay@vrfy.org>
> ---
>  printk.c |   15 ++++++---------
>  1 file changed, 6 insertions(+), 9 deletions(-)
>
> diff --git a/kernel/printk.c b/kernel/printk.c
> index 2d607f4..35a7f4f 100644
> --- a/kernel/printk.c
> +++ b/kernel/printk.c
> @@ -1183,12 +1183,10 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
>         /* Number of chars in the log buffer */
>         case SYSLOG_ACTION_SIZE_UNREAD:
>                 raw_spin_lock_irq(&logbuf_lock);
> -               if (syslog_seq < log_first_seq) {
> +               if (clear_seq < 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;
> +                       clear_seq = log_first_seq;
> +                       clear_idx = log_first_idx;
>                 }
>                 if (from_file) {
>                         /*
> @@ -1198,9 +1196,9 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
>                          */
>                         error = log_next_idx - syslog_idx;
>                 } else {
> -                       u64 seq = syslog_seq;
> -                       u32 idx = syslog_idx;
> -                       enum log_flags prev = syslog_prev;
> +                       u64 seq = clear_seq;
> +                       u32 idx = clear_idx;
> +                       enum log_flags prev = 0;
>
>                         error = 0;
>                         while (seq < log_next_seq) {
> @@ -1211,7 +1209,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
>                                 seq++;
>                                 prev = msg->flags;
>                         }
> -                       error -= syslog_partial;
>                 }
>                 raw_spin_unlock_irq(&logbuf_lock);
>                 break;

Hello Kay,

I'm going to call my report yesterday bogus. Somewhere along the way,
I got confused while testing something, and my statement about 2.6.31
behavior is wrong: the 2.6.31 and 3.5 behaviors are the same. As such,
your patch is unneeded. Sorry for wasting your time.

Thanks,

Michael


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-29 13:18           ` Michael Kerrisk (man-pages)
@ 2012-11-29 13:28             ` Kay Sievers
  2012-11-29 13:37               ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-11-29 13:28 UTC (permalink / raw)
  To: mtk.manpages
  Cc: Linus Torvalds, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Thu, Nov 29, 2012 at 2:18 PM, Michael Kerrisk (man-pages)
<mtk.manpages@gmail.com> wrote:
> On Wed, Nov 28, 2012 at 6:51 PM, Kay Sievers <kay@vrfy.org> wrote:

>> Before:
>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<12>"..., 1000000) = 24000
>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>
>> After:
>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 90402
>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<5>"..., 1000000) = 90402
>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 0

> I'm going to call my report yesterday bogus. Somewhere along the way,
> I got confused while testing something, and my statement about 2.6.31
> behavior is wrong: the 2.6.31 and 3.5 behaviors are the same. As such,
> your patch is unneeded. Sorry for wasting your time.

I think you have been right with your report. The above pasted
before/after from the patch commit text is actually a result of real
testing with current git. And your initial description sounds right,
and the patch seems to produce the expected results here. I just
confused the numbers in your report and wrongly parsed 2.6 > 3.6.

Hmm, at least do far we did not blame anybody else than ourselves as
confused. One of us at least is right, and it looks you have been, and
I also think the patch is at least intended to be right. :)

Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-29 13:28             ` Kay Sievers
@ 2012-11-29 13:37               ` Michael Kerrisk (man-pages)
  2012-11-29 14:08                 ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Michael Kerrisk (man-pages) @ 2012-11-29 13:37 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Linus Torvalds, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Thu, Nov 29, 2012 at 2:28 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Thu, Nov 29, 2012 at 2:18 PM, Michael Kerrisk (man-pages)
> <mtk.manpages@gmail.com> wrote:
>> On Wed, Nov 28, 2012 at 6:51 PM, Kay Sievers <kay@vrfy.org> wrote:
>
>>> Before:
>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<12>"..., 1000000) = 24000
>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>>
>>> After:
>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 90402
>>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<5>"..., 1000000) = 90402
>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 0
>
>> I'm going to call my report yesterday bogus. Somewhere along the way,
>> I got confused while testing something, and my statement about 2.6.31
>> behavior is wrong: the 2.6.31 and 3.5 behaviors are the same. As such,
>> your patch is unneeded. Sorry for wasting your time.
>
> I think you have been right with your report. The above pasted
> before/after from the patch commit text is actually a result of real
> testing with current git. And your initial description sounds right,
> and the patch seems to produce the expected results here. I just
> confused the numbers in your report and wrongly parsed 2.6 > 3.6.
>
> Hmm, at least do far we did not blame anybody else than ourselves as
> confused. One of us at least is right, and it looks you have been, and
> I also think the patch is at least intended to be right. :)

Okay -- I'm pretty sure I am right about being wrong ;-).

Could you do some comparative testing please between 3.5 and pre-3.5.
I have a little test program below. When I rechecked 2.6.31 and 3.5
using this program I found the behavior was the same, which is why I
conclude my report is wrong. (And also, your proposed patch in
response to my bogus report produces different behavior from 2.6.31).

Thanks,

Michael

/*#* t_klogctl.c

  klogctl(3) is the glibc interface for syslog(2)

*/

#include <sys/klog.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define errMsg(msg) 	do { perror(msg); } while (0)

#define errExit(msg) 	do { perror(msg); exit(EXIT_FAILURE); \
			} while (0)

#define fatal(msg) 	do { fprintf(stderr, "%s\n", msg); \
     			     exit(EXIT_FAILURE); } while (0)


/* Close the log.  Currently a NOP. */
#define SYSLOG_ACTION_CLOSE          0
/* Open the log. Currently a NOP. */
#define SYSLOG_ACTION_OPEN           1
/* Read from the log. */
#define SYSLOG_ACTION_READ           2
/* Read all messages remaining in the ring buffer. */
#define SYSLOG_ACTION_READ_ALL       3
/* Read and clear all messages remaining in the ring buffer */
#define SYSLOG_ACTION_READ_CLEAR     4
/* Clear ring buffer. */
#define SYSLOG_ACTION_CLEAR          5
/* Disable printk's to console */
#define SYSLOG_ACTION_CONSOLE_OFF    6
/* Enable printk's to console */
#define SYSLOG_ACTION_CONSOLE_ON     7
/* Set level of messages printed to console */
#define SYSLOG_ACTION_CONSOLE_LEVEL  8
/* Return number of unread characters in the log buffer */
#define SYSLOG_ACTION_SIZE_UNREAD    9
/* Return size of the log buffer */
#define SYSLOG_ACTION_SIZE_BUFFER   10


int
main(int argc, char *argv[])
{
    int s;
#define BSIZE 500000
    char buf[BSIZE];

    if (argc < 2) {
	fprintf(stderr, "Usage: %s command-num [arg]\n", argv[0]);
	exit(EXIT_FAILURE);
    }

    int cmd;

    cmd = atoi(argv[1]);

    switch (cmd) {

    case SYSLOG_ACTION_READ:		/* 2 */
	printf("SYSLOG_ACTION_READ\n");
        s = klogctl(SYSLOG_ACTION_READ, buf,
		(argc > 2) ? atoi(argv[2]) : BSIZE);
        if (s == -1)
	    errExit("klogctl-READ");
        printf("Return value: %d\n", s);

        if (write(2, buf, s) != s)
	    errMsg("write");
        break;

    case SYSLOG_ACTION_READ_ALL:	/* 3 */
    case SYSLOG_ACTION_READ_CLEAR:	/* 4 */
	if (cmd == SYSLOG_ACTION_READ_CLEAR)
	    printf("SYSLOG_ACTION_READ_CLEAR\n");
	else
	    printf("SYSLOG_ACTION_READ_ALL\n");


        s = klogctl(cmd, buf,
		(argc > 2) ? atoi(argv[2]) : BSIZE);
        if (s == -1)
	    errExit("klogctl-READ_ALL/READ_CLEAR");
        printf("Return value: %d\n", s);

        if (write(2, buf, s) != s)
	    errMsg("write");

	if (cmd == SYSLOG_ACTION_READ_CLEAR)
	    printf("Ring buffer cleared\n");
        break;

    case SYSLOG_ACTION_CLEAR:		/* 5 */
	printf("SYSLOG_ACTION_CLEAR\n");
        s = klogctl(SYSLOG_ACTION_CLEAR, NULL, 0);
        if (s == -1)
	    errExit("klogctl-CLEAR");
        printf("Return value: %d\n", s);
	printf("Ring buffer cleared\n");
	break;

    case SYSLOG_ACTION_SIZE_UNREAD:	/* 9 */
	printf("SYSLOG_ACTION_SIZE_UNREAD\n");
        s = klogctl(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0);
        if (s == -1)
	    errExit("klogctl-SIZE_UNREAD");
        printf("Number of unread bytes: %d\n", s);
	break;

    case SYSLOG_ACTION_SIZE_BUFFER:	/* 10 */
	printf("SYSLOG_ACTION_SIZE_BUFFER\n");
        s = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0);
        if (s == -1)
	    errExit("klogctl-SIZE_BUFFER");
        printf("Size of buffer: %d\n", s);
	break;

    default:
	fatal("Bad command");
	break;
    }

    exit(EXIT_SUCCESS);
}

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-29 13:37               ` Michael Kerrisk (man-pages)
@ 2012-11-29 14:08                 ` Kay Sievers
  2012-11-29 14:18                   ` Michael Kerrisk (man-pages)
  0 siblings, 1 reply; 100+ messages in thread
From: Kay Sievers @ 2012-11-29 14:08 UTC (permalink / raw)
  To: mtk.manpages
  Cc: Linus Torvalds, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Thu, Nov 29, 2012 at 2:37 PM, Michael Kerrisk (man-pages)
<mtk.manpages@gmail.com> wrote:
> On Thu, Nov 29, 2012 at 2:28 PM, Kay Sievers <kay@vrfy.org> wrote:
>> On Thu, Nov 29, 2012 at 2:18 PM, Michael Kerrisk (man-pages)
>> <mtk.manpages@gmail.com> wrote:
>>> On Wed, Nov 28, 2012 at 6:51 PM, Kay Sievers <kay@vrfy.org> wrote:
>>
>>>> Before:
>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<12>"..., 1000000) = 24000
>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>>>
>>>> After:
>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 90402
>>>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<5>"..., 1000000) = 90402
>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 0
>>
>>> I'm going to call my report yesterday bogus. Somewhere along the way,
>>> I got confused while testing something, and my statement about 2.6.31
>>> behavior is wrong: the 2.6.31 and 3.5 behaviors are the same. As such,
>>> your patch is unneeded. Sorry for wasting your time.
>>
>> I think you have been right with your report. The above pasted
>> before/after from the patch commit text is actually a result of real
>> testing with current git. And your initial description sounds right,
>> and the patch seems to produce the expected results here. I just
>> confused the numbers in your report and wrongly parsed 2.6 > 3.6.
>>
>> Hmm, at least do far we did not blame anybody else than ourselves as
>> confused. One of us at least is right, and it looks you have been, and
>> I also think the patch is at least intended to be right. :)
>
> Okay -- I'm pretty sure I am right about being wrong ;-).
>
> Could you do some comparative testing please between 3.5 and pre-3.5.
> I have a little test program below. When I rechecked 2.6.31 and 3.5
> using this program I found the behavior was the same, which is why I
> conclude my report is wrong. (And also, your proposed patch in
> response to my bogus report produces different behavior from 2.6.31).

Oh, seems you are right.

The old kernel does not return 0, while it probably should. The
current kernel seems to do the same thing.

But the behaviour with the patch stills seems like the better and the
obvious and expected behaviour to me. :)

Thanks,
Kay

######### old fedora kernel (pre-new-logging) ###############
# uname -a
Linux nja 3.4.4-3.fc17.x86_64

# echo 1234567890 > /dev/kmsg

# ./syslog-test 9
SYSLOG_ACTION_SIZE_UNREAD
Number of unread bytes: 95299

# ./syslog-test 4
SYSLOG_ACTION_READ_CLEAR
Return value: 29
<4>[   54.933282] 1234567890
Ring buffer cleared

# ./syslog-test 9
SYSLOG_ACTION_SIZE_UNREAD
Number of unread bytes: 95299

######### current fedora kernel (new logging) ############

# uname -a
Linux nja 3.6.6-3.fc18.x86_64

# echo 1234567890 > /dev/kmsg

# ./syslog-test 9
SYSLOG_ACTION_SIZE_UNREAD
Number of unread bytes: 286822

# ./syslog-test 4
SYSLOG_ACTION_READ_CLEAR
Return value: 31
<12>[259301.067699] 1234567890
Ring buffer cleared

# ./syslog-test 9
SYSLOG_ACTION_SIZE_UNREAD
Number of unread bytes: 286822

######### git kernel with the above patch applied #############

# uname -a
Linux nja 3.7.0-rc7+

# echo 1234567890 > /dev/kmsg

# ./syslog-test 9
SYSLOG_ACTION_SIZE_UNREAD
Number of unread bytes: 30

# ./syslog-test 4
SYSLOG_ACTION_READ_CLEAR
Return value: 30
<12>[   69.591745] 1234567890
Ring buffer cleared

# ./syslog-test 9
SYSLOG_ACTION_SIZE_UNREAD
Number of unread bytes: 0

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-29 14:08                 ` Kay Sievers
@ 2012-11-29 14:18                   ` Michael Kerrisk (man-pages)
  2012-11-29 14:31                     ` Kay Sievers
  0 siblings, 1 reply; 100+ messages in thread
From: Michael Kerrisk (man-pages) @ 2012-11-29 14:18 UTC (permalink / raw)
  To: Kay Sievers
  Cc: Linus Torvalds, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Thu, Nov 29, 2012 at 3:08 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Thu, Nov 29, 2012 at 2:37 PM, Michael Kerrisk (man-pages)
> <mtk.manpages@gmail.com> wrote:
>> On Thu, Nov 29, 2012 at 2:28 PM, Kay Sievers <kay@vrfy.org> wrote:
>>> On Thu, Nov 29, 2012 at 2:18 PM, Michael Kerrisk (man-pages)
>>> <mtk.manpages@gmail.com> wrote:
>>>> On Wed, Nov 28, 2012 at 6:51 PM, Kay Sievers <kay@vrfy.org> wrote:
>>>
>>>>> Before:
>>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>>>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<12>"..., 1000000) = 24000
>>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 286965
>>>>>
>>>>> After:
>>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 90402
>>>>>   syslog(SYSLOG_ACTION_READ_CLEAR, "<5>"..., 1000000) = 90402
>>>>>   syslog(SYSLOG_ACTION_SIZE_UNREAD, 0, 0) = 0
>>>
>>>> I'm going to call my report yesterday bogus. Somewhere along the way,
>>>> I got confused while testing something, and my statement about 2.6.31
>>>> behavior is wrong: the 2.6.31 and 3.5 behaviors are the same. As such,
>>>> your patch is unneeded. Sorry for wasting your time.
>>>
>>> I think you have been right with your report. The above pasted
>>> before/after from the patch commit text is actually a result of real
>>> testing with current git. And your initial description sounds right,
>>> and the patch seems to produce the expected results here. I just
>>> confused the numbers in your report and wrongly parsed 2.6 > 3.6.
>>>
>>> Hmm, at least do far we did not blame anybody else than ourselves as
>>> confused. One of us at least is right, and it looks you have been, and
>>> I also think the patch is at least intended to be right. :)
>>
>> Okay -- I'm pretty sure I am right about being wrong ;-).
>>
>> Could you do some comparative testing please between 3.5 and pre-3.5.
>> I have a little test program below. When I rechecked 2.6.31 and 3.5
>> using this program I found the behavior was the same, which is why I
>> conclude my report is wrong. (And also, your proposed patch in
>> response to my bogus report produces different behavior from 2.6.31).
>
> Oh, seems you are right.
>
> The old kernel does not return 0, while it probably should. The
> current kernel seems to do the same thing.
>
> But the behaviour with the patch stills seems like the better and the
> obvious and expected behaviour to me. :)

The point here I think is that the semantics of the various syslog()
commands are surprising, which is what led me into some confusion in
testing. Essentially, command 5 ("clear ring buffer") does not really
clear anything, it simply sets bookkeeping variables that affect the
behavior of commands 3 and 4. Of particular note is that command 5
does NOT affect commands 2 and 9, and command 9 is only returning the
number of bytes that would be read by command 2. The man page could do
with some improvement (and will get it).

So, just to be clear: you better not apply your patch; it might break
something ;-).

Cheers,

Michael

^ permalink raw reply	[flat|nested] 100+ messages in thread

* Re: [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer
  2012-11-29 14:18                   ` Michael Kerrisk (man-pages)
@ 2012-11-29 14:31                     ` Kay Sievers
  0 siblings, 0 replies; 100+ messages in thread
From: Kay Sievers @ 2012-11-29 14:31 UTC (permalink / raw)
  To: mtk.manpages
  Cc: Linus Torvalds, Greg Kroah-Hartmann, Ingo Molnar,
	Linux Kernel Mailing List

On Thu, Nov 29, 2012 at 3:18 PM, Michael Kerrisk (man-pages)
<mtk.manpages@gmail.com> wrote:
> So, just to be clear: you better not apply your patch; it might break
> something ;-).

Sounds good to me. :)

Thanks,
Kay

^ permalink raw reply	[flat|nested] 100+ messages in thread

end of thread, other threads:[~2012-11-29 14:31 UTC | newest]

Thread overview: 100+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-03  0:29 [PATCH RESEND 1/3] printk: convert byte-buffer to variable-length record buffer Kay Sievers
2012-05-03 19:48 ` Peter Zijlstra
2012-05-03 19:54   ` Kay Sievers
2012-05-03 19:55     ` Peter Zijlstra
2012-05-03 19:56   ` Linus Torvalds
2012-05-03 20:02     ` Peter Zijlstra
2012-05-03 20:09       ` Linus Torvalds
2012-05-03 20:11         ` Peter Zijlstra
2012-05-03 20:18           ` Greg Kroah-Hartmann
2012-05-08  8:48 ` Sasha Levin
2012-05-08 11:14   ` Kay Sievers
2012-05-08 13:33     ` Sasha Levin
2012-05-08 14:29       ` Kay Sievers
2012-05-08 15:33         ` Kay Sievers
2012-05-08 15:57           ` Sasha Levin
2012-05-08 16:27             ` Kay Sievers
2012-05-08 22:57               ` Greg Kroah-Hartmann
2012-05-09  3:52     ` Linus Torvalds
2012-05-09  4:06       ` Joe Perches
2012-05-09  4:11       ` Sasha Levin
2012-05-09  4:27         ` Linus Torvalds
2012-05-09  4:36           ` Linus Torvalds
2012-05-09  7:07             ` Ingo Molnar
2012-05-09 13:21               ` Kay Sievers
2012-05-09 13:29               ` Kay Sievers
2012-05-10  0:54                 ` Kay Sievers
2012-05-10  1:18                   ` Linus Torvalds
2012-05-10  2:32                     ` Kay Sievers
2012-05-10  2:46                       ` Joe Perches
2012-05-10 16:39                     ` Kay Sievers
2012-05-10 16:47                       ` Linus Torvalds
2012-05-10 18:49                         ` Tony Luck
2012-05-10 19:09                         ` Kay Sievers
2012-05-10 20:14                           ` Ted Ts'o
2012-05-10 20:37                             ` Joe Perches
2012-05-10 20:39                               ` Kay Sievers
2012-05-10 20:46                                 ` Joe Perches
2012-05-10 20:52                                   ` Linus Torvalds
2012-05-10 21:11                                     ` Joe Perches
2012-05-10 21:15                                       ` Kay Sievers
2012-05-10 21:58                                       ` Linus Torvalds
2012-05-11  0:13                                         ` Joe Perches
2012-05-11  0:38                                     ` Kay Sievers
2012-05-11  1:23                                       ` Kay Sievers
2012-05-14 18:46                                         ` Kay Sievers
2012-05-10 21:01                                   ` Kay Sievers
2012-05-10 20:38                             ` Kay Sievers
2012-05-09  9:38       ` Kay Sievers
2012-05-09 13:50         ` Joe Perches
2012-05-09 14:37           ` Kay Sievers
2012-05-09 23:02             ` Yinghai Lu
2012-05-09 23:06               ` Greg Kroah-Hartmann
2012-05-10  2:30                 ` Kay Sievers
2012-05-11 10:35                   ` Sasha Levin
2012-05-11 15:19                     ` Greg KH
2012-05-11 15:22                       ` Sasha Levin
2012-05-11 15:35                       ` Linus Torvalds
2012-05-11 15:40                         ` Kay Sievers
2012-05-11 15:47                           ` Linus Torvalds
2012-05-11 19:51                             ` Mark Lord
2012-05-11 20:02                               ` Linus Torvalds
2012-05-12 18:04                                 ` Mark Lord
2012-05-12  7:43                             ` Sasha Levin
2012-05-12 18:35                               ` Linus Torvalds
2012-05-13 11:08                                 ` Kay Sievers
2012-05-13 13:22                                 ` Mark Lord
2012-05-13 18:01                                   ` Linus Torvalds
2012-05-13 22:19                                     ` Mark Lord
2012-05-14 16:40                                   ` valdis.kletnieks
2012-05-17  3:44                                 ` H. Peter Anvin
2012-05-13 21:48                               ` Kay Sievers
2012-05-13 21:30                     ` Kay Sievers
2012-05-26 11:11 ` Anton Vorontsov
2012-05-27 14:23   ` Kay Sievers
2012-05-29 16:07     ` Kay Sievers
2012-05-29 16:14       ` Joe Perches
2012-05-29 16:34         ` Kay Sievers
2012-05-29 16:51           ` Joe Perches
2012-05-29 17:11       ` Luck, Tony
2012-05-29 17:22         ` Kay Sievers
2012-05-30 11:29           ` Kay Sievers
2012-06-06  6:33       ` Greg Kroah-Hartmann
2012-06-15  0:04       ` Greg KH
2012-06-15  1:31         ` Anton Vorontsov
2012-06-15 12:07         ` Kay Sievers
2012-06-15 12:23           ` Ingo Molnar
2012-06-15 21:53             ` Greg KH
2012-06-15 12:23           ` Anton Vorontsov
2012-06-15 20:54           ` Tony Luck
2012-11-28 13:33 ` Michael Kerrisk
2012-11-28 16:22   ` Kay Sievers
2012-11-28 16:37     ` Linus Torvalds
2012-11-28 16:49       ` Kay Sievers
2012-11-28 17:51         ` Kay Sievers
2012-11-29 13:18           ` Michael Kerrisk (man-pages)
2012-11-29 13:28             ` Kay Sievers
2012-11-29 13:37               ` Michael Kerrisk (man-pages)
2012-11-29 14:08                 ` Kay Sievers
2012-11-29 14:18                   ` Michael Kerrisk (man-pages)
2012-11-29 14:31                     ` Kay Sievers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).