@@ -5,7 +5,7 @@ use std::os::unix::io::{AsRawFd, RawFd};
55use std:: time:: { Duration , Instant } ;
66use std:: { fmt, io} ;
77
8- use timerfd:: { ClockId , SetTimeFlags , TimerFd , TimerState } ;
8+ use vmm_sys_util :: timerfd:: { TimerFd , TimerFdFlag } ;
99
1010pub mod persist;
1111
@@ -14,12 +14,12 @@ pub mod persist;
1414pub enum RateLimiterError {
1515 /// Rate limiter event handler called without a present timer
1616 SpuriousRateLimiterEvent ,
17+ /// Error reading timerfd: {0}
18+ Read ( #[ from] vmm_sys_util:: errno:: Error ) ,
1719}
1820
1921// 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 ) ;
2323
2424const NANOSEC_IN_ONE_MILLISEC : u64 = 1_000_000 ;
2525
@@ -367,7 +367,7 @@ impl RateLimiter {
367367 // We'll need a timer_fd, even if our current config effectively disables rate limiting,
368368 // because `Self::update_buckets()` might re-enable it later, and we might be
369369 // 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 ) ?;
371371
372372 Ok ( RateLimiter {
373373 bandwidth : bytes_token_bucket,
@@ -378,9 +378,11 @@ impl RateLimiter {
378378 }
379379
380380 // 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 ) {
382382 // 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" ) ;
384386 self . timer_active = true ;
385387 }
386388
@@ -407,7 +409,7 @@ impl RateLimiter {
407409 // make sure there is only one running timer for this limiter.
408410 BucketReduction :: Failure => {
409411 if !self . timer_active {
410- self . activate_timer ( TIMER_REFILL_STATE ) ;
412+ self . activate_timer ( REFILL_TIMER_DURATION ) ;
411413 }
412414 false
413415 }
@@ -424,9 +426,7 @@ impl RateLimiter {
424426 // `ratio * refill_time` milliseconds.
425427 // The conversion should be safe because the ratio is positive.
426428 #[ 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 ) ) ;
430430 true
431431 }
432432 }
@@ -469,7 +469,7 @@ impl RateLimiter {
469469 ///
470470 /// If the rate limiter is disabled or is not blocked, an error is returned.
471471 pub fn event_handler ( & mut self ) -> Result < ( ) , RateLimiterError > {
472- match self . timer_fd . read ( ) {
472+ match self . timer_fd . wait ( ) ? {
473473 0 => Err ( RateLimiterError :: SpuriousRateLimiterEvent ) ,
474474 _ => {
475475 self . timer_active = false ;
@@ -777,7 +777,7 @@ pub(crate) mod tests {
777777 // second wait will always result in the limiter being refilled. Otherwise
778778 // there is a chance for a race condition between limiter refilling and limiter
779779 // 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 ) ;
781781
782782 impl TokenBucket {
783783 // Resets the token bucket: budget set to max capacity and last-updated set to now.
@@ -1014,11 +1014,11 @@ pub(crate) mod tests {
10141014 // since consume failed, limiter should be blocked now
10151015 assert ! ( l. is_blocked( ) ) ;
10161016 // 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 ) ;
10181018 // limiter should still be blocked
10191019 assert ! ( l. is_blocked( ) ) ;
10201020 // 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 ) ;
10221022 // the timer_fd should have an event on it by now
10231023 l. event_handler ( ) . unwrap ( ) ;
10241024 // limiter should now be unblocked
@@ -1047,11 +1047,11 @@ pub(crate) mod tests {
10471047 // since consume failed, limiter should be blocked now
10481048 assert ! ( l. is_blocked( ) ) ;
10491049 // 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 ) ;
10511051 // limiter should still be blocked
10521052 assert ! ( l. is_blocked( ) ) ;
10531053 // 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 ) ;
10551055 // the timer_fd should have an event on it by now
10561056 l. event_handler ( ) . unwrap ( ) ;
10571057 // limiter should now be unblocked
@@ -1081,11 +1081,11 @@ pub(crate) mod tests {
10811081 // since consume failed, limiter should be blocked now
10821082 assert ! ( l. is_blocked( ) ) ;
10831083 // 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 ) ;
10851085 // limiter should still be blocked
10861086 assert ! ( l. is_blocked( ) ) ;
10871087 // 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 ) ;
10891089 // the timer_fd should have an event on it by now
10901090 l. event_handler ( ) . unwrap ( ) ;
10911091 // limiter should now be unblocked
0 commit comments