Skip to content

Commit 3370155

Browse files
cdownpmladek
authored andcommitted
printk: Userspace format indexing support
We have a number of systems industry-wide that have a subset of their functionality that works as follows: 1. Receive a message from local kmsg, serial console, or netconsole; 2. Apply a set of rules to classify the message; 3. Do something based on this classification (like scheduling a remediation for the machine), rinse, and repeat. As a couple of examples of places we have this implemented just inside Facebook, although this isn't a Facebook-specific problem, we have this inside our netconsole processing (for alarm classification), and as part of our machine health checking. We use these messages to determine fairly important metrics around production health, and it's important that we get them right. While for some kinds of issues we have counters, tracepoints, or metrics with a stable interface which can reliably indicate the issue, in order to react to production issues quickly we need to work with the interface which most kernel developers naturally use when developing: printk. Most production issues come from unexpected phenomena, and as such usually the code in question doesn't have easily usable tracepoints or other counters available for the specific problem being mitigated. We have a number of lines of monitoring defence against problems in production (host metrics, process metrics, service metrics, etc), and where it's not feasible to reliably monitor at another level, this kind of pragmatic netconsole monitoring is essential. As one would expect, monitoring using printk is rather brittle for a number of reasons -- most notably that the message might disappear entirely in a new version of the kernel, or that the message may change in some way that the regex or other classification methods start to silently fail. One factor that makes this even harder is that, under normal operation, many of these messages are never expected to be hit. For example, there may be a rare hardware bug which one wants to detect if it was to ever happen again, but its recurrence is not likely or anticipated. This precludes using something like checking whether the printk in question was printed somewhere fleetwide recently to determine whether the message in question is still present or not, since we don't anticipate that it should be printed anywhere, but still need to monitor for its future presence in the long-term. This class of issue has happened on a number of occasions, causing unhealthy machines with hardware issues to remain in production for longer than ideal. As a recent example, some monitoring around blk_update_request fell out of date and caused semi-broken machines to remain in production for longer than would be desirable. Searching through the codebase to find the message is also extremely fragile, because many of the messages are further constructed beyond their callsite (eg. btrfs_printk and other module-specific wrappers, each with their own functionality). Even if they aren't, guessing the format and formulation of the underlying message based on the aesthetics of the message emitted is not a recipe for success at scale, and our previous issues with fleetwide machine health checking demonstrate as much. This provides a solution to the issue of silently changed or deleted printks: we record pointers to all printk format strings known at compile time into a new .printk_index section, both in vmlinux and modules. At runtime, this can then be iterated by looking at <debugfs>/printk/index/<module>, which emits the following format, both readable by humans and able to be parsed by machines: $ head -1 vmlinux; shuf -n 5 vmlinux # <level[,flags]> filename:line function "format" <5> block/blk-settings.c:661 disk_stack_limits "%s: Warning: Device %s is misaligned\n" <4> kernel/trace/trace.c:8296 trace_create_file "Could not create tracefs '%s' entry\n" <6> arch/x86/kernel/hpet.c:144 _hpet_print_config "hpet: %s(%d):\n" <6> init/do_mounts.c:605 prepare_namespace "Waiting for root device %s...\n" <6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n" This mitigates the majority of cases where we have a highly-specific printk which we want to match on, as we can now enumerate and check whether the format changed or the printk callsite disappeared entirely in userspace. This allows us to catch changes to printks we monitor earlier and decide what to do about it before it becomes problematic. There is no additional runtime cost for printk callers or printk itself, and the assembly generated is exactly the same. Signed-off-by: Chris Down <[email protected]> Cc: Petr Mladek <[email protected]> Cc: Jessica Yu <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Cc: John Ogness <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Kees Cook <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Tested-by: Petr Mladek <[email protected]> Reported-by: kernel test robot <[email protected]> Acked-by: Andy Shevchenko <[email protected]> Acked-by: Jessica Yu <[email protected]> # for module.{c,h} Signed-off-by: Petr Mladek <[email protected]> Link: https://lore.kernel.org/r/e42070983637ac5e384f17fbdbe86d19c7b212a5.1623775748.git.chris@chrisdown.name
1 parent f3d75cf commit 3370155

File tree

19 files changed

+353
-24
lines changed

19 files changed

+353
-24
lines changed

MAINTAINERS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14918,6 +14918,11 @@ S: Maintained
1491814918
F: include/linux/printk.h
1491914919
F: kernel/printk/
1492014920

14921+
PRINTK INDEXING
14922+
R: Chris Down <[email protected]>
14923+
S: Maintained
14924+
F: kernel/printk/index.c
14925+
1492114926
PRISM54 WIRELESS DRIVER
1492214927
M: Luis Chamberlain <[email protected]>
1492314928

