]> git.proxmox.com Git - mirror_zfs-debian.git/commitdiff
Prototype/structure update for Linux
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 8 Feb 2011 19:16:06 +0000 (11:16 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Feb 2011 17:27:21 +0000 (09:27 -0800)
I appologize in advance why to many things ended up in this commit.
When it could be seperated in to a whole series of commits teasing
that all apart now would take considerable time and I'm not sure
there's much merrit in it.  As such I'll just summerize the intent
of the changes which are all (or partly) in this commit.  Broadly
the intent is to remove as much Solaris specific code as possible
and replace it with native Linux equivilants.  More specifically:

1) Replace all instances of zfsvfs_t with zfs_sb_t.  While the
type is largely the same calling it private super block data
rather than a zfsvfs is more consistent with how Linux names
this.  While non critical it makes the code easier to read when
your thinking in Linux friendly VFS terms.

2) Replace vnode_t with struct inode.  The Linux VFS doesn't have
the notion of a vnode and there's absolutely no good reason to
create one.  There are in fact several good reasons to remove it.
It just adds overhead on Linux if we were to manage one, it
conplicates the code, and it likely will lead to bugs so there's
a good change it will be out of date.  The code has been updated
to remove all need for this type.

3) Replace all vtype_t's with umode types.  Along with this shift
all uses of types to mode bits.  The Solaris code would pass a
vtype which is redundant with the Linux mode.  Just update all the
code to use the Linux mode macros and remove this redundancy.

4) Remove using of vn_* helpers and replace where needed with
inode helpers.  The big example here is creating iput_aync to
replace vn_rele_async.  Other vn helpers will be addressed as
needed but they should be be emulated.  They are a Solaris VFS'ism
and should simply be replaced with Linux equivilants.

5) Update znode alloc/free code.  Under Linux it's common to
embed the inode specific data with the inode itself.  This removes
the need for an extra memory allocation.  In zfs this information
is called a znode and it now embeds the inode with it.  Allocators
have been updated accordingly.

6) Minimal integration with the vfs flags for setting up the
super block and handling mount options has been added this
code will need to be refined but functionally it's all there.

This will be the first and last of these to large to review commits.

22 files changed:
include/sys/dsl_pool.h
include/sys/zfs_acl.h
include/sys/zfs_dir.h
include/sys/zfs_fuid.h
include/sys/zfs_vfsops.h
include/sys/zfs_vnops.h
include/sys/zfs_znode.h
module/zfs/dmu_objset.c
module/zfs/dsl_dataset.c
module/zfs/dsl_pool.c
module/zfs/spa_config.c
module/zfs/vdev_file.c
module/zfs/zfs_acl.c
module/zfs/zfs_dir.c
module/zfs/zfs_fuid.c
module/zfs/zfs_ioctl.c
module/zfs/zfs_log.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

index 7d25bd7c020db9a49e4b0b6749246fe570e30a8f..99a131eec483d26ab7d16fa3ab3cd670e0d99271 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 c1a0aeebdce442462680c52e836d19e3da429ad5..6f7cef2adf5f138c41e74634a834b6376a26f9fc 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 349f8ef3732161225de5d52c00913d371555a25e..8610fbe0861d5f12ac7fed0227331a01357b8dfd 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 91650a22d8474823bbedc64e18f0570ff4984170..deaebcc82bd08b46a5852671f4983ccdbbf07eb5 100644 (file)
@@ -100,24 +100,24 @@ typedef struct zfs_fuid_info {
 
 #ifdef _KERNEL
 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);
+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 34a871587a81c2bc8b9a7b94dc1e5f560743a242..a2f00acf08f1c04a90800d73ccba61bad7c946ab 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 */
@@ -87,6 +89,8 @@ struct zfsvfs {
 
 #define        ZFS_SUPER_MAGIC 0x2fc12fc1
 
+#define        ZSB_XATTR_USER  0x0001          /* Enable user xattrs */
+
 
 /*
  * Minimal snapshot helpers, the bulk of the Linux snapshot implementation
@@ -162,30 +166,30 @@ 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(vfs_t *vfsp);
-extern void zfs_unregister_callbacks(zfsvfs_t *zfsvfs);
-extern int zfs_domount(vfs_t *vfsp, char *osname);
-extern int zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr);
-extern int zfs_root(vfs_t *vfsp, vnode_t **vpp);
-extern int zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp);
-extern int zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp);
+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
 }
index 64e2210de498c086e6f6b5eb740580fbb0d38459..2cacb9c6faf4b4c1c505e4dbcd96868c2e336cb6 100644 (file)
 #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(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr,
-    caller_context_t *ct);
-extern int zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr,
-    caller_context_t *ct);
-extern 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);
-extern int zfs_create(vnode_t *dvp, char *name, vattr_t *vap,
-    int excl, int mode, vnode_t **vpp, cred_t *cr, int flag,
-    caller_context_t *ct, vsecattr_t *vsecp);
-extern int zfs_remove(vnode_t *dvp, char *name, cred_t *cr,
-    caller_context_t *ct, int flags);
-extern 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);
-extern int zfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
-    caller_context_t *ct, int flags);
-extern int zfs_fsync(vnode_t *vp, int syncflag, cred_t *cr,
-    caller_context_t *ct);
-extern int zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct);
-extern int zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct);
-extern int zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
-    cred_t *cr, caller_context_t *ct, int flags);
-extern int zfs_symlink(vnode_t *dvp, char *name, vattr_t *vap, char *link,
-    cred_t *cr, caller_context_t *ct, int flags);
-extern int zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr,
-    caller_context_t *ct);
-extern int zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
-    caller_context_t *ct, int flags);
-extern void zfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct);
-extern int zfs_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag,
-    offset_t offset, cred_t *cr, caller_context_t *ct);
-extern int zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct);
-extern int zfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag,
-    cred_t *cr, caller_context_t *ct);
-extern int zfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag,
-    cred_t *cr, caller_context_t *ct);
+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
 }
index 4dbecb4b5e9a566ca1c0a0e121aa5313d99bec17..2f25cc7fe378cda53f45d6dd61d2da9a7e3d84b0 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 */
@@ -235,48 +233,52 @@ typedef struct znode {
 /*
  * Convert between znode pointers and inode pointers
  */
-#define        ZTOI(ZP)        (&((ZP)->z_inode))
-#define        ITOZ(IP)        (container_of((IP), znode_t, z_inode))
-
-/* XXX - REMOVE ME ONCE THE OTHER BUILD ISSUES ARE RESOLVED */
-#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 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
@@ -296,15 +298,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);
@@ -314,18 +316,19 @@ 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,
@@ -347,12 +350,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);
index 7da5c1aa08f5b5321e8575c333fb38816e8c52e8..cbd177819398c6d70f2c0a72b7fe9cf17fcf4068 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 dfccede04199ad1e9d6a04ec2851ad63a97a24ac..c34ac2a76fbd802fa0a8f437eadfbc94f6bf9aeb 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 6a0e3632c7fa2e5a3fa76aa7a96c4d643b013c05..7185540f1a40d1a0908435a10f9ceebcf706a6a4 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 79664cbe1df70908b1c2b850f7f361ab04e2c34e..d84d6b0f91ab9542d6f0cf4d452f11b256e0e16f 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 f31389a6df0acb0be0ac0ee2e11c133e77a32690..bbc85e733011a9c07b06def549d2e8992dd36de7 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 45ec20647e564d566b507ff4b08180b00e4e3caa..0ae749e6b4dda058d31d5aa8273c72dbeeb96073 100644 (file)
@@ -345,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 {
@@ -368,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);
 
