Merge tag 'printk-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/printk...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 5 Aug 2020 05:22:25 +0000 (22:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 5 Aug 2020 05:22:25 +0000 (22:22 -0700)
Pull printk updates from Petr Mladek:

 - Herbert Xu made printk header file self-contained.

 - Andy Shevchenko and Sergey Senozhatsky cleaned up console->setup()
   error handling.

 - Andy Shevchenko did some cleanups (e.g. sparse warning) in vsprintf
   code.

 - Minor documentation updates.

* tag 'printk-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
  lib/vsprintf: Force type of flags value for gfp_t
  lib/vsprintf: Replace custom spec to print decimals with generic one
  lib/vsprintf: Replace hidden BUILD_BUG_ON() with static_assert()
  printk: Make linux/printk.h self-contained
  doc:kmsg: explicitly state the return value in case of SEEK_CUR
  Replace HTTP links with HTTPS ones: vsprintf
  hvc: unify console setup naming
  console: Fix trivia typo 'change' -> 'chance'
  console: Propagate error code from console ->setup()
  tty: hvc: Return proper error code from console ->setup() hook
  serial: sunzilog: Return proper error code from console ->setup() hook
  serial: sunsab: Return proper error code from console ->setup() hook
  mips: Return proper error code from console ->setup() hook

13 files changed:
Documentation/ABI/testing/dev-kmsg
Documentation/core-api/printk-formats.rst
arch/mips/fw/arc/arc_con.c
arch/s390/include/asm/bug.h
drivers/tty/hvc/hvc_xen.c
drivers/tty/hvc/hvsi.c
drivers/tty/serial/sunsab.c
drivers/tty/serial/sunzilog.c
include/linux/printk.h
include/linux/ratelimit.h
include/linux/ratelimit_types.h [new file with mode: 0644]
kernel/printk/printk.c
lib/vsprintf.c

index f307506eb54ce9a44601ba37ba798314049da762..3c0bb76e3417e7ce402378e849d4ee7858ae019c 100644 (file)
@@ -56,6 +56,17 @@ Description: The /dev/kmsg character device node provides userspace access
                  seek after the last record available at the time
                  the last SYSLOG_ACTION_CLEAR was issued.
 
+               Other seek operations or offsets are not supported because of
+               the special behavior this device has. The device allows to read
+               or write only whole variable length messages (records) that are
+               stored in a ring buffer.
+
+               Because of the non-standard behavior also the error values are
+               non-standard. -ESPIPE is returned for non-zero offset. -EINVAL
+               is returned for other operations, e.g. SEEK_CUR. This behavior
+               and values are historical and could not be modified without the
+               risk of breaking userspace.
+
                The output format consists of a prefix carrying the syslog
                prefix including priority and facility, the 64 bit message
                sequence number and the monotonic timestamp in microseconds,
index 8c9aba262b1ea3c082467232169c65167c49b0f9..1beac4719e437f798cd98cd5c31c601a7c721e38 100644 (file)
@@ -317,7 +317,7 @@ colon-separators. Leading zeros are always used.
 
 The additional ``c`` specifier can be used with the ``I`` specifier to
 print a compressed IPv6 address as described by
-http://tools.ietf.org/html/rfc5952
+https://tools.ietf.org/html/rfc5952
 
 Passed by reference.
 
@@ -341,7 +341,7 @@ The additional ``p``, ``f``, and ``s`` specifiers are used to specify port
 flowinfo a ``/`` and scope a ``%``, each followed by the actual value.
 
 In case of an IPv6 address the compressed IPv6 address as described by
-http://tools.ietf.org/html/rfc5952 is being used if the additional
+https://tools.ietf.org/html/rfc5952 is being used if the additional
 specifier ``c`` is given. The IPv6 address is surrounded by ``[``, ``]`` in
 case of additional specifiers ``p``, ``f`` or ``s`` as suggested by
 https://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07
index 365e3913231ef0ed581710b95407685a304063a2..7fdce236b298b609354c109ba6ffbcabafed1427 100644 (file)
@@ -28,7 +28,9 @@ static void prom_console_write(struct console *co, const char *s,
 
 static int prom_console_setup(struct console *co, char *options)
 {
-       return !(prom_flags & PROM_FLAG_USE_AS_CONSOLE);
+       if (prom_flags & PROM_FLAG_USE_AS_CONSOLE)
+               return 0;
+       return -ENODEV;
 }
 
 static struct console arc_cons = {
index 7725f8006fdfb32a9b60b06a6f70c4954f1edafb..0b25f28351edc496ddfe728b169a4700e724cd7f 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _ASM_S390_BUG_H
 #define _ASM_S390_BUG_H
 
-#include <linux/kernel.h>
+#include <linux/compiler.h>
 
 #ifdef CONFIG_BUG
 
index 5ef08905fe05c72167180dfd1cd388e8ccd1f33e..2a0e51a20e342911748ba524d19c03fc99af59fd 100644 (file)
@@ -603,7 +603,7 @@ static void xen_hvm_early_write(uint32_t vtermno, const char *str, int len) { }
 #endif
 
 #ifdef CONFIG_EARLY_PRINTK
-static int __init xenboot_setup_console(struct console *console, char *string)
+static int __init xenboot_console_setup(struct console *console, char *string)
 {
        static struct xencons_info xenboot;
 
@@ -647,7 +647,7 @@ static void xenboot_write_console(struct console *console, const char *string,
 struct console xenboot_console = {
        .name           = "xenboot",
        .write          = xenboot_write_console,
-       .setup          = xenboot_setup_console,
+       .setup          = xenboot_console_setup,
        .flags          = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME,
        .index          = -1,
 };
index 66f95f758be05722d326d34875f994e44431a16c..e8c58f9bd2632c984855276c87a76628dc9c1c64 100644 (file)
@@ -1128,7 +1128,7 @@ static int __init hvsi_console_setup(struct console *console, char *options)
        int ret;
 
        if (console->index < 0 || console->index >= hvsi_count)
-               return -1;
+               return -EINVAL;
        hp = &hvsi_ports[console->index];
 
        /* give the FSP a chance to change the baud rate when we re-open */
index 1eb703c980e054b55b41f0134488316fdc6b7f1a..bab551f46963128acbe1f6aaf389c88f9a84281a 100644 (file)
@@ -886,7 +886,7 @@ static int sunsab_console_setup(struct console *con, char *options)
         * though...
         */
        if (up->port.type != PORT_SUNSAB)
-               return -1;
+               return -EINVAL;
 
        printk("Console: ttyS%d (SAB82532)\n",
               (sunsab_reg.minor - 64) + con->index);
index 103ab8c556e736b46649f2f2469960ecb78e732a..7ea06bbc61973e501c449e517f561f0865819b39 100644 (file)
@@ -1221,7 +1221,7 @@ static int __init sunzilog_console_setup(struct console *con, char *options)
        int baud, brg;
 
        if (up->port.type != PORT_SUNZILOG)
-               return -1;
+               return -EINVAL;
 
        printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n",
               (sunzilog_reg.minor - 64) + con->index, con->index);
index fc8f03c545430292daa322b8dd941d88f951dc2f..34c1a7be3e014ffa75dff86237942dc73bcb16ed 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/kern_levels.h>
 #include <linux/linkage.h>
 #include <linux/cache.h>
+#include <linux/ratelimit_types.h>
 
 extern const char linux_banner[];
 extern const char linux_proc_banner[];
index 8ddf79e9207a9db19a91fd09081f8df3c18eea22..b17e0cd0a30cfb9fc15c23bad511ef82007f7414 100644 (file)
@@ -2,41 +2,10 @@
 #ifndef _LINUX_RATELIMIT_H
 #define _LINUX_RATELIMIT_H
 
-#include <linux/param.h>
+#include <linux/ratelimit_types.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 
-#define DEFAULT_RATELIMIT_INTERVAL     (5 * HZ)
-#define DEFAULT_RATELIMIT_BURST                10
-
-/* issue num suppressed message on exit */
-#define RATELIMIT_MSG_ON_RELEASE       BIT(0)
-
-struct ratelimit_state {
-       raw_spinlock_t  lock;           /* protect the state */
-
-       int             interval;
-       int             burst;
-       int             printed;
-       int             missed;
-       unsigned long   begin;
-       unsigned long   flags;
-};
-
-#define RATELIMIT_STATE_INIT(name, interval_init, burst_init) {                \
-               .lock           = __RAW_SPIN_LOCK_UNLOCKED(name.lock),  \
-               .interval       = interval_init,                        \
-               .burst          = burst_init,                           \
-       }
-
-#define RATELIMIT_STATE_INIT_DISABLED                                  \
-       RATELIMIT_STATE_INIT(ratelimit_state, 0, DEFAULT_RATELIMIT_BURST)
-
-#define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init)                \
-                                                                       \
-       struct ratelimit_state name =                                   \
-               RATELIMIT_STATE_INIT(name, interval_init, burst_init)   \
-
 static inline void ratelimit_state_init(struct ratelimit_state *rs,
                                        int interval, int burst)
 {
@@ -73,9 +42,6 @@ ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags)
 
 extern struct ratelimit_state printk_ratelimit_state;
 
-extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
-#define __ratelimit(state) ___ratelimit(state, __func__)
-
 #ifdef CONFIG_PRINTK
 
 #define WARN_ON_RATELIMIT(condition, state)    ({              \
diff --git a/include/linux/ratelimit_types.h b/include/linux/ratelimit_types.h
new file mode 100644 (file)
index 0000000..b676aa4
--- /dev/null
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_RATELIMIT_TYPES_H
+#define _LINUX_RATELIMIT_TYPES_H
+
+#include <linux/bits.h>
+#include <linux/param.h>
+#include <linux/spinlock_types.h>
+
+#define DEFAULT_RATELIMIT_INTERVAL     (5 * HZ)
+#define DEFAULT_RATELIMIT_BURST                10
+
+/* issue num suppressed message on exit */
+#define RATELIMIT_MSG_ON_RELEASE       BIT(0)
+
+struct ratelimit_state {
+       raw_spinlock_t  lock;           /* protect the state */
+
+       int             interval;
+       int             burst;
+       int             printed;
+       int             missed;
+       unsigned long   begin;
+       unsigned long   flags;
+};
+
+#define RATELIMIT_STATE_INIT(name, interval_init, burst_init) {                \
+               .lock           = __RAW_SPIN_LOCK_UNLOCKED(name.lock),  \
+               .interval       = interval_init,                        \
+               .burst          = burst_init,                           \
+       }
+
+#define RATELIMIT_STATE_INIT_DISABLED                                  \
+       RATELIMIT_STATE_INIT(ratelimit_state, 0, DEFAULT_RATELIMIT_BURST)
+
+#define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init)                \
+                                                                       \
+       struct ratelimit_state name =                                   \
+               RATELIMIT_STATE_INIT(name, interval_init, burst_init)   \
+
+extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
+#define __ratelimit(state) ___ratelimit(state, __func__)
+
+#endif /* _LINUX_RATELIMIT_TYPES_H */
index b71eaf5f5a86375591d480d36bd729b320e141e1..9b75f6bfc3333b9aff77a0f0dc52f5c8e5b67a34 100644 (file)
@@ -943,6 +943,14 @@ out:
        return ret;
 }
 
