summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-03-15 11:16:12 +0000
committerkib <kib@FreeBSD.org>2013-03-15 11:16:12 +0000
commit9b5b993aea1b3a3be06fefb010355b869ce49aa8 (patch)
tree171c4b37d2331533580a57ec367eb78122d201b6 /sys
parenta10c1a7c72239c6be42dd7e90417b5caef91c8c7 (diff)
downloadFreeBSD-src-9b5b993aea1b3a3be06fefb010355b869ce49aa8.zip
FreeBSD-src-9b5b993aea1b3a3be06fefb010355b869ce49aa8.tar.gz
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
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_vnops.c39
-rw-r--r--sys/sys/vnode.h2
2 files changed, 41 insertions, 0 deletions
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index d367340..cebc4f9 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -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.
*/
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 0696edd..bc16acf 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -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))
OpenPOWER on IntegriCloud