1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23eda14cbcSMatt Macy */ 24eda14cbcSMatt Macy 25eda14cbcSMatt Macy #include <sys/zfs_context.h> 26eda14cbcSMatt Macy #include <sys/dmu.h> 27eda14cbcSMatt Macy #include <sys/avl.h> 28eda14cbcSMatt Macy #include <sys/zap.h> 29eda14cbcSMatt Macy #include <sys/nvpair.h> 30eda14cbcSMatt Macy #ifdef _KERNEL 31eda14cbcSMatt Macy #include <sys/sid.h> 32eda14cbcSMatt Macy #include <sys/zfs_vfsops.h> 33eda14cbcSMatt Macy #include <sys/zfs_znode.h> 34eda14cbcSMatt Macy #endif 35eda14cbcSMatt Macy #include <sys/zfs_fuid.h> 36eda14cbcSMatt Macy 37eda14cbcSMatt Macy /* 38eda14cbcSMatt Macy * FUID Domain table(s). 39eda14cbcSMatt Macy * 40eda14cbcSMatt Macy * The FUID table is stored as a packed nvlist of an array 41eda14cbcSMatt Macy * of nvlists which contain an index, domain string and offset 42eda14cbcSMatt Macy * 43eda14cbcSMatt Macy * During file system initialization the nvlist(s) are read and 44eda14cbcSMatt Macy * two AVL trees are created. One tree is keyed by the index number 45eda14cbcSMatt Macy * and the other by the domain string. Nodes are never removed from 46eda14cbcSMatt Macy * trees, but new entries may be added. If a new entry is added then 47eda14cbcSMatt Macy * the zfsvfs->z_fuid_dirty flag is set to true and the caller will then 48eda14cbcSMatt Macy * be responsible for calling zfs_fuid_sync() to sync the changes to disk. 49eda14cbcSMatt Macy * 50eda14cbcSMatt Macy */ 51eda14cbcSMatt Macy 52eda14cbcSMatt Macy #define FUID_IDX "fuid_idx" 53eda14cbcSMatt Macy #define FUID_DOMAIN "fuid_domain" 54eda14cbcSMatt Macy #define FUID_OFFSET "fuid_offset" 55eda14cbcSMatt Macy #define FUID_NVP_ARRAY "fuid_nvlist" 56eda14cbcSMatt Macy 57eda14cbcSMatt Macy typedef struct fuid_domain { 58eda14cbcSMatt Macy avl_node_t f_domnode; 59eda14cbcSMatt Macy avl_node_t f_idxnode; 60eda14cbcSMatt Macy ksiddomain_t *f_ksid; 61eda14cbcSMatt Macy uint64_t f_idx; 62eda14cbcSMatt Macy } fuid_domain_t; 63eda14cbcSMatt Macy 64a0b956f5SMartin Matuska static const char *const nulldomain = ""; 65eda14cbcSMatt Macy 66eda14cbcSMatt Macy /* 67eda14cbcSMatt Macy * Compare two indexes. 68eda14cbcSMatt Macy */ 69eda14cbcSMatt Macy static int 70eda14cbcSMatt Macy idx_compare(const void *arg1, const void *arg2) 71eda14cbcSMatt Macy { 72eda14cbcSMatt Macy const fuid_domain_t *node1 = (const fuid_domain_t *)arg1; 73eda14cbcSMatt Macy const fuid_domain_t *node2 = (const fuid_domain_t *)arg2; 74eda14cbcSMatt Macy 75eda14cbcSMatt Macy return (TREE_CMP(node1->f_idx, node2->f_idx)); 76eda14cbcSMatt Macy } 77eda14cbcSMatt Macy 78eda14cbcSMatt Macy /* 79eda14cbcSMatt Macy * Compare two domain strings. 80eda14cbcSMatt Macy */ 81eda14cbcSMatt Macy static int 82eda14cbcSMatt Macy domain_compare(const void *arg1, const void *arg2) 83eda14cbcSMatt Macy { 84eda14cbcSMatt Macy const fuid_domain_t *node1 = (const fuid_domain_t *)arg1; 85eda14cbcSMatt Macy const fuid_domain_t *node2 = (const fuid_domain_t *)arg2; 86eda14cbcSMatt Macy int val; 87eda14cbcSMatt Macy 88eda14cbcSMatt Macy val = strcmp(node1->f_ksid->kd_name, node2->f_ksid->kd_name); 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy return (TREE_ISIGN(val)); 91eda14cbcSMatt Macy } 92eda14cbcSMatt Macy 93eda14cbcSMatt Macy void 94eda14cbcSMatt Macy zfs_fuid_avl_tree_create(avl_tree_t *idx_tree, avl_tree_t *domain_tree) 95eda14cbcSMatt Macy { 96eda14cbcSMatt Macy avl_create(idx_tree, idx_compare, 97eda14cbcSMatt Macy sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_idxnode)); 98eda14cbcSMatt Macy avl_create(domain_tree, domain_compare, 99eda14cbcSMatt Macy sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_domnode)); 100eda14cbcSMatt Macy } 101eda14cbcSMatt Macy 102eda14cbcSMatt Macy /* 103eda14cbcSMatt Macy * load initial fuid domain and idx trees. This function is used by 104eda14cbcSMatt Macy * both the kernel and zdb. 105eda14cbcSMatt Macy */ 106eda14cbcSMatt Macy uint64_t 107eda14cbcSMatt Macy zfs_fuid_table_load(objset_t *os, uint64_t fuid_obj, avl_tree_t *idx_tree, 108eda14cbcSMatt Macy avl_tree_t *domain_tree) 109eda14cbcSMatt Macy { 110eda14cbcSMatt Macy dmu_buf_t *db; 111eda14cbcSMatt Macy uint64_t fuid_size; 112eda14cbcSMatt Macy 113eda14cbcSMatt Macy ASSERT(fuid_obj != 0); 114eda14cbcSMatt Macy VERIFY(0 == dmu_bonus_hold(os, fuid_obj, 115eda14cbcSMatt Macy FTAG, &db)); 116eda14cbcSMatt Macy fuid_size = *(uint64_t *)db->db_data; 117eda14cbcSMatt Macy dmu_buf_rele(db, FTAG); 118eda14cbcSMatt Macy 119eda14cbcSMatt Macy if (fuid_size) { 120eda14cbcSMatt Macy nvlist_t **fuidnvp; 121eda14cbcSMatt Macy nvlist_t *nvp = NULL; 122eda14cbcSMatt Macy uint_t count; 123eda14cbcSMatt Macy char *packed; 124eda14cbcSMatt Macy int i; 125eda14cbcSMatt Macy 126eda14cbcSMatt Macy packed = kmem_alloc(fuid_size, KM_SLEEP); 127eda14cbcSMatt Macy VERIFY(dmu_read(os, fuid_obj, 0, 128eda14cbcSMatt Macy fuid_size, packed, DMU_READ_PREFETCH) == 0); 129eda14cbcSMatt Macy VERIFY(nvlist_unpack(packed, fuid_size, 130eda14cbcSMatt Macy &nvp, 0) == 0); 131eda14cbcSMatt Macy VERIFY(nvlist_lookup_nvlist_array(nvp, FUID_NVP_ARRAY, 132eda14cbcSMatt Macy &fuidnvp, &count) == 0); 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy for (i = 0; i != count; i++) { 135eda14cbcSMatt Macy fuid_domain_t *domnode; 136eda14cbcSMatt Macy char *domain; 137eda14cbcSMatt Macy uint64_t idx; 138eda14cbcSMatt Macy 139eda14cbcSMatt Macy VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN, 140eda14cbcSMatt Macy &domain) == 0); 141eda14cbcSMatt Macy VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_IDX, 142eda14cbcSMatt Macy &idx) == 0); 143eda14cbcSMatt Macy 144eda14cbcSMatt Macy domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP); 145eda14cbcSMatt Macy 146eda14cbcSMatt Macy domnode->f_idx = idx; 147eda14cbcSMatt Macy domnode->f_ksid = ksid_lookupdomain(domain); 148eda14cbcSMatt Macy avl_add(idx_tree, domnode); 149eda14cbcSMatt Macy avl_add(domain_tree, domnode); 150eda14cbcSMatt Macy } 151eda14cbcSMatt Macy nvlist_free(nvp); 152eda14cbcSMatt Macy kmem_free(packed, fuid_size); 153eda14cbcSMatt Macy } 154eda14cbcSMatt Macy return (fuid_size); 155eda14cbcSMatt Macy } 156eda14cbcSMatt Macy 157eda14cbcSMatt Macy void 158eda14cbcSMatt Macy zfs_fuid_table_destroy(avl_tree_t *idx_tree, avl_tree_t *domain_tree) 159eda14cbcSMatt Macy { 160eda14cbcSMatt Macy fuid_domain_t *domnode; 161eda14cbcSMatt Macy void *cookie; 162eda14cbcSMatt Macy 163eda14cbcSMatt Macy cookie = NULL; 164eda14cbcSMatt Macy while ((domnode = avl_destroy_nodes(domain_tree, &cookie))) 165eda14cbcSMatt Macy ksiddomain_rele(domnode->f_ksid); 166eda14cbcSMatt Macy 167eda14cbcSMatt Macy avl_destroy(domain_tree); 168eda14cbcSMatt Macy cookie = NULL; 169eda14cbcSMatt Macy while ((domnode = avl_destroy_nodes(idx_tree, &cookie))) 170eda14cbcSMatt Macy kmem_free(domnode, sizeof (fuid_domain_t)); 171eda14cbcSMatt Macy avl_destroy(idx_tree); 172eda14cbcSMatt Macy } 173eda14cbcSMatt Macy 174a0b956f5SMartin Matuska const char * 175eda14cbcSMatt Macy zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx) 176eda14cbcSMatt Macy { 177eda14cbcSMatt Macy fuid_domain_t searchnode, *findnode; 178eda14cbcSMatt Macy avl_index_t loc; 179eda14cbcSMatt Macy 180eda14cbcSMatt Macy searchnode.f_idx = idx; 181eda14cbcSMatt Macy 182eda14cbcSMatt Macy findnode = avl_find(idx_tree, &searchnode, &loc); 183eda14cbcSMatt Macy 184eda14cbcSMatt Macy return (findnode ? findnode->f_ksid->kd_name : nulldomain); 185eda14cbcSMatt Macy } 186eda14cbcSMatt Macy 187eda14cbcSMatt Macy #ifdef _KERNEL 188eda14cbcSMatt Macy /* 189eda14cbcSMatt Macy * Load the fuid table(s) into memory. 190eda14cbcSMatt Macy */ 191eda14cbcSMatt Macy static void 192eda14cbcSMatt Macy zfs_fuid_init(zfsvfs_t *zfsvfs) 193eda14cbcSMatt Macy { 194eda14cbcSMatt Macy rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER); 195eda14cbcSMatt Macy 196eda14cbcSMatt Macy if (zfsvfs->z_fuid_loaded) { 197eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 198eda14cbcSMatt Macy return; 199eda14cbcSMatt Macy } 200eda14cbcSMatt Macy 201eda14cbcSMatt Macy zfs_fuid_avl_tree_create(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain); 202eda14cbcSMatt Macy 203eda14cbcSMatt Macy (void) zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ, 204eda14cbcSMatt Macy ZFS_FUID_TABLES, 8, 1, &zfsvfs->z_fuid_obj); 205eda14cbcSMatt Macy if (zfsvfs->z_fuid_obj != 0) { 206eda14cbcSMatt Macy zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os, 207eda14cbcSMatt Macy zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx, 208eda14cbcSMatt Macy &zfsvfs->z_fuid_domain); 209eda14cbcSMatt Macy } 210eda14cbcSMatt Macy 211eda14cbcSMatt Macy zfsvfs->z_fuid_loaded = B_TRUE; 212eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 213eda14cbcSMatt Macy } 214eda14cbcSMatt Macy 215eda14cbcSMatt Macy /* 216eda14cbcSMatt Macy * sync out AVL trees to persistent storage. 217eda14cbcSMatt Macy */ 218eda14cbcSMatt Macy void 219eda14cbcSMatt Macy zfs_fuid_sync(zfsvfs_t *zfsvfs, dmu_tx_t *tx) 220eda14cbcSMatt Macy { 221eda14cbcSMatt Macy nvlist_t *nvp; 222eda14cbcSMatt Macy nvlist_t **fuids; 223eda14cbcSMatt Macy size_t nvsize = 0; 224eda14cbcSMatt Macy char *packed; 225eda14cbcSMatt Macy dmu_buf_t *db; 226eda14cbcSMatt Macy fuid_domain_t *domnode; 227eda14cbcSMatt Macy int numnodes; 228eda14cbcSMatt Macy int i; 229eda14cbcSMatt Macy 230eda14cbcSMatt Macy if (!zfsvfs->z_fuid_dirty) { 231eda14cbcSMatt Macy return; 232eda14cbcSMatt Macy } 233eda14cbcSMatt Macy 234eda14cbcSMatt Macy rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER); 235eda14cbcSMatt Macy 236eda14cbcSMatt Macy /* 237eda14cbcSMatt Macy * First see if table needs to be created? 238eda14cbcSMatt Macy */ 239eda14cbcSMatt Macy if (zfsvfs->z_fuid_obj == 0) { 240eda14cbcSMatt Macy zfsvfs->z_fuid_obj = dmu_object_alloc(zfsvfs->z_os, 241eda14cbcSMatt Macy DMU_OT_FUID, 1 << 14, DMU_OT_FUID_SIZE, 242eda14cbcSMatt Macy sizeof (uint64_t), tx); 243eda14cbcSMatt Macy VERIFY(zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, 244eda14cbcSMatt Macy ZFS_FUID_TABLES, sizeof (uint64_t), 1, 245eda14cbcSMatt Macy &zfsvfs->z_fuid_obj, tx) == 0); 246eda14cbcSMatt Macy } 247eda14cbcSMatt Macy 248eda14cbcSMatt Macy VERIFY(nvlist_alloc(&nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 249eda14cbcSMatt Macy 250eda14cbcSMatt Macy numnodes = avl_numnodes(&zfsvfs->z_fuid_idx); 251eda14cbcSMatt Macy fuids = kmem_alloc(numnodes * sizeof (void *), KM_SLEEP); 252eda14cbcSMatt Macy for (i = 0, domnode = avl_first(&zfsvfs->z_fuid_domain); domnode; i++, 253eda14cbcSMatt Macy domnode = AVL_NEXT(&zfsvfs->z_fuid_domain, domnode)) { 254eda14cbcSMatt Macy VERIFY(nvlist_alloc(&fuids[i], NV_UNIQUE_NAME, KM_SLEEP) == 0); 255eda14cbcSMatt Macy VERIFY(nvlist_add_uint64(fuids[i], FUID_IDX, 256eda14cbcSMatt Macy domnode->f_idx) == 0); 257eda14cbcSMatt Macy VERIFY(nvlist_add_uint64(fuids[i], FUID_OFFSET, 0) == 0); 258eda14cbcSMatt Macy VERIFY(nvlist_add_string(fuids[i], FUID_DOMAIN, 259eda14cbcSMatt Macy domnode->f_ksid->kd_name) == 0); 260eda14cbcSMatt Macy } 261681ce946SMartin Matuska fnvlist_add_nvlist_array(nvp, FUID_NVP_ARRAY, 262681ce946SMartin Matuska (const nvlist_t * const *)fuids, numnodes); 263eda14cbcSMatt Macy for (i = 0; i != numnodes; i++) 264eda14cbcSMatt Macy nvlist_free(fuids[i]); 265eda14cbcSMatt Macy kmem_free(fuids, numnodes * sizeof (void *)); 266eda14cbcSMatt Macy VERIFY(nvlist_size(nvp, &nvsize, NV_ENCODE_XDR) == 0); 267eda14cbcSMatt Macy packed = kmem_alloc(nvsize, KM_SLEEP); 268eda14cbcSMatt Macy VERIFY(nvlist_pack(nvp, &packed, &nvsize, 269eda14cbcSMatt Macy NV_ENCODE_XDR, KM_SLEEP) == 0); 270eda14cbcSMatt Macy nvlist_free(nvp); 271eda14cbcSMatt Macy zfsvfs->z_fuid_size = nvsize; 272eda14cbcSMatt Macy dmu_write(zfsvfs->z_os, zfsvfs->z_fuid_obj, 0, 273eda14cbcSMatt Macy zfsvfs->z_fuid_size, packed, tx); 274eda14cbcSMatt Macy kmem_free(packed, zfsvfs->z_fuid_size); 275eda14cbcSMatt Macy VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, zfsvfs->z_fuid_obj, 276eda14cbcSMatt Macy FTAG, &db)); 277eda14cbcSMatt Macy dmu_buf_will_dirty(db, tx); 278eda14cbcSMatt Macy *(uint64_t *)db->db_data = zfsvfs->z_fuid_size; 279eda14cbcSMatt Macy dmu_buf_rele(db, FTAG); 280eda14cbcSMatt Macy 281eda14cbcSMatt Macy zfsvfs->z_fuid_dirty = B_FALSE; 282eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 283eda14cbcSMatt Macy } 284eda14cbcSMatt Macy 285eda14cbcSMatt Macy /* 286eda14cbcSMatt Macy * Query domain table for a given domain. 287eda14cbcSMatt Macy * 288eda14cbcSMatt Macy * If domain isn't found and addok is set, it is added to AVL trees and 289eda14cbcSMatt Macy * the zfsvfs->z_fuid_dirty flag will be set to TRUE. It will then be 290eda14cbcSMatt Macy * necessary for the caller or another thread to detect the dirty table 291eda14cbcSMatt Macy * and sync out the changes. 292eda14cbcSMatt Macy */ 293a0b956f5SMartin Matuska static int 294eda14cbcSMatt Macy zfs_fuid_find_by_domain(zfsvfs_t *zfsvfs, const char *domain, 295a0b956f5SMartin Matuska const char **retdomain, boolean_t addok) 296eda14cbcSMatt Macy { 297eda14cbcSMatt Macy fuid_domain_t searchnode, *findnode; 298eda14cbcSMatt Macy avl_index_t loc; 299eda14cbcSMatt Macy krw_t rw = RW_READER; 300eda14cbcSMatt Macy 301eda14cbcSMatt Macy /* 302eda14cbcSMatt Macy * If the dummy "nobody" domain then return an index of 0 303eda14cbcSMatt Macy * to cause the created FUID to be a standard POSIX id 304eda14cbcSMatt Macy * for the user nobody. 305eda14cbcSMatt Macy */ 306eda14cbcSMatt Macy if (domain[0] == '\0') { 307eda14cbcSMatt Macy if (retdomain) 308eda14cbcSMatt Macy *retdomain = nulldomain; 309eda14cbcSMatt Macy return (0); 310eda14cbcSMatt Macy } 311eda14cbcSMatt Macy 312eda14cbcSMatt Macy searchnode.f_ksid = ksid_lookupdomain(domain); 313eda14cbcSMatt Macy if (retdomain) 314eda14cbcSMatt Macy *retdomain = searchnode.f_ksid->kd_name; 315eda14cbcSMatt Macy if (!zfsvfs->z_fuid_loaded) 316eda14cbcSMatt Macy zfs_fuid_init(zfsvfs); 317eda14cbcSMatt Macy 318eda14cbcSMatt Macy retry: 319eda14cbcSMatt Macy rw_enter(&zfsvfs->z_fuid_lock, rw); 320eda14cbcSMatt Macy findnode = avl_find(&zfsvfs->z_fuid_domain, &searchnode, &loc); 321eda14cbcSMatt Macy 322eda14cbcSMatt Macy if (findnode) { 323eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 324eda14cbcSMatt Macy ksiddomain_rele(searchnode.f_ksid); 325eda14cbcSMatt Macy return (findnode->f_idx); 326eda14cbcSMatt Macy } else if (addok) { 327eda14cbcSMatt Macy fuid_domain_t *domnode; 328eda14cbcSMatt Macy uint64_t retidx; 329eda14cbcSMatt Macy 330eda14cbcSMatt Macy if (rw == RW_READER && !rw_tryupgrade(&zfsvfs->z_fuid_lock)) { 331eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 332eda14cbcSMatt Macy rw = RW_WRITER; 333eda14cbcSMatt Macy goto retry; 334eda14cbcSMatt Macy } 335eda14cbcSMatt Macy 336eda14cbcSMatt Macy domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP); 337eda14cbcSMatt Macy domnode->f_ksid = searchnode.f_ksid; 338eda14cbcSMatt Macy 339eda14cbcSMatt Macy retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1; 340eda14cbcSMatt Macy 341eda14cbcSMatt Macy avl_add(&zfsvfs->z_fuid_domain, domnode); 342eda14cbcSMatt Macy avl_add(&zfsvfs->z_fuid_idx, domnode); 343eda14cbcSMatt Macy zfsvfs->z_fuid_dirty = B_TRUE; 344eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 345eda14cbcSMatt Macy return (retidx); 346eda14cbcSMatt Macy } else { 347eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 348eda14cbcSMatt Macy return (-1); 349eda14cbcSMatt Macy } 350eda14cbcSMatt Macy } 351eda14cbcSMatt Macy 352eda14cbcSMatt Macy /* 353eda14cbcSMatt Macy * Query domain table by index, returning domain string 354eda14cbcSMatt Macy * 355eda14cbcSMatt Macy * Returns a pointer from an avl node of the domain string. 356eda14cbcSMatt Macy * 357eda14cbcSMatt Macy */ 358eda14cbcSMatt Macy const char * 359eda14cbcSMatt Macy zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx) 360eda14cbcSMatt Macy { 361a0b956f5SMartin Matuska const char *domain; 362eda14cbcSMatt Macy 363eda14cbcSMatt Macy if (idx == 0 || !zfsvfs->z_use_fuids) 364eda14cbcSMatt Macy return (NULL); 365eda14cbcSMatt Macy 366eda14cbcSMatt Macy if (!zfsvfs->z_fuid_loaded) 367eda14cbcSMatt Macy zfs_fuid_init(zfsvfs); 368eda14cbcSMatt Macy 369eda14cbcSMatt Macy rw_enter(&zfsvfs->z_fuid_lock, RW_READER); 370eda14cbcSMatt Macy 371eda14cbcSMatt Macy if (zfsvfs->z_fuid_obj || zfsvfs->z_fuid_dirty) 372eda14cbcSMatt Macy domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx); 373eda14cbcSMatt Macy else 374eda14cbcSMatt Macy domain = nulldomain; 375eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 376eda14cbcSMatt Macy 377eda14cbcSMatt Macy ASSERT(domain); 378eda14cbcSMatt Macy return (domain); 379eda14cbcSMatt Macy } 380eda14cbcSMatt Macy 381eda14cbcSMatt Macy void 382eda14cbcSMatt Macy zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp) 383eda14cbcSMatt Macy { 384eda14cbcSMatt Macy *uidp = zfs_fuid_map_id(ZTOZSB(zp), KUID_TO_SUID(ZTOUID(zp)), 385eda14cbcSMatt Macy cr, ZFS_OWNER); 386eda14cbcSMatt Macy *gidp = zfs_fuid_map_id(ZTOZSB(zp), KGID_TO_SGID(ZTOGID(zp)), 387eda14cbcSMatt Macy cr, ZFS_GROUP); 388eda14cbcSMatt Macy } 389eda14cbcSMatt Macy 390eda14cbcSMatt Macy #ifdef __FreeBSD__ 391eda14cbcSMatt Macy uid_t 392eda14cbcSMatt Macy zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid, 393eda14cbcSMatt Macy cred_t *cr, zfs_fuid_type_t type) 394eda14cbcSMatt Macy { 395eda14cbcSMatt Macy uint32_t index = FUID_INDEX(fuid); 396eda14cbcSMatt Macy 397eda14cbcSMatt Macy if (index == 0) 398eda14cbcSMatt Macy return (fuid); 399eda14cbcSMatt Macy 400eda14cbcSMatt Macy return (UID_NOBODY); 401eda14cbcSMatt Macy } 402eda14cbcSMatt Macy #elif defined(__linux__) 403eda14cbcSMatt Macy uid_t 404eda14cbcSMatt Macy zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid, 405eda14cbcSMatt Macy cred_t *cr, zfs_fuid_type_t type) 406eda14cbcSMatt Macy { 407eda14cbcSMatt Macy /* 408eda14cbcSMatt Macy * The Linux port only supports POSIX IDs, use the passed id. 409eda14cbcSMatt Macy */ 410eda14cbcSMatt Macy return (fuid); 411eda14cbcSMatt Macy } 412eda14cbcSMatt Macy 413eda14cbcSMatt Macy #else 414eda14cbcSMatt Macy uid_t 415eda14cbcSMatt Macy zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid, 416eda14cbcSMatt Macy cred_t *cr, zfs_fuid_type_t type) 417eda14cbcSMatt Macy { 418eda14cbcSMatt Macy uint32_t index = FUID_INDEX(fuid); 419eda14cbcSMatt Macy const char *domain; 420eda14cbcSMatt Macy uid_t id; 421eda14cbcSMatt Macy 422eda14cbcSMatt Macy if (index == 0) 423eda14cbcSMatt Macy return (fuid); 424eda14cbcSMatt Macy 425eda14cbcSMatt Macy domain = zfs_fuid_find_by_idx(zfsvfs, index); 426eda14cbcSMatt Macy ASSERT(domain != NULL); 427eda14cbcSMatt Macy 428eda14cbcSMatt Macy if (type == ZFS_OWNER || type == ZFS_ACE_USER) { 429eda14cbcSMatt Macy (void) kidmap_getuidbysid(crgetzone(cr), domain, 430eda14cbcSMatt Macy FUID_RID(fuid), &id); 431eda14cbcSMatt Macy } else { 432eda14cbcSMatt Macy (void) kidmap_getgidbysid(crgetzone(cr), domain, 433eda14cbcSMatt Macy FUID_RID(fuid), &id); 434eda14cbcSMatt Macy } 435eda14cbcSMatt Macy return (id); 436eda14cbcSMatt Macy } 437eda14cbcSMatt Macy #endif 438eda14cbcSMatt Macy 439eda14cbcSMatt Macy /* 440eda14cbcSMatt Macy * Add a FUID node to the list of fuid's being created for this 441eda14cbcSMatt Macy * ACL 442eda14cbcSMatt Macy * 443eda14cbcSMatt Macy * If ACL has multiple domains, then keep only one copy of each unique 444eda14cbcSMatt Macy * domain. 445eda14cbcSMatt Macy */ 446eda14cbcSMatt Macy void 447eda14cbcSMatt Macy zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid, 448eda14cbcSMatt Macy uint64_t idx, uint64_t id, zfs_fuid_type_t type) 449eda14cbcSMatt Macy { 450eda14cbcSMatt Macy zfs_fuid_t *fuid; 451eda14cbcSMatt Macy zfs_fuid_domain_t *fuid_domain; 452eda14cbcSMatt Macy zfs_fuid_info_t *fuidp; 453eda14cbcSMatt Macy uint64_t fuididx; 454eda14cbcSMatt Macy boolean_t found = B_FALSE; 455eda14cbcSMatt Macy 456eda14cbcSMatt Macy if (*fuidpp == NULL) 457eda14cbcSMatt Macy *fuidpp = zfs_fuid_info_alloc(); 458eda14cbcSMatt Macy 459eda14cbcSMatt Macy fuidp = *fuidpp; 460eda14cbcSMatt Macy /* 461eda14cbcSMatt Macy * First find fuid domain index in linked list 462eda14cbcSMatt Macy * 463eda14cbcSMatt Macy * If one isn't found then create an entry. 464eda14cbcSMatt Macy */ 465eda14cbcSMatt Macy 466eda14cbcSMatt Macy for (fuididx = 1, fuid_domain = list_head(&fuidp->z_domains); 467eda14cbcSMatt Macy fuid_domain; fuid_domain = list_next(&fuidp->z_domains, 468eda14cbcSMatt Macy fuid_domain), fuididx++) { 469eda14cbcSMatt Macy if (idx == fuid_domain->z_domidx) { 470eda14cbcSMatt Macy found = B_TRUE; 471eda14cbcSMatt Macy break; 472eda14cbcSMatt Macy } 473eda14cbcSMatt Macy } 474eda14cbcSMatt Macy 475eda14cbcSMatt Macy if (!found) { 476eda14cbcSMatt Macy fuid_domain = kmem_alloc(sizeof (zfs_fuid_domain_t), KM_SLEEP); 477eda14cbcSMatt Macy fuid_domain->z_domain = domain; 478eda14cbcSMatt Macy fuid_domain->z_domidx = idx; 479eda14cbcSMatt Macy list_insert_tail(&fuidp->z_domains, fuid_domain); 480eda14cbcSMatt Macy fuidp->z_domain_str_sz += strlen(domain) + 1; 481eda14cbcSMatt Macy fuidp->z_domain_cnt++; 482eda14cbcSMatt Macy } 483eda14cbcSMatt Macy 484eda14cbcSMatt Macy if (type == ZFS_ACE_USER || type == ZFS_ACE_GROUP) { 485eda14cbcSMatt Macy 486eda14cbcSMatt Macy /* 487eda14cbcSMatt Macy * Now allocate fuid entry and add it on the end of the list 488eda14cbcSMatt Macy */ 489eda14cbcSMatt Macy 490eda14cbcSMatt Macy fuid = kmem_alloc(sizeof (zfs_fuid_t), KM_SLEEP); 491eda14cbcSMatt Macy fuid->z_id = id; 492eda14cbcSMatt Macy fuid->z_domidx = idx; 493eda14cbcSMatt Macy fuid->z_logfuid = FUID_ENCODE(fuididx, rid); 494eda14cbcSMatt Macy 495eda14cbcSMatt Macy list_insert_tail(&fuidp->z_fuids, fuid); 496eda14cbcSMatt Macy fuidp->z_fuid_cnt++; 497eda14cbcSMatt Macy } else { 498eda14cbcSMatt Macy if (type == ZFS_OWNER) 499eda14cbcSMatt Macy fuidp->z_fuid_owner = FUID_ENCODE(fuididx, rid); 500eda14cbcSMatt Macy else 501eda14cbcSMatt Macy fuidp->z_fuid_group = FUID_ENCODE(fuididx, rid); 502eda14cbcSMatt Macy } 503eda14cbcSMatt Macy } 504eda14cbcSMatt Macy 505eda14cbcSMatt Macy #ifdef HAVE_KSID 506eda14cbcSMatt Macy /* 507eda14cbcSMatt Macy * Create a file system FUID, based on information in the users cred 508eda14cbcSMatt Macy * 509eda14cbcSMatt Macy * If cred contains KSID_OWNER then it should be used to determine 510eda14cbcSMatt Macy * the uid otherwise cred's uid will be used. By default cred's gid 511eda14cbcSMatt Macy * is used unless it's an ephemeral ID in which case KSID_GROUP will 512eda14cbcSMatt Macy * be used if it exists. 513eda14cbcSMatt Macy */ 514eda14cbcSMatt Macy uint64_t 515eda14cbcSMatt Macy zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type, 516eda14cbcSMatt Macy cred_t *cr, zfs_fuid_info_t **fuidp) 517eda14cbcSMatt Macy { 518eda14cbcSMatt Macy uint64_t idx; 519eda14cbcSMatt Macy ksid_t *ksid; 520eda14cbcSMatt Macy uint32_t rid; 521a0b956f5SMartin Matuska const char *kdomain, *domain; 522eda14cbcSMatt Macy uid_t id; 523eda14cbcSMatt Macy 524eda14cbcSMatt Macy VERIFY(type == ZFS_OWNER || type == ZFS_GROUP); 525eda14cbcSMatt Macy 526eda14cbcSMatt Macy ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP); 527eda14cbcSMatt Macy 528eda14cbcSMatt Macy if (!zfsvfs->z_use_fuids || (ksid == NULL)) { 529eda14cbcSMatt Macy id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr); 530eda14cbcSMatt Macy 531eda14cbcSMatt Macy if (IS_EPHEMERAL(id)) 532eda14cbcSMatt Macy return ((type == ZFS_OWNER) ? UID_NOBODY : GID_NOBODY); 533eda14cbcSMatt Macy 534eda14cbcSMatt Macy return ((uint64_t)id); 535eda14cbcSMatt Macy } 536eda14cbcSMatt Macy 537eda14cbcSMatt Macy /* 538eda14cbcSMatt Macy * ksid is present and FUID is supported 539eda14cbcSMatt Macy */ 540eda14cbcSMatt Macy id = (type == ZFS_OWNER) ? ksid_getid(ksid) : crgetgid(cr); 541eda14cbcSMatt Macy 542eda14cbcSMatt Macy if (!IS_EPHEMERAL(id)) 543eda14cbcSMatt Macy return ((uint64_t)id); 544eda14cbcSMatt Macy 545eda14cbcSMatt Macy if (type == ZFS_GROUP) 546eda14cbcSMatt Macy id = ksid_getid(ksid); 547eda14cbcSMatt Macy 548eda14cbcSMatt Macy rid = ksid_getrid(ksid); 549eda14cbcSMatt Macy domain = ksid_getdomain(ksid); 550eda14cbcSMatt Macy 551eda14cbcSMatt Macy idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE); 552eda14cbcSMatt Macy 553eda14cbcSMatt Macy zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type); 554eda14cbcSMatt Macy 555eda14cbcSMatt Macy return (FUID_ENCODE(idx, rid)); 556eda14cbcSMatt Macy } 557eda14cbcSMatt Macy #endif /* HAVE_KSID */ 558eda14cbcSMatt Macy 559eda14cbcSMatt Macy /* 560eda14cbcSMatt Macy * Create a file system FUID for an ACL ace 561eda14cbcSMatt Macy * or a chown/chgrp of the file. 562eda14cbcSMatt Macy * This is similar to zfs_fuid_create_cred, except that 563eda14cbcSMatt Macy * we can't find the domain + rid information in the 564eda14cbcSMatt Macy * cred. Instead we have to query Winchester for the 565eda14cbcSMatt Macy * domain and rid. 566eda14cbcSMatt Macy * 567eda14cbcSMatt Macy * During replay operations the domain+rid information is 568eda14cbcSMatt Macy * found in the zfs_fuid_info_t that the replay code has 569eda14cbcSMatt Macy * attached to the zfsvfs of the file system. 570eda14cbcSMatt Macy */ 571eda14cbcSMatt Macy uint64_t 572eda14cbcSMatt Macy zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr, 573eda14cbcSMatt Macy zfs_fuid_type_t type, zfs_fuid_info_t **fuidpp) 574eda14cbcSMatt Macy { 575eda14cbcSMatt Macy #ifdef HAVE_KSID 576a0b956f5SMartin Matuska const char *domain, *kdomain; 577eda14cbcSMatt Macy uint32_t fuid_idx = FUID_INDEX(id); 578eda14cbcSMatt Macy uint32_t rid = 0; 579eda14cbcSMatt Macy idmap_stat status; 580eda14cbcSMatt Macy uint64_t idx = UID_NOBODY; 581eda14cbcSMatt Macy zfs_fuid_t *zfuid = NULL; 582eda14cbcSMatt Macy zfs_fuid_info_t *fuidp = NULL; 583eda14cbcSMatt Macy 584eda14cbcSMatt Macy /* 585eda14cbcSMatt Macy * If POSIX ID, or entry is already a FUID then 586eda14cbcSMatt Macy * just return the id 587eda14cbcSMatt Macy * 588eda14cbcSMatt Macy * We may also be handed an already FUID'ized id via 589eda14cbcSMatt Macy * chmod. 590eda14cbcSMatt Macy */ 591eda14cbcSMatt Macy 592eda14cbcSMatt Macy if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0) 593eda14cbcSMatt Macy return (id); 594eda14cbcSMatt Macy 595eda14cbcSMatt Macy if (zfsvfs->z_replay) { 596eda14cbcSMatt Macy fuidp = zfsvfs->z_fuid_replay; 597eda14cbcSMatt Macy 598eda14cbcSMatt Macy /* 599eda14cbcSMatt Macy * If we are passed an ephemeral id, but no 600eda14cbcSMatt Macy * fuid_info was logged then return NOBODY. 601eda14cbcSMatt Macy * This is most likely a result of idmap service 602eda14cbcSMatt Macy * not being available. 603eda14cbcSMatt Macy */ 604eda14cbcSMatt Macy if (fuidp == NULL) 605eda14cbcSMatt Macy return (UID_NOBODY); 606eda14cbcSMatt Macy 607eda14cbcSMatt Macy VERIFY3U(type, >=, ZFS_OWNER); 608eda14cbcSMatt Macy VERIFY3U(type, <=, ZFS_ACE_GROUP); 609eda14cbcSMatt Macy 610eda14cbcSMatt Macy switch (type) { 611eda14cbcSMatt Macy case ZFS_ACE_USER: 612eda14cbcSMatt Macy case ZFS_ACE_GROUP: 613eda14cbcSMatt Macy zfuid = list_head(&fuidp->z_fuids); 614eda14cbcSMatt Macy rid = FUID_RID(zfuid->z_logfuid); 615eda14cbcSMatt Macy idx = FUID_INDEX(zfuid->z_logfuid); 616eda14cbcSMatt Macy break; 617eda14cbcSMatt Macy case ZFS_OWNER: 618eda14cbcSMatt Macy rid = FUID_RID(fuidp->z_fuid_owner); 619eda14cbcSMatt Macy idx = FUID_INDEX(fuidp->z_fuid_owner); 620eda14cbcSMatt Macy break; 621eda14cbcSMatt Macy case ZFS_GROUP: 622eda14cbcSMatt Macy rid = FUID_RID(fuidp->z_fuid_group); 623eda14cbcSMatt Macy idx = FUID_INDEX(fuidp->z_fuid_group); 624eda14cbcSMatt Macy break; 625*15f0b8c3SMartin Matuska } 626eda14cbcSMatt Macy domain = fuidp->z_domain_table[idx - 1]; 627eda14cbcSMatt Macy } else { 628eda14cbcSMatt Macy if (type == ZFS_OWNER || type == ZFS_ACE_USER) 629eda14cbcSMatt Macy status = kidmap_getsidbyuid(crgetzone(cr), id, 630eda14cbcSMatt Macy &domain, &rid); 631eda14cbcSMatt Macy else 632eda14cbcSMatt Macy status = kidmap_getsidbygid(crgetzone(cr), id, 633eda14cbcSMatt Macy &domain, &rid); 634eda14cbcSMatt Macy 635eda14cbcSMatt Macy if (status != 0) { 636eda14cbcSMatt Macy /* 637eda14cbcSMatt Macy * When returning nobody we will need to 638eda14cbcSMatt Macy * make a dummy fuid table entry for logging 639eda14cbcSMatt Macy * purposes. 640eda14cbcSMatt Macy */ 641eda14cbcSMatt Macy rid = UID_NOBODY; 642eda14cbcSMatt Macy domain = nulldomain; 643eda14cbcSMatt Macy } 644eda14cbcSMatt Macy } 645eda14cbcSMatt Macy 646eda14cbcSMatt Macy idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE); 647eda14cbcSMatt Macy 648eda14cbcSMatt Macy if (!zfsvfs->z_replay) 649eda14cbcSMatt Macy zfs_fuid_node_add(fuidpp, kdomain, 650eda14cbcSMatt Macy rid, idx, id, type); 651eda14cbcSMatt Macy else if (zfuid != NULL) { 652eda14cbcSMatt Macy list_remove(&fuidp->z_fuids, zfuid); 653eda14cbcSMatt Macy kmem_free(zfuid, sizeof (zfs_fuid_t)); 654eda14cbcSMatt Macy } 655eda14cbcSMatt Macy return (FUID_ENCODE(idx, rid)); 656eda14cbcSMatt Macy #else 657eda14cbcSMatt Macy /* 658eda14cbcSMatt Macy * The Linux port only supports POSIX IDs, use the passed id. 659eda14cbcSMatt Macy */ 660eda14cbcSMatt Macy return (id); 661eda14cbcSMatt Macy #endif 662eda14cbcSMatt Macy } 663eda14cbcSMatt Macy 664eda14cbcSMatt Macy void 665eda14cbcSMatt Macy zfs_fuid_destroy(zfsvfs_t *zfsvfs) 666eda14cbcSMatt Macy { 667eda14cbcSMatt Macy rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER); 668eda14cbcSMatt Macy if (!zfsvfs->z_fuid_loaded) { 669eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 670eda14cbcSMatt Macy return; 671eda14cbcSMatt Macy } 672eda14cbcSMatt Macy zfs_fuid_table_destroy(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain); 673eda14cbcSMatt Macy rw_exit(&zfsvfs->z_fuid_lock); 674eda14cbcSMatt Macy } 675eda14cbcSMatt Macy 676eda14cbcSMatt Macy /* 677eda14cbcSMatt Macy * Allocate zfs_fuid_info for tracking FUIDs created during 678eda14cbcSMatt Macy * zfs_mknode, VOP_SETATTR() or VOP_SETSECATTR() 679eda14cbcSMatt Macy */ 680eda14cbcSMatt Macy zfs_fuid_info_t * 681eda14cbcSMatt Macy zfs_fuid_info_alloc(void) 682eda14cbcSMatt Macy { 683eda14cbcSMatt Macy zfs_fuid_info_t *fuidp; 684eda14cbcSMatt Macy 685eda14cbcSMatt Macy fuidp = kmem_zalloc(sizeof (zfs_fuid_info_t), KM_SLEEP); 686eda14cbcSMatt Macy list_create(&fuidp->z_domains, sizeof (zfs_fuid_domain_t), 687eda14cbcSMatt Macy offsetof(zfs_fuid_domain_t, z_next)); 688eda14cbcSMatt Macy list_create(&fuidp->z_fuids, sizeof (zfs_fuid_t), 689eda14cbcSMatt Macy offsetof(zfs_fuid_t, z_next)); 690eda14cbcSMatt Macy return (fuidp); 691eda14cbcSMatt Macy } 692eda14cbcSMatt Macy 693eda14cbcSMatt Macy /* 694eda14cbcSMatt Macy * Release all memory associated with zfs_fuid_info_t 695eda14cbcSMatt Macy */ 696eda14cbcSMatt Macy void 697eda14cbcSMatt Macy zfs_fuid_info_free(zfs_fuid_info_t *fuidp) 698eda14cbcSMatt Macy { 699eda14cbcSMatt Macy zfs_fuid_t *zfuid; 700eda14cbcSMatt Macy zfs_fuid_domain_t *zdomain; 701eda14cbcSMatt Macy 702eda14cbcSMatt Macy while ((zfuid = list_head(&fuidp->z_fuids)) != NULL) { 703eda14cbcSMatt Macy list_remove(&fuidp->z_fuids, zfuid); 704eda14cbcSMatt Macy kmem_free(zfuid, sizeof (zfs_fuid_t)); 705eda14cbcSMatt Macy } 706eda14cbcSMatt Macy 707eda14cbcSMatt Macy if (fuidp->z_domain_table != NULL) 708eda14cbcSMatt Macy kmem_free(fuidp->z_domain_table, 709eda14cbcSMatt Macy (sizeof (char *)) * fuidp->z_domain_cnt); 710eda14cbcSMatt Macy 711eda14cbcSMatt Macy while ((zdomain = list_head(&fuidp->z_domains)) != NULL) { 712eda14cbcSMatt Macy list_remove(&fuidp->z_domains, zdomain); 713eda14cbcSMatt Macy kmem_free(zdomain, sizeof (zfs_fuid_domain_t)); 714eda14cbcSMatt Macy } 715eda14cbcSMatt Macy 716eda14cbcSMatt Macy kmem_free(fuidp, sizeof (zfs_fuid_info_t)); 717eda14cbcSMatt Macy } 718eda14cbcSMatt Macy 719eda14cbcSMatt Macy /* 720eda14cbcSMatt Macy * Check to see if id is a groupmember. If cred 721eda14cbcSMatt Macy * has ksid info then sidlist is checked first 722eda14cbcSMatt Macy * and if still not found then POSIX groups are checked 723eda14cbcSMatt Macy * 724eda14cbcSMatt Macy * Will use a straight FUID compare when possible. 725eda14cbcSMatt Macy */ 726eda14cbcSMatt Macy boolean_t 727eda14cbcSMatt Macy zfs_groupmember(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr) 728eda14cbcSMatt Macy { 729eda14cbcSMatt Macy uid_t gid; 730eda14cbcSMatt Macy 731eda14cbcSMatt Macy #ifdef illumos 732eda14cbcSMatt Macy ksid_t *ksid = crgetsid(cr, KSID_GROUP); 733eda14cbcSMatt Macy ksidlist_t *ksidlist = crgetsidlist(cr); 734eda14cbcSMatt Macy 735eda14cbcSMatt Macy if (ksid && ksidlist) { 736eda14cbcSMatt Macy int i; 737eda14cbcSMatt Macy ksid_t *ksid_groups; 738eda14cbcSMatt Macy uint32_t idx = FUID_INDEX(id); 739eda14cbcSMatt Macy uint32_t rid = FUID_RID(id); 740eda14cbcSMatt Macy 741eda14cbcSMatt Macy ksid_groups = ksidlist->ksl_sids; 742eda14cbcSMatt Macy 743eda14cbcSMatt Macy for (i = 0; i != ksidlist->ksl_nsid; i++) { 744eda14cbcSMatt Macy if (idx == 0) { 745eda14cbcSMatt Macy if (id != IDMAP_WK_CREATOR_GROUP_GID && 746eda14cbcSMatt Macy id == ksid_groups[i].ks_id) { 747eda14cbcSMatt Macy return (B_TRUE); 748eda14cbcSMatt Macy } 749eda14cbcSMatt Macy } else { 750eda14cbcSMatt Macy const char *domain; 751eda14cbcSMatt Macy 752eda14cbcSMatt Macy domain = zfs_fuid_find_by_idx(zfsvfs, idx); 753eda14cbcSMatt Macy ASSERT(domain != NULL); 754eda14cbcSMatt Macy 755eda14cbcSMatt Macy if (strcmp(domain, 756eda14cbcSMatt Macy IDMAP_WK_CREATOR_SID_AUTHORITY) == 0) 757eda14cbcSMatt Macy return (B_FALSE); 758eda14cbcSMatt Macy 759eda14cbcSMatt Macy if ((strcmp(domain, 760eda14cbcSMatt Macy ksid_groups[i].ks_domain->kd_name) == 0) && 761eda14cbcSMatt Macy rid == ksid_groups[i].ks_rid) 762eda14cbcSMatt Macy return (B_TRUE); 763eda14cbcSMatt Macy } 764eda14cbcSMatt Macy } 765eda14cbcSMatt Macy } 766eda14cbcSMatt Macy #endif /* illumos */ 767eda14cbcSMatt Macy 768eda14cbcSMatt Macy /* 769eda14cbcSMatt Macy * Not found in ksidlist, check posix groups 770eda14cbcSMatt Macy */ 771eda14cbcSMatt Macy gid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP); 772eda14cbcSMatt Macy return (groupmember(gid, cr)); 773eda14cbcSMatt Macy } 774eda14cbcSMatt Macy 775eda14cbcSMatt Macy void 776eda14cbcSMatt Macy zfs_fuid_txhold(zfsvfs_t *zfsvfs, dmu_tx_t *tx) 777eda14cbcSMatt Macy { 778eda14cbcSMatt Macy if (zfsvfs->z_fuid_obj == 0) { 779eda14cbcSMatt Macy dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT); 780eda14cbcSMatt Macy dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 781eda14cbcSMatt Macy FUID_SIZE_ESTIMATE(zfsvfs)); 782eda14cbcSMatt Macy dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL); 783eda14cbcSMatt Macy } else { 784eda14cbcSMatt Macy dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj); 785eda14cbcSMatt Macy dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0, 786eda14cbcSMatt Macy FUID_SIZE_ESTIMATE(zfsvfs)); 787eda14cbcSMatt Macy } 788eda14cbcSMatt Macy } 789eda14cbcSMatt Macy 790eda14cbcSMatt Macy /* 791eda14cbcSMatt Macy * buf must be big enough (eg, 32 bytes) 792eda14cbcSMatt Macy */ 793eda14cbcSMatt Macy int 794eda14cbcSMatt Macy zfs_id_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid, 795eda14cbcSMatt Macy char *buf, size_t len, boolean_t addok) 796eda14cbcSMatt Macy { 797eda14cbcSMatt Macy uint64_t fuid; 798eda14cbcSMatt Macy int domainid = 0; 799eda14cbcSMatt Macy 800eda14cbcSMatt Macy if (domain && domain[0]) { 801eda14cbcSMatt Macy domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok); 802eda14cbcSMatt Macy if (domainid == -1) 803eda14cbcSMatt Macy return (SET_ERROR(ENOENT)); 804eda14cbcSMatt Macy } 805eda14cbcSMatt Macy fuid = FUID_ENCODE(domainid, rid); 806eda14cbcSMatt Macy (void) snprintf(buf, len, "%llx", (longlong_t)fuid); 807eda14cbcSMatt Macy return (0); 808eda14cbcSMatt Macy } 809eda14cbcSMatt Macy #endif 810