@@ -418,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 {
@@ -444,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 *
@@ -531,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
@@ -554,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;
 
@@ -648,7 +648,7 @@ zfs_ace_walk(void *datap, uint64_t cookie, int aclcnt,
  * 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)
 {
@@ -666,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);
                }
@@ -674,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);
 
@@ -710,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;
@@ -753,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 {
@@ -767,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;
@@ -781,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);
        }
@@ -825,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;
@@ -1100,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 {
@@ -1108,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);
        }
 
@@ -1295,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;
@@ -1309,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) {
@@ -1324,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;
@@ -1341,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;
@@ -1351,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);
 
@@ -1365,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;
@@ -1386,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;
                        }
@@ -1396,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);
@@ -1425,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));
        }
 
@@ -1444,19 +1444,19 @@ zfs_aclset_common(znode_t *zp, zfs_acl_t *aclp, cred_t *cr, dmu_tx_t *tx)
 }
 
 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;
@@ -1516,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))
@@ -1558,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);
@@ -1568,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);
@@ -1583,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);
 }
@@ -1599,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;
@@ -1612,21 +1612,21 @@ 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))) {
@@ -1642,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;
 
                /*
@@ -1690,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;
                }
 
@@ -1723,7 +1723,7 @@ 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;
@@ -1732,11 +1732,11 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
        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;
@@ -1745,21 +1745,19 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
        /*
         * 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;
@@ -1774,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,
@@ -1789,7 +1787,7 @@ 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);
                        }
@@ -1805,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) &&
@@ -1816,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 =
@@ -1832,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);
                }
        }
 
@@ -1864,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));
 }
 
 /*
@@ -1939,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;
@@ -1971,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;
@@ -1982,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);
@@ -1995,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);
@@ -2031,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;
@@ -2050,7 +2048,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *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);
@@ -2067,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
@@ -2081,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);
@@ -2116,7 +2114,7 @@ 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);
 
@@ -2139,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);
        }
 
@@ -2149,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);
        }
@@ -2198,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;
@@ -2231,7 +2229,8 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode,
                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 */
@@ -2252,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;
@@ -2263,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)
@@ -2325,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);
 }
@@ -2335,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;
@@ -2344,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);
        }
@@ -2391,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;
 
@@ -2439,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);
 }
 
@@ -2456,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
@@ -2471,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);
                }
@@ -2497,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.
         */
@@ -2514,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);
        }
 
@@ -2556,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))
@@ -2588,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
@@ -2627,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);
@@ -2750,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));
 
@@ -2767,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;
 
        /*
index aced2886aba0fbf2e219d4ea0c24d544b877460d..f54ed1912bd4ce6f888c6619f552334adbc14b72 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>
  * 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;
@@ -83,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);
 }
@@ -137,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;
 
@@ -160,7 +163,7 @@ zfs_dirent_lock(zfs_dirlock_t **dlpp, znode_t *dzp, char *name, znode_t **zpp,
        /*
         * 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.
         *
@@ -180,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
@@ -193,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
@@ -208,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.
@@ -288,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)) {
@@ -322,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;
@@ -377,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;
@@ -386,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;
 
@@ -420,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 */
                }
@@ -450,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));
 }
 
 /*
@@ -464,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;
@@ -475,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)) {
 
@@ -483,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;
 
@@ -494,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.
@@ -506,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);
 }
@@ -529,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;
                }
@@ -570,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)
@@ -581,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;
@@ -590,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;
                }
        }
@@ -616,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;
        }
 
@@ -624,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);
        }
 
@@ -638,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)
@@ -656,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;
        }
 
@@ -665,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);
@@ -673,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
@@ -688,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);
 }
@@ -700,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;
@@ -718,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);
@@ -742,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);
@@ -758,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);
 }
@@ -773,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);
        }
 
@@ -803,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);
                }
 
@@ -839,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) {
@@ -856,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)
@@ -879,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);
@@ -914,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) {
@@ -960,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);
 }
@@ -990,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;
@@ -1009,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);
        }
@@ -1035,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) {
@@ -1067,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 a5741185a960ca1bc0e280f95d4c904fe7ca5033..f1e071fc7f7c41a536565c802f6acb9362c8d635 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.
  *
  */
@@ -196,34 +196,34 @@ zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx)
  * 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;
@@ -234,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);
@@ -275,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;
@@ -319,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;
                }
@@ -343,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);
        }
 }
@@ -363,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);
@@ -388,12 +387,12 @@ 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
@@ -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) {
@@ -499,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;
 
@@ -513,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))
@@ -536,7 +535,7 @@ 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);
 
@@ -554,10 +553,10 @@ 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
@@ -578,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
@@ -629,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) {
@@ -648,15 +647,15 @@ zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
 }
 
 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);
 }
 
 /*
@@ -710,7 +709,7 @@ 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);
@@ -718,7 +717,7 @@ zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *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);
@@ -734,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,
@@ -752,7 +751,7 @@ 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);
@@ -760,17 +759,17 @@ zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
 }
 
 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
index 593ed74bbd9ef5da992acd1f085e4d4336ad5873..994d65f7e2412e86740dc0298d2be3c56d9a7b43 100644 (file)
@@ -432,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) {
@@ -849,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.
@@ -1105,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;
@@ -1121,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;
        }
@@ -1131,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
@@ -2086,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;
@@ -2095,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) {
@@ -2120,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
 }
 
 /*
@@ -2185,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;
@@ -2748,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
@@ -2764,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;
                }
@@ -2773,7 +2745,7 @@ zfs_get_vfs(const char *resource)
        vfs_list_unlock();
        return (vfs_found);
 }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_SNAPSHOT */
 
 /* ARGSUSED */
 static void
@@ -3128,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) {
@@ -3148,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);
 }
 
@@ -3215,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);
@@ -3252,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;
 
@@ -3265,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);
@@ -3289,9 +3260,6 @@ out:
        if (ds)
                dsl_dataset_rele(ds, FTAG);
        return (error);
-#else
-       return (ENOTSUP);
-#endif /* HAVE_ZPL */
 }
 
 /*
@@ -3741,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;
@@ -4087,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 */
 }
 
 /*
@@ -4122,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) {
@@ -4144,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 */
 }
 
 /*
@@ -4162,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);
@@ -4192,9 +4149,6 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
        }
 
        return (error);
-#else
-       return (ENOTSUP);
-#endif /* HAVE_ZPL */
 }
 
 /*
@@ -4456,10 +4410,10 @@ 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,
@@ -4479,7 +4433,7 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
        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;
@@ -4500,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);
@@ -4518,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;
@@ -4565,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) ||
@@ -4573,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);
                }
@@ -4594,7 +4547,7 @@ zfs_ioc_smb_acl(zfs_cmd_t *zc)
        VN_RELE(vp);
        VN_RELE(ZTOV(sharedir));
 
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
 
        return (error);
 #else
index 59a6451c7c06cfbbc1ed6b72c5fb6470aaa02627..945b734ceeac6c06e15134e7225c4b707b6fe3e5 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>
@@ -411,9 +410,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 +495,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 +512,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))
@@ -629,7 +628,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 +666,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 4e3c176a3608ed313c1ca6868ad97bfe1f4b1a3a..6709ce80b65a89571555a1c51690b94f92b5ee2f 100644 (file)
@@ -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;
                        }
index 68bce0a6ed8a36f4aabef9ba436cc2786e1a1a80..ed696490fa0674ea8642a90ea95f4b8b3c5c6e3c 100644 (file)
@@ -81,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);
@@ -107,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);
@@ -122,13 +122,13 @@ zfs_sa_symlink(znode_t *zp, char *link, int len, dmu_tx_t *tx)
 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,7 +179,7 @@ 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));
        }
 }
@@ -198,7 +198,7 @@ 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;
+       zfs_sb_t *zsb = ZTOZSB(zp);
        int count = 0;
        sa_bulk_attr_t *bulk, *sa_attrs;
        zfs_acl_locator_cb_t locate = { 0 };
@@ -216,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;
 
        /*
@@ -237,16 +237,16 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
 
        /* First do a bulk query of the attributes that aren't cached */
        bulk = kmem_alloc(sizeof(sa_bulk_attr_t) * 20, KM_SLEEP);
-       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,
+       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) {
@@ -260,42 +260,42 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
         */
        count = 0;
        sa_attrs = kmem_zalloc(sizeof(sa_bulk_attr_t) * 20, KM_SLEEP);
-       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_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
@@ -304,7 +304,7 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
        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;
        }
@@ -314,7 +314,7 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
        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;
@@ -328,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;
 
 
index 7c980b1182ec9a46278829852e38ab46e97469c5..1763d171a06ddf9f7d15f99a73b2c0a0712c037f 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>
 #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
 
 /*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
@@ -77,15 +78,14 @@ zfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
        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
                /*
@@ -96,15 +96,15 @@ zfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
                 *      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
@@ -121,113 +121,106 @@ 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;
        }
 }
 
@@ -242,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;
 }
 
 int
-zfs_register_callbacks(vfs_t *vfsp)
+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.
@@ -383,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);
 
@@ -431,22 +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);
 }
 EXPORT_SYMBOL(zfs_register_callbacks);
-#endif /* HAVE_ZPL */
 
 static int
 zfs_space_delta_cb(dmu_object_type_t bonustype, void *data,
@@ -497,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;
@@ -507,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
@@ -516,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:
@@ -524,9 +460,9 @@ 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);
        }
@@ -534,7 +470,7 @@ zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type)
 }
 
 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;
@@ -543,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;
@@ -580,14 +516,14 @@ 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);
        }
@@ -597,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];
@@ -606,18 +542,18 @@ 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);
@@ -625,7 +561,7 @@ zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
 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];
@@ -637,74 +573,74 @@ 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);
@@ -712,40 +648,40 @@ zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid)
 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);
        }
 
@@ -754,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) 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);
@@ -810,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
@@ -900,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.
@@ -933,157 +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));
 }
 
-#ifdef HAVE_FUID_FEATURES
 static void
-zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
+zfs_set_fuid_feature(zfs_sb_t *zsb)
 {
-       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);
+       zsb->z_use_fuids = USE_FUIDS(zsb->z_version, zsb->z_os);
+       zsb->z_use_sa = USE_SA(zsb->z_version, zsb->z_os);
 }
-#endif /* HAVE_FUID_FEATURES */
-
-int
-zfs_domount(vfs_t *vfsp, char *osname)
-{
-       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 ((error = dsl_prop_get_integer(osname, "recordsize",
-           &recordsize, NULL)))
-               goto out;
-
-       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);
-
-#ifdef HAVE_FUID_FEATURES
-       /*
-        * 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);
-#endif /* HAVE_FUID_FEATURES */
-
-       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);
-       }
-
-       return (error);
-}
-EXPORT_SYMBOL(zfs_domount);
 
 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;
 
        /*
@@ -1092,34 +922,34 @@ 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);
@@ -1155,15 +985,15 @@ zfs_check_global_label(const char *dsname, const char *hexsl)
 #endif /* HAVE_MLSLABEL */
 
 int
-zfs_statvfs(vfs_t *vfsp, struct statvfs64 *statp)
+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);
 
        /*
@@ -1172,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 */
 
        /*
@@ -1193,63 +1024,54 @@ 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, MNTTYPE_ZFS);
-
-       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);
 
 int
-zfs_root(vfs_t *vfsp, vnode_t **vpp)
+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);
 
+#ifdef HAVE_DNLC
        if (!unmounting) {
                /*
                 * We purge the parent filesystem's vfsp as the parent
@@ -1257,28 +1079,29 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
                 * v_vfsp set to the parent's filesystem's vfsp.  Note,
                 * 'z_parent' is self referential for non-snapshots.
                 */
-               (void) dnlc_purge_vfsp(zfsvfs->z_parent->z_vfs, 0);
+               (void) dnlc_purge_vfsp(zsb->z_parent->z_vfs, 0);
        }
+#endif /* HAVE_DNLC */
 
        /*
         * 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);
        }
 
@@ -1289,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
@@ -1304,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*/
 int
-zfs_umount(vfs_t *vfsp, int fflag, cred_t *cr)
+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;
        }
 
-       vfsp->vfs_flag |= VFS_UNMOUNTED;
+       /* 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);
+       }
 
-       VERIFY(zfsvfs_teardown(zfsvfs, B_TRUE) == 0);
-       os = zfsvfs->z_os;
+       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(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) {
                /*
@@ -1406,33 +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);
 
 int
-zfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp)
+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;
@@ -1445,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) {
@@ -1462,103 +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);
-       if (*vpp)
-               zfs_inode_update(VTOZ(*vpp));
+       *ipp = ZTOI(zp);
+       if (*ipp)
+               zfs_inode_update(ITOZ(*ipp));
 
-       ZFS_EXIT(zfsvfs);
+       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
@@ -1566,78 +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;
-
-       zfsvfs_free(zfsvfs);
-}
-#endif /* HAVE_ZPL */
-
-void
-zfs_init(void)
-{
-       zfsctl_init();
-       zfs_znode_init();
-
-       dmu_objset_register_type(DMU_OST_ZFS, zfs_space_delta_cb);
-}
-
-void
-zfs_fini(void)
-{
-       zfsctl_fini();
-       zfs_znode_fini();
-}
-
-#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);
@@ -1656,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);
@@ -1674,21 +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;
 
-#ifdef HAVE_FUID_FEATURES
-       if (zfsvfs->z_version >= ZPL_VERSION_FUID)
-               zfs_set_fuid_feature(zfsvfs);
-#endif /* HAVE_FUID_FEATURES */
+       if (zsb->z_version >= ZPL_VERSION_FUID)
+               zfs_set_fuid_feature(zsb);
 
        return (0);
 }
 EXPORT_SYMBOL(zfs_set_version);
-#endif /* HAVE_ZPL */
 
 /*
  * Read a property stored within the master node.
@@ -1731,3 +1568,18 @@ zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value)
        }
        return (error);
 }
+
+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 764f530408249bc4fa90616e3140953507f3c0bb..a8019ba5ca9949e5772bc58847fe905a46c26441 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>
  * 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)
+#if defined(_KERNEL) && defined(HAVE_MMAP)
 /*
  * Utility functions to map and unmap a single physical page.  These
  * are used to manage the mappable copies of ZFS file data, and therefore
@@ -346,7 +188,6 @@ zfs_unmap_page(page_t *pp, caddr_t addr)
                ppmapout(addr);
        }
 }
-#endif /* _KERNEL && HAVE_UIO_RW */
 
 /*
  * When a file is memory mapped, we must keep the IO data synchronized
@@ -356,7 +197,8 @@ 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)
 {
        int64_t off;
 
@@ -365,7 +207,7 @@ update_pages(vnode_t *vp, int64_t start, int len, objset_t *os, uint64_t oid)
                page_t *pp;
                uint64_t nbytes = MIN(PAGESIZE - off, len);
 
-               if (pp = page_lookup(vp, start, SE_SHARED)) {
+               if (pp = page_lookup(ip, start, SE_SHARED)) {
                        caddr_t va;
 
                        va = zfs_map_page(pp, S_WRITE);
@@ -390,10 +232,10 @@ 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;
+       znode_t *zp = ITOZ(ip);
+       objset_t *os = ITOZSB(ip)->z_os;
        int64_t start, off;
        int len = nbytes;
        int error = 0;
@@ -404,7 +246,7 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
                page_t *pp;
                uint64_t bytes = MIN(PAGESIZE - off, len);
 
-               if (pp = page_lookup(vp, start, SE_SHARED)) {
+               if (pp = page_lookup(ip, start, SE_SHARED)) {
                        caddr_t va;
 
                        va = zfs_map_page(pp, S_READ);
@@ -421,18 +263,18 @@ mappedread(vnode_t *vp, int nbytes, uio_t *uio)
        }
        return (error);
 }
+#endif /* _KERNEL && HAVE_MMAP */
 
 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.
  *             cr      - credentials of caller.
- *             ct      - caller context
  *
  *     OUT:    uio     - updated offset and range, buffer filled.
  *
@@ -440,26 +282,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 */
 int
-zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
+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 = 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 +311,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 +319,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 +359,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 +376,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 +388,21 @@ 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);
+/* XXX: Drop this, ARC update handled by zpl layer */
+#ifdef HAVE_MMAP
+               if (vn_has_cached_data(ip))
+                       error = mappedread(ip, nbytes, uio);
                else
                        error = dmu_read_uio(os, zp->z_id, uio, nbytes);
