struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto;
+ typeof(nf_conntrack_destroyed) destroyed;
DEBUGP("destroy_conntrack(%p)\n", ct);
NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
if (l4proto && l4proto->destroy)
l4proto->destroy(ct);
- rcu_read_unlock();
- if (nf_conntrack_destroyed)
- nf_conntrack_destroyed(ct);
+ destroyed = rcu_dereference(nf_conntrack_destroyed);
+ if (destroyed)
+ destroyed(ct);
+
+ rcu_read_unlock();
write_lock_bh(&nf_conntrack_lock);
/* Expectations will have been removed in clean_from_lists,
static void __nf_conntrack_hash_insert(struct nf_conn *ct,
unsigned int hash,
- unsigned int repl_hash)
+ unsigned int repl_hash)
{
ct->id = ++nf_conntrack_next_id;
list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
if (del_timer(&ct->timeout)) {
death_by_timeout((unsigned long)ct);
dropped = 1;
- NF_CT_STAT_INC(early_drop);
+ NF_CT_STAT_INC_ATOMIC(early_drop);
}
nf_ct_put(ct);
return dropped;
/* Previously seen (loopback or untracked)? Ignore. */
if ((*pskb)->nfct) {
- NF_CT_STAT_INC(ignore);
+ NF_CT_STAT_INC_ATOMIC(ignore);
return NF_ACCEPT;
}
* core what to do with the packet. */
if (l4proto->error != NULL &&
(ret = l4proto->error(*pskb, dataoff, &ctinfo, pf, hooknum)) <= 0) {
- NF_CT_STAT_INC(error);
- NF_CT_STAT_INC(invalid);
+ NF_CT_STAT_INC_ATOMIC(error);
+ NF_CT_STAT_INC_ATOMIC(invalid);
return -ret;
}
&set_reply, &ctinfo);
if (!ct) {
/* Not valid part of a connection */
- NF_CT_STAT_INC(invalid);
+ NF_CT_STAT_INC_ATOMIC(invalid);
return NF_ACCEPT;
}
if (IS_ERR(ct)) {
/* Too stressed to deal. */
- NF_CT_STAT_INC(drop);
+ NF_CT_STAT_INC_ATOMIC(drop);
return NF_DROP;
}
DEBUGP("nf_conntrack_in: Can't track with proto module\n");
nf_conntrack_put((*pskb)->nfct);
(*pskb)->nfct = NULL;
- NF_CT_STAT_INC(invalid);
+ NF_CT_STAT_INC_ATOMIC(invalid);
return -ret;
}
}
EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct);
-#if defined(CONFIG_NF_CT_NETLINK) || \
- defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
if (iter(ct, data))
goto found;
}
- }
+ }
list_for_each_entry(h, &unconfirmed, list) {
ct = nf_ct_tuplehash_to_ctrack(h);
if (iter(ct, data))
- goto found;
+ set_bit(IPS_DYING_BIT, &ct->status);
}
write_unlock_bh(&nf_conntrack_lock);
return NULL;
if (vmalloced)
vfree(hash);
else
- free_pages((unsigned long)hash,
+ free_pages((unsigned long)hash,
get_order(sizeof(struct list_head) * size));
}
struct list_head *hash;
unsigned int i;
- *vmalloced = 0;
- hash = (void*)__get_free_pages(GFP_KERNEL,
+ *vmalloced = 0;
+ hash = (void*)__get_free_pages(GFP_KERNEL,
get_order(sizeof(struct list_head)
* size));
- if (!hash) {
+ if (!hash) {
*vmalloced = 1;
printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
hash = vmalloc(sizeof(struct list_head) * size);
}
if (hash)
- for (i = 0; i < size; i++)
+ for (i = 0; i < size; i++)
INIT_LIST_HEAD(&hash[i]);
return hash;
/* Don't NEED lock here, but good form anyway. */
write_lock_bh(&nf_conntrack_lock);
- for (i = 0; i < AF_MAX; i++)
+ for (i = 0; i < AF_MAX; i++)
nf_ct_l3protos[i] = &nf_conntrack_l3proto_generic;
- write_unlock_bh(&nf_conntrack_lock);
+ write_unlock_bh(&nf_conntrack_lock);
/* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, __nf_conntrack_attach);