Commit e474619a2498c57f7f0ed8b4abb29d6c62e2393b
Committed by
David S. Miller
1 parent
31f1a0e37c
net: sched: flower: don't check for rtnl on head dereference
Flower classifier only changes root pointer during init and destroy. Cls API implements reference counting for tcf_proto, so there is no danger of concurrent access to tp when it is being destroyed, even without protection provided by rtnl lock. Implement new function fl_head_dereference() to dereference tp->root without checking for rtnl lock. Use it in all flower function that obtain head pointer instead of rtnl_dereference(). Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Reviewed-by: Stefano Brivio <sbrivio@redhat.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 17 additions and 7 deletions Side-by-side Diff
net/sched/cls_flower.c
... | ... | @@ -437,10 +437,20 @@ |
437 | 437 | cls_flower.stats.lastused); |
438 | 438 | } |
439 | 439 | |
440 | +static struct cls_fl_head *fl_head_dereference(struct tcf_proto *tp) | |
441 | +{ | |
442 | + /* Flower classifier only changes root pointer during init and destroy. | |
443 | + * Users must obtain reference to tcf_proto instance before calling its | |
444 | + * API, so tp->root pointer is protected from concurrent call to | |
445 | + * fl_destroy() by reference counting. | |
446 | + */ | |
447 | + return rcu_dereference_raw(tp->root); | |
448 | +} | |
449 | + | |
440 | 450 | static bool __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f, |
441 | 451 | struct netlink_ext_ack *extack) |
442 | 452 | { |
443 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
453 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
444 | 454 | bool async = tcf_exts_get_net(&f->exts); |
445 | 455 | bool last; |
446 | 456 | |
... | ... | @@ -472,7 +482,7 @@ |
472 | 482 | static void fl_destroy(struct tcf_proto *tp, bool rtnl_held, |
473 | 483 | struct netlink_ext_ack *extack) |
474 | 484 | { |
475 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
485 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
476 | 486 | struct fl_flow_mask *mask, *next_mask; |
477 | 487 | struct cls_fl_filter *f, *next; |
478 | 488 | |
... | ... | @@ -490,7 +500,7 @@ |
490 | 500 | |
491 | 501 | static void *fl_get(struct tcf_proto *tp, u32 handle) |
492 | 502 | { |
493 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
503 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
494 | 504 | |
495 | 505 | return idr_find(&head->handle_idr, handle); |
496 | 506 | } |
... | ... | @@ -1308,7 +1318,7 @@ |
1308 | 1318 | void **arg, bool ovr, bool rtnl_held, |
1309 | 1319 | struct netlink_ext_ack *extack) |
1310 | 1320 | { |
1311 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
1321 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
1312 | 1322 | struct cls_fl_filter *fold = *arg; |
1313 | 1323 | struct cls_fl_filter *fnew; |
1314 | 1324 | struct fl_flow_mask *mask; |
... | ... | @@ -1446,7 +1456,7 @@ |
1446 | 1456 | static int fl_delete(struct tcf_proto *tp, void *arg, bool *last, |
1447 | 1457 | bool rtnl_held, struct netlink_ext_ack *extack) |
1448 | 1458 | { |
1449 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
1459 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
1450 | 1460 | struct cls_fl_filter *f = arg; |
1451 | 1461 | |
1452 | 1462 | rhashtable_remove_fast(&f->mask->ht, &f->ht_node, |
... | ... | @@ -1459,7 +1469,7 @@ |
1459 | 1469 | static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg, |
1460 | 1470 | bool rtnl_held) |
1461 | 1471 | { |
1462 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
1472 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
1463 | 1473 | struct cls_fl_filter *f; |
1464 | 1474 | |
1465 | 1475 | arg->count = arg->skip; |
... | ... | @@ -1478,7 +1488,7 @@ |
1478 | 1488 | static int fl_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, |
1479 | 1489 | void *cb_priv, struct netlink_ext_ack *extack) |
1480 | 1490 | { |
1481 | - struct cls_fl_head *head = rtnl_dereference(tp->root); | |
1491 | + struct cls_fl_head *head = fl_head_dereference(tp); | |
1482 | 1492 | struct tc_cls_flower_offload cls_flower = {}; |
1483 | 1493 | struct tcf_block *block = tp->chain->block; |
1484 | 1494 | struct fl_flow_mask *mask; |