Implement the helper function vn_io_fault_pgmove(), intended to use by

the filesystem VOP_READ() and VOP_WRITE() implementations in the same
way as vn_io_fault_uiomove() over the unmapped buffers.  Helper
provides the convenient wrapper over the pmap_copy_pages() for struct
uio consumers, taking care of the TDP_UIOHELD situations.

Sponsored by:	The FreeBSD Foundation
Tested by:	pho
MFC after:	2 weeks
This commit is contained in:
Konstantin Belousov 2013-03-15 11:16:12 +00:00
parent c8b59ea750
commit 5f5f055441
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248319
2 changed files with 41 additions and 0 deletions

View File

@ -1122,6 +1122,45 @@ vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio)
return (error);
}
int
vn_io_fault_pgmove(vm_page_t ma[], vm_offset_t offset, int xfersize,
struct uio *uio)
{
struct thread *td;
vm_offset_t iov_base;
int cnt, pgadv;
td = curthread;
if ((td->td_pflags & TDP_UIOHELD) == 0 ||
uio->uio_segflg != UIO_USERSPACE)
return (uiomove_fromphys(ma, offset, xfersize, uio));
KASSERT(uio->uio_iovcnt == 1, ("uio_iovcnt %d", uio->uio_iovcnt));
cnt = xfersize > uio->uio_resid ? uio->uio_resid : xfersize;
iov_base = (vm_offset_t)uio->uio_iov->iov_base;
switch (uio->uio_rw) {
case UIO_WRITE:
pmap_copy_pages(td->td_ma, iov_base & PAGE_MASK, ma,
offset, cnt);
break;
case UIO_READ:
pmap_copy_pages(ma, offset, td->td_ma, iov_base & PAGE_MASK,
cnt);
break;
}
pgadv = ((iov_base + cnt) >> PAGE_SHIFT) - (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 *)(iov_base + cnt);
uio->uio_iov->iov_len -= cnt;
uio->uio_resid -= cnt;
uio->uio_offset += cnt;
return (0);
}
/*
* File table truncate routine.
*/

View File

@ -693,6 +693,8 @@ int vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags,
struct vnode **rvp);
int vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio);
int vn_io_fault_pgmove(vm_page_t ma[], vm_offset_t offset, int xfersize,
struct uio *uio);
#define vn_rangelock_unlock(vp, cookie) \
rangelock_unlock(&(vp)->v_rl, (cookie), VI_MTX(vp))