diff options
Diffstat (limited to 'backport')
-rw-r--r-- | backport/compat/backport-4.12.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/backport/compat/backport-4.12.c b/backport/compat/backport-4.12.c index 382a3af4..767ecb98 100644 --- a/backport/compat/backport-4.12.c +++ b/backport/compat/backport-4.12.c @@ -19,10 +19,14 @@ enum nlmsgerr_attrs { struct bp_extack_genl_family { struct genl_family family; struct genl_family *real_family; + struct list_head list; struct genl_ops ops[]; }; +static LIST_HEAD(copies_list); +static DEFINE_MUTEX(copies_mutex); + static const struct nla_policy extack_dummy_policy[1] = {}; static struct bp_extack_genl_family *get_copy(__genl_const struct genl_ops *op) @@ -212,25 +216,39 @@ int bp_extack_genl_register_family(struct genl_family *family) copy->family.pre_doit = extack_pre_doit; copy->family.post_doit = extack_post_doit; - /* - * store in attrbuf, so that even if we re-register the family - * the data will be overwritten and we don't overwrite data - * that's used again later... - */ - family->attrbuf = (void *)copy; - err = __real_bp_extack_genl_register_family(©->family); - if (err) + if (err) { kfree(copy); - return err; + return err; + } + + /* copy this since the family might access it directly */ + family->attrbuf = copy->family.attrbuf; + + mutex_lock(&copies_mutex); + list_add_tail(©->list, &copies_list); + mutex_unlock(&copies_mutex); + + return 0; } EXPORT_SYMBOL_GPL(bp_extack_genl_register_family); int bp_extack_genl_unregister_family(struct genl_family *family) { - struct bp_extack_genl_family *copy = (void *)family->attrbuf; + struct bp_extack_genl_family *tmp, *copy = NULL; int err; + mutex_lock(&copies_mutex); + list_for_each_entry(tmp, &copies_list, list) { + if (tmp->real_family == family) { + copy = tmp; + break; + } + } + if (copy) + list_del(©->list); + mutex_unlock(&copies_mutex); + if (!copy) return -ENOENT; |