diff options
| author | David S. Miller <davem@davemloft.net> | 2012-07-19 11:17:30 -0700 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-07-19 11:17:30 -0700 | 
| commit | abaa72d7fd9a20a67b62e6afa0e746e27851dc33 (patch) | |
| tree | ebe4134fcc93a6e205e6004b3e652d7a62281651 /net/core | |
| parent | 67da22d23fa6f3324e03bcd0580b914b2e4afbf3 (diff) | |
| parent | 3e4b9459fb0e149c6b74c9e89399a8fc39a92b44 (diff) | |
| download | linux-abaa72d7fd9a20a67b62e6afa0e746e27851dc33.tar.bz2 | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
	drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 3 | ||||
| -rw-r--r-- | net/core/net_namespace.c | 4 | ||||
| -rw-r--r-- | net/core/netprio_cgroup.c | 71 | ||||
| -rw-r--r-- | net/core/skbuff.c | 2 | 
4 files changed, 60 insertions, 20 deletions
| diff --git a/net/core/dev.c b/net/core/dev.c index 73e87c7b4377..d70e4a3a49f2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6313,7 +6313,8 @@ static struct hlist_head *netdev_create_hash(void)  /* Initialize per network namespace state */  static int __net_init netdev_init(struct net *net)  { -	INIT_LIST_HEAD(&net->dev_base_head); +	if (net != &init_net) +		INIT_LIST_HEAD(&net->dev_base_head);  	net->dev_name_head = netdev_create_hash();  	if (net->dev_name_head == NULL) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index dddbacb8f28c..42f1e1c7514f 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -27,7 +27,9 @@ static DEFINE_MUTEX(net_mutex);  LIST_HEAD(net_namespace_list);  EXPORT_SYMBOL_GPL(net_namespace_list); -struct net init_net; +struct net init_net = { +	.dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head), +};  EXPORT_SYMBOL(init_net);  #define INITIAL_NET_GEN_PTRS	13 /* +1 for len +2 for rcu_head */ diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 3e953eaddbfc..b2e9caa1ad1a 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -65,7 +65,7 @@ static void put_prioidx(u32 idx)  	spin_unlock_irqrestore(&prioidx_map_lock, flags);  } -static void extend_netdev_table(struct net_device *dev, u32 new_len) +static int extend_netdev_table(struct net_device *dev, u32 new_len)  {  	size_t new_size = sizeof(struct netprio_map) +  			   ((sizeof(u32) * new_len)); @@ -77,7 +77,7 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)  	if (!new_priomap) {  		pr_warn("Unable to alloc new priomap!\n"); -		return; +		return -ENOMEM;  	}  	for (i = 0; @@ -90,46 +90,79 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len)  	rcu_assign_pointer(dev->priomap, new_priomap);  	if (old_priomap)  		kfree_rcu(old_priomap, rcu); +	return 0;  } -static void update_netdev_tables(void) +static int write_update_netdev_table(struct net_device *dev)  { +	int ret = 0; +	u32 max_len; +	struct netprio_map *map; + +	rtnl_lock(); +	max_len = atomic_read(&max_prioidx) + 1; +	map = rtnl_dereference(dev->priomap); +	if (!map || map->priomap_len < max_len) +		ret = extend_netdev_table(dev, max_len); +	rtnl_unlock(); + +	return ret; +} + +static int update_netdev_tables(void) +{ +	int ret = 0;  	struct net_device *dev; -	u32 max_len = atomic_read(&max_prioidx) + 1; +	u32 max_len;  	struct netprio_map *map;  	rtnl_lock(); +	max_len = atomic_read(&max_prioidx) + 1;  	for_each_netdev(&init_net, dev) {  		map = rtnl_dereference(dev->priomap); -		if ((!map) || -		    (map->priomap_len < max_len)) -			extend_netdev_table(dev, max_len); +		/* +		 * don't allocate priomap if we didn't +		 * change net_prio.ifpriomap (map == NULL), +		 * this will speed up skb_update_prio. +		 */ +		if (map && map->priomap_len < max_len) { +			ret = extend_netdev_table(dev, max_len); +			if (ret < 0) +				break; +		}  	}  	rtnl_unlock(); +	return ret;  }  static struct cgroup_subsys_state *cgrp_create(struct cgroup *cgrp)  {  	struct cgroup_netprio_state *cs; -	int ret; +	int ret = -EINVAL;  	cs = kzalloc(sizeof(*cs), GFP_KERNEL);  	if (!cs)  		return ERR_PTR(-ENOMEM); -	if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) { -		kfree(cs); -		return ERR_PTR(-EINVAL); -	} +	if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) +		goto out;  	ret = get_prioidx(&cs->prioidx); -	if (ret != 0) { +	if (ret < 0) {  		pr_warn("No space in priority index array\n"); -		kfree(cs); -		return ERR_PTR(ret); +		goto out; +	} + +	ret = update_netdev_tables(); +	if (ret < 0) { +		put_prioidx(cs->prioidx); +		goto out;  	}  	return &cs->css; +out: +	kfree(cs); +	return ERR_PTR(ret);  }  static void cgrp_destroy(struct cgroup *cgrp) @@ -221,13 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft,  	if (!dev)  		goto out_free_devname; -	update_netdev_tables(); -	ret = 0; +	ret = write_update_netdev_table(dev); +	if (ret < 0) +		goto out_put_dev; +  	rcu_read_lock();  	map = rcu_dereference(dev->priomap);  	if (map)  		map->priomap[prioidx] = priority;  	rcu_read_unlock(); + +out_put_dev:  	dev_put(dev);  out_free_devname: diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c011d7fab62d..ccfcb7d8711e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -365,7 +365,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,  	unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +  			      SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); -	if (fragsz <= PAGE_SIZE && !(gfp_mask & __GFP_WAIT)) { +	if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) {  		void *data = netdev_alloc_frag(fragsz);  		if (likely(data)) { |