summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/Makefile.am1
-rw-r--r--include/sys/Makefile.in3
-rw-r--r--include/sys/uio_impl.h49
-rw-r--r--include/sys/zfs_context.h3
-rw-r--r--lib/libzpool/Makefile.am1
-rw-r--r--lib/libzpool/Makefile.in18
-rw-r--r--module/zcommon/Makefile.in1
-rw-r--r--module/zcommon/zfs_uio.c255
8 files changed, 325 insertions, 6 deletions
diff --git a/include/sys/Makefile.am b/include/sys/Makefile.am
index 1aeb5da2d..a2e8dd01b 100644
--- a/include/sys/Makefile.am
+++ b/include/sys/Makefile.am
@@ -42,6 +42,7 @@ COMMON_H = \
$(top_srcdir)/include/sys/u8_textprep.h \
$(top_srcdir)/include/sys/uberblock.h \
$(top_srcdir)/include/sys/uberblock_impl.h \
+ $(top_srcdir)/include/sys/uio_impl.h \
$(top_srcdir)/include/sys/unique.h \
$(top_srcdir)/include/sys/uuid.h \
$(top_srcdir)/include/sys/vdev_disk.h \
diff --git a/include/sys/Makefile.in b/include/sys/Makefile.in
index 59066479a..4ab3927b0 100644
--- a/include/sys/Makefile.in
+++ b/include/sys/Makefile.in
@@ -132,6 +132,7 @@ am__kernel_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
$(top_srcdir)/include/sys/u8_textprep.h \
$(top_srcdir)/include/sys/uberblock.h \
$(top_srcdir)/include/sys/uberblock_impl.h \
+ $(top_srcdir)/include/sys/uio_impl.h \
$(top_srcdir)/include/sys/unique.h \
$(top_srcdir)/include/sys/uuid.h \
$(top_srcdir)/include/sys/vdev_disk.h \
@@ -227,6 +228,7 @@ am__libzfs_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
$(top_srcdir)/include/sys/u8_textprep.h \
$(top_srcdir)/include/sys/uberblock.h \
$(top_srcdir)/include/sys/uberblock_impl.h \
+ $(top_srcdir)/include/sys/uio_impl.h \
$(top_srcdir)/include/sys/unique.h \
$(top_srcdir)/include/sys/uuid.h \
$(top_srcdir)/include/sys/vdev_disk.h \
@@ -498,6 +500,7 @@ COMMON_H = \
$(top_srcdir)/include/sys/u8_textprep.h \
$(top_srcdir)/include/sys/uberblock.h \
$(top_srcdir)/include/sys/uberblock_impl.h \
+ $(top_srcdir)/include/sys/uio_impl.h \
$(top_srcdir)/include/sys/unique.h \
$(top_srcdir)/include/sys/uuid.h \
$(top_srcdir)/include/sys/vdev_disk.h \
diff --git a/include/sys/uio_impl.h b/include/sys/uio_impl.h
new file mode 100644
index 000000000..37e283da0
--- /dev/null
+++ b/include/sys/uio_impl.h
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#ifndef _SYS_UIO_IMPL_H
+#define _SYS_UIO_IMPL_H
+
+#include <sys/uio.h>
+
+extern int uiomove(void *, size_t, enum uio_rw, uio_t *);
+extern void uio_prefaultpages(ssize_t, uio_t *);
+extern int uiocopy(void *, size_t, enum uio_rw, uio_t *, size_t *);
+extern void uioskip(uio_t *, size_t);
+
+#endif /* _SYS_UIO_IMPL_H */
diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h
index 44e3dd1d3..0ebacbc64 100644
--- a/include/sys/zfs_context.h
+++ b/include/sys/zfs_context.h
@@ -49,12 +49,11 @@
#include <sys/byteorder.h>
#include <sys/systm.h>
#include <sys/list.h>
-#include <sys/uio.h>
+#include <sys/uio_impl.h>
#include <sys/dirent.h>
#include <sys/time.h>
#include <vm/seg_kmem.h>
#include <sys/zone.h>
-#include <sys/uio.h>
#include <sys/zfs_debug.h>
#include <sys/fm/fs/zfs.h>
#include <sys/sunddi.h>
diff --git a/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am
index 388b631e5..0c22b8cf7 100644
--- a/lib/libzpool/Makefile.am
+++ b/lib/libzpool/Makefile.am
@@ -22,6 +22,7 @@ libzpool_la_SOURCES = \
$(top_srcdir)/module/zcommon/zfs_fletcher.c \
$(top_srcdir)/module/zcommon/zfs_namecheck.c \
$(top_srcdir)/module/zcommon/zfs_prop.c \
+ $(top_srcdir)/module/zcommon/zfs_uio.c \
$(top_srcdir)/module/zcommon/zpool_prop.c \
$(top_srcdir)/module/zcommon/zprop_common.c \
$(top_srcdir)/module/zfs/arc.c \
diff --git a/lib/libzpool/Makefile.in b/lib/libzpool/Makefile.in
index 209b8594e..17f70e6fe 100644
--- a/lib/libzpool/Makefile.in
+++ b/lib/libzpool/Makefile.in
@@ -105,10 +105,10 @@ libzpool_la_DEPENDENCIES = \
$(top_builddir)/lib/libspl/libspl.la
am_libzpool_la_OBJECTS = kernel.lo taskq.lo util.lo zfs_comutil.lo \
zfs_deleg.lo zfs_fletcher.lo zfs_namecheck.lo zfs_prop.lo \
- zpool_prop.lo zprop_common.lo arc.lo bplist.lo bpobj.lo \
- dbuf.lo ddt.lo ddt_zap.lo dmu.lo dmu_diff.lo dmu_object.lo \
- dmu_objset.lo dmu_send.lo dmu_traverse.lo dmu_tx.lo \
- dmu_zfetch.lo dnode.lo dnode_sync.lo dsl_dataset.lo \
+ zfs_uio.lo zpool_prop.lo zprop_common.lo arc.lo bplist.lo \
+ bpobj.lo dbuf.lo ddt.lo ddt_zap.lo dmu.lo dmu_diff.lo \
+ dmu_object.lo dmu_objset.lo dmu_send.lo dmu_traverse.lo \
+ dmu_tx.lo dmu_zfetch.lo dnode.lo dnode_sync.lo dsl_dataset.lo \
dsl_deadlist.lo dsl_deleg.lo dsl_dir.lo dsl_pool.lo \
dsl_prop.lo dsl_scan.lo dsl_synctask.lo fm.lo gzip.lo lzjb.lo \
metaslab.lo refcount.lo rrwlock.lo sa.lo sha256.lo spa.lo \
@@ -344,6 +344,7 @@ libzpool_la_SOURCES = \
$(top_srcdir)/module/zcommon/zfs_fletcher.c \
$(top_srcdir)/module/zcommon/zfs_namecheck.c \
$(top_srcdir)/module/zcommon/zfs_prop.c \
+ $(top_srcdir)/module/zcommon/zfs_uio.c \
$(top_srcdir)/module/zcommon/zpool_prop.c \
$(top_srcdir)/module/zcommon/zprop_common.c \
$(top_srcdir)/module/zfs/arc.c \
@@ -571,6 +572,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_namecheck.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_prop.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_sa.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_uio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zfs_znode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zil.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zio.Plo@am__quote@
@@ -670,6 +672,14 @@ zfs_prop.lo: $(top_srcdir)/module/zcommon/zfs_prop.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zfs_prop.lo `test -f '$(top_srcdir)/module/zcommon/zfs_prop.c' || echo '$(srcdir)/'`$(top_srcdir)/module/zcommon/zfs_prop.c
+zfs_uio.lo: $(top_srcdir)/module/zcommon/zfs_uio.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zfs_uio.lo -MD -MP -MF $(DEPDIR)/zfs_uio.Tpo -c -o zfs_uio.lo `test -f '$(top_srcdir)/module/zcommon/zfs_uio.c' || echo '$(srcdir)/'`$(top_srcdir)/module/zcommon/zfs_uio.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/zfs_uio.Tpo $(DEPDIR)/zfs_uio.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_srcdir)/module/zcommon/zfs_uio.c' object='zfs_uio.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zfs_uio.lo `test -f '$(top_srcdir)/module/zcommon/zfs_uio.c' || echo '$(srcdir)/'`$(top_srcdir)/module/zcommon/zfs_uio.c
+
zpool_prop.lo: $(top_srcdir)/module/zcommon/zpool_prop.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zpool_prop.lo -MD -MP -MF $(DEPDIR)/zpool_prop.Tpo -c -o zpool_prop.lo `test -f '$(top_srcdir)/module/zcommon/zpool_prop.c' || echo '$(srcdir)/'`$(top_srcdir)/module/zcommon/zpool_prop.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/zpool_prop.Tpo $(DEPDIR)/zpool_prop.Plo
diff --git a/module/zcommon/Makefile.in b/module/zcommon/Makefile.in
index ee4864ffc..e564b77b4 100644
--- a/module/zcommon/Makefile.in
+++ b/module/zcommon/Makefile.in
@@ -13,4 +13,5 @@ $(MODULE)-objs += @top_srcdir@/module/zcommon/zprop_common.o
$(MODULE)-objs += @top_srcdir@/module/zcommon/zfs_namecheck.o
$(MODULE)-objs += @top_srcdir@/module/zcommon/zfs_comutil.o
$(MODULE)-objs += @top_srcdir@/module/zcommon/zfs_fletcher.o
+$(MODULE)-objs += @top_srcdir@/module/zcommon/zfs_uio.o
$(MODULE)-objs += @top_srcdir@/module/zcommon/zpool_prop.o
diff --git a/module/zcommon/zfs_uio.c b/module/zcommon/zfs_uio.c
new file mode 100644
index 000000000..990464594
--- /dev/null
+++ b/module/zcommon/zfs_uio.c
@@ -0,0 +1,255 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+/*
+ * The uio support from OpenSolaris has been added as a short term
+ * work around. The hope is to adopt native Linux type and drop the
+ * use of uio's entirely. Under Linux they only add overhead and
+ * when possible we want to use native APIs for the ZPL layer.
+ */
+#ifdef _KERNEL
+
+#include <sys/types.h>
+#include <sys/uio_impl.h>
+
+/*
+ * Move "n" bytes at byte address "p"; "rw" indicates the direction
+ * of the move, and the I/O parameters are provided in "uio", which is
+ * update to reflect the data which was moved. Returns 0 on success or
+ * a non-zero errno on failure.
+ */
+int
+uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio)
+{
+ struct iovec *iov;
+ ulong_t cnt;
+
+ while (n && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = MIN(iov->iov_len, n);
+ if (cnt == 0l) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ switch (uio->uio_segflg) {
+ case UIO_USERSPACE:
+ case UIO_USERISPACE:
+ /* p = kernel data pointer
+ * iov->iov_base = user data pointer */
+
+ if (rw == UIO_READ) {
+ if (copy_to_user(iov->iov_base, p, cnt))
+ return EFAULT;
+ /* error = xcopyout_nta(p, iov->iov_base, cnt,
+ * (uio->uio_extflg & UIO_COPY_CACHED)); */
+ } else {
+ /* error = xcopyin_nta(iov->iov_base, p, cnt,
+ * (uio->uio_extflg & UIO_COPY_CACHED)); */
+ if (copy_from_user(p, iov->iov_base, cnt))
+ return EFAULT;
+ }
+ break;
+ case UIO_SYSSPACE:
+ if (rw == UIO_READ)
+ bcopy(p, iov->iov_base, cnt);
+ else
+ bcopy(iov->iov_base, p, cnt);
+ break;
+ }
+ iov->iov_base += cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_loffset += cnt;
+ p = (caddr_t)p + cnt;
+ n -= cnt;
+ }
+ return (0);
+}
+EXPORT_SYMBOL(uiomove);
+
+#define fuword8(uptr, vptr) get_user((*vptr), (uptr))
+
+/*
+ * Fault in the pages of the first n bytes specified by the uio structure.
+ * 1 byte in each page is touched and the uio struct is unmodified. Any
+ * error will terminate the process as this is only a best attempt to get
+ * the pages resident.
+ */
+void
+uio_prefaultpages(ssize_t n, struct uio *uio)
+{
+ struct iovec *iov;
+ ulong_t cnt, incr;
+ caddr_t p;
+ uint8_t tmp;
+ int iovcnt;
+
+ iov = uio->uio_iov;
+ iovcnt = uio->uio_iovcnt;
+
+ while ((n > 0) && (iovcnt > 0)) {
+ cnt = MIN(iov->iov_len, n);
+ if (cnt == 0) {
+ /* empty iov entry */
+ iov++;
+ iovcnt--;
+ continue;
+ }
+ n -= cnt;
+ /*
+ * touch each page in this segment.
+ */
+ p = iov->iov_base;
+ while (cnt) {
+ switch (uio->uio_segflg) {
+ case UIO_USERSPACE:
+ case UIO_USERISPACE:
+ if (fuword8((uint8_t *) p, &tmp))
+ return;
+ break;
+ case UIO_SYSSPACE:
+ bcopy(p, &tmp, 1);
+ break;
+ }
+ incr = MIN(cnt, PAGESIZE);
+ p += incr;
+ cnt -= incr;
+ }
+ /*
+ * touch the last byte in case it straddles a page.
+ */
+ p--;
+ switch (uio->uio_segflg) {
+ case UIO_USERSPACE:
+ case UIO_USERISPACE:
+ if (fuword8((uint8_t *) p, &tmp))
+ return;
+ break;
+ case UIO_SYSSPACE:
+ bcopy(p, &tmp, 1);
+ break;
+ }
+ iov++;
+ iovcnt--;
+ }
+}
+EXPORT_SYMBOL(uio_prefaultpages);
+
+/*
+ * same as uiomove() but doesn't modify uio structure.
+ * return in cbytes how many bytes were copied.
+ */
+int
+uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes)
+{
+ struct iovec *iov;
+ ulong_t cnt;
+ int iovcnt;
+
+ iovcnt = uio->uio_iovcnt;
+ *cbytes = 0;
+
+ for (iov = uio->uio_iov; n && iovcnt; iov++, iovcnt--) {
+ cnt = MIN(iov->iov_len, n);
+ if (cnt == 0)
+ continue;
+
+ switch (uio->uio_segflg) {
+
+ case UIO_USERSPACE:
+ case UIO_USERISPACE:
+ /* p = kernel data pointer
+ * iov->iov_base = user data pointer */
+
+ if (rw == UIO_READ) {
+ /* * UIO_READ = copy data from kernel to user * */
+ if (copy_to_user(iov->iov_base, p, cnt))
+ return EFAULT;
+ /* error = xcopyout_nta(p, iov->iov_base, cnt,
+ * (uio->uio_extflg & UIO_COPY_CACHED)); */
+ } else {
+ /* * UIO_WRITE = copy data from user to kernel * */
+ /* error = xcopyin_nta(iov->iov_base, p, cnt,
+ * (uio->uio_extflg & UIO_COPY_CACHED)); */
+ if (copy_from_user(p, iov->iov_base, cnt))
+ return EFAULT;
+ }
+ break;
+
+ case UIO_SYSSPACE:
+ if (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);
+}
+EXPORT_SYMBOL(uiocopy);
+
+/*
+ * Drop the next n chars out of *uiop.
+ */
+void
+uioskip(uio_t *uiop, size_t n)
+{
+ if (n > uiop->uio_resid)
+ return;
+ while (n != 0) {
+ iovec_t *iovp = uiop->uio_iov;
+ 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;
+ }
+}
+EXPORT_SYMBOL(uioskip);
+#endif /* _KERNEL */