register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); register struct buf *bp; struct buf *nbp; struct nfsmount *nmp; int s, error = 0, slptimeo = 0, slpflag = 0;
nfs_fsync(v)	void *v;{	struct vop_fsync_args /* {		struct vnodeop_desc *a_desc;		struct vnode * a_vp;		struct ucred * a_cred;		int  a_waitfor;		struct proc * a_p;	} */ *ap = v;	register struct vnode *vp = ap->a_vp;	register struct nfsnode *np = VTONFS(vp);	register struct buf *bp;	struct buf *nbp;	struct nfsmount *nmp;	int s, error = 0, slptimeo = 0, slpflag = 0;	nmp = VFSTONFS(vp->v_mount);	if (nmp->nm_flag & NFSMNT_INT)		slpflag = PCATCH;loop:	s = splbio();	for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {		nbp = bp->b_vnbufs.le_next;		if (bp->b_flags & B_BUSY) {			if (ap->a_waitfor != MNT_WAIT)				continue;			bp->b_flags |= B_WANTED;			error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1),				"nfsfsync", slptimeo);			splx(s);			if (error) {			    if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p))				return (EINTR);			    if (slpflag == PCATCH) {				slpflag = 0;				slptimeo = 2 * hz;			    }			}			goto loop;		}		if ((bp->b_flags & B_DELWRI) == 0)			panic("nfs_fsync: not dirty");		bremfree(bp);		bp->b_flags |= B_BUSY;		splx(s);		bp->b_flags |= B_ASYNC;		VOP_BWRITE(bp);		goto loop;	}	splx(s);	if (ap->a_waitfor == MNT_WAIT) {		while (vp->v_numoutput) {			vp->v_flag |= VBWAIT;			error = tsleep((caddr_t)&vp->v_numoutput,				slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);			if (error) {			    if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p))				return (EINTR);			    if (slpflag == PCATCH) {				slpflag = 0;				slptimeo = 2 * hz;			    }			}		}		if (vp->v_dirtyblkhd.lh_first) {#ifdef DIAGNOSTIC			vprint("nfs_fsync: dirty", vp);#endif			goto loop;		}	}	if (np->n_flag & NWRITEERR) {		error = np->n_error;		np->n_flag &= ~NWRITEERR;	}	return (error);}