[comp.sys.ibm.pc.rt] Patch for NFS

brunner@bullhead.uucp (11/17/89)

Subject: Patch for NFS (MIT "hammerfix" posted as patch)
Index: /sys/nfs/nfs_server.c /sys/rpc/clnt_kudp.c /sys/sys/vfs_vnode.c

Description:
	This patch is equivalent to the files contained in the "hammerfix" 
	compressed tar image previously installed on ibmsupt. The fix is
	posted here as a forward context diff for the benefit of sites
	which may not have known about or applied the fix.
	
	A well known NFS problem that MIT found and fixed is the occasional
	zeroing out of blocks of information during internodal transmission.
	VERY simplistically, the problem is created when a block of data is
	retransmitted, due to loss or timeout. Certain operations, notably
	"open (with trucate)" were being performed more than once on a block,
	causing previously received data to be truncated, and hence lost.
	This would show up as loader errors, RCS errors, etc.
	
	Basically, some limited transmission state information has been
	added (in the form of a packet timestamp) to allow checking for
	whether a block is an original or a retransmission.

	The source code changes have been ifdef'd else NOMITFIX so that
	the fix code would be the default.

Fix:
	Apply the following patch to the files:

	/sys/nfs/nfs_server.c
	/sys/rpc/clnt_kudp.c
	/sys/sys/vfs_vnode.c

	Note that this may be accomplished easiest from /sys,
	passing the -p1 flag to patch, e.g.,

		patch -p1 < this_file


diff -r -c2 sys/nfs/nfs_server.c sys.fix/nfs/nfs_server.c
*** sys/nfs/nfs_server.c	Fri Dec  9 14:57:57 1988
--- sys.fix/nfs/nfs_server.c	Wed Oct 25 18:00:50 1989
***************
*** 1,12 ****
  /*
!  * 5799-WZQ (C) COPYRIGHT = NONE
   * LICENSED MATERIALS - PROPERTY OF IBM
   */
! /* $Header:nfs_server.c 12.0$ */
! /* $ACIS:nfs_server.c 12.0$ */
  /* $Source: /ibm/acis/usr/sys/nfs/RCS/nfs_server.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:nfs_server.c 12.0$";
  #endif
  
--- 1,11 ----
  /*
!  * P_R_P_Q_# (C) COPYRIGHT = NONE
   * LICENSED MATERIALS - PROPERTY OF IBM
   */
