Skip to contentSkip to conversation

kernel/printk.c lockless access

PATCH In review Linas Vepstas 10 participants 11 messages Jan 6, 2005 – Jan 10, 2005

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 kernel/printk.c lockless access

Hi Linus, Andrew,

I was wondering if you could see your way to accepting the attached patch, which provides access to the syslog buffer pointers.

The basic idea is that if a system has crashed, it can be handy to be able to view the contents of the syslog buffer. Unfortunately, this is currently hard to do.

-- char __log_buf[] is declared static in printk.c, so it cannot
be found in the ksyms table.

-- do_syslog() uses spinlocks to protect the data structure, and
so will typically deadlock if called.

The 'fix' is to provide a routine that simply returns the pointers to the log buffer.

I'd be thrilled to have this patch accepted ...

--linas

===== kernel/printk.c 1.47 vs edited =====

kernel/printk.c +17 -0
@@ -380,6 +380,23 @@ asmlinkage long sys_syslog(int type, cha
 	return do_syslog(type, buf, len);
 }
 
+#ifdef   CONFIG_DEBUG_KERNEL
+/**
+ * Its very handy to be able to view the syslog buffer during debug.
+ * But do_syslog() uses locks and so it will deadlock if called during 
+ * a debugging session. The routine provides the start and end of the 
+ * physical and logical logs, and is equivalent to do_syslog(3).
+ */
+
+void debugger_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;
+}
+#endif   /* CONFIG_DEBUG_KERNEL */
+
 /*
  * Call the console drivers on a range of log_buf
  */
#1 lore raw
Quoted 2 lines · Linas Vepstas

The 'fix' is to provide a routine that simply returns the pointers to the log buffer.

Better&simpler fix would be to just unstatic __log_buf You cannot call such functions generally when looking at memory dumps of some form.

-Andi

#2 lore raw
In reply to Linas Vepstas
Quoted 11 lines · Linas Vepstas

I was wondering if you could see your way to accepting the attached patch, which provides access to the syslog buffer pointers.

The basic idea is that if a system has crashed, it can be handy to be able to view the contents of the syslog buffer. Unfortunately, this is currently hard to do.

-- char __log_buf[] is declared static in printk.c, so it cannot
be found in the ksyms table.

Quoted 7 lines

-- do_syslog() uses spinlocks to protect the data structure, and
so will typically deadlock if called.

The 'fix' is to provide a routine that simply returns the pointers to the log buffer.

I'd be thrilled to have this patch accepted ...

We faced the same problem in the Digeo kernel. When the kernel oopses we want to grab the last kilobyte or so of the printk buffer and stash it into nvram. We did this via a function which copies the data rather than exporting all those variables, which I think is a nicer and more maintainable approach:

/** get_printk_state - read the printk log buffer state
*
* @how_far_back: how many bytes back-in-time to look
*
* get_printk_state() gives the caller the current printk
* log buffer head index, for later use by get_printk_buffer()
* The index is offset by @how_far_back, which allows the caller
* to look at previously-emitted information. Negative values of
* how_far_back don't make sense.
*/
int get_printk_state(int how_far_back)

{
	return (log_end - how_far_back) & LOG_BUF_MASK;
}

/** get_printk_buffer - read bytes from the printk buffer
*
* get_printk_buffer() will copy some bytes from the printk
* ring buffer into the caller's buffer.
*
* @buf - the caller's buffer. Bytes are written here.
* @len - the amount of space at *@buf
* @start_at - where in the log buffer to start copying out
* data. Presumably from a previous get_printk_state() call. *
* get_printk_buffer() does not place a null at the end of *@buf *
* get_printk_state() returns the number of bytes which it wrote
* to *@buf.
*/
int get_printk_buffer(char *buf, int len, int start_at)

{
	int count;
	int at = start_at;

	for (count = 0; count < len; count++, at++) {
		if ((at & LOG_BUF_MASK) == (log_end & LOG_BUF_MASK))
			break;
		buf[count] = LOG_BUF(at);
	}
	return count;
}

