diff options
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/datapath.c | 19 | ||||
| -rw-r--r-- | net/openvswitch/vport.c | 18 | 
2 files changed, 16 insertions, 21 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index fcee6012293b..58f530f60172 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -236,9 +236,6 @@ void ovs_dp_detach_port(struct vport *p)  	/* First drop references to device. */  	hlist_del_rcu(&p->dp_hash_node); -	/* Free percpu memory */ -	free_percpu(p->upcall_stats); -  	/* Then destroy it. */  	ovs_vport_del(p);  } @@ -1858,12 +1855,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)  		goto err_destroy_portids;  	} -	vport->upcall_stats = netdev_alloc_pcpu_stats(struct vport_upcall_stats_percpu); -	if (!vport->upcall_stats) { -		err = -ENOMEM; -		goto err_destroy_vport; -	} -  	err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,  				   info->snd_seq, 0, OVS_DP_CMD_NEW);  	BUG_ON(err < 0); @@ -1876,8 +1867,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)  	ovs_notify(&dp_datapath_genl_family, reply, info);  	return 0; -err_destroy_vport: -	ovs_dp_detach_port(vport);  err_destroy_portids:  	kfree(rcu_dereference_raw(dp->upcall_portids));  err_unlock_and_destroy_meters: @@ -2322,12 +2311,6 @@ restart:  		goto exit_unlock_free;  	} -	vport->upcall_stats = netdev_alloc_pcpu_stats(struct vport_upcall_stats_percpu); -	if (!vport->upcall_stats) { -		err = -ENOMEM; -		goto exit_unlock_free_vport; -	} -  	err = ovs_vport_cmd_fill_info(vport, reply, genl_info_net(info),  				      info->snd_portid, info->snd_seq, 0,  				      OVS_VPORT_CMD_NEW, GFP_KERNEL); @@ -2345,8 +2328,6 @@ restart:  	ovs_notify(&dp_vport_genl_family, reply, info);  	return 0; -exit_unlock_free_vport: -	ovs_dp_detach_port(vport);  exit_unlock_free:  	ovs_unlock();  	kfree_skb(reply); diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 7e0f5c45b512..972ae01a70f7 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -124,6 +124,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,  {  	struct vport *vport;  	size_t alloc_size; +	int err;  	alloc_size = sizeof(struct vport);  	if (priv_size) { @@ -135,17 +136,29 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,  	if (!vport)  		return ERR_PTR(-ENOMEM); +	vport->upcall_stats = netdev_alloc_pcpu_stats(struct vport_upcall_stats_percpu); +	if (!vport->upcall_stats) { +		err = -ENOMEM; +		goto err_kfree_vport; +	} +  	vport->dp = parms->dp;  	vport->port_no = parms->port_no;  	vport->ops = ops;  	INIT_HLIST_NODE(&vport->dp_hash_node);  	if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids)) { -		kfree(vport); -		return ERR_PTR(-EINVAL); +		err = -EINVAL; +		goto err_free_percpu;  	}  	return vport; + +err_free_percpu: +	free_percpu(vport->upcall_stats); +err_kfree_vport: +	kfree(vport); +	return ERR_PTR(err);  }  EXPORT_SYMBOL_GPL(ovs_vport_alloc); @@ -165,6 +178,7 @@ void ovs_vport_free(struct vport *vport)  	 * it is safe to use raw dereference.  	 */  	kfree(rcu_dereference_raw(vport->upcall_portids)); +	free_percpu(vport->upcall_stats);  	kfree(vport);  }  EXPORT_SYMBOL_GPL(ovs_vport_free);  | 