+/*
+ * Be careful when modifying this function!!!
+ *
+ * Only few operations are supported because the device works only with the
+ * entire variable length messages (records). Non-standard values are
+ * returned in the other cases and has been this way for quite some time.
+ * User space applications might depend on this behavior.
+ */
 static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
 {
        struct devkmsg_user *user = file->private_data;
@@ -2658,7 +2666,7 @@ early_param("keep_bootcon", keep_bootcon_setup);
 static int try_enable_new_console(struct console *newcon, bool user_specified)
 {
        struct console_cmdline *c;
-       int i;
+       int i, err;
 
        for (i = 0, c = console_cmdline;
             i < MAX_CMDLINECONSOLES && c->name[0];
@@ -2681,8 +2689,8 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
                                return 0;
 
                        if (newcon->setup &&
-                           newcon->setup(newcon, c->options) != 0)
-                               return -EIO;
+                           (err = newcon->setup(newcon, c->options)) != 0)
+                               return err;
                }
                newcon->flags |= CON_ENABLED;
                if (i == preferred_console) {
@@ -2695,7 +2703,7 @@ static int try_enable_new_console(struct console *newcon, bool user_specified)
        /*
         * Some consoles, such as pstore and netconsole, can be enabled even
         * without matching. Accept the pre-enabled consoles only when match()
-        * and setup() had a change to be called.
+        * and setup() had a chance to be called.
         */
        if (newcon->flags & CON_ENABLED && c->user_specified == user_specified)
                return 0;
index 259e55895933f795aad4238dc72a5c91ab3dbb2d..c155769559abe27064e609ee80ff60abda8122b9 100644 (file)
@@ -381,6 +381,9 @@ int num_to_str(char *buf, int size, unsigned long long num, unsigned int width)
 #define SMALL  32              /* use lowercase in hex (must be 32 == 0x20) */
 #define SPECIAL        64              /* prefix hex with "0x", octal with "0" */
 
+static_assert(ZEROPAD == ('0' - ' '));
+static_assert(SMALL == ' ');
+
 enum format_type {
        FORMAT_TYPE_NONE, /* Just a string part */
        FORMAT_TYPE_WIDTH,
@@ -507,7 +510,7 @@ char *number(char *buf, char *end, unsigned long long num,
        /* zero or space padding */
        if (!(spec.flags & LEFT)) {
                char c = ' ' + (spec.flags & ZEROPAD);
-               BUILD_BUG_ON(' ' + ZEROPAD != '0');
+
                while (--field_width >= 0) {
                        if (buf < end)
                                *buf = c;
@@ -1934,7 +1937,7 @@ char *flags_string(char *buf, char *end, void *flags_ptr,
                names = vmaflag_names;
                break;
        case 'g':
-               flags = *(gfp_t *)flags_ptr;
+               flags = (__force unsigned long)(*(gfp_t *)flags_ptr);
                names = gfpflag_names;
                break;
        default:
@@ -1976,12 +1979,6 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
        char *buf_start = buf;
        struct property *prop;
        bool has_mult, pass;
-       static const struct printf_spec num_spec = {
-               .flags = SMALL,
-               .field_width = -1,
-               .precision = -1,
-               .base = 10,
-       };
 
        struct printf_spec str_spec = spec;
        str_spec.field_width = -1;
@@ -2021,7 +2018,7 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
                        str_spec.precision = precision;
                        break;
                case 'p':       /* phandle */
-                       buf = number(buf, end, (unsigned int)dn->phandle, num_spec);
+                       buf = number(buf, end, (unsigned int)dn->phandle, default_dec_spec);
                        break;
                case 'P':       /* path-spec */
                        p = fwnode_get_name(of_fwnode_handle(dn));
@@ -2134,7 +2131,7 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
  *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
  * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
  * - 'I[6S]c' for IPv6 addresses printed as specified by
- *       http://tools.ietf.org/html/rfc5952
+ *       https://tools.ietf.org/html/rfc5952
  * - 'E[achnops]' For an escaped buffer, where rules are defined by combination
  *                of the following flags (see string_escape_mem() for the
  *                details):