int got_buf = 0, error = 0, n = 0, on = 0;
int got_buf = 0, nra, error = 0, n = 0, on = 0, not_readin;
nfs_bioread(vp, uio, ioflag, cred)	struct vnode *vp;	struct uio *uio;	int ioflag;	struct ucred *cred;{	struct nfsnode *np = VTONFS(vp);	int biosize;	struct buf *bp = NULL;	struct vattr vattr;	struct proc *p;	struct nfsmount *nmp = VFSTONFS(vp->v_mount);	caddr_t baddr;	int got_buf = 0, error = 0, n = 0, on = 0;#ifdef DIAGNOSTIC	if (uio->uio_rw != UIO_READ)		panic("nfs_read mode");#endif	if (uio->uio_resid == 0)		return (0);	if (uio->uio_offset < 0)		return (EINVAL);	p = uio->uio_procp;	if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)		(void)nfs_fsinfo(nmp, vp, cred, p);	biosize = nmp->nm_rsize;	/*	 * For nfs, cache consistency can only be maintained approximately.	 * Although RFC1094 does not specify the criteria, the following is	 * believed to be compatible with the reference port.	 * For nfs:	 * If the file's modify time on the server has changed since the	 * last read rpc or you have written to the file,	 * you may have lost data cache consistency with the	 * server, so flush all of the file's data out of the cache.	 * Then force a getattr rpc to ensure that you have up to date	 * attributes.	 * NB: This implies that cache data can be read when up to	 * NFS_ATTRTIMEO seconds out of date. If you find that you need current	 * attributes this could be forced by setting n_attrstamp to 0 before	 * the VOP_GETATTR() call.	 */	/* 	 * There is no way to modify a symbolic link via NFS or via	 * VFS, so we don't check if the link was modified 	 */	if (vp->v_type != VLNK) {		if (np->n_flag & NMODIFIED) {			np->n_attrstamp = 0;			error = VOP_GETATTR(vp, &vattr, cred, p);			if (error)				return (error);			np->n_mtime = vattr.va_mtime.tv_sec;		} else {			error = VOP_GETATTR(vp, &vattr, cred, p);			if (error)				return (error);			if (np->n_mtime != vattr.va_mtime.tv_sec) {				error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);				if (error)					return (error);				np->n_mtime = vattr.va_mtime.tv_sec;			}		}	}	/*	 * update the cache read creds for this vnode	 */	if (np->n_rcred)		crfree(np->n_rcred);	np->n_rcred = cred;	crhold(cred);	do {	    if ((vp->v_flag & VROOT) && vp->v_type == VLNK) {		    return (nfs_readlinkrpc(vp, uio, cred));	    }	    baddr = (caddr_t)0;	    switch (vp->v_type) {	    case VREG:		nfsstats.biocache_reads++;		error = 0;		while (uio->uio_resid > 0) {			void *win;			vsize_t bytelen = MIN(np->n_size - uio->uio_offset,					      uio->uio_resid);			if (bytelen == 0)				break;			win = ubc_alloc(&vp->v_uobj, uio->uio_offset,					&bytelen, UBC_READ);			error = uiomove(win, bytelen, uio);			ubc_release(win, 0);			if (error) {				break;			}		}		n = 0;		break;	    case VLNK:		nfsstats.biocache_readlinks++;		bp = nfs_getcacheblk(vp, (daddr_t)0, NFS_MAXPATHLEN, p);		if (!bp)			return (EINTR);		if ((bp->b_flags & B_DONE) == 0) {			bp->b_flags |= B_READ;			error = nfs_doio(bp, p);			if (error) {				brelse(bp);				return (error);			}		}		n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);		got_buf = 1;		on = 0;		break;	    default:		printf(" nfsbioread: type %x unexpected\n",vp->v_type);		break;	    }	    if (n > 0) {		if (!baddr)			baddr = bp->b_data;		error = uiomove(baddr + on, (int)n, uio);	    }	    switch (vp->v_type) {	    case VREG:		break;	    case VLNK:		n = 0;		break;	    default:		printf(" nfsbioread: type %x unexpected\n",vp->v_type);	    }	    if (got_buf)		brelse(bp);	} while (error == 0 && uio->uio_resid > 0 && n > 0);	return (error);}