Merge branch 'zpl'
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 18 Feb 2011 17:31:25 +0000 (09:31 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 18 Feb 2011 17:31:25 +0000 (09:31 -0800)
128 files changed:
AUTHORS
META
Makefile.in
cmd/Makefile.in
cmd/zdb/Makefile.am
cmd/zdb/Makefile.in
cmd/zfs/Makefile.am
cmd/zfs/Makefile.in
cmd/zfs/zfs_main.c
cmd/zinject/Makefile.am
cmd/zinject/Makefile.in
cmd/zinject/translate.c
cmd/zinject/zinject.c
cmd/zpios/Makefile.in
cmd/zpool/Makefile.am
cmd/zpool/Makefile.in
cmd/zpool/zpool_main.c
cmd/zpool_id/Makefile.in
cmd/zpool_layout/Makefile.in
cmd/ztest/Makefile.in
config/kernel-evict-inode.m4 [new file with mode: 0644]
config/kernel-fsync.m4 [new file with mode: 0644]
config/kernel-xattr-handler.m4 [new file with mode: 0644]
config/kernel.m4
config/user-libshare.m4 [deleted file]
config/user-selinux.m4 [new file with mode: 0644]
config/user.m4
configure
configure.ac
etc/Makefile.in
include/Makefile.am
include/Makefile.in
include/libzfs.h
include/linux/Makefile.am [new file with mode: 0644]
include/linux/Makefile.in [new file with mode: 0644]
include/linux/dcache_compat.h [new file with mode: 0644]
include/linux/vfs_compat.h [new file with mode: 0644]
include/linux/xattr_compat.h [new file with mode: 0644]
include/sys/Makefile.am
include/sys/Makefile.in
include/sys/dmu.h
include/sys/dsl_pool.h
include/sys/fm/Makefile.in
include/sys/fm/fs/Makefile.in
include/sys/fs/Makefile.in
include/sys/uio_impl.h [new file with mode: 0644]
include/sys/vdev_disk.h
include/sys/zfs_acl.h
include/sys/zfs_context.h
include/sys/zfs_ctldir.h [deleted file]
include/sys/zfs_dir.h
include/sys/zfs_fuid.h
include/sys/zfs_vfsops.h
include/sys/zfs_vnops.h [new file with mode: 0644]
include/sys/zfs_znode.h
include/sys/zpl.h [new file with mode: 0644]
lib/Makefile.in
lib/libavl/Makefile.in
lib/libefi/Makefile.in
lib/libefi/rdwr_efi.c
lib/libnvpair/Makefile.in
lib/libspl/Makefile.in
lib/libspl/asm-generic/Makefile.in
lib/libspl/asm-i386/Makefile.in
lib/libspl/asm-x86_64/Makefile.in
lib/libspl/include/Makefile.in
lib/libspl/include/ia32/Makefile.in
lib/libspl/include/ia32/sys/Makefile.in
lib/libspl/include/libgen.h [new file with mode: 0644]
lib/libspl/include/libshare.h
lib/libspl/include/rpc/Makefile.in
lib/libspl/include/sys/Makefile.in
lib/libspl/include/sys/dktp/Makefile.in
lib/libspl/include/sys/mntent.h
lib/libspl/include/sys/mnttab.h
lib/libspl/include/sys/mount.h
lib/libspl/include/sys/sysevent/Makefile.in
lib/libspl/include/util/Makefile.in
lib/libunicode/Makefile.in
lib/libuutil/Makefile.in
lib/libzfs/Makefile.am
lib/libzfs/Makefile.in
lib/libzfs/libzfs_changelist.c
lib/libzfs/libzfs_dataset.c
lib/libzfs/libzfs_import.c
lib/libzfs/libzfs_mount.c
lib/libzfs/libzfs_util.c
lib/libzpool/Makefile.am
lib/libzpool/Makefile.in
man/Makefile.in
man/man8/Makefile.in
man/man8/zfs.8
module/zcommon/Makefile.in
module/zcommon/zfs_uio.c [new file with mode: 0644]
module/zfs/Makefile.in
module/zfs/arc.c
module/zfs/dmu.c
module/zfs/dmu_objset.c
module/zfs/dsl_dataset.c
module/zfs/dsl_pool.c
module/zfs/sa.c
module/zfs/spa_config.c
module/zfs/vdev_disk.c
module/zfs/vdev_file.c
module/zfs/zfs_acl.c
module/zfs/zfs_ctldir.c [deleted file]
module/zfs/zfs_dir.c
module/zfs/zfs_fuid.c
module/zfs/zfs_ioctl.c
module/zfs/zfs_log.c
module/zfs/zfs_replay.c
module/zfs/zfs_rlock.c
module/zfs/zfs_sa.c
module/zfs/zfs_vfsops.c
module/zfs/zfs_vnops.c
module/zfs/zfs_znode.c
module/zfs/zpl_file.c [new file with mode: 0644]
module/zfs/zpl_inode.c [new file with mode: 0644]
module/zfs/zpl_super.c [new file with mode: 0644]
module/zfs/zpl_xattr.c [new file with mode: 0644]
module/zfs/zvol.c
scripts/Makefile.in
scripts/zfs.sh
scripts/zpios-profile/Makefile.in
scripts/zpios-test/Makefile.in
scripts/zpool-config/Makefile.in
scripts/zpool-layout/Makefile.in
zfs_config.h.in

diff --git a/AUTHORS b/AUTHORS
index 04ebc20..e2c474f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,34 @@
-Brian Behlendorf <behlendorf1@llnl.gov>,
-Herb Wartens <wartens2@llnl.gov>,
-Jim Garlick <garlick@llnl.gov>,
-Ricardo M. Correia <Ricardo.M.Correia@sun.com>
+Brian Behlendorf is the principle developer of the ZFS on Linux port.
+He works full time as a computer scientist at Lawrence Livermore
+National Laboratory on the ZFS and Lustre filesystems.  However,
+this port would not have been possible without the help of many
+others who have contributed their time, effort, and insight.
+
+  Brian Behlendorf <behlendorf1@llnl.gov>
+
+First and foremost the hard working ZFS developers at Sun/Oracle.
+They are responsible for the bulk of the code in this project and
+without their efforts there never would have been a ZFS filesystem.
+
+  The ZFS Development Team at Sun/Oracle
+
+Next all the developers at KQ Infotech who implemented a working
+ZFS Posix Layer (ZPL) for this port.  Their implementation provided
+an excellent reference for adding the missing ZPL functionality.
+
+  Anand Mitra <mitra@kqinfotech.com>
+  Anurag Agarwal <anurag@kqinfotech.com>
+  Neependra Khare <neependra@kqinfotech.com>
+  Prasad Joshi <prasad@kqinfotech.com>
+  Rohan Puri <rohan@kqinfotech.com>
+  Sandip Divekar <sandipd@kqinfotech.com>
+  Shoaib <shoaib@kqinfotech.com>
+  Shrirang <shrirang@kqinfotech.com>
+
+Additionally the following individuals have all made contributions
+to the project and deserve to be acknowledged.
+
+  Ricardo M. Correia <Ricardo.M.Correia@sun.com>
+  Ned Bass <bass6@llnl.gov>
+  Herb Wartens <wartens2@llnl.gov>
+  Jim Garlick <garlick@llnl.gov>
diff --git a/META b/META
index 6ecc7a6..d9f9e09 100644 (file)
--- a/META
+++ b/META
@@ -1,7 +1,7 @@
 Meta:         1
 Name:         zfs
 Branch:       1.0
-Version:      0.5.2
+Version:      0.6.0
 Release:      1
 Release-Tags: relext
 License:      CDDL
index 2502482..3c266e1 100644 (file)
@@ -65,21 +65,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -210,6 +213,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index f8f5a76..05e70be 100644 (file)
@@ -50,21 +50,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -178,6 +181,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 16d7499..9304bfc 100644 (file)
@@ -20,4 +20,4 @@ zdb_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zdb_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zdb_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
index 88152b8..0ff5b4b 100644 (file)
@@ -53,21 +53,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -180,6 +183,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -310,7 +314,7 @@ zdb_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zdb_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zdb_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
 all: all-am
 
 .SUFFIXES:
index ba3e644..1b7cd84 100644 (file)
@@ -22,4 +22,4 @@ zfs_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zfs_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zfs_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
index dd44b26..d6ce3ae 100644 (file)
@@ -53,21 +53,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -180,6 +183,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -312,7 +316,7 @@ zfs_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zfs_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zfs_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
 all: all-am
 
 .SUFFIXES:
index 5f22e43..86f0d5c 100644 (file)
@@ -318,7 +318,6 @@ safe_malloc(size_t size)
        return (data);
 }
 
-#ifdef HAVE_ZPL
 static char *
 safe_strdup(char *str)
 {
@@ -329,7 +328,6 @@ safe_strdup(char *str)
 
        return (dupstr);
 }
-#endif /* HAVE_ZPL */
 
 /*
  * Callback routine that will print out information for each of
@@ -497,7 +495,6 @@ parse_depth(char *opt, int *flags)
 
 #define        PROGRESS_DELAY 2                /* seconds */
 
-#ifdef HAVE_ZPL
 static char *pt_reverse = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
 static time_t pt_begin;
 static char *pt_header = NULL;
@@ -549,7 +546,6 @@ finish_progress(char *done)
        free(pt_header);
        pt_header = NULL;
 }
-#endif /* HAVE_ZPL */
 
 /*
  * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol>
@@ -631,7 +627,6 @@ zfs_do_clone(int argc, char **argv)
        ret = zfs_clone(zhp, argv[1], props);
 
        /* create the mountpoint if necessary */
-#ifdef HAVE_ZPL
        if (ret == 0) {
                zfs_handle_t *clone;
 
@@ -643,7 +638,6 @@ zfs_do_clone(int argc, char **argv)
                        zfs_close(clone);
                }
        }
-#endif /* HAVE_ZPL */
 
        zfs_close(zhp);
        nvlist_free(props);
@@ -831,7 +825,6 @@ zfs_do_create(int argc, char **argv)
         * verbose error message to let the user know that their filesystem was
         * in fact created, even if we failed to mount or share it.
         */
-#ifdef HAVE_ZPL
        if (canmount == ZFS_CANMOUNT_ON) {
                if (zfs_mount(zhp, NULL, 0) != 0) {
                        (void) fprintf(stderr, gettext("filesystem "
@@ -843,7 +836,6 @@ zfs_do_create(int argc, char **argv)
                        ret = 1;
                }
        }
-#endif /* HAVE_ZPL */
 
 error:
        if (zhp)
@@ -2340,7 +2332,6 @@ typedef struct rollback_cbdata {
  * 'cb_dependent' is set, then this is a dependent and we should report it
  * without checking the transaction group.
  */
-#ifdef HAVE_ZPL
 static int
 rollback_check(zfs_handle_t *zhp, void *data)
 {
@@ -2400,12 +2391,10 @@ rollback_check(zfs_handle_t *zhp, void *data)
        zfs_close(zhp);
        return (0);
 }
-#endif /* HAVE_ZPL */
 
 static int
 zfs_do_rollback(int argc, char **argv)
 {
-#ifdef HAVE_ZPL
        int ret;
        int c;
        boolean_t force = B_FALSE;
@@ -2487,9 +2476,6 @@ out:
                return (0);
        else
                return (1);
-#else
-       return ENOSYS;
-#endif /*HAVE_ZPL*/
 }
 
 /*
@@ -2955,7 +2941,6 @@ zfs_do_release(int argc, char **argv)
 #define        SPINNER_TIME 3          /* seconds */
 #define        MOUNT_TIME 5            /* seconds */
 
-#ifdef HAVE_ZPL
 static int
 get_one_dataset(zfs_handle_t *zhp, void *data)
 {
@@ -3153,11 +3138,11 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
                shared_nfs = zfs_is_shared_nfs(zhp, NULL);
                shared_smb = zfs_is_shared_smb(zhp, NULL);
 
-               if (shared_nfs && shared_smb ||
-                   (shared_nfs && strcmp(shareopts, "on") == 0 &&
-                   strcmp(smbshareopts, "off") == 0) ||
-                   (shared_smb && strcmp(smbshareopts, "on") == 0 &&
-                   strcmp(shareopts, "off") == 0)) {
+               if ((shared_nfs && shared_smb) ||
+                   ((shared_nfs && strcmp(shareopts, "on") == 0) &&
+                   (strcmp(smbshareopts, "off") == 0)) ||
+                   ((shared_smb && strcmp(smbshareopts, "on") == 0) &&
+                   (strcmp(shareopts, "off") == 0))) {
                        if (!explicit)
                                return (0);
 
@@ -3275,7 +3260,7 @@ share_mount(int op, int argc, char **argv)
        int flags = 0;
 
        /* check options */
-       while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:O" : "a"))
+       while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:" : "a"))
            != -1) {
                switch (c) {
                case 'a':
@@ -3298,9 +3283,6 @@ share_mount(int op, int argc, char **argv)
                        append_options(options, optarg);
                        break;
 
-               case 'O':
-                       flags |= MS_OVERLAY;
-                       break;
                case ':':
                        (void) fprintf(stderr, gettext("missing argument for "
                            "'%c' option\n"), optopt);
@@ -3368,7 +3350,7 @@ share_mount(int op, int argc, char **argv)
                }
 
                /*
-                * When mount is given no arguments, go through /etc/mnttab and
+                * When mount is given no arguments, go through /etc/mtab and
                 * display any active ZFS mounts.  We hide any snapshots, since
                 * they are controlled automatically.
                 */
@@ -3403,7 +3385,6 @@ share_mount(int op, int argc, char **argv)
 
        return (ret);
 }
-#endif  /* HAVE_ZPL */
 
 /*
  * zfs mount -a [nfs]
@@ -3414,11 +3395,7 @@ share_mount(int op, int argc, char **argv)
 static int
 zfs_do_mount(int argc, char **argv)
 {
-#ifdef HAVE_ZPL
        return (share_mount(OP_MOUNT, argc, argv));
-#else
-       return ENOSYS;
-#endif  /* HAVE_ZPL */
 }
 
 /*
@@ -3430,14 +3407,9 @@ zfs_do_mount(int argc, char **argv)
 static int
 zfs_do_share(int argc, char **argv)
 {
-#ifdef HAVE_ZPL
        return (share_mount(OP_SHARE, argc, argv));
-#else
-       return ENOSYS;
-#endif  /* HAVE_ZPL */
 }
 
-#ifdef HAVE_ZPL
 typedef struct unshare_unmount_node {
        zfs_handle_t    *un_zhp;
        char            *un_mountp;
@@ -3456,7 +3428,7 @@ unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
 
 /*
  * Convenience routine used by zfs_do_umount() and manual_unmount().  Given an
- * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem,
+ * absolute path, find the entry /etc/mtab, verify that its a ZFS filesystem,
  * and unmount it appropriately.
  */
 static int
@@ -3470,7 +3442,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
        ino_t path_inode;
 
        /*
-        * Search for the path in /etc/mnttab.  Rather than looking for the
+        * Search for the path in /etc/mtab.  Rather than looking for the
         * specific path, which can be fooled by non-standard paths (i.e. ".."
         * or "//"), we stat() the path and search for the corresponding
         * (major,minor) device pair.
@@ -3497,7 +3469,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
                            "currently mounted\n"), cmdname, path);
                        return (1);
                }
-               (void) fprintf(stderr, gettext("warning: %s not in mnttab\n"),
+               (void) fprintf(stderr, gettext("warning: %s not in mtab\n"),
                    path);
                if ((ret = umount2(path, flags)) != 0)
                        (void) fprintf(stderr, gettext("%s: %s\n"), path,
@@ -3539,8 +3511,8 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
                    strcmp(smbshare_prop, "off") == 0) {
                        (void) fprintf(stderr, gettext("cannot unshare "
                            "'%s': legacy share\n"), path);
-                       (void) fprintf(stderr, gettext("use "
-                           "unshare(1M) to unshare this filesystem\n"));
+                       (void) fprintf(stderr, gettext("use exportfs(8) "
+                           "or smbcontrol(1) to unshare this filesystem\n"));
                } else if (!zfs_is_shared(zhp)) {
                        (void) fprintf(stderr, gettext("cannot unshare '%s': "
                            "not currently shared\n"), path);
@@ -3559,7 +3531,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
                        (void) fprintf(stderr, gettext("cannot unmount "
                            "'%s': legacy mountpoint\n"),
                            zfs_get_name(zhp));
-                       (void) fprintf(stderr, gettext("use umount(1M) "
+                       (void) fprintf(stderr, gettext("use umount(8) "
                            "to unmount this filesystem\n"));
                } else {
                        ret = zfs_unmountall(zhp, flags);
@@ -3609,8 +3581,8 @@ unshare_unmount(int op, int argc, char **argv)
                /*
                 * We could make use of zfs_for_each() to walk all datasets in
                 * the system, but this would be very inefficient, especially
-                * since we would have to linearly search /etc/mnttab for each
-                * one.  Instead, do one pass through /etc/mnttab looking for
+                * since we would have to linearly search /etc/mtab for each
+                * one.  Instead, do one pass through /etc/mtab looking for
                 * zfs entries and call zfs_unmount() for each one.
                 *
                 * Things get a little tricky if the administrator has created
@@ -3622,7 +3594,7 @@ unshare_unmount(int op, int argc, char **argv)
                 */
                struct mnttab entry;
                uu_avl_pool_t *pool;
-               uu_avl_t *tree;
+               uu_avl_t *tree = NULL;
                unshare_unmount_node_t *node;
                uu_avl_index_t idx;
                uu_avl_walk_t *walk;
@@ -3821,7 +3793,6 @@ unshare_unmount(int op, int argc, char **argv)
 
        return (ret);
 }
-#endif  /* HAVE_ZPL */
 
 /*
  * zfs unmount -a
@@ -3832,11 +3803,7 @@ unshare_unmount(int op, int argc, char **argv)
 static int
 zfs_do_unmount(int argc, char **argv)
 {
-#ifdef HAVE_ZPL
        return (unshare_unmount(OP_MOUNT, argc, argv));
-#else
-       return ENOSYS;
-#endif  /* HAVE_ZPL */
 }
 
 /*
@@ -3848,11 +3815,7 @@ zfs_do_unmount(int argc, char **argv)
 static int
 zfs_do_unshare(int argc, char **argv)
 {
-#ifdef HAVE_ZPL
        return (unshare_unmount(OP_SHARE, argc, argv));
-#else
-       return ENOSYS;
-#endif  /* HAVE_ZPL */
 }
 
 /* ARGSUSED */
@@ -3864,45 +3827,210 @@ zfs_do_python(int argc, char **argv)
        return (-1);
 }
 
+typedef struct option_map {
+       const char *name;
+       int mask;
+} option_map_t;
+
+static const option_map_t option_map[] = {
+       /* Canonicalized filesystem independent options from mount(8) */
+       { MNTOPT_NOAUTO,        MS_COMMENT      },
+       { MNTOPT_DEFAULTS,      MS_COMMENT      },
+       { MNTOPT_NODEVICES,     MS_NODEV        },
+       { MNTOPT_DIRSYNC,       MS_DIRSYNC      },
+       { MNTOPT_NOEXEC,        MS_NOEXEC       },
+       { MNTOPT_GROUP,         MS_GROUP        },
+       { MNTOPT_NETDEV,        MS_COMMENT      },
+       { MNTOPT_NOFAIL,        MS_COMMENT      },
+       { MNTOPT_NOSUID,        MS_NOSUID       },
+       { MNTOPT_OWNER,         MS_OWNER        },
+       { MNTOPT_REMOUNT,       MS_REMOUNT      },
+       { MNTOPT_RO,            MS_RDONLY       },
+       { MNTOPT_SYNC,          MS_SYNCHRONOUS  },
+       { MNTOPT_USER,          MS_USERS        },
+       { MNTOPT_USERS,         MS_USERS        },
+#ifdef MS_NOATIME
+       { MNTOPT_NOATIME,       MS_NOATIME      },
+#endif
+#ifdef MS_NODIRATIME
+       { MNTOPT_NODIRATIME,    MS_NODIRATIME   },
+#endif
+#ifdef MS_RELATIME
+       { MNTOPT_RELATIME,      MS_RELATIME     },
+#endif
+#ifdef MS_STRICTATIME
+       { MNTOPT_DFRATIME,      MS_STRICTATIME  },
+#endif
+#ifdef HAVE_SELINUX
+       { MNTOPT_CONTEXT,       MS_COMMENT      },
+       { MNTOPT_FSCONTEXT,     MS_COMMENT      },
+       { MNTOPT_DEFCONTEXT,    MS_COMMENT      },
+       { MNTOPT_ROOTCONTEXT,   MS_COMMENT      },
+#endif
+#ifdef MS_I_VERSION
+       { MNTOPT_IVERSION,      MS_I_VERSION    },
+#endif
+#ifdef MS_MANDLOCK
+       { MNTOPT_NBMAND,        MS_MANDLOCK     },
+#endif
+       /* Valid options not found in mount(8) */
+       { MNTOPT_BIND,          MS_BIND         },
+#ifdef MS_REC
+       { MNTOPT_RBIND,         MS_BIND|MS_REC  },
+#endif
+       { MNTOPT_COMMENT,       MS_COMMENT      },
+       { MNTOPT_BOOTWAIT,      MS_COMMENT      },
+       { MNTOPT_NOBOOTWAIT,    MS_COMMENT      },
+       { MNTOPT_OPTIONAL,      MS_COMMENT      },
+       { MNTOPT_SHOWTHROUGH,   MS_COMMENT      },
+#ifdef MS_NOSUB
+       { MNTOPT_NOSUB,         MS_NOSUB        },
+#endif
+#ifdef MS_SILENT
+       { MNTOPT_QUIET,         MS_SILENT       },
+#endif
+       /* Custom zfs options */
+       { MNTOPT_NOXATTR,       MS_COMMENT      },
+       { NULL,                 0               } };
+
+/*
+ * Break the mount option in to a name/value pair.  The name is
+ * validated against the option map and mount flags set accordingly.
+ */
+static int
+parse_option(char *mntopt, unsigned long *mntflags, int sloppy)
+{
+       const option_map_t *opt;
+       char *ptr, *name, *value = NULL;
+       int rc;
+
+       name = strdup(mntopt);
+       if (name == NULL)
+               return (ENOMEM);
+
+       for (ptr = name; ptr && *ptr; ptr++) {
+               if (*ptr == '=') {
+                       *ptr = '\0';
+                       value = ptr+1;
+                       break;
+               }
+       }
+
+       for (opt = option_map; opt->name != NULL; opt++) {
+               if (strncmp(name, opt->name, strlen(name)) == 0) {
+                       *mntflags |= opt->mask;
+
+                       /* MS_USERS implies default user options */
+                       if (opt->mask & (MS_USERS))
+                               *mntflags |= (MS_NOEXEC|MS_NOSUID|MS_NODEV);
+
+                       /* MS_OWNER|MS_GROUP imply default owner options */
+                       if (opt->mask & (MS_OWNER | MS_GROUP))
+                               *mntflags |= (MS_NOSUID|MS_NODEV);
+
+                       rc = 0;
+                       goto out;
+               }
+       }
+
+       if (!sloppy)
+               rc = ENOENT;
+out:
+       /* If required further process on the value may be done here */
+       free(name);
+       return (rc);
+}
+
+/*
+ * Translate the mount option string in to MS_* mount flags for the
+ * kernel vfs.  When sloppy is non-zero unknown options will be ignored
+ * otherwise they are considered fatal are copied in to badopt.
+ */
+static int
+parse_options(char *mntopts, unsigned long *mntflags, int sloppy, char *badopt)
+{
+       int rc = 0, quote = 0;
+       char *ptr, *opt, *opts;
+
+       opts = strdup(mntopts);
+       if (opts == NULL)
+               return (ENOMEM);
+
+       *mntflags = 0;
+       opt = NULL;
+
+       /*
+        * Scan through all mount options which must be comma delimited.
+        * We must be careful to notice regions which are double quoted
+        * and skip commas in these regions.  Each option is then checked
+        * to determine if it is a known option.
+        */
+       for (ptr = opts; ptr && *ptr; ptr++) {
+               if (opt == NULL)
+                       opt = ptr;
+
+               if (*ptr == '"')
+                       quote = !quote;
+
+               if (quote)
+                       continue;
+
+               if ((*ptr == ',') || (*ptr == '\0')) {
+                       *ptr = '\0';
+                       rc = parse_option(opt, mntflags, sloppy);
+                       if (rc) {
+                               strcpy(badopt, opt);
+                               goto out;
+                       }
+
+                       opt = NULL;
+               }
+       }
+out:
+       free(opts);
+       return (rc);
+}
+
 /*
- * Called when invoked as /etc/fs/zfs/mount.  Do the mount if the mountpoint is
- * 'legacy'.  Otherwise, complain that use should be using 'zfs mount'.
+ * Called when invoked as /sbin/mount.zfs, mount helper for mount(8).
  */
-#ifdef HAVE_ZPL
 static int
 manual_mount(int argc, char **argv)
 {
        zfs_handle_t *zhp;
-       char mountpoint[ZFS_MAXPROPLEN];
+       char legacy[ZFS_MAXPROPLEN];
        char mntopts[MNT_LINE_MAX] = { '\0' };
-       int ret;
-       int c;
-       int flags = 0;
-       char *dataset, *path;
+       char badopt[MNT_LINE_MAX] = { '\0' };
+       char *dataset, *mntpoint;
+       unsigned long mntflags;
+       int sloppy = 0, fake = 0, verbose = 0;
+       int rc, c;
 
        /* check options */
-       while ((c = getopt(argc, argv, ":mo:O")) != -1) {
+       while ((c = getopt(argc, argv, "sfnvo:h?")) != -1) {
                switch (c) {
-               case 'o':
-                       (void) strlcpy(mntopts, optarg, sizeof (mntopts));
+               case 's':
+                       sloppy = 1;
                        break;
-               case 'O':
-                       flags |= MS_OVERLAY;
+               case 'f':
+                       fake = 1;
                        break;
-               case 'm':
-                       flags |= MS_NOMNTTAB;
+               case 'n':
+                       /* Ignored, handled by mount(8) */
                        break;
-               case ':':
-                       (void) fprintf(stderr, gettext("missing argument for "
-                           "'%c' option\n"), optopt);
-                       usage(B_FALSE);
+               case 'v':
+                       verbose++;
+                       break;
+               case 'o':
+                       (void) strlcpy(mntopts, optarg, sizeof (mntopts));
                        break;
+               case 'h':
                case '?':
-                       (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+                       (void) fprintf(stderr, gettext("Invalid option '%c'\n"),
                            optopt);
-                       (void) fprintf(stderr, gettext("usage: mount [-o opts] "
-                           "<path>\n"));
-                       return (2);
+                       (void) fprintf(stderr, gettext("Usage: mount.zfs "
+                           "[-sfnv] [-o options] <dataset> <mountpoint>\n"));
+                       return (MOUNT_USAGE);
                }
        }
 
@@ -3920,86 +4048,149 @@ manual_mount(int argc, char **argv)
                else
                        (void) fprintf(stderr, gettext("too many arguments\n"));
                (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n");
-               return (2);
+               return (MOUNT_USAGE);
        }
 
        dataset = argv[0];
-       path = argv[1];
+       mntpoint = argv[1];
 
-       /* try to open the dataset */
-       if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL)
-               return (1);
+       /* try to open the dataset to access the mount point */
+       if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
+               (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
+                   "mounted, unable to open the dataset\n"), dataset);
+               return (MOUNT_USAGE);
+       }
 
-       (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
-           sizeof (mountpoint), NULL, NULL, 0, B_FALSE);
+       (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, legacy,
+           sizeof (legacy), NULL, NULL, 0, B_FALSE);
 
-       /* check for legacy mountpoint and complain appropriately */
-       ret = 0;
-       if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
-               if (mount(dataset, path, MS_OPTIONSTR | flags, MNTTYPE_ZFS,
-                   NULL, 0, mntopts, sizeof (mntopts)) != 0) {
-                       (void) fprintf(stderr, gettext("mount failed: %s\n"),
-                           strerror(errno));
-                       ret = 1;
-               }
-       } else {
+       zfs_close(zhp);
+
+       /* check for legacy mountpoint or util mount option */
+       if ((!strcmp(legacy, ZFS_MOUNTPOINT_LEGACY) == 0) &&
+           (strstr(mntopts, MNTOPT_ZFSUTIL) == NULL)) {
                (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
-                   "mounted using 'mount -F zfs'\n"), dataset);
+                   "mounted using 'mount -a -t zfs'\n"), dataset);
                (void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' "
-                   "instead.\n"), path);
-               (void) fprintf(stderr, gettext("If you must use 'mount -F zfs' "
-                   "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n"));
-               (void) fprintf(stderr, gettext("See zfs(1M) for more "
+                   "instead.\n"), mntpoint);
+               (void) fprintf(stderr, gettext("If you must use 'mount -a -t "
+                   "zfs' or /etc/fstab, use 'zfs set mountpoint=legacy'.\n"));
+               (void) fprintf(stderr, gettext("See zfs(8) for more "
                    "information.\n"));
-               ret = 1;
+               return (MOUNT_USAGE);
+       }
+
+       /* validate mount options and set mntflags */
+       rc = parse_options(mntopts, &mntflags, sloppy, badopt);
+       if (rc) {
+               switch (rc) {
+               case ENOMEM:
+                       (void) fprintf(stderr, gettext("filesystem '%s' "
+                           "cannot be mounted due to a memory allocation "
+                           "failure\n"), dataset);
+                       return (MOUNT_SYSERR);
+               case EINVAL:
+                       (void) fprintf(stderr, gettext("filesystem '%s' "
+                           "cannot be mounted of due to the invalid option "
+                           "'%s'\n"), dataset, badopt);
+                       (void) fprintf(stderr, gettext("Use the '-s' option "
+                           "to ignore the bad mount option.\n"));
+                       return (MOUNT_USAGE);
+               default:
+                       (void) fprintf(stderr, gettext("filesystem '%s' "
+                           "cannot be mounted due to internal error %d\n"),
+                           dataset, rc);
+                       return (MOUNT_SOFTWARE);
+               }
        }
 
-       return (ret);
+       if (verbose > 2)
+               printf("mount.zfs: dataset: \"%s\", mountpoint: \"%s\" "
+                   "mountflags: 0x%lx, mountopts: \"%s\"\n", dataset,
+                   mntpoint, mntflags, mntopts);
+
+       /* load the zfs posix layer module (zpl) */
+       if (libzfs_load_module("zpl")) {
+               (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
+                   "mounted without the zpl kernel module\n"), dataset);
+               (void) fprintf(stderr, gettext("Use 'dmesg' to determine why "
+                   "the module could not be loaded.\n"));
+               return (MOUNT_SYSERR);
+       }
+
+       if (!fake) {
+               rc = mount(dataset, mntpoint, MNTTYPE_ZFS, mntflags, mntopts);
+               if (rc) {
+                       (void) fprintf(stderr, gettext("filesystem '%s' can"
+                           "not be mounted due to error %d\n"), dataset, rc);
+                       return (MOUNT_USAGE);
+               }
+       }
+
+       return (MOUNT_SUCCESS);
 }
 
+#ifdef HAVE_UNMOUNT_HELPER
 /*
- * Called when invoked as /etc/fs/zfs/umount.  Unlike a manual mount, we allow
- * unmounts of non-legacy filesystems, as this is the dominant administrative
- * interface.
+ * Called when invoked as /sbin/umount.zfs, mount helper for mount(8).
+ * Unlike a manual mount, we allow unmounts of non-legacy filesystems,
+ * as this is the dominant administrative interface.
  */
 static int
 manual_unmount(int argc, char **argv)
 {
-       int flags = 0;
+       int verbose = 0, flags = 0;
        int c;
 
        /* check options */
-       while ((c = getopt(argc, argv, "f")) != -1) {
+       while ((c = getopt(argc, argv, "nlfvrh?")) != -1) {
                switch (c) {
+               case 'n':
+                       /* Ignored, handled by mount(8) */
+                       break;
+               case 'l':
+                       flags = MS_DETACH;
+                       break;
                case 'f':
                        flags = MS_FORCE;
                        break;
+               case 'v':
+                       verbose++;
+                       break;
+               case 'r':
+                       /* Remount read-only on umount failure, unsupported */
+                       (void) fprintf(stderr, gettext("Unsupported option "
+                           "'%c'\n"), optopt);
+                       return (MOUNT_USAGE);
+               case 'h':
                case '?':
-                       (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+                       (void) fprintf(stderr, gettext("Invalid option '%c'\n"),
                            optopt);
-                       (void) fprintf(stderr, gettext("usage: unmount [-f] "
-                           "<path>\n"));
-                       return (2);
+                       (void) fprintf(stderr, gettext("Usage: umount.zfs "
+                           "[-nlfvr] <mountpoint>\n"));
+                       return (MOUNT_USAGE);
                }
        }
 
        argc -= optind;
        argv += optind;
 
-       /* check arguments */
+       /* check that we only have one argument */
        if (argc != 1) {
                if (argc == 0)
-                       (void) fprintf(stderr, gettext("missing path "
+                       (void) fprintf(stderr, gettext("missing mountpoint "
                            "argument\n"));
                else
                        (void) fprintf(stderr, gettext("too many arguments\n"));
-               (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
-               return (2);
+
+               (void) fprintf(stderr, gettext("Usage: umount.zfs [-nlfvr] "
+                   "<mountpoint>\n"));
+               return (MOUNT_USAGE);
        }
 
        return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
 }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_UNMOUNT_HELPER */
 
 static int
 find_command_idx(char *command, int *idx)
@@ -4098,9 +4289,7 @@ main(int argc, char **argv)
 {
        int ret;
        int i = 0;
-#ifdef HAVE_ZPL
        char *progname;
-#endif
        char *cmdname;
 
        (void) setlocale(LC_ALL, "");
@@ -4114,20 +4303,18 @@ main(int argc, char **argv)
                return (1);
        }
 
-#ifdef HAVE_ZPL
        /*
         * This command also doubles as the /etc/fs mount and unmount program.
         * Determine if we should take this behavior based on argv[0].
         */
        progname = basename(argv[0]);
-       if (strcmp(progname, "mount") == 0) {
+       if (strcmp(progname, "mount.zfs") == 0) {
                ret = manual_mount(argc, argv);
-       } else if (strcmp(progname, "umount") == 0) {
+#ifdef HAVE_UNMOUNT_HELPER
+       } else if (strcmp(progname, "umount.zfs") == 0) {
                ret = manual_unmount(argc, argv);
+#endif /* HAVE_UNMOUNT_HELPER */
        } else {
-#else
-       {
-#endif /* HAVE_ZPL */
                /*
                 * Make sure the user has specified some command.
                 */
index df97db3..eb67b15 100644 (file)
@@ -21,4 +21,4 @@ zinject_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zinject_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zinject_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
index ddf61bc..8182ab3 100644 (file)
@@ -53,21 +53,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -180,6 +183,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -311,7 +315,7 @@ zinject_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zinject_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zinject_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
 all: all-am
 
 .SUFFIXES:
index 9960752..1607866 100644 (file)
@@ -115,7 +115,7 @@ parse_pathname(const char *inpath, char *dataset, char *relpath,
        }
 
        if ((fp = fopen(MNTTAB, "r")) == NULL) {
-               (void) fprintf(stderr, "cannot open /etc/mnttab\n");
+               (void) fprintf(stderr, "cannot open /etc/mtab\n");
                return (-1);
        }
 
index 3ad90e3..d584ead 100644 (file)
@@ -566,7 +566,7 @@ main(int argc, char **argv)
        zinject_record_t record = { 0 };
        char pool[MAXNAMELEN];
        char dataset[MAXNAMELEN];
-       zfs_handle_t *zhp;
+       zfs_handle_t *zhp = NULL;
        int nowrites = 0;
        int dur_txg = 0;
        int dur_secs = 0;
@@ -951,20 +951,16 @@ main(int argc, char **argv)
        if (dataset[0] != '\0' && domount) {
                if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
                        return (1);
-#ifdef HAVE_ZPL
                if (zfs_unmount(zhp, NULL, 0) != 0)
                        return (1);
-#endif /* HAVE_ZPL */
        }
 
        record.zi_error = error;
 
        ret = register_handler(pool, flags, &record, quiet);
 
-#ifdef HAVE_ZPL
        if (dataset[0] != '\0' && domount)
                ret = (zfs_mount(zhp, NULL, 0) != 0);
-#endif /* HAVE_ZPL */
 
        libzfs_fini(g_zfs);
 
index 911f9c3..b29bfd7 100644 (file)
@@ -53,21 +53,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -170,6 +173,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index a0d1646..d3ca061 100644 (file)
@@ -23,4 +23,4 @@ zpool_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zpool_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zpool_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
index 258de64..9ceb474 100644 (file)
@@ -53,21 +53,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -181,6 +184,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -314,7 +318,7 @@ zpool_LDADD = \
        $(top_builddir)/lib/libzpool/libzpool.la \
        $(top_builddir)/lib/libzfs/libzfs.la
 
-zpool_LDFLAGS = -pthread -lm $(ZLIB) -lrt $(LIBUUID) $(LIBBLKID)
+zpool_LDFLAGS = -pthread -lm $(ZLIB) -lrt -ldl $(LIBUUID) $(LIBBLKID)
 all: all-am
 
 .SUFFIXES:
index 1e9b3b6..bad4e2a 100644 (file)
@@ -716,9 +716,7 @@ zpool_do_create(int argc, char **argv)
            (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
            strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
                char buf[MAXPATHLEN];
-#ifdef HAVE_ZPL
                DIR *dirp;
-#endif
 
                if (mountpoint && mountpoint[0] != '/') {
                        (void) fprintf(stderr, gettext("invalid mountpoint "
@@ -743,7 +741,6 @@ zpool_do_create(int argc, char **argv)
                                    mountpoint);
                }
 
-#ifdef HAVE_ZPL
                if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
                        (void) fprintf(stderr, gettext("mountpoint '%s' : "
                            "%s\n"), buf, strerror(errno));
@@ -766,7 +763,6 @@ zpool_do_create(int argc, char **argv)
                                goto errout;
                        }
                }
-#endif /* HAVE_ZPL */
        }
 
        if (dryrun) {
@@ -797,12 +793,8 @@ zpool_do_create(int argc, char **argv)
                                            zfs_prop_to_name(
                                            ZFS_PROP_MOUNTPOINT),
                                            mountpoint) == 0);
-#ifdef HAVE_ZPL
                                if (zfs_mount(pool, NULL, 0) == 0)
                                        ret = zfs_shareall(pool);
-#else
-                               ret = 0;
-#endif /* HAVE_ZPL */
                                zfs_close(pool);
                        }
                } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
@@ -1579,14 +1571,12 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
        if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
                return (1);
 
-#if HAVE_ZPL
        if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
            !(flags & ZFS_IMPORT_ONLY) &&
            zpool_enable_datasets(zhp, mntopts, 0) != 0) {
                zpool_close(zhp);
                return (1);
        }
-#endif /* HAVE_ZPL */
 
        zpool_close(zhp);
        return (0);
index 6d2fd50..c518542 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index ea8947c..6b21c3e 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index c102d02..c7291cb 100644 (file)
@@ -53,21 +53,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -180,6 +183,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
diff --git a/config/kernel-evict-inode.m4 b/config/kernel-evict-inode.m4
new file mode 100644 (file)
index 0000000..3cf5a36
--- /dev/null
@@ -0,0 +1,21 @@
+dnl #
+dnl # 2.6.36 API change
+dnl # The sops->delete_inode() and sops->clear_inode() callbacks have
+dnl # replaced by a single sops->evict_inode() callback.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_EVICT_INODE], [
+       AC_MSG_CHECKING([whether sops->evict_inode() exists])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               void (*evict_inode) (struct inode *) = NULL;
+               struct super_operations sops;
+
+               sops.evict_inode = evict_inode;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_EVICT_INODE, 1, [sops->evict_inode() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
diff --git a/config/kernel-fsync.m4 b/config/kernel-fsync.m4
new file mode 100644 (file)
index 0000000..2733dba
--- /dev/null
@@ -0,0 +1,20 @@
+dnl #
+dnl # 2.6.35 API change
+dnl # The dentry argument was deamed unused and dropped in 2.6.36.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_FSYNC_2ARGS], [
+       AC_MSG_CHECKING([whether fops->fsync() wants 2 args])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               int (*fsync) (struct file *, int datasync) = NULL;
+               struct file_operations fops;
+
+               fops.fsync = fsync;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_2ARGS_FSYNC, 1, [fops->fsync() want 2 args])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4
new file mode 100644 (file)
index 0000000..1ebe1f0
--- /dev/null
@@ -0,0 +1,81 @@
+dnl #
+dnl # 2.6.35 API change,
+dnl # The 'struct xattr_handler' was constified in the generic
+dnl # super_block structure.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_CONST_XATTR_HANDLER],
+       [AC_MSG_CHECKING([whether super_block uses const struct xattr_hander])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+               #include <linux/xattr.h>
+
+               const struct xattr_handler xattr_test_handler = {
+                       .prefix = "test",
+                       .get    = NULL,
+                       .set    = NULL,
+               };
+
+               const struct xattr_handler *xattr_handlers[] = {
+                       &xattr_test_handler,
+               };
+       ],[
+               struct super_block sb;
+
+               sb.s_xattr = xattr_handlers;
+       ],[
+               AC_MSG_RESULT([yes])
+               AC_DEFINE(HAVE_CONST_XATTR_HANDLER, 1,
+                         [super_block uses const struct xattr_hander])
+       ],[
+               AC_MSG_RESULT([no])
+       ])
+])
+
+dnl #
+dnl # 2.6.33 API change,
+dnl # The xattr_hander->get() callback was changed to take a dentry
+dnl # instead of an inode, and a handler_flags argument was added.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_GET], [
+       AC_MSG_CHECKING([whether xattr_handler->get() wants dentry])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/xattr.h>
+       ],[
+               int (*get)(struct dentry *dentry, const char *name,
+                   void *buffer, size_t size, int handler_flags) = NULL;
+               struct xattr_handler xops;
+
+               xops.get = get;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_DENTRY_XATTR_GET, 1,
+                   [xattr_handler->get() wants dentry])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+dnl #
+dnl # 2.6.33 API change,
+dnl # The xattr_hander->set() callback was changed to take a dentry
+dnl # instead of an inode, and a handler_flags argument was added.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [
+       AC_MSG_CHECKING([whether xattr_handler->set() wants dentry])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/xattr.h>
+       ],[
+               int (*set)(struct dentry *dentry, const char *name,
+                   const void *buffer, size_t size, int flags,
+                   int handler_flags) = NULL;
+               struct xattr_handler xops;
+
+               xops.set = set;
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_DENTRY_XATTR_SET, 1,
+                   [xattr_handler->set() wants dentry])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
index c2fc5a0..c3321ed 100644 (file)
@@ -28,6 +28,11 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
        ZFS_AC_KERNEL_GET_DISK_RO
        ZFS_AC_KERNEL_RQ_IS_SYNC
        ZFS_AC_KERNEL_RQ_FOR_EACH_SEGMENT
+       ZFS_AC_KERNEL_CONST_XATTR_HANDLER
+       ZFS_AC_KERNEL_XATTR_HANDLER_GET
+       ZFS_AC_KERNEL_XATTR_HANDLER_SET
+       ZFS_AC_KERNEL_FSYNC_2ARGS
+       ZFS_AC_KERNEL_EVICT_INODE
 
        if test "$LINUX_OBJ" != "$LINUX"; then
                KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
@@ -78,8 +83,11 @@ AC_DEFUN([ZFS_AC_KERNEL], [
 
        AC_MSG_CHECKING([kernel source directory])
        if test -z "$kernelsrc"; then
-               headersdir="/lib/modules/$(uname -r)/build"
-               if test -e "$headersdir"; then
+               if test -e "/lib/modules/$(uname -r)/source"; then
+                       headersdir="/lib/modules/$(uname -r)/source"
+                       sourcelink=$(readlink -f "$headersdir")
+               elif test -e "/lib/modules/$(uname -r)/build"; then
+                       headersdir="/lib/modules/$(uname -r)/build"
                        sourcelink=$(readlink -f "$headersdir")
                else
                        sourcelink=$(ls -1d /usr/src/kernels/* \
@@ -105,7 +113,9 @@ AC_DEFUN([ZFS_AC_KERNEL], [
        AC_MSG_RESULT([$kernelsrc])
        AC_MSG_CHECKING([kernel build directory])
        if test -z "$kernelbuild"; then
-               if test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}; then
+               if test -e "/lib/modules/$(uname -r)/build"; then
+                       kernelbuild=`readlink -f /lib/modules/$(uname -r)/build`
+               elif test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}; then
                        kernelbuild=${kernelsrc}-obj/${target_cpu}/${target_cpu}
                elif test -d ${kernelsrc}-obj/${target_cpu}/default; then
                        kernelbuild=${kernelsrc}-obj/${target_cpu}/default
diff --git a/config/user-libshare.m4 b/config/user-libshare.m4
deleted file mode 100644 (file)
index 3b92bba..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-dnl #
-dnl # Check for libshare
-dnl #
-AC_DEFUN([ZFS_AC_CONFIG_USER_LIBSHARE], [
-       AC_CHECK_LIB([share], [sa_init],
-               [AC_DEFINE([HAVE_LIBSHARE], 1,
-               [Define to 1 if 'libshare' library available])])
-])
diff --git a/config/user-selinux.m4 b/config/user-selinux.m4
new file mode 100644 (file)
index 0000000..84df6ce
--- /dev/null
@@ -0,0 +1,36 @@
+dnl #
+dnl # Check to see if the selinux libraries are available.  If they
+dnl # are then they will be consulted during mount to determine if
+dnl # selinux is enabled or disabled.
+dnl #
+AC_DEFUN([ZFS_AC_CONFIG_USER_LIBSELINUX], [
+       AC_ARG_WITH([selinux],
+               [AS_HELP_STRING([--with-selinux],
+               [support selinux @<:@default=check@:>@])],
+               [],
+               [with_selinux=check])
+
+       LIBSELINUX=
+       AS_IF([test "x$with_selinux" != xno], [
+               AC_CHECK_HEADER([selinux/selinux.h], [
+                       AC_CHECK_LIB([selinux], [is_selinux_enabled], [
+                               AC_SUBST([LIBSELINUX], ["-lselinux"])
+                               AC_DEFINE([HAVE_LIBSELINUX], 1,
+                                       [Define if you have selinux])
+                       ], [
+                               AS_IF([test "x$with_selinux" != xcheck],
+                                       [AC_MSG_FAILURE(
+                                       [--with-selinux given but unavailable])
+                               ])
+                       ])
+               ], [
+                       AS_IF([test "x$with_selinux" != xcheck],
+                               [AC_MSG_FAILURE(
+                               [--with-selinux given but unavailable])
+                       ])
+               ])
+       ], [
+               AC_MSG_CHECKING([for selinux support])
+               AC_MSG_RESULT([no])
+       ])
+])
index bc68808..a79deef 100644 (file)
@@ -3,11 +3,11 @@ dnl # Default ZFS user configuration
 dnl #
 AC_DEFUN([ZFS_AC_CONFIG_USER], [
        ZFS_AC_CONFIG_USER_ARCH
-       ZFS_AC_CONFIG_USER_LIBSHARE
        ZFS_AC_CONFIG_USER_IOCTL
        ZFS_AC_CONFIG_USER_ZLIB
        ZFS_AC_CONFIG_USER_LIBUUID
        ZFS_AC_CONFIG_USER_LIBBLKID
+       ZFS_AC_CONFIG_USER_LIBSELINUX
        ZFS_AC_CONFIG_USER_FRAME_LARGER_THAN
        ZFS_AC_CONFIG_USER_STACK_GUARD
 ])
index 8c4ce63..02a0715 100755 (executable)
--- a/configure
+++ b/configure
@@ -794,6 +794,7 @@ CONFIG_KERNEL_TRUE
 CONFIG_USER_FALSE
 CONFIG_USER_TRUE
 FRAME_LARGER_THAN
+LIBSELINUX
 LIBBLKID
 LIBUUID
 ZLIB
@@ -972,6 +973,7 @@ with_linux_obj
 with_spl
 with_spl_obj
 with_blkid
+with_selinux
 enable_debug
 '
       ac_precious_vars='build_alias
@@ -1639,6 +1641,7 @@ Optional Packages:
   --with-spl=PATH         Path to spl source
   --with-spl-obj=PATH     Path to spl build objects
   --with-blkid            support blkid caching [default=check]
+  --with-selinux          support selinux [default=check]
 
 Some influential environment variables:
   CC          C compiler command
@@ -4817,13 +4820,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
 else
   lt_cv_nm_interface="BSD nm"
   echo "int some_variable = 0;" > conftest.$ac_ext
-  (eval echo "\"\$as_me:4820: $ac_compile\"" >&5)
+  (eval echo "\"\$as_me:4823: $ac_compile\"" >&5)
   (eval "$ac_compile" 2>conftest.err)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:4823: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+  (eval echo "\"\$as_me:4826: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
   (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
   cat conftest.err >&5
-  (eval echo "\"\$as_me:4826: output\"" >&5)
+  (eval echo "\"\$as_me:4829: output\"" >&5)
   cat conftest.out >&5
   if $GREP 'External.*some_variable' conftest.out > /dev/null; then
     lt_cv_nm_interface="MS dumpbin"
@@ -6029,7 +6032,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6032 "configure"' > conftest.$ac_ext
+  echo '#line 6035 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7882,11 +7885,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7885: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7888: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7889: \$? = $ac_status" >&5
+   echo "$as_me:7892: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8221,11 +8224,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8224: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8227: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8228: \$? = $ac_status" >&5
+   echo "$as_me:8231: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8326,11 +8329,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8329: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8332: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8333: \$? = $ac_status" >&5
+   echo "$as_me:8336: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -8381,11 +8384,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8384: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8387: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8388: \$? = $ac_status" >&5
+   echo "$as_me:8391: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -11184,7 +11187,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11187 "configure"
+#line 11190 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11280,7 +11283,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11283 "configure"
+#line 11286 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
        { $as_echo "$as_me:$LINENO: checking kernel source directory" >&5
 $as_echo_n "checking kernel source directory... " >&6; }
        if test -z "$kernelsrc"; then
-               headersdir="/lib/modules/$(uname -r)/build"
-               if test -e "$headersdir"; then
+               if test -e "/lib/modules/$(uname -r)/source"; then
+                       headersdir="/lib/modules/$(uname -r)/source"
+                       sourcelink=$(readlink -f "$headersdir")
+               elif test -e "/lib/modules/$(uname -r)/build"; then
+                       headersdir="/lib/modules/$(uname -r)/build"
                        sourcelink=$(readlink -f "$headersdir")
                else
                        sourcelink=$(ls -1d /usr/src/kernels/* \
@@ -11888,7 +11894,9 @@ $as_echo "$kernelsrc" >&6; }
        { $as_echo "$as_me:$LINENO: checking kernel build directory" >&5
 $as_echo_n "checking kernel build directory... " >&6; }
        if test -z "$kernelbuild"; then
-               if test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}; then
+               if test -e "/lib/modules/$(uname -r)/build"; then
+                       kernelbuild=`readlink -f /lib/modules/$(uname -r)/build`
+               elif test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}; then
                        kernelbuild=${kernelsrc}-obj/${target_cpu}/${target_cpu}
                elif test -d ${kernelsrc}-obj/${target_cpu}/default; then
                        kernelbuild=${kernelsrc}-obj/${target_cpu}/default
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether super_block uses const struct xattr_hander" >&5
+$as_echo_n "checking whether super_block uses const struct xattr_hander... " >&6; }
 
-       if test "$LINUX_OBJ" != "$LINUX"; then
-               KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
-       fi
 
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
 
 
-                       KERNELCPPFLAGS="$KERNELCPPFLAGS -DHAVE_SPL -D_KERNEL"
-       KERNELCPPFLAGS="$KERNELCPPFLAGS -DTEXT_DOMAIN=\\\"zfs-linux-kernel\\\""
+               #include <linux/fs.h>
+               #include <linux/xattr.h>
 
+               const struct xattr_handler xattr_test_handler = {
+                       .prefix = "test",
+                       .get    = NULL,
+                       .set    = NULL,
+               };
 
- ;;
-               user)
+               const struct xattr_handler *xattr_handlers[] = {
+                       &xattr_test_handler,
+               };
 
-       { $as_echo "$as_me:$LINENO: checking for target asm dir" >&5
-$as_echo_n "checking for target asm dir... " >&6; }
-       TARGET_ARCH=`echo ${target_cpu} | sed -e s/i.86/i386/`
+int
+main (void)
+{
 
-       case $TARGET_ARCH in
-       i386|x86_64)
-               TARGET_ASM_DIR=asm-${TARGET_ARCH}
-               ;;
-       *)
-               TARGET_ASM_DIR=asm-generic
-               ;;
-       esac
+               struct super_block sb;
 
+               sb.s_xattr = xattr_handlers;
 
-       { $as_echo "$as_me:$LINENO: result: $TARGET_ASM_DIR" >&5
-$as_echo "$TARGET_ASM_DIR" >&6; }
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CONST_XATTR_HANDLER 1
+_ACEOF
 
 
-       { $as_echo "$as_me:$LINENO: checking for sa_init in -lshare" >&5
-$as_echo_n "checking for sa_init in -lshare... " >&6; }
-if test "${ac_cv_lib_share_sa_init+set}" = set; then
-  $as_echo_n "(cached) " >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lshare  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+fi
+
+       rm -Rf build
+
+
+
+
+       { $as_echo "$as_me:$LINENO: checking whether xattr_handler->get() wants dentry" >&5
+$as_echo_n "checking whether xattr_handler->get() wants dentry... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char sa_init ();
+
+               #include <linux/xattr.h>
+
 int
-main ()
+main (void)
 {
-return sa_init ();
+
+               int (*get)(struct dentry *dentry, const char *name,
+                   void *buffer, size_t size, int handler_flags) = NULL;
+               struct xattr_handler xops;
+
+               xops.get = get;
+
   ;
   return 0;
 }
+
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>conftest.er1
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
-       }; then
-  ac_cv_lib_share_sa_init=yes
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DENTRY_XATTR_GET 1
+_ACEOF
+
+
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_share_sa_init=no
-fi
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_share_sa_init" >&5
-$as_echo "$ac_cv_lib_share_sa_init" >&6; }
-if test "x$ac_cv_lib_share_sa_init" = x""yes; then
 
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBSHARE 1
-_ACEOF
 
 fi
 
+       rm -Rf build
 
 
-       { $as_echo "$as_me:$LINENO: checking for ioctl()" >&5
-$as_echo_n "checking for ioctl()... " >&6; }
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <unistd.h>
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "ioctl" >/dev/null 2>&1; then
-  is_unistd=yes
-else
-  is_unistd=no
-fi
-rm -f conftest*
 
-       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <sys/ioctl.h>
+       { $as_echo "$as_me:$LINENO: checking whether xattr_handler->set() wants dentry" >&5
+$as_echo_n "checking whether xattr_handler->set() wants dentry... " >&6; }
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "ioctl" >/dev/null 2>&1; then
-  is_sys_ioctl=yes
-else
-  is_sys_ioctl=no
-fi
-rm -f conftest*
 
-       cat >conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.c
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <stropts.h>
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "ioctl" >/dev/null 2>&1; then
-  is_stropts=yes
-else
-  is_stropts=no
-fi
-rm -f conftest*
 
+               #include <linux/xattr.h>
 
-       if test $is_unistd = yes; then
-               result=unistd.h
+int
+main (void)
+{
 
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_IOCTL_IN_UNISTD_H 1
-_ACEOF
+               int (*set)(struct dentry *dentry, const char *name,
+                   const void *buffer, size_t size, int flags,
+                   int handler_flags) = NULL;
+               struct xattr_handler xops;
 
-       else
+               xops.set = set;
 
-               if test $is_sys_ioctl = yes; then
-                       result=sys/ioctl.h
+  ;
+  return 0;
+}
 
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_IOCTL_IN_SYS_IOCTL_H 1
 _ACEOF
 
-               elif test $is_stropts = yes; then
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_IOCTL_IN_STROPTS_H 1
+#define HAVE_DENTRY_XATTR_SET 1
 _ACEOF
 
-               else
-                       result=no
-               fi
-       fi
 
-       if test $result = no; then
-                { $as_echo "$as_me:$LINENO: result: no" >&5
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
 $as_echo "no" >&6; }
-                { { $as_echo "$as_me:$LINENO: error: *** Cannot locate ioctl() definition" >&5
-$as_echo "$as_me: error: *** Cannot locate ioctl() definition" >&2;}
-   { (exit 1); exit 1; }; }
-       else
-               { $as_echo "$as_me:$LINENO: result: yes" >&5
-$as_echo "yes" >&6; }
-       fi
 
 
-       ZLIB=
 
-       if test "${ac_cv_header_zlib_h+set}" = set; then
-  { $as_echo "$as_me:$LINENO: checking for zlib.h" >&5
-$as_echo_n "checking for zlib.h... " >&6; }
-if test "${ac_cv_header_zlib_h+set}" = set; then
-  $as_echo_n "(cached) " >&6
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
-$as_echo "$ac_cv_header_zlib_h" >&6; }
-else
-  # Is the header compilable?
-{ $as_echo "$as_me:$LINENO: checking zlib.h usability" >&5
-$as_echo_n "checking zlib.h usability... " >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <zlib.h>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest.$ac_objext; then
-  ac_header_compiler=yes
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_header_compiler=no
-fi
+       rm -Rf build
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
 
-# Is the header present?
-{ $as_echo "$as_me:$LINENO: checking zlib.h presence" >&5
-$as_echo_n "checking zlib.h presence... " >&6; }
-cat >conftest.$ac_ext <<_ACEOF
+
+
+       { $as_echo "$as_me:$LINENO: checking whether fops->fsync() wants 2 args" >&5
+$as_echo_n "checking whether fops->fsync() wants 2 args... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <zlib.h>
+
+
+               #include <linux/fs.h>
+
+int
+main (void)
+{
+
+               int (*fsync) (struct file *, int datasync) = NULL;
+               struct file_operations fops;
+
+               fops.fsync = fsync;
+
+  ;
+  return 0;
+}
+
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null && {
-        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       }; then
-  ac_header_preproc=yes
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_2ARGS_FSYNC 1
+_ACEOF
+
+
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  ac_header_preproc=no
-fi
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
-rm -f conftest.err conftest.$ac_ext
-{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
 
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: zlib.h:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: zlib.h:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
-$as_echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
-$as_echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
 
-    ;;
-esac
-{ $as_echo "$as_me:$LINENO: checking for zlib.h" >&5
-$as_echo_n "checking for zlib.h... " >&6; }
-if test "${ac_cv_header_zlib_h+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_header_zlib_h=$ac_header_preproc
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
-$as_echo "$ac_cv_header_zlib_h" >&6; }
 
-fi
-if test "x$ac_cv_header_zlib_h" = x""yes; then
-  :
-else
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error:
-       *** zlib.h missing, zlib-devel package required
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error:
-       *** zlib.h missing, zlib-devel package required
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
-fi
+       rm -Rf build
 
 
 
 
-{ $as_echo "$as_me:$LINENO: checking for compress2 in -lz" >&5
-$as_echo_n "checking for compress2 in -lz... " >&6; }
-if test "${ac_cv_lib_z_compress2+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+       { $as_echo "$as_me:$LINENO: checking whether sops->evict_inode() exists" >&5
+$as_echo_n "checking whether sops->evict_inode() exists... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char compress2 ();
+
+               #include <linux/fs.h>
+
 int
-main ()
+main (void)
 {
-return compress2 ();
+
+               void (*evict_inode) (struct inode *) = NULL;
+               struct super_operations sops;
+
+               sops.evict_inode = evict_inode;
+
   ;
   return 0;
 }
+
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>conftest.er1
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
-       }; then
-  ac_cv_lib_z_compress2=yes
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_EVICT_INODE 1
+_ACEOF
+
+
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_z_compress2=no
-fi
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress2" >&5
-$as_echo "$ac_cv_lib_z_compress2" >&6; }
-if test "x$ac_cv_lib_z_compress2" = x""yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBZ 1
-_ACEOF
 
-  LIBS="-lz $LIBS"
 
-else
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error:
-       *** compress2() missing, zlib-devel package required
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error:
-       *** compress2() missing, zlib-devel package required
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
 fi
 
+       rm -Rf build
 
 
-{ $as_echo "$as_me:$LINENO: checking for uncompress in -lz" >&5
-$as_echo_n "checking for uncompress in -lz... " >&6; }
-if test "${ac_cv_lib_z_uncompress+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char uncompress ();
-int
-main ()
-{
-return uncompress ();
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
-       }; then
-  ac_cv_lib_z_uncompress=yes
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_z_uncompress=no
-fi
+       if test "$LINUX_OBJ" != "$LINUX"; then
+               KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
+       fi
 
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_uncompress" >&5
-$as_echo "$ac_cv_lib_z_uncompress" >&6; }
-if test "x$ac_cv_lib_z_uncompress" = x""yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBZ 1
-_ACEOF
 
-  LIBS="-lz $LIBS"
 
-else
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error:
-       *** uncompress() missing, zlib-devel package required
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error:
-       *** uncompress() missing, zlib-devel package required
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
-fi
+                       KERNELCPPFLAGS="$KERNELCPPFLAGS -DHAVE_SPL -D_KERNEL"
+       KERNELCPPFLAGS="$KERNELCPPFLAGS -DTEXT_DOMAIN=\\\"zfs-linux-kernel\\\""
 
 
+ ;;
+               user)
 
-{ $as_echo "$as_me:$LINENO: checking for crc32 in -lz" >&5
-$as_echo_n "checking for crc32 in -lz... " >&6; }
-if test "${ac_cv_lib_z_crc32+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+       { $as_echo "$as_me:$LINENO: checking for target asm dir" >&5
+$as_echo_n "checking for target asm dir... " >&6; }
+       TARGET_ARCH=`echo ${target_cpu} | sed -e s/i.86/i386/`
+
+       case $TARGET_ARCH in
+       i386|x86_64)
+               TARGET_ASM_DIR=asm-${TARGET_ARCH}
+               ;;
+       *)
+               TARGET_ASM_DIR=asm-generic
+               ;;
+       esac
+
+
+       { $as_echo "$as_me:$LINENO: result: $TARGET_ASM_DIR" >&5
+$as_echo "$TARGET_ASM_DIR" >&6; }
+
+
+       { $as_echo "$as_me:$LINENO: checking for ioctl()" >&5
+$as_echo_n "checking for ioctl()... " >&6; }
+       cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+#include <unistd.h>
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char crc32 ();
-int
-main ()
-{
-return crc32 ();
-  ;
-  return 0;
-}
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
-       }; then
-  ac_cv_lib_z_crc32=yes
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ioctl" >/dev/null 2>&1; then
+  is_unistd=yes
 else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       ac_cv_lib_z_crc32=no
+  is_unistd=no
 fi
+rm -f conftest*
+
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/ioctl.h>
 
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_crc32" >&5
-$as_echo "$ac_cv_lib_z_crc32" >&6; }
-if test "x$ac_cv_lib_z_crc32" = x""yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBZ 1
 _ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ioctl" >/dev/null 2>&1; then
+  is_sys_ioctl=yes
+else
+  is_sys_ioctl=no
+fi
+rm -f conftest*
 
-  LIBS="-lz $LIBS"
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stropts.h>
 
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "ioctl" >/dev/null 2>&1; then
+  is_stropts=yes
 else
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error:
-       *** crc32() missing, zlib-devel package required
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error:
-       *** crc32() missing, zlib-devel package required
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
+  is_stropts=no
 fi
+rm -f conftest*
 
 
-       ZLIB="-lz"
+       if test $is_unistd = yes; then
+               result=unistd.h
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_IOCTL_IN_UNISTD_H 1
+_ACEOF
+
+       else
 
+               if test $is_sys_ioctl = yes; then
+                       result=sys/ioctl.h
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_ZLIB 1
+#define HAVE_IOCTL_IN_SYS_IOCTL_H 1
 _ACEOF
 
+               elif test $is_stropts = yes; then
 
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_IOCTL_IN_STROPTS_H 1
+_ACEOF
 
-       LIBUUID=
+               else
+                       result=no
+               fi
+       fi
 
-       if test "${ac_cv_header_uuid_uuid_h+set}" = set; then
-  { $as_echo "$as_me:$LINENO: checking for uuid/uuid.h" >&5
-$as_echo_n "checking for uuid/uuid.h... " >&6; }
-if test "${ac_cv_header_uuid_uuid_h+set}" = set; then
+       if test $result = no; then
+                { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+                { { $as_echo "$as_me:$LINENO: error: *** Cannot locate ioctl() definition" >&5
+$as_echo "$as_me: error: *** Cannot locate ioctl() definition" >&2;}
+   { (exit 1); exit 1; }; }
+       else
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+       fi
+
+
+       ZLIB=
+
+       if test "${ac_cv_header_zlib_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for zlib.h" >&5
+$as_echo_n "checking for zlib.h... " >&6; }
+if test "${ac_cv_header_zlib_h+set}" = set; then
   $as_echo_n "(cached) " >&6
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_uuid_uuid_h" >&5
-$as_echo "$ac_cv_header_uuid_uuid_h" >&6; }
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+$as_echo "$ac_cv_header_zlib_h" >&6; }
 else
   # Is the header compilable?
-{ $as_echo "$as_me:$LINENO: checking uuid/uuid.h usability" >&5
-$as_echo_n "checking uuid/uuid.h usability... " >&6; }
+{ $as_echo "$as_me:$LINENO: checking zlib.h usability" >&5
+$as_echo_n "checking zlib.h usability... " >&6; }
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -14447,7 +14320,7 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#include <uuid/uuid.h>
+#include <zlib.h>
 _ACEOF
 rm -f conftest.$ac_objext
 if { (ac_try="$ac_compile"
@@ -14480,15 +14353,15 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 $as_echo "$ac_header_compiler" >&6; }
 
 # Is the header present?
-{ $as_echo "$as_me:$LINENO: checking uuid/uuid.h presence" >&5
-$as_echo_n "checking uuid/uuid.h presence... " >&6; }
+{ $as_echo "$as_me:$LINENO: checking zlib.h presence" >&5
+$as_echo_n "checking zlib.h presence... " >&6; }
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <uuid/uuid.h>
+#include <zlib.h>
 _ACEOF
 if { (ac_try="$ac_cpp conftest.$ac_ext"
 case "(($ac_try" in
@@ -14522,49 +14395,49 @@ $as_echo "$ac_header_preproc" >&6; }
 # So?  What about this header?
 case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
   yes:no: )
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h: proceeding with the compiler's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
     ac_header_preproc=yes
     ;;
   no:yes:* )
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: proceeding with the preprocessor's result" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h: proceeding with the preprocessor's result" >&2;}
-    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: in the future, the compiler will take precedence" >&5
-$as_echo "$as_me: WARNING: uuid/uuid.h: in the future, the compiler will take precedence" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: zlib.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: zlib.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
 
     ;;
 esac
-{ $as_echo "$as_me:$LINENO: checking for uuid/uuid.h" >&5
-$as_echo_n "checking for uuid/uuid.h... " >&6; }
-if test "${ac_cv_header_uuid_uuid_h+set}" = set; then
+{ $as_echo "$as_me:$LINENO: checking for zlib.h" >&5
+$as_echo_n "checking for zlib.h... " >&6; }
+if test "${ac_cv_header_zlib_h+set}" = set; then
   $as_echo_n "(cached) " >&6
 else
-  ac_cv_header_uuid_uuid_h=$ac_header_preproc
+  ac_cv_header_zlib_h=$ac_header_preproc
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_uuid_uuid_h" >&5
-$as_echo "$ac_cv_header_uuid_uuid_h" >&6; }
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+$as_echo "$ac_cv_header_zlib_h" >&6; }
 
 fi
-if test "x$ac_cv_header_uuid_uuid_h" = x""yes; then
+if test "x$ac_cv_header_zlib_h" = x""yes; then
   :
 else
   { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 { { $as_echo "$as_me:$LINENO: error:
-       *** uuid/uuid.h missing, libuuid-devel package required
+       *** zlib.h missing, zlib-devel package required
 See \`config.log' for more details." >&5
 $as_echo "$as_me: error:
-       *** uuid/uuid.h missing, libuuid-devel package required
+       *** zlib.h missing, zlib-devel package required
 See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }; }
 fi
 
 
 
-{ $as_echo "$as_me:$LINENO: checking for uuid_generate in -luuid" >&5
-$as_echo_n "checking for uuid_generate in -luuid... " >&6; }
-if test "${ac_cv_lib_uuid_uuid_generate+set}" = set; then
+{ $as_echo "$as_me:$LINENO: checking for compress2 in -lz" >&5
+$as_echo_n "checking for compress2 in -lz... " >&6; }
+if test "${ac_cv_lib_z_compress2+set}" = set; then
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-luuid  $LIBS"
+LIBS="-lz  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -14592,11 +14465,11 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char uuid_generate ();
+char compress2 ();
 int
 main ()
 {
-return uuid_generate ();
+return compress2 ();
   ;
   return 0;
 }
@@ -14622,12 +14495,12 @@ $as_echo "$ac_try_echo") >&5
         test "$cross_compiling" = yes ||
         $as_test_x conftest$ac_exeext
        }; then
-  ac_cv_lib_uuid_uuid_generate=yes
+  ac_cv_lib_z_compress2=yes
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_uuid_uuid_generate=no
+       ac_cv_lib_z_compress2=no
 fi
 
 rm -rf conftest.dSYM
@@ -14635,36 +14508,36 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_uuid_uuid_generate" >&5
-$as_echo "$ac_cv_lib_uuid_uuid_generate" >&6; }
-if test "x$ac_cv_lib_uuid_uuid_generate" = x""yes; then
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress2" >&5
+$as_echo "$ac_cv_lib_z_compress2" >&6; }
+if test "x$ac_cv_lib_z_compress2" = x""yes; then
   cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBUUID 1
+#define HAVE_LIBZ 1
 _ACEOF
 
-  LIBS="-luuid $LIBS"
+  LIBS="-lz $LIBS"
 
 else
   { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 { { $as_echo "$as_me:$LINENO: error:
-       *** uuid_generate() missing, libuuid-devel package required
+       *** compress2() missing, zlib-devel package required
 See \`config.log' for more details." >&5
 $as_echo "$as_me: error:
-       *** uuid_generate() missing, libuuid-devel package required
+       *** compress2() missing, zlib-devel package required
 See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }; }
 fi
 
 
 
-{ $as_echo "$as_me:$LINENO: checking for uuid_is_null in -luuid" >&5
-$as_echo_n "checking for uuid_is_null in -luuid... " >&6; }
-if test "${ac_cv_lib_uuid_uuid_is_null+set}" = set; then
+{ $as_echo "$as_me:$LINENO: checking for uncompress in -lz" >&5
+$as_echo_n "checking for uncompress in -lz... " >&6; }
+if test "${ac_cv_lib_z_uncompress+set}" = set; then
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-luuid  $LIBS"
+LIBS="-lz  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -14678,11 +14551,11 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char uuid_is_null ();
+char uncompress ();
 int
 main ()
 {
-return uuid_is_null ();
+return uncompress ();
   ;
   return 0;
 }
@@ -14708,12 +14581,12 @@ $as_echo "$ac_try_echo") >&5
         test "$cross_compiling" = yes ||
         $as_test_x conftest$ac_exeext
        }; then
-  ac_cv_lib_uuid_uuid_is_null=yes
+  ac_cv_lib_z_uncompress=yes
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_uuid_uuid_is_null=no
+       ac_cv_lib_z_uncompress=no
 fi
 
 rm -rf conftest.dSYM
@@ -14721,56 +14594,36 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_uuid_uuid_is_null" >&5
-$as_echo "$ac_cv_lib_uuid_uuid_is_null" >&6; }
-if test "x$ac_cv_lib_uuid_uuid_is_null" = x""yes; then
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_uncompress" >&5
+$as_echo "$ac_cv_lib_z_uncompress" >&6; }
+if test "x$ac_cv_lib_z_uncompress" = x""yes; then
   cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBUUID 1
+#define HAVE_LIBZ 1
 _ACEOF
 
-  LIBS="-luuid $LIBS"
+  LIBS="-lz $LIBS"
 
 else
   { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 { { $as_echo "$as_me:$LINENO: error:
-       *** uuid_is_null() missing, libuuid-devel package required
+       *** uncompress() missing, zlib-devel package required
 See \`config.log' for more details." >&5
 $as_echo "$as_me: error:
-       *** uuid_is_null() missing, libuuid-devel package required
+       *** uncompress() missing, zlib-devel package required
 See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }; }
 fi
 
 
-       LIBUUID="-luuid"
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBUUID 1
-_ACEOF
-
-
-
-
-# Check whether --with-blkid was given.
-if test "${with_blkid+set}" = set; then
-  withval=$with_blkid;
-else
-  with_blkid=check
-fi
-
-
-       LIBBLKID=
-       if test "x$with_blkid" != xno; then
 
-               { $as_echo "$as_me:$LINENO: checking for blkid_get_cache in -lblkid" >&5
-$as_echo_n "checking for blkid_get_cache in -lblkid... " >&6; }
-if test "${ac_cv_lib_blkid_blkid_get_cache+set}" = set; then
+{ $as_echo "$as_me:$LINENO: checking for crc32 in -lz" >&5
+$as_echo_n "checking for crc32 in -lz... " >&6; }
+if test "${ac_cv_lib_z_crc32+set}" = set; then
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lblkid  $LIBS"
+LIBS="-lz  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -14784,11 +14637,11 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char blkid_get_cache ();
+char crc32 ();
 int
 main ()
 {
-return blkid_get_cache ();
+return crc32 ();
   ;
   return 0;
 }
@@ -14814,12 +14667,12 @@ $as_echo "$ac_try_echo") >&5
         test "$cross_compiling" = yes ||
         $as_test_x conftest$ac_exeext
        }; then
-  ac_cv_lib_blkid_blkid_get_cache=yes
+  ac_cv_lib_z_crc32=yes
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_blkid_blkid_get_cache=no
+       ac_cv_lib_z_crc32=no
 fi
 
 rm -rf conftest.dSYM
@@ -14827,189 +14680,213 @@ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_blkid_blkid_get_cache" >&5
-$as_echo "$ac_cv_lib_blkid_blkid_get_cache" >&6; }
-if test "x$ac_cv_lib_blkid_blkid_get_cache" = x""yes; then
-
-                       { $as_echo "$as_me:$LINENO: checking for blkid zfs support" >&5
-$as_echo_n "checking for blkid zfs support... " >&6; }
-
-                       ZFS_DEV=`mktemp`
-                       dd if=/dev/zero of=$ZFS_DEV bs=1024k count=8 \
-                               >/dev/null 2>/dev/null
-                       echo -en "\x0c\xb1\xba\0\0\0\0\0" | \
-                               dd of=$ZFS_DEV bs=1k count=8 \
-                               seek=132 conv=notrunc &>/dev/null \
-                               >/dev/null 2>/dev/null
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_crc32" >&5
+$as_echo "$ac_cv_lib_z_crc32" >&6; }
+if test "x$ac_cv_lib_z_crc32" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
 
-                       saved_LDFLAGS="$LDFLAGS"
-                       LDFLAGS="-lblkid"
+  LIBS="-lz $LIBS"
 
-                       if test "$cross_compiling" = yes; then
+else
   { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+{ { $as_echo "$as_me:$LINENO: error:
+       *** crc32() missing, zlib-devel package required
 See \`config.log' for more details." >&5
-$as_echo "$as_me: error: cannot run test program while cross compiling
+$as_echo "$as_me: error:
+       *** crc32() missing, zlib-devel package required
 See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }; }
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
+fi
 
-                               #include <stdio.h>
-                               #include <blkid/blkid.h>
 
-int
-main ()
-{
+       ZLIB="-lz"
 
-                               blkid_cache cache;
-                               char *value;
 
-                               if (blkid_get_cache(&cache, NULL) < 0)
-                                       return 1;
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ZLIB 1
+_ACEOF
 
-                               value = blkid_get_tag_value(cache, "TYPE",
-                                                           "$ZFS_DEV");
-                               if (!value) {
-                                       blkid_put_cache(cache);
-                                       return 2;
-                               }
 
-                               if (strcmp(value, "zfs")) {
-                                       free(value);
-                                       blkid_put_cache(cache);
-                                       return 3;
-                               }
 
-                               free(value);
-                               blkid_put_cache(cache);
+       LIBUUID=
 
-  ;
-  return 0;
-}
+       if test "${ac_cv_header_uuid_uuid_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for uuid/uuid.h" >&5
+$as_echo_n "checking for uuid/uuid.h... " >&6; }
+if test "${ac_cv_header_uuid_uuid_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_uuid_uuid_h" >&5
+$as_echo "$ac_cv_header_uuid_uuid_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking uuid/uuid.h usability" >&5
+$as_echo_n "checking uuid/uuid.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
 _ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <uuid/uuid.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
   *) ac_try_echo=$ac_try;;
 esac
 eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
 $as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_try") 2>&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-
-                               rm -f $ZFS_DEV
-                               { $as_echo "$as_me:$LINENO: result: yes" >&5
-$as_echo "yes" >&6; }
-                               LIBBLKID="-lblkid"
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBBLKID 1
-_ACEOF
-
-
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
 else
-  $as_echo "$as_me: program exited with status $ac_status" >&5
-$as_echo "$as_me: failed program was:" >&5
+  $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
-
-                               rm -f $ZFS_DEV
-                               { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-                               if test "x$with_blkid" != xcheck; then
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error: --with-blkid given but unavailable
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: --with-blkid given but unavailable
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
+       ac_header_compiler=no
 fi
 
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
 
-fi
-rm -rf conftest.dSYM
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking uuid/uuid.h presence" >&5
+$as_echo_n "checking uuid/uuid.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <uuid/uuid.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+  ac_header_preproc=no
+fi
 
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
 
-                       LDFLAGS="$saved_LDFLAGS"
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: uuid/uuid.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: uuid/uuid.h: in the future, the compiler will take precedence" >&2;}
 
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for uuid/uuid.h" >&5
+$as_echo_n "checking for uuid/uuid.h... " >&6; }
+if test "${ac_cv_header_uuid_uuid_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
 else
+  ac_cv_header_uuid_uuid_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_uuid_uuid_h" >&5
+$as_echo "$ac_cv_header_uuid_uuid_h" >&6; }
 
-                       if test "x$with_blkid" != xcheck; then
+fi
+if test "x$ac_cv_header_uuid_uuid_h" = x""yes; then
+  :
+else
   { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error: --with-blkid given but unavailable
+{ { $as_echo "$as_me:$LINENO: error:
+       *** uuid/uuid.h missing, libuuid-devel package required
 See \`config.log' for more details." >&5
-$as_echo "$as_me: error: --with-blkid given but unavailable
+$as_echo "$as_me: error:
+       *** uuid/uuid.h missing, libuuid-devel package required
 See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }; }
 fi
 
 
 
-fi
-
-
-fi
-
-
-
-       { $as_echo "$as_me:$LINENO: checking for -Wframe-larger-than=<size> support" >&5
-$as_echo_n "checking for -Wframe-larger-than=<size> support... " >&6; }
-
-       saved_flags="$CFLAGS"
-       CFLAGS="$CFLAGS -Wframe-larger-than=1024"
 
-       if test "$cross_compiling" = yes; then
-  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling
-See \`config.log' for more details." >&5
-$as_echo "$as_me: error: cannot run test program while cross compiling
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }; }
+{ $as_echo "$as_me:$LINENO: checking for uuid_generate in -luuid" >&5
+$as_echo_n "checking for uuid_generate in -luuid... " >&6; }
+if test "${ac_cv_lib_uuid_uuid_generate+set}" = set; then
+  $as_echo_n "(cached) " >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-luuid  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char uuid_generate ();
 int
 main ()
 {
-
+return uuid_generate ();
   ;
   return 0;
 }
 _ACEOF
-rm -f conftest$ac_exeext
+rm -f conftest.$ac_objext conftest$ac_exeext
 if { (ac_try="$ac_link"
 case "(($ac_try" in
   *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
@@ -15017,102 +14894,286 @@ case "(($ac_try" in
 esac
 eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
 $as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_try") 2>&5
+  (eval "$ac_link") 2>conftest.er1
   ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-
-               FRAME_LARGER_THAN=-Wframe-larger-than=1024
-               { $as_echo "$as_me:$LINENO: result: yes" >&5
-$as_echo "yes" >&6; }
-
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_uuid_uuid_generate=yes
 else
-  $as_echo "$as_me: program exited with status $ac_status" >&5
-$as_echo "$as_me: failed program was:" >&5
+  $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
-
-               FRAME_LARGER_THAN=
-               { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-
+       ac_cv_lib_uuid_uuid_generate=no
 fi
+
 rm -rf conftest.dSYM
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_uuid_uuid_generate" >&5
+$as_echo "$ac_cv_lib_uuid_uuid_generate" >&6; }
+if test "x$ac_cv_lib_uuid_uuid_generate" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUUID 1
+_ACEOF
 
+  LIBS="-luuid $LIBS"
 
-
-       CFLAGS="$saved_flags"
-
-
-
-
-       { $as_echo "$as_me:$LINENO: checking whether pthread stack includes guard" >&5
-$as_echo_n "checking whether pthread stack includes guard... " >&6; }
-
-       saved_CFLAGS="$CFLAGS"
-       CFLAGS="-fstack-check"
-       saved_LDFLAGS="$LDFLAGS"
-       LDFLAGS="-lpthread"
-
-       if test "$cross_compiling" = yes; then
+else
   { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+{ { $as_echo "$as_me:$LINENO: error:
+       *** uuid_generate() missing, libuuid-devel package required
 See \`config.log' for more details." >&5
-$as_echo "$as_me: error: cannot run test program while cross compiling
+$as_echo "$as_me: error:
+       *** uuid_generate() missing, libuuid-devel package required
 See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }; }
+fi
+
+
+
+{ $as_echo "$as_me:$LINENO: checking for uuid_is_null in -luuid" >&5
+$as_echo_n "checking for uuid_is_null in -luuid... " >&6; }
+if test "${ac_cv_lib_uuid_uuid_is_null+set}" = set; then
+  $as_echo_n "(cached) " >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-luuid  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-               #include <pthread.h>
-               #include <sys/resource.h>
-               #include <unistd.h>
-               #include <bits/local_lim.h>
-
-               #define PAGESIZE (sysconf(_SC_PAGESIZE))
-               #define STACK_SIZE 8192
-               #define BUFSIZE 4096
-
-               void * func(void *arg)
-               {
-                       char buf[BUFSIZE];
-               }
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char uuid_is_null ();
+int
+main ()
+{
+return uuid_is_null ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_uuid_uuid_is_null=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_uuid_uuid_is_null=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_uuid_uuid_is_null" >&5
+$as_echo "$ac_cv_lib_uuid_uuid_is_null" >&6; }
+if test "x$ac_cv_lib_uuid_uuid_is_null" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUUID 1
+_ACEOF
+
+  LIBS="-luuid $LIBS"
+
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error:
+       *** uuid_is_null() missing, libuuid-devel package required
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error:
+       *** uuid_is_null() missing, libuuid-devel package required
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+
+       LIBUUID="-luuid"
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBUUID 1
+_ACEOF
+
+
+
+
+# Check whether --with-blkid was given.
+if test "${with_blkid+set}" = set; then
+  withval=$with_blkid;
+else
+  with_blkid=check
+fi
+
+
+       LIBBLKID=
+       if test "x$with_blkid" != xno; then
+
+               { $as_echo "$as_me:$LINENO: checking for blkid_get_cache in -lblkid" >&5
+$as_echo_n "checking for blkid_get_cache in -lblkid... " >&6; }
+if test "${ac_cv_lib_blkid_blkid_get_cache+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lblkid  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char blkid_get_cache ();
+int
+main ()
+{
+return blkid_get_cache ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_blkid_blkid_get_cache=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_blkid_blkid_get_cache=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_blkid_blkid_get_cache" >&5
+$as_echo "$ac_cv_lib_blkid_blkid_get_cache" >&6; }
+if test "x$ac_cv_lib_blkid_blkid_get_cache" = x""yes; then
+
+                       { $as_echo "$as_me:$LINENO: checking for blkid zfs support" >&5
+$as_echo_n "checking for blkid zfs support... " >&6; }
+
+                       ZFS_DEV=`mktemp`
+                       dd if=/dev/zero of=$ZFS_DEV bs=1024k count=8 \
+                               >/dev/null 2>/dev/null
+                       echo -en "\x0c\xb1\xba\0\0\0\0\0" | \
+                               dd of=$ZFS_DEV bs=1k count=8 \
+                               seek=132 conv=notrunc &>/dev/null \
+                               >/dev/null 2>/dev/null
+
+                       saved_LDFLAGS="$LDFLAGS"
+                       LDFLAGS="-lblkid"
+
+                       if test "$cross_compiling" = yes; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+                               #include <stdio.h>
+                               #include <blkid/blkid.h>
 
 int
 main ()
 {
 
-               pthread_t tid;
-               pthread_attr_t attr;
-               struct rlimit l;
+                               blkid_cache cache;
+                               char *value;
 
-               l.rlim_cur = 0;
-               l.rlim_max = 0;
-               setrlimit(RLIMIT_CORE, &l);
-               pthread_attr_init(&attr);
-               pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + STACK_SIZE);
-               pthread_attr_setguardsize(&attr, PAGESIZE);
-               pthread_create(&tid, &attr, func, NULL);
-               pthread_join(tid, NULL);
+                               if (blkid_get_cache(&cache, NULL) < 0)
+                                       return 1;
+
+                               value = blkid_get_tag_value(cache, "TYPE",
+                                                           "$ZFS_DEV");
+                               if (!value) {
+                                       blkid_put_cache(cache);
+                                       return 2;
+                               }
+
+                               if (strcmp(value, "zfs")) {
+                                       free(value);
+                                       blkid_put_cache(cache);
+                                       return 3;
+                               }
+
+                               free(value);
+                               blkid_put_cache(cache);
 
   ;
   return 0;
@@ -15141,8 +15202,16 @@ $as_echo "$ac_try_echo") >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
+                               rm -f $ZFS_DEV
+                               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+                               LIBBLKID="-lblkid"
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBBLKID 1
+_ACEOF
+
 
 else
   $as_echo "$as_me: program exited with status $ac_status" >&5
@@ -15151,13 +15220,19 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
 ( exit $ac_status )
 
+                               rm -f $ZFS_DEV
+                               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+                               if test "x$with_blkid" != xcheck; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: --with-blkid given but unavailable
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: --with-blkid given but unavailable
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
 
-cat >>confdefs.h <<\_ACEOF
-#define NPTL_GUARD_WITHIN_STACK 1
-_ACEOF
-
-               { $as_echo "$as_me:$LINENO: result: yes" >&5
-$as_echo "yes" >&6; }
 
 fi
 rm -rf conftest.dSYM
@@ -15165,257 +15240,1069 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$a
 fi
 
 
-       CFLAGS="$saved_CFLAGS"
-       LDFLAGS="$saved_LDFLAGS"
 
-   ;;
-               all)
+                       LDFLAGS="$saved_LDFLAGS"
+
+else
+
+                       if test "x$with_blkid" != xcheck; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: --with-blkid given but unavailable
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: --with-blkid given but unavailable
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+
+
+fi
+
+
+fi
+
+
+
+
+# Check whether --with-selinux was given.
+if test "${with_selinux+set}" = set; then
+  withval=$with_selinux;
+else
+  with_selinux=check
+fi
+
+
+       LIBSELINUX=
+       if test "x$with_selinux" != xno; then
+
+               if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for selinux/selinux.h" >&5
+$as_echo_n "checking for selinux/selinux.h... " >&6; }
+if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_selinux_selinux_h" >&5
+$as_echo "$ac_cv_header_selinux_selinux_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking selinux/selinux.h usability" >&5
+$as_echo_n "checking selinux/selinux.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <selinux/selinux.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking selinux/selinux.h presence" >&5
+$as_echo_n "checking selinux/selinux.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <selinux/selinux.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for selinux/selinux.h" >&5
+$as_echo_n "checking for selinux/selinux.h... " >&6; }
+if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_selinux_selinux_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_selinux_selinux_h" >&5
+$as_echo "$ac_cv_header_selinux_selinux_h" >&6; }
+
+fi
+if test "x$ac_cv_header_selinux_selinux_h" = x""yes; then
+
+                       { $as_echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
+$as_echo_n "checking for is_selinux_enabled in -lselinux... " >&6; }
+if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lselinux  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char is_selinux_enabled ();
+int
+main ()
+{
+return is_selinux_enabled ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_selinux_is_selinux_enabled=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_selinux_is_selinux_enabled=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5
+$as_echo "$ac_cv_lib_selinux_is_selinux_enabled" >&6; }
+if test "x$ac_cv_lib_selinux_is_selinux_enabled" = x""yes; then
+
+                               LIBSELINUX="-lselinux"
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBSELINUX 1
+_ACEOF
+
+
+else
+
+                               if test "x$with_selinux" != xcheck; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+fi
+
+
+fi
+
+
+else
+
+                       if test "x$with_selinux" != xcheck; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+fi
+
+
+fi
+
+
+
+else
+
+               { $as_echo "$as_me:$LINENO: checking for selinux support" >&5
+$as_echo_n "checking for selinux support... " >&6; }
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+
+
+
+       { $as_echo "$as_me:$LINENO: checking for -Wframe-larger-than=<size> support" >&5
+$as_echo_n "checking for -Wframe-larger-than=<size> support... " >&6; }
+
+       saved_flags="$CFLAGS"
+       CFLAGS="$CFLAGS -Wframe-larger-than=1024"
+
+       if test "$cross_compiling" = yes; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               FRAME_LARGER_THAN=-Wframe-larger-than=1024
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+               FRAME_LARGER_THAN=
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+       CFLAGS="$saved_flags"
+
+
+
+
+       { $as_echo "$as_me:$LINENO: checking whether pthread stack includes guard" >&5
+$as_echo_n "checking whether pthread stack includes guard... " >&6; }
+
+       saved_CFLAGS="$CFLAGS"
+       CFLAGS="-fstack-check"
+       saved_LDFLAGS="$LDFLAGS"
+       LDFLAGS="-lpthread"
+
+       if test "$cross_compiling" = yes; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+               #include <pthread.h>
+               #include <sys/resource.h>
+               #include <unistd.h>
+               #include <bits/local_lim.h>
+
+               #define PAGESIZE (sysconf(_SC_PAGESIZE))
+               #define STACK_SIZE 8192
+               #define BUFSIZE 4096
+
+               void * func(void *arg)
+               {
+                       char buf[BUFSIZE];
+               }
+
+int
+main ()
+{
+
+               pthread_t tid;
+               pthread_attr_t attr;
+               struct rlimit l;
+
+               l.rlim_cur = 0;
+               l.rlim_max = 0;
+               setrlimit(RLIMIT_CORE, &l);
+               pthread_attr_init(&attr);
+               pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN + STACK_SIZE);
+               pthread_attr_setguardsize(&attr, PAGESIZE);
+               pthread_create(&tid, &attr, func, NULL);
+               pthread_join(tid, NULL);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+
+cat >>confdefs.h <<\_ACEOF
+#define NPTL_GUARD_WITHIN_STACK 1
+_ACEOF
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+       CFLAGS="$saved_CFLAGS"
+       LDFLAGS="$saved_LDFLAGS"
+
+   ;;
+               all)
+
+
+# Check whether --with-linux was given.
+if test "${with_linux+set}" = set; then
+  withval=$with_linux; kernelsrc="$withval"
+fi
+
+
+
+# Check whether --with-linux-obj was given.
+if test "${with_linux_obj+set}" = set; then
+  withval=$with_linux_obj; kernelbuild="$withval"
+fi
+
+
+       { $as_echo "$as_me:$LINENO: checking kernel source directory" >&5
+$as_echo_n "checking kernel source directory... " >&6; }
+       if test -z "$kernelsrc"; then
+               if test -e "/lib/modules/$(uname -r)/source"; then
+                       headersdir="/lib/modules/$(uname -r)/source"
+                       sourcelink=$(readlink -f "$headersdir")
+               elif test -e "/lib/modules/$(uname -r)/build"; then
+                       headersdir="/lib/modules/$(uname -r)/build"
+                       sourcelink=$(readlink -f "$headersdir")
+               else
+                       sourcelink=$(ls -1d /usr/src/kernels/* \
+                                    /usr/src/linux-* \
+                                    2>/dev/null | grep -v obj | tail -1)
+               fi
+
+               if test -n "$sourcelink" && test -e ${sourcelink}; then
+                       kernelsrc=`readlink -f ${sourcelink}`
+               else
+                       { $as_echo "$as_me:$LINENO: result: Not found" >&5
+$as_echo "Not found" >&6; }
+                       { { $as_echo "$as_me:$LINENO: error:
+       *** Please make sure the kernel devel package for your distribution
+       *** is installed then try again.  If that fails you can specify the
+       *** location of the kernel source with the '--with-linux=PATH' option." >&5
+$as_echo "$as_me: error:
+       *** Please make sure the kernel devel package for your distribution
+       *** is installed then try again.  If that fails you can specify the
+       *** location of the kernel source with the '--with-linux=PATH' option." >&2;}
+   { (exit 1); exit 1; }; }
+               fi
+       else
+               if test "$kernelsrc" = "NONE"; then
+                       kernsrcver=NONE
+               fi
+       fi
+
+       { $as_echo "$as_me:$LINENO: result: $kernelsrc" >&5
+$as_echo "$kernelsrc" >&6; }
+       { $as_echo "$as_me:$LINENO: checking kernel build directory" >&5
+$as_echo_n "checking kernel build directory... " >&6; }
+       if test -z "$kernelbuild"; then
+               if test -e "/lib/modules/$(uname -r)/build"; then
+                       kernelbuild=`readlink -f /lib/modules/$(uname -r)/build`
+               elif test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}; then
+                       kernelbuild=${kernelsrc}-obj/${target_cpu}/${target_cpu}
+               elif test -d ${kernelsrc}-obj/${target_cpu}/default; then
+                       kernelbuild=${kernelsrc}-obj/${target_cpu}/default
+               elif test -d `dirname ${kernelsrc}`/build-${target_cpu}; then
+                       kernelbuild=`dirname ${kernelsrc}`/build-${target_cpu}
+               else
+                       kernelbuild=${kernelsrc}
+               fi
+       fi
+       { $as_echo "$as_me:$LINENO: result: $kernelbuild" >&5
+$as_echo "$kernelbuild" >&6; }
+
+       { $as_echo "$as_me:$LINENO: checking kernel source version" >&5
+$as_echo_n "checking kernel source version... " >&6; }
+       utsrelease1=$kernelbuild/include/linux/version.h
+       utsrelease2=$kernelbuild/include/linux/utsrelease.h
+       utsrelease3=$kernelbuild/include/generated/utsrelease.h
+       if test -r $utsrelease1 && fgrep -q UTS_RELEASE $utsrelease1; then
+               utsrelease=linux/version.h
+       elif test -r $utsrelease2 && fgrep -q UTS_RELEASE $utsrelease2; then
+               utsrelease=linux/utsrelease.h
+       elif test -r $utsrelease3 && fgrep -q UTS_RELEASE $utsrelease3; then
+               utsrelease=generated/utsrelease.h
+       fi
+
+       if test "$utsrelease"; then
+               kernsrcver=`(echo "#include <$utsrelease>";
+                            echo "kernsrcver=UTS_RELEASE") |
+                            cpp -I $kernelbuild/include |
+                            grep "^kernsrcver=" | cut -d \" -f 2`
+
+               if test -z "$kernsrcver"; then
+                       { $as_echo "$as_me:$LINENO: result: Not found" >&5
+$as_echo "Not found" >&6; }
+                       { { $as_echo "$as_me:$LINENO: error: *** Cannot determine kernel version." >&5
+$as_echo "$as_me: error: *** Cannot determine kernel version." >&2;}
+   { (exit 1); exit 1; }; }
+               fi
+       else
+               { $as_echo "$as_me:$LINENO: result: Not found" >&5
+$as_echo "Not found" >&6; }
+               { { $as_echo "$as_me:$LINENO: error: *** Cannot find UTS_RELEASE definition." >&5
+$as_echo "$as_me: error: *** Cannot find UTS_RELEASE definition." >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+
+       { $as_echo "$as_me:$LINENO: result: $kernsrcver" >&5
+$as_echo "$kernsrcver" >&6; }
+
+       LINUX=${kernelsrc}
+       LINUX_OBJ=${kernelbuild}
+       LINUX_VERSION=${kernsrcver}
+
+
+
+
+
+
+       modpost=$LINUX/scripts/Makefile.modpost
+       { $as_echo "$as_me:$LINENO: checking kernel file name for module symbols" >&5
+$as_echo_n "checking kernel file name for module symbols... " >&6; }
+       if test -f "$modpost"; then
+               if grep -q Modules.symvers $modpost; then
+                       LINUX_SYMBOLS=Modules.symvers
+               else
+                       LINUX_SYMBOLS=Module.symvers
+               fi
+       else
+               LINUX_SYMBOLS=NONE
+       fi
+       { $as_echo "$as_me:$LINENO: result: $LINUX_SYMBOLS" >&5
+$as_echo "$LINUX_SYMBOLS" >&6; }
+
+
+
+
+
+# Check whether --with-spl was given.
+if test "${with_spl+set}" = set; then
+  withval=$with_spl; splsrc="$withval"
+fi
+
+
+
+# Check whether --with-spl-obj was given.
+if test "${with_spl_obj+set}" = set; then
+  withval=$with_spl_obj; splbuild="$withval"
+fi
+
+
+
+       { $as_echo "$as_me:$LINENO: checking spl source directory" >&5
+$as_echo_n "checking spl source directory... " >&6; }
+       if test -z "$splsrc"; then
+               sourcelink=`ls -1d /usr/src/spl-*/${LINUX_VERSION} \
+                           2>/dev/null | tail -1`
+
+               if test -z "$sourcelink" || test ! -e $sourcelink; then
+                       sourcelink=../spl
+               fi
+
+               if test -e $sourcelink; then
+                       splsrc=`readlink -f ${sourcelink}`
+               else
+                       { $as_echo "$as_me:$LINENO: result: Not found" >&5
+$as_echo "Not found" >&6; }
+                       { { $as_echo "$as_me:$LINENO: error:
+       *** Please make sure the spl devel package for your distribution
+       *** is installed then try again.  If that fails you can specify the
+       *** location of the spl source with the '--with-spl=PATH' option." >&5
+$as_echo "$as_me: error:
+       *** Please make sure the spl devel package for your distribution
+       *** is installed then try again.  If that fails you can specify the
+       *** location of the spl source with the '--with-spl=PATH' option." >&2;}
+   { (exit 1); exit 1; }; }
+               fi
+       else
+               if test "$splsrc" = "NONE"; then
+                       splbuild=NONE
+                       splsrcver=NONE
+               fi
+       fi
+
+       { $as_echo "$as_me:$LINENO: result: $splsrc" >&5
+$as_echo "$splsrc" >&6; }
+       { $as_echo "$as_me:$LINENO: checking spl build directory" >&5
+$as_echo_n "checking spl build directory... " >&6; }
+       if test -z "$splbuild"; then
+               splbuild=${splsrc}
+       fi
+       { $as_echo "$as_me:$LINENO: result: $splbuild" >&5
+$as_echo "$splbuild" >&6; }
+
+       { $as_echo "$as_me:$LINENO: checking spl source version" >&5
+$as_echo_n "checking spl source version... " >&6; }
+       if test -r $splbuild/spl_config.h &&
+               fgrep -q SPL_META_VERSION $splbuild/spl_config.h; then
+
+               splsrcver=`(echo "#include <spl_config.h>";
+                           echo "splsrcver=SPL_META_VERSION") |
+                           cpp -I $splbuild |
+                           grep "^splsrcver=" | cut -d \" -f 2`
+       fi
+
+       if test -z "$splsrcver"; then
+               { $as_echo "$as_me:$LINENO: result: Not found" >&5
+$as_echo "Not found" >&6; }
+               { { $as_echo "$as_me:$LINENO: error:
+               *** Cannot determine the version of the spl source.
+               *** Please prepare the spl source before running this script" >&5
+$as_echo "$as_me: error:
+               *** Cannot determine the version of the spl source.
+               *** Please prepare the spl source before running this script" >&2;}
+   { (exit 1); exit 1; }; }
+       fi
+
+       { $as_echo "$as_me:$LINENO: result: $splsrcver" >&5
+$as_echo "$splsrcver" >&6; }
+
+       SPL=${splsrc}
+       SPL_OBJ=${splbuild}
+       SPL_VERSION=${splsrcver}
+
+
+
+
+
+
+       { $as_echo "$as_me:$LINENO: checking spl file name for module symbols" >&5
+$as_echo_n "checking spl file name for module symbols... " >&6; }
+       if test -r $SPL_OBJ/Module.symvers; then
+               SPL_SYMBOLS=Module.symvers
+       elif test -r $SPL_OBJ/Modules.symvers; then
+               SPL_SYMBOLS=Modules.symvers
+       elif test -r $SPL_OBJ/module/Module.symvers; then
+               SPL_SYMBOLS=Module.symvers
+       elif test -r $SPL_OBJ/module/Modules.symvers; then
+               SPL_SYMBOLS=Modules.symvers
+       else
+               SPL_SYMBOLS=$LINUX_SYMBOLS
+       fi
+
+       { $as_echo "$as_me:$LINENO: result: $SPL_SYMBOLS" >&5
+$as_echo "$SPL_SYMBOLS" >&6; }
+
+
+
+
+
+       if test "$ZFS_META_LICENSE" = CDDL; then
+               { $as_echo "$as_me:$LINENO: checking whether Linux was built with CONFIG_DEBUG_LOCK_ALLOC" >&5
+$as_echo_n "checking whether Linux was built with CONFIG_DEBUG_LOCK_ALLOC... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+               #ifndef AUTOCONF_INCLUDED
+               #include <linux/config.h>
+               #endif
+
+int
+main (void)
+{
+
+               #ifndef CONFIG_DEBUG_LOCK_ALLOC
+               #error CONFIG_DEBUG_LOCK_ALLOC not #defined
+               #endif
+
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+               { { $as_echo "$as_me:$LINENO: error:
+               *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is
+               *** incompatible with the CDDL license.  You must rebuild
+               *** your kernel without this option." >&5
+$as_echo "$as_me: error:
+               *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is
+               *** incompatible with the CDDL license.  You must rebuild
+               *** your kernel without this option." >&2;}
+   { (exit 1); exit 1; }; }
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+
+
+
+fi
+
+       rm -Rf build
+
+
+
+       fi
+
+       if test "$ZFS_META_LICENSE" = GPL; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GPL_ONLY_SYMBOLS 1
+_ACEOF
+
+       fi
+
+
+       { $as_echo "$as_me:$LINENO: checking block device operation prototypes" >&5
+$as_echo_n "checking block device operation prototypes... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+
+               #include <linux/blkdev.h>
+
+int
+main (void)
+{
+
+               int (*blk_open) (struct block_device *, fmode_t) = NULL;
+               int (*blk_release) (struct gendisk *, fmode_t) = NULL;
+               int (*blk_ioctl) (struct block_device *, fmode_t,
+                                 unsigned, unsigned long) = NULL;
+               int (*blk_compat_ioctl) (struct block_device *, fmode_t,
+                                         unsigned, unsigned long) = NULL;
+               struct block_device_operations blk_ops = {
+                       .open           = blk_open,
+                       .release        = blk_release,
+                       .ioctl          = blk_ioctl,
+                       .compat_ioctl   = blk_compat_ioctl,
+               };
+
+               blk_ops.open(NULL, 0);
+               blk_ops.release(NULL, 0);
+               blk_ops.ioctl(NULL, 0, 0, 0);
+               blk_ops.compat_ioctl(NULL, 0, 0, 0);
+
+  ;
+  return 0;
+}
+
+_ACEOF
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: struct block_device" >&5
+$as_echo "struct block_device" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_BDEV_BLOCK_DEVICE_OPERATIONS 1
+_ACEOF
+
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: struct inode" >&5
+$as_echo "struct inode" >&6; }
+
+
+
+fi
+
+       rm -Rf build
+
+
+
+       { $as_echo "$as_me:$LINENO: checking whether kernel defines fmode_t" >&5
+$as_echo_n "checking whether kernel defines fmode_t... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
 
 
-# Check whether --with-linux was given.
-if test "${with_linux+set}" = set; then
-  withval=$with_linux; kernelsrc="$withval"
-fi
+               #include <linux/types.h>
 
+int
+main (void)
+{
 
+               fmode_t *ptr;
 
-# Check whether --with-linux-obj was given.
-if test "${with_linux_obj+set}" = set; then
-  withval=$with_linux_obj; kernelbuild="$withval"
-fi
+  ;
+  return 0;
+}
 
+_ACEOF
 
-       { $as_echo "$as_me:$LINENO: checking kernel source directory" >&5
-$as_echo_n "checking kernel source directory... " >&6; }
-       if test -z "$kernelsrc"; then
-               headersdir="/lib/modules/$(uname -r)/build"
-               if test -e "$headersdir"; then
-                       sourcelink=$(readlink -f "$headersdir")
-               else
-                       sourcelink=$(ls -1d /usr/src/kernels/* \
-                                    /usr/src/linux-* \
-                                    2>/dev/null | grep -v obj | tail -1)
-               fi
 
-               if test -n "$sourcelink" && test -e ${sourcelink}; then
-                       kernelsrc=`readlink -f ${sourcelink}`
-               else
-                       { $as_echo "$as_me:$LINENO: result: Not found" >&5
-$as_echo "Not found" >&6; }
-                       { { $as_echo "$as_me:$LINENO: error:
-       *** Please make sure the kernel devel package for your distribution
-       *** is installed then try again.  If that fails you can specify the
-       *** location of the kernel source with the '--with-linux=PATH' option." >&5
-$as_echo "$as_me: error:
-       *** Please make sure the kernel devel package for your distribution
-       *** is installed then try again.  If that fails you can specify the
-       *** location of the kernel source with the '--with-linux=PATH' option." >&2;}
-   { (exit 1); exit 1; }; }
-               fi
-       else
-               if test "$kernelsrc" = "NONE"; then
-                       kernsrcver=NONE
-               fi
-       fi
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
 
-       { $as_echo "$as_me:$LINENO: result: $kernelsrc" >&5
-$as_echo "$kernelsrc" >&6; }
-       { $as_echo "$as_me:$LINENO: checking kernel build directory" >&5
-$as_echo_n "checking kernel build directory... " >&6; }
-       if test -z "$kernelbuild"; then
-               if test -d ${kernelsrc}-obj/${target_cpu}/${target_cpu}; then
-                       kernelbuild=${kernelsrc}-obj/${target_cpu}/${target_cpu}
-               elif test -d ${kernelsrc}-obj/${target_cpu}/default; then
-                       kernelbuild=${kernelsrc}-obj/${target_cpu}/default
-               elif test -d `dirname ${kernelsrc}`/build-${target_cpu}; then
-                       kernelbuild=`dirname ${kernelsrc}`/build-${target_cpu}
-               else
-                       kernelbuild=${kernelsrc}
-               fi
-       fi
-       { $as_echo "$as_me:$LINENO: result: $kernelbuild" >&5
-$as_echo "$kernelbuild" >&6; }
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
 
-       { $as_echo "$as_me:$LINENO: checking kernel source version" >&5
-$as_echo_n "checking kernel source version... " >&6; }
-       utsrelease1=$kernelbuild/include/linux/version.h
-       utsrelease2=$kernelbuild/include/linux/utsrelease.h
-       utsrelease3=$kernelbuild/include/generated/utsrelease.h
-       if test -r $utsrelease1 && fgrep -q UTS_RELEASE $utsrelease1; then
-               utsrelease=linux/version.h
-       elif test -r $utsrelease2 && fgrep -q UTS_RELEASE $utsrelease2; then
-               utsrelease=linux/utsrelease.h
-       elif test -r $utsrelease3 && fgrep -q UTS_RELEASE $utsrelease3; then
-               utsrelease=generated/utsrelease.h
-       fi
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FMODE_T 1
+_ACEOF
 
-       if test "$utsrelease"; then
-               kernsrcver=`(echo "#include <$utsrelease>";
-                            echo "kernsrcver=UTS_RELEASE") |
-                            cpp -I $kernelbuild/include |
-                            grep "^kernsrcver=" | cut -d \" -f 2`
 
-               if test -z "$kernsrcver"; then
-                       { $as_echo "$as_me:$LINENO: result: Not found" >&5
-$as_echo "Not found" >&6; }
-                       { { $as_echo "$as_me:$LINENO: error: *** Cannot determine kernel version." >&5
-$as_echo "$as_me: error: *** Cannot determine kernel version." >&2;}
-   { (exit 1); exit 1; }; }
-               fi
-       else
-               { $as_echo "$as_me:$LINENO: result: Not found" >&5
-$as_echo "Not found" >&6; }
-               { { $as_echo "$as_me:$LINENO: error: *** Cannot find UTS_RELEASE definition." >&5
-$as_echo "$as_me: error: *** Cannot find UTS_RELEASE definition." >&2;}
-   { (exit 1); exit 1; }; }
-       fi
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-       { $as_echo "$as_me:$LINENO: result: $kernsrcver" >&5
-$as_echo "$kernsrcver" >&6; }
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
-       LINUX=${kernelsrc}
-       LINUX_OBJ=${kernelbuild}
-       LINUX_VERSION=${kernsrcver}
 
 
+fi
 
+       rm -Rf build
 
 
 
-       modpost=$LINUX/scripts/Makefile.modpost
-       { $as_echo "$as_me:$LINENO: checking kernel file name for module symbols" >&5
-$as_echo_n "checking kernel file name for module symbols... " >&6; }
-       if test -f "$modpost"; then
-               if grep -q Modules.symvers $modpost; then
-                       LINUX_SYMBOLS=Modules.symvers
-               else
-                       LINUX_SYMBOLS=Module.symvers
-               fi
-       else
-               LINUX_SYMBOLS=NONE
-       fi
-       { $as_echo "$as_me:$LINENO: result: $LINUX_SYMBOLS" >&5
-$as_echo "$LINUX_SYMBOLS" >&6; }
 
+       { $as_echo "$as_me:$LINENO: checking whether kernel defines KOBJ_NAME_LEN" >&5
+$as_echo_n "checking whether kernel defines KOBJ_NAME_LEN... " >&6; }
 
 
+cat confdefs.h - <<_ACEOF >conftest.c
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
 
 
-# Check whether --with-spl was given.
-if test "${with_spl+set}" = set; then
-  withval=$with_spl; splsrc="$withval"
-fi
+               #include <linux/kobject.h>
 
+int
+main (void)
+{
 
+               int val;
+               val = KOBJ_NAME_LEN;
 
-# Check whether --with-spl-obj was given.
-if test "${with_spl_obj+set}" = set; then
-  withval=$with_spl_obj; splbuild="$withval"
-fi
+  ;
+  return 0;
+}
 
+_ACEOF
 
 
-       { $as_echo "$as_me:$LINENO: checking spl source directory" >&5
-$as_echo_n "checking spl source directory... " >&6; }
-       if test -z "$splsrc"; then
-               sourcelink=`ls -1d /usr/src/spl-*/${LINUX_VERSION} \
-                           2>/dev/null | tail -1`
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
 
-               if test -z "$sourcelink" || test ! -e $sourcelink; then
-                       sourcelink=../spl
-               fi
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
 
-               if test -e $sourcelink; then
-                       splsrc=`readlink -f ${sourcelink}`
-               else
-                       { $as_echo "$as_me:$LINENO: result: Not found" >&5
-$as_echo "Not found" >&6; }
-                       { { $as_echo "$as_me:$LINENO: error:
-       *** Please make sure the spl devel package for your distribution
-       *** is installed then try again.  If that fails you can specify the
-       *** location of the spl source with the '--with-spl=PATH' option." >&5
-$as_echo "$as_me: error:
-       *** Please make sure the spl devel package for your distribution
-       *** is installed then try again.  If that fails you can specify the
-       *** location of the spl source with the '--with-spl=PATH' option." >&2;}
-   { (exit 1); exit 1; }; }
-               fi
-       else
-               if test "$splsrc" = "NONE"; then
-                       splbuild=NONE
-                       splsrcver=NONE
-               fi
-       fi
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_KOBJ_NAME_LEN 1
+_ACEOF
 
-       { $as_echo "$as_me:$LINENO: result: $splsrc" >&5
-$as_echo "$splsrc" >&6; }
-       { $as_echo "$as_me:$LINENO: checking spl build directory" >&5
-$as_echo_n "checking spl build directory... " >&6; }
-       if test -z "$splbuild"; then
-               splbuild=${splsrc}
-       fi
-       { $as_echo "$as_me:$LINENO: result: $splbuild" >&5
-$as_echo "$splbuild" >&6; }
 
-       { $as_echo "$as_me:$LINENO: checking spl source version" >&5
-$as_echo_n "checking spl source version... " >&6; }
-       if test -r $splbuild/spl_config.h &&
-               fgrep -q SPL_META_VERSION $splbuild/spl_config.h; then
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-               splsrcver=`(echo "#include <spl_config.h>";
-                           echo "splsrcver=SPL_META_VERSION") |
-                           cpp -I $splbuild |
-                           grep "^splsrcver=" | cut -d \" -f 2`
-       fi
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
-       if test -z "$splsrcver"; then
-               { $as_echo "$as_me:$LINENO: result: Not found" >&5
-$as_echo "Not found" >&6; }
-               { { $as_echo "$as_me:$LINENO: error:
-               *** Cannot determine the version of the spl source.
-               *** Please prepare the spl source before running this script" >&5
-$as_echo "$as_me: error:
-               *** Cannot determine the version of the spl source.
-               *** Please prepare the spl source before running this script" >&2;}
-   { (exit 1); exit 1; }; }
-       fi
 
-       { $as_echo "$as_me:$LINENO: result: $splsrcver" >&5
-$as_echo "$splsrcver" >&6; }
 
-       SPL=${splsrc}
-       SPL_OBJ=${splbuild}
-       SPL_VERSION=${splsrcver}
+fi
+
+       rm -Rf build
 
 
 
 
+       { $as_echo "$as_me:$LINENO: checking whether symbol open_bdev_exclusive is exported" >&5
+$as_echo_n "checking whether symbol open_bdev_exclusive is exported... " >&6; }
+       grep -q -E '[[:space:]]open_bdev_exclusive[[:space:]]' \
+               $LINUX_OBJ/$LINUX_SYMBOLS 2>/dev/null
+       rc=$?
+       if test $rc -ne 0; then
+               export=0
+               for file in fs/block_dev.c; do
+                       grep -q -E "EXPORT_SYMBOL.*(open_bdev_exclusive)" "$LINUX/$file" 2>/dev/null
+                       rc=$?
+                       if test $rc -eq 0; then
+                               export=1
+                               break;
+                       fi
+               done
+               if test $export -eq 0; then
+                       { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+               else
+                       { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
 
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_OPEN_BDEV_EXCLUSIVE 1
+_ACEOF
 
-       { $as_echo "$as_me:$LINENO: checking spl file name for module symbols" >&5
-$as_echo_n "checking spl file name for module symbols... " >&6; }
-       if test -r $SPL_OBJ/Module.symvers; then
-               SPL_SYMBOLS=Module.symvers
-       elif test -r $SPL_OBJ/Modules.symvers; then
-               SPL_SYMBOLS=Modules.symvers
-       elif test -r $SPL_OBJ/module/Module.symvers; then
-               SPL_SYMBOLS=Module.symvers
-       elif test -r $SPL_OBJ/module/Modules.symvers; then
-               SPL_SYMBOLS=Modules.symvers
+               fi
        else
-               SPL_SYMBOLS=$LINUX_SYMBOLS
-       fi
-
-       { $as_echo "$as_me:$LINENO: result: $SPL_SYMBOLS" >&5
-$as_echo "$SPL_SYMBOLS" >&6; }
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
 
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_OPEN_BDEV_EXCLUSIVE 1
+_ACEOF
 
+       fi
 
 
 
-       if test "$ZFS_META_LICENSE" = CDDL; then
-               { $as_echo "$as_me:$LINENO: checking whether Linux was built with CONFIG_DEBUG_LOCK_ALLOC" >&5
-$as_echo_n "checking whether Linux was built with CONFIG_DEBUG_LOCK_ALLOC... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether invalidate_bdev() wants 1 arg" >&5
+$as_echo_n "checking whether invalidate_bdev() wants 1 arg... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15426,17 +16313,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #ifndef AUTOCONF_INCLUDED
-               #include <linux/config.h>
-               #endif
+               #include <linux/buffer_head.h>
 
 int
 main (void)
 {
 
-               #ifndef CONFIG_DEBUG_LOCK_ALLOC
-               #error CONFIG_DEBUG_LOCK_ALLOC not #defined
-               #endif
+               struct block_device *bdev;
+               invalidate_bdev(bdev);
 
   ;
   return 0;
@@ -15461,15 +16345,11 @@ _ACEOF
 
                { $as_echo "$as_me:$LINENO: result: yes" >&5
 $as_echo "yes" >&6; }
-               { { $as_echo "$as_me:$LINENO: error:
-               *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is
-               *** incompatible with the CDDL license.  You must rebuild
-               *** your kernel without this option." >&5
-$as_echo "$as_me: error:
-               *** Kernel built with CONFIG_DEBUG_LOCK_ALLOC which is
-               *** incompatible with the CDDL license.  You must rebuild
-               *** your kernel without this option." >&2;}
-   { (exit 1); exit 1; }; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_1ARG_INVALIDATE_BDEV 1
+_ACEOF
+
 
 else
   $as_echo "$as_me: failed program was:" >&5
@@ -15480,26 +16360,15 @@ $as_echo "no" >&6; }
 
 
 
-
 fi
 
        rm -Rf build
 
 
 
-       fi
-
-       if test "$ZFS_META_LICENSE" = GPL; then
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_GPL_ONLY_SYMBOLS 1
-_ACEOF
-
-       fi
-
 
-       { $as_echo "$as_me:$LINENO: checking block device operation prototypes" >&5
-$as_echo_n "checking block device operation prototypes... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether bdev_logical_block_size() is available" >&5
+$as_echo_n "checking whether bdev_logical_block_size() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15516,23 +16385,8 @@ int
 main (void)
 {
 
-               int (*blk_open) (struct block_device *, fmode_t) = NULL;
-               int (*blk_release) (struct gendisk *, fmode_t) = NULL;
-               int (*blk_ioctl) (struct block_device *, fmode_t,
-                                 unsigned, unsigned long) = NULL;
-               int (*blk_compat_ioctl) (struct block_device *, fmode_t,
-                                         unsigned, unsigned long) = NULL;
-               struct block_device_operations blk_ops = {
-                       .open           = blk_open,
-                       .release        = blk_release,
-                       .ioctl          = blk_ioctl,
-                       .compat_ioctl   = blk_compat_ioctl,
-               };
-
-               blk_ops.open(NULL, 0);
-               blk_ops.release(NULL, 0);
-               blk_ops.ioctl(NULL, 0, 0, 0);
-               blk_ops.compat_ioctl(NULL, 0, 0, 0);
+               struct block_device *bdev = NULL;
+               bdev_logical_block_size(bdev);
 
   ;
   return 0;
@@ -15555,11 +16409,11 @@ _ACEOF
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               { $as_echo "$as_me:$LINENO: result: struct block_device" >&5
-$as_echo "struct block_device" >&6; }
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BDEV_BLOCK_DEVICE_OPERATIONS 1
+#define HAVE_BDEV_LOGICAL_BLOCK_SIZE 1
 _ACEOF
 
 
@@ -15567,8 +16421,8 @@ else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-               { $as_echo "$as_me:$LINENO: result: struct inode" >&5
-$as_echo "struct inode" >&6; }
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
 
 
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether kernel defines fmode_t" >&5
-$as_echo_n "checking whether kernel defines fmode_t... " >&6; }
+
+       { $as_echo "$as_me:$LINENO: checking whether bio_empty_barrier() is defined" >&5
+$as_echo_n "checking whether bio_empty_barrier() is defined... " >&6; }
+       EXTRA_KCFLAGS="-Werror"
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15590,13 +16446,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/types.h>
+               #include <linux/bio.h>
 
 int
 main (void)
 {
 
-               fmode_t *ptr;
+               struct bio bio;
+               (void)bio_empty_barrier(&bio);
 
   ;
   return 0;
@@ -15623,7 +16480,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_FMODE_T 1
+#define HAVE_BIO_EMPTY_BARRIER 1
 _ACEOF
 
 
@@ -15643,8 +16500,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether kernel defines KOBJ_NAME_LEN" >&5
-$as_echo_n "checking whether kernel defines KOBJ_NAME_LEN... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_FAILFAST is defined" >&5
+$as_echo_n "checking whether BIO_RW_FAILFAST is defined... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15655,14 +16512,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/kobject.h>
+               #include <linux/bio.h>
 
 int
 main (void)
 {
 
-               int val;
-               val = KOBJ_NAME_LEN;
+               int flags;
+               flags = (1 << BIO_RW_FAILFAST);
 
   ;
   return 0;
@@ -15689,7 +16546,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_KOBJ_NAME_LEN 1
+#define HAVE_BIO_RW_FAILFAST 1
 _ACEOF
 
 
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether symbol open_bdev_exclusive is exported" >&5
-$as_echo_n "checking whether symbol open_bdev_exclusive is exported... " >&6; }
-       grep -q -E '[[:space:]]open_bdev_exclusive[[:space:]]' \
-               $LINUX_OBJ/$LINUX_SYMBOLS 2>/dev/null
-       rc=$?
-       if test $rc -ne 0; then
-               export=0
-               for file in fs/block_dev.c; do
-                       grep -q -E "EXPORT_SYMBOL.*(open_bdev_exclusive)" "$LINUX/$file" 2>/dev/null
-                       rc=$?
-                       if test $rc -eq 0; then
-                               export=1
-                               break;
-                       fi
-               done
-               if test $export -eq 0; then
-                       { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-
-               else
-                       { $as_echo "$as_me:$LINENO: result: yes" >&5
-$as_echo "yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_OPEN_BDEV_EXCLUSIVE 1
-_ACEOF
-
-               fi
-       else
-               { $as_echo "$as_me:$LINENO: result: yes" >&5
-$as_echo "yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_OPEN_BDEV_EXCLUSIVE 1
-_ACEOF
-
-       fi
-
-
-
-       { $as_echo "$as_me:$LINENO: checking whether invalidate_bdev() wants 1 arg" >&5
-$as_echo_n "checking whether invalidate_bdev() wants 1 arg... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_FAILFAST_* are defined" >&5
+$as_echo_n "checking whether BIO_RW_FAILFAST_* are defined... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15761,14 +16578,16 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/buffer_head.h>
+               #include <linux/bio.h>
 
 int
 main (void)
 {
 
-               struct block_device *bdev;
-               invalidate_bdev(bdev);
+               int flags;
+               flags = ((1 << BIO_RW_FAILFAST_DEV) |
+                        (1 << BIO_RW_FAILFAST_TRANSPORT) |
+                        (1 << BIO_RW_FAILFAST_DRIVER));
 
   ;
   return 0;
@@ -15795,7 +16614,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_1ARG_INVALIDATE_BDEV 1
+#define HAVE_BIO_RW_FAILFAST_DTD 1
 _ACEOF
 
 
@@ -15815,8 +16634,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether bdev_logical_block_size() is available" >&5
-$as_echo_n "checking whether bdev_logical_block_size() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether REQ_FAILFAST_MASK is defined" >&5
+$as_echo_n "checking whether REQ_FAILFAST_MASK is defined... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15827,14 +16646,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/blkdev.h>
+               #include <linux/bio.h>
 
 int
 main (void)
 {
 
-               struct block_device *bdev = NULL;
-               bdev_logical_block_size(bdev);
+               int flags;
+               flags = REQ_FAILFAST_MASK;
 
   ;
   return 0;
@@ -15861,7 +16680,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BDEV_LOGICAL_BLOCK_SIZE 1
+#define HAVE_BIO_REQ_FAILFAST_MASK 1
 _ACEOF
 
 
@@ -15881,8 +16700,9 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether bio_empty_barrier() is defined" >&5
-$as_echo_n "checking whether bio_empty_barrier() is defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether bio_end_io_t wants 2 args" >&5
+$as_echo_n "checking whether bio_end_io_t wants 2 args... " >&6; }
+       tmp_flags="$EXTRA_KCFLAGS"
        EXTRA_KCFLAGS="-Werror"
 
 
@@ -15900,8 +16720,10 @@ int
 main (void)
 {
 
-               struct bio bio;
-               (void)bio_empty_barrier(&bio);
+               void (*wanted_end_io)(struct bio *, int) = NULL;
+               bio_end_io_t *local_end_io;
+
+               local_end_io = wanted_end_io;
 
   ;
   return 0;
@@ -15928,7 +16750,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BIO_EMPTY_BARRIER 1
+#define HAVE_2ARGS_BIO_END_IO_T 1
 _ACEOF
 
 
        rm -Rf build
 
 
+       EXTRA_KCFLAGS="$tmp_flags"
 
 
-       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_FAILFAST is defined" >&5
-$as_echo_n "checking whether BIO_RW_FAILFAST is defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_SYNC is defined" >&5
+$as_echo_n "checking whether BIO_RW_SYNC is defined... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -15967,7 +16790,7 @@ main (void)
 {
 
                int flags;
-               flags = (1 << BIO_RW_FAILFAST);
+               flags = BIO_RW_SYNC;
 
   ;
   return 0;
@@ -15994,7 +16817,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BIO_RW_FAILFAST 1
+#define HAVE_BIO_RW_SYNC 1
 _ACEOF
 
 
@@ -16014,8 +16837,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_FAILFAST_* are defined" >&5
-$as_echo_n "checking whether BIO_RW_FAILFAST_* are defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_SYNCIO is defined" >&5
+$as_echo_n "checking whether BIO_RW_SYNCIO is defined... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16033,9 +16856,7 @@ main (void)
 {
 
                int flags;
-               flags = ((1 << BIO_RW_FAILFAST_DEV) |
-                        (1 << BIO_RW_FAILFAST_TRANSPORT) |
-                        (1 << BIO_RW_FAILFAST_DRIVER));
+               flags = BIO_RW_SYNCIO;
 
   ;
   return 0;
@@ -16062,7 +16883,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BIO_RW_FAILFAST_DTD 1
+#define HAVE_BIO_RW_SYNCIO 1
 _ACEOF
 
 
@@ -16082,8 +16903,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether REQ_FAILFAST_MASK is defined" >&5
-$as_echo_n "checking whether REQ_FAILFAST_MASK is defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether REQ_SYNC is defined" >&5
+$as_echo_n "checking whether REQ_SYNC is defined... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16101,7 +16922,7 @@ main (void)
 {
 
                int flags;
-               flags = REQ_FAILFAST_MASK;
+               flags = REQ_SYNC;
 
   ;
   return 0;
@@ -16128,7 +16949,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BIO_REQ_FAILFAST_MASK 1
+#define HAVE_REQ_SYNC 1
 _ACEOF
 
 
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether bio_end_io_t wants 2 args" >&5
-$as_echo_n "checking whether bio_end_io_t wants 2 args... " >&6; }
-       tmp_flags="$EXTRA_KCFLAGS"
-       EXTRA_KCFLAGS="-Werror"
+       { $as_echo "$as_me:$LINENO: checking whether blk_end_request() is available" >&5
+$as_echo_n "checking whether blk_end_request() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16162,16 +16981,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/bio.h>
+               #include <linux/blkdev.h>
 
 int
 main (void)
 {
 
-               void (*wanted_end_io)(struct bio *, int) = NULL;
-               bio_end_io_t *local_end_io;
-
-               local_end_io = wanted_end_io;
+               struct request *req = NULL;
+               (void) blk_end_request(req, 0, 0);
 
   ;
   return 0;
@@ -16198,7 +17015,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_2ARGS_BIO_END_IO_T 1
+#define HAVE_BLK_END_REQUEST 1
 _ACEOF
 
 
        rm -Rf build
 
 
-       EXTRA_KCFLAGS="$tmp_flags"
-
 
-       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_SYNC is defined" >&5
-$as_echo_n "checking whether BIO_RW_SYNC is defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_end_request() is GPL-only" >&5
+$as_echo_n "checking whether blk_end_request() is GPL-only... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16231,14 +17046,17 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/bio.h>
+               #include <linux/module.h>
+               #include <linux/blkdev.h>
+
+               MODULE_LICENSE("CDDL");
 
 int
 main (void)
 {
 
-               int flags;
-               flags = BIO_RW_SYNC;
+               struct request *req = NULL;
+               (void) blk_end_request(req, 0, 0);
 
   ;
   return 0;
@@ -16261,21 +17079,21 @@ _ACEOF
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
                { $as_echo "$as_me:$LINENO: result: yes" >&5
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BIO_RW_SYNC 1
+#define HAVE_BLK_END_REQUEST_GPL_ONLY 1
 _ACEOF
 
 
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-               { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-
 
 
 fi
@@ -16285,8 +17103,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether BIO_RW_SYNCIO is defined" >&5
-$as_echo_n "checking whether BIO_RW_SYNCIO is defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_fetch_request() is available" >&5
+$as_echo_n "checking whether blk_fetch_request() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16297,14 +17115,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/bio.h>
+               #include <linux/blkdev.h>
 
 int
 main (void)
 {
 
-               int flags;
-               flags = BIO_RW_SYNCIO;
+               struct request_queue *q = NULL;
+               (void) blk_fetch_request(q);
 
   ;
   return 0;
@@ -16331,7 +17149,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BIO_RW_SYNCIO 1
+#define HAVE_BLK_FETCH_REQUEST 1
 _ACEOF
 
 
@@ -16351,8 +17169,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether REQ_SYNC is defined" >&5
-$as_echo_n "checking whether REQ_SYNC is defined... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_requeue_request() is available" >&5
+$as_echo_n "checking whether blk_requeue_request() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16363,14 +17181,15 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/bio.h>
+               #include <linux/blkdev.h>
 
 int
 main (void)
 {
 
-               int flags;
-               flags = REQ_SYNC;
+               struct request_queue *q = NULL;
+               struct request *req = NULL;
+               blk_requeue_request(q, req);
 
   ;
   return 0;
@@ -16397,7 +17216,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_REQ_SYNC 1
+#define HAVE_BLK_REQUEUE_REQUEST 1
 _ACEOF
 
 
@@ -16417,8 +17236,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_end_request() is available" >&5
-$as_echo_n "checking whether blk_end_request() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_rq_bytes() is available" >&5
+$as_echo_n "checking whether blk_rq_bytes() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16436,7 +17255,7 @@ main (void)
 {
 
                struct request *req = NULL;
-               (void) blk_end_request(req, 0, 0);
+               (void) blk_rq_bytes(req);
 
   ;
   return 0;
@@ -16463,7 +17282,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_END_REQUEST 1
+#define HAVE_BLK_RQ_BYTES 1
 _ACEOF
 
 
@@ -16482,8 +17301,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_end_request() is GPL-only" >&5
-$as_echo_n "checking whether blk_end_request() is GPL-only... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_rq_bytes() is GPL-only" >&5
+$as_echo_n "checking whether blk_rq_bytes() is GPL-only... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16504,7 +17323,7 @@ main (void)
 {
 
                struct request *req = NULL;
-               (void) blk_end_request(req, 0, 0);
+               (void) blk_rq_bytes(req);
 
   ;
   return 0;
@@ -16538,7 +17357,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_END_REQUEST_GPL_ONLY 1
+#define HAVE_BLK_RQ_BYTES_GPL_ONLY 1
 _ACEOF
 
 
@@ -16551,8 +17370,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_fetch_request() is available" >&5
-$as_echo_n "checking whether blk_fetch_request() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_rq_pos() is available" >&5
+$as_echo_n "checking whether blk_rq_pos() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16569,8 +17388,8 @@ int
 main (void)
 {
 
-               struct request_queue *q = NULL;
-               (void) blk_fetch_request(q);
+               struct request *req = NULL;
+               (void) blk_rq_pos(req);
 
   ;
   return 0;
@@ -16597,7 +17416,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_FETCH_REQUEST 1
+#define HAVE_BLK_RQ_POS 1
 _ACEOF
 
 
@@ -16617,8 +17436,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_requeue_request() is available" >&5
-$as_echo_n "checking whether blk_requeue_request() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether blk_rq_sectors() is available" >&5
+$as_echo_n "checking whether blk_rq_sectors() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16635,9 +17454,8 @@ int
 main (void)
 {
 
-               struct request_queue *q = NULL;
                struct request *req = NULL;
-               blk_requeue_request(q, req);
+               (void) blk_rq_sectors(req);
 
   ;
   return 0;
@@ -16664,7 +17482,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_REQUEUE_REQUEST 1
+#define HAVE_BLK_RQ_SECTORS 1
 _ACEOF
 
 
@@ -16684,8 +17502,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_rq_bytes() is available" >&5
-$as_echo_n "checking whether blk_rq_bytes() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether get_disk_ro() is available" >&5
+$as_echo_n "checking whether get_disk_ro() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16702,8 +17520,8 @@ int
 main (void)
 {
 
-               struct request *req = NULL;
-               (void) blk_rq_bytes(req);
+               struct gendisk *disk = NULL;
+               (void) get_disk_ro(disk);
 
   ;
   return 0;
@@ -16730,7 +17548,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_RQ_BYTES 1
+#define HAVE_GET_DISK_RO 1
 _ACEOF
 
 
@@ -16749,8 +17567,9 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_rq_bytes() is GPL-only" >&5
-$as_echo_n "checking whether blk_rq_bytes() is GPL-only... " >&6; }
+
+       { $as_echo "$as_me:$LINENO: checking whether rq_is_sync() is available" >&5
+$as_echo_n "checking whether rq_is_sync() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16761,17 +17580,14 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/module.h>
                #include <linux/blkdev.h>
 
-               MODULE_LICENSE("CDDL");
-
 int
 main (void)
 {
 
                struct request *req = NULL;
-               (void) blk_rq_bytes(req);
+               (void) rq_is_sync(req);
 
   ;
   return 0;
@@ -16794,21 +17610,21 @@ _ACEOF
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               { $as_echo "$as_me:$LINENO: result: no" >&5
-$as_echo "no" >&6; }
-
-else
-  $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
                { $as_echo "$as_me:$LINENO: result: yes" >&5
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_RQ_BYTES_GPL_ONLY 1
+#define HAVE_RQ_IS_SYNC 1
 _ACEOF
 
 
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
 
 
 fi
@@ -16818,8 +17634,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether blk_rq_pos() is available" >&5
-$as_echo_n "checking whether blk_rq_pos() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether rq_for_each_segment() is available" >&5
+$as_echo_n "checking whether rq_for_each_segment() is available... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16836,8 +17652,10 @@ int
 main (void)
 {
 
+               struct bio_vec *bv;
+               struct req_iterator iter;
                struct request *req = NULL;
-               (void) blk_rq_pos(req);
+               rq_for_each_segment(bv, req, iter) { }
 
   ;
   return 0;
@@ -16864,7 +17682,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_RQ_POS 1
+#define HAVE_RQ_FOR_EACH_SEGMENT 1
 _ACEOF
 
 
@@ -16883,9 +17701,8 @@ fi
 
 
 
-
-       { $as_echo "$as_me:$LINENO: checking whether blk_rq_sectors() is available" >&5
-$as_echo_n "checking whether blk_rq_sectors() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether super_block uses const struct xattr_hander" >&5
+$as_echo_n "checking whether super_block uses const struct xattr_hander... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16896,14 +17713,26 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/blkdev.h>
+               #include <linux/fs.h>
+               #include <linux/xattr.h>
+
+               const struct xattr_handler xattr_test_handler = {
+                       .prefix = "test",
+                       .get    = NULL,
+                       .set    = NULL,
+               };
+
+               const struct xattr_handler *xattr_handlers[] = {
+                       &xattr_test_handler,
+               };
 
 int
 main (void)
 {
 
-               struct request *req = NULL;
-               (void) blk_rq_sectors(req);
+               struct super_block sb;
+
+               sb.s_xattr = xattr_handlers;
 
   ;
   return 0;
@@ -16930,7 +17759,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_BLK_RQ_SECTORS 1
+#define HAVE_CONST_XATTR_HANDLER 1
 _ACEOF
 
 
@@ -16950,8 +17779,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether get_disk_ro() is available" >&5
-$as_echo_n "checking whether get_disk_ro() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether xattr_handler->get() wants dentry" >&5
+$as_echo_n "checking whether xattr_handler->get() wants dentry... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -16962,14 +17791,17 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/blkdev.h>
+               #include <linux/xattr.h>
 
 int
 main (void)
 {
 
-               struct gendisk *disk = NULL;
-               (void) get_disk_ro(disk);
+               int (*get)(struct dentry *dentry, const char *name,
+                   void *buffer, size_t size, int handler_flags) = NULL;
+               struct xattr_handler xops;
+
+               xops.get = get;
 
   ;
   return 0;
@@ -16996,7 +17828,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_GET_DISK_RO 1
+#define HAVE_DENTRY_XATTR_GET 1
 _ACEOF
 
 
@@ -17016,8 +17848,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether rq_is_sync() is available" >&5
-$as_echo_n "checking whether rq_is_sync() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether xattr_handler->set() wants dentry" >&5
+$as_echo_n "checking whether xattr_handler->set() wants dentry... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -17028,14 +17860,18 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/blkdev.h>
+               #include <linux/xattr.h>
 
 int
 main (void)
 {
 
-               struct request *req = NULL;
-               (void) rq_is_sync(req);
+               int (*set)(struct dentry *dentry, const char *name,
+                   const void *buffer, size_t size, int flags,
+                   int handler_flags) = NULL;
+               struct xattr_handler xops;
+
+               xops.set = set;
 
   ;
   return 0;
@@ -17062,7 +17898,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_RQ_IS_SYNC 1
+#define HAVE_DENTRY_XATTR_SET 1
 _ACEOF
 
 
@@ -17082,8 +17918,8 @@ fi
 
 
 
-       { $as_echo "$as_me:$LINENO: checking whether rq_for_each_segment() is available" >&5
-$as_echo_n "checking whether rq_for_each_segment() is available... " >&6; }
+       { $as_echo "$as_me:$LINENO: checking whether fops->fsync() wants 2 args" >&5
+$as_echo_n "checking whether fops->fsync() wants 2 args... " >&6; }
 
 
 cat confdefs.h - <<_ACEOF >conftest.c
@@ -17094,16 +17930,16 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
 
-               #include <linux/blkdev.h>
+               #include <linux/fs.h>
 
 int
 main (void)
 {
 
-               struct bio_vec *bv;
-               struct req_iterator iter;
-               struct request *req = NULL;
-               rq_for_each_segment(bv, req, iter) { }
+               int (*fsync) (struct file *, int datasync) = NULL;
+               struct file_operations fops;
+
+               fops.fsync = fsync;
 
   ;
   return 0;
@@ -17130,7 +17966,7 @@ _ACEOF
 $as_echo "yes" >&6; }
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_RQ_FOR_EACH_SEGMENT 1
+#define HAVE_2ARGS_FSYNC 1
 _ACEOF
 
 
 
 
 
-       if test "$LINUX_OBJ" != "$LINUX"; then
-               KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
-       fi
-
-
-
-                       KERNELCPPFLAGS="$KERNELCPPFLAGS -DHAVE_SPL -D_KERNEL"
-       KERNELCPPFLAGS="$KERNELCPPFLAGS -DTEXT_DOMAIN=\\\"zfs-linux-kernel\\\""
-
-
-
-
+       { $as_echo "$as_me:$LINENO: checking whether sops->evict_inode() exists" >&5
+$as_echo_n "checking whether sops->evict_inode() exists... " >&6; }
 
-       { $as_echo "$as_me:$LINENO: checking for target asm dir" >&5
-$as_echo_n "checking for target asm dir... " >&6; }
-       TARGET_ARCH=`echo ${target_cpu} | sed -e s/i.86/i386/`
-
-       case $TARGET_ARCH in
-       i386|x86_64)
-               TARGET_ASM_DIR=asm-${TARGET_ARCH}
-               ;;
-       *)
-               TARGET_ASM_DIR=asm-generic
-               ;;
-       esac
-
-
-       { $as_echo "$as_me:$LINENO: result: $TARGET_ASM_DIR" >&5
-$as_echo "$TARGET_ASM_DIR" >&6; }
 
-
-       { $as_echo "$as_me:$LINENO: checking for sa_init in -lshare" >&5
-$as_echo_n "checking for sa_init in -lshare... " >&6; }
-if test "${ac_cv_lib_share_sa_init+set}" = set; then
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lshare  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+cat confdefs.h - <<_ACEOF >conftest.c
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char sa_init ();
+
+               #include <linux/fs.h>
+
 int
-main ()
+main (void)
 {
-return sa_init ();
+
+               void (*evict_inode) (struct inode *) = NULL;
+               struct super_operations sops;
+
+               sops.evict_inode = evict_inode;
+
   ;
   return 0;
 }
+
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
-$as_echo "$ac_try_echo") >&5
-  (eval "$ac_link") 2>conftest.er1
+
+
+       rm -Rf build && mkdir -p build
+       echo "obj-m := conftest.o" >build/Makefile
+       if { ac_try='cp conftest.c build && make modules -C $LINUX_OBJ EXTRA_CFLAGS="-Werror-implicit-function-declaration $EXTRA_KCFLAGS" $ARCH_UM M=$PWD/build'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
   $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && {
-        test -z "$ac_c_werror_flag" ||
-        test ! -s conftest.err
-       } && test -s conftest$ac_exeext && {
-        test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
-       }; then
-  ac_cv_lib_share_sa_init=yes
+  (exit $ac_status); }; } >/dev/null && { ac_try='test -s build/conftest.o'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+               { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_EVICT_INODE 1
+_ACEOF
+
+
 else
   $as_echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_share_sa_init=no
-fi
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
 
-rm -rf conftest.dSYM
-rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_share_sa_init" >&5
-$as_echo "$ac_cv_lib_share_sa_init" >&6; }
-if test "x$ac_cv_lib_share_sa_init" = x""yes; then
 
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBSHARE 1
-_ACEOF
 
 fi
 
+       rm -Rf build
+
+
+
+
+       if test "$LINUX_OBJ" != "$LINUX"; then
+               KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"
+       fi
+
+
+
+                       KERNELCPPFLAGS="$KERNELCPPFLAGS -DHAVE_SPL -D_KERNEL"
+       KERNELCPPFLAGS="$KERNELCPPFLAGS -DTEXT_DOMAIN=\\\"zfs-linux-kernel\\\""
+
+
+
+
+
+       { $as_echo "$as_me:$LINENO: checking for target asm dir" >&5
+$as_echo_n "checking for target asm dir... " >&6; }
+       TARGET_ARCH=`echo ${target_cpu} | sed -e s/i.86/i386/`
+
+       case $TARGET_ARCH in
+       i386|x86_64)
+               TARGET_ASM_DIR=asm-${TARGET_ARCH}
+               ;;
+       *)
+               TARGET_ASM_DIR=asm-generic
+               ;;
+       esac
+
+
+       { $as_echo "$as_me:$LINENO: result: $TARGET_ASM_DIR" >&5
+$as_echo "$TARGET_ASM_DIR" >&6; }
 
 
        { $as_echo "$as_me:$LINENO: checking for ioctl()" >&5
 
 
 
+
+# Check whether --with-selinux was given.
+if test "${with_selinux+set}" = set; then
+  withval=$with_selinux;
+else
+  with_selinux=check
+fi
+
+
+       LIBSELINUX=
+       if test "x$with_selinux" != xno; then
+
+               if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for selinux/selinux.h" >&5
+$as_echo_n "checking for selinux/selinux.h... " >&6; }
+if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_selinux_selinux_h" >&5
+$as_echo "$ac_cv_header_selinux_selinux_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking selinux/selinux.h usability" >&5
+$as_echo_n "checking selinux/selinux.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <selinux/selinux.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking selinux/selinux.h presence" >&5
+$as_echo_n "checking selinux/selinux.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <selinux/selinux.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: selinux/selinux.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: selinux/selinux.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for selinux/selinux.h" >&5
+$as_echo_n "checking for selinux/selinux.h... " >&6; }
+if test "${ac_cv_header_selinux_selinux_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_selinux_selinux_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_selinux_selinux_h" >&5
+$as_echo "$ac_cv_header_selinux_selinux_h" >&6; }
+
+fi
+if test "x$ac_cv_header_selinux_selinux_h" = x""yes; then
+
+                       { $as_echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5
+$as_echo_n "checking for is_selinux_enabled in -lselinux... " >&6; }
+if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lselinux  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char is_selinux_enabled ();
+int
+main ()
+{
+return is_selinux_enabled ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_selinux_is_selinux_enabled=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_selinux_is_selinux_enabled=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5
+$as_echo "$ac_cv_lib_selinux_is_selinux_enabled" >&6; }
+if test "x$ac_cv_lib_selinux_is_selinux_enabled" = x""yes; then
+
+                               LIBSELINUX="-lselinux"
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBSELINUX 1
+_ACEOF
+
+
+else
+
+                               if test "x$with_selinux" != xcheck; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+fi
+
+
+fi
+
+
+else
+
+                       if test "x$with_selinux" != xcheck; then
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: --with-selinux given but unavailable
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+fi
+
+
+fi
+
+
+
+else
+
+               { $as_echo "$as_me:$LINENO: checking for selinux support" >&5
+$as_echo_n "checking for selinux support... " >&6; }
+               { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+
+
+
        { $as_echo "$as_me:$LINENO: checking for -Wframe-larger-than=<size> support" >&5
 $as_echo_n "checking for -Wframe-larger-than=<size> support... " >&6; }
 
@@ -18568,7 +19659,7 @@ fi
 $as_echo "$enable_debug" >&6; }
 
 
-ac_config_files="$ac_config_files Makefile etc/Makefile man/Makefile man/man8/Makefile lib/Makefile lib/libspl/Makefile lib/libspl/asm-generic/Makefile lib/libspl/asm-i386/Makefile lib/libspl/asm-x86_64/Makefile lib/libspl/include/Makefile lib/libspl/include/ia32/Makefile lib/libspl/include/ia32/sys/Makefile lib/libspl/include/rpc/Makefile lib/libspl/include/sys/Makefile lib/libspl/include/sys/sysevent/Makefile lib/libspl/include/sys/dktp/Makefile lib/libspl/include/util/Makefile lib/libavl/Makefile lib/libefi/Makefile lib/libnvpair/Makefile lib/libunicode/Makefile lib/libuutil/Makefile lib/libzpool/Makefile lib/libzfs/Makefile cmd/Makefile cmd/zdb/Makefile cmd/zfs/Makefile cmd/zinject/Makefile cmd/zpool/Makefile cmd/zpool_id/Makefile cmd/zpool_layout/Makefile cmd/ztest/Makefile cmd/zpios/Makefile module/Makefile module/avl/Makefile module/nvpair/Makefile module/unicode/Makefile module/zcommon/Makefile module/zfs/Makefile module/zpios/Makefile include/Makefile include/sys/Makefile include/sys/fs/Makefile include/sys/fm/Makefile include/sys/fm/fs/Makefile scripts/Makefile scripts/zpios-profile/Makefile scripts/zpios-test/Makefile scripts/zpool-config/Makefile scripts/zpool-layout/Makefile scripts/common.sh zfs.spec zfs-modules.spec zfs-script-config.sh"
+ac_config_files="$ac_config_files Makefile etc/Makefile man/Makefile man/man8/Makefile lib/Makefile lib/libspl/Makefile lib/libspl/asm-generic/Makefile lib/libspl/asm-i386/Makefile lib/libspl/asm-x86_64/Makefile lib/libspl/include/Makefile lib/libspl/include/ia32/Makefile lib/libspl/include/ia32/sys/Makefile lib/libspl/include/rpc/Makefile lib/libspl/include/sys/Makefile lib/libspl/include/sys/sysevent/Makefile lib/libspl/include/sys/dktp/Makefile lib/libspl/include/util/Makefile lib/libavl/Makefile lib/libefi/Makefile lib/libnvpair/Makefile lib/libunicode/Makefile lib/libuutil/Makefile lib/libzpool/Makefile lib/libzfs/Makefile cmd/Makefile cmd/zdb/Makefile cmd/zfs/Makefile cmd/zinject/Makefile cmd/zpool/Makefile cmd/zpool_id/Makefile cmd/zpool_layout/Makefile cmd/ztest/Makefile cmd/zpios/Makefile module/Makefile module/avl/Makefile module/nvpair/Makefile module/unicode/Makefile module/zcommon/Makefile module/zfs/Makefile module/zpios/Makefile include/Makefile include/linux/Makefile include/sys/Makefile include/sys/fs/Makefile include/sys/fm/Makefile include/sys/fm/fs/Makefile scripts/Makefile scripts/zpios-profile/Makefile scripts/zpios-test/Makefile scripts/zpool-config/Makefile scripts/zpool-layout/Makefile scripts/common.sh zfs.spec zfs-modules.spec zfs-script-config.sh"
 
 
 cat >confcache <<\_ACEOF
@@ -19525,6 +20616,7 @@ do
     "module/zfs/Makefile") CONFIG_FILES="$CONFIG_FILES module/zfs/Makefile" ;;
     "module/zpios/Makefile") CONFIG_FILES="$CONFIG_FILES module/zpios/Makefile" ;;
     "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+    "include/linux/Makefile") CONFIG_FILES="$CONFIG_FILES include/linux/Makefile" ;;
     "include/sys/Makefile") CONFIG_FILES="$CONFIG_FILES include/sys/Makefile" ;;
     "include/sys/fs/Makefile") CONFIG_FILES="$CONFIG_FILES include/sys/fs/Makefile" ;;
     "include/sys/fm/Makefile") CONFIG_FILES="$CONFIG_FILES include/sys/fm/Makefile" ;;
index 5932710..efebf71 100644 (file)
@@ -95,6 +95,7 @@ AC_CONFIG_FILES([
        module/zfs/Makefile
        module/zpios/Makefile
        include/Makefile
+       include/linux/Makefile
        include/sys/Makefile
        include/sys/fs/Makefile
        include/sys/fm/Makefile
index 5eb5551..88640a7 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 0926c6a..1d7493b 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = sys
+SUBDIRS = linux sys
 
 COMMON_H = \
        $(top_srcdir)/include/zfs_comutil.h \
index 6821a67..f47e747 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -222,6 +225,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -331,7 +335,7 @@ target_vendor = @target_vendor@
 top_build_prefix = @top_build_prefix@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-SUBDIRS = sys
+SUBDIRS = linux sys
 COMMON_H = \
        $(top_srcdir)/include/zfs_comutil.h \
        $(top_srcdir)/include/zfs_deleg.h \
index 6752579..082b690 100644 (file)
@@ -673,6 +673,12 @@ extern void zfs_nicenum(uint64_t, char *, size_t);
 extern int zfs_nicestrtonum(libzfs_handle_t *, const char *, uint64_t *);
 
 /*
+ * Utility functions to run an external process.
+ */
+int libzfs_run_process(const char *, char **);
+int libzfs_load_module(const char *);
+
+/*
  * Given a device or file, determine if it is part of a pool.
  */
 extern int zpool_in_use(libzfs_handle_t *, int, pool_state_t *, char **,
diff --git a/include/linux/Makefile.am b/include/linux/Makefile.am
new file mode 100644 (file)
index 0000000..0ea6cfe
--- /dev/null
@@ -0,0 +1,20 @@
+COMMON_H =
+
+KERNEL_H = \
+       $(top_srcdir)/include/linux/dcache_compat.h \
+       $(top_srcdir)/include/linux/xattr_compat.h \
+       $(top_srcdir)/include/linux/vfs_compat.h
+
+USER_H =
+
+EXTRA_DIST = $(COMMON_H) $(KERNEL_H) $(USER_H)
+
+if CONFIG_USER
+libzfsdir = $(includedir)/libzfs/linux
+libzfs_HEADERS = $(COMMON_H) $(USER_H)
+endif
+
+if CONFIG_KERNEL
+kerneldir = /usr/src/zfs-$(ZFS_META_VERSION)/$(LINUX_VERSION)/linux
+kernel_HEADERS = $(COMMON_H) $(KERNEL_H)
+endif
diff --git a/include/linux/Makefile.in b/include/linux/Makefile.in
new file mode 100644 (file)
index 0000000..e70c16a
--- /dev/null
@@ -0,0 +1,575 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = include/linux
+DIST_COMMON = $(am__kernel_HEADERS_DIST) $(libzfs_HEADERS) \
+       $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps =  \
+       $(top_srcdir)/config/kernel-bdev-block-device-operations.m4 \
+       $(top_srcdir)/config/kernel-bdev-logical-size.m4 \
+       $(top_srcdir)/config/kernel-bio-empty-barrier.m4 \
+       $(top_srcdir)/config/kernel-bio-end-io-t-args.m4 \
+       $(top_srcdir)/config/kernel-bio-failfast.m4 \
+       $(top_srcdir)/config/kernel-bio-rw-syncio.m4 \
+       $(top_srcdir)/config/kernel-blk-end-request.m4 \
+       $(top_srcdir)/config/kernel-blk-fetch-request.m4 \
+       $(top_srcdir)/config/kernel-blk-requeue-request.m4 \
+       $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
+       $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
+       $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
+       $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
+       $(top_srcdir)/config/kernel-get-disk-ro.m4 \
+       $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
+       $(top_srcdir)/config/kernel-kobj-name-len.m4 \
+       $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
+       $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
+       $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
+       $(top_srcdir)/config/kernel.m4 \
+       $(top_srcdir)/config/user-arch.m4 \
+       $(top_srcdir)/config/user-frame-larger-than.m4 \
+       $(top_srcdir)/config/user-ioctl.m4 \
+       $(top_srcdir)/config/user-libblkid.m4 \
+       $(top_srcdir)/config/user-libuuid.m4 \
+       $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
+       $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
+       $(top_srcdir)/config/zfs-build.m4 \
+       $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/zfs_config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN   " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+am__kernel_HEADERS_DIST = $(top_srcdir)/include/linux/dcache_compat.h \
+       $(top_srcdir)/include/linux/xattr_compat.h \
+       $(top_srcdir)/include/linux/vfs_compat.h
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(kerneldir)" "$(DESTDIR)$(libzfsdir)"
+HEADERS = $(kernel_HEADERS) $(libzfs_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALIEN = @ALIEN@
+ALIEN_VERSION = @ALIEN_VERSION@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEBUG_STACKFLAGS = @DEBUG_STACKFLAGS@
+DEFAULT_PACKAGE = @DEFAULT_PACKAGE@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DPKG = @DPKG@
+DPKGBUILD = @DPKGBUILD@
+DPKGBUILD_VERSION = @DPKGBUILD_VERSION@
+DPKG_VERSION = @DPKG_VERSION@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FRAME_LARGER_THAN = @FRAME_LARGER_THAN@
+GREP = @GREP@
+HAVE_ALIEN = @HAVE_ALIEN@
+HAVE_DPKG = @HAVE_DPKG@
+HAVE_DPKGBUILD = @HAVE_DPKGBUILD@
+HAVE_RPM = @HAVE_RPM@
+HAVE_RPMBUILD = @HAVE_RPMBUILD@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KERNELCPPFLAGS = @KERNELCPPFLAGS@
+KERNELMAKE_PARAMS = @KERNELMAKE_PARAMS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBBLKID = @LIBBLKID@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
+LIBTOOL = @LIBTOOL@
+LIBUUID = @LIBUUID@
+LINUX = @LINUX@
+LINUX_OBJ = @LINUX_OBJ@
+LINUX_SYMBOLS = @LINUX_SYMBOLS@
+LINUX_VERSION = @LINUX_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+RPM = @RPM@
+RPMBUILD = @RPMBUILD@
+RPMBUILD_VERSION = @RPMBUILD_VERSION@
+RPM_VERSION = @RPM_VERSION@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPL = @SPL@
+SPL_OBJ = @SPL_OBJ@
+SPL_SYMBOLS = @SPL_SYMBOLS@
+SPL_VERSION = @SPL_VERSION@
+STRIP = @STRIP@
+TARGET_ASM_DIR = @TARGET_ASM_DIR@
+VENDOR = @VENDOR@
+VERSION = @VERSION@
+ZFS_CONFIG = @ZFS_CONFIG@
+ZFS_META_ALIAS = @ZFS_META_ALIAS@
+ZFS_META_AUTHOR = @ZFS_META_AUTHOR@
+ZFS_META_DATA = @ZFS_META_DATA@
+ZFS_META_LICENSE = @ZFS_META_LICENSE@
+ZFS_META_LT_AGE = @ZFS_META_LT_AGE@
+ZFS_META_LT_CURRENT = @ZFS_META_LT_CURRENT@
+ZFS_META_LT_REVISION = @ZFS_META_LT_REVISION@
+ZFS_META_NAME = @ZFS_META_NAME@
+ZFS_META_RELEASE = @ZFS_META_RELEASE@
+ZFS_META_VERSION = @ZFS_META_VERSION@
+ZLIB = @ZLIB@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+COMMON_H = 
+KERNEL_H = \
+       $(top_srcdir)/include/linux/dcache_compat.h \
+       $(top_srcdir)/include/linux/xattr_compat.h \
+       $(top_srcdir)/include/linux/vfs_compat.h
+
+USER_H = 
+EXTRA_DIST = $(COMMON_H) $(KERNEL_H) $(USER_H)
+@CONFIG_USER_TRUE@libzfsdir = $(includedir)/libzfs/linux
+@CONFIG_USER_TRUE@libzfs_HEADERS = $(COMMON_H) $(USER_H)
+@CONFIG_KERNEL_TRUE@kerneldir = /usr/src/zfs-$(ZFS_META_VERSION)/$(LINUX_VERSION)/linux
+@CONFIG_KERNEL_TRUE@kernel_HEADERS = $(COMMON_H) $(KERNEL_H)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/linux/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu include/linux/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-kernelHEADERS: $(kernel_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(kerneldir)" || $(MKDIR_P) "$(DESTDIR)$(kerneldir)"
+       @list='$(kernel_HEADERS)'; test -n "$(kerneldir)" || list=; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(kerneldir)'"; \
+         $(INSTALL_HEADER) $$files "$(DESTDIR)$(kerneldir)" || exit $$?; \
+       done
+
+uninstall-kernelHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(kernel_HEADERS)'; test -n "$(kerneldir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(kerneldir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(kerneldir)" && rm -f $$files
+install-libzfsHEADERS: $(libzfs_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(libzfsdir)" || $(MKDIR_P) "$(DESTDIR)$(libzfsdir)"
+       @list='$(libzfs_HEADERS)'; test -n "$(libzfsdir)" || list=; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libzfsdir)'"; \
+         $(INSTALL_HEADER) $$files "$(DESTDIR)$(libzfsdir)" || exit $$?; \
+       done
+
+uninstall-libzfsHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(libzfs_HEADERS)'; test -n "$(libzfsdir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(libzfsdir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(libzfsdir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(kerneldir)" "$(DESTDIR)$(libzfsdir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-kernelHEADERS install-libzfsHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-kernelHEADERS uninstall-libzfsHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libtool ctags distclean distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-kernelHEADERS install-libzfsHEADERS \
+       install-man install-pdf install-pdf-am install-ps \
+       install-ps-am install-strip installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+       ps ps-am tags uninstall uninstall-am uninstall-kernelHEADERS \
+       uninstall-libzfsHEADERS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/include/linux/dcache_compat.h b/include/linux/dcache_compat.h
new file mode 100644 (file)
index 0000000..a624d4d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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 (C) 2011 Lawrence Livermore National Security, LLC.
+ */
+
+#ifndef _ZFS_DCACHE_H
+#define _ZFS_DCACHE_H
+
+#include <linux/dcache.h>
+
+#define dname(dentry)  ((char *)((dentry)->d_name.name))
+
+#endif /* _ZFS_DCACHE_H */
diff --git a/include/linux/vfs_compat.h b/include/linux/vfs_compat.h
new file mode 100644 (file)
index 0000000..bbc23a9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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 (C) 2011 Lawrence Livermore National Security, LLC.
+ */
+
+#ifndef _ZFS_VFS_H
+#define _ZFS_VFS_H
+
+/*
+ * 2.6.35 API change,
+ * The dentry argument to the .fsync() vfs hook was deemed unused by
+ * all filesystem consumers and dropped.  Add a compatibility prototype
+ * to ensure correct usage when defining this callback.
+ */
+#ifdef HAVE_2ARGS_FSYNC
+#define ZPL_FSYNC_PROTO(fn, x, y, z)   static int fn(struct file *x, int z)
+#else
+#define ZPL_FSYNC_PROTO(fn, x, y, z)   static int fn(struct file *x, \
+                                                     struct dentry *y, int z)
+#endif
+
+#endif /* _ZFS_VFS_H */
diff --git a/include/linux/xattr_compat.h b/include/linux/xattr_compat.h
new file mode 100644 (file)
index 0000000..9878aab
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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 (C) 2011 Lawrence Livermore National Security, LLC.
+ */
+
+#ifndef _ZFS_XATTR_H
+#define _ZFS_XATTR_H
+
+/*
+ * 2.6.35 API change,
+ * The const keyword was added to the 'struct xattr_handler' in the
+ * generic Linux super_block structure.  To handle this we define an
+ * appropriate xattr_handler_t typedef which can be used.  This was
+ * the preferred solution because it keeps the code clean and readable.
+ */
+#ifdef HAVE_CONST_XATTR_HANDLER
+typedef const struct xattr_handler     xattr_handler_t;
+#else
+typedef struct xattr_handler           xattr_handler_t;
+#endif
+
+/*
+ * 2.6.33 API change,
+ * The xattr_hander->get() callback was changed to take a dentry
+ * instead of an inode, and a handler_flags argument was added.
+ */
+#ifdef HAVE_DENTRY_XATTR_GET
+#define ZPL_XATTR_GET_WRAPPER(fn)                                      \
+static int                                                             \
+fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \
+    int unused_handler_flags)                                          \
+{                                                                      \
+       return __ ## fn(dentry->d_inode, name, buffer, size);           \
+}
+#else
+#define ZPL_XATTR_GET_WRAPPER(fn)                                      \
+static int                                                             \
+fn(struct inode *ip, const char *name, void *buffer, size_t size)      \
+{                                                                      \
+       return __ ## fn(ip, name, buffer, size);                        \
+}
+#endif /* HAVE_DENTRY_XATTR_GET */
+
+/*
+ * 2.6.33 API change,
+ * The xattr_hander->set() callback was changed to take a dentry
+ * instead of an inode, and a handler_flags argument was added.
+ */
+#ifdef HAVE_DENTRY_XATTR_SET
+#define ZPL_XATTR_SET_WRAPPER(fn)                                      \
+static int                                                             \
+fn(struct dentry *dentry, const char *name, const void *buffer,                \
+    size_t size, int flags, int unused_handler_flags)                  \
+{                                                                      \
+       return __ ## fn(dentry->d_inode, name, buffer, size, flags);    \
+}
+#else
+#define ZPL_XATTR_SET_WRAPPER(fn)                                      \
+static int                                                             \
+fn(struct inode *ip, const char *name, const void *buffer,             \
+    size_t size, int flags)                                            \
+{                                                                      \
+       return __ ## fn(ip, name, buffer, size, flags);                 \
+}
+#endif /* HAVE_DENTRY_XATTR_SET */
+
+#endif /* _ZFS_XATTR_H */
index 59e1371..bde71b7 100644 (file)
@@ -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 \
@@ -53,7 +54,6 @@ COMMON_H = \
        $(top_srcdir)/include/sys/zap_leaf.h \
        $(top_srcdir)/include/sys/zfs_acl.h \
        $(top_srcdir)/include/sys/zfs_context.h \
-       $(top_srcdir)/include/sys/zfs_ctldir.h \
        $(top_srcdir)/include/sys/zfs_debug.h \
        $(top_srcdir)/include/sys/zfs_dir.h \
        $(top_srcdir)/include/sys/zfs_fuid.h \
@@ -62,6 +62,7 @@ COMMON_H = \
        $(top_srcdir)/include/sys/zfs_stat.h \
        $(top_srcdir)/include/sys/zfs_vfsops.h \
        $(top_srcdir)/include/sys/zfs_znode.h \
+       $(top_srcdir)/include/sys/zfs_vnops.h \
        $(top_srcdir)/include/sys/zil.h \
        $(top_srcdir)/include/sys/zil_impl.h \
        $(top_srcdir)/include/sys/zio_checksum.h \
@@ -74,6 +75,7 @@ KERNEL_H = \
        $(top_srcdir)/include/sys/blkdev.h \
        $(top_srcdir)/include/sys/zfs_ioctl.h \
        $(top_srcdir)/include/sys/zfs_onexit.h \
+       ${top_srcdir}/include/sys/zpl.h \
        $(top_srcdir)/include/sys/zvol.h
 
 USER_H =
index 8964aae..37339e2 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -132,6 +135,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 \
@@ -143,7 +147,6 @@ am__kernel_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
        $(top_srcdir)/include/sys/zap_leaf.h \
        $(top_srcdir)/include/sys/zfs_acl.h \
        $(top_srcdir)/include/sys/zfs_context.h \
-       $(top_srcdir)/include/sys/zfs_ctldir.h \
        $(top_srcdir)/include/sys/zfs_debug.h \
        $(top_srcdir)/include/sys/zfs_dir.h \
        $(top_srcdir)/include/sys/zfs_fuid.h \
@@ -152,6 +155,7 @@ am__kernel_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
        $(top_srcdir)/include/sys/zfs_stat.h \
        $(top_srcdir)/include/sys/zfs_vfsops.h \
        $(top_srcdir)/include/sys/zfs_znode.h \
+       $(top_srcdir)/include/sys/zfs_vnops.h \
        $(top_srcdir)/include/sys/zil.h \
        $(top_srcdir)/include/sys/zil_impl.h \
        $(top_srcdir)/include/sys/zio_checksum.h \
@@ -162,6 +166,7 @@ am__kernel_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
        $(top_srcdir)/include/sys/blkdev.h \
        $(top_srcdir)/include/sys/zfs_ioctl.h \
        $(top_srcdir)/include/sys/zfs_onexit.h \
+       ${top_srcdir}/include/sys/zpl.h \
        $(top_srcdir)/include/sys/zvol.h
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
@@ -226,6 +231,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 \
@@ -237,7 +243,6 @@ am__libzfs_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
        $(top_srcdir)/include/sys/zap_leaf.h \
        $(top_srcdir)/include/sys/zfs_acl.h \
        $(top_srcdir)/include/sys/zfs_context.h \
-       $(top_srcdir)/include/sys/zfs_ctldir.h \
        $(top_srcdir)/include/sys/zfs_debug.h \
        $(top_srcdir)/include/sys/zfs_dir.h \
        $(top_srcdir)/include/sys/zfs_fuid.h \
@@ -246,6 +251,7 @@ am__libzfs_HEADERS_DIST = $(top_srcdir)/include/sys/arc.h \
        $(top_srcdir)/include/sys/zfs_stat.h \
        $(top_srcdir)/include/sys/zfs_vfsops.h \
        $(top_srcdir)/include/sys/zfs_znode.h \
+       $(top_srcdir)/include/sys/zfs_vnops.h \
        $(top_srcdir)/include/sys/zil.h \
        $(top_srcdir)/include/sys/zil_impl.h \
        $(top_srcdir)/include/sys/zio_checksum.h \
@@ -343,6 +349,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -495,6 +502,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 \
@@ -506,7 +514,6 @@ COMMON_H = \
        $(top_srcdir)/include/sys/zap_leaf.h \
        $(top_srcdir)/include/sys/zfs_acl.h \
        $(top_srcdir)/include/sys/zfs_context.h \
-       $(top_srcdir)/include/sys/zfs_ctldir.h \
        $(top_srcdir)/include/sys/zfs_debug.h \
        $(top_srcdir)/include/sys/zfs_dir.h \
        $(top_srcdir)/include/sys/zfs_fuid.h \
@@ -515,6 +522,7 @@ COMMON_H = \
        $(top_srcdir)/include/sys/zfs_stat.h \
        $(top_srcdir)/include/sys/zfs_vfsops.h \
        $(top_srcdir)/include/sys/zfs_znode.h \
+       $(top_srcdir)/include/sys/zfs_vnops.h \
        $(top_srcdir)/include/sys/zil.h \
        $(top_srcdir)/include/sys/zil_impl.h \
        $(top_srcdir)/include/sys/zio_checksum.h \
@@ -527,6 +535,7 @@ KERNEL_H = \
        $(top_srcdir)/include/sys/blkdev.h \
        $(top_srcdir)/include/sys/zfs_ioctl.h \
        $(top_srcdir)/include/sys/zfs_onexit.h \
+       ${top_srcdir}/include/sys/zpl.h \
        $(top_srcdir)/include/sys/zvol.h
 
 USER_H = 
index 575cb2d..7040b67 100644 (file)
@@ -515,11 +515,13 @@ void dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
        dmu_tx_t *tx);
 #ifdef _KERNEL
 int dmu_read_req(objset_t *os, uint64_t object, struct request *req);
-int dmu_write_req(objset_t *os, uint64_t object, struct request *req, dmu_tx_t *tx);
-#endif
-#ifdef HAVE_ZPL
-int dmu_write_pages(objset_t *os, uint64_t object, uint64_t offset,
-    uint64_t size, struct page *pp, dmu_tx_t *tx);
+int dmu_write_req(objset_t *os, uint64_t object, struct request *req,
+       dmu_tx_t *tx);
+int dmu_read_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size);
+int dmu_write_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size,
+       dmu_tx_t *tx);
+int dmu_write_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size,
+       dmu_tx_t *tx);
 #endif
 struct arc_buf *dmu_request_arcbuf(dmu_buf_t *handle, int size);
 void dmu_return_arcbuf(struct arc_buf *buf);
index 7d25bd7..99a131e 100644 (file)
@@ -75,7 +75,7 @@ typedef struct dsl_pool {
        struct dsl_dir *dp_free_dir;
        struct dsl_dataset *dp_origin_snap;
        uint64_t dp_root_dir_obj;
-       struct taskq *dp_vnrele_taskq;
+       struct taskq *dp_iput_taskq;
 
        /* No lock needed - sync context only */
        blkptr_t dp_meta_rootbp;
@@ -135,7 +135,7 @@ void dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx);
 void dsl_pool_upgrade_clones(dsl_pool_t *dp, dmu_tx_t *tx);
 void dsl_pool_upgrade_dir_clones(dsl_pool_t *dp, dmu_tx_t *tx);
 
-taskq_t *dsl_pool_vnrele_taskq(dsl_pool_t *dp);
+taskq_t *dsl_pool_iput_taskq(dsl_pool_t *dp);
 
 extern int dsl_pool_user_hold(dsl_pool_t *dp, uint64_t dsobj,
     const char *tag, uint64_t *now, dmu_tx_t *tx);
index 5e1f4b8..d05018d 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -207,6 +210,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index ed828eb..e2ad953 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -167,6 +170,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 3103ffa..ce196fb 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -167,6 +170,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
diff --git a/include/sys/uio_impl.h b/include/sys/uio_impl.h
new file mode 100644 (file)
index 0000000..37e283d
--- /dev/null
@@ -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 */
index 021e66d..03e7048 100644 (file)
@@ -81,6 +81,9 @@ extern int vdev_disk_read_rootlabel(char *, char *, nvlist_t **);
 # define vdev_bdev_block_size(bdev)    bdev_hardsect_size(bdev)
 #endif
 
+/* Default Linux IO Scheduler */
+#define        VDEV_SCHEDULER                  "noop"
+
 #endif /* _KERNEL */
 
 #ifdef __cplusplus
index c1a0aee..6f7cef2 100644 (file)
@@ -200,13 +200,13 @@ typedef struct zfs_acl_ids {
 #define        ZFS_ACL_PASSTHROUGH_X   5
 
 struct znode;
-struct zfsvfs;
+struct zfs_sb;
 
 #ifdef _KERNEL
 int zfs_acl_ids_create(struct znode *, int, vattr_t *,
     cred_t *, vsecattr_t *, zfs_acl_ids_t *);
 void zfs_acl_ids_free(zfs_acl_ids_t *);
-boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *);
+boolean_t zfs_acl_ids_overquota(struct zfs_sb *, zfs_acl_ids_t *);
 int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
 int zfs_setacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
 void zfs_acl_rele(void *);
@@ -223,7 +223,7 @@ int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *);
 int zfs_zaccess_rename(struct znode *, struct znode *,
     struct znode *, struct znode *, cred_t *cr);
 void zfs_acl_free(zfs_acl_t *);
-int zfs_vsec_2_aclp(struct zfsvfs *, vtype_t, vsecattr_t *, cred_t *,
+int zfs_vsec_2_aclp(struct zfs_sb *, umode_t, vsecattr_t *, cred_t *,
     struct zfs_fuid_info **, zfs_acl_t **);
 int zfs_aclset_common(struct znode *, zfs_acl_t *, cred_t *, dmu_tx_t *);
 uint64_t zfs_external_acl(struct znode *);
index c449903..a0165bb 100644 (file)
 #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>
+#include <linux/dcache_compat.h>
 
 #else /* _KERNEL */
 
@@ -310,6 +310,7 @@ extern void cv_wait(kcondvar_t *cv, kmutex_t *mp);
 extern clock_t cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime);
 extern void cv_signal(kcondvar_t *cv);
 extern void cv_broadcast(kcondvar_t *cv);
+#define cv_timedwait_interruptible(cv, mp, at) cv_timedwait(cv, mp, at);
 
 /*
  * kstat creation, installation and deletion
diff --git a/include/sys/zfs_ctldir.h b/include/sys/zfs_ctldir.h
deleted file mode 100644 (file)
index f88ef95..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef        _ZFS_CTLDIR_H
-#define        _ZFS_CTLDIR_H
-
-#include <sys/pathname.h>
-#include <sys/vnode.h>
-#include <sys/zfs_vfsops.h>
-#include <sys/zfs_znode.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define        ZFS_CTLDIR_NAME         ".zfs"
-
-#define        zfs_has_ctldir(zdp)     \
-       ((zdp)->z_id == (zdp)->z_zfsvfs->z_root && \
-       ((zdp)->z_zfsvfs->z_ctldir != NULL))
-#define        zfs_show_ctldir(zdp)    \
-       (zfs_has_ctldir(zdp) && \
-       ((zdp)->z_zfsvfs->z_show_ctldir))
-
-void zfsctl_create(zfsvfs_t *);
-void zfsctl_destroy(zfsvfs_t *);
-vnode_t *zfsctl_root(znode_t *);
-void zfsctl_init(void);
-void zfsctl_fini(void);
-boolean_t zfsctl_is_node(vnode_t *);
-
-int zfsctl_rename_snapshot(const char *from, const char *to);
-int zfsctl_destroy_snapshot(const char *snapname, int force);
-int zfsctl_umount_snapshots(vfs_t *, int, cred_t *);
-
-int zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
-    int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
-    int *direntflags, pathname_t *realpnp);
-
-int zfsctl_make_fid(zfsvfs_t *zfsvfsp, uint64_t object, uint32_t gen,
-    fid_t *fidp);
-int zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp);
-
-#define        ZFSCTL_INO_ROOT         0x1
-#define        ZFSCTL_INO_SNAPDIR      0x2
-#define        ZFSCTL_INO_SHARES       0x3
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ZFS_CTLDIR_H */
index 349f8ef..8610fbe 100644 (file)
@@ -54,7 +54,7 @@ extern void zfs_dirent_unlock(zfs_dirlock_t *);
 extern int zfs_link_create(zfs_dirlock_t *, znode_t *, dmu_tx_t *, int);
 extern int zfs_link_destroy(zfs_dirlock_t *, znode_t *, dmu_tx_t *, int,
     boolean_t *);
-extern int zfs_dirlook(znode_t *, char *, vnode_t **, int, int *,
+extern int zfs_dirlook(znode_t *, char *, struct inode **, int, int *,
     pathname_t *);
 extern void zfs_mknode(znode_t *, vattr_t *, dmu_tx_t *, cred_t *,
     uint_t, znode_t **, zfs_acl_ids_t *);
@@ -62,10 +62,10 @@ extern void zfs_rmnode(znode_t *);
 extern void zfs_dl_name_switch(zfs_dirlock_t *dl, char *new, char **old);
 extern boolean_t zfs_dirempty(znode_t *);
 extern void zfs_unlinked_add(znode_t *, dmu_tx_t *);
-extern void zfs_unlinked_drain(zfsvfs_t *zfsvfs);
+extern void zfs_unlinked_drain(zfs_sb_t *);
 extern int zfs_sticky_remove_access(znode_t *, znode_t *, cred_t *cr);
-extern int zfs_get_xattrdir(znode_t *, vnode_t **, cred_t *, int);
-extern int zfs_make_xattrdir(znode_t *, vattr_t *, vnode_t **, cred_t *);
+extern int zfs_get_xattrdir(znode_t *, struct inode **, cred_t *, int);
+extern int zfs_make_xattrdir(znode_t *, vattr_t *, struct inode **, cred_t *);
 
 #ifdef __cplusplus
 }
index d2989c8..deaebcc 100644 (file)
@@ -99,27 +99,25 @@ typedef struct zfs_fuid_info {
 } zfs_fuid_info_t;
 
 #ifdef _KERNEL
-#ifdef HAVE_ZPL
 struct znode;
-extern uid_t zfs_fuid_map_id(zfsvfs_t *, uint64_t, cred_t *, zfs_fuid_type_t);
+extern uid_t zfs_fuid_map_id(zfs_sb_t *, uint64_t, cred_t *, zfs_fuid_type_t);
 extern void zfs_fuid_node_add(zfs_fuid_info_t **, const char *, uint32_t,
     uint64_t, uint64_t, zfs_fuid_type_t);
-extern void zfs_fuid_destroy(zfsvfs_t *);
-extern uint64_t zfs_fuid_create_cred(zfsvfs_t *, zfs_fuid_type_t,
+extern void zfs_fuid_destroy(zfs_sb_t *);
+extern uint64_t zfs_fuid_create_cred(zfs_sb_t *, zfs_fuid_type_t,
     cred_t *, zfs_fuid_info_t **);
-extern uint64_t zfs_fuid_create(zfsvfs_t *, uint64_t, cred_t *, zfs_fuid_type_t,
+extern uint64_t zfs_fuid_create(zfs_sb_t *, uint64_t, cred_t *, zfs_fuid_type_t,
     zfs_fuid_info_t **);
 extern void zfs_fuid_map_ids(struct znode *zp, cred_t *cr,
     uid_t *uid, uid_t *gid);
 extern zfs_fuid_info_t *zfs_fuid_info_alloc(void);
 extern void zfs_fuid_info_free(zfs_fuid_info_t *);
-extern boolean_t zfs_groupmember(zfsvfs_t *, uint64_t, cred_t *);
-void zfs_fuid_sync(zfsvfs_t *, dmu_tx_t *);
-extern int zfs_fuid_find_by_domain(zfsvfs_t *, const char *domain,
+extern boolean_t zfs_groupmember(zfs_sb_t *, uint64_t, cred_t *);
+void zfs_fuid_sync(zfs_sb_t *, dmu_tx_t *);
+extern int zfs_fuid_find_by_domain(zfs_sb_t *, const char *domain,
     char **retdomain, boolean_t addok);
-extern const char *zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx);
-extern void zfs_fuid_txhold(zfsvfs_t *zfsvfs, dmu_tx_t *tx);
-#endif /* HAVE_ZPL */
+extern const char *zfs_fuid_find_by_idx(zfs_sb_t *zsb, uint32_t idx);
+extern void zfs_fuid_txhold(zfs_sb_t *zsb, dmu_tx_t *tx);
 #endif
 
 char *zfs_fuid_idx_domain(avl_tree_t *, uint32_t);
index 38c87df..a2f00ac 100644 (file)
 extern "C" {
 #endif
 
-typedef struct zfsvfs zfsvfs_t;
+struct zfs_sb;
 struct znode;
 
-struct zfsvfs {
-       vfs_t           *z_vfs;         /* generic fs struct */
-       zfsvfs_t        *z_parent;      /* parent fs */
+typedef struct zfs_sb {
+       struct vfsmount *z_vfs;         /* generic vfs struct */
+       struct super_block *z_sb;       /* generic super_block */
+       struct zfs_sb   *z_parent;      /* parent fs */
        objset_t        *z_os;          /* objset reference */
+       uint64_t        z_flags;        /* super_block flags */
        uint64_t        z_root;         /* id of root znode */
        uint64_t        z_unlinkedobj;  /* id of unlinked zapobj */
        uint64_t        z_max_blksz;    /* maximum block size for files */
@@ -67,7 +69,7 @@ struct zfsvfs {
        krwlock_t       z_teardown_inactive_lock;
        list_t          z_all_znodes;   /* all vnodes in the fs */
        kmutex_t        z_znodes_lock;  /* lock for z_all_znodes */
-       vnode_t         *z_ctldir;      /* .zfs directory pointer */
+       struct inode    *z_ctldir;      /* .zfs directory inode */
        boolean_t       z_show_ctldir;  /* expose .zfs in the root dir */
        boolean_t       z_issnap;       /* true if this is a snapshot */
        boolean_t       z_vscan;        /* virus scan on/off */
@@ -83,7 +85,36 @@ struct zfsvfs {
        sa_attr_type_t  *z_attr_table;  /* SA attr mapping->id */
 #define        ZFS_OBJ_MTX_SZ  64
        kmutex_t        z_hold_mtx[ZFS_OBJ_MTX_SZ];     /* znode hold locks */
-};
+} zfs_sb_t;
+
+#define        ZFS_SUPER_MAGIC 0x2fc12fc1
+
+#define        ZSB_XATTR_USER  0x0001          /* Enable user xattrs */
+
+
+/*
+ * Minimal snapshot helpers, the bulk of the Linux snapshot implementation
+ * lives in the zpl_snap.c file which is part of the zpl source.
+ */
+#define        ZFS_CTLDIR_NAME         ".zfs"
+
+#define        zfs_has_ctldir(zdp)     \
+       ((zdp)->z_id == ZTOZSB(zdp)->z_root && \
+       (ZTOZSB(zdp)->z_ctldir != NULL))
+#define        zfs_show_ctldir(zdp)    \
+       (zfs_has_ctldir(zdp) && \
+       (ZTOZSB(zdp)->z_show_ctldir))
+
+#define        ZFSCTL_INO_ROOT         0x1
+#define        ZFSCTL_INO_SNAPDIR      0x2
+#define        ZFSCTL_INO_SHARES       0x3
+
+/*
+ * Allow a maximum number of links.  While ZFS does not internally limit
+ * this most Linux filesystems do.  It's probably a good idea to limit
+ * this to a large value until it is validated that this is safe.
+ */
+#define ZFS_LINK_MAX           65536
 
 /*
  * Normal filesystems (those not under .zfs/snapshot) have a total
@@ -135,23 +166,31 @@ typedef struct zfid_long {
 
 extern uint_t zfs_fsyncer_key;
 
-extern int zfs_suspend_fs(zfsvfs_t *zfsvfs);
-extern int zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname);
-extern int zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
+extern int zfs_suspend_fs(zfs_sb_t *zsb);
+extern int zfs_resume_fs(zfs_sb_t *zsb, const char *osname);
+extern int zfs_userspace_one(zfs_sb_t *zsb, zfs_userquota_prop_t type,
     const char *domain, uint64_t rid, uint64_t *valuep);
-extern int zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
+extern int zfs_userspace_many(zfs_sb_t *zsb, zfs_userquota_prop_t type,
     uint64_t *cookiep, void *vbuf, uint64_t *bufsizep);
-extern int zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
+extern int zfs_set_userquota(zfs_sb_t *zsb, zfs_userquota_prop_t type,
     const char *domain, uint64_t rid, uint64_t quota);
-extern boolean_t zfs_owner_overquota(zfsvfs_t *zfsvfs, struct znode *,
+extern boolean_t zfs_owner_overquota(zfs_sb_t *zsb, struct znode *,
     boolean_t isgroup);
-extern boolean_t zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup,
+extern boolean_t zfs_fuid_overquota(zfs_sb_t *zsb, boolean_t isgroup,
     uint64_t fuid);
-extern int zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers);
-extern int zfsvfs_create(const char *name, zfsvfs_t **zfvp);
-extern void zfsvfs_free(zfsvfs_t *zfsvfs);
+extern int zfs_set_version(zfs_sb_t *zsb, uint64_t newvers);
+extern int zfs_sb_create(const char *name, zfs_sb_t **zsbp);
+extern void zfs_sb_free(zfs_sb_t *zsb);
 extern int zfs_check_global_label(const char *dsname, const char *hexsl);
 
+extern int zfs_register_callbacks(zfs_sb_t *zsb);
+extern void zfs_unregister_callbacks(zfs_sb_t *zsb);
+extern int zfs_domount(struct super_block *sb, void *data, int silent);
+extern int zfs_umount(struct super_block *sb);
+extern int zfs_root(zfs_sb_t *zsb, struct inode **ipp);
+extern int zfs_statvfs(struct dentry *dentry, struct kstatfs *statp);
+extern int zfs_vget(struct vfsmount *vfsp, struct inode **ipp, fid_t *fidp);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/sys/zfs_vnops.h b/include/sys/zfs_vnops.h
new file mode 100644 (file)
index 0000000..2cacb9c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef        _SYS_FS_ZFS_VNOPS_H
+#define        _SYS_FS_ZFS_VNOPS_H
+
+#include <sys/vnode.h>
+#include <sys/uio.h>
+#include <sys/cred.h>
+#include <sys/fcntl.h>
+#include <sys/pathname.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr);
+extern int zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr);
+extern int zfs_access(struct inode *ip, int mode, int flag, cred_t *cr);
+extern int zfs_lookup(struct inode *dip, char *nm, struct inode **ipp,
+    int flags, cred_t *cr, int *direntflags, pathname_t *realpnp);
+extern int zfs_create(struct inode *dip, char *name, vattr_t *vap, int excl,
+    int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp);
+extern int zfs_remove(struct inode *dip, char *name, cred_t *cr);
+extern int zfs_mkdir(struct inode *dip, char *dirname, vattr_t *vap,
+    struct inode **ipp, cred_t *cr, int flags, vsecattr_t *vsecp);
+extern int zfs_rmdir(struct inode *dip, char *name, struct inode *cwd,
+    cred_t *cr, int flags);
+extern int zfs_readdir(struct inode *ip, void *dirent, filldir_t filldir,
+    loff_t *pos, cred_t *cr);
+extern int zfs_fsync(struct inode *ip, int syncflag, cred_t *cr);
+extern int zfs_getattr(struct inode *ip, struct kstat *stat, int flag,
+    cred_t *cr);
+extern int zfs_setattr(struct inode *ip, struct iattr *attr, int flag,
+    cred_t *cr);
+extern int zfs_rename(struct inode *sdip, char *snm, struct inode *tdip,
+    char *tnm, cred_t *cr, int flags);
+extern int zfs_symlink(struct inode *dip, char *name, vattr_t *vap,
+    char *link, struct inode **ipp, cred_t *cr, int flags);
+extern int zfs_follow_link(struct dentry *dentry, struct nameidata *nd);
+extern int zfs_readlink(struct inode *ip, uio_t *uio, cred_t *cr);
+extern int zfs_link(struct inode *tdip, struct inode *sip,
+    char *name, cred_t *cr);
+extern void zfs_inactive(struct inode *ip);
+extern int zfs_space(struct inode *ip, int cmd, flock64_t *bfp, int flag,
+    offset_t offset, cred_t *cr);
+extern int zfs_fid(struct inode *ip, fid_t *fidp);
+extern int zfs_getsecattr(struct inode *ip, vsecattr_t *vsecp, int flag,
+    cred_t *cr);
+extern int zfs_setsecattr(struct inode *ip, vsecattr_t *vsecp, int flag,
+    cred_t *cr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_FS_ZFS_VNOPS_H */
index aa1f449..9d12a11 100644 (file)
@@ -69,7 +69,7 @@ extern "C" {
                pflags |= attr; \
        else \
                pflags &= ~attr; \
-       VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(zp->z_zfsvfs), \
+       VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(zp->z_sb), \
            &pflags, sizeof (pflags), tx)); \
 }
 
@@ -181,8 +181,6 @@ typedef struct zfs_dirlock {
 } zfs_dirlock_t;
 
 typedef struct znode {
-       struct zfsvfs   *z_zfsvfs;
-       vnode_t         *z_vnode;
        uint64_t        z_id;           /* object ID for this znode */
        kmutex_t        z_lock;         /* znode modification lock */
        krwlock_t       z_parent_lock;  /* parent lock for directories */
@@ -211,6 +209,9 @@ typedef struct znode {
        list_node_t     z_link_node;    /* all znodes in fs link */
        sa_handle_t     *z_sa_hdl;      /* handle to sa data */
        boolean_t       z_is_sa;        /* are we native sa? */
+       boolean_t       z_is_zvol;      /* are we used by the zvol */
+       boolean_t       z_is_mapped;    /* are we mmap'ed */
+       struct inode    z_inode;        /* generic vfs inode */
 } znode_t;
 
 
@@ -231,45 +232,54 @@ typedef struct znode {
  */
 
 /*
- * Convert between znode pointers and vnode pointers
+ * Convert between znode pointers and inode pointers
  */
-#define        ZTOV(ZP)        ((ZP)->z_vnode)
-#define        VTOZ(VP)        ((znode_t *)(VP)->v_data)
+#define        ZTOI(znode)     (&((znode)->z_inode))
+#define        ITOZ(inode)     (container_of((inode), znode_t, z_inode))
+#define VTOZSB(vfs)    ((zfs_sb_t *)((vfs)->mnt_sb->s_fs_info))
+#define ZTOZSB(znode)  ((zfs_sb_t *)(ZTOI(znode)->i_sb->s_fs_info))
+#define ITOZSB(inode)  ((zfs_sb_t *)((inode)->i_sb->s_fs_info))
+
+#define        S_ISDEV(mode)   (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode))
 
 /*
- * ZFS_ENTER() is called on entry to each ZFS vnode and vfs operation.
+ * ZFS_ENTER() is called on entry to each ZFS inode and vfs operation.
  * ZFS_EXIT() must be called before exitting the vop.
  * ZFS_VERIFY_ZP() verifies the znode is valid.
  */
-#define        ZFS_ENTER(zfsvfs) \
+#define        ZFS_ENTER(zsb) \
        { \
-               rrw_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG); \
-               if ((zfsvfs)->z_unmounted) { \
-                       ZFS_EXIT(zfsvfs); \
+               rrw_enter(&(zsb)->z_teardown_lock, RW_READER, FTAG); \
+               if ((zsb)->z_unmounted) { \
+                       ZFS_EXIT(zsb); \
                        return (EIO); \
                } \
        }
 
-#define        ZFS_EXIT(zfsvfs) rrw_exit(&(zfsvfs)->z_teardown_lock, FTAG)
+#define        ZFS_EXIT(zsb) \
+       { \
+               rrw_exit(&(zsb)->z_teardown_lock, FTAG); \
+               tsd_exit(); \
+       }
 
 #define        ZFS_VERIFY_ZP(zp) \
        if ((zp)->z_sa_hdl == NULL) { \
-               ZFS_EXIT((zp)->z_zfsvfs); \
+               ZFS_EXIT(ZTOZSB(zp)); \
                return (EIO); \
-       } \
+       }
 
 /*
  * Macros for dealing with dmu_buf_hold
  */
 #define        ZFS_OBJ_HASH(obj_num)   ((obj_num) & (ZFS_OBJ_MTX_SZ - 1))
-#define        ZFS_OBJ_MUTEX(zfsvfs, obj_num)  \
-       (&(zfsvfs)->z_hold_mtx[ZFS_OBJ_HASH(obj_num)])
-#define        ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num) \
-       mutex_enter(ZFS_OBJ_MUTEX((zfsvfs), (obj_num)))
-#define        ZFS_OBJ_HOLD_TRYENTER(zfsvfs, obj_num) \
-       mutex_tryenter(ZFS_OBJ_MUTEX((zfsvfs), (obj_num)))
-#define        ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num) \
-       mutex_exit(ZFS_OBJ_MUTEX((zfsvfs), (obj_num)))
+#define        ZFS_OBJ_MUTEX(zsb, obj_num)     \
+       (&(zsb)->z_hold_mtx[ZFS_OBJ_HASH(obj_num)])
+#define        ZFS_OBJ_HOLD_ENTER(zsb, obj_num) \
+       mutex_enter(ZFS_OBJ_MUTEX((zsb), (obj_num)))
+#define        ZFS_OBJ_HOLD_TRYENTER(zsb, obj_num) \
+       mutex_tryenter(ZFS_OBJ_MUTEX((zsb), (obj_num)))
+#define        ZFS_OBJ_HOLD_EXIT(zsb, obj_num) \
+       mutex_exit(ZFS_OBJ_MUTEX((zsb), (obj_num)))
 
 /*
  * Macros to encode/decode ZFS stored time values from/to struct timespec
@@ -289,15 +299,15 @@ typedef struct znode {
 /*
  * Timestamp defines
  */
-#define        ACCESSED                (AT_ATIME)
-#define        STATE_CHANGED           (AT_CTIME)
-#define        CONTENT_MODIFIED        (AT_MTIME | AT_CTIME)
+#define        ACCESSED                (ATTR_ATIME)
+#define        STATE_CHANGED           (ATTR_CTIME)
+#define        CONTENT_MODIFIED        (ATTR_MTIME | ATTR_CTIME)
 
-#define        ZFS_ACCESSTIME_STAMP(zfsvfs, zp) \
-       if ((zfsvfs)->z_atime && !((zfsvfs)->z_vfs->vfs_flag & VFS_RDONLY)) \
+#define        ZFS_ACCESSTIME_STAMP(zsb, zp) \
+       if ((zsb)->z_atime && !((zsb)->z_vfs->mnt_flags & MNT_READONLY)) \
                zfs_tstamp_update_setup(zp, ACCESSED, NULL, NULL, B_FALSE);
 
-extern int     zfs_init_fs(zfsvfs_t *, znode_t **);
+extern int     zfs_init_fs(zfs_sb_t *, znode_t **);
 extern void    zfs_set_dataprop(objset_t *);
 extern void    zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *,
     dmu_tx_t *tx);
@@ -307,18 +317,20 @@ extern void       zfs_grow_blocksize(znode_t *, uint64_t, dmu_tx_t *);
 extern int     zfs_freesp(znode_t *, uint64_t, uint64_t, int, boolean_t);
 extern void    zfs_znode_init(void);
 extern void    zfs_znode_fini(void);
-extern int     zfs_zget(zfsvfs_t *, uint64_t, znode_t **);
+extern int     zfs_zget(zfs_sb_t *, uint64_t, znode_t **);
 extern int     zfs_rezget(znode_t *);
 extern void    zfs_zinactive(znode_t *);
 extern void    zfs_znode_delete(znode_t *, dmu_tx_t *);
-extern void    zfs_znode_free(znode_t *);
 extern void    zfs_remove_op_tables(void);
 extern int     zfs_create_op_tables(void);
-extern int     zfs_sync(vfs_t *vfsp, short flag, cred_t *cr);
+extern int     zfs_sync(zfs_sb_t *, short, cred_t *);
 extern dev_t   zfs_cmpldev(uint64_t);
 extern int     zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value);
 extern int     zfs_get_stats(objset_t *os, nvlist_t *nv);
 extern void    zfs_znode_dmu_fini(znode_t *);
+extern int     zfs_inode_alloc(struct super_block *, struct inode **ip);
+extern void    zfs_inode_destroy(struct inode *);
+extern void    zfs_inode_update(znode_t *);
 
 extern void zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
     znode_t *dzp, znode_t *zp, char *name, vsecattr_t *, zfs_fuid_info_t *,
@@ -339,12 +351,13 @@ extern void zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
 extern void zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
     znode_t *zp, uint64_t off, uint64_t len);
 extern void zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
-    znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp);
+    znode_t *zp, struct iattr *attr, uint_t mask_applied,
+    zfs_fuid_info_t *fuidp);
 extern void zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
     vsecattr_t *vsecp, zfs_fuid_info_t *fuidp);
 extern void zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx);
-extern void zfs_upgrade(zfsvfs_t *zfsvfs, dmu_tx_t *tx);
-extern int zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx);
+extern void zfs_upgrade(zfs_sb_t *zsb, dmu_tx_t *tx);
+extern int zfs_create_share_dir(zfs_sb_t *zsb, dmu_tx_t *tx);
 
 #if defined(HAVE_UIO_RW)
 extern caddr_t zfs_map_page(page_t *, enum seg_rw);
diff --git a/include/sys/zpl.h b/include/sys/zpl.h
new file mode 100644 (file)
index 0000000..b6da0d2
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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 (c) 2011, Lawrence Livermore National Security, LLC.
+ */
+
+#ifndef        _SYS_ZPL_H
+#define        _SYS_ZPL_H
+
+#include <sys/vfs.h>
+#include <linux/vfs_compat.h>
+#include <linux/xattr_compat.h>
+
+/* zpl_inode.c */
+extern const struct inode_operations zpl_inode_operations;
+extern const struct inode_operations zpl_dir_inode_operations;
+extern const struct inode_operations zpl_symlink_inode_operations;
+extern const struct inode_operations zpl_special_inode_operations;
+
+/* zpl_file.c */
+extern ssize_t zpl_read_common(struct inode *ip, const char *buf,
+    size_t len, loff_t pos, uio_seg_t segment, int flags, cred_t *cr);
+extern ssize_t zpl_write_common(struct inode *ip, const char *buf,
+    size_t len, loff_t pos, uio_seg_t segment, int flags, cred_t *cr);
+
+extern const struct address_space_operations zpl_address_space_operations;
+extern const struct file_operations zpl_file_operations;
+extern const struct file_operations zpl_dir_file_operations;
+
+/* zpl_super.c */
+typedef struct zpl_mount_data {
+       const char *z_osname;   /* Dataset name */
+       void *z_data;           /* Mount options string */
+       struct vfsmount *z_vfs; /* VFS mount point */
+} zpl_mount_data_t;
+
+extern const struct super_operations zpl_super_operations;
+/* extern const struct export_operations zpl_export_operations; */
+extern struct file_system_type zpl_fs_type;
+
+/* zpl_xattr.c */
+extern ssize_t zpl_xattr_list(struct dentry *dentry, char *buf, size_t size);
+extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip);
+
+extern xattr_handler_t *zpl_xattr_handlers[];
+
+#endif /* _SYS_ZPL_H */
index 9749b77..139d3e4 100644 (file)
@@ -50,21 +50,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -178,6 +181,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 930f8e5..421b285 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -190,6 +193,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 294cac0..00f109d 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -190,6 +193,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index da71e34..2af0c4e 100644 (file)
@@ -269,19 +269,12 @@ efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc)
        struct uuid     uuid;
        struct dk_cinfo dki_info;
 
-       if (read_disk_info(fd, &capacity, &lbsize) != 0) {
-               if (efi_debug)
-                       (void) fprintf(stderr,
-                           "couldn't read disk information\n");
+       if (read_disk_info(fd, &capacity, &lbsize) != 0)
                return (-1);
-       }
+
 #if defined(__linux__)
-       if (efi_get_info(fd, &dki_info) != 0) {
-               if (efi_debug)
-                       (void) fprintf(stderr,
-                           "couldn't read disk information\n");
+       if (efi_get_info(fd, &dki_info) != 0)
                return (-1);
-       }
 
        if (dki_info.dki_partition != 0)
                return (-1);
index 8f689d4..c47aa7d 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -191,6 +194,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 6bf1478..be5ddf1 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -241,6 +244,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 8b87c31..67e9a0f 100644 (file)
@@ -51,21 +51,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -139,6 +142,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index fe9d9cb..bbb7265 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -143,6 +146,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 7506903..625adc5 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -143,6 +146,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 1a0a7f8..66ba65f 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -203,6 +206,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 4b97ee1..c083628 100644 (file)
@@ -50,21 +50,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -178,6 +181,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 1b2fb35..243eaeb 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -165,6 +168,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
diff --git a/lib/libspl/include/libgen.h b/lib/libspl/include/libgen.h
new file mode 100644 (file)
index 0000000..29e5400
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (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 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LIBSPL_LIBGEN_H
+#define _LIBSPL_LIBGEN_H
+
+#include <sys/types.h>
+
+extern int mkdirp(const char *, mode_t);
+
+#endif /* _LIBSPL_LIBGEN_H */
index afbdf5b..f1fbfad 100644 (file)
  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-/*
- * basic API declarations for share management
- */
-
 #ifndef _LIBSPL_LIBSHARE_H
 #define _LIBSPL_LIBSHARE_H
 
+typedef void *sa_handle_t;     /* opaque handle to access core functions */
+typedef void *sa_group_t;
+typedef void *sa_share_t;
+
+/* API Initialization */
+#define        SA_INIT_SHARE_API       0x0001  /* init share specific interface */
+#define        SA_INIT_CONTROL_API     0x0002  /* init control specific interface */
+
+/* Error values */
+#define        SA_OK                   0
+#define        SA_NO_MEMORY            2       /* no memory for data structures */
+#define        SA_CONFIG_ERR           6       /* system configuration error */
+
 #endif /* _LIBSPL_LIBSHARE_H */
index f5385d9..35c2b14 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -165,6 +168,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 20fdfca..b0b29bf 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -203,6 +206,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 713aa88..f984554 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -165,6 +168,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index c0594ca..d552c9c 100644 (file)
 #ifndef _SYS_MNTENT_H
 #define        _SYS_MNTENT_H
 
+#define        MNTTYPE_ZFS     "zfs"           /* ZFS file system */
 
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define        MNTTAB          "/proc/mounts"
-#define        VFSTAB          "/etc/vfstab"
+#define        FSTAB           "/etc/fstab"
 #define        MNTMAXSTR       128
 
-#define        MNTTYPE_ZFS     "zfs"           /* ZFS file system */
-#define        MNTTYPE_UFS     "ufs"           /* Unix file system */
-#define        MNTTYPE_SMBFS   "smbfs"         /* SMBFS file system */
-#define        MNTTYPE_NFS     "nfs"           /* NFS file system */
-#define        MNTTYPE_NFS3    "nfs3"          /* NFS Version 3 file system */
-#define        MNTTYPE_NFS4    "nfs4"          /* NFS Version 4 file system */
-#define        MNTTYPE_CACHEFS "cachefs"       /* Cache File System */
-#define        MNTTYPE_PCFS    "pcfs"          /* PC (MSDOS) file system */
-#define        MNTTYPE_PC      MNTTYPE_PCFS    /* Deprecated name; use MNTTYPE_PCFS */
-#define        MNTTYPE_LOFS    "lofs"          /* Loop back file system */
-#define        MNTTYPE_LO      MNTTYPE_LOFS    /* Deprecated name; use MNTTYPE_LOFS */
-#define        MNTTYPE_HSFS    "hsfs"          /* High Sierra (9660) file system */
-#define        MNTTYPE_SWAP    "swap"          /* Swap file system */
-#define        MNTTYPE_TMPFS   "tmpfs"         /* Tmp volatile file system */
-#define        MNTTYPE_AUTOFS  "autofs"        /* Automounter ``file'' system */
-#define        MNTTYPE_MNTFS   "mntfs"         /* In-kernel mnttab */
-#define        MNTTYPE_DEV     "dev"           /* /dev file system */
-#define        MNTTYPE_CTFS    "ctfs"          /* Contract file system */
-#define        MNTTYPE_OBJFS   "objfs"         /* Kernel object file system */
-#define        MNTTYPE_SHAREFS "sharefs"       /* Kernel sharetab file system */
-
+#define        MOUNT_SUCCESS   0x00            /* Success */
+#define        MOUNT_USAGE     0x01            /* Invalid invocation or permissions */
+#define        MOUNT_SYSERR    0x02            /* System error (ENOMEM, etc) */
+#define        MOUNT_SOFTWARE  0x04            /* Internal mount bug */
+#define        MOUNT_USER      0x08            /* Interrupted by user (EINTR) */
+#define        MOUNT_FILEIO    0x10            /* Error updating/locking /etc/mtab */
+#define        MOUNT_FAIL      0x20            /* Mount failed */
+#define        MOUNT_SOMEOK    0x40            /* At least on mount succeeded */
 
-#define        MNTOPT_RO       "ro"            /* Read only */
-#define        MNTOPT_RW       "rw"            /* Read/write */
-#define        MNTOPT_RQ       "rq"            /* Read/write with quotas */
-#define        MNTOPT_QUOTA    "quota"         /* Check quotas */
-#define        MNTOPT_NOQUOTA  "noquota"       /* Don't check quotas */
-#define        MNTOPT_ONERROR  "onerror"       /* action to taken on error */
-#define        MNTOPT_SOFT     "soft"          /* Soft mount */
-#define        MNTOPT_SEMISOFT "semisoft"      /* partial soft, uncommited interface */
-#define        MNTOPT_HARD     "hard"          /* Hard mount */
-#define        MNTOPT_SUID     "suid"          /* Both setuid and devices allowed */
-#define        MNTOPT_NOSUID   "nosuid"        /* Neither setuid nor devices allowed */
-#define        MNTOPT_DEVICES  "devices"       /* Device-special allowed */
-#define        MNTOPT_NODEVICES        "nodevices"     /* Device-special disallowed */
-#define        MNTOPT_SETUID   "setuid"        /* Set uid allowed */
-#define        MNTOPT_NOSETUID "nosetuid"      /* Set uid not allowed */
-#define        MNTOPT_GRPID    "grpid"         /* SysV-compatible gid on create */
-#define        MNTOPT_REMOUNT  "remount"       /* Change mount options */
-#define        MNTOPT_NOSUB    "nosub"         /* Disallow mounts on subdirs */
-#define        MNTOPT_MULTI    "multi"         /* Do multi-component lookup */
-#define        MNTOPT_INTR     "intr"          /* Allow NFS ops to be interrupted */
-#define        MNTOPT_NOINTR   "nointr"        /* Don't allow interrupted ops */
-#define        MNTOPT_PORT     "port"          /* NFS server IP port number */
-#define        MNTOPT_SECURE   "secure"        /* Secure (AUTH_DES) mounting */
-#define        MNTOPT_RSIZE    "rsize"         /* Max NFS read size (bytes) */
-#define        MNTOPT_WSIZE    "wsize"         /* Max NFS write size (bytes) */
-#define        MNTOPT_TIMEO    "timeo"         /* NFS timeout (1/10 sec) */
-#define        MNTOPT_RETRANS  "retrans"       /* Max retransmissions (soft mnts) */
-#define        MNTOPT_ACTIMEO  "actimeo"       /* Attr cache timeout (sec) */
-#define        MNTOPT_ACREGMIN "acregmin"      /* Min attr cache timeout (files) */
-#define        MNTOPT_ACREGMAX "acregmax"      /* Max attr cache timeout (files) */
-#define        MNTOPT_ACDIRMIN "acdirmin"      /* Min attr cache timeout (dirs) */
-#define        MNTOPT_ACDIRMAX "acdirmax"      /* Max attr cache timeout (dirs) */
-#define        MNTOPT_NOAC     "noac"          /* Don't cache attributes at all */
-#define        MNTOPT_NOCTO    "nocto"         /* No close-to-open consistency */
-#define        MNTOPT_BG       "bg"            /* Do mount retries in background */
-#define        MNTOPT_FG       "fg"            /* Do mount retries in foreground */
-#define        MNTOPT_RETRY    "retry"         /* Number of mount retries */
-#define        MNTOPT_DEV      "dev"           /* Device id of mounted fs */
-#define        MNTOPT_POSIX    "posix"         /* Get static pathconf for mount */
-#define        MNTOPT_MAP      "map"           /* Automount map */
-#define        MNTOPT_DIRECT   "direct"        /* Automount   direct map mount */
-#define        MNTOPT_INDIRECT "indirect"      /* Automount indirect map mount */
-#define        MNTOPT_LLOCK    "llock"         /* Local locking (no lock manager) */
-#define        MNTOPT_IGNORE   "ignore"        /* Ignore this entry */
-#define        MNTOPT_VERS     "vers"          /* protocol version number indicator */
-#define        MNTOPT_PROTO    "proto"         /* protocol network_id indicator */
-#define        MNTOPT_SEC      "sec"           /* Security flavor indicator */
-#define        MNTOPT_SYNCDIR  "syncdir"       /* Synchronous local directory ops */
-#define        MNTOPT_NOSETSEC "nosec"         /* Do no allow setting sec attrs */
-#define        MNTOPT_NOPRINT  "noprint"       /* Do not print messages */
-#define        MNTOPT_LARGEFILES "largefiles"  /* allow large files */
-#define        MNTOPT_NOLARGEFILES "nolargefiles" /* don't allow large files */
-#define        MNTOPT_FORCEDIRECTIO "forcedirectio" /* Force DirectIO on all files */
-#define        MNTOPT_NOFORCEDIRECTIO "noforcedirectio" /* No Force DirectIO */
-#define        MNTOPT_DISABLEDIRECTIO "disabledirectio" /* Disable DirectIO ioctls */
-#define        MNTOPT_PUBLIC   "public"        /* Use NFS public file handlee */
-#define        MNTOPT_LOGGING "logging"        /* enable logging */
-#define        MNTOPT_NOLOGGING "nologging"    /* disable logging */
+#define        MNTOPT_ASYNC    "async"         /* all I/O is asynchronous */
 #define        MNTOPT_ATIME    "atime"         /* update atime for files */
-#define        MNTOPT_NOATIME  "noatime"       /* do not update atime for files */
-#define        MNTOPT_GLOBAL   "global"        /* Cluster-wide global mount */
-#define        MNTOPT_NOGLOBAL "noglobal"      /* Mount local to single node */
-#define        MNTOPT_DFRATIME "dfratime"      /* Deferred access time updates */
-#define        MNTOPT_NODFRATIME "nodfratime"  /* No Deferred access time updates */
-#define        MNTOPT_NBMAND   "nbmand"        /* allow non-blocking mandatory locks */
-#define        MNTOPT_NONBMAND "nonbmand"      /* deny non-blocking mandatory locks */
-#define        MNTOPT_XATTR    "xattr"         /* enable extended attributes */
-#define        MNTOPT_NOXATTR  "noxattr"       /* disable extended attributes */
+#define        MNTOPT_NOATIME  "noatime"       /* do not update atime for files */
+#define        MNTOPT_AUTO     "auto"          /* automount */
+#define        MNTOPT_NOAUTO   "noauto"        /* do not automount */
+#define        MNTOPT_CONTEXT  "context"       /* selinux context */
+#define        MNTOPT_FSCONTEXT "fscontext"    /* selinux fscontext */
+#define        MNTOPT_DEFCONTEXT "defcontext"  /* selinux defcontext */
+#define        MNTOPT_ROOTCONTEXT "rootcontext" /* selinux rootcontext */
+#define        MNTOPT_DEFAULTS "defaults"      /* defaults */
+#define        MNTOPT_DEVICES  "dev"           /* device-special allowed */
+#define        MNTOPT_NODEVICES "nodev"        /* device-special disallowed */
+#define        MNTOPT_DIRATIME "diratime"      /* update atime for dirs */
+#define        MNTOPT_NODIRATIME "nodiratime"  /* do not update atime for dirs */
+#define        MNTOPT_DIRSYNC  "dirsync"       /* do dir updates synchronously */
 #define        MNTOPT_EXEC     "exec"          /* enable executables */
 #define        MNTOPT_NOEXEC   "noexec"        /* disable executables */
-#define        MNTOPT_RESTRICT "restrict"      /* restricted autofs mount */
-#define        MNTOPT_BROWSE   "browse"        /* browsable autofs mount */
-#define        MNTOPT_NOBROWSE "nobrowse"      /* non-browsable autofs mount */
-
-#ifdef __cplusplus
-}
-#endif
+#define        MNTOPT_GROUP    "group"         /* allow group mount */
+#define        MNTOPT_NOGROUP  "nogroup"       /* do not allow group mount */
+#define        MNTOPT_IVERSION "iversion"      /* update inode version */
+#define        MNTOPT_NOIVERSION "noiversion"  /* do not update inode version */
+#define        MNTOPT_NBMAND   "mand"          /* allow non-blocking mandatory locks */
+#define        MNTOPT_NONBMAND "nomand"        /* deny non-blocking mandatory locks */
+#define        MNTOPT_NETDEV   "_netdev"       /* network device */
+#define        MNTOPT_NOFAIL   "nofail"        /* no failure */
+#define        MNTOPT_RELATIME "relatime"      /* allow relative time updates */
+#define        MNTOPT_NORELATIME "norelatime"  /* do not allow relative time updates */
+#define        MNTOPT_DFRATIME "strictatime"   /* Deferred access time updates */
+#define        MNTOPT_NODFRATIME "nostrictatime" /* No Deferred access time updates */
+#define        MNTOPT_SETUID   "suid"          /* Both setuid and devices allowed */
+#define        MNTOPT_NOSETUID "nosuid"        /* Neither setuid nor devices allowed */
+#define        MNTOPT_OWNER    "owner"         /* allow owner mount */
+#define        MNTOPT_NOOWNER  "noowner"       /* do not allow owner mount */
+#define        MNTOPT_REMOUNT  "remount"       /* change mount options */
+#define        MNTOPT_RO       "ro"            /* read only */
+#define        MNTOPT_RW       "rw"            /* read/write */
+#define        MNTOPT_SYNC     "sync"          /* all I/O is synchronous */
+#define        MNTOPT_USER     "user"          /* allow user mount */
+#define        MNTOPT_NOUSER   "nouser"        /* do not allow user mount */
+#define        MNTOPT_USERS    "users"         /* allow user mount */
+#define        MNTOPT_NOUSERS  "nousers"       /* do not allow user mount */
+#define        MNTOPT_SUB      "sub"           /* allow mounts on subdirs */
+#define        MNTOPT_NOSUB    "nosub"         /* do not allow mounts on subdirs */
+#define        MNTOPT_QUIET    "quiet"         /* quiet mount */
+#define        MNTOPT_LOUD     "loud"          /* verbose mount */
+#define        MNTOPT_BIND     "bind"          /* remount part of a tree */
+#define        MNTOPT_RBIND    "rbind"         /* include subtrees */
+#define        MNTOPT_XATTR    "user_xattr"    /* enable extended attributes */
+#define        MNTOPT_NOXATTR  "nouser_xattr"  /* disable extended attributes */
+#define        MNTOPT_COMMENT  "comment"       /* comment */
+#define        MNTOPT_BOOTWAIT "bootwait"
+#define        MNTOPT_NOBOOTWAIT "nobootwait"
+#define        MNTOPT_OPTIONAL "optional"
+#define        MNTOPT_SHOWTHROUGH "showthrough"
+#define        MNTOPT_ZFSUTIL  "zfsutil"       /* called by zfs utility */
 
 #endif /* _SYS_MNTENT_H */
index 70f1449..a30549a 100644 (file)
 
 #ifdef MNTTAB
 #undef MNTTAB
-#endif
+#endif /* MNTTAB */
 
-#define MNTTAB "/proc/mounts"
-#define MNT_LINE_MAX 1024
+#define        MNTTAB          "/etc/mtab"
+#define        MNT_LINE_MAX    1024
 
-#define MNT_TOOLONG 1    /* entry exceeds MNT_LINE_MAX */
-#define MNT_TOOMANY 2    /* too many fields in line */
-#define MNT_TOOFEW  3    /* too few fields in line */
+#define        MNT_TOOLONG     1       /* entry exceeds MNT_LINE_MAX */
+#define        MNT_TOOMANY     2       /* too many fields in line */
+#define        MNT_TOOFEW      3       /* too few fields in line */
 
 struct mnttab {
        char *mnt_special;
index 144f915..9eb893f 100644 (file)
 #define BLKGETSIZE64           _IOR(0x12, 114, size_t)
 #endif
 
-#define MS_FORCE               MNT_FORCE
-#define MS_OVERLAY             32768
-#define MS_NOMNTTAB            0         /* Not supported in Linux */
-#define MS_OPTIONSTR           0         /* Not necessary in Linux */
+/*
+ * Some old glibc headers don't correctly define MS_DIRSYNC and
+ * instead use the enum name S_WRITE.  When using these older
+ * headers define MS_DIRSYNC to be S_WRITE.
+ */
+#if !defined(MS_DIRSYNC)
+#define MS_DIRSYNC             S_WRITE
+#endif
+
+#define        MS_USERS        0x40000000
+#define        MS_OWNER        0x10000000
+#define        MS_GROUP        0x08000000
+#define        MS_COMMENT      0x02000000
+#define        MS_FORCE        MNT_FORCE
+#define        MS_DETACH       MNT_DETACH
 
 #endif /* _LIBSPL_SYS_MOUNT_H */
index 858e388..d787d8a 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -165,6 +168,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 1cdbb57..f3950b9 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -165,6 +168,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 1f431da..64bfe39 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -190,6 +193,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index e600ba4..6b0525e 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -192,6 +195,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 70210c3..f6b0b05 100644 (file)
@@ -6,7 +6,7 @@ DEFAULT_INCLUDES += \
 
 lib_LTLIBRARIES = libzfs.la
 
-libzfs_la_LDFLAGS = -lm
+libzfs_la_LDFLAGS = -lm -ldl $(LIBSELINUX)
 
 libzfs_la_LIBADD = \
        $(top_builddir)/lib/libefi/libefi.la \
index 741f39d..e10cd80 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -197,6 +200,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -314,7 +318,7 @@ AM_CFLAGS = -Wall -Wstrict-prototypes -fno-strict-aliasing \
        -D_POSIX_PTHREAD_SEMANTICS -D_FILE_OFFSET_BITS=64 \
        -D_LARGEFILE64_SOURCE -DTEXT_DOMAIN=\"zfs-linux-user\"
 lib_LTLIBRARIES = libzfs.la
-libzfs_la_LDFLAGS = -lm
+libzfs_la_LDFLAGS = -lm -ldl $(LIBSELINUX)
 libzfs_la_LIBADD = \
        $(top_builddir)/lib/libefi/libefi.la \
        $(top_builddir)/lib/libuutil/libuutil.la
index 6f067d5..0bcfc04 100644 (file)
@@ -93,7 +93,6 @@ struct prop_changelist {
 int
 changelist_prefix(prop_changelist_t *clp)
 {
-#ifdef HAVE_ZPL
        prop_changenode_t *cn;
        int ret = 0;
 
@@ -142,9 +141,6 @@ changelist_prefix(prop_changelist_t *clp)
                (void) changelist_postfix(clp);
 
        return (ret);
-#else
-       return 0;
-#endif  /* HAVE_ZPL */
 }
 
 /*
@@ -159,7 +155,6 @@ changelist_prefix(prop_changelist_t *clp)
 int
 changelist_postfix(prop_changelist_t *clp)
 {
-#ifdef HAVE_ZPL
        prop_changenode_t *cn;
        char shareopts[ZFS_MAXPROPLEN];
        int errors = 0;
@@ -260,9 +255,6 @@ changelist_postfix(prop_changelist_t *clp)
        }
 
        return (errors ? -1 : 0);
-#else
-       return 0;
-#endif  /* HAVE_ZPL */
 }
 
 /*
@@ -325,7 +317,6 @@ changelist_rename(prop_changelist_t *clp, const char *src, const char *dst)
 int
 changelist_unshare(prop_changelist_t *clp, zfs_share_proto_t *proto)
 {
-#ifdef HAVE_ZPL
        prop_changenode_t *cn;
        int ret = 0;
 
@@ -340,9 +331,6 @@ changelist_unshare(prop_changelist_t *clp, zfs_share_proto_t *proto)
        }
 
        return (ret);
-#else
-       return 0;
-#endif
 }
 
 /*
index d876e5d..378bbc7 100644 (file)
@@ -995,7 +995,6 @@ badlabel:
 
                        /*FALLTHRU*/
 
-#ifdef HAVE_ZPL
                case ZFS_PROP_SHARESMB:
                case ZFS_PROP_SHARENFS:
                        /*
@@ -1106,7 +1105,6 @@ badlabel:
                        }
 
                        break;
-#endif /* HAVE_ZPL */
                case ZFS_PROP_UTF8ONLY:
                        chosen_utf = (int)intval;
                        break;
@@ -1600,7 +1598,7 @@ zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
  * zfs_prop_get_int() are built using this interface.
  *
  * Certain properties can be overridden using 'mount -o'.  In this case, scan
- * the contents of the /etc/mnttab entry, searching for the appropriate options.
+ * the contents of the /etc/mtab entry, searching for the appropriate options.
  * If they differ from the on-disk values, report the current values and mark
  * the source "temporary".
  */
@@ -1658,7 +1656,7 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
 
        /*
         * Because looking up the mount options is potentially expensive
-        * (iterating over all of /etc/mnttab), we defer its calculation until
+        * (iterating over all of /etc/mtab), we defer its calculation until
         * we're looking up a property which requires its presence.
         */
        if (!zhp->zfs_mntcheck &&
@@ -2745,7 +2743,6 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
                        goto ancestorerr;
                }
 
-#ifdef HAVE_ZPL
                if (zfs_mount(h, NULL, 0) != 0) {
                        opname = dgettext(TEXT_DOMAIN, "mount");
                        goto ancestorerr;
@@ -2755,7 +2752,6 @@ create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
                        opname = dgettext(TEXT_DOMAIN, "share");
                        goto ancestorerr;
                }
-#endif /* HAVE_ZPL */
 
                zfs_close(h);
        }
@@ -4037,28 +4033,6 @@ zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
        return (0);
 }
 
-#ifdef HAVE_ZPL
-int
-zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
-    char *resource, void *export, void *sharetab,
-    int sharemax, zfs_share_op_t operation)
-{
-       zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 };
-       int error;
-
-       (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
-       (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
-       if (resource)
-               (void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
-       zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
-       zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
-       zc.zc_share.z_sharetype = operation;
-       zc.zc_share.z_sharemax = sharemax;
-       error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
-       return (error);
-}
-#endif /* HAVE_ZPL */
-
 void
 zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
 {
index 8668583..7048a52 100644 (file)
@@ -1078,6 +1078,10 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
                         * parport* - Parallel port interface.
                         * lp*      - Printer interface.
                         * fd*      - Floppy interface.
+                        * hpet     - High Precision Event Timer, crashes qemu
+                        *            when accessed from a virtual machine.
+                        * core     - Symlink to /proc/kcore, causes a crash
+                        *            when access from Xen dom0.
                         */
                        if ((strncmp(name, "watchdog", 8) == 0) ||
                            (strncmp(name, "fuse", 4) == 0)     ||
@@ -1087,22 +1091,21 @@ zpool_find_import_impl(libzfs_handle_t *hdl, importargs_t *iarg)
                            (strncmp(name, "parport", 7) == 0)  ||
                            (strncmp(name, "lp", 2) == 0)       ||
                            (strncmp(name, "fd", 2) == 0)       ||
-                           (strncmp(name, "hpet", 4) == 0))
-                               continue;
-
-                       if ((fd = openat64(dfd, name, O_RDONLY)) < 0)
+                           (strncmp(name, "hpet", 4) == 0)     ||
+                           (strncmp(name, "core", 4) == 0))
                                continue;
 
                        /*
                         * Ignore failed stats.  We only want regular
-                        * files and block devs.
+                        * files and block devices.
                         */
-                       if (fstat64(fd, &statbuf) != 0 ||
+                       if ((fstatat64(dfd, name, &statbuf, 0) != 0) ||
                            (!S_ISREG(statbuf.st_mode) &&
-                           !S_ISBLK(statbuf.st_mode))) {
-                               (void) close(fd);
+                           !S_ISBLK(statbuf.st_mode)))
+                               continue;
+
+                       if ((fd = openat64(dfd, name, O_RDONLY)) < 0)
                                continue;
-                       }
 
                        if ((zpool_read_label(fd, &config)) != 0) {
                                (void) close(fd);
index 4b9038d..f8f12d1 100644 (file)
@@ -72,6 +72,9 @@
 #include <sys/mntent.h>
 #include <sys/mount.h>
 #include <sys/stat.h>
+#ifdef HAVE_LIBSELINUX
+#include <selinux/selinux.h>
+#endif /* HAVE_LIBSELINUX */
 
 #include <libzfs.h>
 
@@ -81,7 +84,6 @@
 #include <sys/systeminfo.h>
 #define        MAXISALEN       257     /* based on sysinfo(2) man page */
 
-#ifdef HAVE_ZPL
 static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *);
 zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **,
     zfs_share_proto_t);
@@ -118,20 +120,21 @@ zfs_share_proto_t share_all_proto[] = {
 };
 
 /*
- * Search the sharetab for the given mountpoint and protocol, returning
+ * Search for NFS and SMB exports for the given mountpoint and protocol, returning
  * a zfs_share_type_t value.
  */
 static zfs_share_type_t
 is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto)
 {
        char buf[MAXPATHLEN], *tab;
-       char *ptr;
 
        if (hdl->libzfs_sharetab == NULL)
                return (SHARED_NOT_SHARED);
 
        (void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET);
 
+       /* Search /etc/exports for NFS exports */
+       /* FIXME: Assumes the file is tab delimited. */
        while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) {
 
                /* the mountpoint is the first entry on each line */
@@ -140,31 +143,15 @@ is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto)
 
                *tab = '\0';
                if (strcmp(buf, mountpoint) == 0) {
-                       /*
-                        * the protocol field is the third field
-                        * skip over second field
-                        */
-                       ptr = ++tab;
-                       if ((tab = strchr(ptr, '\t')) == NULL)
-                               continue;
-                       ptr = ++tab;
-                       if ((tab = strchr(ptr, '\t')) == NULL)
-                               continue;
-                       *tab = '\0';
-                       if (strcmp(ptr,
-                           proto_table[proto].p_name) == 0) {
-                               switch (proto) {
-                               case PROTO_NFS:
-                                       return (SHARED_NFS);
-                               case PROTO_SMB:
-                                       return (SHARED_SMB);
-                               default:
-                                       return (0);
-                               }
-                       }
+                       if (proto == PROTO_NFS)
+                               return (SHARED_NFS);
+                       else
+                               return (SHARED_NOT_SHARED);
                }
        }
 
+       /* XXX: Search /etc/samba/smb.conf for SMB exports, return SHARED_SMB */
+
        return (SHARED_NOT_SHARED);
 }
 
@@ -256,6 +243,82 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen,
 }
 
 /*
+ * The filesystem is mounted by invoking the system mount utility rather
+ * than by the system call mount(2).  This ensures that the /etc/mtab
+ * file is correctly locked for the update.  Performing our own locking
+ * and /etc/mtab update requires making an unsafe assumption about how
+ * the mount utility performs its locking.  Unfortunately, this also means
+ * in the case of a mount failure we do not have the exact errno.  We must
+ * make due with return value from the mount process.
+ *
+ * In the long term a shared library called libmount is under development
+ * which provides a common API to address the locking and errno issues.
+ * Once the standard mount utility has been updated to use this library
+ * we can add an autoconf check to conditionally use it.
+ *
+ * http://www.kernel.org/pub/linux/utils/util-linux/libmount-docs/index.html
+ */
+
+static int
+do_mount(const char *src, const char *mntpt, char *opts)
+{
+       char *argv[8] = {
+           "/bin/mount",
+           "-t", MNTTYPE_ZFS,
+           "-o", opts,
+           (char *)src,
+            (char *)mntpt,
+           (char *)NULL };
+       int rc;
+
+       /* Return only the most critical mount error */
+       rc = libzfs_run_process(argv[0], argv);
+       if (rc) {
+               if (rc & MOUNT_FILEIO)
+                       return EIO;
+               if (rc & MOUNT_USER)
+                       return EINTR;
+               if (rc & MOUNT_SOFTWARE)
+                       return EPIPE;
+               if (rc & MOUNT_SYSERR)
+                       return EAGAIN;
+               if (rc & MOUNT_USAGE)
+                       return EINVAL;
+
+               return ENXIO; /* Generic error */
+       }
+
+       return 0;
+}
+
+static int
+do_unmount(const char *mntpt, int flags)
+{
+       char force_opt[] = "-f";
+       char lazy_opt[] = "-l";
+       char *argv[7] = {
+           "/bin/umount",
+           "-t", MNTTYPE_ZFS,
+           NULL, NULL, NULL, NULL };
+       int rc, count = 3;
+
+       if (flags & MS_FORCE) {
+               argv[count] = force_opt;
+               count++;
+       }
+
+       if (flags & MS_DETACH) {
+               argv[count] = lazy_opt;
+               count++;
+       }
+
+       argv[count] = (char *)mntpt;
+       rc = libzfs_run_process(argv[0], argv);
+
+       return (rc ? EINVAL : 0);
+}
+
+/*
  * Mount the given filesystem.
  */
 int
@@ -265,9 +328,10 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
        char mountpoint[ZFS_MAXPROPLEN];
        char mntopts[MNT_LINE_MAX];
        libzfs_handle_t *hdl = zhp->zfs_hdl;
+       int rc;
 
        if (options == NULL)
-               mntopts[0] = '\0';
+               (void) strlcpy(mntopts, MNTOPT_DEFAULTS, sizeof (mntopts));
        else
                (void) strlcpy(mntopts, options, sizeof (mntopts));
 
@@ -275,7 +339,18 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
         * If the pool is imported read-only then all mounts must be read-only
         */
        if (zpool_get_prop_int(zhp->zpool_hdl, ZPOOL_PROP_READONLY, NULL))
-               flags |= MS_RDONLY;
+               (void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts));
+
+       /*
+        * Append zfsutil option so the mount helper allow the mount
+        */
+       strlcat(mntopts, "," MNTOPT_ZFSUTIL, sizeof (mntopts));
+
+#ifdef HAVE_LIBSELINUX
+       if (is_selinux_enabled())
+               (void) strlcat(mntopts, ",context=\"system_u:"
+                   "object_r:file_t:s0\"", sizeof (mntopts));
+#endif /* HAVE_LIBSELINUX */
 
        if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL))
                return (0);
@@ -293,12 +368,9 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
 
        /*
         * Determine if the mountpoint is empty.  If so, refuse to perform the
-        * mount.  We don't perform this check if MS_OVERLAY is specified, which
-        * would defeat the point.  We also avoid this check if 'remount' is
-        * specified.
+        * mount.  We don't perform this check if 'remount' is specified.
         */
-       if ((flags & MS_OVERLAY) == 0 &&
-           strstr(mntopts, MNTOPT_REMOUNT) == NULL &&
+       if (strstr(mntopts, MNTOPT_REMOUNT) == NULL &&
            !dir_is_empty(mountpoint)) {
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                    "directory is not empty"));
@@ -307,20 +379,20 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
        }
 
        /* perform the mount */
-       if (mount(zfs_get_name(zhp), mountpoint, MS_OPTIONSTR | flags,
-           MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) {
+       rc = do_mount(zfs_get_name(zhp), mountpoint, mntopts);
+       if (rc) {
                /*
                 * Generic errors are nasty, but there are just way too many
                 * from mount(), and they're well-understood.  We pick a few
                 * common ones to improve upon.
                 */
-               if (errno == EBUSY) {
+               if (rc == EBUSY) {
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "mountpoint or dataset is busy"));
-               } else if (errno == EPERM) {
+               } else if (rc == EPERM) {
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                            "Insufficient privileges"));
-               } else if (errno == ENOTSUP) {
+               } else if (rc == ENOTSUP) {
                        char buf[256];
                        int spa_version;
 
@@ -333,7 +405,7 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
                            ZFS_PROP_VERSION), spa_version);
                        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, buf));
                } else {
-                       zfs_error_aux(hdl, strerror(errno));
+                       zfs_error_aux(hdl, strerror(rc));
                }
                return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED,
                    dgettext(TEXT_DOMAIN, "cannot mount '%s'"),
@@ -341,8 +413,7 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
        }
 
        /* add the mounted entry into our cache */
-       libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint,
-           mntopts);
+       libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint, mntopts);
        return (0);
 }
 
@@ -352,7 +423,7 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags)
 static int
 unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags)
 {
-       if (umount2(mountpoint, flags) != 0) {
+       if (do_unmount(mountpoint, flags) != 0) {
                zfs_error_aux(hdl, strerror(errno));
                return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED,
                    dgettext(TEXT_DOMAIN, "cannot unmount '%s'"),
@@ -467,7 +538,7 @@ zfs_is_shared_proto(zfs_handle_t *zhp, char **where, zfs_share_proto_t proto)
        if (!zfs_is_mounted(zhp, &mountpoint))
                return (SHARED_NOT_SHARED);
 
-       if (rc = is_shared(zhp->zfs_hdl, mountpoint, proto)) {
+       if ((rc = is_shared(zhp->zfs_hdl, mountpoint, proto))) {
                if (where != NULL)
                        *where = mountpoint;
                else
@@ -721,11 +792,14 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto)
                return (0);
 
        if ((ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) {
+#ifdef HAVE_SHARE
                (void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED,
                    dgettext(TEXT_DOMAIN, "cannot share '%s': %s"),
                    zfs_get_name(zhp), _sa_errorstr != NULL ?
                    _sa_errorstr(ret) : "");
                return (-1);
+#endif /* HAVE_SHARE */
+               return (0);
        }
 
        for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) {
@@ -1138,7 +1212,7 @@ mountpoint_compare(const void *a, const void *b)
  * Unshare and unmount all datasets within the given pool.  We don't want to
  * rely on traversing the DSL to discover the filesystems within the pool,
  * because this may be expensive (if not all of them are mounted), and can fail
- * arbitrarily (on I/O error, for example).  Instead, we walk /etc/mnttab and
+ * arbitrarily (on I/O error, for example).  Instead, we walk /etc/mtab and
  * gather all the filesystems that are currently mounted.
  */
 int
@@ -1269,53 +1343,3 @@ out:
 
        return (ret);
 }
-
-#else  /* HAVE_ZPL */
-
-int
-zfs_unshare_iscsi(zfs_handle_t *zhp)
-{
-       return 0;
-}
-
-int
-zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags)
-{
-       return 0;
-}
-
-void
-remove_mountpoint(zfs_handle_t *zhp) {
-       return;
-}
-
-boolean_t
-is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where)
-{
-       return B_FALSE;
-}
-
-boolean_t
-zfs_is_mounted(zfs_handle_t *zhp, char **where)
-{
-       return is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where);
-}
-
-boolean_t
-zfs_is_shared(zfs_handle_t *zhp)
-{
-       return B_FALSE;
-}
-
-int
-zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
-{
-       return B_FALSE;
-}
-
-int
-zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
-{
-       return B_FALSE;
-}
-#endif /* HAVE_ZPL */
index 33c440c..163cd16 100644 (file)
@@ -631,7 +631,7 @@ libzfs_module_loaded(const char *module)
        return result;
 }
 
-static int
+int
 libzfs_run_process(const char *path, char *argv[])
 {
        pid_t pid;
@@ -657,13 +657,14 @@ libzfs_run_process(const char *path, char *argv[])
        return -1;
 }
 
-static int
+int
 libzfs_load_module(const char *module)
 {
        char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0};
 
        if (libzfs_module_loaded(module))
                return 0;
+
        return libzfs_run_process("/sbin/modprobe", argv);
 }
 
@@ -726,9 +727,7 @@ libzfs_fini(libzfs_handle_t *hdl)
 #endif
        if (hdl->libzfs_sharetab)
                (void) fclose(hdl->libzfs_sharetab);
-#ifdef HAVE_ZPL
        zfs_uninit_libshare(hdl);
-#endif
        if (hdl->libzfs_log_str)
                (void) free(hdl->libzfs_log_str);
        zpool_free_handles(hdl);
index 388b631..b15830d 100644 (file)
@@ -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 \
@@ -97,7 +98,6 @@ libzpool_la_LDFLAGS = -pthread
 EXTRA_DIST = \
        $(top_srcdir)/module/zfs/vdev_disk.c \
        $(top_srcdir)/module/zfs/zfs_acl.c \
-       $(top_srcdir)/module/zfs/zfs_ctldir.c \
        $(top_srcdir)/module/zfs/zfs_dir.c \
        $(top_srcdir)/module/zfs/zfs_ioctl.c \
        $(top_srcdir)/module/zfs/zfs_log.c \
@@ -106,5 +106,9 @@ EXTRA_DIST = \
        $(top_srcdir)/module/zfs/zfs_rlock.c \
        $(top_srcdir)/module/zfs/zfs_vfsops.c \
        $(top_srcdir)/module/zfs/zfs_vnops.c \
+       $(top_srcdir)/module/zfs/zpl_file.c \
+       $(top_srcdir)/module/zfs/zpl_inode.c \
+       $(top_srcdir)/module/zfs/zpl_super.c \
+       $(top_srcdir)/module/zfs/zpl_xattr.c \
        $(top_srcdir)/module/zfs/zvol.c \
        $(top_srcdir)/module/zpios/pios.c
index 99ad719..96bced0 100644 (file)
@@ -52,21 +52,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -105,10 +108,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 \
@@ -211,6 +214,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
@@ -343,6 +347,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 \
@@ -417,7 +422,6 @@ libzpool_la_LDFLAGS = -pthread
 EXTRA_DIST = \
        $(top_srcdir)/module/zfs/vdev_disk.c \
        $(top_srcdir)/module/zfs/zfs_acl.c \
-       $(top_srcdir)/module/zfs/zfs_ctldir.c \
        $(top_srcdir)/module/zfs/zfs_dir.c \
        $(top_srcdir)/module/zfs/zfs_ioctl.c \
        $(top_srcdir)/module/zfs/zfs_log.c \
@@ -426,6 +430,10 @@ EXTRA_DIST = \
        $(top_srcdir)/module/zfs/zfs_rlock.c \
        $(top_srcdir)/module/zfs/zfs_vfsops.c \
        $(top_srcdir)/module/zfs/zfs_vnops.c \
+       $(top_srcdir)/module/zfs/zpl_file.c \
+       $(top_srcdir)/module/zfs/zpl_inode.c \
+       $(top_srcdir)/module/zfs/zpl_super.c \
+       $(top_srcdir)/module/zfs/zpl_xattr.c \
        $(top_srcdir)/module/zfs/zvol.c \
        $(top_srcdir)/module/zpios/pios.c
 
@@ -570,6 +578,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@
@@ -669,6 +678,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
index c18b275..c209c29 100644 (file)
@@ -50,21 +50,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -178,6 +181,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 8cace2c..0a8d529 100644 (file)
@@ -50,21 +50,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index ecde1d9..a7404e6 100644 (file)
@@ -302,19 +302,19 @@ The clone parent-child dependency relationship can be reversed by using the \fBp
 .SS "Mount Points"
 .sp
 .LP
-Creating a \fBZFS\fR file system is a simple operation, so the number of file systems per system is likely to be numerous. To cope with this, \fBZFS\fR automatically manages mounting and unmounting file systems without the need to edit the \fB/etc/vfstab\fR file. All automatically managed file systems are mounted by \fBZFS\fR at boot time.
+Creating a \fBZFS\fR file system is a simple operation, so the number of file systems per system is likely to be numerous. To cope with this, \fBZFS\fR automatically manages mounting and unmounting file systems without the need to edit the \fB/etc/fstab\fR file. All automatically managed file systems are mounted by \fBZFS\fR at boot time.
 .sp
 .LP
 By default, file systems are mounted under \fB/\fIpath\fR\fR, where \fIpath\fR is the name of the file system in the \fBZFS\fR namespace. Directories are created and destroyed as needed.
 .sp
 .LP
-A file system can also have a mount point set in the \fBmountpoint\fR property. This directory is created as needed, and \fBZFS\fR automatically mounts the file system when the \fBzfs mount -a\fR command is invoked (without editing \fB/etc/vfstab\fR). The \fBmountpoint\fR property can be inherited, so if \fBpool/home\fR has a mount point of \fB/export/stuff\fR, then \fBpool/home/user\fR automatically inherits a mount point of \fB/export/stuff/user\fR.
+A file system can also have a mount point set in the \fBmountpoint\fR property. This directory is created as needed, and \fBZFS\fR automatically mounts the file system when the \fBzfs mount -a\fR command is invoked (without editing \fB/etc/fstab\fR). The \fBmountpoint\fR property can be inherited, so if \fBpool/home\fR has a mount point of \fB/export/stuff\fR, then \fBpool/home/user\fR automatically inherits a mount point of \fB/export/stuff/user\fR.
 .sp
 .LP
 A file system \fBmountpoint\fR property of \fBnone\fR prevents the file system from being mounted.
 .sp
 .LP
-If needed, \fBZFS\fR file systems can also be managed with traditional tools (\fBmount\fR, \fBumount\fR, \fB/etc/vfstab\fR). If a file system's mount point is set to \fBlegacy\fR, \fBZFS\fR makes no attempt to manage the file system, and the administrator is responsible for mounting and unmounting the file system.
+If needed, \fBZFS\fR file systems can also be managed with traditional tools (\fBmount\fR, \fBumount\fR, \fB/etc/fstab\fR). If a file system's mount point is set to \fBlegacy\fR, \fBZFS\fR makes no attempt to manage the file system, and the administrator is responsible for mounting and unmounting the file system.
 .SS "Zones"
 .sp
 .LP
index ee4864f..e564b77 100644 (file)
@@ -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 (file)
index 0000000..9904645
--- /dev/null
@@ -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 */
index 71dbb39..5a99852 100644 (file)
@@ -64,7 +64,6 @@ $(MODULE)-objs += @top_srcdir@/module/zfs/zap_leaf.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zap_micro.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zfs_acl.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zfs_byteswap.o
-$(MODULE)-objs += @top_srcdir@/module/zfs/zfs_ctldir.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zfs_debug.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zfs_dir.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zfs_fm.o
@@ -84,5 +83,9 @@ $(MODULE)-objs += @top_srcdir@/module/zfs/zio_checksum.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zio_compress.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zio_inject.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zle.o
+$(MODULE)-objs += @top_srcdir@/module/zfs/zpl_file.o
+$(MODULE)-objs += @top_srcdir@/module/zfs/zpl_inode.o
+$(MODULE)-objs += @top_srcdir@/module/zfs/zpl_super.o
+$(MODULE)-objs += @top_srcdir@/module/zfs/zpl_xattr.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zrlock.o
 $(MODULE)-objs += @top_srcdir@/module/zfs/zvol.o
index 32d99bf..808c8e8 100644 (file)
@@ -2149,7 +2149,7 @@ arc_reclaim_thread(void)
 
                /* block until needed, or one second, whichever is shorter */
                CALLB_CPR_SAFE_BEGIN(&cpr);
-               (void) cv_timedwait(&arc_reclaim_thr_cv,
+               (void) cv_timedwait_interruptible(&arc_reclaim_thr_cv,
                    &arc_reclaim_thr_lock, (ddi_get_lbolt() + hz));
                CALLB_CPR_SAFE_END(&cpr, &arc_reclaim_thr_lock);
        }
@@ -4435,8 +4435,8 @@ l2arc_feed_thread(void)
 
        while (l2arc_thread_exit == 0) {
                CALLB_CPR_SAFE_BEGIN(&cpr);
-               (void) cv_timedwait(&l2arc_feed_thr_cv, &l2arc_feed_thr_lock,
-                   next);
+               (void) cv_timedwait_interruptible(&l2arc_feed_thr_cv,
+                   &l2arc_feed_thr_lock, next);
                CALLB_CPR_SAFE_END(&cpr, &l2arc_feed_thr_lock);
                next = ddi_get_lbolt() + hz;
 
index aaeec41..04b02c7 100644 (file)
@@ -381,7 +381,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
                }
                nblks = 1;
        }
-       dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_SLEEP);
+       dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_SLEEP | KM_NODEBUG);
 
        if (dn->dn_objset->os_dsl_dataset)
                dp = dn->dn_objset->os_dsl_dataset->ds_dir->dd_pool;
@@ -1122,75 +1122,82 @@ dmu_write_req(objset_t *os, uint64_t object, struct request *req, dmu_tx_t *tx)
        dmu_buf_rele_array(dbp, numbufs, FTAG);
        return (err);
 }
-#endif
 
-#ifdef HAVE_ZPL
 int
-dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
-    dmu_tx_t *tx)
+dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
 {
-       dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
-       dnode_t *dn;
-       int err;
-
-       if (size == 0)
-               return (0);
+       dmu_buf_t **dbp;
+       int numbufs, i, err;
+       xuio_t *xuio = NULL;
 
-       DB_DNODE_ENTER(db);
-       dn = DB_DNODE(db);
-       err = dmu_write_uio_dnode(dn, uio, size, tx);
-       DB_DNODE_EXIT(db);
+       /*
+        * NB: we could do this block-at-a-time, but it's nice
+        * to be reading in parallel.
+        */
+       err = dmu_buf_hold_array(os, object, uio->uio_loffset, size, TRUE, FTAG,
+           &numbufs, &dbp);
+       if (err)
+               return (err);
 
-       return (err);
-}
+       for (i = 0; i < numbufs; i++) {
+               int tocpy;
+               int bufoff;
+               dmu_buf_t *db = dbp[i];
 
-int
-dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size,
-    dmu_tx_t *tx)
-{
-       dnode_t *dn;
-       int err;
+               ASSERT(size > 0);
 
-       if (size == 0)
-               return (0);
+               bufoff = uio->uio_loffset - db->db_offset;
+               tocpy = (int)MIN(db->db_size - bufoff, size);
 
-       err = dnode_hold(os, object, FTAG, &dn);
-       if (err)
-               return (err);
+               if (xuio) {
+                       dmu_buf_impl_t *dbi = (dmu_buf_impl_t *)db;
+                       arc_buf_t *dbuf_abuf = dbi->db_buf;
+                       arc_buf_t *abuf = dbuf_loan_arcbuf(dbi);
+                       err = dmu_xuio_add(xuio, abuf, bufoff, tocpy);
+                       if (!err) {
+                               uio->uio_resid -= tocpy;
+                               uio->uio_loffset += tocpy;
+                       }
 
-       err = dmu_write_uio_dnode(dn, uio, size, tx);
+                       if (abuf == dbuf_abuf)
+                               XUIOSTAT_BUMP(xuiostat_rbuf_nocopy);
+                       else
+                               XUIOSTAT_BUMP(xuiostat_rbuf_copied);
+               } else {
+                       err = uiomove((char *)db->db_data + bufoff, tocpy,
+                           UIO_READ, uio);
+               }
+               if (err)
+                       break;
 
-       dnode_rele(dn, FTAG);
+               size -= tocpy;
+       }
+       dmu_buf_rele_array(dbp, numbufs, FTAG);
 
        return (err);
 }
 
-int
-dmu_write_pages(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
-    page_t *pp, dmu_tx_t *tx)
+static int
+dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
 {
        dmu_buf_t **dbp;
-       int numbufs, i;
-       int err;
-
-       if (size == 0)
-               return (0);
+       int numbufs;
+       int err = 0;
+       int i;
 
-       err = dmu_buf_hold_array(os, object, offset, size,
-           FALSE, FTAG, &numbufs, &dbp);
+       err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size,
+           FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH);
        if (err)
                return (err);
 
        for (i = 0; i < numbufs; i++) {
-               int tocpy, copied, thiscpy;
+               int tocpy;
                int bufoff;
                dmu_buf_t *db = dbp[i];
-               caddr_t va;
 
                ASSERT(size > 0);
-               ASSERT3U(db->db_size, >=, PAGESIZE);
 
-               bufoff = offset - db->db_offset;
+               bufoff = uio->uio_loffset - db->db_offset;
                tocpy = (int)MIN(db->db_size - bufoff, size);
 
                ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);
@@ -1200,26 +1207,68 @@ dmu_write_pages(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
                else
                        dmu_buf_will_dirty(db, tx);
 
-               for (copied = 0; copied < tocpy; copied += PAGESIZE) {
-                       ASSERT3U(pp->p_offset, ==, db->db_offset + bufoff);
-                       thiscpy = MIN(PAGESIZE, tocpy - copied);
-                       va = zfs_map_page(pp, S_READ);
-                       bcopy(va, (char *)db->db_data + bufoff, thiscpy);
-                       zfs_unmap_page(pp, va);
-                       pp = pp->p_next;
-                       bufoff += PAGESIZE;
-               }
+               /*
+                * XXX uiomove could block forever (eg.nfs-backed
+                * pages).  There needs to be a uiolockdown() function
+                * to lock the pages in memory, so that uiomove won't
+                * block.
+                */
+               err = uiomove((char *)db->db_data + bufoff, tocpy,
+                   UIO_WRITE, uio);
 
                if (tocpy == db->db_size)
                        dmu_buf_fill_done(db, tx);
 
-               offset += tocpy;
+               if (err)
+                       break;
+
                size -= tocpy;
        }
+
        dmu_buf_rele_array(dbp, numbufs, FTAG);
        return (err);
 }
-#endif
+
+int
+dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
+    dmu_tx_t *tx)
+{
+       dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
+       dnode_t *dn;
+       int err;
+
+       if (size == 0)
+               return (0);
+
+       DB_DNODE_ENTER(db);
+       dn = DB_DNODE(db);
+       err = dmu_write_uio_dnode(dn, uio, size, tx);
+       DB_DNODE_EXIT(db);
+
+       return (err);
+}
+
+int
+dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size,
+    dmu_tx_t *tx)
+{
+       dnode_t *dn;
+       int err;
+
+       if (size == 0)
+               return (0);
+
+       err = dnode_hold(os, object, FTAG, &dn);
+       if (err)
+               return (err);
+
+       err = dmu_write_uio_dnode(dn, uio, size, tx);
+
+       dnode_rele(dn, FTAG);
+
+       return (err);
+}
+#endif /* _KERNEL */
 
 /*
  * Allocate a loaned anonymous arc buffer.
index 0ff95a6..0703a94 100644 (file)
@@ -910,10 +910,8 @@ dmu_objset_snapshot_one(const char *name, void *arg)
         * permission checks for the starting dataset have already been
         * performed in zfs_secpolicy_snapshot()
         */
-#ifdef HAVE_ZPL
        if (sn->recursive && (err = zfs_secpolicy_snapshot_perms(name, CRED())))
                return (err);
-#endif
 
        err = dmu_objset_hold(name, sn, &os);
        if (err != 0)
index dfccede..c34ac2a 100644 (file)
@@ -2364,13 +2364,11 @@ dsl_snapshot_rename_one(const char *name, void *arg)
         * For recursive snapshot renames the parent won't be changing
         * so we just pass name for both the to/from argument.
         */
-#ifdef HAVE_ZPL
        err = zfs_secpolicy_rename_perms(snapname, snapname, CRED());
        if (err != 0) {
                strfree(snapname);
                return (err == ENOENT ? 0 : err);
        }
-#endif
 
 /* XXX: Ignore for SPL version until mounting the FS is supported */
 #if defined(_KERNEL) && !defined(HAVE_SPL)
index 6a0e363..7185540 100644 (file)
@@ -92,7 +92,7 @@ dsl_pool_open_impl(spa_t *spa, uint64_t txg)
 
        mutex_init(&dp->dp_lock, NULL, MUTEX_DEFAULT, NULL);
 
-       dp->dp_vnrele_taskq = taskq_create("zfs_vn_rele_taskq", 1, minclsyspri,
+       dp->dp_iput_taskq = taskq_create("zfs_iput_taskq", 1, minclsyspri,
            1, 4, 0);
 
        return (dp);
@@ -214,7 +214,7 @@ dsl_pool_close(dsl_pool_t *dp)
        dsl_scan_fini(dp);
        rw_destroy(&dp->dp_config_rwlock);
        mutex_destroy(&dp->dp_lock);
-       taskq_destroy(dp->dp_vnrele_taskq);
+       taskq_destroy(dp->dp_iput_taskq);
        if (dp->dp_blkstats)
                kmem_free(dp->dp_blkstats, sizeof (zfs_all_blkstats_t));
        kmem_free(dp, sizeof (dsl_pool_t));
@@ -738,9 +738,9 @@ dsl_pool_create_origin(dsl_pool_t *dp, dmu_tx_t *tx)
 }
 
 taskq_t *
-dsl_pool_vnrele_taskq(dsl_pool_t *dp)
+dsl_pool_iput_taskq(dsl_pool_t *dp)
 {
-       return (dp->dp_vnrele_taskq);
+       return (dp->dp_iput_taskq);
 }
 
 /*
index ee1140f..c900082 100644 (file)
@@ -1436,7 +1436,6 @@ sa_lookup(sa_handle_t *hdl, sa_attr_type_t attr, void *buf, uint32_t buflen)
 int
 sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, uio_t *uio)
 {
-#ifdef HAVE_ZPL
        int error;
        sa_bulk_attr_t bulk;
 
@@ -1453,9 +1452,6 @@ sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, uio_t *uio)
        }
        mutex_exit(&hdl->sa_lock);
        return (error);
-#else
-       return ENOSYS;
-#endif /* HAVE_ZPL */
 }
 #endif
 
index 79664cb..d84d6b0 100644 (file)
@@ -179,7 +179,6 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
                        (void) vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
                }
                (void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
-               VN_RELE(vp);
        }
 
        (void) vn_remove(temp, UIO_SYSSPACE, RMFILE);
index 3e59bd2..aba3c4a 100644 (file)
@@ -33,6 +33,8 @@
 #include <sys/zio.h>
 #include <sys/sunldi.h>
 
+char *zfs_vdev_scheduler = VDEV_SCHEDULER;
+
 /*
  * Virtual device vector for disks.
  */
@@ -102,6 +104,43 @@ vdev_disk_error(zio_t *zio)
 #endif
 }
 
+/*
+ * Use the Linux 'noop' elevator for zfs managed block devices.  This
+ * strikes the ideal balance by allowing the zfs elevator to do all
+ * request ordering and prioritization.  While allowing the Linux
+ * elevator to do the maximum front/back merging allowed by the
+ * physical device.  This yields the largest possible requests for
+ * the device with the lowest total overhead.
+ *
+ * Unfortunately we cannot directly call the elevator_switch() function
+ * because it is not exported from the block layer.  This means we have
+ * to use the sysfs interface and a user space upcall.  Pools will be
+ * automatically imported on module load so we must do this at device
+ * open time from the kernel.
+ */
+static int
+vdev_elevator_switch(vdev_t *v, char *elevator, char *device)
+{
+       char sh_path[] = "/bin/sh";
+       char sh_cmd[128];
+       char *argv[] = { sh_path, "-c", sh_cmd };
+       char *envp[] = { NULL };
+       int error;
+
+       if (!strncmp(elevator, "none", 4) && (strlen(elevator) == 4))
+               return (0);
+
+       sprintf(sh_cmd, "%s \"%s\" >/sys/block/%s/queue/scheduler",
+           "/bin/echo", elevator, device);
+
+       error = call_usermodehelper(sh_path, argv, envp, 1);
+       if (error)
+               printk("ZFS: Unable to set \"%s\" scheduler for %s (%s): %d\n",
+                   elevator, v->vdev_path, device, error);
+
+       return (error);
+}
+
 static int
 vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
 {
@@ -167,6 +206,10 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *ashift)
        /* Based on the minimum sector size set the block size */
        *ashift = highbit(MAX(block_size, SPA_MINBLOCKSIZE)) - 1;
 
+       /* Try to set the io scheduler elevator algorithm */
+       (void) vdev_elevator_switch(v, zfs_vdev_scheduler,
+           bdev->bd_disk->disk_name);
+
        return 0;
 }
 
@@ -702,3 +745,6 @@ vdev_disk_read_rootlabel(char *devpath, char *devid, nvlist_t **config)
 
        return 0;
 }
+
+module_param(zfs_vdev_scheduler, charp, 0644);
+MODULE_PARM_DESC(zfs_vdev_scheduler, "IO Scheduler (noop)");
index f31389a..bbc85e7 100644 (file)
@@ -130,7 +130,6 @@ vdev_file_close(vdev_t *vd)
                (void) VOP_PUTPAGE(vf->vf_vnode, 0, 0, B_INVAL, kcred, NULL);
                (void) VOP_CLOSE(vf->vf_vnode, spa_mode(vd->vdev_spa), 1, 0,
                    kcred, NULL);
-               VN_RELE(vf->vf_vnode);
        }
 
        vd->vdev_delayed_close = B_FALSE;
index f1ba9af..0ae749e 100644 (file)
@@ -22,7 +22,6 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#ifdef HAVE_ZPL
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -53,7 +52,6 @@
 #include <sys/zap.h>
 #include <sys/sa.h>
 #include "fs/fs_subr.h"
-#include <acl/acl_common.h>
 
 #define        ALLOW   ACE_ACCESS_ALLOWED_ACE_TYPE
 #define        DENY    ACE_ACCESS_DENIED_ACE_TYPE
@@ -347,7 +345,7 @@ zfs_external_acl(znode_t *zp)
         * changed.
         */
 
-       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zp->z_zfsvfs),
+       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(ZTOZSB(zp)),
            &acl_phys, sizeof (acl_phys))) == 0)
                return (acl_phys.z_acl_extern_obj);
        else {
@@ -370,23 +368,23 @@ static int
 zfs_acl_znode_info(znode_t *zp, int *aclsize, int *aclcount,
     zfs_acl_phys_t *aclphys)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        uint64_t acl_count;
        int size;
        int error;
 
        ASSERT(MUTEX_HELD(&zp->z_acl_lock));
        if (zp->z_is_sa) {
-               if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zfsvfs),
+               if ((error = sa_size(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zsb),
                    &size)) != 0)
                        return (error);
                *aclsize = size;
-               if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_COUNT(zfsvfs),
+               if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_COUNT(zsb),
                    &acl_count, sizeof (acl_count))) != 0)
                        return (error);
                *aclcount = acl_count;
        } else {
-               if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs),
+               if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zsb),
                    aclphys, sizeof (*aclphys))) != 0)
                        return (error);
 
@@ -420,7 +418,7 @@ zfs_znode_acl_version(znode_t *zp)
                 * changed.
                 */
                if ((error = sa_lookup(zp->z_sa_hdl,
-                   SA_ZPL_ZNODE_ACL(zp->z_zfsvfs),
+                   SA_ZPL_ZNODE_ACL(ZTOZSB(zp)),
                    &acl_phys, sizeof (acl_phys))) == 0)
                        return (acl_phys.z_acl_version);
                else {
@@ -446,7 +444,7 @@ zfs_acl_version(int version)
 static int
 zfs_acl_version_zp(znode_t *zp)
 {
-       return (zfs_acl_version(zp->z_zfsvfs->z_version));
+       return (zfs_acl_version(ZTOZSB(zp)->z_version));
 }
 
 zfs_acl_t *
@@ -494,7 +492,7 @@ zfs_acl_release_nodes(zfs_acl_t *aclp)
 {
        zfs_acl_node_t *aclnode;
 
-       while (aclnode = list_head(&aclp->z_acl)) {
+       while ((aclnode = list_head(&aclp->z_acl))) {
                list_remove(&aclp->z_acl, aclnode);
                zfs_acl_node_free(aclnode);
        }
@@ -533,7 +531,7 @@ zfs_acl_valid_ace_type(uint_t type, uint_t flags)
 }
 
 static boolean_t
-zfs_ace_valid(vtype_t obj_type, zfs_acl_t *aclp, uint16_t type, uint16_t iflags)
+zfs_ace_valid(umode_t obj_mode, zfs_acl_t *aclp, uint16_t type, uint16_t iflags)
 {
        /*
         * first check type of entry
@@ -556,7 +554,7 @@ zfs_ace_valid(vtype_t obj_type, zfs_acl_t *aclp, uint16_t type, uint16_t iflags)
         * next check inheritance level flags
         */
 
-       if (obj_type == VDIR &&
+       if (S_ISDIR(obj_mode) &&
            (iflags & (ACE_FILE_INHERIT_ACE|ACE_DIRECTORY_INHERIT_ACE)))
                aclp->z_hints |= ZFS_INHERIT_ACE;
 
@@ -644,20 +642,13 @@ zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt,
        return ((uint64_t)(uintptr_t)acep);
 }
 
-static zfs_acl_node_t *
-zfs_acl_curr_node(zfs_acl_t *aclp)
-{
-       ASSERT(aclp->z_curr_node);
-       return (aclp->z_curr_node);
-}
-
 /*
  * Copy ACE to internal ZFS format.
  * While processing the ACL each ACE will be validated for correctness.
  * ACE FUIDs will be created later.
  */
 int
-zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp,
+zfs_copy_ace_2_fuid(zfs_sb_t *zsb, umode_t obj_mode, zfs_acl_t *aclp,
     void *datap, zfs_ace_t *z_acl, uint64_t aclcnt, size_t *size,
     zfs_fuid_info_t **fuidp, cred_t *cr)
 {
@@ -675,7 +666,7 @@ zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp,
                entry_type = aceptr->z_hdr.z_flags & ACE_TYPE_FLAGS;
                if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP &&
                    entry_type != ACE_EVERYONE) {
-                       aceptr->z_fuid = zfs_fuid_create(zfsvfs, acep->a_who,
+                       aceptr->z_fuid = zfs_fuid_create(zsb, acep->a_who,
                            cr, (entry_type == 0) ?
                            ZFS_ACE_USER : ZFS_ACE_GROUP, fuidp);
                }
@@ -683,7 +674,7 @@ zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp,
                /*
                 * Make sure ACE is valid
                 */
-               if (zfs_ace_valid(obj_type, aclp, aceptr->z_hdr.z_type,
+               if (zfs_ace_valid(obj_mode, aclp, aceptr->z_hdr.z_type,
                    aceptr->z_hdr.z_flags) != B_TRUE)
                        return (EINVAL);
 
@@ -719,7 +710,7 @@ zfs_copy_ace_2_fuid(zfsvfs_t *zfsvfs, vtype_t obj_type, zfs_acl_t *aclp,
  * Copy ZFS ACEs to fixed size ace_t layout
  */
 static void
-zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr,
+zfs_copy_fuid_2_ace(zfs_sb_t *zsb, zfs_acl_t *aclp, cred_t *cr,
     void *datap, int filter)
 {
        uint64_t who;
@@ -732,8 +723,8 @@ zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr,
        size_t ace_size;
        uint16_t entry_type;
 
-       while (zacep = zfs_acl_next_ace(aclp, zacep,
-           &who, &access_mask, &iflags, &type)) {
+       while ((zacep = zfs_acl_next_ace(aclp, zacep,
+           &who, &access_mask, &iflags, &type))) {
 
                switch (type) {
                case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
@@ -762,7 +753,7 @@ zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr,
                if ((entry_type != ACE_OWNER &&
                    entry_type != OWNING_GROUP &&
                    entry_type != ACE_EVERYONE)) {
-                       acep->a_who = zfs_fuid_map_id(zfsvfs, who,
+                       acep->a_who = zfs_fuid_map_id(zsb, who,
                            cr, (entry_type & ACE_IDENTIFIER_GROUP) ?
                            ZFS_ACE_GROUP : ZFS_ACE_USER);
                } else {
@@ -776,7 +767,7 @@ zfs_copy_fuid_2_ace(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, cred_t *cr,
 }
 
 static int
-zfs_copy_ace_2_oldace(vtype_t obj_type, zfs_acl_t *aclp, ace_t *acep,
+zfs_copy_ace_2_oldace(umode_t obj_mode, zfs_acl_t *aclp, ace_t *acep,
     zfs_oldace_t *z_acl, int aclcnt, size_t *size)
 {
        int i;
@@ -790,7 +781,7 @@ zfs_copy_ace_2_oldace(vtype_t obj_type, zfs_acl_t *aclp, ace_t *acep,
                /*
                 * Make sure ACE is valid
                 */
-               if (zfs_ace_valid(obj_type, aclp, aceptr->z_type,
+               if (zfs_ace_valid(obj_mode, aclp, aceptr->z_type,
                    aceptr->z_flags) != B_TRUE)
                        return (EINVAL);
        }
@@ -823,8 +814,8 @@ zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr)
        oldaclp = kmem_alloc(sizeof (zfs_oldace_t) * aclp->z_acl_count,
            KM_SLEEP);
        i = 0;
-       while (cookie = zfs_acl_next_ace(aclp, cookie, &who,
-           &access_mask, &iflags, &type)) {
+       while ((cookie = zfs_acl_next_ace(aclp, cookie, &who,
+           &access_mask, &iflags, &type))) {
                oldaclp[i].z_flags = iflags;
                oldaclp[i].z_type = type;
                oldaclp[i].z_fuid = who;
@@ -834,8 +825,8 @@ zfs_acl_xform(znode_t *zp, zfs_acl_t *aclp, cred_t *cr)
        newaclnode = zfs_acl_node_alloc(aclp->z_acl_count *
            sizeof (zfs_object_ace_t));
        aclp->z_ops = zfs_acl_fuid_ops;
-       VERIFY(zfs_copy_ace_2_fuid(zp->z_zfsvfs, ZTOV(zp)->v_type, aclp,
-           oldaclp, newaclnode->z_acldata, aclp->z_acl_count,
+       VERIFY(zfs_copy_ace_2_fuid(ZTOZSB(zp), ZTOI(zp)->i_mode,
+           aclp, oldaclp, newaclnode->z_acldata, aclp->z_acl_count,
            &newaclnode->z_size, NULL, cr) == 0);
        newaclnode->z_ace_count = aclp->z_acl_count;
        aclp->z_version = ZFS_ACL_VERSION;
@@ -904,8 +895,8 @@ zfs_mode_compute(uint64_t fmode, zfs_acl_t *aclp,
 
        mode = (fmode & (S_IFMT | S_ISUID | S_ISGID | S_ISVTX));
 
-       while (acep = zfs_acl_next_ace(aclp, acep, &who,
-           &access_mask, &iflags, &type)) {
+       while ((acep = zfs_acl_next_ace(aclp, acep, &who,
+           &access_mask, &iflags, &type))) {
 
                if (!zfs_acl_valid_ace_type(type, iflags))
                        continue;
@@ -1109,7 +1100,7 @@ zfs_acl_node_read(znode_t *zp, boolean_t have_lock, zfs_acl_t **aclpp,
 
        if (!zp->z_is_sa) {
                if (znode_acl.z_acl_extern_obj) {
-                       error = dmu_read(zp->z_zfsvfs->z_os,
+                       error = dmu_read(ZTOZSB(zp)->z_os,
                            znode_acl.z_acl_extern_obj, 0, aclnode->z_size,
                            aclnode->z_acldata, DMU_READ_PREFETCH);
                } else {
@@ -1117,7 +1108,7 @@ zfs_acl_node_read(znode_t *zp, boolean_t have_lock, zfs_acl_t **aclpp,
                            aclnode->z_size);
                }
        } else {
-               error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_ACES(zp->z_zfsvfs),
+               error = sa_lookup(zp->z_sa_hdl, SA_ZPL_DACL_ACES(ZTOZSB(zp)),
                    aclnode->z_acldata, aclnode->z_size);
        }
 
@@ -1173,6 +1164,126 @@ zfs_acl_chown_setattr(znode_t *zp)
        return (error);
 }
 
+static void
+acl_trivial_access_masks(mode_t mode, uint32_t *allow0, uint32_t *deny1,
+    uint32_t *deny2, uint32_t *owner, uint32_t *group, uint32_t *everyone)
+{
+       *deny1 = *deny2 = *allow0 = *group = 0;
+
+       if (!(mode & S_IRUSR) && (mode & (S_IRGRP|S_IROTH)))
+               *deny1 |= ACE_READ_DATA;
+       if (!(mode & S_IWUSR) && (mode & (S_IWGRP|S_IWOTH)))
+               *deny1 |= ACE_WRITE_DATA;
+       if (!(mode & S_IXUSR) && (mode & (S_IXGRP|S_IXOTH)))
+               *deny1 |= ACE_EXECUTE;
+
+       if (!(mode & S_IRGRP) && (mode & S_IROTH))
+               *deny2 = ACE_READ_DATA;
+       if (!(mode & S_IWGRP) && (mode & S_IWOTH))
+               *deny2 |= ACE_WRITE_DATA;
+       if (!(mode & S_IXGRP) && (mode & S_IXOTH))
+               *deny2 |= ACE_EXECUTE;
+
+       if ((mode & S_IRUSR) && (!(mode & S_IRGRP) && (mode & S_IROTH)))
+               *allow0 |= ACE_READ_DATA;
+       if ((mode & S_IWUSR) && (!(mode & S_IWGRP) && (mode & S_IWOTH)))
+               *allow0 |= ACE_WRITE_DATA;
+       if ((mode & S_IXUSR) && (!(mode & S_IXGRP) && (mode & S_IXOTH)))
+               *allow0 |= ACE_EXECUTE;
+
+       *owner = ACE_WRITE_ATTRIBUTES|ACE_WRITE_OWNER|ACE_WRITE_ACL|
+           ACE_WRITE_NAMED_ATTRS|ACE_READ_ACL|ACE_READ_ATTRIBUTES|
+           ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE;
+       if (mode & S_IRUSR)
+               *owner |= ACE_READ_DATA;
+       if (mode & S_IWUSR)
+               *owner |= ACE_WRITE_DATA|ACE_APPEND_DATA;
+       if (mode & S_IXUSR)
+               *owner |= ACE_EXECUTE;
+
+       *group = ACE_READ_ACL|ACE_READ_ATTRIBUTES| ACE_READ_NAMED_ATTRS|
+           ACE_SYNCHRONIZE;
+       if (mode & S_IRGRP)
+               *group |= ACE_READ_DATA;
+       if (mode & S_IWGRP)
+               *group |= ACE_WRITE_DATA|ACE_APPEND_DATA;
+       if (mode & S_IXGRP)
+               *group |= ACE_EXECUTE;
+
+       *everyone = ACE_READ_ACL|ACE_READ_ATTRIBUTES| ACE_READ_NAMED_ATTRS|
+           ACE_SYNCHRONIZE;
+       if (mode & S_IROTH)
+               *everyone |= ACE_READ_DATA;
+       if (mode & S_IWOTH)
+               *everyone |= ACE_WRITE_DATA|ACE_APPEND_DATA;
+       if (mode & S_IXOTH)
+               *everyone |= ACE_EXECUTE;
+}
+
+/*
+ * ace_trivial:
+ * determine whether an ace_t acl is trivial
+ *
+ * Trivialness implies that the acl is composed of only
+ * owner, group, everyone entries.  ACL can't
+ * have read_acl denied, and write_owner/write_acl/write_attributes
+ * can only be owner@ entry.
+ */
+static int
+ace_trivial_common(void *acep, int aclcnt,
+    uint64_t (*walk)(void *, uint64_t, int aclcnt,
+    uint16_t *, uint16_t *, uint32_t *))
+{
+       uint16_t flags;
+       uint32_t mask;
+       uint16_t type;
+       uint64_t cookie = 0;
+
+       while ((cookie = walk(acep, cookie, aclcnt, &flags, &type, &mask))) {
+               switch (flags & ACE_TYPE_FLAGS) {
+               case ACE_OWNER:
+               case ACE_GROUP|ACE_IDENTIFIER_GROUP:
+               case ACE_EVERYONE:
+                       break;
+               default:
+                       return (1);
+               }
+
+               if (flags & (ACE_FILE_INHERIT_ACE|
+                   ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
+                   ACE_INHERIT_ONLY_ACE))
+                       return (1);
+
+               /*
+                * Special check for some special bits
+                *
+                * Don't allow anybody to deny reading basic
+                * attributes or a files ACL.
+                */
+               if ((mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES)) &&
+                   (type == ACE_ACCESS_DENIED_ACE_TYPE))
+                       return (1);
+
+               /*
+                * Delete permissions are never set by default
+                */
+               if (mask & (ACE_DELETE|ACE_DELETE_CHILD))
+                       return (1);
+               /*
+                * only allow owner@ to have
+                * write_acl/write_owner/write_attributes/write_xattr/
+                */
+               if (type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
+                   (!(flags & ACE_OWNER) && (mask &
+                   (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
+                   ACE_WRITE_NAMED_ATTRS))))
+                       return (1);
+
+       }
+
+       return (0);
+}
+
 /*
  * common code for setting ACLs.
  *
@@ -1184,7 +1295,7 @@ int
 zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
 {
        int                     error;
-       zfsvfs_t                *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t                *zsb = ZTOZSB(zp);
        dmu_object_type_t       otype;
        zfs_acl_locator_cb_t    locate = { 0 };
        uint64_t                mode;
@@ -1198,11 +1309,11 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
            zp->z_uid, zp->z_gid);
 
        zp->z_mode = mode;
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb), NULL,
            &mode, sizeof (mode));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, sizeof (zp->z_pflags));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL,
            &ctime, sizeof (ctime));
 
        if (zp->z_acl_cached) {
@@ -1213,11 +1324,11 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
        /*
         * Upgrade needed?
         */
-       if (!zfsvfs->z_use_fuids) {
+       if (!zsb->z_use_fuids) {
                otype = DMU_OT_OLDACL;
        } else {
                if ((aclp->z_version == ZFS_ACL_VERSION_INITIAL) &&
-                   (zfsvfs->z_version >= ZPL_VERSION_FUID))
+                   (zsb->z_version >= ZPL_VERSION_FUID))
                        zfs_acl_xform(zp, aclp, cr);
                ASSERT(aclp->z_version >= ZFS_ACL_VERSION_FUID);
                otype = DMU_OT_ACL;
@@ -1230,9 +1341,9 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
 
        if (zp->z_is_sa) { /* the easy case, just update the ACL attribute */
                locate.cb_aclp = aclp;
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_ACES(zfsvfs),
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_ACES(zsb),
                    zfs_acl_data_locator, &locate, aclp->z_acl_bytes);
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_COUNT(zfsvfs),
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_DACL_COUNT(zsb),
                    NULL, &aclp->z_acl_count, sizeof (uint64_t));
        } else { /* Painful legacy way */
                zfs_acl_node_t *aclnode;
@@ -1240,7 +1351,7 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
                zfs_acl_phys_t acl_phys;
                uint64_t aoid;
 
-               if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zfsvfs),
+               if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_ZNODE_ACL(zsb),
                    &acl_phys, sizeof (acl_phys))) != 0)
                        return (error);
 
@@ -1254,20 +1365,20 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
                         */
                        if (aoid &&
                            aclp->z_version != acl_phys.z_acl_version) {
-                               error = dmu_object_free(zfsvfs->z_os, aoid, tx);
+                               error = dmu_object_free(zsb->z_os, aoid, tx);
                                if (error)
                                        return (error);
                                aoid = 0;
                        }
                        if (aoid == 0) {
-                               aoid = dmu_object_alloc(zfsvfs->z_os,
+                               aoid = dmu_object_alloc(zsb->z_os,
                                    otype, aclp->z_acl_bytes,
                                    otype == DMU_OT_ACL ?
                                    DMU_OT_SYSACL : DMU_OT_NONE,
                                    otype == DMU_OT_ACL ?
                                    DN_MAX_BONUSLEN : 0, tx);
                        } else {
-                               (void) dmu_object_set_blocksize(zfsvfs->z_os,
+                               (void) dmu_object_set_blocksize(zsb->z_os,
                                    aoid, aclp->z_acl_bytes, 0, tx);
                        }
                        acl_phys.z_acl_extern_obj = aoid;
@@ -1275,7 +1386,7 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
                            aclnode = list_next(&aclp->z_acl, aclnode)) {
                                if (aclnode->z_ace_count == 0)
                                        continue;
-                               dmu_write(zfsvfs->z_os, aoid, off,
+                               dmu_write(zsb->z_os, aoid, off,
                                    aclnode->z_size, aclnode->z_acldata, tx);
                                off += aclnode->z_size;
                        }
@@ -1285,7 +1396,7 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
                         * Migrating back embedded?
                         */
                        if (acl_phys.z_acl_extern_obj) {
-                               error = dmu_object_free(zfsvfs->z_os,
+                               error = dmu_object_free(zsb->z_os,
                                    acl_phys.z_acl_extern_obj, tx);
                                if (error)
                                        return (error);
@@ -1314,7 +1425,7 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
                }
                acl_phys.z_acl_version = aclp->z_version;
 
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zsb), NULL,
                    &acl_phys, sizeof (acl_phys));
        }
 
@@ -1332,87 +1443,20 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
        return (sa_bulk_update(zp->z_sa_hdl, bulk, count, tx));
 }
 
-/*
- * Update access mask for prepended ACE
- *
- * This applies the "groupmask" value for aclmode property.
- */
 static void
-zfs_acl_prepend_fixup(zfs_acl_t *aclp, void  *acep, void  *origacep,
-    mode_t mode, uint64_t owner)
-{
-       int     rmask, wmask, xmask;
-       int     user_ace;
-       uint16_t aceflags;
-       uint32_t origmask, acepmask;
-       uint64_t fuid;
-
-       aceflags = aclp->z_ops.ace_flags_get(acep);
-       fuid = aclp->z_ops.ace_who_get(acep);
-       origmask = aclp->z_ops.ace_mask_get(origacep);
-       acepmask = aclp->z_ops.ace_mask_get(acep);
-
-       user_ace = (!(aceflags &
-           (ACE_OWNER|ACE_GROUP|ACE_IDENTIFIER_GROUP)));
-
-       if (user_ace && (fuid == owner)) {
-               rmask = S_IRUSR;
-               wmask = S_IWUSR;
-               xmask = S_IXUSR;
-       } else {
-               rmask = S_IRGRP;
-               wmask = S_IWGRP;
-               xmask = S_IXGRP;
-       }
-
-       if (origmask & ACE_READ_DATA) {
-               if (mode & rmask) {
-                       acepmask &= ~ACE_READ_DATA;
-               } else {
-                       acepmask |= ACE_READ_DATA;
-               }
-       }
-
-       if (origmask & ACE_WRITE_DATA) {
-               if (mode & wmask) {
-                       acepmask &= ~ACE_WRITE_DATA;
-               } else {
-                       acepmask |= ACE_WRITE_DATA;
-               }
-       }
-
-       if (origmask & ACE_APPEND_DATA) {
-               if (mode & wmask) {
-                       acepmask &= ~ACE_APPEND_DATA;
-               } else {
-                       acepmask |= ACE_APPEND_DATA;
-               }
-       }
-
-       if (origmask & ACE_EXECUTE) {
-               if (mode & xmask) {
-                       acepmask &= ~ACE_EXECUTE;
-               } else {
-                       acepmask |= ACE_EXECUTE;
-               }
-       }
-       aclp->z_ops.ace_mask_set(acep, acepmask);
-}
-
-static void
-zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t mode, zfs_acl_t *aclp)
+zfs_acl_chmod(zfs_sb_t *zsb, uint64_t mode, zfs_acl_t *aclp)
 {
        void            *acep = NULL;
        uint64_t        who;
        int             new_count, new_bytes;
        int             ace_size;
-       int             entry_type;
+       int             entry_type;
        uint16_t        iflags, type;
        uint32_t        access_mask;
        zfs_acl_node_t  *newnode;
-       size_t          abstract_size = aclp->z_ops.ace_abstract_size();
-       void            *zacep;
-       uint32_t        owner, group, everyone;
+       size_t          abstract_size = aclp->z_ops.ace_abstract_size();
+       void            *zacep;
+       uint32_t        owner, group, everyone;
        uint32_t        deny1, deny2, allow0;
 
        new_count = new_bytes = 0;
@@ -1441,8 +1485,8 @@ zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t mode, zfs_acl_t *aclp)
                new_bytes += abstract_size;
        }
 
-       while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,
-           &iflags, &type)) {
+       while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,
+           &iflags, &type))) {
                uint16_t inherit_flags;
 
                entry_type = (iflags & ACE_TYPE_FLAGS);
@@ -1472,7 +1516,7 @@ zfs_acl_chmod(zfsvfs_t *zfsvfs, uint64_t mode, zfs_acl_t *aclp)
                         * Limit permissions to be no greater than
                         * group permissions
                         */
-                       if (zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) {
+                       if (zsb->z_acl_inherit == ZFS_ACL_RESTRICTED) {
                                if (!(mode & S_IRGRP))
                                        access_mask &= ~ACE_READ_DATA;
                                if (!(mode & S_IWGRP))
@@ -1514,7 +1558,7 @@ zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode)
        mutex_enter(&zp->z_lock);
        *aclp = zfs_acl_alloc(zfs_acl_version_zp(zp));
        (*aclp)->z_hints = zp->z_pflags & V4_ACL_WIDE_FLAGS;
-       zfs_acl_chmod(zp->z_zfsvfs, mode, *aclp);
+       zfs_acl_chmod(ZTOZSB(zp), mode, *aclp);
        mutex_exit(&zp->z_lock);
        mutex_exit(&zp->z_acl_lock);
        ASSERT(*aclp);
@@ -1524,11 +1568,11 @@ zfs_acl_chmod_setattr(znode_t *zp, zfs_acl_t **aclp, uint64_t mode)
  * strip off write_owner and write_acl
  */
 static void
-zfs_restricted_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep)
+zfs_restricted_update(zfs_sb_t *zsb, zfs_acl_t *aclp, void *acep)
 {
        uint32_t mask = aclp->z_ops.ace_mask_get(acep);
 
-       if ((zfsvfs->z_acl_inherit == ZFS_ACL_RESTRICTED) &&
+       if ((zsb->z_acl_inherit == ZFS_ACL_RESTRICTED) &&
            (aclp->z_ops.ace_type_get(acep) == ALLOW)) {
                mask &= ~RESTRICTED_CLEAR;
                aclp->z_ops.ace_mask_set(acep, mask);
@@ -1539,14 +1583,14 @@ zfs_restricted_update(zfsvfs_t *zfsvfs, zfs_acl_t *aclp, void *acep)
  * Should ACE be inherited?
  */
 static int
-zfs_ace_can_use(vtype_t vtype, uint16_t acep_flags)
+zfs_ace_can_use(umode_t obj_mode, uint16_t acep_flags)
 {
        int     iflags = (acep_flags & 0xf);
 
-       if ((vtype == VDIR) && (iflags & ACE_DIRECTORY_INHERIT_ACE))
+       if (S_ISDIR(obj_mode) && (iflags & ACE_DIRECTORY_INHERIT_ACE))
                return (1);
        else if (iflags & ACE_FILE_INHERIT_ACE)
-               return (!((vtype == VDIR) &&
+               return (!(S_ISDIR(obj_mode) &&
                    (iflags & ACE_NO_PROPAGATE_INHERIT_ACE)));
        return (0);
 }
@@ -1555,7 +1599,7 @@ zfs_ace_can_use(vtype_t vtype, uint16_t acep_flags)
  * inherit inheritable ACEs from parent
  */
 static zfs_acl_t *
-zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
+zfs_acl_inherit(zfs_sb_t *zsb, umode_t obj_mode, zfs_acl_t *paclp,
     uint64_t mode, boolean_t *need_chmod)
 {
        void            *pacep;
@@ -1568,24 +1612,24 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
        size_t          ace_size;
        void            *data1, *data2;
        size_t          data1sz, data2sz;
-       boolean_t       vdir = vtype == VDIR;
-       boolean_t       vreg = vtype == VREG;
+       boolean_t       vdir = S_ISDIR(obj_mode);
+       boolean_t       vreg = S_ISREG(obj_mode);
        boolean_t       passthrough, passthrough_x, noallow;
 
        passthrough_x =
-           zfsvfs->z_acl_inherit == ZFS_ACL_PASSTHROUGH_X;
+           zsb->z_acl_inherit == ZFS_ACL_PASSTHROUGH_X;
        passthrough = passthrough_x ||
-           zfsvfs->z_acl_inherit == ZFS_ACL_PASSTHROUGH;
+           zsb->z_acl_inherit == ZFS_ACL_PASSTHROUGH;
        noallow =
-           zfsvfs->z_acl_inherit == ZFS_ACL_NOALLOW;
+           zsb->z_acl_inherit == ZFS_ACL_NOALLOW;
 
        *need_chmod = B_TRUE;
        pacep = NULL;
        aclp = zfs_acl_alloc(paclp->z_version);
-       if (zfsvfs->z_acl_inherit == ZFS_ACL_DISCARD || vtype == VLNK)
+       if (zsb->z_acl_inherit == ZFS_ACL_DISCARD || S_ISLNK(obj_mode))
                return (aclp);
-       while (pacep = zfs_acl_next_ace(paclp, pacep, &who,
-           &access_mask, &iflags, &type)) {
+       while ((pacep = zfs_acl_next_ace(paclp, pacep, &who,
+           &access_mask, &iflags, &type))) {
 
                /*
                 * don't inherit bogus ACEs
@@ -1598,7 +1642,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
 
                ace_size = aclp->z_ops.ace_size(pacep);
 
-               if (!zfs_ace_can_use(vtype, iflags))
+               if (!zfs_ace_can_use(obj_mode, iflags))
                        continue;
 
                /*
@@ -1646,7 +1690,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
                        newflags &= ~ALL_INHERIT;
                        aclp->z_ops.ace_flags_set(acep,
                            newflags|ACE_INHERITED_ACE);
-                       zfs_restricted_update(zfsvfs, aclp, acep);
+                       zfs_restricted_update(zsb, aclp, acep);
                        continue;
                }
 
@@ -1679,37 +1723,41 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
     vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids)
 {
        int             error;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(dzp);
        zfs_acl_t       *paclp;
+#ifdef HAVE_KSID
        gid_t           gid;
+#endif /* HAVE_KSID */
        boolean_t       need_chmod = B_TRUE;
        boolean_t       inherited = B_FALSE;
 
        bzero(acl_ids, sizeof (zfs_acl_ids_t));
-       acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode);
+       acl_ids->z_mode = vap->va_mode;
 
        if (vsecp)
-               if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr,
-                   &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0)
+               if ((error = zfs_vsec_2_aclp(zsb, vap->va_mode, vsecp,
+                   cr, &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0)
                        return (error);
+
+       acl_ids->z_fuid = vap->va_uid;
+       acl_ids->z_fgid = vap->va_gid;
+#ifdef HAVE_KSID
        /*
         * Determine uid and gid.
         */
-       if ((flag & IS_ROOT_NODE) || zfsvfs->z_replay ||
-           ((flag & IS_XATTR) && (vap->va_type == VDIR))) {
-               acl_ids->z_fuid = zfs_fuid_create(zfsvfs,
-                   (uint64_t)vap->va_uid, cr,
-                   ZFS_OWNER, &acl_ids->z_fuidp);
-               acl_ids->z_fgid = zfs_fuid_create(zfsvfs,
-                   (uint64_t)vap->va_gid, cr,
-                   ZFS_GROUP, &acl_ids->z_fuidp);
+       if ((flag & IS_ROOT_NODE) || zsb->z_replay ||
+           ((flag & IS_XATTR) && (S_ISDIR(vap->va_mode)))) {
+               acl_ids->z_fuid = zfs_fuid_create(zsb, (uint64_t)vap->va_uid,
+                   cr, ZFS_OWNER, &acl_ids->z_fuidp);
+               acl_ids->z_fgid = zfs_fuid_create(zsb, (uint64_t)vap->va_gid,
+                   cr, ZFS_GROUP, &acl_ids->z_fuidp);
                gid = vap->va_gid;
        } else {
-               acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER,
+               acl_ids->z_fuid = zfs_fuid_create_cred(zsb, ZFS_OWNER,
                    cr, &acl_ids->z_fuidp);
                acl_ids->z_fgid = 0;
                if (vap->va_mask & AT_GID)  {
-                       acl_ids->z_fgid = zfs_fuid_create(zfsvfs,
+                       acl_ids->z_fgid = zfs_fuid_create(zsb,
                            (uint64_t)vap->va_gid,
                            cr, ZFS_GROUP, &acl_ids->z_fuidp);
                        gid = vap->va_gid;
@@ -1724,13 +1772,13 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
                                uint32_t        rid;
 
                                acl_ids->z_fgid = dzp->z_gid;
-                               gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid,
+                               gid = zfs_fuid_map_id(zsb, acl_ids->z_fgid,
                                    cr, ZFS_GROUP);
 
-                               if (zfsvfs->z_use_fuids &&
+                               if (zsb->z_use_fuids &&
                                    IS_EPHEMERAL(acl_ids->z_fgid)) {
                                        domain = zfs_fuid_idx_domain(
-                                           &zfsvfs->z_fuid_idx,
+                                           &zsb->z_fuid_idx,
                                            FUID_INDEX(acl_ids->z_fgid));
                                        rid = FUID_RID(acl_ids->z_fgid);
                                        zfs_fuid_node_add(&acl_ids->z_fuidp,
@@ -1739,12 +1787,13 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
                                            acl_ids->z_fgid, ZFS_GROUP);
                                }
                        } else {
-                               acl_ids->z_fgid = zfs_fuid_create_cred(zfsvfs,
+                               acl_ids->z_fgid = zfs_fuid_create_cred(zsb,
                                    ZFS_GROUP, cr, &acl_ids->z_fuidp);
                                gid = crgetgid(cr);
                        }
                }
        }
+#endif /* HAVE_KSID */
 
        /*
         * If we're creating a directory, and the parent directory has the
@@ -1754,7 +1803,7 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
         */
 
        if (!(flag & IS_ROOT_NODE) && (dzp->z_mode & S_ISGID) &&
-           (vap->va_type == VDIR)) {
+           (S_ISDIR(vap->va_mode))) {
                acl_ids->z_mode |= S_ISGID;
        } else {
                if ((acl_ids->z_mode & S_ISGID) &&
@@ -1765,13 +1814,13 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
        if (acl_ids->z_aclp == NULL) {
                mutex_enter(&dzp->z_acl_lock);
                mutex_enter(&dzp->z_lock);
-               if (!(flag & IS_ROOT_NODE) && (ZTOV(dzp)->v_type == VDIR &&
+               if (!(flag & IS_ROOT_NODE) && (S_ISDIR(ZTOI(dzp)->i_mode) &&
                    (dzp->z_pflags & ZFS_INHERIT_ACE)) &&
                    !(dzp->z_pflags & ZFS_XATTR)) {
                        VERIFY(0 == zfs_acl_node_read(dzp, B_TRUE,
                            &paclp, B_FALSE));
-                       acl_ids->z_aclp = zfs_acl_inherit(zfsvfs,
-                           vap->va_type, paclp, acl_ids->z_mode, &need_chmod);
+                       acl_ids->z_aclp = zfs_acl_inherit(zsb,
+                           vap->va_mode, paclp, acl_ids->z_mode, &need_chmod);
                        inherited = B_TRUE;
                } else {
                        acl_ids->z_aclp =
@@ -1781,9 +1830,9 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
                mutex_exit(&dzp->z_lock);
                mutex_exit(&dzp->z_acl_lock);
                if (need_chmod) {
-                       acl_ids->z_aclp->z_hints |= (vap->va_type == VDIR) ?
+                       acl_ids->z_aclp->z_hints |= S_ISDIR(vap->va_mode) ?
                            ZFS_ACL_AUTO_INHERIT : 0;
-                       zfs_acl_chmod(zfsvfs, acl_ids->z_mode, acl_ids->z_aclp);
+                       zfs_acl_chmod(zsb, acl_ids->z_mode, acl_ids->z_aclp);
                }
        }
 
@@ -1813,10 +1862,10 @@ zfs_acl_ids_free(zfs_acl_ids_t *acl_ids)
 }
 
 boolean_t
-zfs_acl_ids_overquota(zfsvfs_t *zfsvfs, zfs_acl_ids_t *acl_ids)
+zfs_acl_ids_overquota(zfs_sb_t *zsb, zfs_acl_ids_t *acl_ids)
 {
-       return (zfs_fuid_overquota(zfsvfs, B_FALSE, acl_ids->z_fuid) ||
-           zfs_fuid_overquota(zfsvfs, B_TRUE, acl_ids->z_fgid));
+       return (zfs_fuid_overquota(zsb, B_FALSE, acl_ids->z_fuid) ||
+           zfs_fuid_overquota(zsb, B_TRUE, acl_ids->z_fgid));
 }
 
 /*
@@ -1837,7 +1886,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
        if (mask == 0)
                return (ENOSYS);
 
-       if (error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr))
+       if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)))
                return (error);
 
        mutex_enter(&zp->z_acl_lock);
@@ -1857,8 +1906,8 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
                uint32_t access_mask;
                uint16_t type, iflags;
 
-               while (zacep = zfs_acl_next_ace(aclp, zacep,
-                   &who, &access_mask, &iflags, &type)) {
+               while ((zacep = zfs_acl_next_ace(aclp, zacep,
+                   &who, &access_mask, &iflags, &type))) {
                        switch (type) {
                        case ACE_ACCESS_ALLOWED_OBJECT_ACE_TYPE:
                        case ACE_ACCESS_DENIED_OBJECT_ACE_TYPE:
@@ -1888,7 +1937,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
                vsecp->vsa_aclentsz = aclsz;
 
                if (aclp->z_version == ZFS_ACL_VERSION_FUID)
-                       zfs_copy_fuid_2_ace(zp->z_zfsvfs, aclp, cr,
+                       zfs_copy_fuid_2_ace(ZTOZSB(zp), aclp, cr,
                            vsecp->vsa_aclentp, !(mask & VSA_ACE_ALLTYPES));
                else {
                        zfs_acl_node_t *aclnode;
@@ -1920,7 +1969,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
 }
 
 int
-zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type,
+zfs_vsec_2_aclp(zfs_sb_t *zsb, umode_t obj_mode,
     vsecattr_t *vsecp, cred_t *cr, zfs_fuid_info_t **fuidp, zfs_acl_t **zaclp)
 {
        zfs_acl_t *aclp;
@@ -1931,12 +1980,12 @@ zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type,
        if (vsecp->vsa_aclcnt > MAX_ACL_ENTRIES || vsecp->vsa_aclcnt <= 0)
                return (EINVAL);
 
-       aclp = zfs_acl_alloc(zfs_acl_version(zfsvfs->z_version));
+       aclp = zfs_acl_alloc(zfs_acl_version(zsb->z_version));
 
        aclp->z_hints = 0;
        aclnode = zfs_acl_node_alloc(aclcnt * sizeof (zfs_object_ace_t));
        if (aclp->z_version == ZFS_ACL_VERSION_INITIAL) {
-               if ((error = zfs_copy_ace_2_oldace(obj_type, aclp,
+               if ((error = zfs_copy_ace_2_oldace(obj_mode, aclp,
                    (ace_t *)vsecp->vsa_aclentp, aclnode->z_acldata,
                    aclcnt, &aclnode->z_size)) != 0) {
                        zfs_acl_free(aclp);
@@ -1944,7 +1993,7 @@ zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type,
                        return (error);
                }
        } else {
-               if ((error = zfs_copy_ace_2_fuid(zfsvfs, obj_type, aclp,
+               if ((error = zfs_copy_ace_2_fuid(zsb, obj_mode, aclp,
                    vsecp->vsa_aclentp, aclnode->z_acldata, aclcnt,
                    &aclnode->z_size, fuidp, cr)) != 0) {
                        zfs_acl_free(aclp);
@@ -1980,8 +2029,8 @@ zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type,
 int
 zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
 {
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
-       zilog_t         *zilog = zfsvfs->z_log;
+       zfs_sb_t        *zsb = ZTOZSB(zp);
+       zilog_t         *zilog = zsb->z_log;
        ulong_t         mask = vsecp->vsa_mask & (VSA_ACE | VSA_ACECNT);
        dmu_tx_t        *tx;
        int             error;
@@ -1996,10 +2045,10 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
        if (zp->z_pflags & ZFS_IMMUTABLE)
                return (EPERM);
 
-       if (error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr))
+       if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)))
                return (error);
 
-       error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp,
+       error = zfs_vsec_2_aclp(zsb, ZTOI(zp)->i_mode, vsecp, cr, &fuidp,
            &aclp);
        if (error)
                return (error);
@@ -2016,13 +2065,13 @@ top:
        mutex_enter(&zp->z_acl_lock);
        mutex_enter(&zp->z_lock);
 
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
 
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
 
-       fuid_dirtied = zfsvfs->z_fuid_dirty;
+       fuid_dirtied = zsb->z_fuid_dirty;
        if (fuid_dirtied)
-               zfs_fuid_txhold(zfsvfs, tx);
+               zfs_fuid_txhold(zsb, tx);
 
        /*
         * If old version and ACL won't fit in bonus and we aren't
@@ -2030,7 +2079,7 @@ top:
         */
 
        if ((acl_obj = zfs_external_acl(zp)) != 0) {
-               if (zfsvfs->z_version >= ZPL_VERSION_FUID &&
+               if (zsb->z_version >= ZPL_VERSION_FUID &&
                    zfs_znode_acl_version(zp) <= ZFS_ACL_VERSION_INITIAL) {
                        dmu_tx_hold_free(tx, acl_obj, 0,
                            DMU_OBJECT_END);
@@ -2065,14 +2114,14 @@ top:
        zp->z_acl_cached = aclp;
 
        if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
+               zfs_fuid_sync(zsb, tx);
 
        zfs_log_acl(zilog, tx, zp, vsecp, fuidp);
 
        if (fuidp)
                zfs_fuid_info_free(fuidp);
        dmu_tx_commit(tx);
-done:
+
        mutex_exit(&zp->z_lock);
        mutex_exit(&zp->z_acl_lock);
 
@@ -2088,9 +2137,9 @@ static int
 zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
 {
        if ((v4_mode & WRITE_MASK) &&
-           (zp->z_zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) &&
-           (!IS_DEVVP(ZTOV(zp)) ||
-           (IS_DEVVP(ZTOV(zp)) && (v4_mode & WRITE_MASK_ATTRS)))) {
+           (ZTOZSB(zp)->z_vfs->mnt_flags & MNT_READONLY) &&
+           (!S_ISDEV(ZTOI(zp)->i_mode) ||
+           (S_ISDEV(ZTOI(zp)->i_mode) && (v4_mode & WRITE_MASK_ATTRS)))) {
                return (EROFS);
        }
 
@@ -2098,9 +2147,9 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
         * Only check for READONLY on non-directories.
         */
        if ((v4_mode & WRITE_MASK_DATA) &&
-           (((ZTOV(zp)->v_type != VDIR) &&
+           ((!S_ISDIR(ZTOI(zp)->i_mode) &&
            (zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
-           (ZTOV(zp)->v_type == VDIR &&
+           (S_ISDIR(ZTOI(zp)->i_mode) &&
            (zp->z_pflags & ZFS_IMMUTABLE)))) {
                return (EPERM);
        }
@@ -2147,11 +2196,11 @@ static int
 zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
     boolean_t anyaccess, cred_t *cr)
 {
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(zp);
        zfs_acl_t       *aclp;
        int             error;
        uid_t           uid = crgetuid(cr);
-       uint64_t        who;
+       uint64_t        who;
        uint16_t        type, iflags;
        uint16_t        entry_type;
        uint32_t        access_mask;
@@ -2173,14 +2222,15 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
 
        ASSERT(zp->z_acl_cached);
 
-       while (acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,
-           &iflags, &type)) {
+       while ((acep = zfs_acl_next_ace(aclp, acep, &who, &access_mask,
+           &iflags, &type))) {
                uint32_t mask_matched;
 
                if (!zfs_acl_valid_ace_type(type, iflags))
                        continue;
 
-               if (ZTOV(zp)->v_type == VDIR && (iflags & ACE_INHERIT_ONLY_ACE))
+               if (S_ISDIR(ZTOI(zp)->i_mode) &&
+                   (iflags & ACE_INHERIT_ONLY_ACE))
                        continue;
 
                /* Skip ACE if it does not affect any AoI */
@@ -2201,7 +2251,7 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
                        who = gowner;
                        /*FALLTHROUGH*/
                case ACE_IDENTIFIER_GROUP:
-                       checkit = zfs_groupmember(zfsvfs, who, cr);
+                       checkit = zfs_groupmember(zsb, who, cr);
                        break;
                case ACE_EVERYONE:
                        checkit = B_TRUE;
@@ -2212,7 +2262,7 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
                        if (entry_type == 0) {
                                uid_t newid;
 
-                               newid = zfs_fuid_map_id(zfsvfs, who, cr,
+                               newid = zfs_fuid_map_id(zsb, who, cr,
                                    ZFS_ACE_USER);
                                if (newid != IDMAP_WK_CREATOR_OWNER_UID &&
                                    uid == newid)
@@ -2274,8 +2324,8 @@ zfs_has_access(znode_t *zp, cred_t *cr)
        if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr) != 0) {
                uid_t owner;
 
-               owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
-               return (secpolicy_vnode_any_access(cr, ZTOV(zp), owner) == 0);
+               owner = zfs_fuid_map_id(ZTOZSB(zp), zp->z_uid, cr, ZFS_OWNER);
+               return (secpolicy_vnode_any_access(cr, ZTOI(zp), owner) == 0);
        }
        return (B_TRUE);
 }
@@ -2284,7 +2334,7 @@ static int
 zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
     boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        int err;
 
        *working_mode = v4_mode;
@@ -2293,7 +2343,7 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
        /*
         * Short circuit empty requests
         */
-       if (v4_mode == 0 || zfsvfs->z_replay) {
+       if (v4_mode == 0 || zsb->z_replay) {
                *working_mode = 0;
                return (0);
        }
@@ -2340,7 +2390,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
                return (EACCES);
 
        is_attr = ((zdp->z_pflags & ZFS_XATTR) &&
-           (ZTOV(zdp)->v_type == VDIR));
+           (S_ISDIR(ZTOI(zdp)->i_mode)));
        if (is_attr)
                goto slow;
 
@@ -2388,9 +2438,9 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
 
 slow:
        DTRACE_PROBE(zfs__fastpath__execute__access__miss);
-       ZFS_ENTER(zdp->z_zfsvfs);
+       ZFS_ENTER(ZTOZSB(zdp));
        error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr);
-       ZFS_EXIT(zdp->z_zfsvfs);
+       ZFS_EXIT(ZTOZSB(zdp));
        return (error);
 }
 
@@ -2405,13 +2455,13 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
        uint32_t        working_mode;
        int             error;
        int             is_attr;
-       boolean_t       check_privs;
+       boolean_t       check_privs;
        znode_t         *xzp;
-       znode_t         *check_zp = zp;
+       znode_t         *check_zp = zp;
        mode_t          needed_bits;
        uid_t           owner;
 
-       is_attr = ((zp->z_pflags & ZFS_XATTR) && (ZTOV(zp)->v_type == VDIR));
+       is_attr = ((zp->z_pflags & ZFS_XATTR) && S_ISDIR(ZTOI(zp)->i_mode));
 
        /*
         * If attribute then validate against base file
@@ -2420,11 +2470,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
                uint64_t        parent;
 
                if ((error = sa_lookup(zp->z_sa_hdl,
-                   SA_ZPL_PARENT(zp->z_zfsvfs), &parent,
+                   SA_ZPL_PARENT(ZTOZSB(zp)), &parent,
                    sizeof (parent))) != 0)
                        return (error);
 
-               if ((error = zfs_zget(zp->z_zfsvfs,
+               if ((error = zfs_zget(ZTOZSB(zp),
                    parent, &xzp)) != 0)        {
                        return (error);
                }
@@ -2446,11 +2496,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
                }
        }
 
-       owner = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
+       owner = zfs_fuid_map_id(ZTOZSB(zp), zp->z_uid, cr, ZFS_OWNER);
        /*
-        * Map the bits required to the standard vnode flags VREAD|VWRITE|VEXEC
-        * in needed_bits.  Map the bits mapped by working_mode (currently
-        * missing) in missing_bits.
+        * Map the bits required to the standard inode flags
+        * S_IRUSR|S_IWUSR|S_IXUSR in the needed_bits.  Map the bits
+        * mapped by working_mode (currently missing) in missing_bits.
         * Call secpolicy_vnode_access2() with (needed_bits & ~checkmode),
         * needed_bits.
         */
@@ -2463,24 +2513,24 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
 
        if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS|
            ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE))
-               needed_bits |= VREAD;
+               needed_bits |= S_IRUSR;
        if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS|
            ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE))
-               needed_bits |= VWRITE;
+               needed_bits |= S_IWUSR;
        if (working_mode & ACE_EXECUTE)
-               needed_bits |= VEXEC;
+               needed_bits |= S_IXUSR;
 
        if ((error = zfs_zaccess_common(check_zp, mode, &working_mode,
            &check_privs, skipaclchk, cr)) == 0) {
                if (is_attr)
-                       VN_RELE(ZTOV(xzp));
-               return (secpolicy_vnode_access2(cr, ZTOV(zp), owner,
+                       iput(ZTOI(xzp));
+               return (secpolicy_vnode_access2(cr, ZTOI(zp), owner,
                    needed_bits, needed_bits));
        }
 
        if (error && !check_privs) {
                if (is_attr)
-                       VN_RELE(ZTOV(xzp));
+                       iput(ZTOI(xzp));
                return (error);
        }
 
@@ -2505,14 +2555,14 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
 
                if (working_mode & (ACE_READ_DATA|ACE_READ_NAMED_ATTRS|
                    ACE_READ_ACL|ACE_READ_ATTRIBUTES|ACE_SYNCHRONIZE))
-                       checkmode |= VREAD;
+                       checkmode |= S_IRUSR;
                if (working_mode & (ACE_WRITE_DATA|ACE_WRITE_NAMED_ATTRS|
                    ACE_APPEND_DATA|ACE_WRITE_ATTRIBUTES|ACE_SYNCHRONIZE))
-                       checkmode |= VWRITE;
+                       checkmode |= S_IWUSR;
                if (working_mode & ACE_EXECUTE)
-                       checkmode |= VEXEC;
+                       checkmode |= S_IXUSR;
 
-               error = secpolicy_vnode_access2(cr, ZTOV(check_zp), owner,
+               error = secpolicy_vnode_access2(cr, ZTOI(check_zp), owner,
                    needed_bits & ~checkmode, needed_bits);
 
                if (error == 0 && (working_mode & ACE_WRITE_OWNER))
@@ -2537,19 +2587,19 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
                        }
                }
        } else if (error == 0) {
-               error = secpolicy_vnode_access2(cr, ZTOV(zp), owner,
+               error = secpolicy_vnode_access2(cr, ZTOI(zp), owner,
                    needed_bits, needed_bits);
        }
 
 
        if (is_attr)
-               VN_RELE(ZTOV(xzp));
+               iput(ZTOI(xzp));
 
        return (error);
 }
 
 /*
- * Translate traditional unix VREAD/VWRITE/VEXEC mode into
+ * Translate traditional unix S_IRUSR/S_IWUSR/S_IXUSR mode into
  * native ACL format and call zfs_zaccess()
  */
 int
@@ -2576,10 +2626,10 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp,
        int error;
        uid_t downer;
 
-       downer = zfs_fuid_map_id(dzp->z_zfsvfs, dzp->z_uid, cr, ZFS_OWNER);
+       downer = zfs_fuid_map_id(ZTOZSB(dzp), dzp->z_uid, cr, ZFS_OWNER);
 
-       error = secpolicy_vnode_access2(cr, ZTOV(dzp),
-           downer, available_perms, VWRITE|VEXEC);
+       error = secpolicy_vnode_access2(cr, ZTOI(dzp),
+           downer, available_perms, S_IWUSR|S_IXUSR);
 
        if (error == 0)
                error = zfs_sticky_remove_access(dzp, zp, cr);
@@ -2699,8 +2749,8 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
         * Fourth row
         */
 
-       available_perms = (dzp_working_mode & ACE_WRITE_DATA) ? 0 : VWRITE;
-       available_perms |= (dzp_working_mode & ACE_EXECUTE) ? 0 : VEXEC;
+       available_perms = (dzp_working_mode & ACE_WRITE_DATA) ? 0 : S_IWUSR;
+       available_perms |= (dzp_working_mode & ACE_EXECUTE) ? 0 : S_IXUSR;
 
        return (zfs_delete_final_check(zp, dzp, available_perms, cr));
 
@@ -2716,7 +2766,7 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
        if (szp->z_pflags & ZFS_AV_QUARANTINED)
                return (EACCES);
 
-       add_perm = (ZTOV(szp)->v_type == VDIR) ?
+       add_perm = S_ISDIR(ZTOI(szp)->i_mode) ?
            ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE;
 
        /*
@@ -2730,14 +2780,14 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
         * If that succeeds then check for add_file/add_subdir permissions
         */
 
-       if (error = zfs_zaccess_delete(sdzp, szp, cr))
+       if ((error = zfs_zaccess_delete(sdzp, szp, cr)))
                return (error);
 
        /*
         * If we have a tzp, see if we can delete it?
         */
        if (tzp) {
-               if (error = zfs_zaccess_delete(tdzp, tzp, cr))
+               if ((error = zfs_zaccess_delete(tdzp, tzp, cr)))
                        return (error);
        }
 
@@ -2748,5 +2798,3 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
 
        return (error);
 }
-
-#endif /* HAVE_ZPL */
diff --git a/module/zfs/zfs_ctldir.c b/module/zfs/zfs_ctldir.c
deleted file mode 100644 (file)
index 51b12a1..0000000
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
- * 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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-/*
- * ZFS control directory (a.k.a. ".zfs")
- *
- * This directory provides a common location for all ZFS meta-objects.
- * Currently, this is only the 'snapshot' directory, but this may expand in the
- * future.  The elements are built using the GFS primitives, as the hierarchy
- * does not actually exist on disk.
- *
- * For 'snapshot', we don't want to have all snapshots always mounted, because
- * this would take up a huge amount of space in /etc/mnttab.  We have three
- * types of objects:
- *
- *     ctldir ------> snapshotdir -------> snapshot
- *                                             |
- *                                             |
- *                                             V
- *                                         mounted fs
- *
- * The 'snapshot' node contains just enough information to lookup '..' and act
- * as a mountpoint for the snapshot.  Whenever we lookup a specific snapshot, we
- * perform an automount of the underlying filesystem and return the
- * corresponding vnode.
- *
- * All mounts are handled automatically by the kernel, but unmounts are
- * (currently) handled from user land.  The main reason is that there is no
- * reliable way to auto-unmount the filesystem when it's "no longer in use".
- * When the user unmounts a filesystem, we call zfsctl_unmount(), which
- * unmounts any snapshots within the snapshot directory.
- *
- * The '.zfs', '.zfs/snapshot', and all directories created under
- * '.zfs/snapshot' (ie: '.zfs/snapshot/<snapname>') are all GFS nodes and
- * share the same vfs_t as the head filesystem (what '.zfs' lives under).
- *
- * File systems mounted ontop of the GFS nodes '.zfs/snapshot/<snapname>'
- * (ie: snapshots) are ZFS nodes and have their own unique vfs_t.
- * However, vnodes within these mounted on file systems have their v_vfsp
- * fields set to the head filesystem to make NFS happy (see
- * zfsctl_snapdir_lookup()). We VFS_HOLD the head filesystem's vfs_t
- * so that it cannot be freed until all snapshots have been unmounted.
- */
-
-#ifdef HAVE_ZPL
-
-#include <fs/fs_subr.h>
-#include <sys/zfs_ctldir.h>
-#include <sys/zfs_ioctl.h>
-#include <sys/zfs_vfsops.h>
-#include <sys/vfs_opreg.h>
-#include <sys/gfs.h>
-#include <sys/stat.h>
-#include <sys/dmu.h>
-#include <sys/dsl_deleg.h>
-#include <sys/mount.h>
-#include <sys/sunddi.h>
-
-#include "zfs_namecheck.h"
-
-typedef struct zfsctl_node {
-       gfs_dir_t       zc_gfs_private;
-       uint64_t        zc_id;
-       timestruc_t     zc_cmtime;      /* ctime and mtime, always the same */
-} zfsctl_node_t;
-
-typedef struct zfsctl_snapdir {
-       zfsctl_node_t   sd_node;
-       kmutex_t        sd_lock;
-       avl_tree_t      sd_snaps;
-} zfsctl_snapdir_t;
-
-typedef struct {
-       char            *se_name;
-       vnode_t         *se_root;
-       avl_node_t      se_node;
-} zfs_snapentry_t;
-
-static int
-snapentry_compare(const void *a, const void *b)
-{
-       const zfs_snapentry_t *sa = a;
-       const zfs_snapentry_t *sb = b;
-       int ret = strcmp(sa->se_name, sb->se_name);
-
-       if (ret < 0)
-               return (-1);
-       else if (ret > 0)
-               return (1);
-       else
-               return (0);
-}
-
-vnodeops_t *zfsctl_ops_root;
-vnodeops_t *zfsctl_ops_snapdir;
-vnodeops_t *zfsctl_ops_snapshot;
-vnodeops_t *zfsctl_ops_shares;
-vnodeops_t *zfsctl_ops_shares_dir;
-
-static const fs_operation_def_t zfsctl_tops_root[];
-static const fs_operation_def_t zfsctl_tops_snapdir[];
-static const fs_operation_def_t zfsctl_tops_snapshot[];
-static const fs_operation_def_t zfsctl_tops_shares[];
-
-static vnode_t *zfsctl_mknode_snapdir(vnode_t *);
-static vnode_t *zfsctl_mknode_shares(vnode_t *);
-static vnode_t *zfsctl_snapshot_mknode(vnode_t *, uint64_t objset);
-static int zfsctl_unmount_snap(zfs_snapentry_t *, int, cred_t *);
-
-static gfs_opsvec_t zfsctl_opsvec[] = {
-       { ".zfs", zfsctl_tops_root, &zfsctl_ops_root },
-       { ".zfs/snapshot", zfsctl_tops_snapdir, &zfsctl_ops_snapdir },
-       { ".zfs/snapshot/vnode", zfsctl_tops_snapshot, &zfsctl_ops_snapshot },
-       { ".zfs/shares", zfsctl_tops_shares, &zfsctl_ops_shares_dir },
-       { ".zfs/shares/vnode", zfsctl_tops_shares, &zfsctl_ops_shares },
-       { NULL }
-};
-
-/*
- * Root directory elements.  We only have two entries
- * snapshot and shares.
- */
-static gfs_dirent_t zfsctl_root_entries[] = {
-       { "snapshot", zfsctl_mknode_snapdir, GFS_CACHE_VNODE },
-       { "shares", zfsctl_mknode_shares, GFS_CACHE_VNODE },
-       { NULL }
-};
-
-/* include . and .. in the calculation */
-#define        NROOT_ENTRIES   ((sizeof (zfsctl_root_entries) / \
-    sizeof (gfs_dirent_t)) + 1)
-
-
-/*
- * Initialize the various GFS pieces we'll need to create and manipulate .zfs
- * directories.  This is called from the ZFS init routine, and initializes the
- * vnode ops vectors that we'll be using.
- */
-void
-zfsctl_init(void)
-{
-       VERIFY(gfs_make_opsvec(zfsctl_opsvec) == 0);
-}
-
-void
-zfsctl_fini(void)
-{
-       /*
-        * Remove vfsctl vnode ops
-        */
-       if (zfsctl_ops_root)
-               vn_freevnodeops(zfsctl_ops_root);
-       if (zfsctl_ops_snapdir)
-               vn_freevnodeops(zfsctl_ops_snapdir);
-       if (zfsctl_ops_snapshot)
-               vn_freevnodeops(zfsctl_ops_snapshot);
-       if (zfsctl_ops_shares)
-               vn_freevnodeops(zfsctl_ops_shares);
-       if (zfsctl_ops_shares_dir)
-               vn_freevnodeops(zfsctl_ops_shares_dir);
-
-       zfsctl_ops_root = NULL;
-       zfsctl_ops_snapdir = NULL;
-       zfsctl_ops_snapshot = NULL;
-       zfsctl_ops_shares = NULL;
-       zfsctl_ops_shares_dir = NULL;
-}
-
-boolean_t
-zfsctl_is_node(vnode_t *vp)
-{
-       return (vn_matchops(vp, zfsctl_ops_root) ||
-           vn_matchops(vp, zfsctl_ops_snapdir) ||
-           vn_matchops(vp, zfsctl_ops_snapshot) ||
-           vn_matchops(vp, zfsctl_ops_shares) ||
-           vn_matchops(vp, zfsctl_ops_shares_dir));
-
-}
-
-/*
- * Return the inode number associated with the 'snapshot' or
- * 'shares' directory.
- */
-/* ARGSUSED */
-static ino64_t
-zfsctl_root_inode_cb(vnode_t *vp, int index)
-{
-       zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
-
-       ASSERT(index <= 2);
-
-       if (index == 0)
-               return (ZFSCTL_INO_SNAPDIR);
-
-       return (zfsvfs->z_shares_dir);
-}
-
-/*
- * Create the '.zfs' directory.  This directory is cached as part of the VFS
- * structure.  This results in a hold on the vfs_t.  The code in zfs_umount()
- * therefore checks against a vfs_count of 2 instead of 1.  This reference
- * is removed when the ctldir is destroyed in the unmount.
- */
-void
-zfsctl_create(zfsvfs_t *zfsvfs)
-{
-       vnode_t *vp, *rvp;
-       zfsctl_node_t *zcp;
-       uint64_t crtime[2];
-
-       ASSERT(zfsvfs->z_ctldir == NULL);
-
-       vp = gfs_root_create(sizeof (zfsctl_node_t), zfsvfs->z_vfs,
-           zfsctl_ops_root, ZFSCTL_INO_ROOT, zfsctl_root_entries,
-           zfsctl_root_inode_cb, MAXNAMELEN, NULL, NULL);
-       zcp = vp->v_data;
-       zcp->zc_id = ZFSCTL_INO_ROOT;
-
-       VERIFY(VFS_ROOT(zfsvfs->z_vfs, &rvp) == 0);
-       VERIFY(0 == sa_lookup(VTOZ(rvp)->z_sa_hdl, SA_ZPL_CRTIME(zfsvfs),
-           &crtime, sizeof (crtime)));
-       ZFS_TIME_DECODE(&zcp->zc_cmtime, crtime);
-       VN_RELE(rvp);
-
-       /*
-        * We're only faking the fact that we have a root of a filesystem for
-        * the sake of the GFS interfaces.  Undo the flag manipulation it did
-        * for us.
-        */
-       vp->v_flag &= ~(VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT);
-
-       zfsvfs->z_ctldir = vp;
-}
-
-/*
- * Destroy the '.zfs' directory.  Only called when the filesystem is unmounted.
- * There might still be more references if we were force unmounted, but only
- * new zfs_inactive() calls can occur and they don't reference .zfs
- */
-void
-zfsctl_destroy(zfsvfs_t *zfsvfs)
-{
-       VN_RELE(zfsvfs->z_ctldir);
-       zfsvfs->z_ctldir = NULL;
-}
-
-/*
- * Given a root znode, retrieve the associated .zfs directory.
- * Add a hold to the vnode and return it.
- */
-vnode_t *
-zfsctl_root(znode_t *zp)
-{
-       ASSERT(zfs_has_ctldir(zp));
-       VN_HOLD(zp->z_zfsvfs->z_ctldir);
-       return (zp->z_zfsvfs->z_ctldir);
-}
-
-/*
- * Common open routine.  Disallow any write access.
- */
-/* ARGSUSED */
-static int
-zfsctl_common_open(vnode_t **vpp, int flags, cred_t *cr, caller_context_t *ct)
-{
-       if (flags & FWRITE)
-               return (EACCES);
-
-       return (0);
-}
-
-/*
- * Common close routine.  Nothing to do here.
- */
-/* ARGSUSED */
-static int
-zfsctl_common_close(vnode_t *vpp, int flags, int count, offset_t off,
-    cred_t *cr, caller_context_t *ct)
-{
-       return (0);
-}
-
-/*
- * Common access routine.  Disallow writes.
- */
-/* ARGSUSED */
-static int
-zfsctl_common_access(vnode_t *vp, int mode, int flags, cred_t *cr,
-    caller_context_t *ct)
-{
-       if (flags & V_ACE_MASK) {
-               if (mode & ACE_ALL_WRITE_PERMS)
-                       return (EACCES);
-       } else {
-               if (mode & VWRITE)
-                       return (EACCES);
-       }
-
-       return (0);
-}
-
-/*
- * Common getattr function.  Fill in basic information.
- */
-static void
-zfsctl_common_getattr(vnode_t *vp, vattr_t *vap)
-{
-       timestruc_t     now;
-
-       vap->va_uid = 0;
-       vap->va_gid = 0;
-       vap->va_rdev = 0;
-       /*
-        * We are a purely virtual object, so we have no
-        * blocksize or allocated blocks.
-        */
-       vap->va_blksize = 0;
-       vap->va_nblocks = 0;
-       vap->va_seq = 0;
-       vap->va_fsid = vp->v_vfsp->vfs_dev;
-       vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP |
-           S_IROTH | S_IXOTH;
-       vap->va_type = VDIR;
-       /*
-        * We live in the now (for atime).
-        */
-       gethrestime(&now);
-       vap->va_atime = now;
-}
-
-/*ARGSUSED*/
-static int
-zfsctl_common_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
-{
-       zfsvfs_t        *zfsvfs = vp->v_vfsp->vfs_data;
-       zfsctl_node_t   *zcp = vp->v_data;
-       uint64_t        object = zcp->zc_id;
-       zfid_short_t    *zfid;
-       int             i;
-
-       ZFS_ENTER(zfsvfs);
-
-       if (fidp->fid_len < SHORT_FID_LEN) {
-               fidp->fid_len = SHORT_FID_LEN;
-               ZFS_EXIT(zfsvfs);
-               return (ENOSPC);
-       }
-
-       zfid = (zfid_short_t *)fidp;
-
-       zfid->zf_len = SHORT_FID_LEN;
-
-       for (i = 0; i < sizeof (zfid->zf_object); i++)
-               zfid->zf_object[i] = (uint8_t)(object >> (8 * i));
-
-       /* .zfs znodes always have a generation number of 0 */
-       for (i = 0; i < sizeof (zfid->zf_gen); i++)
-               zfid->zf_gen[i] = 0;
-
-       ZFS_EXIT(zfsvfs);
-       return (0);
-}
-
-
-/*ARGSUSED*/
-static int
-zfsctl_shares_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
-{
-       zfsvfs_t        *zfsvfs = vp->v_vfsp->vfs_data;
-       znode_t         *dzp;
-       int             error;
-
-       ZFS_ENTER(zfsvfs);
-
-       if (zfsvfs->z_shares_dir == 0) {
-               ZFS_EXIT(zfsvfs);
-               return (ENOTSUP);
-       }
-
-       if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) {
-               error = VOP_FID(ZTOV(dzp), fidp, ct);
-               VN_RELE(ZTOV(dzp));
-       }
-
-       ZFS_EXIT(zfsvfs);
-       return (error);
-}
-/*
- * .zfs inode namespace
- *
- * We need to generate unique inode numbers for all files and directories
- * within the .zfs pseudo-filesystem.  We use the following scheme:
- *
- *     ENTRY                   ZFSCTL_INODE
- *     .zfs                    1
- *     .zfs/snapshot           2
- *     .zfs/snapshot/<snap>    objectid(snap)
- */
-
-#define        ZFSCTL_INO_SNAP(id)     (id)
-
-/*
- * Get root directory attributes.
- */
-/* ARGSUSED */
-static int
-zfsctl_root_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct)
-{
-       zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
-       zfsctl_node_t *zcp = vp->v_data;
-
-       ZFS_ENTER(zfsvfs);
-       vap->va_nodeid = ZFSCTL_INO_ROOT;
-       vap->va_nlink = vap->va_size = NROOT_ENTRIES;
-       vap->va_mtime = vap->va_ctime = zcp->zc_cmtime;
-
-       zfsctl_common_getattr(vp, vap);
-       ZFS_EXIT(zfsvfs);
-
-       return (0);
-}
-
-/*
- * Special case the handling of "..".
- */
-/* ARGSUSED */
-int
-zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
-    int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
-    int *direntflags, pathname_t *realpnp)
-{
-       zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
-       int err;
-
-       /*
-        * No extended attributes allowed under .zfs
-        */
-       if (flags & LOOKUP_XATTR)
-               return (EINVAL);
-
-       ZFS_ENTER(zfsvfs);
-
-       if (strcmp(nm, "..") == 0) {
-               err = VFS_ROOT(dvp->v_vfsp, vpp);
-       } else {
-               err = gfs_vop_lookup(dvp, nm, vpp, pnp, flags, rdir,
-                   cr, ct, direntflags, realpnp);
-       }
-
-       ZFS_EXIT(zfsvfs);
-
-       return (err);
-}
-
-static int
-zfsctl_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
-    caller_context_t *ct)
-{
-       /*
-        * We only care about ACL_ENABLED so that libsec can
-        * display ACL correctly and not default to POSIX draft.
-        */
-       if (cmd == _PC_ACL_ENABLED) {
-               *valp = _ACL_ACE_ENABLED;
-               return (0);
-       }
-
-       return (fs_pathconf(vp, cmd, valp, cr, ct));
-}
-
-static const fs_operation_def_t zfsctl_tops_root[] = {
-       { VOPNAME_OPEN,         { .vop_open = zfsctl_common_open }      },
-       { VOPNAME_CLOSE,        { .vop_close = zfsctl_common_close }    },
-       { VOPNAME_IOCTL,        { .error = fs_inval }                   },
-       { VOPNAME_GETATTR,      { .vop_getattr = zfsctl_root_getattr }  },
-       { VOPNAME_ACCESS,       { .vop_access = zfsctl_common_access }  },
-       { VOPNAME_READDIR,      { .vop_readdir = gfs_vop_readdir }      },
-       { VOPNAME_LOOKUP,       { .vop_lookup = zfsctl_root_lookup }    },
-       { VOPNAME_SEEK,         { .vop_seek = fs_seek }                 },
-       { VOPNAME_INACTIVE,     { .vop_inactive = gfs_vop_inactive }    },
-       { VOPNAME_PATHCONF,     { .vop_pathconf = zfsctl_pathconf }     },
-       { VOPNAME_FID,          { .vop_fid = zfsctl_common_fid  }       },
-       { NULL }
-};
-
-static int
-zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname)
-{
-       objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os;
-
-       if (snapshot_namecheck(name, NULL, NULL) != 0)
-               return (EILSEQ);
-       dmu_objset_name(os, zname);
-       if (strlen(zname) + 1 + strlen(name) >= len)
-               return (ENAMETOOLONG);
-       (void) strcat(zname, "@");
-       (void) strcat(zname, name);
-       return (0);
-}
-
-static int
-zfsctl_unmount_snap(zfs_snapentry_t *sep, int fflags, cred_t *cr)
-{
-       vnode_t *svp = sep->se_root;
-       int error;
-
-       ASSERT(vn_ismntpt(svp));
-
-       /* this will be dropped by dounmount() */
-       if ((error = vn_vfswlock(svp)) != 0)
-               return (error);
-
-       VN_HOLD(svp);
-       error = dounmount(vn_mountedvfs(svp), fflags, cr);
-       if (error) {
-               VN_RELE(svp);
-               return (error);
-       }
-
-       /*
-        * We can't use VN_RELE(), as that will try to invoke
-        * zfsctl_snapdir_inactive(), which would cause us to destroy
-        * the sd_lock mutex held by our caller.
-        */
-       ASSERT(svp->v_count == 1);
-       gfs_vop_inactive(svp, cr, NULL);
-
-       kmem_free(sep->se_name, strlen(sep->se_name) + 1);
-       kmem_free(sep, sizeof (zfs_snapentry_t));
-
-       return (0);
-}
-
-static void
-zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm)
-{
-       avl_index_t where;
-       vfs_t *vfsp;
-       refstr_t *pathref;
-       char newpath[MAXNAMELEN];
-       char *tail;
-
-       ASSERT(MUTEX_HELD(&sdp->sd_lock));
-       ASSERT(sep != NULL);
-
-       vfsp = vn_mountedvfs(sep->se_root);
-       ASSERT(vfsp != NULL);
-
-       vfs_lock_wait(vfsp);
-
-       /*
-        * Change the name in the AVL tree.
-        */
-       avl_remove(&sdp->sd_snaps, sep);
-       kmem_free(sep->se_name, strlen(sep->se_name) + 1);
-       sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP);
-       (void) strcpy(sep->se_name, nm);
-       VERIFY(avl_find(&sdp->sd_snaps, sep, &where) == NULL);
-       avl_insert(&sdp->sd_snaps, sep, where);
-
-       /*
-        * Change the current mountpoint info:
-        *      - update the tail of the mntpoint path
-        *      - update the tail of the resource path
-        */
-       pathref = vfs_getmntpoint(vfsp);
-       (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath));
-       VERIFY((tail = strrchr(newpath, '/')) != NULL);
-       *(tail+1) = '\0';
-       ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath));
-       (void) strcat(newpath, nm);
-       refstr_rele(pathref);
-       vfs_setmntpoint(vfsp, newpath, 0);
-
-       pathref = vfs_getresource(vfsp);
-       (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath));
-       VERIFY((tail = strrchr(newpath, '@')) != NULL);
-       *(tail+1) = '\0';
-       ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath));
-       (void) strcat(newpath, nm);
-       refstr_rele(pathref);
-       vfs_setresource(vfsp, newpath, 0);
-
-       vfs_unlock(vfsp);
-}
-
-/*ARGSUSED*/
-static int
-zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
-    cred_t *cr, caller_context_t *ct, int flags)
-{
-       zfsctl_snapdir_t *sdp = sdvp->v_data;
-       zfs_snapentry_t search, *sep;
-       zfsvfs_t *zfsvfs;
-       avl_index_t where;
-       char from[MAXNAMELEN], to[MAXNAMELEN];
-       char real[MAXNAMELEN];
-       int err;
-
-       zfsvfs = sdvp->v_vfsp->vfs_data;
-       ZFS_ENTER(zfsvfs);
-
-       if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
-               err = dmu_snapshot_realname(zfsvfs->z_os, snm, real,
-                   MAXNAMELEN, NULL);
-               if (err == 0) {
-                       snm = real;
-               } else if (err != ENOTSUP) {
-                       ZFS_EXIT(zfsvfs);
-                       return (err);
-               }
-       }
-
-       ZFS_EXIT(zfsvfs);
-
-       err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from);
-       if (!err)
-               err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to);
-       if (!err)
-               err = zfs_secpolicy_rename_perms(from, to, cr);
-       if (err)
-               return (err);
-
-       /*
-        * Cannot move snapshots out of the snapdir.
-        */
-       if (sdvp != tdvp)
-               return (EINVAL);
-
-       if (strcmp(snm, tnm) == 0)
-               return (0);
-
-       mutex_enter(&sdp->sd_lock);
-
-       search.se_name = (char *)snm;
-       if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) {
-               mutex_exit(&sdp->sd_lock);
-               return (ENOENT);
-       }
-
-       err = dmu_objset_rename(from, to, B_FALSE);
-       if (err == 0)
-               zfsctl_rename_snap(sdp, sep, tnm);
-
-       mutex_exit(&sdp->sd_lock);
-
-       return (err);
-}
-
-/* ARGSUSED */
-static int
-zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
-    caller_context_t *ct, int flags)
-{
-       zfsctl_snapdir_t *sdp = dvp->v_data;
-       zfs_snapentry_t *sep;
-       zfs_snapentry_t search;
-       zfsvfs_t *zfsvfs;
-       char snapname[MAXNAMELEN];
-       char real[MAXNAMELEN];
-       int err;
-
-       zfsvfs = dvp->v_vfsp->vfs_data;
-       ZFS_ENTER(zfsvfs);
-
-       if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
-
-               err = dmu_snapshot_realname(zfsvfs->z_os, name, real,
-                   MAXNAMELEN, NULL);
-               if (err == 0) {
-                       name = real;
-               } else if (err != ENOTSUP) {
-                       ZFS_EXIT(zfsvfs);
-                       return (err);
-               }
-       }
-
-       ZFS_EXIT(zfsvfs);
-
-       err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname);
-       if (!err)
-               err = zfs_secpolicy_destroy_perms(snapname, cr);
-       if (err)
-               return (err);
-
-       mutex_enter(&sdp->sd_lock);
-
-       search.se_name = name;
-       sep = avl_find(&sdp->sd_snaps, &search, NULL);
-       if (sep) {
-               avl_remove(&sdp->sd_snaps, sep);
-               err = zfsctl_unmount_snap(sep, MS_FORCE, cr);
-               if (err)
-                       avl_add(&sdp->sd_snaps, sep);
-               else
-                       err = dmu_objset_destroy(snapname, B_FALSE);
-       } else {
-               err = ENOENT;
-       }
-
-       mutex_exit(&sdp->sd_lock);
-
-       return (err);
-}
-
-/*
- * This creates a snapshot under '.zfs/snapshot'.
- */
-/* ARGSUSED */
-static int
-zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t  **vpp,
-    cred_t *cr, caller_context_t *cc, int flags, vsecattr_t *vsecp)
-{
-       zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
-       char name[MAXNAMELEN];
-       int err;
-       static enum symfollow follow = NO_FOLLOW;
-       static enum uio_seg seg = UIO_SYSSPACE;
-
-       if (snapshot_namecheck(dirname, NULL, NULL) != 0)
-               return (EILSEQ);
-
-       dmu_objset_name(zfsvfs->z_os, name);
-
-       *vpp = NULL;
-
-       err = zfs_secpolicy_snapshot_perms(name, cr);
-       if (err)
-               return (err);
-
-       if (err == 0) {
-               err = dmu_objset_snapshot(name, dirname, NULL, NULL,
-                   B_FALSE, B_FALSE, -1);
-               if (err)
-                       return (err);
-               err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp);
-       }
-
-       return (err);
-}
-
-/*
- * Lookup entry point for the 'snapshot' directory.  Try to open the
- * snapshot if it exist, creating the pseudo filesystem vnode as necessary.
- * Perform a mount of the associated dataset on top of the vnode.
- */
-/* ARGSUSED */
-static int
-zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
-    int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
-    int *direntflags, pathname_t *realpnp)
-{
-       zfsctl_snapdir_t *sdp = dvp->v_data;
-       objset_t *snap;
-       char snapname[MAXNAMELEN];
-       char real[MAXNAMELEN];
-       char *mountpoint;
-       zfs_snapentry_t *sep, search;
-       struct mounta margs;
-       vfs_t *vfsp;
-       size_t mountpoint_len;
-       avl_index_t where;
-       zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
-       int err;
-
-       /*
-        * No extended attributes allowed under .zfs
-        */
-       if (flags & LOOKUP_XATTR)
-               return (EINVAL);
-
-       ASSERT(dvp->v_type == VDIR);
-
-       /*
-        * If we get a recursive call, that means we got called
-        * from the domount() code while it was trying to look up the
-        * spec (which looks like a local path for zfs).  We need to
-        * add some flag to domount() to tell it not to do this lookup.
-        */
-       if (MUTEX_HELD(&sdp->sd_lock))
-               return (ENOENT);
-
-       ZFS_ENTER(zfsvfs);
-
-       if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0) {
-               ZFS_EXIT(zfsvfs);
-               return (0);
-       }
-
-       if (flags & FIGNORECASE) {
-               boolean_t conflict = B_FALSE;
-
-               err = dmu_snapshot_realname(zfsvfs->z_os, nm, real,
-                   MAXNAMELEN, &conflict);
-               if (err == 0) {
-                       nm = real;
-               } else if (err != ENOTSUP) {
-                       ZFS_EXIT(zfsvfs);
-                       return (err);
-               }
-               if (realpnp)
-                       (void) strlcpy(realpnp->pn_buf, nm,
-                           realpnp->pn_bufsize);
-               if (conflict && direntflags)
-                       *direntflags = ED_CASE_CONFLICT;
-       }
-
-       mutex_enter(&sdp->sd_lock);
-       search.se_name = (char *)nm;
-       if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) {
-               *vpp = sep->se_root;
-               VN_HOLD(*vpp);
-               err = traverse(vpp);
-               if (err) {
-                       VN_RELE(*vpp);
-                       *vpp = NULL;
-               } else if (*vpp == sep->se_root) {
-                       /*
-                        * The snapshot was unmounted behind our backs,
-                        * try to remount it.
-                        */
-                       goto domount;
-               } else {
-                       /*
-                        * VROOT was set during the traverse call.  We need
-                        * to clear it since we're pretending to be part
-                        * of our parent's vfs.
-                        */
-                       (*vpp)->v_flag &= ~VROOT;
-               }
-               mutex_exit(&sdp->sd_lock);
-               ZFS_EXIT(zfsvfs);
-               return (err);
-       }
-
-       /*
-        * The requested snapshot is not currently mounted, look it up.
-        */
-       err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname);
-       if (err) {
-               mutex_exit(&sdp->sd_lock);
-               ZFS_EXIT(zfsvfs);
-               /*
-                * handle "ls *" or "?" in a graceful manner,
-                * forcing EILSEQ to ENOENT.
-                * Since shell ultimately passes "*" or "?" as name to lookup
-                */
-               return (err == EILSEQ ? ENOENT : err);
-       }
-       if (dmu_objset_hold(snapname, FTAG, &snap) != 0) {
-               mutex_exit(&sdp->sd_lock);
-               ZFS_EXIT(zfsvfs);
-               return (ENOENT);
-       }
-
-       sep = kmem_alloc(sizeof (zfs_snapentry_t), KM_SLEEP);
-       sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP);
-       (void) strcpy(sep->se_name, nm);
-       *vpp = sep->se_root = zfsctl_snapshot_mknode(dvp, dmu_objset_id(snap));
-       avl_insert(&sdp->sd_snaps, sep, where);
-
-       dmu_objset_rele(snap, FTAG);
-domount:
-       mountpoint_len = strlen(refstr_value(dvp->v_vfsp->vfs_mntpt)) +
-           strlen("/.zfs/snapshot/") + strlen(nm) + 1;
-       mountpoint = kmem_alloc(mountpoint_len, KM_SLEEP);
-       (void) snprintf(mountpoint, mountpoint_len, "%s/.zfs/snapshot/%s",
-           refstr_value(dvp->v_vfsp->vfs_mntpt), nm);
-
-       margs.spec = snapname;
-       margs.dir = mountpoint;
-       margs.flags = MS_SYSSPACE | MS_NOMNTTAB;
-       margs.fstype = "zfs";
-       margs.dataptr = NULL;
-       margs.datalen = 0;
-       margs.optptr = NULL;
-       margs.optlen = 0;
-
-       err = domount("zfs", &margs, *vpp, kcred, &vfsp);
-       kmem_free(mountpoint, mountpoint_len);
-
-       if (err == 0) {
-               /*
-                * Return the mounted root rather than the covered mount point.
-                * Takes the GFS vnode at .zfs/snapshot/<snapname> and returns
-                * the ZFS vnode mounted on top of the GFS node.  This ZFS
-                * vnode is the root of the newly created vfsp.
-                */
-               VFS_RELE(vfsp);
-               err = traverse(vpp);
-       }
-
-       if (err == 0) {
-               /*
-                * Fix up the root vnode mounted on .zfs/snapshot/<snapname>.
-                *
-                * This is where we lie about our v_vfsp in order to
-                * make .zfs/snapshot/<snapname> accessible over NFS
-                * without requiring manual mounts of <snapname>.
-                */
-               ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs);
-               VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs;
-               (*vpp)->v_vfsp = zfsvfs->z_vfs;
-               (*vpp)->v_flag &= ~VROOT;
-       }
-       mutex_exit(&sdp->sd_lock);
-       ZFS_EXIT(zfsvfs);
-
-       /*
-        * If we had an error, drop our hold on the vnode and
-        * zfsctl_snapshot_inactive() will clean up.
-        */
-       if (err) {
-               VN_RELE(*vpp);
-               *vpp = NULL;
-       }
-       return (err);
-}
-
-/* ARGSUSED */
-static int
-zfsctl_shares_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
-    int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct,
-    int *direntflags, pathname_t *realpnp)
-{
-       zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data;
-       znode_t *dzp;
-       int error;
-
-       ZFS_ENTER(zfsvfs);
-
-       if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0) {
-               ZFS_EXIT(zfsvfs);
-               return (0);
-       }
-
-       if (zfsvfs->z_shares_dir == 0) {
-               ZFS_EXIT(zfsvfs);
-               return (ENOTSUP);
-       }
-       if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0)
-               error = VOP_LOOKUP(ZTOV(dzp), nm, vpp, pnp,
-                   flags, rdir, cr, ct, direntflags, realpnp);
-
-       VN_RELE(ZTOV(dzp));
-       ZFS_EXIT(zfsvfs);
-
-       return (error);
-}
-
-/* ARGSUSED */
-static int
-zfsctl_snapdir_readdir_cb(vnode_t *vp, void *dp, int *eofp,
-    offset_t *offp, offset_t *nextp, void *data, int flags)
-{
-       zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
-       char snapname[MAXNAMELEN];
-       uint64_t id, cookie;
-       boolean_t case_conflict;
-       int error;
-
-       ZFS_ENTER(zfsvfs);
-
-       cookie = *offp;
-       error = dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id,
-           &cookie, &case_conflict);
-       if (error) {
-               ZFS_EXIT(zfsvfs);
-               if (error == ENOENT) {
-                       *eofp = 1;
-                       return (0);
-               }
-               return (error);
-       }
-
-       if (flags & V_RDDIR_ENTFLAGS) {
-               edirent_t *eodp = dp;
-
-               (void) strcpy(eodp->ed_name, snapname);
-               eodp->ed_ino = ZFSCTL_INO_SNAP(id);
-               eodp->ed_eflags = case_conflict ? ED_CASE_CONFLICT : 0;
-       } else {
-               struct dirent64 *odp = dp;
-
-               (void) strcpy(odp->d_name, snapname);
-               odp->d_ino = ZFSCTL_INO_SNAP(id);
-       }
-       *nextp = cookie;
-
-       ZFS_EXIT(zfsvfs);
-
-       return (0);
-}
-
-/* ARGSUSED */
-static int
-zfsctl_shares_readdir(vnode_t *vp, uio_t *uiop, cred_t *cr, int *eofp,
-    caller_context_t *ct, int flags)
-{
-       zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
-       znode_t *dzp;
-       int error;
-
-       ZFS_ENTER(zfsvfs);
-
-       if (zfsvfs->z_shares_dir == 0) {
-               ZFS_EXIT(zfsvfs);
-               return (ENOTSUP);
-       }
-       if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) {
-               error = VOP_READDIR(ZTOV(dzp), uiop, cr, eofp, ct, flags);
-               VN_RELE(ZTOV(dzp));
-       } else {
-               *eofp = 1;
-               error = ENOENT;
-       }
-
-       ZFS_EXIT(zfsvfs);
-       return (error);
-}
-
-/*
- * pvp is the '.zfs' directory (zfsctl_node_t).
- * Creates vp, which is '.zfs/snapshot' (zfsctl_snapdir_t).
- *
- * This function is the callback to create a GFS vnode for '.zfs/snapshot'
- * when a lookup is performed on .zfs for "snapshot".
- */
-vnode_t *
-zfsctl_mknode_snapdir(vnode_t *pvp)
-{
-       vnode_t *vp;
-       zfsctl_snapdir_t *sdp;
-
-       vp = gfs_dir_create(sizeof (zfsctl_snapdir_t), pvp,
-           zfsctl_ops_snapdir, NULL, NULL, MAXNAMELEN,
-           zfsctl_snapdir_readdir_cb, NULL);
-       sdp = vp->v_data;
-       sdp->sd_node.zc_id = ZFSCTL_INO_SNAPDIR;
-       sdp->sd_node.zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime;
-       mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL);
-       avl_create(&sdp->sd_snaps, snapentry_compare,
-           sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node));
-       return (vp);
-}
-
-vnode_t *
-zfsctl_mknode_shares(vnode_t *pvp)
-{
-       vnode_t *vp;
-       zfsctl_node_t *sdp;
-
-       vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp,
-           zfsctl_ops_shares, NULL, NULL, MAXNAMELEN,
-           NULL, NULL);
-       sdp = vp->v_data;
-       sdp->zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime;
-       return (vp);
-
-}
-
-/* ARGSUSED */
-static int
-zfsctl_shares_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct)
-{
-       zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
-       znode_t *dzp;
-       int error;
-
-       ZFS_ENTER(zfsvfs);
-       if (zfsvfs->z_shares_dir == 0) {
-               ZFS_EXIT(zfsvfs);
-               return (ENOTSUP);
-       }
-       if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) {
-               error = VOP_GETATTR(ZTOV(dzp), vap, flags, cr, ct);
-               VN_RELE(ZTOV(dzp));
-       }
-       ZFS_EXIT(zfsvfs);
-       return (error);
-
-
-}
-
-/* ARGSUSED */
-static int
-zfsctl_snapdir_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct)
-{
-       zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data;
-       zfsctl_snapdir_t *sdp = vp->v_data;
-
-       ZFS_ENTER(zfsvfs);
-       zfsctl_common_getattr(vp, vap);
-       vap->va_nodeid = gfs_file_inode(vp);
-       vap->va_nlink = vap->va_size = avl_numnodes(&sdp->sd_snaps) + 2;
-       vap->va_ctime = vap->va_mtime = dmu_objset_snap_cmtime(zfsvfs->z_os);
-       ZFS_EXIT(zfsvfs);
-
-       return (0);
-}
-
-/* ARGSUSED */
-static void
-zfsctl_snapdir_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
-{
-       zfsctl_snapdir_t *sdp = vp->v_data;
-       void *private;
-
-       private = gfs_dir_inactive(vp);
-       if (private != NULL) {
-               ASSERT(avl_numnodes(&sdp->sd_snaps) == 0);
-               mutex_destroy(&sdp->sd_lock);
-               avl_destroy(&sdp->sd_snaps);
-               kmem_free(private, sizeof (zfsctl_snapdir_t));
-       }
-}
-
-static const fs_operation_def_t zfsctl_tops_snapdir[] = {
-       { VOPNAME_OPEN,         { .vop_open = zfsctl_common_open }      },
-       { VOPNAME_CLOSE,        { .vop_close = zfsctl_common_close }    },
-       { VOPNAME_IOCTL,        { .error = fs_inval }                   },
-       { VOPNAME_GETATTR,      { .vop_getattr = zfsctl_snapdir_getattr } },
-       { VOPNAME_ACCESS,       { .vop_access = zfsctl_common_access }  },
-       { VOPNAME_RENAME,       { .vop_rename = zfsctl_snapdir_rename } },
-       { VOPNAME_RMDIR,        { .vop_rmdir = zfsctl_snapdir_remove }  },
-       { VOPNAME_MKDIR,        { .vop_mkdir = zfsctl_snapdir_mkdir }   },
-       { VOPNAME_READDIR,      { .vop_readdir = gfs_vop_readdir }      },
-       { VOPNAME_LOOKUP,       { .vop_lookup = zfsctl_snapdir_lookup } },
-       { VOPNAME_SEEK,         { .vop_seek = fs_seek }                 },
-       { VOPNAME_INACTIVE,     { .vop_inactive = zfsctl_snapdir_inactive } },
-       { VOPNAME_FID,          { .vop_fid = zfsctl_common_fid }        },
-       { NULL }
-};
-
-static const fs_operation_def_t zfsctl_tops_shares[] = {
-       { VOPNAME_OPEN,         { .vop_open = zfsctl_common_open }      },
-       { VOPNAME_CLOSE,        { .vop_close = zfsctl_common_close }    },
-       { VOPNAME_IOCTL,        { .error = fs_inval }                   },
-       { VOPNAME_GETATTR,      { .vop_getattr = zfsctl_shares_getattr } },
-       { VOPNAME_ACCESS,       { .vop_access = zfsctl_common_access }  },
-       { VOPNAME_READDIR,      { .vop_readdir = zfsctl_shares_readdir } },
-       { VOPNAME_LOOKUP,       { .vop_lookup = zfsctl_shares_lookup }  },
-       { VOPNAME_SEEK,         { .vop_seek = fs_seek }                 },
-       { VOPNAME_INACTIVE,     { .vop_inactive = gfs_vop_inactive } },
-       { VOPNAME_FID,          { .vop_fid = zfsctl_shares_fid } },
-       { NULL }
-};
-
-/*
- * pvp is the GFS vnode '.zfs/snapshot'.
- *
- * This creates a GFS node under '.zfs/snapshot' representing each
- * snapshot.  This newly created GFS node is what we mount snapshot
- * vfs_t's ontop of.
- */
-static vnode_t *
-zfsctl_snapshot_mknode(vnode_t *pvp, uint64_t objset)
-{
-       vnode_t *vp;
-       zfsctl_node_t *zcp;
-
-       vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp,
-           zfsctl_ops_snapshot, NULL, NULL, MAXNAMELEN, NULL, NULL);
-       zcp = vp->v_data;
-       zcp->zc_id = objset;
-
-       return (vp);
-}
-
-static void
-zfsctl_snapshot_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
-{
-       zfsctl_snapdir_t *sdp;
-       zfs_snapentry_t *sep, *next;
-       vnode_t *dvp;
-
-       VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr, 0, NULL, NULL) == 0);
-       sdp = dvp->v_data;
-
-       mutex_enter(&sdp->sd_lock);
-
-       if (vp->v_count > 1) {
-               mutex_exit(&sdp->sd_lock);
-               return;
-       }
-       ASSERT(!vn_ismntpt(vp));
-
-       sep = avl_first(&sdp->sd_snaps);
-       while (sep != NULL) {
-               next = AVL_NEXT(&sdp->sd_snaps, sep);
-
-               if (sep->se_root == vp) {
-                       avl_remove(&sdp->sd_snaps, sep);
-                       kmem_free(sep->se_name, strlen(sep->se_name) + 1);
-                       kmem_free(sep, sizeof (zfs_snapentry_t));
-                       break;
-               }
-               sep = next;
-       }
-       ASSERT(sep != NULL);
-
-       mutex_exit(&sdp->sd_lock);
-       VN_RELE(dvp);
-
-       /*
-        * Dispose of the vnode for the snapshot mount point.
-        * This is safe to do because once this entry has been removed
-        * from the AVL tree, it can't be found again, so cannot become
-        * "active".  If we lookup the same name again we will end up
-        * creating a new vnode.
-        */
-       gfs_vop_inactive(vp, cr, ct);
-}
-
-
-/*
- * These VP's should never see the light of day.  They should always
- * be covered.
- */
-static const fs_operation_def_t zfsctl_tops_snapshot[] = {
-       VOPNAME_INACTIVE, { .vop_inactive =  zfsctl_snapshot_inactive },
-       NULL, NULL
-};
-
-int
-zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp)
-{
-       zfsvfs_t *zfsvfs = vfsp->vfs_data;
-       vnode_t *dvp, *vp;
-       zfsctl_snapdir_t *sdp;
-       zfsctl_node_t *zcp;
-       zfs_snapentry_t *sep;
-       int error;
-
-       ASSERT(zfsvfs->z_ctldir != NULL);
-       error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
-           NULL, 0, NULL, kcred, NULL, NULL, NULL);
-       if (error != 0)
-               return (error);
-       sdp = dvp->v_data;
-
-       mutex_enter(&sdp->sd_lock);
-       sep = avl_first(&sdp->sd_snaps);
-       while (sep != NULL) {
-               vp = sep->se_root;
-               zcp = vp->v_data;
-               if (zcp->zc_id == objsetid)
-                       break;
-
-               sep = AVL_NEXT(&sdp->sd_snaps, sep);
-       }
-
-       if (sep != NULL) {
-               VN_HOLD(vp);
-               /*
-                * Return the mounted root rather than the covered mount point.
-                * Takes the GFS vnode at .zfs/snapshot/<snapshot objsetid>
-                * and returns the ZFS vnode mounted on top of the GFS node.
-                * This ZFS vnode is the root of the vfs for objset 'objsetid'.
-                */
-               error = traverse(&vp);
-               if (error == 0) {
-                       if (vp == sep->se_root)
-                               error = EINVAL;
-                       else
-                               *zfsvfsp = VTOZ(vp)->z_zfsvfs;
-               }
-               mutex_exit(&sdp->sd_lock);
-               VN_RELE(vp);
-       } else {
-               error = EINVAL;
-               mutex_exit(&sdp->sd_lock);
-       }
-
-       VN_RELE(dvp);
-
-       return (error);
-}
-
-/*
- * Unmount any snapshots for the given filesystem.  This is called from
- * zfs_umount() - if we have a ctldir, then go through and unmount all the
- * snapshots.
- */
-int
-zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr)
-{
-       zfsvfs_t *zfsvfs = vfsp->vfs_data;
-       vnode_t *dvp;
-       zfsctl_snapdir_t *sdp;
-       zfs_snapentry_t *sep, *next;
-       int error;
-
-       ASSERT(zfsvfs->z_ctldir != NULL);
-       error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
-           NULL, 0, NULL, cr, NULL, NULL, NULL);
-       if (error != 0)
-               return (error);
-       sdp = dvp->v_data;
-
-       mutex_enter(&sdp->sd_lock);
-
-       sep = avl_first(&sdp->sd_snaps);
-       while (sep != NULL) {
-               next = AVL_NEXT(&sdp->sd_snaps, sep);
-
-               /*
-                * If this snapshot is not mounted, then it must
-                * have just been unmounted by somebody else, and
-                * will be cleaned up by zfsctl_snapdir_inactive().
-                */
-               if (vn_ismntpt(sep->se_root)) {
-                       avl_remove(&sdp->sd_snaps, sep);
-                       error = zfsctl_unmount_snap(sep, fflags, cr);
-                       if (error) {
-                               avl_add(&sdp->sd_snaps, sep);
-                               break;
-                       }
-               }
-               sep = next;
-       }
-
-       mutex_exit(&sdp->sd_lock);
-       VN_RELE(dvp);
-
-       return (error);
-}
-#endif /* HAVE_ZPL */
index f0084cd..f54ed19 100644 (file)
@@ -22,7 +22,6 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#ifdef HAVE_ZPL
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -51,7 +50,6 @@
 #include <sys/zap.h>
 #include <sys/dmu.h>
 #include <sys/atomic.h>
-#include <sys/zfs_ctldir.h>
 #include <sys/zfs_fuid.h>
 #include <sys/sa.h>
 #include <sys/zfs_sa.h>
  * of names after deciding which is the appropriate lookup interface.
  */
 static int
-zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, boolean_t exact,
+zfs_match_find(zfs_sb_t *zsb, znode_t *dzp, char *name, boolean_t exact,
     boolean_t update, int *deflags, pathname_t *rpnp, uint64_t *zoid)
 {
        int error;
 
-       if (zfsvfs->z_norm) {
+       if (zsb->z_norm) {
                matchtype_t mt = MT_FIRST;
                boolean_t conflict = B_FALSE;
                size_t bufsz = 0;
@@ -84,17 +82,19 @@ zfs_match_find(zfsvfs_t *zfsvfs, znode_t *dzp, char *name, boolean_t exact,
                 * In the non-mixed case we only expect there would ever
                 * be one match, but we need to use the normalizing lookup.
                 */
-               error = zap_lookup_norm(zfsvfs->z_os, dzp->z_id, name, 8, 1,
+               error = zap_lookup_norm(zsb->z_os, dzp->z_id, name, 8, 1,
                    zoid, mt, buf, bufsz, &conflict);
                if (!error && deflags)
                        *deflags = conflict ? ED_CASE_CONFLICT : 0;
        } else {
-               error = zap_lookup(zfsvfs->z_os, dzp->z_id, name, 8, 1, zoid);
+               error = zap_lookup(zsb->z_os, dzp->z_id, name, 8, 1, zoid);
        }
        *zoid = ZFS_DIRENT_OBJ(*zoid);
 
+#ifdef HAVE_DNLC
        if (error == ENOENT && update)
-               dnlc_update(ZTOV(dzp), name, DNLC_NO_VNODE);
+               dnlc_update(ZTOI(dzp), name, DNLC_NO_VNODE);
+#endif /* HAVE_DNLC */
 
        return (error);
 }
@@ -138,12 +138,14 @@ int
 zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
     int flag, int *direntflags, pathname_t *realpnp)
 {
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(dzp);
        zfs_dirlock_t   *dl;
        boolean_t       update;
        boolean_t       exact;
        uint64_t        zoid;
+#ifdef HAVE_DNLC
        vnode_t         *vp = NULL;
+#endif /* HAVE_DNLC */
        int             error = 0;
        int             cmpflags;
 
@@ -153,15 +155,15 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
        /*
         * Verify that we are not trying to lock '.', '..', or '.zfs'
         */
-       if (name[0] == '.' &&
-           (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) ||
-           zfs_has_ctldir(dzp) && strcmp(name, ZFS_CTLDIR_NAME) == 0)
+       if ((name[0] == '.' &&
+           (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) ||
+           (zfs_has_ctldir(dzp) && strcmp(name, ZFS_CTLDIR_NAME) == 0))
                return (EEXIST);
 
        /*
         * Case sensitivity and normalization preferences are set when
         * the file system is created.  These are stored in the
-        * zfsvfs->z_case and zfsvfs->z_norm fields.  These choices
+        * zsb->z_case and zsb->z_norm fields.  These choices
         * affect what vnodes can be cached in the DNLC, how we
         * perform zap lookups, and the "width" of our dirlocks.
         *
@@ -181,8 +183,8 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
         * access.
         */
        exact =
-           ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE) && (flag & ZCIEXACT)) ||
-           ((zfsvfs->z_case == ZFS_CASE_MIXED) && !(flag & ZCILOOK));
+           ((zsb->z_case == ZFS_CASE_INSENSITIVE) && (flag & ZCIEXACT)) ||
+           ((zsb->z_case == ZFS_CASE_MIXED) && !(flag & ZCILOOK));
 
        /*
         * Only look in or update the DNLC if we are looking for the
@@ -194,9 +196,9 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
         * Maybe can add TO-UPPERed version of name to dnlc in ci-only
         * case for performance improvement?
         */
-       update = !zfsvfs->z_norm ||
-           ((zfsvfs->z_case == ZFS_CASE_MIXED) &&
-           !(zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER) && !(flag & ZCILOOK));
+       update = !zsb->z_norm ||
+           ((zsb->z_case == ZFS_CASE_MIXED) &&
+           !(zsb->z_norm & ~U8_TEXTPREP_TOUPPER) && !(flag & ZCILOOK));
 
        /*
         * ZRENAMING indicates we are in a situation where we should
@@ -209,7 +211,7 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
        if (flag & ZRENAMING)
                cmpflags = 0;
        else
-               cmpflags = zfsvfs->z_norm;
+               cmpflags = zsb->z_norm;
 
        /*
         * Wait until there are no locks on this name.
@@ -289,29 +291,34 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
         * See if there's an object by this name; if so, put a hold on it.
         */
        if (flag & ZXATTR) {
-               error = sa_lookup(dzp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &zoid,
+               error = sa_lookup(dzp->z_sa_hdl, SA_ZPL_XATTR(zsb), &zoid,
                    sizeof (zoid));
                if (error == 0)
                        error = (zoid == 0 ? ENOENT : 0);
        } else {
+#ifdef HAVE_DNLC
                if (update)
-                       vp = dnlc_lookup(ZTOV(dzp), name);
+                       vp = dnlc_lookup(ZTOI(dzp), name);
                if (vp == DNLC_NO_VNODE) {
-                       VN_RELE(vp);
+                       iput(vp);
                        error = ENOENT;
                } else if (vp) {
                        if (flag & ZNEW) {
                                zfs_dirent_unlock(dl);
-                               VN_RELE(vp);
+                               iput(vp);
                                return (EEXIST);
                        }
                        *dlpp = dl;
                        *zpp = VTOZ(vp);
                        return (0);
                } else {
-                       error = zfs_match_find(zfsvfs, dzp, name, exact,
+                       error = zfs_match_find(zsb, dzp, name, exact,
                            update, direntflags, realpnp, &zoid);
                }
+#else
+               error = zfs_match_find(zsb, dzp, name, exact,
+                   update, direntflags, realpnp, &zoid);
+#endif /* HAVE_DNLC */
        }
        if (error) {
                if (error != ENOENT || (flag & ZEXISTS)) {
@@ -323,13 +330,15 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
                        zfs_dirent_unlock(dl);
                        return (EEXIST);
                }
-               error = zfs_zget(zfsvfs, zoid, zpp);
+               error = zfs_zget(zsb, zoid, zpp);
                if (error) {
                        zfs_dirent_unlock(dl);
                        return (error);
                }
+#ifdef HAVE_DNLC
                if (!(flag & ZXATTR) && update)
-                       dnlc_update(ZTOV(dzp), name, ZTOV(*zpp));
+                       dnlc_update(ZTOI(dzp), name, ZTOI(*zpp));
+#endif /* HAVE_DNLC */
        }
 
        *dlpp = dl;
@@ -378,7 +387,7 @@ zfs_dirent_unlock(zfs_dirlock_t *dl)
  *     special pseudo-directory.
  */
 int
-zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags,
+zfs_dirlook(znode_t *dzp, char *name, struct inode **ipp, int flags,
     int *deflg, pathname_t *rpnp)
 {
        zfs_dirlock_t *dl;
@@ -387,31 +396,35 @@ zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags,
        uint64_t parent;
 
        if (name[0] == 0 || (name[0] == '.' && name[1] == 0)) {
-               *vpp = ZTOV(dzp);
-               VN_HOLD(*vpp);
+               *ipp = ZTOI(dzp);
+               igrab(*ipp);
        } else if (name[0] == '.' && name[1] == '.' && name[2] == 0) {
-               zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
+               zfs_sb_t *zsb = ZTOZSB(dzp);
 
                /*
                 * If we are a snapshot mounted under .zfs, return
                 * the vp for the snapshot directory.
                 */
                if ((error = sa_lookup(dzp->z_sa_hdl,
-                   SA_ZPL_PARENT(zfsvfs), &parent, sizeof (parent))) != 0)
+                   SA_ZPL_PARENT(zsb), &parent, sizeof (parent))) != 0)
                        return (error);
-               if (parent == dzp->z_id && zfsvfs->z_parent != zfsvfs) {
-                       error = zfsctl_root_lookup(zfsvfs->z_parent->z_ctldir,
-                           "snapshot", vpp, NULL, 0, NULL, kcred,
+#ifdef HAVE_SNAPSHOT
+               if (parent == dzp->z_id && zsb->z_parent != zsb) {
+                       error = zfsctl_root_lookup(zsb->z_parent->z_ctldir,
+                           "snapshot", ipp, NULL, 0, NULL, kcred,
                            NULL, NULL, NULL);
                        return (error);
                }
+#endif /* HAVE_SNAPSHOT */
                rw_enter(&dzp->z_parent_lock, RW_READER);
-               error = zfs_zget(zfsvfs, parent, &zp);
+               error = zfs_zget(zsb, parent, &zp);
                if (error == 0)
-                       *vpp = ZTOV(zp);
+                       *ipp = ZTOI(zp);
                rw_exit(&dzp->z_parent_lock);
+#ifdef HAVE_SNAPSHOT
        } else if (zfs_has_ctldir(dzp) && strcmp(name, ZFS_CTLDIR_NAME) == 0) {
-               *vpp = zfsctl_root(dzp);
+               *ipp = zfsctl_root(dzp);
+#endif /* HAVE_SNAPSHOT */
        } else {
                int zf;
 
@@ -421,7 +434,7 @@ zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags,
 
                error = zfs_dirent_lock(&dl, dzp, name, &zp, zf, deflg, rpnp);
                if (error == 0) {
-                       *vpp = ZTOV(zp);
+                       *ipp = ZTOI(zp);
                        zfs_dirent_unlock(dl);
                        dzp->z_zn_prefetch = B_TRUE; /* enable prefetching */
                }
@@ -451,13 +464,13 @@ zfs_dirlook(znode_t *dzp, char *name, vnode_t **vpp, int flags,
 void
 zfs_unlinked_add(znode_t *zp, dmu_tx_t *tx)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
 
        ASSERT(zp->z_unlinked);
        ASSERT(zp->z_links == 0);
 
        VERIFY3U(0, ==,
-           zap_add_int(zfsvfs->z_os, zfsvfs->z_unlinkedobj, zp->z_id, tx));
+           zap_add_int(zsb->z_os, zsb->z_unlinkedobj, zp->z_id, tx));
 }
 
 /*
@@ -465,7 +478,7 @@ zfs_unlinked_add(znode_t *zp, dmu_tx_t *tx)
  * (force) umounted the file system.
  */
 void
-zfs_unlinked_drain(zfsvfs_t *zfsvfs)
+zfs_unlinked_drain(zfs_sb_t *zsb)
 {
        zap_cursor_t    zc;
        zap_attribute_t zap;
@@ -476,7 +489,7 @@ zfs_unlinked_drain(zfsvfs_t *zfsvfs)
        /*
         * Interate over the contents of the unlinked set.
         */
-       for (zap_cursor_init(&zc, zfsvfs->z_os, zfsvfs->z_unlinkedobj);
+       for (zap_cursor_init(&zc, zsb->z_os, zsb->z_unlinkedobj);
            zap_cursor_retrieve(&zc, &zap) == 0;
            zap_cursor_advance(&zc)) {
 
@@ -484,8 +497,7 @@ zfs_unlinked_drain(zfsvfs_t *zfsvfs)
                 * See what kind of object we have in list
                 */
 
-               error = dmu_object_info(zfsvfs->z_os,
-                   zap.za_first_integer, &doi);
+               error = dmu_object_info(zsb->z_os, zap.za_first_integer, &doi);
                if (error != 0)
                        continue;
 
@@ -495,7 +507,7 @@ zfs_unlinked_drain(zfsvfs_t *zfsvfs)
                 * We need to re-mark these list entries for deletion,
                 * so we pull them back into core and set zp->z_unlinked.
                 */
-               error = zfs_zget(zfsvfs, zap.za_first_integer, &zp);
+               error = zfs_zget(zsb, zap.za_first_integer, &zp);
 
                /*
                 * We may pick up znodes that are already marked for deletion.
@@ -507,7 +519,7 @@ zfs_unlinked_drain(zfsvfs_t *zfsvfs)
                        continue;
 
                zp->z_unlinked = B_TRUE;
-               VN_RELE(ZTOV(zp));
+               iput(ZTOI(zp));
        }
        zap_cursor_fini(&zc);
 }
@@ -530,35 +542,34 @@ zfs_purgedir(znode_t *dzp)
        zap_attribute_t zap;
        znode_t         *xzp;
        dmu_tx_t        *tx;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(dzp);
        zfs_dirlock_t   dl;
        int skipped = 0;
        int error;
 
-       for (zap_cursor_init(&zc, zfsvfs->z_os, dzp->z_id);
+       for (zap_cursor_init(&zc, zsb->z_os, dzp->z_id);
            (error = zap_cursor_retrieve(&zc, &zap)) == 0;
            zap_cursor_advance(&zc)) {
-               error = zfs_zget(zfsvfs,
+               error = zfs_zget(zsb,
                    ZFS_DIRENT_OBJ(zap.za_first_integer), &xzp);
                if (error) {
                        skipped += 1;
                        continue;
                }
 
-               ASSERT((ZTOV(xzp)->v_type == VREG) ||
-                   (ZTOV(xzp)->v_type == VLNK));
+               ASSERT(S_ISREG(ZTOI(xzp)->i_mode)||S_ISLNK(ZTOI(xzp)->i_mode));
 
-               tx = dmu_tx_create(zfsvfs->z_os);
+               tx = dmu_tx_create(zsb->z_os);
                dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE);
                dmu_tx_hold_zap(tx, dzp->z_id, FALSE, zap.za_name);
                dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE);
-               dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
+               dmu_tx_hold_zap(tx, zsb->z_unlinkedobj, FALSE, NULL);
                /* Is this really needed ? */
                zfs_sa_upgrade_txholds(tx, xzp);
                error = dmu_tx_assign(tx, TXG_WAIT);
                if (error) {
                        dmu_tx_abort(tx);
-                       VN_RELE(ZTOV(xzp));
+                       iput(ZTOI(xzp));
                        skipped += 1;
                        continue;
                }
@@ -571,7 +582,7 @@ zfs_purgedir(znode_t *dzp)
                        skipped += 1;
                dmu_tx_commit(tx);
 
-               VN_RELE(ZTOV(xzp));
+               iput(ZTOI(xzp));
        }
        zap_cursor_fini(&zc);
        if (error != ENOENT)
@@ -582,8 +593,8 @@ zfs_purgedir(znode_t *dzp)
 void
 zfs_rmnode(znode_t *zp)
 {
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
-       objset_t        *os = zfsvfs->z_os;
+       zfs_sb_t        *zsb = ZTOZSB(zp);
+       objset_t        *os = zsb->z_os;
        znode_t         *xzp = NULL;
        dmu_tx_t        *tx;
        uint64_t        acl_obj;
@@ -591,19 +602,20 @@ zfs_rmnode(znode_t *zp)
        int             error;
 
        ASSERT(zp->z_links == 0);
-       ASSERT(ZTOV(zp)->v_count == 0);
+       ASSERT(atomic_read(&ZTOI(zp)->i_count) == 0);
 
        /*
         * If this is an attribute directory, purge its contents.
         */
-       if (ZTOV(zp)->v_type == VDIR && (zp->z_pflags & ZFS_XATTR)) {
+       if (S_ISDIR(ZTOI(zp)->i_mode) && (zp->z_pflags & ZFS_XATTR)) {
                if (zfs_purgedir(zp) != 0) {
                        /*
                         * Not enough space to delete some xattrs.
                         * Leave it in the unlinked set.
                         */
                        zfs_znode_dmu_fini(zp);
-                       zfs_znode_free(zp);
+                       zfs_inode_destroy(ZTOI(zp));
+
                        return;
                }
        }
@@ -617,7 +629,7 @@ zfs_rmnode(znode_t *zp)
                 * Not enough space.  Leave the file in the unlinked set.
                 */
                zfs_znode_dmu_fini(zp);
-               zfs_znode_free(zp);
+               zfs_inode_destroy(ZTOI(zp));
                return;
        }
 
@@ -625,10 +637,10 @@ zfs_rmnode(znode_t *zp)
         * If the file has extended attributes, we're going to unlink
         * the xattr dir.
         */
-       error = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs),
+       error = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zsb),
            &xattr_obj, sizeof (xattr_obj));
        if (error == 0 && xattr_obj) {
-               error = zfs_zget(zfsvfs, xattr_obj, &xzp);
+               error = zfs_zget(zsb, xattr_obj, &xzp);
                ASSERT(error == 0);
        }
 
@@ -639,9 +651,9 @@ zfs_rmnode(znode_t *zp)
         */
        tx = dmu_tx_create(os);
        dmu_tx_hold_free(tx, zp->z_id, 0, DMU_OBJECT_END);
-       dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
+       dmu_tx_hold_zap(tx, zsb->z_unlinkedobj, FALSE, NULL);
        if (xzp) {
-               dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, TRUE, NULL);
+               dmu_tx_hold_zap(tx, zsb->z_unlinkedobj, TRUE, NULL);
                dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE);
        }
        if (acl_obj)
@@ -657,7 +669,7 @@ zfs_rmnode(znode_t *zp)
                 */
                dmu_tx_abort(tx);
                zfs_znode_dmu_fini(zp);
-               zfs_znode_free(zp);
+               zfs_inode_destroy(ZTOI(zp));
                goto out;
        }
 
@@ -666,7 +678,7 @@ zfs_rmnode(znode_t *zp)
                mutex_enter(&xzp->z_lock);
                xzp->z_unlinked = B_TRUE;       /* mark xzp for deletion */
                xzp->z_links = 0;       /* no more links to it */
-               VERIFY(0 == sa_update(xzp->z_sa_hdl, SA_ZPL_LINKS(zfsvfs),
+               VERIFY(0 == sa_update(xzp->z_sa_hdl, SA_ZPL_LINKS(zsb),
                    &xzp->z_links, sizeof (xzp->z_links), tx));
                mutex_exit(&xzp->z_lock);
                zfs_unlinked_add(xzp, tx);
@@ -674,14 +686,14 @@ zfs_rmnode(znode_t *zp)
 
        /* Remove this znode from the unlinked set */
        VERIFY3U(0, ==,
-           zap_remove_int(zfsvfs->z_os, zfsvfs->z_unlinkedobj, zp->z_id, tx));
+           zap_remove_int(zsb->z_os, zsb->z_unlinkedobj, zp->z_id, tx));
 
        zfs_znode_delete(zp, tx);
 
        dmu_tx_commit(tx);
 out:
        if (xzp)
-               VN_RELE(ZTOV(xzp));
+               iput(ZTOI(xzp));
 }
 
 static uint64_t
@@ -689,7 +701,7 @@ zfs_dirent(znode_t *zp, uint64_t mode)
 {
        uint64_t de = zp->z_id;
 
-       if (zp->z_zfsvfs->z_version >= ZPL_VERSION_DIRENT_TYPE)
+       if (ZTOZSB(zp)->z_version >= ZPL_VERSION_DIRENT_TYPE)
                de |= IFTODT(mode) << 60;
        return (de);
 }
@@ -701,10 +713,9 @@ int
 zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
 {
        znode_t *dzp = dl->dl_dzp;
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-       vnode_t *vp = ZTOV(zp);
+       zfs_sb_t *zsb = ZTOZSB(zp);
        uint64_t value;
-       int zp_is_dir = (vp->v_type == VDIR);
+       int zp_is_dir = S_ISDIR(ZTOI(zp)->i_mode);
        sa_bulk_attr_t bulk[5];
        uint64_t mtime[2], ctime[2];
        int count = 0;
@@ -719,17 +730,17 @@ zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
                        return (ENOENT);
                }
                zp->z_links++;
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb), NULL,
                    &zp->z_links, sizeof (zp->z_links));
 
        }
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zsb), NULL,
            &dzp->z_id, sizeof (dzp->z_id));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, sizeof (zp->z_pflags));
 
        if (!(flag & ZNEW)) {
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL,
                    ctime, sizeof (ctime));
                zfs_tstamp_update_setup(zp, STATE_CHANGED, mtime,
                    ctime, B_TRUE);
@@ -743,15 +754,15 @@ zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
        dzp->z_size++;
        dzp->z_links += zp_is_dir;
        count = 0;
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb), NULL,
            &dzp->z_size, sizeof (dzp->z_size));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb), NULL,
            &dzp->z_links, sizeof (dzp->z_links));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL,
            mtime, sizeof (mtime));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL,
            ctime, sizeof (ctime));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &dzp->z_pflags, sizeof (dzp->z_pflags));
        zfs_tstamp_update_setup(dzp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
        error = sa_bulk_update(dzp->z_sa_hdl, bulk, count, tx);
@@ -759,11 +770,13 @@ zfs_link_create(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag)
        mutex_exit(&dzp->z_lock);
 
        value = zfs_dirent(zp, zp->z_mode);
-       error = zap_add(zp->z_zfsvfs->z_os, dzp->z_id, dl->dl_name,
+       error = zap_add(ZTOZSB(zp)->z_os, dzp->z_id, dl->dl_name,
            8, 1, &value, tx);
        ASSERT(error == 0);
 
-       dnlc_update(ZTOV(dzp), dl->dl_name, vp);
+#ifdef HAVE_DNLC
+       dnlc_update(ZTOI(dzp), dl->dl_name, vp);
+#endif /* HAVE_DNLC */
 
        return (0);
 }
@@ -774,18 +787,18 @@ zfs_dropname(zfs_dirlock_t *dl, znode_t *zp, znode_t *dzp, dmu_tx_t *tx,
 {
        int error;
 
-       if (zp->z_zfsvfs->z_norm) {
-               if (((zp->z_zfsvfs->z_case == ZFS_CASE_INSENSITIVE) &&
+       if (ZTOZSB(zp)->z_norm) {
+               if (((ZTOZSB(zp)->z_case == ZFS_CASE_INSENSITIVE) &&
                    (flag & ZCIEXACT)) ||
-                   ((zp->z_zfsvfs->z_case == ZFS_CASE_MIXED) &&
+                   ((ZTOZSB(zp)->z_case == ZFS_CASE_MIXED) &&
                    !(flag & ZCILOOK)))
-                       error = zap_remove_norm(zp->z_zfsvfs->z_os,
+                       error = zap_remove_norm(ZTOZSB(zp)->z_os,
                            dzp->z_id, dl->dl_name, MT_EXACT, tx);
                else
-                       error = zap_remove_norm(zp->z_zfsvfs->z_os,
+                       error = zap_remove_norm(ZTOZSB(zp)->z_os,
                            dzp->z_id, dl->dl_name, MT_FIRST, tx);
        } else {
-               error = zap_remove(zp->z_zfsvfs->z_os,
+               error = zap_remove(ZTOZSB(zp)->z_os,
                    dzp->z_id, dl->dl_name, tx);
        }
 
@@ -804,31 +817,23 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
        boolean_t *unlinkedp)
 {
        znode_t *dzp = dl->dl_dzp;
-       zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
-       vnode_t *vp = ZTOV(zp);
-       int zp_is_dir = (vp->v_type == VDIR);
+       zfs_sb_t *zsb = ZTOZSB(dzp);
+       int zp_is_dir = S_ISDIR(ZTOI(zp)->i_mode);
        boolean_t unlinked = B_FALSE;
        sa_bulk_attr_t bulk[5];
        uint64_t mtime[2], ctime[2];
        int count = 0;
        int error;
 
-       dnlc_remove(ZTOV(dzp), dl->dl_name);
+#ifdef HAVE_DNLC
+       dnlc_remove(ZTOI(dzp), dl->dl_name);
+#endif /* HAVE_DNLC */
 
        if (!(flag & ZRENAMING)) {
-               if (vn_vfswlock(vp))            /* prevent new mounts on zp */
-                       return (EBUSY);
-
-               if (vn_ismntpt(vp)) {           /* don't remove mount point */
-                       vn_vfsunlock(vp);
-                       return (EBUSY);
-               }
-
                mutex_enter(&zp->z_lock);
 
                if (zp_is_dir && !zfs_dirempty(zp)) {
                        mutex_exit(&zp->z_lock);
-                       vn_vfsunlock(vp);
                        return (EEXIST);
                }
 
@@ -840,16 +845,13 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
                error = zfs_dropname(dl, zp, dzp, tx, flag);
                if (error != 0) {
                        mutex_exit(&zp->z_lock);
-                       vn_vfsunlock(vp);
                        return (error);
                }
 
                if (zp->z_links <= zp_is_dir) {
-                       zfs_panic_recover("zfs: link count on %s is %u, "
-                           "should be at least %u",
-                           zp->z_vnode->v_path ? zp->z_vnode->v_path :
-                           "<unknown>", (int)zp->z_links,
-                           zp_is_dir + 1);
+                       zfs_panic_recover("zfs: link count on %lu is %u, "
+                           "should be at least %u", zp->z_id,
+                           (int)zp->z_links, zp_is_dir + 1);
                        zp->z_links = zp_is_dir + 1;
                }
                if (--zp->z_links == zp_is_dir) {
@@ -857,20 +859,19 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
                        zp->z_links = 0;
                        unlinked = B_TRUE;
                } else {
-                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs),
+                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb),
                            NULL, &ctime, sizeof (ctime));
-                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb),
                            NULL, &zp->z_pflags, sizeof (zp->z_pflags));
                        zfs_tstamp_update_setup(zp, STATE_CHANGED, mtime, ctime,
                            B_TRUE);
                }
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs),
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb),
                    NULL, &zp->z_links, sizeof (zp->z_links));
                error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
                count = 0;
                ASSERT(error == 0);
                mutex_exit(&zp->z_lock);
-               vn_vfsunlock(vp);
        } else {
                error = zfs_dropname(dl, zp, dzp, tx, flag);
                if (error != 0)
@@ -880,15 +881,15 @@ zfs_link_destroy(zfs_dirlock_t *dl, znode_t *zp, dmu_tx_t *tx, int flag,
        mutex_enter(&dzp->z_lock);
        dzp->z_size--;          /* one dirent removed */
        dzp->z_links -= zp_is_dir;      /* ".." link from zp */
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb),
            NULL, &dzp->z_links, sizeof (dzp->z_links));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb),
            NULL, &dzp->z_size, sizeof (dzp->z_size));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb),
            NULL, ctime, sizeof (ctime));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb),
            NULL, mtime, sizeof (mtime));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb),
            NULL, &dzp->z_pflags, sizeof (dzp->z_pflags));
        zfs_tstamp_update_setup(dzp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
        error = sa_bulk_update(dzp->z_sa_hdl, bulk, count, tx);
@@ -915,38 +916,40 @@ zfs_dirempty(znode_t *dzp)
 }
 
 int
-zfs_make_xattrdir(znode_t *zp, vattr_t *vap, vnode_t **xvpp, cred_t *cr)
+zfs_make_xattrdir(znode_t *zp, vattr_t *vap, struct inode **xipp, cred_t *cr)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        znode_t *xzp;
        dmu_tx_t *tx;
        int error;
        zfs_acl_ids_t acl_ids;
        boolean_t fuid_dirtied;
+#ifdef DEBUG
        uint64_t parent;
+#endif
 
-       *xvpp = NULL;
+       *xipp = NULL;
 
-       if (error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr))
+       if ((error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr)))
                return (error);
 
        if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL,
            &acl_ids)) != 0)
                return (error);
-       if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+       if (zfs_acl_ids_overquota(zsb, &acl_ids)) {
                zfs_acl_ids_free(&acl_ids);
                return (EDQUOT);
        }
 
 top:
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes +
            ZFS_SA_BASE_ATTR_SIZE);
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
        dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
-       fuid_dirtied = zfsvfs->z_fuid_dirty;
+       fuid_dirtied = zsb->z_fuid_dirty;
        if (fuid_dirtied)
-               zfs_fuid_txhold(zfsvfs, tx);
+               zfs_fuid_txhold(zsb, tx);
        error = dmu_tx_assign(tx, TXG_NOWAIT);
        if (error) {
                if (error == ERESTART) {
@@ -961,24 +964,24 @@ top:
        zfs_mknode(zp, vap, tx, cr, IS_XATTR, &xzp, &acl_ids);
 
        if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
+               zfs_fuid_sync(zsb, tx);
 
 #ifdef DEBUG
-       error = sa_lookup(xzp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
+       error = sa_lookup(xzp->z_sa_hdl, SA_ZPL_PARENT(zsb),
            &parent, sizeof (parent));
        ASSERT(error == 0 && parent == zp->z_id);
 #endif
 
-       VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs), &xzp->z_id,
+       VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_XATTR(zsb), &xzp->z_id,
            sizeof (xzp->z_id), tx));
 
-       (void) zfs_log_create(zfsvfs->z_log, tx, TX_MKXATTR, zp,
+       (void) zfs_log_create(zsb->z_log, tx, TX_MKXATTR, zp,
            xzp, "", NULL, acl_ids.z_fuidp, vap);
 
        zfs_acl_ids_free(&acl_ids);
        dmu_tx_commit(tx);
 
-       *xvpp = ZTOV(xzp);
+       *xipp = ZTOI(xzp);
 
        return (0);
 }
@@ -991,15 +994,15 @@ top:
  *             cr      - credentials of caller
  *             flags   - flags from the VOP_LOOKUP call
  *
- *     OUT:    xzpp    - pointer to extended attribute znode
+ *     OUT:    xipp    - pointer to extended attribute znode
  *
  *     RETURN: 0 on success
  *             error number on failure
  */
 int
-zfs_get_xattrdir(znode_t *zp, vnode_t **xvpp, cred_t *cr, int flags)
+zfs_get_xattrdir(znode_t *zp, struct inode **xipp, cred_t *cr, int flags)
 {
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(zp);
        znode_t         *xzp;
        zfs_dirlock_t   *dl;
        vattr_t         va;
@@ -1010,18 +1013,17 @@ top:
                return (error);
 
        if (xzp != NULL) {
-               *xvpp = ZTOV(xzp);
+               *xipp = ZTOI(xzp);
                zfs_dirent_unlock(dl);
                return (0);
        }
 
-
        if (!(flags & CREATE_XATTR_DIR)) {
                zfs_dirent_unlock(dl);
                return (ENOENT);
        }
 
-       if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
+       if (zsb->z_vfs->mnt_flags & MNT_READONLY) {
                zfs_dirent_unlock(dl);
                return (EROFS);
        }
@@ -1036,12 +1038,11 @@ top:
         * Once in a directory the ability to read/write attributes
         * is controlled by the permissions on the attribute file.
         */
-       va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
-       va.va_type = VDIR;
+       va.va_mask = ATTR_MODE | ATTR_UID | ATTR_GID;
        va.va_mode = S_IFDIR | S_ISVTX | 0777;
        zfs_fuid_map_ids(zp, cr, &va.va_uid, &va.va_gid);
 
-       error = zfs_make_xattrdir(zp, &va, xvpp, cr);
+       error = zfs_make_xattrdir(zp, &va, xipp, cr);
        zfs_dirent_unlock(dl);
 
        if (error == ERESTART) {
@@ -1068,25 +1069,24 @@ top:
 int
 zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
 {
-       uid_t           uid;
+       uid_t           uid;
        uid_t           downer;
        uid_t           fowner;
-       zfsvfs_t        *zfsvfs = zdp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(zdp);
 
-       if (zdp->z_zfsvfs->z_replay)
+       if (zsb->z_replay)
                return (0);
 
        if ((zdp->z_mode & S_ISVTX) == 0)
                return (0);
 
-       downer = zfs_fuid_map_id(zfsvfs, zdp->z_uid, cr, ZFS_OWNER);
-       fowner = zfs_fuid_map_id(zfsvfs, zp->z_uid, cr, ZFS_OWNER);
+       downer = zfs_fuid_map_id(zsb, zdp->z_uid, cr, ZFS_OWNER);
+       fowner = zfs_fuid_map_id(zsb, zp->z_uid, cr, ZFS_OWNER);
 
        if ((uid = crgetuid(cr)) == downer || uid == fowner ||
-           (ZTOV(zp)->v_type == VREG &&
+           (S_ISDIR(ZTOI(zp)->i_mode) &&
            zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0))
                return (0);
        else
                return (secpolicy_vnode_remove(cr));
 }
-#endif /* HAVE_ZPL */
index 97fceea..ca03373 100644 (file)
@@ -46,7 +46,7 @@
  * two AVL trees are created.  One tree is keyed by the index number
  * and the other by the domain string.  Nodes are never removed from
  * trees, but new entries may be added.  If a new entry is added then
- * the zfsvfs->z_fuid_dirty flag is set to true and the caller will then
+ * the zsb->z_fuid_dirty flag is set to true and the caller will then
  * be responsible for calling zfs_fuid_sync() to sync the changes to disk.
  *
  */
@@ -192,39 +192,38 @@ zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx)
 }
 
 #ifdef _KERNEL
-#ifdef HAVE_ZPL
 /*
  * Load the fuid table(s) into memory.
  */
 static void
-zfs_fuid_init(zfsvfs_t *zfsvfs)
+zfs_fuid_init(zfs_sb_t *zsb)
 {
-       rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
+       rw_enter(&zsb->z_fuid_lock, RW_WRITER);
 
-       if (zfsvfs->z_fuid_loaded) {
-               rw_exit(&zfsvfs->z_fuid_lock);
+       if (zsb->z_fuid_loaded) {
+               rw_exit(&zsb->z_fuid_lock);
                return;
        }
 
-       zfs_fuid_avl_tree_create(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
+       zfs_fuid_avl_tree_create(&zsb->z_fuid_idx, &zsb->z_fuid_domain);
 
-       (void) zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
-           ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj);
-       if (zfsvfs->z_fuid_obj != 0) {
-               zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
-                   zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx,
-                   &zfsvfs->z_fuid_domain);
+       (void) zap_lookup(zsb->z_os, MASTER_NODE_OBJ,
+           ZFS_FUID_TABLES, 8, 1, &zsb->z_fuid_obj);
+       if (zsb->z_fuid_obj != 0) {
+               zsb->z_fuid_size = zfs_fuid_table_load(zsb->z_os,
+                   zsb->z_fuid_obj, &zsb->z_fuid_idx,
+                   &zsb->z_fuid_domain);
        }
 
-       zfsvfs->z_fuid_loaded = B_TRUE;
-       rw_exit(&zfsvfs->z_fuid_lock);
+       zsb->z_fuid_loaded = B_TRUE;
+       rw_exit(&zsb->z_fuid_lock);
 }
 
 /*
  * sync out AVL trees to persistent storage.
  */
 void
-zfs_fuid_sync(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
+zfs_fuid_sync(zfs_sb_t *zsb, dmu_tx_t *tx)
 {
        nvlist_t *nvp;
        nvlist_t **fuids;
@@ -235,30 +234,30 @@ zfs_fuid_sync(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
        int numnodes;
        int i;
 
-       if (!zfsvfs->z_fuid_dirty) {
+       if (!zsb->z_fuid_dirty) {
                return;
        }
 
-       rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
+       rw_enter(&zsb->z_fuid_lock, RW_WRITER);
 
        /*
         * First see if table needs to be created?
         */
-       if (zfsvfs->z_fuid_obj == 0) {
-               zfsvfs->z_fuid_obj = dmu_object_alloc(zfsvfs->z_os,
+       if (zsb->z_fuid_obj == 0) {
+               zsb->z_fuid_obj = dmu_object_alloc(zsb->z_os,
                    DMU_OT_FUID, 1 << 14, DMU_OT_FUID_SIZE,
                    sizeof (uint64_t), tx);
-               VERIFY(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
+               VERIFY(zap_add(zsb->z_os, MASTER_NODE_OBJ,
                    ZFS_FUID_TABLES, sizeof (uint64_t), 1,
-                   &zfsvfs->z_fuid_obj, tx) == 0);
+                   &zsb->z_fuid_obj, tx) == 0);
        }
 
        VERIFY(nvlist_alloc(&nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
 
-       numnodes = avl_numnodes(&zfsvfs->z_fuid_idx);
+       numnodes = avl_numnodes(&zsb->z_fuid_idx);
        fuids = kmem_alloc(numnodes * sizeof (void *), KM_SLEEP);
-       for (i = 0, domnode = avl_first(&zfsvfs->z_fuid_domain); domnode; i++,
-           domnode = AVL_NEXT(&zfsvfs->z_fuid_domain, domnode)) {
+       for (i = 0, domnode = avl_first(&zsb->z_fuid_domain); domnode; i++,
+           domnode = AVL_NEXT(&zsb->z_fuid_domain, domnode)) {
                VERIFY(nvlist_alloc(&fuids[i], NV_UNIQUE_NAME, KM_SLEEP) == 0);
                VERIFY(nvlist_add_uint64(fuids[i], FUID_IDX,
                    domnode->f_idx) == 0);
@@ -276,30 +275,29 @@ zfs_fuid_sync(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
        VERIFY(nvlist_pack(nvp, &packed, &nvsize,
            NV_ENCODE_XDR, KM_SLEEP) == 0);
        nvlist_free(nvp);
-       zfsvfs->z_fuid_size = nvsize;
-       dmu_write(zfsvfs->z_os, zfsvfs->z_fuid_obj, 0,
-           zfsvfs->z_fuid_size, packed, tx);
-       kmem_free(packed, zfsvfs->z_fuid_size);
-       VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, zfsvfs->z_fuid_obj,
+       zsb->z_fuid_size = nvsize;
+       dmu_write(zsb->z_os, zsb->z_fuid_obj, 0, zsb->z_fuid_size, packed, tx);
+       kmem_free(packed, zsb->z_fuid_size);
+       VERIFY(0 == dmu_bonus_hold(zsb->z_os, zsb->z_fuid_obj,
            FTAG, &db));
        dmu_buf_will_dirty(db, tx);
-       *(uint64_t *)db->db_data = zfsvfs->z_fuid_size;
+       *(uint64_t *)db->db_data = zsb->z_fuid_size;
        dmu_buf_rele(db, FTAG);
 
-       zfsvfs->z_fuid_dirty = B_FALSE;
-       rw_exit(&zfsvfs->z_fuid_lock);
+       zsb->z_fuid_dirty = B_FALSE;
+       rw_exit(&zsb->z_fuid_lock);
 }
 
 /*
  * Query domain table for a given domain.
  *
  * If domain isn't found and addok is set, it is added to AVL trees and
- * the zfsvfs->z_fuid_dirty flag will be set to TRUE.  It will then be
+ * the zsb->z_fuid_dirty flag will be set to TRUE.  It will then be
  * necessary for the caller or another thread to detect the dirty table
  * and sync out the changes.
  */
 int
-zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain,
+zfs_fuid_find_by_domain(zfs_sb_t *zsb, const char *domain,
     char **retdomain, boolean_t addok)
 {
        fuid_domain_t searchnode, *findnode;
@@ -320,23 +318,23 @@ zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain,
        searchnode.f_ksid = ksid_lookupdomain(domain);
        if (retdomain)
                *retdomain = searchnode.f_ksid->kd_name;
-       if (!zfsvfs->z_fuid_loaded)
-               zfs_fuid_init(zfsvfs);
+       if (!zsb->z_fuid_loaded)
+               zfs_fuid_init(zsb);
 
 retry:
-       rw_enter(&zfsvfs->z_fuid_lock, rw);
-       findnode = avl_find(&zfsvfs->z_fuid_domain, &searchnode, &loc);
+       rw_enter(&zsb->z_fuid_lock, rw);
+       findnode = avl_find(&zsb->z_fuid_domain, &searchnode, &loc);
 
        if (findnode) {
-               rw_exit(&zfsvfs->z_fuid_lock);
+               rw_exit(&zsb->z_fuid_lock);
                ksiddomain_rele(searchnode.f_ksid);
                return (findnode->f_idx);
        } else if (addok) {
                fuid_domain_t *domnode;
                uint64_t retidx;
 
-               if (rw == RW_READER && !rw_tryupgrade(&zfsvfs->z_fuid_lock)) {
-                       rw_exit(&zfsvfs->z_fuid_lock);
+               if (rw == RW_READER && !rw_tryupgrade(&zsb->z_fuid_lock)) {
+                       rw_exit(&zsb->z_fuid_lock);
                        rw = RW_WRITER;
                        goto retry;
                }
@@ -344,15 +342,15 @@ retry:
                domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
                domnode->f_ksid = searchnode.f_ksid;
 
-               retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
+               retidx = domnode->f_idx = avl_numnodes(&zsb->z_fuid_idx) + 1;
 
-               avl_add(&zfsvfs->z_fuid_domain, domnode);
-               avl_add(&zfsvfs->z_fuid_idx, domnode);
-               zfsvfs->z_fuid_dirty = B_TRUE;
-               rw_exit(&zfsvfs->z_fuid_lock);
+               avl_add(&zsb->z_fuid_domain, domnode);
+               avl_add(&zsb->z_fuid_idx, domnode);
+               zsb->z_fuid_dirty = B_TRUE;
+               rw_exit(&zsb->z_fuid_lock);
                return (retidx);
        } else {
-               rw_exit(&zfsvfs->z_fuid_lock);
+               rw_exit(&zsb->z_fuid_lock);
                return (-1);
        }
 }
@@ -364,23 +362,23 @@ retry:
  *
  */
 const char *
-zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
+zfs_fuid_find_by_idx(zfs_sb_t *zsb, uint32_t idx)
 {
        char *domain;
 
-       if (idx == 0 || !zfsvfs->z_use_fuids)
+       if (idx == 0 || !zsb->z_use_fuids)
                return (NULL);
 
-       if (!zfsvfs->z_fuid_loaded)
-               zfs_fuid_init(zfsvfs);
+       if (!zsb->z_fuid_loaded)
+               zfs_fuid_init(zsb);
 
-       rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
+       rw_enter(&zsb->z_fuid_lock, RW_READER);
 
-       if (zfsvfs->z_fuid_obj || zfsvfs->z_fuid_dirty)
-               domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx);
+       if (zsb->z_fuid_obj || zsb->z_fuid_dirty)
+               domain = zfs_fuid_idx_domain(&zsb->z_fuid_idx, idx);
        else
                domain = nulldomain;
-       rw_exit(&zfsvfs->z_fuid_lock);
+       rw_exit(&zsb->z_fuid_lock);
 
        ASSERT(domain);
        return (domain);
@@ -389,14 +387,15 @@ zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
 void
 zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
 {
-       *uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
-       *gidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_gid, cr, ZFS_GROUP);
+       *uidp = zfs_fuid_map_id(ZTOZSB(zp), zp->z_uid, cr, ZFS_OWNER);
+       *gidp = zfs_fuid_map_id(ZTOZSB(zp), zp->z_gid, cr, ZFS_GROUP);
 }
 
 uid_t
-zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
+zfs_fuid_map_id(zfs_sb_t *zsb, uint64_t fuid,
     cred_t *cr, zfs_fuid_type_t type)
 {
+#ifdef HAVE_KSID
        uint32_t index = FUID_INDEX(fuid);
        const char *domain;
        uid_t id;
@@ -404,7 +403,7 @@ zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
        if (index == 0)
                return (fuid);
 
-       domain = zfs_fuid_find_by_idx(zfsvfs, index);
+       domain = zfs_fuid_find_by_idx(zsb, index);
        ASSERT(domain != NULL);
 
        if (type == ZFS_OWNER || type == ZFS_ACE_USER) {
@@ -415,6 +414,12 @@ zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
                    FUID_RID(fuid), &id);
        }
        return (id);
+#else
+       if(type == ZFS_OWNER || type == ZFS_ACE_USER)
+               return (crgetuid(cr));
+       else
+               return (crgetgid(cr));
+#endif /* HAVE_KSID */
 }
 
 /*
@@ -483,6 +488,7 @@ zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid,
        }
 }
 
+#ifdef HAVE_KSID
 /*
  * Create a file system FUID, based on information in the users cred
  *
@@ -492,13 +498,13 @@ zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid,
  * be used if it exists.
  */
 uint64_t
-zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
+zfs_fuid_create_cred(zfs_sb_t *zsb, zfs_fuid_type_t type,
     cred_t *cr, zfs_fuid_info_t **fuidp)
 {
        uint64_t        idx;
        ksid_t          *ksid;
        uint32_t        rid;
-       char            *kdomain;
+       char            *kdomain;
        const char      *domain;
        uid_t           id;
 
@@ -506,7 +512,7 @@ zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
 
        ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);
 
-       if (!zfsvfs->z_use_fuids || (ksid == NULL)) {
+       if (!zsb->z_use_fuids || (ksid == NULL)) {
                id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr);
 
                if (IS_EPHEMERAL(id))
@@ -529,12 +535,13 @@ zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
        rid = ksid_getrid(ksid);
        domain = ksid_getdomain(ksid);
 
-       idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);
+       idx = zfs_fuid_find_by_domain(zsb, domain, &kdomain, B_TRUE);
 
        zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);
 
        return (FUID_ENCODE(idx, rid));
 }
+#endif /* HAVE_KSID */
 
 /*
  * Create a file system FUID for an ACL ace
@@ -546,12 +553,13 @@ zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
  *
  * During replay operations the domain+rid information is
  * found in the zfs_fuid_info_t that the replay code has
- * attached to the zfsvfs of the file system.
+ * attached to the zsb of the file system.
  */
 uint64_t
-zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
+zfs_fuid_create(zfs_sb_t *zsb, uint64_t id, cred_t *cr,
     zfs_fuid_type_t type, zfs_fuid_info_t **fuidpp)
 {
+#ifdef HAVE_KSID
        const char *domain;
        char *kdomain;
        uint32_t fuid_idx = FUID_INDEX(id);
@@ -569,11 +577,11 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
         * chmod.
         */
 
-       if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
+       if (!zsb->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
                return (id);
 
-       if (zfsvfs->z_replay) {
-               fuidp = zfsvfs->z_fuid_replay;
+       if (zsb->z_replay) {
+               fuidp = zsb->z_fuid_replay;
 
                /*
                 * If we are passed an ephemeral id, but no
@@ -620,9 +628,9 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
                }
        }
 
-       idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);
+       idx = zfs_fuid_find_by_domain(zsb, domain, &kdomain, B_TRUE);
 
-       if (!zfsvfs->z_replay)
+       if (!zsb->z_replay)
                zfs_fuid_node_add(fuidpp, kdomain,
                    rid, idx, id, type);
        else if (zfuid != NULL) {
@@ -630,18 +638,24 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
                kmem_free(zfuid, sizeof (zfs_fuid_t));
        }
        return (FUID_ENCODE(idx, rid));
+#else
+       /*
+        * The Linux port only supports POSIX IDs, use the passed id.
+        */
+       return (id);
+#endif
 }
 
 void
-zfs_fuid_destroy(zfsvfs_t *zfsvfs)
+zfs_fuid_destroy(zfs_sb_t *zsb)
 {
-       rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
-       if (!zfsvfs->z_fuid_loaded) {
-               rw_exit(&zfsvfs->z_fuid_lock);
+       rw_enter(&zsb->z_fuid_lock, RW_WRITER);
+       if (!zsb->z_fuid_loaded) {
+               rw_exit(&zsb->z_fuid_lock);
                return;
        }
-       zfs_fuid_table_destroy(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
-       rw_exit(&zfsvfs->z_fuid_lock);
+       zfs_fuid_table_destroy(&zsb->z_fuid_idx, &zsb->z_fuid_domain);
+       rw_exit(&zsb->z_fuid_lock);
 }
 
 /*
@@ -695,14 +709,15 @@ zfs_fuid_info_free(zfs_fuid_info_t *fuidp)
  * Will use a straight FUID compare when possible.
  */
 boolean_t
-zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
+zfs_groupmember(zfs_sb_t *zsb, uint64_t id, cred_t *cr)
 {
+#ifdef HAVE_KSID
        ksid_t          *ksid = crgetsid(cr, KSID_GROUP);
        ksidlist_t      *ksidlist = crgetsidlist(cr);
        uid_t           gid;
 
        if (ksid && ksidlist) {
-               int             i;
+               int             i;
                ksid_t          *ksid_groups;
                uint32_t        idx = FUID_INDEX(id);
                uint32_t        rid = FUID_RID(id);
@@ -718,7 +733,7 @@ zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
                        } else {
                                const char *domain;
 
-                               domain = zfs_fuid_find_by_idx(zfsvfs, idx);
+                               domain = zfs_fuid_find_by_idx(zsb, idx);
                                ASSERT(domain != NULL);
 
                                if (strcmp(domain,
@@ -736,23 +751,25 @@ zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
        /*
         * Not found in ksidlist, check posix groups
         */
-       gid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP);
+       gid = zfs_fuid_map_id(zsb, id, cr, ZFS_GROUP);
        return (groupmember(gid, cr));
+#else
+       return (B_TRUE);
+#endif
 }
 
 void
-zfs_fuid_txhold(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
+zfs_fuid_txhold(zfs_sb_t *zsb, dmu_tx_t *tx)
 {
-       if (zfsvfs->z_fuid_obj == 0) {
+       if (zsb->z_fuid_obj == 0) {
                dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
                dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
-                   FUID_SIZE_ESTIMATE(zfsvfs));
+                   FUID_SIZE_ESTIMATE(zsb));
                dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL);
        } else {
-               dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj);
-               dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0,
-                   FUID_SIZE_ESTIMATE(zfsvfs));
+               dmu_tx_hold_bonus(tx, zsb->z_fuid_obj);
+               dmu_tx_hold_write(tx, zsb->z_fuid_obj, 0,
+                   FUID_SIZE_ESTIMATE(zsb));
        }
 }
-#endif /* HAVE_ZPL */
 #endif
index 45e118e..994d65f 100644 (file)
@@ -58,7 +58,6 @@
 #include <sys/mount.h>
 #include <sys/sdt.h>
 #include <sys/fs/zfs.h>
-#include <sys/zfs_ctldir.h>
 #include <sys/zfs_dir.h>
 #include <sys/zfs_onexit.h>
 #include <sys/zvol.h>
@@ -433,7 +432,7 @@ zfs_set_slabel_policy(const char *name, char *strval, cred_t *cr)
        /*
         * If the existing dataset label is nondefault, check if the
         * dataset is mounted (label cannot be changed while mounted).
-        * Get the zfsvfs; if there isn't one, then the dataset isn't
+        * Get the zfs_sb_t; if there isn't one, then the dataset isn't
         * mounted (or isn't a dataset, doesn't exist, ...).
         */
        if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) != 0) {
@@ -592,7 +591,7 @@ zfs_secpolicy_send(zfs_cmd_t *zc, cred_t *cr)
        return (error);
 }
 
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
 static int
 zfs_secpolicy_deleg_share(zfs_cmd_t *zc, cred_t *cr)
 {
@@ -616,12 +615,12 @@ zfs_secpolicy_deleg_share(zfs_cmd_t *zc, cred_t *cr)
        return (dsl_deleg_access(zc->zc_name,
            ZFS_DELEG_PERM_SHARE, cr));
 }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 
 int
 zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr)
 {
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
        if (!INGLOBALZONE(curproc))
                return (EPERM);
 
@@ -632,13 +631,13 @@ zfs_secpolicy_share(zfs_cmd_t *zc, cred_t *cr)
        }
 #else
        return (ENOTSUP);
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 }
 
 int
 zfs_secpolicy_smb_acl(zfs_cmd_t *zc, cred_t *cr)
 {
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
        if (!INGLOBALZONE(curproc))
                return (EPERM);
 
@@ -649,7 +648,7 @@ zfs_secpolicy_smb_acl(zfs_cmd_t *zc, cred_t *cr)
        }
 #else
        return (ENOTSUP);
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 }
 
 static int
@@ -850,20 +849,6 @@ zfs_secpolicy_create(zfs_cmd_t *zc, cred_t *cr)
        return (error);
 }
 
-#ifdef HAVE_ZPL
-static int
-zfs_secpolicy_umount(zfs_cmd_t *zc, cred_t *cr)
-{
-       int error;
-
-       error = secpolicy_fs_unmount(cr, NULL);
-       if (error) {
-               error = dsl_deleg_access(zc->zc_name, ZFS_DELEG_PERM_MOUNT, cr);
-       }
-       return (error);
-}
-#endif /* HAVE_ZPL */
-
 /*
  * Policy for pool operations - create/destroy pools, add vdevs, etc.  Requires
  * SYS_CONFIG privilege, which is not available in a local zone.
@@ -1106,9 +1091,8 @@ put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
        return (error);
 }
 
-#ifdef HAVE_ZPL
 static int
-getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
+get_zfs_sb(const char *dsname, zfs_sb_t **zsbp)
 {
        objset_t *os;
        int error;
@@ -1122,9 +1106,9 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
        }
 
        mutex_enter(&os->os_user_ptr_lock);
-       *zfvp = dmu_objset_get_user(os);
-       if (*zfvp) {
-               VFS_HOLD((*zfvp)->z_vfs);
+       *zsbp = dmu_objset_get_user(os);
+       if (*zsbp) {
+               mntget((*zsbp)->z_vfs);
        } else {
                error = ESRCH;
        }
@@ -1132,52 +1116,45 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
        dmu_objset_rele(os, FTAG);
        return (error);
 }
-#endif
 
 /*
- * Find a zfsvfs_t for a mounted filesystem, or create our own, in which
+ * Find a zfs_sb_t for a mounted filesystem, or create our own, in which
  * case its z_vfs will be NULL, and it will be opened as the owner.
  */
 static int
-zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer)
+zfs_sb_hold(const char *name, void *tag, zfs_sb_t **zsbp, boolean_t writer)
 {
-#ifdef HAVE_ZPL
        int error = 0;
 
-       if (getzfsvfs(name, zfvp) != 0)
-               error = zfsvfs_create(name, zfvp);
+       if (get_zfs_sb(name, zsbp) != 0)
+               error = zfs_sb_create(name, zsbp);
        if (error == 0) {
-               rrw_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER :
+               rrw_enter(&(*zsbp)->z_teardown_lock, (writer) ? RW_WRITER :
                    RW_READER, tag);
-               if ((*zfvp)->z_unmounted) {
+               if ((*zsbp)->z_unmounted) {
                        /*
                         * XXX we could probably try again, since the unmounting
                         * thread should be just about to disassociate the
                         * objset from the zfsvfs.
                         */
-                       rrw_exit(&(*zfvp)->z_teardown_lock, tag);
+                       rrw_exit(&(*zsbp)->z_teardown_lock, tag);
                        return (EBUSY);
                }
        }
        return (error);
-#else
-       return ENOTSUP;
-#endif
 }
 
 static void
-zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag)
+zfs_sb_rele(zfs_sb_t *zsb, void *tag)
 {
-#ifdef HAVE_ZPL
-       rrw_exit(&zfsvfs->z_teardown_lock, tag);
+       rrw_exit(&zsb->z_teardown_lock, tag);
 
-       if (zfsvfs->z_vfs) {
-               VFS_RELE(zfsvfs->z_vfs);
+       if (zsb->z_vfs) {
+               mntput(zsb->z_vfs);
        } else {
-               dmu_objset_disown(zfsvfs->z_os, zfsvfs);
-               zfsvfs_free(zfsvfs);
+               dmu_objset_disown(zsb->z_os, zsb);
+               zfs_sb_free(zsb);
        }
-#endif
 }
 
 static int
@@ -2087,7 +2064,6 @@ top:
 static int
 zfs_prop_set_userquota(const char *dsname, nvpair_t *pair)
 {
-#ifdef HAVE_ZPL
        const char *propname = nvpair_name(pair);
        uint64_t *valary;
        unsigned int vallen;
@@ -2096,7 +2072,7 @@ zfs_prop_set_userquota(const char *dsname, nvpair_t *pair)
        zfs_userquota_prop_t type;
        uint64_t rid;
        uint64_t quota;
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
        int err;
 
        if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
@@ -2121,16 +2097,13 @@ zfs_prop_set_userquota(const char *dsname, nvpair_t *pair)
        rid = valary[1];
        quota = valary[2];
 
-       err = zfsvfs_hold(dsname, FTAG, &zfsvfs, B_FALSE);
+       err = zfs_sb_hold(dsname, FTAG, &zsb, B_FALSE);
        if (err == 0) {
-               err = zfs_set_userquota(zfsvfs, type, domain, rid, quota);
-               zfsvfs_rele(zfsvfs, FTAG);
+               err = zfs_set_userquota(zsb, type, domain, rid, quota);
+               zfs_sb_rele(zsb, FTAG);
        }
 
        return (err);
-#else
-       return ENOTSUP;
-#endif
 }
 
 /*
@@ -2186,15 +2159,13 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
                break;
        case ZFS_PROP_VERSION:
        {
-               zfsvfs_t *zfsvfs;
+               zfs_sb_t *zsb;
 
-               if ((err = zfsvfs_hold(dsname, FTAG, &zfsvfs, B_TRUE)) != 0)
+               if ((err = zfs_sb_hold(dsname, FTAG, &zsb, B_TRUE)) != 0)
                        break;
 
-#ifdef HAVE_ZPL
-               err = zfs_set_version(zfsvfs, intval);
-#endif
-               zfsvfs_rele(zfsvfs, FTAG);
+               err = zfs_set_version(zsb, intval);
+               zfs_sb_rele(zsb, FTAG);
 
                if (err == 0 && intval >= ZPL_VERSION_USERSPACE) {
                        zfs_cmd_t *zc;
@@ -2749,7 +2720,7 @@ zfs_ioc_get_fsacl(zfs_cmd_t *zc)
        return (error);
 }
 
-#ifdef HAVE_ZPL
+#ifdef HAVE_SNAPSHOT
 /*
  * Search the vfs list for a specified resource.  Returns a pointer to it
  * or NULL if no suitable entry is found. The caller of this routine
@@ -2765,7 +2736,7 @@ zfs_get_vfs(const char *resource)
        vfsp = rootvfs;
        do {
                if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) {
-                       VFS_HOLD(vfsp);
+                       mntget(vfsp);
                        vfs_found = vfsp;
                        break;
                }
@@ -2774,7 +2745,7 @@ zfs_get_vfs(const char *resource)
        vfs_list_unlock();
        return (vfs_found);
 }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SNAPSHOT */
 
 /* ARGSUSED */
 static void
@@ -3129,7 +3100,7 @@ out:
 int
 zfs_unmount_snap(const char *name, void *arg)
 {
-#ifdef HAVE_ZPL
+#ifdef HAVE_SNAPSHOT
        vfs_t *vfsp = NULL;
 
        if (arg) {
@@ -3149,14 +3120,14 @@ zfs_unmount_snap(const char *name, void *arg)
                int err;
 
                if ((err = vn_vfswlock(vfsp->vfs_vnodecovered)) != 0) {
-                       VFS_RELE(vfsp);
+                       mntput(vfsp);
                        return (err);
                }
-               VFS_RELE(vfsp);
+               mntput(vfsp);
                if ((err = dounmount(vfsp, flag, kcred)) != 0)
                        return (err);
        }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SNAPSHOT */
        return (0);
 }
 
@@ -3216,10 +3187,9 @@ zfs_ioc_destroy(zfs_cmd_t *zc)
 static int
 zfs_ioc_rollback(zfs_cmd_t *zc)
 {
-#ifdef HAVE_ZPL
        dsl_dataset_t *ds, *clone;
        int error;
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
        char *clone_name;
 
        error = dsl_dataset_hold(zc->zc_name, FTAG, &ds);
@@ -3253,8 +3223,8 @@ zfs_ioc_rollback(zfs_cmd_t *zc)
        /*
         * Do clone swap.
         */
-       if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
-               error = zfs_suspend_fs(zfsvfs);
+       if (get_zfs_sb(zc->zc_name, &zsb) == 0) {
+               error = zfs_suspend_fs(zsb);
                if (error == 0) {
                        int resume_err;
 
@@ -3266,10 +3236,10 @@ zfs_ioc_rollback(zfs_cmd_t *zc)
                        } else {
                                error = EBUSY;
                        }
-                       resume_err = zfs_resume_fs(zfsvfs, zc->zc_name);
+                       resume_err = zfs_resume_fs(zsb, zc->zc_name);
                        error = error ? error : resume_err;
                }
-               VFS_RELE(zfsvfs->z_vfs);
+               mntput(zsb->z_vfs);
        } else {
                if (dsl_dataset_tryown(ds, B_FALSE, FTAG)) {
                        error = dsl_dataset_clone_swap(clone, ds, B_TRUE);
@@ -3290,9 +3260,6 @@ out:
        if (ds)
                dsl_dataset_rele(ds, FTAG);
        return (error);
-#else
-       return (ENOTSUP);
-#endif /* HAVE_ZPL */
 }
 
 /*
@@ -3307,6 +3274,7 @@ static int
 zfs_ioc_rename(zfs_cmd_t *zc)
 {
        boolean_t recursive = zc->zc_cookie & 1;
+       int err;
 
        zc->zc_value[sizeof (zc->zc_value) - 1] = '\0';
        if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
@@ -3320,13 +3288,18 @@ zfs_ioc_rename(zfs_cmd_t *zc)
         */
        if (!recursive && strchr(zc->zc_name, '@') != NULL &&
            zc->zc_objset_type == DMU_OST_ZFS) {
-               int err = zfs_unmount_snap(zc->zc_name, NULL);
+               err = zfs_unmount_snap(zc->zc_name, NULL);
                if (err)
                        return (err);
        }
-       if (zc->zc_objset_type == DMU_OST_ZVOL)
+
+       err = dmu_objset_rename(zc->zc_name, zc->zc_value, recursive);
+       if ((err == 0) && (zc->zc_objset_type == DMU_OST_ZVOL)) {
                (void) zvol_remove_minor(zc->zc_name);
-       return (dmu_objset_rename(zc->zc_name, zc->zc_value, recursive));
+               (void) zvol_create_minor(zc->zc_value);
+       }
+
+       return (err);
 }
 
 static int
@@ -3736,29 +3709,25 @@ zfs_ioc_recv(zfs_cmd_t *zc)
            &zc->zc_action_handle);
 
        if (error == 0) {
-#ifdef HAVE_ZPL
-               zfsvfs_t *zfsvfs = NULL;
+               zfs_sb_t *zsb = NULL;
 
-               if (getzfsvfs(tofs, &zfsvfs) == 0) {
+               if (get_zfs_sb(tofs, &zsb) == 0) {
                        /* online recv */
                        int end_err;
 
-                       error = zfs_suspend_fs(zfsvfs);
+                       error = zfs_suspend_fs(zsb);
                        /*
                         * If the suspend fails, then the recv_end will
                         * likely also fail, and clean up after itself.
                         */
                        end_err = dmu_recv_end(&drc);
                        if (error == 0)
-                               error = zfs_resume_fs(zfsvfs, tofs);
+                               error = zfs_resume_fs(zsb, tofs);
                        error = error ? error : end_err;
-                       VFS_RELE(zfsvfs->z_vfs);
+                       mntput(zsb->z_vfs);
                } else {
                        error = dmu_recv_end(&drc);
                }
-#else
-               error = dmu_recv_end(&drc);
-#endif /* HAVE_ZPL */
        }
 
        zc->zc_cookie = off - fp->f_offset;
@@ -4082,25 +4051,21 @@ zfs_ioc_promote(zfs_cmd_t *zc)
 static int
 zfs_ioc_userspace_one(zfs_cmd_t *zc)
 {
-#ifdef HAVE_ZPL
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
        int error;
 
        if (zc->zc_objset_type >= ZFS_NUM_USERQUOTA_PROPS)
                return (EINVAL);
 
-       error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs, B_FALSE);
+       error = zfs_sb_hold(zc->zc_name, FTAG, &zsb, B_FALSE);
        if (error)
                return (error);
 
-       error = zfs_userspace_one(zfsvfs,
+       error = zfs_userspace_one(zsb,
            zc->zc_objset_type, zc->zc_value, zc->zc_guid, &zc->zc_cookie);
-       zfsvfs_rele(zfsvfs, FTAG);
+       zfs_sb_rele(zsb, FTAG);
 
        return (error);
-#else
-       return (ENOTSUP);
-#endif /* HAVE_ZPL */
 }
 
 /*
@@ -4117,20 +4082,21 @@ zfs_ioc_userspace_one(zfs_cmd_t *zc)
 static int
 zfs_ioc_userspace_many(zfs_cmd_t *zc)
 {
-#ifdef HAVE_ZPL
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
        int bufsize = zc->zc_nvlist_dst_size;
+       int error;
+       void *buf;
 
        if (bufsize <= 0)
                return (ENOMEM);
 
-       int error = zfsvfs_hold(zc->zc_name, FTAG, &zfsvfs, B_FALSE);
+       error = zfs_sb_hold(zc->zc_name, FTAG, &zsb, B_FALSE);
        if (error)
                return (error);
 
-       void *buf = kmem_alloc(bufsize, KM_SLEEP);
+       buf = kmem_alloc(bufsize, KM_SLEEP);
 
-       error = zfs_userspace_many(zfsvfs, zc->zc_objset_type, &zc->zc_cookie,
+       error = zfs_userspace_many(zsb, zc->zc_objset_type, &zc->zc_cookie,
            buf, &zc->zc_nvlist_dst_size);
 
        if (error == 0) {
@@ -4139,12 +4105,9 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc)
                    zc->zc_nvlist_dst_size);
        }
        kmem_free(buf, bufsize);
-       zfsvfs_rele(zfsvfs, FTAG);
+       zfs_sb_rele(zsb, FTAG);
 
        return (error);
-#else
-       return (ENOTSUP);
-#endif /* HAVE_ZPL */
 }
 
 /*
@@ -4157,25 +4120,24 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc)
 static int
 zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
 {
-#ifdef HAVE_ZPL
        objset_t *os;
        int error = 0;
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
 
-       if (getzfsvfs(zc->zc_name, &zfsvfs) == 0) {
-               if (!dmu_objset_userused_enabled(zfsvfs->z_os)) {
+       if (get_zfs_sb(zc->zc_name, &zsb) == 0) {
+               if (!dmu_objset_userused_enabled(zsb->z_os)) {
                        /*
                         * If userused is not enabled, it may be because the
                         * objset needs to be closed & reopened (to grow the
                         * objset_phys_t).  Suspend/resume the fs will do that.
                         */
-                       error = zfs_suspend_fs(zfsvfs);
+                       error = zfs_suspend_fs(zsb);
                        if (error == 0)
-                               error = zfs_resume_fs(zfsvfs, zc->zc_name);
+                               error = zfs_resume_fs(zsb, zc->zc_name);
                }
                if (error == 0)
-                       error = dmu_objset_userspace_upgrade(zfsvfs->z_os);
-               VFS_RELE(zfsvfs->z_vfs);
+                       error = dmu_objset_userspace_upgrade(zsb->z_os);
+               mntput(zsb->z_vfs);
        } else {
                /* XXX kind of reading contents without owning */
                error = dmu_objset_hold(zc->zc_name, FTAG, &os);
@@ -4187,9 +4149,6 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
        }
 
        return (error);
-#else
-       return (ENOTSUP);
-#endif /* HAVE_ZPL */
 }
 
 /*
@@ -4199,7 +4158,7 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
  * the first file system is shared.
  * Neither sharefs, nfs or smbsrv are unloadable modules.
  */
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
 int (*znfsexport_fs)(void *arg);
 int (*zshare_fs)(enum sharefs_sys_op, share_t *, uint32_t);
 int (*zsmbexport_fs)(void *arg, boolean_t add_share);
@@ -4231,12 +4190,12 @@ zfs_init_sharefs()
        }
        return (0);
 }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 
 static int
 zfs_ioc_share(zfs_cmd_t *zc)
 {
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
        int error;
        int opcode;
 
@@ -4328,7 +4287,7 @@ zfs_ioc_share(zfs_cmd_t *zc)
        return (error);
 #else
        return (ENOTSUP);
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 }
 
 ace_t full_access[] = {
@@ -4445,16 +4404,16 @@ zfs_ioc_diff(zfs_cmd_t *zc)
 /*
  * Remove all ACL files in shares dir
  */
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
 static int
 zfs_smb_acl_purge(znode_t *dzp)
 {
        zap_cursor_t    zc;
        zap_attribute_t zap;
-       zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(dzp);
        int error;
 
-       for (zap_cursor_init(&zc, zfsvfs->z_os, dzp->z_id);
+       for (zap_cursor_init(&zc, zsb->z_os, dzp->z_id);
            (error = zap_cursor_retrieve(&zc, &zap)) == 0;
            zap_cursor_advance(&zc)) {
                if ((error = VOP_REMOVE(ZTOV(dzp), zap.za_name, kcred,
@@ -4464,17 +4423,17 @@ zfs_smb_acl_purge(znode_t *dzp)
        zap_cursor_fini(&zc);
        return (error);
 }
-#endif /* HAVE ZPL */
+#endif /* HAVE SHARE */
 
 static int
 zfs_ioc_smb_acl(zfs_cmd_t *zc)
 {
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
        vnode_t *vp;
        znode_t *dzp;
        vnode_t *resourcevp = NULL;
        znode_t *sharedir;
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
        nvlist_t *nvlist;
        char *src, *target;
        vattr_t vattr;
@@ -4495,17 +4454,17 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
        }
 
        dzp = VTOZ(vp);
-       zfsvfs = dzp->z_zfsvfs;
-       ZFS_ENTER(zfsvfs);
+       zsb = ZTOZSB(dzp);
+       ZFS_ENTER(zsb);
 
        /*
         * Create share dir if its missing.
         */
-       mutex_enter(&zfsvfs->z_lock);
-       if (zfsvfs->z_shares_dir == 0) {
+       mutex_enter(&zsb->z_lock);
+       if (zsb->z_shares_dir == 0) {
                dmu_tx_t *tx;
 
-               tx = dmu_tx_create(zfsvfs->z_os);
+               tx = dmu_tx_create(zsb->z_os);
                dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, TRUE,
                    ZFS_SHARES_DIR);
                dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
@@ -4513,29 +4472,28 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
                if (error) {
                        dmu_tx_abort(tx);
                } else {
-                       error = zfs_create_share_dir(zfsvfs, tx);
+                       error = zfs_create_share_dir(zsb, tx);
                        dmu_tx_commit(tx);
                }
                if (error) {
-                       mutex_exit(&zfsvfs->z_lock);
+                       mutex_exit(&zsb->z_lock);
                        VN_RELE(vp);
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
-       mutex_exit(&zfsvfs->z_lock);
+       mutex_exit(&zsb->z_lock);
 
-       ASSERT(zfsvfs->z_shares_dir);
-       if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &sharedir)) != 0) {
+       ASSERT(zsb->z_shares_dir);
+       if ((error = zfs_zget(zsb, zsb->z_shares_dir, &sharedir)) != 0) {
                VN_RELE(vp);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
        switch (zc->zc_cookie) {
        case ZFS_SMB_ACL_ADD:
                vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
-               vattr.va_type = VREG;
                vattr.va_mode = S_IFREG|0777;
                vattr.va_uid = 0;
                vattr.va_gid = 0;
@@ -4560,7 +4518,7 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
                if ((error = get_nvlist(zc->zc_nvlist_src,
                    zc->zc_nvlist_src_size, zc->zc_iflags, &nvlist)) != 0) {
                        VN_RELE(vp);
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
                if (nvlist_lookup_string(nvlist, ZFS_SMB_ACL_SRC, &src) ||
@@ -4568,7 +4526,7 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
                    &target)) {
                        VN_RELE(vp);
                        VN_RELE(ZTOV(sharedir));
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        nvlist_free(nvlist);
                        return (error);
                }
@@ -4589,12 +4547,12 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
        VN_RELE(vp);
        VN_RELE(ZTOV(sharedir));
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
 
        return (error);
 #else
        return (ENOTSUP);
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 }
 
 /*
@@ -5190,10 +5148,8 @@ zfs_detach(void)
        list_destroy(&zfsdev_state_list);
 }
 
-#ifdef HAVE_ZPL
 uint_t zfs_fsyncer_key;
 extern uint_t rrw_tsd_key;
-#endif
 
 #ifdef DEBUG
 #define ZFS_DEBUG_STR  " (DEBUG mode)"
@@ -5215,12 +5171,12 @@ _init(void)
        if ((error = zfs_attach()) != 0)
                goto out2;
 
-#ifdef HAVE_ZPL
        tsd_create(&zfs_fsyncer_key, NULL);
        tsd_create(&rrw_tsd_key, NULL);
 
+#ifdef HAVE_SHARE
        mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SHARE */
 
        printk(KERN_NOTICE "ZFS: Loaded ZFS Filesystem v%s%s\n",
               ZFS_META_VERSION, ZFS_DEBUG_STR);
@@ -5245,7 +5201,7 @@ _fini(void)
        zvol_fini();
        zfs_fini();
        spa_fini();
-#ifdef HAVE_ZPL
+#ifdef HAVE_SHARE
        if (zfs_nfsshare_inited)
                (void) ddi_modclose(nfs_mod);
        if (zfs_smbshare_inited)
@@ -5254,8 +5210,9 @@ _fini(void)
                (void) ddi_modclose(sharefs_mod);
 
        mutex_destroy(&zfs_share_lock);
+#endif /* HAVE_SHARE */
        tsd_destroy(&zfs_fsyncer_key);
-#endif /* HAVE_ZPL */
+       tsd_destroy(&rrw_tsd_key);
 
        printk(KERN_NOTICE "ZFS: Unloaded ZFS Filesystem v%s%s\n",
               ZFS_META_VERSION, ZFS_DEBUG_STR);
index 59a6451..5cdbb6c 100644 (file)
@@ -22,7 +22,6 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#ifdef HAVE_ZPL
 
 #include <sys/types.h>
 #include <sys/param.h>
 int
 zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap)
 {
+#ifdef HAVE_XVATTR
        int isxvattr = (vap->va_mask & AT_XVATTR);
+#else
+       int isxvattr = 0;
+#endif /* HAVE_XVATTR */
        switch (type) {
        case Z_FILE:
                if (vsecp == NULL && !isxvattr)
@@ -98,6 +101,7 @@ zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap)
        return (TX_MAX_TYPE);
 }
 
+#ifdef HAVE_XVATTR
 /*
  * build up the log data necessary for logging xvattr_t
  * First lr_attr_t is initialized.  following the lr_attr_t
@@ -211,6 +215,7 @@ zfs_log_fuid_domains(zfs_fuid_info_t *fuidp, void *start)
        }
        return (start);
 }
+#endif /* HAVE_XVATTR */
 
 /*
  * zfs_log_create() is used to handle TX_CREATE, TX_CREATE_ATTR, TX_MKDIR,
@@ -239,11 +244,13 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
 {
        itx_t *itx;
        lr_create_t *lr;
+#ifdef HAVE_XVATTR
        lr_acl_create_t *lracl;
+       xvattr_t *xvap = (xvattr_t *)vap;
+#endif /* HAVE_XVATTR */
        size_t aclsize;
        size_t xvatsize = 0;
        size_t txsize;
-       xvattr_t *xvap = (xvattr_t *)vap;
        void *end;
        size_t lrsize;
        size_t namesize = strlen(name) + 1;
@@ -261,8 +268,10 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
                fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t);
        }
 
+#ifdef HAVE_XVATTR
        if (vap->va_mask & AT_XVATTR)
                xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize);
+#endif /* HAVE_XVATTR */
 
        if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR ||
            (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR ||
@@ -293,18 +302,19 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
        } else {
                lr->lr_gid = fuidp->z_fuid_group;
        }
-       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zp->z_zfsvfs), &lr->lr_gen,
+       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen,
            sizeof (uint64_t));
-       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs),
+       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)),
            lr->lr_crtime, sizeof (uint64_t) * 2);
 
-       if (sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zp->z_zfsvfs), &lr->lr_rdev,
+       if (sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(zp)), &lr->lr_rdev,
            sizeof (lr->lr_rdev)) != 0)
                lr->lr_rdev = 0;
 
        /*
         * Fill in xvattr info if any
         */
+#ifdef HAVE_XVATTR
        if (vap->va_mask & AT_XVATTR) {
                zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap);
                end = (caddr_t)lr + lrsize + xvatsize;
@@ -334,6 +344,9 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
                end = zfs_log_fuid_ids(fuidp, end);
                end = zfs_log_fuid_domains(fuidp, end);
        }
+#else
+       end = (caddr_t)lr + lrsize;
+#endif /* HAVE_XVATTR */
        /*
         * Now place file name in log record
         */
@@ -411,9 +424,9 @@ zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
        lr->lr_uid = zp->z_uid;
        lr->lr_gid = zp->z_gid;
        lr->lr_mode = zp->z_mode;
-       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zp->z_zfsvfs), &lr->lr_gen,
+       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(ZTOZSB(zp)), &lr->lr_gen,
            sizeof (uint64_t));
-       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs),
+       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)),
            lr->lr_crtime, sizeof (uint64_t) * 2);
        bcopy(name, (char *)(lr + 1), namesize);
        bcopy(link, (char *)(lr + 1) + namesize, linksize);
@@ -496,7 +509,7 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
                itx = zil_itx_create(txtype, sizeof (*lr) +
                    (write_state == WR_COPIED ? len : 0));
                lr = (lr_write_t *)&itx->itx_lr;
-               if (write_state == WR_COPIED && dmu_read(zp->z_zfsvfs->z_os,
+               if (write_state == WR_COPIED && dmu_read(ZTOZSB(zp)->z_os,
                    zp->z_id, off, len, lr + 1, DMU_READ_NO_PREFETCH) != 0) {
                        zil_itx_destroy(itx);
                        itx = zil_itx_create(txtype, sizeof (*lr));
@@ -513,7 +526,7 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype,
                lr->lr_blkoff = 0;
                BP_ZERO(&lr->lr_blkptr);
 
-               itx->itx_private = zp->z_zfsvfs;
+               itx->itx_private = ZTOZSB(zp);
 
                if (!(ioflag & (FSYNC | FDSYNC)) && (zp->z_sync_cnt == 0) &&
                    (fsync_cnt == 0))
@@ -553,12 +566,14 @@ zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
  * zfs_log_setattr() handles TX_SETATTR transactions.
  */
 void
-zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
-       znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp)
+zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp,
+    struct iattr *attr, uint_t mask_applied, zfs_fuid_info_t *fuidp)
 {
        itx_t           *itx;
        lr_setattr_t    *lr;
+#ifdef HAVE_XVATTR
        xvattr_t        *xvap = (xvattr_t *)vap;
+#endif /* HAVEXVATTR */
        size_t          recsize = sizeof (lr_setattr_t);
        void            *start;
 
@@ -570,32 +585,35 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
         * for lr_attr_t + xvattr mask, mapsize and create time
         * plus actual attribute values
         */
-       if (vap->va_mask & AT_XVATTR)
+#ifdef HAVE_XVATTR
+       if (attr->ia_valid & AT_XVATTR)
                recsize = sizeof (*lr) + ZIL_XVAT_SIZE(xvap->xva_mapsize);
 
        if (fuidp)
                recsize += fuidp->z_domain_str_sz;
+#endif /* HAVE_XVATTR */
 
        itx = zil_itx_create(txtype, recsize);
        lr = (lr_setattr_t *)&itx->itx_lr;
        lr->lr_foid = zp->z_id;
        lr->lr_mask = (uint64_t)mask_applied;
-       lr->lr_mode = (uint64_t)vap->va_mode;
-       if ((mask_applied & AT_UID) && IS_EPHEMERAL(vap->va_uid))
+       lr->lr_mode = (uint64_t)attr->ia_mode;
+       if ((mask_applied & ATTR_UID) && IS_EPHEMERAL(attr->ia_uid))
                lr->lr_uid = fuidp->z_fuid_owner;
        else
-               lr->lr_uid = (uint64_t)vap->va_uid;
+               lr->lr_uid = (uint64_t)attr->ia_uid;
 
-       if ((mask_applied & AT_GID) && IS_EPHEMERAL(vap->va_gid))
+       if ((mask_applied & ATTR_GID) && IS_EPHEMERAL(attr->ia_gid))
                lr->lr_gid = fuidp->z_fuid_group;
        else
-               lr->lr_gid = (uint64_t)vap->va_gid;
+               lr->lr_gid = (uint64_t)attr->ia_gid;
 
-       lr->lr_size = (uint64_t)vap->va_size;
-       ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime);
-       ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime);
+       lr->lr_size = (uint64_t)attr->ia_size;
+       ZFS_TIME_ENCODE(&attr->ia_atime, lr->lr_atime);
+       ZFS_TIME_ENCODE(&attr->ia_mtime, lr->lr_mtime);
        start = (lr_setattr_t *)(lr + 1);
-       if (vap->va_mask & AT_XVATTR) {
+#ifdef HAVE_XVATTR
+       if (attr->ia_valid & ATTR_XVATTR) {
                zfs_log_xvattr((lr_attr_t *)start, xvap);
                start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize);
        }
@@ -606,6 +624,7 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
 
        if (fuidp)
                (void) zfs_log_fuid_domains(fuidp, start);
+#endif /* HAVE_XVATTR */
 
        itx->itx_sync = (zp->z_sync_cnt != 0);
        zil_itx_assign(zilog, itx, tx);
@@ -629,7 +648,7 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
        if (zil_replaying(zilog, tx) || zp->z_unlinked)
                return;
 
-       txtype = (zp->z_zfsvfs->z_version < ZPL_VERSION_FUID) ?
+       txtype = (ZTOZSB(zp)->z_version < ZPL_VERSION_FUID) ?
            TX_ACL_V0 : TX_ACL;
 
        if (txtype == TX_ACL)
@@ -667,14 +686,14 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
 
                start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes);
 
+#ifdef HAVE_XVATTR
                if (fuidp) {
                        start = zfs_log_fuid_ids(fuidp, start);
                        (void) zfs_log_fuid_domains(fuidp, start);
                }
+#endif /* HAVE_XVATTR */
        }
 
        itx->itx_sync = (zp->z_sync_cnt != 0);
        zil_itx_assign(zilog, itx, tx);
 }
-
-#endif /* HAVE_ZPL */
index bd29ab9..f02d5ad 100644 (file)
@@ -22,8 +22,6 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#ifdef HAVE_ZPL
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -41,6 +39,7 @@
 #include <sys/zfs_fuid.h>
 #include <sys/spa.h>
 #include <sys/zil.h>
+#include <sys/zfs_vnops.h>
 #include <sys/byteorder.h>
 #include <sys/stat.h>
 #include <sys/mode.h>
  */
 
 static void
-zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode,
-       uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid)
+zfs_init_iattr(struct iattr *attr, uint64_t mask, uint64_t mode,
+       uint64_t uid, uint64_t gid)
 {
-       bzero(vap, sizeof (*vap));
-       vap->va_mask = (uint_t)mask;
-       vap->va_type = IFTOVT(mode);
-       vap->va_mode = mode & MODEMASK;
-       vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
-       vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
-       vap->va_rdev = zfs_cmpldev(rdev);
-       vap->va_nodeid = nodeid;
+       memset(attr, 0, sizeof(*attr));
+       attr->ia_valid = (uint_t)mask;
+       attr->ia_mode = mode;
+       attr->ia_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
+       attr->ia_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
 }
 
 /* ARGSUSED */
 static int
-zfs_replay_error(zfsvfs_t *zfsvfs, lr_t *lr, boolean_t byteswap)
+zfs_replay_error(zfs_sb_t *zsb, lr_t *lr, boolean_t byteswap)
 {
        return (ENOTSUP);
 }
 
+#ifdef HAVE_XVATTR
 static void
 zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
 {
@@ -135,6 +132,7 @@ zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
        if (XVA_ISSET_REQ(xvap, XAT_SPARSE))
                xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0);
 }
+#endif /* HAVE_XVATTR */
 
 static int
 zfs_replay_domain_cnt(uint64_t uid, uint64_t gid)
@@ -263,16 +261,17 @@ zfs_replay_swap_attrs(lr_attr_t *lrattr)
  * as option FUID information.
  */
 static int
-zfs_replay_create_acl(zfsvfs_t *zfsvfs,
-    lr_acl_create_t *lracl, boolean_t byteswap)
+zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap)
 {
        char *name = NULL;              /* location determined later */
        lr_create_t *lr = (lr_create_t *)lracl;
        znode_t *dzp;
-       vnode_t *vp = NULL;
+       struct inode *ip = NULL;
+#ifdef HAVE_XVATTR
        xvattr_t xva;
-       int vflg = 0;
        vsecattr_t vsec = { 0 };
+#endif /* HAVE_XVATTR */
+       int vflg = 0;
        lr_attr_t *lrattr;
        void *aclstart;
        void *fuidstart;
@@ -300,24 +299,26 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs,
                }
        }
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0)
                return (error);
 
+#ifdef HAVE_XVATTR
        xva_init(&xva);
-       zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID,
-           lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid);
+       zfs_init_iattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID,
+           lr->lr_mode, lr->lr_uid, lr->lr_gid, /*lr->lr_rdev, lr->lr_foid*/);
 
        /*
         * All forms of zfs create (create, mkdir, mkxattrdir, symlink)
         * eventually end up in zfs_mknode(), which assigns the object's
-        * creation time and generation number.  The generic VOP_CREATE()
+        * creation time and generation number.  The generic zfs_create()
         * doesn't have either concept, so we smuggle the values inside
         * the vattr's otherwise unused va_ctime and va_nblocks fields.
         */
        ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime);
        xva.xva_vattr.va_nblocks = lr->lr_gen;
+#endif /* HAVE_XVATTR */
 
-       error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL);
+       error = dmu_object_info(zsb->z_os, lr->lr_foid, NULL);
        if (error != ENOENT)
                goto bail;
 
@@ -328,11 +329,12 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs,
                aclstart = (caddr_t)(lracl + 1);
                fuidstart = (caddr_t)aclstart +
                    ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
-               zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart,
+               zsb->z_fuid_replay = zfs_replay_fuids(fuidstart,
                    (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
                    lr->lr_uid, lr->lr_gid);
                /*FALLTHROUGH*/
        case TX_CREATE_ACL_ATTR:
+#ifdef HAVE_XVATTR
                if (name == NULL) {
                        lrattr = (lr_attr_t *)(caddr_t)(lracl + 1);
                        xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
@@ -344,27 +346,29 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs,
                vsec.vsa_aclcnt = lracl->lr_aclcnt;
                vsec.vsa_aclentsz = lracl->lr_acl_bytes;
                vsec.vsa_aclflags = lracl->lr_acl_flags;
-               if (zfsvfs->z_fuid_replay == NULL) {
+               if (zsb->z_fuid_replay == NULL) {
                        fuidstart = (caddr_t)(lracl + 1) + xvatlen +
                            ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
-                       zfsvfs->z_fuid_replay =
+                       zsb->z_fuid_replay =
                            zfs_replay_fuids(fuidstart,
                            (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
                            lr->lr_uid, lr->lr_gid);
                }
 
-               error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr,
-                   0, 0, &vp, kcred, vflg, NULL, &vsec);
+               error = zfs_create(ZTOI(dzp), name, &xva.xva_vattr,
+                   0, 0, &ip, kcred, vflg, NULL, &vsec);
+#endif /* HAVE_XVATTR */
                break;
        case TX_MKDIR_ACL:
                aclstart = (caddr_t)(lracl + 1);
                fuidstart = (caddr_t)aclstart +
                    ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
-               zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart,
+               zsb->z_fuid_replay = zfs_replay_fuids(fuidstart,
                    (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
                    lr->lr_uid, lr->lr_gid);
                /*FALLTHROUGH*/
        case TX_MKDIR_ACL_ATTR:
+#ifdef HAVE_XVATTR
                if (name == NULL) {
                        lrattr = (lr_attr_t *)(caddr_t)(lracl + 1);
                        xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
@@ -375,47 +379,50 @@ zfs_replay_create_acl(zfsvfs_t *zfsvfs,
                vsec.vsa_aclcnt = lracl->lr_aclcnt;
                vsec.vsa_aclentsz = lracl->lr_acl_bytes;
                vsec.vsa_aclflags = lracl->lr_acl_flags;
-               if (zfsvfs->z_fuid_replay == NULL) {
+               if (zsb->z_fuid_replay == NULL) {
                        fuidstart = (caddr_t)(lracl + 1) + xvatlen +
                            ZIL_ACE_LENGTH(lracl->lr_acl_bytes);
-                       zfsvfs->z_fuid_replay =
+                       zsb->z_fuid_replay =
                            zfs_replay_fuids(fuidstart,
                            (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt,
                            lr->lr_uid, lr->lr_gid);
                }
-               error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr,
-                   &vp, kcred, NULL, vflg, &vsec);
+               error = zfs_mkdir(ZTOI(dzp), name, &xva.xva_vattr,
+                   &ip, kcred, NULL, vflg, &vsec);
+#endif /* HAVE_XVATTR */
                break;
        default:
                error = ENOTSUP;
        }
 
 bail:
-       if (error == 0 && vp != NULL)
-               VN_RELE(vp);
+       if (error == 0 && ip != NULL)
+               iput(ip);
 
-       VN_RELE(ZTOV(dzp));
+       iput(ZTOI(dzp));
 
-       if (zfsvfs->z_fuid_replay)
-               zfs_fuid_info_free(zfsvfs->z_fuid_replay);
-       zfsvfs->z_fuid_replay = NULL;
+       if (zsb->z_fuid_replay)
+               zfs_fuid_info_free(zsb->z_fuid_replay);
+       zsb->z_fuid_replay = NULL;
 
        return (error);
 }
 
 static int
-zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap)
+zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap)
 {
        char *name = NULL;              /* location determined later */
        char *link;                     /* symlink content follows name */
        znode_t *dzp;
-       vnode_t *vp = NULL;
+       struct inode *ip = NULL;
        xvattr_t xva;
        int vflg = 0;
+#ifdef HAVE_XVATTR
        size_t lrsize = sizeof (lr_create_t);
        lr_attr_t *lrattr;
-       void *start;
        size_t xvatlen;
+#endif /* HAVE_XVATTR */
+       void *start;
        uint64_t txtype;
        int error;
 
@@ -427,24 +434,26 @@ zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap)
        }
 
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0)
                return (error);
 
+#ifdef HAVE_XVATTR
        xva_init(&xva);
-       zfs_init_vattr(&xva.xva_vattr, AT_TYPE | AT_MODE | AT_UID | AT_GID,
-           lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid);
+       zfs_init_iattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID,
+           lr->lr_mode, lr->lr_uid, lr->lr_gid, /*lr->lr_rdev, lr->lr_foid*/);
 
        /*
         * All forms of zfs create (create, mkdir, mkxattrdir, symlink)
         * eventually end up in zfs_mknode(), which assigns the object's
-        * creation time and generation number.  The generic VOP_CREATE()
+        * creation time and generation number.  The generic zfs_create()
         * doesn't have either concept, so we smuggle the values inside
         * the vattr's otherwise unused va_ctime and va_nblocks fields.
         */
        ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime);
        xva.xva_vattr.va_nblocks = lr->lr_gen;
+#endif /* HAVE_XVATTR */
 
-       error = dmu_object_info(zfsvfs->z_os, lr->lr_foid, NULL);
+       error = dmu_object_info(zsb->z_os, lr->lr_foid, NULL);
        if (error != ENOENT)
                goto out;
 
@@ -461,75 +470,79 @@ zfs_replay_create(zfsvfs_t *zfsvfs, lr_create_t *lr, boolean_t byteswap)
            (int)lr->lr_common.lrc_txtype != TX_MKDIR_ATTR &&
            (int)lr->lr_common.lrc_txtype != TX_CREATE_ATTR) {
                start = (lr + 1);
-               zfsvfs->z_fuid_replay =
+               zsb->z_fuid_replay =
                    zfs_replay_fuid_domain(start, &start,
                    lr->lr_uid, lr->lr_gid);
        }
 
        switch (txtype) {
        case TX_CREATE_ATTR:
+#ifdef HAVE_XVATTR
                lrattr = (lr_attr_t *)(caddr_t)(lr + 1);
                xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
                zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva);
                start = (caddr_t)(lr + 1) + xvatlen;
-               zfsvfs->z_fuid_replay =
+               zsb->z_fuid_replay =
                    zfs_replay_fuid_domain(start, &start,
                    lr->lr_uid, lr->lr_gid);
                name = (char *)start;
+#endif /* HAVE_XVATTR */
 
                /*FALLTHROUGH*/
        case TX_CREATE:
                if (name == NULL)
                        name = (char *)start;
 
-               error = VOP_CREATE(ZTOV(dzp), name, &xva.xva_vattr,
-                   0, 0, &vp, kcred, vflg, NULL, NULL);
+               error = zfs_create(ZTOI(dzp), name, &xva.xva_vattr,
+                   0, 0, &ip, kcred, vflg, NULL);
                break;
        case TX_MKDIR_ATTR:
+#ifdef HAVE_XVATTR
                lrattr = (lr_attr_t *)(caddr_t)(lr + 1);
                xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize);
                zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva);
                start = (caddr_t)(lr + 1) + xvatlen;
-               zfsvfs->z_fuid_replay =
+               zsb->z_fuid_replay =
                    zfs_replay_fuid_domain(start, &start,
                    lr->lr_uid, lr->lr_gid);
                name = (char *)start;
+#endif /* HAVE_XVATTR */
 
                /*FALLTHROUGH*/
        case TX_MKDIR:
                if (name == NULL)
                        name = (char *)(lr + 1);
 
-               error = VOP_MKDIR(ZTOV(dzp), name, &xva.xva_vattr,
-                   &vp, kcred, NULL, vflg, NULL);
+               error = zfs_mkdir(ZTOI(dzp), name, &xva.xva_vattr,
+                   &ip, kcred, vflg, NULL);
                break;
        case TX_MKXATTR:
-               error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &vp, kcred);
+               error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &ip, kcred);
                break;
        case TX_SYMLINK:
                name = (char *)(lr + 1);
                link = name + strlen(name) + 1;
-               error = VOP_SYMLINK(ZTOV(dzp), name, &xva.xva_vattr,
-                   link, kcred, NULL, vflg);
+               error = zfs_symlink(ZTOI(dzp), name, &xva.xva_vattr,
+                   link, &ip, kcred, vflg);
                break;
        default:
                error = ENOTSUP;
        }
 
 out:
-       if (error == 0 && vp != NULL)
-               VN_RELE(vp);
+       if (error == 0 && ip != NULL)
+               iput(ip);
 
-       VN_RELE(ZTOV(dzp));
+       iput(ZTOI(dzp));
 
-       if (zfsvfs->z_fuid_replay)
-               zfs_fuid_info_free(zfsvfs->z_fuid_replay);
-       zfsvfs->z_fuid_replay = NULL;
+       if (zsb->z_fuid_replay)
+               zfs_fuid_info_free(zsb->z_fuid_replay);
+       zsb->z_fuid_replay = NULL;
        return (error);
 }
 
 static int
-zfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap)
+zfs_replay_remove(zfs_sb_t *zsb, lr_remove_t *lr, boolean_t byteswap)
 {
        char *name = (char *)(lr + 1);  /* name follows lr_remove_t */
        znode_t *dzp;
@@ -539,60 +552,63 @@ zfs_replay_remove(zfsvfs_t *zfsvfs, lr_remove_t *lr, boolean_t byteswap)
        if (byteswap)
                byteswap_uint64_array(lr, sizeof (*lr));
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0)
                return (error);
 
+#ifdef HAVE_PN_UTILS
        if (lr->lr_common.lrc_txtype & TX_CI)
                vflg |= FIGNORECASE;
+#endif
 
        switch ((int)lr->lr_common.lrc_txtype) {
        case TX_REMOVE:
-               error = VOP_REMOVE(ZTOV(dzp), name, kcred, NULL, vflg);
+               error = zfs_remove(ZTOI(dzp), name, kcred);
                break;
        case TX_RMDIR:
-               error = VOP_RMDIR(ZTOV(dzp), name, NULL, kcred, NULL, vflg);
+               error = zfs_rmdir(ZTOI(dzp), name, NULL, kcred, vflg);
                break;
        default:
                error = ENOTSUP;
        }
 
-       VN_RELE(ZTOV(dzp));
+       iput(ZTOI(dzp));
 
        return (error);
 }
 
 static int
-zfs_replay_link(zfsvfs_t *zfsvfs, lr_link_t *lr, boolean_t byteswap)
+zfs_replay_link(zfs_sb_t *zsb, lr_link_t *lr, boolean_t byteswap)
 {
        char *name = (char *)(lr + 1);  /* name follows lr_link_t */
        znode_t *dzp, *zp;
        int error;
-       int vflg = 0;
 
        if (byteswap)
                byteswap_uint64_array(lr, sizeof (*lr));
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_doid, &dzp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0)
                return (error);
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_link_obj, &zp)) != 0) {
-               VN_RELE(ZTOV(dzp));
+       if ((error = zfs_zget(zsb, lr->lr_link_obj, &zp)) != 0) {
+               iput(ZTOI(dzp));
                return (error);
        }
 
+#ifdef HAVE_PN_UTILS
        if (lr->lr_common.lrc_txtype & TX_CI)
                vflg |= FIGNORECASE;
+#endif
 
-       error = VOP_LINK(ZTOV(dzp), ZTOV(zp), name, kcred, NULL, vflg);
+       error = zfs_link(ZTOI(dzp), ZTOI(zp), name, kcred);
 
-       VN_RELE(ZTOV(zp));
-       VN_RELE(ZTOV(dzp));
+       iput(ZTOI(zp));
+       iput(ZTOI(dzp));
 
        return (error);
 }
 
 static int
-zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap)
+zfs_replay_rename(zfs_sb_t *zsb, lr_rename_t *lr, boolean_t byteswap)
 {
        char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */
        char *tname = sname + strlen(sname) + 1;
@@ -603,39 +619,39 @@ zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, boolean_t byteswap)
        if (byteswap)
                byteswap_uint64_array(lr, sizeof (*lr));
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_sdoid, &sdzp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_sdoid, &sdzp)) != 0)
                return (error);
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_tdoid, &tdzp)) != 0) {
-               VN_RELE(ZTOV(sdzp));
+       if ((error = zfs_zget(zsb, lr->lr_tdoid, &tdzp)) != 0) {
+               iput(ZTOI(sdzp));
                return (error);
        }
 
        if (lr->lr_common.lrc_txtype & TX_CI)
                vflg |= FIGNORECASE;
 
-       error = VOP_RENAME(ZTOV(sdzp), sname, ZTOV(tdzp), tname, kcred,
-           NULL, vflg);
+       error = zfs_rename(ZTOI(sdzp), sname, ZTOI(tdzp), tname, kcred, vflg);
 
-       VN_RELE(ZTOV(tdzp));
-       VN_RELE(ZTOV(sdzp));
+       iput(ZTOI(tdzp));
+       iput(ZTOI(sdzp));
 
        return (error);
 }
 
 static int
-zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap)
+zfs_replay_write(zfs_sb_t *zsb, lr_write_t *lr, boolean_t byteswap)
 {
+#if 0
        char *data = (char *)(lr + 1);  /* data follows lr_write_t */
+#endif
        znode_t *zp;
        int error;
-       ssize_t resid;
        uint64_t eod, offset, length;
 
        if (byteswap)
                byteswap_uint64_array(lr, sizeof (*lr));
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) {
+       if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0) {
                /*
                 * As we can log writes out of order, it's possible the
                 * file has been removed. In this case just drop the write
@@ -658,10 +674,10 @@ zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap)
         * write needs to be there. So we write the whole block and
         * reduce the eof. This needs to be done within the single dmu
         * transaction created within vn_rdwr -> zfs_write. So a possible
-        * new end of file is passed through in zfsvfs->z_replay_eof
+        * new end of file is passed through in zsb->z_replay_eof
         */
 
-       zfsvfs->z_replay_eof = 0; /* 0 means don't change end of file */
+       zsb->z_replay_eof = 0; /* 0 means don't change end of file */
 
        /* If it's a dmu_sync() block, write the whole block */
        if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
@@ -671,14 +687,19 @@ zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap)
                        length = blocksize;
                }
                if (zp->z_size < eod)
-                       zfsvfs->z_replay_eof = eod;
+                       zsb->z_replay_eof = eod;
        }
 
-       error = vn_rdwr(UIO_WRITE, ZTOV(zp), data, length, offset,
+       /*
+        * XXX: Use zfs_write() once uio types are removed
+        */
+#if 0
+        error = vn_rdwr(UIO_WRITE, ZTOI(zp), data, length, offset,
            UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid);
+#endif
 
-       VN_RELE(ZTOV(zp));
-       zfsvfs->z_replay_eof = 0;       /* safety */
+       iput(ZTOI(zp));
+       zsb->z_replay_eof = 0;  /* safety */
 
        return (error);
 }
@@ -690,7 +711,7 @@ zfs_replay_write(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap)
  * the file is grown.
  */
 static int
-zfs_replay_write2(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap)
+zfs_replay_write2(zfs_sb_t *zsb, lr_write_t *lr, boolean_t byteswap)
 {
        znode_t *zp;
        int error;
@@ -699,19 +720,19 @@ zfs_replay_write2(zfsvfs_t *zfsvfs, lr_write_t *lr, boolean_t byteswap)
        if (byteswap)
                byteswap_uint64_array(lr, sizeof (*lr));
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0)
                return (error);
 
 top:
        end = lr->lr_offset + lr->lr_length;
        if (end > zp->z_size) {
-               dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os);
+               dmu_tx_t *tx = dmu_tx_create(zsb->z_os);
 
                zp->z_size = end;
                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
                error = dmu_tx_assign(tx, TXG_WAIT);
                if (error) {
-                       VN_RELE(ZTOV(zp));
+                       iput(ZTOI(zp));
                        if (error == ERESTART) {
                                dmu_tx_wait(tx);
                                dmu_tx_abort(tx);
@@ -720,22 +741,22 @@ top:
                        dmu_tx_abort(tx);
                        return (error);
                }
-               (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs),
+               (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zsb),
                    (void *)&zp->z_size, sizeof (uint64_t), tx);
 
                /* Ensure the replayed seq is updated */
-               (void) zil_replaying(zfsvfs->z_log, tx);
+               (void) zil_replaying(zsb->z_log, tx);
 
                dmu_tx_commit(tx);
        }
 
-       VN_RELE(ZTOV(zp));
+       iput(ZTOI(zp));
 
        return (error);
 }
 
 static int
-zfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap)
+zfs_replay_truncate(zfs_sb_t *zsb, lr_truncate_t *lr, boolean_t byteswap)
 {
        znode_t *zp;
        flock64_t fl;
@@ -744,7 +765,7 @@ zfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap)
        if (byteswap)
                byteswap_uint64_array(lr, sizeof (*lr));
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0)
                return (error);
 
        bzero(&fl, sizeof (fl));
@@ -753,68 +774,75 @@ zfs_replay_truncate(zfsvfs_t *zfsvfs, lr_truncate_t *lr, boolean_t byteswap)
        fl.l_start = lr->lr_offset;
        fl.l_len = lr->lr_length;
 
-       error = VOP_SPACE(ZTOV(zp), F_FREESP, &fl, FWRITE | FOFFMAX,
-           lr->lr_offset, kcred, NULL);
+       error = zfs_space(ZTOI(zp), F_FREESP, &fl, FWRITE | FOFFMAX,
+           lr->lr_offset, kcred);
 
-       VN_RELE(ZTOV(zp));
+       iput(ZTOI(zp));
 
        return (error);
 }
 
 static int
-zfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap)
+zfs_replay_setattr(zfs_sb_t *zsb, lr_setattr_t *lr, boolean_t byteswap)
 {
        znode_t *zp;
+#ifdef HAVE_XVATTR
        xvattr_t xva;
-       vattr_t *vap = &xva.xva_vattr;
+#endif /* HAVE_XATTR */
+       struct iattr attr;
        int error;
        void *start;
 
+#ifdef HAVE_XVATTR
        xva_init(&xva);
+#endif /* HAVE_XVATTR */
        if (byteswap) {
                byteswap_uint64_array(lr, sizeof (*lr));
 
+#ifdef HAVE_XVATTR
                if ((lr->lr_mask & AT_XVATTR) &&
-                   zfsvfs->z_version >= ZPL_VERSION_INITIAL)
+                   zsb->z_version >= ZPL_VERSION_INITIAL)
                        zfs_replay_swap_attrs((lr_attr_t *)(lr + 1));
+#endif /* HAVE_XVATTR */
        }
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0)
                return (error);
 
-       zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode,
-           lr->lr_uid, lr->lr_gid, 0, lr->lr_foid);
+       zfs_init_iattr(&attr, lr->lr_mask, lr->lr_mode, lr->lr_uid, lr->lr_gid);
 
-       vap->va_size = lr->lr_size;
-       ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime);
-       ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime);
+       attr.ia_size = lr->lr_size;
+       ZFS_TIME_DECODE(&attr.ia_atime, lr->lr_atime);
+       ZFS_TIME_DECODE(&attr.ia_mtime, lr->lr_mtime);
 
        /*
         * Fill in xvattr_t portions if necessary.
         */
 
        start = (lr_setattr_t *)(lr + 1);
-       if (vap->va_mask & AT_XVATTR) {
+#ifdef HAVE_XVATTR
+       if (iattr->ia_mask & AT_XVATTR) {
                zfs_replay_xvattr((lr_attr_t *)start, &xva);
                start = (caddr_t)start +
                    ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize);
        } else
                xva.xva_vattr.va_mask &= ~AT_XVATTR;
+#endif /* HAVE_XVATTR */
 
-       zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start,
+       zsb->z_fuid_replay = zfs_replay_fuid_domain(start, &start,
            lr->lr_uid, lr->lr_gid);
 
-       error = VOP_SETATTR(ZTOV(zp), vap, 0, kcred, NULL);
+       error = zfs_setattr(ZTOI(zp), &attr, 0, kcred);
 
-       zfs_fuid_info_free(zfsvfs->z_fuid_replay);
-       zfsvfs->z_fuid_replay = NULL;
-       VN_RELE(ZTOV(zp));
+       zfs_fuid_info_free(zsb->z_fuid_replay);
+       zsb->z_fuid_replay = NULL;
+       iput(ZTOI(zp));
 
        return (error);
 }
 
 static int
-zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap)
+zfs_replay_acl_v0(zfs_sb_t *zsb, lr_acl_v0_t *lr, boolean_t byteswap)
 {
        ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */
        vsecattr_t vsa;
@@ -826,7 +854,7 @@ zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap)
                zfs_oldace_byteswap(ace, lr->lr_aclcnt);
        }
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0)
                return (error);
 
        bzero(&vsa, sizeof (vsa));
@@ -836,9 +864,9 @@ zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap)
        vsa.vsa_aclflags = 0;
        vsa.vsa_aclentp = ace;
 
-       error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL);
+       error = zfs_setsecattr(ZTOI(zp), &vsa, 0, kcred);
 
-       VN_RELE(ZTOV(zp));
+       iput(ZTOI(zp));
 
        return (error);
 }
@@ -858,7 +886,7 @@ zfs_replay_acl_v0(zfsvfs_t *zfsvfs, lr_acl_v0_t *lr, boolean_t byteswap)
  *
  */
 static int
-zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap)
+zfs_replay_acl(zfs_sb_t *zsb, lr_acl_t *lr, boolean_t byteswap)
 {
        ace_t *ace = (ace_t *)(lr + 1);
        vsecattr_t vsa;
@@ -875,7 +903,7 @@ zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap)
                }
        }
 
-       if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0)
+       if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0)
                return (error);
 
        bzero(&vsa, sizeof (vsa));
@@ -889,18 +917,18 @@ zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap)
                void *fuidstart = (caddr_t)ace +
                    ZIL_ACE_LENGTH(lr->lr_acl_bytes);
 
-               zfsvfs->z_fuid_replay =
+               zsb->z_fuid_replay =
                    zfs_replay_fuids(fuidstart, &fuidstart,
                    lr->lr_fuidcnt, lr->lr_domcnt, 0, 0);
        }
 
-       error = VOP_SETSECATTR(ZTOV(zp), &vsa, 0, kcred, NULL);
+       error = zfs_setsecattr(ZTOI(zp), &vsa, 0, kcred);
 
-       if (zfsvfs->z_fuid_replay)
-               zfs_fuid_info_free(zfsvfs->z_fuid_replay);
+       if (zsb->z_fuid_replay)
+               zfs_fuid_info_free(zsb->z_fuid_replay);
 
-       zfsvfs->z_fuid_replay = NULL;
-       VN_RELE(ZTOV(zp));
+       zsb->z_fuid_replay = NULL;
+       iput(ZTOI(zp));
 
        return (error);
 }
@@ -909,26 +937,25 @@ zfs_replay_acl(zfsvfs_t *zfsvfs, lr_acl_t *lr, boolean_t byteswap)
  * Callback vectors for replaying records
  */
 zil_replay_func_t *zfs_replay_vector[TX_MAX_TYPE] = {
-       zfs_replay_error,       /* 0 no such transaction type */
-       zfs_replay_create,      /* TX_CREATE */
-       zfs_replay_create,      /* TX_MKDIR */
-       zfs_replay_create,      /* TX_MKXATTR */
-       zfs_replay_create,      /* TX_SYMLINK */
-       zfs_replay_remove,      /* TX_REMOVE */
-       zfs_replay_remove,      /* TX_RMDIR */
-       zfs_replay_link,        /* TX_LINK */
-       zfs_replay_rename,      /* TX_RENAME */
-       zfs_replay_write,       /* TX_WRITE */
-       zfs_replay_truncate,    /* TX_TRUNCATE */
-       zfs_replay_setattr,     /* TX_SETATTR */
-       zfs_replay_acl_v0,      /* TX_ACL_V0 */
-       zfs_replay_acl,         /* TX_ACL */
-       zfs_replay_create_acl,  /* TX_CREATE_ACL */
-       zfs_replay_create,      /* TX_CREATE_ATTR */
-       zfs_replay_create_acl,  /* TX_CREATE_ACL_ATTR */
-       zfs_replay_create_acl,  /* TX_MKDIR_ACL */
-       zfs_replay_create,      /* TX_MKDIR_ATTR */
-       zfs_replay_create_acl,  /* TX_MKDIR_ACL_ATTR */
-       zfs_replay_write2,      /* TX_WRITE2 */
+       (zil_replay_func_t *)zfs_replay_error,          /* no such type */
+       (zil_replay_func_t *)zfs_replay_create,         /* TX_CREATE */
+       (zil_replay_func_t *)zfs_replay_create,         /* TX_MKDIR */
+       (zil_replay_func_t *)zfs_replay_create,         /* TX_MKXATTR */
+       (zil_replay_func_t *)zfs_replay_create,         /* TX_SYMLINK */
+       (zil_replay_func_t *)zfs_replay_remove,         /* TX_REMOVE */
+       (zil_replay_func_t *)zfs_replay_remove,         /* TX_RMDIR */
+       (zil_replay_func_t *)zfs_replay_link,           /* TX_LINK */
+       (zil_replay_func_t *)zfs_replay_rename,         /* TX_RENAME */
+       (zil_replay_func_t *)zfs_replay_write,          /* TX_WRITE */
+       (zil_replay_func_t *)zfs_replay_truncate,       /* TX_TRUNCATE */
+       (zil_replay_func_t *)zfs_replay_setattr,        /* TX_SETATTR */
+       (zil_replay_func_t *)zfs_replay_acl_v0,         /* TX_ACL_V0 */
+       (zil_replay_func_t *)zfs_replay_acl,            /* TX_ACL */
+       (zil_replay_func_t *)zfs_replay_create_acl,     /* TX_CREATE_ACL */
+       (zil_replay_func_t *)zfs_replay_create,         /* TX_CREATE_ATTR */
+       (zil_replay_func_t *)zfs_replay_create_acl,     /* TX_CREATE_ACL_ATTR */
+       (zil_replay_func_t *)zfs_replay_create_acl,     /* TX_MKDIR_ACL */
+       (zil_replay_func_t *)zfs_replay_create,         /* TX_MKDIR_ATTR */
+       (zil_replay_func_t *)zfs_replay_create_acl,     /* TX_MKDIR_ACL_ATTR */
+       (zil_replay_func_t *)zfs_replay_write2,         /* TX_WRITE2 */
 };
-#endif /* HAVE_ZPL */
index 4e3c176..26ad58d 100644 (file)
@@ -112,14 +112,14 @@ zfs_range_lock_writer(znode_t *zp, rl_t *new)
                 * Range locking is also used by zvol and uses a
                 * dummied up znode. However, for zvol, we don't need to
                 * append or grow blocksize, and besides we don't have
-                * a "sa" data or z_zfsvfs - so skip that processing.
+                * a "sa" data or zfs_sb_t - so skip that processing.
                 *
                 * Yes, this is ugly, and would be solved by not handling
                 * grow or append in range lock code. If that was done then
                 * we could make the range locking code generically available
                 * to other non-zfs consumers.
                 */
-               if (zp->z_vnode) { /* caller is ZPL */
+               if (!zp->z_is_zvol) { /* caller is ZPL */
                        /*
                         * If in append mode pick up the current end of file.
                         * This is done under z_range_lock to avoid races.
@@ -134,7 +134,7 @@ zfs_range_lock_writer(znode_t *zp, rl_t *new)
                         */
                        end_size = MAX(zp->z_size, new->r_off + len);
                        if (end_size > zp->z_blksz && (!ISP2(zp->z_blksz) ||
-                           zp->z_blksz < zp->z_zfsvfs->z_max_blksz)) {
+                           zp->z_blksz < ZTOZSB(zp)->z_max_blksz)) {
                                new->r_off = 0;
                                new->r_len = UINT64_MAX;
                        }
@@ -453,6 +453,20 @@ zfs_range_lock(znode_t *zp, uint64_t off, uint64_t len, rl_type_t type)
        return (new);
 }
 
+static void
+zfs_range_free(void *arg)
+{
+       rl_t *rl = arg;
+
+       if (rl->r_write_wanted)
+               cv_destroy(&rl->r_wr_cv);
+
+       if (rl->r_read_wanted)
+               cv_destroy(&rl->r_rd_cv);
+
+       kmem_free(rl, sizeof (rl_t));
+}
+
 /*
  * Unlock a reader lock
  */
@@ -472,14 +486,14 @@ zfs_range_unlock_reader(znode_t *zp, rl_t *remove)
         */
        if (remove->r_cnt == 1) {
                avl_remove(tree, remove);
-               if (remove->r_write_wanted) {
+               mutex_exit(&zp->z_range_lock);
+               if (remove->r_write_wanted)
                        cv_broadcast(&remove->r_wr_cv);
-                       cv_destroy(&remove->r_wr_cv);
-               }
-               if (remove->r_read_wanted) {
+
+               if (remove->r_read_wanted)
                        cv_broadcast(&remove->r_rd_cv);
-                       cv_destroy(&remove->r_rd_cv);
-               }
+
+               taskq_dispatch(system_taskq, zfs_range_free, remove, 0);
        } else {
                ASSERT3U(remove->r_cnt, ==, 0);
                ASSERT3U(remove->r_write_wanted, ==, 0);
@@ -505,19 +519,21 @@ zfs_range_unlock_reader(znode_t *zp, rl_t *remove)
                        rl->r_cnt--;
                        if (rl->r_cnt == 0) {
                                avl_remove(tree, rl);
-                               if (rl->r_write_wanted) {
+
+                               if (rl->r_write_wanted)
                                        cv_broadcast(&rl->r_wr_cv);
-                                       cv_destroy(&rl->r_wr_cv);
-                               }
-                               if (rl->r_read_wanted) {
+
+                               if (rl->r_read_wanted)
                                        cv_broadcast(&rl->r_rd_cv);
-                                       cv_destroy(&rl->r_rd_cv);
-                               }
-                               kmem_free(rl, sizeof (rl_t));
+
+                               taskq_dispatch(system_taskq,
+                                   zfs_range_free, rl, 0);
                        }
                }
+
+               mutex_exit(&zp->z_range_lock);
+               kmem_free(remove, sizeof (rl_t));
        }
-       kmem_free(remove, sizeof (rl_t));
 }
 
 /*
@@ -537,22 +553,19 @@ zfs_range_unlock(rl_t *rl)
                /* writer locks can't be shared or split */
                avl_remove(&zp->z_range_avl, rl);
                mutex_exit(&zp->z_range_lock);
-               if (rl->r_write_wanted) {
+               if (rl->r_write_wanted)
                        cv_broadcast(&rl->r_wr_cv);
-                       cv_destroy(&rl->r_wr_cv);
-               }
-               if (rl->r_read_wanted) {
+
+               if (rl->r_read_wanted)
                        cv_broadcast(&rl->r_rd_cv);
-                       cv_destroy(&rl->r_rd_cv);
-               }
-               kmem_free(rl, sizeof (rl_t));
+
+               taskq_dispatch(system_taskq, zfs_range_free, rl, 0);
        } else {
                /*
                 * lock may be shared, let zfs_range_unlock_reader()
-                * release the lock and free the rl_t
+                * release the zp->z_range_lock lock and free the rl_t
                 */
                zfs_range_unlock_reader(zp, rl);
-               mutex_exit(&zp->z_range_lock);
        }
 }
 
index 88fd789..ed69649 100644 (file)
@@ -67,7 +67,6 @@ sa_attr_reg_t zfs_attr_table[ZPL_END+1] = {
 };
 
 #ifdef _KERNEL
-#ifdef HAVE_ZPL
 int
 zfs_sa_readlink(znode_t *zp, uio_t *uio)
 {
@@ -82,7 +81,7 @@ zfs_sa_readlink(znode_t *zp, uio_t *uio)
                    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
        } else {
                dmu_buf_t *dbp;
-               if ((error = dmu_buf_hold(zp->z_zfsvfs->z_os, zp->z_id,
+               if ((error = dmu_buf_hold(ZTOZSB(zp)->z_os, zp->z_id,
                    0, FTAG, &dbp, DMU_READ_NO_PREFETCH)) == 0) {
                        error = uiomove(dbp->db_data,
                            MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
@@ -108,7 +107,7 @@ zfs_sa_symlink(znode_t *zp, char *link, int len, dmu_tx_t *tx)
                dmu_buf_t *dbp;
 
                zfs_grow_blocksize(zp, len, tx);
-               VERIFY(0 == dmu_buf_hold(zp->z_zfsvfs->z_os,
+               VERIFY(0 == dmu_buf_hold(ZTOZSB(zp)->z_os,
                    zp->z_id, 0, FTAG, &dbp, DMU_READ_NO_PREFETCH));
 
                dmu_buf_will_dirty(dbp, tx);
@@ -119,16 +118,17 @@ zfs_sa_symlink(znode_t *zp, char *link, int len, dmu_tx_t *tx)
        }
 }
 
+#ifdef HAVE_SCANSTAMP
 void
 zfs_sa_get_scanstamp(znode_t *zp, xvattr_t *xvap)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        xoptattr_t *xoap;
 
        ASSERT(MUTEX_HELD(&zp->z_lock));
        VERIFY((xoap = xva_getxoptattr(xvap)) != NULL);
        if (zp->z_is_sa) {
-               if (sa_lookup(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zfsvfs),
+               if (sa_lookup(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zsb),
                    &xoap->xoa_av_scanstamp,
                    sizeof (xoap->xoa_av_scanstamp)) != 0)
                        return;
@@ -156,13 +156,13 @@ zfs_sa_get_scanstamp(znode_t *zp, xvattr_t *xvap)
 void
 zfs_sa_set_scanstamp(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        xoptattr_t *xoap;
 
        ASSERT(MUTEX_HELD(&zp->z_lock));
        VERIFY((xoap = xva_getxoptattr(xvap)) != NULL);
        if (zp->z_is_sa)
-               VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zfsvfs),
+               VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zsb),
                    &xoap->xoa_av_scanstamp,
                    sizeof (xoap->xoa_av_scanstamp), tx));
        else {
@@ -179,10 +179,11 @@ zfs_sa_set_scanstamp(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
                    xoap->xoa_av_scanstamp, sizeof (xoap->xoa_av_scanstamp));
 
                zp->z_pflags |= ZFS_BONUS_SCANSTAMP;
-               VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs),
+               VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(zsb),
                    &zp->z_pflags, sizeof (uint64_t), tx));
        }
 }
+#endif /* HAVE_SCANSTAMP */
 
 /*
  * I'm not convinced we should do any of this upgrade.
@@ -197,15 +198,16 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
 {
        dmu_buf_t *db = sa_get_db(hdl);
        znode_t *zp = sa_get_userdata(hdl);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-       sa_bulk_attr_t bulk[20];
+       zfs_sb_t *zsb = ZTOZSB(zp);
        int count = 0;
-       sa_bulk_attr_t sa_attrs[20] = { 0 };
+       sa_bulk_attr_t *bulk, *sa_attrs;
        zfs_acl_locator_cb_t locate = { 0 };
        uint64_t uid, gid, mode, rdev, xattr, parent;
        uint64_t crtime[2], mtime[2], ctime[2];
        zfs_acl_phys_t znode_acl;
+#ifdef HAVE_SCANSTAMP
        char scanstamp[AV_SCANSTAMP_SZ];
+#endif /* HAVE_SCANSTAMP */
        boolean_t drop_lock = B_FALSE;
 
        /*
@@ -214,7 +216,7 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
         * and ready the ACL would require special "locked"
         * interfaces that would be messy
         */
-       if (zp->z_acl_cached == NULL || ZTOV(zp)->v_type == VLNK)
+       if (zp->z_acl_cached == NULL || S_ISLNK(ZTOI(zp)->i_mode))
                return;
 
        /*
@@ -234,83 +236,90 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
        }
 
        /* First do a bulk query of the attributes that aren't cached */
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &crtime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_XATTR(zfsvfs), NULL, &xattr, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_RDEV(zfsvfs), NULL, &rdev, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, &uid, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, &gid, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,
+       bulk = kmem_alloc(sizeof(sa_bulk_attr_t) * 20, KM_SLEEP);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL, &mtime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL, &ctime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zsb), NULL, &crtime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb), NULL, &mode, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zsb), NULL, &parent, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_XATTR(zsb), NULL, &xattr, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_RDEV(zsb), NULL, &rdev, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zsb), NULL, &uid, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zsb), NULL, &gid, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zsb), NULL,
            &znode_acl, 88);
 
-       if (sa_bulk_lookup_locked(hdl, bulk, count) != 0)
+       if (sa_bulk_lookup_locked(hdl, bulk, count) != 0) {
+               kmem_free(bulk, sizeof(sa_bulk_attr_t) * 20);
                goto done;
-
+       }
 
        /*
         * While the order here doesn't matter its best to try and organize
         * it is such a way to pick up an already existing layout number
         */
        count = 0;
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_SIZE(zfsvfs), NULL,
+       sa_attrs = kmem_zalloc(sizeof(sa_bulk_attr_t) * 20, KM_SLEEP);
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_MODE(zsb), NULL, &mode, 8);
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_SIZE(zsb), NULL,
            &zp->z_size, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_GEN(zfsvfs),
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_GEN(zsb),
            NULL, &zp->z_gen, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_UID(zfsvfs), NULL, &uid, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_GID(zfsvfs), NULL, &gid, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_PARENT(zfsvfs),
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_UID(zsb), NULL, &uid, 8);
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_GID(zsb), NULL, &gid, 8);
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_PARENT(zsb),
            NULL, &parent, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_ATIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_ATIME(zsb), NULL,
            zp->z_atime, 16);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_MTIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_MTIME(zsb), NULL,
            &mtime, 16);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_CTIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_CTIME(zsb), NULL,
            &ctime, 16);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_CRTIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_CRTIME(zsb), NULL,
            &crtime, 16);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_LINKS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_LINKS(zsb), NULL,
            &zp->z_links, 8);
-       if (zp->z_vnode->v_type == VBLK || zp->z_vnode->v_type == VCHR)
-               SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_RDEV(zfsvfs), NULL,
+       if (S_ISBLK(ZTOI(zp)->i_mode) || S_ISCHR(ZTOI(zp)->i_mode))
+               SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_RDEV(zsb), NULL,
                    &rdev, 8);
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_COUNT(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_COUNT(zsb), NULL,
            &zp->z_acl_cached->z_acl_count, 8);
 
        if (zp->z_acl_cached->z_version < ZFS_ACL_VERSION_FUID)
                zfs_acl_xform(zp, zp->z_acl_cached, CRED());
 
        locate.cb_aclp = zp->z_acl_cached;
-       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_ACES(zfsvfs),
+       SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_ACES(zsb),
            zfs_acl_data_locator, &locate, zp->z_acl_cached->z_acl_bytes);
 
        if (xattr)
-               SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_XATTR(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_XATTR(zsb),
                    NULL, &xattr, 8);
 
+#ifdef HAVE_SCANSTAMP
        /* if scanstamp then add scanstamp */
 
        if (zp->z_pflags & ZFS_BONUS_SCANSTAMP) {
                bcopy((caddr_t)db->db_data + ZFS_OLD_ZNODE_PHYS_SIZE,
                    scanstamp, AV_SCANSTAMP_SZ);
-               SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_SCANSTAMP(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_SCANSTAMP(zsb),
                    NULL, scanstamp, AV_SCANSTAMP_SZ);
                zp->z_pflags &= ~ZFS_BONUS_SCANSTAMP;
        }
+#endif /* HAVE_SCANSTAMP */
 
        VERIFY(dmu_set_bonustype(db, DMU_OT_SA, tx) == 0);
        VERIFY(sa_replace_all_by_template_locked(hdl, sa_attrs,
            count, tx) == 0);
        if (znode_acl.z_acl_extern_obj)
-               VERIFY(0 == dmu_object_free(zfsvfs->z_os,
+               VERIFY(0 == dmu_object_free(zsb->z_os,
                    znode_acl.z_acl_extern_obj, tx));
 
        zp->z_is_sa = B_TRUE;
+       kmem_free(sa_attrs, sizeof(sa_bulk_attr_t) * 20);
+       kmem_free(bulk, sizeof(sa_bulk_attr_t) * 20);
 done:
        if (drop_lock)
                mutex_exit(&zp->z_lock);
@@ -319,7 +328,7 @@ done:
 void
 zfs_sa_upgrade_txholds(dmu_tx_t *tx, znode_t *zp)
 {
-       if (!zp->z_zfsvfs->z_use_sa || zp->z_is_sa)
+       if (!ZTOZSB(zp)->z_use_sa || zp->z_is_sa)
                return;
 
 
@@ -331,5 +340,4 @@ zfs_sa_upgrade_txholds(dmu_tx_t *tx, znode_t *zp)
        }
 }
 
-#endif /* HAVE_ZPL */
 #endif
index 77bef00..bb2fdb0 100644 (file)
@@ -38,6 +38,7 @@
 #include <sys/cmn_err.h>
 #include "fs/fs_subr.h"
 #include <sys/zfs_znode.h>
+#include <sys/zfs_vnops.h>
 #include <sys/zfs_dir.h>
 #include <sys/zil.h>
 #include <sys/fs/zfs.h>
@@ -55,7 +56,6 @@
 #include <sys/modctl.h>
 #include <sys/refstr.h>
 #include <sys/zfs_ioctl.h>
-#include <sys/zfs_ctldir.h>
 #include <sys/zfs_fuid.h>
 #include <sys/bootconf.h>
 #include <sys/sunddi.h>
 #include <sys/dmu_objset.h>
 #include <sys/spa_boot.h>
 #include <sys/sa.h>
+#include <sys/zpl.h>
 #include "zfs_comutil.h"
 
-#ifdef HAVE_ZPL
-int zfsfstype;
-vfsops_t *zfs_vfsops = NULL;
-static major_t zfs_major;
-static minor_t zfs_minor;
-static kmutex_t        zfs_dev_mtx;
-
-extern int sys_shutdown;
-
-static int zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr);
-static int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr);
-static int zfs_mountroot(vfs_t *vfsp, enum whymountroot);
-static int zfs_root(vfs_t *vfsp, vnode_t **vpp);
-static int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp);
-static int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp);
-static void zfs_freevfs(vfs_t *vfsp);
-
-static const fs_operation_def_t zfs_vfsops_template[] = {
-       VFSNAME_MOUNT,          { .vfs_mount = zfs_mount },
-       VFSNAME_MOUNTROOT,      { .vfs_mountroot = zfs_mountroot },
-       VFSNAME_UNMOUNT,        { .vfs_unmount = zfs_umount },
-       VFSNAME_ROOT,           { .vfs_root = zfs_root },
-       VFSNAME_STATVFS,        { .vfs_statvfs = zfs_statvfs },
-       VFSNAME_SYNC,           { .vfs_sync = zfs_sync },
-       VFSNAME_VGET,           { .vfs_vget = zfs_vget },
-       VFSNAME_FREEVFS,        { .vfs_freevfs = zfs_freevfs },
-       NULL,                   NULL
-};
-
-static const fs_operation_def_t zfs_vfsops_eio_template[] = {
-       VFSNAME_FREEVFS,        { .vfs_freevfs =  zfs_freevfs },
-       NULL,                   NULL
-};
-
-/*
- * We need to keep a count of active fs's.
- * This is necessary to prevent our module
- * from being unloaded after a umount -f
- */
-static uint32_t        zfs_active_fs_count = 0;
-
-static char *noatime_cancel[] = { MNTOPT_ATIME, NULL };
-static char *atime_cancel[] = { MNTOPT_NOATIME, NULL };
-static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL };
-static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL };
-
-/*
- * MO_DEFAULT is not used since the default value is determined
- * by the equivalent property.
- */
-static mntopt_t mntopts[] = {
-       { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, NULL },
-       { MNTOPT_XATTR, xattr_cancel, NULL, 0, NULL },
-       { MNTOPT_NOATIME, noatime_cancel, NULL, 0, NULL },
-       { MNTOPT_ATIME, atime_cancel, NULL, 0, NULL }
-};
-
-static mntopts_t zfs_mntopts = {
-       sizeof (mntopts) / sizeof (mntopt_t),
-       mntopts
-};
 
 /*ARGSUSED*/
 int
-zfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
+zfs_sync(zfs_sb_t *zsb, short flag, cred_t *cr)
 {
        /*
         * Data integrity is job one.  We don't want a compromised kernel
         * writing to the storage pool, so we never sync during panic.
         */
-       if (panicstr)
-               return (0);
-
-       /*
-        * SYNC_ATTR is used by fsflush() to force old filesystems like UFS
-        * to sync metadata, which they would otherwise cache indefinitely.
-        * Semantically, the only requirement is that the sync be initiated.
-        * The DMU syncs out txgs frequently, so there's nothing to do.
-        */
-       if (flag & SYNC_ATTR)
+       if (unlikely(oops_in_progress))
                return (0);
 
-       if (vfsp != NULL) {
+       if (zsb != NULL) {
                /*
                 * Sync a specific filesystem.
                 */
-               zfsvfs_t *zfsvfs = vfsp->vfs_data;
                dsl_pool_t *dp;
 
-               ZFS_ENTER(zfsvfs);
-               dp = dmu_objset_pool(zfsvfs->z_os);
+               ZFS_ENTER(zsb);
+               dp = dmu_objset_pool(zsb->z_os);
 
+#ifdef HAVE_SHUTDOWN
                /*
                 * If the system is shutting down, then skip any
                 * filesystems which may exist on a suspended pool.
+                *
+                * XXX: This can be implemented using the Linux reboot
+                *      notifiers: {un}register_reboot_notifier().
                 */
                if (sys_shutdown && spa_suspended(dp->dp_spa)) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (0);
                }
+#endif /* HAVE_SHUTDOWN */
 
-               if (zfsvfs->z_log != NULL)
-                       zil_commit(zfsvfs->z_log, 0);
+               if (zsb->z_log != NULL)
+                       zil_commit(zsb->z_log, 0);
 
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
        } else {
                /*
                 * Sync all ZFS filesystems.  This is what happens when you
@@ -181,169 +116,111 @@ zfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
 
        return (0);
 }
-
-static int
-zfs_create_unique_device(dev_t *dev)
-{
-       major_t new_major;
-
-       do {
-               ASSERT3U(zfs_minor, <=, MAXMIN32);
-               minor_t start = zfs_minor;
-               do {
-                       mutex_enter(&zfs_dev_mtx);
-                       if (zfs_minor >= MAXMIN32) {
-                               /*
-                                * If we're still using the real major
-                                * keep out of /dev/zfs and /dev/zvol minor
-                                * number space.  If we're using a getudev()'ed
-                                * major number, we can use all of its minors.
-                                */
-                               if (zfs_major == ddi_name_to_major(ZFS_DRIVER))
-                                       zfs_minor = ZFS_MIN_MINOR;
-                               else
-                                       zfs_minor = 0;
-                       } else {
-                               zfs_minor++;
-                       }
-                       *dev = makedevice(zfs_major, zfs_minor);
-                       mutex_exit(&zfs_dev_mtx);
-               } while (vfs_devismounted(*dev) && zfs_minor != start);
-               if (zfs_minor == start) {
-                       /*
-                        * We are using all ~262,000 minor numbers for the
-                        * current major number.  Create a new major number.
-                        */
-                       if ((new_major = getudev()) == (major_t)-1) {
-                               cmn_err(CE_WARN,
-                                   "zfs_mount: Can't get unique major "
-                                   "device number.");
-                               return (-1);
-                       }
-                       mutex_enter(&zfs_dev_mtx);
-                       zfs_major = new_major;
-                       zfs_minor = 0;
-
-                       mutex_exit(&zfs_dev_mtx);
-               } else {
-                       break;
-               }
-               /* CONSTANTCONDITION */
-       } while (1);
-
-       return (0);
-}
+EXPORT_SYMBOL(zfs_sync);
 
 static void
 atime_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
+       struct super_block *sb = zsb->z_sb;
+       struct vfsmount *vfs = zsb->z_vfs;
 
        if (newval == TRUE) {
-               zfsvfs->z_atime = TRUE;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_ATIME, NULL, 0);
+               vfs->mnt_flags &= ~MNT_NOATIME;
+               sb->s_flags &= ~MS_NOATIME;
+               zsb->z_atime = TRUE;
        } else {
-               zfsvfs->z_atime = FALSE;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_ATIME);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOATIME, NULL, 0);
+               vfs->mnt_flags |= MNT_NOATIME;
+               sb->s_flags |= MS_NOATIME;
+               zsb->z_atime = FALSE;
        }
 }
 
 static void
 xattr_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
 
        if (newval == TRUE) {
-               /* XXX locking on vfs_flag? */
-               zfsvfs->z_vfs->vfs_flag |= VFS_XATTR;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_XATTR, NULL, 0);
+               zsb->z_flags |= ZSB_XATTR_USER;
        } else {
-               /* XXX locking on vfs_flag? */
-               zfsvfs->z_vfs->vfs_flag &= ~VFS_XATTR;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_XATTR);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOXATTR, NULL, 0);
+               zsb->z_flags &= ~ZSB_XATTR_USER;
        }
 }
 
 static void
 blksz_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
 
        if (newval < SPA_MINBLOCKSIZE ||
            newval > SPA_MAXBLOCKSIZE || !ISP2(newval))
                newval = SPA_MAXBLOCKSIZE;
 
-       zfsvfs->z_max_blksz = newval;
-       zfsvfs->z_vfs->vfs_bsize = newval;
+       zsb->z_max_blksz = newval;
 }
 
 static void
 readonly_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
+       struct super_block *sb = zsb->z_sb;
+       struct vfsmount *vfs = zsb->z_vfs;
 
        if (newval) {
-               /* XXX locking on vfs_flag? */
-               zfsvfs->z_vfs->vfs_flag |= VFS_RDONLY;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RW);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RO, NULL, 0);
+               vfs->mnt_flags |= MNT_READONLY;
+               sb->s_flags |= MS_RDONLY;
        } else {
-               /* XXX locking on vfs_flag? */
-               zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_RO);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_RW, NULL, 0);
+               vfs->mnt_flags &= ~MNT_READONLY;
+               sb->s_flags &= ~MS_RDONLY;
        }
 }
 
 static void
 devices_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
+       struct super_block *sb = zsb->z_sb;
+       struct vfsmount *vfs = zsb->z_vfs;
 
        if (newval == FALSE) {
-               zfsvfs->z_vfs->vfs_flag |= VFS_NODEVICES;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES, NULL, 0);
+               vfs->mnt_flags |= MNT_NODEV;
+               sb->s_flags |= MS_NODEV;
        } else {
-               zfsvfs->z_vfs->vfs_flag &= ~VFS_NODEVICES;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NODEVICES);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_DEVICES, NULL, 0);
+               vfs->mnt_flags &= ~MNT_NODEV;
+               sb->s_flags &= ~MS_NODEV;
        }
 }
 
 static void
 setuid_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
+       struct super_block *sb = zsb->z_sb;
+       struct vfsmount *vfs = zsb->z_vfs;
 
        if (newval == FALSE) {
-               zfsvfs->z_vfs->vfs_flag |= VFS_NOSETUID;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_SETUID);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID, NULL, 0);
+               vfs->mnt_flags |= MNT_NOSUID;
+               sb->s_flags |= MS_NOSUID;
        } else {
-               zfsvfs->z_vfs->vfs_flag &= ~VFS_NOSETUID;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOSETUID);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_SETUID, NULL, 0);
+               vfs->mnt_flags &= ~MNT_NOSUID;
+               sb->s_flags &= ~MS_NOSUID;
        }
 }
 
 static void
 exec_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
+       zfs_sb_t *zsb = arg;
+       struct super_block *sb = zsb->z_sb;
+       struct vfsmount *vfs = zsb->z_vfs;
 
        if (newval == FALSE) {
-               zfsvfs->z_vfs->vfs_flag |= VFS_NOEXEC;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_EXEC);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC, NULL, 0);
+               vfs->mnt_flags |= MNT_NOEXEC;
+               sb->s_flags |= MS_NOEXEC;
        } else {
-               zfsvfs->z_vfs->vfs_flag &= ~VFS_NOEXEC;
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NOEXEC);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_EXEC, NULL, 0);
+               vfs->mnt_flags &= ~MNT_NOEXEC;
+               sb->s_flags &= ~MS_NOEXEC;
        }
 }
 
@@ -358,138 +235,89 @@ exec_changed_cb(void *arg, uint64_t newval)
 static void
 nbmand_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
-       if (newval == FALSE) {
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND, NULL, 0);
+       zfs_sb_t *zsb = arg;
+       struct super_block *sb = zsb->z_sb;
+
+       if (newval == TRUE) {
+               sb->s_flags |= MS_MANDLOCK;
        } else {
-               vfs_clearmntopt(zfsvfs->z_vfs, MNTOPT_NONBMAND);
-               vfs_setmntopt(zfsvfs->z_vfs, MNTOPT_NBMAND, NULL, 0);
+               sb->s_flags &= ~MS_MANDLOCK;
        }
 }
 
 static void
 snapdir_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
-
-       zfsvfs->z_show_ctldir = newval;
+       ((zfs_sb_t *)arg)->z_show_ctldir = newval;
 }
 
 static void
 vscan_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
-
-       zfsvfs->z_vscan = newval;
+       ((zfs_sb_t *)arg)->z_vscan = newval;
 }
 
 static void
 acl_inherit_changed_cb(void *arg, uint64_t newval)
 {
-       zfsvfs_t *zfsvfs = arg;
-
-       zfsvfs->z_acl_inherit = newval;
+       ((zfs_sb_t *)arg)->z_acl_inherit = newval;
 }
 
-static int
-zfs_register_callbacks(vfs_t *vfsp)
+int
+zfs_register_callbacks(zfs_sb_t *zsb)
 {
+       struct vfsmount *vfsp = zsb->z_vfs;
        struct dsl_dataset *ds = NULL;
-       objset_t *os = NULL;
-       zfsvfs_t *zfsvfs = NULL;
+       objset_t *os = zsb->z_os;
        uint64_t nbmand;
-       int readonly, do_readonly = B_FALSE;
-       int setuid, do_setuid = B_FALSE;
-       int exec, do_exec = B_FALSE;
-       int devices, do_devices = B_FALSE;
-       int xattr, do_xattr = B_FALSE;
-       int atime, do_atime = B_FALSE;
+       boolean_t readonly = B_FALSE;
+       boolean_t setuid = B_TRUE;
+       boolean_t exec = B_TRUE;
+       boolean_t devices = B_TRUE;
+       boolean_t xattr = B_TRUE;
+       boolean_t atime = B_TRUE;
+       char osname[MAXNAMELEN];
        int error = 0;
 
-       ASSERT(vfsp);
-       zfsvfs = vfsp->vfs_data;
-       ASSERT(zfsvfs);
-       os = zfsvfs->z_os;
-
        /*
-        * The act of registering our callbacks will destroy any mount
-        * options we may have.  In order to enable temporary overrides
-        * of mount options, we stash away the current values and
-        * restore them after we register the callbacks.
+        * While Linux allows multiple vfs mounts per super block we have
+        * limited it artificially to one in zfs_fill_super.  Thus it is
+        * safe for us to modify the vfs mount fails through the callbacks.
         */
-       if (vfs_optionisset(vfsp, MNTOPT_RO, NULL) ||
-           !spa_writeable(dmu_objset_spa(os))) {
+       if ((vfsp->mnt_flags & MNT_READONLY) ||
+           !spa_writeable(dmu_objset_spa(os)))
                readonly = B_TRUE;
-               do_readonly = B_TRUE;
-       } else if (vfs_optionisset(vfsp, MNTOPT_RW, NULL)) {
-               readonly = B_FALSE;
-               do_readonly = B_TRUE;
-       }
-       if (vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL)) {
+
+       if (vfsp->mnt_flags & MNT_NOSUID) {
                devices = B_FALSE;
                setuid = B_FALSE;
-               do_devices = B_TRUE;
-               do_setuid = B_TRUE;
        } else {
-               if (vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL)) {
+               if (vfsp->mnt_flags & MNT_NODEV)
                        devices = B_FALSE;
-                       do_devices = B_TRUE;
-               } else if (vfs_optionisset(vfsp, MNTOPT_DEVICES, NULL)) {
-                       devices = B_TRUE;
-                       do_devices = B_TRUE;
-               }
-
-               if (vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL)) {
-                       setuid = B_FALSE;
-                       do_setuid = B_TRUE;
-               } else if (vfs_optionisset(vfsp, MNTOPT_SETUID, NULL)) {
-                       setuid = B_TRUE;
-                       do_setuid = B_TRUE;
-               }
        }
-       if (vfs_optionisset(vfsp, MNTOPT_NOEXEC, NULL)) {
+
+       if (vfsp->mnt_flags & MNT_NOEXEC)
                exec = B_FALSE;
-               do_exec = B_TRUE;
-       } else if (vfs_optionisset(vfsp, MNTOPT_EXEC, NULL)) {
-               exec = B_TRUE;
-               do_exec = B_TRUE;
-       }
-       if (vfs_optionisset(vfsp, MNTOPT_NOXATTR, NULL)) {
-               xattr = B_FALSE;
-               do_xattr = B_TRUE;
-       } else if (vfs_optionisset(vfsp, MNTOPT_XATTR, NULL)) {
-               xattr = B_TRUE;
-               do_xattr = B_TRUE;
-       }
-       if (vfs_optionisset(vfsp, MNTOPT_NOATIME, NULL)) {
+
+       if (vfsp->mnt_flags & MNT_NOATIME)
                atime = B_FALSE;
-               do_atime = B_TRUE;
-       } else if (vfs_optionisset(vfsp, MNTOPT_ATIME, NULL)) {
-               atime = B_TRUE;
-               do_atime = B_TRUE;
-       }
 
        /*
-        * nbmand is a special property.  It can only be changed at
-        * mount time.
+        * nbmand is a special property which may only be changed at
+        * mount time.  Unfortunately, Linux does not have a VFS mount
+        * flag instead this is a super block flag.  So setting this
+        * option at mount time will have to wait until we can parse
+        * the mount option string.  For now we rely on the nbmand
+        * value stored with the object set.  Additional mount option
+        * string to be handled:
         *
-        * This is weird, but it is documented to only be changeable
-        * at mount time.
+        *   case: sensitive|insensitive|mixed
+        *   zerocopy: on|off
         */
-       if (vfs_optionisset(vfsp, MNTOPT_NONBMAND, NULL)) {
-               nbmand = B_FALSE;
-       } else if (vfs_optionisset(vfsp, MNTOPT_NBMAND, NULL)) {
-               nbmand = B_TRUE;
-       } else {
-               char osname[MAXNAMELEN];
 
-               dmu_objset_name(os, osname);
-               if (error = dsl_prop_get_integer(osname, "nbmand", &nbmand,
-                   NULL)) {
-                       return (error);
-               }
-       }
+       dmu_objset_name(os, osname);
+       if ((error = dsl_prop_get_integer(osname, "nbmand", &nbmand, NULL)))
+               return (error);
 
        /*
         * Register property callbacks.
@@ -499,45 +327,39 @@ zfs_register_callbacks(vfs_t *vfsp)
         * overboard...
         */
        ds = dmu_objset_ds(os);
-       error = dsl_prop_register(ds, "atime", atime_changed_cb, zfsvfs);
+       error = dsl_prop_register(ds,
+           "atime", atime_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "xattr", xattr_changed_cb, zfsvfs);
+           "xattr", xattr_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "recordsize", blksz_changed_cb, zfsvfs);
+           "recordsize", blksz_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "readonly", readonly_changed_cb, zfsvfs);
+           "readonly", readonly_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "devices", devices_changed_cb, zfsvfs);
+           "devices", devices_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "setuid", setuid_changed_cb, zfsvfs);
+           "setuid", setuid_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "exec", exec_changed_cb, zfsvfs);
+           "exec", exec_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "snapdir", snapdir_changed_cb, zfsvfs);
+           "snapdir", snapdir_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "aclinherit", acl_inherit_changed_cb, zfsvfs);
+           "aclinherit", acl_inherit_changed_cb, zsb);
        error = error ? error : dsl_prop_register(ds,
-           "vscan", vscan_changed_cb, zfsvfs);
+           "vscan", vscan_changed_cb, zsb);
        if (error)
                goto unregister;
 
        /*
-        * Invoke our callbacks to restore temporary mount options.
+        * Invoke our callbacks to set required flags.
         */
-       if (do_readonly)
-               readonly_changed_cb(zfsvfs, readonly);
-       if (do_setuid)
-               setuid_changed_cb(zfsvfs, setuid);
-       if (do_exec)
-               exec_changed_cb(zfsvfs, exec);
-       if (do_devices)
-               devices_changed_cb(zfsvfs, devices);
-       if (do_xattr)
-               xattr_changed_cb(zfsvfs, xattr);
-       if (do_atime)
-               atime_changed_cb(zfsvfs, atime);
-
-       nbmand_changed_cb(zfsvfs, nbmand);
+       readonly_changed_cb(zsb, readonly);
+       setuid_changed_cb(zsb, setuid);
+       exec_changed_cb(zsb, exec);
+       devices_changed_cb(zsb, devices);
+       xattr_changed_cb(zsb, xattr);
+       atime_changed_cb(zsb, atime);
+       nbmand_changed_cb(zsb, nbmand);
 
        return (0);
 
@@ -547,21 +369,21 @@ unregister:
         * registered, but this is OK; it will simply return ENOMSG,
         * which we will ignore.
         */
-       (void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "devices", devices_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zfsvfs);
-       (void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zfsvfs);
+       (void) dsl_prop_unregister(ds, "atime", atime_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "xattr", xattr_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "recordsize", blksz_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "readonly", readonly_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "devices", devices_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "setuid", setuid_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "exec", exec_changed_cb, zsb);
+       (void) dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb, zsb);
        (void) dsl_prop_unregister(ds, "aclinherit", acl_inherit_changed_cb,
-           zfsvfs);
-       (void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zfsvfs);
-       return (error);
+           zsb);
+       (void) dsl_prop_unregister(ds, "vscan", vscan_changed_cb, zsb);
 
+       return (error);
 }
-#endif /* HAVE_ZPL */
+EXPORT_SYMBOL(zfs_register_callbacks);
 
 static int
 zfs_space_delta_cb(dmu_object_type_t bonustype, void *data,
@@ -612,9 +434,8 @@ zfs_space_delta_cb(dmu_object_type_t bonustype, void *data,
        return (error);
 }
 
-#ifdef HAVE_ZPL
 static void
-fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr,
+fuidstr_to_sid(zfs_sb_t *zsb, const char *fuidstr,
     char *domainbuf, int buflen, uid_t *ridp)
 {
        uint64_t fuid;
@@ -622,7 +443,7 @@ fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr,
 
        fuid = strtonum(fuidstr, NULL);
 
-       domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid));
+       domain = zfs_fuid_find_by_idx(zsb, FUID_INDEX(fuid));
        if (domain)
                (void) strlcpy(domainbuf, domain, buflen);
        else
@@ -631,7 +452,7 @@ fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr,
 }
 
 static uint64_t
-zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type)
+zfs_userquota_prop_to_obj(zfs_sb_t *zsb, zfs_userquota_prop_t type)
 {
        switch (type) {
        case ZFS_PROP_USERUSED:
@@ -639,15 +460,17 @@ zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type)
        case ZFS_PROP_GROUPUSED:
                return (DMU_GROUPUSED_OBJECT);
        case ZFS_PROP_USERQUOTA:
-               return (zfsvfs->z_userquota_obj);
+               return (zsb->z_userquota_obj);
        case ZFS_PROP_GROUPQUOTA:
-               return (zfsvfs->z_groupquota_obj);
+               return (zsb->z_groupquota_obj);
+       default:
+               return (ENOTSUP);
        }
        return (0);
 }
 
 int
-zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
+zfs_userspace_many(zfs_sb_t *zsb, zfs_userquota_prop_t type,
     uint64_t *cookiep, void *vbuf, uint64_t *bufsizep)
 {
        int error;
@@ -656,23 +479,23 @@ zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
        zfs_useracct_t *buf = vbuf;
        uint64_t obj;
 
-       if (!dmu_objset_userspace_present(zfsvfs->z_os))
+       if (!dmu_objset_userspace_present(zsb->z_os))
                return (ENOTSUP);
 
-       obj = zfs_userquota_prop_to_obj(zfsvfs, type);
+       obj = zfs_userquota_prop_to_obj(zsb, type);
        if (obj == 0) {
                *bufsizep = 0;
                return (0);
        }
 
-       for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep);
+       for (zap_cursor_init_serialized(&zc, zsb->z_os, obj, *cookiep);
            (error = zap_cursor_retrieve(&zc, &za)) == 0;
            zap_cursor_advance(&zc)) {
                if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) >
                    *bufsizep)
                        break;
 
-               fuidstr_to_sid(zfsvfs, za.za_name,
+               fuidstr_to_sid(zsb, za.za_name,
                    buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid);
 
                buf->zu_space = za.za_first_integer;
@@ -687,19 +510,20 @@ zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
        zap_cursor_fini(&zc);
        return (error);
 }
+EXPORT_SYMBOL(zfs_userspace_many);
 
 /*
  * buf must be big enough (eg, 32 bytes)
  */
 static int
-id_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid,
+id_to_fuidstr(zfs_sb_t *zsb, const char *domain, uid_t rid,
     char *buf, boolean_t addok)
 {
        uint64_t fuid;
        int domainid = 0;
 
        if (domain && domain[0]) {
-               domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok);
+               domainid = zfs_fuid_find_by_domain(zsb, domain, NULL, addok);
                if (domainid == -1)
                        return (ENOENT);
        }
@@ -709,7 +533,7 @@ id_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid,
 }
 
 int
-zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
+zfs_userspace_one(zfs_sb_t *zsb, zfs_userquota_prop_t type,
     const char *domain, uint64_t rid, uint64_t *valp)
 {
        char buf[32];
@@ -718,25 +542,26 @@ zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
 
        *valp = 0;
 
-       if (!dmu_objset_userspace_present(zfsvfs->z_os))
+       if (!dmu_objset_userspace_present(zsb->z_os))
                return (ENOTSUP);
 
-       obj = zfs_userquota_prop_to_obj(zfsvfs, type);
+       obj = zfs_userquota_prop_to_obj(zsb, type);
        if (obj == 0)
                return (0);
 
-       err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_FALSE);
+       err = id_to_fuidstr(zsb, domain, rid, buf, B_FALSE);
        if (err)
                return (err);
 
-       err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp);
+       err = zap_lookup(zsb->z_os, obj, buf, 8, 1, valp);
        if (err == ENOENT)
                err = 0;
        return (err);
 }
+EXPORT_SYMBOL(zfs_userspace_one);
 
 int
-zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
+zfs_set_userquota(zfs_sb_t *zsb, zfs_userquota_prop_t type,
     const char *domain, uint64_t rid, uint64_t quota)
 {
        char buf[32];
@@ -748,112 +573,115 @@ zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
        if (type != ZFS_PROP_USERQUOTA && type != ZFS_PROP_GROUPQUOTA)
                return (EINVAL);
 
-       if (zfsvfs->z_version < ZPL_VERSION_USERSPACE)
+       if (zsb->z_version < ZPL_VERSION_USERSPACE)
                return (ENOTSUP);
 
-       objp = (type == ZFS_PROP_USERQUOTA) ? &zfsvfs->z_userquota_obj :
-           &zfsvfs->z_groupquota_obj;
+       objp = (type == ZFS_PROP_USERQUOTA) ? &zsb->z_userquota_obj :
+           &zsb->z_groupquota_obj;
 
-       err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_TRUE);
+       err = id_to_fuidstr(zsb, domain, rid, buf, B_TRUE);
        if (err)
                return (err);
-       fuid_dirtied = zfsvfs->z_fuid_dirty;
+       fuid_dirtied = zsb->z_fuid_dirty;
 
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL);
        if (*objp == 0) {
                dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE,
                    zfs_userquota_prop_prefixes[type]);
        }
        if (fuid_dirtied)
-               zfs_fuid_txhold(zfsvfs, tx);
+               zfs_fuid_txhold(zsb, tx);
        err = dmu_tx_assign(tx, TXG_WAIT);
        if (err) {
                dmu_tx_abort(tx);
                return (err);
        }
 
-       mutex_enter(&zfsvfs->z_lock);
+       mutex_enter(&zsb->z_lock);
        if (*objp == 0) {
-               *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA,
+               *objp = zap_create(zsb->z_os, DMU_OT_USERGROUP_QUOTA,
                    DMU_OT_NONE, 0, tx);
-               VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
+               VERIFY(0 == zap_add(zsb->z_os, MASTER_NODE_OBJ,
                    zfs_userquota_prop_prefixes[type], 8, 1, objp, tx));
        }
-       mutex_exit(&zfsvfs->z_lock);
+       mutex_exit(&zsb->z_lock);
 
        if (quota == 0) {
-               err = zap_remove(zfsvfs->z_os, *objp, buf, tx);
+               err = zap_remove(zsb->z_os, *objp, buf, tx);
                if (err == ENOENT)
                        err = 0;
        } else {
-               err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, &quota, tx);
+               err = zap_update(zsb->z_os, *objp, buf, 8, 1, &quota, tx);
        }
        ASSERT(err == 0);
        if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
+               zfs_fuid_sync(zsb, tx);
        dmu_tx_commit(tx);
        return (err);
 }
+EXPORT_SYMBOL(zfs_set_userquota);
 
 boolean_t
-zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid)
+zfs_fuid_overquota(zfs_sb_t *zsb, boolean_t isgroup, uint64_t fuid)
 {
        char buf[32];
        uint64_t used, quota, usedobj, quotaobj;
        int err;
 
        usedobj = isgroup ? DMU_GROUPUSED_OBJECT : DMU_USERUSED_OBJECT;
-       quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj;
+       quotaobj = isgroup ? zsb->z_groupquota_obj : zsb->z_userquota_obj;
 
-       if (quotaobj == 0 || zfsvfs->z_replay)
+       if (quotaobj == 0 || zsb->z_replay)
                return (B_FALSE);
 
        (void) sprintf(buf, "%llx", (longlong_t)fuid);
-       err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, &quota);
+       err = zap_lookup(zsb->z_os, quotaobj, buf, 8, 1, &quota);
        if (err != 0)
                return (B_FALSE);
 
-       err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used);
+       err = zap_lookup(zsb->z_os, usedobj, buf, 8, 1, &used);
        if (err != 0)
                return (B_FALSE);
        return (used >= quota);
 }
+EXPORT_SYMBOL(zfs_fuid_overquota);
 
 boolean_t
-zfs_owner_overquota(zfsvfs_t *zfsvfs, znode_t *zp, boolean_t isgroup)
+zfs_owner_overquota(zfs_sb_t *zsb, znode_t *zp, boolean_t isgroup)
 {
        uint64_t fuid;
        uint64_t quotaobj;
 
-       quotaobj = isgroup ? zfsvfs->z_groupquota_obj : zfsvfs->z_userquota_obj;
+       quotaobj = isgroup ? zsb->z_groupquota_obj : zsb->z_userquota_obj;
 
        fuid = isgroup ? zp->z_gid : zp->z_uid;
 
-       if (quotaobj == 0 || zfsvfs->z_replay)
+       if (quotaobj == 0 || zsb->z_replay)
                return (B_FALSE);
 
-       return (zfs_fuid_overquota(zfsvfs, isgroup, fuid));
+       return (zfs_fuid_overquota(zsb, isgroup, fuid));
 }
+EXPORT_SYMBOL(zfs_owner_overquota);
 
 int
-zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
+zfs_sb_create(const char *osname, zfs_sb_t **zsbp)
 {
        objset_t *os;
-       zfsvfs_t *zfsvfs;
+       zfs_sb_t *zsb;
        uint64_t zval;
        int i, error;
        uint64_t sa_obj;
 
-       zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP);
+       zsb = kmem_zalloc(sizeof (zfs_sb_t), KM_SLEEP);
 
        /*
         * We claim to always be readonly so we can open snapshots;
         * other ZPL code will prevent us from writing to snapshots.
         */
-       error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, zfsvfs, &os);
+       error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, zsb, &os);
        if (error) {
-               kmem_free(zfsvfs, sizeof (zfsvfs_t));
+               kmem_free(zsb, sizeof (zfs_sb_t));
                return (error);
        }
 
@@ -862,48 +690,48 @@ zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
         * Should probably make this a kmem cache, shuffle fields,
         * and just bzero up to z_hold_mtx[].
         */
-       zfsvfs->z_vfs = NULL;
-       zfsvfs->z_parent = zfsvfs;
-       zfsvfs->z_max_blksz = SPA_MAXBLOCKSIZE;
-       zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE;
-       zfsvfs->z_os = os;
+       zsb->z_vfs = NULL;
+       zsb->z_parent = zsb;
+       zsb->z_max_blksz = SPA_MAXBLOCKSIZE;
+       zsb->z_show_ctldir = ZFS_SNAPDIR_VISIBLE;
+       zsb->z_os = os;
 
-       error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zfsvfs->z_version);
+       error = zfs_get_zplprop(os, ZFS_PROP_VERSION, &zsb->z_version);
        if (error) {
                goto out;
-       } else if (zfsvfs->z_version >
+       } else if (zsb->z_version >
            zfs_zpl_version_map(spa_version(dmu_objset_spa(os)))) {
-               (void) printf("Can't mount a version %lld file system "
+               (void) printk("Can't mount a version %lld file system "
                    "on a version %lld pool\n. Pool must be upgraded to mount "
-                   "this file system.", (u_longlong_t)zfsvfs->z_version,
+                   "this file system.", (u_longlong_t)zsb->z_version,
                    (u_longlong_t)spa_version(dmu_objset_spa(os)));
                error = ENOTSUP;
                goto out;
        }
        if ((error = zfs_get_zplprop(os, ZFS_PROP_NORMALIZE, &zval)) != 0)
                goto out;
-       zfsvfs->z_norm = (int)zval;
+       zsb->z_norm = (int)zval;
 
        if ((error = zfs_get_zplprop(os, ZFS_PROP_UTF8ONLY, &zval)) != 0)
                goto out;
-       zfsvfs->z_utf8 = (zval != 0);
+       zsb->z_utf8 = (zval != 0);
 
        if ((error = zfs_get_zplprop(os, ZFS_PROP_CASE, &zval)) != 0)
                goto out;
-       zfsvfs->z_case = (uint_t)zval;
+       zsb->z_case = (uint_t)zval;
 
        /*
         * Fold case on file systems that are always or sometimes case
         * insensitive.
         */
-       if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE ||
-           zfsvfs->z_case == ZFS_CASE_MIXED)
-               zfsvfs->z_norm |= U8_TEXTPREP_TOUPPER;
+       if (zsb->z_case == ZFS_CASE_INSENSITIVE ||
+           zsb->z_case == ZFS_CASE_MIXED)
+               zsb->z_norm |= U8_TEXTPREP_TOUPPER;
 
-       zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
-       zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
+       zsb->z_use_fuids = USE_FUIDS(zsb->z_version, zsb->z_os);
+       zsb->z_use_sa = USE_SA(zsb->z_version, zsb->z_os);
 
-       if (zfsvfs->z_use_sa) {
+       if (zsb->z_use_sa) {
                /* should either have both of these objects or none */
                error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS, 8, 1,
                    &sa_obj);
@@ -918,83 +746,83 @@ zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
        }
 
        error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
-           &zfsvfs->z_attr_table);
+           &zsb->z_attr_table);
        if (error)
                goto out;
 
-       if (zfsvfs->z_version >= ZPL_VERSION_SA)
+       if (zsb->z_version >= ZPL_VERSION_SA)
                sa_register_update_callback(os, zfs_sa_upgrade);
 
        error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1,
-           &zfsvfs->z_root);
+           &zsb->z_root);
        if (error)
                goto out;
-       ASSERT(zfsvfs->z_root != 0);
+       ASSERT(zsb->z_root != 0);
 
        error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_UNLINKED_SET, 8, 1,
-           &zfsvfs->z_unlinkedobj);
+           &zsb->z_unlinkedobj);
        if (error)
                goto out;
 
        error = zap_lookup(os, MASTER_NODE_OBJ,
            zfs_userquota_prop_prefixes[ZFS_PROP_USERQUOTA],
-           8, 1, &zfsvfs->z_userquota_obj);
+           8, 1, &zsb->z_userquota_obj);
        if (error && error != ENOENT)
                goto out;
 
        error = zap_lookup(os, MASTER_NODE_OBJ,
            zfs_userquota_prop_prefixes[ZFS_PROP_GROUPQUOTA],
-           8, 1, &zfsvfs->z_groupquota_obj);
+           8, 1, &zsb->z_groupquota_obj);
        if (error && error != ENOENT)
                goto out;
 
        error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES, 8, 1,
-           &zfsvfs->z_fuid_obj);
+           &zsb->z_fuid_obj);
        if (error && error != ENOENT)
                goto out;
 
        error = zap_lookup(os, MASTER_NODE_OBJ, ZFS_SHARES_DIR, 8, 1,
-           &zfsvfs->z_shares_dir);
+           &zsb->z_shares_dir);
        if (error && error != ENOENT)
                goto out;
 
-       mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
-       mutex_init(&zfsvfs->z_lock, NULL, MUTEX_DEFAULT, NULL);
-       list_create(&zfsvfs->z_all_znodes, sizeof (znode_t),
+       mutex_init(&zsb->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
+       mutex_init(&zsb->z_lock, NULL, MUTEX_DEFAULT, NULL);
+       list_create(&zsb->z_all_znodes, sizeof (znode_t),
            offsetof(znode_t, z_link_node));
-       rrw_init(&zfsvfs->z_teardown_lock);
-       rw_init(&zfsvfs->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
-       rw_init(&zfsvfs->z_fuid_lock, NULL, RW_DEFAULT, NULL);
+       rrw_init(&zsb->z_teardown_lock);
+       rw_init(&zsb->z_teardown_inactive_lock, NULL, RW_DEFAULT, NULL);
+       rw_init(&zsb->z_fuid_lock, NULL, RW_DEFAULT, NULL);
        for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
-               mutex_init(&zfsvfs->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
+               mutex_init(&zsb->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
 
-       *zfvp = zfsvfs;
+       *zsbp = zsb;
        return (0);
 
 out:
-       dmu_objset_disown(os, zfsvfs);
-       *zfvp = NULL;
-       kmem_free(zfsvfs, sizeof (zfsvfs_t));
+       dmu_objset_disown(os, zsb);
+       *zsbp = NULL;
+       kmem_free(zsb, sizeof (zfs_sb_t));
        return (error);
 }
 
 static int
-zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
+zfs_sb_setup(zfs_sb_t *zsb, boolean_t mounting)
 {
        int error;
 
-       error = zfs_register_callbacks(zfsvfs->z_vfs);
+       error = zfs_register_callbacks(zsb);
        if (error)
                return (error);
 
        /*
-        * Set the objset user_ptr to track its zfsvfs.
+        * Set the objset user_ptr to track its zsb.
         */
-       mutex_enter(&zfsvfs->z_os->os_user_ptr_lock);
-       dmu_objset_set_user(zfsvfs->z_os, zfsvfs);
-       mutex_exit(&zfsvfs->z_os->os_user_ptr_lock);
+       mutex_enter(&zsb->z_os->os_user_ptr_lock);
+       dmu_objset_set_user(zsb->z_os, zsb);
+       mutex_exit(&zsb->z_os->os_user_ptr_lock);
 
-       zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
+       zsb->z_log = zil_open(zsb->z_os, zfs_get_data);
 
        /*
         * If we are not mounting (ie: online recv), then we don't
@@ -1008,11 +836,11 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
                 * During replay we remove the read only flag to
                 * allow replays to succeed.
                 */
-               readonly = zfsvfs->z_vfs->vfs_flag & VFS_RDONLY;
+               readonly = zsb->z_vfs->mnt_flags & MNT_READONLY;
                if (readonly != 0)
-                       zfsvfs->z_vfs->vfs_flag &= ~VFS_RDONLY;
+                       zsb->z_vfs->mnt_flags &= ~MNT_READONLY;
                else
-                       zfs_unlinked_drain(zfsvfs);
+                       zfs_unlinked_drain(zsb);
 
                /*
                 * Parse and replay the intent log.
@@ -1041,164 +869,51 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
                 * allocated and in the unlinked set, and there is an
                 * intent log record saying to allocate it.
                 */
-               if (spa_writeable(dmu_objset_spa(zfsvfs->z_os))) {
+               if (spa_writeable(dmu_objset_spa(zsb->z_os))) {
                        if (zil_replay_disable) {
-                               zil_destroy(zfsvfs->z_log, B_FALSE);
+                               zil_destroy(zsb->z_log, B_FALSE);
                        } else {
-                               zfsvfs->z_replay = B_TRUE;
-                               zil_replay(zfsvfs->z_os, zfsvfs,
+                               zsb->z_replay = B_TRUE;
+                               zil_replay(zsb->z_os, zsb,
                                    zfs_replay_vector);
-                               zfsvfs->z_replay = B_FALSE;
+                               zsb->z_replay = B_FALSE;
                        }
                }
-               zfsvfs->z_vfs->vfs_flag |= readonly; /* restore readonly bit */
+               zsb->z_vfs->mnt_flags |= readonly; /* restore readonly bit */
        }
 
        return (0);
 }
 
 void
-zfsvfs_free(zfsvfs_t *zfsvfs)
+zfs_sb_free(zfs_sb_t *zsb)
 {
        int i;
-       extern krwlock_t zfsvfs_lock; /* in zfs_znode.c */
 
-       /*
-        * This is a barrier to prevent the filesystem from going away in
-        * zfs_znode_move() until we can safely ensure that the filesystem is
-        * not unmounted. We consider the filesystem valid before the barrier
-        * and invalid after the barrier.
-        */
-       rw_enter(&zfsvfs_lock, RW_READER);
-       rw_exit(&zfsvfs_lock);
-
-       zfs_fuid_destroy(zfsvfs);
+       zfs_fuid_destroy(zsb);
 
-       mutex_destroy(&zfsvfs->z_znodes_lock);
-       mutex_destroy(&zfsvfs->z_lock);
-       list_destroy(&zfsvfs->z_all_znodes);
-       rrw_destroy(&zfsvfs->z_teardown_lock);
-       rw_destroy(&zfsvfs->z_teardown_inactive_lock);
-       rw_destroy(&zfsvfs->z_fuid_lock);
+       mutex_destroy(&zsb->z_znodes_lock);
+       mutex_destroy(&zsb->z_lock);
+       list_destroy(&zsb->z_all_znodes);
+       rrw_destroy(&zsb->z_teardown_lock);
+       rw_destroy(&zsb->z_teardown_inactive_lock);
+       rw_destroy(&zsb->z_fuid_lock);
        for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
-               mutex_destroy(&zfsvfs->z_hold_mtx[i]);
-       kmem_free(zfsvfs, sizeof (zfsvfs_t));
+               mutex_destroy(&zsb->z_hold_mtx[i]);
+       kmem_free(zsb, sizeof (zfs_sb_t));
 }
 
 static void
-zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
-{
-       zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
-       if (zfsvfs->z_use_fuids && zfsvfs->z_vfs) {
-               vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
-               vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
-               vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
-               vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
-               vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
-               vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
-       }
-       zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
-}
-
-static int
-zfs_domount(vfs_t *vfsp, char *osname)
+zfs_set_fuid_feature(zfs_sb_t *zsb)
 {
-       dev_t mount_dev;
-       uint64_t recordsize, fsid_guid;
-       int error = 0;
-       zfsvfs_t *zfsvfs;
-
-       ASSERT(vfsp);
-       ASSERT(osname);
-
-       error = zfsvfs_create(osname, &zfsvfs);
-       if (error)
-               return (error);
-       zfsvfs->z_vfs = vfsp;
-
-       /* Initialize the generic filesystem structure. */
-       vfsp->vfs_bcount = 0;
-       vfsp->vfs_data = NULL;
-
-       if (zfs_create_unique_device(&mount_dev) == -1) {
-               error = ENODEV;
-               goto out;
-       }
-       ASSERT(vfs_devismounted(mount_dev) == 0);
-
-       if (error = dsl_prop_get_integer(osname, "recordsize", &recordsize,
-           NULL))
-               goto out;
-
-       vfsp->vfs_dev = mount_dev;
-       vfsp->vfs_fstype = zfsfstype;
-       vfsp->vfs_bsize = recordsize;
-       vfsp->vfs_flag |= VFS_NOTRUNC;
-       vfsp->vfs_data = zfsvfs;
-
-       /*
-        * The fsid is 64 bits, composed of an 8-bit fs type, which
-        * separates our fsid from any other filesystem types, and a
-        * 56-bit objset unique ID.  The objset unique ID is unique to
-        * all objsets open on this system, provided by unique_create().
-        * The 8-bit fs type must be put in the low bits of fsid[1]
-        * because that's where other Solaris filesystems put it.
-        */
-       fsid_guid = dmu_objset_fsid_guid(zfsvfs->z_os);
-       ASSERT((fsid_guid & ~((1ULL<<56)-1)) == 0);
-       vfsp->vfs_fsid.val[0] = fsid_guid;
-       vfsp->vfs_fsid.val[1] = ((fsid_guid>>32) << 8) |
-           zfsfstype & 0xFF;
-
-       /*
-        * Set features for file system.
-        */
-       zfs_set_fuid_feature(zfsvfs);
-       if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {
-               vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
-               vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
-               vfs_set_feature(vfsp, VFSFT_NOCASESENSITIVE);
-       } else if (zfsvfs->z_case == ZFS_CASE_MIXED) {
-               vfs_set_feature(vfsp, VFSFT_DIRENTFLAGS);
-               vfs_set_feature(vfsp, VFSFT_CASEINSENSITIVE);
-       }
-       vfs_set_feature(vfsp, VFSFT_ZEROCOPY_SUPPORTED);
-
-       if (dmu_objset_is_snapshot(zfsvfs->z_os)) {
-               uint64_t pval;
-
-               atime_changed_cb(zfsvfs, B_FALSE);
-               readonly_changed_cb(zfsvfs, B_TRUE);
-               if (error = dsl_prop_get_integer(osname, "xattr", &pval, NULL))
-                       goto out;
-               xattr_changed_cb(zfsvfs, pval);
-               zfsvfs->z_issnap = B_TRUE;
-               zfsvfs->z_os->os_sync = ZFS_SYNC_DISABLED;
-
-               mutex_enter(&zfsvfs->z_os->os_user_ptr_lock);
-               dmu_objset_set_user(zfsvfs->z_os, zfsvfs);
-               mutex_exit(&zfsvfs->z_os->os_user_ptr_lock);
-       } else {
-               error = zfsvfs_setup(zfsvfs, B_TRUE);
-       }
-
-       if (!zfsvfs->z_issnap)
-               zfsctl_create(zfsvfs);
-out:
-       if (error) {
-               dmu_objset_disown(zfsvfs->z_os, zfsvfs);
-               zfsvfs_free(zfsvfs);
-       } else {
-               atomic_add_32(&zfs_active_fs_count, 1);
-       }
-
-       return (error);
+       zsb->z_use_fuids = USE_FUIDS(zsb->z_version, zsb->z_os);
+       zsb->z_use_sa = USE_SA(zsb->z_version, zsb->z_os);
 }
 
 void
-zfs_unregister_callbacks(zfsvfs_t *zfsvfs)
+zfs_unregister_callbacks(zfs_sb_t *zsb)
 {
-       objset_t *os = zfsvfs->z_os;
+       objset_t *os = zsb->z_os;
        struct dsl_dataset *ds;
 
        /*
@@ -1207,92 +922,39 @@ zfs_unregister_callbacks(zfsvfs_t *zfsvfs)
        if (!dmu_objset_is_snapshot(os)) {
                ds = dmu_objset_ds(os);
                VERIFY(dsl_prop_unregister(ds, "atime", atime_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "xattr", xattr_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "recordsize", blksz_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "readonly", readonly_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "devices", devices_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "setuid", setuid_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "exec", exec_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "snapdir", snapdir_changed_cb,
-                   zfsvfs) == 0);
+                   zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "aclinherit",
-                   acl_inherit_changed_cb, zfsvfs) == 0);
+                   acl_inherit_changed_cb, zsb) == 0);
 
                VERIFY(dsl_prop_unregister(ds, "vscan",
-                   vscan_changed_cb, zfsvfs) == 0);
+                   vscan_changed_cb, zsb) == 0);
        }
 }
+EXPORT_SYMBOL(zfs_unregister_callbacks);
 
-/*
- * Convert a decimal digit string to a uint64_t integer.
- */
-static int
-str_to_uint64(char *str, uint64_t *objnum)
-{
-       uint64_t num = 0;
-
-       while (*str) {
-               if (*str < '0' || *str > '9')
-                       return (EINVAL);
-
-               num = num*10 + *str++ - '0';
-       }
-
-       *objnum = num;
-       return (0);
-}
-
-/*
- * The boot path passed from the boot loader is in the form of
- * "rootpool-name/root-filesystem-object-number'. Convert this
- * string to a dataset name: "rootpool-name/root-filesystem-name".
- */
-static int
-zfs_parse_bootfs(char *bpath, char *outpath)
-{
-       char *slashp;
-       uint64_t objnum;
-       int error;
-
-       if (*bpath == 0 || *bpath == '/')
-               return (EINVAL);
-
-       (void) strcpy(outpath, bpath);
-
-       slashp = strchr(bpath, '/');
-
-       /* if no '/', just return the pool name */
-       if (slashp == NULL) {
-               return (0);
-       }
-
-       /* if not a number, just return the root dataset name */
-       if (str_to_uint64(slashp+1, &objnum)) {
-               return (0);
-       }
-
-       *slashp = '\0';
-       error = dsl_dsobj_to_dsname(bpath, objnum, outpath);
-       *slashp = '/';
-
-       return (error);
-}
-
+#ifdef HAVE_MLSLABEL
 /*
  * zfs_check_global_label:
  *     Check that the hex label string is appropriate for the dataset
@@ -1320,337 +982,18 @@ zfs_check_global_label(const char *dsname, const char *hexsl)
        }
        return (EACCES);
 }
+#endif /* HAVE_MLSLABEL */
 
-/*
- * zfs_mount_label_policy:
- *     Determine whether the mount is allowed according to MAC check.
- *     by comparing (where appropriate) label of the dataset against
- *     the label of the zone being mounted into.  If the dataset has
- *     no label, create one.
- *
- *     Returns:
- *              0 :    access allowed
- *             >0 :    error code, such as EACCES
- */
-static int
-zfs_mount_label_policy(vfs_t *vfsp, char *osname)
-{
-       int             error, retv;
-       zone_t          *mntzone = NULL;
-       ts_label_t      *mnt_tsl;
-       bslabel_t       *mnt_sl;
-       bslabel_t       ds_sl;
-       char            ds_hexsl[MAXNAMELEN];
-
-       retv = EACCES;                          /* assume the worst */
-
-       /*
-        * Start by getting the dataset label if it exists.
-        */
-       error = dsl_prop_get(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
-           1, sizeof (ds_hexsl), &ds_hexsl, NULL);
-       if (error)
-               return (EACCES);
-
-       /*
-        * If labeling is NOT enabled, then disallow the mount of datasets
-        * which have a non-default label already.  No other label checks
-        * are needed.
-        */
-       if (!is_system_labeled()) {
-               if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0)
-                       return (0);
-               return (EACCES);
-       }
-
-       /*
-        * Get the label of the mountpoint.  If mounting into the global
-        * zone (i.e. mountpoint is not within an active zone and the
-        * zoned property is off), the label must be default or
-        * admin_low/admin_high only; no other checks are needed.
-        */
-       mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE);
-       if (mntzone->zone_id == GLOBAL_ZONEID) {
-               uint64_t zoned;
-
-               zone_rele(mntzone);
-
-               if (dsl_prop_get_integer(osname,
-                   zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL))
-                       return (EACCES);
-               if (!zoned)
-                       return (zfs_check_global_label(osname, ds_hexsl));
-               else
-                       /*
-                        * This is the case of a zone dataset being mounted
-                        * initially, before the zone has been fully created;
-                        * allow this mount into global zone.
-                        */
-                       return (0);
-       }
-
-       mnt_tsl = mntzone->zone_slabel;
-       ASSERT(mnt_tsl != NULL);
-       label_hold(mnt_tsl);
-       mnt_sl = label2bslabel(mnt_tsl);
-
-       if (strcasecmp(ds_hexsl, ZFS_MLSLABEL_DEFAULT) == 0) {
-               /*
-                * The dataset doesn't have a real label, so fabricate one.
-                */
-               char *str = NULL;
-
-               if (l_to_str_internal(mnt_sl, &str) == 0 &&
-                   dsl_prop_set(osname, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
-                   ZPROP_SRC_LOCAL, 1, strlen(str) + 1, str) == 0)
-                       retv = 0;
-               if (str != NULL)
-                       kmem_free(str, strlen(str) + 1);
-       } else if (hexstr_to_label(ds_hexsl, &ds_sl) == 0) {
-               /*
-                * Now compare labels to complete the MAC check.  If the
-                * labels are equal then allow access.  If the mountpoint
-                * label dominates the dataset label, allow readonly access.
-                * Otherwise, access is denied.
-                */
-               if (blequal(mnt_sl, &ds_sl))
-                       retv = 0;
-               else if (bldominates(mnt_sl, &ds_sl)) {
-                       vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0);
-                       retv = 0;
-               }
-       }
-
-       label_rele(mnt_tsl);
-       zone_rele(mntzone);
-       return (retv);
-}
-
-static int
-zfs_mountroot(vfs_t *vfsp, enum whymountroot why)
-{
-       int error = 0;
-       static int zfsrootdone = 0;
-       zfsvfs_t *zfsvfs = NULL;
-       znode_t *zp = NULL;
-       vnode_t *vp = NULL;
-       char *zfs_bootfs;
-       char *zfs_devid;
-
-       ASSERT(vfsp);
-
-       /*
-        * The filesystem that we mount as root is defined in the
-        * boot property "zfs-bootfs" with a format of
-        * "poolname/root-dataset-objnum".
-        */
-       if (why == ROOT_INIT) {
-               if (zfsrootdone++)
-                       return (EBUSY);
-               /*
-                * the process of doing a spa_load will require the
-                * clock to be set before we could (for example) do
-                * something better by looking at the timestamp on
-                * an uberblock, so just set it to -1.
-                */
-               clkset(-1);
-
-               if ((zfs_bootfs = spa_get_bootprop("zfs-bootfs")) == NULL) {
-                       cmn_err(CE_NOTE, "spa_get_bootfs: can not get "
-                           "bootfs name");
-                       return (EINVAL);
-               }
-               zfs_devid = spa_get_bootprop("diskdevid");
-               error = spa_import_rootpool(rootfs.bo_name, zfs_devid);
-               if (zfs_devid)
-                       spa_free_bootprop(zfs_devid);
-               if (error) {
-                       spa_free_bootprop(zfs_bootfs);
-                       cmn_err(CE_NOTE, "spa_import_rootpool: error %d",
-                           error);
-                       return (error);
-               }
-               if (error = zfs_parse_bootfs(zfs_bootfs, rootfs.bo_name)) {
-                       spa_free_bootprop(zfs_bootfs);
-                       cmn_err(CE_NOTE, "zfs_parse_bootfs: error %d",
-                           error);
-                       return (error);
-               }
-
-               spa_free_bootprop(zfs_bootfs);
-
-               if (error = vfs_lock(vfsp))
-                       return (error);
-
-               if (error = zfs_domount(vfsp, rootfs.bo_name)) {
-                       cmn_err(CE_NOTE, "zfs_domount: error %d", error);
-                       goto out;
-               }
-
-               zfsvfs = (zfsvfs_t *)vfsp->vfs_data;
-               ASSERT(zfsvfs);
-               if (error = zfs_zget(zfsvfs, zfsvfs->z_root, &zp)) {
-                       cmn_err(CE_NOTE, "zfs_zget: error %d", error);
-                       goto out;
-               }
-
-               vp = ZTOV(zp);
-               mutex_enter(&vp->v_lock);
-               vp->v_flag |= VROOT;
-               mutex_exit(&vp->v_lock);
-               rootvp = vp;
-
-               /*
-                * Leave rootvp held.  The root file system is never unmounted.
-                */
-
-               vfs_add((struct vnode *)0, vfsp,
-                   (vfsp->vfs_flag & VFS_RDONLY) ? MS_RDONLY : 0);
-out:
-               vfs_unlock(vfsp);
-               return (error);
-       } else if (why == ROOT_REMOUNT) {
-               readonly_changed_cb(vfsp->vfs_data, B_FALSE);
-               vfsp->vfs_flag |= VFS_REMOUNT;
-
-               /* refresh mount options */
-               zfs_unregister_callbacks(vfsp->vfs_data);
-               return (zfs_register_callbacks(vfsp));
-
-       } else if (why == ROOT_UNMOUNT) {
-               zfs_unregister_callbacks((zfsvfs_t *)vfsp->vfs_data);
-               (void) zfs_sync(vfsp, 0, 0);
-               return (0);
-       }
-
-       /*
-        * if "why" is equal to anything else other than ROOT_INIT,
-        * ROOT_REMOUNT, or ROOT_UNMOUNT, we do not support it.
-        */
-       return (ENOTSUP);
-}
-
-/*ARGSUSED*/
-static int
-zfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
-{
-       char            *osname;
-       pathname_t      spn;
-       int             error = 0;
-       uio_seg_t       fromspace = (uap->flags & MS_SYSSPACE) ?
-           UIO_SYSSPACE : UIO_USERSPACE;
-       int             canwrite;
-
-       if (mvp->v_type != VDIR)
-               return (ENOTDIR);
-
-       mutex_enter(&mvp->v_lock);
-       if ((uap->flags & MS_REMOUNT) == 0 &&
-           (uap->flags & MS_OVERLAY) == 0 &&
-           (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
-               mutex_exit(&mvp->v_lock);
-               return (EBUSY);
-       }
-       mutex_exit(&mvp->v_lock);
-
-       /*
-        * ZFS does not support passing unparsed data in via MS_DATA.
-        * Users should use the MS_OPTIONSTR interface; this means
-        * that all option parsing is already done and the options struct
-        * can be interrogated.
-        */
-       if ((uap->flags & MS_DATA) && uap->datalen > 0)
-               return (EINVAL);
-
-       /*
-        * Get the objset name (the "special" mount argument).
-        */
-       if (error = pn_get(uap->spec, fromspace, &spn))
-               return (error);
-
-       osname = spn.pn_path;
-
-       /*
-        * Check for mount privilege?
-        *
-        * If we don't have privilege then see if
-        * we have local permission to allow it
-        */
-       error = secpolicy_fs_mount(cr, mvp, vfsp);
-       if (error) {
-               if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) == 0) {
-                       vattr_t         vattr;
-
-                       /*
-                        * Make sure user is the owner of the mount point
-                        * or has sufficient privileges.
-                        */
-
-                       vattr.va_mask = AT_UID;
-
-                       if (VOP_GETATTR(mvp, &vattr, 0, cr, NULL)) {
-                               goto out;
-                       }
-
-                       if (secpolicy_vnode_owner(cr, vattr.va_uid) != 0 &&
-                           VOP_ACCESS(mvp, VWRITE, 0, cr, NULL) != 0) {
-                               goto out;
-                       }
-                       secpolicy_fs_mount_clearopts(cr, vfsp);
-               } else {
-                       goto out;
-               }
-       }
-
-       /*
-        * Refuse to mount a filesystem if we are in a local zone and the
-        * dataset is not visible.
-        */
-       if (!INGLOBALZONE(curproc) &&
-           (!zone_dataset_visible(osname, &canwrite) || !canwrite)) {
-               error = EPERM;
-               goto out;
-       }
-
-       error = zfs_mount_label_policy(vfsp, osname);
-       if (error)
-               goto out;
-
-       /*
-        * When doing a remount, we simply refresh our temporary properties
-        * according to those options set in the current VFS options.
-        */
-       if (uap->flags & MS_REMOUNT) {
-               /* refresh mount options */
-               zfs_unregister_callbacks(vfsp->vfs_data);
-               error = zfs_register_callbacks(vfsp);
-               goto out;
-       }
-
-       error = zfs_domount(vfsp, osname);
-
-       /*
-        * Add an extra VFS_HOLD on our parent vfs so that it can't
-        * disappear due to a forced unmount.
-        */
-       if (error == 0 && ((zfsvfs_t *)vfsp->vfs_data)->z_issnap)
-               VFS_HOLD(mvp->v_vfsp);
-
-out:
-       pn_free(&spn);
-       return (error);
-}
-
-static int
-zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp)
+int
+zfs_statvfs(struct dentry *dentry, struct kstatfs *statp)
 {
-       zfsvfs_t *zfsvfs = vfsp->vfs_data;
-       dev32_t d32;
+       zfs_sb_t *zsb = dentry->d_sb->s_fs_info;
        uint64_t refdbytes, availbytes, usedobjs, availobjs;
+       uint32_t bshift;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
 
-       dmu_objset_space(zfsvfs->z_os,
+       dmu_objset_space(zsb->z_os,
            &refdbytes, &availbytes, &usedobjs, &availobjs);
 
        /*
@@ -1659,16 +1002,17 @@ zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp)
         * and we report our blocksize as the filesystem's maximum blocksize.
         */
        statp->f_frsize = 1UL << SPA_MINBLOCKSHIFT;
-       statp->f_bsize = zfsvfs->z_max_blksz;
+       statp->f_bsize = zsb->z_max_blksz;
+       bshift = fls(statp->f_bsize) - 1;
 
        /*
-        * The following report "total" blocks of various kinds in the
-        * file system, but reported in terms of f_frsize - the
-        * "fragment" size.
+        * The following report "total" blocks of various kinds in
+        * the file system, but reported in terms of f_bsize - the
+        * "preferred" size.
         */
 
-       statp->f_blocks = (refdbytes + availbytes) >> SPA_MINBLOCKSHIFT;
-       statp->f_bfree = availbytes >> SPA_MINBLOCKSHIFT;
+       statp->f_blocks = (refdbytes + availbytes) >> bshift;
+       statp->f_bfree = availbytes >> bshift;
        statp->f_bavail = statp->f_bfree; /* no root reservation */
 
        /*
@@ -1680,90 +1024,84 @@ zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp)
         * and the number of blocks (each object will take at least a block).
         */
        statp->f_ffree = MIN(availobjs, statp->f_bfree);
-       statp->f_favail = statp->f_ffree;       /* no "root reservation" */
        statp->f_files = statp->f_ffree + usedobjs;
-
-       (void) cmpldev(&d32, vfsp->vfs_dev);
-       statp->f_fsid = d32;
+       statp->f_fsid.val[0] = 0; /* XXX: Map up some unique ID */
+       statp->f_fsid.val[1] = 0;
+       statp->f_type = ZFS_SUPER_MAGIC;
+       statp->f_namelen = ZFS_MAXNAMELEN;
 
        /*
-        * We're a zfs filesystem.
-        */
-       (void) strcpy(statp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name);
-
-       statp->f_flag = vf_to_stf(vfsp->vfs_flag);
-
-       statp->f_namemax = ZFS_MAXNAMELEN;
-
-       /*
-        * We have all of 32 characters to stuff a string here.
+        * We have all of 40 characters to stuff a string here.
         * Is there anything useful we could/should provide?
         */
-       bzero(statp->f_fstr, sizeof (statp->f_fstr));
+       bzero(statp->f_spare, sizeof (statp->f_spare));
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (0);
 }
+EXPORT_SYMBOL(zfs_statvfs);
 
-static int
-zfs_root(vfs_t *vfsp, vnode_t **vpp)
+int
+zfs_root(zfs_sb_t *zsb, struct inode **ipp)
 {
-       zfsvfs_t *zfsvfs = vfsp->vfs_data;
        znode_t *rootzp;
        int error;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
 
-       error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
+       error = zfs_zget(zsb, zsb->z_root, &rootzp);
        if (error == 0)
-               *vpp = ZTOV(rootzp);
+               *ipp = ZTOI(rootzp);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_root);
 
 /*
- * Teardown the zfsvfs::z_os.
+ * Teardown the zfs_sb_t::z_os.
  *
  * Note, if 'unmounting' if FALSE, we return with the 'z_teardown_lock'
  * and 'z_teardown_inactive_lock' held.
  */
-static int
-zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
+int
+zfsvfs_teardown(zfs_sb_t *zsb, boolean_t unmounting)
 {
        znode_t *zp;
 
-       rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
+       rrw_enter(&zsb->z_teardown_lock, RW_WRITER, FTAG);
 
        if (!unmounting) {
                /*
-                * We purge the parent filesystem's vfsp as the parent
-                * filesystem and all of its snapshots have their vnode's
-                * v_vfsp set to the parent's filesystem's vfsp.  Note,
-                * 'z_parent' is self referential for non-snapshots.
+                * We purge the parent filesystem's super block as the
+                * parent filesystem and all of its snapshots have their
+                * inode's super block set to the parent's filesystem's
+                * super block.  Note,  'z_parent' is self referential
+                * for non-snapshots.
                 */
-               (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0);
+               shrink_dcache_sb(zsb->z_parent->z_sb);
+               invalidate_inodes(zsb->z_parent->z_sb);
        }
 
        /*
         * Close the zil. NB: Can't close the zil while zfs_inactive
         * threads are blocked as zil_close can call zfs_inactive.
         */
-       if (zfsvfs->z_log) {
-               zil_close(zfsvfs->z_log);
-               zfsvfs->z_log = NULL;
+       if (zsb->z_log) {
+               zil_close(zsb->z_log);
+               zsb->z_log = NULL;
        }
 
-       rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER);
+       rw_enter(&zsb->z_teardown_inactive_lock, RW_WRITER);
 
        /*
         * If we are not unmounting (ie: online recv) and someone already
         * unmounted this file system while we were doing the switcheroo,
         * or a reopen of z_os failed then just bail out now.
         */
-       if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) {
-               rw_exit(&zfsvfs->z_teardown_inactive_lock);
-               rrw_exit(&zfsvfs->z_teardown_lock, FTAG);
+       if (!unmounting && (zsb->z_unmounted || zsb->z_os == NULL)) {
+               rw_exit(&zsb->z_teardown_inactive_lock);
+               rrw_exit(&zsb->z_teardown_lock, FTAG);
                return (EIO);
        }
 
@@ -1774,14 +1112,14 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
         *
         * Release all holds on dbufs.
         */
-       mutex_enter(&zfsvfs->z_znodes_lock);
-       for (zp = list_head(&zfsvfs->z_all_znodes); zp != NULL;
-           zp = list_next(&zfsvfs->z_all_znodes, zp))
+       mutex_enter(&zsb->z_znodes_lock);
+       for (zp = list_head(&zsb->z_all_znodes); zp != NULL;
+           zp = list_next(&zsb->z_all_znodes, zp))
                if (zp->z_sa_hdl) {
-                       ASSERT(ZTOV(zp)->v_count > 0);
+                       ASSERT(atomic_read(&ZTOI(zp)->i_count) > 0);
                        zfs_znode_dmu_fini(zp);
                }
-       mutex_exit(&zfsvfs->z_znodes_lock);
+       mutex_exit(&zsb->z_znodes_lock);
 
        /*
         * If we are unmounting, set the unmounted flag and let new vops
@@ -1789,96 +1127,142 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
         * other vops will fail with EIO.
         */
        if (unmounting) {
-               zfsvfs->z_unmounted = B_TRUE;
-               rrw_exit(&zfsvfs->z_teardown_lock, FTAG);
-               rw_exit(&zfsvfs->z_teardown_inactive_lock);
+               zsb->z_unmounted = B_TRUE;
+               rrw_exit(&zsb->z_teardown_lock, FTAG);
+               rw_exit(&zsb->z_teardown_inactive_lock);
        }
 
        /*
         * z_os will be NULL if there was an error in attempting to reopen
-        * zfsvfs, so just return as the properties had already been
+        * zsb, so just return as the properties had already been
+        *
         * unregistered and cached data had been evicted before.
         */
-       if (zfsvfs->z_os == NULL)
+       if (zsb->z_os == NULL)
                return (0);
 
        /*
         * Unregister properties.
         */
-       zfs_unregister_callbacks(zfsvfs);
+       zfs_unregister_callbacks(zsb);
 
        /*
         * Evict cached data
         */
-       if (dmu_objset_is_dirty_anywhere(zfsvfs->z_os))
-               if (!(zfsvfs->z_vfs->vfs_flag & VFS_RDONLY))
-                       txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
-       (void) dmu_objset_evict_dbufs(zfsvfs->z_os);
+       if (dmu_objset_is_dirty_anywhere(zsb->z_os))
+               if (!(zsb->z_vfs->mnt_flags & MNT_READONLY))
+                       txg_wait_synced(dmu_objset_pool(zsb->z_os), 0);
+       (void) dmu_objset_evict_dbufs(zsb->z_os);
 
        return (0);
 }
 
-/*ARGSUSED*/
-static int
-zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr)
+int
+zfs_domount(struct super_block *sb, void *data, int silent)
 {
-       zfsvfs_t *zfsvfs = vfsp->vfs_data;
-       objset_t *os;
-       int ret;
-
-       ret = secpolicy_fs_unmount(cr, vfsp);
-       if (ret) {
-               if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource),
-                   ZFS_DELEG_PERM_MOUNT, cr))
-                       return (ret);
-       }
+       zpl_mount_data_t *zmd = data;
+       const char *osname = zmd->z_osname;
+       zfs_sb_t *zsb;
+       struct inode *root_inode;
+       uint64_t recordsize;
+       int error;
 
        /*
-        * We purge the parent filesystem's vfsp as the parent filesystem
-        * and all of its snapshots have their vnode's v_vfsp set to the
-        * parent's filesystem's vfsp.  Note, 'z_parent' is self
-        * referential for non-snapshots.
+        * Linux allows multiple vfs mounts per super block.  However, the
+        * zfs_sb_t only contains a pointer for a single vfs mount.  This
+        * back reference in the long term could be extended to a list of
+        * vfs mounts if a hook were added to the kernel to notify us when
+        * a vfsmount is destroyed.  Until then we must limit the number
+        * of mounts per super block to one.
         */
-       (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0);
+       if (atomic_read(&sb->s_active) > 1)
+               return (EBUSY);
 
-       /*
-        * Unmount any snapshots mounted under .zfs before unmounting the
-        * dataset itself.
-        */
-       if (zfsvfs->z_ctldir != NULL &&
-           (ret = zfsctl_umount_snapshots(vfsp, fflag, cr)) != 0) {
-               return (ret);
+       error = zfs_sb_create(osname, &zsb);
+       if (error)
+               return (error);
+
+       if ((error = dsl_prop_get_integer(osname, "recordsize",
+           &recordsize, NULL)))
+               goto out;
+
+       zsb->z_sb = sb;
+       zsb->z_vfs = zmd->z_vfs;
+       sb->s_fs_info = zsb;
+       sb->s_magic = ZFS_SUPER_MAGIC;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
+       sb->s_time_gran = 1;
+       sb->s_blocksize = recordsize;
+       sb->s_blocksize_bits = ilog2(recordsize);
+
+       /* Set callback operations for the file system. */
+       sb->s_op = &zpl_super_operations;
+       sb->s_xattr = zpl_xattr_handlers;
+#ifdef HAVE_EXPORTS
+        sb->s_export_op = &zpl_export_operations;
+#endif /* HAVE_EXPORTS */
+
+       /* Set features for file system. */
+       zfs_set_fuid_feature(zsb);
+
+       if (dmu_objset_is_snapshot(zsb->z_os)) {
+               uint64_t pval;
+
+               atime_changed_cb(zsb, B_FALSE);
+               readonly_changed_cb(zsb, B_TRUE);
+               if ((error = dsl_prop_get_integer(osname,"xattr",&pval,NULL)))
+                       goto out;
+               xattr_changed_cb(zsb, pval);
+               zsb->z_issnap = B_TRUE;
+               zsb->z_os->os_sync = ZFS_SYNC_DISABLED;
+
+               mutex_enter(&zsb->z_os->os_user_ptr_lock);
+               dmu_objset_set_user(zsb->z_os, zsb);
+               mutex_exit(&zsb->z_os->os_user_ptr_lock);
+       } else {
+               error = zfs_sb_setup(zsb, B_TRUE);
+#ifdef HAVE_SNAPSHOT
+               (void) zfs_snap_create(zsb);
+#endif /* HAVE_SNAPSHOT */
        }
 
-       if (!(fflag & MS_FORCE)) {
-               /*
-                * Check the number of active vnodes in the file system.
-                * Our count is maintained in the vfs structure, but the
-                * number is off by 1 to indicate a hold on the vfs
-                * structure itself.
-                *
-                * The '.zfs' directory maintains a reference of its
-                * own, and any active references underneath are
-                * reflected in the vnode count.
-                */
-               if (zfsvfs->z_ctldir == NULL) {
-                       if (vfsp->vfs_count > 1)
-                               return (EBUSY);
-               } else {
-                       if (vfsp->vfs_count > 2 ||
-                           zfsvfs->z_ctldir->v_count > 1)
-                               return (EBUSY);
-               }
+       /* Allocate a root inode for the filesystem. */
+       error = zfs_root(zsb, &root_inode);
+       if (error) {
+               (void) zfs_umount(sb);
+               goto out;
+       }
+
+       /* Allocate a root dentry for the filesystem */
+       sb->s_root = d_alloc_root(root_inode);
+       if (sb->s_root == NULL) {
+               (void) zfs_umount(sb);
+               error = ENOMEM;
+               goto out;
+       }
+out:
+       if (error) {
+               dmu_objset_disown(zsb->z_os, zsb);
+               zfs_sb_free(zsb);
        }
 
-       vfsp->vfs_flag |= VFS_UNMOUNTED;
+       return (error);
+}
+EXPORT_SYMBOL(zfs_domount);
+
+/*ARGSUSED*/
+int
+zfs_umount(struct super_block *sb)
+{
+       zfs_sb_t *zsb = sb->s_fs_info;
+       objset_t *os;
 
-       VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);
-       os = zfsvfs->z_os;
+       VERIFY(zfsvfs_teardown(zsb, B_TRUE) == 0);
+       os = zsb->z_os;
 
        /*
         * z_os will be NULL if there was an error in
-        * attempting to reopen zfsvfs.
+        * attempting to reopen zsb.
         */
        if (os != NULL) {
                /*
@@ -1891,32 +1275,28 @@ zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr)
                /*
                 * Finally release the objset
                 */
-               dmu_objset_disown(os, zfsvfs);
+               dmu_objset_disown(os, zsb);
        }
 
-       /*
-        * We can now safely destroy the '.zfs' directory node.
-        */
-       if (zfsvfs->z_ctldir != NULL)
-               zfsctl_destroy(zfsvfs);
-
+       zfs_sb_free(zsb);
        return (0);
 }
+EXPORT_SYMBOL(zfs_umount);
 
-static int
-zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
+int
+zfs_vget(struct vfsmount *vfsp, struct inode **ipp, fid_t *fidp)
 {
-       zfsvfs_t        *zfsvfs = vfsp->vfs_data;
+       zfs_sb_t        *zsb = VTOZSB(vfsp);
        znode_t         *zp;
        uint64_t        object = 0;
        uint64_t        fid_gen = 0;
        uint64_t        gen_mask;
        uint64_t        zp_gen;
-       int             i, err;
+       int             i, err;
 
-       *vpp = NULL;
+       *ipp = NULL;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
 
        if (fidp->fid_len == LONG_FID_LEN) {
                zfid_long_t     *zlfid = (zfid_long_t *)fidp;
@@ -1929,12 +1309,14 @@ zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
                for (i = 0; i < sizeof (zlfid->zf_setgen); i++)
                        setgen |= ((uint64_t)zlfid->zf_setgen[i]) << (8 * i);
 
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
 
-               err = zfsctl_lookup_objset(vfsp, objsetid, &zfsvfs);
+#ifdef HAVE_SNAPSHOT
+               err = zfsctl_lookup_objset(vfsp, objsetid, &zsb);
                if (err)
                        return (EINVAL);
-               ZFS_ENTER(zfsvfs);
+#endif /* HAVE_SNAPSHOT */
+               ZFS_ENTER(zsb);
        }
 
        if (fidp->fid_len == SHORT_FID_LEN || fidp->fid_len == LONG_FID_LEN) {
@@ -1946,98 +1328,104 @@ zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
                for (i = 0; i < sizeof (zfid->zf_gen); i++)
                        fid_gen |= ((uint64_t)zfid->zf_gen[i]) << (8 * i);
        } else {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
+#ifdef HAVE_SNAPSHOT
        /* A zero fid_gen means we are in the .zfs control directories */
        if (fid_gen == 0 &&
            (object == ZFSCTL_INO_ROOT || object == ZFSCTL_INO_SNAPDIR)) {
-               *vpp = zfsvfs->z_ctldir;
-               ASSERT(*vpp != NULL);
+               *ipp = zsb->z_ctldir;
+               ASSERT(*ipp != NULL);
                if (object == ZFSCTL_INO_SNAPDIR) {
-                       VERIFY(zfsctl_root_lookup(*vpp, "snapshot", vpp, NULL,
+                       VERIFY(zfsctl_root_lookup(*ipp, "snapshot", ipp, NULL,
                            0, NULL, NULL, NULL, NULL, NULL) == 0);
                } else {
-                       VN_HOLD(*vpp);
+                       igrab(*ipp);
                }
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (0);
        }
+#endif /* HAVE_SNAPSHOT */
 
        gen_mask = -1ULL >> (64 - 8 * i);
 
        dprintf("getting %llu [%u mask %llx]\n", object, fid_gen, gen_mask);
-       if (err = zfs_zget(zfsvfs, object, &zp)) {
-               ZFS_EXIT(zfsvfs);
+       if ((err = zfs_zget(zsb, object, &zp))) {
+               ZFS_EXIT(zsb);
                return (err);
        }
-       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs), &zp_gen,
+       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zsb), &zp_gen,
            sizeof (uint64_t));
        zp_gen = zp_gen & gen_mask;
        if (zp_gen == 0)
                zp_gen = 1;
        if (zp->z_unlinked || zp_gen != fid_gen) {
                dprintf("znode gen (%u) != fid gen (%u)\n", zp_gen, fid_gen);
-               VN_RELE(ZTOV(zp));
-               ZFS_EXIT(zfsvfs);
+               iput(ZTOI(zp));
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
-       *vpp = ZTOV(zp);
-       ZFS_EXIT(zfsvfs);
+       *ipp = ZTOI(zp);
+       if (*ipp)
+               zfs_inode_update(ITOZ(*ipp));
+
+       ZFS_EXIT(zsb);
        return (0);
 }
+EXPORT_SYMBOL(zfs_vget);
 
 /*
- * Block out VOPs and close zfsvfs_t::z_os
+ * Block out VOPs and close zfs_sb_t::z_os
  *
  * Note, if successful, then we return with the 'z_teardown_lock' and
  * 'z_teardown_inactive_lock' write held.
  */
 int
-zfs_suspend_fs(zfsvfs_t *zfsvfs)
+zfs_suspend_fs(zfs_sb_t *zsb)
 {
        int error;
 
-       if ((error = zfsvfs_teardown(zfsvfs, B_FALSE)) != 0)
+       if ((error = zfsvfs_teardown(zsb, B_FALSE)) != 0)
                return (error);
-       dmu_objset_disown(zfsvfs->z_os, zfsvfs);
+       dmu_objset_disown(zsb->z_os, zsb);
 
        return (0);
 }
+EXPORT_SYMBOL(zfs_suspend_fs);
 
 /*
- * Reopen zfsvfs_t::z_os and release VOPs.
+ * Reopen zfs_sb_t::z_os and release VOPs.
  */
 int
-zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname)
+zfs_resume_fs(zfs_sb_t *zsb, const char *osname)
 {
        int err, err2;
 
-       ASSERT(RRW_WRITE_HELD(&zfsvfs->z_teardown_lock));
-       ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
+       ASSERT(RRW_WRITE_HELD(&zsb->z_teardown_lock));
+       ASSERT(RW_WRITE_HELD(&zsb->z_teardown_inactive_lock));
 
-       err = dmu_objset_own(osname, DMU_OST_ZFS, B_FALSE, zfsvfs,
-           &zfsvfs->z_os);
+       err = dmu_objset_own(osname, DMU_OST_ZFS, B_FALSE, zsb, &zsb->z_os);
        if (err) {
-               zfsvfs->z_os = NULL;
+               zsb->z_os = NULL;
        } else {
                znode_t *zp;
                uint64_t sa_obj = 0;
 
-               err2 = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
+               err2 = zap_lookup(zsb->z_os, MASTER_NODE_OBJ,
                    ZFS_SA_ATTRS, 8, 1, &sa_obj);
 
-               if ((err || err2) && zfsvfs->z_version >= ZPL_VERSION_SA)
+               if ((err || err2) && zsb->z_version >= ZPL_VERSION_SA)
                        goto bail;
 
 
-               if ((err = sa_setup(zfsvfs->z_os, sa_obj,
-                   zfs_attr_table,  ZPL_END, &zfsvfs->z_attr_table)) != 0)
+               if ((err = sa_setup(zsb->z_os, sa_obj,
+                   zfs_attr_table,  ZPL_END, &zsb->z_attr_table)) != 0)
                        goto bail;
 
-               VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0);
+               VERIFY(zfs_sb_setup(zsb, B_FALSE) == 0);
 
                /*
                 * Attempt to re-establish all the active znodes with
@@ -2045,141 +1433,51 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname)
                 * any potential callers discover that via ZFS_ENTER_VERIFY_VP
                 * when they try to use their znode.
                 */
-               mutex_enter(&zfsvfs->z_znodes_lock);
-               for (zp = list_head(&zfsvfs->z_all_znodes); zp;
-                   zp = list_next(&zfsvfs->z_all_znodes, zp)) {
+               mutex_enter(&zsb->z_znodes_lock);
+               for (zp = list_head(&zsb->z_all_znodes); zp;
+                   zp = list_next(&zsb->z_all_znodes, zp)) {
                        (void) zfs_rezget(zp);
                }
-               mutex_exit(&zfsvfs->z_znodes_lock);
+               mutex_exit(&zsb->z_znodes_lock);
 
        }
 
 bail:
        /* release the VOPs */
-       rw_exit(&zfsvfs->z_teardown_inactive_lock);
-       rrw_exit(&zfsvfs->z_teardown_lock, FTAG);
+       rw_exit(&zsb->z_teardown_inactive_lock);
+       rrw_exit(&zsb->z_teardown_lock, FTAG);
 
        if (err) {
                /*
-                * Since we couldn't reopen zfsvfs::z_os, force
+                * Since we couldn't reopen zfs_sb_t::z_os, force
                 * unmount this file system.
                 */
-               if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0)
-                       (void) dounmount(zfsvfs->z_vfs, MS_FORCE, CRED());
+               (void) zfs_umount(zsb->z_sb);
        }
        return (err);
 }
+EXPORT_SYMBOL(zfs_resume_fs);
 
-static void
-zfs_freevfs(vfs_t *vfsp)
-{
-       zfsvfs_t *zfsvfs = vfsp->vfs_data;
-
-       /*
-        * If this is a snapshot, we have an extra VFS_HOLD on our parent
-        * from zfs_mount().  Release it here.  If we came through
-        * zfs_mountroot() instead, we didn't grab an extra hold, so
-        * skip the VFS_RELE for rootvfs.
-        */
-       if (zfsvfs->z_issnap && (vfsp != rootvfs))
-               VFS_RELE(zfsvfs->z_parent->z_vfs);
-
-       zfsvfs_free(zfsvfs);
-
-       atomic_add_32(&zfs_active_fs_count, -1);
-}
-
-/*
- * VFS_INIT() initialization.  Note that there is no VFS_FINI(),
- * so we can't safely do any non-idempotent initialization here.
- * Leave that to zfs_init() and zfs_fini(), which are called
- * from the module's _init() and _fini() entry points.
- */
-/*ARGSUSED*/
-static int
-zfs_vfsinit(int fstype, char *name)
-{
-       int error;
-
-       zfsfstype = fstype;
-
-       /*
-        * Setup vfsops and vnodeops tables.
-        */
-       error = vfs_setfsops(fstype, zfs_vfsops_template, &zfs_vfsops);
-       if (error != 0) {
-               cmn_err(CE_WARN, "zfs: bad vfs ops template");
-       }
-
-       error = zfs_create_op_tables();
-       if (error) {
-               zfs_remove_op_tables();
-               cmn_err(CE_WARN, "zfs: bad vnode ops template");
-               (void) vfs_freevfsops_by_type(zfsfstype);
-               return (error);
-       }
-
-       mutex_init(&zfs_dev_mtx, NULL, MUTEX_DEFAULT, NULL);
-
-       /*
-        * Unique major number for all zfs mounts.
-        * If we run out of 32-bit minors, we'll getudev() another major.
-        */
-       zfs_major = ddi_name_to_major(ZFS_DRIVER);
-       zfs_minor = ZFS_MIN_MINOR;
-
-       return (0);
-}
-#endif /* HAVE_ZPL */
-
-void
-zfs_init(void)
-{
-#ifdef HAVE_ZPL
-       /*
-        * Initialize .zfs directory structures
-        */
-       zfsctl_init();
-
-       /*
-        * Initialize znode cache, vnode ops, etc...
-        */
-       zfs_znode_init();
-#endif /* HAVE_ZPL */
-
-       dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
-}
-
-void
-zfs_fini(void)
-{
-#ifdef HAVE_ZPL
-       zfsctl_fini();
-       zfs_znode_fini();
-#endif /* HAVE_ZPL */
-}
-
-#ifdef HAVE_ZPL
 int
-zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
+zfs_set_version(zfs_sb_t *zsb, uint64_t newvers)
 {
        int error;
-       objset_t *os = zfsvfs->z_os;
+       objset_t *os = zsb->z_os;
        dmu_tx_t *tx;
 
        if (newvers < ZPL_VERSION_INITIAL || newvers > ZPL_VERSION)
                return (EINVAL);
 
-       if (newvers < zfsvfs->z_version)
+       if (newvers < zsb->z_version)
                return (EINVAL);
 
        if (zfs_spa_version_map(newvers) >
-           spa_version(dmu_objset_spa(zfsvfs->z_os)))
+           spa_version(dmu_objset_spa(zsb->z_os)))
                return (ENOTSUP);
 
        tx = dmu_tx_create(os);
        dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_FALSE, ZPL_VERSION_STR);
-       if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) {
+       if (newvers >= ZPL_VERSION_SA && !zsb->z_use_sa) {
                dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE,
                    ZFS_SA_ATTRS);
                dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
@@ -2198,10 +1496,10 @@ zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
                return (error);
        }
 
-       if (newvers >= ZPL_VERSION_SA && !zfsvfs->z_use_sa) {
+       if (newvers >= ZPL_VERSION_SA && !zsb->z_use_sa) {
                uint64_t sa_obj;
 
-               ASSERT3U(spa_version(dmu_objset_spa(zfsvfs->z_os)), >=,
+               ASSERT3U(spa_version(dmu_objset_spa(zsb->z_os)), >=,
                    SPA_VERSION_SA);
                sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE,
                    DMU_OT_NONE, 0, tx);
@@ -2216,18 +1514,18 @@ zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
 
        spa_history_log_internal(LOG_DS_UPGRADE,
            dmu_objset_spa(os), tx, "oldver=%llu newver=%llu dataset = %llu",
-           zfsvfs->z_version, newvers, dmu_objset_id(os));
+           zsb->z_version, newvers, dmu_objset_id(os));
 
        dmu_tx_commit(tx);
 
-       zfsvfs->z_version = newvers;
+       zsb->z_version = newvers;
 
-       if (zfsvfs->z_version >= ZPL_VERSION_FUID)
-               zfs_set_fuid_feature(zfsvfs);
+       if (zsb->z_version >= ZPL_VERSION_FUID)
+               zfs_set_fuid_feature(zsb);
 
        return (0);
 }
-#endif /* HAVE_ZPL */
+EXPORT_SYMBOL(zfs_set_version);
 
 /*
  * Read a property stored within the master node.
@@ -2271,17 +1569,17 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
        return (error);
 }
 
-#ifdef HAVE_ZPL
-static vfsdef_t vfw = {
-       VFSDEF_VERSION,
-       MNTTYPE_ZFS,
-       zfs_vfsinit,
-       VSW_HASPROTO|VSW_CANRWRO|VSW_CANREMOUNT|VSW_VOLATILEDEV|VSW_STATS|
-           VSW_XID|VSW_ZMOUNT,
-       &zfs_mntopts
-};
-
-struct modlfs zfs_modlfs = {
-       &mod_fsops, "ZFS filesystem version " SPA_VERSION_STRING, &vfw
-};
-#endif /* HAVE_ZPL */
+void
+zfs_init(void)
+{
+       zfs_znode_init();
+       dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
+       register_filesystem(&zpl_fs_type);
+}
+
+void
+zfs_fini(void)
+{
+       unregister_filesystem(&zpl_fs_type);
+       zfs_znode_fini();
+}
index 5899c7f..b20e3b2 100644 (file)
@@ -25,7 +25,6 @@
 /* Portions Copyright 2007 Jeremy Teo */
 /* Portions Copyright 2010 Robert Milkowski */
 
-#ifdef HAVE_ZPL
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -35,7 +34,6 @@
 #include <sys/resource.h>
 #include <sys/vfs.h>
 #include <sys/vfs_opreg.h>
-#include <sys/vnode.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/kmem.h>
 #include <sys/uio.h>
 #include <sys/vmsystm.h>
 #include <sys/atomic.h>
-#include <sys/vm.h>
-#include <vm/seg_vn.h>
 #include <vm/pvn.h>
-#include <vm/as.h>
-#include <vm/kpm.h>
-#include <vm/seg_kpm.h>
-#include <sys/mman.h>
 #include <sys/pathname.h>
 #include <sys/cmn_err.h>
 #include <sys/errno.h>
 #include <sys/dirent.h>
 #include <sys/policy.h>
 #include <sys/sunddi.h>
-#include <sys/filio.h>
 #include <sys/sid.h>
+#include <sys/mode.h>
 #include "fs/fs_subr.h"
-#include <sys/zfs_ctldir.h>
 #include <sys/zfs_fuid.h>
 #include <sys/zfs_sa.h>
+#include <sys/zfs_vnops.h>
 #include <sys/dnlc.h>
 #include <sys/zfs_rlock.h>
 #include <sys/extdirent.h>
  * to freed memory.  The example below illustrates the following Big Rules:
  *
  *  (1) A check must be made in each zfs thread for a mounted file system.
- *     This is done avoiding races using ZFS_ENTER(zfsvfs).
- *      A ZFS_EXIT(zfsvfs) is needed before all returns.  Any znodes
+ *     This is done avoiding races using ZFS_ENTER(zsb).
+ *      A ZFS_EXIT(zsb) is needed before all returns.  Any znodes
  *      must be checked with ZFS_VERIFY_ZP(zp).  Both of these macros
  *      can return EIO from the calling function.
  *
- *  (2)        VN_RELE() should always be the last thing except for zil_commit()
+ *  (2)        iput() should always be the last thing except for zil_commit()
  *     (if necessary) and ZFS_EXIT(). This is for 3 reasons:
  *     First, if it's the last reference, the vnode/znode
  *     can be freed, so the zp may point to freed memory.  Second, the last
  *     pushing cached pages (which acquires range locks) and syncing out
  *     cached atime changes.  Third, zfs_zinactive() may require a new tx,
  *     which could deadlock the system if you were already holding one.
- *     If you must call VN_RELE() within a tx then use VN_RELE_ASYNC().
+ *     If you must call iput() within a tx then use iput_ASYNC().
  *
  *  (3)        All range locks must be grabbed before calling dmu_tx_assign(),
  *     as they can span dmu_tx_assign() calls.
  *     Thread A calls dmu_tx_assign(TXG_WAIT) and blocks in txg_wait_open()
  *     forever, because the previous txg can't quiesce until B's tx commits.
  *
- *     If dmu_tx_assign() returns ERESTART and zfsvfs->z_assign is TXG_NOWAIT,
+ *     If dmu_tx_assign() returns ERESTART and zsb->z_assign is TXG_NOWAIT,
  *     then drop all locks, call dmu_tx_wait(), and try again.
  *
  *  (5)        If the operation succeeded, generate the intent log entry for it
  *
  * In general, this is how things should be ordered in each vnode op:
  *
- *     ZFS_ENTER(zfsvfs);              // exit if unmounted
+ *     ZFS_ENTER(zsb);         // exit if unmounted
  * top:
- *     zfs_dirent_lock(&dl, ...)       // lock directory entry (may VN_HOLD())
+ *     zfs_dirent_lock(&dl, ...)       // lock directory entry (may igrab())
  *     rw_enter(...);                  // grab any other locks you need
  *     tx = dmu_tx_create(...);        // get DMU tx
  *     dmu_tx_hold_*();                // hold each object you might modify
  *     if (error) {
  *             rw_exit(...);           // drop locks
  *             zfs_dirent_unlock(dl);  // unlock directory entry
- *             VN_RELE(...);           // release held vnodes
+ *             iput(...);              // release held vnodes
  *             if (error == ERESTART) {
  *                     dmu_tx_wait(tx);
  *                     dmu_tx_abort(tx);
  *                     goto top;
  *             }
  *             dmu_tx_abort(tx);       // abort DMU tx
- *             ZFS_EXIT(zfsvfs);       // finished in zfs
+ *             ZFS_EXIT(zsb);  // finished in zfs
  *             return (error);         // really out of space
  *     }
  *     error = do_real_work();         // do whatever this VOP does
  *     dmu_tx_commit(tx);              // commit DMU tx -- error or not
  *     rw_exit(...);                   // drop locks
  *     zfs_dirent_unlock(dl);          // unlock directory entry
- *     VN_RELE(...);                   // release held vnodes
+ *     iput(...);                      // release held vnodes
  *     zil_commit(zilog, foid);        // synchronous when necessary
- *     ZFS_EXIT(zfsvfs);               // finished in zfs
+ *     ZFS_EXIT(zsb);          // finished in zfs
  *     return (error);                 // done, report error
  */
 
-/* ARGSUSED */
-static int
-zfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
-{
-       znode_t *zp = VTOZ(*vpp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-
-       ZFS_ENTER(zfsvfs);
-       ZFS_VERIFY_ZP(zp);
-
-       if ((flag & FWRITE) && (zp->z_pflags & ZFS_APPENDONLY) &&
-           ((flag & FAPPEND) == 0)) {
-               ZFS_EXIT(zfsvfs);
-               return (EPERM);
-       }
-
-       if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan &&
-           ZTOV(zp)->v_type == VREG &&
-           !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0) {
-               if (fs_vscan(*vpp, cr, 0) != 0) {
-                       ZFS_EXIT(zfsvfs);
-                       return (EACCES);
-               }
-       }
-
-       /* Keep a count of the synchronous opens in the znode */
-       if (flag & (FSYNC | FDSYNC))
-               atomic_inc_32(&zp->z_sync_cnt);
-
-       ZFS_EXIT(zfsvfs);
-       return (0);
-}
-
-/* ARGSUSED */
-static int
-zfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr,
-    caller_context_t *ct)
-{
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-
-       /*
-        * Clean up any locks held by this process on the vp.
-        */
-       cleanlocks(vp, ddi_get_pid(), 0);
-       cleanshares(vp, ddi_get_pid());
-
-       ZFS_ENTER(zfsvfs);
-       ZFS_VERIFY_ZP(zp);
-
-       /* Decrement the synchronous opens in the znode */
-       if ((flag & (FSYNC | FDSYNC)) && (count == 1))
-               atomic_dec_32(&zp->z_sync_cnt);
-
-       if (!zfs_has_ctldir(zp) && zp->z_zfsvfs->z_vscan &&
-           ZTOV(zp)->v_type == VREG &&
-           !(zp->z_pflags & ZFS_AV_QUARANTINED) && zp->z_size > 0)
-               VERIFY(fs_vscan(vp, cr, 1) == 0);
-
-       ZFS_EXIT(zfsvfs);
-       return (0);
-}
-
-/*
- * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and
- * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter.
- */
-static int
-zfs_holey(vnode_t *vp, int cmd, offset_t *off)
-{
-       znode_t *zp = VTOZ(vp);
-       uint64_t noff = (uint64_t)*off; /* new offset */
-       uint64_t file_sz;
-       int error;
-       boolean_t hole;
-
-       file_sz = zp->z_size;
-       if (noff >= file_sz)  {
-               return (ENXIO);
-       }
-
-       if (cmd == _FIO_SEEK_HOLE)
-               hole = B_TRUE;
-       else
-               hole = B_FALSE;
-
-       error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff);
-
-       /* end of file? */
-       if ((error == ESRCH) || (noff > file_sz)) {
-               /*
-                * Handle the virtual hole at the end of file.
-                */
-               if (hole) {
-                       *off = file_sz;
-                       return (0);
-               }
-               return (ENXIO);
-       }
-
-       if (noff < *off)
-               return (error);
-       *off = noff;
-       return (error);
-}
-
-/* ARGSUSED */
-static int
-zfs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred,
-    int *rvalp, caller_context_t *ct)
-{
-       offset_t off;
-       int error;
-       zfsvfs_t *zfsvfs;
-       znode_t *zp;
-
-       switch (com) {
-       case _FIOFFS:
-               return (zfs_sync(vp->v_vfsp, 0, cred));
-
-               /*
-                * The following two ioctls are used by bfu.  Faking out,
-                * necessary to avoid bfu errors.
-                */
-       case _FIOGDIO:
-       case _FIOSDIO:
-               return (0);
-
-       case _FIO_SEEK_DATA:
-       case _FIO_SEEK_HOLE:
-               if (ddi_copyin((void *)data, &off, sizeof (off), flag))
-                       return (EFAULT);
-
-               zp = VTOZ(vp);
-               zfsvfs = zp->z_zfsvfs;
-               ZFS_ENTER(zfsvfs);
-               ZFS_VERIFY_ZP(zp);
-
-               /* offset parameter is in/out */
-               error = zfs_holey(vp, com, &off);
-               ZFS_EXIT(zfsvfs);
-               if (error)
-                       return (error);
-               if (ddi_copyout(&off, (void *)data, sizeof (off), flag))
-                       return (EFAULT);
-               return (0);
-       }
-       return (ENOTTY);
-}
-
-#if defined(_KERNEL) && defined(HAVE_UIO_RW)
-/*
- * Utility functions to map and unmap a single physical page.  These
- * are used to manage the mappable copies of ZFS file data, and therefore
- * do not update ref/mod bits.
- */
-caddr_t
-zfs_map_page(page_t *pp, enum seg_rw rw)
-{
-       if (kpm_enable)
-               return (hat_kpm_mapin(pp, 0));
-       ASSERT(rw == S_READ || rw == S_WRITE);
-       return (ppmapin(pp, PROT_READ | ((rw == S_WRITE) ? PROT_WRITE : 0),
-           (caddr_t)-1));
-}
-
-void
-zfs_unmap_page(page_t *pp, caddr_t addr)
-{
-       if (kpm_enable) {
-               hat_kpm_mapout(pp, 0, addr);
-       } else {
-               ppmapout(addr);
-       }
-}
-#endif /* _KERNEL && HAVE_UIO_RW */
-
+#if defined(_KERNEL)
 /*
  * When a file is memory mapped, we must keep the IO data synchronized
  * between the DMU cache and the memory mapped pages.  What this means:
@@ -356,24 +172,39 @@ zfs_unmap_page(page_t *pp, caddr_t addr)
  *             the page and the dmu buffer.
  */
 static void
-update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid)
+update_pages(struct inode *ip, int64_t start, int len,
+    objset_t *os, uint64_t oid)
 {
+       struct address_space *mp = ip->i_mapping;
+       struct page *pp;
+       uint64_t nbytes;
        int64_t off;
+       void *pb;
 
-       off = start & PAGEOFFSET;
-       for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
-               page_t *pp;
-               uint64_t nbytes = MIN(PAGESIZE - off, len);
+       off = start & (PAGE_CACHE_SIZE-1);
+       for (start &= PAGE_CACHE_MASK; len > 0; start += PAGE_CACHE_SIZE) {
+               nbytes = MIN(PAGE_CACHE_SIZE - off, len);
 
-               if (pp = page_lookup(vp, start, SE_SHARED)) {
-                       caddr_t va;
+               pp = find_lock_page(mp, start >> PAGE_CACHE_SHIFT);
+               if (pp) {
+                       if (mapping_writably_mapped(mp))
+                               flush_dcache_page(pp);
 
-                       va = zfs_map_page(pp, S_WRITE);
-                       (void) dmu_read(os, oid, start+off, nbytes, va+off,
+                       pb = kmap(pp);
+                       (void) dmu_read(os, oid, start+off, nbytes, pb+off,
                            DMU_READ_PREFETCH);
-                       zfs_unmap_page(pp, va);
-                       page_unlock(pp);
+                       kunmap(pp);
+
+                       if (mapping_writably_mapped(mp))
+                               flush_dcache_page(pp);
+
+                       mark_page_accessed(pp);
+                       SetPageUptodate(pp);
+                       ClearPageError(pp);
+                       unlock_page(pp);
+                       page_cache_release(pp);
                }
+
                len -= nbytes;
                off = 0;
        }
@@ -390,30 +221,41 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid)
  *     the file is memory mapped.
  */
 static int
-mappedread(vnode_t *vp, int nbytes, uio_t *uio)
+mappedread(struct inode *ip, int nbytes, uio_t *uio)
 {
-       znode_t *zp = VTOZ(vp);
-       objset_t *os = zp->z_zfsvfs->z_os;
+       struct address_space *mp = ip->i_mapping;
+       struct page *pp;
+       znode_t *zp = ITOZ(ip);
+       objset_t *os = ITOZSB(ip)->z_os;
        int64_t start, off;
+       uint64_t bytes;
        int len = nbytes;
        int error = 0;
+       void *pb;
 
        start = uio->uio_loffset;
-       off = start & PAGEOFFSET;
-       for (start &= PAGEMASK; len > 0; start += PAGESIZE) {
-               page_t *pp;
-               uint64_t bytes = MIN(PAGESIZE - off, len);
-
-               if (pp = page_lookup(vp, start, SE_SHARED)) {
-                       caddr_t va;
-
-                       va = zfs_map_page(pp, S_READ);
-                       error = uiomove(va + off, bytes, UIO_READ, uio);
-                       zfs_unmap_page(pp, va);
-                       page_unlock(pp);
+       off = start & (PAGE_CACHE_SIZE-1);
+       for (start &= PAGE_CACHE_MASK; len > 0; start += PAGE_CACHE_SIZE) {
+               bytes = MIN(PAGE_CACHE_SIZE - off, len);
+
+               pp = find_lock_page(mp, start >> PAGE_CACHE_SHIFT);
+               if (pp) {
+                       ASSERT(PageUptodate(pp));
+
+                       pb = kmap(pp);
+                       error = uiomove(pb + off, bytes, UIO_READ, uio);
+                       kunmap(pp);
+
+                       if (mapping_writably_mapped(mp))
+                               flush_dcache_page(pp);
+
+                       mark_page_accessed(pp);
+                       unlock_page(pp);
+                       page_cache_release(pp);
                } else {
                        error = dmu_read_uio(os, zp->z_id, uio, bytes);
                }
+
                len -= bytes;
                off = 0;
                if (error)
@@ -421,18 +263,19 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
        }
        return (error);
 }
+#endif /* _KERNEL */
 
 offset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */
 
 /*
  * Read bytes from specified file into supplied buffer.
  *
- *     IN:     vp      - vnode of file to be read from.
+ *     IN:     ip      - inode of file to be read from.
  *             uio     - structure supplying read location, range info,
  *                       and return buffer.
- *             ioflag  - SYNC flags; used to provide FRSYNC semantics.
+ *             ioflag  - FSYNC flags; used to provide FRSYNC semantics.
+ *                       O_DIRECT flag; used to bypass page cache.
  *             cr      - credentials of caller.
- *             ct      - caller context
  *
  *     OUT:    uio     - updated offset and range, buffer filled.
  *
@@ -440,26 +283,28 @@ offset_t zfs_read_chunk_size = 1024 * 1024; /* Tunable */
  *             error code if failure
  *
  * Side Effects:
- *     vp - atime updated if byte count > 0
+ *     inode - atime updated if byte count > 0
  */
 /* ARGSUSED */
-static int
-zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
+int
+zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
 {
-       znode_t         *zp = VTOZ(vp);
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
        objset_t        *os;
        ssize_t         n, nbytes;
-       int             error;
+       int             error = 0;
        rl_t            *rl;
+#ifdef HAVE_UIO_ZEROCOPY
        xuio_t          *xuio = NULL;
+#endif /* HAVE_UIO_ZEROCOPY */
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
-       os = zfsvfs->z_os;
+       os = zsb->z_os;
 
        if (zp->z_pflags & ZFS_AV_QUARANTINED) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EACCES);
        }
 
@@ -467,7 +312,7 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
         * Validate file offset
         */
        if (uio->uio_loffset < (offset_t)0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
@@ -475,26 +320,28 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
         * Fasttrack empty reads
         */
        if (uio->uio_resid == 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (0);
        }
 
+#ifdef HAVE_MANDLOCKS
        /*
         * Check for mandatory locks
         */
        if (MANDMODE(zp->z_mode)) {
-               if (error = chklock(vp, FREAD,
+               if (error = chklock(ip, FREAD,
                    uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct)) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
+#endif /* HAVE_MANDLOCK */
 
        /*
         * If we're in FRSYNC mode, sync out this znode before reading it.
         */
-       if (ioflag & FRSYNC || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
-               zil_commit(zfsvfs->z_log, zp->z_id);
+       if (ioflag & FRSYNC || zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
+               zil_commit(zsb->z_log, zp->z_id);
 
        /*
         * Lock the range against changes.
@@ -513,6 +360,7 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
        ASSERT(uio->uio_loffset < zp->z_size);
        n = MIN(uio->uio_resid, zp->z_size - uio->uio_loffset);
 
+#ifdef HAVE_UIO_ZEROCOPY
        if ((uio->uio_extflg == UIO_XUIO) &&
            (((xuio_t *)uio)->xu_type == UIOTYPE_ZEROCOPY)) {
                int nblk;
@@ -529,7 +377,7 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
                }
                (void) dmu_xuio_init(xuio, nblk);
 
-               if (vn_has_cached_data(vp)) {
+               if (vn_has_cached_data(ip)) {
                        /*
                         * For simplicity, we always allocate a full buffer
                         * even if we only expect to read a portion of a block.
@@ -541,15 +389,17 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
                        }
                }
        }
+#endif /* HAVE_UIO_ZEROCOPY */
 
        while (n > 0) {
                nbytes = MIN(n, zfs_read_chunk_size -
                    P2PHASE(uio->uio_loffset, zfs_read_chunk_size));
 
-               if (vn_has_cached_data(vp))
-                       error = mappedread(vp, nbytes, uio);
+               if (zp->z_is_mapped && !(ioflag & O_DIRECT))
+                       error = mappedread(ip, nbytes, uio);
                else
                        error = dmu_read_uio(os, zp->z_id, uio, nbytes);
+
                if (error) {
                        /* convert checksum errors into IO errors */
                        if (error == ECKSUM)
@@ -562,20 +412,22 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
 out:
        zfs_range_unlock(rl);
 
-       ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
-       ZFS_EXIT(zfsvfs);
+       ZFS_ACCESSTIME_STAMP(zsb, zp);
+       zfs_inode_update(zp);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_read);
 
 /*
  * Write the bytes to a file.
  *
- *     IN:     vp      - vnode of file to be written to.
+ *     IN:     ip      - inode of file to be written to.
  *             uio     - structure supplying write location, range info,
  *                       and data buffer.
  *             ioflag  - FAPPEND flag set if in append mode.
+ *                       O_DIRECT flag; used to bypass page cache.
  *             cr      - credentials of caller.
- *             ct      - caller context (NFS/CIFS fem monitor only)
  *
  *     OUT:    uio     - updated offset and range.
  *
@@ -583,36 +435,36 @@ out:
  *             error code if failure
  *
  * Timestamps:
- *     vp - ctime|mtime updated if byte count > 0
+ *     ip - ctime|mtime updated if byte count > 0
  */
 
 /* ARGSUSED */
-static int
-zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
+int
+zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
 {
-       znode_t         *zp = VTOZ(vp);
-       rlim64_t        limit = uio->uio_llimit;
+       znode_t         *zp = ITOZ(ip);
+       rlim64_t        limit = uio->uio_limit;
        ssize_t         start_resid = uio->uio_resid;
        ssize_t         tx_bytes;
        uint64_t        end_size;
        dmu_tx_t        *tx;
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(zp);
        zilog_t         *zilog;
        offset_t        woff;
        ssize_t         n, nbytes;
        rl_t            *rl;
-       int             max_blksz = zfsvfs->z_max_blksz;
-       int             error;
+       int             max_blksz = zsb->z_max_blksz;
+       int             error = 0;
        arc_buf_t       *abuf;
-       iovec_t         *aiov;
+       iovec_t         *aiov = NULL;
        xuio_t          *xuio = NULL;
        int             i_iov = 0;
-       int             iovcnt = uio->uio_iovcnt;
        iovec_t         *iovp = uio->uio_iov;
        int             write_eof;
        int             count = 0;
        sa_bulk_attr_t  bulk[4];
        uint64_t        mtime[2], ctime[2];
+       ASSERTV(int     iovcnt = uio->uio_iovcnt);
 
        /*
         * Fasttrack empty write
@@ -624,14 +476,13 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
        if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
                limit = MAXOFFSET_T;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
-           &zp->z_size, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL, &mtime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL, &ctime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb), NULL, &zp->z_size, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, 8);
 
        /*
@@ -640,31 +491,34 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
        if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) ||
            ((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & FAPPEND) &&
            (uio->uio_loffset < zp->z_size))) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EPERM);
        }
 
-       zilog = zfsvfs->z_log;
+       zilog = zsb->z_log;
 
        /*
         * Validate file offset
         */
        woff = ioflag & FAPPEND ? zp->z_size : uio->uio_loffset;
        if (woff < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
+#ifdef HAVE_MANDLOCKS
        /*
         * Check for mandatory locks before calling zfs_range_lock()
         * in order to prevent a deadlock with locks set via fcntl().
         */
        if (MANDMODE((mode_t)zp->z_mode) &&
-           (error = chklock(vp, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) {
-               ZFS_EXIT(zfsvfs);
+           (error = chklock(ip, FWRITE, woff, n, uio->uio_fmode, ct)) != 0) {
+               ZFS_EXIT(zsb);
                return (error);
        }
+#endif /* HAVE_MANDLOCKS */
 
+#ifdef HAVE_UIO_ZEROCOPY
        /*
         * Pre-fault the pages to ensure slow (eg NFS) pages
         * don't hold up txg.
@@ -675,6 +529,7 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
                xuio = (xuio_t *)uio;
        else
                uio_prefaultpages(MIN(n, max_blksz), uio);
+#endif /* HAVE_UIO_ZEROCOPY */
 
        /*
         * If in append mode, set the io offset pointer to eof.
@@ -706,7 +561,7 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
 
        if (woff >= limit) {
                zfs_range_unlock(rl);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EFBIG);
        }
 
@@ -727,8 +582,8 @@ zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
                abuf = NULL;
                woff = uio->uio_loffset;
 again:
-               if (zfs_owner_overquota(zfsvfs, zp, B_FALSE) ||
-                   zfs_owner_overquota(zfsvfs, zp, B_TRUE)) {
+               if (zfs_owner_overquota(zsb, zp, B_FALSE) ||
+                   zfs_owner_overquota(zsb, zp, B_TRUE)) {
                        if (abuf != NULL)
                                dmu_return_arcbuf(abuf);
                        error = EDQUOT;
@@ -740,8 +595,6 @@ again:
                        aiov = &iovp[i_iov];
                        abuf = dmu_xuio_arcbuf(xuio, i_iov);
                        dmu_xuio_clear(xuio, i_iov);
-                       DTRACE_PROBE3(zfs_cp_write, int, i_iov,
-                           iovec_t *, aiov, arc_buf_t *, abuf);
                        ASSERT((aiov->iov_base == abuf->b_data) ||
                            ((char *)aiov->iov_base - (char *)abuf->b_data +
                            aiov->iov_len == arc_buf_size(abuf)));
@@ -763,8 +616,8 @@ again:
                            max_blksz);
                        ASSERT(abuf != NULL);
                        ASSERT(arc_buf_size(abuf) == max_blksz);
-                       if (error = uiocopy(abuf->b_data, max_blksz,
-                           UIO_WRITE, uio, &cbytes)) {
+                       if ((error = uiocopy(abuf->b_data, max_blksz,
+                           UIO_WRITE, uio, &cbytes))) {
                                dmu_return_arcbuf(abuf);
                                break;
                        }
@@ -774,7 +627,7 @@ again:
                /*
                 * Start a transaction.
                 */
-               tx = dmu_tx_create(zfsvfs->z_os);
+               tx = dmu_tx_create(zsb->z_os);
                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
                dmu_tx_hold_write(tx, zp->z_id, woff, MIN(n, max_blksz));
                zfs_sa_upgrade_txholds(tx, zp);
@@ -833,7 +686,7 @@ again:
                        if (tx_bytes < max_blksz && (!write_eof ||
                            aiov->iov_base != abuf->b_data)) {
                                ASSERT(xuio);
-                               dmu_write(zfsvfs->z_os, zp->z_id, woff,
+                               dmu_write(zsb->z_os, zp->z_id, woff,
                                    aiov->iov_len, aiov->iov_base, tx);
                                dmu_return_arcbuf(abuf);
                                xuio_stat_wbuf_copied();
@@ -845,17 +698,16 @@ again:
                        ASSERT(tx_bytes <= uio->uio_resid);
                        uioskip(uio, tx_bytes);
                }
-               if (tx_bytes && vn_has_cached_data(vp)) {
-                       update_pages(vp, woff,
-                           tx_bytes, zfsvfs->z_os, zp->z_id);
-               }
+
+               if (tx_bytes && zp->z_is_mapped && !(ioflag & O_DIRECT))
+                       update_pages(ip, woff, tx_bytes, zsb->z_os, zp->z_id);
 
                /*
                 * If we made no progress, we're done.  If we made even
                 * partial progress, update the znode and ZIL accordingly.
                 */
                if (tx_bytes == 0) {
-                       (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs),
+                       (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zsb),
                            (void *)&zp->z_size, sizeof (uint64_t), tx);
                        dmu_tx_commit(tx);
                        ASSERT(error != 0);
@@ -882,7 +734,7 @@ again:
                        uint64_t newmode;
                        zp->z_mode &= ~(S_ISUID | S_ISGID);
                        newmode = zp->z_mode;
-                       (void) sa_update(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs),
+                       (void) sa_update(zp->z_sa_hdl, SA_ZPL_MODE(zsb),
                            (void *)&newmode, sizeof (uint64_t), tx);
                }
                mutex_exit(&zp->z_acl_lock);
@@ -904,8 +756,8 @@ again:
                 * the file size to the specified eof. Note, there's no
                 * concurrency during replay.
                 */
-               if (zfsvfs->z_replay && zfsvfs->z_replay_eof != 0)
-                       zp->z_size = zfsvfs->z_replay_eof;
+               if (zsb->z_replay && zsb->z_replay_eof != 0)
+                       zp->z_size = zsb->z_replay_eof;
 
                error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
 
@@ -927,24 +779,36 @@ again:
         * If we're in replay mode, or we made no progress, return error.
         * Otherwise, it's at least a partial write, so it's successful.
         */
-       if (zfsvfs->z_replay || uio->uio_resid == start_resid) {
-               ZFS_EXIT(zfsvfs);
+       if (zsb->z_replay || uio->uio_resid == start_resid) {
+               ZFS_EXIT(zsb);
                return (error);
        }
 
        if (ioflag & (FSYNC | FDSYNC) ||
-           zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+           zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, zp->z_id);
 
-       ZFS_EXIT(zfsvfs);
+       zfs_inode_update(zp);
+       ZFS_EXIT(zsb);
        return (0);
 }
+EXPORT_SYMBOL(zfs_write);
+
+static void
+iput_async(struct inode *ip, taskq_t *taskq)
+{
+       ASSERT(atomic_read(&ip->i_count) > 0);
+       if (atomic_read(&ip->i_count) == 1)
+               taskq_dispatch(taskq, (task_func_t *)iput, ip, TQ_SLEEP);
+       else
+               iput(ip);
+}
 
 void
 zfs_get_done(zgd_t *zgd, int error)
 {
        znode_t *zp = zgd->zgd_private;
-       objset_t *os = zp->z_zfsvfs->z_os;
+       objset_t *os = ZTOZSB(zp)->z_os;
 
        if (zgd->zgd_db)
                dmu_buf_rele(zgd->zgd_db, zgd);
@@ -955,7 +819,7 @@ zfs_get_done(zgd_t *zgd, int error)
         * Release the vnode asynchronously as we currently have the
         * txg stopped from syncing.
         */
-       VN_RELE_ASYNC(ZTOV(zp), dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
+       iput_async(ZTOI(zp), dsl_pool_iput_taskq(dmu_objset_pool(os)));
 
        if (error == 0 && zgd->zgd_bp)
                zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
@@ -973,8 +837,8 @@ static int zil_fault_io = 0;
 int
 zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
 {
-       zfsvfs_t *zfsvfs = arg;
-       objset_t *os = zfsvfs->z_os;
+       zfs_sb_t *zsb = arg;
+       objset_t *os = zsb->z_os;
        znode_t *zp;
        uint64_t object = lr->lr_foid;
        uint64_t offset = lr->lr_offset;
@@ -990,20 +854,19 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
        /*
         * Nothing to do if the file has been removed
         */
-       if (zfs_zget(zfsvfs, object, &zp) != 0)
+       if (zfs_zget(zsb, object, &zp) != 0)
                return (ENOENT);
        if (zp->z_unlinked) {
                /*
                 * Release the vnode asynchronously as we currently have the
                 * txg stopped from syncing.
                 */
-               VN_RELE_ASYNC(ZTOV(zp),
-                   dsl_pool_vnrele_taskq(dmu_objset_pool(os)));
+               iput_async(ZTOI(zp), dsl_pool_iput_taskq(dmu_objset_pool(os)));
                return (ENOENT);
        }
 
        zgd = (zgd_t *)kmem_zalloc(sizeof (zgd_t), KM_SLEEP);
-       zgd->zgd_zilog = zfsvfs->z_log;
+       zgd->zgd_zilog = zsb->z_log;
        zgd->zgd_private = zp;
 
        /*
@@ -1088,15 +951,14 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
 }
 
 /*ARGSUSED*/
-static int
-zfs_access(vnode_t *vp, int mode, int flag, cred_t *cr,
-    caller_context_t *ct)
+int
+zfs_access(struct inode *ip, int mode, int flag, cred_t *cr)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
        int error;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
        if (flag & V_ACE_MASK)
@@ -1104,46 +966,23 @@ zfs_access(vnode_t *vp, int mode, int flag, cred_t *cr,
        else
                error = zfs_zaccess_rwx(zp, mode, flag, cr);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
-
-/*
- * If vnode is for a device return a specfs vnode instead.
- */
-static int
-specvp_check(vnode_t **vpp, cred_t *cr)
-{
-       int error = 0;
-
-       if (IS_DEVVP(*vpp)) {
-               struct vnode *svp;
-
-               svp = specvp(*vpp, (*vpp)->v_rdev, (*vpp)->v_type, cr);
-               VN_RELE(*vpp);
-               if (svp == NULL)
-                       error = ENOSYS;
-               *vpp = svp;
-       }
-       return (error);
-}
-
+EXPORT_SYMBOL(zfs_access);
 
 /*
  * Lookup an entry in a directory, or an extended attribute directory.
- * If it exists, return a held vnode reference for it.
+ * If it exists, return a held inode reference for it.
  *
- *     IN:     dvp     - vnode of directory to search.
+ *     IN:     dip     - inode of directory to search.
  *             nm      - name of entry to lookup.
- *             pnp     - full pathname to lookup [UNUSED].
  *             flags   - LOOKUP_XATTR set if looking for an attribute.
- *             rdir    - root directory vnode [UNUSED].
  *             cr      - credentials of caller.
- *             ct      - caller context
  *             direntflags - directory lookup flags
  *             realpnp - returned pathname.
  *
- *     OUT:    vpp     - vnode of located entry, NULL if not found.
+ *     OUT:    ipp     - inode of located entry, NULL if not found.
  *
  *     RETURN: 0 if success
  *             error code if failure
@@ -1152,19 +991,18 @@ specvp_check(vnode_t **vpp, cred_t *cr)
  *     NA
  */
 /* ARGSUSED */
-static int
-zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
-    int flags, vnode_t *rdir, cred_t *cr,  caller_context_t *ct,
-    int *direntflags, pathname_t *realpnp)
+int
+zfs_lookup(struct inode *dip, char *nm, struct inode **ipp, int flags,
+    cred_t *cr, int *direntflags, pathname_t *realpnp)
 {
-       znode_t *zdp = VTOZ(dvp);
-       zfsvfs_t *zfsvfs = zdp->z_zfsvfs;
-       int     error = 0;
+       znode_t *zdp = ITOZ(dip);
+       zfs_sb_t *zsb = ITOZSB(dip);
+       int error = 0;
 
        /* fast path */
        if (!(flags & (LOOKUP_XATTR | FIGNORECASE))) {
 
-               if (dvp->v_type != VDIR) {
+               if (!S_ISDIR(dip->i_mode)) {
                        return (ENOTDIR);
                } else if (zdp->z_sa_hdl == NULL) {
                        return (EIO);
@@ -1173,44 +1011,44 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
                if (nm[0] == 0 || (nm[0] == '.' && nm[1] == '\0')) {
                        error = zfs_fastaccesschk_execute(zdp, cr);
                        if (!error) {
-                               *vpp = dvp;
-                               VN_HOLD(*vpp);
+                               *ipp = dip;
+                               igrab(*ipp);
                                return (0);
                        }
                        return (error);
+#ifdef HAVE_DNLC
                } else {
                        vnode_t *tvp = dnlc_lookup(dvp, nm);
 
                        if (tvp) {
                                error = zfs_fastaccesschk_execute(zdp, cr);
                                if (error) {
-                                       VN_RELE(tvp);
+                                       iput(tvp);
                                        return (error);
                                }
                                if (tvp == DNLC_NO_VNODE) {
-                                       VN_RELE(tvp);
+                                       iput(tvp);
                                        return (ENOENT);
                                } else {
                                        *vpp = tvp;
                                        return (specvp_check(vpp, cr));
                                }
                        }
+#endif /* HAVE_DNLC */
                }
        }
 
-       DTRACE_PROBE2(zfs__fastpath__lookup__miss, vnode_t *, dvp, char *, nm);
-
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zdp);
 
-       *vpp = NULL;
+       *ipp = NULL;
 
        if (flags & LOOKUP_XATTR) {
                /*
                 * If the xattr property is off, refuse the lookup request.
                 */
-               if (!(zfsvfs->z_vfs->vfs_flag & VFS_XATTR)) {
-                       ZFS_EXIT(zfsvfs);
+               if (!(zsb->z_flags & ZSB_XATTR_USER)) {
+                       ZFS_EXIT(zsb);
                        return (EINVAL);
                }
 
@@ -1219,12 +1057,12 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
                 * Maybe someday we will.
                 */
                if (zdp->z_pflags & ZFS_XATTR) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (EINVAL);
                }
 
-               if (error = zfs_get_xattrdir(VTOZ(dvp), vpp, cr, flags)) {
-                       ZFS_EXIT(zfsvfs);
+               if ((error = zfs_get_xattrdir(zdp, ipp, cr, flags))) {
+                       ZFS_EXIT(zsb);
                        return (error);
                }
 
@@ -1232,18 +1070,18 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
                 * Do we have permission to get into attribute directory?
                 */
 
-               if (error = zfs_zaccess(VTOZ(*vpp), ACE_EXECUTE, 0,
-                   B_FALSE, cr)) {
-                       VN_RELE(*vpp);
-                       *vpp = NULL;
+               if ((error = zfs_zaccess(ITOZ(*ipp), ACE_EXECUTE, 0,
+                   B_FALSE, cr))) {
+                       iput(*ipp);
+                       *ipp = NULL;
                }
 
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       if (dvp->v_type != VDIR) {
-               ZFS_EXIT(zfsvfs);
+       if (!S_ISDIR(dip->i_mode)) {
+               ZFS_EXIT(zsb);
                return (ENOTDIR);
        }
 
@@ -1251,66 +1089,64 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
         * Check accessibility of directory.
         */
 
-       if (error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr)) {
-               ZFS_EXIT(zfsvfs);
+       if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) {
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       if (zfsvfs->z_utf8 && u8_validate(nm, strlen(nm),
+       if (zsb->z_utf8 && u8_validate(nm, strlen(nm),
            NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EILSEQ);
        }
 
-       error = zfs_dirlook(zdp, nm, vpp, flags, direntflags, realpnp);
-       if (error == 0)
-               error = specvp_check(vpp, cr);
+       error = zfs_dirlook(zdp, nm, ipp, flags, direntflags, realpnp);
+       if ((error == 0) && (*ipp))
+               zfs_inode_update(ITOZ(*ipp));
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_lookup);
 
 /*
  * Attempt to create a new entry in a directory.  If the entry
  * already exists, truncate the file if permissible, else return
- * an error.  Return the vp of the created or trunc'd file.
+ * an error.  Return the ip of the created or trunc'd file.
  *
- *     IN:     dvp     - vnode of directory to put new file entry in.
+ *     IN:     dip     - inode of directory to put new file entry in.
  *             name    - name of new file entry.
  *             vap     - attributes of new file.
  *             excl    - flag indicating exclusive or non-exclusive mode.
  *             mode    - mode to open file with.
  *             cr      - credentials of caller.
  *             flag    - large file flag [UNUSED].
- *             ct      - caller context
- *             vsecp   - ACL to be set
+ *             vsecp   - ACL to be set
  *
- *     OUT:    vpp     - vnode of created or trunc'd entry.
+ *     OUT:    ipp     - inode of created or trunc'd entry.
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     dvp - ctime|mtime updated if new entry created
- *      vp - ctime|mtime always, atime if new
+ *     dip - ctime|mtime updated if new entry created
+ *      ip - ctime|mtime always, atime if new
  */
 
 /* ARGSUSED */
-static int
-zfs_create(vnode_t *dvp, char *name, vattr_t *vap, vcexcl_t excl,
-    int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
-    vsecattr_t *vsecp)
+int
+zfs_create(struct inode *dip, char *name, vattr_t *vap, int excl,
+    int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp)
 {
-       znode_t         *zp, *dzp = VTOZ(dvp);
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       znode_t         *zp, *dzp = ITOZ(dip);
+       zfs_sb_t        *zsb = ITOZSB(dip);
        zilog_t         *zilog;
        objset_t        *os;
        zfs_dirlock_t   *dl;
        dmu_tx_t        *tx;
        int             error;
-       ksid_t          *ksid;
        uid_t           uid;
-       gid_t           gid = crgetgid(cr);
+       gid_t           gid;
        zfs_acl_ids_t   acl_ids;
        boolean_t       fuid_dirtied;
        boolean_t       have_acl = B_FALSE;
@@ -1320,51 +1156,46 @@ zfs_create(vnode_t *dvp, char *name, vattr_t *vap, vcexcl_t excl,
         * make sure file system is at proper version
         */
 
-       ksid = crgetsid(cr, KSID_OWNER);
-       if (ksid)
-               uid = ksid_getid(ksid);
-       else
-               uid = crgetuid(cr);
+       gid = crgetgid(cr);
+       uid = crgetuid(cr);
 
-       if (zfsvfs->z_use_fuids == B_FALSE &&
-           (vsecp || (vap->va_mask & AT_XVATTR) ||
-           IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
+       if (zsb->z_use_fuids == B_FALSE &&
+           (vsecp || IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
                return (EINVAL);
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(dzp);
-       os = zfsvfs->z_os;
-       zilog = zfsvfs->z_log;
+       os = zsb->z_os;
+       zilog = zsb->z_log;
 
-       if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
+       if (zsb->z_utf8 && u8_validate(name, strlen(name),
            NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EILSEQ);
        }
 
+#ifdef HAVE_XVATTR
        if (vap->va_mask & AT_XVATTR) {
                if ((error = secpolicy_xvattr((xvattr_t *)vap,
-                   crgetuid(cr), cr, vap->va_type)) != 0) {
-                       ZFS_EXIT(zfsvfs);
+                   crgetuid(cr), cr, vap->va_mode)) != 0) {
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
-top:
-       *vpp = NULL;
-
-       if ((vap->va_mode & VSVTX) && secpolicy_vnode_stky_modify(cr))
-               vap->va_mode &= ~VSVTX;
+#endif /* HAVE_XVATTR */
 
+top:
+       *ipp = NULL;
        if (*name == '\0') {
                /*
                 * Null component name refers to the directory itself.
                 */
-               VN_HOLD(dvp);
+               igrab(dip);
                zp = dzp;
                dl = NULL;
                error = 0;
        } else {
-               /* possible VN_HOLD(zp) */
+               /* possible igrab(zp) */
                int zflg = 0;
 
                if (flag & FIGNORECASE)
@@ -1377,7 +1208,7 @@ top:
                                zfs_acl_ids_free(&acl_ids);
                        if (strcmp(name, "..") == 0)
                                error = EISDIR;
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
@@ -1389,7 +1220,7 @@ top:
                 * Create a new file object and update the directory
                 * to reference it.
                 */
-               if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) {
+               if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
                        if (have_acl)
                                zfs_acl_ids_free(&acl_ids);
                        goto out;
@@ -1400,8 +1231,7 @@ top:
                 * extended attribute directories.
                 */
 
-               if ((dzp->z_pflags & ZFS_XATTR) &&
-                   (vap->va_type != VREG)) {
+               if ((dzp->z_pflags & ZFS_XATTR) && !S_ISREG(vap->va_mode)) {
                        if (have_acl)
                                zfs_acl_ids_free(&acl_ids);
                        error = EINVAL;
@@ -1413,7 +1243,7 @@ top:
                        goto out;
                have_acl = B_TRUE;
 
-               if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+               if (zfs_acl_ids_overquota(zsb, &acl_ids)) {
                        zfs_acl_ids_free(&acl_ids);
                        error = EDQUOT;
                        goto out;
@@ -1424,12 +1254,12 @@ top:
                dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes +
                    ZFS_SA_BASE_ATTR_SIZE);
 
-               fuid_dirtied = zfsvfs->z_fuid_dirty;
+               fuid_dirtied = zsb->z_fuid_dirty;
                if (fuid_dirtied)
-                       zfs_fuid_txhold(zfsvfs, tx);
+                       zfs_fuid_txhold(zsb, tx);
                dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
                dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE);
-               if (!zfsvfs->z_use_sa &&
+               if (!zsb->z_use_sa &&
                    acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
                        dmu_tx_hold_write(tx, DMU_NEW_OBJECT,
                            0, acl_ids.z_aclp->z_acl_bytes);
@@ -1444,13 +1274,13 @@ top:
                        }
                        zfs_acl_ids_free(&acl_ids);
                        dmu_tx_abort(tx);
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
                zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
 
                if (fuid_dirtied)
-                       zfs_fuid_sync(zfsvfs, tx);
+                       zfs_fuid_sync(zsb, tx);
 
                (void) zfs_link_create(dl, zp, tx, ZNEW);
                txtype = zfs_log_create_txtype(Z_FILE, vsecp, vap);
@@ -1473,14 +1303,14 @@ top:
                /*
                 * Can't truncate an existing file if in exclusive mode.
                 */
-               if (excl == EXCL) {
+               if (excl) {
                        error = EEXIST;
                        goto out;
                }
                /*
                 * Can't open a directory for writing.
                 */
-               if ((ZTOV(zp)->v_type == VDIR) && (mode & S_IWRITE)) {
+               if (S_ISDIR(ZTOI(zp)->i_mode)) {
                        error = EISDIR;
                        goto out;
                }
@@ -1498,15 +1328,12 @@ top:
                /*
                 * Truncate regular files if requested.
                 */
-               if ((ZTOV(zp)->v_type == VREG) &&
-                   (vap->va_mask & AT_SIZE) && (vap->va_size == 0)) {
+               if (S_ISREG(ZTOI(zp)->i_mode) &&
+                   (vap->va_mask & ATTR_SIZE) && (vap->va_size == 0)) {
                        /* we can't hold any locks when calling zfs_freesp() */
                        zfs_dirent_unlock(dl);
                        dl = NULL;
                        error = zfs_freesp(zp, 0, 0, mode, TRUE);
-                       if (error == 0) {
-                               vnevent_create(ZTOV(zp), ct);
-                       }
                }
        }
 out:
@@ -1516,70 +1343,72 @@ out:
 
        if (error) {
                if (zp)
-                       VN_RELE(ZTOV(zp));
+                       iput(ZTOI(zp));
        } else {
-               *vpp = ZTOV(zp);
-               error = specvp_check(vpp, cr);
+               zfs_inode_update(dzp);
+               zfs_inode_update(zp);
+               *ipp = ZTOI(zp);
        }
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_create);
 
 /*
  * Remove an entry from a directory.
  *
- *     IN:     dvp     - vnode of directory to remove entry from.
+ *     IN:     dip     - inode of directory to remove entry from.
  *             name    - name of entry to remove.
  *             cr      - credentials of caller.
- *             ct      - caller context
- *             flags   - case flags
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     dvp - ctime|mtime
- *      vp - ctime (if nlink > 0)
+ *     dip - ctime|mtime
+ *      ip - ctime (if nlink > 0)
  */
 
 uint64_t null_xattr = 0;
 
 /*ARGSUSED*/
-static int
-zfs_remove(vnode_t *dvp, char *name, cred_t *cr, caller_context_t *ct,
-    int flags)
+int
+zfs_remove(struct inode *dip, char *name, cred_t *cr)
 {
-       znode_t         *zp, *dzp = VTOZ(dvp);
+       znode_t         *zp, *dzp = ITOZ(dip);
        znode_t         *xzp;
-       vnode_t         *vp;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       struct inode    *ip;
+       zfs_sb_t        *zsb = ITOZSB(dip);
        zilog_t         *zilog;
-       uint64_t        acl_obj, xattr_obj;
-       uint64_t        xattr_obj_unlinked = 0;
+       uint64_t        xattr_obj;
+       uint64_t        xattr_obj_unlinked = 0;
        uint64_t        obj = 0;
        zfs_dirlock_t   *dl;
        dmu_tx_t        *tx;
-       boolean_t       may_delete_now, delete_now = FALSE;
-       boolean_t       unlinked, toobig = FALSE;
+       boolean_t       unlinked;
        uint64_t        txtype;
        pathname_t      *realnmp = NULL;
+#ifdef HAVE_PN_UTILS
        pathname_t      realnm;
+#endif /* HAVE_PN_UTILS */
        int             error;
        int             zflg = ZEXISTS;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(dzp);
-       zilog = zfsvfs->z_log;
+       zilog = zsb->z_log;
 
+#ifdef HAVE_PN_UTILS
        if (flags & FIGNORECASE) {
                zflg |= ZCILOOK;
                pn_alloc(&realnm);
                realnmp = &realnm;
        }
+#endif /* HAVE_PN_UTILS */
 
 top:
        xattr_obj = 0;
@@ -1587,92 +1416,79 @@ top:
        /*
         * Attempt to lock directory; fail if entry doesn't exist.
         */
-       if (error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
-           NULL, realnmp)) {
+       if ((error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
+           NULL, realnmp))) {
+#ifdef HAVE_PN_UTILS
                if (realnmp)
                        pn_free(realnmp);
-               ZFS_EXIT(zfsvfs);
+#endif /* HAVE_PN_UTILS */
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       vp = ZTOV(zp);
+       ip = ZTOI(zp);
 
-       if (error = zfs_zaccess_delete(dzp, zp, cr)) {
+       if ((error = zfs_zaccess_delete(dzp, zp, cr))) {
                goto out;
        }
 
        /*
         * Need to use rmdir for removing directories.
         */
-       if (vp->v_type == VDIR) {
+       if (S_ISDIR(ip->i_mode)) {
                error = EPERM;
                goto out;
        }
 
-       vnevent_remove(vp, dvp, name, ct);
-
+#ifdef HAVE_DNLC
        if (realnmp)
                dnlc_remove(dvp, realnmp->pn_buf);
        else
                dnlc_remove(dvp, name);
-
-       mutex_enter(&vp->v_lock);
-       may_delete_now = vp->v_count == 1 && !vn_has_cached_data(vp);
-       mutex_exit(&vp->v_lock);
+#endif /* HAVE_DNLC */
 
        /*
-        * We may delete the znode now, or we may put it in the unlinked set;
-        * it depends on whether we're the last link, and on whether there are
-        * other holds on the vnode.  So we dmu_tx_hold() the right things to
-        * allow for either case.
+        * We never delete the znode and always place it in the unlinked
+        * set.  The dentry cache will always hold the last reference and
+        * is responsible for safely freeing the znode.
         */
        obj = zp->z_id;
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
        zfs_sa_upgrade_txholds(tx, zp);
        zfs_sa_upgrade_txholds(tx, dzp);
-       if (may_delete_now) {
-               toobig =
-                   zp->z_size > zp->z_blksz * DMU_MAX_DELETEBLKCNT;
-               /* if the file is too big, only hold_free a token amount */
-               dmu_tx_hold_free(tx, zp->z_id, 0,
-                   (toobig ? DMU_MAX_ACCESS : DMU_OBJECT_END));
-       }
 
        /* are there any extended attributes? */
-       error = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs),
+       error = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zsb),
            &xattr_obj, sizeof (xattr_obj));
        if (error == 0 && xattr_obj) {
-               error = zfs_zget(zfsvfs, xattr_obj, &xzp);
+               error = zfs_zget(zsb, xattr_obj, &xzp);
                ASSERT3U(error, ==, 0);
                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
                dmu_tx_hold_sa(tx, xzp->z_sa_hdl, B_FALSE);
        }
 
-       mutex_enter(&zp->z_lock);
-       if ((acl_obj = zfs_external_acl(zp)) != 0 && may_delete_now)
-               dmu_tx_hold_free(tx, acl_obj, 0, DMU_OBJECT_END);
-       mutex_exit(&zp->z_lock);
-
        /* charge as an update -- would be nice not to charge at all */
-       dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
+       dmu_tx_hold_zap(tx, zsb->z_unlinkedobj, FALSE, NULL);
 
        error = dmu_tx_assign(tx, TXG_NOWAIT);
        if (error) {
                zfs_dirent_unlock(dl);
-               VN_RELE(vp);
+               iput(ip);
                if (xzp)
-                       VN_RELE(ZTOV(xzp));
+                       iput(ZTOI(xzp));
                if (error == ERESTART) {
                        dmu_tx_wait(tx);
                        dmu_tx_abort(tx);
                        goto top;
                }
+#ifdef HAVE_PN_UTILS
                if (realnmp)
                        pn_free(realnmp);
+#endif /* HAVE_PN_UTILS */
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -1687,163 +1503,129 @@ top:
        }
 
        if (unlinked) {
-
                /*
                 * Hold z_lock so that we can make sure that the ACL obj
                 * hasn't changed.  Could have been deleted due to
                 * zfs_sa_upgrade().
                 */
                mutex_enter(&zp->z_lock);
-               mutex_enter(&vp->v_lock);
-               (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs),
+               (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zsb),
                    &xattr_obj_unlinked, sizeof (xattr_obj_unlinked));
-               delete_now = may_delete_now && !toobig &&
-                   vp->v_count == 1 && !vn_has_cached_data(vp) &&
-                   xattr_obj == xattr_obj_unlinked && zfs_external_acl(zp) ==
-                   acl_obj;
-               mutex_exit(&vp->v_lock);
-       }
-
-       if (delete_now) {
-               if (xattr_obj_unlinked) {
-                       ASSERT3U(xzp->z_links, ==, 2);
-                       mutex_enter(&xzp->z_lock);
-                       xzp->z_unlinked = 1;
-                       xzp->z_links = 0;
-                       error = sa_update(xzp->z_sa_hdl, SA_ZPL_LINKS(zfsvfs),
-                           &xzp->z_links, sizeof (xzp->z_links), tx);
-                       ASSERT3U(error,  ==,  0);
-                       mutex_exit(&xzp->z_lock);
-                       zfs_unlinked_add(xzp, tx);
-
-                       if (zp->z_is_sa)
-                               error = sa_remove(zp->z_sa_hdl,
-                                   SA_ZPL_XATTR(zfsvfs), tx);
-                       else
-                               error = sa_update(zp->z_sa_hdl,
-                                   SA_ZPL_XATTR(zfsvfs), &null_xattr,
-                                   sizeof (uint64_t), tx);
-                       ASSERT3U(error, ==, 0);
-               }
-               mutex_enter(&vp->v_lock);
-               vp->v_count--;
-               ASSERT3U(vp->v_count, ==, 0);
-               mutex_exit(&vp->v_lock);
-               mutex_exit(&zp->z_lock);
-               zfs_znode_delete(zp, tx);
-       } else if (unlinked) {
                mutex_exit(&zp->z_lock);
                zfs_unlinked_add(zp, tx);
        }
 
        txtype = TX_REMOVE;
+#ifdef HAVE_PN_UTILS
        if (flags & FIGNORECASE)
                txtype |= TX_CI;
+#endif /* HAVE_PN_UTILS */
        zfs_log_remove(zilog, tx, txtype, dzp, name, obj);
 
        dmu_tx_commit(tx);
 out:
+#ifdef HAVE_PN_UTILS
        if (realnmp)
                pn_free(realnmp);
+#endif /* HAVE_PN_UTILS */
 
        zfs_dirent_unlock(dl);
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
+       if (xzp)
+               zfs_inode_update(xzp);
 
-       if (!delete_now)
-               VN_RELE(vp);
+       iput(ip);
        if (xzp)
-               VN_RELE(ZTOV(xzp));
+               iput(ZTOI(xzp));
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_remove);
 
 /*
- * Create a new directory and insert it into dvp using the name
+ * Create a new directory and insert it into dip using the name
  * provided.  Return a pointer to the inserted directory.
  *
- *     IN:     dvp     - vnode of directory to add subdir to.
+ *     IN:     dip     - inode of directory to add subdir to.
  *             dirname - name of new directory.
  *             vap     - attributes of new directory.
  *             cr      - credentials of caller.
- *             ct      - caller context
  *             vsecp   - ACL to be set
  *
- *     OUT:    vpp     - vnode of created directory.
+ *     OUT:    ipp     - inode of created directory.
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     dvp - ctime|mtime updated
- *      vp - ctime|mtime|atime updated
+ *     dip - ctime|mtime updated
+ *     ipp - ctime|mtime|atime updated
  */
 /*ARGSUSED*/
-static int
-zfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr,
-    caller_context_t *ct, int flags, vsecattr_t *vsecp)
+int
+zfs_mkdir(struct inode *dip, char *dirname, vattr_t *vap, struct inode **ipp,
+    cred_t *cr, int flags, vsecattr_t *vsecp)
 {
-       znode_t         *zp, *dzp = VTOZ(dvp);
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       znode_t         *zp, *dzp = ITOZ(dip);
+       zfs_sb_t        *zsb = ITOZSB(dip);
        zilog_t         *zilog;
        zfs_dirlock_t   *dl;
        uint64_t        txtype;
        dmu_tx_t        *tx;
        int             error;
        int             zf = ZNEW;
-       ksid_t          *ksid;
        uid_t           uid;
        gid_t           gid = crgetgid(cr);
        zfs_acl_ids_t   acl_ids;
        boolean_t       fuid_dirtied;
 
-       ASSERT(vap->va_type == VDIR);
+       ASSERT(S_ISDIR(vap->va_mode));
 
        /*
         * If we have an ephemeral id, ACL, or XVATTR then
         * make sure file system is at proper version
         */
 
-       ksid = crgetsid(cr, KSID_OWNER);
-       if (ksid)
-               uid = ksid_getid(ksid);
-       else
-               uid = crgetuid(cr);
-       if (zfsvfs->z_use_fuids == B_FALSE &&
-           (vsecp || (vap->va_mask & AT_XVATTR) ||
-           IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
+       uid = crgetuid(cr);
+       if (zsb->z_use_fuids == B_FALSE &&
+           (vsecp || IS_EPHEMERAL(uid) || IS_EPHEMERAL(gid)))
                return (EINVAL);
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(dzp);
-       zilog = zfsvfs->z_log;
+       zilog = zsb->z_log;
 
        if (dzp->z_pflags & ZFS_XATTR) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
-       if (zfsvfs->z_utf8 && u8_validate(dirname,
+       if (zsb->z_utf8 && u8_validate(dirname,
            strlen(dirname), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EILSEQ);
        }
        if (flags & FIGNORECASE)
                zf |= ZCILOOK;
 
+#ifdef HAVE_XVATTR
        if (vap->va_mask & AT_XVATTR) {
                if ((error = secpolicy_xvattr((xvattr_t *)vap,
-                   crgetuid(cr), cr, vap->va_type)) != 0) {
-                       ZFS_EXIT(zfsvfs);
+                   crgetuid(cr), cr, vap->va_mode)) != 0) {
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
+#endif /* HAVE_XVATTR */
 
        if ((error = zfs_acl_ids_create(dzp, 0, vap, cr,
            vsecp, &acl_ids)) != 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
        /*
@@ -1854,39 +1636,39 @@ zfs_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, cred_t *cr,
         * to fail.
         */
 top:
-       *vpp = NULL;
+       *ipp = NULL;
 
-       if (error = zfs_dirent_lock(&dl, dzp, dirname, &zp, zf,
-           NULL, NULL)) {
+       if ((error = zfs_dirent_lock(&dl, dzp, dirname, &zp, zf,
+           NULL, NULL))) {
                zfs_acl_ids_free(&acl_ids);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       if (error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr)) {
+       if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) {
                zfs_acl_ids_free(&acl_ids);
                zfs_dirent_unlock(dl);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+       if (zfs_acl_ids_overquota(zsb, &acl_ids)) {
                zfs_acl_ids_free(&acl_ids);
                zfs_dirent_unlock(dl);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EDQUOT);
        }
 
        /*
         * Add a new entry to the directory.
         */
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname);
        dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
-       fuid_dirtied = zfsvfs->z_fuid_dirty;
+       fuid_dirtied = zsb->z_fuid_dirty;
        if (fuid_dirtied)
-               zfs_fuid_txhold(zfsvfs, tx);
-       if (!zfsvfs->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
+               zfs_fuid_txhold(zsb, tx);
+       if (!zsb->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
                dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
                    acl_ids.z_aclp->z_acl_bytes);
        }
@@ -1904,7 +1686,7 @@ top:
                }
                zfs_acl_ids_free(&acl_ids);
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -1914,14 +1696,14 @@ top:
        zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
 
        if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
+               zfs_fuid_sync(zsb, tx);
 
        /*
         * Now put new name in parent dir.
         */
        (void) zfs_link_create(dl, zp, tx, ZNEW);
 
-       *vpp = ZTOV(zp);
+       *ipp = ZTOI(zp);
 
        txtype = zfs_log_create_txtype(Z_DIR, vsecp, vap);
        if (flags & FIGNORECASE)
@@ -1935,49 +1717,51 @@ top:
 
        zfs_dirent_unlock(dl);
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
+       ZFS_EXIT(zsb);
        return (0);
 }
+EXPORT_SYMBOL(zfs_mkdir);
 
 /*
  * Remove a directory subdir entry.  If the current working
  * directory is the same as the subdir to be removed, the
  * remove will fail.
  *
- *     IN:     dvp     - vnode of directory to remove from.
+ *     IN:     dip     - inode of directory to remove from.
  *             name    - name of directory to be removed.
- *             cwd     - vnode of current working directory.
+ *             cwd     - inode of current working directory.
  *             cr      - credentials of caller.
- *             ct      - caller context
  *             flags   - case flags
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     dvp - ctime|mtime updated
+ *     dip - ctime|mtime updated
  */
 /*ARGSUSED*/
-static int
-zfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
-    caller_context_t *ct, int flags)
+int
+zfs_rmdir(struct inode *dip, char *name, struct inode *cwd, cred_t *cr,
+    int flags)
 {
-       znode_t         *dzp = VTOZ(dvp);
+       znode_t         *dzp = ITOZ(dip);
        znode_t         *zp;
-       vnode_t         *vp;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       struct inode    *ip;
+       zfs_sb_t        *zsb = ITOZSB(dip);
        zilog_t         *zilog;
        zfs_dirlock_t   *dl;
        dmu_tx_t        *tx;
        int             error;
        int             zflg = ZEXISTS;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(dzp);
-       zilog = zfsvfs->z_log;
+       zilog = zsb->z_log;
 
        if (flags & FIGNORECASE)
                zflg |= ZCILOOK;
@@ -1987,30 +1771,28 @@ top:
        /*
         * Attempt to lock directory; fail if entry doesn't exist.
         */
-       if (error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
-           NULL, NULL)) {
-               ZFS_EXIT(zfsvfs);
+       if ((error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
+           NULL, NULL))) {
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       vp = ZTOV(zp);
+       ip = ZTOI(zp);
 
-       if (error = zfs_zaccess_delete(dzp, zp, cr)) {
+       if ((error = zfs_zaccess_delete(dzp, zp, cr))) {
                goto out;
        }
 
-       if (vp->v_type != VDIR) {
+       if (!S_ISDIR(ip->i_mode)) {
                error = ENOTDIR;
                goto out;
        }
 
-       if (vp == cwd) {
+       if (ip == cwd) {
                error = EINVAL;
                goto out;
        }
 
-       vnevent_rmdir(vp, dvp, name, ct);
-
        /*
         * Grab a lock on the directory to make sure that noone is
         * trying to add (or lookup) entries while we are removing it.
@@ -2023,10 +1805,10 @@ top:
         */
        rw_enter(&zp->z_parent_lock, RW_WRITER);
 
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_zap(tx, dzp->z_id, FALSE, name);
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
-       dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
+       dmu_tx_hold_zap(tx, zsb->z_unlinkedobj, FALSE, NULL);
        zfs_sa_upgrade_txholds(tx, zp);
        zfs_sa_upgrade_txholds(tx, dzp);
        error = dmu_tx_assign(tx, TXG_NOWAIT);
@@ -2034,14 +1816,14 @@ top:
                rw_exit(&zp->z_parent_lock);
                rw_exit(&zp->z_name_lock);
                zfs_dirent_unlock(dl);
-               VN_RELE(vp);
+               iput(ip);
                if (error == ERESTART) {
                        dmu_tx_wait(tx);
                        dmu_tx_abort(tx);
                        goto top;
                }
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -2061,35 +1843,32 @@ top:
 out:
        zfs_dirent_unlock(dl);
 
-       VN_RELE(vp);
+       iput(ip);
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_rmdir);
 
 /*
  * Read as many directory entries as will fit into the provided
- * buffer from the given directory cursor position (specified in
- * the uio structure.
+ * dirent buffer from the given directory cursor position.
  *
- *     IN:     vp      - vnode of directory to read.
- *             uio     - structure supplying read location, range info,
- *                       and return buffer.
- *             cr      - credentials of caller.
- *             ct      - caller context
- *             flags   - case flags
+ *     IN:     ip      - inode of directory to read.
+ *             dirent  - buffer for directory entries.
  *
- *     OUT:    uio     - updated offset and range, buffer filled.
- *             eofp    - set to true if end-of-file detected.
+ *     OUT:    dirent  - filler buffer of directory entries.
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     vp - atime updated
+ *     ip - atime updated
  *
  * Note that the low 4 bits of the cookie returned by zap is always zero.
  * This allows us to use the low range for "special" directory entries:
@@ -2097,70 +1876,42 @@ out:
  * we use the offset 2 for the '.zfs' directory.
  */
 /* ARGSUSED */
-static int
-zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
-    caller_context_t *ct, int flags)
+int
+zfs_readdir(struct inode *ip, void *dirent, filldir_t filldir,
+    loff_t *pos, cred_t *cr)
 {
-       znode_t         *zp = VTOZ(vp);
-       iovec_t         *iovp;
-       edirent_t       *eodp;
-       dirent64_t      *odp;
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
        objset_t        *os;
-       caddr_t         outbuf;
-       size_t          bufsize;
        zap_cursor_t    zc;
        zap_attribute_t zap;
-       uint_t          bytes_wanted;
-       uint64_t        offset; /* must be unsigned; checks for < 1 */
-       uint64_t        parent;
-       int             local_eof;
        int             outcount;
        int             error;
        uint8_t         prefetch;
-       boolean_t       check_sysattrs;
+       int             done = 0;
+       uint64_t        parent;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
-       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
-           &parent, sizeof (parent))) != 0) {
-               ZFS_EXIT(zfsvfs);
-               return (error);
-       }
-
-       /*
-        * If we are not given an eof variable,
-        * use a local one.
-        */
-       if (eofp == NULL)
-               eofp = &local_eof;
-
-       /*
-        * Check for valid iov_len.
-        */
-       if (uio->uio_iov->iov_len <= 0) {
-               ZFS_EXIT(zfsvfs);
-               return (EINVAL);
-       }
+       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zsb),
+           &parent, sizeof (parent))) != 0)
+               goto out;
 
        /*
         * Quit if directory has been removed (posix)
         */
-       if ((*eofp = zp->z_unlinked) != 0) {
-               ZFS_EXIT(zfsvfs);
-               return (0);
-       }
-
        error = 0;
-       os = zfsvfs->z_os;
-       offset = uio->uio_loffset;
+       if (zp->z_unlinked)
+               goto out;
+
+       os = zsb->z_os;
        prefetch = zp->z_zn_prefetch;
 
        /*
         * Initialize the iterator cursor.
         */
-       if (offset <= 3) {
+       if (*pos <= 3) {
                /*
                 * Start iteration from the beginning of the directory.
                 */
@@ -2169,55 +1920,28 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
                /*
                 * The offset is a serialized cursor.
                 */
-               zap_cursor_init_serialized(&zc, os, zp->z_id, offset);
+               zap_cursor_init_serialized(&zc, os, zp->z_id, *pos);
        }
 
        /*
-        * Get space to change directory entries into fs independent format.
-        */
-       iovp = uio->uio_iov;
-       bytes_wanted = iovp->iov_len;
-       if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) {
-               bufsize = bytes_wanted;
-               outbuf = kmem_alloc(bufsize, KM_SLEEP);
-               odp = (struct dirent64 *)outbuf;
-       } else {
-               bufsize = bytes_wanted;
-               odp = (struct dirent64 *)iovp->iov_base;
-       }
-       eodp = (struct edirent *)odp;
-
-       /*
-        * If this VFS supports the system attribute view interface; and
-        * we're looking at an extended attribute directory; and we care
-        * about normalization conflicts on this vfs; then we must check
-        * for normalization conflicts with the sysattr name space.
-        */
-       check_sysattrs = vfs_has_feature(vp->v_vfsp, VFSFT_SYSATTR_VIEWS) &&
-           (vp->v_flag & V_XATTRDIR) && zfsvfs->z_norm &&
-           (flags & V_RDDIR_ENTFLAGS);
-
-       /*
         * Transform to file-system independent format
         */
        outcount = 0;
-       while (outcount < bytes_wanted) {
-               ino64_t objnum;
-               ushort_t reclen;
-               off64_t *next = NULL;
 
+       while (!done) {
+               uint64_t objnum;
                /*
                 * Special case `.', `..', and `.zfs'.
                 */
-               if (offset == 0) {
+               if (*pos == 0) {
                        (void) strcpy(zap.za_name, ".");
                        zap.za_normalization_conflict = 0;
                        objnum = zp->z_id;
-               } else if (offset == 1) {
+               } else if (*pos == 1) {
                        (void) strcpy(zap.za_name, "..");
                        zap.za_normalization_conflict = 0;
                        objnum = parent;
-               } else if (offset == 2 && zfs_show_ctldir(zp)) {
+               } else if (*pos == 2 && zfs_show_ctldir(zp)) {
                        (void) strcpy(zap.za_name, ZFS_CTLDIR_NAME);
                        zap.za_normalization_conflict = 0;
                        objnum = ZFSCTL_INO_ROOT;
@@ -2225,8 +1949,8 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
                        /*
                         * Grab next entry.
                         */
-                       if (error = zap_cursor_retrieve(&zc, &zap)) {
-                               if ((*eofp = (error == ENOENT)) != 0)
+                       if ((error = zap_cursor_retrieve(&zc, &zap))) {
+                               if (error == ENOENT)
                                        break;
                                else
                                        goto update;
@@ -2237,201 +1961,104 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp,
                                cmn_err(CE_WARN, "zap_readdir: bad directory "
                                    "entry, obj = %lld, offset = %lld\n",
                                    (u_longlong_t)zp->z_id,
-                                   (u_longlong_t)offset);
+                                   (u_longlong_t)*pos);
                                error = ENXIO;
                                goto update;
                        }
 
                        objnum = ZFS_DIRENT_OBJ(zap.za_first_integer);
-                       /*
-                        * MacOS X can extract the object type here such as:
-                        * uint8_t type = ZFS_DIRENT_TYPE(zap.za_first_integer);
-                        */
-
-                       if (check_sysattrs && !zap.za_normalization_conflict) {
-                               zap.za_normalization_conflict =
-                                   xattr_sysattr_casechk(zap.za_name);
-                       }
                }
-
-               if (flags & V_RDDIR_ACCFILTER) {
-                       /*
-                        * If we have no access at all, don't include
-                        * this entry in the returned information
-                        */
-                       znode_t *ezp;
-                       if (zfs_zget(zp->z_zfsvfs, objnum, &ezp) != 0)
-                               goto skip_entry;
-                       if (!zfs_has_access(ezp, cr)) {
-                               VN_RELE(ZTOV(ezp));
-                               goto skip_entry;
-                       }
-                       VN_RELE(ZTOV(ezp));
-               }
-
-               if (flags & V_RDDIR_ENTFLAGS)
-                       reclen = EDIRENT_RECLEN(strlen(zap.za_name));
-               else
-                       reclen = DIRENT64_RECLEN(strlen(zap.za_name));
-
-               /*
-                * Will this entry fit in the buffer?
-                */
-               if (outcount + reclen > bufsize) {
-                       /*
-                        * Did we manage to fit anything in the buffer?
-                        */
-                       if (!outcount) {
-                               error = EINVAL;
-                               goto update;
-                       }
+               done = filldir(dirent, zap.za_name, strlen(zap.za_name),
+                              zap_cursor_serialize(&zc), objnum, 0);
+               if (done) {
                        break;
                }
-               if (flags & V_RDDIR_ENTFLAGS) {
-                       /*
-                        * Add extended flag entry:
-                        */
-                       eodp->ed_ino = objnum;
-                       eodp->ed_reclen = reclen;
-                       /* NOTE: ed_off is the offset for the *next* entry */
-                       next = &(eodp->ed_off);
-                       eodp->ed_eflags = zap.za_normalization_conflict ?
-                           ED_CASE_CONFLICT : 0;
-                       (void) strncpy(eodp->ed_name, zap.za_name,
-                           EDIRENT_NAMELEN(reclen));
-                       eodp = (edirent_t *)((intptr_t)eodp + reclen);
-               } else {
-                       /*
-                        * Add normal entry:
-                        */
-                       odp->d_ino = objnum;
-                       odp->d_reclen = reclen;
-                       /* NOTE: d_off is the offset for the *next* entry */
-                       next = &(odp->d_off);
-                       (void) strncpy(odp->d_name, zap.za_name,
-                           DIRENT64_NAMELEN(reclen));
-                       odp = (dirent64_t *)((intptr_t)odp + reclen);
-               }
-               outcount += reclen;
-
-               ASSERT(outcount <= bufsize);
 
                /* Prefetch znode */
-               if (prefetch)
+               if (prefetch) {
                        dmu_prefetch(os, objnum, 0, 0);
+               }
 
-       skip_entry:
-               /*
-                * Move to the next entry, fill in the previous offset.
-                */
-               if (offset > 2 || (offset == 2 && !zfs_show_ctldir(zp))) {
+               if (*pos >= 2) {
                        zap_cursor_advance(&zc);
-                       offset = zap_cursor_serialize(&zc);
+                       *pos = zap_cursor_serialize(&zc);
                } else {
-                       offset += 1;
+                       (*pos)++;
                }
-               if (next)
-                       *next = offset;
        }
        zp->z_zn_prefetch = B_FALSE; /* a lookup will re-enable pre-fetching */
 
-       if (uio->uio_segflg == UIO_SYSSPACE && uio->uio_iovcnt == 1) {
-               iovp->iov_base += outcount;
-               iovp->iov_len -= outcount;
-               uio->uio_resid -= outcount;
-       } else if (error = uiomove(outbuf, (long)outcount, UIO_READ, uio)) {
-               /*
-                * Reset the pointer.
-                */
-               offset = uio->uio_loffset;
-       }
-
 update:
        zap_cursor_fini(&zc);
-       if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
-               kmem_free(outbuf, bufsize);
-
        if (error == ENOENT)
                error = 0;
 
-       ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
+       ZFS_ACCESSTIME_STAMP(zsb, zp);
+       zfs_inode_update(zp);
+
+out:
+       ZFS_EXIT(zsb);
 
-       uio->uio_loffset = offset;
-       ZFS_EXIT(zfsvfs);
        return (error);
 }
+EXPORT_SYMBOL(zfs_readdir);
 
 ulong_t zfs_fsync_sync_cnt = 4;
 
-static int
-zfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
+int
+zfs_fsync(struct inode *ip, int syncflag, cred_t *cr)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-
-       /*
-        * Regardless of whether this is required for standards conformance,
-        * this is the logical behavior when fsync() is called on a file with
-        * dirty pages.  We use B_ASYNC since the ZIL transactions are already
-        * going to be pushed out as part of the zil_commit().
-        */
-       if (vn_has_cached_data(vp) && !(syncflag & FNODSYNC) &&
-           (vp->v_type == VREG) && !(IS_SWAPVP(vp)))
-               (void) VOP_PUTPAGE(vp, (offset_t)0, (size_t)0, B_ASYNC, cr, ct);
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
 
        (void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt);
 
-       if (zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) {
-               ZFS_ENTER(zfsvfs);
+       if (zsb->z_os->os_sync != ZFS_SYNC_DISABLED) {
+               ZFS_ENTER(zsb);
                ZFS_VERIFY_ZP(zp);
-               zil_commit(zfsvfs->z_log, zp->z_id);
-               ZFS_EXIT(zfsvfs);
+               zil_commit(zsb->z_log, zp->z_id);
+               ZFS_EXIT(zsb);
        }
        return (0);
 }
+EXPORT_SYMBOL(zfs_fsync);
 
 
 /*
  * Get the requested file attributes and place them in the provided
  * vattr structure.
  *
- *     IN:     vp      - vnode of file.
- *             vap     - va_mask identifies requested attributes.
- *                       If AT_XVATTR set, then optional attrs are requested
+ *     IN:     ip      - inode of file.
+ *             stat    - kstat structure to fill in.
  *             flags   - ATTR_NOACLCHECK (CIFS server context)
  *             cr      - credentials of caller.
- *             ct      - caller context
  *
- *     OUT:    vap     - attribute values.
- *
- *     RETURN: 0 (always succeeds)
+ *     OUT:    stat    - filled in kstat values.
  */
 /* ARGSUSED */
-static int
-zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct)
+int
+zfs_getattr(struct inode *ip, struct kstat *stat, int flags, cred_t *cr)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
        int     error = 0;
        uint64_t links;
        uint64_t mtime[2], ctime[2];
-       xvattr_t *xvap = (xvattr_t *)vap;       /* vap may be an xvattr_t * */
-       xoptattr_t *xoap = NULL;
+       uint32_t blksz;
        boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
        sa_bulk_attr_t bulk[2];
        int count = 0;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
-       zfs_fuid_map_ids(zp, cr, &vap->va_uid, &vap->va_gid);
+       zfs_fuid_map_ids(zp, cr, &stat->uid, &stat->gid);
 
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL, &mtime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL, &ctime, 16);
 
        if ((error = sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) != 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -2441,10 +2068,10 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
         * always be allowed to read basic attributes of file.
         */
        if (!(zp->z_pflags & ZFS_ACL_TRIVIAL) &&
-           (vap->va_uid != crgetuid(cr))) {
-               if (error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0,
-                   skipaclchk, cr)) {
-                       ZFS_EXIT(zfsvfs);
+           (stat->uid != crgetuid(cr))) {
+               if ((error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0,
+                   skipaclchk, cr))) {
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
@@ -2455,175 +2082,67 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
         */
 
        mutex_enter(&zp->z_lock);
-       vap->va_type = vp->v_type;
-       vap->va_mode = zp->z_mode & MODEMASK;
-       vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev;
-       vap->va_nodeid = zp->z_id;
-       if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp))
+       stat->ino = ip->i_ino;
+       stat->mode = zp->z_mode;
+       stat->uid = zp->z_uid;
+       stat->gid = zp->z_gid;
+       if ((zp->z_id == zsb->z_root) && zfs_show_ctldir(zp))
                links = zp->z_links + 1;
        else
                links = zp->z_links;
-       vap->va_nlink = MIN(links, UINT32_MAX); /* nlink_t limit! */
-       vap->va_size = zp->z_size;
-       vap->va_rdev = vp->v_rdev;
-       vap->va_seq = zp->z_seq;
-
-       /*
-        * Add in any requested optional attributes and the create time.
-        * Also set the corresponding bits in the returned attribute bitmap.
-        */
-       if ((xoap = xva_getxoptattr(xvap)) != NULL && zfsvfs->z_use_fuids) {
-               if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
-                       xoap->xoa_archive =
-                           ((zp->z_pflags & ZFS_ARCHIVE) != 0);
-                       XVA_SET_RTN(xvap, XAT_ARCHIVE);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
-                       xoap->xoa_readonly =
-                           ((zp->z_pflags & ZFS_READONLY) != 0);
-                       XVA_SET_RTN(xvap, XAT_READONLY);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
-                       xoap->xoa_system =
-                           ((zp->z_pflags & ZFS_SYSTEM) != 0);
-                       XVA_SET_RTN(xvap, XAT_SYSTEM);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
-                       xoap->xoa_hidden =
-                           ((zp->z_pflags & ZFS_HIDDEN) != 0);
-                       XVA_SET_RTN(xvap, XAT_HIDDEN);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) {
-                       xoap->xoa_nounlink =
-                           ((zp->z_pflags & ZFS_NOUNLINK) != 0);
-                       XVA_SET_RTN(xvap, XAT_NOUNLINK);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) {
-                       xoap->xoa_immutable =
-                           ((zp->z_pflags & ZFS_IMMUTABLE) != 0);
-                       XVA_SET_RTN(xvap, XAT_IMMUTABLE);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) {
-                       xoap->xoa_appendonly =
-                           ((zp->z_pflags & ZFS_APPENDONLY) != 0);
-                       XVA_SET_RTN(xvap, XAT_APPENDONLY);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) {
-                       xoap->xoa_nodump =
-                           ((zp->z_pflags & ZFS_NODUMP) != 0);
-                       XVA_SET_RTN(xvap, XAT_NODUMP);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) {
-                       xoap->xoa_opaque =
-                           ((zp->z_pflags & ZFS_OPAQUE) != 0);
-                       XVA_SET_RTN(xvap, XAT_OPAQUE);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) {
-                       xoap->xoa_av_quarantined =
-                           ((zp->z_pflags & ZFS_AV_QUARANTINED) != 0);
-                       XVA_SET_RTN(xvap, XAT_AV_QUARANTINED);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) {
-                       xoap->xoa_av_modified =
-                           ((zp->z_pflags & ZFS_AV_MODIFIED) != 0);
-                       XVA_SET_RTN(xvap, XAT_AV_MODIFIED);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) &&
-                   vp->v_type == VREG) {
-                       zfs_sa_get_scanstamp(zp, xvap);
-               }
+       stat->nlink = MIN(links, ZFS_LINK_MAX);
+       stat->size = i_size_read(ip);
+       stat->rdev = ip->i_rdev;
+       stat->dev = ip->i_rdev;
 
-               if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
-                       uint64_t times[2];
-
-                       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zfsvfs),
-                           times, sizeof (times));
-                       ZFS_TIME_DECODE(&xoap->xoa_createtime, times);
-                       XVA_SET_RTN(xvap, XAT_CREATETIME);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
-                       xoap->xoa_reparse = ((zp->z_pflags & ZFS_REPARSE) != 0);
-                       XVA_SET_RTN(xvap, XAT_REPARSE);
-               }
-               if (XVA_ISSET_REQ(xvap, XAT_GEN)) {
-                       xoap->xoa_generation = zp->z_gen;
-                       XVA_SET_RTN(xvap, XAT_GEN);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) {
-                       xoap->xoa_offline =
-                           ((zp->z_pflags & ZFS_OFFLINE) != 0);
-                       XVA_SET_RTN(xvap, XAT_OFFLINE);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) {
-                       xoap->xoa_sparse =
-                           ((zp->z_pflags & ZFS_SPARSE) != 0);
-                       XVA_SET_RTN(xvap, XAT_SPARSE);
-               }
-       }
-
-       ZFS_TIME_DECODE(&vap->va_atime, zp->z_atime);
-       ZFS_TIME_DECODE(&vap->va_mtime, mtime);
-       ZFS_TIME_DECODE(&vap->va_ctime, ctime);
+       ZFS_TIME_DECODE(&stat->atime, zp->z_atime);
+       ZFS_TIME_DECODE(&stat->mtime, mtime);
+       ZFS_TIME_DECODE(&stat->ctime, ctime);
 
        mutex_exit(&zp->z_lock);
 
-       sa_object_size(zp->z_sa_hdl, &vap->va_blksize, &vap->va_nblocks);
+       sa_object_size(zp->z_sa_hdl, &blksz, &stat->blocks);
+       stat->blksize = (1 << ip->i_blkbits);
 
        if (zp->z_blksz == 0) {
                /*
                 * Block size hasn't been set; suggest maximal I/O transfers.
                 */
-               vap->va_blksize = zfsvfs->z_max_blksz;
+               stat->blksize = zsb->z_max_blksz;
        }
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (0);
 }
+EXPORT_SYMBOL(zfs_getattr);
 
 /*
  * Set the file attributes to the values contained in the
  * vattr structure.
  *
- *     IN:     vp      - vnode of file to be modified.
+ *     IN:     ip      - inode of file to be modified.
  *             vap     - new attribute values.
  *                       If AT_XVATTR set, then optional attrs are being set
  *             flags   - ATTR_UTIME set if non-default time values provided.
  *                     - ATTR_NOACLCHECK (CIFS context only).
  *             cr      - credentials of caller.
- *             ct      - caller context
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     vp - ctime updated, mtime updated if size changed.
+ *     ip - ctime updated, mtime updated if size changed.
  */
 /* ARGSUSED */
-static int
-zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-       caller_context_t *ct)
+int
+zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr)
 {
-       znode_t         *zp = VTOZ(vp);
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
        zilog_t         *zilog;
        dmu_tx_t        *tx;
        vattr_t         oldva;
-       xvattr_t        tmpxvattr;
-       uint_t          mask = vap->va_mask;
+       uint_t          mask = attr->ia_valid;
        uint_t          saved_mask;
        int             trim_mask = 0;
        uint64_t        new_mode;
@@ -2634,10 +2153,8 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
        int             need_policy = FALSE;
        int             err, err2;
        zfs_fuid_info_t *fuidp = NULL;
-       xvattr_t *xvap = (xvattr_t *)vap;       /* vap may be an xvattr_t * */
-       xoptattr_t      *xoap;
-       zfs_acl_t       *aclp;
        boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
+       zfs_acl_t       *aclp = NULL;
        boolean_t       fuid_dirtied = B_FALSE;
        sa_bulk_attr_t  bulk[7], xattr_bulk[7];
        int             count = 0, xattr_count = 0;
@@ -2645,81 +2162,44 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
        if (mask == 0)
                return (0);
 
-       if (mask & AT_NOSET)
-               return (EINVAL);
-
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
-       zilog = zfsvfs->z_log;
+       zilog = zsb->z_log;
 
        /*
         * Make sure that if we have ephemeral uid/gid or xvattr specified
         * that file system is at proper version level
         */
-
-       if (zfsvfs->z_use_fuids == B_FALSE &&
-           (((mask & AT_UID) && IS_EPHEMERAL(vap->va_uid)) ||
-           ((mask & AT_GID) && IS_EPHEMERAL(vap->va_gid)) ||
-           (mask & AT_XVATTR))) {
-               ZFS_EXIT(zfsvfs);
+       if (zsb->z_use_fuids == B_FALSE &&
+           (((mask & ATTR_UID) && IS_EPHEMERAL(attr->ia_uid)) ||
+           ((mask & ATTR_GID) && IS_EPHEMERAL(attr->ia_gid)))) {
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
-       if (mask & AT_SIZE && vp->v_type == VDIR) {
-               ZFS_EXIT(zfsvfs);
+       if (mask & ATTR_SIZE && S_ISDIR(ip->i_mode)) {
+               ZFS_EXIT(zsb);
                return (EISDIR);
        }
 
-       if (mask & AT_SIZE && vp->v_type != VREG && vp->v_type != VFIFO) {
-               ZFS_EXIT(zfsvfs);
+       if (mask & ATTR_SIZE && !S_ISREG(ip->i_mode) && !S_ISFIFO(ip->i_mode)) {
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
-       /*
-        * If this is an xvattr_t, then get a pointer to the structure of
-        * optional attributes.  If this is NULL, then we have a vattr_t.
-        */
-       xoap = xva_getxoptattr(xvap);
-
-       xva_init(&tmpxvattr);
-
-       /*
-        * Immutable files can only alter immutable bit and atime
-        */
-       if ((zp->z_pflags & ZFS_IMMUTABLE) &&
-           ((mask & (AT_SIZE|AT_UID|AT_GID|AT_MTIME|AT_MODE)) ||
-           ((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME)))) {
-               ZFS_EXIT(zfsvfs);
+       if ((mask & ATTR_SIZE) && (zp->z_pflags & ZFS_READONLY)) {
+               ZFS_EXIT(zsb);
                return (EPERM);
        }
 
-       if ((mask & AT_SIZE) && (zp->z_pflags & ZFS_READONLY)) {
-               ZFS_EXIT(zfsvfs);
-               return (EPERM);
-       }
-
-       /*
-        * Verify timestamps doesn't overflow 32 bits.
-        * ZFS can handle large timestamps, but 32bit syscalls can't
-        * handle times greater than 2039.  This check should be removed
-        * once large timestamps are fully supported.
-        */
-       if (mask & (AT_ATIME | AT_MTIME)) {
-               if (((mask & AT_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) ||
-                   ((mask & AT_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime))) {
-                       ZFS_EXIT(zfsvfs);
-                       return (EOVERFLOW);
-               }
-       }
-
 top:
        attrzp = NULL;
        aclp = NULL;
 
        /* Can this be moved to before the top label? */
-       if (zfsvfs->z_vfs->vfs_flag & VFS_RDONLY) {
-               ZFS_EXIT(zfsvfs);
+       if (zsb->z_vfs->mnt_flags & MNT_READONLY) {
+               ZFS_EXIT(zsb);
                return (EROFS);
        }
 
@@ -2727,10 +2207,10 @@ top:
         * First validate permissions
         */
 
-       if (mask & AT_SIZE) {
+       if (mask & ATTR_SIZE) {
                err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr);
                if (err) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (err);
                }
                /*
@@ -2740,27 +2220,22 @@ top:
                 * should be addressed in openat().
                 */
                /* XXX - would it be OK to generate a log record here? */
-               err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE);
+               err = zfs_freesp(zp, attr->ia_size, 0, 0, FALSE);
                if (err) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (err);
                }
-       }
 
-       if (mask & (AT_ATIME|AT_MTIME) ||
-           ((mask & AT_XVATTR) && (XVA_ISSET_REQ(xvap, XAT_HIDDEN) ||
-           XVA_ISSET_REQ(xvap, XAT_READONLY) ||
-           XVA_ISSET_REQ(xvap, XAT_ARCHIVE) ||
-           XVA_ISSET_REQ(xvap, XAT_OFFLINE) ||
-           XVA_ISSET_REQ(xvap, XAT_SPARSE) ||
-           XVA_ISSET_REQ(xvap, XAT_CREATETIME) ||
-           XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) {
-               need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0,
-                   skipaclchk, cr);
+               /* Careful negative Linux return code here */
+               err = -vmtruncate(ip, attr->ia_size);
+               if (err) {
+                       ZFS_EXIT(zsb);
+                       return (err);
+               }
        }
 
-       if (mask & (AT_UID|AT_GID)) {
-               int     idmask = (mask & (AT_UID|AT_GID));
+       if (mask & (ATTR_UID|ATTR_GID)) {
+               int     idmask = (mask & (ATTR_UID|ATTR_GID));
                int     take_owner;
                int     take_group;
 
@@ -2769,141 +2244,61 @@ top:
                 * we may clear S_ISUID/S_ISGID bits.
                 */
 
-               if (!(mask & AT_MODE))
-                       vap->va_mode = zp->z_mode;
+               if (!(mask & ATTR_MODE))
+                       attr->ia_mode = zp->z_mode;
 
                /*
                 * Take ownership or chgrp to group we are a member of
                 */
 
-               take_owner = (mask & AT_UID) && (vap->va_uid == crgetuid(cr));
-               take_group = (mask & AT_GID) &&
-                   zfs_groupmember(zfsvfs, vap->va_gid, cr);
+               take_owner = (mask & ATTR_UID) &&
+                   (attr->ia_uid == crgetuid(cr));
+               take_group = (mask & ATTR_GID) &&
+                   zfs_groupmember(zsb, attr->ia_gid, cr);
 
                /*
                 * If both AT_UID and AT_GID are set then take_owner and
                 * take_group must both be set in order to allow taking
                 * ownership.
-                *
-                * Otherwise, send the check through secpolicy_vnode_setattr()
-                *
-                */
-
-               if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) ||
-                   ((idmask == AT_UID) && take_owner) ||
-                   ((idmask == AT_GID) && take_group)) {
-                       if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0,
-                           skipaclchk, cr) == 0) {
-                               /*
-                                * Remove setuid/setgid for non-privileged users
-                                */
-                               secpolicy_setid_clear(vap, cr);
-                               trim_mask = (mask & (AT_UID|AT_GID));
-                       } else {
-                               need_policy =  TRUE;
-                       }
-               } else {
-                       need_policy =  TRUE;
-               }
-       }
-
-       mutex_enter(&zp->z_lock);
-       oldva.va_mode = zp->z_mode;
-       zfs_fuid_map_ids(zp, cr, &oldva.va_uid, &oldva.va_gid);
-       if (mask & AT_XVATTR) {
-               /*
-                * Update xvattr mask to include only those attributes
-                * that are actually changing.
-                *
-                * the bits will be restored prior to actually setting
-                * the attributes so the caller thinks they were set.
-                */
-               if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) {
-                       if (xoap->xoa_appendonly !=
-                           ((zp->z_pflags & ZFS_APPENDONLY) != 0)) {
-                               need_policy = TRUE;
-                       } else {
-                               XVA_CLR_REQ(xvap, XAT_APPENDONLY);
-                               XVA_SET_REQ(&tmpxvattr, XAT_APPENDONLY);
-                       }
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) {
-                       if (xoap->xoa_nounlink !=
-                           ((zp->z_pflags & ZFS_NOUNLINK) != 0)) {
-                               need_policy = TRUE;
-                       } else {
-                               XVA_CLR_REQ(xvap, XAT_NOUNLINK);
-                               XVA_SET_REQ(&tmpxvattr, XAT_NOUNLINK);
-                       }
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) {
-                       if (xoap->xoa_immutable !=
-                           ((zp->z_pflags & ZFS_IMMUTABLE) != 0)) {
-                               need_policy = TRUE;
-                       } else {
-                               XVA_CLR_REQ(xvap, XAT_IMMUTABLE);
-                               XVA_SET_REQ(&tmpxvattr, XAT_IMMUTABLE);
-                       }
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) {
-                       if (xoap->xoa_nodump !=
-                           ((zp->z_pflags & ZFS_NODUMP) != 0)) {
-                               need_policy = TRUE;
-                       } else {
-                               XVA_CLR_REQ(xvap, XAT_NODUMP);
-                               XVA_SET_REQ(&tmpxvattr, XAT_NODUMP);
-                       }
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) {
-                       if (xoap->xoa_av_modified !=
-                           ((zp->z_pflags & ZFS_AV_MODIFIED) != 0)) {
-                               need_policy = TRUE;
-                       } else {
-                               XVA_CLR_REQ(xvap, XAT_AV_MODIFIED);
-                               XVA_SET_REQ(&tmpxvattr, XAT_AV_MODIFIED);
-                       }
-               }
+                *
+                * Otherwise, send the check through secpolicy_vnode_setattr()
+                *
+                */
 
-               if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) {
-                       if ((vp->v_type != VREG &&
-                           xoap->xoa_av_quarantined) ||
-                           xoap->xoa_av_quarantined !=
-                           ((zp->z_pflags & ZFS_AV_QUARANTINED) != 0)) {
-                               need_policy = TRUE;
+               if (((idmask == (ATTR_UID|ATTR_GID)) &&
+                   take_owner && take_group) ||
+                   ((idmask == ATTR_UID) && take_owner) ||
+                   ((idmask == ATTR_GID) && take_group)) {
+                       if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0,
+                           skipaclchk, cr) == 0) {
+                               /*
+                                * Remove setuid/setgid for non-privileged users
+                                */
+                               secpolicy_setid_clear(attr, cr);
+                               trim_mask = (mask & (ATTR_UID|ATTR_GID));
                        } else {
-                               XVA_CLR_REQ(xvap, XAT_AV_QUARANTINED);
-                               XVA_SET_REQ(&tmpxvattr, XAT_AV_QUARANTINED);
+                               need_policy =  TRUE;
                        }
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
-                       mutex_exit(&zp->z_lock);
-                       ZFS_EXIT(zfsvfs);
-                       return (EPERM);
-               }
-
-               if (need_policy == FALSE &&
-                   (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) ||
-                   XVA_ISSET_REQ(xvap, XAT_OPAQUE))) {
-                       need_policy = TRUE;
+               } else {
+                       need_policy =  TRUE;
                }
        }
 
+       mutex_enter(&zp->z_lock);
+       oldva.va_mode = zp->z_mode;
+       zfs_fuid_map_ids(zp, cr, &oldva.va_uid, &oldva.va_gid);
+
        mutex_exit(&zp->z_lock);
 
-       if (mask & AT_MODE) {
+       if (mask & ATTR_MODE) {
                if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) {
-                       err = secpolicy_setid_setsticky_clear(vp, vap,
+                       err = secpolicy_setid_setsticky_clear(ip, attr,
                            &oldva, cr);
                        if (err) {
-                               ZFS_EXIT(zfsvfs);
+                               ZFS_EXIT(zsb);
                                return (err);
                        }
-                       trim_mask |= AT_MODE;
+                       trim_mask |= ATTR_MODE;
                } else {
                        need_policy = TRUE;
                }
@@ -2919,65 +2314,65 @@ top:
                 */
 
                if (trim_mask) {
-                       saved_mask = vap->va_mask;
-                       vap->va_mask &= ~trim_mask;
+                       saved_mask = attr->ia_valid;
+                       attr->ia_valid &= ~trim_mask;
                }
-               err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
+               err = secpolicy_vnode_setattr(cr, ip, attr, &oldva, flags,
                    (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp);
                if (err) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (err);
                }
 
                if (trim_mask)
-                       vap->va_mask |= saved_mask;
+                       attr->ia_valid |= saved_mask;
        }
 
        /*
         * secpolicy_vnode_setattr, or take ownership may have
         * changed va_mask
         */
-       mask = vap->va_mask;
+       mask = attr->ia_valid;
 
-       if ((mask & (AT_UID | AT_GID))) {
-               err = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zfsvfs),
+       if ((mask & (ATTR_UID | ATTR_GID))) {
+               err = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zsb),
                    &xattr_obj, sizeof (xattr_obj));
 
                if (err == 0 && xattr_obj) {
-                       err = zfs_zget(zp->z_zfsvfs, xattr_obj, &attrzp);
+                       err = zfs_zget(ZTOZSB(zp), xattr_obj, &attrzp);
                        if (err)
                                goto out2;
                }
-               if (mask & AT_UID) {
-                       new_uid = zfs_fuid_create(zfsvfs,
-                           (uint64_t)vap->va_uid, cr, ZFS_OWNER, &fuidp);
+               if (mask & ATTR_UID) {
+                       new_uid = zfs_fuid_create(zsb,
+                           (uint64_t)attr->ia_uid, cr, ZFS_OWNER, &fuidp);
                        if (new_uid != zp->z_uid &&
-                           zfs_fuid_overquota(zfsvfs, B_FALSE, new_uid)) {
+                           zfs_fuid_overquota(zsb, B_FALSE, new_uid)) {
                                if (attrzp)
-                                       VN_RELE(ZTOV(attrzp));
+                                       iput(ZTOI(attrzp));
                                err = EDQUOT;
                                goto out2;
                        }
                }
 
-               if (mask & AT_GID) {
-                       new_gid = zfs_fuid_create(zfsvfs, (uint64_t)vap->va_gid,
+               if (mask & ATTR_GID) {
+                       new_gid = zfs_fuid_create(zsb, (uint64_t)attr->ia_gid,
                            cr, ZFS_GROUP, &fuidp);
                        if (new_gid != zp->z_gid &&
-                           zfs_fuid_overquota(zfsvfs, B_TRUE, new_gid)) {
+                           zfs_fuid_overquota(zsb, B_TRUE, new_gid)) {
                                if (attrzp)
-                                       VN_RELE(ZTOV(attrzp));
+                                       iput(ZTOI(attrzp));
                                err = EDQUOT;
                                goto out2;
                        }
                }
        }
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
 
-       if (mask & AT_MODE) {
+       if (mask & ATTR_MODE) {
                uint64_t pmode = zp->z_mode;
                uint64_t acl_obj;
-               new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT);
+               new_mode = (pmode & S_IFMT) | (attr->ia_mode & ~S_IFMT);
 
                zfs_acl_chmod_setattr(zp, &aclp, new_mode);
 
@@ -2987,7 +2382,7 @@ top:
                         * Are we upgrading ACL from old V0 format
                         * to V1 format?
                         */
-                       if (zfsvfs->z_version >= ZPL_VERSION_FUID &&
+                       if (zsb->z_version >= ZPL_VERSION_FUID &&
                            zfs_znode_acl_version(zp) ==
                            ZFS_ACL_VERSION_INITIAL) {
                                dmu_tx_hold_free(tx, acl_obj, 0,
@@ -3005,20 +2400,16 @@ top:
                mutex_exit(&zp->z_lock);
                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
        } else {
-               if ((mask & AT_XVATTR) &&
-                   XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP))
-                       dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
-               else
-                       dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
+               dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
        }
 
        if (attrzp) {
                dmu_tx_hold_sa(tx, attrzp->z_sa_hdl, B_FALSE);
        }
 
-       fuid_dirtied = zfsvfs->z_fuid_dirty;
+       fuid_dirtied = zsb->z_fuid_dirty;
        if (fuid_dirtied)
-               zfs_fuid_txhold(zfsvfs, tx);
+               zfs_fuid_txhold(zsb, tx);
 
        zfs_sa_upgrade_txholds(tx, zp);
 
@@ -3039,49 +2430,49 @@ top:
         */
 
 
-       if (mask & (AT_UID|AT_GID|AT_MODE))
+       if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE))
                mutex_enter(&zp->z_acl_lock);
        mutex_enter(&zp->z_lock);
 
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, sizeof (zp->z_pflags));
 
        if (attrzp) {
-               if (mask & (AT_UID|AT_GID|AT_MODE))
+               if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE))
                        mutex_enter(&attrzp->z_acl_lock);
                mutex_enter(&attrzp->z_lock);
                SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
-                   SA_ZPL_FLAGS(zfsvfs), NULL, &attrzp->z_pflags,
+                   SA_ZPL_FLAGS(zsb), NULL, &attrzp->z_pflags,
                    sizeof (attrzp->z_pflags));
        }
 
-       if (mask & (AT_UID|AT_GID)) {
+       if (mask & (ATTR_UID|ATTR_GID)) {
 
-               if (mask & AT_UID) {
-                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
+               if (mask & ATTR_UID) {
+                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zsb), NULL,
                            &new_uid, sizeof (new_uid));
                        zp->z_uid = new_uid;
                        if (attrzp) {
                                SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
-                                   SA_ZPL_UID(zfsvfs), NULL, &new_uid,
+                                   SA_ZPL_UID(zsb), NULL, &new_uid,
                                    sizeof (new_uid));
                                attrzp->z_uid = new_uid;
                        }
                }
 
-               if (mask & AT_GID) {
-                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs),
+               if (mask & ATTR_GID) {
+                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zsb),
                            NULL, &new_gid, sizeof (new_gid));
                        zp->z_gid = new_gid;
                        if (attrzp) {
                                SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
-                                   SA_ZPL_GID(zfsvfs), NULL, &new_gid,
+                                   SA_ZPL_GID(zsb), NULL, &new_gid,
                                    sizeof (new_gid));
                                attrzp->z_gid = new_gid;
                        }
                }
-               if (!(mask & AT_MODE)) {
-                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs),
+               if (!(mask & ATTR_MODE)) {
+                       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb),
                            NULL, &new_mode, sizeof (new_mode));
                        new_mode = zp->z_mode;
                }
@@ -3093,8 +2484,8 @@ top:
                }
        }
 
-       if (mask & AT_MODE) {
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
+       if (mask & ATTR_MODE) {
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb), NULL,
                    &new_mode, sizeof (new_mode));
                zp->z_mode = new_mode;
                ASSERT3U((uintptr_t)aclp, !=, NULL);
@@ -3107,34 +2498,34 @@ top:
        }
 
 
-       if (mask & AT_ATIME) {
-               ZFS_TIME_ENCODE(&vap->va_atime, zp->z_atime);
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
+       if (mask & ATTR_ATIME) {
+               ZFS_TIME_ENCODE(&attr->ia_atime, zp->z_atime);
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zsb), NULL,
                    &zp->z_atime, sizeof (zp->z_atime));
        }
 
-       if (mask & AT_MTIME) {
-               ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
+       if (mask & ATTR_MTIME) {
+               ZFS_TIME_ENCODE(&attr->ia_mtime, mtime);
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL,
                    mtime, sizeof (mtime));
        }
 
        /* XXX - shouldn't this be done *before* the ATIME/MTIME checks? */
-       if (mask & AT_SIZE && !(mask & AT_MTIME)) {
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs),
+       if (mask & ATTR_SIZE && !(mask & ATTR_MTIME)) {
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb),
                    NULL, mtime, sizeof (mtime));
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL,
                    &ctime, sizeof (ctime));
                zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime,
                    B_TRUE);
        } else if (mask != 0) {
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL,
                    &ctime, sizeof (ctime));
                zfs_tstamp_update_setup(zp, STATE_CHANGED, mtime, ctime,
                    B_TRUE);
                if (attrzp) {
                        SA_ADD_BULK_ATTR(xattr_bulk, xattr_count,
-                           SA_ZPL_CTIME(zfsvfs), NULL,
+                           SA_ZPL_CTIME(zsb), NULL,
                            &ctime, sizeof (ctime));
                        zfs_tstamp_update_setup(attrzp, STATE_CHANGED,
                            mtime, ctime, B_TRUE);
@@ -3145,50 +2536,18 @@ top:
         * update from toggling bit
         */
 
-       if (xoap && (mask & AT_XVATTR)) {
-
-               /*
-                * restore trimmed off masks
-                * so that return masks can be set for caller.
-                */
-
-               if (XVA_ISSET_REQ(&tmpxvattr, XAT_APPENDONLY)) {
-                       XVA_SET_REQ(xvap, XAT_APPENDONLY);
-               }
-               if (XVA_ISSET_REQ(&tmpxvattr, XAT_NOUNLINK)) {
-                       XVA_SET_REQ(xvap, XAT_NOUNLINK);
-               }
-               if (XVA_ISSET_REQ(&tmpxvattr, XAT_IMMUTABLE)) {
-                       XVA_SET_REQ(xvap, XAT_IMMUTABLE);
-               }
-               if (XVA_ISSET_REQ(&tmpxvattr, XAT_NODUMP)) {
-                       XVA_SET_REQ(xvap, XAT_NODUMP);
-               }
-               if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_MODIFIED)) {
-                       XVA_SET_REQ(xvap, XAT_AV_MODIFIED);
-               }
-               if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_QUARANTINED)) {
-                       XVA_SET_REQ(xvap, XAT_AV_QUARANTINED);
-               }
-
-               if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP))
-                       ASSERT(vp->v_type == VREG);
-
-               zfs_xvattr_set(zp, xvap, tx);
-       }
-
        if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
+               zfs_fuid_sync(zsb, tx);
 
        if (mask != 0)
-               zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask, fuidp);
+               zfs_log_setattr(zilog, tx, TX_SETATTR, zp, attr, mask, fuidp);
 
        mutex_exit(&zp->z_lock);
-       if (mask & (AT_UID|AT_GID|AT_MODE))
+       if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE))
                mutex_exit(&zp->z_acl_lock);
 
        if (attrzp) {
-               if (mask & (AT_UID|AT_GID|AT_MODE))
+               if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE))
                        mutex_exit(&attrzp->z_acl_lock);
                mutex_exit(&attrzp->z_lock);
        }
@@ -3200,7 +2559,7 @@ out:
        }
 
        if (attrzp)
-               VN_RELE(ZTOV(attrzp));
+               iput(ZTOI(attrzp));
        if (aclp)
                zfs_acl_free(aclp);
 
@@ -3216,15 +2575,17 @@ out:
        } else {
                err2 = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
                dmu_tx_commit(tx);
+               zfs_inode_update(zp);
        }
 
 out2:
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (err);
 }
+EXPORT_SYMBOL(zfs_setattr);
 
 typedef struct zfs_zlock {
        krwlock_t       *zl_rwlock;     /* lock we acquired */
@@ -3242,7 +2603,7 @@ zfs_rename_unlock(zfs_zlock_t **zlpp)
 
        while ((zl = *zlpp) != NULL) {
                if (zl->zl_znode != NULL)
-                       VN_RELE(ZTOV(zl->zl_znode));
+                       iput(ZTOI(zl->zl_znode));
                rw_exit(zl->zl_rwlock);
                *zlpp = zl->zl_next;
                kmem_free(zl, sizeof (*zl));
@@ -3260,7 +2621,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
 {
        zfs_zlock_t     *zl;
        znode_t         *zp = tdzp;
-       uint64_t        rootid = zp->z_zfsvfs->z_root;
+       uint64_t        rootid = ZTOZSB(zp)->z_root;
        uint64_t        oidp = zp->z_id;
        krwlock_t       *rwlp = &szp->z_parent_lock;
        krw_t           rw = RW_WRITER;
@@ -3308,12 +2669,12 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
                        return (0);
 
                if (rw == RW_READER) {          /* i.e. not the first pass */
-                       int error = zfs_zget(zp->z_zfsvfs, oidp, &zp);
+                       int error = zfs_zget(ZTOZSB(zp), oidp, &zp);
                        if (error)
                                return (error);
                        zl->zl_znode = zp;
                }
-               (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(zp->z_zfsvfs),
+               (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_PARENT(ZTOZSB(zp)),
                    &oidp, sizeof (oidp));
                rwlp = &zp->z_parent_lock;
                rw = RW_READER;
@@ -3327,30 +2688,28 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp)
  * Move an entry from the provided source directory to the target
  * directory.  Change the entry name as indicated.
  *
- *     IN:     sdvp    - Source directory containing the "old entry".
+ *     IN:     sdip    - Source directory containing the "old entry".
  *             snm     - Old entry name.
- *             tdvp    - Target directory to contain the "new entry".
+ *             tdip    - Target directory to contain the "new entry".
  *             tnm     - New entry name.
  *             cr      - credentials of caller.
- *             ct      - caller context
  *             flags   - case flags
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     sdvp,tdvp - ctime|mtime updated
+ *     sdip,tdip - ctime|mtime updated
  */
 /*ARGSUSED*/
-static int
-zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
-    caller_context_t *ct, int flags)
+int
+zfs_rename(struct inode *sdip, char *snm, struct inode *tdip, char *tnm,
+    cred_t *cr, int flags)
 {
        znode_t         *tdzp, *szp, *tzp;
-       znode_t         *sdzp = VTOZ(sdvp);
-       zfsvfs_t        *zfsvfs = sdzp->z_zfsvfs;
+       znode_t         *sdzp = ITOZ(sdip);
+       zfs_sb_t        *zsb = ITOZSB(sdip);
        zilog_t         *zilog;
-       vnode_t         *realvp;
        zfs_dirlock_t   *sdl, *tdl;
        dmu_tx_t        *tx;
        zfs_zlock_t     *zl;
@@ -3358,26 +2717,20 @@ zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
        int             error = 0;
        int             zflg = 0;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(sdzp);
-       zilog = zfsvfs->z_log;
-
-       /*
-        * Make sure we have the real vp for the target directory.
-        */
-       if (VOP_REALVP(tdvp, &realvp, ct) == 0)
-               tdvp = realvp;
+       zilog = zsb->z_log;
 
-       if (tdvp->v_vfsp != sdvp->v_vfsp || zfsctl_is_node(tdvp)) {
-               ZFS_EXIT(zfsvfs);
+       if (tdip->i_sb != sdip->i_sb) {
+               ZFS_EXIT(zsb);
                return (EXDEV);
        }
 
-       tdzp = VTOZ(tdvp);
+       tdzp = ITOZ(tdip);
        ZFS_VERIFY_ZP(tdzp);
-       if (zfsvfs->z_utf8 && u8_validate(tnm,
+       if (zsb->z_utf8 && u8_validate(tnm,
            strlen(tnm), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EILSEQ);
        }
 
@@ -3395,7 +2748,7 @@ top:
         * See the comment in zfs_link() for why this is considered bad.
         */
        if ((tdzp->z_pflags & ZFS_XATTR) != (sdzp->z_pflags & ZFS_XATTR)) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
@@ -3414,10 +2767,10 @@ top:
                 * First compare the two name arguments without
                 * considering any case folding.
                 */
-               int nofold = (zfsvfs->z_norm & ~U8_TEXTPREP_TOUPPER);
+               int nofold = (zsb->z_norm & ~U8_TEXTPREP_TOUPPER);
 
                cmp = u8_strcmp(snm, tnm, 0, nofold, U8_UNICODE_LATEST, &error);
-               ASSERT(error == 0 || !zfsvfs->z_utf8);
+               ASSERT(error == 0 || !zsb->z_utf8);
                if (cmp == 0) {
                        /*
                         * POSIX: "If the old argument and the new argument
@@ -3425,7 +2778,7 @@ top:
                         * the rename() function shall return successfully
                         * and perform no other action."
                         */
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (0);
                }
                /*
@@ -3446,10 +2799,10 @@ top:
                 * is an exact match, we will allow this to proceed as
                 * a name-change request.
                 */
-               if ((zfsvfs->z_case == ZFS_CASE_INSENSITIVE ||
-                   (zfsvfs->z_case == ZFS_CASE_MIXED &&
+               if ((zsb->z_case == ZFS_CASE_INSENSITIVE ||
+                   (zsb->z_case == ZFS_CASE_MIXED &&
                    flags & FIGNORECASE)) &&
-                   u8_strcmp(snm, tnm, 0, zfsvfs->z_norm, U8_UNICODE_LATEST,
+                   u8_strcmp(snm, tnm, 0, zsb->z_norm, U8_UNICODE_LATEST,
                    &error) == 0) {
                        /*
                         * case preserving rename request, require exact
@@ -3489,7 +2842,7 @@ top:
                if (!terr) {
                        zfs_dirent_unlock(tdl);
                        if (tzp)
-                               VN_RELE(ZTOV(tzp));
+                               iput(ZTOI(tzp));
                }
 
                if (sdzp == tdzp)
@@ -3497,19 +2850,19 @@ top:
 
                if (strcmp(snm, "..") == 0)
                        serr = EINVAL;
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (serr);
        }
        if (terr) {
                zfs_dirent_unlock(sdl);
-               VN_RELE(ZTOV(szp));
+               iput(ZTOI(szp));
 
                if (sdzp == tdzp)
                        rw_exit(&sdzp->z_name_lock);
 
                if (strcmp(tnm, "..") == 0)
                        terr = EINVAL;
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (terr);
        }
 
@@ -3520,15 +2873,15 @@ top:
         * done in a single check.
         */
 
-       if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))
+       if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)))
                goto out;
 
-       if (ZTOV(szp)->v_type == VDIR) {
+       if (S_ISDIR(ZTOI(szp)->i_mode)) {
                /*
                 * Check to make sure rename is valid.
                 * Can't do a move like this: /usr/a/b to /usr/a/b/c/d
                 */
-               if (error = zfs_rename_lock(szp, tdzp, sdzp, &zl))
+               if ((error = zfs_rename_lock(szp, tdzp, sdzp, &zl)))
                        goto out;
        }
 
@@ -3539,13 +2892,13 @@ top:
                /*
                 * Source and target must be the same type.
                 */
-               if (ZTOV(szp)->v_type == VDIR) {
-                       if (ZTOV(tzp)->v_type != VDIR) {
+               if (S_ISDIR(ZTOI(szp)->i_mode)) {
+                       if (!S_ISDIR(ZTOI(tzp)->i_mode)) {
                                error = ENOTDIR;
                                goto out;
                        }
                } else {
-                       if (ZTOV(tzp)->v_type == VDIR) {
+                       if (S_ISDIR(ZTOI(tzp)->i_mode)) {
                                error = EISDIR;
                                goto out;
                        }
@@ -3561,19 +2914,7 @@ top:
                }
        }
 
-       vnevent_rename_src(ZTOV(szp), sdvp, snm, ct);
-       if (tzp)
-               vnevent_rename_dest(ZTOV(tzp), tdvp, tnm, ct);
-
-       /*
-        * notify the target directory if it is not the same
-        * as source directory.
-        */
-       if (tdvp != sdvp) {
-               vnevent_rename_dest_dir(tdvp, ct);
-       }
-
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_sa(tx, szp->z_sa_hdl, B_FALSE);
        dmu_tx_hold_sa(tx, sdzp->z_sa_hdl, B_FALSE);
        dmu_tx_hold_zap(tx, sdzp->z_id, FALSE, snm);
@@ -3588,7 +2929,7 @@ top:
        }
 
        zfs_sa_upgrade_txholds(tx, szp);
-       dmu_tx_hold_zap(tx, zfsvfs->z_unlinkedobj, FALSE, NULL);
+       dmu_tx_hold_zap(tx, zsb->z_unlinkedobj, FALSE, NULL);
        error = dmu_tx_assign(tx, TXG_NOWAIT);
        if (error) {
                if (zl != NULL)
@@ -3599,16 +2940,16 @@ top:
                if (sdzp == tdzp)
                        rw_exit(&sdzp->z_name_lock);
 
-               VN_RELE(ZTOV(szp));
+               iput(ZTOI(szp));
                if (tzp)
-                       VN_RELE(ZTOV(tzp));
+                       iput(ZTOI(tzp));
                if (error == ERESTART) {
                        dmu_tx_wait(tx);
                        dmu_tx_abort(tx);
                        goto top;
                }
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -3620,7 +2961,7 @@ top:
                if (error == 0) {
                        szp->z_pflags |= ZFS_AV_MODIFIED;
 
-                       error = sa_update(szp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs),
+                       error = sa_update(szp->z_sa_hdl, SA_ZPL_FLAGS(zsb),
                            (void *)&szp->z_pflags, sizeof (uint64_t), tx);
                        ASSERT3U(error, ==, 0);
 
@@ -3629,12 +2970,6 @@ top:
                                zfs_log_rename(zilog, tx, TX_RENAME |
                                    (flags & FIGNORECASE ? TX_CI : 0), sdzp,
                                    sdl->dl_name, tdzp, tdl->dl_name, szp);
-
-                               /*
-                                * Update path information for the target vnode
-                                */
-                               vn_renamepath(tdvp, ZTOV(szp), tnm,
-                                   strlen(tnm));
                        } else {
                                /*
                                 * At this point, we have successfully created
@@ -3662,47 +2997,54 @@ out:
        zfs_dirent_unlock(sdl);
        zfs_dirent_unlock(tdl);
 
+       zfs_inode_update(sdzp);
        if (sdzp == tdzp)
                rw_exit(&sdzp->z_name_lock);
 
+       if (sdzp != tdzp)
+               zfs_inode_update(tdzp);
 
-       VN_RELE(ZTOV(szp));
-       if (tzp)
-               VN_RELE(ZTOV(tzp));
+       zfs_inode_update(szp);
+       iput(ZTOI(szp));
+       if (tzp) {
+               zfs_inode_update(tzp);
+               iput(ZTOI(tzp));
+       }
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_rename);
 
 /*
  * Insert the indicated symbolic reference entry into the directory.
  *
- *     IN:     dvp     - Directory to contain new symbolic link.
+ *     IN:     dip     - Directory to contain new symbolic link.
  *             link    - Name for new symlink entry.
  *             vap     - Attributes of new entry.
  *             target  - Target path of new symlink.
+ *
  *             cr      - credentials of caller.
- *             ct      - caller context
  *             flags   - case flags
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     dvp - ctime|mtime updated
+ *     dip - ctime|mtime updated
  */
 /*ARGSUSED*/
-static int
-zfs_symlink(vnode_t *dvp, char *name, vattr_t *vap, char *link, cred_t *cr,
-    caller_context_t *ct, int flags)
+int
+zfs_symlink(struct inode *dip, char *name, vattr_t *vap, char *link,
+    struct inode **ipp, cred_t *cr, int flags)
 {
-       znode_t         *zp, *dzp = VTOZ(dvp);
+       znode_t         *zp, *dzp = ITOZ(dip);
        zfs_dirlock_t   *dl;
        dmu_tx_t        *tx;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t        *zsb = ITOZSB(dip);
        zilog_t         *zilog;
        uint64_t        len = strlen(link);
        int             error;
@@ -3711,67 +3053,69 @@ zfs_symlink(vnode_t *dvp, char *name, vattr_t *vap, char *link, cred_t *cr,
        boolean_t       fuid_dirtied;
        uint64_t        txtype = TX_SYMLINK;
 
-       ASSERT(vap->va_type == VLNK);
+       ASSERT(S_ISLNK(vap->va_mode));
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(dzp);
-       zilog = zfsvfs->z_log;
+       zilog = zsb->z_log;
 
-       if (zfsvfs->z_utf8 && u8_validate(name, strlen(name),
+       if (zsb->z_utf8 && u8_validate(name, strlen(name),
            NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EILSEQ);
        }
        if (flags & FIGNORECASE)
                zflg |= ZCILOOK;
 
        if (len > MAXPATHLEN) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (ENAMETOOLONG);
        }
 
        if ((error = zfs_acl_ids_create(dzp, 0,
            vap, cr, NULL, &acl_ids)) != 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 top:
+       *ipp = NULL;
+
        /*
         * Attempt to lock directory; fail if entry already exists.
         */
        error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg, NULL, NULL);
        if (error) {
                zfs_acl_ids_free(&acl_ids);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) {
+       if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
                zfs_acl_ids_free(&acl_ids);
                zfs_dirent_unlock(dl);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       if (zfs_acl_ids_overquota(zfsvfs, &acl_ids)) {
+       if (zfs_acl_ids_overquota(zsb, &acl_ids)) {
                zfs_acl_ids_free(&acl_ids);
                zfs_dirent_unlock(dl);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EDQUOT);
        }
-       tx = dmu_tx_create(zfsvfs->z_os);
-       fuid_dirtied = zfsvfs->z_fuid_dirty;
+       tx = dmu_tx_create(zsb->z_os);
+       fuid_dirtied = zsb->z_fuid_dirty;
        dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, MAX(1, len));
        dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
        dmu_tx_hold_sa_create(tx, acl_ids.z_aclp->z_acl_bytes +
            ZFS_SA_BASE_ATTR_SIZE + len);
        dmu_tx_hold_sa(tx, dzp->z_sa_hdl, B_FALSE);
-       if (!zfsvfs->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
+       if (!zsb->z_use_sa && acl_ids.z_aclp->z_acl_bytes > ZFS_ACE_SPACE) {
                dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
                    acl_ids.z_aclp->z_acl_bytes);
        }
        if (fuid_dirtied)
-               zfs_fuid_txhold(zfsvfs, tx);
+               zfs_fuid_txhold(zsb, tx);
        error = dmu_tx_assign(tx, TXG_NOWAIT);
        if (error) {
                zfs_dirent_unlock(dl);
@@ -3782,7 +3126,7 @@ top:
                }
                zfs_acl_ids_free(&acl_ids);
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -3793,18 +3137,18 @@ top:
        zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
 
        if (fuid_dirtied)
-               zfs_fuid_sync(zfsvfs, tx);
+               zfs_fuid_sync(zsb, tx);
 
        mutex_enter(&zp->z_lock);
        if (zp->z_is_sa)
-               error = sa_update(zp->z_sa_hdl, SA_ZPL_SYMLINK(zfsvfs),
+               error = sa_update(zp->z_sa_hdl, SA_ZPL_SYMLINK(zsb),
                    link, len, tx);
        else
                zfs_sa_symlink(zp, link, len, tx);
        mutex_exit(&zp->z_lock);
 
        zp->z_size = len;
-       (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zfsvfs),
+       (void) sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zsb),
            &zp->z_size, sizeof (zp->z_size), tx);
        /*
         * Insert the new object into the directory.
@@ -3815,141 +3159,139 @@ top:
                txtype |= TX_CI;
        zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
 
+       zfs_inode_update(dzp);
+       zfs_inode_update(zp);
+
        zfs_acl_ids_free(&acl_ids);
 
        dmu_tx_commit(tx);
 
        zfs_dirent_unlock(dl);
 
-       VN_RELE(ZTOV(zp));
+       *ipp = ZTOI(zp);
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_symlink);
 
 /*
  * Return, in the buffer contained in the provided uio structure,
- * the symbolic path referred to by vp.
+ * the symbolic path referred to by ip.
  *
- *     IN:     vp      - vnode of symbolic link.
- *             uoip    - structure to contain the link path.
+ *     IN:     ip      - inode of symbolic link
+ *             uio     - structure to contain the link path.
  *             cr      - credentials of caller.
- *             ct      - caller context
- *
- *     OUT:    uio     - structure to contain the link path.
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     vp - atime updated
+ *     ip - atime updated
  */
 /* ARGSUSED */
-static int
-zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct)
+int
+zfs_readlink(struct inode *ip, uio_t *uio, cred_t *cr)
 {
-       znode_t         *zp = VTOZ(vp);
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
        int             error;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
        mutex_enter(&zp->z_lock);
        if (zp->z_is_sa)
                error = sa_lookup_uio(zp->z_sa_hdl,
-                   SA_ZPL_SYMLINK(zfsvfs), uio);
+                   SA_ZPL_SYMLINK(zsb), uio);
        else
                error = zfs_sa_readlink(zp, uio);
        mutex_exit(&zp->z_lock);
 
-       ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
-
-       ZFS_EXIT(zfsvfs);
+       ZFS_ACCESSTIME_STAMP(zsb, zp);
+       zfs_inode_update(zp);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_readlink);
 
 /*
- * Insert a new entry into directory tdvp referencing svp.
+ * Insert a new entry into directory tdip referencing sip.
  *
- *     IN:     tdvp    - Directory to contain new entry.
- *             svp     - vnode of new entry.
+ *     IN:     tdip    - Directory to contain new entry.
+ *             sip     - inode of new entry.
  *             name    - name of new entry.
  *             cr      - credentials of caller.
- *             ct      - caller context
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     tdvp - ctime|mtime updated
- *      svp - ctime updated
+ *     tdip - ctime|mtime updated
+ *      sip - ctime updated
  */
 /* ARGSUSED */
-static int
-zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
-    caller_context_t *ct, int flags)
+int
+zfs_link(struct inode *tdip, struct inode *sip, char *name, cred_t *cr)
 {
-       znode_t         *dzp = VTOZ(tdvp);
+       znode_t         *dzp = ITOZ(tdip);
        znode_t         *tzp, *szp;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t        *zsb = ITOZSB(tdip);
        zilog_t         *zilog;
        zfs_dirlock_t   *dl;
        dmu_tx_t        *tx;
-       vnode_t         *realvp;
        int             error;
        int             zf = ZNEW;
        uint64_t        parent;
        uid_t           owner;
 
-       ASSERT(tdvp->v_type == VDIR);
+       ASSERT(S_ISDIR(tdip->i_mode));
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(dzp);
-       zilog = zfsvfs->z_log;
-
-       if (VOP_REALVP(svp, &realvp, ct) == 0)
-               svp = realvp;
+       zilog = zsb->z_log;
 
        /*
         * POSIX dictates that we return EPERM here.
         * Better choices include ENOTSUP or EISDIR.
         */
-       if (svp->v_type == VDIR) {
-               ZFS_EXIT(zfsvfs);
+       if (S_ISDIR(sip->i_mode)) {
+               ZFS_EXIT(zsb);
                return (EPERM);
        }
 
-       if (svp->v_vfsp != tdvp->v_vfsp || zfsctl_is_node(svp)) {
-               ZFS_EXIT(zfsvfs);
+       if (sip->i_sb != tdip->i_sb) {
+               ZFS_EXIT(zsb);
                return (EXDEV);
        }
 
-       szp = VTOZ(svp);
+       szp = ITOZ(sip);
        ZFS_VERIFY_ZP(szp);
 
        /* Prevent links to .zfs/shares files */
 
-       if ((error = sa_lookup(szp->z_sa_hdl, SA_ZPL_PARENT(zfsvfs),
+       if ((error = sa_lookup(szp->z_sa_hdl, SA_ZPL_PARENT(zsb),
            &parent, sizeof (uint64_t))) != 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
-       if (parent == zfsvfs->z_shares_dir) {
-               ZFS_EXIT(zfsvfs);
+       if (parent == zsb->z_shares_dir) {
+               ZFS_EXIT(zsb);
                return (EPERM);
        }
 
-       if (zfsvfs->z_utf8 && u8_validate(name,
+       if (zsb->z_utf8 && u8_validate(name,
            strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EILSEQ);
        }
+#ifdef HAVE_PN_UTILS
        if (flags & FIGNORECASE)
                zf |= ZCILOOK;
+#endif /* HAVE_PN_UTILS */
 
        /*
         * We do not support links between attributes and non-attributes
@@ -3958,19 +3300,18 @@ zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
         * imposed in attribute space.
         */
        if ((szp->z_pflags & ZFS_XATTR) != (dzp->z_pflags & ZFS_XATTR)) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
-
-       owner = zfs_fuid_map_id(zfsvfs, szp->z_uid, cr, ZFS_OWNER);
+       owner = zfs_fuid_map_id(zsb, szp->z_uid, cr, ZFS_OWNER);
        if (owner != crgetuid(cr) && secpolicy_basic_link(cr) != 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EPERM);
        }
 
-       if (error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr)) {
-               ZFS_EXIT(zfsvfs);
+       if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) {
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -3980,11 +3321,11 @@ top:
         */
        error = zfs_dirent_lock(&dl, dzp, name, &tzp, zf, NULL, NULL);
        if (error) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_sa(tx, szp->z_sa_hdl, B_FALSE);
        dmu_tx_hold_zap(tx, dzp->z_id, TRUE, name);
        zfs_sa_upgrade_txholds(tx, szp);
@@ -3998,7 +3339,7 @@ top:
                        goto top;
                }
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -4006,8 +3347,10 @@ top:
 
        if (error == 0) {
                uint64_t txtype = TX_LINK;
+#ifdef HAVE_PN_UTILS
                if (flags & FIGNORECASE)
                        txtype |= TX_CI;
+#endif /* HAVE_PN_UTILS */
                zfs_log_link(zilog, tx, txtype, dzp, szp, name);
        }
 
@@ -4015,17 +3358,17 @@ top:
 
        zfs_dirent_unlock(dl);
 
-       if (error == 0) {
-               vnevent_link(svp, ct);
-       }
-
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       zfs_inode_update(dzp);
+       zfs_inode_update(szp);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_link);
 
+#ifdef HAVE_MMAP
 /*
  * zfs_null_putapage() is used when the file system has been force
  * unmounted. It just drops the pages.
@@ -4261,48 +3604,28 @@ out:
        ZFS_EXIT(zfsvfs);
        return (error);
 }
+#endif /* HAVE_MMAP */
 
 /*ARGSUSED*/
 void
-zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
+zfs_inactive(struct inode *ip)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
        int error;
 
-       rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_READER);
-       if (zp->z_sa_hdl == NULL) {
-               /*
-                * The fs has been unmounted, or we did a
-                * suspend/resume and this file no longer exists.
-                */
-               if (vn_has_cached_data(vp)) {
-                       (void) pvn_vplist_dirty(vp, 0, zfs_null_putapage,
-                           B_INVAL, cr);
-               }
+#ifdef HAVE_SNAPSHOT
+       /* Early return for snapshot inode? */
+#endif /* HAVE_SNAPSHOT */
 
-               mutex_enter(&zp->z_lock);
-               mutex_enter(&vp->v_lock);
-               ASSERT(vp->v_count == 1);
-               vp->v_count = 0;
-               mutex_exit(&vp->v_lock);
-               mutex_exit(&zp->z_lock);
-               rw_exit(&zfsvfs->z_teardown_inactive_lock);
-               zfs_znode_free(zp);
+       rw_enter(&zsb->z_teardown_inactive_lock, RW_READER);
+       if (zp->z_sa_hdl == NULL) {
+               rw_exit(&zsb->z_teardown_inactive_lock);
                return;
        }
 
-       /*
-        * Attempt to push any data in the page cache.  If this fails
-        * we will get kicked out later in zfs_zinactive().
-        */
-       if (vn_has_cached_data(vp)) {
-               (void) pvn_vplist_dirty(vp, 0, zfs_putapage, B_INVAL|B_ASYNC,
-                   cr);
-       }
-
        if (zp->z_atime_dirty && zp->z_unlinked == 0) {
-               dmu_tx_t *tx = dmu_tx_create(zfsvfs->z_os);
+               dmu_tx_t *tx = dmu_tx_create(zsb->z_os);
 
                dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
                zfs_sa_upgrade_txholds(tx, zp);
@@ -4311,7 +3634,7 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
                        dmu_tx_abort(tx);
                } else {
                        mutex_enter(&zp->z_lock);
-                       (void) sa_update(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs),
+                       (void) sa_update(zp->z_sa_hdl, SA_ZPL_ATIME(zsb),
                            (void *)&zp->z_atime, sizeof (zp->z_atime), tx);
                        zp->z_atime_dirty = 0;
                        mutex_exit(&zp->z_lock);
@@ -4320,13 +3643,14 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
        }
 
        zfs_zinactive(zp);
-       rw_exit(&zfsvfs->z_teardown_inactive_lock);
+       rw_exit(&zsb->z_teardown_inactive_lock);
 }
+EXPORT_SYMBOL(zfs_inactive);
 
 /*
  * Bounds-check the seek operation.
  *
- *     IN:     vp      - vnode seeking within
+ *     IN:     ip      - inode seeking within
  *             ooff    - old file offset
  *             noffp   - pointer to new file offset
  *             ct      - caller context
@@ -4335,15 +3659,17 @@ zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
  *             EINVAL if new offset invalid
  */
 /* ARGSUSED */
-static int
-zfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp,
+int
+zfs_seek(struct inode *ip, offset_t ooff, offset_t *noffp,
     caller_context_t *ct)
 {
-       if (vp->v_type == VDIR)
+       if (S_ISDIR(ip->i_mode))
                return (0);
        return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0);
 }
+EXPORT_SYMBOL(zfs_seek);
 
+#ifdef HAVE_MMAP
 /*
  * Pre-filter the generic locking function to trap attempts to place
  * a mandatory lock on a memory mapped file.
@@ -4688,6 +4014,55 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
 
        return (0);
 }
+#endif /* HAVE_MMAP */
+
+/*
+ * convoff - converts the given data (start, whence) to the
+ * given whence.
+ */
+int
+convoff(struct inode *ip, flock64_t *lckdat, int  whence, offset_t offset)
+{
+       struct kstat stat;
+       int error;
+
+       if ((lckdat->l_whence == 2) || (whence == 2)) {
+               if ((error = zfs_getattr(ip, &stat, 0, CRED()) != 0))
+                       return (error);
+       }
+
+       switch (lckdat->l_whence) {
+       case 1:
+               lckdat->l_start += offset;
+               break;
+       case 2:
+               lckdat->l_start += stat.size;
+               /* FALLTHRU */
+       case 0:
+               break;
+       default:
+               return (EINVAL);
+       }
+
+       if (lckdat->l_start < 0)
+               return (EINVAL);
+
+       switch (whence) {
+       case 1:
+               lckdat->l_start -= offset;
+               break;
+       case 2:
+               lckdat->l_start -= stat.size;
+               /* FALLTHRU */
+       case 0:
+               break;
+       default:
+               return (EINVAL);
+       }
+
+       lckdat->l_whence = (short)whence;
+       return (0);
+}
 
 /*
  * Free or allocate space in a file.  Currently, this function only
@@ -4695,45 +4070,44 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
  * misnamed, as its functionality includes the ability to allocate as
  * well as free space.
  *
- *     IN:     vp      - vnode of file to free data in.
+ *     IN:     ip      - inode of file to free data in.
  *             cmd     - action to take (only F_FREESP supported).
  *             bfp     - section of file to free/alloc.
  *             flag    - current file open mode flags.
  *             offset  - current file offset.
  *             cr      - credentials of caller [UNUSED].
- *             ct      - caller context.
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     vp - ctime|mtime updated
+ *     ip - ctime|mtime updated
  */
 /* ARGSUSED */
-static int
-zfs_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag,
-    offset_t offset, cred_t *cr, caller_context_t *ct)
+int
+zfs_space(struct inode *ip, int cmd, flock64_t *bfp, int flag,
+    offset_t offset, cred_t *cr)
 {
-       znode_t         *zp = VTOZ(vp);
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
        uint64_t        off, len;
        int             error;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
        if (cmd != F_FREESP) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
-       if (error = convoff(vp, bfp, 0, offset)) {
-               ZFS_EXIT(zfsvfs);
+       if ((error = convoff(ip, bfp, 0, offset))) {
+               ZFS_EXIT(zsb);
                return (error);
        }
 
        if (bfp->l_len < 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
@@ -4742,37 +4116,38 @@ zfs_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag,
 
        error = zfs_freesp(zp, off, len, flag, TRUE);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_space);
 
 /*ARGSUSED*/
-static int
-zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
+int
+zfs_fid(struct inode *ip, fid_t *fidp)
 {
-       znode_t         *zp = VTOZ(vp);
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
        uint32_t        gen;
        uint64_t        gen64;
        uint64_t        object = zp->z_id;
        zfid_short_t    *zfid;
        int             size, i, error;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
-       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zfsvfs),
+       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_GEN(zsb),
            &gen64, sizeof (uint64_t))) != 0) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
        gen = (uint32_t)gen64;
 
-       size = (zfsvfs->z_parent != zfsvfs) ? LONG_FID_LEN : SHORT_FID_LEN;
+       size = (zsb->z_parent != zsb) ? LONG_FID_LEN : SHORT_FID_LEN;
        if (fidp->fid_len < size) {
                fidp->fid_len = size;
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (ENOSPC);
        }
 
@@ -4790,7 +4165,7 @@ zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
                zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));
 
        if (size == LONG_FID_LEN) {
-               uint64_t        objsetid = dmu_objset_id(zfsvfs->z_os);
+               uint64_t        objsetid = dmu_objset_id(zsb->z_os);
                zfid_long_t     *zlfid;
 
                zlfid = (zfid_long_t *)fidp;
@@ -4803,139 +4178,70 @@ zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
                        zlfid->zf_setgen[i] = 0;
        }
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (0);
 }
-
-static int
-zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
-    caller_context_t *ct)
-{
-       znode_t         *zp, *xzp;
-       zfsvfs_t        *zfsvfs;
-       zfs_dirlock_t   *dl;
-       int             error;
-
-       switch (cmd) {
-       case _PC_LINK_MAX:
-               *valp = ULONG_MAX;
-               return (0);
-
-       case _PC_FILESIZEBITS:
-               *valp = 64;
-               return (0);
-
-       case _PC_XATTR_EXISTS:
-               zp = VTOZ(vp);
-               zfsvfs = zp->z_zfsvfs;
-               ZFS_ENTER(zfsvfs);
-               ZFS_VERIFY_ZP(zp);
-               *valp = 0;
-               error = zfs_dirent_lock(&dl, zp, "", &xzp,
-                   ZXATTR | ZEXISTS | ZSHARED, NULL, NULL);
-               if (error == 0) {
-                       zfs_dirent_unlock(dl);
-                       if (!zfs_dirempty(xzp))
-                               *valp = 1;
-                       VN_RELE(ZTOV(xzp));
-               } else if (error == ENOENT) {
-                       /*
-                        * If there aren't extended attributes, it's the
-                        * same as having zero of them.
-                        */
-                       error = 0;
-               }
-               ZFS_EXIT(zfsvfs);
-               return (error);
-
-       case _PC_SATTR_ENABLED:
-       case _PC_SATTR_EXISTS:
-               *valp = vfs_has_feature(vp->v_vfsp, VFSFT_SYSATTR_VIEWS) &&
-                   (vp->v_type == VREG || vp->v_type == VDIR);
-               return (0);
-
-       case _PC_ACCESS_FILTERING:
-               *valp = vfs_has_feature(vp->v_vfsp, VFSFT_ACCESS_FILTER) &&
-                   vp->v_type == VDIR;
-               return (0);
-
-       case _PC_ACL_ENABLED:
-               *valp = _ACL_ACE_ENABLED;
-               return (0);
-
-       case _PC_MIN_HOLE_SIZE:
-               *valp = (ulong_t)SPA_MINBLOCKSIZE;
-               return (0);
-
-       case _PC_TIMESTAMP_RESOLUTION:
-               /* nanosecond timestamp resolution */
-               *valp = 1L;
-               return (0);
-
-       default:
-               return (fs_pathconf(vp, cmd, valp, cr, ct));
-       }
-}
+EXPORT_SYMBOL(zfs_fid);
 
 /*ARGSUSED*/
-static int
-zfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr,
-    caller_context_t *ct)
+int
+zfs_getsecattr(struct inode *ip, vsecattr_t *vsecp, int flag, cred_t *cr)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
        int error;
        boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
        error = zfs_getacl(zp, vsecp, skipaclchk, cr);
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
 
        return (error);
 }
+EXPORT_SYMBOL(zfs_getsecattr);
 
 /*ARGSUSED*/
-static int
-zfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr,
-    caller_context_t *ct)
+int
+zfs_setsecattr(struct inode *ip, vsecattr_t *vsecp, int flag, cred_t *cr)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
        int error;
        boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
-       zilog_t *zilog = zfsvfs->z_log;
+       zilog_t *zilog = zsb->z_log;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
        error = zfs_setacl(zp, vsecp, skipaclchk, cr);
 
-       if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+       if (zsb->z_os->os_sync == ZFS_SYNC_ALWAYS)
                zil_commit(zilog, 0);
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
+EXPORT_SYMBOL(zfs_setsecattr);
 
+#ifdef HAVE_UIO_ZEROCOPY
 /*
  * Tunable, both must be a power of 2.
  *
  * zcr_blksz_min: the smallest read we may consider to loan out an arcbuf
  * zcr_blksz_max: if set to less than the file block size, allow loaning out of
- *                an arcbuf for a partial block read
+ *             an arcbuf for a partial block read
  */
 int zcr_blksz_min = (1 << 10); /* 1K */
 int zcr_blksz_max = (1 << 17); /* 128K */
 
 /*ARGSUSED*/
 static int
-zfs_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr,
-    caller_context_t *ct)
+zfs_reqzcbuf(struct inode *ip, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr)
 {
-       znode_t *zp = VTOZ(vp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-       int max_blksz = zfsvfs->z_max_blksz;
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ITOZSB(ip);
+       int max_blksz = zsb->z_max_blksz;
        uio_t *uio = &xuio->xu_uio;
        ssize_t size = uio->uio_resid;
        offset_t offset = uio->uio_loffset;
@@ -4948,7 +4254,7 @@ zfs_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr,
        if (xuio->xu_type != UIOTYPE_ZEROCOPY)
                return (EINVAL);
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
        switch (ioflag) {
        case UIO_WRITE:
@@ -4958,7 +4264,7 @@ zfs_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr,
                 */
                blksz = max_blksz;
                if (size < blksz || zp->z_blksz != blksz) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (EINVAL);
                }
                /*
@@ -4981,9 +4287,6 @@ zfs_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr,
                fullblk = size / blksz;
                (void) dmu_xuio_init(xuio,
                    (preamble != 0) + fullblk + (postamble != 0));
-               DTRACE_PROBE3(zfs_reqzcbuf_align, int, preamble,
-                   int, postamble, int,
-                   (preamble != 0) + fullblk + (postamble != 0));
 
                /*
                 * Have to fix iov base/len for partial buffers.  They
@@ -5026,7 +4329,7 @@ zfs_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr,
                        blksz = zcr_blksz_max;
                /* avoid potential complexity of dealing with it */
                if (blksz > max_blksz) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (EINVAL);
                }
 
@@ -5034,25 +4337,25 @@ zfs_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *xuio, cred_t *cr,
                if (size > maxsize)
                        size = maxsize;
 
-               if (size < blksz || vn_has_cached_data(vp)) {
-                       ZFS_EXIT(zfsvfs);
+               if (size < blksz) {
+                       ZFS_EXIT(zsb);
                        return (EINVAL);
                }
                break;
        default:
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (EINVAL);
        }
 
        uio->uio_extflg = UIO_XUIO;
        XUIO_XUZC_RW(xuio) = ioflag;
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (0);
 }
 
 /*ARGSUSED*/
 static int
-zfs_retzcbuf(vnode_t *vp, xuio_t *xuio, cred_t *cr, caller_context_t *ct)
+zfs_retzcbuf(struct inode *ip, xuio_t *xuio, cred_t *cr)
 {
        int i;
        arc_buf_t *abuf;
@@ -5075,174 +4378,4 @@ zfs_retzcbuf(vnode_t *vp, xuio_t *xuio, cred_t *cr, caller_context_t *ct)
        dmu_xuio_fini(xuio);
        return (0);
 }
-
-/*
- * Predeclare these here so that the compiler assumes that
- * this is an "old style" function declaration that does
- * not include arguments => we won't get type mismatch errors
- * in the initializations that follow.
- */
-static int zfs_inval();
-static int zfs_isdir();
-
-static int
-zfs_inval()
-{
-       return (EINVAL);
-}
-
-static int
-zfs_isdir()
-{
-       return (EISDIR);
-}
-/*
- * Directory vnode operations template
- */
-vnodeops_t *zfs_dvnodeops;
-const fs_operation_def_t zfs_dvnodeops_template[] = {
-       VOPNAME_OPEN,           { .vop_open = zfs_open },
-       VOPNAME_CLOSE,          { .vop_close = zfs_close },
-       VOPNAME_READ,           { .error = zfs_isdir },
-       VOPNAME_WRITE,          { .error = zfs_isdir },
-       VOPNAME_IOCTL,          { .vop_ioctl = zfs_ioctl },
-       VOPNAME_GETATTR,        { .vop_getattr = zfs_getattr },
-       VOPNAME_SETATTR,        { .vop_setattr = zfs_setattr },
-       VOPNAME_ACCESS,         { .vop_access = zfs_access },
-       VOPNAME_LOOKUP,         { .vop_lookup = zfs_lookup },
-       VOPNAME_CREATE,         { .vop_create = zfs_create },
-       VOPNAME_REMOVE,         { .vop_remove = zfs_remove },
-       VOPNAME_LINK,           { .vop_link = zfs_link },
-       VOPNAME_RENAME,         { .vop_rename = zfs_rename },
-       VOPNAME_MKDIR,          { .vop_mkdir = zfs_mkdir },
-       VOPNAME_RMDIR,          { .vop_rmdir = zfs_rmdir },
-       VOPNAME_READDIR,        { .vop_readdir = zfs_readdir },
-       VOPNAME_SYMLINK,        { .vop_symlink = zfs_symlink },
-       VOPNAME_FSYNC,          { .vop_fsync = zfs_fsync },
-       VOPNAME_INACTIVE,       { .vop_inactive = zfs_inactive },
-       VOPNAME_FID,            { .vop_fid = zfs_fid },
-       VOPNAME_SEEK,           { .vop_seek = zfs_seek },
-       VOPNAME_PATHCONF,       { .vop_pathconf = zfs_pathconf },
-       VOPNAME_GETSECATTR,     { .vop_getsecattr = zfs_getsecattr },
-       VOPNAME_SETSECATTR,     { .vop_setsecattr = zfs_setsecattr },
-       VOPNAME_VNEVENT,        { .vop_vnevent = fs_vnevent_support },
-       NULL,                   NULL
-};
-
-/*
- * Regular file vnode operations template
- */
-vnodeops_t *zfs_fvnodeops;
-const fs_operation_def_t zfs_fvnodeops_template[] = {
-       VOPNAME_OPEN,           { .vop_open = zfs_open },
-       VOPNAME_CLOSE,          { .vop_close = zfs_close },
-       VOPNAME_READ,           { .vop_read = zfs_read },
-       VOPNAME_WRITE,          { .vop_write = zfs_write },
-       VOPNAME_IOCTL,          { .vop_ioctl = zfs_ioctl },
-       VOPNAME_GETATTR,        { .vop_getattr = zfs_getattr },
-       VOPNAME_SETATTR,        { .vop_setattr = zfs_setattr },
-       VOPNAME_ACCESS,         { .vop_access = zfs_access },
-       VOPNAME_LOOKUP,         { .vop_lookup = zfs_lookup },
-       VOPNAME_RENAME,         { .vop_rename = zfs_rename },
-       VOPNAME_FSYNC,          { .vop_fsync = zfs_fsync },
-       VOPNAME_INACTIVE,       { .vop_inactive = zfs_inactive },
-       VOPNAME_FID,            { .vop_fid = zfs_fid },
-       VOPNAME_SEEK,           { .vop_seek = zfs_seek },
-       VOPNAME_FRLOCK,         { .vop_frlock = zfs_frlock },
-       VOPNAME_SPACE,          { .vop_space = zfs_space },
-       VOPNAME_GETPAGE,        { .vop_getpage = zfs_getpage },
-       VOPNAME_PUTPAGE,        { .vop_putpage = zfs_putpage },
-       VOPNAME_MAP,            { .vop_map = zfs_map },
-       VOPNAME_ADDMAP,         { .vop_addmap = zfs_addmap },
-       VOPNAME_DELMAP,         { .vop_delmap = zfs_delmap },
-       VOPNAME_PATHCONF,       { .vop_pathconf = zfs_pathconf },
-       VOPNAME_GETSECATTR,     { .vop_getsecattr = zfs_getsecattr },
-       VOPNAME_SETSECATTR,     { .vop_setsecattr = zfs_setsecattr },
-       VOPNAME_VNEVENT,        { .vop_vnevent = fs_vnevent_support },
-       VOPNAME_REQZCBUF,       { .vop_reqzcbuf = zfs_reqzcbuf },
-       VOPNAME_RETZCBUF,       { .vop_retzcbuf = zfs_retzcbuf },
-       NULL,                   NULL
-};
-
-/*
- * Symbolic link vnode operations template
- */
-vnodeops_t *zfs_symvnodeops;
-const fs_operation_def_t zfs_symvnodeops_template[] = {
-       VOPNAME_GETATTR,        { .vop_getattr = zfs_getattr },
-       VOPNAME_SETATTR,        { .vop_setattr = zfs_setattr },
-       VOPNAME_ACCESS,         { .vop_access = zfs_access },
-       VOPNAME_RENAME,         { .vop_rename = zfs_rename },
-       VOPNAME_READLINK,       { .vop_readlink = zfs_readlink },
-       VOPNAME_INACTIVE,       { .vop_inactive = zfs_inactive },
-       VOPNAME_FID,            { .vop_fid = zfs_fid },
-       VOPNAME_PATHCONF,       { .vop_pathconf = zfs_pathconf },
-       VOPNAME_VNEVENT,        { .vop_vnevent = fs_vnevent_support },
-       NULL,                   NULL
-};
-
-/*
- * special share hidden files vnode operations template
- */
-vnodeops_t *zfs_sharevnodeops;
-const fs_operation_def_t zfs_sharevnodeops_template[] = {
-       VOPNAME_GETATTR,        { .vop_getattr = zfs_getattr },
-       VOPNAME_ACCESS,         { .vop_access = zfs_access },
-       VOPNAME_INACTIVE,       { .vop_inactive = zfs_inactive },
-       VOPNAME_FID,            { .vop_fid = zfs_fid },
-       VOPNAME_PATHCONF,       { .vop_pathconf = zfs_pathconf },
-       VOPNAME_GETSECATTR,     { .vop_getsecattr = zfs_getsecattr },
-       VOPNAME_SETSECATTR,     { .vop_setsecattr = zfs_setsecattr },
-       VOPNAME_VNEVENT,        { .vop_vnevent = fs_vnevent_support },
-       NULL,                   NULL
-};
-
-/*
- * Extended attribute directory vnode operations template
- *     This template is identical to the directory vnodes
- *     operation template except for restricted operations:
- *             VOP_MKDIR()
- *             VOP_SYMLINK()
- * Note that there are other restrictions embedded in:
- *     zfs_create()    - restrict type to VREG
- *     zfs_link()      - no links into/out of attribute space
- *     zfs_rename()    - no moves into/out of attribute space
- */
-vnodeops_t *zfs_xdvnodeops;
-const fs_operation_def_t zfs_xdvnodeops_template[] = {
-       VOPNAME_OPEN,           { .vop_open = zfs_open },
-       VOPNAME_CLOSE,          { .vop_close = zfs_close },
-       VOPNAME_IOCTL,          { .vop_ioctl = zfs_ioctl },
-       VOPNAME_GETATTR,        { .vop_getattr = zfs_getattr },
-       VOPNAME_SETATTR,        { .vop_setattr = zfs_setattr },
-       VOPNAME_ACCESS,         { .vop_access = zfs_access },
-       VOPNAME_LOOKUP,         { .vop_lookup = zfs_lookup },
-       VOPNAME_CREATE,         { .vop_create = zfs_create },
-       VOPNAME_REMOVE,         { .vop_remove = zfs_remove },
-       VOPNAME_LINK,           { .vop_link = zfs_link },
-       VOPNAME_RENAME,         { .vop_rename = zfs_rename },
-       VOPNAME_MKDIR,          { .error = zfs_inval },
-       VOPNAME_RMDIR,          { .vop_rmdir = zfs_rmdir },
-       VOPNAME_READDIR,        { .vop_readdir = zfs_readdir },
-       VOPNAME_SYMLINK,        { .error = zfs_inval },
-       VOPNAME_FSYNC,          { .vop_fsync = zfs_fsync },
-       VOPNAME_INACTIVE,       { .vop_inactive = zfs_inactive },
-       VOPNAME_FID,            { .vop_fid = zfs_fid },
-       VOPNAME_SEEK,           { .vop_seek = zfs_seek },
-       VOPNAME_PATHCONF,       { .vop_pathconf = zfs_pathconf },
-       VOPNAME_GETSECATTR,     { .vop_getsecattr = zfs_getsecattr },
-       VOPNAME_SETSECATTR,     { .vop_setsecattr = zfs_setsecattr },
-       VOPNAME_VNEVENT,        { .vop_vnevent = fs_vnevent_support },
-       NULL,                   NULL
-};
-
-/*
- * Error vnode operations template
- */
-vnodeops_t *zfs_evnodeops;
-const fs_operation_def_t zfs_evnodeops_template[] = {
-       VOPNAME_INACTIVE,       { .vop_inactive = zfs_inactive },
-       VOPNAME_PATHCONF,       { .vop_pathconf = zfs_pathconf },
-       NULL,                   NULL
-};
-#endif /* HAVE_ZPL */
+#endif /* HAVE_UIO_ZEROCOPY */
index 4f6185f..56ac2ab 100644 (file)
 #include <sys/zfs_ioctl.h>
 #include <sys/zfs_rlock.h>
 #include <sys/zfs_fuid.h>
+#include <sys/zfs_vnops.h>
 #include <sys/dnode.h>
 #include <sys/fs/zfs.h>
 #include <sys/kidmap.h>
+#include <sys/zpl.h>
 #endif /* _KERNEL */
 
 #include <sys/dmu.h>
  * (such as VFS logic) that will not compile easily in userland.
  */
 #ifdef _KERNEL
-#ifdef HAVE_ZPL
-/*
- * Needed to close a small window in zfs_znode_move() that allows the zfsvfs to
- * be freed before it can be safely accessed.
- */
-krwlock_t zfsvfs_lock;
 
 static kmem_cache_t *znode_cache = NULL;
 
 /*ARGSUSED*/
-static void
-znode_evict_error(dmu_buf_t *dbuf, void *user_ptr)
-{
-       /*
-        * We should never drop all dbuf refs without first clearing
-        * the eviction callback.
-        */
-       panic("evicting znode %p\n", user_ptr);
-}
-
-/*ARGSUSED*/
 static int
 zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
 {
        znode_t *zp = buf;
 
-       ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
-
-       zp->z_vnode = vn_alloc(kmflags);
-       if (zp->z_vnode == NULL) {
-               return (-1);
-       }
-       ZTOV(zp)->v_data = zp;
-
+       inode_init_once(ZTOI(zp));
        list_link_init(&zp->z_link_node);
 
        mutex_init(&zp->z_lock, NULL, MUTEX_DEFAULT, NULL);
@@ -145,9 +123,6 @@ zfs_znode_cache_destructor(void *buf, void *arg)
 {
        znode_t *zp = buf;
 
-       ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
-       ASSERT(ZTOV(zp)->v_data == zp);
-       vn_free(ZTOV(zp));
        ASSERT(!list_link_active(&zp->z_link_node));
        mutex_destroy(&zp->z_lock);
        rw_destroy(&zp->z_parent_lock);
@@ -160,315 +135,33 @@ zfs_znode_cache_destructor(void *buf, void *arg)
        ASSERT(zp->z_acl_cached == NULL);
 }
 
-#ifdef ZNODE_STATS
-static struct {
-       uint64_t zms_zfsvfs_invalid;
-       uint64_t zms_zfsvfs_recheck1;
-       uint64_t zms_zfsvfs_unmounted;
-       uint64_t zms_zfsvfs_recheck2;
-       uint64_t zms_obj_held;
-       uint64_t zms_vnode_locked;
-       uint64_t zms_not_only_dnlc;
-} znode_move_stats;
-#endif /* ZNODE_STATS */
-
-static void
-zfs_znode_move_impl(znode_t *ozp, znode_t *nzp)
-{
-       vnode_t *vp;
-
-       /* Copy fields. */
-       nzp->z_zfsvfs = ozp->z_zfsvfs;
-
-       /* Swap vnodes. */
-       vp = nzp->z_vnode;
-       nzp->z_vnode = ozp->z_vnode;
-       ozp->z_vnode = vp; /* let destructor free the overwritten vnode */
-       ZTOV(ozp)->v_data = ozp;
-       ZTOV(nzp)->v_data = nzp;
-
-       nzp->z_id = ozp->z_id;
-       ASSERT(ozp->z_dirlocks == NULL); /* znode not in use */
-       ASSERT(avl_numnodes(&ozp->z_range_avl) == 0);
-       nzp->z_unlinked = ozp->z_unlinked;
-       nzp->z_atime_dirty = ozp->z_atime_dirty;
-       nzp->z_zn_prefetch = ozp->z_zn_prefetch;
-       nzp->z_blksz = ozp->z_blksz;
-       nzp->z_seq = ozp->z_seq;
-       nzp->z_mapcnt = ozp->z_mapcnt;
-       nzp->z_gen = ozp->z_gen;
-       nzp->z_sync_cnt = ozp->z_sync_cnt;
-       nzp->z_is_sa = ozp->z_is_sa;
-       nzp->z_sa_hdl = ozp->z_sa_hdl;
-       bcopy(ozp->z_atime, nzp->z_atime, sizeof (uint64_t) * 2);
-       nzp->z_links = ozp->z_links;
-       nzp->z_size = ozp->z_size;
-       nzp->z_pflags = ozp->z_pflags;
-       nzp->z_uid = ozp->z_uid;
-       nzp->z_gid = ozp->z_gid;
-       nzp->z_mode = ozp->z_mode;
-
-       /*
-        * Since this is just an idle znode and kmem is already dealing with
-        * memory pressure, release any cached ACL.
-        */
-       if (ozp->z_acl_cached) {
-               zfs_acl_free(ozp->z_acl_cached);
-               ozp->z_acl_cached = NULL;
-       }
-
-       sa_set_userp(nzp->z_sa_hdl, nzp);
-
-       /*
-        * Invalidate the original znode by clearing fields that provide a
-        * pointer back to the znode. Set the low bit of the vfs pointer to
-        * ensure that zfs_znode_move() recognizes the znode as invalid in any
-        * subsequent callback.
-        */
-       ozp->z_sa_hdl = NULL;
-       POINTER_INVALIDATE(&ozp->z_zfsvfs);
-
-       /*
-        * Mark the znode.
-        */
-       nzp->z_moved = 1;
-       ozp->z_moved = (uint8_t)-1;
-}
-
-/*ARGSUSED*/
-static kmem_cbrc_t
-zfs_znode_move(void *buf, void *newbuf, size_t size, void *arg)
-{
-       znode_t *ozp = buf, *nzp = newbuf;
-       zfsvfs_t *zfsvfs;
-       vnode_t *vp;
-
-       /*
-        * The znode is on the file system's list of known znodes if the vfs
-        * pointer is valid. We set the low bit of the vfs pointer when freeing
-        * the znode to invalidate it, and the memory patterns written by kmem
-        * (baddcafe and deadbeef) set at least one of the two low bits. A newly
-        * created znode sets the vfs pointer last of all to indicate that the
-        * znode is known and in a valid state to be moved by this function.
-        */
-       zfsvfs = ozp->z_zfsvfs;
-       if (!POINTER_IS_VALID(zfsvfs)) {
-               ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_invalid);
-               return (KMEM_CBRC_DONT_KNOW);
-       }
-
-       /*
-        * Close a small window in which it's possible that the filesystem could
-        * be unmounted and freed, and zfsvfs, though valid in the previous
-        * statement, could point to unrelated memory by the time we try to
-        * prevent the filesystem from being unmounted.
-        */
-       rw_enter(&zfsvfs_lock, RW_WRITER);
-       if (zfsvfs != ozp->z_zfsvfs) {
-               rw_exit(&zfsvfs_lock);
-               ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck1);
-               return (KMEM_CBRC_DONT_KNOW);
-       }
-
-       /*
-        * If the znode is still valid, then so is the file system. We know that
-        * no valid file system can be freed while we hold zfsvfs_lock, so we
-        * can safely ensure that the filesystem is not and will not be
-        * unmounted. The next statement is equivalent to ZFS_ENTER().
-        */
-       rrw_enter(&zfsvfs->z_teardown_lock, RW_READER, FTAG);
-       if (zfsvfs->z_unmounted) {
-               ZFS_EXIT(zfsvfs);
-               rw_exit(&zfsvfs_lock);
-               ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_unmounted);
-               return (KMEM_CBRC_DONT_KNOW);
-       }
-       rw_exit(&zfsvfs_lock);
-
-       mutex_enter(&zfsvfs->z_znodes_lock);
-       /*
-        * Recheck the vfs pointer in case the znode was removed just before
-        * acquiring the lock.
-        */
-       if (zfsvfs != ozp->z_zfsvfs) {
-               mutex_exit(&zfsvfs->z_znodes_lock);
-               ZFS_EXIT(zfsvfs);
-               ZNODE_STAT_ADD(znode_move_stats.zms_zfsvfs_recheck2);
-               return (KMEM_CBRC_DONT_KNOW);
-       }
-
-       /*
-        * At this point we know that as long as we hold z_znodes_lock, the
-        * znode cannot be freed and fields within the znode can be safely
-        * accessed. Now, prevent a race with zfs_zget().
-        */
-       if (ZFS_OBJ_HOLD_TRYENTER(zfsvfs, ozp->z_id) == 0) {
-               mutex_exit(&zfsvfs->z_znodes_lock);
-               ZFS_EXIT(zfsvfs);
-               ZNODE_STAT_ADD(znode_move_stats.zms_obj_held);
-               return (KMEM_CBRC_LATER);
-       }
-
-       vp = ZTOV(ozp);
-       if (mutex_tryenter(&vp->v_lock) == 0) {
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
-               mutex_exit(&zfsvfs->z_znodes_lock);
-               ZFS_EXIT(zfsvfs);
-               ZNODE_STAT_ADD(znode_move_stats.zms_vnode_locked);
-               return (KMEM_CBRC_LATER);
-       }
-
-       /* Only move znodes that are referenced _only_ by the DNLC. */
-       if (vp->v_count != 1 || !vn_in_dnlc(vp)) {
-               mutex_exit(&vp->v_lock);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
-               mutex_exit(&zfsvfs->z_znodes_lock);
-               ZFS_EXIT(zfsvfs);
-               ZNODE_STAT_ADD(znode_move_stats.zms_not_only_dnlc);
-               return (KMEM_CBRC_LATER);
-       }
-
-       /*
-        * The znode is known and in a valid state to move. We're holding the
-        * locks needed to execute the critical section.
-        */
-       zfs_znode_move_impl(ozp, nzp);
-       mutex_exit(&vp->v_lock);
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, ozp->z_id);
-
-       list_link_replace(&ozp->z_link_node, &nzp->z_link_node);
-       mutex_exit(&zfsvfs->z_znodes_lock);
-       ZFS_EXIT(zfsvfs);
-
-       return (KMEM_CBRC_YES);
-}
-
 void
 zfs_znode_init(void)
 {
        /*
         * Initialize zcache
         */
-       rw_init(&zfsvfs_lock, NULL, RW_DEFAULT, NULL);
        ASSERT(znode_cache == NULL);
        znode_cache = kmem_cache_create("zfs_znode_cache",
            sizeof (znode_t), 0, zfs_znode_cache_constructor,
-           zfs_znode_cache_destructor, NULL, NULL, NULL, 0);
-       kmem_cache_set_move(znode_cache, zfs_znode_move);
+           zfs_znode_cache_destructor, NULL, NULL, NULL, KMC_KMEM);
 }
 
 void
 zfs_znode_fini(void)
 {
        /*
-        * Cleanup vfs & vnode ops
-        */
-       zfs_remove_op_tables();
-
-       /*
         * Cleanup zcache
         */
        if (znode_cache)
                kmem_cache_destroy(znode_cache);
        znode_cache = NULL;
-       rw_destroy(&zfsvfs_lock);
-}
-
-struct vnodeops *zfs_dvnodeops;
-struct vnodeops *zfs_fvnodeops;
-struct vnodeops *zfs_symvnodeops;
-struct vnodeops *zfs_xdvnodeops;
-struct vnodeops *zfs_evnodeops;
-struct vnodeops *zfs_sharevnodeops;
-
-void
-zfs_remove_op_tables()
-{
-       /*
-        * Remove vfs ops
-        */
-       ASSERT(zfsfstype);
-       (void) vfs_freevfsops_by_type(zfsfstype);
-       zfsfstype = 0;
-
-       /*
-        * Remove vnode ops
-        */
-       if (zfs_dvnodeops)
-               vn_freevnodeops(zfs_dvnodeops);
-       if (zfs_fvnodeops)
-               vn_freevnodeops(zfs_fvnodeops);
-       if (zfs_symvnodeops)
-               vn_freevnodeops(zfs_symvnodeops);
-       if (zfs_xdvnodeops)
-               vn_freevnodeops(zfs_xdvnodeops);
-       if (zfs_evnodeops)
-               vn_freevnodeops(zfs_evnodeops);
-       if (zfs_sharevnodeops)
-               vn_freevnodeops(zfs_sharevnodeops);
-
-       zfs_dvnodeops = NULL;
-       zfs_fvnodeops = NULL;
-       zfs_symvnodeops = NULL;
-       zfs_xdvnodeops = NULL;
-       zfs_evnodeops = NULL;
-       zfs_sharevnodeops = NULL;
-}
-
-extern const fs_operation_def_t zfs_dvnodeops_template[];
-extern const fs_operation_def_t zfs_fvnodeops_template[];
-extern const fs_operation_def_t zfs_xdvnodeops_template[];
-extern const fs_operation_def_t zfs_symvnodeops_template[];
-extern const fs_operation_def_t zfs_evnodeops_template[];
-extern const fs_operation_def_t zfs_sharevnodeops_template[];
-
-int
-zfs_create_op_tables()
-{
-       int error;
-
-       /*
-        * zfs_dvnodeops can be set if mod_remove() calls mod_installfs()
-        * due to a failure to remove the the 2nd modlinkage (zfs_modldrv).
-        * In this case we just return as the ops vectors are already set up.
-        */
-       if (zfs_dvnodeops)
-               return (0);
-
-       error = vn_make_ops(MNTTYPE_ZFS, zfs_dvnodeops_template,
-           &zfs_dvnodeops);
-       if (error)
-               return (error);
-
-       error = vn_make_ops(MNTTYPE_ZFS, zfs_fvnodeops_template,
-           &zfs_fvnodeops);
-       if (error)
-               return (error);
-
-       error = vn_make_ops(MNTTYPE_ZFS, zfs_symvnodeops_template,
-           &zfs_symvnodeops);
-       if (error)
-               return (error);
-
-       error = vn_make_ops(MNTTYPE_ZFS, zfs_xdvnodeops_template,
-           &zfs_xdvnodeops);
-       if (error)
-               return (error);
-
-       error = vn_make_ops(MNTTYPE_ZFS, zfs_evnodeops_template,
-           &zfs_evnodeops);
-       if (error)
-               return (error);
-
-       error = vn_make_ops(MNTTYPE_ZFS, zfs_sharevnodeops_template,
-           &zfs_sharevnodeops);
-
-       return (error);
 }
 
 int
-zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
+zfs_create_share_dir(zfs_sb_t *zsb, dmu_tx_t *tx)
 {
+#ifdef HAVE_SHARE
        zfs_acl_ids_t acl_ids;
        vattr_t vattr;
        znode_t *sharezp;
@@ -477,13 +170,11 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
        int error;
 
        vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
-       vattr.va_type = VDIR;
-       vattr.va_mode = S_IFDIR|0555;
+       vattr.va_mode = S_IFDIR | 0555;
        vattr.va_uid = crgetuid(kcred);
        vattr.va_gid = crgetgid(kcred);
 
        sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP);
-       ASSERT(!POINTER_IS_VALID(sharezp->z_zfsvfs));
        sharezp->z_moved = 0;
        sharezp->z_unlinked = 0;
        sharezp->z_atime_dirty = 0;
@@ -505,11 +196,14 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
        zfsvfs->z_shares_dir = sharezp->z_id;
 
        zfs_acl_ids_free(&acl_ids);
-       ZTOV(sharezp)->v_count = 0;
+       // ZTOV(sharezp)->v_count = 0;
        sa_handle_destroy(sharezp->z_sa_hdl);
        kmem_cache_free(znode_cache, sharezp);
 
        return (error);
+#else
+       return (0);
+#endif /* HAVE_SHARE */
 }
 
 /*
@@ -546,42 +240,18 @@ zfs_expldev(dev_t dev)
 #endif
 }
 
-/*
- * Special cmpldev for ZFS private use.
- * Can't use standard cmpldev since it takes
- * a long dev_t and compresses it to dev32_t in
- * LP64.  We need to do a compaction of a long dev_t
- * to a dev32_t in ILP32.
- */
-dev_t
-zfs_cmpldev(uint64_t dev)
-{
-#ifndef _LP64
-       minor_t minor = (minor_t)dev & MAXMIN64;
-       major_t major = (major_t)(dev >> NBITSMINOR64) & MAXMAJ64;
-
-       if (major > MAXMAJ32 || minor > MAXMIN32)
-               return (NODEV32);
-
-       return (((dev32_t)major << NBITSMINOR32) | minor);
-#else
-       return (dev);
-#endif
-}
-
 static void
-zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
+zfs_znode_sa_init(zfs_sb_t *zsb, znode_t *zp,
     dmu_buf_t *db, dmu_object_type_t obj_type, sa_handle_t *sa_hdl)
 {
-       ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs) || (zfsvfs == zp->z_zfsvfs));
-       ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zfsvfs, zp->z_id)));
+       ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zsb, zp->z_id)));
 
        mutex_enter(&zp->z_lock);
 
        ASSERT(zp->z_sa_hdl == NULL);
        ASSERT(zp->z_acl_cached == NULL);
        if (sa_hdl == NULL) {
-               VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, zp,
+               VERIFY(0 == sa_handle_get_from_db(zsb->z_os, db, zp,
                    SA_HDL_SHARED, &zp->z_sa_hdl));
        } else {
                zp->z_sa_hdl = sa_hdl;
@@ -590,55 +260,119 @@ zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
 
        zp->z_is_sa = (obj_type == DMU_OT_SA) ? B_TRUE : B_FALSE;
 
-       /*
-        * Slap on VROOT if we are the root znode
-        */
-       if (zp->z_id == zfsvfs->z_root)
-               ZTOV(zp)->v_flag |= VROOT;
-
        mutex_exit(&zp->z_lock);
-       vn_exists(ZTOV(zp));
 }
 
 void
 zfs_znode_dmu_fini(znode_t *zp)
 {
-       ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(zp->z_zfsvfs, zp->z_id)) ||
+       ASSERT(MUTEX_HELD(ZFS_OBJ_MUTEX(ZTOZSB(zp), zp->z_id)) ||
            zp->z_unlinked ||
-           RW_WRITE_HELD(&zp->z_zfsvfs->z_teardown_inactive_lock));
+           RW_WRITE_HELD(&ZTOZSB(zp)->z_teardown_inactive_lock));
 
        sa_handle_destroy(zp->z_sa_hdl);
        zp->z_sa_hdl = NULL;
 }
 
 /*
- * Construct a new znode/vnode and intialize.
+ * Called by new_inode() to allocate a new inode.
+ */
+int
+zfs_inode_alloc(struct super_block *sb, struct inode **ip)
+{
+       znode_t *zp;
+
+       zp = kmem_cache_alloc(znode_cache, KM_SLEEP);
+       *ip = ZTOI(zp);
+
+       return (0);
+}
+
+/*
+ * Called in multiple places when an inode should be destroyed.
+ */
+void
+zfs_inode_destroy(struct inode *ip)
+{
+       znode_t *zp = ITOZ(ip);
+       zfs_sb_t *zsb = ZTOZSB(zp);
+
+       mutex_enter(&zsb->z_znodes_lock);
+       list_remove(&zsb->z_all_znodes, zp);
+       mutex_exit(&zsb->z_znodes_lock);
+
+       if (zp->z_acl_cached) {
+               zfs_acl_free(zp->z_acl_cached);
+               zp->z_acl_cached = NULL;
+       }
+
+       kmem_cache_free(znode_cache, zp);
+}
+
+static void
+zfs_inode_set_ops(zfs_sb_t *zsb, struct inode *ip)
+{
+       uint64_t rdev;
+
+       switch (ip->i_mode & S_IFMT) {
+       case S_IFREG:
+               ip->i_op = &zpl_inode_operations;
+               ip->i_fop = &zpl_file_operations;
+               ip->i_mapping->a_ops = &zpl_address_space_operations;
+               break;
+
+       case S_IFDIR:
+               ip->i_op = &zpl_dir_inode_operations;
+               ip->i_fop = &zpl_dir_file_operations;
+               ITOZ(ip)->z_zn_prefetch = B_TRUE;
+               break;
+
+       case S_IFLNK:
+               ip->i_op = &zpl_symlink_inode_operations;
+               break;
+
+       case S_IFCHR:
+       case S_IFBLK:
+       case S_IFIFO:
+       case S_IFSOCK:
+               VERIFY(sa_lookup(ITOZ(ip)->z_sa_hdl, SA_ZPL_RDEV(zsb),
+                   &rdev, sizeof (rdev)) == 0);
+               init_special_inode(ip, ip->i_mode, rdev);
+               ip->i_op = &zpl_special_inode_operations;
+               break;
+
+       default:
+               printk("ZFS: Invalid mode: 0x%x\n", ip->i_mode);
+               VERIFY(0);
+       }
+}
+
+/*
+ * Construct a znode+inode and initialize.
  *
  * This does not do a call to dmu_set_user() that is
  * up to the caller to do, in case you don't want to
  * return the znode
  */
 static znode_t *
-zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
-    dmu_object_type_t obj_type, sa_handle_t *hdl)
+zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
+    dmu_object_type_t obj_type, uint64_t obj, sa_handle_t *hdl)
 {
        znode_t *zp;
-       vnode_t *vp;
-       uint64_t mode;
+       struct inode *ip;
        uint64_t parent;
        sa_bulk_attr_t bulk[9];
        int count = 0;
 
-       zp = kmem_cache_alloc(znode_cache, KM_SLEEP);
+       ASSERT(zsb != NULL);
+
+       ip = new_inode(zsb->z_sb);
+       if (ip == NULL)
+               return (NULL);
 
+       zp = ITOZ(ip);
        ASSERT(zp->z_dirlocks == NULL);
-       ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
        zp->z_moved = 0;
-
-       /*
-        * Defer setting z_zfsvfs until the znode is ready to be a candidate for
-        * the zfs_znode_move() callback.
-        */
        zp->z_sa_hdl = NULL;
        zp->z_unlinked = 0;
        zp->z_atime_dirty = 0;
@@ -648,93 +382,89 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
        zp->z_seq = 0x7A4653;
        zp->z_sync_cnt = 0;
 
-       vp = ZTOV(zp);
-       vn_reinit(vp);
-
-       zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
+       zfs_znode_sa_init(zsb, zp, db, obj_type, hdl);
 
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL, &zp->z_gen, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
-           &zp->z_size, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
-           &zp->z_links, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb), NULL, &zp->z_mode, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zsb), NULL, &zp->z_gen, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb), NULL, &zp->z_size, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb), NULL, &zp->z_links, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zsb), NULL,
+           &parent, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zsb), NULL,
            &zp->z_atime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
-           &zp->z_uid, 8);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
-           &zp->z_gid, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zsb), NULL, &zp->z_uid, 8);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zsb), NULL, &zp->z_gid, 8);
 
        if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
                if (hdl == NULL)
                        sa_handle_destroy(zp->z_sa_hdl);
-               kmem_cache_free(znode_cache, zp);
-               return (NULL);
-       }
 
-       zp->z_mode = mode;
-       vp->v_vfsp = zfsvfs->z_parent->z_vfs;
+               goto error;
+       }
 
-       vp->v_type = IFTOVT((mode_t)mode);
+       ip->i_ino = obj;
+       ip->i_mode = zp->z_mode;
+       ip->i_mtime = ip->i_atime = ip->i_ctime = CURRENT_TIME_SEC;
+       zfs_inode_set_ops(zsb, ip);
 
-       switch (vp->v_type) {
-       case VDIR:
-               if (zp->z_pflags & ZFS_XATTR) {
-                       vn_setops(vp, zfs_xdvnodeops);
-                       vp->v_flag |= V_XATTRDIR;
-               } else {
-                       vn_setops(vp, zfs_dvnodeops);
-               }
-               zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
-               break;
-       case VBLK:
-       case VCHR:
-               {
-                       uint64_t rdev;
-                       VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
-                           &rdev, sizeof (rdev)) == 0);
-
-                       vp->v_rdev = zfs_cmpldev(rdev);
-               }
-               /*FALLTHROUGH*/
-       case VFIFO:
-       case VSOCK:
-       case VDOOR:
-               vn_setops(vp, zfs_fvnodeops);
-               break;
-       case VREG:
-               vp->v_flag |= VMODSORT;
-               if (parent == zfsvfs->z_shares_dir) {
-                       ASSERT(zp->z_uid == 0 && zp->z_gid == 0);
-                       vn_setops(vp, zfs_sharevnodeops);
-               } else {
-                       vn_setops(vp, zfs_fvnodeops);
-               }
-               break;
-       case VLNK:
-               vn_setops(vp, zfs_symvnodeops);
-               break;
-       default:
-               vn_setops(vp, zfs_evnodeops);
-               break;
-       }
+       if (insert_inode_locked(ip))
+               goto error;
 
-       mutex_enter(&zfsvfs->z_znodes_lock);
-       list_insert_tail(&zfsvfs->z_all_znodes, zp);
+       mutex_enter(&zsb->z_znodes_lock);
+       list_insert_tail(&zsb->z_all_znodes, zp);
        membar_producer();
-       /*
-        * Everything else must be valid before assigning z_zfsvfs makes the
-        * znode eligible for zfs_znode_move().
-        */
-       zp->z_zfsvfs = zfsvfs;
-       mutex_exit(&zfsvfs->z_znodes_lock);
+       mutex_exit(&zsb->z_znodes_lock);
 
-       VFS_HOLD(zfsvfs->z_vfs);
+       unlock_new_inode(ip);
        return (zp);
+
+error:
+       unlock_new_inode(ip);
+       iput(ip);
+       return NULL;
+}
+
+/*
+ * Update the embedded inode given the znode.  We should work toward
+ * eliminating this function as soon as possible by removing values
+ * which are duplicated between the znode and inode.  If the generic
+ * inode has the correct field it should be used, and the ZFS code
+ * updated to access the inode.  This can be done incrementally.
+ */
+void
+zfs_inode_update(znode_t *zp)
+{
+       zfs_sb_t        *zsb;
+       struct inode    *ip;
+       uint32_t        blksize;
+       uint64_t        atime[2], mtime[2], ctime[2];
+
+       ASSERT(zp != NULL);
+       zsb = ZTOZSB(zp);
+       ip = ZTOI(zp);
+
+       sa_lookup(zp->z_sa_hdl, SA_ZPL_ATIME(zsb), &atime, 16);
+       sa_lookup(zp->z_sa_hdl, SA_ZPL_MTIME(zsb), &mtime, 16);
+       sa_lookup(zp->z_sa_hdl, SA_ZPL_CTIME(zsb), &ctime, 16);
+
+       spin_lock(&ip->i_lock);
+       ip->i_generation = zp->z_gen;
+       ip->i_uid = zp->z_uid;
+       ip->i_gid = zp->z_gid;
+       ip->i_nlink = zp->z_links;
+       ip->i_mode = zp->z_mode;
+       ip->i_blkbits = SPA_MINBLOCKSHIFT;
+       dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &blksize,
+           (u_longlong_t *)&ip->i_blocks);
+
+       ZFS_TIME_DECODE(&ip->i_atime, atime);
+       ZFS_TIME_DECODE(&ip->i_mtime, mtime);
+       ZFS_TIME_DECODE(&ip->i_ctime, ctime);
+
+       i_size_write(ip, zp->z_size);
+       spin_unlock(&ip->i_lock);
 }
 
 static uint64_t empty_xattr;
@@ -765,7 +495,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        uint64_t        mode, size, links, parent, pflags;
        uint64_t        dzp_pflags = 0;
        uint64_t        rdev = 0;
-       zfsvfs_t        *zfsvfs = dzp->z_zfsvfs;
+       zfs_sb_t        *zsb = ZTOZSB(dzp);
        dmu_buf_t       *db;
        timestruc_t     now;
        uint64_t        gen, obj;
@@ -773,13 +503,11 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        int             bonuslen;
        sa_handle_t     *sa_hdl;
        dmu_object_type_t obj_type;
-       sa_bulk_attr_t  sa_attrs[ZPL_END];
+       sa_bulk_attr_t  *sa_attrs;
        int             cnt = 0;
        zfs_acl_locator_cb_t locate = { 0 };
 
-       ASSERT(vap && (vap->va_mask & (AT_TYPE|AT_MODE)) == (AT_TYPE|AT_MODE));
-
-       if (zfsvfs->z_replay) {
+       if (zsb->z_replay) {
                obj = vap->va_nodeid;
                now = vap->va_ctime;            /* see zfs_replay_create() */
                gen = vap->va_nblocks;          /* ditto */
@@ -789,7 +517,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
                gen = dmu_tx_get_txg(tx);
        }
 
-       obj_type = zfsvfs->z_use_sa ? DMU_OT_SA : DMU_OT_ZNODE;
+       obj_type = zsb->z_use_sa ? DMU_OT_SA : DMU_OT_ZNODE;
        bonuslen = (obj_type == DMU_OT_SA) ?
            DN_MAX_BONUSLEN : ZFS_OLD_ZNODE_PHYS_SIZE;
 
@@ -802,32 +530,32 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
         * that there will be an i/o error and we will fail one of the
         * assertions below.
         */
-       if (vap->va_type == VDIR) {
-               if (zfsvfs->z_replay) {
-                       err = zap_create_claim_norm(zfsvfs->z_os, obj,
-                           zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS,
+       if (S_ISDIR(vap->va_mode)) {
+               if (zsb->z_replay) {
+                       err = zap_create_claim_norm(zsb->z_os, obj,
+                           zsb->z_norm, DMU_OT_DIRECTORY_CONTENTS,
                            obj_type, bonuslen, tx);
                        ASSERT3U(err, ==, 0);
                } else {
-                       obj = zap_create_norm(zfsvfs->z_os,
-                           zfsvfs->z_norm, DMU_OT_DIRECTORY_CONTENTS,
+                       obj = zap_create_norm(zsb->z_os,
+                           zsb->z_norm, DMU_OT_DIRECTORY_CONTENTS,
                            obj_type, bonuslen, tx);
                }
        } else {
-               if (zfsvfs->z_replay) {
-                       err = dmu_object_claim(zfsvfs->z_os, obj,
+               if (zsb->z_replay) {
+                       err = dmu_object_claim(zsb->z_os, obj,
                            DMU_OT_PLAIN_FILE_CONTENTS, 0,
                            obj_type, bonuslen, tx);
                        ASSERT3U(err, ==, 0);
                } else {
-                       obj = dmu_object_alloc(zfsvfs->z_os,
+                       obj = dmu_object_alloc(zsb->z_os,
                            DMU_OT_PLAIN_FILE_CONTENTS, 0,
                            obj_type, bonuslen, tx);
                }
        }
 
-       ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
-       VERIFY(0 == sa_buf_hold(zfsvfs->z_os, obj, NULL, &db));
+       ZFS_OBJ_HOLD_ENTER(zsb, obj);
+       VERIFY(0 == sa_buf_hold(zsb->z_os, obj, NULL, &db));
 
        /*
         * If this is the root, fix up the half-initialized parent pointer
@@ -846,21 +574,21 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
                flag |= IS_XATTR;
        }
 
-       if (zfsvfs->z_use_fuids)
+       if (zsb->z_use_fuids)
                pflags = ZFS_ARCHIVE | ZFS_AV_MODIFIED;
        else
                pflags = 0;
 
-       if (vap->va_type == VDIR) {
+       if (S_ISDIR(vap->va_mode)) {
                size = 2;               /* contents ("." and "..") */
                links = (flag & (IS_ROOT_NODE | IS_XATTR)) ? 2 : 1;
        } else {
                size = links = 0;
        }
 
-       if (vap->va_type == VBLK || vap->va_type == VCHR) {
+       if (S_ISBLK(vap->va_mode)  || S_ISCHR(vap->va_mode) ||
+           S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))
                rdev = zfs_expldev(vap->va_rdev);
-       }
 
        parent = dzp->z_id;
        mode = acl_ids->z_mode;
@@ -877,20 +605,20 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        ZFS_TIME_ENCODE(&now, crtime);
        ZFS_TIME_ENCODE(&now, ctime);
 
-       if (vap->va_mask & AT_ATIME) {
+       if (vap->va_mask & ATTR_ATIME) {
                ZFS_TIME_ENCODE(&vap->va_atime, atime);
        } else {
                ZFS_TIME_ENCODE(&now, atime);
        }
 
-       if (vap->va_mask & AT_MTIME) {
+       if (vap->va_mask & ATTR_MTIME) {
                ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
        } else {
                ZFS_TIME_ENCODE(&now, mtime);
        }
 
        /* Now add in all of the "SA" attributes */
-       VERIFY(0 == sa_handle_get_from_db(zfsvfs->z_os, db, NULL, SA_HDL_SHARED,
+       VERIFY(0 == sa_handle_get_from_db(zsb->z_os, db, NULL, SA_HDL_SHARED,
            &sa_hdl));
 
        /*
@@ -899,77 +627,78 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
         * order for  DMU_OT_ZNODE is critical since it needs to be constructed
         * in the old znode_phys_t format.  Don't change this ordering
         */
+       sa_attrs = kmem_alloc(sizeof(sa_bulk_attr_t) * ZPL_END, KM_SLEEP);
 
        if (obj_type == DMU_OT_ZNODE) {
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zsb),
                    NULL, &atime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zsb),
                    NULL, &mtime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zsb),
                    NULL, &ctime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zsb),
                    NULL, &crtime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zsb),
                    NULL, &gen, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zsb),
                    NULL, &mode, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zsb),
                    NULL, &size, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zsb),
                    NULL, &parent, 8);
        } else {
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MODE(zsb),
                    NULL, &mode, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_SIZE(zsb),
                    NULL, &size, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GEN(zsb),
                    NULL, &gen, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL,
-                   &acl_ids->z_fuid, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL,
-                   &acl_ids->z_fgid, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zsb),
+                   NULL, &acl_ids->z_fuid, 8);
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zsb),
+                   NULL, &acl_ids->z_fgid, 8);
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PARENT(zsb),
                    NULL, &parent, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zsb),
                    NULL, &pflags, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ATIME(zsb),
                    NULL, &atime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_MTIME(zsb),
                    NULL, &mtime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CTIME(zsb),
                    NULL, &ctime, 16);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_CRTIME(zsb),
                    NULL, &crtime, 16);
        }
 
-       SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_LINKS(zfsvfs), NULL, &links, 8);
+       SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_LINKS(zsb), NULL, &links, 8);
 
        if (obj_type == DMU_OT_ZNODE) {
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_XATTR(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_XATTR(zsb), NULL,
                    &empty_xattr, 8);
        }
        if (obj_type == DMU_OT_ZNODE ||
-           (vap->va_type == VBLK || vap->va_type == VCHR)) {
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zfsvfs),
+           (S_ISBLK(vap->va_mode)  || S_ISCHR(vap->va_mode) ||
+            S_ISFIFO(vap->va_mode) || S_ISSOCK(vap->va_mode))) {
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_RDEV(zsb),
                    NULL, &rdev, 8);
-
        }
        if (obj_type == DMU_OT_ZNODE) {
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_FLAGS(zsb),
                    NULL, &pflags, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_UID(zsb), NULL,
                    &acl_ids->z_fuid, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_GID(zsb), NULL,
                    &acl_ids->z_fgid, 8);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PAD(zfsvfs), NULL, pad,
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_PAD(zsb), NULL, pad,
                    sizeof (uint64_t) * 4);
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_ZNODE_ACL(zsb), NULL,
                    &acl_phys, sizeof (zfs_acl_phys_t));
        } else if (acl_ids->z_aclp->z_version >= ZFS_ACL_VERSION_FUID) {
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_COUNT(zfsvfs), NULL,
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_COUNT(zsb), NULL,
                    &acl_ids->z_aclp->z_acl_count, 8);
                locate.cb_aclp = acl_ids->z_aclp;
-               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zfsvfs),
+               SA_ADD_BULK_ATTR(sa_attrs, cnt, SA_ZPL_DACL_ACES(zsb),
                    zfs_acl_data_locator, &locate,
                    acl_ids->z_aclp->z_acl_bytes);
                mode = zfs_mode_compute(mode, acl_ids->z_aclp, &pflags,
@@ -979,8 +708,11 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        VERIFY(sa_replace_all_by_template(sa_hdl, sa_attrs, cnt, tx) == 0);
 
        if (!(flag & IS_ROOT_NODE)) {
-               *zpp = zfs_znode_alloc(zfsvfs, db, 0, obj_type, sa_hdl);
+               *zpp = zfs_znode_alloc(zsb, db, 0, obj_type, obj, sa_hdl);
                ASSERT(*zpp != NULL);
+               ASSERT(dzp != NULL);
+               err = zpl_xattr_security_init(ZTOI(*zpp), ZTOI(dzp));
+               ASSERT3S(err, ==, 0);
        } else {
                /*
                 * If we are creating the root node, the "parent" we
@@ -994,115 +726,17 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        (*zpp)->z_pflags = pflags;
        (*zpp)->z_mode = mode;
 
-       if (vap->va_mask & AT_XVATTR)
-               zfs_xvattr_set(*zpp, (xvattr_t *)vap, tx);
-
        if (obj_type == DMU_OT_ZNODE ||
            acl_ids->z_aclp->z_version < ZFS_ACL_VERSION_FUID) {
                err = zfs_aclset_common(*zpp, acl_ids->z_aclp, cr, tx);
-               ASSERT3P(err, ==, 0);
-       }
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
-}
-
-/*
- * zfs_xvattr_set only updates the in-core attributes
- * it is assumed the caller will be doing an sa_bulk_update
- * to push the changes out
- */
-void
-zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
-{
-       xoptattr_t *xoap;
-
-       xoap = xva_getxoptattr(xvap);
-       ASSERT(xoap);
-
-       if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
-               uint64_t times[2];
-               ZFS_TIME_ENCODE(&xoap->xoa_createtime, times);
-               (void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(zp->z_zfsvfs),
-                   &times, sizeof (times), tx);
-               XVA_SET_RTN(xvap, XAT_CREATETIME);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
-               ZFS_ATTR_SET(zp, ZFS_READONLY, xoap->xoa_readonly,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_READONLY);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
-               ZFS_ATTR_SET(zp, ZFS_HIDDEN, xoap->xoa_hidden,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_HIDDEN);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
-               ZFS_ATTR_SET(zp, ZFS_SYSTEM, xoap->xoa_system,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_SYSTEM);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
-               ZFS_ATTR_SET(zp, ZFS_ARCHIVE, xoap->xoa_archive,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_ARCHIVE);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) {
-               ZFS_ATTR_SET(zp, ZFS_IMMUTABLE, xoap->xoa_immutable,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_IMMUTABLE);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) {
-               ZFS_ATTR_SET(zp, ZFS_NOUNLINK, xoap->xoa_nounlink,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_NOUNLINK);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) {
-               ZFS_ATTR_SET(zp, ZFS_APPENDONLY, xoap->xoa_appendonly,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_APPENDONLY);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) {
-               ZFS_ATTR_SET(zp, ZFS_NODUMP, xoap->xoa_nodump,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_NODUMP);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) {
-               ZFS_ATTR_SET(zp, ZFS_OPAQUE, xoap->xoa_opaque,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_OPAQUE);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) {
-               ZFS_ATTR_SET(zp, ZFS_AV_QUARANTINED,
-                   xoap->xoa_av_quarantined, zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_AV_QUARANTINED);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) {
-               ZFS_ATTR_SET(zp, ZFS_AV_MODIFIED, xoap->xoa_av_modified,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_AV_MODIFIED);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) {
-               zfs_sa_set_scanstamp(zp, xvap, tx);
-               XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
-               ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_REPARSE);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) {
-               ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_OFFLINE);
-       }
-       if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) {
-               ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse,
-                   zp->z_pflags, tx);
-               XVA_SET_RTN(xvap, XAT_SPARSE);
+               ASSERT3S(err, ==, 0);
        }
+       kmem_free(sa_attrs, sizeof(sa_bulk_attr_t) * ZPL_END);
+       ZFS_OBJ_HOLD_EXIT(zsb, obj);
 }
 
 int
-zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
+zfs_zget(zfs_sb_t *zsb, uint64_t obj_num, znode_t **zpp)
 {
        dmu_object_info_t doi;
        dmu_buf_t       *db;
@@ -1112,11 +746,11 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
 
        *zpp = NULL;
 
-       ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
+       ZFS_OBJ_HOLD_ENTER(zsb, obj_num);
 
-       err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
+       err = sa_buf_hold(zsb->z_os, obj_num, NULL, &db);
        if (err) {
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (err);
        }
 
@@ -1126,7 +760,7 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
            (doi.doi_bonus_type == DMU_OT_ZNODE &&
            doi.doi_bonus_size < sizeof (znode_phys_t)))) {
                sa_buf_rele(db, NULL);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (EINVAL);
        }
 
@@ -1148,19 +782,18 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
                if (zp->z_unlinked) {
                        err = ENOENT;
                } else {
-                       VN_HOLD(ZTOV(zp));
+                       igrab(ZTOI(zp));
                        *zpp = zp;
                        err = 0;
                }
                sa_buf_rele(db, NULL);
                mutex_exit(&zp->z_lock);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (err);
        }
 
        /*
-        * Not found create new znode/vnode
-        * but only if file exists.
+        * Not found create new znode/vnode but only if file exists.
         *
         * There is a small window where zfs_vget() could
         * find this object while a file create is still in
@@ -1169,21 +802,21 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_num, znode_t **zpp)
         * if zfs_znode_alloc() fails it will drop the hold on the
         * bonus buffer.
         */
-       zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size,
-           doi.doi_bonus_type, NULL);
+       zp = zfs_znode_alloc(zsb, db, doi.doi_data_block_size,
+           doi.doi_bonus_type, obj_num, NULL);
        if (zp == NULL) {
                err = ENOENT;
        } else {
                *zpp = zp;
        }
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+       ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
        return (err);
 }
 
 int
 zfs_rezget(znode_t *zp)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        dmu_object_info_t doi;
        dmu_buf_t *db;
        uint64_t obj_num = zp->z_id;
@@ -1193,7 +826,7 @@ zfs_rezget(znode_t *zp)
        int count = 0;
        uint64_t gen;
 
-       ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
+       ZFS_OBJ_HOLD_ENTER(zsb, obj_num);
 
        mutex_enter(&zp->z_acl_lock);
        if (zp->z_acl_cached) {
@@ -1203,9 +836,9 @@ zfs_rezget(znode_t *zp)
 
        mutex_exit(&zp->z_acl_lock);
        ASSERT(zp->z_sa_hdl == NULL);
-       err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
+       err = sa_buf_hold(zsb->z_os, obj_num, NULL, &db);
        if (err) {
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (err);
        }
 
@@ -1215,33 +848,33 @@ zfs_rezget(znode_t *zp)
            (doi.doi_bonus_type == DMU_OT_ZNODE &&
            doi.doi_bonus_size < sizeof (znode_phys_t)))) {
                sa_buf_rele(db, NULL);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (EINVAL);
        }
 
-       zfs_znode_sa_init(zfsvfs, zp, db, doi.doi_bonus_type, NULL);
+       zfs_znode_sa_init(zsb, zp, db, doi.doi_bonus_type, NULL);
 
        /* reload cached values */
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GEN(zsb), NULL,
            &gen, sizeof (gen));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb), NULL,
            &zp->z_size, sizeof (zp->z_size));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_LINKS(zsb), NULL,
            &zp->z_links, sizeof (zp->z_links));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb), NULL,
            &zp->z_pflags, sizeof (zp->z_pflags));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zsb), NULL,
            &zp->z_atime, sizeof (zp->z_atime));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zsb), NULL,
            &zp->z_uid, sizeof (zp->z_uid));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zsb), NULL,
            &zp->z_gid, sizeof (zp->z_gid));
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zsb), NULL,
            &mode, sizeof (mode));
 
        if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) {
                zfs_znode_dmu_fini(zp);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (EIO);
        }
 
@@ -1249,14 +882,14 @@ zfs_rezget(znode_t *zp)
 
        if (gen != zp->z_gen) {
                zfs_znode_dmu_fini(zp);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+               ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
                return (EIO);
        }
 
        zp->z_unlinked = (zp->z_links == 0);
        zp->z_blksz = doi.doi_data_block_size;
 
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+       ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
 
        return (0);
 }
@@ -1264,27 +897,25 @@ zfs_rezget(znode_t *zp)
 void
 zfs_znode_delete(znode_t *zp, dmu_tx_t *tx)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-       objset_t *os = zfsvfs->z_os;
+       zfs_sb_t *zsb = ZTOZSB(zp);
+       objset_t *os = zsb->z_os;
        uint64_t obj = zp->z_id;
        uint64_t acl_obj = zfs_external_acl(zp);
 
-       ZFS_OBJ_HOLD_ENTER(zfsvfs, obj);
+       ZFS_OBJ_HOLD_ENTER(zsb, obj);
        if (acl_obj) {
                VERIFY(!zp->z_is_sa);
                VERIFY(0 == dmu_object_free(os, acl_obj, tx));
        }
        VERIFY(0 == dmu_object_free(os, obj, tx));
        zfs_znode_dmu_fini(zp);
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
-       zfs_znode_free(zp);
+       ZFS_OBJ_HOLD_EXIT(zsb, obj);
 }
 
 void
 zfs_zinactive(znode_t *zp)
 {
-       vnode_t *vp = ZTOV(zp);
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        uint64_t z_id = zp->z_id;
 
        ASSERT(zp->z_sa_hdl);
@@ -1292,29 +923,8 @@ zfs_zinactive(znode_t *zp)
        /*
         * Don't allow a zfs_zget() while were trying to release this znode
         */
-       ZFS_OBJ_HOLD_ENTER(zfsvfs, z_id);
-
+       ZFS_OBJ_HOLD_ENTER(zsb, z_id);
        mutex_enter(&zp->z_lock);
-       mutex_enter(&vp->v_lock);
-       vp->v_count--;
-       if (vp->v_count > 0 || vn_has_cached_data(vp)) {
-               /*
-                * If the hold count is greater than zero, somebody has
-                * obtained a new reference on this znode while we were
-                * processing it here, so we are done.  If we still have
-                * mapped pages then we are also done, since we don't
-                * want to inactivate the znode until the pages get pushed.
-                *
-                * XXX - if vn_has_cached_data(vp) is true, but count == 0,
-                * this seems like it would leave the znode hanging with
-                * no chance to go inactive...
-                */
-               mutex_exit(&vp->v_lock);
-               mutex_exit(&zp->z_lock);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
-               return;
-       }
-       mutex_exit(&vp->v_lock);
 
        /*
         * If this was the last reference to a file with no links,
@@ -1322,39 +932,14 @@ zfs_zinactive(znode_t *zp)
         */
        if (zp->z_unlinked) {
                mutex_exit(&zp->z_lock);
-               ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
+               ZFS_OBJ_HOLD_EXIT(zsb, z_id);
                zfs_rmnode(zp);
                return;
        }
 
        mutex_exit(&zp->z_lock);
        zfs_znode_dmu_fini(zp);
-       ZFS_OBJ_HOLD_EXIT(zfsvfs, z_id);
-       zfs_znode_free(zp);
-}
-
-void
-zfs_znode_free(znode_t *zp)
-{
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-
-       vn_invalid(ZTOV(zp));
-
-       ASSERT(ZTOV(zp)->v_count == 0);
-
-       mutex_enter(&zfsvfs->z_znodes_lock);
-       POINTER_INVALIDATE(&zp->z_zfsvfs);
-       list_remove(&zfsvfs->z_all_znodes, zp);
-       mutex_exit(&zfsvfs->z_znodes_lock);
-
-       if (zp->z_acl_cached) {
-               zfs_acl_free(zp->z_acl_cached);
-               zp->z_acl_cached = NULL;
-       }
-
-       kmem_cache_free(znode_cache, zp);
-
-       VFS_RELE(zfsvfs->z_vfs);
+       ZFS_OBJ_HOLD_EXIT(zsb, z_id);
 }
 
 void
@@ -1372,21 +957,21 @@ zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
                zp->z_atime_dirty = 1;
        }
 
-       if (flag & AT_ATIME) {
+       if (flag & ATTR_ATIME) {
                ZFS_TIME_ENCODE(&now, zp->z_atime);
        }
 
-       if (flag & AT_MTIME) {
+       if (flag & ATTR_MTIME) {
                ZFS_TIME_ENCODE(&now, mtime);
-               if (zp->z_zfsvfs->z_use_fuids) {
+               if (ZTOZSB(zp)->z_use_fuids) {
                        zp->z_pflags |= (ZFS_ARCHIVE |
                            ZFS_AV_MODIFIED);
                }
        }
 
-       if (flag & AT_CTIME) {
+       if (flag & ATTR_CTIME) {
                ZFS_TIME_ENCODE(&now, ctime);
-               if (zp->z_zfsvfs->z_use_fuids)
+               if (ZTOZSB(zp)->z_use_fuids)
                        zp->z_pflags |= ZFS_ARCHIVE;
        }
 }
@@ -1416,7 +1001,7 @@ zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx)
        if (zp->z_blksz && zp->z_size > zp->z_blksz)
                return;
 
-       error = dmu_object_set_blocksize(zp->z_zfsvfs->z_os, zp->z_id,
+       error = dmu_object_set_blocksize(ZTOZSB(zp)->z_os, zp->z_id,
            size, 0, tx);
 
        if (error == ENOTSUP)
@@ -1427,6 +1012,7 @@ zfs_grow_blocksize(znode_t *zp, uint64_t size, dmu_tx_t *tx)
        dmu_object_size_from_db(sa_get_db(zp->z_sa_hdl), &zp->z_blksz, &dummy);
 }
 
+#ifdef HAVE_MMAP
 /*
  * This is a dummy interface used when pvn_vplist_dirty() should *not*
  * be calling back into the fs for a putpage().  E.g.: when truncating
@@ -1440,6 +1026,7 @@ zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
        ASSERT(0);
        return (0);
 }
+#endif /* HAVE_MMAP */
 
 /*
  * Increase the file length
@@ -1453,7 +1040,7 @@ zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
 static int
 zfs_extend(znode_t *zp, uint64_t end)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        dmu_tx_t *tx;
        rl_t *rl;
        uint64_t newblksz;
@@ -1472,19 +1059,19 @@ zfs_extend(znode_t *zp, uint64_t end)
                return (0);
        }
 top:
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
        zfs_sa_upgrade_txholds(tx, zp);
        if (end > zp->z_blksz &&
-           (!ISP2(zp->z_blksz) || zp->z_blksz < zfsvfs->z_max_blksz)) {
+           (!ISP2(zp->z_blksz) || zp->z_blksz < zsb->z_max_blksz)) {
                /*
                 * We are growing the file past the current block size.
                 */
-               if (zp->z_blksz > zp->z_zfsvfs->z_max_blksz) {
+               if (zp->z_blksz > ZTOZSB(zp)->z_max_blksz) {
                        ASSERT(!ISP2(zp->z_blksz));
                        newblksz = MIN(end, SPA_MAXBLOCKSIZE);
                } else {
-                       newblksz = MIN(end, zp->z_zfsvfs->z_max_blksz);
+                       newblksz = MIN(end, ZTOZSB(zp)->z_max_blksz);
                }
                dmu_tx_hold_write(tx, zp->z_id, 0, newblksz);
        } else {
@@ -1508,7 +1095,7 @@ top:
 
        zp->z_size = end;
 
-       VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs),
+       VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(ZTOZSB(zp)),
            &zp->z_size, sizeof (zp->z_size), tx));
 
        zfs_range_unlock(rl);
@@ -1525,13 +1112,13 @@ top:
  *             off     - start of section to free.
  *             len     - length of section to free.
  *
- *     RETURN: 0 if success
+ *     RETURN: 0 if success
  *             error code if failure
  */
 static int
 zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        rl_t *rl;
        int error;
 
@@ -1551,7 +1138,7 @@ zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
        if (off + len > zp->z_size)
                len = zp->z_size - off;
 
-       error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, off, len);
+       error = dmu_free_long_range(zsb->z_os, zp->z_id, off, len);
 
        zfs_range_unlock(rl);
 
@@ -1564,14 +1151,13 @@ zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
  *     IN:     zp      - znode of file to free data in.
  *             end     - new end-of-file.
  *
- *     RETURN: 0 if success
+ *     RETURN: 0 if success
  *             error code if failure
  */
 static int
 zfs_trunc(znode_t *zp, uint64_t end)
 {
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-       vnode_t *vp = ZTOV(zp);
+       zfs_sb_t *zsb = ZTOZSB(zp);
        dmu_tx_t *tx;
        rl_t *rl;
        int error;
@@ -1591,13 +1177,13 @@ zfs_trunc(znode_t *zp, uint64_t end)
                return (0);
        }
 
-       error = dmu_free_long_range(zfsvfs->z_os, zp->z_id, end,  -1);
+       error = dmu_free_long_range(zsb->z_os, zp->z_id, end,  -1);
        if (error) {
                zfs_range_unlock(rl);
                return (error);
        }
 top:
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
        zfs_sa_upgrade_txholds(tx, zp);
        error = dmu_tx_assign(tx, TXG_NOWAIT);
@@ -1613,42 +1199,18 @@ top:
        }
 
        zp->z_size = end;
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zsb),
            NULL, &zp->z_size, sizeof (zp->z_size));
 
        if (end == 0) {
                zp->z_pflags &= ~ZFS_SPARSE;
-               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+               SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb),
                    NULL, &zp->z_pflags, 8);
        }
        VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0);
 
        dmu_tx_commit(tx);
 
-       /*
-        * Clear any mapped pages in the truncated region.  This has to
-        * happen outside of the transaction to avoid the possibility of
-        * a deadlock with someone trying to push a page that we are
-        * about to invalidate.
-        */
-       if (vn_has_cached_data(vp)) {
-               page_t *pp;
-               uint64_t start = end & PAGEMASK;
-               int poff = end & PAGEOFFSET;
-
-               if (poff != 0 && (pp = page_lookup(vp, start, SE_SHARED))) {
-                       /*
-                        * We need to zero a partial page.
-                        */
-                       pagezero(pp, poff, PAGESIZE - poff);
-                       start += PAGESIZE;
-                       page_unlock(pp);
-               }
-               error = pvn_vplist_dirty(vp, start, zfs_no_putpage,
-                   B_INVAL | B_TRUNC, NULL);
-               ASSERT(error == 0);
-       }
-
        zfs_range_unlock(rl);
 
        return (0);
@@ -1663,23 +1225,25 @@ top:
  *             flag    - current file open mode flags.
  *             log     - TRUE if this action should be logged
  *
- *     RETURN: 0 if success
+ *     RETURN: 0 if success
  *             error code if failure
  */
 int
 zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
 {
-       vnode_t *vp = ZTOV(zp);
+#ifdef HAVE_MANDLOCKS
+       struct inode *ip = ZTOI(zp);
+#endif /* HAVE_MANDLOCKS */
        dmu_tx_t *tx;
-       zfsvfs_t *zfsvfs = zp->z_zfsvfs;
-       zilog_t *zilog = zfsvfs->z_log;
+       zfs_sb_t *zsb = ZTOZSB(zp);
+       zilog_t *zilog = zsb->z_log;
        uint64_t mode;
        uint64_t mtime[2], ctime[2];
        sa_bulk_attr_t bulk[3];
        int count = 0;
        int error;
 
-       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zfsvfs), &mode,
+       if ((error = sa_lookup(zp->z_sa_hdl, SA_ZPL_MODE(zsb), &mode,
            sizeof (mode))) != 0)
                return (error);
 
@@ -1691,15 +1255,17 @@ zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
                        return (error);
        }
 
+#ifdef HAVE_MANDLOCKS
        /*
         * Check for any locks in the region to be freed.
         */
 
-       if (MANDLOCK(vp, (mode_t)mode)) {
+       if (MANDLOCK(ip, (mode_t)mode)) {
                uint64_t length = (len ? len : zp->z_size - off);
-               if (error = chklock(vp, FWRITE, off, length, flag, NULL))
+               if (error = chklock(ip, FWRITE, off, length, flag, NULL))
                        return (error);
        }
+#endif /* HAVE_MANDLOCKS */
 
        if (len == 0) {
                error = zfs_trunc(zp, off);
@@ -1711,7 +1277,7 @@ zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
        if (error || !log)
                return (error);
 log:
-       tx = dmu_tx_create(zfsvfs->z_os);
+       tx = dmu_tx_create(zsb->z_os);
        dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
        zfs_sa_upgrade_txholds(tx, zp);
        error = dmu_tx_assign(tx, TXG_NOWAIT);
@@ -1725,9 +1291,9 @@ log:
                return (error);
        }
 
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, mtime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, ctime, 16);
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL, mtime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL, ctime, 16);
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zsb),
            NULL, &zp->z_pflags, 8);
        zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime, B_TRUE);
        error = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
@@ -1736,31 +1302,20 @@ log:
        zfs_log_truncate(zilog, tx, TX_TRUNCATE, zp, off, len);
 
        dmu_tx_commit(tx);
+       zfs_inode_update(zp);
        return (0);
 }
-#endif /* HAVE_ZPL */
 
 void
 zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
 {
        uint64_t        moid, obj, sa_obj, version;
-       uint64_t        sense = ZFS_CASE_SENSITIVE;
        uint64_t        norm = 0;
        nvpair_t        *elem;
        int             error;
-#ifdef HAVE_ZPL
-       zfsvfs_t        zfsvfs;
-       int             i;
-       znode_t         *rootzp = NULL;
-       vnode_t         *vp;
-       vattr_t         vattr;
-       znode_t         *zp;
-       zfs_acl_ids_t   acl_ids;
-#else
        timestruc_t     now;
        dmu_buf_t       *db;
        znode_phys_t    *pzp;
-#endif /* HAVE_ZPL */
 
        /*
         * First attempt to create master node.
@@ -1796,8 +1351,6 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
                ASSERT(error == 0);
                if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0)
                        norm = val;
-               else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0)
-                       sense = val;
        }
        ASSERT(version != 0);
        error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
@@ -1822,79 +1375,11 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
        error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &obj, tx);
        ASSERT(error == 0);
 
-#ifdef HAVE_ZPL
-       /*
-        * Create root znode.  Create minimal znode/vnode/zfsvfs
-        * to allow zfs_mknode to work.
-        */
-       vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
-       vattr.va_type = VDIR;
-       vattr.va_mode = S_IFDIR|0755;
-       vattr.va_uid = crgetuid(cr);
-       vattr.va_gid = crgetgid(cr);
-
-       rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
-       ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs));
-       rootzp->z_moved = 0;
-       rootzp->z_unlinked = 0;
-       rootzp->z_atime_dirty = 0;
-       rootzp->z_is_sa = USE_SA(version, os);
-
-       vp = ZTOV(rootzp);
-       vn_reinit(vp);
-       vp->v_type = VDIR;
-
-       bzero(&zfsvfs, sizeof (zfsvfs_t));
-
-       zfsvfs.z_os = os;
-       zfsvfs.z_parent = &zfsvfs;
-       zfsvfs.z_version = version;
-       zfsvfs.z_use_fuids = USE_FUIDS(version, os);
-       zfsvfs.z_use_sa = USE_SA(version, os);
-       zfsvfs.z_norm = norm;
-
-       error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
-           &zfsvfs.z_attr_table);
-
-       ASSERT(error == 0);
-
-       /*
-        * Fold case on file systems that are always or sometimes case
-        * insensitive.
-        */
-       if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED)
-               zfsvfs.z_norm |= U8_TEXTPREP_TOUPPER;
-
-       /* XXX - This must be destroyed but I'm not quite sure yet so
-        * I'm just annotating that fact when it's an issue.  -Brian */
-       mutex_init(&zfsvfs.z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
-       list_create(&zfsvfs.z_all_znodes, sizeof (znode_t),
-           offsetof(znode_t, z_link_node));
-
-       for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
-               mutex_init(&zfsvfs.z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
-
-       rootzp->z_zfsvfs = &zfsvfs;
-       VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr,
-           cr, NULL, &acl_ids));
-       zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids);
-       ASSERT3P(zp, ==, rootzp);
-       ASSERT(!vn_in_dnlc(ZTOV(rootzp))); /* not valid to move */
-       error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx);
-       ASSERT(error == 0);
-       zfs_acl_ids_free(&acl_ids);
-       POINTER_INVALIDATE(&rootzp->z_zfsvfs);
-
-       ZTOV(rootzp)->v_count = 0;
-       sa_handle_destroy(rootzp->z_sa_hdl);
-       kmem_cache_free(znode_cache, rootzp);
-       error = zfs_create_share_dir(&zfsvfs, tx);
-
-       for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
-               mutex_destroy(&zfsvfs.z_hold_mtx[i]);
-#else
        /*
-        * Create root znode with code free of VFS dependencies
+        * Create root znode with code free of VFS dependencies.  This
+        * is important because without a registered filesystem and super
+        * block all the required VFS hooks will be missing.  The critical
+        * thing is to just crete the required root znode.
         */
        obj = zap_create_norm(os, norm, DMU_OT_DIRECTORY_CONTENTS,
                              DMU_OT_ZNODE, sizeof (znode_phys_t), tx);
@@ -1930,7 +1415,6 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
        ASSERT(error == 0);
 
        dmu_buf_rele(db, FTAG);
-#endif /* HAVE_ZPL */
 }
 
 #endif /* _KERNEL */
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
new file mode 100644 (file)
index 0000000..ed6704b
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * 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 (c) 2011, Lawrence Livermore National Security, LLC.
+ */
+
+
+#include <sys/zfs_vfsops.h>
+#include <sys/zfs_vnops.h>
+#include <sys/zfs_znode.h>
+#include <sys/zpl.h>
+
+
+static int
+zpl_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct dentry *dentry = filp->f_path.dentry;
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_readdir(dentry->d_inode, dirent, filldir,
+           &filp->f_pos, cr);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+ZPL_FSYNC_PROTO(zpl_fsync, filp, unused_dentry, datasync)
+{
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_fsync(filp->f_path.dentry->d_inode, datasync, cr);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+ssize_t
+zpl_read_common(struct inode *ip, const char *buf, size_t len, loff_t pos,
+     uio_seg_t segment, int flags, cred_t *cr)
+{
+       int error;
+       struct iovec iov;
+       uio_t uio;
+
+       iov.iov_base = (void *)buf;
+       iov.iov_len = len;
+
+       uio.uio_iov = &iov;
+       uio.uio_resid = len;
+       uio.uio_iovcnt = 1;
+       uio.uio_loffset = pos;
+       uio.uio_limit = MAXOFFSET_T;
+       uio.uio_segflg = segment;
+
+       error = -zfs_read(ip, &uio, flags, cr);
+       if (error < 0)
+               return (error);
+
+       return (len - uio.uio_resid);
+}
+
+static ssize_t
+zpl_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
+{
+       cred_t *cr;
+       ssize_t read;
+
+       cr = (cred_t *)get_current_cred();
+       read = zpl_read_common(filp->f_mapping->host, buf, len, *ppos,
+           UIO_USERSPACE, filp->f_flags, cr);
+       put_cred(cr);
+
+       if (read < 0)
+               return (read);
+
+       *ppos += read;
+       return (read);
+}
+
+ssize_t
+zpl_write_common(struct inode *ip, const char *buf, size_t len, loff_t pos,
+    uio_seg_t segment, int flags, cred_t *cr)
+{
+       int error;
+       struct iovec iov;
+       uio_t uio;
+
+       iov.iov_base = (void *)buf;
+       iov.iov_len = len;
+
+       uio.uio_iov = &iov;
+       uio.uio_resid = len,
+       uio.uio_iovcnt = 1;
+       uio.uio_loffset = pos;
+       uio.uio_limit = MAXOFFSET_T;
+       uio.uio_segflg = segment;
+
+       error = -zfs_write(ip, &uio, flags, cr);
+       if (error < 0)
+               return (error);
+
+       return (len - uio.uio_resid);
+}
+
+static ssize_t
+zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
+{
+       cred_t *cr;
+       ssize_t wrote;
+
+       cr = (cred_t *)get_current_cred();
+       wrote = zpl_write_common(filp->f_mapping->host, buf, len, *ppos,
+           UIO_USERSPACE, filp->f_flags, cr);
+       put_cred(cr);
+
+       if (wrote < 0)
+               return (wrote);
+
+       *ppos += wrote;
+       return (wrote);
+}
+
+/*
+ * It's worth taking a moment to describe how mmap is implemented
+ * for zfs because it differs considerably from other Linux filesystems.
+ * However, this issue is handled the same way under OpenSolaris.
+ *
+ * The issue is that by design zfs bypasses the Linux page cache and
+ * leaves all caching up to the ARC.  This has been shown to work
+ * well for the common read(2)/write(2) case.  However, mmap(2)
+ * is problem because it relies on being tightly integrated with the
+ * page cache.  To handle this we cache mmap'ed files twice, once in
+ * the ARC and a second time in the page cache.  The code is careful
+ * to keep both copies synchronized.
+ *
+ * When a file with an mmap'ed region is written to using write(2)
+ * both the data in the ARC and existing pages in the page cache
+ * are updated.  For a read(2) data will be read first from the page
+ * cache then the ARC if needed.  Neither a write(2) or read(2) will
+ * will ever result in new pages being added to the page cache.
+ *
+ * New pages are added to the page cache only via .readpage() which
+ * is called when the vfs needs to read a page off disk to back the
+ * virtual memory region.  These pages may be modified without
+ * notifying the ARC and will be written out periodically via
+ * .writepage().  This will occur due to either a sync or the usual
+ * page aging behavior.  Note because a read(2) of a mmap'ed file
+ * will always check the page cache first even when the ARC is out
+ * of date correct data will still be returned.
+ *
+ * While this implementation ensures correct behavior it does have
+ * have some drawbacks.  The most obvious of which is that it
+ * increases the required memory footprint when access mmap'ed
+ * files.  It also adds additional complexity to the code keeping
+ * both caches synchronized.
+ *
+ * Longer term it may be possible to cleanly resolve this wart by
+ * mapping page cache pages directly on to the ARC buffers.  The
+ * Linux address space operations are flexible enough to allow
+ * selection of which pages back a particular index.  The trick
+ * would be working out the details of which subsystem is in
+ * charge, the ARC, the page cache, or both.  It may also prove
+ * helpful to move the ARC buffers to a scatter-gather lists
+ * rather than a vmalloc'ed region.
+ */
+static int
+zpl_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       znode_t *zp = ITOZ(filp->f_mapping->host);
+       int error;
+
+       error = generic_file_mmap(filp, vma);
+       if (error)
+               return (error);
+
+       mutex_enter(&zp->z_lock);
+       zp->z_is_mapped = 1;
+       mutex_exit(&zp->z_lock);
+
+       return (error);
+}
+
+/*
+ * Populate a page with data for the Linux page cache.  This function is
+ * only used to support mmap(2).  There will be an identical copy of the
+ * data in the ARC which is kept up to date via .write() and .writepage().
+ *
+ * Current this function relies on zpl_read_common() and the O_DIRECT
+ * flag to read in a page.  This works but the more correct way is to
+ * update zfs_fillpage() to be Linux friendly and use that interface.
+ */
+static int
+zpl_readpage(struct file *filp, struct page *pp)
+{
+       struct inode *ip;
+       loff_t off, i_size;
+       size_t len, wrote;
+       cred_t *cr;
+       void *pb;
+       int error = 0;
+
+       ASSERT(PageLocked(pp));
+       ip = pp->mapping->host;
+       off = page_offset(pp);
+       i_size = i_size_read(ip);
+       ASSERT3S(off, <, i_size);
+
+       cr = (cred_t *)get_current_cred();
+       len = MIN(PAGE_CACHE_SIZE, i_size - off);
+
+       pb = kmap(pp);
+
+       /* O_DIRECT is passed to bypass the page cache and avoid deadlock. */
+       wrote = zpl_read_common(ip, pb, len, off, UIO_SYSSPACE, O_DIRECT, cr);
+       if (wrote != len)
+               error = -EIO;
+
+       if (!error && (len < PAGE_CACHE_SIZE))
+               memset(pb + len, 0, PAGE_CACHE_SIZE - len);
+
+       kunmap(pp);
+       put_cred(cr);
+
+       if (error) {
+               SetPageError(pp);
+               ClearPageUptodate(pp);
+       } else {
+               ClearPageError(pp);
+               SetPageUptodate(pp);
+               flush_dcache_page(pp);
+       }
+
+       unlock_page(pp);
+
+       return (error);
+}
+
+/*
+ * Write out dirty pages to the ARC, this function is only required to
+ * support mmap(2).  Mapped pages may be dirtied by memory operations
+ * which never call .write().  These dirty pages are kept in sync with
+ * the ARC buffers via this hook.
+ *
+ * Currently this function relies on zpl_write_common() and the O_DIRECT
+ * flag to push out the page.  This works but the more correct way is
+ * to update zfs_putapage() to be Linux friendly and use that interface.
+ */
+static int
+zpl_writepage(struct page *pp, struct writeback_control *wbc)
+{
+       struct inode *ip;
+       loff_t off, i_size;
+       size_t len, read;
+       cred_t *cr;
+       void *pb;
+       int error = 0;
+
+       ASSERT(PageLocked(pp));
+       ip = pp->mapping->host;
+       off = page_offset(pp);
+       i_size = i_size_read(ip);
+
+       cr = (cred_t *)get_current_cred();
+       len = MIN(PAGE_CACHE_SIZE, i_size - off);
+
+       pb = kmap(pp);
+
+       /* O_DIRECT is passed to bypass the page cache and avoid deadlock. */
+       read = zpl_write_common(ip, pb, len, off, UIO_SYSSPACE, O_DIRECT, cr);
+       if (read != len)
+               error = -EIO;
+
+       kunmap(pp);
+       put_cred(cr);
+
+       if (error) {
+               SetPageError(pp);
+               ClearPageUptodate(pp);
+       } else {
+               ClearPageError(pp);
+               SetPageUptodate(pp);
+       }
+
+       unlock_page(pp);
+
+       return (error);
+}
+
+const struct address_space_operations zpl_address_space_operations = {
+       .readpage       = zpl_readpage,
+       .writepage      = zpl_writepage,
+};
+
+const struct file_operations zpl_file_operations = {
+       .open           = generic_file_open,
+       .llseek         = generic_file_llseek,
+       .read           = zpl_read,
+       .write          = zpl_write,
+       .readdir        = zpl_readdir,
+       .mmap           = zpl_mmap,
+       .fsync          = zpl_fsync,
+};
+
+const struct file_operations zpl_dir_file_operations = {
+       .llseek         = generic_file_llseek,
+       .read           = generic_read_dir,
+       .readdir        = zpl_readdir,
+       .fsync          = zpl_fsync,
+};
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
new file mode 100644 (file)
index 0000000..888dc17
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * 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 (c) 2011, Lawrence Livermore National Security, LLC.
+ */
+
+
+#include <sys/zfs_vfsops.h>
+#include <sys/zfs_vnops.h>
+#include <sys/vfs.h>
+#include <sys/zpl.h>
+
+
+static struct dentry *
+zpl_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+{
+       struct inode *ip;
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL);
+       ASSERT3S(error, <=, 0);
+       put_cred(cr);
+
+       if (error) {
+               if (error == -ENOENT)
+                       return d_splice_alias(NULL, dentry);
+               else
+                       return ERR_PTR(error);
+       }
+
+       return d_splice_alias(ip, dentry);
+}
+
+static int
+zpl_create(struct inode *dir, struct dentry *dentry, int mode,
+    struct nameidata *nd)
+{
+       const struct cred *cred;
+       struct inode *ip;
+       vattr_t *vap;
+       int error;
+
+       cred = get_current_cred();
+       vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+       vap->va_mode = mode;
+       vap->va_mask = ATTR_MODE;
+       vap->va_uid = current_fsuid();
+       vap->va_gid = current_fsgid();
+
+       error = -zfs_create(dir, (char *)dentry->d_name.name,
+           vap, 0, mode, &ip, (struct cred *)cred, 0, NULL);
+       if (error)
+               goto out;
+
+       d_instantiate(dentry, ip);
+out:
+       kmem_free(vap, sizeof(vattr_t));
+       put_cred(cred);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
+{
+        const struct cred *cred;
+       struct inode *ip;
+       vattr_t *vap;
+       int error;
+
+       cred = get_current_cred();
+       vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+       vap->va_mode = mode;
+       vap->va_mask = ATTR_MODE;
+       vap->va_rdev = rdev;
+       vap->va_uid = current_fsuid();
+       vap->va_gid = current_fsgid();
+
+       error = -zfs_create(dir, (char *)dentry->d_name.name,
+           vap, 0, mode, &ip, (struct cred *)cred, 0, NULL);
+       if (error)
+               goto out;
+
+       d_instantiate(dentry, ip);
+out:
+       kmem_free(vap, sizeof(vattr_t));
+       put_cred(cred);
+       ASSERT3S(error, <=, 0);
+
+       return (-error);
+}
+
+static int
+zpl_unlink(struct inode *dir, struct dentry *dentry)
+{
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_remove(dir, dname(dentry), cr);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+       cred_t *cr;
+       vattr_t *vap;
+       struct inode *ip;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+       vap->va_mode = S_IFDIR | mode;
+       vap->va_mask = ATTR_MODE;
+       vap->va_uid = current_fsuid();
+       vap->va_gid = current_fsgid();
+
+       error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL);
+       if (error)
+               goto out;
+
+       d_instantiate(dentry, ip);
+out:
+       kmem_free(vap, sizeof(vattr_t));
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_rmdir(struct inode * dir, struct dentry *dentry)
+{
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_rmdir(dir, dname(dentry), NULL, cr, 0);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_getattr(dentry->d_inode, stat, 0, cr);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_setattr(struct dentry *dentry, struct iattr *attr)
+{
+       cred_t *cr;
+       int error;
+
+       error = inode_change_ok(dentry->d_inode, attr);
+       if (error)
+               return (error);
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_setattr(dentry->d_inode, attr, 0, cr);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (-error);
+}
+
+static int
+zpl_rename(struct inode *sdip, struct dentry *sdentry,
+    struct inode *tdip, struct dentry *tdentry)
+{
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       error = -zfs_rename(sdip, dname(sdentry), tdip, dname(tdentry), cr, 0);
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
+{
+       cred_t *cr;
+       vattr_t *vap;
+       struct inode *ip;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+       vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+       vap->va_mode = S_IFLNK | S_IRWXUGO;
+       vap->va_mask = ATTR_MODE;
+       vap->va_uid = current_fsuid();
+       vap->va_gid = current_fsgid();
+
+       error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0);
+       if (error)
+               goto out;
+
+       d_instantiate(dentry, ip);
+out:
+       kmem_free(vap, sizeof(vattr_t));
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static void *
+zpl_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+       struct inode *ip = dentry->d_inode;
+       struct iovec iov;
+       uio_t uio;
+       char *link;
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+
+       iov.iov_len = MAXPATHLEN;
+       iov.iov_base = link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+
+       uio.uio_iov = &iov;
+       uio.uio_iovcnt = 1;
+       uio.uio_resid = (MAXPATHLEN - 1);
+       uio.uio_segflg = UIO_SYSSPACE;
+
+       error = -zfs_readlink(ip, &uio, cr);
+       if (error) {
+               kmem_free(link, MAXPATHLEN);
+               nd_set_link(nd, ERR_PTR(error));
+       } else {
+               nd_set_link(nd, link);
+       }
+
+       put_cred(cr);
+       return (NULL);
+}
+
+static void
+zpl_put_link(struct dentry *dentry, struct nameidata *nd, void *ptr)
+{
+       char *link;
+
+       link = nd_get_link(nd);
+       if (!IS_ERR(link))
+               kmem_free(link, MAXPATHLEN);
+}
+
+static int
+zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+{
+       struct inode *ip = old_dentry->d_inode;
+       cred_t *cr;
+       int error;
+
+       if (ip->i_nlink >= ZFS_LINK_MAX)
+               return -EMLINK;
+
+       cr = (cred_t *)get_current_cred();
+       ip->i_ctime = CURRENT_TIME_SEC;
+       igrab(ip); /* Use ihold() if available */
+
+       error = -zfs_link(dir, ip, dname(dentry), cr);
+       if (error) {
+               iput(ip);
+               goto out;
+       }
+
+       d_instantiate(dentry, ip);
+out:
+       put_cred(cr);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+const struct inode_operations zpl_inode_operations = {
+       .create         = zpl_create,
+       .link           = zpl_link,
+       .unlink         = zpl_unlink,
+       .symlink        = zpl_symlink,
+       .mkdir          = zpl_mkdir,
+       .rmdir          = zpl_rmdir,
+       .mknod          = zpl_mknod,
+       .rename         = zpl_rename,
+       .setattr        = zpl_setattr,
+       .getattr        = zpl_getattr,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .removexattr    = generic_removexattr,
+       .listxattr      = zpl_xattr_list,
+};
+
+const struct inode_operations zpl_dir_inode_operations = {
+       .create         = zpl_create,
+       .lookup         = zpl_lookup,
+       .link           = zpl_link,
+       .unlink         = zpl_unlink,
+       .symlink        = zpl_symlink,
+       .mkdir          = zpl_mkdir,
+       .rmdir          = zpl_rmdir,
+       .mknod          = zpl_mknod,
+       .rename         = zpl_rename,
+       .setattr        = zpl_setattr,
+       .getattr        = zpl_getattr,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .removexattr    = generic_removexattr,
+       .listxattr      = zpl_xattr_list,
+};
+
+const struct inode_operations zpl_symlink_inode_operations = {
+       .readlink       = generic_readlink,
+       .follow_link    = zpl_follow_link,
+       .put_link       = zpl_put_link,
+};
+
+const struct inode_operations zpl_special_inode_operations = {
+       .setattr        = zpl_setattr,
+       .getattr        = zpl_getattr,
+       .setxattr       = generic_setxattr,
+       .getxattr       = generic_getxattr,
+       .removexattr    = generic_removexattr,
+       .listxattr      = zpl_xattr_list,
+};
diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c
new file mode 100644 (file)
index 0000000..0417ce2
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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 (c) 2011, Lawrence Livermore National Security, LLC.
+ */
+
+
+#include <sys/zfs_vfsops.h>
+#include <sys/zfs_vnops.h>
+#include <sys/zfs_znode.h>
+#include <sys/zpl.h>
+
+
+static struct inode *
+zpl_inode_alloc(struct super_block *sb)
+{
+       struct inode *ip;
+
+       VERIFY3S(zfs_inode_alloc(sb, &ip), ==, 0);
+       ip->i_version = 1;
+
+       return (ip);
+}
+
+static void
+zpl_inode_destroy(struct inode *ip)
+{
+        ASSERT(atomic_read(&ip->i_count) == 0);
+       zfs_inode_destroy(ip);
+}
+
+/*
+ * When ->drop_inode() is called its return value indicates if the
+ * inode should be evicted from the inode cache.  If the inode is
+ * unhashed and has no links the default policy is to evict it
+ * immediately.
+ *
+ * Prior to 2.6.36 this eviction was accomplished by the vfs calling
+ * ->delete_inode().  It was ->delete_inode()'s responsibility to
+ * truncate the inode pages and call clear_inode().  The call to
+ * clear_inode() synchronously invalidates all the buffers and
+ * calls ->clear_inode().  It was ->clear_inode()'s responsibility
+ * to cleanup and filesystem specific data before freeing the inode.
+ *
+ * This elaborate mechanism was replaced by ->evict_inode() which
+ * does the job of both ->delete_inode() and ->clear_inode().  It
+ * will be called exactly once, and when it returns the inode must
+ * be in a state where it can simply be freed.  The ->evict_inode()
+ * callback must minimally truncate the inode pages, and call
+ * end_writeback() to complete all outstanding writeback for the
+ * inode.  After this is complete evict inode can cleanup any
+ * remaining filesystem specific data.
+ */
+#ifdef HAVE_EVICT_INODE
+static void
+zpl_evict_inode(struct inode *ip)
+{
+       truncate_inode_pages(&ip->i_data, 0);
+       end_writeback(ip);
+       zfs_inactive(ip);
+}
+
+#else
+
+static void
+zpl_clear_inode(struct inode *ip)
+{
+       zfs_inactive(ip);
+}
+
+static void
+zpl_inode_delete(struct inode *ip)
+{
+       truncate_inode_pages(&ip->i_data, 0);
+       clear_inode(ip);
+}
+
+#endif /* HAVE_EVICT_INODE */
+
+static void
+zpl_put_super(struct super_block *sb)
+{
+       int error;
+
+       error = -zfs_umount(sb);
+       ASSERT3S(error, <=, 0);
+}
+
+static int
+zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
+{
+       int error;
+
+       error = -zfs_statvfs(dentry, statp);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
+{
+       struct super_block *sb = vfsp->mnt_sb;
+       zfs_sb_t *zsb = sb->s_fs_info;
+
+       /*
+        * The Linux VFS automatically handles the following flags:
+        * MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, MNT_NOATIME, MNT_READONLY
+        */
+
+       if (zsb->z_flags & ZSB_XATTR_USER)
+               seq_printf(seq, ",%s", "xattr");
+
+       return (0);
+}
+
+static int
+zpl_fill_super(struct super_block *sb, void *data, int silent)
+{
+       int error;
+
+       error = -zfs_domount(sb, data, silent);
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+zpl_get_sb(struct file_system_type *fs_type, int flags,
+    const char *osname, void *data, struct vfsmount *mnt)
+{
+       zpl_mount_data_t zmd = { osname, data, mnt };
+
+       return get_sb_nodev(fs_type, flags, &zmd, zpl_fill_super, mnt);
+}
+
+static void
+zpl_kill_sb(struct super_block *sb)
+{
+#ifdef HAVE_SNAPSHOT
+       zfs_sb_t *zsb = sb->s_fs_info;
+
+       if (zsb && dmu_objset_is_snapshot(zsb->z_os))
+               zfs_snap_destroy(zsb);
+#endif /* HAVE_SNAPSHOT */
+
+       kill_anon_super(sb);
+}
+
+const struct super_operations zpl_super_operations = {
+       .alloc_inode    = zpl_inode_alloc,
+       .destroy_inode  = zpl_inode_destroy,
+       .dirty_inode    = NULL,
+       .write_inode    = NULL,
+       .drop_inode     = NULL,
+#ifdef HAVE_EVICT_INODE
+       .evict_inode    = zpl_evict_inode,
+#else
+       .clear_inode    = zpl_clear_inode,
+       .delete_inode   = zpl_inode_delete,
+#endif /* HAVE_EVICT_INODE */
+       .put_super      = zpl_put_super,
+       .write_super    = NULL,
+       .sync_fs        = NULL,
+       .freeze_fs      = NULL,
+       .unfreeze_fs    = NULL,
+       .statfs         = zpl_statfs,
+       .remount_fs     = NULL,
+       .show_options   = zpl_show_options,
+       .show_stats     = NULL,
+};
+
+#if 0
+const struct export_operations zpl_export_operations = {
+       .fh_to_dentry   = NULL,
+       .fh_to_parent   = NULL,
+       .get_parent     = NULL,
+};
+#endif
+
+struct file_system_type zpl_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = ZFS_DRIVER,
+       .get_sb         = zpl_get_sb,
+       .kill_sb        = zpl_kill_sb,
+};
diff --git a/module/zfs/zpl_xattr.c b/module/zfs/zpl_xattr.c
new file mode 100644 (file)
index 0000000..7a1ecec
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * 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 (c) 2011, Lawrence Livermore National Security, LLC.
+ *
+ * Extended attributes (xattr) on Solaris are implemented as files
+ * which exist in a hidden xattr directory.  These extended attributes
+ * can be accessed using the attropen() system call which opens
+ * the extended attribute.  It can then be manipulated just like
+ * a standard file descriptor.  This has a couple advantages such
+ * as practically no size limit on the file, and the extended
+ * attributes permissions may differ from those of the parent file.
+ * This interface is really quite clever, but it's also completely
+ * different than what is supported on Linux.
+ *
+ * Under Linux extended attributes are manipulated by the system
+ * calls getxattr(2), setxattr(2), and listxattr(2).  They consider
+ * extended attributes to be name/value pairs where the name is a
+ * NULL terminated string.  The name must also include one of the
+ * following name space prefixes:
+ *
+ *   user     - No restrictions and is available to user applications.
+ *   trusted  - Restricted to kernel and root (CAP_SYS_ADMIN) use.
+ *   system   - Used for access control lists (system.nfs4_acl, etc).
+ *   security - Used by SELinux to store a files security context.
+ *
+ * This Linux interface is implemented internally using the more
+ * flexible Solaris style extended attributes.  Every extended
+ * attribute is store as a file in a hidden directory associated
+ * with the parent file.  This ensures on disk compatibility with
+ * zfs implementations on other platforms (Solaris, FreeBSD, MacOS).
+ *
+ * One consequence of this implementation is that when an extended
+ * attribute is manipulated an inode is created.  This inode will
+ * exist in the Linux inode cache but there will be no associated
+ * entry in the dentry cache which references it.  This is safe
+ * but it may result in some confusion.
+ *
+ * Longer term I would like to see the 'security.selinux' extended
+ * attribute moved to a SA.  This should significantly improve
+ * performance on a SELinux enabled system by minimizing the
+ * number of seeks required to access a file.  However, for now
+ * this xattr is still stored in a file because I'm pretty sure
+ * adding a new SA will break on-disk compatibility.
+ */
+
+
+#include <sys/zfs_vfsops.h>
+#include <sys/zfs_vnops.h>
+#include <sys/zfs_znode.h>
+#include <sys/vfs.h>
+#include <sys/zpl.h>
+
+typedef struct xattr_filldir {
+       size_t size;
+       size_t offset;
+       char *buf;
+       struct inode *inode;
+} xattr_filldir_t;
+
+static int
+zpl_xattr_filldir(void *arg, const char *name, int name_len,
+    loff_t offset, uint64_t objnum, unsigned int d_type)
+{
+       xattr_filldir_t *xf = arg;
+
+       if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
+               if (!(ITOZSB(xf->inode)->z_flags & ZSB_XATTR_USER))
+                       return (0);
+
+       if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
+               if (!capable(CAP_SYS_ADMIN))
+                       return (0);
+
+       /* When xf->buf is NULL only calculate the required size. */
+       if (xf->buf) {
+               if (xf->offset + name_len + 1 > xf->size)
+                       return (-ERANGE);
+
+               memcpy(xf->buf + xf->offset, name, name_len);
+               xf->buf[xf->offset + name_len] = '\0';
+       }
+
+       xf->offset += (name_len + 1);
+
+       return (0);
+}
+
+ssize_t
+zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+{
+       struct inode *ip = dentry->d_inode;
+       struct inode *dxip = NULL;
+       loff_t pos = 3;  /* skip '.', '..', and '.zfs' entries. */
+       cred_t *cr;
+       int error;
+       xattr_filldir_t xf = { buffer_size, 0, buffer, ip };
+
+       cr = (cred_t *)get_current_cred();
+
+       /* Lookup the xattr directory */
+       error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL);
+       if (error) {
+               if (error == -ENOENT)
+                       error = 0;
+
+               goto out;
+       }
+
+       /* Fill provided buffer via zpl_zattr_filldir helper */
+       error = -zfs_readdir(dxip, (void *)&xf, zpl_xattr_filldir, &pos, cr);
+       if (error)
+               goto out;
+
+       error = xf.offset;
+out:
+       if (dxip)
+               iput(dxip);
+
+       put_cred(cr);
+
+       return (error);
+}
+
+static int
+zpl_xattr_get(struct inode *ip, const char *name, void *buf, size_t size)
+{
+       struct inode *dxip = NULL;
+       struct inode *xip = NULL;
+       cred_t *cr;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+
+       /* Lookup the xattr directory */
+       error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL);
+       if (error)
+               goto out;
+
+       /* Lookup a specific xattr name in the directory */
+       error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL);
+       if (error)
+               goto out;
+
+       if (!size) {
+               error = i_size_read(xip);
+               goto out;
+       }
+
+       error = zpl_read_common(xip, buf, size, 0, UIO_SYSSPACE, 0, cr);
+out:
+       if (xip)
+               iput(xip);
+
+       if (dxip)
+               iput(dxip);
+
+       put_cred(cr);
+
+       if (error == -ENOENT)
+               error = -ENODATA;
+
+       return (error);
+}
+
+static int
+zpl_xattr_set(struct inode *ip, const char *name, const void *value,
+    size_t size, int flags)
+{
+       struct inode *dxip = NULL;
+       struct inode *xip = NULL;
+       vattr_t *vap = NULL;
+       cred_t *cr;
+       ssize_t wrote;
+       int error;
+
+       cr = (cred_t *)get_current_cred();
+
+       /* Lookup the xattr directory and create it if required. */
+       error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR | CREATE_XATTR_DIR,
+           cr, NULL, NULL);
+       if (error)
+               goto out;
+
+       /*
+        * Lookup a specific xattr name in the directory, two failure modes:
+        *   XATTR_CREATE: fail if xattr already exists
+        *   XATTR_REMOVE: fail if xattr does not exist
+        */
+       error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL);
+       if (error) {
+               if (error != -ENOENT)
+                       goto out;
+
+               if ((error == -ENOENT) && (flags & XATTR_REPLACE))
+                       goto out;
+       } else {
+               error = -EEXIST;
+               if (flags & XATTR_CREATE)
+                       goto out;
+       }
+       error = 0;
+
+       /* Remove a specific name xattr when value is set to NULL. */
+       if (value == NULL) {
+               if (xip)
+                       error = -zfs_remove(dxip, (char *)name, cr);
+
+               goto out;
+       }
+
+       /* Lookup failed create a new xattr. */
+       if (xip == NULL) {
+               vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
+               vap->va_mode = S_IFREG | 0644;
+               vap->va_mask = ATTR_MODE;
+               vap->va_uid = current_fsuid();
+               vap->va_gid = current_fsgid();
+
+               error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip,
+                   cr, 0, NULL);
+               if (error)
+                       goto out;
+       }
+
+       ASSERT(xip != NULL);
+       wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr);
+       if (wrote < 0)
+               error = wrote;
+
+out:
+       if (vap)
+               kmem_free(vap, sizeof(vattr_t));
+
+       if (xip)
+               iput(xip);
+
+       if (dxip)
+               iput(dxip);
+
+       put_cred(cr);
+       if (error == -ENOENT)
+               error = -ENODATA;
+
+       ASSERT3S(error, <=, 0);
+
+       return (error);
+}
+
+static int
+__zpl_xattr_user_get(struct inode *ip, const char *name,
+    void *buffer, size_t size)
+{
+       char *xattr_name;
+       int error;
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       if (!(ITOZSB(ip)->z_flags & ZSB_XATTR_USER))
+               return -EOPNOTSUPP;
+
+       xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
+       error = zpl_xattr_get(ip, xattr_name, buffer, size);
+       strfree(xattr_name);
+
+       return (error);
+}
+ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get);
+
+static int
+__zpl_xattr_user_set(struct inode *ip, const char *name,
+    const void *value, size_t size, int flags)
+{
+       char *xattr_name;
+       int error;
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       if (!(ITOZSB(ip)->z_flags & ZSB_XATTR_USER))
+               return -EOPNOTSUPP;
+
+       xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
+       error = zpl_xattr_set(ip, xattr_name, value, size, flags);
+       strfree(xattr_name);
+
+       return (error);
+}
+ZPL_XATTR_SET_WRAPPER(zpl_xattr_user_set);
+
+xattr_handler_t zpl_xattr_user_handler = {
+       .prefix = XATTR_USER_PREFIX,
+       .get    = zpl_xattr_user_get,
+       .set    = zpl_xattr_user_set,
+};
+
+static int
+__zpl_xattr_trusted_get(struct inode *ip, const char *name,
+    void *buffer, size_t size)
+{
+       char *xattr_name;
+       int error;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
+       error = zpl_xattr_get(ip, xattr_name, buffer, size);
+       strfree(xattr_name);
+
+       return (error);
+}
+ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get);
+
+static int
+__zpl_xattr_trusted_set(struct inode *ip, const char *name,
+    const void *value, size_t size, int flags)
+{
+       char *xattr_name;
+       int error;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
+       error = zpl_xattr_set(ip, xattr_name, value, size, flags);
+       strfree(xattr_name);
+
+       return (error);
+}
+ZPL_XATTR_SET_WRAPPER(zpl_xattr_trusted_set);
+
+xattr_handler_t zpl_xattr_trusted_handler = {
+       .prefix = XATTR_TRUSTED_PREFIX,
+       .get    = zpl_xattr_trusted_get,
+       .set    = zpl_xattr_trusted_set,
+};
+
+static int
+__zpl_xattr_security_get(struct inode *ip, const char *name,
+    void *buffer, size_t size)
+{
+       char *xattr_name;
+       int error;
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
+       error = zpl_xattr_get(ip, xattr_name, buffer, size);
+       strfree(xattr_name);
+
+       return (error);
+}
+ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get);
+
+static int
+__zpl_xattr_security_set(struct inode *ip, const char *name,
+    const void *value, size_t size, int flags)
+{
+       char *xattr_name;
+       int error;
+
+       if (strcmp(name, "") == 0)
+               return -EINVAL;
+
+       xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
+       error = zpl_xattr_set(ip, xattr_name, value, size, flags);
+       strfree(xattr_name);
+
+       return (error);
+}
+ZPL_XATTR_SET_WRAPPER(zpl_xattr_security_set);
+
+int
+zpl_xattr_security_init(struct inode *ip, struct inode *dip)
+{
+        int error;
+        size_t len;
+        void *value;
+        char *name;
+
+        error = security_inode_init_security(ip, dip, &name, &value, &len);
+        if (error) {
+                if (error == -EOPNOTSUPP)
+                        return 0;
+
+                return (error);
+        }
+
+       error = __zpl_xattr_security_set(ip, name, value, len, 0);
+
+        kfree(name);
+        kfree(value);
+
+        return (error);
+}
+
+xattr_handler_t zpl_xattr_security_handler = {
+       .prefix = XATTR_SECURITY_PREFIX,
+       .get    = zpl_xattr_security_get,
+       .set    = zpl_xattr_security_set,
+};
+
+xattr_handler_t *zpl_xattr_handlers[] = {
+       &zpl_xattr_security_handler,
+       &zpl_xattr_trusted_handler,
+       &zpl_xattr_user_handler,
+#ifdef HAVE_POSIX_ACLS
+       &zpl_xattr_acl_access_handler,
+        &zpl_xattr_acl_default_handler,
+#endif /* HAVE_POSIX_ACLS */
+};
index b2a08fb..04c885f 100644 (file)
@@ -1062,6 +1062,8 @@ zvol_alloc(dev_t dev, const char *name)
        mutex_init(&zv->zv_znode.z_range_lock, NULL, MUTEX_DEFAULT, NULL);
        avl_create(&zv->zv_znode.z_range_avl, zfs_range_compare,
            sizeof (rl_t), offsetof(rl_t, r_node));
+       zv->zv_znode.z_is_zvol = TRUE;
+
        spin_lock_init(&zv->zv_lock);
        list_link_init(&zv->zv_next);
 
@@ -1228,7 +1230,8 @@ zvol_create_minors_cb(spa_t *spa, uint64_t dsobj,
        if (strchr(dsname, '/') == NULL)
                return 0;
 
-       return __zvol_create_minor(dsname);
+       (void) __zvol_create_minor(dsname);
+       return (0);
 }
 
 /*
index 3e68eda..ba491bc 100644 (file)
@@ -51,21 +51,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -203,6 +206,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 6060fba..4a707fa 100755 (executable)
@@ -65,6 +65,7 @@ if [ $(id -u) != 0 ]; then
 fi
 
 if [ ${UNLOAD} ]; then
+       umount -t zfs -a
        unload_modules
 else
        check_modules || die "${ERROR}"
index 1aa1306..bd35629 100644 (file)
@@ -51,21 +51,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index dcd0fca..0030fa3 100644 (file)
@@ -51,21 +51,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 56a5630..5fd446d 100644 (file)
@@ -51,21 +51,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index baa2088..d8b181d 100644 (file)
@@ -51,21 +51,24 @@ am__aclocal_m4_deps =  \
        $(top_srcdir)/config/kernel-blk-rq-bytes.m4 \
        $(top_srcdir)/config/kernel-blk-rq-pos.m4 \
        $(top_srcdir)/config/kernel-blk-rq-sectors.m4 \
+       $(top_srcdir)/config/kernel-evict-inode.m4 \
        $(top_srcdir)/config/kernel-fmode-t.m4 \
+       $(top_srcdir)/config/kernel-fsync.m4 \
        $(top_srcdir)/config/kernel-get-disk-ro.m4 \
        $(top_srcdir)/config/kernel-invalidate-bdev-args.m4 \
        $(top_srcdir)/config/kernel-kobj-name-len.m4 \
        $(top_srcdir)/config/kernel-open-bdev-exclusive.m4 \
        $(top_srcdir)/config/kernel-rq-for-each_segment.m4 \
        $(top_srcdir)/config/kernel-rq-is_sync.m4 \
+       $(top_srcdir)/config/kernel-xattr-handler.m4 \
        $(top_srcdir)/config/kernel.m4 \
        $(top_srcdir)/config/user-arch.m4 \
        $(top_srcdir)/config/user-frame-larger-than.m4 \
        $(top_srcdir)/config/user-ioctl.m4 \
        $(top_srcdir)/config/user-libblkid.m4 \
-       $(top_srcdir)/config/user-libshare.m4 \
        $(top_srcdir)/config/user-libuuid.m4 \
        $(top_srcdir)/config/user-nptl_guard_within_stack.m4 \
+       $(top_srcdir)/config/user-selinux.m4 \
        $(top_srcdir)/config/user-zlib.m4 $(top_srcdir)/config/user.m4 \
        $(top_srcdir)/config/zfs-build.m4 \
        $(top_srcdir)/config/zfs-meta.m4 $(top_srcdir)/configure.ac
@@ -163,6 +166,7 @@ LDFLAGS = @LDFLAGS@
 LIBBLKID = @LIBBLKID@
 LIBOBJS = @LIBOBJS@
 LIBS = @LIBS@
+LIBSELINUX = @LIBSELINUX@
 LIBTOOL = @LIBTOOL@
 LIBUUID = @LIBUUID@
 LINUX = @LINUX@
index 6e0e623..2f09157 100644 (file)
@@ -6,6 +6,9 @@
 /* bio_end_io_t wants 2 args */
 #undef HAVE_2ARGS_BIO_END_IO_T
 
+/* fops->fsync() want 2 args */
+#undef HAVE_2ARGS_FSYNC
+
 /* struct block_device_operations use bdevs */
 #undef HAVE_BDEV_BLOCK_DEVICE_OPERATIONS
 
 /* blk_rq_sectors() is available */
 #undef HAVE_BLK_RQ_SECTORS
 
+/* super_block uses const struct xattr_hander */
+#undef HAVE_CONST_XATTR_HANDLER
+
+/* xattr_handler->get() wants dentry */
+#undef HAVE_DENTRY_XATTR_GET
+
+/* xattr_handler->set() wants dentry */
+#undef HAVE_DENTRY_XATTR_SET
+
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #undef HAVE_DLFCN_H
 
+/* sops->evict_inode() exists */
+#undef HAVE_EVICT_INODE
+
 /* kernel defines fmode_t */
 #undef HAVE_FMODE_T
 
@@ -84,8 +99,8 @@
 /* Define if you have libblkid */
 #undef HAVE_LIBBLKID
 
-/* Define to 1 if 'libshare' library available */
-#undef HAVE_LIBSHARE
+/* Define if you have selinux */
+#undef HAVE_LIBSELINUX
 
 /* Define if you have libuuid */
 #undef HAVE_LIBUUID