diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 16:04:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 16:04:55 -0700 |
commit | d75ae5bdf2353e5c6a1f83da5f6f2d31582f09a3 (patch) | |
tree | de5fc796d1148baaca18497b6f62cc58a6f742e6 | |
parent | 0eb0061381b2bac082cc26d573fc48fe99db3922 (diff) | |
parent | 8bafa2a44ff3647904eaa3c9228bfbd36742b9b4 (diff) |
Merge tag 'printk-for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk
Pull printk updates from Petr Mladek:
- Help userspace log daemons to catch up with a flood of messages. They
will get woken after each message even if the console is far behind
and handled by another process.
- Flush printk safe buffers safely even when panic() happens in the
normal context.
- Fix possible va_list reuse when race happened in printk_safe().
- Remove %pCr printf format to prevent sleeping in the atomic context.
- Misc vsprintf code cleanup.
* tag 'printk-for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk:
printk: drop in_nmi check from printk_safe_flush_on_panic()
lib/vsprintf: Remove atomic-unsafe support for %pCr
serial: sh-sci: Stop using printk format %pCr
thermal: bcm2835: Stop using printk format %pCr
clk: renesas: cpg-mssr: Stop using printk format %pCr
printk: fix possible reuse of va_list variable
printk: wake up klogd in vprintk_emit
vsprintf: Tweak pF/pf comment
lib/vsprintf: Mark expected switch fall-through
lib/vsprintf: Replace space with '_' before crng is ready
lib/vsprintf: Deduplicate pointer_string()
lib/vsprintf: Move pointer_string() upper
lib/vsprintf: Make flag_spec global
lib/vsprintf: Make strspec global
lib/vsprintf: Make dec_spec global
lib/test_printf: Mark big constant with UL
-rw-r--r-- | Documentation/core-api/printk-formats.rst | 3 | ||||
-rw-r--r-- | drivers/clk/renesas/renesas-cpg-mssr.c | 9 | ||||
-rw-r--r-- | drivers/thermal/broadcom/bcm2835_thermal.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/sh-sci.c | 4 | ||||
-rw-r--r-- | kernel/printk/printk.c | 14 | ||||
-rw-r--r-- | kernel/printk/printk_safe.c | 7 | ||||
-rw-r--r-- | lib/test_printf.c | 2 | ||||
-rw-r--r-- | lib/vsprintf.c | 133 |
8 files changed, 71 insertions, 105 deletions
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index eb30efdd2e78..25dc591cb110 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst @@ -419,11 +419,10 @@ struct clk %pC pll1 %pCn pll1 - %pCr 1560000000 For printing struct clk structures. %pC and %pCn print the name (Common Clock Framework) or address (legacy clock framework) of the -structure; %pCr prints the current clock rate. +structure. Passed by reference. diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 4e88e980fb76..69a7c756658b 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -258,8 +258,9 @@ struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, PTR_ERR(clk)); else - dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n", - clkspec->args[0], clkspec->args[1], clk, clk); + dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n", + clkspec->args[0], clkspec->args[1], clk, + clk_get_rate(clk)); return clk; } @@ -326,7 +327,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, if (IS_ERR_OR_NULL(clk)) goto fail; - dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk); + dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); priv->clks[id] = clk; return; @@ -392,7 +393,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, if (IS_ERR(clk)) goto fail; - dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); + dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); priv->clks[id] = clk; priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32); return; diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index a4d6a0e2e993..23ad4f9f2143 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -213,8 +213,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) rate = clk_get_rate(data->clk); if ((rate < 1920000) || (rate > 5000000)) dev_warn(&pdev->dev, - "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n", - data->clk, data->clk); + "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n", + data->clk, rate); /* register of thermal sensor and get info from DT */ tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data, diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b46b146524ce..c181eb37f985 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2724,8 +2724,8 @@ found: dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], PTR_ERR(clk)); else - dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i], - clk, clk); + dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i], + clk, clk_get_rate(clk)); sci_port->clks[i] = IS_ERR(clk) ? NULL : clk; } return 0; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2f4af216bd6e..247808333ba4 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1908,6 +1908,7 @@ asmlinkage int vprintk_emit(int facility, int level, preempt_enable(); } + wake_up_klogd(); return printed_len; } EXPORT_SYMBOL(vprintk_emit); @@ -2289,9 +2290,7 @@ void console_unlock(void) { static char ext_text[CONSOLE_EXT_LOG_MAX]; static char text[LOG_LINE_MAX + PREFIX_MAX]; - static u64 seen_seq; unsigned long flags; - bool wake_klogd = false; bool do_cond_resched, retry; if (console_suspended) { @@ -2335,11 +2334,6 @@ again: printk_safe_enter_irqsave(flags); raw_spin_lock(&logbuf_lock); - if (seen_seq != log_next_seq) { - wake_klogd = true; - seen_seq = log_next_seq; - } - if (console_seq < log_first_seq) { len = sprintf(text, "** %u printk messages dropped **\n", (unsigned)(log_first_seq - console_seq)); @@ -2397,7 +2391,7 @@ skip: if (console_lock_spinning_disable_and_check()) { printk_safe_exit_irqrestore(flags); - goto out; + return; } printk_safe_exit_irqrestore(flags); @@ -2429,10 +2423,6 @@ skip: if (retry && console_trylock()) goto again; - -out: - if (wake_klogd) - wake_up_klogd(); } EXPORT_SYMBOL(console_unlock); diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 3e3c2004bb23..d7d091309054 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -82,6 +82,7 @@ static __printf(2, 0) int printk_safe_log_store(struct printk_safe_seq_buf *s, { int add; size_t len; + va_list ap; again: len = atomic_read(&s->len); @@ -100,7 +101,9 @@ again: if (!len) smp_rmb(); - add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args); + va_copy(ap, args); + add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, ap); + va_end(ap); if (!add) return 0; @@ -278,7 +281,7 @@ void printk_safe_flush_on_panic(void) * Make sure that we could access the main ring buffer. * Do not risk a double release when more CPUs are up. */ - if (in_nmi() && raw_spin_is_locked(&logbuf_lock)) { + if (raw_spin_is_locked(&logbuf_lock)) { if (num_online_cpus() > 1) return; diff --git a/lib/test_printf.c b/lib/test_printf.c index 71ebfa43ad05..cea592f402ed 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -204,7 +204,7 @@ test_string(void) #if BITS_PER_LONG == 64 #define PTR_WIDTH 16 -#define PTR ((void *)0xffff0123456789ab) +#define PTR ((void *)0xffff0123456789abUL) #define PTR_STR "ffff0123456789ab" #define ZEROS "00000000" /* hex 32 zero bits */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 23920c5ff728..a48aaa79d352 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -703,6 +703,22 @@ char *symbol_string(char *buf, char *end, void *ptr, #endif } +static const struct printf_spec default_str_spec = { + .field_width = -1, + .precision = -1, +}; + +static const struct printf_spec default_flag_spec = { + .base = 16, + .precision = -1, + .flags = SPECIAL | SMALL, +}; + +static const struct printf_spec default_dec_spec = { + .base = 10, + .precision = -1, +}; + static noinline_for_stack char *resource_string(char *buf, char *end, struct resource *res, struct printf_spec spec, const char *fmt) @@ -732,21 +748,11 @@ char *resource_string(char *buf, char *end, struct resource *res, .precision = -1, .flags = SMALL | ZEROPAD, }; - static const struct printf_spec dec_spec = { - .base = 10, - .precision = -1, - .flags = 0, - }; static const struct printf_spec str_spec = { .field_width = -1, .precision = 10, .flags = LEFT, }; - static const struct printf_spec flag_spec = { - .base = 16, - .precision = -1, - .flags = SPECIAL | SMALL, - }; /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8) * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ @@ -770,10 +776,10 @@ char *resource_string(char *buf, char *end, struct resource *res, specp = &mem_spec; } else if (res->flags & IORESOURCE_IRQ) { p = string(p, pend, "irq ", str_spec); - specp = &dec_spec; + specp = &default_dec_spec; } else if (res->flags & IORESOURCE_DMA) { p = string(p, pend, "dma ", str_spec); - specp = &dec_spec; + specp = &default_dec_spec; } else if (res->flags & IORESOURCE_BUS) { p = string(p, pend, "bus ", str_spec); specp = &bus_spec; @@ -803,7 +809,7 @@ char *resource_string(char *buf, char *end, struct resource *res, p = string(p, pend, " disabled", str_spec); } else { p = string(p, pend, " flags ", str_spec); - p = number(p, pend, res->flags, flag_spec); + p = number(p, pend, res->flags, default_flag_spec); } *p++ = ']'; *p = '\0'; @@ -913,9 +919,6 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, int cur, rbot, rtop; bool first = true; - /* reused to print numbers */ - spec = (struct printf_spec){ .base = 10 }; - rbot = cur = find_first_bit(bitmap, nr_bits); while (cur < nr_bits) { rtop = cur; @@ -930,13 +933,13 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, } first = false; - buf = number(buf, end, rbot, spec); + buf = number(buf, end, rbot, default_dec_spec); if (rbot < rtop) { if (buf < end) *buf = '-'; buf++; - buf = number(buf, end, rtop, spec); + buf = number(buf, end, rtop, default_dec_spec); } rbot = cur; @@ -1354,11 +1357,9 @@ char *uuid_string(char *buf, char *end, const u8 *addr, return string(buf, end, uuid, spec); } -int kptr_restrict __read_mostly; - static noinline_for_stack -char *restricted_pointer(char *buf, char *end, const void *ptr, - struct printf_spec spec) +char *pointer_string(char *buf, char *end, const void *ptr, + struct printf_spec spec) { spec.base = 16; spec.flags |= SMALL; @@ -1367,6 +1368,15 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, spec.flags |= ZEROPAD; } + return number(buf, end, (unsigned long int)ptr, spec); +} + +int kptr_restrict __read_mostly; + +static noinline_for_stack +char *restricted_pointer(char *buf, char *end, const void *ptr, + struct printf_spec spec) +{ switch (kptr_restrict) { case 0: /* Always print %pK values */ @@ -1378,8 +1388,11 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, * kptr_restrict==1 cannot be used in IRQ context * because its test for CAP_SYSLOG would be meaningless. */ - if (in_irq() || in_serving_softirq() || in_nmi()) + if (in_irq() || in_serving_softirq() || in_nmi()) { + if (spec.field_width == -1) + spec.field_width = 2 * sizeof(ptr); return string(buf, end, "pK-error", spec); + } /* * Only print the real pointer value if the current @@ -1404,7 +1417,7 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, break; } - return number(buf, end, (unsigned long)ptr, spec); + return pointer_string(buf, end, ptr, spec); } static noinline_for_stack @@ -1456,9 +1469,6 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, return string(buf, end, NULL, spec); switch (fmt[1]) { - case 'r': - return number(buf, end, clk_get_rate(clk), spec); - case 'n': default: #ifdef CONFIG_COMMON_CLK @@ -1474,23 +1484,13 @@ char *format_flags(char *buf, char *end, unsigned long flags, const struct trace_print_flags *names) { unsigned long mask; - const struct printf_spec strspec = { - .field_width = -1, - .precision = -1, - }; - const struct printf_spec numspec = { - .flags = SPECIAL|SMALL, - .field_width = -1, - .precision = -1, - .base = 16, - }; for ( ; flags && names->name; names++) { mask = names->mask; if ((flags & mask) != mask) continue; - buf = string(buf, end, names->name, strspec); + buf = string(buf, end, names->name, default_str_spec); flags &= ~mask; if (flags) { @@ -1501,7 +1501,7 @@ char *format_flags(char *buf, char *end, unsigned long flags, } if (flags) - buf = number(buf, end, flags, numspec); + buf = number(buf, end, flags, default_flag_spec); return buf; } @@ -1548,22 +1548,18 @@ char *device_node_gen_full_name(const struct device_node *np, char *buf, char *e { int depth; const struct device_node *parent = np->parent; - static const struct printf_spec strspec = { - .field_width = -1, - .precision = -1, - }; /* special case for root node */ if (!parent) - return string(buf, end, "/", strspec); + return string(buf, end, "/", default_str_spec); for (depth = 0; parent->parent; depth++) parent = parent->parent; for ( ; depth >= 0; depth--) { - buf = string(buf, end, "/", strspec); + buf = string(buf, end, "/", default_str_spec); buf = string(buf, end, device_node_name_for_depth(np, depth), - strspec); + default_str_spec); } return buf; } @@ -1655,20 +1651,6 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, return widen_string(buf, buf - buf_start, end, spec); } -static noinline_for_stack -char *pointer_string(char *buf, char *end, const void *ptr, - struct printf_spec spec) -{ - spec.base = 16; - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = 2 * sizeof(ptr); - spec.flags |= ZEROPAD; - } - - return number(buf, end, (unsigned long int)ptr, spec); -} - static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); static siphash_key_t ptr_key __read_mostly; @@ -1710,13 +1692,13 @@ early_initcall(initialize_ptr_random); /* Maps a pointer to a 32 bit unique identifier. */ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) { + const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; unsigned long hashval; - const int default_width = 2 * sizeof(ptr); if (static_branch_unlikely(¬_filled_random_ptr_key)) { - spec.field_width = default_width; + spec.field_width = 2 * sizeof(ptr); /* string length must be less than default_width */ - return string(buf, end, "(ptrval)", spec); + return string(buf, end, str, spec); } #ifdef CONFIG_64BIT @@ -1729,15 +1711,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) #else hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); #endif - - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = default_width; - spec.flags |= ZEROPAD; - } - spec.base = 16; - - return number(buf, end, hashval, spec); + return pointer_string(buf, end, (const void *)hashval, spec); } /* @@ -1750,10 +1724,10 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) * * Right now we handle: * - * - 'F' For symbolic function descriptor pointers with offset - * - 'f' For simple symbolic function names without offset - * - 'S' For symbolic direct pointers with offset - * - 's' For symbolic direct pointers without offset + * - 'S' For symbolic direct pointers (or function descriptors) with offset + * - 's' For symbolic direct pointers (or function descriptors) without offset + * - 'F' Same as 'S' + * - 'f' Same as 's' * - '[FfSs]R' as above with __builtin_extract_return_addr() translation * - 'B' For backtraced symbolic direct pointers with offset * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] @@ -1850,10 +1824,6 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) * ** When making changes please also update: * Documentation/core-api/printk-formats.rst * - * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 - * function pointers are really function descriptors, which contain a - * pointer to the real address. - * * Note: The default behaviour (unadorned %p) is to hash the address, * rendering it useful as a unique identifier. */ @@ -2129,6 +2099,7 @@ qualifier: case 'x': spec->flags |= SMALL; + /* fall through */ case 'X': spec->base = 16; @@ -3087,8 +3058,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; case 'i': base = 0; + /* fall through */ case 'd': is_sign = true; + /* fall through */ case 'u': break; case '%': |