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:
parent
c8b59ea750
commit
5f5f055441
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248319
@ -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.
|
||||
*/
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user