Printk Index

There are many ways to monitor the state of the system. One importantsource of information is the system log. It provides a lot of information,including more or less important warnings and error messages.

There are monitoring tools that filter and take action based on messageslogged.

The kernel messages are evolving together with the code. As a result,particular kernel messages are not KABI and never will be!

It is a huge challenge for maintaining the system log monitors. It requiresknowing what messages were updated in a particular kernel version and why.Finding these changes in the sources would require non-trivial parsers.Also it would require matching the sources with the binary kernel whichis not always trivial. Various changes might be backported. Various kernelversions might be used on different monitored systems.

This is where the printk index feature might become useful. It providesa dump of printk formats used all over the source code used for the kerneland modules on the running system. It is accessible at runtime via debugfs.

The printk index helps to find changes in the message formats. Also it helpsto track the strings back to the kernel sources and the related commit.

User Interface

The index of printk formats are split in into separate files. The files arenamed according to the binaries where the printk formats are built-in. Thereis always “vmlinux” and optionally also modules, for example:

/sys/kernel/debug/printk/index/vmlinux/sys/kernel/debug/printk/index/ext4/sys/kernel/debug/printk/index/scsi_mod

Note that only loaded modules are shown. Also printk formats from a modulemight appear in “vmlinux” when the module is built-in.

The content is inspired by the dynamic debug interface and looks like:

$> head -1 /sys/kernel/debug/printk/index/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"

, where the meaning is:

  • level:

    log level value: 0-7 for particular severity, -1 as default,‘c’ as continuous line without an explicit log level

  • flags:

    optional flags: currently only ‘c’ for KERN_CONT

  • filename:line:

    source filename and line number of the relatedprintk() call. Note that there are many wrappers, for example,pr_warn(),pr_warn_once(),dev_warn().

  • function:

    function name where theprintk() call is used.

  • format:

    format string

The extra information makes it a bit harder to find differencesbetween various kernels. Especially the line number might changevery often. On the other hand, it helps a lot to confirm thatit is the same string or find the commit that is responsiblefor eventual changes.

printk() Is Not a Stable KABI

Several developers are afraid that exporting all these implementationdetails into the user space will transform particularprintk() callsinto KABI.

But it is exactly the opposite.printk() calls must _not_ be KABI.And the printk index helps user space tools to deal with this.

Subsystem specific printk wrappers

The printk index is generated using extra metadata that are stored ina dedicated .elf section “.printk_index”. It is achieved using macrowrappers doing__printk_index_emit() together with the realprintk()call. The same technique is used also for the metadata used bythe dynamic debug feature.

The metadata are stored for a particular message only when it is printedusing these special wrappers. It is implemented for the commonlyusedprintk() calls, including, for example,pr_warn(), orpr_once().

Additional changes are necessary for various subsystem specific wrappersthat call the originalprintk() via a common helper function. These needstheir own wrappers adding__printk_index_emit().

Only few subsystem specific wrappers have been updated so far,for example,dev_printk(). As a result, the printk formats fromsome subsystems can be missing in the printk index.

Subsystem specific prefix

The macropr_fmt() macro allows to define a prefix that is printedbefore the string generated by the relatedprintk() calls.

Subsystem specific wrappers usually add even more complicatedprefixes.

These prefixes can be stored into the printk index metadataby an optional parameter of__printk_index_emit(). The debugfsinterface might then show the printk formats including these prefixes.For example, drivers/acpi/osl.c contains:

#define pr_fmt(fmt) "ACPI: OSL: " fmtstatic int __init acpi_no_auto_serialize_setup(char *str){      acpi_gbl_auto_serialize_methods = FALSE;      pr_info("Auto-serialization disabled\n");      return 1;}

This results in the following printk index entry:

<6> drivers/acpi/osl.c:1410 acpi_no_auto_serialize_setup "ACPI: auto-serialization disabled\n"

It helps matching messages from the real log with printk index.Then the source file name, line number, and function name canbe used to match the string with the source code.