These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / netfilter / ipset / ip_set_core.c
index d259da3..54f3d7c 100644 (file)
@@ -32,8 +32,10 @@ static DEFINE_RWLOCK(ip_set_ref_lock);               /* protects the set refs */
 struct ip_set_net {
        struct ip_set * __rcu *ip_set_list;     /* all individual sets */
        ip_set_id_t     ip_set_max;     /* max number of sets */
-       int             is_deleted;     /* deleted by ip_set_net_exit */
+       bool            is_deleted;     /* deleted by ip_set_net_exit */
+       bool            is_destroyed;   /* all sets are destroyed */
 };
+
 static int ip_set_net_id __read_mostly;
 
 static inline struct ip_set_net *ip_set_pernet(struct net *net)
@@ -42,7 +44,7 @@ static inline struct ip_set_net *ip_set_pernet(struct net *net)
 }
 
 #define IP_SET_INC     64
-#define STREQ(a, b)    (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
+#define STRNCMP(a, b)  (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
 
 static unsigned int max_sets;
 
@@ -59,8 +61,7 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
 #define ip_set(inst, id)               \
        ip_set_dereference((inst)->ip_set_list)[id]
 
-/*
- * The set types are implemented in modules and registered set types
+/* The set types are implemented in modules and registered set types
  * can be found in ip_set_type_list. Adding/deleting types is
  * serialized by ip_set_type_mutex.
  */
@@ -85,7 +86,7 @@ find_set_type(const char *name, u8 family, u8 revision)
        struct ip_set_type *type;
 
        list_for_each_entry_rcu(type, &ip_set_type_list, list)
-               if (STREQ(type->name, name) &&
+               if (STRNCMP(type->name, name) &&
                    (type->family == family ||
                     type->family == NFPROTO_UNSPEC) &&
                    revision >= type->revision_min &&
@@ -130,9 +131,10 @@ __find_set_type_get(const char *name, u8 family, u8 revision,
                goto unlock;
        }
        /* Make sure the type is already loaded
-        * but we don't support the revision */
+        * but we don't support the revision
+        */
        list_for_each_entry_rcu(type, &ip_set_type_list, list)
-               if (STREQ(type->name, name)) {
+               if (STRNCMP(type->name, name)) {
                        err = -IPSET_ERR_FIND_TYPE;
                        goto unlock;
                }
@@ -166,7 +168,7 @@ __find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
        *min = 255; *max = 0;
        rcu_read_lock();
        list_for_each_entry_rcu(type, &ip_set_type_list, list)
-               if (STREQ(type->name, name) &&
+               if (STRNCMP(type->name, name) &&
                    (type->family == family ||
                     type->family == NFPROTO_UNSPEC)) {
                        found = true;
@@ -208,15 +210,15 @@ ip_set_type_register(struct ip_set_type *type)
                pr_warn("ip_set type %s, family %s with revision min %u already registered!\n",
                        type->name, family_name(type->family),
                        type->revision_min);
-               ret = -EINVAL;
-               goto unlock;
+               ip_set_type_unlock();
+               return -EINVAL;
        }
        list_add_rcu(&type->list, &ip_set_type_list);
        pr_debug("type %s, family %s, revision %u:%u registered.\n",
                 type->name, family_name(type->family),
                 type->revision_min, type->revision_max);
-unlock:
        ip_set_type_unlock();
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(ip_set_type_register);
@@ -230,12 +232,12 @@ ip_set_type_unregister(struct ip_set_type *type)
                pr_warn("ip_set type %s, family %s with revision min %u not registered\n",
                        type->name, family_name(type->family),
                        type->revision_min);
-               goto unlock;
+               ip_set_type_unlock();
+               return;
        }
        list_del_rcu(&type->list);
        pr_debug("type %s, family %s with revision min %u unregistered.\n",
                 type->name, family_name(type->family), type->revision_min);
-unlock:
        ip_set_type_unlock();
 
        synchronize_rcu();
@@ -289,7 +291,7 @@ static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
 int
 ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr)
 {
-       struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
+       struct nlattr *tb[IPSET_ATTR_IPADDR_MAX + 1];
 
        if (unlikely(!flag_nested(nla)))
                return -IPSET_ERR_PROTOCOL;
@@ -306,7 +308,7 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
 int
 ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
 {
-       struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
+       struct nlattr *tb[IPSET_ATTR_IPADDR_MAX + 1];
 
        if (unlikely(!flag_nested(nla)))
                return -IPSET_ERR_PROTOCOL;
@@ -317,7 +319,7 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
                return -IPSET_ERR_PROTOCOL;
 
        memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
-               sizeof(struct in6_addr));
+              sizeof(struct in6_addr));
        return 0;
 }
 EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
@@ -362,25 +364,27 @@ add_extension(enum ip_set_ext_id id, u32 flags, struct nlattr *tb[])
 }
 
 size_t
-ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len)
+ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len,
+               size_t align)
 {
        enum ip_set_ext_id id;
-       size_t offset = 0;
        u32 cadt_flags = 0;
 
        if (tb[IPSET_ATTR_CADT_FLAGS])
                cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
        if (cadt_flags & IPSET_FLAG_WITH_FORCEADD)
                set->flags |= IPSET_CREATE_FLAG_FORCEADD;
+       if (!align)
+               align = 1;
        for (id = 0; id < IPSET_EXT_ID_MAX; id++) {
                if (!add_extension(id, cadt_flags, tb))
                        continue;
-               offset += ALIGN(len + offset, ip_set_extensions[id].align);
-               set->offset[id] = offset;
+               len = ALIGN(len, ip_set_extensions[id].align);
+               set->offset[id] = len;
                set->extensions |= ip_set_extensions[id].type;
-               offset += ip_set_extensions[id].len;
+               len += ip_set_extensions[id].len;
        }
-       return len + offset;
+       return ALIGN(len, align);
 }
 EXPORT_SYMBOL_GPL(ip_set_elem_len);
 
@@ -389,13 +393,22 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
                      struct ip_set_ext *ext)
 {
        u64 fullmark;
+
+       if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+                    !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
+                    !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
+                    !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
+                    !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
+                    !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
+               return -IPSET_ERR_PROTOCOL;
+
        if (tb[IPSET_ATTR_TIMEOUT]) {
-               if (!(set->extensions & IPSET_EXT_TIMEOUT))
+               if (!SET_WITH_TIMEOUT(set))
                        return -IPSET_ERR_TIMEOUT;
                ext->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
        }
        if (tb[IPSET_ATTR_BYTES] || tb[IPSET_ATTR_PACKETS]) {
-               if (!(set->extensions & IPSET_EXT_COUNTER))
+               if (!SET_WITH_COUNTER(set))
                        return -IPSET_ERR_COUNTER;
                if (tb[IPSET_ATTR_BYTES])
                        ext->bytes = be64_to_cpu(nla_get_be64(
@@ -405,25 +418,25 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
                                                   tb[IPSET_ATTR_PACKETS]));
        }
        if (tb[IPSET_ATTR_COMMENT]) {
-               if (!(set->extensions & IPSET_EXT_COMMENT))
+               if (!SET_WITH_COMMENT(set))
                        return -IPSET_ERR_COMMENT;
                ext->comment = ip_set_comment_uget(tb[IPSET_ATTR_COMMENT]);
        }
        if (tb[IPSET_ATTR_SKBMARK]) {
-               if (!(set->extensions & IPSET_EXT_SKBINFO))
+               if (!SET_WITH_SKBINFO(set))
                        return -IPSET_ERR_SKBINFO;
                fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK]));
                ext->skbmark = fullmark >> 32;
                ext->skbmarkmask = fullmark & 0xffffffff;
        }
        if (tb[IPSET_ATTR_SKBPRIO]) {
-               if (!(set->extensions & IPSET_EXT_SKBINFO))
+               if (!SET_WITH_SKBINFO(set))
                        return -IPSET_ERR_SKBINFO;
                ext->skbprio = be32_to_cpu(nla_get_be32(
                                            tb[IPSET_ATTR_SKBPRIO]));
        }
        if (tb[IPSET_ATTR_SKBQUEUE]) {
-               if (!(set->extensions & IPSET_EXT_SKBINFO))
+               if (!SET_WITH_SKBINFO(set))
                        return -IPSET_ERR_SKBINFO;
                ext->skbqueue = be16_to_cpu(nla_get_be16(
                                            tb[IPSET_ATTR_SKBQUEUE]));
@@ -432,8 +445,32 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
 }
 EXPORT_SYMBOL_GPL(ip_set_get_extensions);
 
-/*
- * Creating/destroying/renaming/swapping affect the existence and
+int
+ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
+                     const void *e, bool active)
+{
+       if (SET_WITH_TIMEOUT(set)) {
+               unsigned long *timeout = ext_timeout(e, set);
+
+               if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
+                       htonl(active ? ip_set_timeout_get(timeout)
+                               : *timeout)))
+                       return -EMSGSIZE;
+       }
+       if (SET_WITH_COUNTER(set) &&
+           ip_set_put_counter(skb, ext_counter(e, set)))
+               return -EMSGSIZE;
+       if (SET_WITH_COMMENT(set) &&
+           ip_set_put_comment(skb, ext_comment(e, set)))
+               return -EMSGSIZE;
+       if (SET_WITH_SKBINFO(set) &&
+           ip_set_put_skbinfo(skb, ext_skbinfo(e, set)))
+               return -EMSGSIZE;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ip_set_put_extensions);
+
+/* Creating/destroying/renaming/swapping affect the existence and
  * the properties of a set. All of these can be executed from userspace
  * only and serialized by the nfnl mutex indirectly from nfnetlink.
  *
@@ -460,8 +497,7 @@ __ip_set_put(struct ip_set *set)
        write_unlock_bh(&ip_set_ref_lock);
 }
 
-/*
- * Add, del and test set entries from kernel.
+/* Add, del and test set entries from kernel.
  *
  * The set behind the index must exist and must be referenced
  * so it can't be destroyed (or changed) under our foot.
@@ -485,27 +521,26 @@ int
 ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
            const struct xt_action_param *par, struct ip_set_adt_opt *opt)
 {
-       struct ip_set *set = ip_set_rcu_get(
-                       dev_net(par->in ? par->in : par->out), index);
+       struct ip_set *set = ip_set_rcu_get(par->net, index);
        int ret = 0;
 
-       BUG_ON(set == NULL);
+       BUG_ON(!set);
        pr_debug("set %s, index %u\n", set->name, index);
 
        if (opt->dim < set->type->dimension ||
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return 0;
 
-       read_lock_bh(&set->lock);
+       rcu_read_lock_bh();
        ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);
-       read_unlock_bh(&set->lock);
+       rcu_read_unlock_bh();
 
        if (ret == -EAGAIN) {
                /* Type requests element to be completed */
                pr_debug("element must be completed, ADD is triggered\n");
