Possible race in printk?

Rogier Wolff (R.E.Wolff@BitWizard.nl)
Thu, 11 Nov 1999 14:04:51 +0100 (MET)


Hi,

/*
* The logged_chars, log_start, and log_size values may
* change from an interrupt, so we disable interrupts.
*/
__save_flags(flags);
__cli();
count = len;
if (count > LOG_BUF_LEN)
count = LOG_BUF_LEN;
if (count > logged_chars)
count = logged_chars;
j = log_start + log_size - count;
__restore_flags(flags);
for (i = 0; i < count; i++) {
c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
__put_user(c, buf++);
}
if (do_clear)

What if at the start the ringbuffer is "full", and an interrupt which
prints something comes in while we're blocking interrupts. The
interrupt will happen the moment "restore flags" is called.

We'll print "new" info from the buffer, which has just overwritten
"old" info. This can be very confusing.

during CLI area:
start of buffer end of buffer.
^ ^
0 1 2 3 4 5 6 7 8 9
j^
<------count------>

after interrupt;

start of buffer end of buffer.
^ ^
a b c 3 4 5 6 7 8 9
j^
<------count------>

the copy will copy over abc3456789, instead of 3456789abc.

The naive thing to do would be to move the restore flags to past the
forloop, but that, I'm told, leads to nasty Oopsen when the put_user
causes some paging.

Does anybody know how I can get printk to print stuff to the console
again? I'm trying to track down a "system hang" and my "cat
/proc/kmsg" works great, as long as the system doesn't hang....

So far I've been playing with the syslog system call, the "klogd"
program iwth the -c argument, and the /proc/sys/kernel/printk file...

Roger.

-- 
** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2137555 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
 "I didn't say it was your fault. I said I was going to blame it on you."

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/