From: Liping Zhang <zlpnobody@xxxxxxxxx> Similar to commit 474803d37e7f ("netfilter: cttimeout: unlink timeout obj again when hash resize happen"), when hash resize happen, we should try to do cleanup work from the 0#bucket again, so we will never miss the conntrack entries which we are intrested in. This is important for the module removal. Signed-off-by: Liping Zhang <zlpnobody@xxxxxxxxx> --- net/netfilter/nf_conntrack_core.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e847dba..dec4c2a 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1587,7 +1587,7 @@ static void nf_conntrack_attach(struct sk_buff *nskb, const struct sk_buff *skb) /* Bring out ya dead! */ static struct nf_conn * get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), - void *data, unsigned int *bucket) + void *data, unsigned int *bucket, unsigned int *hsize) { struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; @@ -1595,20 +1595,28 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), int cpu; spinlock_t *lockp; - for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { + for (; *bucket < *hsize; (*bucket)++) { lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS]; local_bh_disable(); nf_conntrack_lock(lockp); - if (*bucket < nf_conntrack_htable_size) { - hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnnode) { - if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) - continue; - ct = nf_ct_tuplehash_to_ctrack(h); - if (net_eq(nf_ct_net(ct), net) && - iter(ct, data)) - goto found; - } + + /* nf conntrack hash resize happened. */ + if (*hsize != nf_conntrack_htable_size) { + *hsize = nf_conntrack_htable_size; + *bucket = 0; + goto cont; + } + + hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[*bucket], + hnnode) { + if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) + continue; + ct = nf_ct_tuplehash_to_ctrack(h); + if (net_eq(nf_ct_net(ct), net) && + iter(ct, data)) + goto found; } +cont: spin_unlock(lockp); local_bh_enable(); cond_resched(); @@ -1640,13 +1648,16 @@ void nf_ct_iterate_cleanup(struct net *net, { struct nf_conn *ct; unsigned int bucket = 0; + unsigned int hsize; might_sleep(); if (atomic_read(&net->ct.count) == 0) return; - while ((ct = get_next_corpse(net, iter, data, &bucket)) != NULL) { + hsize = nf_conntrack_htable_size; + while ((ct = get_next_corpse(net, iter, data, &bucket, + &hsize)) != NULL) { /* Time to push up daises... */ nf_ct_delete(ct, portid, report); -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html