Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] Provide better printk() support for SMP machines

The attached patch prevents oopses interleaving with characters from
other printks on other CPUs by only breaking the lock if the oops is
happening on the machine holding the lock.

It might be better if the oops generator got the lock and then called an
inner vprintk routine that assumed the caller holds the lock, thus
making oops reports "atomic".

Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

David Howells and committed by
Linus Torvalds
fe21773d c3d8c141

+12 -1
+12 -1
kernel/printk.c
··· 514 514 return r; 515 515 } 516 516 517 + /* cpu currently holding logbuf_lock */ 518 + static volatile unsigned int printk_cpu = UINT_MAX; 519 + 517 520 asmlinkage int vprintk(const char *fmt, va_list args) 518 521 { 519 522 unsigned long flags; ··· 525 522 static char printk_buf[1024]; 526 523 static int log_level_unknown = 1; 527 524 528 - if (unlikely(oops_in_progress)) 525 + preempt_disable(); 526 + if (unlikely(oops_in_progress) && printk_cpu == smp_processor_id()) 527 + /* If a crash is occurring during printk() on this CPU, 528 + * make sure we can't deadlock */ 529 529 zap_locks(); 530 530 531 531 /* This stops the holder of console_sem just where we want him */ 532 532 spin_lock_irqsave(&logbuf_lock, flags); 533 + printk_cpu = smp_processor_id(); 533 534 534 535 /* Emit the output into the temporary buffer */ 535 536 printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); ··· 602 595 * CPU until it is officially up. We shouldn't be calling into 603 596 * random console drivers on a CPU which doesn't exist yet.. 604 597 */ 598 + printk_cpu = UINT_MAX; 605 599 spin_unlock_irqrestore(&logbuf_lock, flags); 606 600 goto out; 607 601 } ··· 612 604 * We own the drivers. We can drop the spinlock and let 613 605 * release_console_sem() print the text 614 606 */ 607 + printk_cpu = UINT_MAX; 615 608 spin_unlock_irqrestore(&logbuf_lock, flags); 616 609 console_may_schedule = 0; 617 610 release_console_sem(); ··· 622 613 * allows the semaphore holder to proceed and to call the 623 614 * console drivers with the output which we just produced. 624 615 */ 616 + printk_cpu = UINT_MAX; 625 617 spin_unlock_irqrestore(&logbuf_lock, flags); 626 618 } 627 619 out: 620 + preempt_enable(); 628 621 return printed_len; 629 622 } 630 623 EXPORT_SYMBOL(printk);