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); /**