diff options
Diffstat (limited to 'kernel/printk/printk.c')
| -rw-r--r-- | kernel/printk/printk.c | 29 | 
1 files changed, 18 insertions, 11 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 5ba37f813723..4e22230f1f6c 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1418,10 +1418,9 @@ static int have_callable_console(void)  /*   * Can we actually use the console at this time on this cpu?   * - * Console drivers may assume that per-cpu resources have - * been allocated. So unless they're explicitly marked as - * being able to cope (CON_ANYTIME) don't call them until - * this CPU is officially up. + * Console drivers may assume that per-cpu resources have been allocated. So + * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't + * call them until this CPU is officially up.   */  static inline int can_use_console(unsigned int cpu)  { @@ -1434,8 +1433,10 @@ static inline int can_use_console(unsigned int cpu)   * console_lock held, and 'console_locked' set) if it   * is successful, false otherwise.   */ -static int console_trylock_for_printk(unsigned int cpu) +static int console_trylock_for_printk(void)  { +	unsigned int cpu = smp_processor_id(); +  	if (!console_trylock())  		return 0;  	/* @@ -1605,7 +1606,8 @@ asmlinkage int vprintk_emit(int facility, int level,  		 */  		if (!oops_in_progress && !lockdep_recursing(current)) {  			recursion_bug = 1; -			goto out_restore_irqs; +			local_irq_restore(flags); +			return 0;  		}  		zap_locks();  	} @@ -1708,17 +1710,22 @@ asmlinkage int vprintk_emit(int facility, int level,  	logbuf_cpu = UINT_MAX;  	raw_spin_unlock(&logbuf_lock); +	lockdep_on(); +	local_irq_restore(flags); + +	/* +	 * Disable preemption to avoid being preempted while holding +	 * console_sem which would prevent anyone from printing to console +	 */ +	preempt_disable();  	/*  	 * Try to acquire and then immediately release the console semaphore.  	 * The release will print out buffers and wake up /dev/kmsg and syslog()  	 * users.  	 */ -	if (console_trylock_for_printk(this_cpu)) +	if (console_trylock_for_printk())  		console_unlock(); - -	lockdep_on(); -out_restore_irqs: -	local_irq_restore(flags); +	preempt_enable();  	return printed_len;  }  | 
