Commit 12efa1fa authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

net_sched: gen_estimator: account for timer drifts

Under heavy stress, timer used in estimators tend to slowly be delayed
by a few jiffies, leading to inaccuracies.

Lets remember what was the last scheduled jiffies so that we get more
precise estimations, without having to add a multiply/divide in the loop
to account for the drifts.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e01b16a7
...@@ -78,8 +78,7 @@ ...@@ -78,8 +78,7 @@
#define EST_MAX_INTERVAL 5 #define EST_MAX_INTERVAL 5
struct gen_estimator struct gen_estimator {
{
struct list_head list; struct list_head list;
struct gnet_stats_basic_packed *bstats; struct gnet_stats_basic_packed *bstats;
struct gnet_stats_rate_est64 *rate_est; struct gnet_stats_rate_est64 *rate_est;
...@@ -96,8 +95,8 @@ struct gen_estimator ...@@ -96,8 +95,8 @@ struct gen_estimator
struct rcu_head head; struct rcu_head head;
}; };
struct gen_estimator_head struct gen_estimator_head {
{ unsigned long next_jiffies;
struct timer_list timer; struct timer_list timer;
struct list_head list; struct list_head list;
}; };
...@@ -146,8 +145,15 @@ static void est_timer(unsigned long arg) ...@@ -146,8 +145,15 @@ static void est_timer(unsigned long arg)
spin_unlock(e->stats_lock); spin_unlock(e->stats_lock);
} }
if (!list_empty(&elist[idx].list)) if (!list_empty(&elist[idx].list)) {
mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx)); elist[idx].next_jiffies += ((HZ/4) << idx);
if (unlikely(time_after_eq(jiffies, elist[idx].next_jiffies))) {
/* Ouch... timer was delayed. */
elist[idx].next_jiffies = jiffies + 1;
}
mod_timer(&elist[idx].timer, elist[idx].next_jiffies);
}
rcu_read_unlock(); rcu_read_unlock();
} }
...@@ -251,9 +257,10 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, ...@@ -251,9 +257,10 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
setup_timer(&elist[idx].timer, est_timer, idx); setup_timer(&elist[idx].timer, est_timer, idx);
} }
if (list_empty(&elist[idx].list)) if (list_empty(&elist[idx].list)) {
mod_timer(&elist[idx].timer, jiffies + ((HZ/4) << idx)); elist[idx].next_jiffies = jiffies + ((HZ/4) << idx);
mod_timer(&elist[idx].timer, elist[idx].next_jiffies);
}
list_add_rcu(&est->list, &elist[idx].list); list_add_rcu(&est->list, &elist[idx].list);
gen_add_node(est); gen_add_node(est);
spin_unlock_bh(&est_tree_lock); spin_unlock_bh(&est_tree_lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment