Commit e91a159e authored by David S. Miller's avatar David S. Miller

Merge branch 'net_sched-next'

John Fastabend says:

====================
net sched rcu updates

This fixes the use of tcf_proto from RCU callbacks it requires
moving the unbind calls out of the callbacks and removing the
tcf_proto argument from the tcf_em_tree_destroy().

This is a rework of two previous series and addresses comments
from Cong. And should apply against latest net-next.

The previous series links below for reference:

(1/2) net: sched: do not use tcf_proto 'tp' argument from call_rcu
http://patchwork.ozlabs.org/patch/396149/

(2/2) net: sched: replace ematch calls to use struct net
http://patchwork.ozlabs.org/patch/396150/

net: sched: cls_cgroup tear down exts and ematch from rcu callback
http://patchwork.ozlabs.org/patch/396307/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents fcbeb976 18cdb37e
...@@ -166,6 +166,7 @@ struct tcf_ematch { ...@@ -166,6 +166,7 @@ struct tcf_ematch {
unsigned int datalen; unsigned int datalen;
u16 matchid; u16 matchid;
u16 flags; u16 flags;
struct net *net;
}; };
static inline int tcf_em_is_container(struct tcf_ematch *em) static inline int tcf_em_is_container(struct tcf_ematch *em)
...@@ -229,12 +230,11 @@ struct tcf_ematch_tree { ...@@ -229,12 +230,11 @@ struct tcf_ematch_tree {
struct tcf_ematch_ops { struct tcf_ematch_ops {
int kind; int kind;
int datalen; int datalen;
int (*change)(struct tcf_proto *, void *, int (*change)(struct net *net, void *,
int, struct tcf_ematch *); int, struct tcf_ematch *);
int (*match)(struct sk_buff *, struct tcf_ematch *, int (*match)(struct sk_buff *, struct tcf_ematch *,
struct tcf_pkt_info *); struct tcf_pkt_info *);
void (*destroy)(struct tcf_proto *, void (*destroy)(struct tcf_ematch *);
struct tcf_ematch *);
int (*dump)(struct sk_buff *, struct tcf_ematch *); int (*dump)(struct sk_buff *, struct tcf_ematch *);
struct module *owner; struct module *owner;
struct list_head link; struct list_head link;
...@@ -244,7 +244,7 @@ int tcf_em_register(struct tcf_ematch_ops *); ...@@ -244,7 +244,7 @@ int tcf_em_register(struct tcf_ematch_ops *);
void tcf_em_unregister(struct tcf_ematch_ops *); void tcf_em_unregister(struct tcf_ematch_ops *);
int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *, int tcf_em_tree_validate(struct tcf_proto *, struct nlattr *,
struct tcf_ematch_tree *); struct tcf_ematch_tree *);
void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *); void tcf_em_tree_destroy(struct tcf_ematch_tree *);
int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int); int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *, int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
struct tcf_pkt_info *); struct tcf_pkt_info *);
...@@ -301,7 +301,7 @@ struct tcf_ematch_tree { ...@@ -301,7 +301,7 @@ struct tcf_ematch_tree {
}; };
#define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0) #define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
#define tcf_em_tree_destroy(tp, t) do { (void)(t); } while(0) #define tcf_em_tree_destroy(t) do { (void)(t); } while(0)
#define tcf_em_tree_dump(skb, t, tlv) (0) #define tcf_em_tree_dump(skb, t, tlv) (0)
#define tcf_em_tree_change(tp, dst, src) do { } while(0) #define tcf_em_tree_change(tp, dst, src) do { } while(0)
#define tcf_em_tree_match(skb, t, info) ((void)(info), 1) #define tcf_em_tree_match(skb, t, info) ((void)(info), 1)
......
...@@ -91,11 +91,9 @@ static int basic_init(struct tcf_proto *tp) ...@@ -91,11 +91,9 @@ static int basic_init(struct tcf_proto *tp)
static void basic_delete_filter(struct rcu_head *head) static void basic_delete_filter(struct rcu_head *head)
{ {
struct basic_filter *f = container_of(head, struct basic_filter, rcu); struct basic_filter *f = container_of(head, struct basic_filter, rcu);
struct tcf_proto *tp = f->tp;
tcf_unbind_filter(tp, &f->res);
tcf_exts_destroy(&f->exts); tcf_exts_destroy(&f->exts);
tcf_em_tree_destroy(tp, &f->ematches); tcf_em_tree_destroy(&f->ematches);
kfree(f); kfree(f);
} }
...@@ -106,6 +104,7 @@ static void basic_destroy(struct tcf_proto *tp) ...@@ -106,6 +104,7 @@ static void basic_destroy(struct tcf_proto *tp)
list_for_each_entry_safe(f, n, &head->flist, link) { list_for_each_entry_safe(f, n, &head->flist, link) {
list_del_rcu(&f->link); list_del_rcu(&f->link);
tcf_unbind_filter(tp, &f->res);
call_rcu(&f->rcu, basic_delete_filter); call_rcu(&f->rcu, basic_delete_filter);
} }
RCU_INIT_POINTER(tp->root, NULL); RCU_INIT_POINTER(tp->root, NULL);
...@@ -120,6 +119,7 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg) ...@@ -120,6 +119,7 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg)
list_for_each_entry(t, &head->flist, link) list_for_each_entry(t, &head->flist, link)
if (t == f) { if (t == f) {
list_del_rcu(&t->link); list_del_rcu(&t->link);
tcf_unbind_filter(tp, &t->res);
call_rcu(&t->rcu, basic_delete_filter); call_rcu(&t->rcu, basic_delete_filter);
return 0; return 0;
} }
...@@ -222,6 +222,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, ...@@ -222,6 +222,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
if (fold) { if (fold) {
list_replace_rcu(&fold->link, &fnew->link); list_replace_rcu(&fold->link, &fnew->link);
tcf_unbind_filter(tp, &fold->res);
call_rcu(&fold->rcu, basic_delete_filter); call_rcu(&fold->rcu, basic_delete_filter);
} else { } else {
list_add_rcu(&fnew->link, &head->flist); list_add_rcu(&fnew->link, &head->flist);
......
...@@ -92,7 +92,6 @@ static int cls_bpf_init(struct tcf_proto *tp) ...@@ -92,7 +92,6 @@ static int cls_bpf_init(struct tcf_proto *tp)
static void cls_bpf_delete_prog(struct tcf_proto *tp, struct cls_bpf_prog *prog) static void cls_bpf_delete_prog(struct tcf_proto *tp, struct cls_bpf_prog *prog)
{ {
tcf_unbind_filter(tp, &prog->res);
tcf_exts_destroy(&prog->exts); tcf_exts_destroy(&prog->exts);
bpf_prog_destroy(prog->filter); bpf_prog_destroy(prog->filter);
...@@ -116,6 +115,7 @@ static int cls_bpf_delete(struct tcf_proto *tp, unsigned long arg) ...@@ -116,6 +115,7 @@ static int cls_bpf_delete(struct tcf_proto *tp, unsigned long arg)
list_for_each_entry(prog, &head->plist, link) { list_for_each_entry(prog, &head->plist, link) {
if (prog == todel) { if (prog == todel) {
list_del_rcu(&prog->link); list_del_rcu(&prog->link);
tcf_unbind_filter(tp, &prog->res);
call_rcu(&prog->rcu, __cls_bpf_delete_prog); call_rcu(&prog->rcu, __cls_bpf_delete_prog);
return 0; return 0;
} }
...@@ -131,6 +131,7 @@ static void cls_bpf_destroy(struct tcf_proto *tp) ...@@ -131,6 +131,7 @@ static void cls_bpf_destroy(struct tcf_proto *tp)
list_for_each_entry_safe(prog, tmp, &head->plist, link) { list_for_each_entry_safe(prog, tmp, &head->plist, link) {
list_del_rcu(&prog->link); list_del_rcu(&prog->link);
tcf_unbind_filter(tp, &prog->res);
call_rcu(&prog->rcu, __cls_bpf_delete_prog); call_rcu(&prog->rcu, __cls_bpf_delete_prog);
} }
...@@ -282,6 +283,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, ...@@ -282,6 +283,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
if (oldprog) { if (oldprog) {
list_replace_rcu(&prog->link, &oldprog->link); list_replace_rcu(&prog->link, &oldprog->link);
tcf_unbind_filter(tp, &oldprog->res);
call_rcu(&oldprog->rcu, __cls_bpf_delete_prog); call_rcu(&oldprog->rcu, __cls_bpf_delete_prog);
} else { } else {
list_add_rcu(&prog->link, &head->plist); list_add_rcu(&prog->link, &head->plist);
......
...@@ -87,7 +87,7 @@ static void cls_cgroup_destroy_rcu(struct rcu_head *root) ...@@ -87,7 +87,7 @@ static void cls_cgroup_destroy_rcu(struct rcu_head *root)
rcu); rcu);
tcf_exts_destroy(&head->exts); tcf_exts_destroy(&head->exts);
tcf_em_tree_destroy(head->tp, &head->ematches); tcf_em_tree_destroy(&head->ematches);
kfree(head); kfree(head);
} }
...@@ -156,10 +156,8 @@ static void cls_cgroup_destroy(struct tcf_proto *tp) ...@@ -156,10 +156,8 @@ static void cls_cgroup_destroy(struct tcf_proto *tp)
struct cls_cgroup_head *head = rtnl_dereference(tp->root); struct cls_cgroup_head *head = rtnl_dereference(tp->root);
if (head) { if (head) {
tcf_exts_destroy(&head->exts);
tcf_em_tree_destroy(tp, &head->ematches);
RCU_INIT_POINTER(tp->root, NULL); RCU_INIT_POINTER(tp->root, NULL);
kfree_rcu(head, rcu); call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
} }
} }
......
...@@ -355,7 +355,7 @@ static void flow_destroy_filter(struct rcu_head *head) ...@@ -355,7 +355,7 @@ static void flow_destroy_filter(struct rcu_head *head)
del_timer_sync(&f->perturb_timer); del_timer_sync(&f->perturb_timer);
tcf_exts_destroy(&f->exts); tcf_exts_destroy(&f->exts);
tcf_em_tree_destroy(f->tp, &f->ematches); tcf_em_tree_destroy(&f->ematches);
kfree(f); kfree(f);
} }
...@@ -530,7 +530,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, ...@@ -530,7 +530,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
return 0; return 0;
err2: err2:
tcf_em_tree_destroy(tp, &t); tcf_em_tree_destroy(&t);
kfree(fnew); kfree(fnew);
err1: err1:
tcf_exts_destroy(&e); tcf_exts_destroy(&e);
......
...@@ -123,9 +123,7 @@ static int fw_init(struct tcf_proto *tp) ...@@ -123,9 +123,7 @@ static int fw_init(struct tcf_proto *tp)
static void fw_delete_filter(struct rcu_head *head) static void fw_delete_filter(struct rcu_head *head)
{ {
struct fw_filter *f = container_of(head, struct fw_filter, rcu); struct fw_filter *f = container_of(head, struct fw_filter, rcu);
struct tcf_proto *tp = f->tp;
tcf_unbind_filter(tp, &f->res);
tcf_exts_destroy(&f->exts); tcf_exts_destroy(&f->exts);
kfree(f); kfree(f);
} }
...@@ -143,6 +141,7 @@ static void fw_destroy(struct tcf_proto *tp) ...@@ -143,6 +141,7 @@ static void fw_destroy(struct tcf_proto *tp)
while ((f = rtnl_dereference(head->ht[h])) != NULL) { while ((f = rtnl_dereference(head->ht[h])) != NULL) {
RCU_INIT_POINTER(head->ht[h], RCU_INIT_POINTER(head->ht[h],
rtnl_dereference(f->next)); rtnl_dereference(f->next));
tcf_unbind_filter(tp, &f->res);
call_rcu(&f->rcu, fw_delete_filter); call_rcu(&f->rcu, fw_delete_filter);
} }
} }
...@@ -166,6 +165,7 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg) ...@@ -166,6 +165,7 @@ static int fw_delete(struct tcf_proto *tp, unsigned long arg)
fp = &pfp->next, pfp = rtnl_dereference(*fp)) { fp = &pfp->next, pfp = rtnl_dereference(*fp)) {
if (pfp == f) { if (pfp == f) {
RCU_INIT_POINTER(*fp, rtnl_dereference(f->next)); RCU_INIT_POINTER(*fp, rtnl_dereference(f->next));
tcf_unbind_filter(tp, &f->res);
call_rcu(&f->rcu, fw_delete_filter); call_rcu(&f->rcu, fw_delete_filter);
return 0; return 0;
} }
...@@ -280,6 +280,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, ...@@ -280,6 +280,7 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
RCU_INIT_POINTER(fnew->next, rtnl_dereference(pfp->next)); RCU_INIT_POINTER(fnew->next, rtnl_dereference(pfp->next));
rcu_assign_pointer(*fp, fnew); rcu_assign_pointer(*fp, fnew);
tcf_unbind_filter(tp, &f->res);
call_rcu(&f->rcu, fw_delete_filter); call_rcu(&f->rcu, fw_delete_filter);
*arg = (unsigned long)fnew; *arg = (unsigned long)fnew;
......
...@@ -269,9 +269,7 @@ static void ...@@ -269,9 +269,7 @@ static void
route4_delete_filter(struct rcu_head *head) route4_delete_filter(struct rcu_head *head)
{ {
struct route4_filter *f = container_of(head, struct route4_filter, rcu); struct route4_filter *f = container_of(head, struct route4_filter, rcu);
struct tcf_proto *tp = f->tp;
tcf_unbind_filter(tp, &f->res);
tcf_exts_destroy(&f->exts); tcf_exts_destroy(&f->exts);
kfree(f); kfree(f);
} }
...@@ -297,6 +295,7 @@ static void route4_destroy(struct tcf_proto *tp) ...@@ -297,6 +295,7 @@ static void route4_destroy(struct tcf_proto *tp)
next = rtnl_dereference(f->next); next = rtnl_dereference(f->next);
RCU_INIT_POINTER(b->ht[h2], next); RCU_INIT_POINTER(b->ht[h2], next);
tcf_unbind_filter(tp, &f->res);
call_rcu(&f->rcu, route4_delete_filter); call_rcu(&f->rcu, route4_delete_filter);
} }
} }
...@@ -338,6 +337,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg) ...@@ -338,6 +337,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
route4_reset_fastmap(head); route4_reset_fastmap(head);
/* Delete it */ /* Delete it */
tcf_unbind_filter(tp, &f->res);
call_rcu(&f->rcu, route4_delete_filter); call_rcu(&f->rcu, route4_delete_filter);
/* Strip RTNL protected tree */ /* Strip RTNL protected tree */
...@@ -545,8 +545,10 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, ...@@ -545,8 +545,10 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
route4_reset_fastmap(head); route4_reset_fastmap(head);
*arg = (unsigned long)f; *arg = (unsigned long)f;
if (fold) if (fold) {
tcf_unbind_filter(tp, &fold->res);
call_rcu(&fold->rcu, route4_delete_filter); call_rcu(&fold->rcu, route4_delete_filter);
}
return 0; return 0;
errout: errout:
......
...@@ -120,7 +120,7 @@ static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m, ...@@ -120,7 +120,7 @@ static int em_canid_match(struct sk_buff *skb, struct tcf_ematch *m,
return match; return match;
} }
static int em_canid_change(struct tcf_proto *tp, void *data, int len, static int em_canid_change(struct net *net, void *data, int len,
struct tcf_ematch *m) struct tcf_ematch *m)
{ {
struct can_filter *conf = data; /* Array with rules */ struct can_filter *conf = data; /* Array with rules */
...@@ -183,7 +183,7 @@ static int em_canid_change(struct tcf_proto *tp, void *data, int len, ...@@ -183,7 +183,7 @@ static int em_canid_change(struct tcf_proto *tp, void *data, int len,
return 0; return 0;
} }
static void em_canid_destroy(struct tcf_proto *tp, struct tcf_ematch *m) static void em_canid_destroy(struct tcf_ematch *m)
{ {
struct canid_match *cm = em_canid_priv(m); struct canid_match *cm = em_canid_priv(m);
......
...@@ -19,12 +19,11 @@ ...@@ -19,12 +19,11 @@
#include <net/ip.h> #include <net/ip.h>
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
static int em_ipset_change(struct tcf_proto *tp, void *data, int data_len, static int em_ipset_change(struct net *net, void *data, int data_len,
struct tcf_ematch *em) struct tcf_ematch *em)
{ {
struct xt_set_info *set = data; struct xt_set_info *set = data;
ip_set_id_t index; ip_set_id_t index;
struct net *net = dev_net(qdisc_dev(tp->q));
if (data_len != sizeof(*set)) if (data_len != sizeof(*set))
return -EINVAL; return -EINVAL;
...@@ -42,11 +41,11 @@ static int em_ipset_change(struct tcf_proto *tp, void *data, int data_len, ...@@ -42,11 +41,11 @@ static int em_ipset_change(struct tcf_proto *tp, void *data, int data_len,
return -ENOMEM; return -ENOMEM;
} }
static void em_ipset_destroy(struct tcf_proto *p, struct tcf_ematch *em) static void em_ipset_destroy(struct tcf_ematch *em)
{ {
const struct xt_set_info *set = (const void *) em->data; const struct xt_set_info *set = (const void *) em->data;
if (set) { if (set) {
ip_set_nfnl_put(dev_net(qdisc_dev(p->q)), set->index); ip_set_nfnl_put(em->net, set->index);
kfree((void *) em->data); kfree((void *) em->data);
} }
} }
......
...@@ -856,7 +856,7 @@ static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = { ...@@ -856,7 +856,7 @@ static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = {
[TCA_EM_META_HDR] = { .len = sizeof(struct tcf_meta_hdr) }, [TCA_EM_META_HDR] = { .len = sizeof(struct tcf_meta_hdr) },
}; };
static int em_meta_change(struct tcf_proto *tp, void *data, int len, static int em_meta_change(struct net *net, void *data, int len,
struct tcf_ematch *m) struct tcf_ematch *m)
{ {
int err; int err;
...@@ -908,7 +908,7 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len, ...@@ -908,7 +908,7 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
return err; return err;
} }
static void em_meta_destroy(struct tcf_proto *tp, struct tcf_ematch *m) static void em_meta_destroy(struct tcf_ematch *m)
{ {
if (m) if (m)
meta_delete((struct meta_match *) m->data); meta_delete((struct meta_match *) m->data);
......
...@@ -23,7 +23,7 @@ struct nbyte_data { ...@@ -23,7 +23,7 @@ struct nbyte_data {
char pattern[0]; char pattern[0];
}; };
static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len, static int em_nbyte_change(struct net *net, void *data, int data_len,
struct tcf_ematch *em) struct tcf_ematch *em)
{ {
struct tcf_em_nbyte *nbyte = data; struct tcf_em_nbyte *nbyte = data;
......
...@@ -45,7 +45,7 @@ static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m, ...@@ -45,7 +45,7 @@ static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m,
return skb_find_text(skb, from, to, tm->config, &state) != UINT_MAX; return skb_find_text(skb, from, to, tm->config, &state) != UINT_MAX;
} }
static int em_text_change(struct tcf_proto *tp, void *data, int len, static int em_text_change(struct net *net, void *data, int len,
struct tcf_ematch *m) struct tcf_ematch *m)
{ {
struct text_match *tm; struct text_match *tm;
...@@ -100,7 +100,7 @@ static int em_text_change(struct tcf_proto *tp, void *data, int len, ...@@ -100,7 +100,7 @@ static int em_text_change(struct tcf_proto *tp, void *data, int len,
return 0; return 0;
} }
static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m) static void em_text_destroy(struct tcf_ematch *m)
{ {
if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config)
textsearch_destroy(EM_TEXT_PRIV(m)->config); textsearch_destroy(EM_TEXT_PRIV(m)->config);
......
...@@ -178,6 +178,7 @@ static int tcf_em_validate(struct tcf_proto *tp, ...@@ -178,6 +178,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
struct tcf_ematch_hdr *em_hdr = nla_data(nla); struct tcf_ematch_hdr *em_hdr = nla_data(nla);
int data_len = nla_len(nla) - sizeof(*em_hdr); int data_len = nla_len(nla) - sizeof(*em_hdr);
void *data = (void *) em_hdr + sizeof(*em_hdr); void *data = (void *) em_hdr + sizeof(*em_hdr);
struct net *net = dev_net(qdisc_dev(tp->q));
if (!TCF_EM_REL_VALID(em_hdr->flags)) if (!TCF_EM_REL_VALID(em_hdr->flags))
goto errout; goto errout;
...@@ -240,7 +241,7 @@ static int tcf_em_validate(struct tcf_proto *tp, ...@@ -240,7 +241,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
goto errout; goto errout;
if (em->ops->change) { if (em->ops->change) {
err = em->ops->change(tp, data, data_len, em); err = em->ops->change(net, data, data_len, em);
if (err < 0) if (err < 0)
goto errout; goto errout;
} else if (data_len > 0) { } else if (data_len > 0) {
...@@ -271,6 +272,7 @@ static int tcf_em_validate(struct tcf_proto *tp, ...@@ -271,6 +272,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
em->matchid = em_hdr->matchid; em->matchid = em_hdr->matchid;
em->flags = em_hdr->flags; em->flags = em_hdr->flags;
em->datalen = data_len; em->datalen = data_len;
em->net = net;
err = 0; err = 0;
errout: errout:
...@@ -378,7 +380,7 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla, ...@@ -378,7 +380,7 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
return err; return err;
errout_abort: errout_abort:
tcf_em_tree_destroy(tp, tree); tcf_em_tree_destroy(tree);
return err; return err;
} }
EXPORT_SYMBOL(tcf_em_tree_validate); EXPORT_SYMBOL(tcf_em_tree_validate);
...@@ -393,7 +395,7 @@ EXPORT_SYMBOL(tcf_em_tree_validate); ...@@ -393,7 +395,7 @@ EXPORT_SYMBOL(tcf_em_tree_validate);
* tcf_em_tree_validate()/tcf_em_tree_change(). You must ensure that * tcf_em_tree_validate()/tcf_em_tree_change(). You must ensure that
* the ematch tree is not in use before calling this function. * the ematch tree is not in use before calling this function.
*/ */
void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree) void tcf_em_tree_destroy(struct tcf_ematch_tree *tree)
{ {
int i; int i;
...@@ -405,7 +407,7 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree) ...@@ -405,7 +407,7 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree)
if (em->ops) { if (em->ops) {
if (em->ops->destroy) if (em->ops->destroy)
em->ops->destroy(tp, em); em->ops->destroy(em);
else if (!tcf_em_is_simple(em)) else if (!tcf_em_is_simple(em))
kfree((void *) em->data); kfree((void *) em->data);
module_put(em->ops->owner); module_put(em->ops->owner);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment