X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fdsl_deleg.c;h=294932c450bf7c2d2dd624673c009dd868b699bc;hb=refs%2Fheads%2Frertzinger%2Ffeature-zpool-get--p;hp=529fb052fa75db007efb217169b920ef16545c3b;hpb=572e285762521df27fe5b026f409ba1a21abb7ac;p=zfs.git diff --git a/module/zfs/dsl_deleg.c b/module/zfs/dsl_deleg.c index 529fb05..294932c 100644 --- a/module/zfs/dsl_deleg.c +++ b/module/zfs/dsl_deleg.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ /* @@ -96,13 +97,13 @@ dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr) if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0) return (error); - while (whopair = nvlist_next_nvpair(nvp, whopair)) { + while ((whopair = nvlist_next_nvpair(nvp, whopair))) { nvlist_t *perms; nvpair_t *permpair = NULL; VERIFY(nvpair_value_nvlist(whopair, &perms) == 0); - while (permpair = nvlist_next_nvpair(perms, permpair)) { + while ((permpair = nvlist_next_nvpair(perms, permpair))) { const char *perm = nvpair_name(permpair); if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0) @@ -133,7 +134,7 @@ dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr) (void) snprintf(idstr, sizeof (idstr), "%lld", (longlong_t)crgetuid(cr)); - while (whopair = nvlist_next_nvpair(nvp, whopair)) { + while ((whopair = nvlist_next_nvpair(nvp, whopair))) { zfs_deleg_who_type_t type = nvpair_name(whopair)[0]; if (type != ZFS_DELEG_USER && @@ -161,7 +162,7 @@ dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx) DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); } - while (whopair = nvlist_next_nvpair(nvp, whopair)) { + while ((whopair = nvlist_next_nvpair(nvp, whopair))) { const char *whokey = nvpair_name(whopair); nvlist_t *perms; nvpair_t *permpair = NULL; @@ -170,13 +171,11 @@ dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx) VERIFY(nvpair_value_nvlist(whopair, &perms) == 0); if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) { - jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, - DMU_OT_NONE, 0, tx); - VERIFY(zap_update(mos, zapobj, - whokey, 8, 1, &jumpobj, tx) == 0); + jumpobj = zap_create_link(mos, DMU_OT_DSL_PERMS, + zapobj, whokey, tx); } - while (permpair = nvlist_next_nvpair(perms, permpair)) { + while ((permpair = nvlist_next_nvpair(perms, permpair))) { const char *perm = nvpair_name(permpair); uint64_t n = 0; @@ -202,7 +201,7 @@ dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx) if (zapobj == 0) return; - while (whopair = nvlist_next_nvpair(nvp, whopair)) { + while ((whopair = nvlist_next_nvpair(nvp, whopair))) { const char *whokey = nvpair_name(whopair); nvlist_t *perms; nvpair_t *permpair = NULL; @@ -224,7 +223,7 @@ dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx) if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) continue; - while (permpair = nvlist_next_nvpair(perms, permpair)) { + while ((permpair = nvlist_next_nvpair(perms, permpair))) { const char *perm = nvpair_name(permpair); uint64_t n = 0; @@ -261,7 +260,7 @@ dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset) return (ENOTSUP); } - while (whopair = nvlist_next_nvpair(nvp, whopair)) + while ((whopair = nvlist_next_nvpair(nvp, whopair))) blocks_modified++; error = dsl_sync_task_do(dd->dd_pool, NULL, @@ -296,6 +295,9 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp) dsl_pool_t *dp; int error; objset_t *mos; + zap_cursor_t *basezc, *zc; + zap_attribute_t *baseza, *za; + char *source; error = dsl_dir_open(ddname, FTAG, &startdd, NULL); if (error) @@ -304,15 +306,17 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp) dp = startdd->dd_pool; mos = dp->dp_meta_objset; + zc = kmem_alloc(sizeof(zap_cursor_t), KM_SLEEP); + za = kmem_alloc(sizeof(zap_attribute_t), KM_SLEEP); + basezc = kmem_alloc(sizeof(zap_cursor_t), KM_SLEEP); + baseza = kmem_alloc(sizeof(zap_attribute_t), KM_SLEEP); + source = kmem_alloc(MAXNAMELEN + strlen(MOS_DIR_NAME) + 1, KM_SLEEP); VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); rw_enter(&dp->dp_config_rwlock, RW_READER); for (dd = startdd; dd != NULL; dd = dd->dd_parent) { - zap_cursor_t basezc; - zap_attribute_t baseza; nvlist_t *sp_nvp; uint64_t n; - char source[MAXNAMELEN]; if (dd->dd_phys->dd_deleg_zapobj && (zap_count(mos, dd->dd_phys->dd_deleg_zapobj, @@ -323,32 +327,30 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp) continue; } - for (zap_cursor_init(&basezc, mos, + for (zap_cursor_init(basezc, mos, dd->dd_phys->dd_deleg_zapobj); - zap_cursor_retrieve(&basezc, &baseza) == 0; - zap_cursor_advance(&basezc)) { - zap_cursor_t zc; - zap_attribute_t za; + zap_cursor_retrieve(basezc, baseza) == 0; + zap_cursor_advance(basezc)) { nvlist_t *perms_nvp; - ASSERT(baseza.za_integer_length == 8); - ASSERT(baseza.za_num_integers == 1); + ASSERT(baseza->za_integer_length == 8); + ASSERT(baseza->za_num_integers == 1); VERIFY(nvlist_alloc(&perms_nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); - for (zap_cursor_init(&zc, mos, baseza.za_first_integer); - zap_cursor_retrieve(&zc, &za) == 0; - zap_cursor_advance(&zc)) { + for (zap_cursor_init(zc, mos, baseza->za_first_integer); + zap_cursor_retrieve(zc, za) == 0; + zap_cursor_advance(zc)) { VERIFY(nvlist_add_boolean(perms_nvp, - za.za_name) == 0); + za->za_name) == 0); } - zap_cursor_fini(&zc); - VERIFY(nvlist_add_nvlist(sp_nvp, baseza.za_name, + zap_cursor_fini(zc); + VERIFY(nvlist_add_nvlist(sp_nvp, baseza->za_name, perms_nvp) == 0); nvlist_free(perms_nvp); } - zap_cursor_fini(&basezc); + zap_cursor_fini(basezc); dsl_dir_name(dd, source); VERIFY(nvlist_add_nvlist(*nvp, source, sp_nvp) == 0); @@ -356,6 +358,12 @@ dsl_deleg_get(const char *ddname, nvlist_t **nvp) } rw_exit(&dp->dp_config_rwlock); + kmem_free(source, MAXNAMELEN + strlen(MOS_DIR_NAME) + 1); + kmem_free(baseza, sizeof(zap_attribute_t)); + kmem_free(basezc, sizeof(zap_cursor_t)); + kmem_free(za, sizeof(zap_attribute_t)); + kmem_free(zc, sizeof(zap_cursor_t)); + dsl_dir_close(startdd, FTAG); return (0); } @@ -525,10 +533,12 @@ dsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl, } /* - * Check if user has requested permission. + * Check if user has requested permission. If descendent is set, must have + * descendent perms. */ int -dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr) +dsl_deleg_access_impl(dsl_dataset_t *ds, boolean_t descendent, const char *perm, + cred_t *cr) { dsl_dir_t *dd; dsl_pool_t *dp; @@ -549,7 +559,7 @@ dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr) SPA_VERSION_DELEGATED_PERMS) return (EPERM); - if (dsl_dataset_is_snapshot(ds)) { + if (dsl_dataset_is_snapshot(ds) || descendent) { /* * Snapshots are treated as descendents only, * local permissions do not apply. @@ -642,7 +652,7 @@ dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr) if (error) return (error); - error = dsl_deleg_access_impl(ds, perm, cr); + error = dsl_deleg_access_impl(ds, B_FALSE, perm, cr); dsl_dataset_rele(ds, FTAG); return (error); @@ -744,3 +754,8 @@ dsl_delegation_on(objset_t *os) { return (!!spa_delegation(os->os_spa)); } + +#if defined(_KERNEL) && defined(HAVE_SPL) +EXPORT_SYMBOL(dsl_deleg_get); +EXPORT_SYMBOL(dsl_deleg_set); +#endif