Subject: a couple of bug-fixes for nfs
To: None <freebsd-bugs@FreeBSD.org>
From: None <rick@snowhite.cis.uoguelph.ca>
List: netbsd-bugs
Date: 01/09/1995 21:56:09
Hi,

Here are a couple of nfs related bugs/fixes for FreeBSD2.0R. I don't know if
they also apply to -current or NetBSD or any of the other 4.4BSD-Lite based
systems. The first is a missing brelse() call for an uncommon case during
read-ahead and the second fixes two problems with respect to conversion
to/from the nfs v2 time structure handling microseconds.

The diff -c's are for FreeBSD2.0R, so your line numbers may vary. (I have
not tested these fixes that extensively, but they both seem pretty obvious, so..)

Have fun with it, rick
---- diff -c's -----
*** nfs_bio.c.bak	Mon Jan  9 15:43:57 1995
--- nfs_bio.c	Mon Jan  9 15:45:55 1995
***************
*** 212,232 ****
  			if (!incore(vp, rabn)) {
  			    rabp = nfs_getcacheblk(vp, rabn, biosize, p);
  			    if (!rabp)
  				return (EINTR);
  			    if ((rabp->b_flags & (B_DELWRI | B_DONE)) == 0) {
  				rabp->b_flags |= (B_READ | B_ASYNC);
  				if (nfs_asyncio(rabp, cred)) {
  				    rabp->b_flags |= B_INVAL;
  				    brelse(rabp);
  				}
! 			    }
  			}
  		    }
  		}
  
  		/*
  		 * If the block is in the cache and has the required data
  		 * in a valid region, just copy it out.
  		 * Otherwise, get the block and write back/read in,
  		 * as required.
  		 */
--- 212,233 ----
  			if (!incore(vp, rabn)) {
  			    rabp = nfs_getcacheblk(vp, rabn, biosize, p);
  			    if (!rabp)
  				return (EINTR);
  			    if ((rabp->b_flags & (B_DELWRI | B_DONE)) == 0) {
  				rabp->b_flags |= (B_READ | B_ASYNC);
  				if (nfs_asyncio(rabp, cred)) {
  				    rabp->b_flags |= B_INVAL;
  				    brelse(rabp);
  				}
! 			    } else
! 				brelse(rabp);
  			}
  		    }
  		}
  
  		/*
  		 * If the block is in the cache and has the required data
  		 * in a valid region, just copy it out.
  		 * Otherwise, get the block and write back/read in,
  		 * as required.
  		 */
***************
*** 320,340 ****
  		    rabn != 0 && rabn != np->n_direofoffset &&
  		    !incore(vp, rabn)) {
  			rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
  			if (rabp) {
  			    if ((rabp->b_flags & (B_DONE | B_DELWRI)) == 0) {
  				rabp->b_flags |= (B_READ | B_ASYNC);
  				if (nfs_asyncio(rabp, cred)) {
  				    rabp->b_flags |= B_INVAL;
  				    brelse(rabp);
  				}
! 			    }
  			}
  		}
  		on = 0;
  		n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
  		got_buf = 1;
  		break;
  	    default:
  		printf(" nfsbioread: type %x unexpected\n",vp->v_type);
  		break;
  	    };
--- 321,342 ----
  		    rabn != 0 && rabn != np->n_direofoffset &&
  		    !incore(vp, rabn)) {
  			rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
  			if (rabp) {
  			    if ((rabp->b_flags & (B_DONE | B_DELWRI)) == 0) {
  				rabp->b_flags |= (B_READ | B_ASYNC);
  				if (nfs_asyncio(rabp, cred)) {
  				    rabp->b_flags |= B_INVAL;
  				    brelse(rabp);
  				}
! 			    } else
! 				brelse(rabp);
  			}
  		}
  		on = 0;
  		n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
  		got_buf = 1;
  		break;
  	    default:
  		printf(" nfsbioread: type %x unexpected\n",vp->v_type);
  		break;
  	    };
*** xdr_subs.h.bak	Mon Jan  9 16:37:36 1995
--- xdr_subs.h	Mon Jan  9 16:39:51 1995
***************
*** 49,73 ****
   * machines, and count on them being `#define'd away.  Some of these
   * might be slightly more efficient as quad_t copies on a big-endian,
   * but we cannot count on their alignment anyway.
   */
  
  #define	fxdr_unsigned(t, v)	((t)ntohl((long)(v)))
  #define	txdr_unsigned(v)	(htonl((long)(v)))
  
  #define	fxdr_nfstime(f, t) { \
  	(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfs_sec); \
! 	(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfs_usec); \
  }
  #define	txdr_nfstime(f, t) { \
  	((struct nfsv2_time *)(t))->nfs_sec = htonl((f)->ts_sec); \
! 	((struct nfsv2_time *)(t))->nfs_usec = htonl((f)->ts_nsec) / 1000; \
  }
  
  #define	fxdr_nqtime(f, t) { \
  	(t)->ts_sec = ntohl(((struct nqnfs_time *)(f))->nq_sec); \
  	(t)->ts_nsec = ntohl(((struct nqnfs_time *)(f))->nq_nsec); \
  }
  #define	txdr_nqtime(f, t) { \
  	((struct nqnfs_time *)(t))->nq_sec = htonl((f)->ts_sec); \
  	((struct nqnfs_time *)(t))->nq_nsec = htonl((f)->ts_nsec); \
  }
--- 49,79 ----
   * machines, and count on them being `#define'd away.  Some of these
   * might be slightly more efficient as quad_t copies on a big-endian,
   * but we cannot count on their alignment anyway.
   */
  
  #define	fxdr_unsigned(t, v)	((t)ntohl((long)(v)))
  #define	txdr_unsigned(v)	(htonl((long)(v)))
  
  #define	fxdr_nfstime(f, t) { \
  	(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfs_sec); \
! 	if (((struct nfsv2_time *)(f))->nfs_usec != 0xffffffff) \
! 		(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfs_usec); \
! 	else \
! 		(t)->ts_nsec = -1; \
  }
  #define	txdr_nfstime(f, t) { \
  	((struct nfsv2_time *)(t))->nfs_sec = htonl((f)->ts_sec); \
! 	if ((f)->ts_nsec != -1) \
! 		((struct nfsv2_time *)(t))->nfs_usec = htonl((f)->ts_nsec / 1000); \
! 	else \
! 		((struct nfsv2_time *)(t))->nfs_usec = 0xffffffff; \
  }
  
  #define	fxdr_nqtime(f, t) { \
  	(t)->ts_sec = ntohl(((struct nqnfs_time *)(f))->nq_sec); \
  	(t)->ts_nsec = ntohl(((struct nqnfs_time *)(f))->nq_nsec); \
  }
  #define	txdr_nqtime(f, t) { \
  	((struct nqnfs_time *)(t))->nq_sec = htonl((f)->ts_sec); \
  	((struct nqnfs_time *)(t))->nq_nsec = htonl((f)->ts_nsec); \
  }