Commit 12db03b6 authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller

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: default avatarVlad Buslov <vladbu@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d5509fa
...@@ -47,7 +47,7 @@ void tcf_chain_put_by_act(struct tcf_chain *chain); ...@@ -47,7 +47,7 @@ void tcf_chain_put_by_act(struct tcf_chain *chain);
struct tcf_chain *tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *tcf_get_next_chain(struct tcf_block *block,
struct tcf_chain *chain); struct tcf_chain *chain);
struct tcf_proto *tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tcf_get_next_proto(struct tcf_chain *chain,
struct tcf_proto *tp); struct tcf_proto *tp, bool rtnl_held);
void tcf_block_netif_keep_dst(struct tcf_block *block); void tcf_block_netif_keep_dst(struct tcf_block *block);
int tcf_block_get(struct tcf_block **p_block, int tcf_block_get(struct tcf_block **p_block,
struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q, struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
......
...@@ -273,7 +273,7 @@ struct tcf_proto_ops { ...@@ -273,7 +273,7 @@ struct tcf_proto_ops {
const struct tcf_proto *, const struct tcf_proto *,
struct tcf_result *); struct tcf_result *);
int (*init)(struct tcf_proto*); int (*init)(struct tcf_proto*);
void (*destroy)(struct tcf_proto *tp, void (*destroy)(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
void* (*get)(struct tcf_proto*, u32 handle); void* (*get)(struct tcf_proto*, u32 handle);
...@@ -281,12 +281,13 @@ struct tcf_proto_ops { ...@@ -281,12 +281,13 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *, int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long, struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **, u32 handle, struct nlattr **,
void **, bool, void **, bool, bool,
struct netlink_ext_ack *); struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg, int (*delete)(struct tcf_proto *tp, void *arg,
bool *last, bool *last, bool rtnl_held,
struct netlink_ext_ack *); struct netlink_ext_ack *);
void (*walk)(struct tcf_proto*, struct tcf_walker *arg); void (*walk)(struct tcf_proto *tp,
struct tcf_walker *arg, bool rtnl_held);
int (*reoffload)(struct tcf_proto *tp, bool add, int (*reoffload)(struct tcf_proto *tp, bool add,
tc_setup_cb_t *cb, void *cb_priv, tc_setup_cb_t *cb, void *cb_priv,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
...@@ -299,12 +300,18 @@ struct tcf_proto_ops { ...@@ -299,12 +300,18 @@ struct tcf_proto_ops {
/* rtnetlink specific */ /* rtnetlink specific */
int (*dump)(struct net*, struct tcf_proto*, void *, int (*dump)(struct net*, struct tcf_proto*, void *,
struct sk_buff *skb, struct tcmsg*); struct sk_buff *skb, struct tcmsg*,
bool);
int (*tmplt_dump)(struct sk_buff *skb, int (*tmplt_dump)(struct sk_buff *skb,
struct net *net, struct net *net,
void *tmplt_priv); void *tmplt_priv);
struct module *owner; struct module *owner;
int flags;
};
enum tcf_proto_ops_flags {
TCF_PROTO_OPS_DOIT_UNLOCKED = 1,
}; };
struct tcf_proto { struct tcf_proto {
......
This diff is collapsed.
...@@ -107,7 +107,8 @@ static void basic_delete_filter_work(struct work_struct *work) ...@@ -107,7 +107,8 @@ static void basic_delete_filter_work(struct work_struct *work)
rtnl_unlock(); rtnl_unlock();
} }
static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void basic_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct basic_head *head = rtnl_dereference(tp->root); struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f, *n; struct basic_filter *f, *n;
...@@ -126,7 +127,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) ...@@ -126,7 +127,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
} }
static int basic_delete(struct tcf_proto *tp, void *arg, bool *last, static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct basic_head *head = rtnl_dereference(tp->root); struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f = arg; struct basic_filter *f = arg;
...@@ -173,7 +174,7 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -173,7 +174,7 @@ static int basic_set_parms(struct net *net, struct tcf_proto *tp,
static int basic_change(struct net *net, struct sk_buff *in_skb, static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg, bool ovr,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
int err; int err;
struct basic_head *head = rtnl_dereference(tp->root); struct basic_head *head = rtnl_dereference(tp->root);
...@@ -247,7 +248,8 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, ...@@ -247,7 +248,8 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct basic_head *head = rtnl_dereference(tp->root); struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f; struct basic_filter *f;
...@@ -274,7 +276,7 @@ static void basic_bind_class(void *fh, u32 classid, unsigned long cl) ...@@ -274,7 +276,7 @@ static void basic_bind_class(void *fh, u32 classid, unsigned long cl)
} }
static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh, static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct tc_basic_pcnt gpf = {}; struct tc_basic_pcnt gpf = {};
struct basic_filter *f = fh; struct basic_filter *f = fh;
......
...@@ -298,7 +298,7 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog, ...@@ -298,7 +298,7 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog,
} }
static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last, static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct cls_bpf_head *head = rtnl_dereference(tp->root); struct cls_bpf_head *head = rtnl_dereference(tp->root);
...@@ -307,7 +307,7 @@ static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last, ...@@ -307,7 +307,7 @@ static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
return 0; return 0;
} }
static void cls_bpf_destroy(struct tcf_proto *tp, static void cls_bpf_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct cls_bpf_head *head = rtnl_dereference(tp->root); 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, ...@@ -456,7 +456,8 @@ static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, struct netlink_ext_ack *extack) void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct cls_bpf_head *head = rtnl_dereference(tp->root); struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *oldprog = *arg; struct cls_bpf_prog *oldprog = *arg;
...@@ -576,7 +577,7 @@ static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog, ...@@ -576,7 +577,7 @@ static int cls_bpf_dump_ebpf_info(const struct cls_bpf_prog *prog,
} }
static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, void *fh, static int cls_bpf_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *tm) struct sk_buff *skb, struct tcmsg *tm, bool rtnl_held)
{ {
struct cls_bpf_prog *prog = fh; struct cls_bpf_prog *prog = fh;
struct nlattr *nest; struct nlattr *nest;
...@@ -636,7 +637,8 @@ static void cls_bpf_bind_class(void *fh, u32 classid, unsigned long cl) ...@@ -636,7 +637,8 @@ static void cls_bpf_bind_class(void *fh, u32 classid, unsigned long cl)
prog->res.class = cl; prog->res.class = cl;
} }
static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void cls_bpf_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct cls_bpf_head *head = rtnl_dereference(tp->root); struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *prog; struct cls_bpf_prog *prog;
......
...@@ -78,7 +78,7 @@ static void cls_cgroup_destroy_work(struct work_struct *work) ...@@ -78,7 +78,7 @@ static void cls_cgroup_destroy_work(struct work_struct *work)
static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct nlattr *tb[TCA_CGROUP_MAX + 1]; struct nlattr *tb[TCA_CGROUP_MAX + 1];
...@@ -130,7 +130,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb, ...@@ -130,7 +130,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
static void cls_cgroup_destroy(struct tcf_proto *tp, static void cls_cgroup_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct cls_cgroup_head *head = rtnl_dereference(tp->root); struct cls_cgroup_head *head = rtnl_dereference(tp->root);
...@@ -145,12 +145,13 @@ static void cls_cgroup_destroy(struct tcf_proto *tp, ...@@ -145,12 +145,13 @@ static void cls_cgroup_destroy(struct tcf_proto *tp,
} }
static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last, static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct cls_cgroup_head *head = rtnl_dereference(tp->root); struct cls_cgroup_head *head = rtnl_dereference(tp->root);
...@@ -166,7 +167,7 @@ static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg) ...@@ -166,7 +167,7 @@ static void cls_cgroup_walk(struct tcf_proto *tp, struct tcf_walker *arg)
} }
static int cls_cgroup_dump(struct net *net, struct tcf_proto *tp, void *fh, static int cls_cgroup_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct cls_cgroup_head *head = rtnl_dereference(tp->root); struct cls_cgroup_head *head = rtnl_dereference(tp->root);
struct nlattr *nest; struct nlattr *nest;
......
...@@ -391,7 +391,8 @@ static void flow_destroy_filter_work(struct work_struct *work) ...@@ -391,7 +391,8 @@ static void flow_destroy_filter_work(struct work_struct *work)
static int flow_change(struct net *net, struct sk_buff *in_skb, static int flow_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, struct netlink_ext_ack *extack) void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct flow_head *head = rtnl_dereference(tp->root); struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *fold, *fnew; struct flow_filter *fold, *fnew;
...@@ -566,7 +567,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb, ...@@ -566,7 +567,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
} }
static int flow_delete(struct tcf_proto *tp, void *arg, bool *last, static int flow_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct flow_head *head = rtnl_dereference(tp->root); struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f = arg; struct flow_filter *f = arg;
...@@ -590,7 +591,8 @@ static int flow_init(struct tcf_proto *tp) ...@@ -590,7 +591,8 @@ static int flow_init(struct tcf_proto *tp)
return 0; return 0;
} }
static void flow_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void flow_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct flow_head *head = rtnl_dereference(tp->root); struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f, *next; struct flow_filter *f, *next;
...@@ -617,7 +619,7 @@ static void *flow_get(struct tcf_proto *tp, u32 handle) ...@@ -617,7 +619,7 @@ static void *flow_get(struct tcf_proto *tp, u32 handle)
} }
static int flow_dump(struct net *net, struct tcf_proto *tp, void *fh, static int flow_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct flow_filter *f = fh; struct flow_filter *f = fh;
struct nlattr *nest; struct nlattr *nest;
...@@ -677,7 +679,8 @@ static int flow_dump(struct net *net, struct tcf_proto *tp, void *fh, ...@@ -677,7 +679,8 @@ static int flow_dump(struct net *net, struct tcf_proto *tp, void *fh,
return -1; return -1;
} }
static void flow_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void flow_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct flow_head *head = rtnl_dereference(tp->root); struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f; struct flow_filter *f;
......
...@@ -465,7 +465,8 @@ static void fl_destroy_sleepable(struct work_struct *work) ...@@ -465,7 +465,8 @@ static void fl_destroy_sleepable(struct work_struct *work)
module_put(THIS_MODULE); module_put(THIS_MODULE);
} }
static void fl_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void fl_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct cls_fl_head *head = rtnl_dereference(tp->root); struct cls_fl_head *head = rtnl_dereference(tp->root);
struct fl_flow_mask *mask, *next_mask; struct fl_flow_mask *mask, *next_mask;
...@@ -1300,7 +1301,8 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -1300,7 +1301,8 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp,
static int fl_change(struct net *net, struct sk_buff *in_skb, static int fl_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, struct netlink_ext_ack *extack) void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct cls_fl_head *head = rtnl_dereference(tp->root); struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *fold = *arg; struct cls_fl_filter *fold = *arg;
...@@ -1437,7 +1439,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, ...@@ -1437,7 +1439,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
} }
static int fl_delete(struct tcf_proto *tp, void *arg, bool *last, static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct cls_fl_head *head = rtnl_dereference(tp->root); struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f = arg; struct cls_fl_filter *f = arg;
...@@ -1449,7 +1451,8 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last, ...@@ -1449,7 +1451,8 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
return 0; return 0;
} }
static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void fl_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct cls_fl_head *head = rtnl_dereference(tp->root); struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f; struct cls_fl_filter *f;
...@@ -2044,7 +2047,7 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net, ...@@ -2044,7 +2047,7 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
} }
static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh, static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct cls_fl_filter *f = fh; struct cls_fl_filter *f = fh;
struct nlattr *nest; struct nlattr *nest;
......
...@@ -139,7 +139,8 @@ static void fw_delete_filter_work(struct work_struct *work) ...@@ -139,7 +139,8 @@ static void fw_delete_filter_work(struct work_struct *work)
rtnl_unlock(); rtnl_unlock();
} }
static void fw_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void fw_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
struct fw_filter *f; struct fw_filter *f;
...@@ -163,7 +164,7 @@ static void fw_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) ...@@ -163,7 +164,7 @@ static void fw_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
} }
static int fw_delete(struct tcf_proto *tp, void *arg, bool *last, static int fw_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
struct fw_filter *f = arg; struct fw_filter *f = arg;
...@@ -250,7 +251,8 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -250,7 +251,8 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
static int fw_change(struct net *net, struct sk_buff *in_skb, static int fw_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, void **arg, u32 handle, struct nlattr **tca, void **arg,
bool ovr, struct netlink_ext_ack *extack) bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
struct fw_filter *f = *arg; struct fw_filter *f = *arg;
...@@ -354,7 +356,8 @@ static int fw_change(struct net *net, struct sk_buff *in_skb, ...@@ -354,7 +356,8 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
int h; int h;
...@@ -384,7 +387,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) ...@@ -384,7 +387,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
} }
static int fw_dump(struct net *net, struct tcf_proto *tp, void *fh, static int fw_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct fw_head *head = rtnl_dereference(tp->root); struct fw_head *head = rtnl_dereference(tp->root);
struct fw_filter *f = fh; struct fw_filter *f = fh;
......
...@@ -109,7 +109,8 @@ static int mall_replace_hw_filter(struct tcf_proto *tp, ...@@ -109,7 +109,8 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
return 0; return 0;
} }
static void mall_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void mall_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct cls_mall_head *head = rtnl_dereference(tp->root); struct cls_mall_head *head = rtnl_dereference(tp->root);
...@@ -160,7 +161,8 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -160,7 +161,8 @@ static int mall_set_parms(struct net *net, struct tcf_proto *tp,
static int mall_change(struct net *net, struct sk_buff *in_skb, static int mall_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca, u32 handle, struct nlattr **tca,
void **arg, bool ovr, struct netlink_ext_ack *extack) void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct cls_mall_head *head = rtnl_dereference(tp->root); struct cls_mall_head *head = rtnl_dereference(tp->root);
struct nlattr *tb[TCA_MATCHALL_MAX + 1]; struct nlattr *tb[TCA_MATCHALL_MAX + 1];
...@@ -233,12 +235,13 @@ static int mall_change(struct net *net, struct sk_buff *in_skb, ...@@ -233,12 +235,13 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
} }
static int mall_delete(struct tcf_proto *tp, void *arg, bool *last, static int mall_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void mall_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct cls_mall_head *head = rtnl_dereference(tp->root); struct cls_mall_head *head = rtnl_dereference(tp->root);
...@@ -280,7 +283,7 @@ static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb, ...@@ -280,7 +283,7 @@ static int mall_reoffload(struct tcf_proto *tp, bool add, tc_setup_cb_t *cb,
} }
static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh, static int mall_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct tc_matchall_pcnt gpf = {}; struct tc_matchall_pcnt gpf = {};
struct cls_mall_head *head = fh; struct cls_mall_head *head = fh;
......
...@@ -276,7 +276,8 @@ static void route4_queue_work(struct route4_filter *f) ...@@ -276,7 +276,8 @@ static void route4_queue_work(struct route4_filter *f)
tcf_queue_work(&f->rwork, route4_delete_filter_work); tcf_queue_work(&f->rwork, route4_delete_filter_work);
} }
static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void route4_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct route4_head *head = rtnl_dereference(tp->root); struct route4_head *head = rtnl_dereference(tp->root);
int h1, h2; int h1, h2;
...@@ -312,7 +313,7 @@ static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) ...@@ -312,7 +313,7 @@ static void route4_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
} }
static int route4_delete(struct tcf_proto *tp, void *arg, bool *last, static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct route4_head *head = rtnl_dereference(tp->root); struct route4_head *head = rtnl_dereference(tp->root);
struct route4_filter *f = arg; struct route4_filter *f = arg;
...@@ -468,7 +469,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp, ...@@ -468,7 +469,7 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
static int route4_change(struct net *net, struct sk_buff *in_skb, static int route4_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg, bool ovr,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct route4_head *head = rtnl_dereference(tp->root); struct route4_head *head = rtnl_dereference(tp->root);
struct route4_filter __rcu **fp; struct route4_filter __rcu **fp;
...@@ -560,7 +561,8 @@ static int route4_change(struct net *net, struct sk_buff *in_skb, ...@@ -560,7 +561,8 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct route4_head *head = rtnl_dereference(tp->root); struct route4_head *head = rtnl_dereference(tp->root);
unsigned int h, h1; unsigned int h, h1;
...@@ -597,7 +599,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg) ...@@ -597,7 +599,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg)
} }
static int route4_dump(struct net *net, struct tcf_proto *tp, void *fh, static int route4_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct route4_filter *f = fh; struct route4_filter *f = fh;
struct nlattr *nest; struct nlattr *nest;
......
...@@ -312,7 +312,8 @@ static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f) ...@@ -312,7 +312,8 @@ static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
__rsvp_delete_filter(f); __rsvp_delete_filter(f);
} }
static void rsvp_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void rsvp_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct rsvp_head *data = rtnl_dereference(tp->root); struct rsvp_head *data = rtnl_dereference(tp->root);
int h1, h2; int h1, h2;
...@@ -341,7 +342,7 @@ static void rsvp_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) ...@@ -341,7 +342,7 @@ static void rsvp_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
} }
static int rsvp_delete(struct tcf_proto *tp, void *arg, bool *last, static int rsvp_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct rsvp_head *head = rtnl_dereference(tp->root); struct rsvp_head *head = rtnl_dereference(tp->root);
struct rsvp_filter *nfp, *f = arg; struct rsvp_filter *nfp, *f = arg;
...@@ -477,7 +478,8 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb, ...@@ -477,7 +478,8 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, struct tcf_proto *tp, unsigned long base,
u32 handle, u32 handle,
struct nlattr **tca, struct nlattr **tca,
void **arg, bool ovr, struct netlink_ext_ack *extack) void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct rsvp_head *data = rtnl_dereference(tp->root); struct rsvp_head *data = rtnl_dereference(tp->root);
struct rsvp_filter *f, *nfp; struct rsvp_filter *f, *nfp;
...@@ -655,7 +657,8 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb, ...@@ -655,7 +657,8 @@ static int rsvp_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct rsvp_head *head = rtnl_dereference(tp->root); struct rsvp_head *head = rtnl_dereference(tp->root);
unsigned int h, h1; unsigned int h, h1;
...@@ -689,7 +692,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg) ...@@ -689,7 +692,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
} }
static int rsvp_dump(struct net *net, struct tcf_proto *tp, void *fh, static int rsvp_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct rsvp_filter *f = fh; struct rsvp_filter *f = fh;
struct rsvp_session *s; struct rsvp_session *s;
......
...@@ -173,7 +173,7 @@ static void tcindex_destroy_fexts_work(struct work_struct *work) ...@@ -173,7 +173,7 @@ static void tcindex_destroy_fexts_work(struct work_struct *work)
} }
static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last, static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct tcindex_data *p = rtnl_dereference(tp->root); struct tcindex_data *p = rtnl_dereference(tp->root);
struct tcindex_filter_result *r = arg; struct tcindex_filter_result *r = arg;
...@@ -226,7 +226,7 @@ static int tcindex_destroy_element(struct tcf_proto *tp, ...@@ -226,7 +226,7 @@ static int tcindex_destroy_element(struct tcf_proto *tp,
{ {
bool last; bool last;
return tcindex_delete(tp, arg, &last, NULL); return tcindex_delete(tp, arg, &last, false, NULL);
} }
static void __tcindex_destroy(struct rcu_head *head) static void __tcindex_destroy(struct rcu_head *head)
...@@ -499,7 +499,7 @@ static int ...@@ -499,7 +499,7 @@ static int
tcindex_change(struct net *net, struct sk_buff *in_skb, tcindex_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg, bool ovr,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct nlattr *opt = tca[TCA_OPTIONS]; struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_TCINDEX_MAX + 1]; struct nlattr *tb[TCA_TCINDEX_MAX + 1];
...@@ -522,7 +522,8 @@ tcindex_change(struct net *net, struct sk_buff *in_skb, ...@@ -522,7 +522,8 @@ tcindex_change(struct net *net, struct sk_buff *in_skb,
tca[TCA_RATE], ovr, extack); tca[TCA_RATE], ovr, extack);
} }
static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker) static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker,
bool rtnl_held)
{ {
struct tcindex_data *p = rtnl_dereference(tp->root); struct tcindex_data *p = rtnl_dereference(tp->root);
struct tcindex_filter *f, *next; struct tcindex_filter *f, *next;
...@@ -558,7 +559,7 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker) ...@@ -558,7 +559,7 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
} }
} }
static void tcindex_destroy(struct tcf_proto *tp, static void tcindex_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tcindex_data *p = rtnl_dereference(tp->root); struct tcindex_data *p = rtnl_dereference(tp->root);
...@@ -568,14 +569,14 @@ static void tcindex_destroy(struct tcf_proto *tp, ...@@ -568,14 +569,14 @@ static void tcindex_destroy(struct tcf_proto *tp,
walker.count = 0; walker.count = 0;
walker.skip = 0; walker.skip = 0;
walker.fn = tcindex_destroy_element; walker.fn = tcindex_destroy_element;
tcindex_walk(tp, &walker); tcindex_walk(tp, &walker, true);
call_rcu(&p->rcu, __tcindex_destroy); call_rcu(&p->rcu, __tcindex_destroy);
} }
static int tcindex_dump(struct net *net, struct tcf_proto *tp, void *fh, static int tcindex_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct tcindex_data *p = rtnl_dereference(tp->root); struct tcindex_data *p = rtnl_dereference(tp->root);
struct tcindex_filter_result *r = fh; struct tcindex_filter_result *r = fh;
......
...@@ -629,7 +629,8 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht, ...@@ -629,7 +629,8 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
return -ENOENT; return -ENOENT;
} }
static void u32_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) static void u32_destroy(struct tcf_proto *tp, bool rtnl_held,
struct netlink_ext_ack *extack)
{ {
struct tc_u_common *tp_c = tp->data; struct tc_u_common *tp_c = tp->data;
struct tc_u_hnode *root_ht = rtnl_dereference(tp->root); 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,7 +664,7 @@ static void u32_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
} }
static int u32_delete(struct tcf_proto *tp, void *arg, bool *last, static int u32_delete(struct tcf_proto *tp, void *arg, bool *last,
struct netlink_ext_ack *extack) bool rtnl_held, struct netlink_ext_ack *extack)
{ {
struct tc_u_hnode *ht = arg; struct tc_u_hnode *ht = arg;
struct tc_u_common *tp_c = tp->data; 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,7 +859,7 @@ static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp,
static int u32_change(struct net *net, struct sk_buff *in_skb, static int u32_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle, struct tcf_proto *tp, unsigned long base, u32 handle,
struct nlattr **tca, void **arg, bool ovr, struct nlattr **tca, void **arg, bool ovr, bool rtnl_held,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct tc_u_common *tp_c = tp->data; struct tc_u_common *tp_c = tp->data;
...@@ -1123,7 +1124,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, ...@@ -1123,7 +1124,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
return err; return err;
} }
static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg) static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg,
bool rtnl_held)
{ {
struct tc_u_common *tp_c = tp->data; struct tc_u_common *tp_c = tp->data;
struct tc_u_hnode *ht; struct tc_u_hnode *ht;
...@@ -1281,7 +1283,7 @@ static void u32_bind_class(void *fh, u32 classid, unsigned long cl) ...@@ -1281,7 +1283,7 @@ static void u32_bind_class(void *fh, u32 classid, unsigned long cl)
} }
static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh, static int u32_dump(struct net *net, struct tcf_proto *tp, void *fh,
struct sk_buff *skb, struct tcmsg *t) struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
{ {
struct tc_u_knode *n = fh; struct tc_u_knode *n = fh;
struct tc_u_hnode *ht_up, *ht_down; struct tc_u_hnode *ht_up, *ht_down;
......
...@@ -1914,14 +1914,14 @@ static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid, ...@@ -1914,14 +1914,14 @@ static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid,
chain = tcf_get_next_chain(block, chain)) { chain = tcf_get_next_chain(block, chain)) {
struct tcf_proto *tp; struct tcf_proto *tp;
for (tp = tcf_get_next_proto(chain, NULL); for (tp = tcf_get_next_proto(chain, NULL, true);
tp; tp = tcf_get_next_proto(chain, tp)) { tp; tp = tcf_get_next_proto(chain, tp, true)) {
struct tcf_bind_args arg = {}; struct tcf_bind_args arg = {};
arg.w.fn = tcf_node_bind; arg.w.fn = tcf_node_bind;
arg.classid = clid; arg.classid = clid;
arg.cl = new_cl; arg.cl = new_cl;
tp->ops->walk(tp, &arg.w); tp->ops->walk(tp, &arg.w, true);
} }
} }
} }
......
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