So, let's try something easy first: #ifdef __KERNEL__. (I know there are many esthetes around, but since this subject looks quite dirty...)
Alternatively we could change an api, and as a matter of fact there was such a try some time ago, but is it really worth of such a mess? Regards, Jarek P. -----------> (take 2) gen_kill_estimator() is called during qdisc_destroy() with BHs disabled, and each time does searching for each list member. This can block soft interrupts for quite a long time when many classes are used. This patch changes this by storing pointers to internal gen_estimator structures with gnet_stats_rate_est structures used by clients of gen_estimator. This method removes currently possible registering in gen_estimator the same structures more than once, but it isn't used after all. (There is added a warning if gen_new_estimator() is called with structures being used by gen_estimator already.) Thanks to David Miller for pointing an error in the first version of this patch. Reported-by: Badalian Vyacheslav <[EMAIL PROTECTED]> Signed-off-by: Jarek Poplawski <[EMAIL PROTECTED]> [needs more testing] --- include/linux/gen_stats.h | 4 ++++ net/core/gen_estimator.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff -Nurp 2.6.24-rc8-mm1-/include/linux/gen_stats.h 2.6.24-rc8-mm1+/include/linux/gen_stats.h --- 2.6.24-rc8-mm1-/include/linux/gen_stats.h 2007-10-09 22:31:38.000000000 +0200 +++ 2.6.24-rc8-mm1+/include/linux/gen_stats.h 2008-01-21 22:53:47.000000000 +0100 @@ -28,11 +28,15 @@ struct gnet_stats_basic * struct gnet_stats_rate_est - rate estimator * @bps: current byte rate * @pps: current packet rate + * @gen_estimator: internal data */ struct gnet_stats_rate_est { __u32 bps; __u32 pps; +#ifdef __KERNEL__ + unsigned long gen_estimator; +#endif }; /** diff -Nurp 2.6.24-rc8-mm1-/net/core/gen_estimator.c 2.6.24-rc8-mm1+/net/core/gen_estimator.c --- 2.6.24-rc8-mm1-/net/core/gen_estimator.c 2008-01-19 17:54:45.000000000 +0100 +++ 2.6.24-rc8-mm1+/net/core/gen_estimator.c 2008-01-20 20:58:35.000000000 +0100 @@ -139,6 +139,9 @@ skip: rcu_read_unlock(); } +static void gen_kill_estimator_find(struct gnet_stats_basic *bstats, + struct gnet_stats_rate_est *rate_est); + /** * gen_new_estimator - create a new rate estimator * @bstats: basic statistics @@ -171,6 +174,10 @@ int gen_new_estimator(struct gnet_stats_ if (parm->interval < -2 || parm->interval > 3) return -EINVAL; + if (rate_est->gen_estimator) + /* not sure: not zeroed in alloc or reused */ + gen_kill_estimator_find(bstats, rate_est); + est = kzalloc(sizeof(*est), GFP_KERNEL); if (est == NULL) return -ENOBUFS; @@ -184,6 +191,7 @@ int gen_new_estimator(struct gnet_stats_ est->avbps = rate_est->bps<<5; est->last_packets = bstats->packets; est->avpps = rate_est->pps<<10; + rate_est->gen_estimator = (unsigned long)est; if (!elist[idx].timer.function) { INIT_LIST_HEAD(&elist[idx].list); @@ -209,13 +217,30 @@ static void __gen_kill_estimator(struct * @bstats: basic statistics * @rate_est: rate estimator statistics * - * Removes the rate estimator specified by &bstats and &rate_est - * and deletes the timer. + * Removes the rate estimator specified by &bstats and &rate_est. * * NOTE: Called under rtnl_mutex */ void gen_kill_estimator(struct gnet_stats_basic *bstats, - struct gnet_stats_rate_est *rate_est) + struct gnet_stats_rate_est *rate_est) +{ + if (rate_est && rate_est->gen_estimator) { + struct gen_estimator *e; + + e = (struct gen_estimator *)rate_est->gen_estimator; + + rate_est->gen_estimator = 0; + write_lock_bh(&est_lock); + e->bstats = NULL; + write_unlock_bh(&est_lock); + + list_del_rcu(&e->list); + call_rcu(&e->e_rcu, __gen_kill_estimator); + } +} + +static void gen_kill_estimator_find(struct gnet_stats_basic *bstats, + struct gnet_stats_rate_est *rate_est) { int idx; struct gen_estimator *e, *n; @@ -236,6 +261,11 @@ void gen_kill_estimator(struct gnet_stat list_del_rcu(&e->list); call_rcu(&e->e_rcu, __gen_kill_estimator); + + WARN_ON_ONCE(1); /* gen_new_estimator() repeated? */ + rate_est->gen_estimator = 0; + + return; } } } -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html