ctx->nla   = nla;
 }
 
-static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, u32 size)
+static struct nft_trans *nft_trans_alloc(struct nft_ctx *ctx, int msg_type,
+                                        u32 size)
 {
        struct nft_trans *trans;
 
        if (trans == NULL)
                return NULL;
 
+       trans->msg_type = msg_type;
        trans->ctx      = *ctx;
 
        return trans;
        kfree(rule);
 }
 
-static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx,
+static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
                                            struct nft_rule *rule)
 {
        struct nft_trans *trans;
 
-       trans = nft_trans_alloc(ctx, sizeof(struct nft_trans_rule));
+       trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
        if (trans == NULL)
                return NULL;
 
 
        if (nlh->nlmsg_flags & NLM_F_REPLACE) {
                if (nft_rule_is_active_next(net, old_rule)) {
-                       trans = nft_trans_rule_add(&ctx, old_rule);
+                       trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE,
+                                                  old_rule);
                        if (trans == NULL) {
                                err = -ENOMEM;
                                goto err2;
                        list_add_rcu(&rule->list, &chain->rules);
        }
 
-       if (nft_trans_rule_add(&ctx, rule) == NULL) {
+       if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
                err = -ENOMEM;
                goto err3;
        }
 {
        /* You cannot delete the same rule twice */
        if (nft_rule_is_active_next(ctx->net, rule)) {
-               if (nft_trans_rule_add(ctx, rule) == NULL)
+               if (nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule) == NULL)
                        return -ENOMEM;
                nft_rule_disactivate_next(ctx->net, rule);
                return 0;
        synchronize_rcu();
 
        list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
-               /* This rule was inactive in the past and just became active.
-                * Clear the next bit of the genmask since its meaning has
-                * changed, now it is the future.
-                */
-               if (nft_rule_is_active(net, nft_trans_rule(trans))) {
-                       nft_rule_clear(net, nft_trans_rule(trans));
-                       nf_tables_rule_notify(skb, trans->ctx.nlh,
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWRULE:
+                       nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
+                       nf_tables_rule_notify(trans->ctx.skb, trans->ctx.nlh,
                                              trans->ctx.table,
                                              trans->ctx.chain,
                                              nft_trans_rule(trans),
                                              NFT_MSG_NEWRULE, 0,
                                              trans->ctx.afi->family);
                        nft_trans_destroy(trans);
-                       continue;
+                       break;
+               case NFT_MSG_DELRULE:
+                       list_del_rcu(&nft_trans_rule(trans)->list);
+                       nf_tables_rule_notify(trans->ctx.skb, trans->ctx.nlh,
+                                             trans->ctx.table,
+                                             trans->ctx.chain,
+                                             nft_trans_rule(trans), NFT_MSG_DELRULE, 0,
+                                             trans->ctx.afi->family);
+                       break;
                }
-
-               /* This rule is in the past, get rid of it */
-               list_del_rcu(&nft_trans_rule(trans)->list);
-               nf_tables_rule_notify(skb, trans->ctx.nlh,
-                                     trans->ctx.table, trans->ctx.chain,
-                                     nft_trans_rule(trans), NFT_MSG_DELRULE,
-                                     0, trans->ctx.afi->family);
        }
 
        /* Make sure we don't see any packet traversing old rules */
 
        /* Now we can safely release unused old rules */
        list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
-               nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
-               nft_trans_destroy(trans);
+               switch (trans->msg_type) {
+               case NFT_MSG_DELRULE:
+                       nf_tables_rule_destroy(&trans->ctx,
+                                              nft_trans_rule(trans));
+                       nft_trans_destroy(trans);
+                       break;
+               }
        }
 
        return 0;
        struct nft_trans *trans, *next;
 
        list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
-               if (!nft_rule_is_active_next(net, nft_trans_rule(trans))) {
-                       nft_rule_clear(net, nft_trans_rule(trans));
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWRULE:
+                       list_del_rcu(&nft_trans_rule(trans)->list);
+                       break;
+               case NFT_MSG_DELRULE:
+                       nft_rule_clear(trans->ctx.net, nft_trans_rule(trans));
                        nft_trans_destroy(trans);
-                       continue;
+                       break;
                }
-
-               /* This rule is inactive, get rid of it */
-               list_del_rcu(&nft_trans_rule(trans)->list);
        }
 
        /* Make sure we don't see any packet accessing aborted rules */
        synchronize_rcu();
 
        list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
-               nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
-               nft_trans_destroy(trans);
+               switch (trans->msg_type) {
+               case NFT_MSG_NEWRULE:
+                       nf_tables_rule_destroy(&trans->ctx,
+                                              nft_trans_rule(trans));
+                       nft_trans_destroy(trans);
+                       break;
+               }
        }
 
        return 0;