svn commit: r326067 - head/sys/cddl/compat/opensolaris/kern

Andriy Gapon avg at FreeBSD.org
Tue Nov 21 18:01:45 UTC 2017


Author: avg
Date: Tue Nov 21 18:01:43 2017
New Revision: 326067
URL: https://svnweb.freebsd.org/changeset/base/326067

Log:
  make illumos uiocopy use vn_io_fault_uiomove
  
  uiocopy() is currently unused, its purpose is copy data from a uio
  without modifying the uio.  It was in use before the vn_io_fault support
  was added to ZFS, at which point our code diverged from the illumos code
  a little bit.  Because ZFS is the only (potential) user of the function
  we are free to modify it to better suit ZFS needs.
  
  The intention behind this change is to remove the differences introduced
  earlier in zfs_write().
  
  While here, re-implement uioskip() using uiomove() with
  uio_segflg == UIO_NOCOPY.
  The story of uioskip is the same as with uiocopy.
  
  Reviewed by:	mav
  MFC after:	1 week

Modified:
  head/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c

Modified: head/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c
==============================================================================
--- head/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c	Tue Nov 21 17:23:16 2017	(r326066)
+++ head/sys/cddl/compat/opensolaris/kern/opensolaris_uio.c	Tue Nov 21 18:01:43 2017	(r326067)
@@ -42,6 +42,7 @@
 
 #include <sys/types.h>
 #include <sys/uio.h>
+#include <sys/vnode.h>
 
 /*
  * same as uiomove() but doesn't modify uio structure.
@@ -50,63 +51,42 @@
 int
 uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes)
 {
-	struct iovec *iov;
-	ulong_t cnt;
-	int error, iovcnt;
+	struct iovec small_iovec[1];
+	struct uio small_uio_clone;
+	struct uio *uio_clone;
+	int error;
 
-	iovcnt = uio->uio_iovcnt;
-	*cbytes = 0;
-
-	for (iov = uio->uio_iov; n > 0 && iovcnt > 0; iov++, iovcnt--) {
-		cnt = MIN(iov->iov_len, n);
-		if (cnt == 0)
-			continue;
-
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			if (rw == UIO_READ)
-				error = copyout(p, iov->iov_base, cnt);
-			else
-				error = copyin(iov->iov_base, p, cnt);
-			if (error)
-				return (error);
-			break;
-		case UIO_SYSSPACE:
-			if (uio->uio_rw == UIO_READ)
-				bcopy(p, iov->iov_base, cnt);
-			else
-				bcopy(iov->iov_base, p, cnt);
-			break;
-		}
-
-		p = (caddr_t)p + cnt;
-		n -= cnt;
-		*cbytes += cnt;
+	ASSERT3U(uio->uio_rw, ==, rw);
+	if (uio->uio_iovcnt == 1) {
+		small_uio_clone = *uio;
+		small_iovec[0] = *uio->uio_iov;
+		small_uio_clone.uio_iov = small_iovec;
+		uio_clone = &small_uio_clone;
+	} else {
+		uio_clone = cloneuio(uio);
 	}
-	return (0);
+
+	error = vn_io_fault_uiomove(p, n, uio_clone);
+	*cbytes = uio->uio_resid - uio_clone->uio_resid;
+	if (uio_clone != &small_uio_clone)
+		free(uio_clone, M_IOV);
+	return (error);
 }
 
 /*
  * Drop the next n chars out of *uiop.
  */
 void
-uioskip(uio_t *uiop, size_t n)
+uioskip(uio_t *uio, size_t n)
 {
-	if (n > uiop->uio_resid)
+	enum uio_seg segflg;
+
+	/* For the full compatibility with illumos. */
+	if (n > uio->uio_resid)
 		return;
-	while (n != 0) {
-		register iovec_t	*iovp = uiop->uio_iov;
-		register size_t		niovb = MIN(iovp->iov_len, n);
 
-		if (niovb == 0) {
-			uiop->uio_iov++;
-			uiop->uio_iovcnt--;
-			continue;
-		}
-		iovp->iov_base += niovb;
-		uiop->uio_loffset += niovb;
-		iovp->iov_len -= niovb;
-		uiop->uio_resid -= niovb;
-		n -= niovb;
-	}
+	segflg = uio->uio_segflg;
+	uio->uio_segflg = UIO_NOCOPY;
+	uiomove(NULL, n, uio->uio_rw, uio);
+	uio->uio_segflg = segflg;
 }


More information about the svn-src-all mailing list