FreeBSD/sys/fs/nfsclient/nfs_clbio.c
/*
 * Vnode op for VM putpages.
 */
Vnode op for VM putpages.
Vnode op for VM putpages .
int
ncl_putpages(struct vop_putpages_args *ap)
{
	struct uio uio;
	struct iovec iov;
	vm_offset_t kva;
	struct buf *bp;
	int iomode, must_commit, i, error, npages, count;
	off_t offset;
	int *rtvals;
	struct vnode *vp;
	struct thread *td;
	struct ucred *cred;
	struct nfsmount *nmp;
	struct nfsnode *np;
	vm_page_t *pages;
	vp = ap->a_vp;
	np = VTONFS(vp);
	td = curthread;				
	if (np->n_writecred != NULL)
		cred = crhold(np->n_writecred);
	else
		cred = crhold(curthread->td_ucred);	
	nmp = VFSTONFS(vp->v_mount);
	pages = ap->a_m;
	count = ap->a_count;
	rtvals = ap->a_rtvals;
	npages = btoc(count);
	offset = IDX_TO_OFF(pages[0]->pindex);
	mtx_lock(&nmp->nm_mtx);
	if ((nmp->nm_flag & NFSMNT_NFSV3) != 0 &&
	    (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
		mtx_unlock(&nmp->nm_mtx);
		(void)ncl_fsinfo(nmp, vp, cred, td);
	} else
		mtx_unlock(&nmp->nm_mtx);
	mtx_lock(&np->n_mtx);
	if (newnfs_directio_enable && !newnfs_directio_allow_mmap &&
	    (np->n_flag & NNONCACHE) && (vp->v_type == VREG)) {
		mtx_unlock(&np->n_mtx);
		printf("ncl_putpages: called on noncache-able vnode\n");
		mtx_lock(&np->n_mtx);
	}
	for (i = 0; i < npages; i++)
		rtvals[i] = VM_PAGER_ERROR;
	if (offset + count > np->n_size) {
		count = np->n_size - offset;
		if (count < 0)
			count = 0;
	}
	mtx_unlock(&np->n_mtx);
	bp = getpbuf(&ncl_pbuf_freecnt);
	kva = (vm_offset_t) bp->b_data;
	pmap_qenter(kva, pages, npages);
	PCPU_INC(cnt.v_vnodeout);
	PCPU_ADD(cnt.v_vnodepgsout, count);
	iov.iov_base = (caddr_t) kva;
	iov.iov_len = count;
	uio.uio_iov = &iov;
	uio.uio_iovcnt = 1;
	uio.uio_offset = offset;
	uio.uio_resid = count;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_rw = UIO_WRITE;
	uio.uio_td = td;
	if ((ap->a_sync & VM_PAGER_PUT_SYNC) == 0)
	    iomode = NFSWRITE_UNSTABLE;
	else
	    iomode = NFSWRITE_FILESYNC;
	error = ncl_writerpc(vp, &uio, cred, &iomode, &must_commit, 0);
	crfree(cred);
	pmap_qremove(kva, npages);
	relpbuf(bp, &ncl_pbuf_freecnt);
	if (error == 0 || !nfs_keep_dirty_on_error) {
		vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
		if (must_commit)
			ncl_clearcommit(vp->v_mount);
	}
	return rtvals[0];
}
int ncl_putpages ( struct vop_putpages_args * ap ) { struct uio uio ; struct iovec iov ; vm_offset_t kva ; struct buf * bp ; int iomode , must_commit , i , error , npages , count ; off_t offset ; int * rtvals ; struct vnode * vp ; struct thread * td ; struct ucred * cred ; struct nfsmount * nmp ; struct nfsnode * np ; vm_page_t * pages ; vp = ap -> a_vp ; np = VTONFS ( vp ) ; td = curthread ; if ( np -> n_writecred != NULL ) cred = crhold ( np -> n_writecred ) ; else cred = crhold ( curthread -> td_ucred ) ; nmp = VFSTONFS ( vp -> v_mount ) ; pages = ap -> a_m ; count = ap -> a_count ; rtvals = ap -> a_rtvals ; npages = btoc ( count ) ; offset = IDX_TO_OFF ( pages [ 0 ] -> pindex ) ; mtx_lock ( & nmp -> nm_mtx ) ; if ( ( nmp -> nm_flag & NFSMNT_NFSV3 ) != 0 && ( nmp -> nm_state & NFSSTA_GOTFSINFO ) == 0 ) { mtx_unlock ( & nmp -> nm_mtx ) ; ( void ) ncl_fsinfo ( nmp , vp , cred , td ) ; } else mtx_unlock ( & nmp -> nm_mtx ) ; mtx_lock ( & np -> n_mtx ) ; if ( newnfs_directio_enable && ! newnfs_directio_allow_mmap && ( np -> n_flag & NNONCACHE ) && ( vp -> v_type == VREG ) ) { mtx_unlock ( & np -> n_mtx ) ; printf ( " \n " ) ; mtx_lock ( & np -> n_mtx ) ; } for ( i = 0 ; i < npages ; i ++ ) rtvals [ i ] = VM_PAGER_ERROR ; if ( offset + count > np -> n_size ) { count = np -> n_size - offset ; if ( count < 0 ) count = 0 ; } mtx_unlock ( & np -> n_mtx ) ; bp = getpbuf ( & ncl_pbuf_freecnt ) ; kva = ( vm_offset_t ) bp -> b_data ; pmap_qenter ( kva , pages , npages ) ; PCPU_INC ( cnt . v_vnodeout ) ; PCPU_ADD ( cnt . v_vnodepgsout , count ) ; iov . iov_base = ( caddr_t ) kva ; iov . iov_len = count ; uio . uio_iov = & iov ; uio . uio_iovcnt = 1 ; uio . uio_offset = offset ; uio . uio_resid = count ; uio . uio_segflg = UIO_SYSSPACE ; uio . uio_rw = UIO_WRITE ; uio . uio_td = td ; if ( ( ap -> a_sync & VM_PAGER_PUT_SYNC ) == 0 ) iomode = NFSWRITE_UNSTABLE ; else iomode = NFSWRITE_FILESYNC ; error = ncl_writerpc ( vp , & uio , cred , & iomode , & must_commit , 0 ) ; crfree ( cred ) ; pmap_qremove ( kva , npages ) ; relpbuf ( bp , & ncl_pbuf_freecnt ) ; if ( error == 0 || ! nfs_keep_dirty_on_error ) { vnode_pager_undirty_pages ( pages , rtvals , count - uio . uio_resid ) ; if ( must_commit ) ncl_clearcommit ( vp -> v_mount ) ; } return rtvals [ 0 ] ; }
Vnode op for VM putpages.
Vnode op for VM putpages .
/* XXX */ /* Set the cred to n_writecred for the write rpcs. */ /* XXX */ /*
	 * When putting pages, do not extend file past EOF.
	 */ /*
	 * We use only the kva address for the buffer, but this is extremely
	 * convenient and fast.
	 */