-               write_lock_bh(&set->lock);
+               spin_lock_bh(&set->lock);
                set->variant->kadt(set, skb, par, IPSET_ADD, opt);
-               write_unlock_bh(&set->lock);
+               spin_unlock_bh(&set->lock);
                ret = 1;
        } else {
                /* --return-nomatch: invert matched element */
@@ -524,20 +559,19 @@ int
 ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
           const struct xt_action_param *par, struct ip_set_adt_opt *opt)
 {
-       struct ip_set *set = ip_set_rcu_get(
-                       dev_net(par->in ? par->in : par->out), index);
+       struct ip_set *set = ip_set_rcu_get(par->net, index);
        int ret;
 
-       BUG_ON(set == NULL);
+       BUG_ON(!set);
        pr_debug("set %s, index %u\n", set->name, index);
 
        if (opt->dim < set->type->dimension ||
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       write_lock_bh(&set->lock);
+       spin_lock_bh(&set->lock);
        ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
-       write_unlock_bh(&set->lock);
+       spin_unlock_bh(&set->lock);
 
        return ret;
 }
@@ -547,27 +581,25 @@ int
 ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
           const struct xt_action_param *par, struct ip_set_adt_opt *opt)
 {
-       struct ip_set *set = ip_set_rcu_get(
-                       dev_net(par->in ? par->in : par->out), index);
+       struct ip_set *set = ip_set_rcu_get(par->net, index);
        int ret = 0;
 
-       BUG_ON(set == NULL);
+       BUG_ON(!set);
        pr_debug("set %s, index %u\n", set->name, index);
 
        if (opt->dim < set->type->dimension ||
            !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       write_lock_bh(&set->lock);
+       spin_lock_bh(&set->lock);
        ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
-       write_unlock_bh(&set->lock);
+       spin_unlock_bh(&set->lock);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(ip_set_del);
 
-/*
- * Find set by name, reference it once. The reference makes sure the
+/* Find set by name, reference it once. The reference makes sure the
  * thing pointed to, does not go away under our feet.
  *
  */
@@ -581,7 +613,7 @@ ip_set_get_byname(struct net *net, const char *name, struct ip_set **set)
        rcu_read_lock();
        for (i = 0; i < inst->ip_set_max; i++) {
                s = rcu_dereference(inst->ip_set_list)[i];
-               if (s != NULL && STREQ(s->name, name)) {
+               if (s && STRNCMP(s->name, name)) {
                        __ip_set_get(s);
                        index = i;
                        *set = s;
@@ -594,8 +626,7 @@ ip_set_get_byname(struct net *net, const char *name, struct ip_set **set)
 }
 EXPORT_SYMBOL_GPL(ip_set_get_byname);
 
-/*
- * If the given set pointer points to a valid set, decrement
+/* If the given set pointer points to a valid set, decrement
  * reference count by 1. The caller shall not assume the index
  * to be valid, after calling this function.
  *
@@ -608,7 +639,7 @@ __ip_set_put_byindex(struct ip_set_net *inst, ip_set_id_t index)
 
        rcu_read_lock();
        set = rcu_dereference(inst->ip_set_list)[index];
-       if (set != NULL)
+       if (set)
                __ip_set_put(set);
        rcu_read_unlock();
 }
@@ -622,8 +653,7 @@ ip_set_put_byindex(struct net *net, ip_set_id_t index)
 }
 EXPORT_SYMBOL_GPL(ip_set_put_byindex);
 
-/*
- * Get the name of a set behind a set index.
+/* Get the name of a set behind a set index.
  * We assume the set is referenced, so it does exist and
  * can't be destroyed. The set cannot be renamed due to
  * the referencing either.
@@ -634,7 +664,7 @@ ip_set_name_byindex(struct net *net, ip_set_id_t index)
 {
        const struct ip_set *set = ip_set_rcu_get(net, index);
 
-       BUG_ON(set == NULL);
+       BUG_ON(!set);
        BUG_ON(set->ref == 0);
 
        /* Referenced, so it's safe */
@@ -642,13 +672,11 @@ ip_set_name_byindex(struct net *net, ip_set_id_t index)
 }
 EXPORT_SYMBOL_GPL(ip_set_name_byindex);
 
-/*
- * Routines to call by external subsystems, which do not
+/* Routines to call by external subsystems, which do not
  * call nfnl_lock for us.
  */
 
-/*
- * Find set by index, reference it once. The reference makes sure the
+/* Find set by index, reference it once. The reference makes sure the
  * thing pointed to, does not go away under our feet.
  *
  * The nfnl mutex is used in the function.
@@ -674,8 +702,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index)
 }
 EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
 
-/*
- * If the given set pointer points to a valid set, decrement
+/* If the given set pointer points to a valid set, decrement
  * reference count by 1. The caller shall not assume the index
  * to be valid, after calling this function.
  *
@@ -690,15 +717,14 @@ ip_set_nfnl_put(struct net *net, ip_set_id_t index)
        nfnl_lock(NFNL_SUBSYS_IPSET);
        if (!inst->is_deleted) { /* already deleted from ip_set_net_exit() */
                set = ip_set(inst, index);
-               if (set != NULL)
+               if (set)
                        __ip_set_put(set);
        }
        nfnl_unlock(NFNL_SUBSYS_IPSET);
 }
 EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
 
-/*
- * Communication protocol with userspace over netlink.
+/* Communication protocol with userspace over netlink.
  *
  * The commands are serialized by the nfnl mutex.
  */
@@ -725,7 +751,7 @@ start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags,
 
        nlh = nlmsg_put(skb, portid, seq, cmd | (NFNL_SUBSYS_IPSET << 8),
                        sizeof(*nfmsg), flags);
-       if (nlh == NULL)
+       if (!nlh)
                return NULL;
 
        nfmsg = nlmsg_data(nlh);
@@ -758,7 +784,7 @@ find_set_and_id(struct ip_set_net *inst, const char *name, ip_set_id_t *id)
        *id = IPSET_INVALID_ID;
        for (i = 0; i < inst->ip_set_max; i++) {
                set = ip_set(inst, i);
-               if (set != NULL && STREQ(set->name, name)) {
+               if (set && STRNCMP(set->name, name)) {
                        *id = i;
                        break;
                }
@@ -784,10 +810,10 @@ find_free_id(struct ip_set_net *inst, const char *name, ip_set_id_t *index,
        *index = IPSET_INVALID_ID;
        for (i = 0;  i < inst->ip_set_max; i++) {
                s = ip_set(inst, i);
-               if (s == NULL) {
+               if (!s) {
                        if (*index == IPSET_INVALID_ID)
                                *index = i;
-               } else if (STREQ(name, s->name)) {
+               } else if (STRNCMP(name, s->name)) {
                        /* Name clash */
                        *set = s;
                        return -EEXIST;
@@ -816,18 +842,18 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
        struct ip_set_net *inst = ip_set_pernet(net);
        struct ip_set *set, *clash = NULL;
        ip_set_id_t index = IPSET_INVALID_ID;
-       struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {};
+       struct nlattr *tb[IPSET_ATTR_CREATE_MAX + 1] = {};
        const char *name, *typename;
        u8 family, revision;
        u32 flags = flag_exist(nlh);
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL ||
-                    attr[IPSET_ATTR_TYPENAME] == NULL ||
-                    attr[IPSET_ATTR_REVISION] == NULL ||
-                    attr[IPSET_ATTR_FAMILY] == NULL ||
-                    (attr[IPSET_ATTR_DATA] != NULL &&
+                    !attr[IPSET_ATTR_SETNAME] ||
+                    !attr[IPSET_ATTR_TYPENAME] ||
+                    !attr[IPSET_ATTR_REVISION] ||
+                    !attr[IPSET_ATTR_FAMILY] ||
+                    (attr[IPSET_ATTR_DATA] &&
                      !flag_nested(attr[IPSET_ATTR_DATA]))))
                return -IPSET_ERR_PROTOCOL;
 
@@ -838,33 +864,29 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
        pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
                 name, typename, family_name(family), revision);
 
-       /*
-        * First, and without any locks, allocate and initialize
+       /* First, and without any locks, allocate and initialize
         * a normal base set structure.
         */
-       set = kzalloc(sizeof(struct ip_set), GFP_KERNEL);
+       set = kzalloc(sizeof(*set), GFP_KERNEL);
        if (!set)
                return -ENOMEM;
-       rwlock_init(&set->lock);
+       spin_lock_init(&set->lock);
        strlcpy(set->name, name, IPSET_MAXNAMELEN);
        set->family = family;
        set->revision = revision;
 
-       /*
-        * Next, check that we know the type, and take
+       /* Next, check that we know the type, and take
         * a reference on the type, to make sure it stays available
         * while constructing our new set.
         *
         * After referencing the type, we try to create the type
         * specific part of the set without holding any locks.
         */
-       ret = find_set_type_get(typename, family, revision, &(set->type));
+       ret = find_set_type_get(typename, family, revision, &set->type);
        if (ret)
                goto out;
 
-       /*
-        * Without holding any locks, create private part.
-        */
+       /* Without holding any locks, create private part. */
        if (attr[IPSET_ATTR_DATA] &&
            nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
                             set->type->create_policy)) {
@@ -878,8 +900,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
 
        /* BTW, ret==0 here. */
 
-       /*
-        * Here, we have a valid, constructed set and we are protected
+       /* Here, we have a valid, constructed set and we are protected
         * by the nfnl mutex. Find the first free index in ip_set_list
         * and check clashing.
         */
@@ -887,7 +908,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
        if (ret == -EEXIST) {
                /* If this is the same set and requested, ignore error */
                if ((flags & IPSET_FLAG_EXIST) &&
-                   STREQ(set->type->name, clash->type->name) &&
+                   STRNCMP(set->type->name, clash->type->name) &&
                    set->type->family == clash->type->family &&
                    set->type->revision_min == clash->type->revision_min &&
                    set->type->revision_max == clash->type->revision_max &&
@@ -902,7 +923,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
                        /* Wraparound */
                        goto cleanup;
 
-               list = kzalloc(sizeof(struct ip_set *) * i, GFP_KERNEL);
+               list = kcalloc(i, sizeof(struct ip_set *), GFP_KERNEL);
                if (!list)
                        goto cleanup;
                /* nfnl mutex is held, both lists are valid */
@@ -916,12 +937,11 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
                inst->ip_set_max = i;
                kfree(tmp);
                ret = 0;
-       } else if (ret)
+       } else if (ret) {
                goto cleanup;
+       }
 
-       /*
-        * Finally! Add our shiny new set to the list, and be done.
-        */
+       /* Finally! Add our shiny new set to the list, and be done. */
        pr_debug("create: '%s' created with index %u!\n", set->name, index);
        ip_set(inst, index) = set;
 
@@ -946,12 +966,9 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
 };
 
 static void
-ip_set_destroy_set(struct ip_set_net *inst, ip_set_id_t index)
+ip_set_destroy_set(struct ip_set *set)
 {
-       struct ip_set *set = ip_set(inst, index);
-
        pr_debug("set: %s\n",  set->name);
-       ip_set(inst, index) = NULL;
 
        /* Must call it without holding any lock */
        set->variant->destroy(set);
@@ -986,30 +1003,36 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
        if (!attr[IPSET_ATTR_SETNAME]) {
                for (i = 0; i < inst->ip_set_max; i++) {
                        s = ip_set(inst, i);
-                       if (s != NULL && s->ref) {
+                       if (s && s->ref) {
                                ret = -IPSET_ERR_BUSY;
                                goto out;
                        }
                }
+               inst->is_destroyed = true;
                read_unlock_bh(&ip_set_ref_lock);
                for (i = 0; i < inst->ip_set_max; i++) {
                        s = ip_set(inst, i);
-                       if (s != NULL)
-                               ip_set_destroy_set(inst, i);
+                       if (s) {
+                               ip_set(inst, i) = NULL;
+                               ip_set_destroy_set(s);
+                       }
                }
+               /* Modified by ip_set_destroy() only, which is serialized */
+               inst->is_destroyed = false;
        } else {
                s = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
                                    &i);
-               if (s == NULL) {
+               if (!s) {
                        ret = -ENOENT;
                        goto out;
                } else if (s->ref) {
                        ret = -IPSET_ERR_BUSY;
                        goto out;
                }
+               ip_set(inst, i) = NULL;
                read_unlock_bh(&ip_set_ref_lock);
 
-               ip_set_destroy_set(inst, i);
+               ip_set_destroy_set(s);
        }
        return 0;
 out:
@@ -1024,9 +1047,9 @@ ip_set_flush_set(struct ip_set *set)
 {
        pr_debug("set: %s\n",  set->name);
 
-       write_lock_bh(&set->lock);
+       spin_lock_bh(&set->lock);
        set->variant->flush(set);
-       write_unlock_bh(&set->lock);
+       spin_unlock_bh(&set->lock);
 }
 
 static int
@@ -1044,12 +1067,12 @@ ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
        if (!attr[IPSET_ATTR_SETNAME]) {
                for (i = 0; i < inst->ip_set_max; i++) {
                        s = ip_set(inst, i);
-                       if (s != NULL)
+                       if (s)
                                ip_set_flush_set(s);
                }
        } else {
                s = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME]));
-               if (s == NULL)
+               if (!s)
                        return -ENOENT;
 
                ip_set_flush_set(s);
@@ -1081,12 +1104,12 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL ||
-                    attr[IPSET_ATTR_SETNAME2] == NULL))
+                    !attr[IPSET_ATTR_SETNAME] ||
+                    !attr[IPSET_ATTR_SETNAME2]))
                return -IPSET_ERR_PROTOCOL;
 
        set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (set == NULL)
