|
@@ -341,22 +341,25 @@ int tcf_register_action(struct tc_action_ops *act,
|
|
if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
|
|
if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ /* We have to register pernet ops before making the action ops visible,
|
|
|
|
+ * otherwise tcf_action_init_1() could get a partially initialized
|
|
|
|
+ * netns.
|
|
|
|
+ */
|
|
|
|
+ ret = register_pernet_subsys(ops);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
write_lock(&act_mod_lock);
|
|
write_lock(&act_mod_lock);
|
|
list_for_each_entry(a, &act_base, head) {
|
|
list_for_each_entry(a, &act_base, head) {
|
|
if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
|
|
if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
|
|
write_unlock(&act_mod_lock);
|
|
write_unlock(&act_mod_lock);
|
|
|
|
+ unregister_pernet_subsys(ops);
|
|
return -EEXIST;
|
|
return -EEXIST;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
list_add_tail(&act->head, &act_base);
|
|
list_add_tail(&act->head, &act_base);
|
|
write_unlock(&act_mod_lock);
|
|
write_unlock(&act_mod_lock);
|
|
|
|
|
|
- ret = register_pernet_subsys(ops);
|
|
|
|
- if (ret) {
|
|
|
|
- tcf_unregister_action(act, ops);
|
|
|
|
- return ret;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(tcf_register_action);
|
|
EXPORT_SYMBOL(tcf_register_action);
|
|
@@ -367,8 +370,6 @@ int tcf_unregister_action(struct tc_action_ops *act,
|
|
struct tc_action_ops *a;
|
|
struct tc_action_ops *a;
|
|
int err = -ENOENT;
|
|
int err = -ENOENT;
|
|
|
|
|
|
- unregister_pernet_subsys(ops);
|
|
|
|
-
|
|
|
|
write_lock(&act_mod_lock);
|
|
write_lock(&act_mod_lock);
|
|
list_for_each_entry(a, &act_base, head) {
|
|
list_for_each_entry(a, &act_base, head) {
|
|
if (a == act) {
|
|
if (a == act) {
|
|
@@ -378,6 +379,8 @@ int tcf_unregister_action(struct tc_action_ops *act,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
write_unlock(&act_mod_lock);
|
|
write_unlock(&act_mod_lock);
|
|
|
|
+ if (!err)
|
|
|
|
+ unregister_pernet_subsys(ops);
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(tcf_unregister_action);
|
|
EXPORT_SYMBOL(tcf_unregister_action);
|