Revert "printk: Never set console_may_schedule in console_trylock()"
authorSasha Levin <sashal@kernel.org>
Thu, 13 Dec 2018 14:24:35 +0000 (09:24 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Dec 2018 08:28:54 +0000 (09:28 +0100)
This reverts commit c9b8d580b3fb0ab65d37c372aef19a318fda3199.

This is just a technical revert to make the printk fix apply cleanly,
this patch will be re-picked in about 3 commits.

kernel/printk/printk.c

index a9cf2e1..7161312 100644 (file)
@@ -1763,19 +1763,12 @@ asmlinkage int vprintk_emit(int facility, int level,
        /* If called from the scheduler, we can not call up(). */
        if (!in_sched) {
                /*
-                * 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())
                        console_unlock();
-               preempt_enable();
        }
 
        return printed_len;
@@ -2090,7 +2083,20 @@ int console_trylock(void)
                return 0;
        }
        console_locked = 1;
-       console_may_schedule = 0;
+       /*
+        * When PREEMPT_COUNT disabled we can't reliably detect if it's
+        * safe to schedule (e.g. calling printk while holding a spin_lock),
+        * because preempt_disable()/preempt_enable() are just barriers there
+        * and preempt_count() is always 0.
+        *
+        * RCU read sections have a separate preemption counter when
+        * PREEMPT_RCU enabled thus we must take extra care and check
+        * rcu_preempt_depth(), otherwise RCU read sections modify
+        * preempt_count().
+        */
+       console_may_schedule = !oops_in_progress &&
+                       preemptible() &&
+                       !rcu_preempt_depth();
        return 1;
 }
 EXPORT_SYMBOL(console_trylock);