summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2011-07-20 16:50:22 -0700
committerBrian Behlendorf <[email protected]>2011-07-20 19:52:26 -0700
commit22872ff5da0d12fe393e40d3e4b3c5a58d93e360 (patch)
treeb7a402d5588a747f58c0b68623dae7b43bfa921e
parent9fd91daeef4df4e2bc66f54bb97c88225c6dd2c7 (diff)
Use zfs_mknode() to create dataset root
Long, long, long ago when the effort to port ZFS was begun the zfs_create_fs() function was heavily modified to remove all of its VFS dependencies. This allowed Lustre to use the dataset without us having to spend the time porting all the required VFS code. Fast-forward several years and we now have all the VFS code in place but are still relying on the modified zfs_create_fs(). This isn't required anymore and we can now use zfs_mknode() to create the root znode for the filesystem. This commit reverts the contents of zfs_create_fs() to largely match the upstream OpenSolaris code. There have been minor modifications to accomidate the Linux VFS but that is all. This code fixes issue #116 by bootstraping enough of the VFS data structures so we can rely on zfs_mknode() to create the root directory. This ensures it is created properly with support for system attributes. Previously it wasn't which is why it behaved differently that all other directories when modified. Signed-off-by: Brian Behlendorf <[email protected]> Closes #116
-rw-r--r--module/zfs/zfs_znode.c99
1 files changed, 68 insertions, 31 deletions
diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
index b56e290cb..ea8b4c505 100644
--- a/module/zfs/zfs_znode.c
+++ b/module/zfs/zfs_znode.c
@@ -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