From 8f73910dd1fc1fa6dc6904ae406b7598cdcd96d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Tue, 30 Jul 2019 00:00:00 +0000 Subject: [PATCH] printk: understand almost all of /proc/sys/kernel/printk --- README.adoc | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/README.adoc b/README.adoc index a9a6033..9bd7afd 100644 --- a/README.adoc +++ b/README.adoc @@ -5511,6 +5511,154 @@ This format is selected by the following boot options: The debug highest level is a bit more magic, see: xref:pr_debug[xrefstyle=full] for more info. +==== /proc/sys/kernel/printk + +The current printk level can be obtained with: + +.... +cat /proc/sys/kernel/printk +.... + +As of `87e846fc1f9c57840e143513ebd69c638bd37aa8` this prints: + +.... +7 4 1 7 +.... + +which contains: + +* `7`: current log level, modifiable by previously mentioned methods +* `4`: documented as: "printk's without a loglevel use this": TODO what does that mean, how to call `printk` without a log level? +* `1`: minimum log level that still prints something (`0` prints nothing) +* `7`: default log level + +We start at the boot time default after boot by default, as can be seen from: + +.... +insmod myprintk.ko +.... + +which outputs something like: + +.... +<1>[ 12.494429] pr_alert +<2>[ 12.494666] pr_crit +<3>[ 12.494823] pr_err +<4>[ 12.494911] pr_warning +<5>[ 12.495170] pr_notice +<6>[ 12.495327] pr_info +.... + +Source: link:kernel_modules/myprintk.c[] + +This proc entry is defined at: https://github.com/torvalds/linux/blob/v5.1/kernel/sysctl.c#L839 + +.... +#if defined CONFIG_PRINTK + { + .procname = "printk", + .data = &console_loglevel, + .maxlen = 4*sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, +.... + +which teaches us that printk can be completely disabled at compile time: + +.... + +config PRINTK + default y + bool "Enable support for printk" if EXPERT + select IRQ_WORK + help + This option enables normal printk support. Removing it + eliminates most of the message strings from the kernel image + and makes the kernel more or less silent. As this makes it + very difficult to diagnose system problems, saying N here is + strongly discouraged. +.... + +`console_loglevel` is defined at: + +.... +#define console_loglevel (console_printk[0]) +.... + +and `console_printk` is an array with 4 ints: + +.... +int console_printk[4] = { + CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */ + MESSAGE_LOGLEVEL_DEFAULT, /* default_message_loglevel */ + CONSOLE_LOGLEVEL_MIN, /* minimum_console_loglevel */ + CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */ +}; +.... + +and then we see that the default is configurable with `CONFIG_CONSOLE_LOGLEVEL_DEFAULT`: + +.... +/* + * Default used to be hard-coded at 7, quiet used to be hardcoded at 4, + * we're now allowing both to be set from kernel config. + */ +#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT +#define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET +.... + +The message loglevel default is explained at: + +.... +/* printk's without a loglevel use this.. */ +#define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT +.... + +The min is just hardcoded to one as you would expect, with some amazing kernel comedy around it: + +.... +/* We show everything that is MORE important than this.. */ +#define CONSOLE_LOGLEVEL_SILENT 0 /* Mum's the word */ +#define CONSOLE_LOGLEVEL_MIN 1 /* Minimum loglevel we let people use */ +#define CONSOLE_LOGLEVEL_DEBUG 10 /* issue debug messages */ +#define CONSOLE_LOGLEVEL_MOTORMOUTH 15 /* You can't shut this one up */ +.... + +We then also learn about the useless `quiet` and `debug` kernel parameters at: + +.... +config CONSOLE_LOGLEVEL_QUIET + int "quiet console loglevel (1-15)" + range 1 15 + default "4" + help + loglevel to use when "quiet" is passed on the kernel commandline. + + When "quiet" is passed on the kernel commandline this loglevel + will be used as the loglevel. IOW passing "quiet" will be the + equivalent of passing "loglevel=" +.... + +which explains the useless reason why that number is special. This is implemented at: + +.... +static int __init debug_kernel(char *str) +{ + console_loglevel = CONSOLE_LOGLEVEL_DEBUG; + return 0; +} + +static int __init quiet_kernel(char *str) +{ + console_loglevel = CONSOLE_LOGLEVEL_QUIET; + return 0; +} + +early_param("debug", debug_kernel); +early_param("quiet", quiet_kernel); +.... + ==== ignore_loglevel ....