zfs/module/zfs/zfs_ratelimit.c

100 lines
2.4 KiB
C

/*
* 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);
}