FreeBSD ZFS
The Zettabyte File System
|
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