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
This commit is contained in:
Andriy Gapon 2017-11-21 18:01:43 +00:00
parent a3dff126f9
commit bf71fe61af
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=326067

View File

@ -42,6 +42,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <sys/vnode.h>
/* /*
* same as uiomove() but doesn't modify uio structure. * same as uiomove() but doesn't modify uio structure.
@ -50,63 +51,42 @@
int int
uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes) uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes)
{ {
struct iovec *iov; struct iovec small_iovec[1];
ulong_t cnt; struct uio small_uio_clone;
int error, iovcnt; struct uio *uio_clone;
int error;
iovcnt = uio->uio_iovcnt; ASSERT3U(uio->uio_rw, ==, rw);
*cbytes = 0; if (uio->uio_iovcnt == 1) {
small_uio_clone = *uio;
for (iov = uio->uio_iov; n > 0 && iovcnt > 0; iov++, iovcnt--) { small_iovec[0] = *uio->uio_iov;
cnt = MIN(iov->iov_len, n); small_uio_clone.uio_iov = small_iovec;
if (cnt == 0) uio_clone = &small_uio_clone;
continue; } else {
uio_clone = cloneuio(uio);
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;
} }
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. * Drop the next n chars out of *uiop.
*/ */
void void
uioskip(uio_t *uiop, size_t n) uioskip(uio_t *uio, size_t n)
{ {
if (n > uiop->uio_resid) enum uio_seg segflg;
return;
while (n != 0) {
register iovec_t *iovp = uiop->uio_iov;
register size_t niovb = MIN(iovp->iov_len, n);
if (niovb == 0) { /* For the full compatibility with illumos. */
uiop->uio_iov++; if (n > uio->uio_resid)
uiop->uio_iovcnt--; return;
continue;
} segflg = uio->uio_segflg;
iovp->iov_base += niovb; uio->uio_segflg = UIO_NOCOPY;
uiop->uio_loffset += niovb; uiomove(NULL, n, uio->uio_rw, uio);
iovp->iov_len -= niovb; uio->uio_segflg = segflg;
uiop->uio_resid -= niovb;
n -= niovb;
}
} }