(all available in a horrendous tarball at
http://www.digeo.com/assets/datasheets/digeo-mc1-2.0.8-mods.tar.bz2)

You want to cook up something like that? (That's 2.4 code, and might need work for 2.6 changes).

#3 lore raw
Quoted 6 lines

We faced the same problem in the Digeo kernel. When the kernel oopses we want to grab the last kilobyte or so of the printk buffer and stash it into nvram. We did this via a function which copies the data rather than exporting all those variables, which I think is a nicer and more maintainable approach:

Actually Id love to do this on ppc64 too. Its always difficult to get a customer to remember to save away an oops report.

Anton

#4 lore raw
Quoted 11 lines · Anton Blanchard
Quoted 7 lines

We faced the same problem in the Digeo kernel. When the kernel oopses we want to grab the last kilobyte or so of the printk buffer and stash it into nvram. We did this via a function which copies the data rather than exporting all those variables, which I think is a nicer and more maintainable approach:

Actually Id love to do this on ppc64 too. Its always difficult to get a customer to remember to save away an oops report.

We need /proc/kallsyms, /proc/modules, etc. also.... can you capture all of that for a complete oops/panic analysis? (short of kdump, that is)

Signature · 1 line
~Randy
#5 lore raw
Quoted 6 lines · Randy.Dunlap
Quoted 2 lines

Actually Id love to do this on ppc64 too. Its always difficult to get a customer to remember to save away an oops report.

We need /proc/kallsyms, /proc/modules, etc. also.... can you capture all of that for a complete oops/panic analysis? (short of kdump, that is)

Ditto on x86 - several of us raised the ideal of ACPI actually defining a "log area" in the E820 map types or some other ACPI resource that would be a chunk of RAM used for logs that wasn't going to get bios eaten on a soft reboot but could be reclaimed by the OS but we didn't get it.

#6 lore raw
Quoted 6 lines · Alan Cox

Ditto on x86 - several of us raised the ideal of ACPI actually defining a "log area" in the E820 map types or some other ACPI resource that would be a chunk of RAM used for logs that wasn't going to get bios eaten on a soft reboot but could be reclaimed by the OS but we didn't get it.

What about UDP (or just eth) broadcasting the oops and catching it on another system? That would be useful if one has a lot of systems (I have about 40) and makes it possible to immediately alert someone without the need for ping games.

Signature · 1 line
Frank
#7 lore raw
Quoted 2 lines · Frank van Maarseveen

What about UDP (or just eth) broadcasting the oops and catching it on another system?

For security reasons, it better be optional and disabled by default. (That should be easy enough to ensure, so this is obviously not something to stand in the way of doing something like this.)

#8 lore raw
In reply to Frank van Maarseveen
Quoted 4 lines · Frank van Maarseveen

What about UDP (or just eth) broadcasting the oops and catching it on another system? That would be useful if one has a lot of systems (I have about 40) and makes it possible to immediately alert someone without the need for ping games.

netdump and kgdb both can do this. The 2.6.10-tiny1 has some nice kgdb patches that include using the polling network debug interfaces.

#9 lore raw
Quoted 8 lines · Alan Cox
Quoted 4 lines · Frank van Maarseveen

What about UDP (or just eth) broadcasting the oops and catching it on another system? That would be useful if one has a lot of systems (I have about 40) and makes it possible to immediately alert someone without the need for ping games.

netdump and kgdb both can do this. The 2.6.10-tiny1 has some nice kgdb patches that include using the polling network debug interfaces.

Netconsole can sends oopses over UDP right now in mainline (since 2.6.3 or so?). And my kgdb over ethernet bits have been in -mm for quite some time as well.

(Though testing of -tiny is still appreciated of course.)

Signature · 1 line
Mathematics is the supreme nostalgia of our time.
#10 lore raw
In reply to Linas Vepstas
Quoted 14 lines · Linas Vepstas

===== kernel/printk.c 1.47 vs edited =====

kernel/printk.c +7 -0
@@ -380,6 +380,23 @@ asmlinkage long sys_syslog(int type, cha
 	return do_syslog(type, buf, len);
 }
 
+#ifdef   CONFIG_DEBUG_KERNEL
+/**
+ * Its very handy to be able to view the syslog buffer during debug.
+ * But do_syslog() uses locks and so it will deadlock if called during 
+ * a debugging session. The routine provides the start and end of the 
+ * physical and logical logs, and is equivalent to do_syslog(3).
+ */

kernel/printk.c asmlinkage long sys_syslog(int type, cha · line 399

Quoted 10 lines
kernel/printk.c +10 -0
+
+void debugger_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;
+}
+#endif   /* CONFIG_DEBUG_KERNEL */
+

Replace __LOG_BUF_LEN with log_buf_len. __LOG_BUF_LEN is the default size, log_buf_len is the actual size used, including boot time overrides with log_buf_len=.

On Thu, 06 Jan 2005 21:50:17 +0100,
Andi Kleen <[email protected]> wrote:

AK>Better&simpler fix would be to just unstatic __log_buf

The debug caller needs to know where the ring pointers are as well. Also __log_buf is not necessarily the current log buffer, boot with log_buf_len= and you get a different buffer. The caller needs the

On Thu, 6 Jan 2005 16:12:41 -0800,
Andrew Morton <[email protected]> wrote:

AKPM>We faced the same problem in the Digeo kernel. When the kernel oopses we AKPM>want to grab the last kilobyte or so of the printk buffer and stash it into AKPM>nvram. We did this via a function which copies the data rather than AKPM>exporting all those variables, which I think is a nicer and more AKPM>maintainable approach:

That assumes that you have enough free space to copy the log buffer to. In the general debugging case that is not true, especially if you want the entire print buffer to be printed. The only safe way to access the complete print buffer is in situ. Which is what the patch above does.