Merge tag 'printk-for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/printk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Oct 2022 18:24:19 +0000 (11:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 10 Oct 2022 18:24:19 +0000 (11:24 -0700)
Pull printk updates from Petr Mladek:

 - Initialize pointer hashing using the system workqueue. It avoids
   taking locks in printk()/vsprintf() code path

 - Misc code clean up

* tag 'printk-for-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  printk: Mark __printk percpu data ready __ro_after_init
  printk: Remove bogus comment vs. boot consoles
  printk: Remove write only variable nr_ext_console_drivers
  printk: Declare log_wait properly
  printk: Make pr_flush() static
  lib/vsprintf: Initialize vsprintf's pointer hash once the random core is ready.
  lib/vsprintf: Remove static_branch_likely() from __ptr_to_hashval().
  lib/vnsprintf: add const modifier for param 'bitmap'

fs/proc/kmsg.c
include/linux/printk.h
include/linux/syslog.h
kernel/printk/printk.c
lib/vsprintf.c

index 592e6dc7c1102b54ea136b21e9b42b711ba09702..2fc92a13f9f8f46a1f51a6882cddbd0c1125e184 100644 (file)
@@ -17,8 +17,6 @@
 
 #include <asm/io.h>
 
-extern wait_queue_head_t log_wait;
-
 static int kmsg_open(struct inode * inode, struct file * file)
 {
        return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_PROC);
index cf7d666ab1f8e38dec0f2edd8272def486507f01..8c81806c2e99f906184269505fcc2a549dd25a28 100644 (file)
@@ -169,8 +169,6 @@ extern void __printk_safe_exit(void);
 #define printk_deferred_enter __printk_safe_enter
 #define printk_deferred_exit __printk_safe_exit
 
-extern bool pr_flush(int timeout_ms, bool reset_on_progress);
-
 /*
  * Please don't use printk_ratelimit(), because it shares ratelimiting state
  * with all other unrelated printk_ratelimit() callsites.  Instead use
@@ -221,11 +219,6 @@ static inline void printk_deferred_exit(void)
 {
 }
 
-static inline bool pr_flush(int timeout_ms, bool reset_on_progress)
-{
-       return true;
-}
-
 static inline int printk_ratelimit(void)
 {
        return 0;
index 86af908e26633f9dda7ab6cf7300badb7a4d2321..955f80e34d4fda361fd120907930d4595842ca8a 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _LINUX_SYSLOG_H
 #define _LINUX_SYSLOG_H
 
+#include <linux/wait.h>
+
 /* Close the log.  Currently a NOP. */
 #define SYSLOG_ACTION_CLOSE          0
 /* Open the log. Currently a NOP. */
@@ -35,5 +37,6 @@
 #define SYSLOG_FROM_PROC             1
 
 int do_syslog(int type, char __user *buf, int count, int source);
+extern wait_queue_head_t log_wait;
 
 #endif /* _LINUX_SYSLOG_H */
index a1a81fd9889bb35d54102ce3cbc84a76cca24020..e4f1e7478b521a7028ac8cd658cc54ae5e917bc0 100644 (file)
@@ -220,9 +220,6 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
 }
 #endif /* CONFIG_PRINTK && CONFIG_SYSCTL */
 
-/* Number of registered extended console drivers. */
-static int nr_ext_console_drivers;
-
 /*
  * Helper macros to handle lockdep when locking/unlocking console_sem. We use
  * macros instead of functions so that _RET_IP_ contains useful information.
@@ -433,7 +430,7 @@ static struct printk_ringbuffer *prb = &printk_rb_static;
  * per_cpu_areas are initialised. This variable is set to true when
  * it's safe to access per-CPU data.
  */
-static bool __printk_percpu_data_ready __read_mostly;
+static bool __printk_percpu_data_ready __ro_after_init;
 
 bool printk_percpu_data_ready(void)
 {
@@ -2296,6 +2293,7 @@ asmlinkage __visible int _printk(const char *fmt, ...)
 }
 EXPORT_SYMBOL(_printk);
 
+static bool pr_flush(int timeout_ms, bool reset_on_progress);
 static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
 
 #else /* CONFIG_PRINTK */
@@ -2330,6 +2328,7 @@ static void call_console_driver(struct console *con, const char *text, size_t le
 {
 }
 static bool suppress_message_printing(int level) { return false; }
+static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; }
 static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
 
 #endif /* CONFIG_PRINTK */
@@ -3186,9 +3185,6 @@ void register_console(struct console *newcon)
                console_drivers->next = newcon;
        }
 
