net: sched: don't set q pointer for shared blocks

It is pointless to set block->q for block which are shared among
multiple qdiscs. So remove the assignment in that case. Do a bit of code
reshuffle to make block->index initialized at that point so we can use
tcf_block_shared() helper.

Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
Fixes: 4861738775 ("net: sched: introduce shared filter blocks infrastructure")
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jiri Pirko 2018-02-13 12:00:16 +01:00 committed by David S. Miller
parent 0f2d2b2736
commit bb047ddd14
1 changed files with 12 additions and 14 deletions

View File

@ -376,17 +376,12 @@ struct tcf_net {
static unsigned int tcf_net_id; static unsigned int tcf_net_id;
static int tcf_block_insert(struct tcf_block *block, struct net *net, static int tcf_block_insert(struct tcf_block *block, struct net *net,
u32 block_index, struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tcf_net *tn = net_generic(net, tcf_net_id); struct tcf_net *tn = net_generic(net, tcf_net_id);
int err;
err = idr_alloc_u32(&tn->idr, block, &block_index, block_index, return idr_alloc_u32(&tn->idr, block, &block->index, block->index,
GFP_KERNEL); GFP_KERNEL);
if (err)
return err;
block->index = block_index;
return 0;
} }
static void tcf_block_remove(struct tcf_block *block, struct net *net) static void tcf_block_remove(struct tcf_block *block, struct net *net)
@ -397,6 +392,7 @@ static void tcf_block_remove(struct tcf_block *block, struct net *net)
} }
static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
u32 block_index,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tcf_block *block; struct tcf_block *block;
@ -419,10 +415,13 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q,
err = -ENOMEM; err = -ENOMEM;
goto err_chain_create; goto err_chain_create;
} }
block->net = qdisc_net(q);
block->refcnt = 1; block->refcnt = 1;
block->net = net; block->net = net;
block->q = q; block->index = block_index;
/* Don't store q pointer for blocks which are shared */
if (!tcf_block_shared(block))
block->q = q;
return block; return block;
err_chain_create: err_chain_create:
@ -518,13 +517,12 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
} }
if (!block) { if (!block) {
block = tcf_block_create(net, q, extack); block = tcf_block_create(net, q, ei->block_index, extack);
if (IS_ERR(block)) if (IS_ERR(block))
return PTR_ERR(block); return PTR_ERR(block);
created = true; created = true;
if (ei->block_index) { if (tcf_block_shared(block)) {
err = tcf_block_insert(block, net, err = tcf_block_insert(block, net, extack);
ei->block_index, extack);
if (err) if (err)
goto err_block_insert; goto err_block_insert;
} }