diff options
author | David S. Miller <davem@davemloft.net> | 2018-02-13 12:29:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-13 12:29:03 -0500 |
commit | f7219bf31122e2f70887ed48ba7c4c15dad45da0 (patch) | |
tree | 1c8eebd7b5da3e11d1374fe328dc4c254f47d4be | |
parent | 0f2d2b2736b08dafa3bde31d048750fbc8df3a31 (diff) | |
parent | 339c21d7c459238135d87da8fefbfd25d98bc375 (diff) |
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: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/sched/cls_api.c | 26 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 24 |
2 files changed, 32 insertions, 18 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 2bc1bc23d42e..a7dc7271042a 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -376,17 +376,12 @@ struct tcf_net { | |||
376 | static unsigned int tcf_net_id; | 376 | static unsigned int tcf_net_id; |
377 | 377 | ||
378 | static int tcf_block_insert(struct tcf_block *block, struct net *net, | 378 | static int tcf_block_insert(struct tcf_block *block, struct net *net, |
379 | u32 block_index, struct netlink_ext_ack *extack) | 379 | struct netlink_ext_ack *extack) |
380 | { | 380 | { |
381 | struct tcf_net *tn = net_generic(net, tcf_net_id); | 381 | struct tcf_net *tn = net_generic(net, tcf_net_id); |
382 | int err; | ||
383 | 382 | ||
384 | err = idr_alloc_u32(&tn->idr, block, &block_index, block_index, | 383 | return idr_alloc_u32(&tn->idr, block, &block->index, block->index, |
385 | GFP_KERNEL); | 384 | GFP_KERNEL); |
386 | if (err) | ||
387 | return err; | ||
388 | block->index = block_index; | ||
389 | return 0; | ||
390 | } | 385 | } |
391 | 386 | ||
392 | static void tcf_block_remove(struct tcf_block *block, struct net *net) | 387 | 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 | } | 392 | } |
398 | 393 | ||
399 | static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, | 394 | static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, |
395 | u32 block_index, | ||
400 | struct netlink_ext_ack *extack) | 396 | struct netlink_ext_ack *extack) |
401 | { | 397 | { |
402 | struct tcf_block *block; | 398 | struct tcf_block *block; |
@@ -419,10 +415,13 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, | |||
419 | err = -ENOMEM; | 415 | err = -ENOMEM; |
420 | goto err_chain_create; | 416 | goto err_chain_create; |
421 | } | 417 | } |
422 | block->net = qdisc_net(q); | ||
423 | block->refcnt = 1; | 418 | block->refcnt = 1; |
424 | block->net = net; | 419 | block->net = net; |
425 | block->q = q; | 420 | block->index = block_index; |
421 | |||
422 | /* Don't store q pointer for blocks which are shared */ | ||
423 | if (!tcf_block_shared(block)) | ||
424 | block->q = q; | ||
426 | return block; | 425 | return block; |
427 | 426 | ||
428 | err_chain_create: | 427 | err_chain_create: |
@@ -518,13 +517,12 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q, | |||
518 | } | 517 | } |
519 | 518 | ||
520 | if (!block) { | 519 | if (!block) { |
521 | block = tcf_block_create(net, q, extack); | 520 | block = tcf_block_create(net, q, ei->block_index, extack); |
522 | if (IS_ERR(block)) | 521 | if (IS_ERR(block)) |
523 | return PTR_ERR(block); | 522 | return PTR_ERR(block); |
524 | created = true; | 523 | created = true; |
525 | if (ei->block_index) { | 524 | if (tcf_block_shared(block)) { |
526 | err = tcf_block_insert(block, net, | 525 | err = tcf_block_insert(block, net, extack); |
527 | ei->block_index, extack); | ||
528 | if (err) | 526 | if (err) |
529 | goto err_block_insert; | 527 | goto err_block_insert; |
530 | } | 528 | } |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 6c7601a530e3..ed8b6a24b9e9 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -96,7 +96,7 @@ struct tc_u_hnode { | |||
96 | 96 | ||
97 | struct tc_u_common { | 97 | struct tc_u_common { |
98 | struct tc_u_hnode __rcu *hlist; | 98 | struct tc_u_hnode __rcu *hlist; |
99 | struct tcf_block *block; | 99 | void *ptr; |
100 | int refcnt; | 100 | int refcnt; |
101 | struct idr handle_idr; | 101 | struct idr handle_idr; |
102 | struct hlist_node hnode; | 102 | struct hlist_node hnode; |
@@ -330,9 +330,25 @@ static struct hlist_head *tc_u_common_hash; | |||
330 | #define U32_HASH_SHIFT 10 | 330 | #define U32_HASH_SHIFT 10 |
331 | #define U32_HASH_SIZE (1 << U32_HASH_SHIFT) | 331 | #define U32_HASH_SIZE (1 << U32_HASH_SHIFT) |
332 | 332 | ||
333 | static void *tc_u_common_ptr(const struct tcf_proto *tp) | ||
334 | { | ||
335 | struct tcf_block *block = tp->chain->block; | ||
336 | |||
337 | /* The block sharing is currently supported only | ||
338 | * for classless qdiscs. In that case we use block | ||
339 | * for tc_u_common identification. In case the | ||
340 | * block is not shared, block->q is a valid pointer | ||
341 | * and we can use that. That works for classful qdiscs. | ||
342 | */ | ||
343 | if (tcf_block_shared(block)) | ||
344 | return block; | ||
345 | else | ||
346 | return block->q; | ||
347 | } | ||
348 | |||
333 | static unsigned int tc_u_hash(const struct tcf_proto *tp) | 349 | static unsigned int tc_u_hash(const struct tcf_proto *tp) |
334 | { | 350 | { |
335 | return hash_ptr(tp->chain->block, U32_HASH_SHIFT); | 351 | return hash_ptr(tc_u_common_ptr(tp), U32_HASH_SHIFT); |
336 | } | 352 | } |
337 | 353 | ||
338 | static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) | 354 | 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 | 358 | ||
343 | h = tc_u_hash(tp); | 359 | h = tc_u_hash(tp); |
344 | hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) { | 360 | hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) { |
345 | if (tc->block == tp->chain->block) | 361 | if (tc->ptr == tc_u_common_ptr(tp)) |
346 | return tc; | 362 | return tc; |
347 | } | 363 | } |
348 | return NULL; | 364 | return NULL; |
@@ -371,7 +387,7 @@ static int u32_init(struct tcf_proto *tp) | |||
371 | kfree(root_ht); | 387 | kfree(root_ht); |
372 | return -ENOBUFS; | 388 | return -ENOBUFS; |
373 | } | 389 | } |
374 | tp_c->block = tp->chain->block; | 390 | tp_c->ptr = tc_u_common_ptr(tp); |
375 | INIT_HLIST_NODE(&tp_c->hnode); | 391 | INIT_HLIST_NODE(&tp_c->hnode); |
376 | idr_init(&tp_c->handle_idr); | 392 | idr_init(&tp_c->handle_idr); |
377 | 393 | ||