On Mon, 4 Jul 2016 16:24:51 +0200 Borislav Petkov <b...@alien8.de> wrote:
> From: Borislav Petkov <b...@suse.de> > > Extend the ratelimiting facility to print the amount of suppressed lines > when it is being released. > > Separated from a previous patch by Linus. > > Also, make the ON_RELEASE image not use "callbacks" as it is misleading. > > Signed-off-by: Borislav Petkov <b...@suse.de> > Acked-by: Linus Torvalds <torva...@linux-foundation.org> > Cc: Andrew Morton <a...@linux-foundation.org> > Cc: Franck Bui <f...@suse.com> > Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org> > Cc: Ingo Molnar <mi...@kernel.org> > Cc: Linus Torvalds <torva...@linux-foundation.org> > Cc: Peter Zijlstra <pet...@infradead.org> > Cc: Steven Rostedt <rost...@goodmis.org> > Cc: Uwe Kleine-König <u.kleine-koe...@pengutronix.de> > --- > include/linux/ratelimit.h | 36 +++++++++++++++++++++++++++++++----- > lib/ratelimit.c | 6 ++++-- > 2 files changed, 35 insertions(+), 7 deletions(-) > > diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h > index 18102529254e..1d8a17ee8395 100644 > --- a/include/linux/ratelimit.h > +++ b/include/linux/ratelimit.h > @@ -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,33 @@ 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) > + printk(KERN_WARNING "%s: %d output lines suppressed due to > ratelimiting\n", > + current->comm, rs->missed); Is the comm important? Maybe add the function that called it? "%pS", _THIS_IP_ Perhaps add __always_inline, as _THIS_IP_ will point into the function that calls this? -- Steve > +} > + > +static inline void > +ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags) > +{ > + rs->flags = flags; > } > > extern struct ratelimit_state printk_ratelimit_state; > diff --git a/lib/ratelimit.c b/lib/ratelimit.c > index 2c5de86460c5..b753f0cfb00b 100644 > --- a/lib/ratelimit.c > +++ b/lib/ratelimit.c > @@ -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) > + if (rs->missed && !(rs->flags & RATELIMIT_MSG_ON_RELEASE)) > printk(KERN_WARNING "%s: %d callbacks suppressed\n", > func, rs->missed); > rs->begin = jiffies; > rs->printed = 0; > - rs->missed = 0; > + > + if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) > + rs->missed = 0; > } > if (rs->burst && rs->burst > rs->printed) { > rs->printed++;