-       if (newcon->flags & CON_EXTENDED)
-               nr_ext_console_drivers++;
-
        newcon->dropped = 0;
        if (newcon->flags & CON_PRINTBUFFER) {
                /* Get a consistent copy of @syslog_seq. */
@@ -3213,9 +3209,6 @@ void register_console(struct console *newcon)
        if (bootcon_enabled &&
            ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
            !keep_bootcon) {
-               /* We need to iterate through all boot consoles, to make
-                * sure we print everything out, before we unregister them.
-                */
                for_each_console(con)
                        if (con->flags & CON_BOOT)
                                unregister_console(con);
@@ -3254,9 +3247,6 @@ int unregister_console(struct console *console)
        if (res)
                goto out_disable_unlock;
 
-       if (console->flags & CON_EXTENDED)
-               nr_ext_console_drivers--;
-
        /*
         * If this isn't the last console and it has CON_CONSDEV set, we
         * need to set it on the next preferred console.
@@ -3438,11 +3428,10 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
  * Context: Process context. May sleep while acquiring console lock.
  * Return: true if all enabled printers are caught up.
  */
-bool pr_flush(int timeout_ms, bool reset_on_progress)
+static bool pr_flush(int timeout_ms, bool reset_on_progress)
 {
        return __pr_flush(NULL, timeout_ms, reset_on_progress);
 }
-EXPORT_SYMBOL(pr_flush);
 
 /*
  * Delayed printk version, for scheduler-internal messages:
index c414a8d9f1ea912a3fe2cba5e4d8abc9bbeb83bb..24f37bab8bc1f7a9ae5c533e6f155fa2aa30e83b 100644 (file)
@@ -750,37 +750,42 @@ static int __init debug_boot_weak_hash_enable(char *str)
 }
 early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable);
 
-static DEFINE_STATIC_KEY_FALSE(filled_random_ptr_key);
+static bool filled_random_ptr_key __read_mostly;
+static siphash_key_t ptr_key __read_mostly;
+static void fill_ptr_key_workfn(struct work_struct *work);
+static DECLARE_DELAYED_WORK(fill_ptr_key_work, fill_ptr_key_workfn);
 
-static void enable_ptr_key_workfn(struct work_struct *work)
+static void fill_ptr_key_workfn(struct work_struct *work)
 {
-       static_branch_enable(&filled_random_ptr_key);
+       if (!rng_is_initialized()) {
+               queue_delayed_work(system_unbound_wq, &fill_ptr_key_work, HZ  * 2);
+               return;
+       }
+
+       get_random_bytes(&ptr_key, sizeof(ptr_key));
+
+       /* Pairs with smp_rmb() before reading ptr_key. */
+       smp_wmb();
+       WRITE_ONCE(filled_random_ptr_key, true);
+}
+
+static int __init vsprintf_init_hashval(void)
+{
+       fill_ptr_key_workfn(NULL);
+       return 0;
 }
+subsys_initcall(vsprintf_init_hashval)
 
 /* Maps a pointer to a 32 bit unique identifier. */
 static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
 {
-       static siphash_key_t ptr_key __read_mostly;
        unsigned long hashval;
 
-       if (!static_branch_likely(&filled_random_ptr_key)) {
-               static bool filled = false;
-               static DEFINE_SPINLOCK(filling);
-               static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
-               unsigned long flags;
-
-               if (!system_unbound_wq || !rng_is_initialized() ||
-                   !spin_trylock_irqsave(&filling, flags))
-                       return -EAGAIN;
-
-               if (!filled) {
-                       get_random_bytes(&ptr_key, sizeof(ptr_key));
-                       queue_work(system_unbound_wq, &enable_ptr_key_work);
-                       filled = true;
-               }
-               spin_unlock_irqrestore(&filling, flags);
-       }
+       if (!READ_ONCE(filled_random_ptr_key))
+               return -EBUSY;
 
+       /* Pairs with smp_wmb() after writing ptr_key. */
+       smp_rmb();
 
 #ifdef CONFIG_64BIT
        hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);
@@ -1189,7 +1194,7 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec,
 }
 
 static noinline_for_stack
-char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
+char *bitmap_string(char *buf, char *end, const unsigned long *bitmap,
                    struct printf_spec spec, const char *fmt)
 {
        const int CHUNKSZ = 32;
@@ -1233,7 +1238,7 @@ char *bitmap_string(char *buf, char *end, unsigned long *bitmap,
 }
 
 static noinline_for_stack
-char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap,
+char *bitmap_list_string(char *buf, char *end, const unsigned long *bitmap,
                         struct printf_spec spec, const char *fmt)
 {
        int nr_bits = max_t(int, spec.field_width, 0);