+#else
+               error = dmu_read_uio(os, zp->z_id, uio, nbytes);
+#endif /* HAVE_MMAP */
                if (error) {
                        /* convert checksum errors into IO errors */
                        if (error == ECKSUM)
@@ -562,9 +415,9 @@ 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_ACCESSTIME_STAMP(zsb, zp);
        zfs_inode_update(zp);
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
 EXPORT_SYMBOL(zfs_read);
@@ -572,12 +425,11 @@ 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.
  *             cr      - credentials of caller.
- *             ct      - caller context (NFS/CIFS fem monitor only)
  *
  *     OUT:    uio     - updated offset and range.
  *
@@ -585,36 +437,36 @@ EXPORT_SYMBOL(zfs_read);
  *             error code if failure
  *
  * Timestamps:
- *     vp - ctime|mtime updated if byte count > 0
+ *     ip - ctime|mtime updated if byte count > 0
  */
 
 /* ARGSUSED */
 int
-zfs_write(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
+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
@@ -626,14 +478,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);
 
        /*
@@ -642,31 +493,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.
@@ -677,6 +531,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.
@@ -708,7 +563,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);
        }
 
@@ -729,8 +584,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;
@@ -742,8 +597,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)));
@@ -776,7 +629,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);
@@ -835,7 +688,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();
@@ -847,17 +700,20 @@ 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);
+/* XXX: Drop this, ARC update handled by zpl layer */
+#ifdef HAVE_MMAP
+               if (tx_bytes && vn_has_cached_data(ip)) {
+                       update_pages(ip, woff,
+                           tx_bytes, zsb->z_os, zp->z_id);
                }
+#endif /* HAVE_MMAP */
 
                /*
                 * 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);
@@ -884,7 +740,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);
@@ -906,8 +762,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);
 
@@ -929,26 +785,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_inode_update(zp);
-       ZFS_EXIT(zfsvfs);
+       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);
@@ -959,7 +825,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);
@@ -977,8 +843,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;
@@ -994,20 +860,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;
 
        /*
@@ -1092,15 +957,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)
@@ -1108,46 +972,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);
-       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;
-       }
+       ZFS_EXIT(zsb);
        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
@@ -1157,18 +998,17 @@ specvp_check(vnode_t **vpp, cred_t *cr)
  */
 /* ARGSUSED */
 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)
+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);
@@ -1177,44 +1017,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);
                }
 
@@ -1223,12 +1063,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);
                }
 
@@ -1236,18 +1076,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,
+               if ((error = zfs_zaccess(ITOZ(*ipp), ACE_EXECUTE, 0,
                    B_FALSE, cr))) {
-                       VN_RELE(*vpp);
-                       *vpp = NULL;
+                       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);
        }
 
@@ -1256,25 +1096,21 @@ zfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp,
         */
 
        if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) {
-               ZFS_EXIT(zfsvfs);
+               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) {
-               if (*vpp)
-                       zfs_inode_update(VTOZ(*vpp));
-
-               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);
@@ -1282,42 +1118,39 @@ 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 */
 int
-zfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl,
-    int mode, vnode_t **vpp, cred_t *cr, int flag, caller_context_t *ct,
-    vsecattr_t *vsecp)
+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;
        zfs_acl_ids_t   acl_ids;
@@ -1330,51 +1163,45 @@ zfs_create(vnode_t *dvp, char *name, vattr_t *vap, int excl,
         */
 
        gid = crgetgid(cr);
-       ksid = crgetsid(cr, KSID_OWNER);
-       if (ksid)
-               uid = ksid_getid(ksid);
-       else
-               uid = crgetuid(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)
@@ -1387,7 +1214,7 @@ top:
                                zfs_acl_ids_free(&acl_ids);
                        if (strcmp(name, "..") == 0)
                                error = EISDIR;
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
@@ -1410,8 +1237,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;
@@ -1423,7 +1249,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;
@@ -1434,12 +1260,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);
@@ -1454,13 +1280,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);
@@ -1483,14 +1309,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;
                }
@@ -1508,15 +1334,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:
@@ -1526,18 +1349,17 @@ out:
 
        if (error) {
                if (zp)
-                       VN_RELE(ZTOV(zp));
+                       iput(ZTOI(zp));
        } else {
                zfs_inode_update(dzp);
                zfs_inode_update(zp);
-               *vpp = ZTOV(zp);
-               error = specvp_check(vpp, cr);
+               *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);
@@ -1545,54 +1367,54 @@ 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*/
 int
-zfs_remove(vnode_t *dvp, char *name, cred_t *cr, caller_context_t *ct,
-    int flags)
+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;
@@ -1602,13 +1424,15 @@ top:
         */
        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))) {
                goto out;
@@ -1617,75 +1441,60 @@ top:
        /*
         * 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);
        }
 
@@ -1700,64 +1509,31 @@ 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);
@@ -1765,103 +1541,97 @@ out:
        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*/
 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)
+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);
        }
        /*
@@ -1872,39 +1642,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))) {
                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))) {
                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);
        }
@@ -1922,7 +1692,7 @@ top:
                }
                zfs_acl_ids_free(&acl_ids);
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -1932,14 +1702,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)
@@ -1953,12 +1723,12 @@ 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_inode_update(dzp);
        zfs_inode_update(zp);
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (0);
 }
 EXPORT_SYMBOL(zfs_mkdir);
@@ -1968,37 +1738,36 @@ EXPORT_SYMBOL(zfs_mkdir);
  * 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*/
 int
-zfs_rmdir(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr,
-    caller_context_t *ct, int flags)
+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;
@@ -2010,28 +1779,26 @@ top:
         */
        if ((error = zfs_dirent_lock(&dl, dzp, name, &zp, zflg,
            NULL, NULL))) {
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
-       vp = ZTOV(zp);
+       ip = ZTOI(zp);
 
        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.
@@ -2044,10 +1811,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);
@@ -2055,14 +1822,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);
        }
 
@@ -2082,38 +1849,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_inode_update(dzp);
        zfs_inode_update(zp);
-       ZFS_EXIT(zfsvfs);
+       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:
@@ -2121,70 +1882,42 @@ EXPORT_SYMBOL(zfs_rmdir);
  * 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.
                 */
@@ -2193,55 +1926,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;
@@ -2249,8 +1955,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;
@@ -2261,155 +1967,63 @@ 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;
 
 int
-zfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
+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);
 }
@@ -2420,43 +2034,37 @@ 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 */
 int
-zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-    caller_context_t *ct)
+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);
        }
 
@@ -2466,10 +2074,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))) {
+           (stat->uid != crgetuid(cr))) {
                if ((error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0,
                    skipaclchk, cr))) {
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (error);
                }
        }
@@ -2480,142 +2088,36 @@ 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);
-               }
+       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_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);
-               }
-
-               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);
@@ -2624,32 +2126,29 @@ 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 */
 int
-zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
-       caller_context_t *ct)
+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;
@@ -2660,10 +2159,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;
@@ -2671,81 +2168,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);
-               return (EPERM);
-       }
-
-       if ((mask & AT_SIZE) && (zp->z_pflags & ZFS_READONLY)) {
-               ZFS_EXIT(zfsvfs);
+       if ((mask & ATTR_SIZE) && (zp->z_pflags & ZFS_READONLY)) {
+               ZFS_EXIT(zsb);
                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);
        }
 
@@ -2753,10 +2213,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);
                }
                /*
@@ -2766,27 +2226,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;
 
@@ -2795,16 +2250,17 @@ 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
@@ -2815,16 +2271,17 @@ top:
                 *
                 */
 
-               if (((idmask == (AT_UID|AT_GID)) && take_owner && take_group) ||
-                   ((idmask == AT_UID) && take_owner) ||
-                   ((idmask == AT_GID) && take_group)) {
+               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(vap, cr);
-                               trim_mask = (mask & (AT_UID|AT_GID));
+                               secpolicy_setid_clear(attr, cr);
+                               trim_mask = (mask & (ATTR_UID|ATTR_GID));
                        } else {
                                need_policy =  TRUE;
                        }
@@ -2836,100 +2293,18 @@ top:
        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);
-                       }
-               }
-
-               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;
-                       } else {
-                               XVA_CLR_REQ(xvap, XAT_AV_QUARANTINED);
-                               XVA_SET_REQ(&tmpxvattr, XAT_AV_QUARANTINED);
-                       }
-               }
-
-               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;
-               }
-       }
 
        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;
                }
@@ -2945,65 +2320,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);
 
@@ -3013,7 +2388,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,
@@ -3031,20 +2406,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);
 
@@ -3065,49 +2436,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;
                }
@@ -3119,8 +2490,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);
@@ -3133,34 +2504,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);
@@ -3171,50 +2542,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);
        }
@@ -3226,7 +2565,7 @@ out:
        }
 
        if (attrzp)
-               VN_RELE(ZTOV(attrzp));
+               iput(ZTOI(attrzp));
        if (aclp)
                zfs_acl_free(aclp);
 
@@ -3246,10 +2585,10 @@ out:
        }
 
 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);
@@ -3270,7 +2609,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));
@@ -3288,7 +2627,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;
@@ -3336,12 +2675,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;
@@ -3355,30 +2694,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*/
 int
-zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
-    caller_context_t *ct, int flags)
+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;
@@ -3386,26 +2723,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);
        }
 
@@ -3423,7 +2754,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);
        }
 
@@ -3442,10 +2773,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
@@ -3453,7 +2784,7 @@ top:
                         * the rename() function shall return successfully
                         * and perform no other action."
                         */
-                       ZFS_EXIT(zfsvfs);
+                       ZFS_EXIT(zsb);
                        return (0);
                }
                /*
@@ -3474,10 +2805,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
@@ -3517,7 +2848,7 @@ top:
                if (!terr) {
                        zfs_dirent_unlock(tdl);
                        if (tzp)
-                               VN_RELE(ZTOV(tzp));
+                               iput(ZTOI(tzp));
                }
 
                if (sdzp == tdzp)
@@ -3525,19 +2856,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);
        }
 
@@ -3551,7 +2882,7 @@ top:
        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
@@ -3567,13 +2898,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;
                        }
@@ -3589,19 +2920,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);
@@ -3616,7 +2935,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)
@@ -3627,16 +2946,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);
        }
 
@@ -3648,7 +2967,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);
 
@@ -3657,12 +2976,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
@@ -3698,16 +3011,16 @@ out:
                zfs_inode_update(tdzp);
 
        zfs_inode_update(szp);
-       VN_RELE(ZTOV(szp));
+       iput(ZTOI(szp));
        if (tzp) {
                zfs_inode_update(tzp);
-               VN_RELE(ZTOV(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);
@@ -3715,29 +3028,29 @@ 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*/
 int
-zfs_symlink(vnode_t *dvp, char *name, vattr_t *vap, char *link, cred_t *cr,
-    caller_context_t *ct, int flags)
+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;
@@ -3746,67 +3059,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))) {
                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);
@@ -3817,7 +3132,7 @@ top:
                }
                zfs_acl_ids_free(&acl_ids);
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -3828,18 +3143,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.
@@ -3859,138 +3174,148 @@ top:
 
        zfs_dirent_unlock(dl);
 
