svn commit: r286399 - stable/10/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Fri Aug 7 04:38:14 UTC 2015
Author: kib
Date: Fri Aug 7 04:38:13 2015
New Revision: 286399
URL: https://svnweb.freebsd.org/changeset/base/286399
Log:
MFC r286106:
Provide a prefaulting for the userspace i/o buffers, disabled by default.
Modified:
stable/10/sys/kern/vfs_vnops.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/sys/kern/vfs_vnops.c
==============================================================================
--- stable/10/sys/kern/vfs_vnops.c Fri Aug 7 04:35:43 2015 (r286398)
+++ stable/10/sys/kern/vfs_vnops.c Fri Aug 7 04:38:13 2015 (r286399)
@@ -110,6 +110,9 @@ static const int io_hold_cnt = 16;
static int vn_io_fault_enable = 1;
SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_enable, CTLFLAG_RW,
&vn_io_fault_enable, 0, "Enable vn_io_fault lock avoidance");
+static int vn_io_fault_prefault = 0;
+SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_prefault, CTLFLAG_RW,
+ &vn_io_fault_prefault, 0, "Enable vn_io_fault prefaulting");
static u_long vn_io_faults_cnt;
SYSCTL_ULONG(_debug, OID_AUTO, vn_io_faults, CTLFLAG_RD,
&vn_io_faults_cnt, 0, "Count of vn_io_fault lock avoidance triggers");
@@ -1008,6 +1011,59 @@ vn_io_fault_doio(struct vn_io_fault_args
uio->uio_rw);
}
+static int
+vn_io_fault_touch(char *base, const struct uio *uio)
+{
+ int r;
+
+ r = fubyte(base);
+ if (r == -1 || (uio->uio_rw == UIO_READ && subyte(base, r) == -1))
+ return (EFAULT);
+ return (0);
+}
+
+static int
+vn_io_fault_prefault_user(const struct uio *uio)
+{
+ char *base;
+ const struct iovec *iov;
+ size_t len;
+ ssize_t resid;
+ int error, i;
+
+ KASSERT(uio->uio_segflg == UIO_USERSPACE,
+ ("vn_io_fault_prefault userspace"));
+
+ error = i = 0;
+ iov = uio->uio_iov;
+ resid = uio->uio_resid;
+ base = iov->iov_base;
+ len = iov->iov_len;
+ while (resid > 0) {
+ error = vn_io_fault_touch(base, uio);
+ if (error != 0)
+ break;
+ if (len < PAGE_SIZE) {
+ if (len != 0) {
+ error = vn_io_fault_touch(base + len - 1, uio);
+ if (error != 0)
+ break;
+ resid -= len;
+ }
+ if (++i >= uio->uio_iovcnt)
+ break;
+ iov = uio->uio_iov + i;
+ base = iov->iov_base;
+ len = iov->iov_len;
+ } else {
+ len -= PAGE_SIZE;
+ base += PAGE_SIZE;
+ resid -= PAGE_SIZE;
+ }
+ }
+ return (error);
+}
+
/*
* Common code for vn_io_fault(), agnostic to the kind of i/o request.
* Uses vn_io_fault_doio() to make the call to an actual i/o function.
@@ -1029,6 +1085,12 @@ vn_io_fault1(struct vnode *vp, struct ui
ssize_t adv;
int error, cnt, save, saveheld, prev_td_ma_cnt;
+ if (vn_io_fault_prefault) {
+ error = vn_io_fault_prefault_user(uio);
+ if (error != 0)
+ return (error); /* Or ignore ? */
+ }
+
prot = uio->uio_rw == UIO_READ ? VM_PROT_WRITE : VM_PROT_READ;
/*
More information about the svn-src-stable
mailing list