FreeBSD/sys/kern/vfs_bio.c
/*
 * Write, release buffer on completion.  (Done by iodone
 * if async).  Do not bother writing anything if the buffer
 * is invalid.
 *
 * Note that we set B_CACHE here, indicating that buffer is
 * fully valid and thus cacheable.  This is true even of NFS
 * now so we set it generally.  This could be set either here 
 * or in biodone() since the I/O is synchronous.  We put it
 * here.
 */
Write, release buffer on completion.  (Done by iodone
if async).  Do not bother writing anything if the buffer
is invalid.

Note that we set B_CACHE here, indicating that buffer is
fully valid and thus cacheable.  This is true even of NFS
now so we set it generally.  This could be set either here
or in biodone() since the I/O is synchronous.  We put it
here.
Write release buffer on completion . ( Done by iodone if async ) . Do not bother writing anything if the buffer is invalid . Note that we set B_CACHE here indicating that buffer is fully valid and thus cacheable . This is true even of NFS now so we set it generally . This could be set either here or in biodone () since the I / O is synchronous . We put it here .
int
bufwrite(struct buf *bp)
{
	int oldflags;
	struct vnode *vp;
	long space;
	int vp_md;
	CTR3(KTR_BUF, "bufwrite(%p) vp %p flags %X", bp, bp->b_vp, bp->b_flags);
	if ((bp->b_bufobj->bo_flag & BO_DEAD) != 0) {
		bp->b_flags |= B_INVAL | B_RELBUF;
		bp->b_flags &= ~B_CACHE;
		brelse(bp);
		return (ENXIO);
	}
	if (bp->b_flags & B_INVAL) {
		brelse(bp);
		return (0);
	}
	if (bp->b_flags & B_BARRIER)
		barrierwrites++;
	oldflags = bp->b_flags;
	BUF_ASSERT_HELD(bp);
	if (bp->b_pin_count > 0)
		bunpin_wait(bp);
	KASSERT(!(bp->b_vflags & BV_BKGRDINPROG),
	    ("FFS background buffer should not get here %p", bp));
	vp = bp->b_vp;
	if (vp)
		vp_md = vp->v_vflag & VV_MD;
	else
		vp_md = 0;
	bufobj_wref(bp->b_bufobj);
	bundirty(bp);
	bp->b_flags &= ~B_DONE;
	bp->b_ioflags &= ~BIO_ERROR;
	bp->b_flags |= B_CACHE;
	bp->b_iocmd = BIO_WRITE;
	vfs_busy_pages(bp, 1);
	bp->b_runningbufspace = bp->b_bufsize;
	space = atomic_fetchadd_long(&runningbufspace, bp->b_runningbufspace);
	if (!TD_IS_IDLETHREAD(curthread)) {
#ifdef RACCT
		if (racct_enable) {
			PROC_LOCK(curproc);
			racct_add_buf(curproc, bp, 1);
			PROC_UNLOCK(curproc);
		}
#endif 
		curthread->td_ru.ru_oublock++;
	}
	if (oldflags & B_ASYNC)
		BUF_KERNPROC(bp);
	bp->b_iooffset = dbtob(bp->b_blkno);
	bstrategy(bp);
	if ((oldflags & B_ASYNC) == 0) {
		int rtval = bufwait(bp);
		brelse(bp);
		return (rtval);
	} else if (space > hirunningspace) {
		if ((curthread->td_pflags & TDP_NORUNNINGBUF) == 0 && !vp_md)
			waitrunningbufspace();
	}
	return (0);
}
int bufwrite ( struct buf * bp ) { int oldflags ; struct vnode * vp ; long space ; int vp_md ; CTR3 ( KTR_BUF , " " , bp , bp -> b_vp , bp -> b_flags ) ; if ( ( bp -> b_bufobj -> bo_flag & BO_DEAD ) != 0 ) { bp -> b_flags |= B_INVAL | B_RELBUF ; bp -> b_flags &= ~ B_CACHE ; brelse ( bp ) ; return ( ENXIO ) ; } if ( bp -> b_flags & B_INVAL ) { brelse ( bp ) ; return ( 0 ) ; } if ( bp -> b_flags & B_BARRIER ) barrierwrites ++ ; oldflags = bp -> b_flags ; BUF_ASSERT_HELD ( bp ) ; if ( bp -> b_pin_count > 0 ) bunpin_wait ( bp ) ; KASSERT ( ! ( bp -> b_vflags & BV_BKGRDINPROG ) , ( " " , bp ) ) ; vp = bp -> b_vp ; if ( vp ) vp_md = vp -> v_vflag & VV_MD ; else vp_md = 0 ; bufobj_wref ( bp -> b_bufobj ) ; bundirty ( bp ) ; bp -> b_flags &= ~ B_DONE ; bp -> b_ioflags &= ~ BIO_ERROR ; bp -> b_flags |= B_CACHE ; bp -> b_iocmd = BIO_WRITE ; vfs_busy_pages ( bp , 1 ) ; bp -> b_runningbufspace = bp -> b_bufsize ; space = atomic_fetchadd_long ( & runningbufspace , bp -> b_runningbufspace ) ; if ( ! TD_IS_IDLETHREAD ( curthread ) ) { #ifdef RACCT if ( racct_enable ) { PROC_LOCK ( curproc ) ; racct_add_buf ( curproc , bp , 1 ) ; PROC_UNLOCK ( curproc ) ; } #endif curthread -> td_ru . ru_oublock ++ ; } if ( oldflags & B_ASYNC ) BUF_KERNPROC ( bp ) ; bp -> b_iooffset = dbtob ( bp -> b_blkno ) ; bstrategy ( bp ) ; if ( ( oldflags & B_ASYNC ) == 0 ) { int rtval = bufwait ( bp ) ; brelse ( bp ) ; return ( rtval ) ; } else if ( space > hirunningspace ) { if ( ( curthread -> td_pflags & TDP_NORUNNINGBUF ) == 0 && ! vp_md ) waitrunningbufspace ( ) ; } return ( 0 ) ; }
Write, release buffer on completion.
Write release buffer on completion .
/*
	 * Mark the buffer clean.  Increment the bufobj write count
	 * before bundirty() call, to prevent other thread from seeing
	 * empty dirty list and zero counter for writes in progress,
	 * falsely indicating that the bufobj is clean.
	 */ /*
	 * Normal bwrites pipeline writes
	 */ /* RACCT */ /*
		 * don't allow the async write to saturate the I/O
		 * system.  We will not deadlock here because
		 * we are blocking waiting for I/O that is already in-progress
		 * to complete. We do not block here if it is the update
		 * or syncer daemon trying to clean up as that can lead
		 * to deadlock.
		 */