From e6f9b1f96a3ac4066c9d7d4c0a9da7e8abb1597f Mon Sep 17 00:00:00 2001 From: Yi Yang Date: Wed, 13 Apr 2016 18:17:21 +0800 Subject: [PATCH 4/5] Fix too large stack frame size Signed-off-by: Yi Yang --- datapath/datapath.c | 92 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 14 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 5bec072..4baf242 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -928,7 +928,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) struct sw_flow_mask mask; struct sk_buff *reply; struct datapath *dp; - struct sw_flow_key key; + struct sw_flow_key *key = NULL; struct sw_flow_actions *acts; struct sw_flow_match match; u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]); @@ -946,6 +946,12 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) goto error; } + error = -ENOMEM; + key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL); + if (key == NULL) { + goto error; + } + /* Most of the time we need to allocate a new flow, do it before * locking. */ @@ -956,17 +962,17 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) } /* Extract key. */ - ovs_match_init(&match, &key, &mask); + ovs_match_init(&match, key, &mask); error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK], log); if (error) goto err_kfree_flow; - ovs_flow_mask_key(&new_flow->key, &key, true, &mask); + ovs_flow_mask_key(&new_flow->key, key, true, &mask); /* Extract flow identifier. */ error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], - &key, log); + key, log); if (error) goto err_kfree_flow; @@ -996,7 +1002,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) if (ovs_identifier_is_ufid(&new_flow->id)) flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id); if (!flow) - flow = ovs_flow_tbl_lookup(&dp->table, &key); + flow = ovs_flow_tbl_lookup(&dp->table, key); if (likely(!flow)) { rcu_assign_pointer(new_flow->sf_acts, acts); @@ -1066,6 +1072,10 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) if (reply) ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info); + if (key != NULL) { + kfree(key); + key = NULL; + } return 0; err_unlock_ovs: @@ -1076,6 +1086,10 @@ err_kfree_acts: err_kfree_flow: ovs_flow_free(new_flow, false); error: + if (key != NULL) { + kfree(key); + key = NULL; + } return error; } @@ -1106,7 +1120,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) struct net *net = sock_net(skb->sk); struct nlattr **a = info->attrs; struct ovs_header *ovs_header = info->userhdr; - struct sw_flow_key key; + struct sw_flow_key *key = NULL; struct sw_flow *flow; struct sw_flow_mask mask; struct sk_buff *reply = NULL; @@ -1119,6 +1133,12 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) bool log = !a[OVS_FLOW_ATTR_PROBE]; bool ufid_present; + error = -ENOMEM; + key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL); + if (key == NULL) { + goto error; + } + /* Extract key. */ error = -EINVAL; if (!a[OVS_FLOW_ATTR_KEY]) { @@ -1127,7 +1147,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) } ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log); - ovs_match_init(&match, &key, &mask); + ovs_match_init(&match, key, &mask); error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK], log); if (error) @@ -1135,7 +1155,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) /* Validate actions. */ if (a[OVS_FLOW_ATTR_ACTIONS]) { - acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &key, + acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], key, &mask, log); if (IS_ERR(acts)) { error = PTR_ERR(acts); @@ -1203,6 +1223,10 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) if (old_acts) ovs_nla_free_flow_actions_rcu(old_acts); + if (key != NULL) { + kfree(key); + key = NULL; + } return 0; err_unlock_ovs: @@ -1211,6 +1235,10 @@ err_unlock_ovs: err_kfree_acts: ovs_nla_free_flow_actions(acts); error: + if (key != NULL) { + kfree(key); + key = NULL; + } return error; } @@ -1219,7 +1247,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) struct nlattr **a = info->attrs; struct ovs_header *ovs_header = info->userhdr; struct net *net = sock_net(skb->sk); - struct sw_flow_key key; + struct sw_flow_key *key = NULL; struct sk_buff *reply; struct sw_flow *flow; struct datapath *dp; @@ -1230,9 +1258,15 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) bool log = !a[OVS_FLOW_ATTR_PROBE]; bool ufid_present; + err = -ENOMEM; + key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL); + if (key == NULL) { + return err; + } + ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log); if (a[OVS_FLOW_ATTR_KEY]) { - ovs_match_init(&match, &key, NULL); + ovs_match_init(&match, key, NULL); err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL, log); } else if (!ufid_present) { @@ -1240,9 +1274,13 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) "Flow get message rejected, Key attribute missing."); err = -EINVAL; } - if (err) + if (err) { + if (key != NULL) { + kfree(key); + key = NULL; + } return err; - + } ovs_lock(); dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); if (!dp) { @@ -1267,9 +1305,17 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) } ovs_unlock(); + if (key != NULL) { + kfree(key); + key = NULL; + } return genlmsg_reply(reply, info); unlock: ovs_unlock(); + if (key != NULL) { + kfree(key); + key = NULL; + } return err; } @@ -1278,7 +1324,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) struct nlattr **a = info->attrs; struct ovs_header *ovs_header = info->userhdr; struct net *net = sock_net(skb->sk); - struct sw_flow_key key; + struct sw_flow_key *key = NULL; struct sk_buff *reply; struct sw_flow *flow = NULL; struct datapath *dp; @@ -1289,12 +1335,22 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) bool log = !a[OVS_FLOW_ATTR_PROBE]; bool ufid_present; + err = -ENOMEM; + key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL); + if (key == NULL) { + return err; + } + ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log); if (a[OVS_FLOW_ATTR_KEY]) { - ovs_match_init(&match, &key, NULL); + ovs_match_init(&match, key, NULL); err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL, log); if (unlikely(err)) + if (key != NULL) { + kfree(key); + key = NULL; + } return err; } @@ -1344,9 +1400,17 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) } ovs_flow_free(flow, true); + if (key != NULL) { + kfree(key); + key = NULL; + } return 0; unlock: ovs_unlock(); + if (key != NULL) { + kfree(key); + key = NULL; + } return err; } -- 1.9.3