net: sched: implement unlocked action init API
authorVlad Buslov <vladbu@mellanox.com>
Thu, 5 Jul 2018 14:24:25 +0000 (17:24 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 8 Jul 2018 03:42:28 +0000 (12:42 +0900)
Add additional 'rtnl_held' argument to act API init functions. It is
required to implement actions that need to release rtnl lock before loading
kernel module and reacquire if afterwards.

Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
19 files changed:
include/net/act_api.h
net/sched/act_api.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c
net/sched/cls_api.c

index 2759226527a22b391568046e57a5acd4ebe598de..27823f4e24c4bfc530d32dc29ef58aad878a732e 100644 (file)
@@ -92,7 +92,8 @@ struct tc_action_ops {
                          struct netlink_ext_ack *extack);
        int     (*init)(struct net *net, struct nlattr *nla,
                        struct nlattr *est, struct tc_action **act, int ovr,
-                       int bind, struct netlink_ext_ack *extack);
+                       int bind, bool rtnl_held,
+                       struct netlink_ext_ack *extack);
        int     (*walk)(struct net *, struct sk_buff *,
                        struct netlink_callback *, int,
                        const struct tc_action_ops *,
@@ -168,10 +169,11 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
                    struct nlattr *est, char *name, int ovr, int bind,
                    struct list_head *actions, size_t *attr_size,
-                   struct netlink_ext_ack *extack);
+                   bool rtnl_held, struct netlink_ext_ack *extack);
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
                                    struct nlattr *nla, struct nlattr *est,
                                    char *name, int ovr, int bind,
+                                   bool rtnl_held,
                                    struct netlink_ext_ack *extack);
 int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
 int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
index 4f064ecab882bc43076bb3f844bd900986a13669..256b0c93916c16d330a8b3ca646bf0a1c8594604 100644 (file)
@@ -671,6 +671,7 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
                                    struct nlattr *nla, struct nlattr *est,
                                    char *name, int ovr, int bind,
+                                   bool rtnl_held,
                                    struct netlink_ext_ack *extack)
 {
        struct tc_action *a;
@@ -721,9 +722,11 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
        a_o = tc_lookup_action_n(act_name);
        if (a_o == NULL) {
 #ifdef CONFIG_MODULES
-               rtnl_unlock();
+               if (rtnl_held)
+                       rtnl_unlock();
                request_module("act_%s", act_name);
-               rtnl_lock();
+               if (rtnl_held)
+                       rtnl_lock();
 
                a_o = tc_lookup_action_n(act_name);
 
@@ -746,9 +749,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
        /* backward compatibility for policer */
        if (name == NULL)
                err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
-                               extack);
+                               rtnl_held, extack);
        else
-               err = a_o->init(net, nla, est, &a, ovr, bind, extack);
+               err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
+                               extack);
        if (err < 0)
                goto err_mod;
 
@@ -800,7 +804,7 @@ static void cleanup_a(struct list_head *actions, int ovr)
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
                    struct nlattr *est, char *name, int ovr, int bind,
                    struct list_head *actions, size_t *attr_size,
-                   struct netlink_ext_ack *extack)
+                   bool rtnl_held, struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
        struct tc_action *act;
@@ -814,7 +818,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
 
        for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
                act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
-                                       extack);
+                                       rtnl_held, extack);
                if (IS_ERR(act)) {
                        err = PTR_ERR(act);
                        goto err;
@@ -1173,7 +1177,7 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
        LIST_HEAD(actions);
 
        ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, &actions,
-                             &attr_size, extack);
+                             &attr_size, true, extack);
        if (ret)
                return ret;
 
index 15a2a53cbde17b47b631eb33027141c1c1e71c48..8ebf40a3506c863fa774d090691e7e4db56d23a7 100644 (file)
@@ -276,7 +276,8 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
 
 static int tcf_bpf_init(struct net *net, struct nlattr *nla,
                        struct nlattr *est, struct tc_action **act,
-                       int replace, int bind, struct netlink_ext_ack *extack)
+                       int replace, int bind, bool rtnl_held,
+                       struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, bpf_net_id);
        struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
index 188865034f9a78d9e626ce90f1689b94e433cdb9..e3787aa0025a76730a0ee7593a0eac7b51f38721 100644 (file)
@@ -96,7 +96,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
 
 static int tcf_connmark_init(struct net *net, struct nlattr *nla,
                             struct nlattr *est, struct tc_action **a,
-                            int ovr, int bind,
+                            int ovr, int bind, bool rtnl_held,
                             struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, connmark_net_id);
index da865f7b390abc84c18e85ecf7475a936f89d593..334261943f9f44cc59752b09cd71e21bd3db71b1 100644 (file)
@@ -46,7 +46,8 @@ static struct tc_action_ops act_csum_ops;
 
 static int tcf_csum_init(struct net *net, struct nlattr *nla,
                         struct nlattr *est, struct tc_action **a, int ovr,
-                        int bind, struct netlink_ext_ack *extack)
+                        int bind, bool rtnl_held,
+                        struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, csum_net_id);
        struct tcf_csum_params *params_old, *params_new;
index ca83debd5a70095435a62a582deba2239c3e568e..b4dfb2b4addc7bad02334c849f0a325a0402116d 100644 (file)
@@ -56,7 +56,8 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
 
 static int tcf_gact_init(struct net *net, struct nlattr *nla,
                         struct nlattr *est, struct tc_action **a,
-                        int ovr, int bind, struct netlink_ext_ack *extack)
+                        int ovr, int bind, bool rtnl_held,
+                        struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, gact_net_id);
        struct nlattr *tb[TCA_GACT_MAX + 1];
index 3536a23f46b5f39c8440909c19e1757bae9390a5..576ffbba61c3bea5f7e6acd75e4129851a9cad8f 100644 (file)
@@ -448,7 +448,8 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
 
 static int tcf_ife_init(struct net *net, struct nlattr *nla,
                        struct nlattr *est, struct tc_action **a,
-                       int ovr, int bind, struct netlink_ext_ack *extack)
+                       int ovr, int bind, bool rtnl_held,
+                       struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, ife_net_id);
        struct nlattr *tb[TCA_IFE_MAX + 1];
index 7bce88dc11c907d3deb1612462a330f9916258eb..9c21663a86a612ef9aa7e9e67cb5311ae7b6e451 100644 (file)
@@ -196,7 +196,8 @@ err1:
 
 static int tcf_ipt_init(struct net *net, struct nlattr *nla,
                        struct nlattr *est, struct tc_action **a, int ovr,
-                       int bind, struct netlink_ext_ack *extack)
+                       int bind, bool rtnl_held,
+                       struct netlink_ext_ack *extack)
 {
        return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr,
                              bind);
@@ -204,7 +205,8 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla,
 
 static int tcf_xt_init(struct net *net, struct nlattr *nla,
                       struct nlattr *est, struct tc_action **a, int ovr,
-                      int bind, struct netlink_ext_ack *extack)
+                      int bind, bool unlocked,
+                      struct netlink_ext_ack *extack)
 {
        return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr,
                              bind);
index 82a8bdd67c47b3d4bf863ef0edcd4e9a905ca8f0..5434f08f2eb73539d0cd84efe680ba4cc5dcc42f 100644 (file)
@@ -68,8 +68,9 @@ static unsigned int mirred_net_id;
 static struct tc_action_ops act_mirred_ops;
 
 static int tcf_mirred_init(struct net *net, struct nlattr *nla,
-                          struct nlattr *est, struct tc_action **a, int ovr,
-                          int bind, struct netlink_ext_ack *extack)
+                          struct nlattr *est, struct tc_action **a,
+                          int ovr, int bind, bool rtnl_held,
+                          struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, mirred_net_id);
        struct nlattr *tb[TCA_MIRRED_MAX + 1];
index 457c2ae3de46e1fcd5b11fbbfe6723ddfc829084..e6487ad1e4a878c38af65eda026ef6283c3736ac 100644 (file)
@@ -38,7 +38,7 @@ static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
 
 static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
                        struct tc_action **a, int ovr, int bind,
-                       struct netlink_ext_ack *extack)
+                       bool rtnl_held, struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, nat_net_id);
        struct nlattr *tb[TCA_NAT_MAX + 1];
index 889690e0ec39de0fb35d4237f40523f3edbc27a2..f7965f35585b6a9d96223a9388e17878b5423761 100644 (file)
@@ -132,7 +132,8 @@ static int tcf_pedit_key_ex_dump(struct sk_buff *skb,
 
 static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                          struct nlattr *est, struct tc_action **a,
-                         int ovr, int bind, struct netlink_ext_ack *extack)
+                         int ovr, int bind, bool rtnl_held,
+                         struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, pedit_net_id);
        struct nlattr *tb[TCA_PEDIT_MAX + 1];
