diff -ruN linux-orig/net/ipv4/netfilter/ip_conntrack_core.c linux-new/net/ipv4/netfilter/ip_conntrack_core.c --- linux-orig/net/ipv4/netfilter/ip_conntrack_core.c 2005-03-02 02:37:30.000000000 -0500 +++ linux-new/net/ipv4/netfilter/ip_conntrack_core.c 2005-03-14 20:18:46.289349488 -0500 @@ -74,6 +74,7 @@ struct ip_conntrack ip_conntrack_untracked; unsigned int ip_ct_log_invalid; static LIST_HEAD(unconfirmed); +static LIST_HEAD(cleaned); static int ip_conntrack_vmalloc; DEFINE_PER_CPU(struct ip_conntrack_stat, ip_conntrack_stat); @@ -216,6 +217,9 @@ LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]); LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]); + /* Overload tuple linked list to put us in cleaned list. */ + list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list, &cleaned); + /* Destroy all pending expectations */ remove_expectations(ct); } @@ -247,11 +251,9 @@ * too. */ remove_expectations(ct); - /* We overload first tuple to link into unconfirmed list. */ - if (!is_confirmed(ct)) { - BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list)); - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); - } + /* We overload first tuple to link into unconfirmed or cleaned list. + Will always be on one or the other at this point */ + list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); CONNTRACK_STAT_INC(delete); WRITE_UNLOCK(&ip_conntrack_lock); @@ -1019,8 +1021,11 @@ if (!h) h = LIST_FIND_W(&unconfirmed, do_iter, struct ip_conntrack_tuple_hash *, iter, data); + if (!h) + h = LIST_FIND_W(&cleaned, do_iter, + struct ip_conntrack_tuple_hash *, iter, data); if (h) - atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use); + atomic_set(&tuplehash_to_ctrack(h)->ct_general.use, 1); WRITE_UNLOCK(&ip_conntrack_lock); return h;