aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2019-02-11 03:55:45 -0500
committerDavid S. Miller <davem@davemloft.net>2019-02-12 13:41:33 -0500
commit12db03b65c2b90752e4c37666977fd4a1b5f5824 (patch)
tree6915e0a9fae6df1abbd8ce54ce5a13d6b2688953
parent7d5509fa0d3ddfe252b4418513e493ac98de3317 (diff)
net: sched: extend proto ops to support unlocked classifiers
Add 'rtnl_held' flag to tcf proto change, delete, destroy, dump, walk functions to track rtnl lock status. Extend users of these function in cls API to propagate rtnl lock status to them. This allows classifiers to obtain rtnl lock when necessary and to pass rtnl lock status to extensions and driver offload callbacks. Add flags field to tcf proto ops. Add flag value to indicate that classifier doesn't require rtnl lock. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/pkt_cls.h2
-rw-r--r--include/net/sch_generic.h17
-rw-r--r--net/sched/cls_api.c168
-rw-r--r--net/sched/cls_basic.c12
-rw-r--r--net/sched/cls_bpf.c12
-rw-r--r--net/sched/cls_cgroup.c11
-rw-r--r--net/sched/cls_flow.c13
-rw-r--r--net/sched/cls_flower.c13
-rw-r--r--net/sched/cls_fw.c13
-rw-r--r--net/sched/cls_matchall.c13
-rw-r--r--net/sched/cls_route.c12
-rw-r--r--net/sched/cls_rsvp.h13
-rw-r--r--net/sched/cls_tcindex.c15
-rw-r--r--net/sched/cls_u32.c12
-rw-r--r--net/sched/sch_api.c6
15 files changed, 191 insertions, 141 deletions
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 0e3b61016931..6a530bef9253 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -47,7 +47,7 @@ void tcf_chain_put_by_act(struct tcf_chain *chain);
47struct tcf_chain *tcf_get_next_chain(struct tcf_block *block, 47struct tcf_chain *tcf_get_next_chain(struct tcf_block *block,
48 struct tcf_chain *chain); 48 struct tcf_chain *chain);
49struct tcf_proto *tcf_get_next_proto(struct tcf_chain *chain, 49struct tcf_proto *tcf_get_next_proto(struct tcf_chain *chain,
50 struct tcf_proto *tp); 50 struct tcf_proto *tp, bool rtnl_held);
51void tcf_block_netif_keep_dst(struct tcf_block *block); 51void tcf_block_netif_keep_dst(struct tcf_block *block);
52int tcf_block_get(struct tcf_block **p_block, 52int tcf_block_get(struct tcf_block **p_block,
53 struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, 53 struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 410dda80ca62..365801c2a4f5 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -273,7 +273,7 @@ struct tcf_proto_ops {
273 const struct tcf_proto *, 273 const struct tcf_proto *,
274 struct tcf_result *); 274 struct tcf_result *);
275 int (*init)(struct tcf_proto*); 275 int (*init)(struct tcf_proto*);
276 void (*destroy)(struct tcf_proto *tp, 276 void (*destroy)(struct tcf_proto *tp, bool rtnl_held,
277 struct netlink_ext_ack *extack); 277 struct netlink_ext_ack *extack);
278 278
279 void* (*get)(struct tcf_proto*, u32 handle); 279 void* (*get)(struct tcf_proto*, u32 handle);
@@ -281,12 +281,13 @@ struct tcf_proto_ops {
281 int (*change)(struct net *net, struct sk_buff *, 281 int (*change)(struct net *net, struct sk_buff *,
282 struct tcf_proto*, unsigned long, 282 struct tcf_proto*, unsigned long,
283 u32 handle, struct nlattr **, 283 u32 handle, struct nlattr **,
284 void **, bool, 284 void **, bool, bool,
285 struct netlink_ext_ack *); 285 struct netlink_ext_ack *);
286 int (*delete)(struct tcf_proto *tp, void *arg, 286 int (*delete)(struct tcf_proto *tp, void *arg,
287 bool *last, 287 bool *last, bool rtnl_held,
288 struct netlink_ext_ack *); 288 struct netlink_ext_ack *);
289 void (*walk)(struct tcf_proto*, struct tcf_walker *arg); 289 void (*walk)(struct tcf_proto *tp,
290 struct tcf_walker *arg, bool rtnl_held);
290 int (*reoffload)(struct tcf_proto *tp, bool add, 291 int (*reoffload)(struct tcf_proto *tp, bool add,
291 tc_setup_cb_t *cb, void *cb_priv, 292 tc_setup_cb_t *cb, void *cb_priv,
292 struct netlink_ext_ack *extack); 293 struct netlink_ext_ack *extack);
@@ -299,12 +300,18 @@ struct tcf_proto_ops {
299 300
300 /* rtnetlink specific */ 301 /* rtnetlink specific */
301 int (*dump)(struct net*, struct tcf_proto*, void *, 302 int (*dump)(struct net*, struct tcf_proto*, void *,
302 struct sk_buff *skb, struct tcmsg*); 303 struct sk_buff *skb, struct tcmsg*,
304 bool);
303 int (*tmplt_dump)(struct sk_buff *skb, 305 int (*tmplt_dump)(struct sk_buff *skb,
304 struct net *net, 306 struct net *net,
305 void *tmplt_priv); 307 void *tmplt_priv);
306 308
307 struct module *owner; 309 struct module *owner;
310 int flags;
311};
312
313enum tcf_proto_ops_flags {
314 TCF_PROTO_OPS_DOIT_UNLOCKED = 1,
308}; 315};
309 316
310struct tcf_proto { 317struct tcf_proto {
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 8fe38aa180cf..e8ed461e94af 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -69,7 +69,8 @@ static const struct tcf_proto_ops *__tcf_proto_lookup_ops(const char *kind)
69} 69}
70 70
71static const struct tcf_proto_ops * 71static const struct tcf_proto_ops *
72tcf_proto_lookup_ops(const char *kind, struct netlink_ext_ack *extack) 72tcf_proto_lookup_ops(const char *kind, bool rtnl_held,
73 struct netlink_ext_ack *extack)
73{ 74{
74 const struct tcf_proto_ops *ops; 75 const struct tcf_proto_ops *ops;
75 76
@@ -77,9 +78,11 @@ tcf_proto_lookup_ops(const char *kind, struct netlink_ext_ack *extack)
77 if (ops) 78 if (ops)
78 return ops; 79 return ops;
79#ifdef CONFIG_MODULES 80#ifdef CONFIG_MODULES
80 rtnl_unlock(); 81 if (rtnl_held)
82 rtnl_unlock();
81 request_module("cls_%s", kind); 83 request_module("cls_%s", kind);
82 rtnl_lock(); 84 if (rtnl_held)
85 rtnl_lock();
83 ops = __tcf_proto_lookup_ops(kind); 86 ops = __tcf_proto_lookup_ops(kind);
84 /* We dropped the RTNL semaphore in order to perform 87 /* We dropped the RTNL semaphore in order to perform
85 * the module load. So, even if we succeeded in loading 88 * the module load. So, even if we succeeded in loading
@@ -162,6 +165,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
162 165
163static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol, 166static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
164 u32 prio, struct tcf_chain *chain, 167 u32 prio, struct tcf_chain *chain,
168 bool rtnl_held,
165 struct netlink_ext_ack *extack) 169 struct netlink_ext_ack *extack)
166{ 170{
167 struct tcf_proto *tp; 171 struct tcf_proto *tp;
@@ -171,7 +175,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
171 if (!tp) 175 if (!tp)
172 return ERR_PTR(-ENOBUFS); 176 return ERR_PTR(-ENOBUFS);
173 177
174 tp->ops = tcf_proto_lookup_ops(kind, extack); 178 tp->ops = tcf_proto_lookup_ops(kind, rtnl_held, extack);
175 if (IS_ERR(tp->ops)) { 179 if (IS_ERR(tp->ops)) {
176 err = PTR_ERR(tp->ops); 180 err = PTR_ERR(tp->ops);
177 goto errout; 181 goto errout;
@@ -202,20 +206,20 @@ static void tcf_proto_get(struct tcf_proto *tp)
202 206
203static void tcf_chain_put(struct tcf_chain *chain); 207static void tcf_chain_put(struct tcf_chain *chain);
204 208
205static void tcf_proto_destroy(struct tcf_proto *tp, 209static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
206 struct netlink_ext_ack *extack) 210 struct netlink_ext_ack *extack)
207{ 211{
208 tp->ops->destroy(tp, extack); 212 tp->ops->destroy(tp, rtnl_held, extack);
209 tcf_chain_put(tp->chain); 213 tcf_chain_put(tp->chain);
210 module_put(tp->ops->owner); 214 module_put(tp->ops->owner);
211 kfree_rcu(tp, rcu); 215 kfree_rcu(tp, rcu);
212} 216}
213 217
214static void tcf_proto_put(struct tcf_proto *tp, 218static void tcf_proto_put(struct tcf_proto *tp, bool rtnl_held,
215 struct netlink_ext_ack *extack) 219 struct netlink_ext_ack *extack)
216{ 220{
217 if (refcount_dec_and_test(&tp->refcnt)) 221 if (refcount_dec_and_test(&tp->refcnt))
218 tcf_proto_destroy(tp, extack); 222 tcf_proto_destroy(tp, rtnl_held, extack);
219} 223}
220 224
221static int walker_noop(struct tcf_proto *tp, void *d, struct tcf_walker *arg) 225static int walker_noop(struct tcf_proto *tp, void *d, struct tcf_walker *arg)
@@ -223,21 +227,21 @@ static int walker_noop(struct tcf_proto *tp, void *d, struct tcf_walker *arg)
223 return -1; 227 return -1;
224} 228}
225 229
226static bool tcf_proto_is_empty(struct tcf_proto *tp) 230static bool tcf_proto_is_empty(struct tcf_proto *tp, bool rtnl_held)
227{ 231{
228 struct tcf_walker walker = { .fn = walker_noop, }; 232 struct tcf_walker walker = { .fn = walker_noop, };
229 233
230 if (tp->ops->walk) { 234 if (tp->ops->walk) {
231 tp->ops->walk(tp, &walker); 235 tp->ops->walk(tp, &walker, rtnl_held);
232 return !walker.stop; 236 return !walker.stop;
233 } 237 }
234 return true; 238 return true;
235} 239}
236 240
237static bool tcf_proto_check_delete(struct tcf_proto *tp) 241static bool tcf_proto_check_delete(struct tcf_proto *tp, bool rtnl_held)
238{ 242{
239 spin_lock(&tp->lock); 243 spin_lock(&tp->lock);
240 if (tcf_proto_is_empty(tp)) 244 if (tcf_proto_is_empty(tp, rtnl_held))
241 tp->deleting = true; 245 tp->deleting = true;
242 spin_unlock(&tp->lock); 246 spin_unlock(&tp->lock);
243 return tp->deleting; 247 return tp->deleting;
@@ -506,7 +510,7 @@ static void tcf_chain_put_explicitly_created(struct tcf_chain *chain)
506 __tcf_chain_put(chain, false, true); 510 __tcf_chain_put(chain, false, true);
507} 511}
508 512
509static void tcf_chain_flush(struct tcf_chain *chain) 513static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held)
510{ 514{
511 struct tcf_proto *tp, *tp_next; 515 struct tcf_proto *tp, *tp_next;
512 516
@@ -519,7 +523,7 @@ static void tcf_chain_flush(struct tcf_chain *chain)
519 523
520 while (tp) { 524 while (tp) {
521 tp_next = rcu_dereference_protected(tp->next, 1); 525 tp_next = rcu_dereference_protected(tp->next, 1);
522 tcf_proto_put(tp, NULL); 526 tcf_proto_put(tp, rtnl_held, NULL);
523 tp = tp_next; 527 tp = tp_next;
524 } 528 }
525} 529}
@@ -1070,18 +1074,19 @@ __tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp)
1070 */ 1074 */
1071 1075
1072struct tcf_proto * 1076struct tcf_proto *
1073tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp) 1077tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp,
1078 bool rtnl_held)
1074{ 1079{
1075 struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp); 1080 struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp);
1076 1081
1077 if (tp) 1082 if (tp)
1078 tcf_proto_put(tp, NULL); 1083 tcf_proto_put(tp, rtnl_held, NULL);
1079 1084
1080 return tp_next; 1085 return tp_next;
1081} 1086}
1082EXPORT_SYMBOL(tcf_get_next_proto); 1087EXPORT_SYMBOL(tcf_get_next_proto);
1083 1088
1084static void tcf_block_flush_all_chains(struct tcf_block *block) 1089static void tcf_block_flush_all_chains(struct tcf_block *block, bool rtnl_held)
1085{ 1090{
1086 struct tcf_chain *chain; 1091 struct tcf_chain *chain;
1087 1092
@@ -1092,12 +1097,12 @@ static void tcf_block_flush_all_chains(struct tcf_block *block)
1092 chain; 1097 chain;
1093 chain = tcf_get_next_chain(block, chain)) { 1098 chain = tcf_get_next_chain(block, chain)) {
1094 tcf_chain_put_explicitly_created(chain); 1099 tcf_chain_put_explicitly_created(chain);
1095 tcf_chain_flush(chain); 1100 tcf_chain_flush(chain, rtnl_held);
1096 } 1101 }
1097} 1102}
1098 1103
1099static void __tcf_block_put(struct tcf_block *block, struct Qdisc *q, 1104static void __tcf_block_put(struct tcf_block *block, struct Qdisc *q,
1100 struct tcf_block_ext_info *ei) 1105 struct tcf_block_ext_info *ei, bool rtnl_held)
1101{ 1106{
1102 if (refcount_dec_and_mutex_lock(&block->refcnt, &block->lock)) { 1107 if (refcount_dec_and_mutex_lock(&block->refcnt, &block->lock)) {
1103 /* Flushing/putting all chains will cause the block to be 1108 /* Flushing/putting all chains will cause the block to be
@@ -1118,15 +1123,15 @@ static void __tcf_block_put(struct tcf_block *block, struct Qdisc *q,
1118 if (free_block) 1123 if (free_block)
1119 tcf_block_destroy(block); 1124 tcf_block_destroy(block);
1120 else 1125 else
1121 tcf_block_flush_all_chains(block); 1126 tcf_block_flush_all_chains(block, rtnl_held);
1122 } else if (q) { 1127 } else if (q) {
1123 tcf_block_offload_unbind(block, q, ei); 1128 tcf_block_offload_unbind(block, q, ei);
1124 } 1129 }
1125} 1130}
1126 1131
1127static void tcf_block_refcnt_put(struct tcf_block *block) 1132static void tcf_block_refcnt_put(struct tcf_block *block, bool rtnl_held)
1128{ 1133{
1129 __tcf_block_put(block, NULL, NULL); 1134 __tcf_block_put(block, NULL, NULL, rtnl_held);
1130} 1135}
1131 1136
1132/* Find tcf block. 1137/* Find tcf block.
@@ -1244,10 +1249,11 @@ errout_qdisc:
1244 return ERR_PTR(err); 1249 return ERR_PTR(err);
1245} 1250}
1246 1251
1247static void tcf_block_release(struct Qdisc *q, struct tcf_block *block) 1252static void tcf_block_release(struct Qdisc *q, struct tcf_block *block,
1253 bool rtnl_held)
1248{ 1254{
1249 if (!IS_ERR_OR_NULL(block)) 1255 if (!IS_ERR_OR_NULL(block))
1250 tcf_block_refcnt_put(block); 1256 tcf_block_refcnt_put(block, rtnl_held);
1251 1257
1252 if (q) 1258 if (q)
1253 qdisc_put(q); 1259 qdisc_put(q);
@@ -1358,7 +1364,7 @@ err_chain0_head_change_cb_add:
1358 tcf_block_owner_del(block, q, ei->binder_type); 1364 tcf_block_owner_del(block, q, ei->binder_type);
1359err_block_owner_add: 1365err_block_owner_add:
1360err_block_insert: 1366err_block_insert:
1361 tcf_block_refcnt_put(block); 1367 tcf_block_refcnt_put(block, true);
1362 return err; 1368 return err;
1363} 1369}
1364EXPORT_SYMBOL(tcf_block_get_ext); 1370EXPORT_SYMBOL(tcf_block_get_ext);
@@ -1395,7 +1401,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
1395 tcf_chain0_head_change_cb_del(block, ei); 1401 tcf_chain0_head_change_cb_del(block, ei);
1396 tcf_block_owner_del(block, q, ei->binder_type); 1402 tcf_block_owner_del(block, q, ei->binder_type);
1397 1403
1398 __tcf_block_put(block, q, ei); 1404 __tcf_block_put(block, q, ei, true);
1399} 1405}
1400EXPORT_SYMBOL(tcf_block_put_ext); 1406EXPORT_SYMBOL(tcf_block_put_ext);
1401 1407
@@ -1464,7 +1470,7 @@ tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
1464 for (tp = __tcf_get_next_proto(chain, NULL); tp; 1470 for (tp = __tcf_get_next_proto(chain, NULL); tp;
1465 tp_prev = tp, 1471 tp_prev = tp,
1466 tp = __tcf_get_next_proto(chain, tp), 1472 tp = __tcf_get_next_proto(chain, tp),
1467 tcf_proto_put(tp_prev, NULL)) { 1473 tcf_proto_put(tp_prev, true, NULL)) {
1468 if (tp->ops->reoffload) { 1474 if (tp->ops->reoffload) {
1469 err = tp->ops->reoffload(tp, add, cb, cb_priv, 1475 err = tp->ops->reoffload(tp, add, cb, cb_priv,
1470 extack); 1476 extack);
@@ -1481,7 +1487,7 @@ tcf_block_playback_offloads(struct tcf_block *block, tc_setup_cb_t *cb,
1481 return 0; 1487 return 0;
1482 1488
1483err_playback_remove: 1489err_playback_remove:
1484 tcf_proto_put(tp, NULL); 1490 tcf_proto_put(tp, true, NULL);
1485 tcf_chain_put(chain); 1491 tcf_chain_put(chain);
1486 tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use, 1492 tcf_block_playback_offloads(block, cb, cb_priv, false, offload_in_use,
1487 extack); 1493 extack);
@@ -1654,7 +1660,8 @@ static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,
1654 1660
1655static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain, 1661static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain,
1656 struct tcf_proto *tp_new, 1662 struct tcf_proto *tp_new,
1657 u32 protocol, u32 prio) 1663 u32 protocol, u32 prio,
1664 bool rtnl_held)
1658{ 1665{
1659 struct tcf_chain_info chain_info; 1666 struct tcf_chain_info chain_info;
1660 struct tcf_proto *tp; 1667 struct tcf_proto *tp;
@@ -1669,10 +1676,10 @@ static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain,
1669 mutex_unlock(&chain->filter_chain_lock); 1676 mutex_unlock(&chain->filter_chain_lock);
1670 1677
1671 if (tp) { 1678 if (tp) {
1672 tcf_proto_destroy(tp_new, NULL); 1679 tcf_proto_destroy(tp_new, rtnl_held, NULL);
1673 tp_new = tp; 1680 tp_new = tp;
1674 } else if (err) { 1681 } else if (err) {
1675 tcf_proto_destroy(tp_new, NULL); 1682 tcf_proto_destroy(tp_new, rtnl_held, NULL);
1676 tp_new = ERR_PTR(err); 1683 tp_new = ERR_PTR(err);
1677 } 1684 }
1678 1685
@@ -1680,7 +1687,7 @@ static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain,
1680} 1687}
1681 1688
1682static void tcf_chain_tp_delete_empty(struct tcf_chain *chain, 1689static void tcf_chain_tp_delete_empty(struct tcf_chain *chain,
1683 struct tcf_proto *tp, 1690 struct tcf_proto *tp, bool rtnl_held,
1684 struct netlink_ext_ack *extack) 1691 struct netlink_ext_ack *extack)
1685{ 1692{
1686 struct tcf_chain_info chain_info; 1693 struct tcf_chain_info chain_info;
@@ -1705,7 +1712,7 @@ static void tcf_chain_tp_delete_empty(struct tcf_chain *chain,
1705 * concurrently. 1712 * concurrently.
1706 * Mark tp for deletion if it is empty. 1713 * Mark tp for deletion if it is empty.
1707 */ 1714 */
1708 if (!tp_iter || !tcf_proto_check_delete(tp)) { 1715 if (!tp_iter || !tcf_proto_check_delete(tp, rtnl_held)) {
1709 mutex_unlock(&chain->filter_chain_lock); 1716 mutex_unlock(&chain->filter_chain_lock);
1710 return; 1717 return;
1711 } 1718 }
@@ -1716,7 +1723,7 @@ static void tcf_chain_tp_delete_empty(struct tcf_chain *chain,
1716 RCU_INIT_POINTER(*chain_info.pprev, next); 1723 RCU_INIT_POINTER(*chain_info.pprev, next);
1717 mutex_unlock(&chain->filter_chain_lock); 1724 mutex_unlock(&chain->filter_chain_lock);
1718 1725
1719 tcf_proto_put(tp, extack); 1726 tcf_proto_put(tp, rtnl_held, extack);
1720} 1727}
1721 1728
1722static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain, 1729static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,
@@ -1755,7 +1762,8 @@ static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,
1755static int tcf_fill_node(struct net *net, struct sk_buff *skb, 1762static int tcf_fill_node(struct net *net, struct sk_buff *skb,
1756 struct tcf_proto *tp, struct tcf_block *block, 1763 struct tcf_proto *tp, struct tcf_block *block,
1757 struct Qdisc *q, u32 parent, void *fh, 1764 struct Qdisc *q, u32 parent, void *fh,
1758 u32 portid, u32 seq, u16 flags, int event) 1765 u32 portid, u32 seq, u16 flags, int event,
1766 bool rtnl_held)
1759{ 1767{
1760 struct tcmsg *tcm; 1768 struct tcmsg *tcm;
1761 struct nlmsghdr *nlh; 1769 struct nlmsghdr *nlh;
@@ -1783,7 +1791,8 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb,
1783 if (!fh) { 1791 if (!fh) {
1784 tcm->tcm_handle = 0; 1792 tcm->tcm_handle = 0;
1785 } else { 1793 } else {
1786 if (tp->ops->dump && tp->ops->dump(net, tp, fh, skb, tcm) < 0) 1794 if (tp->ops->dump &&
1795 tp->ops->dump(net, tp, fh, skb, tcm, rtnl_held) < 0)
1787 goto nla_put_failure; 1796 goto nla_put_failure;
1788 } 1797 }
1789 nlh->nlmsg_len = skb_tail_pointer(skb) - b; 1798 nlh->nlmsg_len = skb_tail_pointer(skb) - b;
@@ -1798,7 +1807,8 @@ nla_put_failure:
1798static int tfilter_notify(struct net *net, struct sk_buff *oskb, 1807static int tfilter_notify(struct net *net, struct sk_buff *oskb,
1799 struct nlmsghdr *n, struct tcf_proto *tp, 1808 struct nlmsghdr *n, struct tcf_proto *tp,
1800 struct tcf_block *block, struct Qdisc *q, 1809 struct tcf_block *block, struct Qdisc *q,
1801 u32 parent, void *fh, int event, bool unicast) 1810 u32 parent, void *fh, int event, bool unicast,
1811 bool rtnl_held)
1802{ 1812{
1803 struct sk_buff *skb; 1813 struct sk_buff *skb;
1804 u32 portid = oskb ? NETLINK_CB(oskb).portid : 0; 1814 u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
@@ -1808,7 +1818,8 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
1808 return -ENOBUFS; 1818 return -ENOBUFS;
1809 1819
1810 if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid, 1820 if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid,
1811 n->nlmsg_seq, n->nlmsg_flags, event) <= 0) { 1821 n->nlmsg_seq, n->nlmsg_flags, event,
1822 rtnl_held) <= 0) {
1812 kfree_skb(skb); 1823 kfree_skb(skb);
1813 return -EINVAL; 1824 return -EINVAL;
1814 } 1825 }
@@ -1824,7 +1835,7 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
1824 struct nlmsghdr *n, struct tcf_proto *tp, 1835 struct nlmsghdr *n, struct tcf_proto *tp,
1825 struct tcf_block *block, struct Qdisc *q, 1836 struct tcf_block *block, struct Qdisc *q,
1826 u32 parent, void *fh, bool unicast, bool *last, 1837 u32 parent, void *fh, bool unicast, bool *last,
1827 struct netlink_ext_ack *extack) 1838 bool rtnl_held, struct netlink_ext_ack *extack)
1828{ 1839{
1829 struct sk_buff *skb; 1840 struct sk_buff *skb;
1830 u32 portid = oskb ? NETLINK_CB(oskb).portid : 0; 1841 u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
@@ -1835,13 +1846,14 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
1835 return -ENOBUFS; 1846 return -ENOBUFS;
1836 1847
1837 if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid, 1848 if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid,
1838 n->nlmsg_seq, n->nlmsg_flags, RTM_DELTFILTER) <= 0) { 1849 n->nlmsg_seq, n->nlmsg_flags, RTM_DELTFILTER,
1850 rtnl_held) <= 0) {
1839 NL_SET_ERR_MSG(extack, "Failed to build del event notification"); 1851 NL_SET_ERR_MSG(extack, "Failed to build del event notification");
1840 kfree_skb(skb); 1852 kfree_skb(skb);
1841 return -EINVAL; 1853 return -EINVAL;
1842 } 1854 }
1843 1855
1844 err = tp->ops->delete(tp, fh, last, extack); 1856 err = tp->ops->delete(tp, fh, last, rtnl_held, extack);
1845 if (err) { 1857 if (err) {
1846 kfree_skb(skb); 1858 kfree_skb(skb);
1847 return err; 1859 return err;
@@ -1860,14 +1872,15 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
1860static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb, 1872static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
1861 struct tcf_block *block, struct Qdisc *q, 1873 struct tcf_block *block, struct Qdisc *q,
1862 u32 parent, struct nlmsghdr *n, 1874 u32 parent, struct nlmsghdr *n,
1863 struct tcf_chain *chain, int event) 1875 struct tcf_chain *chain, int event,
1876 bool rtnl_held)
1864{ 1877{
1865 struct tcf_proto *tp; 1878 struct tcf_proto *tp;
1866 1879
1867 for (tp = tcf_get_next_proto(chain, NULL); 1880 for (tp = tcf_get_next_proto(chain, NULL, rtnl_held);
1868 tp; tp = tcf_get_next_proto(chain, tp)) 1881 tp; tp = tcf_get_next_proto(chain, tp, rtnl_held))
1869 tfilter_notify(net, oskb, n, tp, block, 1882 tfilter_notify(net, oskb, n, tp, block,
1870 q, parent, NULL, event, false); 1883 q, parent, NULL, event, false, rtnl_held);
1871} 1884}
1872 1885
1873static void tfilter_put(struct tcf_proto *tp, void *fh) 1886static void tfilter_put(struct tcf_proto *tp, void *fh)
@@ -1896,6 +1909,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
1896 void *fh; 1909 void *fh;
1897 int err; 1910 int err;
1898 int tp_created; 1911 int tp_created;
1912 bool rtnl_held = true;
1899 1913
1900 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) 1914 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
1901 return -EPERM; 1915 return -EPERM;
@@ -1987,14 +2001,16 @@ replay:
1987 2001
1988 mutex_unlock(&chain->filter_chain_lock); 2002 mutex_unlock(&chain->filter_chain_lock);
1989 tp_new = tcf_proto_create(nla_data(tca[TCA_KIND]), 2003 tp_new = tcf_proto_create(nla_data(tca[TCA_KIND]),
1990 protocol, prio, chain, extack); 2004 protocol, prio, chain, rtnl_held,
2005 extack);
1991 if (IS_ERR(tp_new)) { 2006 if (IS_ERR(tp_new)) {
1992 err = PTR_ERR(tp_new); 2007 err = PTR_ERR(tp_new);
1993 goto errout_tp; 2008 goto errout_tp;
1994 } 2009 }
1995 2010
1996 tp_created = 1; 2011 tp_created = 1;
1997 tp = tcf_chain_tp_insert_unique(chain, tp_new, protocol, prio); 2012 tp = tcf_chain_tp_insert_unique(chain, tp_new, protocol, prio,
2013 rtnl_held);
1998 if (IS_ERR(tp)) { 2014 if (IS_ERR(tp)) {
1999 err = PTR_ERR(tp); 2015 err = PTR_ERR(tp);
2000 goto errout_tp; 2016 goto errout_tp;
@@ -2032,24 +2048,24 @@ replay:
2032 2048
2033 err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh, 2049 err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, &fh,
2034 n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE, 2050 n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE,
2035 extack); 2051 rtnl_held, extack);
2036 if (err == 0) { 2052 if (err == 0) {
2037 tfilter_notify(net, skb, n, tp, block, q, parent, fh, 2053 tfilter_notify(net, skb, n, tp, block, q, parent, fh,
2038 RTM_NEWTFILTER, false); 2054 RTM_NEWTFILTER, false, rtnl_held);
2039 tfilter_put(tp, fh); 2055 tfilter_put(tp, fh);
2040 } 2056 }
2041 2057
2042errout: 2058errout:
2043 if (err && tp_created) 2059 if (err && tp_created)
2044 tcf_chain_tp_delete_empty(chain, tp, NULL); 2060 tcf_chain_tp_delete_empty(chain, tp, rtnl_held, NULL);
2045errout_tp: 2061errout_tp:
2046 if (chain) { 2062 if (chain) {
2047 if (tp && !IS_ERR(tp)) 2063 if (tp && !IS_ERR(tp))
2048 tcf_proto_put(tp, NULL); 2064 tcf_proto_put(tp, rtnl_held, NULL);
2049 if (!tp_created) 2065 if (!tp_created)
2050 tcf_chain_put(chain); 2066 tcf_chain_put(chain);
2051 } 2067 }
2052 tcf_block_release(q, block); 2068 tcf_block_release(q, block, rtnl_held);
2053 if (err == -EAGAIN) 2069 if (err == -EAGAIN)
2054 /* Replay the request. */ 2070 /* Replay the request. */
2055 goto replay; 2071 goto replay;
@@ -2078,6 +2094,7 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2078 unsigned long cl = 0; 2094 unsigned long cl = 0;
2079 void *fh = NULL; 2095 void *fh = NULL;
2080 int err; 2096 int err;
2097 bool rtnl_held = true;
2081 2098
2082 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) 2099 if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
2083 return -EPERM; 2100 return -EPERM;
@@ -2127,8 +2144,8 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2127 2144
2128 if (prio == 0) { 2145 if (prio == 0) {
2129 tfilter_notify_chain(net, skb, block, q, parent, n, 2146 tfilter_notify_chain(net, skb, block, q, parent, n,
2130 chain, RTM_DELTFILTER); 2147 chain, RTM_DELTFILTER, rtnl_held);
2131 tcf_chain_flush(chain); 2148 tcf_chain_flush(chain, rtnl_held);
2132 err = 0; 2149 err = 0;
2133 goto errout; 2150 goto errout;
2134 } 2151 }
@@ -2148,9 +2165,9 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2148 tcf_chain_tp_remove(chain, &chain_info, tp); 2165 tcf_chain_tp_remove(chain, &chain_info, tp);
2149 mutex_unlock(&chain->filter_chain_lock); 2166 mutex_unlock(&chain->filter_chain_lock);
2150 2167
2151 tcf_proto_put(tp, NULL); 2168 tcf_proto_put(tp, rtnl_held, NULL);
2152 tfilter_notify(net, skb, n, tp, block, q, parent, fh, 2169 tfilter_notify(net, skb, n, tp, block, q, parent, fh,
2153 RTM_DELTFILTER, false); 2170 RTM_DELTFILTER, false, rtnl_held);
2154 err = 0; 2171 err = 0;
2155 goto errout; 2172 goto errout;
2156 } 2173 }
@@ -2166,20 +2183,21 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2166 2183
2167 err = tfilter_del_notify(net, skb, n, tp, block, 2184 err = tfilter_del_notify(net, skb, n, tp, block,
2168 q, parent, fh, false, &last, 2185 q, parent, fh, false, &last,
2169 extack); 2186 rtnl_held, extack);
2187
2170 if (err) 2188 if (err)
2171 goto errout; 2189 goto errout;
2172 if (last) 2190 if (last)
2173 tcf_chain_tp_delete_empty(chain, tp, extack); 2191 tcf_chain_tp_delete_empty(chain, tp, rtnl_held, extack);
2174 } 2192 }
2175 2193
2176errout: 2194errout:
2177 if (chain) { 2195 if (chain) {
2178 if (tp && !IS_ERR(tp)) 2196 if (tp && !IS_ERR(tp))
2179 tcf_proto_put(tp, NULL); 2197 tcf_proto_put(tp, rtnl_held, NULL);
2180 tcf_chain_put(chain); 2198 tcf_chain_put(chain);
2181 } 2199 }
2182 tcf_block_release(q, block); 2200 tcf_block_release(q, block, rtnl_held);
2183 return err; 2201 return err;
2184 2202
2185errout_locked: 2203errout_locked:
@@ -2205,6 +2223,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2205 unsigned long cl = 0; 2223 unsigned long cl = 0;
2206 void *fh = NULL; 2224 void *fh = NULL;
2207 int err; 2225 int err;
2226 bool rtnl_held = true;
2208 2227
2209 err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, rtm_tca_policy, extack); 2228 err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, rtm_tca_policy, extack);
2210 if (err < 0) 2229 if (err < 0)
@@ -2263,7 +2282,7 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2263 err = -ENOENT; 2282 err = -ENOENT;
2264 } else { 2283 } else {
2265 err = tfilter_notify(net, skb, n, tp, block, q, parent, 2284 err = tfilter_notify(net, skb, n, tp, block, q, parent,
2266 fh, RTM_NEWTFILTER, true); 2285 fh, RTM_NEWTFILTER, true, rtnl_held);
2267 if (err < 0) 2286 if (err < 0)
2268 NL_SET_ERR_MSG(extack, "Failed to send filter notify message"); 2287 NL_SET_ERR_MSG(extack, "Failed to send filter notify message");
2269 } 2288 }
@@ -2272,10 +2291,10 @@ static int tc_get_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
2272errout: 2291errout:
2273 if (chain) { 2292 if (chain) {
2274 if (tp && !IS_ERR(tp)) 2293 if (tp && !IS_ERR(tp))
2275 tcf_proto_put(tp, NULL); 2294 tcf_proto_put(tp, rtnl_held, NULL);
2276 tcf_chain_put(chain); 2295 tcf_chain_put(chain);
2277 } 2296 }
2278 tcf_block_release(q, block); 2297 tcf_block_release(q, block, rtnl_held);
2279 return err; 2298 return err;
2280} 2299}
2281 2300
@@ -2296,7 +2315,7 @@ static int tcf_node_dump(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
2296 return tcf_fill_node(net, a->skb, tp, a->block, a->q, a->parent, 2315 return tcf_fill_node(net, a->skb, tp, a->block, a->q, a->parent,
2297 n, NETLINK_CB(a->cb->skb).portid, 2316 n, NETLINK_CB(a->cb->skb).portid,
2298 a->cb->nlh->nlmsg_seq, NLM_F_MULTI, 2317 a->cb->nlh->nlmsg_seq, NLM_F_MULTI,
2299 RTM_NEWTFILTER); 2318 RTM_NEWTFILTER, true);
2300} 2319}
2301 2320
2302static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent, 2321static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
@@ -2313,7 +2332,7 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
2313 tp; 2332 tp;
2314 tp_prev = tp, 2333 tp_prev = tp,
2315 tp = __tcf_get_next_proto(chain, tp), 2334 tp = __tcf_get_next_proto(chain, tp),
2316 tcf_proto_put(tp_prev, NULL), 2335 tcf_proto_put(tp_prev, true, NULL),
2317 (*p_index)++) { 2336 (*p_index)++) {
2318 if (*p_index < index_start) 2337 if (*p_index < index_start)
2319 continue; 2338 continue;
@@ -2330,9 +2349,8 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
2330 if (tcf_fill_node(net, skb, tp, block, q, parent, NULL, 2349 if (tcf_fill_node(net, skb, tp, block, q, parent, NULL,
2331 NETLINK_CB(cb->skb).portid, 2350 NETLINK_CB(cb->skb).portid,
2332 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2351 cb->nlh->nlmsg_seq, NLM_F_MULTI,
2333 RTM_NEWTFILTER) <= 0) 2352 RTM_NEWTFILTER, true) <= 0)
2334 goto errout; 2353 goto errout;
2335
2336 cb->args[1] = 1; 2354 cb->args[1] = 1;
2337 } 2355 }
2338 if (!tp->ops->walk) 2356 if (!tp->ops->walk)
@@ -2347,7 +2365,7 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
2347 arg.w.skip = cb->args[1] - 1; 2365 arg.w.skip = cb->args[1] - 1;
2348 arg.w.count = 0; 2366 arg.w.count = 0;
2349 arg.w.cookie = cb->args[2]; 2367 arg.w.cookie = cb->args[2];
2350 tp->ops->walk(tp, &arg.w); 2368 tp->ops->walk(tp, &arg.w, true);
2351 cb->args[2] = arg.w.cookie; 2369 cb->args[2] = arg.w.cookie;
2352 cb->args[1] = arg.w.count + 1; 2370 cb->args[1] = arg.w.count + 1;
2353 if (arg.w.stop) 2371 if (arg.w.stop)
@@ -2356,7 +2374,7 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
2356 return true; 2374 return true;
2357 2375
2358errout: 2376errout:
2359 tcf_proto_put(tp, NULL); 2377 tcf_proto_put(tp, true, NULL);
2360 return false; 2378 return false;
2361} 2379}
2362 2380
@@ -2448,7 +2466,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
2448 } 2466 }
2449 2467
2450 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) 2468 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK)
2451 tcf_block_refcnt_put(block); 2469 tcf_block_refcnt_put(block, true);
2452 cb->args[0] = index; 2470 cb->args[0] = index;
2453 2471
2454out: 2472out:
@@ -2569,7 +2587,7 @@ static int tc_chain_tmplt_add(struct tcf_chain *chain, struct net *net,
2569 if (!tca[TCA_KIND]) 2587 if (!tca[TCA_KIND])
2570 return 0; 2588 return 0;
2571 2589
2572 ops = tcf_proto_lookup_ops(nla_data(tca[TCA_KIND]), extack); 2590 ops = tcf_proto_lookup_ops(nla_data(tca[TCA_KIND]), true, extack);
2573 if (IS_ERR(ops)) 2591 if (IS_ERR(ops))
2574 return PTR_ERR(ops); 2592 return PTR_ERR(ops);
2575 if (!ops->tmplt_create || !ops->tmplt_destroy || !ops->tmplt_dump) { 2593 if (!ops->tmplt_create || !ops->tmplt_destroy || !ops->tmplt_dump) {
@@ -2699,9 +2717,9 @@ replay:
2699 break; 2717 break;
2700 case RTM_DELCHAIN: 2718 case RTM_DELCHAIN:
2701 tfilter_notify_chain(net, skb, block, q, parent, n, 2719 tfilter_notify_chain(net, skb, block, q, parent, n,
2702 chain, RTM_DELTFILTER); 2720 chain, RTM_DELTFILTER, true);
2703 /* Flush the chain first as the user requested chain removal. */ 2721 /* Flush the chain first as the user requested chain removal. */
2704 tcf_chain_flush(chain); 2722 tcf_chain_flush(chain, true);
2705 /* In case the chain was successfully deleted, put a reference 2723 /* In case the chain was successfully deleted, put a reference
2706 * to the chain previously taken during addition. 2724 * to the chain previously taken during addition.
2707 */ 2725 */
@@ -2722,7 +2740,7 @@ replay:
2722errout: 2740errout:
2723 tcf_chain_put(chain); 2741 tcf_chain_put(chain);
2724errout_block: 2742errout_block:
2725 tcf_block_release(q, block); 2743 tcf_block_release(q, block, true);
2726 if (err == -EAGAIN) 2744 if (err == -EAGAIN)
2727 /* Replay the request. */ 2745 /* Replay the request. */
2728 goto replay; 2746 goto replay;
@@ -2829,7 +2847,7 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
2829 } 2847 }
2830 2848
2831 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK) 2849 if (tcm->tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK)
2832 tcf_block_refcnt_put(block); 2850 tcf_block_refcnt_put(block, true);
2833 cb->args[0] = index; 2851 cb->args[0] = index;
2834 2852
2835out: 2853out:
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index eaf9c02fe792..2383f449d2bc 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -107,7 +107,8 @@ static void basic_delete_filter_work(struct work_struct *work)
107 rtnl_unlock(); 107 rtnl_unlock();
108} 108}
109 109
110static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 110static void basic_destroy(struct tcf_proto *tp, bool rtnl_held,
111 struct netlink_ext_ack *extack)
111{ 112{
112 struct basic_head *head = rtnl_dereference(tp->root); 113 struct basic_head *head = rtnl_dereference(tp->root);
113 struct basic_filter *f, *n; 114 struct basic_filter *f, *n;
@@ -126,7 +127,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
126} 127}
127 128
128static int basic_delete(struct tcf_proto *tp, void *arg, bool *last, 129static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
129 struct netlink_ext_ack *extack) 130 bool rtnl_held, struct netlink_ext_ack *extack)
130{ 131{
131 struct basic_head *head = rtnl_dereference(tp->root); 132 struct basic_head *head = rtnl_dereference(tp->root);
132 struct basic_filter *f = arg; 133 struct basic_filter *f = arg;
@@ -173,7 +174,7 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,
173static int basic_change(struct net *net, struct sk_buff *in_skb, 174static int basic_change(struct net *net, struct sk_buff *in_skb,
174 struct tcf_proto *tp, unsigned long base, u32 handle, 175 struct tcf_proto *tp, unsigned long base, u32 handle,
175 struct nlattr **tca, void **arg, bool ovr, 176 struct nlattr **tca, void **arg, bool ovr,
176 struct netlink_ext_ack *extack) 177 bool rtnl_held, struct netlink_ext_ack *extack)
177{ 178{
178 int err; 179 int err;
179 struct basic_head *head = rtnl_dereference(tp->root); 180 struct basic_head *head = rtnl_dereference(tp->root);
@@ -247,7 +248,8 @@ errout:
247 return err; 248 return err;
248} 249}
249 250
250static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg) 251static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg,
252 bool rtnl_held)
251{ 253{
252 struct basic_head *head = rtnl_dereference(tp->root); 254 struct basic_head *head = rtnl_dereference(tp->root);
253 struct basic_filter *f; 255 struct basic_filter *f;
@@ -274,7 +276,7 @@ static void basic_bind_class(void *fh, u32 classid, unsigned long cl)
274} 276}
275 277
276static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, 278static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh,
277 struct sk_buff *skb, struct tcmsg *t) 279 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
278{ 280{
279 struct tc_basic_pcnt gpf = {}; 281 struct tc_basic_pcnt gpf = {};
280 struct basic_filter *f = fh; 282 struct basic_filter *f = fh;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 656b3423ad35..062350c6621c 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -298,7 +298,7 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog,
298} 298}
299 299
300static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last, 300static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
301 struct netlink_ext_ack *extack) 301 bool rtnl_held, struct netlink_ext_ack *extack)
302{ 302{
303 struct cls_bpf_head *head = rtnl_dereference(tp->root); 303 struct cls_bpf_head *head = rtnl_dereference(tp->root);
304 304
@@ -307,7 +307,7 @@ static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
307 return 0; 307 return 0;
308} 308}
309 309
310static void cls_bpf_destroy(struct tcf_proto *tp, 310static void cls_bpf_destroy(struct tcf_proto *tp, bool rtnl_held,
311 struct netlink_ext_ack *extack) 311 struct netlink_ext_ack *extack)
312{ 312{
313 struct cls_bpf_head *head = rtnl_dereference(tp->root); 313 struct cls_bpf_head *head = rtnl_dereference(tp->root);
@@ -456,7 +456,8 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
456static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, 456static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
457 struct tcf_proto *tp, unsigned long base, 457 struct tcf_proto *tp, unsigned long base,
458 u32 handle, struct nlattr **tca, 458 u32 handle, struct nlattr **tca,
459 void **arg, bool ovr, struct netlink_ext_ack *extack) 459 void **arg, bool ovr, bool rtnl_held,
460 struct netlink_ext_ack *extack)
460{ 461{
461 struct cls_bpf_head *head = rtnl_dereference(tp->root); 462 struct cls_bpf_head *head = rtnl_dereference(tp->root);
462 struct cls_bpf_prog *oldprog = *arg; 463 struct cls_bpf_prog *oldprog = *arg;
@@ -576,7 +577,7 @@ static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog,
576} 577}
577 578
578static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, void *fh, 579static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, void *fh,
579 struct sk_buff *skb, struct tcmsg *tm) 580 struct sk_buff *skb, struct tcmsg *tm, bool rtnl_held)
580{ 581{
581 struct cls_bpf_prog *prog = fh; 582 struct cls_bpf_prog *prog = fh;
582 struct nlattr *nest; 583 struct nlattr *nest;
@@ -636,7 +637,8 @@ static void cls_bpf_bind_class(void *fh, u32 classid, unsigned long cl)
636 prog->res.class = cl; 637 prog->res.class = cl;
637} 638}
638 639
639static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg) 640static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg,
641 bool rtnl_held)
640{ 642{
641 struct cls_bpf_head *head = rtnl_dereference(tp->root); 643 struct cls_bpf_head *head = rtnl_dereference(tp->root);
642 struct cls_bpf_prog *prog; 644 struct cls_bpf_prog *prog;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 663ee1c6d606..1cef3b416094 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -78,7 +78,7 @@ static void cls_cgroup_destroy_work(struct work_struct *work)
78static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, 78static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
79 struct tcf_proto *tp, unsigned long base, 79 struct tcf_proto *tp, unsigned long base,
80 u32 handle, struct nlattr **tca, 80 u32 handle, struct nlattr **tca,
81 void **arg, bool ovr, 81 void **arg, bool ovr, bool rtnl_held,
82 struct netlink_ext_ack *extack) 82 struct netlink_ext_ack *extack)
83{ 83{
84 struct nlattr *tb[TCA_CGROUP_MAX + 1]; 84 struct nlattr *tb[TCA_CGROUP_MAX + 1];
@@ -130,7 +130,7 @@ errout:
130 return err; 130 return err;
131} 131}
132 132
133static void cls_cgroup_destroy(struct tcf_proto *tp, 133static void cls_cgroup_destroy(struct tcf_proto *tp, bool rtnl_held,
134 struct netlink_ext_ack *extack) 134 struct netlink_ext_ack *extack)
135{ 135{
136 struct cls_cgroup_head *head = rtnl_dereference(tp->root); 136 struct cls_cgroup_head *head = rtnl_dereference(tp->root);
@@ -145,12 +145,13 @@ static void cls_cgroup_destroy(struct tcf_proto *tp,
145} 145}
146 146
147static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last, 147static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last,
148 struct netlink_ext_ack *extack) 148 bool rtnl_held, struct netlink_ext_ack *extack)
149{ 149{
150 return -EOPNOTSUPP; 150 return -EOPNOTSUPP;
151} 151}
152 152
153static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg) 153static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg,
154 bool rtnl_held)
154{ 155{
155 struct cls_cgroup_head *head = rtnl_dereference(tp->root); 156 struct cls_cgroup_head *head = rtnl_dereference(tp->root);
156 157
@@ -166,7 +167,7 @@ skip:
166} 167}
167 168
168static int cls_cgroup_dump(struct net *net, struct tcf_proto *tp, void *fh, 169static int cls_cgroup_dump(struct net *net, struct tcf_proto *tp, void *fh,
169 struct sk_buff *skb, struct tcmsg *t) 170 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
170{ 171{
171 struct cls_cgroup_head *head = rtnl_dereference(tp->root); 172 struct cls_cgroup_head *head = rtnl_dereference(tp->root);
172 struct nlattr *nest; 173 struct nlattr *nest;
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 39a6407d4832..204e2edae8d5 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -391,7 +391,8 @@ static void flow_destroy_filter_work(struct work_struct *work)
391static int flow_change(struct net *net, struct sk_buff *in_skb, 391static int flow_change(struct net *net, struct sk_buff *in_skb,
392 struct tcf_proto *tp, unsigned long base, 392 struct tcf_proto *tp, unsigned long base,
393 u32 handle, struct nlattr **tca, 393 u32 handle, struct nlattr **tca,
394 void **arg, bool ovr, struct netlink_ext_ack *extack) 394 void **arg, bool ovr, bool rtnl_held,
395 struct netlink_ext_ack *extack)
395{ 396{
396 struct flow_head *head = rtnl_dereference(tp->root); 397 struct flow_head *head = rtnl_dereference(tp->root);
397 struct flow_filter *fold, *fnew; 398 struct flow_filter *fold, *fnew;
@@ -566,7 +567,7 @@ err1:
566} 567}
567 568
568static int flow_delete(struct tcf_proto *tp, void *arg, bool *last, 569static int flow_delete(struct tcf_proto *tp, void *arg, bool *last,
569 struct netlink_ext_ack *extack) 570 bool rtnl_held, struct netlink_ext_ack *extack)
570{ 571{
571 struct flow_head *head = rtnl_dereference(tp->root); 572 struct flow_head *head = rtnl_dereference(tp->root);
572 struct flow_filter *f = arg; 573 struct flow_filter *f = arg;
@@ -590,7 +591,8 @@ static int flow_init(struct tcf_proto *tp)
590 return 0; 591 return 0;
591} 592}
592 593
593static void flow_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 594static void flow_destroy(struct tcf_proto *tp, bool rtnl_held,
595 struct netlink_ext_ack *extack)
594{ 596{
595 struct flow_head *head = rtnl_dereference(tp->root); 597 struct flow_head *head = rtnl_dereference(tp->root);
596 struct flow_filter *f, *next; 598 struct flow_filter *f, *next;
@@ -617,7 +619,7 @@ static void *flow_get(struct tcf_proto *tp, u32 handle)
617} 619}
618 620
619static int flow_dump(struct net *net, struct tcf_proto *tp, void *fh, 621static int flow_dump(struct net *net, struct tcf_proto *tp, void *fh,
620 struct sk_buff *skb, struct tcmsg *t) 622 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
621{ 623{
622 struct flow_filter *f = fh; 624 struct flow_filter *f = fh;
623 struct nlattr *nest; 625 struct nlattr *nest;
@@ -677,7 +679,8 @@ nla_put_failure:
677 return -1; 679 return -1;
678} 680}
679 681
680static void flow_walk(struct tcf_proto *tp, struct tcf_walker *arg) 682static void flow_walk(struct tcf_proto *tp, struct tcf_walker *arg,
683 bool rtnl_held)
681{ 684{
682 struct flow_head *head = rtnl_dereference(tp->root); 685 struct flow_head *head = rtnl_dereference(tp->root);
683 struct flow_filter *f; 686 struct flow_filter *f;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 5e3f74ab68ca..32fa3e20adc5 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -465,7 +465,8 @@ static void fl_destroy_sleepable(struct work_struct *work)
465 module_put(THIS_MODULE); 465 module_put(THIS_MODULE);
466} 466}
467 467
468static void fl_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 468static void fl_destroy(struct tcf_proto *tp, bool rtnl_held,
469 struct netlink_ext_ack *extack)
469{ 470{
470 struct cls_fl_head *head = rtnl_dereference(tp->root); 471 struct cls_fl_head *head = rtnl_dereference(tp->root);
471 struct fl_flow_mask *mask, *next_mask; 472 struct fl_flow_mask *mask, *next_mask;
@@ -1300,7 +1301,8 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp,
1300static int fl_change(struct net *net, struct sk_buff *in_skb, 1301static int fl_change(struct net *net, struct sk_buff *in_skb,
1301 struct tcf_proto *tp, unsigned long base, 1302 struct tcf_proto *tp, unsigned long base,
1302 u32 handle, struct nlattr **tca, 1303 u32 handle, struct nlattr **tca,
1303 void **arg, bool ovr, struct netlink_ext_ack *extack) 1304 void **arg, bool ovr, bool rtnl_held,
1305 struct netlink_ext_ack *extack)
1304{ 1306{
1305 struct cls_fl_head *head = rtnl_dereference(tp->root); 1307 struct cls_fl_head *head = rtnl_dereference(tp->root);
1306 struct cls_fl_filter *fold = *arg; 1308 struct cls_fl_filter *fold = *arg;
@@ -1437,7 +1439,7 @@ errout_mask_alloc:
1437} 1439}
1438 1440
1439static int fl_delete(struct tcf_proto *tp, void *arg, bool *last, 1441static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
1440 struct netlink_ext_ack *extack) 1442 bool rtnl_held, struct netlink_ext_ack *extack)
1441{ 1443{
1442 struct cls_fl_head *head = rtnl_dereference(tp->root); 1444 struct cls_fl_head *head = rtnl_dereference(tp->root);
1443 struct cls_fl_filter *f = arg; 1445 struct cls_fl_filter *f = arg;
@@ -1449,7 +1451,8 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
1449 return 0; 1451 return 0;
1450} 1452}
1451 1453
1452static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg) 1454static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
1455 bool rtnl_held)
1453{ 1456{
1454 struct cls_fl_head *head = rtnl_dereference(tp->root); 1457 struct cls_fl_head *head = rtnl_dereference(tp->root);
1455 struct cls_fl_filter *f; 1458 struct cls_fl_filter *f;
@@ -2044,7 +2047,7 @@ nla_put_failure:
2044} 2047}
2045 2048
2046static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh, 2049static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh,
2047 struct sk_buff *skb, struct tcmsg *t) 2050 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
2048{ 2051{
2049 struct cls_fl_filter *f = fh; 2052 struct cls_fl_filter *f = fh;
2050 struct nlattr *nest; 2053 struct nlattr *nest;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index c8173ebb69f2..317151bae73b 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -139,7 +139,8 @@ static void fw_delete_filter_work(struct work_struct *work)
139 rtnl_unlock(); 139 rtnl_unlock();
140} 140}
141 141
142static void fw_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 142static void fw_destroy(struct tcf_proto *tp, bool rtnl_held,
143 struct netlink_ext_ack *extack)
143{ 144{
144 struct fw_head *head = rtnl_dereference(tp->root); 145 struct fw_head *head = rtnl_dereference(tp->root);
145 struct fw_filter *f; 146 struct fw_filter *f;
@@ -163,7 +164,7 @@ static void fw_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
163} 164}
164 165
165static int fw_delete(struct tcf_proto *tp, void *arg, bool *last, 166static int fw_delete(struct tcf_proto *tp, void *arg, bool *last,
166 struct netlink_ext_ack *extack) 167 bool rtnl_held, struct netlink_ext_ack *extack)
167{ 168{
168 struct fw_head *head = rtnl_dereference(tp->root); 169 struct fw_head *head = rtnl_dereference(tp->root);
169 struct fw_filter *f = arg; 170 struct fw_filter *f = arg;
@@ -250,7 +251,8 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
250static int fw_change(struct net *net, struct sk_buff *in_skb, 251static int fw_change(struct net *net, struct sk_buff *in_skb,
251 struct tcf_proto *tp, unsigned long base, 252 struct tcf_proto *tp, unsigned long base,
252 u32 handle, struct nlattr **tca, void **arg, 253 u32 handle, struct nlattr **tca, void **arg,
253 bool ovr, struct netlink_ext_ack *extack) 254 bool ovr, bool rtnl_held,
255 struct netlink_ext_ack *extack)
254{ 256{
255 struct fw_head *head = rtnl_dereference(tp->root); 257 struct fw_head *head = rtnl_dereference(tp->root);
256 struct fw_filter *f = *arg; 258 struct fw_filter *f = *arg;
@@ -354,7 +356,8 @@ errout:
354 return err; 356 return err;
355} 357}
356 358
357static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) 359static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg,
360 bool rtnl_held)
358{ 361{
359 struct fw_head *head = rtnl_dereference(tp->root); 362 struct fw_head *head = rtnl_dereference(tp->root);
360 int h; 363 int h;
@@ -384,7 +387,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
384} 387}
385 388
386static int fw_dump(struct net *net, struct tcf_proto *tp, void *fh, 389static int fw_dump(struct net *net, struct tcf_proto *tp, void *fh,
387 struct sk_buff *skb, struct tcmsg *t) 390 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
388{ 391{
389 struct fw_head *head = rtnl_dereference(tp->root); 392 struct fw_head *head = rtnl_dereference(tp->root);
390 struct fw_filter *f = fh; 393 struct fw_filter *f = fh;
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 8848a147c4bf..a37137430e61 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -109,7 +109,8 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
109 return 0; 109 return 0;
110} 110}
111 111
112static void mall_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 112static void mall_destroy(struct tcf_proto *tp, bool rtnl_held,
113 struct netlink_ext_ack *extack)
113{ 114{
114 struct cls_mall_head *head = rtnl_dereference(tp->root); 115 struct cls_mall_head *head = rtnl_dereference(tp->root);
115 116
@@ -160,7 +161,8 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
160static int mall_change(struct net *net, struct sk_buff *in_skb, 161static int mall_change(struct net *net, struct sk_buff *in_skb,
161 struct tcf_proto *tp, unsigned long base, 162 struct tcf_proto *tp, unsigned long base,
162 u32 handle, struct nlattr **tca, 163 u32 handle, struct nlattr **tca,
163 void **arg, bool ovr, struct netlink_ext_ack *extack) 164 void **arg, bool ovr, bool rtnl_held,
165 struct netlink_ext_ack *extack)
164{ 166{
165 struct cls_mall_head *head = rtnl_dereference(tp->root); 167 struct cls_mall_head *head = rtnl_dereference(tp->root);
166 struct nlattr *tb[TCA_MATCHALL_MAX + 1]; 168 struct nlattr *tb[TCA_MATCHALL_MAX + 1];
@@ -233,12 +235,13 @@ err_exts_init:
233} 235}
234 236
235static int mall_delete(struct tcf_proto *tp, void *arg, bool *last, 237static int mall_delete(struct tcf_proto *tp, void *arg, bool *last,
236 struct netlink_ext_ack *extack) 238 bool rtnl_held, struct netlink_ext_ack *extack)
237{ 239{
238 return -EOPNOTSUPP; 240 return -EOPNOTSUPP;
239} 241}
240 242
241static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg) 243static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg,
244 bool rtnl_held)
242{ 245{
243 struct cls_mall_head *head = rtnl_dereference(tp->root); 246 struct cls_mall_head *head = rtnl_dereference(tp->root);
244 247
@@ -280,7 +283,7 @@ static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
280} 283}
281 284
282static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh, 285static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh,
283 struct sk_buff *skb, struct tcmsg *t) 286 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
284{ 287{
285 struct tc_matchall_pcnt gpf = {}; 288 struct tc_matchall_pcnt gpf = {};
286 struct cls_mall_head *head = fh; 289 struct cls_mall_head *head = fh;
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 44b26038c4c4..e590c3a2999d 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -276,7 +276,8 @@ static void route4_queue_work(struct route4_filter *f)
276 tcf_queue_work(&f->rwork, route4_delete_filter_work); 276 tcf_queue_work(&f->rwork, route4_delete_filter_work);
277} 277}
278 278
279static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 279static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
280 struct netlink_ext_ack *extack)
280{ 281{
281 struct route4_head *head = rtnl_dereference(tp->root); 282 struct route4_head *head = rtnl_dereference(tp->root);
282 int h1, h2; 283 int h1, h2;
@@ -312,7 +313,7 @@ static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
312} 313}
313 314
314static int route4_delete(struct tcf_proto *tp, void *arg, bool *last, 315static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
315 struct netlink_ext_ack *extack) 316 bool rtnl_held, struct netlink_ext_ack *extack)
316{ 317{
317 struct route4_head *head = rtnl_dereference(tp->root); 318 struct route4_head *head = rtnl_dereference(tp->root);
318 struct route4_filter *f = arg; 319 struct route4_filter *f = arg;
@@ -468,7 +469,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
468static int route4_change(struct net *net, struct sk_buff *in_skb, 469static int route4_change(struct net *net, struct sk_buff *in_skb,
469 struct tcf_proto *tp, unsigned long base, u32 handle, 470 struct tcf_proto *tp, unsigned long base, u32 handle,
470 struct nlattr **tca, void **arg, bool ovr, 471 struct nlattr **tca, void **arg, bool ovr,
471 struct netlink_ext_ack *extack) 472 bool rtnl_held, struct netlink_ext_ack *extack)
472{ 473{
473 struct route4_head *head = rtnl_dereference(tp->root); 474 struct route4_head *head = rtnl_dereference(tp->root);
474 struct route4_filter __rcu **fp; 475 struct route4_filter __rcu **fp;
@@ -560,7 +561,8 @@ errout:
560 return err; 561 return err;
561} 562}
562 563
563static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) 564static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg,
565 bool rtnl_held)
564{ 566{
565 struct route4_head *head = rtnl_dereference(tp->root); 567 struct route4_head *head = rtnl_dereference(tp->root);
566 unsigned int h, h1; 568 unsigned int h, h1;
@@ -597,7 +599,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg)
597} 599}
598 600
599static int route4_dump(struct net *net, struct tcf_proto *tp, void *fh, 601static int route4_dump(struct net *net, struct tcf_proto *tp, void *fh,
600 struct sk_buff *skb, struct tcmsg *t) 602 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
601{ 603{
602 struct route4_filter *f = fh; 604 struct route4_filter *f = fh;
603 struct nlattr *nest; 605 struct nlattr *nest;
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 9dd9530e6a52..4d3836178fa5 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -312,7 +312,8 @@ static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
312 __rsvp_delete_filter(f); 312 __rsvp_delete_filter(f);
313} 313}
314 314
315static void rsvp_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 315static void rsvp_destroy(struct tcf_proto *tp, bool rtnl_held,
316 struct netlink_ext_ack *extack)
316{ 317{
317 struct rsvp_head *data = rtnl_dereference(tp->root); 318 struct rsvp_head *data = rtnl_dereference(tp->root);
318 int h1, h2; 319 int h1, h2;
@@ -341,7 +342,7 @@ static void rsvp_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
341} 342}
342 343
343static int rsvp_delete(struct tcf_proto *tp, void *arg, bool *last, 344static int rsvp_delete(struct tcf_proto *tp, void *arg, bool *last,
344 struct netlink_ext_ack *extack) 345 bool rtnl_held, struct netlink_ext_ack *extack)
345{ 346{
346 struct rsvp_head *head = rtnl_dereference(tp->root); 347 struct rsvp_head *head = rtnl_dereference(tp->root);
347 struct rsvp_filter *nfp, *f = arg; 348 struct rsvp_filter *nfp, *f = arg;
@@ -477,7 +478,8 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
477 struct tcf_proto *tp, unsigned long base, 478 struct tcf_proto *tp, unsigned long base,
478 u32 handle, 479 u32 handle,
479 struct nlattr **tca, 480 struct nlattr **tca,
480 void **arg, bool ovr, struct netlink_ext_ack *extack) 481 void **arg, bool ovr, bool rtnl_held,
482 struct netlink_ext_ack *extack)
481{ 483{
482 struct rsvp_head *data = rtnl_dereference(tp->root); 484 struct rsvp_head *data = rtnl_dereference(tp->root);
483 struct rsvp_filter *f, *nfp; 485 struct rsvp_filter *f, *nfp;
@@ -655,7 +657,8 @@ errout2:
655 return err; 657 return err;
656} 658}
657 659
658static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) 660static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg,
661 bool rtnl_held)
659{ 662{
660 struct rsvp_head *head = rtnl_dereference(tp->root); 663 struct rsvp_head *head = rtnl_dereference(tp->root);
661 unsigned int h, h1; 664 unsigned int h, h1;
@@ -689,7 +692,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
689} 692}
690 693
691static int rsvp_dump(struct net *net, struct tcf_proto *tp, void *fh, 694static int rsvp_dump(struct net *net, struct tcf_proto *tp, void *fh,
692 struct sk_buff *skb, struct tcmsg *t) 695 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
693{ 696{
694 struct rsvp_filter *f = fh; 697 struct rsvp_filter *f = fh;
695 struct rsvp_session *s; 698 struct rsvp_session *s;
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index b7dc667b6ec0..14d6b4058045 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -173,7 +173,7 @@ static void tcindex_destroy_fexts_work(struct work_struct *work)
173} 173}
174 174
175static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last, 175static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last,
176 struct netlink_ext_ack *extack) 176 bool rtnl_held, struct netlink_ext_ack *extack)
177{ 177{
178 struct tcindex_data *p = rtnl_dereference(tp->root); 178 struct tcindex_data *p = rtnl_dereference(tp->root);
179 struct tcindex_filter_result *r = arg; 179 struct tcindex_filter_result *r = arg;
@@ -226,7 +226,7 @@ static int tcindex_destroy_element(struct tcf_proto *tp,
226{ 226{
227 bool last; 227 bool last;
228 228
229 return tcindex_delete(tp, arg, &last, NULL); 229 return tcindex_delete(tp, arg, &last, false, NULL);
230} 230}
231 231
232static void __tcindex_destroy(struct rcu_head *head) 232static void __tcindex_destroy(struct rcu_head *head)
@@ -499,7 +499,7 @@ static int
499tcindex_change(struct net *net, struct sk_buff *in_skb, 499tcindex_change(struct net *net, struct sk_buff *in_skb,
500 struct tcf_proto *tp, unsigned long base, u32 handle, 500 struct tcf_proto *tp, unsigned long base, u32 handle,
501 struct nlattr **tca, void **arg, bool ovr, 501 struct nlattr **tca, void **arg, bool ovr,
502 struct netlink_ext_ack *extack) 502 bool rtnl_held, struct netlink_ext_ack *extack)
503{ 503{
504 struct nlattr *opt = tca[TCA_OPTIONS]; 504 struct nlattr *opt = tca[TCA_OPTIONS];
505 struct nlattr *tb[TCA_TCINDEX_MAX + 1]; 505 struct nlattr *tb[TCA_TCINDEX_MAX + 1];
@@ -522,7 +522,8 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
522 tca[TCA_RATE], ovr, extack); 522 tca[TCA_RATE], ovr, extack);
523} 523}
524 524
525static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker) 525static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker,
526 bool rtnl_held)
526{ 527{
527 struct tcindex_data *p = rtnl_dereference(tp->root); 528 struct tcindex_data *p = rtnl_dereference(tp->root);
528 struct tcindex_filter *f, *next; 529 struct tcindex_filter *f, *next;
@@ -558,7 +559,7 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
558 } 559 }
559} 560}
560 561
561static void tcindex_destroy(struct tcf_proto *tp, 562static void tcindex_destroy(struct tcf_proto *tp, bool rtnl_held,
562 struct netlink_ext_ack *extack) 563 struct netlink_ext_ack *extack)
563{ 564{
564 struct tcindex_data *p = rtnl_dereference(tp->root); 565 struct tcindex_data *p = rtnl_dereference(tp->root);
@@ -568,14 +569,14 @@ static void tcindex_destroy(struct tcf_proto *tp,
568 walker.count = 0; 569 walker.count = 0;
569 walker.skip = 0; 570 walker.skip = 0;
570 walker.fn = tcindex_destroy_element; 571 walker.fn = tcindex_destroy_element;
571 tcindex_walk(tp, &walker); 572 tcindex_walk(tp, &walker, true);
572 573
573 call_rcu(&p->rcu, __tcindex_destroy); 574 call_rcu(&p->rcu, __tcindex_destroy);
574} 575}
575 576
576 577
577static int tcindex_dump(struct net *net, struct tcf_proto *tp, void *fh, 578static int tcindex_dump(struct net *net, struct tcf_proto *tp, void *fh,
578 struct sk_buff *skb, struct tcmsg *t) 579 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
579{ 580{
580 struct tcindex_data *p = rtnl_dereference(tp->root); 581 struct tcindex_data *p = rtnl_dereference(tp->root);
581 struct tcindex_filter_result *r = fh; 582 struct tcindex_filter_result *r = fh;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index e891f30d42e9..27d29c04dcc9 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -629,7 +629,8 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
629 return -ENOENT; 629 return -ENOENT;
630} 630}
631 631
632static void u32_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) 632static void u32_destroy(struct tcf_proto *tp, bool rtnl_held,
633 struct netlink_ext_ack *extack)
633{ 634{
634 struct tc_u_common *tp_c = tp->data; 635 struct tc_u_common *tp_c = tp->data;
635 struct tc_u_hnode *root_ht = rtnl_dereference(tp->root); 636 struct tc_u_hnode *root_ht = rtnl_dereference(tp->root);
@@ -663,7 +664,7 @@ static void u32_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
663} 664}
664 665
665static int u32_delete(struct tcf_proto *tp, void *arg, bool *last, 666static int u32_delete(struct tcf_proto *tp, void *arg, bool *last,
666 struct netlink_ext_ack *extack) 667 bool rtnl_held, struct netlink_ext_ack *extack)
667{ 668{
668 struct tc_u_hnode *ht = arg; 669 struct tc_u_hnode *ht = arg;
669 struct tc_u_common *tp_c = tp->data; 670 struct tc_u_common *tp_c = tp->data;
@@ -858,7 +859,7 @@ static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp,
858 859
859static int u32_change(struct net *net, struct sk_buff *in_skb, 860static int u32_change(struct net *net, struct sk_buff *in_skb,
860 struct tcf_proto *tp, unsigned long base, u32 handle, 861 struct tcf_proto *tp, unsigned long base, u32 handle,
861 struct nlattr **tca, void **arg, bool ovr, 862 struct nlattr **tca, void **arg, bool ovr, bool rtnl_held,
862 struct netlink_ext_ack *extack) 863 struct netlink_ext_ack *extack)
863{ 864{
864 struct tc_u_common *tp_c = tp->data; 865 struct tc_u_common *tp_c = tp->data;
@@ -1123,7 +1124,8 @@ erridr:
1123 return err; 1124 return err;
1124} 1125}
1125 1126
1126static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg) 1127static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg,
1128 bool rtnl_held)
1127{ 1129{
1128 struct tc_u_common *tp_c = tp->data; 1130 struct tc_u_common *tp_c = tp->data;
1129 struct tc_u_hnode *ht; 1131 struct tc_u_hnode *ht;
@@ -1281,7 +1283,7 @@ static void u32_bind_class(void *fh, u32 classid, unsigned long cl)
1281} 1283}
1282 1284
1283static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh, 1285static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh,
1284 struct sk_buff *skb, struct tcmsg *t) 1286 struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
1285{ 1287{
1286 struct tc_u_knode *n = fh; 1288 struct tc_u_knode *n = fh;
1287 struct tc_u_hnode *ht_up, *ht_down; 1289 struct tc_u_hnode *ht_up, *ht_down;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 9a530cad2759..2283924fb56d 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1914,14 +1914,14 @@ static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid,
1914 chain = tcf_get_next_chain(block, chain)) { 1914 chain = tcf_get_next_chain(block, chain)) {
1915 struct tcf_proto *tp; 1915 struct tcf_proto *tp;
1916 1916
1917 for (tp = tcf_get_next_proto(chain, NULL); 1917 for (tp = tcf_get_next_proto(chain, NULL, true);
1918 tp; tp = tcf_get_next_proto(chain, tp)) { 1918 tp; tp = tcf_get_next_proto(chain, tp, true)) {
1919 struct tcf_bind_args arg = {}; 1919 struct tcf_bind_args arg = {};
1920 1920
1921 arg.w.fn = tcf_node_bind; 1921 arg.w.fn = tcf_node_bind;
1922 arg.classid = clid; 1922 arg.classid = clid;
1923 arg.cl = new_cl; 1923 arg.cl = new_cl;
1924 tp->ops->walk(tp, &arg.w); 1924 tp->ops->walk(tp, &arg.w, true);
1925 } 1925 }
1926 } 1926 }
1927} 1927}