FreeBSD/sys/fs/nfsclient/nfs_clbio.c
/*
 * Used to aid in handling ftruncate() operations on the NFS client side.
 * Truncation creates a number of special problems for NFS.  We have to
 * throw away VM pages and buffer cache buffers that are beyond EOF, and
 * we have to properly handle VM pages or (potentially dirty) buffers
 * that straddle the truncation point.
 */
Used to aid in handling ftruncate() operations on the NFS client side.
Truncation creates a number of special problems for NFS.  We have to
throw away VM pages and buffer cache buffers that are beyond EOF, and
we have to properly handle VM pages or (potentially dirty) buffers
that straddle the truncation point.
Used to aid in handling ftruncate () operations on the NFS client side . Truncation creates a number of special problems for NFS . We have to throw away VM pages and buffer cache buffers that are beyond EOF and we have to properly handle VM pages or ( potentially dirty ) buffers that straddle the truncation point .
int
ncl_meta_setsize(struct vnode *vp, struct ucred *cred, struct thread *td, u_quad_t nsize)
{
	struct nfsnode *np = VTONFS(vp);
	u_quad_t tsize;
	int biosize = vp->v_bufobj.bo_bsize;
	int error = 0;
	mtx_lock(&np->n_mtx);
	tsize = np->n_size;
	np->n_size = nsize;
	mtx_unlock(&np->n_mtx);
	if (nsize < tsize) {
		struct buf *bp;
		daddr_t lbn;
		int bufsize;
		error = vtruncbuf(vp, cred, nsize, biosize);
		lbn = nsize / biosize;
		bufsize = nsize - (lbn * biosize);
		bp = nfs_getcacheblk(vp, lbn, bufsize, td);
		if (!bp)
			return EINTR;
		if (bp->b_dirtyoff > bp->b_bcount)
			bp->b_dirtyoff = bp->b_bcount;
		if (bp->b_dirtyend > bp->b_bcount)
			bp->b_dirtyend = bp->b_bcount;
		bp->b_flags |= B_RELBUF;  
		brelse(bp);
	} else {
		vnode_pager_setsize(vp, nsize);
	}
	return(error);
}
int ncl_meta_setsize ( struct vnode * vp , struct ucred * cred , struct thread * td , u_quad_t nsize ) { struct nfsnode * np = VTONFS ( vp ) ; u_quad_t tsize ; int biosize = vp -> v_bufobj . bo_bsize ; int error = 0 ; mtx_lock ( & np -> n_mtx ) ; tsize = np -> n_size ; np -> n_size = nsize ; mtx_unlock ( & np -> n_mtx ) ; if ( nsize < tsize ) { struct buf * bp ; daddr_t lbn ; int bufsize ; error = vtruncbuf ( vp , cred , nsize , biosize ) ; lbn = nsize / biosize ; bufsize = nsize - ( lbn * biosize ) ; bp = nfs_getcacheblk ( vp , lbn , bufsize , td ) ; if ( ! bp ) return EINTR ; if ( bp -> b_dirtyoff > bp -> b_bcount ) bp -> b_dirtyoff = bp -> b_bcount ; if ( bp -> b_dirtyend > bp -> b_bcount ) bp -> b_dirtyend = bp -> b_bcount ; bp -> b_flags |= B_RELBUF ; brelse ( bp ) ; } else { vnode_pager_setsize ( vp , nsize ) ; } return ( error ) ; }
Used to aid in handling ftruncate() operations on the NFS client side.
Used to aid in handling ftruncate () operations on the NFS client side .
/*
		 * vtruncbuf() doesn't get the buffer overlapping the
		 * truncation point.  We may have a B_DELWRI and/or B_CACHE
		 * buffer that now needs to be truncated.
		 */ /* don't leave garbage around */