! /* $Header: nfs_server.c,v 12.2 89/01/11 18:40:35 rusty Exp $ */
  /* $Source: /ibm/acis/usr/sys/nfs/RCS/nfs_server.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: nfs_server.c,v 12.2 89/01/11 18:40:35 rusty Exp $";
  #endif
  
***************
*** 40,44 ****
  #include "nfs.h"
  #include "mbuf.h"
!  
  
  extern struct vnodeops nfs_vnodeops;
--- 39,46 ----
  #include "nfs.h"
  #include "mbuf.h"
! #ifdef NOMITFIX
! #else NOMITFIX
! #include "syslog.h"
! #endif NOMITFIX 
  
  extern struct vnodeops nfs_vnodeops;
***************
*** 605,608 ****
--- 607,616 ----
  	struct vnode *vp;
  	register struct vnode *dvp;
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ 	int found = 0;
+ 	int founderror;
+ 	int mismatch = 0;
+ #endif NOMITFIX
  
  #ifdef NFSDEBUG
***************
*** 650,653 ****
--- 658,662 ----
  		error = EROFS;
  	} else {
+ #ifdef NOMITFIX
  		error = VOP_CREATE(dvp, args->ca_da.da_name,
  		    &va, NONEXCL, VWRITE, &vp, u.u_cred);
***************
*** 662,665 ****
--- 671,740 ----
  		}
  	}
+ #else NOMITFIX
+ 	    struct vattr mod_va;
+ 	    if ((int)va.va_mtime.tv_sec != -1) {
+ 		/* Assume new client which breaks protocol spec.--
+ 		   Check mod. time to make sure it's still correct. */
+ 	        founderror = VOP_LOOKUP(dvp,
+                                         args->ca_da.da_name, &vp, u.u_cred);
+                 found = 1;
+                 if (!founderror) {
+                     error = VOP_GETATTR(vp, &mod_va, u.u_cred);
+                     if (!error) {
+                         if ((va.va_mtime.tv_sec != mod_va.va_mtime.tv_sec) ||
+                             (va.va_mtime.tv_usec != mod_va.va_mtime.tv_usec)) {
+                             log(LOG_DEBUG,
+                                 "rfs_create: modtime mismatch [%x %x] %ld.%ld %ld.%ld\n",
+                                  args->ca_da.da_fhandle.fh_fsid,
+                                  args->ca_da.da_fhandle.fh_len,
+                                  va.va_mtime.tv_sec, va.va_mtime.tv_usec,
+                                  mod_va.va_mtime.tv_sec,
+                                  mod_va.va_mtime.tv_usec);
+                              mismatch = 1;
+                              error = ESTALE; /* XXX */
+ 		        }
+ 		    }
+ 		}
+ 	   }
+ 	   
+ 	   /*
+ 	    * jtkohl@ATHENA.MIT.EDU:  Need to check for dup BEFORE
+ 	    * calling VOP_CREATE, since VOP_CREATE may truncate a file.
+ 	    * If retransmitted, and biod's/nfsd's scramble the ordering,
+ 	    * data can be lost.
+ 	    */
+ 	   /* 
+ 	    * check for dup request
+ 	    */
+ 	   if (svckudp_dup(req)) {
+ 	       if (!mismatch)
+ 		    log(LOG_DEBUG, "rfs_create: dup not mismatch[%x %x]\n",
+                                 args->ca_da.da_fhandle.fh_fsid,
+                                 args->ca_da.da_fhandle.fh_len);
+ 
+                 if (!found)
+                     error = VOP_LOOKUP(dvp,
+                                        args->ca_da.da_name, &vp, u.u_cred);
+                 else
+                     error = founderror;
+             } else {
+                 if (mismatch) {
+                     log(LOG_DEBUG, "rfs_create: mismatch not dup [%x %x]\n",
+                                 args->ca_da.da_fhandle.fh_fsid,
+                                 args->ca_da.da_fhandle.fh_len);
+                     if (!found)
+                         error = VOP_LOOKUP(dvp,
+                                            args->ca_da.da_name, &vp, u.u_cred);
+                     else
+                         error = founderror;
+                 } else
+                     if (found && !founderror)
+                         /* release vnode we looked up before */
+                         VN_RELE(vp);
+                     error = VOP_CREATE(dvp, args->ca_da.da_name,
+                                        &va, NONEXCL, VWRITE, &vp, u.u_cred);
+             }
+         }
+ #endif NOMITFIX
  	if (!error) {
  		error = VOP_GETATTR(vp, &va, u.u_cred);
diff -r -c2 sys/rpc/clnt_kudp.c sys.fix/rpc/clnt_kudp.c
*** sys/rpc/clnt_kudp.c	Fri Dec  9 14:58:26 1988
--- sys.fix/rpc/clnt_kudp.c	Wed Oct 25 18:01:44 1989
***************
*** 1,12 ****
  /*
!  * 5799-WZQ (C) COPYRIGHT = NONE
   * LICENSED MATERIALS - PROPERTY OF IBM
   */
! /* $Header:clnt_kudp.c 12.0$ */
! /* $ACIS:clnt_kudp.c 12.0$ */
  /* $Source: /ibm/acis/usr/sys/rpc/RCS/clnt_kudp.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header:clnt_kudp.c 12.0$";
  #endif
  
--- 1,11 ----
  /*
!  * P_R_P_Q_# (C) COPYRIGHT = NONE
   * LICENSED MATERIALS - PROPERTY OF IBM
   */
! /* $Header: clnt_kudp.c,v 12.2 89/01/11 18:31:55 rusty Exp $ */
  /* $Source: /ibm/acis/usr/sys/rpc/RCS/clnt_kudp.c,v $ */
  
  #ifndef lint
! static char *rcsid = "$Header: clnt_kudp.c,v 12.2 89/01/11 18:31:55 rusty Exp $";
  #endif
  
***************
*** 109,112 ****
--- 108,115 ----
  #define	CKU_BUFBUSY	0x008
  #define	CKU_BUFWANTED	0x010
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ #define CKU_ONCE_ONLY	0x020
+ #endif NOMITFIX
  
  /* Times to retry */
***************
*** 116,119 ****
--- 119,137 ----
  int	clntkudpxid;		/* transaction id used by all clients */
  
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ clntkudp_once(cl, flag)
+         CLIENT  *cl;
+ {
+         struct cku_private *p = (struct cku_private *)cl->cl_private;
+ 
+         if (flag != 0) {
+                 p->cku_flags |= CKU_ONCE_ONLY;
+         } else {
+                 p->cku_flags &= ~CKU_ONCE_ONLY;
+         }
+ }
+ #endif NOMITFIX
+ 
  static
  noop()
***************
*** 282,285 ****
--- 300,308 ----
  	p->cku_flags |= CKU_BUSY;
  
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ 	 if ((p->cku_flags & CKU_ONCE_ONLY) != 0)
+                 stries = 1;
+ #endif NOMITFIX
  	/*
  	 * Set credentials into the u structure
***************
*** 413,416 ****
--- 436,447 ----
  			rcstat.rcbadxids++;
  			m_freem(p->cku_inmbuf);
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ #ifdef RPCDEBUG
+                         rpc_debug(1, "callit: bad xid %d %d\n",
+                                   *((u_long *)(p->cku_inbuf)),
+                         *((u_long *)(p->cku_outbuf)));
+ #endif
+ #endif NOMITFIX
  			continue;
  		}
***************
*** 484,487 ****
--- 515,533 ----
  	}
  	u.u_cred = tmpcred;
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ 	/*
+          * Insure that buffer is not busy prior to releasing client handle.
+          */
+         s = splimp();
+         while (p->cku_flags & CKU_BUFBUSY) {
+                 p->cku_flags |= CKU_BUFWANTED;
+                 timeout(wakeup, (caddr_t)&p->cku_outbuf, hz);
+                 (void) sleep((caddr_t)&p->cku_outbuf, PZERO-3);
+                 sbflush(&so->so_rcv);
+         }
+         (void) splx(s);
+ #endif NOMITFIX
+ 
  	p->cku_flags &= ~CKU_BUSY;
  	if (p->cku_flags & CKU_WANTED) {
diff -r -c2 sys/sys/vfs_vnode.c sys.fix/sys/vfs_vnode.c
*** sys/sys/vfs_vnode.c	Fri Dec  9 15:07:22 1988
--- sys.fix/sys/vfs_vnode.c	Wed Oct 25 18:02:18 1989
***************
*** 1,13 ****
  /*
!  * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1988
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header:vfs_vnode.c 12.0$ */
! /* $ACIS:vfs_vnode.c 12.0$ */
  /* $Source: /ibm/acis/usr/sys/sys/RCS/vfs_vnode.c,v $ */
  
! #if !defined(lint) && !defined(NO_RCS_HDRS)
! static char *rcsid = "$Header:vfs_vnode.c 12.0$";
  #endif
  
--- 1,12 ----
  /*
!  * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988,1989
   * LICENSED MATERIALS - PROPERTY OF IBM
   * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
   */
! /* $Header: vfs_vnode.c,v 12.2 89/01/11 18:43:05 rusty Exp $ */
  /* $Source: /ibm/acis/usr/sys/sys/RCS/vfs_vnode.c,v $ */
  
! #if !defined (lint) && !defined(NO_RCS_HDRS)
! static char *rcsid = "$Header: vfs_vnode.c,v 12.2 89/01/11 18:43:05 rusty Exp $";
  #endif
  
***************
*** 105,108 ****
--- 104,111 ----
  	if (filemode & FCREAT) {
  		struct vattr vattr;
+ #ifdef NOMITFIX
+ #else NOMITFIX
+ 		struct vattr extra_vattr;
+ #endif NOMITFIX
  		enum vcexcl excl;
  
***************
*** 120,124 ****
  			excl = NONEXCL;
  		filemode &= ~(FCREAT | FTRUNC | FEXCL);
! 
  		error = vn_create(pnamep, seg, &vattr, excl, mode, &vp);
  		if (error)
--- 123,138 ----
  			excl = NONEXCL;
  		filemode &= ~(FCREAT | FTRUNC | FEXCL);
! #ifdef NOMITFIX
! #else NOMITFIX
! 		 /* Look it up first, and include mod. time in create request.*/
!                 error = lookupname(pnamep, seg, FOLLOW_LINK,
!                                    (struct vnode **)0, &vp);
!                 if (!error) {
!                         error = VOP_GETATTR(vp, &extra_vattr, u.u_cred);
!                         VN_RELE(vp);
!                         if (!error)
!                                 vattr.va_mtime = extra_vattr.va_mtime;
!                 }
! #endif NOMITFIX
  		error = vn_create(pnamep, seg, &vattr, excl, mode, &vp);
  		if (error)

Eric Brunner, Consultant, IBM AWD Palo Alto	(415) 855-4486
inet: brunner@monet.berkeley.edu
uucp: uunet!ibmsupt!brunner