FreeBSD/sys/kern/vfs_vnops.c
/*
 * Helper function to perform the requested uiomove operation using
 * the held pages for io->uio_iov[0].iov_base buffer instead of
 * copyin/copyout.  Access to the pages with uiomove_fromphys()
 * instead of iov_base prevents page faults that could occur due to
 * pmap_collect() invalidating the mapping created by
 * vm_fault_quick_hold_pages(), or pageout daemon, page laundry or
 * object cleanup revoking the write access from page mappings.
 *
 * Filesystems specified MNTK_NO_IOPF shall use vn_io_fault_uiomove()
 * instead of plain uiomove().
 */
Helper function to perform the requested uiomove operation using
the held pages for io->uio_iov[0].iov_base buffer instead of
copyin/copyout.  Access to the pages with uiomove_fromphys()
instead of iov_base prevents page faults that could occur due to
pmap_collect() invalidating the mapping created by
vm_fault_quick_hold_pages(), or pageout daemon, page laundry or
object cleanup revoking the write access from page mappings.

Filesystems specified MNTK_NO_IOPF shall use vn_io_fault_uiomove()
instead of plain uiomove().
Helper function to perform the requested uiomove operation using the held pages for io - > uio_iov [ 0 ] . iov_base buffer instead of copyin / copyout . Access to the pages with uiomove_fromphys () instead of iov_base prevents page faults that could occur due to pmap_collect () invalidating the mapping created by vm_fault_quick_hold_pages () or pageout daemon page laundry or object cleanup revoking the write access from page mappings . Filesystems specified MNTK_NO_IOPF shall use vn_io_fault_uiomove () instead of plain uiomove () .
int
vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio)
{
	struct uio transp_uio;
	struct iovec transp_iov[1];
	struct thread *td;
	size_t adv;
	int error, pgadv;
	td = curthread;
	if ((td->td_pflags & TDP_UIOHELD) == 0 ||
	    uio->uio_segflg != UIO_USERSPACE)
		return (uiomove(data, xfersize, uio));
	KASSERT(uio->uio_iovcnt == 1, ("uio_iovcnt %d", uio->uio_iovcnt));
	transp_iov[0].iov_base = data;
	transp_uio.uio_iov = &transp_iov[0];
	transp_uio.uio_iovcnt = 1;
	if (xfersize > uio->uio_resid)
		xfersize = uio->uio_resid;
	transp_uio.uio_resid = transp_iov[0].iov_len = xfersize;
	transp_uio.uio_offset = 0;
	transp_uio.uio_segflg = UIO_SYSSPACE;
	switch (uio->uio_rw) {
	case UIO_WRITE:
		transp_uio.uio_rw = UIO_READ;
		break;
	case UIO_READ:
		transp_uio.uio_rw = UIO_WRITE;
		break;
	}
	transp_uio.uio_td = uio->uio_td;
	error = uiomove_fromphys(td->td_ma,
	    ((vm_offset_t)uio->uio_iov->iov_base) & PAGE_MASK,
	    xfersize, &transp_uio);
	adv = xfersize - transp_uio.uio_resid;
	pgadv =
	    (((vm_offset_t)uio->uio_iov->iov_base + adv) >> PAGE_SHIFT) -
	    (((vm_offset_t)uio->uio_iov->iov_base) >> PAGE_SHIFT);
	td->td_ma += pgadv;
	KASSERT(td->td_ma_cnt >= pgadv, ("consumed pages %d %d", td->td_ma_cnt,
	    pgadv));
	td->td_ma_cnt -= pgadv;
	uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + adv;
	uio->uio_iov->iov_len -= adv;
	uio->uio_resid -= adv;
	uio->uio_offset += adv;
	return (error);
}
int vn_io_fault_uiomove ( char * data , int xfersize , struct uio * uio ) { struct uio transp_uio ; struct iovec transp_iov [ 1 ] ; struct thread * td ; size_t adv ; int error , pgadv ; td = curthread ; if ( ( td -> td_pflags & TDP_UIOHELD ) == 0 || uio -> uio_segflg != UIO_USERSPACE ) return ( uiomove ( data , xfersize , uio ) ) ; KASSERT ( uio -> uio_iovcnt == 1 , ( " " , uio -> uio_iovcnt ) ) ; transp_iov [ 0 ] . iov_base = data ; transp_uio . uio_iov = & transp_iov [ 0 ] ; transp_uio . uio_iovcnt = 1 ; if ( xfersize > uio -> uio_resid ) xfersize = uio -> uio_resid ; transp_uio . uio_resid = transp_iov [ 0 ] . iov_len = xfersize ; transp_uio . uio_offset = 0 ; transp_uio . uio_segflg = UIO_SYSSPACE ; switch ( uio -> uio_rw ) { case UIO_WRITE : transp_uio . uio_rw = UIO_READ ; break ; case UIO_READ : transp_uio . uio_rw = UIO_WRITE ; break ; } transp_uio . uio_td = uio -> uio_td ; error = uiomove_fromphys ( td -> td_ma , ( ( vm_offset_t ) uio -> uio_iov -> iov_base ) & PAGE_MASK , xfersize , & transp_uio ) ; adv = xfersize - transp_uio . uio_resid ; pgadv = ( ( ( vm_offset_t ) uio -> uio_iov -> iov_base + adv ) >> PAGE_SHIFT ) - ( ( ( vm_offset_t ) uio -> uio_iov -> iov_base ) >> PAGE_SHIFT ) ; td -> td_ma += pgadv ; KASSERT ( td -> td_ma_cnt >= pgadv , ( " " , td -> td_ma_cnt , pgadv ) ) ; td -> td_ma_cnt -= pgadv ; uio -> uio_iov -> iov_base = ( char * ) uio -> uio_iov -> iov_base + adv ; uio -> uio_iov -> iov_len -= adv ; uio -> uio_resid -= adv ; uio -> uio_offset += adv ; return ( error ) ; }
Helper function to perform the requested uiomove operation using
 the held pages for io->uio_iov[0].iov_base buffer instead of
 copyin/copyout.
Helper function to perform the requested uiomove operation using the held pages for io - > uio_iov [ 0 ] . iov_base buffer instead of copyin / copyout .
/*
	 * Since transp_iov points to data, and td_ma page array
	 * corresponds to original uio->uio_iov, we need to invert the
	 * direction of the i/o operation as passed to
	 * uiomove_fromphys().
	 */