• Steven Rostedt's avatar
    printk: remove separate printk_sched buffers and use printk buf instead · 458df9fd
    Steven Rostedt authored
    To prevent deadlocks with doing a printk inside the scheduler,
    printk_sched() was created.  The issue is that printk has a console_sem
    that it can grab and release.  The release does a wake up if there's a
    task pending on the sem, and this wake up grabs the rq locks that is
    held in the scheduler.  This leads to a possible deadlock if the wake up
    uses the same rq as the one with the rq lock held already.
    
    What printk_sched() does is to save the printk write in a per cpu buffer
    and sets the PRINTK_PENDING_SCHED flag.  On a timer tick, if this flag is
    set, the printk() is done against the buffer.
    
    There's a couple of issues with this approach.
    
    1) If two printk_sched()s are called before the tick, the second one
       will overwrite the first one.
    
    2) The temporary buffer is 512 bytes and is per cpu.  This is a quite a
       bit of space wasted for something that is seldom used.
    
    In order to remove this, the printk_sched() can use the printk buffer
    instead, and delay the console_trylock()/console_unlock() to the queued
    work.
    
    Because printk_sched() would then be taking the logbuf_lock, the
    logbuf_lock must not be held while doing anything that may call into the
    scheduler functions, which includes wake ups.  Unfortunately, printk()
    also has a console_sem that it uses, and on release, the up(&console_sem)
    may do a wake up of any pending waiters.  This must be avoided while
    holding the logbuf_lock.
    Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    458df9fd
printk.c 75 KB