+       if (!set)
                return -ENOENT;
 
        read_lock_bh(&ip_set_ref_lock);
@@ -1098,7 +1121,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
        name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
        for (i = 0; i < inst->ip_set_max; i++) {
                s = ip_set(inst, i);
-               if (s != NULL && STREQ(s->name, name2)) {
+               if (s && STRNCMP(s->name, name2)) {
                        ret = -IPSET_ERR_EXIST_SETNAME2;
                        goto out;
                }
@@ -1130,23 +1153,24 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
        char from_name[IPSET_MAXNAMELEN];
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL ||
-                    attr[IPSET_ATTR_SETNAME2] == NULL))
+                    !attr[IPSET_ATTR_SETNAME] ||
+                    !attr[IPSET_ATTR_SETNAME2]))
                return -IPSET_ERR_PROTOCOL;
 
        from = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME]),
                               &from_id);
-       if (from == NULL)
+       if (!from)
                return -ENOENT;
 
        to = find_set_and_id(inst, nla_data(attr[IPSET_ATTR_SETNAME2]),
                             &to_id);
-       if (to == NULL)
+       if (!to)
                return -IPSET_ERR_EXIST_SETNAME2;
 
        /* Features must not change.
-        * Not an artificial restriction anymore, as we must prevent
-        * possible loops created by swapping in setlist type of sets. */
+        * Not an artifical restriction anymore, as we must prevent
+        * possible loops created by swapping in setlist type of sets.
+        */
        if (!(from->type->features == to->type->features &&
              from->family == to->family))
                return -IPSET_ERR_TYPE_MISMATCH;
@@ -1177,12 +1201,16 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
 static int
 ip_set_dump_done(struct netlink_callback *cb)
 {
-       struct ip_set_net *inst = (struct ip_set_net *)cb->args[IPSET_CB_NET];
        if (cb->args[IPSET_CB_ARG0]) {
-               pr_debug("release set %s\n",
-                        ip_set(inst, cb->args[IPSET_CB_INDEX])->name);
-               __ip_set_put_byindex(inst,
-                       (ip_set_id_t) cb->args[IPSET_CB_INDEX]);
+               struct ip_set_net *inst =
+                       (struct ip_set_net *)cb->args[IPSET_CB_NET];
+               ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX];
+               struct ip_set *set = ip_set(inst, index);
+
+               if (set->variant->uref)
+                       set->variant->uref(set, cb, false);
+               pr_debug("release set %s\n", set->name);
+               __ip_set_put_byindex(inst, index);
        }
        return 0;
 }
@@ -1204,7 +1232,7 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
 {
        struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
        int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
-       struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
+       struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1];
        struct nlattr *attr = (void *)nlh + min_len;
        u32 dump_type;
        ip_set_id_t index;
@@ -1213,27 +1241,23 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
        nla_parse(cda, IPSET_ATTR_CMD_MAX,
                  attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
 
-       /* cb->args[IPSET_CB_NET]:      net namespace
-        *         [IPSET_CB_DUMP]:     dump single set/all sets
-        *         [IPSET_CB_INDEX]:    set index
-        *         [IPSET_CB_ARG0]:     type specific
-        */
-
        if (cda[IPSET_ATTR_SETNAME]) {
                struct ip_set *set;
 
                set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]),
                                      &index);
-               if (set == NULL)
+               if (!set)
                        return -ENOENT;
 
                dump_type = DUMP_ONE;
                cb->args[IPSET_CB_INDEX] = index;
-       } else
+       } else {
                dump_type = DUMP_ALL;
+       }
 
        if (cda[IPSET_ATTR_FLAGS]) {
                u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
+
                dump_type |= (f << 16);
        }
        cb->args[IPSET_CB_NET] = (unsigned long)inst;
@@ -1251,6 +1275,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned int flags = NETLINK_CB(cb->skb).portid ? NLM_F_MULTI : 0;
        struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk));
        u32 dump_type, dump_flags;
+       bool is_destroyed;
        int ret = 0;
 
        if (!cb->args[IPSET_CB_DUMP]) {
@@ -1258,7 +1283,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
                if (ret < 0) {
                        nlh = nlmsg_hdr(cb->skb);
                        /* We have to create and send the error message
-                        * manually :-( */
+                        * manually :-(
+                        */
                        if (nlh->nlmsg_flags & NLM_F_ACK)
                                netlink_ack(cb->skb, nlh, ret);
                        return ret;
@@ -1276,13 +1302,21 @@ dump_last:
        pr_debug("dump type, flag: %u %u index: %ld\n",
                 dump_type, dump_flags, cb->args[IPSET_CB_INDEX]);
        for (; cb->args[IPSET_CB_INDEX] < max; cb->args[IPSET_CB_INDEX]++) {
-               index = (ip_set_id_t) cb->args[IPSET_CB_INDEX];
+               index = (ip_set_id_t)cb->args[IPSET_CB_INDEX];
+               write_lock_bh(&ip_set_ref_lock);
                set = ip_set(inst, index);
-               if (set == NULL) {
+               is_destroyed = inst->is_destroyed;
+               if (!set || is_destroyed) {
+                       write_unlock_bh(&ip_set_ref_lock);
                        if (dump_type == DUMP_ONE) {
                                ret = -ENOENT;
                                goto out;
                        }
+                       if (is_destroyed) {
+                               /* All sets are just being destroyed */
+                               ret = 0;
+                               goto out;
+                       }
                        continue;
                }
                /* When dumping all sets, we must dump "sorted"
@@ -1290,14 +1324,17 @@ dump_last:
                 */
                if (dump_type != DUMP_ONE &&
                    ((dump_type == DUMP_ALL) ==
-                    !!(set->type->features & IPSET_DUMP_LAST)))
+                    !!(set->type->features & IPSET_DUMP_LAST))) {
+                       write_unlock_bh(&ip_set_ref_lock);
                        continue;
+               }
                pr_debug("List set: %s\n", set->name);
                if (!cb->args[IPSET_CB_ARG0]) {
                        /* Start listing: make sure set won't be destroyed */
                        pr_debug("reference set\n");
-                       __ip_set_get(set);
+                       set->ref++;
                }
+               write_unlock_bh(&ip_set_ref_lock);
                nlh = start_msg(skb, NETLINK_CB(cb->skb).portid,
                                cb->nlh->nlmsg_seq, flags,
                                IPSET_CMD_LIST);
@@ -1325,11 +1362,13 @@ dump_last:
                                goto release_refcount;
                        if (dump_flags & IPSET_FLAG_LIST_HEADER)
                                goto next_set;
+                       if (set->variant->uref)
+                               set->variant->uref(set, cb, true);
                        /* Fall through and add elements */
                default:
-                       read_lock_bh(&set->lock);
+                       rcu_read_lock_bh();
                        ret = set->variant->list(set, skb, cb);
-                       read_unlock_bh(&set->lock);
+                       rcu_read_unlock_bh();
                        if (!cb->args[IPSET_CB_ARG0])
                                /* Set is done, proceed with next one */
                                goto next_set;
@@ -1341,6 +1380,8 @@ dump_last:
                dump_type = DUMP_LAST;
                cb->args[IPSET_CB_DUMP] = dump_type | (dump_flags << 16);
                cb->args[IPSET_CB_INDEX] = 0;
+               if (set && set->variant->uref)
+                       set->variant->uref(set, cb, false);
                goto dump_last;
        }
        goto out;
@@ -1355,7 +1396,10 @@ next_set:
 release_refcount:
        /* If there was an error or set is done, release set */
        if (ret || !cb->args[IPSET_CB_ARG0]) {
-               pr_debug("release set %s\n", ip_set(inst, index)->name);
+               set = ip_set(inst, index);
+               if (set->variant->uref)
+                       set->variant->uref(set, cb, false);
+               pr_debug("release set %s\n", set->name);
                __ip_set_put_byindex(inst, index);
                cb->args[IPSET_CB_ARG0] = 0;
        }
@@ -1407,9 +1451,9 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
        bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
 
        do {
-               write_lock_bh(&set->lock);
+               spin_lock_bh(&set->lock);
                ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
-               write_unlock_bh(&set->lock);
+               spin_unlock_bh(&set->lock);
                retried = true;
        } while (ret == -EAGAIN &&
                 set->variant->resize &&
@@ -1425,12 +1469,12 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
                size_t payload = min(SIZE_MAX,
                                     sizeof(*errmsg) + nlmsg_len(nlh));
                int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
-               struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
+               struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1];
                struct nlattr *cmdattr;
                u32 *errline;
 
                skb2 = nlmsg_new(payload, GFP_KERNEL);
-               if (skb2 == NULL)
+               if (!skb2)
                        return -ENOMEM;
                rep = __nlmsg_put(skb2, NETLINK_CB(skb).portid,
                                  nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
@@ -1447,7 +1491,8 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
 
                *errline = lineno;
 
-               netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
+               netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
+                               MSG_DONTWAIT);
                /* Signal netlink not to send its ACK/errmsg.  */
                return -EINTR;
        }
@@ -1462,25 +1507,25 @@ ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
 {
        struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
        struct ip_set *set;
-       struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
+       struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
        const struct nlattr *nla;
        u32 flags = flag_exist(nlh);
        bool use_lineno;
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL ||
+                    !attr[IPSET_ATTR_SETNAME] ||
                     !((attr[IPSET_ATTR_DATA] != NULL) ^
                       (attr[IPSET_ATTR_ADT] != NULL)) ||
-                    (attr[IPSET_ATTR_DATA] != NULL &&
+                    (attr[IPSET_ATTR_DATA] &&
                      !flag_nested(attr[IPSET_ATTR_DATA])) ||
-                    (attr[IPSET_ATTR_ADT] != NULL &&
+                    (attr[IPSET_ATTR_ADT] &&
                      (!flag_nested(attr[IPSET_ATTR_ADT]) ||
-                      attr[IPSET_ATTR_LINENO] == NULL))))
+                      !attr[IPSET_ATTR_LINENO]))))
                return -IPSET_ERR_PROTOCOL;
 
        set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (set == NULL)
+       if (!set)
                return -ENOENT;
 
        use_lineno = !!attr[IPSET_ATTR_LINENO];
@@ -1517,25 +1562,25 @@ ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
 {
        struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
        struct ip_set *set;
-       struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
+       struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
        const struct nlattr *nla;
        u32 flags = flag_exist(nlh);
        bool use_lineno;
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL ||
+                    !attr[IPSET_ATTR_SETNAME] ||
                     !((attr[IPSET_ATTR_DATA] != NULL) ^
                       (attr[IPSET_ATTR_ADT] != NULL)) ||
-                    (attr[IPSET_ATTR_DATA] != NULL &&
+                    (attr[IPSET_ATTR_DATA] &&
                      !flag_nested(attr[IPSET_ATTR_DATA])) ||
-                    (attr[IPSET_ATTR_ADT] != NULL &&
+                    (attr[IPSET_ATTR_ADT] &&
                      (!flag_nested(attr[IPSET_ATTR_ADT]) ||
-                      attr[IPSET_ATTR_LINENO] == NULL))))
+                      !attr[IPSET_ATTR_LINENO]))))
                return -IPSET_ERR_PROTOCOL;
 
        set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (set == NULL)
+       if (!set)
                return -ENOENT;
 
        use_lineno = !!attr[IPSET_ATTR_LINENO];