-       VN_RELE(ZTOV(zp));
+       *ipp = ZTOI(zp);
+       iput(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.
- *
- *     IN:     vp      - vnode of symbolic link.
- *             uoip    - structure to contain the link path.
- *             cr      - credentials of caller.
- *             ct      - caller context
+ * the symbolic path referred to by ip.
  *
- *     OUT:    uio     - structure to contain the link path.
+ *     IN:     dentry  - dentry of symbolic link.
+ *             nd      - namedata for symlink
  *
  *     RETURN: 0 if success
  *             error code if failure
  *
  * Timestamps:
- *     vp - atime updated
+ *     ip - atime updated
  */
 /* ARGSUSED */
 int
-zfs_readlink(vnode_t *vp, uio_t *uio, cred_t *cr, caller_context_t *ct)
+zfs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       znode_t         *zp = VTOZ(vp);
-       zfsvfs_t        *zfsvfs = zp->z_zfsvfs;
+       struct inode    *ip = dentry->d_inode;
+       znode_t         *zp = ITOZ(ip);
+       zfs_sb_t        *zsb = ITOZSB(ip);
+       struct iovec    iov;
+       uio_t           uio;
        int             error;
 
-       ZFS_ENTER(zfsvfs);
+       ZFS_ENTER(zsb);
        ZFS_VERIFY_ZP(zp);
 
+       iov.iov_len = MAXPATHLEN + 1;
+       iov.iov_base = kmem_zalloc(iov.iov_len, KM_SLEEP);
+
+       uio.uio_iov = &iov;
+       uio.uio_iovcnt = 1;
+       uio.uio_resid = iov.iov_len;
+       uio.uio_segflg = UIO_SYSSPACE;
+
        mutex_enter(&zp->z_lock);
        if (zp->z_is_sa)
-               error = sa_lookup_uio(zp->z_sa_hdl,
-                   SA_ZPL_SYMLINK(zfsvfs), uio);
+               error = sa_lookup_uio(zp->z_sa_hdl, SA_ZPL_SYMLINK(zsb), &uio);
        else
-               error = zfs_sa_readlink(zp, uio);
+               error = zfs_sa_readlink(zp, &uio);
        mutex_exit(&zp->z_lock);
 
-       ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
-
+       ZFS_ACCESSTIME_STAMP(zsb, zp);
        zfs_inode_update(zp);
-       ZFS_EXIT(zfsvfs);
+
+       if (error) {
+               kmem_free(iov.iov_base, iov.iov_len);
+               nd_set_link(nd, ERR_PTR(error));
+       } else {
+               nd_set_link(nd, iov.iov_base);
+       }
+
+       ZFS_EXIT(zsb);
        return (error);
 }
-EXPORT_SYMBOL(zfs_readlink);
+EXPORT_SYMBOL(zfs_follow_link);
 
 /*
- * 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 */
 int
-zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
-    caller_context_t *ct, int flags)
+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
@@ -3999,19 +3324,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);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -4021,11 +3345,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);
@@ -4039,7 +3363,7 @@ top:
                        goto top;
                }
                dmu_tx_abort(tx);
-               ZFS_EXIT(zfsvfs);
+               ZFS_EXIT(zsb);
                return (error);
        }
 
@@ -4047,8 +3371,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);
        }
 
@@ -4056,16 +3382,12 @@ 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_inode_update(dzp);
        zfs_inode_update(szp);
-       ZFS_EXIT(zfsvfs);
+       ZFS_EXIT(zsb);
        return (error);
 }
 EXPORT_SYMBOL(zfs_link);
@@ -4355,7 +3677,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);
@@ -4364,14 +3686,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
@@ -4380,14 +3702,15 @@ EXPORT_SYMBOL(zfs_inactive);
  *             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);
 
 /*
  * Pre-filter the generic locking function to trap attempts to place
@@ -4734,51 +4057,98 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr,
        return (0);
 }
 
+/*
+ * 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
  * supports the `F_FREESP' command.  However, this command is somewhat
  * 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 */
 int
-zfs_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag,
-    offset_t offset, cred_t *cr, caller_context_t *ct)
+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);
        }
 
@@ -4787,38 +4157,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*/
 int
-zfs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
+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);
        }
 
@@ -4836,7 +4206,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;
@@ -4849,95 +4219,24 @@ 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);
 }
 EXPORT_SYMBOL(zfs_fid);
 
-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));
-       }
-}
-
 /*ARGSUSED*/
 int
-zfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr,
-    caller_context_t *ct)
+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);
 }
@@ -4945,46 +4244,45 @@ EXPORT_SYMBOL(zfs_getsecattr);
 
 /*ARGSUSED*/
 int
-zfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr,
-    caller_context_t *ct)
+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;
@@ -4997,7 +4295,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:
@@ -5007,7 +4305,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);
                }
                /*
@@ -5030,9 +4328,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
@@ -5075,7 +4370,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);
                }
 
@@ -5083,25 +4378,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;
@@ -5124,174 +4419,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 283b4d511027b2c2d220a12f2764606b5d5665a7..02466828767c3b4ab3a697cf3ba2baff25618cf8 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
-/*
- * 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;
 
@@ -102,14 +99,7 @@ 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);
@@ -133,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);
@@ -154,11 +141,10 @@ 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);
+           zfs_znode_cache_destructor, NULL, NULL, NULL, KMC_KMEM);
 }
 
 void
@@ -170,12 +156,10 @@ zfs_znode_fini(void)
        if (znode_cache)
                kmem_cache_destroy(znode_cache);
        znode_cache = NULL;
-       rw_destroy(&zfsvfs_lock);
 }
 
-#ifdef HAVE_ZPL
 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;
@@ -186,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;
@@ -214,7 +196,7 @@ 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);
 
@@ -238,8 +220,6 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
 #define        MAXMIN64        0xffffffffUL
 #endif
 
-#endif /* HAVE_ZPL */
-
 /*
  * Create special expldev for ZFS private use.
  * Can't use standard expldev since it doesn't do
@@ -260,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;
@@ -304,60 +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+inode and initialize.
+ * 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;
-       struct inode *inode;
+       struct inode *ip;
        uint64_t parent;
        sa_bulk_attr_t bulk[9];
        int count = 0;
 
-       ASSERT(zfsvfs != NULL);
-       ASSERT(zfsvfs->z_vfs != NULL);
-       ASSERT(zfsvfs->z_vfs->mnt_sb != NULL);
+       ASSERT(zsb != NULL);
 
-       inode = iget_locked(zfsvfs->z_vfs->mnt_sb, db->db_object);
-       zp = ITOZ(inode);
+       ip = new_inode(zsb->z_sb);
+       if (ip == NULL)
+               return (NULL);
 
-       ASSERT(inode->i_state & I_NEW);
+       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;
@@ -367,59 +382,48 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
        zp->z_seq = 0x7A4653;
        zp->z_sync_cnt = 0;
 
-       zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
-
-       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL,
-           &zp->z_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,
+       zfs_znode_sa_init(zsb, zp, db, obj_type, hdl);
+
+       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,
+       SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zsb), NULL,
            &parent, 8);
-       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, 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);
-               iput(inode);
-               return (NULL);
-       }
 
-       inode->i_mode = (umode_t)zp->z_mode;
-       if ((S_ISCHR(inode->i_mode)) || (S_ISBLK(inode->i_mode))) {
-               uint64_t rdev;
-               VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
-                   &rdev, sizeof (rdev)) == 0);
-               inode->i_rdev = zfs_cmpldev(rdev);
+               goto error;
        }
 
-       /* zp->z_set_ops_inode() must be set in sb->alloc_inode() */
-       ASSERT(zp->z_set_ops_inode != NULL);
-       zp->z_set_ops_inode(inode);
-       unlock_new_inode(inode);
+       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);
+
+       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;
 }
 
 /*
@@ -432,35 +436,35 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
 void
 zfs_inode_update(znode_t *zp)
 {
-       zfsvfs_t        *zfsvfs;
-       struct inode    *inode;
+       zfs_sb_t        *zsb;
+       struct inode    *ip;
        uint32_t        blksize;
        uint64_t        atime[2], mtime[2], ctime[2];
 
        ASSERT(zp != NULL);
-       zfsvfs = zp->z_zfsvfs;
-       inode = ZTOI(zp);
-
-       sa_lookup(zp->z_sa_hdl, SA_ZPL_ATIME(zfsvfs), &atime, 16);
-       sa_lookup(zp->z_sa_hdl, SA_ZPL_MTIME(zfsvfs), &mtime, 16);
-       sa_lookup(zp->z_sa_hdl, SA_ZPL_CTIME(zfsvfs), &ctime, 16);
-
-       spin_lock(&inode->i_lock);
-       inode->i_generation = zp->z_gen;
-       inode->i_uid = zp->z_uid;
-       inode->i_gid = zp->z_gid;
-       inode->i_nlink = zp->z_links;
-       inode->i_mode = zp->z_mode;
-       inode->i_blkbits = SPA_MINBLOCKSHIFT;
+       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 *)&inode->i_blocks);
+           (u_longlong_t *)&ip->i_blocks);
 
-       ZFS_TIME_DECODE(&inode->i_atime, atime);
-       ZFS_TIME_DECODE(&inode->i_mtime, mtime);
-       ZFS_TIME_DECODE(&inode->i_ctime, ctime);
+       ZFS_TIME_DECODE(&ip->i_atime, atime);
+       ZFS_TIME_DECODE(&ip->i_mtime, mtime);
+       ZFS_TIME_DECODE(&ip->i_ctime, ctime);
 
-       i_size_write(inode, zp->z_size);
-       spin_unlock(&inode->i_lock);
+       i_size_write(ip, zp->z_size);
+       spin_unlock(&ip->i_lock);
 }
 
 static uint64_t empty_xattr;
@@ -491,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;
@@ -503,9 +507,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        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 */
@@ -515,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;
 
@@ -528,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
@@ -572,21 +574,20 @@ 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))
                rdev = zfs_expldev(vap->va_rdev);
-       }
 
        parent = dzp->z_id;
        mode = acl_ids->z_mode;
@@ -603,20 +604,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));
 
        /*
@@ -628,75 +629,75 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        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))) {
+               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,
@@ -706,8 +707,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
@@ -721,118 +725,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);
                ASSERT3S(err, ==, 0);
        }
        kmem_free(sa_attrs, sizeof(sa_bulk_attr_t) * ZPL_END);
-       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)
-{
-#ifdef HAVE_XVATTR
-       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);
-       }
-#endif /* HAVE_XVATTR */
+       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;
@@ -842,11 +745,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);
        }
 
@@ -856,7 +759,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);
        }
 
@@ -878,19 +781,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
@@ -899,21 +801,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;
@@ -923,7 +825,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) {
@@ -933,9 +835,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);
        }
 
@@ -945,33 +847,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);
        }
 
@@ -979,14 +881,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);
 }
@@ -994,27 +896,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);
@@ -1022,29 +922,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,
@@ -1052,39 +931,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
@@ -1102,21 +956,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;
        }
 }
@@ -1146,7 +1000,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)
@@ -1157,7 +1011,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_ZPL
+#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
@@ -1171,7 +1025,7 @@ zfs_no_putpage(vnode_t *vp, page_t *pp, u_offset_t *offp, size_t *lenp,
        ASSERT(0);
        return (0);
 }
-#endif /* HAVE_ZPL */
+#endif /* HAVE_MMAP */
 
 /*
  * Increase the file length
@@ -1185,7 +1039,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;
@@ -1204,19 +1058,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 {
@@ -1240,7 +1094,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);
@@ -1257,13 +1111,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;
 
@@ -1283,7 +1137,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);
 
@@ -1296,16 +1150,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;
-#ifdef HAVE_ZPL
-       vnode_t *vp = ZTOV(zp);
-#endif /* HAVE_ZPL */
+       zfs_sb_t *zsb = ZTOZSB(zp);
        dmu_tx_t *tx;
        rl_t *rl;
        int error;
@@ -1325,13 +1176,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);
@@ -1347,44 +1198,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);
 
-#ifdef HAVE_ZPL
-       /*
-        * 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);
-       }
-#endif /* HAVE_ZPL */
-
        zfs_range_unlock(rl);
 
        return (0);
@@ -1399,25 +1224,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)
 {
-#ifdef HAVE_ZPL
-       vnode_t *vp = ZTOV(zp);
-#endif /* HAVE_ZPL */
+#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);
 
@@ -1429,17 +1254,17 @@ zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
                        return (error);
        }
 
-#ifdef HAVE_ZPL
+#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_ZPL */
+#endif /* HAVE_MANDLOCKS */
 
        if (len == 0) {
                error = zfs_trunc(zp, off);
@@ -1451,7 +1276,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);
@@ -1465,9 +1290,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);
@@ -1589,7 +1414,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 */