Re: [RFC/PATCH] Documentation of kernel messages



On Wed, 13 Jun 2007 17:06:57 +0200 holzheu <holzheu@xxxxxxxxxxxxxxxxxx> wrote:
Greetings,

The operation of a Linux system sometimes requires to decode the
meaning of a specific kernel message, e.g. an error message of a
driver. Especially on our mainframe zSeries platform system
administrators want to have descriptions for Linux kernel messages.
They are used to that, because all other operating systems on that
platform like z/OS, z/VM or z/VSE have message catalogs with detailed
descriptions about the semantics of the messages.

In general we think, that also for Linux it is a good thing to have
documentation for the most important kernel/driver messages. Even
kernel hackers not always are aware of the meaning of kernel messages
for components, which they don't know in detail. Most of the messages
are self explaining but sometimes you get something like "Clocksource
tsc unstable (delta = 7304132729 ns)" and you wonder if your system is
going to explode.

Unfortunately currently there is no general infrastructure in the Linux
kernel for the documentation of messages. I worked on a proposal, how
that could be implemented in an easy way using the already existing
kernel-doc infrastructure and using printk. The proposal is as follows

1. We use message identifiers in order to map messages to message
descriptions. A message identifier consists out of a component name and
within that component unique message number.

2. Messages and message descriptions are maintained together in the
kernel sources in order to keep them up to date. Messages catalog are
generated automatically for exactly one kernel level.

3. A special tool checks, if messages are not documented or if there
are message descriptions without corresponding messages.

4. We use the already existing kernel-doc tool to generate an online
message catalog or e.g. a pdf for offline documentation.

Current prototype implementation:
=================================

The structure of a kernel message is: <component>.<msg number>: <msg>

* component: Name of the kernel or driver component e.g. "pci", "ide",
etc.
* msg number: Within the component unique number of a kernel message.
* msg: printk message

New macros KMSG_ERR(), KMSG_WARN(), etc. are defined, which have to be
used in printk. These macros have as parameter the message number and
are using a per c-file defined macro KMSG_COMPONENT.

Example: Define message 2 in component "kmsgtest":

#define KMSG_COMPONENT "kmsgtest"

void f(void)
{
printk(KMSG_ERR(1) "device %x not online\n", devno);
}

The output of that kernel message would be:
"kmsgtest.1: device 4711 not online"

The messages have to be documented within the C source file
in the following way:

/**
* message
* @0: device number of device.
*
* Description:
* An operation has been performed on the msgtest device, but the
* device has not been set online. Therefore the operation failed
*
* User Response:
* Operator should set device online.
* Issue "chccwdev -e <device number>".
*
*/

KMSG_DOC(kmsgtest, 2, "Device %x not online");

I created a patch for the kernel-doc tool so it can be used to generate
a catalog of all kernel messages:

kernel-doc -man kmsgtest.c > kmsgtest.2
man ./kmsgtest.2

# Kernel API(9) Linux Messages Kernel API(9)
#
# MESSAGE:
# kmsgtest.2: "device %x not online"
#
# Parameter:
# 1 Device number of device.
#
# Description:
# An operation has been performed on the msgtest device, but
# the device has not been set online. Therefore the operation failed.
#
# User Response:
# Operator should set device online.
# Issue "chccwdev -e <device number>".
#
# May 2007 kmsgtest.2 Kernel API(9)

A nice thing would be to include the online kernel message catalog in
the kernel rpm. One possibility for that would be to have one man page
per message. If an operator finds the message kmsgtest.2 in
var/log/messages and wants to know what the message means, he simply
issues "man kmsgtest.2" and gets the description.

To ensure that all messages are documented and there are no message
descriptions without corresponding messages, a checker tool is
provided. To enable message checking, in the toplevel Makefile the
following has to be added:

CHECK = scripts/kmsg_check.pl check

To enable message checking during kernel build, the "C" option has
to be used:

make modules C=1
CHK include/linux/version.h
CHK include/linux/utsrelease.h
CHECK drivers/kmsgtest/kmsgtest.c
drivers/kmsgtest/kmsgtest.c: Missing description for: kmsgtest.1
drivers/kmsgtest/kmsgtest.c: Description without message for: kmsgtest.3

Please note, that the patch for the kernel-doc and kmsg-doc tools
is just a prototype and is neither complete nor perfect.

