Pushed to master with the function name change (ovs_vport_cmd_alloc() -> ovs_vport_cmd_alloc_info()).
Jarno On Mar 28, 2014, at 1:26 PM, Pravin Shelar <pshe...@nicira.com> wrote: > On Tue, Mar 25, 2014 at 2:35 PM, Jarno Rajahalme <jrajaha...@nicira.com> > wrote: >> Move most memory allocations away from the ovs_mutex critical >> sections. vport allocations still happen while the lock is taken, as >> changing that would require major refactoring. Also, vports are >> created very rarely so it should not matter. >> >> Change ovs_dp_cmd_get() now only takes the rcu_read_lock(), rather >> than ovs_lock(), as nothing need to be changed. This was done by >> ovs_vport_cmd_get() already. >> >> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> >> --- >> v5: Rebase. >> >> datapath/datapath.c | 223 >> ++++++++++++++++++++++++++------------------------- >> 1 file changed, 112 insertions(+), 111 deletions(-) >> >> diff --git a/datapath/datapath.c b/datapath/datapath.c >> index aa3f789..ca18879 100644 >> --- a/datapath/datapath.c >> +++ b/datapath/datapath.c >> @@ -1271,23 +1271,9 @@ error: >> return -EMSGSIZE; >> } >> >> -/* Must be called with ovs_mutex. */ >> -static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, >> - struct genl_info *info, u8 cmd) >> +static struct sk_buff *ovs_dp_cmd_alloc_info(struct genl_info *info) >> { >> - struct sk_buff *skb; >> - int retval; >> - >> - skb = genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL); >> - if (!skb) >> - return ERR_PTR(-ENOMEM); >> - >> - retval = ovs_dp_cmd_fill_info(dp, skb, info->snd_portid, >> info->snd_seq, 0, cmd); >> - if (retval < 0) { >> - kfree_skb(skb); >> - return ERR_PTR(retval); >> - } >> - return skb; >> + return genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL); >> } >> >> /* Called with rcu_read_lock or ovs_mutex. */ >> @@ -1340,12 +1326,14 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, >> struct genl_info *info) >> if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID]) >> goto err; >> >> - ovs_lock(); >> + reply = ovs_dp_cmd_alloc_info(info); >> + if (!reply) >> + return -ENOMEM; >> >> err = -ENOMEM; >> dp = kzalloc(sizeof(*dp), GFP_KERNEL); >> if (dp == NULL) >> - goto err_unlock_ovs; >> + goto err_free_reply; >> >> ovs_dp_set_net(dp, hold_net(sock_net(skb->sk))); >> >> @@ -1380,6 +1368,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct >> genl_info *info) >> >> ovs_dp_change(dp, a); >> >> + /* So far only local changes have been made, now need the lock. */ >> + ovs_lock(); >> + >> vport = new_vport(&parms); >> if (IS_ERR(vport)) { >> err = PTR_ERR(vport); >> @@ -1398,10 +1389,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct >> genl_info *info) >> goto err_destroy_ports_array; >> } >> >> - reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); >> - err = PTR_ERR(reply); >> - if (IS_ERR(reply)) >> - goto err_destroy_local_port; >> + err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_DP_CMD_NEW); >> + BUG_ON(err < 0); >> >> ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); >> list_add_tail_rcu(&dp->list_node, &ovs_net->dps); >> @@ -1411,9 +1401,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct >> genl_info *info) >> ovs_notify(reply, info, &ovs_dp_datapath_multicast_group); >> return 0; >> >> -err_destroy_local_port: >> - ovs_dp_detach_port(ovs_vport_ovsl(dp, OVSP_LOCAL)); >> err_destroy_ports_array: >> + ovs_unlock(); >> kfree(dp->ports); >> err_destroy_percpu: >> free_percpu(dp->stats_percpu); >> @@ -1422,8 +1411,8 @@ err_destroy_table: >> err_free_dp: >> release_net(ovs_dp_get_net(dp)); >> kfree(dp); >> -err_unlock_ovs: >> - ovs_unlock(); >> +err_free_reply: >> + kfree_skb(reply); >> err: >> return err; >> } >> @@ -1461,25 +1450,29 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, >> struct genl_info *info) >> struct datapath *dp; >> int err; >> >> + reply = ovs_dp_cmd_alloc_info(info); >> + if (!reply) >> + return -ENOMEM; >> + >> ovs_lock(); >> dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); >> err = PTR_ERR(dp); >> if (IS_ERR(dp)) >> - goto unlock; >> + goto err_unlock_free; >> >> - reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_DEL); >> - err = PTR_ERR(reply); >> - if (IS_ERR(reply)) >> - goto unlock; >> + err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_DP_CMD_DEL); >> + BUG_ON(err < 0); >> >> __dp_destroy(dp); >> - ovs_unlock(); >> >> + ovs_unlock(); >> ovs_notify(reply, info, &ovs_dp_datapath_multicast_group); >> - >> return 0; >> -unlock: >> + >> +err_unlock_free: >> ovs_unlock(); >> + kfree_skb(reply); >> return err; >> } >> >> @@ -1489,29 +1482,29 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, >> struct genl_info *info) >> struct datapath *dp; >> int err; >> >> + reply = ovs_dp_cmd_alloc_info(info); >> + if (!reply) >> + return -ENOMEM; >> + >> ovs_lock(); >> dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); >> err = PTR_ERR(dp); >> if (IS_ERR(dp)) >> - goto unlock; >> + goto err_unlock_free; >> >> ovs_dp_change(dp, info->attrs); >> >> - reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); >> - if (IS_ERR(reply)) { >> - err = PTR_ERR(reply); >> - netlink_set_err(sock_net(skb->sk)->genl_sock, 0, >> - ovs_dp_datapath_multicast_group.id, err); >> - err = 0; >> - goto unlock; >> - } >> + err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_DP_CMD_NEW); >> + BUG_ON(err < 0); >> >> ovs_unlock(); >> ovs_notify(reply, info, &ovs_dp_datapath_multicast_group); >> - >> return 0; >> -unlock: >> + >> +err_unlock_free: >> ovs_unlock(); >> + kfree_skb(reply); >> return err; >> } >> >> @@ -1521,24 +1514,26 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, >> struct genl_info *info) >> struct datapath *dp; >> int err; >> >> - ovs_lock(); >> + reply = ovs_dp_cmd_alloc_info(info); >> + if (!reply) >> + return -ENOMEM; >> + >> + rcu_read_lock(); >> dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs); >> if (IS_ERR(dp)) { >> err = PTR_ERR(dp); >> - goto unlock; >> - } >> - >> - reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); >> - if (IS_ERR(reply)) { >> - err = PTR_ERR(reply); >> - goto unlock; >> + goto err_unlock_free; >> } >> + err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_DP_CMD_NEW); >> + BUG_ON(err < 0); >> + rcu_read_unlock(); >> >> - ovs_unlock(); >> return genlmsg_reply(reply, info); >> >> -unlock: >> - ovs_unlock(); >> +err_unlock_free: >> + rcu_read_unlock(); >> + kfree_skb(reply); >> return err; >> } >> >> @@ -1651,7 +1646,12 @@ error: >> return err; >> } >> >> -/* Called with ovs_mutex or RCU read lock. */ >> +static struct sk_buff *ovs_vport_cmd_alloc(void) >> +{ >> + return nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); >> +} >> + > ovs_vport_cmd_alloc is not clear, may be we can use _info suffix? > >> +/* Called with ovs_mutex, only via ovs_dp_notify_wq(). */ >> struct sk_buff *ovs_vport_cmd_build_info(struct vport *vport, u32 portid, >> u32 seq, u8 cmd) >> { >> @@ -1713,33 +1713,35 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, >> struct genl_info *info) >> u32 port_no; >> int err; >> >> - err = -EINVAL; >> if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] || >> !a[OVS_VPORT_ATTR_UPCALL_PID]) >> - goto exit; >> + return -EINVAL; >> + >> + port_no = a[OVS_VPORT_ATTR_PORT_NO] >> + ? nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]) : 0; >> + if (port_no >= DP_MAX_PORTS) >> + return -EFBIG; >> + >> + reply = ovs_vport_cmd_alloc(); >> + if (!reply) >> + return -ENOMEM; >> >> ovs_lock(); >> dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); >> err = -ENODEV; >> if (!dp) >> - goto exit_unlock; >> - >> - if (a[OVS_VPORT_ATTR_PORT_NO]) { >> - port_no = nla_get_u32(a[OVS_VPORT_ATTR_PORT_NO]); >> - >> - err = -EFBIG; >> - if (port_no >= DP_MAX_PORTS) >> - goto exit_unlock; >> + goto exit_unlock_free; >> >> + if (port_no) { >> vport = ovs_vport_ovsl(dp, port_no); >> err = -EBUSY; >> if (vport) >> - goto exit_unlock; >> + goto exit_unlock_free; >> } else { >> for (port_no = 1; ; port_no++) { >> if (port_no >= DP_MAX_PORTS) { >> err = -EFBIG; >> - goto exit_unlock; >> + goto exit_unlock_free; >> } >> vport = ovs_vport_ovsl(dp, port_no); >> if (!vport) >> @@ -1757,25 +1759,23 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, >> struct genl_info *info) >> vport = new_vport(&parms); >> err = PTR_ERR(vport); >> if (IS_ERR(vport)) >> - goto exit_unlock; >> + goto exit_unlock_free; >> >> err = 0; >> if (a[OVS_VPORT_ATTR_STATS]) >> ovs_vport_set_stats(vport, nla_data(a[OVS_VPORT_ATTR_STATS])); >> >> - reply = ovs_vport_cmd_build_info(vport, info->snd_portid, >> info->snd_seq, >> - OVS_VPORT_CMD_NEW); >> - if (IS_ERR(reply)) { >> - err = PTR_ERR(reply); >> - ovs_dp_detach_port(vport); >> - goto exit_unlock; >> - } >> + err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_VPORT_CMD_NEW); >> + BUG_ON(err < 0); >> + ovs_unlock(); >> >> ovs_notify(reply, info, &ovs_dp_vport_multicast_group); >> + return 0; >> >> -exit_unlock: >> +exit_unlock_free: >> ovs_unlock(); >> -exit: >> + kfree_skb(reply); >> return err; >> } >> >> @@ -1786,28 +1786,26 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, >> struct genl_info *info) >> struct vport *vport; >> int err; >> >> + reply = ovs_vport_cmd_alloc(); >> + if (!reply) >> + return -ENOMEM; >> + >> ovs_lock(); >> vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); >> err = PTR_ERR(vport); >> if (IS_ERR(vport)) >> - goto exit_unlock; >> + goto exit_unlock_free; >> >> if (a[OVS_VPORT_ATTR_TYPE] && >> nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type) { >> err = -EINVAL; >> - goto exit_unlock; >> - } >> - >> - reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); >> - if (!reply) { >> - err = -ENOMEM; >> - goto exit_unlock; >> + goto exit_unlock_free; >> } >> >> if (a[OVS_VPORT_ATTR_OPTIONS]) { >> err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]); >> if (err) >> - goto exit_free; >> + goto exit_unlock_free; >> } >> >> if (a[OVS_VPORT_ATTR_STATS]) >> @@ -1819,15 +1817,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, >> struct genl_info *info) >> err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, >> info->snd_seq, 0, OVS_VPORT_CMD_NEW); >> BUG_ON(err < 0); >> - >> ovs_unlock(); >> + >> ovs_notify(reply, info, &ovs_dp_vport_multicast_group); >> return 0; >> >> -exit_free: >> - kfree_skb(reply); >> -exit_unlock: >> +exit_unlock_free: >> ovs_unlock(); >> + kfree_skb(reply); >> return err; >> } >> >> @@ -1838,30 +1835,33 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, >> struct genl_info *info) >> struct vport *vport; >> int err; >> >> + reply = ovs_vport_cmd_alloc(); >> + if (!reply) >> + return -ENOMEM; >> + >> ovs_lock(); >> vport = lookup_vport(sock_net(skb->sk), info->userhdr, a); >> err = PTR_ERR(vport); >> if (IS_ERR(vport)) >> - goto exit_unlock; >> + goto exit_unlock_free; >> >> if (vport->port_no == OVSP_LOCAL) { >> err = -EINVAL; >> - goto exit_unlock; >> + goto exit_unlock_free; >> } >> >> - reply = ovs_vport_cmd_build_info(vport, info->snd_portid, >> - info->snd_seq, OVS_VPORT_CMD_DEL); >> - err = PTR_ERR(reply); >> - if (IS_ERR(reply)) >> - goto exit_unlock; >> - >> - err = 0; >> + err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_VPORT_CMD_DEL); >> + BUG_ON(err < 0); >> ovs_dp_detach_port(vport); >> + ovs_unlock(); >> >> ovs_notify(reply, info, &ovs_dp_vport_multicast_group); >> + return 0; >> >> -exit_unlock: >> +exit_unlock_free: >> ovs_unlock(); >> + kfree_skb(reply); >> return err; >> } >> >> @@ -1873,24 +1873,25 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, >> struct genl_info *info) >> struct vport *vport; >> int err; >> >> + reply = ovs_vport_cmd_alloc(); >> + if (!reply) >> + return -ENOMEM; >> + >> rcu_read_lock(); >> vport = lookup_vport(sock_net(skb->sk), ovs_header, a); >> err = PTR_ERR(vport); >> if (IS_ERR(vport)) >> - goto exit_unlock; >> - >> - reply = ovs_vport_cmd_build_info(vport, info->snd_portid, >> - info->snd_seq, OVS_VPORT_CMD_NEW); >> - err = PTR_ERR(reply); >> - if (IS_ERR(reply)) >> - goto exit_unlock; >> - >> + goto exit_unlock_free; >> + err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, >> + info->snd_seq, 0, OVS_VPORT_CMD_NEW); >> + BUG_ON(err < 0); >> rcu_read_unlock(); >> >> return genlmsg_reply(reply, info); >> >> -exit_unlock: >> +exit_unlock_free: >> rcu_read_unlock(); >> + kfree_skb(reply); >> return err; >> } >> > Acked-by: Pravin B Shelar <pshe...@nicira.com> > >> -- >> 1.7.10.4 >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev