}
                }
                rcu_read_unlock();
+               local_bh_enable();
        }
  
 -      rcu_read_lock();
 -      if (!rcu_dereference(tun->steering_prog))
 +      /* Compute the costly rx hash only if needed for flow updates.
 +       * We may get a very small possibility of OOO during switching, not
 +       * worth to optimize.
 +       */
 +      if (!rcu_access_pointer(tun->steering_prog) && tun->numqueues > 1 &&
 +          !tfile->detached)
                rxhash = __skb_get_hash_symmetric(skb);
 -      rcu_read_unlock();
  
        if (frags) {
                /* Exercise flow dissector code path. */
 
        __u32 map_flags;
        char  name[BPF_OBJ_NAME_LEN];
        __u32 ifindex;
+       __u32 :32;
        __u64 netns_dev;
        __u64 netns_ino;
 +      __u32 btf_id;
 +      __u32 btf_key_type_id;
 +      __u32 btf_value_type_id;
 +} __attribute__((aligned(8)));
 +
 +struct bpf_btf_info {
 +      __aligned_u64 btf;
 +      __u32 btf_size;
 +      __u32 id;
  } __attribute__((aligned(8)));
  
  /* User bpf_sock_addr struct to access socket fields and sockaddr struct passed
 
                rcu_assign_pointer(chain->stats, newstats);
                synchronize_rcu();
                free_percpu(oldstats);
-       } else
+       } else {
                rcu_assign_pointer(chain->stats, newstats);
+               static_branch_inc(&nft_counters_enabled);
+       }
  }
  
 +static void nf_tables_chain_free_chain_rules(struct nft_chain *chain)
 +{
 +      struct nft_rule **g0 = rcu_dereference_raw(chain->rules_gen_0);
 +      struct nft_rule **g1 = rcu_dereference_raw(chain->rules_gen_1);
 +
 +      if (g0 != g1)
 +              kvfree(g1);
 +      kvfree(g0);
 +
 +      /* should be NULL either via abort or via successful commit */
 +      WARN_ON_ONCE(chain->rules_next);
 +      kvfree(chain->rules_next);
 +}
 +
  static void nf_tables_chain_destroy(struct nft_ctx *ctx)
  {
        struct nft_chain *chain = ctx->chain;
 
        kfree(tb);
        return 0;
  
 +errout_mask:
 +      fl_mask_put(head, fnew->mask, false);
 +
  errout_idr:
-       if (fnew->handle)
+       if (!fold)
                idr_remove(&head->handle_idr, fnew->handle);
  errout:
        tcf_exts_destroy(&fnew->exts);
 
        __u32 map_flags;
        char  name[BPF_OBJ_NAME_LEN];
        __u32 ifindex;
+       __u32 :32;
        __u64 netns_dev;
        __u64 netns_ino;
 +      __u32 btf_id;
 +      __u32 btf_key_type_id;
 +      __u32 btf_value_type_id;
 +} __attribute__((aligned(8)));
 +
 +struct bpf_btf_info {
 +      __aligned_u64 btf;
 +      __u32 btf_size;
 +      __u32 id;
  } __attribute__((aligned(8)));
  
  /* User bpf_sock_addr struct to access socket fields and sockaddr struct passed