arch/arm/kernel/entry-v7m.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ __invalid_entry:
2323
adr r0, strerr
2424
mrs r1, ipsr
2525
mov r2, lr
26-
bl printk
26+
bl _printk
2727
#endif
2828
mov r0, sp
2929
bl show_regs

arch/arm/lib/backtrace-clang.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ finished_setup:
202202
1006: adr r0, .Lbad
203203
mov r1, loglvl
204204
mov r2, frame
205-
bl printk
205+
bl _printk
206206
no_frame: ldmfd sp!, {r4 - r9, fp, pc}
207207
ENDPROC(c_backtrace)
208208
.pushsection __ex_table,"a"

arch/arm/lib/backtrace.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ for_each_frame: tst frame, mask @ Check for address exceptions
103103
1006: adr r0, .Lbad
104104
mov r1, loglvl
105105
mov r2, frame
106-
bl printk
106+
bl _printk
107107
no_frame: ldmfd sp!, {r4 - r9, pc}
108108
ENDPROC(c_backtrace)
109109

arch/arm/mach-rpc/io-acorn.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ ENTRY(insl)
2525
ENTRY(outsl)
2626
adr r0, .Liosl_warning
2727
mov r1, lr
28-
b printk
28+
b _printk

arch/arm/vfp/vfphw.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#ifdef DEBUG
2424
stmfd sp!, {r0-r3, ip, lr}
2525
ldr r0, =1f
26-
bl printk
26+
bl _printk
2727
ldmfd sp!, {r0-r3, ip, lr}
2828

2929
.pushsection .rodata, "a"
@@ -38,7 +38,7 @@
3838
stmfd sp!, {r0-r3, ip, lr}
3939
mov r1, \arg
4040
ldr r0, =1f
41-
bl printk
41+
bl _printk
4242
ldmfd sp!, {r0-r3, ip, lr}
4343

4444
.pushsection .rodata, "a"
@@ -55,7 +55,7 @@
5555
mov r2, \arg2
5656
mov r1, \arg1
5757
ldr r0, =1f
58-
bl printk
58+
bl _printk
5959
ldmfd sp!, {r0-r3, ip, lr}
6060

6161
.pushsection .rodata, "a"

arch/ia64/include/uapi/asm/cmpxchg.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,9 @@ extern long ia64_cmpxchg_called_with_bad_pointer(void);
143143
do { \
144144
if (_cmpxchg_bugcheck_count-- <= 0) { \
145145
void *ip; \
146-
extern int printk(const char *fmt, ...); \
146+
extern int _printk(const char *fmt, ...); \
147147
ip = (void *) ia64_getreg(_IA64_REG_IP); \
148-
printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
148+
_printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
149149
break; \
150150
} \
151151
} while (0)

arch/openrisc/kernel/entry.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ EXCEPTION_ENTRY(_external_irq_handler)
551551
l.movhi r3,hi(42f)
552552
l.ori r3,r3,lo(42f)
553553
l.sw 0x0(r1),r3
554-
l.jal printk
554+
l.jal _printk
555555
l.sw 0x4(r1),r4
556556
l.addi r1,r1,0x8
557557

@@ -681,8 +681,8 @@ _syscall_debug:
681681
l.sw -4(r1),r27
682682
l.sw -8(r1),r11
683683
l.addi r1,r1,-8
684-
l.movhi r27,hi(printk)
685-
l.ori r27,r27,lo(printk)
684+
l.movhi r27,hi(_printk)
685+
l.ori r27,r27,lo(_printk)
686686
l.jalr r27
687687
l.nop
688688
l.addi r1,r1,8

arch/powerpc/kernel/head_fsl_booke.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,7 @@ KernelSPE:
858858
ori r3,r3,87f@l
859859
mr r4,r2 /* current */
860860
lwz r5,_NIP(r1)
861-
bl printk
861+
bl _printk
862862
#endif
863863
b interrupt_return
864864
#ifdef CONFIG_PRINTK

arch/um/include/shared/user.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ extern void panic(const char *fmt, ...)
3838
#define UM_KERN_CONT KERN_CONT
3939

4040
#ifdef UML_CONFIG_PRINTK
41-
extern int printk(const char *fmt, ...)
41+
#define printk(...) _printk(__VA_ARGS__)
42+
extern int _printk(const char *fmt, ...)
4243
__attribute__ ((format (printf, 1, 2)));
4344
#else
4445
static inline int printk(const char *fmt, ...)

0 commit comments

Comments
 (0)