Merge branch 'net_sched-some-fixes-for-cls_tcindex'
Cong Wang says: ==================== net_sched: some fixes for cls_tcindex This patchset contains 3 bug fixes for tcindex filter. Please check each patch for details. v2: fix a compile error in patch 2 drop netns refcnt in patch 1 ==================== Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
This commit is contained in:
commit
a090d7948e
|
@ -48,7 +48,7 @@ struct tcindex_data {
|
|||
u32 hash; /* hash table size; 0 if undefined */
|
||||
u32 alloc_hash; /* allocated size */
|
||||
u32 fall_through; /* 0: only classify if explicit match */
|
||||
struct rcu_head rcu;
|
||||
struct rcu_work rwork;
|
||||
};
|
||||
|
||||
static inline int tcindex_filter_is_set(struct tcindex_filter_result *r)
|
||||
|
@ -221,17 +221,11 @@ static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tcindex_destroy_element(struct tcf_proto *tp,
|
||||
void *arg, struct tcf_walker *walker)
|
||||
static void tcindex_destroy_work(struct work_struct *work)
|
||||
{
|
||||
bool last;
|
||||
|
||||
return tcindex_delete(tp, arg, &last, NULL);
|
||||
}
|
||||
|
||||
static void __tcindex_destroy(struct rcu_head *head)
|
||||
{
|
||||
struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
|
||||
struct tcindex_data *p = container_of(to_rcu_work(work),
|
||||
struct tcindex_data,
|
||||
rwork);
|
||||
|
||||
kfree(p->perfect);
|
||||
kfree(p->h);
|
||||
|
@ -258,9 +252,11 @@ static int tcindex_filter_result_init(struct tcindex_filter_result *r)
|
|||
return tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
|
||||
}
|
||||
|
||||
static void __tcindex_partial_destroy(struct rcu_head *head)
|
||||
static void tcindex_partial_destroy_work(struct work_struct *work)
|
||||
{
|
||||
struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
|
||||
struct tcindex_data *p = container_of(to_rcu_work(work),
|
||||
struct tcindex_data,
|
||||
rwork);
|
||||
|
||||
kfree(p->perfect);
|
||||
kfree(p);
|
||||
|
@ -275,7 +271,7 @@ static void tcindex_free_perfect_hash(struct tcindex_data *cp)
|
|||
kfree(cp->perfect);
|
||||
}
|
||||
|
||||
static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
|
||||
static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp)
|
||||
{
|
||||
int i, err = 0;
|
||||
|
||||
|
@ -289,6 +285,9 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
|
|||
TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
cp->perfect[i].exts.net = net;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -305,9 +304,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tcindex_filter_result new_filter_result, *old_r = r;
|
||||
struct tcindex_filter_result cr;
|
||||
struct tcindex_data *cp = NULL, *oldp;
|
||||
struct tcindex_filter *f = NULL; /* make gcc behave */
|
||||
struct tcf_result cr = {};
|
||||
int err, balloc = 0;
|
||||
struct tcf_exts e;
|
||||
|
||||
|
@ -337,7 +336,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
if (p->perfect) {
|
||||
int i;
|
||||
|
||||
if (tcindex_alloc_perfect_hash(cp) < 0)
|
||||
if (tcindex_alloc_perfect_hash(net, cp) < 0)
|
||||
goto errout;
|
||||
for (i = 0; i < cp->hash; i++)
|
||||
cp->perfect[i].res = p->perfect[i].res;
|
||||
|
@ -346,13 +345,10 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
cp->h = p->h;
|
||||
|
||||
err = tcindex_filter_result_init(&new_filter_result);
|
||||
if (err < 0)
|
||||
goto errout1;
|
||||
err = tcindex_filter_result_init(&cr);
|
||||
if (err < 0)
|
||||
goto errout1;
|
||||
if (old_r)
|
||||
cr.res = r->res;
|
||||
cr = r->res;
|
||||
|
||||
if (tb[TCA_TCINDEX_HASH])
|
||||
cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
|
||||
|
@ -406,7 +402,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
err = -ENOMEM;
|
||||
if (!cp->perfect && !cp->h) {
|
||||
if (valid_perfect_hash(cp)) {
|
||||
if (tcindex_alloc_perfect_hash(cp) < 0)
|
||||
if (tcindex_alloc_perfect_hash(net, cp) < 0)
|
||||
goto errout_alloc;
|
||||
balloc = 1;
|
||||
} else {
|
||||
|
@ -443,8 +439,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
}
|
||||
|
||||
if (tb[TCA_TCINDEX_CLASSID]) {
|
||||
cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
|
||||
tcf_bind_filter(tp, &cr.res, base);
|
||||
cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
|
||||
tcf_bind_filter(tp, &cr, base);
|
||||
}
|
||||
|
||||
if (old_r && old_r != r) {
|
||||
|
@ -456,7 +452,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
}
|
||||
|
||||
oldp = p;
|
||||
r->res = cr.res;
|
||||
r->res = cr;
|
||||
tcf_exts_change(&r->exts, &e);
|
||||
|
||||
rcu_assign_pointer(tp->root, cp);
|
||||
|
@ -475,10 +471,12 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
; /* nothing */
|
||||
|
||||
rcu_assign_pointer(*fp, f);
|
||||
} else {
|
||||
tcf_exts_destroy(&new_filter_result.exts);
|
||||
}
|
||||
|
||||
if (oldp)
|
||||
call_rcu(&oldp->rcu, __tcindex_partial_destroy);
|
||||
tcf_queue_work(&oldp->rwork, tcindex_partial_destroy_work);
|
||||
return 0;
|
||||
|
||||
errout_alloc:
|
||||
|
@ -487,7 +485,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
|
|||
else if (balloc == 2)
|
||||
kfree(cp->h);
|
||||
errout1:
|
||||
tcf_exts_destroy(&cr.exts);
|
||||
tcf_exts_destroy(&new_filter_result.exts);
|
||||
errout:
|
||||
kfree(cp);
|
||||
|
@ -562,15 +559,34 @@ static void tcindex_destroy(struct tcf_proto *tp,
|
|||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct tcindex_data *p = rtnl_dereference(tp->root);
|
||||
struct tcf_walker walker;
|
||||
int i;
|
||||
|
||||
pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
|
||||
walker.count = 0;
|
||||
walker.skip = 0;
|
||||
walker.fn = tcindex_destroy_element;
|
||||
tcindex_walk(tp, &walker);
|
||||
|
||||
call_rcu(&p->rcu, __tcindex_destroy);
|
||||
if (p->perfect) {
|
||||
for (i = 0; i < p->hash; i++) {
|
||||
struct tcindex_filter_result *r = p->perfect + i;
|
||||
|
||||
tcf_unbind_filter(tp, &r->res);
|
||||
if (tcf_exts_get_net(&r->exts))
|
||||
tcf_queue_work(&r->rwork,
|
||||
tcindex_destroy_rexts_work);
|
||||
else
|
||||
__tcindex_destroy_rexts(r);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; p->h && i < p->hash; i++) {
|
||||
struct tcindex_filter *f, *next;
|
||||
bool last;
|
||||
|
||||
for (f = rtnl_dereference(p->h[i]); f; f = next) {
|
||||
next = rtnl_dereference(f->next);
|
||||
tcindex_delete(tp, &f->result, &last, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
tcf_queue_work(&p->rwork, tcindex_destroy_work);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue