Zack's Kernel News

Zack's Kernel News

Article from Issue 222/2019

Chronicler Zack Brown reports on printk() wrangling, persistent memory as a generalized resource, making Kernel headers available on running systems, and Kernel licensing Hell. 

printk() Wrangling

Everyone hates the printk() function, because it's supposed to do something very simple – print output to the console – but in order to do that it has to overcome tremendous obstacles, like producing its output while the system itself is in the very midst of total destruction. Unlike other functions, printk() can't rely on any other part of the system actually working. At least, that's the ideal.

John Ogness recently tried to improve matters. Specifically, among other things, he wanted to free printk() from the constraint of requiring a global lock. He wanted to make it pre-emptible, so that even the deep, dark parts of the kernel that absolutely needed to be able to interrupt everything could still call printk() in times of crisis.

It's a worthy goal. If those deep, dark parts of the kernel can't use printk(), then they can't report what went wrong if they were involved in a system crash. Making printk() pre-emptible would allow every nook and cranny of the kernel to give relevant information that could help to debug the crash.

But it's not so simple. As Sergey Senozhatsky pointed out, if it's possible for printk() to be interrupted, then it's also possible for the very cause of the crash to interrupt printk() before printk() can finish making its final report on that cause. In this case, instead of preserving that final piece of debugging information, it would simply be lost.

John explained that, in fact, his patches implemented two separate cases for printk(). In most cases, printk() would be pre-emptible and would be used for plain old system messages of no particular importance. But if the system started to crash, printk() would revert to its old method of locking out all interruptions in order to use the final microseconds of life to give its best guess as to what happened.

John's code included other improvements. Traditionally, printk() timestamps were taken from the end of the printk() operation, even though printk() might have been waiting for a long time before obtaining its global lock and creating its output. John's code changed this so that the timestamp would be calculated by calling the routine that actually invoked printk() – a more accurate representation of when the reported event actually occurred.

The discussion was fairly short, but the patch may have trouble making it into the kernel. John's code does more than simply speed up printk() and make it more reliable; it also changes some of the philosophy behind printk(), from a general logging tool to a tool that requires more thought and consideration from the user. The sticking point is the new concept that some messages have a higher priority than others and that printk() will actually behave differently depending on the type of message it tries to output.

Persistent Memory as Generalized Resource

Dave Hansen recently lamented the fact that persistent RAM, which retains its state across reboots, could not easily be used as regular RAM when needed. Instead, applications had to be coded up special to recognize and use persistent memory. Dave felt that if the user didn't care about persistence, then there should be no obstacle to simply using persistent RAM as regular RAM, with no special coding needed.

There's some slight controversy about this. Intel in particular, as Jeff Moyer pointed out, has already implemented memory modes for its Optane RAM chips to let the system choose to treat the chips either as regular memory or as persistent memory. Presto, no problem.

But this wasn't good enough for Dave, nor for Keith Busch, who pointed out that an architecture-specific solution would only apply to a specific chip or family of chips rather than providing general support for all persistent RAM chips that might come along.

Dave's idea was to write a single driver that would detect all persistent RAM chips and make them available to the kernel as regular memory. And – in response to Keith pointing out that persistent RAM tended to be slower than regular RAM – Dave's code would prioritize faster RAM and only use the slower persistent chips when no faster option was available.

Meanwhile, Dave had nothing bad to say about Intel's memory modes – he saw memory modes as complementary to his own work. However, he saw his own code as providing a generalized solution for chips that didn't implement their own memory mode support. And beyond that, he did point out that memory modes weren't as flexible as his proposed driver.

For example, his driver could allocate just a portion of persistent RAM to be used as regular RAM, leaving the rest available as persistent RAM to any application that was written to make use of it. Also, Dave said, his driver would remain able to identify persistent RAM that was made available as regular RAM, so that applications could decide whether to use it or plain RAM chips, which tended to be faster. Memory modes allowed no such distinction, forcing applications to use RAM without knowing whether it was faster or slower.

No decision was made on Dave's patches per se during the discussion, but it's clear that something like these patches will make it into the kernel at some point. Ultimately, the entire Linux kernel – and all operating system kernels throughout the universe – are resource management tools. As new resources become available, and as existing resources splinter off into diverse categories of related resources, Linux will inevitably come to recognize them and provide whatever sort of access is most useful to user code.

Making Kernel Headers Available on Running Systems

Developers have plenty of opportunity to compile user code that interacts with the operating system kernel, but this requires having the running kernel's header files available for the compiler to read. So, anyone wanting to write code to interoperate with the kernel must install the Linux kernel source for that kernel version. That can be a bit of a time suck, especially if you're writing software to be compiled on a wide array of machines that are each running their own kernel version.

Joel Fernandes thought that it would be nice if the kernel simply stored its header files at compile time and automatically made them available via a /proc subdirectory. Then it wouldn't be necessary to determine which kernel was running and subsequently arrange installing those sources in order to develop your project.

The idea did not appeal to Christoph Hellwig, who thought it as a complete waste of memory. Storing the kernel headers forever in RAM, he said, would only deplete system resources. He felt a better idea would be to simply have the build system produce a compressed archive and unpack it at the appropriate time during bootup.

Greg Kroah-Hartman, on the other hand, said there was nothing wasteful about Joel writing a module to export the kernel headers, given that users were not obliged to load that module. Also, he pointed out that there was already precedent for doing something along the same lines, given that /proc/config.gz was stored in RAM and contained the kernel's build configuration options.

People like Daniel Colascione were more than happy to sacrifice RAM on the altar of easily available kernel headers. Daniel was thrilled at how much easier Joel's module would make his various kernel experiments.

However, H. Peter Anvin sided with Christoph, saying that even though Greg was right that the user could choose not to load the module, there was still no justification for building those header files into the kernel in the way Joel proposed. Peter felt that simply constructing a compressed filesystem and mounting it as needed was a much simpler solution that accomplished all the same goals.

There was no immediate resolution, though the disagreement was between several relatively heavyweight kernel hackers. I'd expect Linus Torvalds to let them duke it out amongst themselves for awhile before issuing a ruling.

Ultimately though, the disagreement seemed to be over the best implementation and not over whether to have the feature at all. So, especially given how excited the feature made someone like Daniel, it seems as though something along the lines of Joel's idea will get into the kernel at some point.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Kernel News

    Zack Brown reports on fixing printk() bit by bit, kernel internationalization (or not), and kernel encryption and secure boot. 

  • Kernel News

    Zack Brown discusses implementing digital rights management in-kernel, improving lighting controls, and updating printk().

  • Kernel News

    This month in Kernel News: Shared Processes with Hyper-Threading; Cleaning Up printk(); and Rust in the Kernel.

  • Kernel News

    Zack Brown discusses preventing the kernel from tainting, encrypting printk() output, and a new kernel bug reporting bot. 

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More