net: sched: extend proto ops with 'put' callback
Add optional tp->ops->put() API to be implemented for filter reference counting. This new function is called by cls API to release filter reference for filters returned by tp->ops->change() or tp->ops->get() functions. Implement tfilter_put() helper to call tp->ops->put() only for classifiers that implement it. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
ec6743a109
Коммит
7d5509fa0d
|
@ -277,6 +277,7 @@ struct tcf_proto_ops {
|
||||||
struct netlink_ext_ack *extack);
|
struct netlink_ext_ack *extack);
|
||||||
|
|
||||||
void* (*get)(struct tcf_proto*, u32 handle);
|
void* (*get)(struct tcf_proto*, u32 handle);
|
||||||
|
void (*put)(struct tcf_proto *tp, void *f);
|
||||||
int (*change)(struct net *net, struct sk_buff *,
|
int (*change)(struct net *net, struct sk_buff *,
|
||||||
struct tcf_proto*, unsigned long,
|
struct tcf_proto*, unsigned long,
|
||||||
u32 handle, struct nlattr **,
|
u32 handle, struct nlattr **,
|
||||||
|
|
|
@ -1870,6 +1870,12 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
|
||||||
q, parent, NULL, event, false);
|
q, parent, NULL, event, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tfilter_put(struct tcf_proto *tp, void *fh)
|
||||||
|
{
|
||||||
|
if (tp->ops->put && fh)
|
||||||
|
tp->ops->put(tp, fh);
|
||||||
|
}
|
||||||
|
|
||||||
static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
|
static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
|
||||||
struct netlink_ext_ack *extack)
|
struct netlink_ext_ack *extack)
|
||||||
{
|
{
|
||||||
|
@ -2012,6 +2018,7 @@ replay:
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
} else if (n->nlmsg_flags & NLM_F_EXCL) {
|
} else if (n->nlmsg_flags & NLM_F_EXCL) {
|
||||||
|
tfilter_put(tp, fh);
|
||||||
NL_SET_ERR_MSG(extack, "Filter already exists");
|
NL_SET_ERR_MSG(extack, "Filter already exists");
|
||||||
err = -EEXIST;
|
err = -EEXIST;
|
||||||
goto errout;
|
goto errout;
|
||||||
|
@ -2026,9 +2033,11 @@ replay:
|
||||||
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
|
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
|
||||||
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE,
|
n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE,
|
||||||
extack);
|
extack);
|
||||||
if (err == 0)
|
if (err == 0) {
|
||||||
tfilter_notify(net, skb, n, tp, block, q, parent, fh,
|
tfilter_notify(net, skb, n, tp, block, q, parent, fh,
|
||||||
RTM_NEWTFILTER, false);
|
RTM_NEWTFILTER, false);
|
||||||
|
tfilter_put(tp, fh);
|
||||||
|
}
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
if (err && tp_created)
|
if (err && tp_created)
|
||||||
|
@ -2259,6 +2268,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
|
||||||
NL_SET_ERR_MSG(extack, "Failed to send filter notify message");
|
NL_SET_ERR_MSG(extack, "Failed to send filter notify message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tfilter_put(tp, fh);
|
||||||
errout:
|
errout:
|
||||||
if (chain) {
|
if (chain) {
|
||||||
if (tp && !IS_ERR(tp))
|
if (tp && !IS_ERR(tp))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче