*     @dtype: data type (verdict or numeric type defined by userspace)
  *     @size: maximum set size
  *     @nelems: number of elements
+ *     @ndeact: number of deactivated elements queued for removal
  *     @timeout: default timeout value in msecs
  *     @gc_int: garbage collection interval in msecs
  *     @policy: set parameterization (see enum nft_set_policies)
        u32                             ktype;
        u32                             dtype;
        u32                             size;
-       u32                             nelems;
+       atomic_t                        nelems;
+       u32                             ndeact;
        u64                             timeout;
        u32                             gc_int;
        u16                             policy;
 
        u32 flags;
        int err;
 
-       if (set->size && set->nelems == set->size)
-               return -ENFILE;
-
        err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
                               nft_set_elem_policy);
        if (err < 0)
                return -EBUSY;
 
        nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+               if (set->size &&
+                   !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact))
+                       return -ENFILE;
+
                err = nft_add_set_elem(&ctx, set, attr);
-               if (err < 0)
+               if (err < 0) {
+                       atomic_dec(&set->nelems);
                        break;
-
-               set->nelems++;
+               }
        }
        return err;
 }
                if (err < 0)
                        break;
 
-               set->nelems--;
+               set->ndeact++;
        }
        return err;
 }
                                                 &te->elem,
                                                 NFT_MSG_DELSETELEM, 0);
                        te->set->ops->remove(te->set, &te->elem);
+                       atomic_dec(&te->set->nelems);
+                       te->set->ndeact--;
                        break;
                }
        }
                        nft_trans_destroy(trans);
                        break;
                case NFT_MSG_NEWSETELEM:
-                       nft_trans_elem_set(trans)->nelems--;
                        te = (struct nft_trans_elem *)trans->data;
 
                        te->set->ops->remove(te->set, &te->elem);
+                       atomic_dec(&te->set->nelems);
                        break;
                case NFT_MSG_DELSETELEM:
                        te = (struct nft_trans_elem *)trans->data;
 
-                       nft_trans_elem_set(trans)->nelems++;
                        te->set->ops->activate(te->set, &te->elem);
+                       te->set->ndeact--;
 
                        nft_trans_destroy(trans);
                        break;
 
 
 static void nft_hash_gc(struct work_struct *work)
 {
-       const struct nft_set *set;
+       struct nft_set *set;
        struct nft_hash_elem *he;
        struct nft_hash *priv;
        struct nft_set_gc_batch *gcb = NULL;
                if (gcb == NULL)
                        goto out;
                rhashtable_remove_fast(&priv->ht, &he->node, nft_hash_params);
+               atomic_dec(&set->nelems);
                nft_set_gc_batch_add(gcb, he);
        }
 out: