act_ife: acquire ife_mod_lock before reading ifeoplist
authorWANG Cong <xiyou.wangcong@gmail.com>
Mon, 20 Jun 2016 20:37:19 +0000 (13:37 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 23 Jun 2016 16:02:36 +0000 (12:02 -0400)
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/act_ife.c

index e4076598f21466b40355c9d82449727a9bb17620..ea4a2fef1b71c506a89ca668c115db367aaa79a6 100644 (file)
@@ -277,7 +277,7 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
  * under ife->tcf_lock for existing action
 */
 static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
-                       int len, bool exists)
+                       int len, bool atomic)
 {
        struct tcf_meta_info *mi = NULL;
        struct tcf_meta_ops *ops = find_ife_oplist(metaid);
@@ -286,7 +286,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
        if (!ops)
                return -ENOENT;
 
-       mi = kzalloc(sizeof(*mi), exists ? GFP_ATOMIC : GFP_KERNEL);
+       mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL);
        if (!mi) {
                /*put back what find_ife_oplist took */
                module_put(ops->owner);
@@ -296,7 +296,7 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
        mi->metaid = metaid;
        mi->ops = ops;
        if (len > 0) {
-               ret = ops->alloc(mi, metaval, exists ? GFP_ATOMIC : GFP_KERNEL);
+               ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL);
                if (ret != 0) {
                        kfree(mi);
                        module_put(ops->owner);
@@ -309,17 +309,19 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
        return ret;
 }
 
-static int use_all_metadata(struct tcf_ife_info *ife, bool exists)
+static int use_all_metadata(struct tcf_ife_info *ife)
 {
        struct tcf_meta_ops *o;
        int rc = 0;
        int installed = 0;
 
+       read_lock(&ife_mod_lock);
        list_for_each_entry(o, &ifeoplist, list) {
-               rc = add_metainfo(ife, o->metaid, NULL, 0, exists);
+               rc = add_metainfo(ife, o->metaid, NULL, 0, true);
                if (rc == 0)
                        installed += 1;
        }
+       read_unlock(&ife_mod_lock);
 
        if (installed)
                return 0;
@@ -523,7 +525,7 @@ metadata_parse_err:
                 * as we can. You better have at least one else we are
                 * going to bail out
                 */
-               err = use_all_metadata(ife, exists);
+               err = use_all_metadata(ife);
                if (err) {
                        if (ret == ACT_P_CREATED)
                                _tcf_ife_cleanup(a, bind);