]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Fix printk_ratelimited()
authorKent Overstreet <kent.overstreet@gmail.com>
Thu, 23 Jun 2022 02:05:39 +0000 (22:05 -0400)
committerKent Overstreet <kent.overstreet@gmail.com>
Thu, 23 Jun 2022 02:05:39 +0000 (22:05 -0400)
printk_ratelimited was behind an #ifdef CONFIG_PRINTK, which we don't
define, so it was a complete noop - oops.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
include/linux/jiffies.h
include/linux/printk.h
include/linux/spinlock.h
linux/ratelimit.c [new file with mode: 0644]

index fe928265ce8b9624caddc8e59457e24d45765946..c3f3e1f20cbd1cb0de77e3087c097c495dc5a7c3 100644 (file)
@@ -43,6 +43,8 @@
        (time_after_eq64(a, b) && \
         time_before_eq64(a, c))
 
+#define time_is_before_jiffies(a) time_after(jiffies, a)
+
 #define HZ             1000
 
 static inline u64 jiffies_to_nsecs(const unsigned long j)
index bc1619f7cbf765e184d4d80a2cd83a876c4b68e1..df9c1920ddfaf14f47a82a4408a3e589e8bf72ec 100644 (file)
@@ -5,6 +5,7 @@
 #define pr_fmt(fmt) fmt
 #endif
 
+#include <linux/compiler.h>
 #include <stdarg.h>
 #include <stdio.h>
 
@@ -169,7 +170,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
  * ratelimited messages with local ratelimit_state,
  * no local ratelimit_state used in the !PRINTK case
  */
-#ifdef CONFIG_PRINTK
 #define printk_ratelimited(fmt, ...)                                   \
 ({                                                                     \
        static DEFINE_RATELIMIT_STATE(_rs,                              \
@@ -179,10 +179,6 @@ static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
        if (__ratelimit(&_rs))                                          \
                printk(fmt, ##__VA_ARGS__);                             \
 })
-#else
-#define printk_ratelimited(fmt, ...)                                   \
-       no_printk(fmt, ##__VA_ARGS__)
-#endif
 
 #define pr_emerg_ratelimited(fmt, ...)                                 \
        printk_ratelimited(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
index bd51188d5e13c30fea3771b6692191cb12a1ebeb..6c4a623c267182d6362ce6a9a1843c230a67fdad 100644 (file)
@@ -15,6 +15,11 @@ static inline void raw_spin_lock_init(raw_spinlock_t *lock)
        pthread_mutex_init(&lock->lock, NULL);
 }
 
+static inline bool raw_spin_trylock(raw_spinlock_t *lock)
+{
+       return !pthread_mutex_trylock(&lock->lock);
+}
+
 static inline void raw_spin_lock(raw_spinlock_t *lock)
 {
        pthread_mutex_lock(&lock->lock);
diff --git a/linux/ratelimit.c b/linux/ratelimit.c
new file mode 100644 (file)
index 0000000..21a6d6c
--- /dev/null
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ratelimit.c - Do something with rate limit.
+ *
+ * Isolated from kernel/printk.c by Dave Young <hidave.darkstar@gmail.com>
+ *
+ * 2008-05-01 rewrite the function and use a ratelimit_state data struct as
+ * parameter. Now every user can use their own standalone ratelimit_state.
+ */
+
+#include <linux/ratelimit.h>
+#include <linux/jiffies.h>
+#include <linux/export.h>
+
+/*
+ * __ratelimit - rate limiting
+ * @rs: ratelimit_state data
+ * @func: name of calling function
+ *
+ * This enforces a rate limit: not more than @rs->burst callbacks
+ * in every @rs->interval
+ *
+ * RETURNS:
+ * 0 means callbacks will be suppressed.
+ * 1 means go ahead and do it.
+ */
+int ___ratelimit(struct ratelimit_state *rs, const char *func)
+{
+       int ret;
+
+       if (!rs->interval)
+               return 1;
+
+       /*
+        * If we contend on this state's lock then almost
+        * by definition we are too busy to print a message,
+        * in addition to the one that will be printed by
+        * the entity that is holding the lock already:
+        */
+       if (!raw_spin_trylock(&rs->lock))
+               return 0;
+
+       if (!rs->begin)
+               rs->begin = jiffies;
+
+       if (time_is_before_jiffies(rs->begin + rs->interval)) {
+               if (rs->missed) {
+                       if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
+                               printk(KERN_WARNING
+                                      "%s: %d callbacks suppressed\n",
+                                      func, rs->missed);
+                               rs->missed = 0;
+                       }
+               }
+               rs->begin   = jiffies;
+               rs->printed = 0;
+       }
+       if (rs->burst && rs->burst > rs->printed) {
+               rs->printed++;
+               ret = 1;
+       } else {
+               rs->missed++;
+               ret = 0;
+       }
+       raw_spin_unlock(&rs->lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(___ratelimit);