FreeBSD ZFS
The Zettabyte File System

dsl_deleg.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  * Copyright (c) 2012 by Delphix. All rights reserved.
00024  */
00025 
00072 #include <sys/dmu.h>
00073 #include <sys/dmu_objset.h>
00074 #include <sys/dmu_tx.h>
00075 #include <sys/dsl_dataset.h>
00076 #include <sys/dsl_dir.h>
00077 #include <sys/dsl_prop.h>
00078 #include <sys/dsl_synctask.h>
00079 #include <sys/dsl_deleg.h>
00080 #include <sys/spa.h>
00081 #include <sys/zap.h>
00082 #include <sys/fs/zfs.h>
00083 #include <sys/cred.h>
00084 #include <sys/sunddi.h>
00085 
00086 #include "zfs_deleg.h"
00087 
00094 int
00095 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr)
00096 {
00097         nvpair_t *whopair = NULL;
00098         int error;
00099 
00100         if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
00101                 return (error);
00102 
00103         while (whopair = nvlist_next_nvpair(nvp, whopair)) {
00104                 nvlist_t *perms;
00105                 nvpair_t *permpair = NULL;
00106 
00107                 VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);
00108 
00109                 while (permpair = nvlist_next_nvpair(perms, permpair)) {
00110                         const char *perm = nvpair_name(permpair);
00111 
00112                         if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0)
00113                                 return (EPERM);
00114 
00115                         if ((error = dsl_deleg_access(ddname, perm, cr)) != 0)
00116                                 return (error);
00117                 }
00118         }
00119         return (0);
00120 }
00121 
00127 int
00128 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
00129 {
00130         nvpair_t *whopair = NULL;
00131         int error;
00132         char idstr[32];
00133 
00134         if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
00135                 return (error);
00136 
00137         (void) snprintf(idstr, sizeof (idstr), "%lld",
00138             (longlong_t)crgetuid(cr));
00139 
00140         while (whopair = nvlist_next_nvpair(nvp, whopair)) {
00141                 zfs_deleg_who_type_t type = nvpair_name(whopair)[0];
00142 
00143                 if (type != ZFS_DELEG_USER &&
00144                     type != ZFS_DELEG_USER_SETS)
00145                         return (EPERM);
00146 
00147                 if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0)
00148                         return (EPERM);
00149         }
00150         return (0);
00151 }
00152 
00153 static void
00154 dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
00155 {
00156         dsl_dir_t *dd = arg1;
00157         nvlist_t *nvp = arg2;
00158         objset_t *mos = dd->dd_pool->dp_meta_objset;
00159         nvpair_t *whopair = NULL;
00160         uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
00161 
00162         if (zapobj == 0) {
00163                 dmu_buf_will_dirty(dd->dd_dbuf, tx);
00164                 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
00165                     DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
00166         }
00167 
00168         while (whopair = nvlist_next_nvpair(nvp, whopair)) {
00169                 const char *whokey = nvpair_name(whopair);
00170                 nvlist_t *perms;
00171                 nvpair_t *permpair = NULL;
00172                 uint64_t jumpobj;
00173 
00174                 VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);
00175 
00176                 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
00177                         jumpobj = zap_create_link(mos, DMU_OT_DSL_PERMS,
00178                             zapobj, whokey, tx);
00179                 }
00180 
00181                 while (permpair = nvlist_next_nvpair(perms, permpair)) {
00182                         const char *perm = nvpair_name(permpair);
00183                         uint64_t n = 0;
00184 
00185                         VERIFY(zap_update(mos, jumpobj,
00186                             perm, 8, 1, &n, tx) == 0);
00187                         spa_history_log_internal(LOG_DS_PERM_UPDATE,
00188                             dd->dd_pool->dp_spa, tx,
00189                             "%s %s dataset = %llu", whokey, perm,
00190                             dd->dd_phys->dd_head_dataset_obj);
00191                 }
00192         }
00193 }
00194 
00195 static void
00196 dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
00197 {
00198         dsl_dir_t *dd = arg1;
00199         nvlist_t *nvp = arg2;
00200         objset_t *mos = dd->dd_pool->dp_meta_objset;
00201         nvpair_t *whopair = NULL;
00202         uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
00203 
00204         if (zapobj == 0)
00205                 return;
00206 
00207         while (whopair = nvlist_next_nvpair(nvp, whopair)) {
00208                 const char *whokey = nvpair_name(whopair);
00209                 nvlist_t *perms;
00210                 nvpair_t *permpair = NULL;
00211                 uint64_t jumpobj;
00212 
00213                 if (nvpair_value_nvlist(whopair, &perms) != 0) {
00214                         if (zap_lookup(mos, zapobj, whokey, 8,
00215                             1, &jumpobj) == 0) {
00216                                 (void) zap_remove(mos, zapobj, whokey, tx);
00217                                 VERIFY(0 == zap_destroy(mos, jumpobj, tx));
00218                         }
00219                         spa_history_log_internal(LOG_DS_PERM_WHO_REMOVE,
00220                             dd->dd_pool->dp_spa, tx,
00221                             "%s dataset = %llu", whokey,
00222                             dd->dd_phys->dd_head_dataset_obj);
00223                         continue;
00224                 }
00225 
00226                 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0)
00227                         continue;
00228 
00229                 while (permpair = nvlist_next_nvpair(perms, permpair)) {
00230                         const char *perm = nvpair_name(permpair);
00231                         uint64_t n = 0;
00232 
00233                         (void) zap_remove(mos, jumpobj, perm, tx);
00234                         if (zap_count(mos, jumpobj, &n) == 0 && n == 0) {
00235                                 (void) zap_remove(mos, zapobj,
00236                                     whokey, tx);
00237                                 VERIFY(0 == zap_destroy(mos,
00238                                     jumpobj, tx));
00239                         }
00240                         spa_history_log_internal(LOG_DS_PERM_REMOVE,
00241                             dd->dd_pool->dp_spa, tx,
00242                             "%s %s dataset = %llu", whokey, perm,
00243                             dd->dd_phys->dd_head_dataset_obj);
00244                 }
00245         }
00246 }
00247 
00248 int
00249 dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset)
00250 {
00251         dsl_dir_t *dd;
00252         int error;
00253         nvpair_t *whopair = NULL;
00254         int blocks_modified = 0;
00255 
00256         error = dsl_dir_open(ddname, FTAG, &dd, NULL);
00257         if (error)
00258                 return (error);
00259 
00260         if (spa_version(dmu_objset_spa(dd->dd_pool->dp_meta_objset)) <
00261             SPA_VERSION_DELEGATED_PERMS) {
00262                 dsl_dir_close(dd, FTAG);
00263                 return (ENOTSUP);
00264         }
00265 
00266         while (whopair = nvlist_next_nvpair(nvp, whopair))
00267                 blocks_modified++;
00268 
00269         error = dsl_sync_task_do(dd->dd_pool, NULL,
00270             unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
00271             dd, nvp, blocks_modified);
00272         dsl_dir_close(dd, FTAG);
00273 
00274         return (error);
00275 }
00276 
00294 int
00295 dsl_deleg_get(const char *ddname, nvlist_t **nvp)
00296 {
00297         dsl_dir_t *dd, *startdd;
00298         dsl_pool_t *dp;
00299         int error;
00300         objset_t *mos;
00301 
00302         error = dsl_dir_open(ddname, FTAG, &startdd, NULL);
00303         if (error)
00304                 return (error);
00305 
00306         dp = startdd->dd_pool;
00307         mos = dp->dp_meta_objset;
00308 
00309         VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
00310 
00311         rw_enter(&dp->dp_config_rwlock, RW_READER);
00312         for (dd = startdd; dd != NULL; dd = dd->dd_parent) {
00313                 zap_cursor_t basezc;
00314                 zap_attribute_t baseza;
00315                 nvlist_t *sp_nvp;
00316                 uint64_t n;
00317                 char source[MAXNAMELEN];
00318 
00319                 if (dd->dd_phys->dd_deleg_zapobj &&
00320                     (zap_count(mos, dd->dd_phys->dd_deleg_zapobj,
00321                     &n) == 0) && n) {
00322                         VERIFY(nvlist_alloc(&sp_nvp,
00323                             NV_UNIQUE_NAME, KM_SLEEP) == 0);
00324                 } else {
00325                         continue;
00326                 }
00327 
00328                 for (zap_cursor_init(&basezc, mos,
00329                     dd->dd_phys->dd_deleg_zapobj);
00330                     zap_cursor_retrieve(&basezc, &baseza) == 0;
00331                     zap_cursor_advance(&basezc)) {
00332                         zap_cursor_t zc;
00333                         zap_attribute_t za;
00334                         nvlist_t *perms_nvp;
00335 
00336                         ASSERT(baseza.za_integer_length == 8);
00337                         ASSERT(baseza.za_num_integers == 1);
00338 
00339                         VERIFY(nvlist_alloc(&perms_nvp,
00340                             NV_UNIQUE_NAME, KM_SLEEP) == 0);
00341                         for (zap_cursor_init(&zc, mos, baseza.za_first_integer);
00342                             zap_cursor_retrieve(&zc, &za) == 0;
00343                             zap_cursor_advance(&zc)) {
00344                                 VERIFY(nvlist_add_boolean(perms_nvp,
00345                                     za.za_name) == 0);
00346                         }
00347                         zap_cursor_fini(&zc);
00348                         VERIFY(nvlist_add_nvlist(sp_nvp, baseza.za_name,
00349                             perms_nvp) == 0);
00350                         nvlist_free(perms_nvp);
00351                 }
00352 
00353                 zap_cursor_fini(&basezc);
00354 
00355                 dsl_dir_name(dd, source);
00356                 VERIFY(nvlist_add_nvlist(*nvp, source, sp_nvp) == 0);
00357                 nvlist_free(sp_nvp);
00358         }
00359         rw_exit(&dp->dp_config_rwlock);
00360 
00361         dsl_dir_close(startdd, FTAG);
00362         return (0);
00363 }
00364 
00368 typedef struct perm_set {
00369         avl_node_t      p_node;
00370         boolean_t       p_matched;
00371         char            p_setname[ZFS_MAX_DELEG_NAME];
00372 } perm_set_t;
00373 
00374 static int
00375 perm_set_compare(const void *arg1, const void *arg2)
00376 {
00377         const perm_set_t *node1 = arg1;
00378         const perm_set_t *node2 = arg2;
00379         int val;
00380 
00381         val = strcmp(node1->p_setname, node2->p_setname);
00382         if (val == 0)
00383                 return (0);
00384         return (val > 0 ? 1 : -1);
00385 }
00386 
00397 static int
00398 dsl_check_access(objset_t *mos, uint64_t zapobj,
00399     char type, char checkflag, void *valp, const char *perm)
00400 {
00401         int error;
00402         uint64_t jumpobj, zero;
00403         char whokey[ZFS_MAX_DELEG_NAME];
00404 
00405         zfs_deleg_whokey(whokey, type, checkflag, valp);
00406         error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj);
00407         if (error == 0) {
00408                 error = zap_lookup(mos, jumpobj, perm, 8, 1, &zero);
00409                 if (error == ENOENT)
00410                         error = EPERM;
00411         }
00412         return (error);
00413 }
00414 
00418 static int
00419 dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm,
00420     int checkflag, cred_t *cr)
00421 {
00422         const   gid_t *gids;
00423         int     ngids;
00424         int     i;
00425         uint64_t id;
00426 
00427         /* check for user */
00428         id = crgetuid(cr);
00429         if (dsl_check_access(mos, zapobj,
00430             ZFS_DELEG_USER, checkflag, &id, perm) == 0)
00431                 return (0);
00432 
00433         /* check for users primary group */
00434         id = crgetgid(cr);
00435         if (dsl_check_access(mos, zapobj,
00436             ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
00437                 return (0);
00438 
00439         /* check for everyone entry */
00440         id = -1;
00441         if (dsl_check_access(mos, zapobj,
00442             ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
00443                 return (0);
00444 
00445         /* check each supplemental group user is a member of */
00446         ngids = crgetngroups(cr);
00447         gids = crgetgroups(cr);
00448         for (i = 0; i != ngids; i++) {
00449                 id = gids[i];
00450                 if (dsl_check_access(mos, zapobj,
00451                     ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
00452                         return (0);
00453         }
00454 
00455         return (EPERM);
00456 }
00457 
00462 static int
00463 dsl_load_sets(objset_t *mos, uint64_t zapobj,
00464     char type, char checkflag, void *valp, avl_tree_t *avl)
00465 {
00466         zap_cursor_t zc;
00467         zap_attribute_t za;
00468         perm_set_t *permnode;
00469         avl_index_t idx;
00470         uint64_t jumpobj;
00471         int error;
00472         char whokey[ZFS_MAX_DELEG_NAME];
00473 
00474         zfs_deleg_whokey(whokey, type, checkflag, valp);
00475 
00476         error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj);
00477         if (error != 0)
00478                 return (error);
00479 
00480         for (zap_cursor_init(&zc, mos, jumpobj);
00481             zap_cursor_retrieve(&zc, &za) == 0;
00482             zap_cursor_advance(&zc)) {
00483                 permnode = kmem_alloc(sizeof (perm_set_t), KM_SLEEP);
00484                 (void) strlcpy(permnode->p_setname, za.za_name,
00485                     sizeof (permnode->p_setname));
00486                 permnode->p_matched = B_FALSE;
00487 
00488                 if (avl_find(avl, permnode, &idx) == NULL) {
00489                         avl_insert(avl, permnode, idx);
00490                 } else {
00491                         kmem_free(permnode, sizeof (perm_set_t));
00492                 }
00493         }
00494         zap_cursor_fini(&zc);
00495         return (0);
00496 }
00497 
00501 static void
00502 dsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl,
00503     char checkflag, cred_t *cr)
00504 {
00505         const   gid_t *gids;
00506         int     ngids, i;
00507         uint64_t id;
00508 
00509         id = crgetuid(cr);
00510         (void) dsl_load_sets(mos, zapobj,
00511             ZFS_DELEG_USER_SETS, checkflag, &id, avl);
00512 
00513         id = crgetgid(cr);
00514         (void) dsl_load_sets(mos, zapobj,
00515             ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
00516 
00517         (void) dsl_load_sets(mos, zapobj,
00518             ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
00519 
00520         ngids = crgetngroups(cr);
00521         gids = crgetgroups(cr);
00522         for (i = 0; i != ngids; i++) {
00523                 id = gids[i];
00524                 (void) dsl_load_sets(mos, zapobj,
00525                     ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
00526         }
00527 }
00528 
00533 int
00534 dsl_deleg_access_impl(dsl_dataset_t *ds, boolean_t descendent, const char *perm,
00535     cred_t *cr)
00536 {
00537         dsl_dir_t *dd;
00538         dsl_pool_t *dp;
00539         void *cookie;
00540         int     error;
00541         char    checkflag;
00542         objset_t *mos;
00543         avl_tree_t permsets;
00544         perm_set_t *setnode;
00545 
00546         dp = ds->ds_dir->dd_pool;
00547         mos = dp->dp_meta_objset;
00548 
00549         if (dsl_delegation_on(mos) == B_FALSE)
00550                 return (ECANCELED);
00551 
00552         if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
00553             SPA_VERSION_DELEGATED_PERMS)
00554                 return (EPERM);
00555 
00556         if (dsl_dataset_is_snapshot(ds) || descendent) {
00557                 /*
00558                  * Snapshots are treated as descendents only,
00559                  * local permissions do not apply.
00560                  */
00561                 checkflag = ZFS_DELEG_DESCENDENT;
00562         } else {
00563                 checkflag = ZFS_DELEG_LOCAL;
00564         }
00565 
00566         avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
00567             offsetof(perm_set_t, p_node));
00568 
00569         rw_enter(&dp->dp_config_rwlock, RW_READER);
00570         for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
00571             checkflag = ZFS_DELEG_DESCENDENT) {
00572                 uint64_t zapobj;
00573                 boolean_t expanded;
00574 
00575                 /*
00576                  * If not in global zone then make sure
00577                  * the zoned property is set
00578                  */
00579                 if (!INGLOBALZONE(curthread)) {
00580                         uint64_t zoned;
00581 
00582                         if (dsl_prop_get_dd(dd,
00583                             zfs_prop_to_name(ZFS_PROP_ZONED),
00584                             8, 1, &zoned, NULL, B_FALSE) != 0)
00585                                 break;
00586                         if (!zoned)
00587                                 break;
00588                 }
00589                 zapobj = dd->dd_phys->dd_deleg_zapobj;
00590 
00591                 if (zapobj == 0)
00592                         continue;
00593 
00594                 dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr);
00595 again:
00596                 expanded = B_FALSE;
00597                 for (setnode = avl_first(&permsets); setnode;
00598                     setnode = AVL_NEXT(&permsets, setnode)) {
00599                         if (setnode->p_matched == B_TRUE)
00600                                 continue;
00601 
00602                         /* See if this set directly grants this permission */
00603                         error = dsl_check_access(mos, zapobj,
00604                             ZFS_DELEG_NAMED_SET, 0, setnode->p_setname, perm);
00605                         if (error == 0)
00606                                 goto success;
00607                         if (error == EPERM)
00608                                 setnode->p_matched = B_TRUE;
00609 
00610                         /* See if this set includes other sets */
00611                         error = dsl_load_sets(mos, zapobj,
00612                             ZFS_DELEG_NAMED_SET_SETS, 0,
00613                             setnode->p_setname, &permsets);
00614                         if (error == 0)
00615                                 setnode->p_matched = expanded = B_TRUE;
00616                 }
00617                 /*
00618                  * If we expanded any sets, that will define more sets,
00619                  * which we need to check.
00620                  */
00621                 if (expanded)
00622                         goto again;
00623 
00624                 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
00625                 if (error == 0)
00626                         goto success;
00627         }
00628         error = EPERM;
00629 success:
00630         rw_exit(&dp->dp_config_rwlock);
00631 
00632         cookie = NULL;
00633         while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
00634                 kmem_free(setnode, sizeof (perm_set_t));
00635 
00636         return (error);
00637 }
00638 
00639 int
00640 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
00641 {
00642         dsl_dataset_t *ds;
00643         int error;
00644 
00645         error = dsl_dataset_hold(dsname, FTAG, &ds);
00646         if (error)
00647                 return (error);
00648 
00649         error = dsl_deleg_access_impl(ds, B_FALSE, perm, cr);
00650         dsl_dataset_rele(ds, FTAG);
00651 
00652         return (error);
00653 }
00654 
00655 /*
00656  * Other routines.
00657  */
00658 
00659 static void
00660 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
00661     boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
00662 {
00663         objset_t *mos = dd->dd_pool->dp_meta_objset;
00664         uint64_t jumpobj, pjumpobj;
00665         uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
00666         zap_cursor_t zc;
00667         zap_attribute_t za;
00668         char whokey[ZFS_MAX_DELEG_NAME];
00669 
00670         zfs_deleg_whokey(whokey,
00671             dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE,
00672             ZFS_DELEG_LOCAL, NULL);
00673         if (zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj) != 0)
00674                 return;
00675 
00676         if (zapobj == 0) {
00677                 dmu_buf_will_dirty(dd->dd_dbuf, tx);
00678                 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
00679                     DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
00680         }
00681 
00682         zfs_deleg_whokey(whokey,
00683             dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER,
00684             ZFS_DELEG_LOCAL, &uid);
00685         if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) {
00686                 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
00687                 VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0);
00688         }
00689 
00690         for (zap_cursor_init(&zc, mos, pjumpobj);
00691             zap_cursor_retrieve(&zc, &za) == 0;
00692             zap_cursor_advance(&zc)) {
00693                 uint64_t zero = 0;
00694                 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
00695 
00696                 VERIFY(zap_update(mos, jumpobj, za.za_name,
00697                     8, 1, &zero, tx) == 0);
00698         }
00699         zap_cursor_fini(&zc);
00700 }
00701 
00705 void
00706 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr)
00707 {
00708         dsl_dir_t *dd;
00709         uint64_t uid = crgetuid(cr);
00710 
00711         if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) <
00712             SPA_VERSION_DELEGATED_PERMS)
00713                 return;
00714 
00715         for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) {
00716                 uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj;
00717 
00718                 if (pzapobj == 0)
00719                         continue;
00720 
00721                 copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx);
00722                 copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx);
00723         }
00724 }
00725 
00726 int
00727 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx)
00728 {
00729         zap_cursor_t zc;
00730         zap_attribute_t za;
00731 
00732         if (zapobj == 0)
00733                 return (0);
00734 
00735         for (zap_cursor_init(&zc, mos, zapobj);
00736             zap_cursor_retrieve(&zc, &za) == 0;
00737             zap_cursor_advance(&zc)) {
00738                 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
00739                 VERIFY(0 == zap_destroy(mos, za.za_first_integer, tx));
00740         }
00741         zap_cursor_fini(&zc);
00742         VERIFY(0 == zap_destroy(mos, zapobj, tx));
00743         return (0);
00744 }
00745 
00746 boolean_t
00747 dsl_delegation_on(objset_t *os)
00748 {
00749         return (!!spa_delegation(os->os_spa));
00750 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines