X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fdsl_deleg.c;h=294932c450bf7c2d2dd624673c009dd868b699bc;hb=68121a03daf58a7d5b9351f110196b8ce806e1fa;hp=4d7ec80a18a637043c13686f76a97d0b1ec18f14;hpb=c65aa5b2b9c48375ea1c451f252f0056e16f4e49;p=zfs.git diff --git a/module/zfs/dsl_deleg.c b/module/zfs/dsl_deleg.c index 4d7ec80..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. */ /* @@ -170,10 +171,8 @@ 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))) { @@ -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