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

Merge branch 'net-sched-couple-of-fixes'

Jiri Pirko says:

====================
net: sched: couple of fixes

This patchset contains couple of fixes following-up the shared block
patchsets.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0f2d2b27 339c21d7
...@@ -376,17 +376,12 @@ struct tcf_net { ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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;
} }
......
...@@ -96,7 +96,7 @@ struct tc_u_hnode { ...@@ -96,7 +96,7 @@ struct tc_u_hnode {
struct tc_u_common { struct tc_u_common {
struct tc_u_hnode __rcu *hlist; struct tc_u_hnode __rcu *hlist;
struct tcf_block *block; void *ptr;
int refcnt; int refcnt;
struct idr handle_idr; struct idr handle_idr;
struct hlist_node hnode; struct hlist_node hnode;
...@@ -330,9 +330,25 @@ static struct hlist_head *tc_u_common_hash; ...@@ -330,9 +330,25 @@ static struct hlist_head *tc_u_common_hash;
#define U32_HASH_SHIFT 10 #define U32_HASH_SHIFT 10
#define U32_HASH_SIZE (1 << U32_HASH_SHIFT) #define U32_HASH_SIZE (1 << U32_HASH_SHIFT)
static void *tc_u_common_ptr(const struct tcf_proto *tp)
{
struct tcf_block *block = tp->chain->block;
/* The block sharing is currently supported only
* for classless qdiscs. In that case we use block
* for tc_u_common identification. In case the
* block is not shared, block->q is a valid pointer
* and we can use that. That works for classful qdiscs.
*/
if (tcf_block_shared(block))
return block;
else
return block->q;
}
static unsigned int tc_u_hash(const struct tcf_proto *tp) static unsigned int tc_u_hash(const struct tcf_proto *tp)
{ {
return hash_ptr(tp->chain->block, U32_HASH_SHIFT); return hash_ptr(tc_u_common_ptr(tp), U32_HASH_SHIFT);
} }
static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
...@@ -342,7 +358,7 @@ static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) ...@@ -342,7 +358,7 @@ static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
h = tc_u_hash(tp); h = tc_u_hash(tp);
hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) { hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) {
if (tc->block == tp->chain->block) if (tc->ptr == tc_u_common_ptr(tp))
return tc; return tc;
} }
return NULL; return NULL;
...@@ -371,7 +387,7 @@ static int u32_init(struct tcf_proto *tp) ...@@ -371,7 +387,7 @@ static int u32_init(struct tcf_proto *tp)
kfree(root_ht); kfree(root_ht);
return -ENOBUFS; return -ENOBUFS;
} }
tp_c->block = tp->chain->block; tp_c->ptr = tc_u_common_ptr(tp);
INIT_HLIST_NODE(&tp_c->hnode); INIT_HLIST_NODE(&tp_c->hnode);
idr_init(&tp_c->handle_idr); idr_init(&tp_c->handle_idr);
......
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