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 + +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 #include #include -#include +#include #include #include #include #include -#include #include #include #include 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 +#include + +/* + * 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 */