]>
Commit | Line | Data |
---|---|---|
46364cb2 BB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
4 | * The contents of this file are subject to the terms of the | |
5 | * Common Development and Distribution License (the "License"). | |
6 | * You may not use this file except in compliance with the License. | |
7 | * | |
8 | * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
1d3ba0bf | 9 | * or https://opensource.org/licenses/CDDL-1.0. |
46364cb2 BB |
10 | * See the License for the specific language governing permissions |
11 | * and limitations under the License. | |
12 | * | |
13 | * When distributing Covered Code, include this CDDL HEADER in each | |
14 | * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 | * If applicable, add the following below this CDDL HEADER, with the | |
16 | * fields enclosed by brackets "[]" replaced with your own identifying | |
17 | * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 | * | |
19 | * CDDL HEADER END | |
20 | */ | |
21 | ||
22 | /* | |
23 | * Copyright (c) 2017, Lawrence Livermore National Security, LLC. | |
24 | */ | |
25 | ||
26 | #include <sys/zfs_ratelimit.h> | |
27 | ||
28 | /* | |
29 | * Initialize rate limit struct | |
30 | * | |
31 | * rl: zfs_ratelimit_t struct | |
32 | * burst: Number to allow in an interval before rate limiting | |
33 | * interval: Interval time in seconds | |
34 | */ | |
35 | void | |
80d52c39 | 36 | zfs_ratelimit_init(zfs_ratelimit_t *rl, unsigned int *burst, |
46364cb2 BB |
37 | unsigned int interval) |
38 | { | |
39 | rl->count = 0; | |
40 | rl->start = 0; | |
41 | rl->interval = interval; | |
42 | rl->burst = burst; | |
43 | mutex_init(&rl->lock, NULL, MUTEX_DEFAULT, NULL); | |
44 | } | |
45 | ||
46 | /* | |
47 | * Finalize rate limit struct | |
48 | * | |
49 | * rl: zfs_ratelimit_t struct | |
50 | */ | |
51 | void | |
52 | zfs_ratelimit_fini(zfs_ratelimit_t *rl) | |
53 | { | |
54 | mutex_destroy(&rl->lock); | |
55 | } | |
56 | ||
57 | /* | |
58 | * Re-implementation of the kernel's __ratelimit() function | |
59 | * | |
60 | * We had to write our own rate limiter because the kernel's __ratelimit() | |
61 | * function annoyingly prints out how many times it rate limited to the kernel | |
62 | * logs (and there's no way to turn it off): | |
63 | * | |
64 | * __ratelimit: 59 callbacks suppressed | |
65 | * | |
66 | * If the kernel ever allows us to disable these prints, we should go back to | |
67 | * using __ratelimit() instead. | |
68 | * | |
69 | * Return values are the same as __ratelimit(): | |
70 | * | |
71 | * 0: If we're rate limiting | |
72 | * 1: If we're not rate limiting. | |
73 | */ | |
74 | int | |
75 | zfs_ratelimit(zfs_ratelimit_t *rl) | |
76 | { | |
77 | hrtime_t now; | |
78 | ||
79 | hrtime_t elapsed; | |
80 | int error = 1; | |
81 | ||
82 | mutex_enter(&rl->lock); | |
83 | ||
84 | now = gethrtime(); | |
85 | elapsed = now - rl->start; | |
86 | ||
87 | rl->count++; | |
88 | if (NSEC2SEC(elapsed) >= rl->interval) { | |
89 | rl->start = now; | |
90 | rl->count = 0; | |
91 | } else { | |
80d52c39 | 92 | if (rl->count >= *rl->burst) { |
46364cb2 BB |
93 | error = 0; /* We're ratelimiting */ |
94 | } | |
95 | } | |
96 | mutex_exit(&rl->lock); | |
97 | ||
98 | return (error); | |
99 | } |