index a789b806096816851f865c744dbdd0e7571f62ea..0e1c2fb0ebeabb08182a37774317beb1e681ef83 100644 (file)
@@ -75,7 +75,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
 
 static int tcf_act_police_init(struct net *net, struct nlattr *nla,
                               struct nlattr *est, struct tc_action **a,
-                              int ovr, int bind,
+                              int ovr, int bind, bool rtnl_held,
                               struct netlink_ext_ack *extack)
 {
        int ret = 0, err;
index 4a46978db0924d47037f3084823d036088cdea71..316fc645595d2d91e7749e3ae1ea52b0915910bd 100644 (file)
@@ -37,7 +37,8 @@ static const struct nla_policy sample_policy[TCA_SAMPLE_MAX + 1] = {
 
 static int tcf_sample_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a, int ovr,
-                          int bind, struct netlink_ext_ack *extack)
+                          int bind, bool rtnl_held,
+                          struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, sample_net_id);
        struct nlattr *tb[TCA_SAMPLE_MAX + 1];
index c3a761097b01fa667e1f96297477971e912e1bc6..dc591cc87f4af8345a4598c0176606cabee51a3b 100644 (file)
@@ -79,7 +79,8 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
 
 static int tcf_simp_init(struct net *net, struct nlattr *nla,
                         struct nlattr *est, struct tc_action **a,
-                        int ovr, int bind, struct netlink_ext_ack *extack)
+                        int ovr, int bind, bool rtnl_held,
+                        struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, simp_net_id);
        struct nlattr *tb[TCA_DEF_MAX + 1];
index cfd20d3d2ca9c0da0780a5bd668667bd76d6d65e..c4ae4bd830aa722592549e581452ea2f3657bbb7 100644 (file)
@@ -94,7 +94,8 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                            struct nlattr *est, struct tc_action **a,
-                           int ovr, int bind, struct netlink_ext_ack *extack)
+                           int ovr, int bind, bool rtnl_held,
+                           struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, skbedit_net_id);
        struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
index ff90d720eda380decc324b4736dbd64fa0293c49..026d6f58eda1527af472e222eed858cfed9a9098 100644 (file)
@@ -84,7 +84,8 @@ static const struct nla_policy skbmod_policy[TCA_SKBMOD_MAX + 1] = {
 
 static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a,
-                          int ovr, int bind, struct netlink_ext_ack *extack)
+                          int ovr, int bind, bool rtnl_held,
+                          struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, skbmod_net_id);
        struct nlattr *tb[TCA_SKBMOD_MAX + 1];
index 2354f07eba1574e58937ee06a0ed5de8ff6388c3..15ea5ce0f9ed6df83b60cba99b51f9f107e726a2 100644 (file)
@@ -201,7 +201,8 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
 
 static int tunnel_key_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a,
-                          int ovr, int bind, struct netlink_ext_ack *extack)
+                          int ovr, int bind, bool rtnl_held,
+                          struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
        struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1];
index 799e3deb44ac43daa29d7f059c7b690a3e9cb762..c61775250722dd516efbe46799c4dfc807f0d472 100644 (file)
@@ -109,7 +109,8 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
 
 static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                         struct nlattr *est, struct tc_action **a,
-                        int ovr, int bind, struct netlink_ext_ack *extack)
+                        int ovr, int bind, bool rtnl_held,
+                        struct netlink_ext_ack *extack)
 {
        struct tc_action_net *tn = net_generic(net, vlan_net_id);
        struct nlattr *tb[TCA_VLAN_MAX + 1];
index bbf8dda96b0e65b46db4ba1429135c24c22227b2..ebc2b9dd783f86e97784182450ff1700373d404a 100644 (file)
@@ -1632,7 +1632,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
                if (exts->police && tb[exts->police]) {
                        act = tcf_action_init_1(net, tp, tb[exts->police],
                                                rate_tlv, "police", ovr,
-                                               TCA_ACT_BIND, extack);
+                                               TCA_ACT_BIND, true, extack);
                        if (IS_ERR(act))
                                return PTR_ERR(act);
 
@@ -1645,7 +1645,8 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
 
                        err = tcf_action_init(net, tp, tb[exts->action],
                                              rate_tlv, NULL, ovr, TCA_ACT_BIND,
-                                             &actions, &attr_size, extack);
+                                             &actions, &attr_size, true,
+                                             extack);
                        if (err)
                                return err;
                        list_for_each_entry(act, &actions, list)