ratelimit: extend to print suppressed messages on release
authorBorislav Petkov <bp@suse.de>
Tue, 2 Aug 2016 21:04:04 +0000 (14:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Aug 2016 23:35:06 +0000 (19:35 -0400)
Extend the ratelimiting facility to print the amount of suppressed lines
when it is being released.

This use case is aimed at short-termed, burst-like users for which we
want to output the suppressed lines stats only once, after it has been
disposed of.  For an example, see /dev/kmsg usage in a follow-on patch.

Also, change the printk() line we issue on release to not use
"callbacks" as it is misleading: we're not suppressing callbacks but
printk() calls.

This has been separated from a previous patch by Linus.

Link: http://lkml.kernel.org/r/20160716061745.15795-2-bp@alien8.de
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Dave Young <dyoung@redhat.com>
Cc: Franck Bui <fbui@suse.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/ratelimit.h
lib/ratelimit.c

index 1810252..57c9e06 100644 (file)
@@ -2,11 +2,15 @@
 #define _LINUX_RATELIMIT_H
 
 #include <linux/param.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 
 #define DEFAULT_RATELIMIT_INTERVAL     (5 * HZ)
 #define DEFAULT_RATELIMIT_BURST                10
 
+/* issue num suppressed message on exit */
+#define RATELIMIT_MSG_ON_RELEASE       BIT(0)
+
 struct ratelimit_state {
        raw_spinlock_t  lock;           /* protect the state */
 
@@ -15,6 +19,7 @@ struct ratelimit_state {
        int             printed;
        int             missed;
        unsigned long   begin;
+       unsigned long   flags;
 };
 
 #define RATELIMIT_STATE_INIT(name, interval_init, burst_init) {                \
@@ -34,12 +39,35 @@ struct ratelimit_state {
 static inline void ratelimit_state_init(struct ratelimit_state *rs,
                                        int interval, int burst)
 {
+       memset(rs, 0, sizeof(*rs));
+
        raw_spin_lock_init(&rs->lock);
-       rs->interval = interval;
-       rs->burst = burst;
-       rs->printed = 0;
-       rs->missed = 0;
-       rs->begin = 0;
+       rs->interval    = interval;
+       rs->burst       = burst;
+}
+
+static inline void ratelimit_default_init(struct ratelimit_state *rs)
+{
+       return ratelimit_state_init(rs, DEFAULT_RATELIMIT_INTERVAL,
+                                       DEFAULT_RATELIMIT_BURST);
+}
+
+static inline void ratelimit_state_exit(struct ratelimit_state *rs)
+{
+       if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE))
+               return;
+
+       if (rs->missed) {
+               pr_warn("%s: %d output lines suppressed due to ratelimiting\n",
+                       current->comm, rs->missed);
+               rs->missed = 0;
+       }
+}
+
+static inline void
+ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags)
+{
+       rs->flags = flags;
 }
 
 extern struct ratelimit_state printk_ratelimit_state;
index 2c5de86..08f8043 100644 (file)
@@ -46,12 +46,14 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func)
                rs->begin = jiffies;
 
        if (time_is_before_jiffies(rs->begin + rs->interval)) {
-               if (rs->missed)
-                       printk(KERN_WARNING "%s: %d callbacks suppressed\n",
-                               func, rs->missed);
+               if (rs->missed) {
+                       if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
+                               pr_warn("%s: %d callbacks suppressed\n", func, rs->missed);
+                               rs->missed = 0;
+                       }
+               }
                rs->begin   = jiffies;
                rs->printed = 0;
-               rs->missed  = 0;
        }
        if (rs->burst && rs->burst > rs->printed) {
                rs->printed++;