FreeBSD/sys/fs/nfsserver/nfs_nfsdport.c
/*
 * Do the fsync() appropriate for the commit.
 */
Do the fsync() appropriate for the commit.
Do the fsync () appropriate for the commit .
int
nfsvno_fsync(struct vnode *vp, u_int64_t off, int cnt, struct ucred *cred,
    struct thread *td)
{
	int error = 0;
	if (cnt == 0 || cnt > MAX_COMMIT_COUNT ||
	    (vp->v_mount->mnt_kern_flag & MNTK_USES_BCACHE) == 0) {
		if (vp->v_object &&
		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
			VM_OBJECT_WLOCK(vp->v_object);
			vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
			VM_OBJECT_WUNLOCK(vp->v_object);
		}
		error = VOP_FSYNC(vp, MNT_WAIT, td);
	} else {
		int iosize = vp->v_mount->mnt_stat.f_iosize;
		int iomask = iosize - 1;
		struct bufobj *bo;
		daddr_t lblkno;
		if (off & iomask) {
			cnt += off & iomask;
			off &= ~(u_quad_t)iomask;
		}
		if (off & PAGE_MASK) {
			cnt += off & PAGE_MASK;
			off &= ~(u_quad_t)PAGE_MASK;
		}
		lblkno = off / iosize;
		if (vp->v_object &&
		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
			VM_OBJECT_WLOCK(vp->v_object);
			vm_object_page_clean(vp->v_object, off, off + cnt,
			    OBJPC_SYNC);
			VM_OBJECT_WUNLOCK(vp->v_object);
		}
		bo = &vp->v_bufobj;
		BO_LOCK(bo);
		while (cnt > 0) {
			struct buf *bp;
			if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
				if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
				    LK_INTERLOCK, BO_LOCKPTR(bo)) == ENOLCK) {
					BO_LOCK(bo);
					continue; 
				}
			    	if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
				    B_DELWRI) {
					bremfree(bp);
					bp->b_flags &= ~B_ASYNC;
					bwrite(bp);
					++nfs_commit_miss;
				} else
					BUF_UNLOCK(bp);
				BO_LOCK(bo);
			}
			++nfs_commit_blks;
			if (cnt < iosize)
				break;
			cnt -= iosize;
			++lblkno;
		}
		BO_UNLOCK(bo);
	}
	NFSEXITCODE(error);
	return (error);
}
int nfsvno_fsync ( struct vnode * vp , u_int64_t off , int cnt , struct ucred * cred , struct thread * td ) { int error = 0 ; if ( cnt == 0 || cnt > MAX_COMMIT_COUNT || ( vp -> v_mount -> mnt_kern_flag & MNTK_USES_BCACHE ) == 0 ) { if ( vp -> v_object && ( vp -> v_object -> flags & OBJ_MIGHTBEDIRTY ) ) { VM_OBJECT_WLOCK ( vp -> v_object ) ; vm_object_page_clean ( vp -> v_object , 0 , 0 , OBJPC_SYNC ) ; VM_OBJECT_WUNLOCK ( vp -> v_object ) ; } error = VOP_FSYNC ( vp , MNT_WAIT , td ) ; } else { int iosize = vp -> v_mount -> mnt_stat . f_iosize ; int iomask = iosize - 1 ; struct bufobj * bo ; daddr_t lblkno ; if ( off & iomask ) { cnt += off & iomask ; off &= ~ ( u_quad_t ) iomask ; } if ( off & PAGE_MASK ) { cnt += off & PAGE_MASK ; off &= ~ ( u_quad_t ) PAGE_MASK ; } lblkno = off / iosize ; if ( vp -> v_object && ( vp -> v_object -> flags & OBJ_MIGHTBEDIRTY ) ) { VM_OBJECT_WLOCK ( vp -> v_object ) ; vm_object_page_clean ( vp -> v_object , off , off + cnt , OBJPC_SYNC ) ; VM_OBJECT_WUNLOCK ( vp -> v_object ) ; } bo = & vp -> v_bufobj ; BO_LOCK ( bo ) ; while ( cnt > 0 ) { struct buf * bp ; if ( ( bp = gbincore ( & vp -> v_bufobj , lblkno ) ) != NULL ) { if ( BUF_LOCK ( bp , LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK , BO_LOCKPTR ( bo ) ) == ENOLCK ) { BO_LOCK ( bo ) ; continue ; } if ( ( bp -> b_flags & ( B_DELWRI | B_INVAL ) ) == B_DELWRI ) { bremfree ( bp ) ; bp -> b_flags &= ~ B_ASYNC ; bwrite ( bp ) ; ++ nfs_commit_miss ; } else BUF_UNLOCK ( bp ) ; BO_LOCK ( bo ) ; } ++ nfs_commit_blks ; if ( cnt < iosize ) break ; cnt -= iosize ; ++ lblkno ; } BO_UNLOCK ( bo ) ; } NFSEXITCODE ( error ) ; return ( error ) ; }
Do the fsync() appropriate for the commit.
Do the fsync () appropriate for the commit .
/*
	 * RFC 1813 3.3.21: if count is 0, a flush from offset to the end of
	 * file is done.  At this time VOP_FSYNC does not accept offset and
	 * byte count parameters so call VOP_FSYNC the whole file for now.
	 * The same is true for NFSv4: RFC 3530 Sec. 14.2.3.
	 * File systems that do not use the buffer cache (as indicated
	 * by MNTK_USES_BCACHE not being set) must use VOP_FSYNC().
	 */ /*
		 * Give up and do the whole thing
		 */ /*
		 * Locate and synchronously write any buffers that fall
		 * into the requested range.  Note:  we are assuming that
		 * f_iosize is a power of 2.
		 */ /*
		 * Align to iosize boundary, super-align to page boundary.
		 */ /*
			 * If we have a buffer and it is marked B_DELWRI we
			 * have to lock and write it.  Otherwise the prior
			 * write is assumed to have already been committed.
			 *
			 * gbincore() can return invalid buffers now so we
			 * have to check that bit as well (though B_DELWRI
			 * should not be set if B_INVAL is set there could be
			 * a race here since we haven't locked the buffer).
			 */ /* retry */