@@ -1572,26 +1617,26 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
 {
        struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
        struct ip_set *set;
-       struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
+       struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL ||
-                    attr[IPSET_ATTR_DATA] == NULL ||
+                    !attr[IPSET_ATTR_SETNAME] ||
+                    !attr[IPSET_ATTR_DATA] ||
                     !flag_nested(attr[IPSET_ATTR_DATA])))
                return -IPSET_ERR_PROTOCOL;
 
        set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (set == NULL)
+       if (!set)
                return -ENOENT;
 
        if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
                             set->type->adt_policy))
                return -IPSET_ERR_PROTOCOL;
 
-       read_lock_bh(&set->lock);
+       rcu_read_lock_bh();
        ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
-       read_unlock_bh(&set->lock);
+       rcu_read_unlock_bh();
        /* Userspace can't trigger element to be re-added */
        if (ret == -EAGAIN)
                ret = 1;
@@ -1613,15 +1658,15 @@ ip_set_header(struct sock *ctnl, struct sk_buff *skb,
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_SETNAME] == NULL))
+                    !attr[IPSET_ATTR_SETNAME]))
                return -IPSET_ERR_PROTOCOL;
 
        set = find_set(inst, nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (set == NULL)
+       if (!set)
                return -ENOENT;
 
        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (skb2 == NULL)
+       if (!skb2)
                return -ENOMEM;
 
        nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
@@ -1670,8 +1715,8 @@ ip_set_type(struct sock *ctnl, struct sk_buff *skb,
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
-                    attr[IPSET_ATTR_TYPENAME] == NULL ||
-                    attr[IPSET_ATTR_FAMILY] == NULL))
+                    !attr[IPSET_ATTR_TYPENAME] ||
+                    !attr[IPSET_ATTR_FAMILY]))
                return -IPSET_ERR_PROTOCOL;
 
        family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
@@ -1681,7 +1726,7 @@ ip_set_type(struct sock *ctnl, struct sk_buff *skb,
                return ret;
 
        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (skb2 == NULL)
+       if (!skb2)
                return -ENOMEM;
 
        nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
@@ -1726,11 +1771,11 @@ ip_set_protocol(struct sock *ctnl, struct sk_buff *skb,
        struct nlmsghdr *nlh2;
        int ret = 0;
 
-       if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
+       if (unlikely(!attr[IPSET_ATTR_PROTOCOL]))
                return -IPSET_ERR_PROTOCOL;
 
        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (skb2 == NULL)
+       if (!skb2)
                return -ENOMEM;
 
        nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
@@ -1858,7 +1903,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
                ret = -EFAULT;
                goto done;
        }
-       op = (unsigned int *) data;
+       op = (unsigned int *)data;
 
        if (*op < IP_SET_OP_VERSION) {
                /* Check the version at the beginning of operations */
@@ -1970,10 +2015,11 @@ ip_set_net_init(struct net *net)
        if (inst->ip_set_max >= IPSET_INVALID_ID)
                inst->ip_set_max = IPSET_INVALID_ID - 1;
 
-       list = kzalloc(sizeof(struct ip_set *) * inst->ip_set_max, GFP_KERNEL);
+       list = kcalloc(inst->ip_set_max, sizeof(struct ip_set *), GFP_KERNEL);
        if (!list)
                return -ENOMEM;
-       inst->is_deleted = 0;
+       inst->is_deleted = false;
+       inst->is_destroyed = false;
        rcu_assign_pointer(inst->ip_set_list, list);
        return 0;
 }
@@ -1986,12 +2032,14 @@ ip_set_net_exit(struct net *net)
        struct ip_set *set = NULL;
        ip_set_id_t i;
 
-       inst->is_deleted = 1; /* flag for ip_set_nfnl_put */
+       inst->is_deleted = true; /* flag for ip_set_nfnl_put */
 
        for (i = 0; i < inst->ip_set_max; i++) {
                set = ip_set(inst, i);
-               if (set != NULL)
-                       ip_set_destroy_set(inst, i);
+               if (set) {
+                       ip_set(inst, i) = NULL;
+                       ip_set_destroy_set(set);
+               }
        }
        kfree(rcu_dereference_protected(inst->ip_set_list, 1));
 }
@@ -2003,11 +2051,11 @@ static struct pernet_operations ip_set_net_ops = {
        .size   = sizeof(struct ip_set_net)
 };
 
-
 static int __init
 ip_set_init(void)
 {
        int ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
+
        if (ret != 0) {
                pr_err("ip_set: cannot register with nfnetlink.\n");
                return ret;