1--- a/CHANGES Thu Mar 06 19:36:02 2008 +0000
2+++ b/CHANGES Thu Mar 06 19:59:39 2008 +0000
3@@ -1,6 +1,6 @@
4 ? - Release 0.4.0_beta2
5 --------------------------------------------------
6- * Updated ZFS code to Nevada build 81.
7+ * Updated ZFS code to Nevada build 85.
8 Features:
9 * gzip compression support (upstream).
10 * Filesystems can have multiple copies of data (zfs set fs copies=x) (upstream).
1.1--- a/src/lib/libsolcompat/include/sys/time.h Thu Mar 06 19:36:02 2008 +0000
1.2+++ b/src/lib/libsolcompat/include/sys/time.h Thu Mar 06 19:59:39 2008 +0000
1.3@@ -20,7 +20,7 @@
1.4 * CDDL HEADER END
1.5 */
1.6 /*
1.7- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
1.8+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
1.9 * Use is subject to license terms.
1.10 */
1.11
1.12@@ -31,6 +31,7 @@
1.13
1.14 #include <stdio.h>
1.15 #include <stdlib.h>
1.16+#include <stdint.h>
1.17 #include <sys/types.h>
1.18 #include <time.h>
1.19
1.20@@ -38,6 +39,11 @@
1.21 typedef struct timespec timestruc_t;
1.22
1.23 #define NANOSEC 1000000000
1.24+
1.25+#define TIME32_MAX INT32_MAX
1.26+#define TIME32_MIN INT32_MIN
1.27+
1.28+#define TIMESPEC_OVERFLOW(ts) ((ts)->tv_sec < TIME32_MIN || (ts)->tv_sec > TIME32_MAX)
1.29
1.30 static inline hrtime_t gethrtime(void) {
1.31 struct timespec ts;
2.1--- a/src/lib/libzpool/SConscript Thu Mar 06 19:36:02 2008 +0000
2.2+++ b/src/lib/libzpool/SConscript Thu Mar 06 19:59:39 2008 +0000
2.3@@ -3,7 +3,7 @@
2.4 BuildDir('build-user', '.', duplicate = 0)
2.5 BuildDir('build-kernel', '.', duplicate = 0)
2.6
2.7-objects = Split('arc.c bplist.c dbuf.c dnode_sync.c dmu.c dmu_object.c dmu_objset.c dmu_send.c dmu_traverse.c dmu_tx.c dmu_zfetch.c dnode.c dsl_dataset.c dsl_deleg.c dsl_dir.c dsl_pool.c dsl_prop.c dsl_synctask.c fletcher.c gzip.c lzjb.c metaslab.c refcount.c rprwlock.c rrwlock.c sha256.c spa.c spa_config.c spa_errlog.c spa_history.c spa_misc.c space_map.c txg.c uberblock.c unique.c util.c vdev.c vdev_cache.c vdev_file.c vdev_label.c vdev_mirror.c vdev_missing.c vdev_queue.c vdev_raidz.c vdev_root.c zap.c zap_leaf.c zap_micro.c zfs_byteswap.c zfs_fm.c zfs_znode.c zil.c zio.c zio_checksum.c zio_compress.c zio_inject.c')
2.8+objects = Split('arc.c bplist.c dbuf.c dnode_sync.c dmu.c dmu_object.c dmu_objset.c dmu_send.c dmu_traverse.c dmu_tx.c dmu_zfetch.c dnode.c dsl_dataset.c dsl_deleg.c dsl_dir.c dsl_pool.c dsl_prop.c dsl_synctask.c fletcher.c gzip.c lzjb.c metaslab.c refcount.c rprwlock.c rrwlock.c sha256.c spa.c spa_config.c spa_errlog.c spa_history.c spa_misc.c space_map.c txg.c uberblock.c unique.c util.c vdev.c vdev_cache.c vdev_file.c vdev_label.c vdev_mirror.c vdev_missing.c vdev_queue.c vdev_raidz.c vdev_root.c zap.c zap_leaf.c zap_micro.c zfs_byteswap.c zfs_fm.c zfs_fuid.c zfs_znode.c zil.c zio.c zio_checksum.c zio_compress.c zio_inject.c')
2.9
2.10 objects_user = ['build-user/' + o for o in objects] + Split('build-user/kernel.c build-user/taskq.c')
2.11 objects_kernel = ['build-kernel/' + o for o in objects]
3.1--- a/src/zfs-fuse/SConscript Thu Mar 06 19:36:02 2008 +0000
3.2+++ b/src/zfs-fuse/SConscript Thu Mar 06 19:59:39 2008 +0000
3.3@@ -1,6 +1,6 @@
3.4 Import('env')
3.5
3.6-objects = Split('main.c cmd_listener.c ptrace.c util.c zfs_acl.c zfs_dir.c zfs_fuid.c zfs_ioctl.c zfs_log.c zfs_replay.c zfs_rlock.c zfs_vfsops.c zfs_vnops.c zvol.c fuse_listener.c zfsfuse_socket.c zfs_operations.c #lib/libzpool/libzpool-kernel.a #lib/libzfscommon/libzfscommon-kernel.a #lib/libnvpair/libnvpair-kernel.a #lib/libavl/libavl.a #lib/libumem/libumem.a #lib/libsolkerncompat/libsolkerncompat.a')
3.7+objects = Split('main.c cmd_listener.c ptrace.c util.c zfs_acl.c zfs_dir.c zfs_ioctl.c zfs_log.c zfs_replay.c zfs_rlock.c zfs_vfsops.c zfs_vnops.c zvol.c fuse_listener.c zfsfuse_socket.c zfs_operations.c #lib/libzpool/libzpool-kernel.a #lib/libzfscommon/libzfscommon-kernel.a #lib/libnvpair/libnvpair-kernel.a #lib/libavl/libavl.a #lib/libumem/libumem.a #lib/libsolkerncompat/libsolkerncompat.a')
3.8 cpppath = Split('#lib/libavl/include #lib/libnvpair/include #lib/libumem/include #lib/libzfscommon/include #lib/libsolkerncompat/include')
3.9 ccflags = Split('-D_KERNEL')
3.10
4.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2+++ b/src/lib/libzpool/zfs_fuid.c Thu Mar 06 19:59:39 2008 +0000
4.3@@ -0,0 +1,688 @@
4.4+/*
4.5+ * CDDL HEADER START
4.6+ *
4.7+ * The contents of this file are subject to the terms of the
4.8+ * Common Development and Distribution License (the "License").
4.9+ * You may not use this file except in compliance with the License.
4.10+ *
4.11+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4.12+ * or http://www.opensolaris.org/os/licensing.
4.13+ * See the License for the specific language governing permissions
4.14+ * and limitations under the License.
4.15+ *
4.16+ * When distributing Covered Code, include this CDDL HEADER in each
4.17+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4.18+ * If applicable, add the following below this CDDL HEADER, with the
4.19+ * fields enclosed by brackets "[]" replaced with your own identifying
4.20+ * information: Portions Copyright [yyyy] [name of copyright owner]
4.21+ *
4.22+ * CDDL HEADER END
4.23+ */
4.24+/*
4.25+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
4.26+ * Use is subject to license terms.
4.27+ */
4.28+
4.29+
4.30+
4.31+#include <sys/zfs_context.h>
4.32+#include <sys/sunddi.h>
4.33+#include <sys/dmu.h>
4.34+#include <sys/avl.h>
4.35+#include <sys/zap.h>
4.36+#include <sys/refcount.h>
4.37+#include <sys/nvpair.h>
4.38+#ifdef _KERNEL
4.39+#include <sys/kidmap.h>
4.40+#include <sys/sid.h>
4.41+#include <sys/zfs_vfsops.h>
4.42+#include <sys/zfs_znode.h>
4.43+#endif
4.44+#include <sys/zfs_fuid.h>
4.45+
4.46+/*
4.47+ * FUID Domain table(s).
4.48+ *
4.49+ * The FUID table is stored as a packed nvlist of an array
4.50+ * of nvlists which contain an index, domain string and offset
4.51+ *
4.52+ * During file system initialization the nvlist(s) are read and
4.53+ * two AVL trees are created. One tree is keyed by the index number
4.54+ * and the other by the domain string. Nodes are never removed from
4.55+ * trees, but new entries may be added. If a new entry is added then the
4.56+ * on-disk packed nvlist will also be updated.
4.57+ */
4.58+
4.59+#define FUID_IDX "fuid_idx"
4.60+#define FUID_DOMAIN "fuid_domain"
4.61+#define FUID_OFFSET "fuid_offset"
4.62+#define FUID_NVP_ARRAY "fuid_nvlist"
4.63+
4.64+typedef struct fuid_domain {
4.65+ avl_node_t f_domnode;
4.66+ avl_node_t f_idxnode;
4.67+ ksiddomain_t *f_ksid;
4.68+ uint64_t f_idx;
4.69+} fuid_domain_t;
4.70+
4.71+/*
4.72+ * Compare two indexes.
4.73+ */
4.74+static int
4.75+idx_compare(const void *arg1, const void *arg2)
4.76+{
4.77+ const fuid_domain_t *node1 = arg1;
4.78+ const fuid_domain_t *node2 = arg2;
4.79+
4.80+ if (node1->f_idx < node2->f_idx)
4.81+ return (-1);
4.82+ else if (node1->f_idx > node2->f_idx)
4.83+ return (1);
4.84+ return (0);
4.85+}
4.86+
4.87+/*
4.88+ * Compare two domain strings.
4.89+ */
4.90+static int
4.91+domain_compare(const void *arg1, const void *arg2)
4.92+{
4.93+ const fuid_domain_t *node1 = arg1;
4.94+ const fuid_domain_t *node2 = arg2;
4.95+ int val;
4.96+
4.97+ val = strcmp(node1->f_ksid->kd_name, node2->f_ksid->kd_name);
4.98+ if (val == 0)
4.99+ return (0);
4.100+ return (val > 0 ? 1 : -1);
4.101+}
4.102+
4.103+/*
4.104+ * load initial fuid domain and idx trees. This function is used by
4.105+ * both the kernel and zdb.
4.106+ */
4.107+uint64_t
4.108+zfs_fuid_table_load(objset_t *os, uint64_t fuid_obj, avl_tree_t *idx_tree,
4.109+ avl_tree_t *domain_tree)
4.110+{
4.111+ dmu_buf_t *db;
4.112+ uint64_t fuid_size;
4.113+
4.114+ avl_create(idx_tree, idx_compare,
4.115+ sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_idxnode));
4.116+ avl_create(domain_tree, domain_compare,
4.117+ sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_domnode));
4.118+
4.119+ VERIFY(0 == dmu_bonus_hold(os, fuid_obj, FTAG, &db));
4.120+ fuid_size = *(uint64_t *)db->db_data;
4.121+ dmu_buf_rele(db, FTAG);
4.122+
4.123+ if (fuid_size) {
4.124+ nvlist_t **fuidnvp;
4.125+ nvlist_t *nvp = NULL;
4.126+ uint_t count;
4.127+ char *packed;
4.128+ int i;
4.129+
4.130+ packed = kmem_alloc(fuid_size, KM_SLEEP);
4.131+ VERIFY(dmu_read(os, fuid_obj, 0, fuid_size, packed) == 0);
4.132+ VERIFY(nvlist_unpack(packed, fuid_size,
4.133+ &nvp, 0) == 0);
4.134+ VERIFY(nvlist_lookup_nvlist_array(nvp, FUID_NVP_ARRAY,
4.135+ &fuidnvp, &count) == 0);
4.136+
4.137+ for (i = 0; i != count; i++) {
4.138+ fuid_domain_t *domnode;
4.139+ char *domain;
4.140+ uint64_t idx;
4.141+
4.142+ VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN,
4.143+ &domain) == 0);
4.144+ VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_IDX,
4.145+ &idx) == 0);
4.146+
4.147+ domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
4.148+
4.149+ domnode->f_idx = idx;
4.150+ domnode->f_ksid = ksid_lookupdomain(domain);
4.151+ avl_add(idx_tree, domnode);
4.152+ avl_add(domain_tree, domnode);
4.153+ }
4.154+ nvlist_free(nvp);
4.155+ kmem_free(packed, fuid_size);
4.156+ }
4.157+ return (fuid_size);
4.158+}
4.159+
4.160+void
4.161+zfs_fuid_table_destroy(avl_tree_t *idx_tree, avl_tree_t *domain_tree)
4.162+{
4.163+ fuid_domain_t *domnode;
4.164+ void *cookie;
4.165+
4.166+ cookie = NULL;
4.167+ while (domnode = avl_destroy_nodes(domain_tree, &cookie))
4.168+ ksiddomain_rele(domnode->f_ksid);
4.169+
4.170+ avl_destroy(domain_tree);
4.171+ cookie = NULL;
4.172+ while (domnode = avl_destroy_nodes(idx_tree, &cookie))
4.173+ kmem_free(domnode, sizeof (fuid_domain_t));
4.174+ avl_destroy(idx_tree);
4.175+}
4.176+
4.177+char *
4.178+zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx)
4.179+{
4.180+ fuid_domain_t searchnode, *findnode;
4.181+ avl_index_t loc;
4.182+
4.183+ searchnode.f_idx = idx;
4.184+
4.185+ findnode = avl_find(idx_tree, &searchnode, &loc);
4.186+
4.187+ return (findnode->f_ksid->kd_name);
4.188+}
4.189+
4.190+#ifdef _KERNEL
4.191+/*
4.192+ * Load the fuid table(s) into memory.
4.193+ */
4.194+static void
4.195+zfs_fuid_init(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
4.196+{
4.197+ int error = 0;
4.198+
4.199+ rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
4.200+
4.201+ if (zfsvfs->z_fuid_loaded) {
4.202+ rw_exit(&zfsvfs->z_fuid_lock);
4.203+ return;
4.204+ }
4.205+
4.206+ if (zfsvfs->z_fuid_obj == 0) {
4.207+
4.208+ /* first make sure we need to allocate object */
4.209+
4.210+ error = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
4.211+ ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj);
4.212+ if (error == ENOENT && tx != NULL) {
4.213+ zfsvfs->z_fuid_obj = dmu_object_alloc(zfsvfs->z_os,
4.214+ DMU_OT_FUID, 1 << 14, DMU_OT_FUID_SIZE,
4.215+ sizeof (uint64_t), tx);
4.216+ VERIFY(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
4.217+ ZFS_FUID_TABLES, sizeof (uint64_t), 1,
4.218+ &zfsvfs->z_fuid_obj, tx) == 0);
4.219+ }
4.220+ }
4.221+
4.222+ zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
4.223+ zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
4.224+
4.225+ zfsvfs->z_fuid_loaded = B_TRUE;
4.226+ rw_exit(&zfsvfs->z_fuid_lock);
4.227+}
4.228+
4.229+/*
4.230+ * Query domain table for a given domain.
4.231+ *
4.232+ * If domain isn't found it is added to AVL trees and
4.233+ * the results are pushed out to disk.
4.234+ */
4.235+int
4.236+zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain, char **retdomain,
4.237+ dmu_tx_t *tx)
4.238+{
4.239+ fuid_domain_t searchnode, *findnode;
4.240+ avl_index_t loc;
4.241+
4.242+ /*
4.243+ * If the dummy "nobody" domain then return an index of 0
4.244+ * to cause the created FUID to be a standard POSIX id
4.245+ * for the user nobody.
4.246+ */
4.247+ if (domain[0] == '\0') {
4.248+ *retdomain = "";
4.249+ return (0);
4.250+ }
4.251+
4.252+ searchnode.f_ksid = ksid_lookupdomain(domain);
4.253+ if (retdomain) {
4.254+ *retdomain = searchnode.f_ksid->kd_name;
4.255+ }
4.256+ if (!zfsvfs->z_fuid_loaded)
4.257+ zfs_fuid_init(zfsvfs, tx);
4.258+
4.259+ rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
4.260+ findnode = avl_find(&zfsvfs->z_fuid_domain, &searchnode, &loc);
4.261+ rw_exit(&zfsvfs->z_fuid_lock);
4.262+
4.263+ if (findnode) {
4.264+ ksiddomain_rele(searchnode.f_ksid);
4.265+ return (findnode->f_idx);
4.266+ } else {
4.267+ fuid_domain_t *domnode;
4.268+ nvlist_t *nvp;
4.269+ nvlist_t **fuids;
4.270+ uint64_t retidx;
4.271+ size_t nvsize = 0;
4.272+ char *packed;
4.273+ dmu_buf_t *db;
4.274+ int i = 0;
4.275+
4.276+ domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
4.277+ domnode->f_ksid = searchnode.f_ksid;
4.278+
4.279+ rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
4.280+ retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
4.281+
4.282+ avl_add(&zfsvfs->z_fuid_domain, domnode);
4.283+ avl_add(&zfsvfs->z_fuid_idx, domnode);
4.284+ /*
4.285+ * Now resync the on-disk nvlist.
4.286+ */
4.287+ VERIFY(nvlist_alloc(&nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
4.288+
4.289+ domnode = avl_first(&zfsvfs->z_fuid_domain);
4.290+ fuids = kmem_alloc(retidx * sizeof (void *), KM_SLEEP);
4.291+ while (domnode) {
4.292+ VERIFY(nvlist_alloc(&fuids[i],
4.293+ NV_UNIQUE_NAME, KM_SLEEP) == 0);
4.294+ VERIFY(nvlist_add_uint64(fuids[i], FUID_IDX,
4.295+ domnode->f_idx) == 0);
4.296+ VERIFY(nvlist_add_uint64(fuids[i],
4.297+ FUID_OFFSET, 0) == 0);
4.298+ VERIFY(nvlist_add_string(fuids[i++], FUID_DOMAIN,
4.299+ domnode->f_ksid->kd_name) == 0);
4.300+ domnode = AVL_NEXT(&zfsvfs->z_fuid_domain, domnode);
4.301+ }
4.302+ VERIFY(nvlist_add_nvlist_array(nvp, FUID_NVP_ARRAY,
4.303+ fuids, retidx) == 0);
4.304+ for (i = 0; i != retidx; i++)
4.305+ nvlist_free(fuids[i]);
4.306+ kmem_free(fuids, retidx * sizeof (void *));
4.307+ VERIFY(nvlist_size(nvp, &nvsize, NV_ENCODE_XDR) == 0);
4.308+ packed = kmem_alloc(nvsize, KM_SLEEP);
4.309+ VERIFY(nvlist_pack(nvp, &packed, &nvsize,
4.310+ NV_ENCODE_XDR, KM_SLEEP) == 0);
4.311+ nvlist_free(nvp);
4.312+ zfsvfs->z_fuid_size = nvsize;
4.313+ dmu_write(zfsvfs->z_os, zfsvfs->z_fuid_obj, 0,
4.314+ zfsvfs->z_fuid_size, packed, tx);
4.315+ kmem_free(packed, zfsvfs->z_fuid_size);
4.316+ VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, zfsvfs->z_fuid_obj,
4.317+ FTAG, &db));
4.318+ dmu_buf_will_dirty(db, tx);
4.319+ *(uint64_t *)db->db_data = zfsvfs->z_fuid_size;
4.320+ dmu_buf_rele(db, FTAG);
4.321+
4.322+ rw_exit(&zfsvfs->z_fuid_lock);
4.323+ return (retidx);
4.324+ }
4.325+}
4.326+
4.327+/*
4.328+ * Query domain table by index, returning domain string
4.329+ *
4.330+ * Returns a pointer from an avl node of the domain string.
4.331+ *
4.332+ */
4.333+static char *
4.334+zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
4.335+{
4.336+ char *domain;
4.337+
4.338+ if (idx == 0 || !zfsvfs->z_use_fuids)
4.339+ return (NULL);
4.340+
4.341+ if (!zfsvfs->z_fuid_loaded)
4.342+ zfs_fuid_init(zfsvfs, NULL);
4.343+
4.344+ rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
4.345+ domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx);
4.346+ rw_exit(&zfsvfs->z_fuid_lock);
4.347+
4.348+ ASSERT(domain);
4.349+ return (domain);
4.350+}
4.351+
4.352+void
4.353+zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
4.354+{
4.355+ *uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_phys->zp_uid,
4.356+ cr, ZFS_OWNER);
4.357+ *gidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_phys->zp_gid,
4.358+ cr, ZFS_GROUP);
4.359+}
4.360+
4.361+uid_t
4.362+zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
4.363+ cred_t *cr, zfs_fuid_type_t type)
4.364+{
4.365+ uint32_t index = FUID_INDEX(fuid);
4.366+ char *domain;
4.367+ uid_t id;
4.368+
4.369+ if (index == 0)
4.370+ return (fuid);
4.371+
4.372+ domain = zfs_fuid_find_by_idx(zfsvfs, index);
4.373+ ASSERT(domain != NULL);
4.374+
4.375+ if (type == ZFS_OWNER || type == ZFS_ACE_USER) {
4.376+ (void) kidmap_getuidbysid(crgetzone(cr), domain,
4.377+ FUID_RID(fuid), &id);
4.378+ } else {
4.379+ (void) kidmap_getgidbysid(crgetzone(cr), domain,
4.380+ FUID_RID(fuid), &id);
4.381+ }
4.382+ return (id);
4.383+}
4.384+
4.385+/*
4.386+ * Add a FUID node to the list of fuid's being created for this
4.387+ * ACL
4.388+ *
4.389+ * If ACL has multiple domains, then keep only one copy of each unique
4.390+ * domain.
4.391+ */
4.392+static void
4.393+zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid,
4.394+ uint64_t idx, uint64_t id, zfs_fuid_type_t type)
4.395+{
4.396+ zfs_fuid_t *fuid;
4.397+ zfs_fuid_domain_t *fuid_domain;
4.398+ zfs_fuid_info_t *fuidp;
4.399+ uint64_t fuididx;
4.400+ boolean_t found = B_FALSE;
4.401+
4.402+ if (*fuidpp == NULL)
4.403+ *fuidpp = zfs_fuid_info_alloc();
4.404+
4.405+ fuidp = *fuidpp;
4.406+ /*
4.407+ * First find fuid domain index in linked list
4.408+ *
4.409+ * If one isn't found then create an entry.
4.410+ */
4.411+
4.412+ for (fuididx = 1, fuid_domain = list_head(&fuidp->z_domains);
4.413+ fuid_domain; fuid_domain = list_next(&fuidp->z_domains,
4.414+ fuid_domain), fuididx++) {
4.415+ if (idx == fuid_domain->z_domidx) {
4.416+ found = B_TRUE;
4.417+ break;
4.418+ }
4.419+ }
4.420+
4.421+ if (!found) {
4.422+ fuid_domain = kmem_alloc(sizeof (zfs_fuid_domain_t), KM_SLEEP);
4.423+ fuid_domain->z_domain = domain;
4.424+ fuid_domain->z_domidx = idx;
4.425+ list_insert_tail(&fuidp->z_domains, fuid_domain);
4.426+ fuidp->z_domain_str_sz += strlen(domain) + 1;
4.427+ fuidp->z_domain_cnt++;
4.428+ }
4.429+
4.430+ if (type == ZFS_ACE_USER || type == ZFS_ACE_GROUP) {
4.431+ /*
4.432+ * Now allocate fuid entry and add it on the end of the list
4.433+ */
4.434+
4.435+ fuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP);
4.436+ fuid->z_id = id;
4.437+ fuid->z_domidx = idx;
4.438+ fuid->z_logfuid = FUID_ENCODE(fuididx, rid);
4.439+
4.440+ list_insert_tail(&fuidp->z_fuids, fuid);
4.441+ fuidp->z_fuid_cnt++;
4.442+ } else {
4.443+ if (type == ZFS_OWNER)
4.444+ fuidp->z_fuid_owner = FUID_ENCODE(fuididx, rid);
4.445+ else
4.446+ fuidp->z_fuid_group = FUID_ENCODE(fuididx, rid);
4.447+ }
4.448+}
4.449+
4.450+/*
4.451+ * Create a file system FUID, based on information in the users cred
4.452+ */
4.453+uint64_t
4.454+zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
4.455+ dmu_tx_t *tx, cred_t *cr, zfs_fuid_info_t **fuidp)
4.456+{
4.457+ uint64_t idx;
4.458+ ksid_t *ksid;
4.459+ uint32_t rid;
4.460+ char *kdomain;
4.461+ const char *domain;
4.462+ uid_t id;
4.463+
4.464+ VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);
4.465+
4.466+ if (type == ZFS_OWNER)
4.467+ id = crgetuid(cr);
4.468+ else
4.469+ id = crgetgid(cr);
4.470+
4.471+ if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id))
4.472+ return ((uint64_t)id);
4.473+
4.474+ ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);
4.475+
4.476+ VERIFY(ksid != NULL);
4.477+ rid = ksid_getrid(ksid);
4.478+ domain = ksid_getdomain(ksid);
4.479+
4.480+ idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);
4.481+
4.482+ zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);
4.483+
4.484+ return (FUID_ENCODE(idx, rid));
4.485+}
4.486+
4.487+/*
4.488+ * Create a file system FUID for an ACL ace
4.489+ * or a chown/chgrp of the file.
4.490+ * This is similar to zfs_fuid_create_cred, except that
4.491+ * we can't find the domain + rid information in the
4.492+ * cred. Instead we have to query Winchester for the
4.493+ * domain and rid.
4.494+ *
4.495+ * During replay operations the domain+rid information is
4.496+ * found in the zfs_fuid_info_t that the replay code has
4.497+ * attached to the zfsvfs of the file system.
4.498+ */
4.499+uint64_t
4.500+zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
4.501+ zfs_fuid_type_t type, dmu_tx_t *tx, zfs_fuid_info_t **fuidpp)
4.502+{
4.503+ const char *domain;
4.504+ char *kdomain;
4.505+ uint32_t fuid_idx = FUID_INDEX(id);
4.506+ uint32_t rid;
4.507+ idmap_stat status;
4.508+ uint64_t idx;
4.509+ boolean_t is_replay = (zfsvfs->z_assign >= TXG_INITIAL);
4.510+ zfs_fuid_t *zfuid = NULL;
4.511+ zfs_fuid_info_t *fuidp;
4.512+
4.513+ /*
4.514+ * If POSIX ID, or entry is already a FUID then
4.515+ * just return the id
4.516+ *
4.517+ * We may also be handed an already FUID'ized id via
4.518+ * chmod.
4.519+ */
4.520+
4.521+ if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
4.522+ return (id);
4.523+
4.524+ if (is_replay) {
4.525+ fuidp = zfsvfs->z_fuid_replay;
4.526+
4.527+ /*
4.528+ * If we are passed an ephemeral id, but no
4.529+ * fuid_info was logged then return NOBODY.
4.530+ * This is most likely a result of idmap service
4.531+ * not being available.
4.532+ */
4.533+ if (fuidp == NULL)
4.534+ return (UID_NOBODY);
4.535+
4.536+ switch (type) {
4.537+ case ZFS_ACE_USER:
4.538+ case ZFS_ACE_GROUP:
4.539+ zfuid = list_head(&fuidp->z_fuids);
4.540+ rid = FUID_RID(zfuid->z_logfuid);
4.541+ idx = FUID_INDEX(zfuid->z_logfuid);
4.542+ break;
4.543+ case ZFS_OWNER:
4.544+ rid = FUID_RID(fuidp->z_fuid_owner);
4.545+ idx = FUID_INDEX(fuidp->z_fuid_owner);
4.546+ break;
4.547+ case ZFS_GROUP:
4.548+ rid = FUID_RID(fuidp->z_fuid_group);
4.549+ idx = FUID_INDEX(fuidp->z_fuid_group);
4.550+ break;
4.551+ };
4.552+ domain = fuidp->z_domain_table[idx -1];
4.553+ } else {
4.554+ if (type == ZFS_OWNER || type == ZFS_ACE_USER)
4.555+ status = kidmap_getsidbyuid(crgetzone(cr), id,
4.556+ &domain, &rid);
4.557+ else
4.558+ status = kidmap_getsidbygid(crgetzone(cr), id,
4.559+ &domain, &rid);
4.560+
4.561+ if (status != 0) {
4.562+ /*
4.563+ * When returning nobody we will need to
4.564+ * make a dummy fuid table entry for logging
4.565+ * purposes.
4.566+ */
4.567+ rid = UID_NOBODY;
4.568+ domain = "";
4.569+ }
4.570+ }
4.571+
4.572+ idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);
4.573+
4.574+ if (!is_replay)
4.575+ zfs_fuid_node_add(fuidpp, kdomain, rid, idx, id, type);
4.576+ else if (zfuid != NULL) {
4.577+ list_remove(&fuidp->z_fuids, zfuid);
4.578+ kmem_free(zfuid, sizeof (zfs_fuid_t));
4.579+ }
4.580+ return (FUID_ENCODE(idx, rid));
4.581+}
4.582+
4.583+void
4.584+zfs_fuid_destroy(zfsvfs_t *zfsvfs)
4.585+{
4.586+ rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
4.587+ if (!zfsvfs->z_fuid_loaded) {
4.588+ rw_exit(&zfsvfs->z_fuid_lock);
4.589+ return;
4.590+ }
4.591+ zfs_fuid_table_destroy(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
4.592+ rw_exit(&zfsvfs->z_fuid_lock);
4.593+}
4.594+
4.595+/*
4.596+ * Allocate zfs_fuid_info for tracking FUIDs created during
4.597+ * zfs_mknode, VOP_SETATTR() or VOP_SETSECATTR()
4.598+ */
4.599+zfs_fuid_info_t *
4.600+zfs_fuid_info_alloc(void)
4.601+{
4.602+ zfs_fuid_info_t *fuidp;
4.603+
4.604+ fuidp = kmem_zalloc(sizeof (zfs_fuid_info_t), KM_SLEEP);
4.605+ list_create(&fuidp->z_domains, sizeof (zfs_fuid_domain_t),
4.606+ offsetof(zfs_fuid_domain_t, z_next));
4.607+ list_create(&fuidp->z_fuids, sizeof (zfs_fuid_t),
4.608+ offsetof(zfs_fuid_t, z_next));
4.609+ return (fuidp);
4.610+}
4.611+
4.612+/*
4.613+ * Release all memory associated with zfs_fuid_info_t
4.614+ */
4.615+void
4.616+zfs_fuid_info_free(zfs_fuid_info_t *fuidp)
4.617+{
4.618+ zfs_fuid_t *zfuid;
4.619+ zfs_fuid_domain_t *zdomain;
4.620+
4.621+ while ((zfuid = list_head(&fuidp->z_fuids)) != NULL) {
4.622+ list_remove(&fuidp->z_fuids, zfuid);
4.623+ kmem_free(zfuid, sizeof (zfs_fuid_t));
4.624+ }
4.625+
4.626+ if (fuidp->z_domain_table != NULL)
4.627+ kmem_free(fuidp->z_domain_table,
4.628+ (sizeof (char **)) * fuidp->z_domain_cnt);
4.629+
4.630+ while ((zdomain = list_head(&fuidp->z_domains)) != NULL) {
4.631+ list_remove(&fuidp->z_domains, zdomain);
4.632+ kmem_free(zdomain, sizeof (zfs_fuid_domain_t));
4.633+ }
4.634+
4.635+ kmem_free(fuidp, sizeof (zfs_fuid_info_t));
4.636+}
4.637+
4.638+/*
4.639+ * Check to see if id is a groupmember. If cred
4.640+ * has ksid info then sidlist is checked first
4.641+ * and if still not found then POSIX groups are checked
4.642+ *
4.643+ * Will use a straight FUID compare when possible.
4.644+ */
4.645+boolean_t
4.646+zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
4.647+{
4.648+ ksid_t *ksid = crgetsid(cr, KSID_GROUP);
4.649+ uid_t gid;
4.650+
4.651+ if (ksid) {
4.652+ int i;
4.653+ ksid_t *ksid_groups;
4.654+ ksidlist_t *ksidlist = crgetsidlist(cr);
4.655+ uint32_t idx = FUID_INDEX(id);
4.656+ uint32_t rid = FUID_RID(id);
4.657+
4.658+ ASSERT(ksidlist);
4.659+ ksid_groups = ksidlist->ksl_sids;
4.660+
4.661+ for (i = 0; i != ksidlist->ksl_nsid; i++) {
4.662+ if (idx == 0) {
4.663+ if (id != IDMAP_WK_CREATOR_GROUP_GID &&
4.664+ id == ksid_groups[i].ks_id) {
4.665+ return (B_TRUE);
4.666+ }
4.667+ } else {
4.668+ char *domain;
4.669+
4.670+ domain = zfs_fuid_find_by_idx(zfsvfs, idx);
4.671+ ASSERT(domain != NULL);
4.672+
4.673+ if (strcmp(domain,
4.674+ IDMAP_WK_CREATOR_SID_AUTHORITY) == 0)
4.675+ return (B_FALSE);
4.676+
4.677+ if ((strcmp(domain,
4.678+ ksid_groups[i].ks_domain->kd_name) == 0) &&
4.679+ rid == ksid_groups[i].ks_rid)
4.680+ return (B_TRUE);
4.681+ }
4.682+ }
4.683+ }
4.684+
4.685+ /*
4.686+ * Not found in ksidlist, check posix groups
4.687+ */
4.688+ gid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP);
4.689+ return (groupmember(gid, cr));
4.690+}
4.691+#endif
5.1--- a/src/zfs-fuse/zfs_fuid.c Thu Mar 06 19:36:02 2008 +0000
5.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3@@ -1,688 +0,0 @@
5.4-/*
5.5- * CDDL HEADER START
5.6- *
5.7- * The contents of this file are subject to the terms of the
5.8- * Common Development and Distribution License (the "License").
5.9- * You may not use this file except in compliance with the License.
5.10- *
5.11- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5.12- * or http://www.opensolaris.org/os/licensing.
5.13- * See the License for the specific language governing permissions
5.14- * and limitations under the License.
5.15- *
5.16- * When distributing Covered Code, include this CDDL HEADER in each
5.17- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5.18- * If applicable, add the following below this CDDL HEADER, with the
5.19- * fields enclosed by brackets "[]" replaced with your own identifying
5.20- * information: Portions Copyright [yyyy] [name of copyright owner]
5.21- *
5.22- * CDDL HEADER END
5.23- */
5.24-/*
5.25- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
5.26- * Use is subject to license terms.
5.27- */
5.28-
5.29-
5.30-
5.31-#include <sys/zfs_context.h>
5.32-#include <sys/sunddi.h>
5.33-#include <sys/dmu.h>
5.34-#include <sys/avl.h>
5.35-#include <sys/zap.h>
5.36-#include <sys/refcount.h>
5.37-#include <sys/nvpair.h>
5.38-#ifdef _KERNEL
5.39-#include <sys/kidmap.h>
5.40-#include <sys/sid.h>
5.41-#include <sys/zfs_vfsops.h>
5.42-#include <sys/zfs_znode.h>
5.43-#endif
5.44-#include <sys/zfs_fuid.h>
5.45-
5.46-/*
5.47- * FUID Domain table(s).
5.48- *
5.49- * The FUID table is stored as a packed nvlist of an array
5.50- * of nvlists which contain an index, domain string and offset
5.51- *
5.52- * During file system initialization the nvlist(s) are read and
5.53- * two AVL trees are created. One tree is keyed by the index number
5.54- * and the other by the domain string. Nodes are never removed from
5.55- * trees, but new entries may be added. If a new entry is added then the
5.56- * on-disk packed nvlist will also be updated.
5.57- */
5.58-
5.59-#define FUID_IDX "fuid_idx"
5.60-#define FUID_DOMAIN "fuid_domain"
5.61-#define FUID_OFFSET "fuid_offset"
5.62-#define FUID_NVP_ARRAY "fuid_nvlist"
5.63-
5.64-typedef struct fuid_domain {
5.65- avl_node_t f_domnode;
5.66- avl_node_t f_idxnode;
5.67- ksiddomain_t *f_ksid;
5.68- uint64_t f_idx;
5.69-} fuid_domain_t;
5.70-
5.71-/*
5.72- * Compare two indexes.
5.73- */
5.74-static int
5.75-idx_compare(const void *arg1, const void *arg2)
5.76-{
5.77- const fuid_domain_t *node1 = arg1;
5.78- const fuid_domain_t *node2 = arg2;
5.79-
5.80- if (node1->f_idx < node2->f_idx)
5.81- return (-1);
5.82- else if (node1->f_idx > node2->f_idx)
5.83- return (1);
5.84- return (0);
5.85-}
5.86-
5.87-/*
5.88- * Compare two domain strings.
5.89- */
5.90-static int
5.91-domain_compare(const void *arg1, const void *arg2)
5.92-{
5.93- const fuid_domain_t *node1 = arg1;
5.94- const fuid_domain_t *node2 = arg2;
5.95- int val;
5.96-
5.97- val = strcmp(node1->f_ksid->kd_name, node2->f_ksid->kd_name);
5.98- if (val == 0)
5.99- return (0);
5.100- return (val > 0 ? 1 : -1);
5.101-}
5.102-
5.103-/*
5.104- * load initial fuid domain and idx trees. This function is used by
5.105- * both the kernel and zdb.
5.106- */
5.107-uint64_t
5.108-zfs_fuid_table_load(objset_t *os, uint64_t fuid_obj, avl_tree_t *idx_tree,
5.109- avl_tree_t *domain_tree)
5.110-{
5.111- dmu_buf_t *db;
5.112- uint64_t fuid_size;
5.113-
5.114- avl_create(idx_tree, idx_compare,
5.115- sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_idxnode));
5.116- avl_create(domain_tree, domain_compare,
5.117- sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_domnode));
5.118-
5.119- VERIFY(0 == dmu_bonus_hold(os, fuid_obj, FTAG, &db));
5.120- fuid_size = *(uint64_t *)db->db_data;
5.121- dmu_buf_rele(db, FTAG);
5.122-
5.123- if (fuid_size) {
5.124- nvlist_t **fuidnvp;
5.125- nvlist_t *nvp = NULL;
5.126- uint_t count;
5.127- char *packed;
5.128- int i;
5.129-
5.130- packed = kmem_alloc(fuid_size, KM_SLEEP);
5.131- VERIFY(dmu_read(os, fuid_obj, 0, fuid_size, packed) == 0);
5.132- VERIFY(nvlist_unpack(packed, fuid_size,
5.133- &nvp, 0) == 0);
5.134- VERIFY(nvlist_lookup_nvlist_array(nvp, FUID_NVP_ARRAY,
5.135- &fuidnvp, &count) == 0);
5.136-
5.137- for (i = 0; i != count; i++) {
5.138- fuid_domain_t *domnode;
5.139- char *domain;
5.140- uint64_t idx;
5.141-
5.142- VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN,
5.143- &domain) == 0);
5.144- VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_IDX,
5.145- &idx) == 0);
5.146-
5.147- domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
5.148-
5.149- domnode->f_idx = idx;
5.150- domnode->f_ksid = ksid_lookupdomain(domain);
5.151- avl_add(idx_tree, domnode);
5.152- avl_add(domain_tree, domnode);
5.153- }
5.154- nvlist_free(nvp);
5.155- kmem_free(packed, fuid_size);
5.156- }
5.157- return (fuid_size);
5.158-}
5.159-
5.160-void
5.161-zfs_fuid_table_destroy(avl_tree_t *idx_tree, avl_tree_t *domain_tree)
5.162-{
5.163- fuid_domain_t *domnode;
5.164- void *cookie;
5.165-
5.166- cookie = NULL;
5.167- while (domnode = avl_destroy_nodes(domain_tree, &cookie))
5.168- ksiddomain_rele(domnode->f_ksid);
5.169-
5.170- avl_destroy(domain_tree);
5.171- cookie = NULL;
5.172- while (domnode = avl_destroy_nodes(idx_tree, &cookie))
5.173- kmem_free(domnode, sizeof (fuid_domain_t));
5.174- avl_destroy(idx_tree);
5.175-}
5.176-
5.177-char *
5.178-zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx)
5.179-{
5.180- fuid_domain_t searchnode, *findnode;
5.181- avl_index_t loc;
5.182-
5.183- searchnode.f_idx = idx;
5.184-
5.185- findnode = avl_find(idx_tree, &searchnode, &loc);
5.186-
5.187- return (findnode->f_ksid->kd_name);
5.188-}
5.189-
5.190-#ifdef _KERNEL
5.191-/*
5.192- * Load the fuid table(s) into memory.
5.193- */
5.194-static void
5.195-zfs_fuid_init(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
5.196-{
5.197- int error = 0;
5.198-
5.199- rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
5.200-
5.201- if (zfsvfs->z_fuid_loaded) {
5.202- rw_exit(&zfsvfs->z_fuid_lock);
5.203- return;
5.204- }
5.205-
5.206- if (zfsvfs->z_fuid_obj == 0) {
5.207-
5.208- /* first make sure we need to allocate object */
5.209-
5.210- error = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
5.211- ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj);
5.212- if (error == ENOENT && tx != NULL) {
5.213- zfsvfs->z_fuid_obj = dmu_object_alloc(zfsvfs->z_os,
5.214- DMU_OT_FUID, 1 << 14, DMU_OT_FUID_SIZE,
5.215- sizeof (uint64_t), tx);
5.216- VERIFY(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
5.217- ZFS_FUID_TABLES, sizeof (uint64_t), 1,
5.218- &zfsvfs->z_fuid_obj, tx) == 0);
5.219- }
5.220- }
5.221-
5.222- zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
5.223- zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
5.224-
5.225- zfsvfs->z_fuid_loaded = B_TRUE;
5.226- rw_exit(&zfsvfs->z_fuid_lock);
5.227-}
5.228-
5.229-/*
5.230- * Query domain table for a given domain.
5.231- *
5.232- * If domain isn't found it is added to AVL trees and
5.233- * the results are pushed out to disk.
5.234- */
5.235-int
5.236-zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain, char **retdomain,
5.237- dmu_tx_t *tx)
5.238-{
5.239- fuid_domain_t searchnode, *findnode;
5.240- avl_index_t loc;
5.241-
5.242- /*
5.243- * If the dummy "nobody" domain then return an index of 0
5.244- * to cause the created FUID to be a standard POSIX id
5.245- * for the user nobody.
5.246- */
5.247- if (domain[0] == '\0') {
5.248- *retdomain = "";
5.249- return (0);
5.250- }
5.251-
5.252- searchnode.f_ksid = ksid_lookupdomain(domain);
5.253- if (retdomain) {
5.254- *retdomain = searchnode.f_ksid->kd_name;
5.255- }
5.256- if (!zfsvfs->z_fuid_loaded)
5.257- zfs_fuid_init(zfsvfs, tx);
5.258-
5.259- rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
5.260- findnode = avl_find(&zfsvfs->z_fuid_domain, &searchnode, &loc);
5.261- rw_exit(&zfsvfs->z_fuid_lock);
5.262-
5.263- if (findnode) {
5.264- ksiddomain_rele(searchnode.f_ksid);
5.265- return (findnode->f_idx);
5.266- } else {
5.267- fuid_domain_t *domnode;
5.268- nvlist_t *nvp;
5.269- nvlist_t **fuids;
5.270- uint64_t retidx;
5.271- size_t nvsize = 0;
5.272- char *packed;
5.273- dmu_buf_t *db;
5.274- int i = 0;
5.275-
5.276- domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
5.277- domnode->f_ksid = searchnode.f_ksid;
5.278-
5.279- rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
5.280- retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
5.281-
5.282- avl_add(&zfsvfs->z_fuid_domain, domnode);
5.283- avl_add(&zfsvfs->z_fuid_idx, domnode);
5.284- /*
5.285- * Now resync the on-disk nvlist.
5.286- */
5.287- VERIFY(nvlist_alloc(&nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
5.288-
5.289- domnode = avl_first(&zfsvfs->z_fuid_domain);
5.290- fuids = kmem_alloc(retidx * sizeof (void *), KM_SLEEP);
5.291- while (domnode) {
5.292- VERIFY(nvlist_alloc(&fuids[i],
5.293- NV_UNIQUE_NAME, KM_SLEEP) == 0);
5.294- VERIFY(nvlist_add_uint64(fuids[i], FUID_IDX,
5.295- domnode->f_idx) == 0);
5.296- VERIFY(nvlist_add_uint64(fuids[i],
5.297- FUID_OFFSET, 0) == 0);
5.298- VERIFY(nvlist_add_string(fuids[i++], FUID_DOMAIN,
5.299- domnode->f_ksid->kd_name) == 0);
5.300- domnode = AVL_NEXT(&zfsvfs->z_fuid_domain, domnode);
5.301- }
5.302- VERIFY(nvlist_add_nvlist_array(nvp, FUID_NVP_ARRAY,
5.303- fuids, retidx) == 0);
5.304- for (i = 0; i != retidx; i++)
5.305- nvlist_free(fuids[i]);
5.306- kmem_free(fuids, retidx * sizeof (void *));
5.307- VERIFY(nvlist_size(nvp, &nvsize, NV_ENCODE_XDR) == 0);
5.308- packed = kmem_alloc(nvsize, KM_SLEEP);
5.309- VERIFY(nvlist_pack(nvp, &packed, &nvsize,
5.310- NV_ENCODE_XDR, KM_SLEEP) == 0);
5.311- nvlist_free(nvp);
5.312- zfsvfs->z_fuid_size = nvsize;
5.313- dmu_write(zfsvfs->z_os, zfsvfs->z_fuid_obj, 0,
5.314- zfsvfs->z_fuid_size, packed, tx);
5.315- kmem_free(packed, zfsvfs->z_fuid_size);
5.316- VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, zfsvfs->z_fuid_obj,
5.317- FTAG, &db));
5.318- dmu_buf_will_dirty(db, tx);
5.319- *(uint64_t *)db->db_data = zfsvfs->z_fuid_size;
5.320- dmu_buf_rele(db, FTAG);
5.321-
5.322- rw_exit(&zfsvfs->z_fuid_lock);
5.323- return (retidx);
5.324- }
5.325-}
5.326-
5.327-/*
5.328- * Query domain table by index, returning domain string
5.329- *
5.330- * Returns a pointer from an avl node of the domain string.
5.331- *
5.332- */
5.333-static char *
5.334-zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
5.335-{
5.336- char *domain;
5.337-
5.338- if (idx == 0 || !zfsvfs->z_use_fuids)
5.339- return (NULL);
5.340-
5.341- if (!zfsvfs->z_fuid_loaded)
5.342- zfs_fuid_init(zfsvfs, NULL);
5.343-
5.344- rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
5.345- domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx);
5.346- rw_exit(&zfsvfs->z_fuid_lock);
5.347-
5.348- ASSERT(domain);
5.349- return (domain);
5.350-}
5.351-
5.352-void
5.353-zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
5.354-{
5.355- *uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_phys->zp_uid,
5.356- cr, ZFS_OWNER);
5.357- *gidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_phys->zp_gid,
<