Use zfs_mknode() to create dataset root
[zfs.git] / module / zfs / zfs_znode.c
index b56e290..ea8b4c5 100644 (file)
@@ -1397,13 +1397,18 @@ log:
 void
 zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
 {
+       struct super_block *sb;
+       zfs_sb_t        *zsb;
        uint64_t        moid, obj, sa_obj, version;
+       uint64_t        sense = ZFS_CASE_SENSITIVE;
        uint64_t        norm = 0;
        nvpair_t        *elem;
        int             error;
-       timestruc_t     now;
-       dmu_buf_t       *db;
-       znode_phys_t    *pzp;
+       int             i;
+       znode_t         *rootzp = NULL;
+       vattr_t         vattr;
+       znode_t         *zp;
+       zfs_acl_ids_t   acl_ids;
 
        /*
         * First attempt to create master node.
@@ -1439,6 +1444,8 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
                ASSERT(error == 0);
                if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0)
                        norm = val;
+               else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0)
+                       sense = val;
        }
        ASSERT(version != 0);
        error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);
@@ -1464,47 +1471,77 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
        ASSERT(error == 0);
 
        /*
-        * Create root znode with code free of VFS dependencies.  This
-        * is important because without a registered filesystem and super
-        * block all the required VFS hooks will be missing.  The critical
-        * thing is to just crete the required root znode.
+        * Create root znode.  Create minimal znode/inode/zsb/sb
+        * to allow zfs_mknode to work.
         */
-       obj = zap_create_norm(os, norm, DMU_OT_DIRECTORY_CONTENTS,
-                             DMU_OT_ZNODE, sizeof (znode_phys_t), tx);
+       vattr.va_mask = ATTR_MODE|ATTR_UID|ATTR_GID;
+       vattr.va_mode = S_IFDIR|0755;
+       vattr.va_uid = crgetuid(cr);
+       vattr.va_gid = crgetgid(cr);
+
+       rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
+       rootzp->z_moved = 0;
+       rootzp->z_unlinked = 0;
+       rootzp->z_atime_dirty = 0;
+       rootzp->z_is_sa = USE_SA(version, os);
+
+       zsb = kmem_zalloc(sizeof (zfs_sb_t), KM_SLEEP);
+       zsb->z_os = os;
+       zsb->z_parent = zsb;
+       zsb->z_version = version;
+       zsb->z_use_fuids = USE_FUIDS(version, os);
+       zsb->z_use_sa = USE_SA(version, os);
+       zsb->z_norm = norm;
+
+       sb = kmem_zalloc(sizeof (struct super_block), KM_SLEEP);
+       sb->s_fs_info = zsb;
+
+       ZTOI(rootzp)->i_sb = sb;
+
+       error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
+           &zsb->z_attr_table);
 
-       VERIFY(0 == dmu_bonus_hold(os, obj, FTAG, &db));
-       dmu_buf_will_dirty(db, tx);
+       ASSERT(error == 0);
 
        /*
-        * Initialize the znode physical data to zero.
+        * Fold case on file systems that are always or sometimes case
+        * insensitive.
         */
-       ASSERT(db->db_size >= sizeof (znode_phys_t));
-       bzero(db->db_data, db->db_size);
-       pzp = db->db_data;
+       if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED)
+               zsb->z_norm |= U8_TEXTPREP_TOUPPER;
 
-       if (USE_FUIDS(version, os))
-               pzp->zp_flags = ZFS_ARCHIVE | ZFS_AV_MODIFIED;
+       mutex_init(&zsb->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
+       list_create(&zsb->z_all_znodes, sizeof (znode_t),
+           offsetof(znode_t, z_link_node));
 
-       pzp->zp_size = 2; /* "." and ".." */
-       pzp->zp_links = 2;
-       pzp->zp_parent = obj;
-       pzp->zp_gen = dmu_tx_get_txg(tx);
-       pzp->zp_mode = S_IFDIR | 0755;
-       pzp->zp_flags = ZFS_ACL_TRIVIAL;
+       for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
+               mutex_init(&zsb->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);
 
-       gethrestime(&now);
+       VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr,
+           cr, NULL, &acl_ids));
+       zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids);
+       ASSERT3P(zp, ==, rootzp);
+       error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx);
+       ASSERT(error == 0);
+       zfs_acl_ids_free(&acl_ids);
 
-       ZFS_TIME_ENCODE(&now, pzp->zp_crtime);
-       ZFS_TIME_ENCODE(&now, pzp->zp_ctime);
-       ZFS_TIME_ENCODE(&now, pzp->zp_atime);
-       ZFS_TIME_ENCODE(&now, pzp->zp_mtime);
+       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);
 
-       error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &obj, tx);
        ASSERT(error == 0);
 
-       dmu_buf_rele(db, FTAG);
+       for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
+               mutex_destroy(&zsb->z_hold_mtx[i]);
 }
-
 #endif /* _KERNEL */
 
 static int