On Thu, Oct 10, 2002 at 06:20:46AM -0700, Tom Lanyon wrote: > [1.] One line summary of the problem: Some sort of coding problem in > conntrack. It's not a bug in the code, it's a bug in the debugging ASSERT macros, as correctly pointed out by Martin Josefsson. The issue is that we are nesting readlocks, because ip_ct_find_proto() grabs itself a readlock on ip_conntrack_lock. The patch below now exports the non-locking __ip_ct_find_proto() function, thus no more grabbing a nested readlock. I wanted to go for a different solution, since exporting __ functions is not exactly clean coding style - but due to the circumstances other solutions look even more ugly. Dave, please apply the following fix (again by Martin Josefsson), Thanks. diff -x '*.orig' -urN linux-2.4.20-pre8-ac3.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.4.20-pre8-ac3/include/linux/netfilter_ipv4/ip_conntrack_core.h --- linux-2.4.20-pre8-ac3.orig/include/linux/netfilter_ipv4/ip_conntrack_core.h 2002-10-10 15:41:55.000000000 +0200 +++ linux-2.4.20-pre8-ac3/include/linux/netfilter_ipv4/ip_conntrack_core.h 2002-10-10 16:07:16.000000000 +0200 @@ -17,7 +17,7 @@ struct ip_conntrack_protocol; extern struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol); /* Like above, but you already have conntrack read lock. */ -extern struct ip_conntrack_protocol *__find_proto(u_int8_t protocol); +extern struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol); extern struct list_head protocol_list; /* Returns conntrack if it dealt with ICMP, and filled in skb->nfct */ diff -x '*.orig' -urN linux-2.4.20-pre8-ac3.orig/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.20-pre8-ac3/net/ipv4/netfilter/ip_conntrack_core.c --- linux-2.4.20-pre8-ac3.orig/net/ipv4/netfilter/ip_conntrack_core.c 2002-10-10 15:41:57.000000000 +0200 +++ linux-2.4.20-pre8-ac3/net/ipv4/netfilter/ip_conntrack_core.c 2002-10-10 16:07:16.000000000 +0200 @@ -74,7 +74,7 @@ return protocol == curr->proto; } -struct ip_conntrack_protocol *__find_proto(u_int8_t protocol) +struct ip_conntrack_protocol *__ip_ct_find_proto(u_int8_t protocol) { struct ip_conntrack_protocol *p; @@ -92,7 +92,7 @@ struct ip_conntrack_protocol *p; READ_LOCK(&ip_conntrack_lock); - p = __find_proto(protocol); + p = __ip_ct_find_proto(protocol); READ_UNLOCK(&ip_conntrack_lock); return p; } diff -x '*.orig' -urN linux-2.4.20-pre8-ac3.orig/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.20-pre8-ac3/net/ipv4/netfilter/ip_conntrack_standalone.c --- linux-2.4.20-pre8-ac3.orig/net/ipv4/netfilter/ip_conntrack_standalone.c 2002-10-10 15:41:57.000000000 +0200 +++ linux-2.4.20-pre8-ac3/net/ipv4/netfilter/ip_conntrack_standalone.c 2002-10-10 16:07:16.000000000 +0200 @@ -71,7 +71,7 @@ len += sprintf(buffer + len, "use=%u proto=%u ", atomic_read(&expect->use), expect->tuple.dst.protonum); len += print_tuple(buffer + len, &expect->tuple, - __find_proto(expect->tuple.dst.protonum)); + __ip_ct_find_proto(expect->tuple.dst.protonum)); len += sprintf(buffer + len, "\n"); return len; } @@ -81,7 +81,7 @@ { unsigned int len; struct ip_conntrack_protocol *proto - = __find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] + = __ip_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.dst.protonum); len = sprintf(buffer, "%-8s %u %lu ", @@ -361,6 +361,7 @@ EXPORT_SYMBOL(ip_ct_selective_cleanup); EXPORT_SYMBOL(ip_ct_refresh); EXPORT_SYMBOL(ip_ct_find_proto); +EXPORT_SYMBOL(__ip_ct_find_proto); EXPORT_SYMBOL(ip_ct_find_helper); EXPORT_SYMBOL(ip_conntrack_expect_related); EXPORT_SYMBOL(ip_conntrack_change_expect); diff -x '*.orig' -urN linux-2.4.20-pre8-ac3.orig/net/ipv4/netfilter/ip_nat_core.c linux-2.4.20-pre8-ac3/net/ipv4/netfilter/ip_nat_core.c --- linux-2.4.20-pre8-ac3.orig/net/ipv4/netfilter/ip_nat_core.c 2002-10-10 16:10:49.000000000 +0200 +++ linux-2.4.20-pre8-ac3/net/ipv4/netfilter/ip_nat_core.c 2002-10-10 16:10:36.000000000 +0200 @@ -739,7 +739,7 @@ int ret = 1; MUST_BE_READ_LOCKED(&ip_conntrack_lock); - proto = ip_ct_find_proto((*pskb)->nh.iph->protocol); + proto = __ip_ct_find_proto((*pskb)->nh.iph->protocol); if (proto->exp_matches_pkt) ret = proto->exp_matches_pkt(exp, pskb); > Thanks for your help Thanks for your help (i mean it!). > Tom Lanyon > toml@internode.on.net -- Live long and prosper - Harald Welte / laforge@gnumonks.org http://www.gnumonks.org/ ============================================================================ "If this were a dictatorship, it'd be a heck of a lot easier, just so long as I'm the dictator." -- George W. Bush Dec 18, 2000