Message ID | 4B251CE4.9080401@gmail.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Eric Dumazet wrote: > Le 13/12/2009 03:41, Yinghai Lu a écrit : >>>> cause the problem: nfs mount fail. >>>> >>>> the setup is: >>>> 64bit kernel, have all needed drivers in kernel, and boot with >>>> ip=dhcp, root disk is 256M ramdisk. >>>> then try to mount nfs.... >>>> >>> change entries default value from 65536 to 256, >>> nfs mount will work. >>> >> interesting: >> >> m:~/dump # grep UDP dmesg.txt >> [ 28.996034] UDP hash table entries: 65536 (order: 11, 10485760 bytes) >> [ 29.032364] UDP-Lite hash table entries: 65536 (order: 11, 10485760 bytes) >> >> will not work >> >> but 32768 will work. > > Thanks a lot for this work Yinghai ! > This last bit helped me a lot ... > > Hmm, udp_lib_get_port() assumes it can loop at least one time in : > > for (last = first + udptable->mask + 1; > first != last; > first++) { > // unit_work > } > > but if udptable->mask == 65535, loop is not entered at all (since last == first) > > We should convert it to a do { } while(...); construct, or use 32bit variables > and (u16) casts. > > Thanks > > [PATCH] udp: udp_lib_get_port() fix > > Now we can have a large udp hash table, udp_lib_get_port() loop > should be converted to a do {} while (cond) form, > or we dont enter it at all if hash table size is exactly 65536. > > Reported-by: Yinghai Lu <yinghai@kernel.org> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> > --- > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > index 1f95348..f0126fd 100644 > --- a/net/ipv4/udp.c > +++ b/net/ipv4/udp.c > @@ -216,9 +216,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, > * force rand to be an odd multiple of UDP_HTABLE_SIZE > */ > rand = (rand | 1) * (udptable->mask + 1); > - for (last = first + udptable->mask + 1; > - first != last; > - first++) { > + last = first + udptable->mask + 1; > + do { > hslot = udp_hashslot(udptable, net, first); > bitmap_zero(bitmap, PORTS_PER_CHAIN); > spin_lock_bh(&hslot->lock); > @@ -238,7 +237,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, > snum += rand; > } while (snum != first); > spin_unlock_bh(&hslot->lock); > - } > + } while (++first != last); > goto fail; > } else { > hslot = udp_hashslot(udptable, net, snum); thanks. that fix the problem. YH -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Yinghai Lu <yinghai@kernel.org> Date: Sun, 13 Dec 2009 14:28:14 -0800 > Eric Dumazet wrote: >> [PATCH] udp: udp_lib_get_port() fix >> >> Now we can have a large udp hash table, udp_lib_get_port() loop >> should be converted to a do {} while (cond) form, >> or we dont enter it at all if hash table size is exactly 65536. >> >> Reported-by: Yinghai Lu <yinghai@kernel.org> >> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> ... > thanks. that fix the problem. Applied, thanks everyone. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1f95348..f0126fd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -216,9 +216,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, * force rand to be an odd multiple of UDP_HTABLE_SIZE */ rand = (rand | 1) * (udptable->mask + 1); - for (last = first + udptable->mask + 1; - first != last; - first++) { + last = first + udptable->mask + 1; + do { hslot = udp_hashslot(udptable, net, first); bitmap_zero(bitmap, PORTS_PER_CHAIN); spin_lock_bh(&hslot->lock); @@ -238,7 +237,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, snum += rand; } while (snum != first); spin_unlock_bh(&hslot->lock); - } + } while (++first != last); goto fail; } else { hslot = udp_hashslot(udptable, net, snum);