Add .zfs control directory
[zfs.git] / module / zfs / zfs_znode.c
index dfbe11a..3a6872f 100644 (file)
@@ -52,6 +52,7 @@
 #include <sys/zfs_rlock.h>
 #include <sys/zfs_fuid.h>
 #include <sys/zfs_vnops.h>
+#include <sys/zfs_ctldir.h>
 #include <sys/dnode.h>
 #include <sys/fs/zfs.h>
 #include <sys/kidmap.h>
@@ -106,6 +107,7 @@ zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
        rw_init(&zp->z_parent_lock, NULL, RW_DEFAULT, NULL);
        rw_init(&zp->z_name_lock, NULL, RW_DEFAULT, NULL);
        mutex_init(&zp->z_acl_lock, NULL, MUTEX_DEFAULT, NULL);
+       rw_init(&zp->z_xattr_lock, NULL, RW_DEFAULT, NULL);
 
        mutex_init(&zp->z_range_lock, NULL, MUTEX_DEFAULT, NULL);
        avl_create(&zp->z_range_avl, zfs_range_compare,
@@ -113,6 +115,7 @@ zfs_znode_cache_constructor(void *buf, void *arg, int kmflags)
 
        zp->z_dirlocks = NULL;
        zp->z_acl_cached = NULL;
+       zp->z_xattr_cached = NULL;
        zp->z_moved = 0;
        return (0);
 }
@@ -128,11 +131,13 @@ zfs_znode_cache_destructor(void *buf, void *arg)
        rw_destroy(&zp->z_parent_lock);
        rw_destroy(&zp->z_name_lock);
        mutex_destroy(&zp->z_acl_lock);
+       rw_destroy(&zp->z_xattr_lock);
        avl_destroy(&zp->z_range_avl);
        mutex_destroy(&zp->z_range_lock);
 
        ASSERT(zp->z_dirlocks == NULL);
        ASSERT(zp->z_acl_cached == NULL);
+       ASSERT(zp->z_xattr_cached == NULL);
 }
 
 void
@@ -263,8 +268,12 @@ zfs_inode_destroy(struct inode *ip)
        znode_t *zp = ITOZ(ip);
        zfs_sb_t *zsb = ZTOZSB(zp);
 
+       if (zfsctl_is_node(ip))
+               zfsctl_inode_destroy(ip);
+
        mutex_enter(&zsb->z_znodes_lock);
        list_remove(&zsb->z_all_znodes, zp);
+       zsb->z_nr_znodes--;
        mutex_exit(&zsb->z_znodes_lock);
 
        if (zp->z_acl_cached) {
@@ -272,6 +281,11 @@ zfs_inode_destroy(struct inode *ip)
                zp->z_acl_cached = NULL;
        }
 
+       if (zp->z_xattr_cached) {
+               nvlist_free(zp->z_xattr_cached);
+               zp->z_xattr_cached = NULL;
+       }
+
        kmem_cache_free(znode_cache, zp);
 }
 
@@ -343,6 +357,8 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
 
        zp = ITOZ(ip);
        ASSERT(zp->z_dirlocks == NULL);
+       ASSERT3P(zp->z_acl_cached, ==, NULL);
+       ASSERT3P(zp->z_xattr_cached, ==, NULL);
        zp->z_moved = 0;
        zp->z_sa_hdl = NULL;
        zp->z_unlinked = 0;
@@ -352,7 +368,9 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
        zp->z_blksz = blksz;
        zp->z_seq = 0x7A4653;
        zp->z_sync_cnt = 0;
-       zp->z_is_zvol = 0;
+       zp->z_is_zvol = B_FALSE;
+       zp->z_is_mapped = B_FALSE;
+       zp->z_is_ctldir = B_FALSE;
 
        zfs_znode_sa_init(zsb, zp, db, obj_type, hdl);
 
@@ -392,6 +410,7 @@ zfs_znode_alloc(zfs_sb_t *zsb, dmu_buf_t *db, int blksz,
 
        mutex_enter(&zsb->z_znodes_lock);
        list_insert_tail(&zsb->z_all_znodes, zp);
+       zsb->z_nr_znodes++;
        membar_producer();
        mutex_exit(&zsb->z_znodes_lock);
 
@@ -423,6 +442,10 @@ zfs_inode_update(znode_t *zp)
        zsb = ZTOZSB(zp);
        ip = ZTOI(zp);
 
+       /* Skip .zfs control nodes which do not exist on disk. */
+       if (zfsctl_is_node(ip))
+               return;
+
        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);
@@ -431,7 +454,7 @@ zfs_inode_update(znode_t *zp)
        ip->i_generation = zp->z_gen;
        ip->i_uid = zp->z_uid;
        ip->i_gid = zp->z_gid;
-       ip->i_nlink = zp->z_links;
+       set_nlink(ip, 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,
@@ -1527,20 +1550,19 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
 
        atomic_set(&ZTOI(rootzp)->i_count, 0);
        sa_handle_destroy(rootzp->z_sa_hdl);
-       kmem_free(sb, sizeof (struct super_block));
-       kmem_free(zsb, sizeof (zfs_sb_t));
        kmem_cache_free(znode_cache, rootzp);
 
        /*
         * Create shares directory
         */
-
        error = zfs_create_share_dir(zsb, tx);
-
        ASSERT(error == 0);
 
        for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
                mutex_destroy(&zsb->z_hold_mtx[i]);
+
+       kmem_free(sb, sizeof (struct super_block));
+       kmem_free(zsb, sizeof (zfs_sb_t));
 }
 #endif /* _KERNEL */