aboutsummaryrefslogtreecommitdiffstats
path: root/module/zcommon
diff options
context:
space:
mode:
Diffstat (limited to 'module/zcommon')
-rw-r--r--module/zcommon/zfs_comutil.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/module/zcommon/zfs_comutil.c b/module/zcommon/zfs_comutil.c
index 6d0314fa7..704ef84c7 100644
--- a/module/zcommon/zfs_comutil.c
+++ b/module/zcommon/zfs_comutil.c
@@ -40,6 +40,7 @@
#include <sys/int_limits.h>
#include <sys/nvpair.h>
#include "zfs_comutil.h"
+#include <sys/zfs_ratelimit.h>
/*
* Are there allocatable vdevs?
@@ -206,10 +207,73 @@ const char *zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = {
"pool split",
};
+/*
+ * Initialize rate limit struct
+ *
+ * rl: zfs_ratelimit_t struct
+ * burst: Number to allow in an interval before rate limiting
+ * interval: Interval time in seconds
+ */
+void
+zfs_ratelimit_init(zfs_ratelimit_t *rl, unsigned int burst,
+ unsigned int interval)
+{
+ rl->count = 0;
+ rl->start = 0;
+ rl->interval = interval;
+ rl->burst = burst;
+ mutex_init(&rl->lock, NULL, MUTEX_DEFAULT, NULL);
+}
+
+/*
+ * Re-implementation of the kernel's __ratelimit() function
+ *
+ * We had to write our own rate limiter because the kernel's __ratelimit()
+ * function annoyingly prints out how many times it rate limited to the kernel
+ * logs (and there's no way to turn it off):
+ *
+ * __ratelimit: 59 callbacks suppressed
+ *
+ * If the kernel ever allows us to disable these prints, we should go back to
+ * using __ratelimit() instead.
+ *
+ * Return values are the same as __ratelimit():
+ *
+ * 0: If we're rate limiting
+ * 1: If we're not rate limiting.
+ */
+int
+zfs_ratelimit(zfs_ratelimit_t *rl)
+{
+ hrtime_t now;
+ hrtime_t elapsed;
+ int rc = 1;
+
+ mutex_enter(&rl->lock);
+
+ now = gethrtime();
+ elapsed = now - rl->start;
+
+ rl->count++;
+ if (NSEC2SEC(elapsed) >= rl->interval) {
+ rl->start = now;
+ rl->count = 0;
+ } else {
+ if (rl->count >= rl->burst) {
+ rc = 0; /* We're ratelimiting */
+ }
+ }
+ mutex_exit(&rl->lock);
+
+ return (rc);
+}
+
#if defined(_KERNEL) && defined(HAVE_SPL)
EXPORT_SYMBOL(zfs_allocatable_devs);
EXPORT_SYMBOL(zpool_get_rewind_policy);
EXPORT_SYMBOL(zfs_zpl_version_map);
EXPORT_SYMBOL(zfs_spa_version_map);
EXPORT_SYMBOL(zfs_history_event_names);
+EXPORT_SYMBOL(zfs_ratelimit_init);
+EXPORT_SYMBOL(zfs_ratelimit);
#endif