Subject: NFSv3 bug
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 09/26/2002 13:29:33
--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,
I've found a bug in our NFSv3 server code, triggered by linux clients.
On occasions Linux will issue commit RPC with a 0 bytes len (mayotte is linux
client, borneo NetBSD 1.6 server):
13:05:14.665859 borneo.nfs > mayotte.2001150512: reply ok 160 write [|nfs]
13:05:14.832899 mayotte.2957451824 > borneo.nfs: 1472 write fh 0,12/1931 24064 bytes @ 720896 (frag 57996:1480@0+)
13:05:14.832937 mayotte.2974229040 > borneo.nfs: 148 commit fh 0,12/1931 720896 bytes @ 0 (DF)
13:05:14.832951 borneo.nfs > mayotte.2957451824: reply ok 160 write [|nfs]
13:05:14.834230 borneo.nfs > mayotte.2974229040: reply ok 152 commit [|nfs]
13:05:15.331788 mayotte.2991006256 > borneo.nfs: 148 commit fh 0,12/1931 0 bytes @ 741376 (DF)
Here a DIAGNOSTIC kernel will panic with:
panic: kernel diagnostic assertion "startoff < endoff || endoff == 0" failed: file "/home/NetBSD-1.6/src/sys/arch/i386/compile/GENERIC_DIAGNOSTIC/../../../../miscfs/genfs/genfs_vnops.c", line 1041

This is because nfsrv_commit() will call VOP_FSYNC() with start == end, so
we end up with startoff == endoff in genfs_vnops.c.

I fixed it by not calling VOP_FSYNC() in nfsrv_commit() when cnt == 0.
Is this the correct fix ?

--
Manuel Bouyer, LIP6, Universite Paris VI.           Manuel.Bouyer@lip6.fr
--

--M9NhX3UHpAaciwkO
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.nfs1"

Index: nfs/nfs_serv.c
===================================================================
RCS file: /cvsroot/syssrc/sys/nfs/nfs_serv.c,v
retrieving revision 1.62
diff -u -r1.62 nfs_serv.c
--- nfs_serv.c	2001/11/10 10:59:09	1.62
+++ nfs_serv.c	2002/09/26 11:29:17
@@ -3010,7 +3010,8 @@
 		return (0);
 	}
 	for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
-	error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, off + cnt, procp);
+	if (cnt > 0)
+		error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, off + cnt, procp);
 	aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
 	vput(vp);
 	nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);

--M9NhX3UHpAaciwkO--