@@ -5,7 +5,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
5
5
use std:: time:: { Duration , Instant } ;
6
6
use std:: { fmt, io} ;
7
7
8
- use timerfd:: { ClockId , SetTimeFlags , TimerFd , TimerState } ;
8
+ use vmm_sys_util :: timerfd:: { TimerFd , TimerFdFlag } ;
9
9
10
10
pub mod persist;
11
11
@@ -14,12 +14,12 @@ pub mod persist;
14
14
pub enum RateLimiterError {
15
15
/// Rate limiter event handler called without a present timer
16
16
SpuriousRateLimiterEvent ,
17
+ /// Error reading timerfd: {0}
18
+ Read ( #[ from] vmm_sys_util:: errno:: Error ) ,
17
19
}
18
20
19
21
// Interval at which the refill timer will run when limiter is at capacity.
20
- const REFILL_TIMER_INTERVAL_MS : u64 = 100 ;
21
- const TIMER_REFILL_STATE : TimerState =
22
- TimerState :: Oneshot ( Duration :: from_millis ( REFILL_TIMER_INTERVAL_MS ) ) ;
22
+ const REFILL_TIMER_DURATION : Duration = Duration :: from_millis ( 100 ) ;
23
23
24
24
const NANOSEC_IN_ONE_MILLISEC : u64 = 1_000_000 ;
25
25
@@ -367,7 +367,7 @@ impl RateLimiter {
367
367
// We'll need a timer_fd, even if our current config effectively disables rate limiting,
368
368
// because `Self::update_buckets()` might re-enable it later, and we might be
369
369
// seccomp-blocked from creating the timer_fd at that time.
370
- let timer_fd = TimerFd :: new_custom ( ClockId :: Monotonic , true , true ) ?;
370
+ let timer_fd = TimerFd :: new_with_flags ( TimerFdFlag :: NONBLOCK ) ?;
371
371
372
372
Ok ( RateLimiter {
373
373
bandwidth : bytes_token_bucket,
@@ -378,9 +378,11 @@ impl RateLimiter {
378
378
}
379
379
380
380
// Arm the timer of the rate limiter with the provided `TimerState`.
381
- fn activate_timer ( & mut self , timer_state : TimerState ) {
381
+ fn activate_timer ( & mut self , one_shot_duration : Duration ) {
382
382
// Register the timer; don't care about its previous state
383
- self . timer_fd . set_state ( timer_state, SetTimeFlags :: Default ) ;
383
+ self . timer_fd
384
+ . reset ( one_shot_duration, None )
385
+ . expect ( "failed to activate ratelimiter timer" ) ;
384
386
self . timer_active = true ;
385
387
}
386
388
@@ -407,7 +409,7 @@ impl RateLimiter {
407
409
// make sure there is only one running timer for this limiter.
408
410
BucketReduction :: Failure => {
409
411
if !self . timer_active {
410
- self . activate_timer ( TIMER_REFILL_STATE ) ;
412
+ self . activate_timer ( REFILL_TIMER_DURATION ) ;
411
413
}
412
414
false
413
415
}
@@ -424,9 +426,7 @@ impl RateLimiter {
424
426
// `ratio * refill_time` milliseconds.
425
427
// The conversion should be safe because the ratio is positive.
426
428
#[ allow( clippy:: cast_sign_loss, clippy:: cast_possible_truncation) ]
427
- self . activate_timer ( TimerState :: Oneshot ( Duration :: from_millis (
428
- ( ratio * refill_time as f64 ) as u64 ,
429
- ) ) ) ;
429
+ self . activate_timer ( Duration :: from_millis ( ( ratio * refill_time as f64 ) as u64 ) ) ;
430
430
true
431
431
}
432
432
}
@@ -469,7 +469,7 @@ impl RateLimiter {
469
469
///
470
470
/// If the rate limiter is disabled or is not blocked, an error is returned.
471
471
pub fn event_handler ( & mut self ) -> Result < ( ) , RateLimiterError > {
472
- match self . timer_fd . read ( ) {
472
+ match self . timer_fd . wait ( ) ? {
473
473
0 => Err ( RateLimiterError :: SpuriousRateLimiterEvent ) ,
474
474
_ => {
475
475
self . timer_active = false ;
@@ -777,7 +777,7 @@ pub(crate) mod tests {
777
777
// second wait will always result in the limiter being refilled. Otherwise
778
778
// there is a chance for a race condition between limiter refilling and limiter
779
779
// checking.
780
- const TEST_REFILL_TIMER_INTERVAL_MS : u64 = REFILL_TIMER_INTERVAL_MS + 10 ;
780
+ const TEST_REFILL_TIMER_DURATION : Duration = Duration :: from_millis ( 110 ) ;
781
781
782
782
impl TokenBucket {
783
783
// Resets the token bucket: budget set to max capacity and last-updated set to now.
@@ -1014,11 +1014,11 @@ pub(crate) mod tests {
1014
1014
// since consume failed, limiter should be blocked now
1015
1015
assert ! ( l. is_blocked( ) ) ;
1016
1016
// wait half the timer period
1017
- thread:: sleep ( Duration :: from_millis ( TEST_REFILL_TIMER_INTERVAL_MS / 2 ) ) ;
1017
+ thread:: sleep ( TEST_REFILL_TIMER_DURATION / 2 ) ;
1018
1018
// limiter should still be blocked
1019
1019
assert ! ( l. is_blocked( ) ) ;
1020
1020
// wait the other half of the timer period
1021
- thread:: sleep ( Duration :: from_millis ( TEST_REFILL_TIMER_INTERVAL_MS / 2 ) ) ;
1021
+ thread:: sleep ( TEST_REFILL_TIMER_DURATION / 2 ) ;
1022
1022
// the timer_fd should have an event on it by now
1023
1023
l. event_handler ( ) . unwrap ( ) ;
1024
1024
// limiter should now be unblocked
@@ -1047,11 +1047,11 @@ pub(crate) mod tests {
1047
1047
// since consume failed, limiter should be blocked now
1048
1048
assert ! ( l. is_blocked( ) ) ;
1049
1049
// wait half the timer period
1050
- thread:: sleep ( Duration :: from_millis ( TEST_REFILL_TIMER_INTERVAL_MS / 2 ) ) ;
1050
+ thread:: sleep ( TEST_REFILL_TIMER_DURATION / 2 ) ;
1051
1051
// limiter should still be blocked
1052
1052
assert ! ( l. is_blocked( ) ) ;
1053
1053
// wait the other half of the timer period
1054
- thread:: sleep ( Duration :: from_millis ( TEST_REFILL_TIMER_INTERVAL_MS / 2 ) ) ;
1054
+ thread:: sleep ( TEST_REFILL_TIMER_DURATION / 2 ) ;
1055
1055
// the timer_fd should have an event on it by now
1056
1056
l. event_handler ( ) . unwrap ( ) ;
1057
1057
// limiter should now be unblocked
@@ -1081,11 +1081,11 @@ pub(crate) mod tests {
1081
1081
// since consume failed, limiter should be blocked now
1082
1082
assert ! ( l. is_blocked( ) ) ;
1083
1083
// wait half the timer period
1084
- thread:: sleep ( Duration :: from_millis ( TEST_REFILL_TIMER_INTERVAL_MS / 2 ) ) ;
1084
+ thread:: sleep ( TEST_REFILL_TIMER_DURATION / 2 ) ;
1085
1085
// limiter should still be blocked
1086
1086
assert ! ( l. is_blocked( ) ) ;
1087
1087
// wait the other half of the timer period
1088
- thread:: sleep ( Duration :: from_millis ( TEST_REFILL_TIMER_INTERVAL_MS / 2 ) ) ;
1088
+ thread:: sleep ( TEST_REFILL_TIMER_DURATION / 2 ) ;
1089
1089
// the timer_fd should have an event on it by now
1090
1090
l. event_handler ( ) . unwrap ( ) ;
1091
1091
// limiter should now be unblocked
0 commit comments