Michael

Acked-by: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>
Acked-by: Heiko Carstens <heiko.carstens@xxxxxxxxxx>
Signed-off-by: Michael Holzheu <holzheu@xxxxxxxxxxxxxxxxxxx>

Your proposal is similar to one I made to some Japanese developers
earlier this year. I was more modest, proposing that we

- add an enhanced printk

xxprintk(msgid, KERN_ERR "some text %d\n", some_number);

- An externally managed database will provide translations, diagnostics,
remedial actions, etc, keyed off the msgid string

- Format and management of the msgid hasn't been clearly identified yet
as far as I know. But all we really need is that each ID be unique,
kernel-wide. We develop a simple tool which can check the whole tree
for duplicated msgids.

- From a practical day-to-day POV what this means is that a person
from the kernel-messages team will prepare a patch for your driver
which adds the msgids and you the driver author should take care not
to break the tagging.

This is deliberately designed to be minimum-impact upon general
developers. We want a system in place where driver/fs/etc developers
can concentrate on what they do, and kernel-message developers can
as independently as possibe take care of what _they_ do.

- A project has started up and there is a mailing list (cc'ed here) and
meetings are happening at the LF collaboration summit this week.

Please see https://lists.linux-foundation.org/mailman/listinfo/lf_kernel_messages
and don't miss the next conference call ;)

(argh. The lf_kernel_messages archives are subscriber-only and it could be that
only members can post to it. Oh well. Please subscribe, and review the archives)


Makefile | 5
drivers/Makefile | 1
drivers/kmsgtest/Makefile | 5
drivers/kmsgtest/kmsgtest.c | 59 +++++++++++
include/linux/kmsg.h | 32 ++++++
scripts/kernel-doc | 116 +++++++++++++++++++++-
scripts/kmsg-doc | 231 ++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 445 insertions(+), 4 deletions(-)

diff -Naur linux-2.6.21/Makefile linux-2.6.21-kmsg/Makefile
--- linux-2.6.21/Makefile 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-kmsg/Makefile 2007-06-05 15:17:51.000000000 +0200
@@ -293,9 +293,8 @@
DEPMOD = /sbin/depmod
KALLSYMS = scripts/kallsyms
PERL = perl
-CHECK = sparse
-
-CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise $(CF)
+CHECK = scripts/kmsg-doc check
+CHECKFLAGS =
MODFLAGS = -DMODULE
CFLAGS_MODULE = $(MODFLAGS)
AFLAGS_MODULE = $(MODFLAGS)
diff -Naur linux-2.6.21/drivers/Makefile linux-2.6.21-kmsg/drivers/Makefile
--- linux-2.6.21/drivers/Makefile 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-kmsg/drivers/Makefile 2007-06-05 15:17:51.000000000 +0200
@@ -8,6 +8,7 @@
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
+obj-m += kmsgtest/
obj-y += video/
obj-$(CONFIG_ACPI) += acpi/
# PnP must come after ACPI since it will eventually need to check if acpi
diff -Naur linux-2.6.21/drivers/kmsgtest/Makefile linux-2.6.21-kmsg/drivers/kmsgtest/Makefile
--- linux-2.6.21/drivers/kmsgtest/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21-kmsg/drivers/kmsgtest/Makefile 2007-06-05 15:17:51.000000000 +0200
@@ -0,0 +1,5 @@
+#
+# Makefile for kernel message test module
+#
+
+obj-m += kmsgtest.o
diff -Naur linux-2.6.21/drivers/kmsgtest/kmsgtest.c linux-2.6.21-kmsg/drivers/kmsgtest/kmsgtest.c
--- linux-2.6.21/drivers/kmsgtest/kmsgtest.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21-kmsg/drivers/kmsgtest/kmsgtest.c 2007-06-05 15:17:51.000000000 +0200
@@ -0,0 +1,59 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kmsg.h>
+
+static int devno = 0x4711;
+static int status = 1;
+
+#define KMSG_COMPONENT "kmsgtest"
+
+static int __init kmsgtest_init(void)
+{
+ printk(KMSG_INFO(1) "device %x has status %i\n", devno, status);
+ printk(KMSG_ERR(2) "device %x not online\n", devno);
+
+ return 0;
+}
+
+static void __exit kmsgtest_exit(void)
+{
+ printk("kmsgtest module exit\n");
+}
+
+module_init(kmsgtest_init);
+module_exit(kmsgtest_exit);
+
+/**
+ * message
+ * @0: Device number of device
+ * @1: Status of device
+ *
+ * Description:
+ * Information message about the status of our virtual msgtest device. The
+ * following values for the status parameter are available.
+ *
+ * 0 - Device is offline
+ *
+ * 1 - Device is online
+ *
+ * 2 - Device is broken
+ *
+ * User Response:
+ * If device is broken, replace it or fix it.
+ */
+
+KMSG_DOC(kmsgtest, 1, "device %x has status %i");
+
+/**
+ * message
+ * @0: Device number of device.
+ *
+ * Description:
+ * An operation has been performed on the msgtest device, but the device has
+ * not been set online. Therefore the operation failed.
+ *
+ * User Response:
+ * Operator should set device online. Issue "chccwdev -e <device number>".
+ */
+
+KMSG_DOC(kmsgtest, 2, "device %x not online");
diff -Naur linux-2.6.21/include/linux/kmsg.h linux-2.6.21-kmsg/include/linux/kmsg.h
--- linux-2.6.21/include/linux/kmsg.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21-kmsg/include/linux/kmsg.h 2007-06-05 15:17:51.000000000 +0200
@@ -0,0 +1,32 @@
+#ifndef _LINUX_KMSG_H
+#define _LINUX_KMSG_H
+
+#ifdef __KMSG_CHECKER
+
+#define KMSG_EMERG(num) __KMSG_CHECK(EMERG, num)
+#define KMSG_ALERT(num) __KMSG_CHECK(ALERT, num)
+#define KMSG_CRIT(num) __KMSG_CHECK(CRIT, num)
+#define KMSG_ERR(num) __KMSG_CHECK(ERR, num)
+#define KMSG_WARNING(num) __KMSG_CHECK(WARNING, num)
+#define KMSG_NOTICE(num) __KMSG_CHECK(NOTICE, num)
+#define KMSG_INFO(num) __KMSG_CHECK(INFO, num)
+#define KMSG_DEBUG(num) __KMSG_CHECK(DEBUG, num)
+
+#define KMSG_DOC(comp, num, str) __KMSG_DOC(comp, num, str)
+
+#else
+
+#define KMSG_EMERG(num) KERN_EMERG KMSG_COMPONENT "." #num ": "
+#define KMSG_ALERT(num) KERN_ALERT KMSG_COMPONENT "." #num ": "
+#define KMSG_CRIT(num) KERN_CRIT KMSG_COMPONENT "." #num ": "
+#define KMSG_ERR(num) KERN_ERR KMSG_COMPONENT "." #num ": "
+#define KMSG_WARNING(num) KERN_WARNING KMSG_COMPONENT "." #num ": "
+#define KMSG_NOTICE(num) KERN_NOTICE KMSG_COMPONENT "." #num ": "
+#define KMSG_INFO(num) KERN_INFO KMSG_COMPONENT "." #num ": "
+#define KMSG_DEBUG(num) KERN_DEBUG KMSG_COMPONENT "." #num ": "
+
+#define KMSG_DOC(comp, num, str)
+
+#endif /* __KMSG_CHECKER */
+
+#endif /* _LINUX_KMSG_H */
diff -Naur linux-2.6.21/scripts/kernel-doc linux-2.6.21-kmsg/scripts/kernel-doc
--- linux-2.6.21/scripts/kernel-doc 2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21-kmsg/scripts/kernel-doc 2007-06-05 15:17:51.000000000 +0200
@@ -256,7 +256,7 @@
my $in_doc_sect;

#declaration types: can be
-# 'function', 'struct', 'union', 'enum', 'typedef'
+# 'function', 'struct', 'union', 'enum', 'typedef', 'message'
my $decl_type;

my $doc_special = "\@\%\$\&";
@@ -1163,6 +1163,55 @@
output_section_text(@_);
}

+##
+# output message in text
+sub output_message_text(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+
+ print $args{'id'}.": \"".$args{'message'}."\"\n\n";
+
+ print "Parameters:\n\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($parameter =~ /^#/) && next;
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ print "$parameter\n\t";
+ print $args{'parameterdescs'}{$parameter_name}."\n";
+ }
+ output_section_text(@_);
+}
+
+##
+# output message in man
+sub output_message_man(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+
+ print ".TH \"$args{'module'}\" 9 \"".$args{'id'}."\" \"$man_date\" \"Linux Messages\" LINUX\n";
+
+ print ".SH MESSAGE\n";
+ print $args{'id'}.": "."\"".$args{'message'}."\"\n";
+
+ print ".SH Parameters\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($parameter =~ /^#/) && next;
+
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ print ".IP \"".$parameter."\" 12\n";
+ output_highlight($args{'parameterdescs'}{$parameter_name});
+ }
+ foreach $section (@{$args{'sectionlist'}}) {
+ print ".SH \"$section\"\n";
+ output_highlight($args{'sections'}{$section});
+ print "\n";
+ }
+}
+
#output sections in text
sub output_section_text(%) {
my %args = %{$_[0]};
@@ -1607,6 +1656,69 @@
});
}

+sub create_parameterlist_msg($$) {
+ my $args = shift;
+ my $file = shift;
+ my $splitter = "%";
+ my $type;
+ my $param = 0;
+ my $first = 1;
+
+ # temporarily replace commas
+ while ($args =~ /(\([^\),]+),/) {
+ $args =~ s/(\([^\),]+),/$1#/g;
+ }
+
+ foreach my $arg (split($splitter, $args)) {
+ if ($first) {
+ $first = 0;
+ next;
+ }
+ $type = substr($arg,0,1);
+
+ # XXX introduce better type checking
+
+ push_parameter($param, $type, $file);
+ $param += 1;
+ }
+}
+
+##
+# takes a message prototype and the name of the current file being
+# processed and spits out all the details stored in the global
+# arrays/hashes.
+sub dump_message($$) {
+ my $x = shift;
+ my $file = shift;
+
+ if ($x =~/(KMSG_DOC)\(\s*(\w+)\s*\,\s*(\w+)\s*\,\s*\"(.*)\"\)/) {
+ $declaration_name = "$2.$3";
+ my $members = $4;
+ # strip comments:
+ $members =~ s/\/\*.*?\*\///gos;
+
+ create_parameterlist_msg($members, $file);
+
+ output_declaration($declaration_name,
+ 'message',
+ {'message' => $members,
+ 'id' => $declaration_name,
+ 'module' => $modulename,
+ 'parameterlist' => \@parameterlist,
+ 'parameterdescs' => \%parameterdescs,
+ 'parametertypes' => \%parametertypes,
+ 'sectionlist' => \@sectionlist,
+ 'sections' => \%sections,
+ 'purpose' => $declaration_purpose,
+ 'type' => $decl_type
+ });
+ }
+ else {
+ print STDERR "Error(${file}:$.): Cannot parse message!\n";
+ ++$errors;
+ }
+}
+
sub process_file($);

# Read the file that maps relative names to absolute names for
@@ -1782,6 +1894,8 @@
$decl_type = 'enum';
} elsif ($identifier =~ m/^typedef/) {
$decl_type = 'typedef';
+ } elsif ($identifier =~ m/^message/) {
+ $decl_type = 'message';
} else {
$decl_type = 'function';
}
diff -Naur linux-2.6.21/scripts/kmsg-doc linux-2.6.21-kmsg/scripts/kmsg-doc
--- linux-2.6.21/scripts/kmsg-doc 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.21-kmsg/scripts/kmsg-doc 2007-06-05 15:17:51.000000000 +0200
@@ -0,0 +1,231 @@
+#!/usr/bin/perl
+#
+# Tool to check kernel messages
+#
+# Can be used in toplevel Linux Makefile in the following way:
+#
+# CHECK = scripts/kmsg-doc check
+# CHECKFLAGS =
+#
+# Note: This is just a prototype and neither perfect nor complete!
+#
+# Copyright (C) IBM Corp. 2007
+# Author(s): Michael Holzheu <holzheu@xxxxxxxxxx>
+#
+
+sub create_message($$$$$)
+{
+ my ($sev, $component, $number, $text, $params) = @_;
+
+ $text =~ s/\\n//; # remove trailing newline character
+ $message_id = "$component.$number";
+ $messages{$message_count}->{'ID'} = $message_id;
+ $messages{$message_count}->{'COMP'} = $component;
+ $messages{$message_count}->{'NR'} = $number;
+ $messages{$message_count}->{'MSG'} = $text;
+ $messages{$message_count}->{'SEV'} = $sev;
+
+ @parms = split(/[\s]*,[\s]*/,$params);
+ $parm_count = 0;
+ foreach $parm (@parms) {
+ if (!($parm eq "")) {
+ $messages{$message_count}->{'PARM_NAME'}->{$parm_count} = $parm;
+ $parm_count += 1;
+ }
+ }
+ $messages{$message_count}->{'PARM_COUNT'} = $parm_count;
+ $message_count += 1;
+}
+
+sub get_msgs($)
+{
+ my ($filename)=@_;
+
+ $message_count = 0;
+ open(FD, $filename);
+ my @lines=<FD>;
+ foreach $line (@lines) {
+ if ($line =~ /\s*printk\([\s]*__KMSG_CHECK\((.*)\,[\s]*(.*)\)[\s]*"(.*)"[\s]*(.*)[\s]*\);/) {
+ create_message($1, $component, $2, $3, $4);
+ }
+ }
+}
+
+sub get_descriptions($)
+{
+ my ($filename)=@_;
+ my $desc_start;
+
+ $description_count = 0;
+ $desc_start = 0;
+ open(FD, $filename);
+ my @lines=<FD>;
+ foreach $line (@lines) {
+ if ($line =~ /#define [\s]*KMSG_COMPONENT [\s]*"(.*)"/) {
+ $component = $1;
+ }
+ if ($line =~ /\s*\/\*\*$/) {
+ $msg_start = 1;
+ $parm_count = 0;
+ next;
+ }
+ if (($msg_start == 1) && ($line =~ / \* message/)) {
+ $desc_start = 1;
+ next;
+ }
+ if ($line =~ / \*\//) {
+ $desc_start = 0;
+ next;
+ }
+ if ($desc_start == 1) {
+ $descriptions{$description_count}->{'DESC'} .= "$line";
+ next;
+ }
+ if ($line =~
+ /\s*KMSG_DOC\(\s*(.*)\s*\,\s*(.*)\s*\,\s*\"(.*)\"\s*\);/) {
+ my $param_count = 0;
+ my $first = 1;
+ my $type;
+
+ $descriptions{$description_count}->{'ID'} = "$1\.$2";
+ $descriptions{$description_count}->{'COMP'} = "$1";
+ $descriptions{$description_count}->{'NR'} = "$2";
+ $descriptions{$description_count}->{'MSG'} = "$3";
+ foreach my $arg (split("%", $3)) {
+ if ($first) {
+ $first = 0;
+ next;
+ }
+ $type = substr($arg, 0, 1);
+ $descriptions{$description_count}->{'PARM_TYPE'}->{$param_count} = $type;
+ $param_count += 1;
+ }
+ $descriptions{$description_count}->{'PARM_COUNT'} = $param_count;
+ $description_count += 1;
+ }
+ }
+}
+
+sub print_messages()
+{
+ for ($i = 0; $i < $message_count; $i++) {
+ print "MESSAGE: $messages{$i}->{'ID'}\n";
+ }
+}
+
+sub print_descriptions($)
+{
+ my ($message_id)=@_;
+
+ for ($i = 0; $i < $description_count; $i++) {
+ if (($descriptions{$i}->{'ID'} eq $message_id) || $message_id eq "all") {
+ print "==============================================================================\n";
+ print "\[$descriptions{$i}->{'COMP'}\.$descriptions{$i}->{'NR'}\] $descriptions{$i}->{'MSG'}\n";
+ print "\n";
+ print "Parameters:\n";
+ for ($j = 0; $j < $descriptions{$i}->{'PARM_COUNT'}; $j++) {
+ print " $descriptions{$i}->{'PARM_TYPE'}->{$j}: $descriptions{$i}->{'PARM_DESC'}->{$j}\n";
+ }
+ print "\n";
+ print "Description:\n";
+ print "$descriptions{$i}->{'DESC'}\n";
+ print "==============================================================================\n";
+ }
+ }
+}
+
+sub check_messages($)
+{
+ my ($filename)=@_;
+
+ for ($i = 0; $i < $message_count; $i++) {
+ $found = 0;
+ for ($j = 0; $j < $description_count; $j++) {
+ if ($messages{$i}->{'ID'} eq $descriptions{$j}->{'ID'}) {
+ $found = 1;
+ last;
+ }
+ }
+ if (!$found) {
+ print STDERR "$filename: Missing description for: $messages{$i}->{'ID'}\n";
+ }
+ }
+ for ($i = 0; $i < $description_count; $i++) {
+ $found = 0;
+ for ($j = 0; $j < $message_count; $j++) {
+ if ($messages{$j}->{'ID'} eq $descriptions{$i}->{'ID'}) {
+ $found = 1;
+ last;
+ }
+ }
+ if (!$found) {
+ print STDERR "$filename: Description without message for: $descriptions{$i}->{'ID'}\n";
+ }
+ }
+}
+
+sub print_templates()
+{
+
+ for ($i = 0; $i < $message_count; $i++) {
+ $found = 0;
+ for ($j = 0; $j < $description_count; $j++) {
+ if ($messages{$i}->{'ID'} eq $descriptions{$j}->{'ID'}) {
+ $found = 1;
+ }
+ }
+ if (!$found) {
+ print "/**\n";
+ print " * message\n";
+ for ($k = 0; $k < $messages{$i}->{'PARM_COUNT'}; $k++) {
+ print " * \@$k: $messages{$i}->{'PARM_NAME'}->{$k}\n";
+ }
+ print " *\n";
+ print " * Description:\n";
+ print " *\n";
+ print " * User Response:\n";
+ print " */\n";
+ print "\n";
+ print "KMSG_DOC($messages{$i}->{'COMP'}, $messages{$i}->{'NR'}, \"$messages{$i}->{'MSG'}\");\n"
+ }
+ }
+}
+
+sub usage()
+{
+ print "USAGE: kmsg_tool print | check <file>\n";
+ exit 1;
+}
+
+$option = shift;
+
+if ($option eq "check") {
+ $gcc_options = "-E -D __KMSG_CHECKER ";
+ do {
+ $filename = $tmp;
+ $tmp = shift;
+ $tmp =~ s/\(/\\\(/;
+ $tmp =~ s/\)/\\\)/;
+ $gcc_options .= " $tmp";
+ } while (!($tmp eq ""));
+
+ $gcc_options =~ s/-Wbitwise//; # XXX hack to remove -Wbitwise CHECKFLAG
+ $gcc_options =~ s/-D__STDC__//; # XXX hack to remove -D__STDC__
+ $tmp_file = "$filename.msg";
+ system("gcc $gcc_options > $tmp_file");
+ get_descriptions($filename);
+ get_msgs($tmp_file);
+ check_messages($filename);
+ print_templates();
+ system("rm $tmp_file");
+} elsif ($option eq "print") {
+ $filename = shift;
+ do {
+ print STDERR "Processing: $filename\n";
+ get_descriptions($filename);
+ print_descriptions("all");
+ $filename = shift;
+ } while (!($filename eq ""));
+} else {
+ usage();
+}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



Relevant Pages

  • kernel Doc/ URL corrections
    ... -Documents about softnet driver issues in general can be found ... Additional documentation is available at Don Becker's Linux Drivers site: ... Just force it to be recognized by kernel parameters. ... Keywords: files, VFS, file operations, kernel interface, character ...
    (Linux-Kernel)
  • Re: differences between kernel-tree and kernel-source and kernel image
    ... > will this install the kernel or try to patch an existing 2.6 kernel or ... affix-source - Driver source for the Affix Bluetooth protocol stack for Linux ... atlas-doc - Automatically Tuned Linear Algebra Software,documentation ...
    (Debian-User)
  • Re: eradicating out of tree modules
    ... crashes of "the Linux kernel" caused by some binary-only driver. ... This harms the reputation of Linux as being stable. ... for breaking out-of-tree open source modules is throwing out the baby ...
    (Linux-Kernel)
  • Re[2]: 2.6.16 serious consequences / GPL_EXPORT_SYMBOL / USB drivers of major vendor excluded
    ... is only truly feasible in kernel space. ... Even though people might do realtime DSP things in user space with Linux ... using usbfs directly, no kernel driver needed. ... release your code under this same license. ...
    (Linux-Kernel)
  • Re: 2.6.16-rc2-mm1: crash on suspend
    ... I've got a kernel crash when trying to suspend to disk. ... Mandriva Linux release 2006.1 for i586, ... # ACPI Support ... # Generic Driver Options ...
    (Linux-Kernel)