FreeBSD ZFS
The Zettabyte File System

zfs_fuid.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 /*
00022  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
00023  */
00024 
00025 #include <sys/zfs_context.h>
00026 #include <sys/dmu.h>
00027 #include <sys/avl.h>
00028 #include <sys/zap.h>
00029 #include <sys/refcount.h>
00030 #include <sys/nvpair.h>
00031 #ifdef _KERNEL
00032 #include <sys/kidmap.h>
00033 #include <sys/sid.h>
00034 #include <sys/zfs_vfsops.h>
00035 #include <sys/zfs_znode.h>
00036 #endif
00037 #include <sys/zfs_fuid.h>
00038 
00055 #define FUID_IDX        "fuid_idx"
00056 #define FUID_DOMAIN     "fuid_domain"
00057 #define FUID_OFFSET     "fuid_offset"
00058 #define FUID_NVP_ARRAY  "fuid_nvlist"
00059 
00060 typedef struct fuid_domain {
00061         avl_node_t      f_domnode;
00062         avl_node_t      f_idxnode;
00063         ksiddomain_t    *f_ksid;
00064         uint64_t        f_idx;
00065 } fuid_domain_t;
00066 
00067 static char *nulldomain = "";
00068 
00072 static int
00073 idx_compare(const void *arg1, const void *arg2)
00074 {
00075         const fuid_domain_t *node1 = arg1;
00076         const fuid_domain_t *node2 = arg2;
00077 
00078         if (node1->f_idx < node2->f_idx)
00079                 return (-1);
00080         else if (node1->f_idx > node2->f_idx)
00081                 return (1);
00082         return (0);
00083 }
00084 
00088 static int
00089 domain_compare(const void *arg1, const void *arg2)
00090 {
00091         const fuid_domain_t *node1 = arg1;
00092         const fuid_domain_t *node2 = arg2;
00093         int val;
00094 
00095         val = strcmp(node1->f_ksid->kd_name, node2->f_ksid->kd_name);
00096         if (val == 0)
00097                 return (0);
00098         return (val > 0 ? 1 : -1);
00099 }
00100 
00101 void
00102 zfs_fuid_avl_tree_create(avl_tree_t *idx_tree, avl_tree_t *domain_tree)
00103 {
00104         avl_create(idx_tree, idx_compare,
00105             sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_idxnode));
00106         avl_create(domain_tree, domain_compare,
00107             sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_domnode));
00108 }
00109 
00114 uint64_t
00115 zfs_fuid_table_load(objset_t *os, uint64_t fuid_obj, avl_tree_t *idx_tree,
00116     avl_tree_t *domain_tree)
00117 {
00118         dmu_buf_t *db;
00119         uint64_t fuid_size;
00120 
00121         ASSERT(fuid_obj != 0);
00122         VERIFY(0 == dmu_bonus_hold(os, fuid_obj,
00123             FTAG, &db));
00124         fuid_size = *(uint64_t *)db->db_data;
00125         dmu_buf_rele(db, FTAG);
00126 
00127         if (fuid_size)  {
00128                 nvlist_t **fuidnvp;
00129                 nvlist_t *nvp = NULL;
00130                 uint_t count;
00131                 char *packed;
00132                 int i;
00133 
00134                 packed = kmem_alloc(fuid_size, KM_SLEEP);
00135                 VERIFY(dmu_read(os, fuid_obj, 0,
00136                     fuid_size, packed, DMU_READ_PREFETCH) == 0);
00137                 VERIFY(nvlist_unpack(packed, fuid_size,
00138                     &nvp, 0) == 0);
00139                 VERIFY(nvlist_lookup_nvlist_array(nvp, FUID_NVP_ARRAY,
00140                     &fuidnvp, &count) == 0);
00141 
00142                 for (i = 0; i != count; i++) {
00143                         fuid_domain_t *domnode;
00144                         char *domain;
00145                         uint64_t idx;
00146 
00147                         VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN,
00148                             &domain) == 0);
00149                         VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_IDX,
00150                             &idx) == 0);
00151 
00152                         domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
00153 
00154                         domnode->f_idx = idx;
00155                         domnode->f_ksid = ksid_lookupdomain(domain);
00156                         avl_add(idx_tree, domnode);
00157                         avl_add(domain_tree, domnode);
00158                 }
00159                 nvlist_free(nvp);
00160                 kmem_free(packed, fuid_size);
00161         }
00162         return (fuid_size);
00163 }
00164 
00165 void
00166 zfs_fuid_table_destroy(avl_tree_t *idx_tree, avl_tree_t *domain_tree)
00167 {
00168         fuid_domain_t *domnode;
00169         void *cookie;
00170 
00171         cookie = NULL;
00172         while (domnode = avl_destroy_nodes(domain_tree, &cookie))
00173                 ksiddomain_rele(domnode->f_ksid);
00174 
00175         avl_destroy(domain_tree);
00176         cookie = NULL;
00177         while (domnode = avl_destroy_nodes(idx_tree, &cookie))
00178                 kmem_free(domnode, sizeof (fuid_domain_t));
00179         avl_destroy(idx_tree);
00180 }
00181 
00182 char *
00183 zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx)
00184 {
00185         fuid_domain_t searchnode, *findnode;
00186         avl_index_t loc;
00187 
00188         searchnode.f_idx = idx;
00189 
00190         findnode = avl_find(idx_tree, &searchnode, &loc);
00191 
00192         return (findnode ? findnode->f_ksid->kd_name : nulldomain);
00193 }
00194 
00195 #ifdef _KERNEL
00196 
00199 static void
00200 zfs_fuid_init(zfsvfs_t *zfsvfs)
00201 {
00202         rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
00203 
00204         if (zfsvfs->z_fuid_loaded) {
00205                 rw_exit(&zfsvfs->z_fuid_lock);
00206                 return;
00207         }
00208 
00209         zfs_fuid_avl_tree_create(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
00210 
00211         (void) zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
00212             ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj);
00213         if (zfsvfs->z_fuid_obj != 0) {
00214                 zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
00215                     zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx,
00216                     &zfsvfs->z_fuid_domain);
00217         }
00218 
00219         zfsvfs->z_fuid_loaded = B_TRUE;
00220         rw_exit(&zfsvfs->z_fuid_lock);
00221 }
00222 
00226 void
00227 zfs_fuid_sync(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
00228 {
00229         nvlist_t *nvp;
00230         nvlist_t **fuids;
00231         size_t nvsize = 0;
00232         char *packed;
00233         dmu_buf_t *db;
00234         fuid_domain_t *domnode;
00235         int numnodes;
00236         int i;
00237 
00238         if (!zfsvfs->z_fuid_dirty) {
00239                 return;
00240         }
00241 
00242         rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
00243 
00244         /*
00245          * First see if table needs to be created?
00246          */
00247         if (zfsvfs->z_fuid_obj == 0) {
00248                 zfsvfs->z_fuid_obj = dmu_object_alloc(zfsvfs->z_os,
00249                     DMU_OT_FUID, 1 << 14, DMU_OT_FUID_SIZE,
00250                     sizeof (uint64_t), tx);
00251                 VERIFY(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
00252                     ZFS_FUID_TABLES, sizeof (uint64_t), 1,
00253                     &zfsvfs->z_fuid_obj, tx) == 0);
00254         }
00255 
00256         VERIFY(nvlist_alloc(&nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
00257 
00258         numnodes = avl_numnodes(&zfsvfs->z_fuid_idx);
00259         fuids = kmem_alloc(numnodes * sizeof (void *), KM_SLEEP);
00260         for (i = 0, domnode = avl_first(&zfsvfs->z_fuid_domain); domnode; i++,
00261             domnode = AVL_NEXT(&zfsvfs->z_fuid_domain, domnode)) {
00262                 VERIFY(nvlist_alloc(&fuids[i], NV_UNIQUE_NAME, KM_SLEEP) == 0);
00263                 VERIFY(nvlist_add_uint64(fuids[i], FUID_IDX,
00264                     domnode->f_idx) == 0);
00265                 VERIFY(nvlist_add_uint64(fuids[i], FUID_OFFSET, 0) == 0);
00266                 VERIFY(nvlist_add_string(fuids[i], FUID_DOMAIN,
00267                     domnode->f_ksid->kd_name) == 0);
00268         }
00269         VERIFY(nvlist_add_nvlist_array(nvp, FUID_NVP_ARRAY,
00270             fuids, numnodes) == 0);
00271         for (i = 0; i != numnodes; i++)
00272                 nvlist_free(fuids[i]);
00273         kmem_free(fuids, numnodes * sizeof (void *));
00274         VERIFY(nvlist_size(nvp, &nvsize, NV_ENCODE_XDR) == 0);
00275         packed = kmem_alloc(nvsize, KM_SLEEP);
00276         VERIFY(nvlist_pack(nvp, &packed, &nvsize,
00277             NV_ENCODE_XDR, KM_SLEEP) == 0);
00278         nvlist_free(nvp);
00279         zfsvfs->z_fuid_size = nvsize;
00280         dmu_write(zfsvfs->z_os, zfsvfs->z_fuid_obj, 0,
00281             zfsvfs->z_fuid_size, packed, tx);
00282         kmem_free(packed, zfsvfs->z_fuid_size);
00283         VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, zfsvfs->z_fuid_obj,
00284             FTAG, &db));
00285         dmu_buf_will_dirty(db, tx);
00286         *(uint64_t *)db->db_data = zfsvfs->z_fuid_size;
00287         dmu_buf_rele(db, FTAG);
00288 
00289         zfsvfs->z_fuid_dirty = B_FALSE;
00290         rw_exit(&zfsvfs->z_fuid_lock);
00291 }
00292 
00301 int
00302 zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain,
00303     char **retdomain, boolean_t addok)
00304 {
00305         fuid_domain_t searchnode, *findnode;
00306         avl_index_t loc;
00307         krw_t rw = RW_READER;
00308 
00309         /*
00310          * If the dummy "nobody" domain then return an index of 0
00311          * to cause the created FUID to be a standard POSIX id
00312          * for the user nobody.
00313          */
00314         if (domain[0] == '\0') {
00315                 if (retdomain)
00316                         *retdomain = nulldomain;
00317                 return (0);
00318         }
00319 
00320         searchnode.f_ksid = ksid_lookupdomain(domain);
00321         if (retdomain)
00322                 *retdomain = searchnode.f_ksid->kd_name;
00323         if (!zfsvfs->z_fuid_loaded)
00324                 zfs_fuid_init(zfsvfs);
00325 
00326 retry:
00327         rw_enter(&zfsvfs->z_fuid_lock, rw);
00328         findnode = avl_find(&zfsvfs->z_fuid_domain, &searchnode, &loc);
00329 
00330         if (findnode) {
00331                 rw_exit(&zfsvfs->z_fuid_lock);
00332                 ksiddomain_rele(searchnode.f_ksid);
00333                 return (findnode->f_idx);
00334         } else if (addok) {
00335                 fuid_domain_t *domnode;
00336                 uint64_t retidx;
00337 
00338                 if (rw == RW_READER && !rw_tryupgrade(&zfsvfs->z_fuid_lock)) {
00339                         rw_exit(&zfsvfs->z_fuid_lock);
00340                         rw = RW_WRITER;
00341                         goto retry;
00342                 }
00343 
00344                 domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
00345                 domnode->f_ksid = searchnode.f_ksid;
00346 
00347                 retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
00348 
00349                 avl_add(&zfsvfs->z_fuid_domain, domnode);
00350                 avl_add(&zfsvfs->z_fuid_idx, domnode);
00351                 zfsvfs->z_fuid_dirty = B_TRUE;
00352                 rw_exit(&zfsvfs->z_fuid_lock);
00353                 return (retidx);
00354         } else {
00355                 rw_exit(&zfsvfs->z_fuid_lock);
00356                 return (-1);
00357         }
00358 }
00359 
00366 const char *
00367 zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
00368 {
00369         char *domain;
00370 
00371         if (idx == 0 || !zfsvfs->z_use_fuids)
00372                 return (NULL);
00373 
00374         if (!zfsvfs->z_fuid_loaded)
00375                 zfs_fuid_init(zfsvfs);
00376 
00377         rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
00378 
00379         if (zfsvfs->z_fuid_obj || zfsvfs->z_fuid_dirty)
00380                 domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx);
00381         else
00382                 domain = nulldomain;
00383         rw_exit(&zfsvfs->z_fuid_lock);
00384 
00385         ASSERT(domain);
00386         return (domain);
00387 }
00388 
00389 void
00390 zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
00391 {
00392         *uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
00393         *gidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_gid, cr, ZFS_GROUP);
00394 }
00395 
00396 uid_t
00397 zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
00398     cred_t *cr, zfs_fuid_type_t type)
00399 {
00400         uint32_t index = FUID_INDEX(fuid);
00401         const char *domain;
00402         uid_t id;
00403 
00404         if (index == 0)
00405                 return (fuid);
00406 
00407         domain = zfs_fuid_find_by_idx(zfsvfs, index);
00408         ASSERT(domain != NULL);
00409 
00410 #ifdef sun
00411         if (type == ZFS_OWNER || type == ZFS_ACE_USER) {
00412                 (void) kidmap_getuidbysid(crgetzone(cr), domain,
00413                     FUID_RID(fuid), &id);
00414         } else {
00415                 (void) kidmap_getgidbysid(crgetzone(cr), domain,
00416                     FUID_RID(fuid), &id);
00417         }
00418 #else   /* !sun */
00419         id = UID_NOBODY;
00420 #endif  /* !sun */
00421         return (id);
00422 }
00423 
00431 void
00432 zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid,
00433     uint64_t idx, uint64_t id, zfs_fuid_type_t type)
00434 {
00435         zfs_fuid_t *fuid;
00436         zfs_fuid_domain_t *fuid_domain;
00437         zfs_fuid_info_t *fuidp;
00438         uint64_t fuididx;
00439         boolean_t found = B_FALSE;
00440 
00441         if (*fuidpp == NULL)
00442                 *fuidpp = zfs_fuid_info_alloc();
00443 
00444         fuidp = *fuidpp;
00445         /*
00446          * First find fuid domain index in linked list
00447          *
00448          * If one isn't found then create an entry.
00449          */
00450 
00451         for (fuididx = 1, fuid_domain = list_head(&fuidp->z_domains);
00452             fuid_domain; fuid_domain = list_next(&fuidp->z_domains,
00453             fuid_domain), fuididx++) {
00454                 if (idx == fuid_domain->z_domidx) {
00455                         found = B_TRUE;
00456                         break;
00457                 }
00458         }
00459 
00460         if (!found) {
00461                 fuid_domain = kmem_alloc(sizeof (zfs_fuid_domain_t), KM_SLEEP);
00462                 fuid_domain->z_domain = domain;
00463                 fuid_domain->z_domidx = idx;
00464                 list_insert_tail(&fuidp->z_domains, fuid_domain);
00465                 fuidp->z_domain_str_sz += strlen(domain) + 1;
00466                 fuidp->z_domain_cnt++;
00467         }
00468 
00469         if (type == ZFS_ACE_USER || type == ZFS_ACE_GROUP) {
00470 
00471                 /*
00472                  * Now allocate fuid entry and add it on the end of the list
00473                  */
00474 
00475                 fuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP);
00476                 fuid->z_id = id;
00477                 fuid->z_domidx = idx;
00478                 fuid->z_logfuid = FUID_ENCODE(fuididx, rid);
00479 
00480                 list_insert_tail(&fuidp->z_fuids, fuid);
00481                 fuidp->z_fuid_cnt++;
00482         } else {
00483                 if (type == ZFS_OWNER)
00484                         fuidp->z_fuid_owner = FUID_ENCODE(fuididx, rid);
00485                 else
00486                         fuidp->z_fuid_group = FUID_ENCODE(fuididx, rid);
00487         }
00488 }
00489 
00498 uint64_t
00499 zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
00500     cred_t *cr, zfs_fuid_info_t **fuidp)
00501 {
00502         uint64_t        idx;
00503         ksid_t          *ksid;
00504         uint32_t        rid;
00505         char            *kdomain;
00506         const char      *domain;
00507         uid_t           id;
00508 
00509         VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);
00510 
00511         ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);
00512 
00513         if (!zfsvfs->z_use_fuids || (ksid == NULL)) {
00514                 id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr);
00515 
00516                 if (IS_EPHEMERAL(id))
00517                         return ((type == ZFS_OWNER) ? UID_NOBODY : GID_NOBODY);
00518 
00519                 return ((uint64_t)id);
00520         }
00521 
00522         /*
00523          * ksid is present and FUID is supported
00524          */
00525         id = (type == ZFS_OWNER) ? ksid_getid(ksid) : crgetgid(cr);
00526 
00527         if (!IS_EPHEMERAL(id))
00528                 return ((uint64_t)id);
00529 
00530         if (type == ZFS_GROUP)
00531                 id = ksid_getid(ksid);
00532 
00533         rid = ksid_getrid(ksid);
00534         domain = ksid_getdomain(ksid);
00535 
00536         idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);
00537 
00538         zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);
00539 
00540         return (FUID_ENCODE(idx, rid));
00541 }
00542 
00555 uint64_t
00556 zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
00557     zfs_fuid_type_t type, zfs_fuid_info_t **fuidpp)
00558 {
00559         const char *domain;
00560         char *kdomain;
00561         uint32_t fuid_idx = FUID_INDEX(id);
00562         uint32_t rid;
00563         idmap_stat status;
00564         uint64_t idx;
00565         zfs_fuid_t *zfuid = NULL;
00566         zfs_fuid_info_t *fuidp;
00567 
00568         /*
00569          * If POSIX ID, or entry is already a FUID then
00570          * just return the id
00571          *
00572          * We may also be handed an already FUID'ized id via
00573          * chmod.
00574          */
00575 
00576         if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
00577                 return (id);
00578 
00579         if (zfsvfs->z_replay) {
00580                 fuidp = zfsvfs->z_fuid_replay;
00581 
00582                 /*
00583                  * If we are passed an ephemeral id, but no
00584                  * fuid_info was logged then return NOBODY.
00585                  * This is most likely a result of idmap service
00586                  * not being available.
00587                  */
00588                 if (fuidp == NULL)
00589                         return (UID_NOBODY);
00590 
00591                 switch (type) {
00592                 case ZFS_ACE_USER:
00593                 case ZFS_ACE_GROUP:
00594                         zfuid = list_head(&fuidp->z_fuids);
00595                         rid = FUID_RID(zfuid->z_logfuid);
00596                         idx = FUID_INDEX(zfuid->z_logfuid);
00597                         break;
00598                 case ZFS_OWNER:
00599                         rid = FUID_RID(fuidp->z_fuid_owner);
00600                         idx = FUID_INDEX(fuidp->z_fuid_owner);
00601                         break;
00602                 case ZFS_GROUP:
00603                         rid = FUID_RID(fuidp->z_fuid_group);
00604                         idx = FUID_INDEX(fuidp->z_fuid_group);
00605                         break;
00606                 };
00607                 domain = fuidp->z_domain_table[idx -1];
00608         } else {
00609                 if (type == ZFS_OWNER || type == ZFS_ACE_USER)
00610                         status = kidmap_getsidbyuid(crgetzone(cr), id,
00611                             &domain, &rid);
00612                 else
00613                         status = kidmap_getsidbygid(crgetzone(cr), id,
00614                             &domain, &rid);
00615 
00616                 if (status != 0) {
00617                         /*
00618                          * When returning nobody we will need to
00619                          * make a dummy fuid table entry for logging
00620                          * purposes.
00621                          */
00622                         rid = UID_NOBODY;
00623                         domain = nulldomain;
00624                 }
00625         }
00626 
00627         idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);
00628 
00629         if (!zfsvfs->z_replay)
00630                 zfs_fuid_node_add(fuidpp, kdomain,
00631                     rid, idx, id, type);
00632         else if (zfuid != NULL) {
00633                 list_remove(&fuidp->z_fuids, zfuid);
00634                 kmem_free(zfuid, sizeof (zfs_fuid_t));
00635         }
00636         return (FUID_ENCODE(idx, rid));
00637 }
00638 
00639 void
00640 zfs_fuid_destroy(zfsvfs_t *zfsvfs)
00641 {
00642         rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
00643         if (!zfsvfs->z_fuid_loaded) {
00644                 rw_exit(&zfsvfs->z_fuid_lock);
00645                 return;
00646         }
00647         zfs_fuid_table_destroy(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
00648         rw_exit(&zfsvfs->z_fuid_lock);
00649 }
00650 
00655 zfs_fuid_info_t *
00656 zfs_fuid_info_alloc(void)
00657 {
00658         zfs_fuid_info_t *fuidp;
00659 
00660         fuidp = kmem_zalloc(sizeof (zfs_fuid_info_t), KM_SLEEP);
00661         list_create(&fuidp->z_domains, sizeof (zfs_fuid_domain_t),
00662             offsetof(zfs_fuid_domain_t, z_next));
00663         list_create(&fuidp->z_fuids, sizeof (zfs_fuid_t),
00664             offsetof(zfs_fuid_t, z_next));
00665         return (fuidp);
00666 }
00667 
00671 void
00672 zfs_fuid_info_free(zfs_fuid_info_t *fuidp)
00673 {
00674         zfs_fuid_t *zfuid;
00675         zfs_fuid_domain_t *zdomain;
00676 
00677         while ((zfuid = list_head(&fuidp->z_fuids)) != NULL) {
00678                 list_remove(&fuidp->z_fuids, zfuid);
00679                 kmem_free(zfuid, sizeof (zfs_fuid_t));
00680         }
00681 
00682         if (fuidp->z_domain_table != NULL)
00683                 kmem_free(fuidp->z_domain_table,
00684                     (sizeof (char **)) * fuidp->z_domain_cnt);
00685 
00686         while ((zdomain = list_head(&fuidp->z_domains)) != NULL) {
00687                 list_remove(&fuidp->z_domains, zdomain);
00688                 kmem_free(zdomain, sizeof (zfs_fuid_domain_t));
00689         }
00690 
00691         kmem_free(fuidp, sizeof (zfs_fuid_info_t));
00692 }
00693 
00701 boolean_t
00702 zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr)
00703 {
00704 #ifdef sun
00705         ksid_t          *ksid = crgetsid(cr, KSID_GROUP);
00706         ksidlist_t      *ksidlist = crgetsidlist(cr);
00707 #endif  /* !sun */
00708         uid_t           gid;
00709 
00710 #ifdef sun
00711         if (ksid && ksidlist) {
00712                 int             i;
00713                 ksid_t          *ksid_groups;
00714                 uint32_t        idx = FUID_INDEX(id);
00715                 uint32_t        rid = FUID_RID(id);
00716 
00717                 ksid_groups = ksidlist->ksl_sids;
00718 
00719                 for (i = 0; i != ksidlist->ksl_nsid; i++) {
00720                         if (idx == 0) {
00721                                 if (id != IDMAP_WK_CREATOR_GROUP_GID &&
00722                                     id == ksid_groups[i].ks_id) {
00723                                         return (B_TRUE);
00724                                 }
00725                         } else {
00726                                 const char *domain;
00727 
00728                                 domain = zfs_fuid_find_by_idx(zfsvfs, idx);
00729                                 ASSERT(domain != NULL);
00730 
00731                                 if (strcmp(domain,
00732                                     IDMAP_WK_CREATOR_SID_AUTHORITY) == 0)
00733                                         return (B_FALSE);
00734 
00735                                 if ((strcmp(domain,
00736                                     ksid_groups[i].ks_domain->kd_name) == 0) &&
00737                                     rid == ksid_groups[i].ks_rid)
00738                                         return (B_TRUE);
00739                         }
00740                 }
00741         }
00742 #endif  /* !sun */
00743 
00744         /*
00745          * Not found in ksidlist, check posix groups
00746          */
00747         gid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP);
00748         return (groupmember(gid, cr));
00749 }
00750 
00751 void
00752 zfs_fuid_txhold(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
00753 {
00754         if (zfsvfs->z_fuid_obj == 0) {
00755                 dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
00756                 dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
00757                     FUID_SIZE_ESTIMATE(zfsvfs));
00758                 dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL);
00759         } else {
00760                 dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj);
00761                 dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0,
00762                     FUID_SIZE_ESTIMATE(zfsvfs));
00763         }
00764 }
00765 #endif
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines