[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Strange things wirh NFS on 2.6.8.1 kernel



On Wed, 2004-10-20 at 23:37 +0200, Storm66 wrote:
> I use to back-up my A2000 on another machine before burning a CD, I
> noticed some problems with the 2.6.8.1 kernel.
> The "mount -t nfs ..." works OK, the distant disk is visibble, all seems
> OK. Small files are copied over the link but bigger files (#1Ko) are not
> and the copy hangs.

I booted 2.6.10 yesterday with my HP and got the same thing happening.
In the past there used to be problems with NFS and fragmented UDP
packets, so I added a wsize=1024 option to the nfsroot command line
argument. That made it work.

Then I used Ethereal to see what was going on in the other case. It
turns out all UDP packets with the "More Fragments" flag have bad IP
header checksums. "Normal" packets are fine.

I played around a bit with the ip_fast_csum() code but it looked like
that code was fine, it at least calculated the expected checksum when
fed the same bytes as a frame with a bad checksum.

But when it was inlined in net/ipv4/ip_output.c:ip_fragment() the
clearing of the checksum field in the IP header (in
net/ipv4/ip_output.c:ip_send_check()) got optimised away...

FYI, I'm using Debian toolchain-source 3.4-4 which uses gcc 3.4.1-1.

Adding a "memory" constraint to the assembly in ip_fast_csum() solved
it. I don't really understand why it's needed, since the code in
ip_fast_csum() does not modify memory...

I first tried adding a __volatile__ statement to the assembly, but that
didn't work.

I also rewrote the function a bit to not always use d0, but leave
register allocation to gcc.

There was also a problem with the constraints of csum_tcpudp_nofold(),
they were inconsistent (I think). I also noticed a rather strange
difference between us and other big-endian arches: they all use len +
(proto<<16) as an input, we use len + proto. I don't really understand
why.

I propose the following changes, but I'd like someone else to look at
them first before committing them.


Kind regards,

Kars.

Index: include/asm-m68k/checksum.h
===================================================================
RCS file: /home/linux-m68k/cvsroot/linux/include/asm-m68k/checksum.h,v
retrieving revision 1.6
diff -u -r1.6 checksum.h
--- include/asm-m68k/checksum.h	5 Apr 2004 13:09:08 -0000	1.6
+++ include/asm-m68k/checksum.h	6 Mar 2005 19:42:42 -0000
@@ -40,20 +40,21 @@
 ip_fast_csum(unsigned char *iph, unsigned int ihl)
 {
 	unsigned int sum = 0;
+	unsigned long tmp;
 
 	__asm__ ("subqw #1,%2\n"
 		 "1:\t"
-		 "movel %1@+,%/d0\n\t"
-		 "addxl %/d0,%0\n\t"
+		 "movel %1@+,%3\n\t"
+		 "addxl %3,%0\n\t"
 		 "dbra  %2,1b\n\t"
-		 "movel %0,%/d0\n\t"
-		 "swap  %/d0\n\t"
-		 "addxw %/d0,%0\n\t"
-		 "clrw  %/d0\n\t"
-		 "addxw %/d0,%0\n\t"
-		 : "=d" (sum), "=a" (iph), "=d" (ihl)
+		 "movel %0,%3\n\t"
+		 "swap  %3\n\t"
+		 "addxw %3,%0\n\t"
+		 "clrw  %3\n\t"
+		 "addxw %3,%0\n\t"
+		 : "=d" (sum), "=&a" (iph), "=&d" (ihl), "=&d" (tmp)
 		 : "0" (sum), "1" (iph), "2" (ihl)
-		 : "d0");
+		 : "memory");
 	return ~sum;
 }
 
@@ -69,7 +70,7 @@
 		"clrw %1\n\t"
 		"addxw %1, %0"
 		: "=&d" (sum), "=&d" (tmp)
-		: "0" (sum), "1" (sum));
+		: "0" (sum), "1" (tmp));
 	return ~sum;
 }
 
@@ -83,14 +84,14 @@
 csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
 		  unsigned short proto, unsigned int sum)
 {
-	__asm__ ("addl  %1,%0\n\t"
+	__asm__ ("addl  %2,%0\n\t"
+		 "addxl %3,%0\n\t"
 		 "addxl %4,%0\n\t"
-		 "addxl %5,%0\n\t"
 		 "clrl %1\n\t"
 		 "addxl %1,%0"
-		 : "=&d" (sum), "=&d" (saddr)
-		 : "0" (daddr), "1" (saddr), "d" (len + proto),
-		   "d"(sum));
+		 : "=&d" (sum), "=d" (saddr)
+		 : "g" (daddr), "1" (saddr), "d" (len + (proto<<16)),
+		   "0" (sum));
 	return sum;
 }
 




Reply to: