Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84bf7430 authored by Ivan Vecera's avatar Ivan Vecera Committed by Greg Kroah-Hartman
Browse files

net/sched: cls_flower: allocate mask dynamically in fl_change()



[ Upstream commit 2cddd20147826aef283115abb00012d4dafe3cdb ]

Recent changes (especially 05cd271f ("cls_flower: Support multiple
masks per priority")) in the fl_flow_mask structure grow it and its
current size e.g. on x86_64 with defconfig is 760 bytes and more than
1024 bytes with some debug options enabled. Prior the mentioned commit
its size was 176 bytes (using defconfig on x86_64).
With regard to this fact it's reasonable to allocate this structure
dynamically in fl_change() to reduce its stack size.

v2:
- use kzalloc() instead of kcalloc()

Fixes: 05cd271f ("cls_flower: Support multiple masks per priority")
Cc: Jiri Pirko <jiri@resnulli.us>
Cc: Paul Blakey <paulb@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIvan Vecera <ivecera@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bdafc159
Loading
Loading
Loading
Loading
+14 −5
Original line number Original line Diff line number Diff line
@@ -1176,17 +1176,23 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
	struct cls_fl_head *head = rtnl_dereference(tp->root);
	struct cls_fl_head *head = rtnl_dereference(tp->root);
	struct cls_fl_filter *fold = *arg;
	struct cls_fl_filter *fold = *arg;
	struct cls_fl_filter *fnew;
	struct cls_fl_filter *fnew;
	struct fl_flow_mask *mask;
	struct nlattr **tb;
	struct nlattr **tb;
	struct fl_flow_mask mask = {};
	int err;
	int err;


	if (!tca[TCA_OPTIONS])
	if (!tca[TCA_OPTIONS])
		return -EINVAL;
		return -EINVAL;


	tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
	mask = kzalloc(sizeof(struct fl_flow_mask), GFP_KERNEL);
	if (!tb)
	if (!mask)
		return -ENOBUFS;
		return -ENOBUFS;


	tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
	if (!tb) {
		err = -ENOBUFS;
		goto errout_mask_alloc;
	}

	err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS],
	err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS],
			       fl_policy, NULL);
			       fl_policy, NULL);
	if (err < 0)
	if (err < 0)
@@ -1229,12 +1235,12 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
		}
		}
	}
	}


	err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr,
	err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
			   tp->chain->tmplt_priv, extack);
			   tp->chain->tmplt_priv, extack);
	if (err)
	if (err)
		goto errout_idr;
		goto errout_idr;


	err = fl_check_assign_mask(head, fnew, fold, &mask);
	err = fl_check_assign_mask(head, fnew, fold, mask);
	if (err)
	if (err)
		goto errout_idr;
		goto errout_idr;


@@ -1281,6 +1287,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
	}
	}


	kfree(tb);
	kfree(tb);
	kfree(mask);
	return 0;
	return 0;


errout_mask:
errout_mask:
@@ -1294,6 +1301,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
	kfree(fnew);
	kfree(fnew);
errout_tb:
errout_tb:
	kfree(tb);
	kfree(tb);
errout_mask_alloc:
	kfree(mask);
	return err;
	return err;
}
}