Issue:

On some conditions, the dmesg is spammed with repeated warnings about the
same issue which is neither critical nor going to be fixed. This may
result in losing the boot messages or missing other important messages.

Examples are:

nfs warning: mount version older than kernel
 (my mount is newer than documented to be required)

atkbd.c: Keyboard on isa0060/serio0 reports too many keys pressed.
 (I'm using a keyboard switch and a IBM PS/2 keyboard)

program smartd is using a deprecated SCSI ioctl, please convert it to SG_IO
 (I'll use the latest version as soon as I need to)



Rate-limiting these messages is won't help, since it would still allow
these messages to (slowly or in a burst) spam the log.

Printing these messages only once after booting might result in missing
important messages, especially on long-running systems (e.g. if my
keyboard really breaks after I have used the keyboard switch).


Suggested solution:

Instead, I decided to use a global flag with a semi-random magic number,
which will indicate the last printk being supposed to be limited, and to
reset this flag on each normal printk. By doing this, dmesg will not be
spammed, but the latest issue is displayed last.

(I suggest using the first value from "cksum file.c" as the magic number
unless there are thousands of printks to convert.)

The magic number depends on the CPU being able to read and write a
complete int at once *or* being lucky not to have a magic value that can
be constructed by combining some other magic numbers and printking with
exactly that magic number while the update happens. I can convert the
variable to an atomic type if it is a concern, but that would increase the
chances of a clash due to the 24 bit limit.

The patch increases the size of vmlinux by 141 bytes.
-- 
The programmer's National Anthem is 'AAAAAAAAHHHHHHHH' 
diff -uprN linux-2.6.11/drivers/block/scsi_ioctl.c 
linux-2.6.11.new/drivers/block/scsi_ioctl.c
--- linux-2.6.11/drivers/block/scsi_ioctl.c     2005-03-03 15:41:28.000000000 
+0100
+++ linux-2.6.11.new/drivers/block/scsi_ioctl.c 2005-03-18 22:08:35.000000000 
+0100
@@ -547,7 +547,7 @@ int scsi_cmd_ioctl(struct file *file, st
                 * old junk scsi send command ioctl
                 */
                case SCSI_IOCTL_SEND_COMMAND:
-                       printk(KERN_WARNING "program %s is using a deprecated 
SCSI ioctl, please convert it to SG_IO\n", current->comm);
+                       printk_nospam(2296159591, KERN_WARNING "program %s is 
using a deprecated SCSI ioctl, please convert it to SG_IO\n", current->comm);
                        err = -EINVAL;
                        if (!arg)
                                break;
diff -uprN linux-2.6.11/drivers/input/keyboard/atkbd.c 
linux-2.6.11.new/drivers/input/keyboard/atkbd.c
--- linux-2.6.11/drivers/input/keyboard/atkbd.c 2005-03-03 15:41:33.000000000 
+0100
+++ linux-2.6.11.new/drivers/input/keyboard/atkbd.c     2005-03-18 
22:45:42.000000000 +0100
@@ -320,7 +320,7 @@ static irqreturn_t atkbd_interrupt(struc
                        atkbd_report_key(&atkbd->dev, regs, KEY_HANJA, 3);
                        goto out;
                case ATKBD_RET_ERR:
-                       printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too 
many keys pressed.\n", serio->phys);
+                       printk_nospam(2260620158, KERN_DEBUG "atkbd.c: Keyboard 
on %s reports too many keys pressed.\n", serio->phys);
                        goto out;
        }
 
diff -uprN linux-2.6.11/fs/nfs/inode.c linux-2.6.11.new/fs/nfs/inode.c
--- linux-2.6.11/fs/nfs/inode.c 2005-03-03 15:41:59.000000000 +0100
+++ linux-2.6.11.new/fs/nfs/inode.c     2005-03-18 22:48:09.000000000 +0100
@@ -1386,7 +1386,7 @@ static struct super_block *nfs_get_sb(st
        init_nfsv4_state(server);
 
        if (data->version != NFS_MOUNT_VERSION) {
-               printk("nfs warning: mount version %s than kernel\n",
+               printk_nospam(1377481036, "nfs warning: mount version %s than 
kernel\n",
                        data->version < NFS_MOUNT_VERSION ? "older" : "newer");
                if (data->version < 2)
                        data->namlen = 0;
diff -uprN linux-2.6.11/include/linux/kernel.h 
linux-2.6.11.new/include/linux/kernel.h
--- linux-2.6.11/include/linux/kernel.h 2005-03-03 15:42:13.000000000 +0100
+++ linux-2.6.11.new/include/linux/kernel.h     2005-03-18 22:06:42.000000000 
+0100
@@ -104,6 +104,10 @@ extern int session_of_pgrp(int pgrp);
 asmlinkage int vprintk(const char *fmt, va_list args);
 asmlinkage int printk(const char * fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
+asmlinkage int printk_nospam(int magic, const char * fmt, ...)
+       __attribute__ ((format (printf, 2, 3)));
+/* use a random value for the magic, e.g. the first value from
+   cksum on the file you're editing */
 
 unsigned long int_sqrt(unsigned long);
 
diff -uprN linux-2.6.11/kernel/printk.c linux-2.6.11.new/kernel/printk.c
--- linux-2.6.11/kernel/printk.c        2005-03-18 21:54:35.000000000 +0100
+++ linux-2.6.11.new/kernel/printk.c    2005-03-18 22:40:02.000000000 +0100
@@ -115,6 +115,8 @@ static int preferred_console = -1;
 /* Flag: console code may call schedule() */
 static int console_may_schedule;
 
+static int antispam_magic;
+
 /*
  *     Setup a list of consoles. Called from init/main.c
  */
@@ -517,6 +519,24 @@ asmlinkage int printk(const char *fmt, .
        va_list args;
        int r;
 
+       antispam_magic = 0;
+
+       va_start(args, fmt);
+       r = vprintk(fmt, args);
+       va_end(args);
+
+       return r;
+}
+
+asmlinkage int printk_nospam(int magic, const char *fmt, ...)
+{
+       va_list args;
+       int r;
+       
+       if (magic == antispam_magic)
+               return 0;
+       antispam_magic = magic;
+
        va_start(args, fmt);
        r = vprintk(fmt, args);
        va_end(args);
@@ -591,6 +611,7 @@ out:
        return printed_len;
 }
 EXPORT_SYMBOL(printk);
+EXPORT_SYMBOL(printk_nospam);
 EXPORT_SYMBOL(vprintk);
 
 /**

Reply via email to