aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_api.c')
-rw-r--r--net/sched/cls_api.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 2bc1bc23d42e..247b7cc20c13 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -376,17 +376,12 @@ struct tcf_net {
376static unsigned int tcf_net_id; 376static unsigned int tcf_net_id;
377 377
378static int tcf_block_insert(struct tcf_block *block, struct net *net, 378static 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
392static void tcf_block_remove(struct tcf_block *block, struct net *net) 387static 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
399static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, 394static 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
428err_chain_create: 427err_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 }
@@ -1399,13 +1397,18 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
1399 nla_get_u32(tca[TCA_CHAIN]) != chain->index) 1397 nla_get_u32(tca[TCA_CHAIN]) != chain->index)
1400 continue; 1398 continue;
1401 if (!tcf_chain_dump(chain, q, parent, skb, cb, 1399 if (!tcf_chain_dump(chain, q, parent, skb, cb,
1402 index_start, &index)) 1400 index_start, &index)) {
1401 err = -EMSGSIZE;
1403 break; 1402 break;
1403 }
1404 } 1404 }
1405 1405
1406 cb->args[0] = index; 1406 cb->args[0] = index;
1407 1407
1408out: 1408out:
1409 /* If we did no progress, the error (EMSGSIZE) is real */
1410 if (skb->len == 0 && err)
1411 return err;
1409 return skb->len; 1412 return skb->len;
1410} 1413}
1411 1414