diff options
Diffstat (limited to 'module/zfs/zfs_ratelimit.c')
-rw-r--r-- | module/zfs/zfs_ratelimit.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/module/zfs/zfs_ratelimit.c b/module/zfs/zfs_ratelimit.c new file mode 100644 index 000000000..d4a7d5217 --- /dev/null +++ b/module/zfs/zfs_ratelimit.c @@ -0,0 +1,99 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2017, Lawrence Livermore National Security, LLC. + */ + +#include <sys/zfs_ratelimit.h> + +/* + * 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); +} + +/* + * Finalize rate limit struct + * + * rl: zfs_ratelimit_t struct + */ +void +zfs_ratelimit_fini(zfs_ratelimit_t *rl) +{ + mutex_destroy(&rl->lock); +} + +/* + * 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 error = 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) { + error = 0; /* We're ratelimiting */ + } + } + mutex_exit(&rl->lock); + + return (error); +} |