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.
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);
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