struct uvm_object *uobj = &vp->v_uobj; struct buf *bp;
register struct buf *bp;
vinvalbuf(vp, flags, cred, p, slpflag, slptimeo)	register struct vnode *vp;	int flags;	struct ucred *cred;	struct proc *p;	int slpflag, slptimeo;{	struct uvm_object *uobj = &vp->v_uobj;	struct buf *bp;	struct buf *nbp, *blist;	int s, error, rv;	int flushflags = PGO_ALLPAGES|PGO_FREE|PGO_SYNCIO|	    (flags & V_SAVE ? PGO_CLEANIT : 0);	/* XXXUBC this doesn't look at flags or slp* */	if (vp->v_type == VREG) {		simple_lock(&uobj->vmobjlock);		rv = (uobj->pgops->pgo_flush)(uobj, 0, 0, flushflags);		simple_unlock(&uobj->vmobjlock);		if (!rv) {			return EIO;		}	}	if (flags & V_SAVE) {		s = splbio();		vwaitforio(vp, 0, "vinvalbuf", 0);		if (vp->v_dirtyblkhd.lh_first != NULL) {			splx(s);			if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0)				return (error);			s = splbio();			if (vp->v_numoutput > 0 ||			    vp->v_dirtyblkhd.lh_first != NULL)				panic("vinvalbuf: dirty bufs");		}		splx(s);	}loop:	s = splbio();	for (;;) {		if ((blist = vp->v_cleanblkhd.lh_first) &&		    (flags & V_SAVEMETA))			while (blist && blist->b_lblkno < 0)				blist = blist->b_vnbufs.le_next;		if (!blist && (blist = vp->v_dirtyblkhd.lh_first) &&		    (flags & V_SAVEMETA))			while (blist && blist->b_lblkno < 0)				blist = blist->b_vnbufs.le_next;		if (!blist)			break;		for (bp = blist; bp; bp = nbp) {			nbp = bp->b_vnbufs.le_next;			if (flags & V_SAVEMETA && bp->b_lblkno < 0)				continue;			if (bp->b_flags & B_BUSY) {				bp->b_flags |= B_WANTED;				error = tsleep((caddr_t)bp,					slpflag | (PRIBIO + 1), "vinvalbuf",					slptimeo);				if (error) {					splx(s);					return (error);				}				break;			}			bremfree(bp);			bp->b_flags |= B_BUSY;			/*			 * XXX Since there are no node locks for NFS, I believe			 * there is a slight chance that a delayed write will			 * occur while sleeping just above, so check for it.			 */			if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {				splx(s);				(void) VOP_BWRITE(bp);				goto loop;			}			bp->b_flags |= B_INVAL;			brelse(bp);		}	}	if (!(flags & V_SAVEMETA) &&	    (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))		panic("vinvalbuf: flush failed");	splx(s);	return (0);}