diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2011-01-13 15:06:28 +0900 | 
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2011-01-13 15:06:28 +0900 | 
| commit | f43dc23d5ea91fca257be02138a255f02d98e806 (patch) | |
| tree | b29722f6e965316e90ac97abf79923ced250dc21 /net/core/gen_estimator.c | |
| parent | f8e53553f452dcbf67cb89c8cba63a1cd6eb4cc0 (diff) | |
| parent | 4162cf64973df51fc885825bc9ca4d055891c49f (diff) | |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into common/serial-rework
Conflicts:
	arch/sh/kernel/cpu/sh2/setup-sh7619.c
	arch/sh/kernel/cpu/sh2a/setup-mxg.c
	arch/sh/kernel/cpu/sh2a/setup-sh7201.c
	arch/sh/kernel/cpu/sh2a/setup-sh7203.c
	arch/sh/kernel/cpu/sh2a/setup-sh7206.c
	arch/sh/kernel/cpu/sh3/setup-sh7705.c
	arch/sh/kernel/cpu/sh3/setup-sh770x.c
	arch/sh/kernel/cpu/sh3/setup-sh7710.c
	arch/sh/kernel/cpu/sh3/setup-sh7720.c
	arch/sh/kernel/cpu/sh4/setup-sh4-202.c
	arch/sh/kernel/cpu/sh4/setup-sh7750.c
	arch/sh/kernel/cpu/sh4/setup-sh7760.c
	arch/sh/kernel/cpu/sh4a/setup-sh7343.c
	arch/sh/kernel/cpu/sh4a/setup-sh7366.c
	arch/sh/kernel/cpu/sh4a/setup-sh7722.c
	arch/sh/kernel/cpu/sh4a/setup-sh7723.c
	arch/sh/kernel/cpu/sh4a/setup-sh7724.c
	arch/sh/kernel/cpu/sh4a/setup-sh7763.c
	arch/sh/kernel/cpu/sh4a/setup-sh7770.c
	arch/sh/kernel/cpu/sh4a/setup-sh7780.c
	arch/sh/kernel/cpu/sh4a/setup-sh7785.c
	arch/sh/kernel/cpu/sh4a/setup-sh7786.c
	arch/sh/kernel/cpu/sh4a/setup-shx3.c
	arch/sh/kernel/cpu/sh5/setup-sh5.c
	drivers/serial/sh-sci.c
	drivers/serial/sh-sci.h
	include/linux/serial_sci.h
Diffstat (limited to 'net/core/gen_estimator.c')
| -rw-r--r-- | net/core/gen_estimator.c | 33 | 
1 files changed, 22 insertions, 11 deletions
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 78e5bfc454a..7c2373321b7 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -32,6 +32,7 @@  #include <linux/rtnetlink.h>  #include <linux/init.h>  #include <linux/rbtree.h> +#include <linux/slab.h>  #include <net/sock.h>  #include <net/gen_stats.h> @@ -81,7 +82,7 @@  struct gen_estimator  {  	struct list_head	list; -	struct gnet_stats_basic	*bstats; +	struct gnet_stats_basic_packed	*bstats;  	struct gnet_stats_rate_est	*rate_est;  	spinlock_t		*stats_lock;  	int			ewma_log; @@ -106,6 +107,7 @@ static DEFINE_RWLOCK(est_lock);  /* Protects against soft lockup during large deletion */  static struct rb_root est_root = RB_ROOT; +static DEFINE_SPINLOCK(est_tree_lock);  static void est_timer(unsigned long arg)  { @@ -165,7 +167,7 @@ static void gen_add_node(struct gen_estimator *est)  }  static -struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats, +struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats,  				    const struct gnet_stats_rate_est *rate_est)  {  	struct rb_node *p = est_root.rb_node; @@ -200,9 +202,8 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats,   *   * Returns 0 on success or a negative error code.   * - * NOTE: Called under rtnl_mutex   */ -int gen_new_estimator(struct gnet_stats_basic *bstats, +int gen_new_estimator(struct gnet_stats_basic_packed *bstats,  		      struct gnet_stats_rate_est *rate_est,  		      spinlock_t *stats_lock,  		      struct nlattr *opt) @@ -231,6 +232,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,  	est->last_packets = bstats->packets;  	est->avpps = rate_est->pps<<10; +	spin_lock_bh(&est_tree_lock);  	if (!elist[idx].timer.function) {  		INIT_LIST_HEAD(&elist[idx].list);  		setup_timer(&elist[idx].timer, est_timer, idx); @@ -241,6 +243,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,  	list_add_rcu(&est->list, &elist[idx].list);  	gen_add_node(est); +	spin_unlock_bh(&est_tree_lock);  	return 0;  } @@ -260,23 +263,25 @@ static void __gen_kill_estimator(struct rcu_head *head)   *   * Removes the rate estimator specified by &bstats and &rate_est.   * - * NOTE: Called under rtnl_mutex + * Note : Caller should respect an RCU grace period before freeing stats_lock   */ -void gen_kill_estimator(struct gnet_stats_basic *bstats, +void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,  			struct gnet_stats_rate_est *rate_est)  {  	struct gen_estimator *e; +	spin_lock_bh(&est_tree_lock);  	while ((e = gen_find_node(bstats, rate_est))) {  		rb_erase(&e->node, &est_root); -		write_lock_bh(&est_lock); +		write_lock(&est_lock);  		e->bstats = NULL; -		write_unlock_bh(&est_lock); +		write_unlock(&est_lock);  		list_del_rcu(&e->list);  		call_rcu(&e->e_rcu, __gen_kill_estimator);  	} +	spin_unlock_bh(&est_tree_lock);  }  EXPORT_SYMBOL(gen_kill_estimator); @@ -292,7 +297,7 @@ EXPORT_SYMBOL(gen_kill_estimator);   *   * Returns 0 on success or a negative error code.   */ -int gen_replace_estimator(struct gnet_stats_basic *bstats, +int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,  			  struct gnet_stats_rate_est *rate_est,  			  spinlock_t *stats_lock, struct nlattr *opt)  { @@ -308,11 +313,17 @@ EXPORT_SYMBOL(gen_replace_estimator);   *   * Returns true if estimator is active, and false if not.   */ -bool gen_estimator_active(const struct gnet_stats_basic *bstats, +bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,  			  const struct gnet_stats_rate_est *rate_est)  { +	bool res; +  	ASSERT_RTNL(); -	return gen_find_node(bstats, rate_est) != NULL; +	spin_lock_bh(&est_tree_lock); +	res = gen_find_node(bstats, rate_est) != NULL; +	spin_unlock_bh(&est_tree_lock); + +	return res;  }  EXPORT_SYMBOL(gen_estimator_active);  | 
