* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
/*
#include <sys/dsl_synctask.h>
#include <sys/dsl_deleg.h>
#include <sys/spa.h>
-#include <sys/spa_impl.h>
-#include <sys/zio_checksum.h> /* for the default checksum value */
#include <sys/zap.h>
#include <sys/fs/zfs.h>
#include <sys/cred.h>
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)
(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 &&
}
static void
-dsl_deleg_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
+dsl_deleg_set_sync(void *arg1, void *arg2, dmu_tx_t *tx)
{
dsl_dir_t *dd = arg1;
nvlist_t *nvp = arg2;
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;
whokey, 8, 1, &jumpobj, tx) == 0);
}
- while (permpair = nvlist_next_nvpair(perms, permpair)) {
+ while ((permpair = nvlist_next_nvpair(perms, permpair))) {
const char *perm = nvpair_name(permpair);
uint64_t n = 0;
VERIFY(zap_update(mos, jumpobj,
perm, 8, 1, &n, tx) == 0);
- spa_history_internal_log(LOG_DS_PERM_UPDATE,
- dd->dd_pool->dp_spa, tx, cr,
+ spa_history_log_internal(LOG_DS_PERM_UPDATE,
+ dd->dd_pool->dp_spa, tx,
"%s %s dataset = %llu", whokey, perm,
dd->dd_phys->dd_head_dataset_obj);
}
}
static void
-dsl_deleg_unset_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx)
+dsl_deleg_unset_sync(void *arg1, void *arg2, dmu_tx_t *tx)
{
dsl_dir_t *dd = arg1;
nvlist_t *nvp = arg2;
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;
(void) zap_remove(mos, zapobj, whokey, tx);
VERIFY(0 == zap_destroy(mos, jumpobj, tx));
}
- spa_history_internal_log(LOG_DS_PERM_WHO_REMOVE,
- dd->dd_pool->dp_spa, tx, cr,
+ spa_history_log_internal(LOG_DS_PERM_WHO_REMOVE,
+ dd->dd_pool->dp_spa, tx,
"%s dataset = %llu", whokey,
dd->dd_phys->dd_head_dataset_obj);
continue;
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;
VERIFY(0 == zap_destroy(mos,
jumpobj, tx));
}
- spa_history_internal_log(LOG_DS_PERM_REMOVE,
- dd->dd_pool->dp_spa, tx, cr,
+ spa_history_log_internal(LOG_DS_PERM_REMOVE,
+ dd->dd_pool->dp_spa, tx,
"%s %s dataset = %llu", whokey, perm,
dd->dd_phys->dd_head_dataset_obj);
}
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,
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)
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,
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);
}
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);
}
}
/*
- * Check if user has requested permission.
+ * Check if user has requested permission. If descendent is set, must have
+ * descendent perms.
*/
int
-dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
+dsl_deleg_access_impl(dsl_dataset_t *ds, boolean_t descendent, const char *perm,
+ cred_t *cr)
{
- dsl_dataset_t *ds;
dsl_dir_t *dd;
dsl_pool_t *dp;
void *cookie;
avl_tree_t permsets;
perm_set_t *setnode;
- error = dsl_dataset_hold(dsname, FTAG, &ds);
- if (error)
- return (error);
-
dp = ds->ds_dir->dd_pool;
mos = dp->dp_meta_objset;
- if (dsl_delegation_on(mos) == B_FALSE) {
- dsl_dataset_rele(ds, FTAG);
+ if (dsl_delegation_on(mos) == B_FALSE)
return (ECANCELED);
- }
if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
- SPA_VERSION_DELEGATED_PERMS) {
- dsl_dataset_rele(ds, FTAG);
+ 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.
if (dsl_prop_get_dd(dd,
zfs_prop_to_name(ZFS_PROP_ZONED),
- 8, 1, &zoned, NULL) != 0)
+ 8, 1, &zoned, NULL, B_FALSE) != 0)
break;
if (!zoned)
break;
error = EPERM;
success:
rw_exit(&dp->dp_config_rwlock);
- dsl_dataset_rele(ds, FTAG);
cookie = NULL;
while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
return (error);
}
+int
+dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
+{
+ dsl_dataset_t *ds;
+ int error;
+
+ error = dsl_dataset_hold(dsname, FTAG, &ds);
+ if (error)
+ return (error);
+
+ error = dsl_deleg_access_impl(ds, B_FALSE, perm, cr);
+ dsl_dataset_rele(ds, FTAG);
+
+ return (error);
+}
+
/*
* Other routines.
*/
boolean_t
dsl_delegation_on(objset_t *os)
{
- return (os->os->os_spa->spa_delegation);
+ return (!!spa_delegation(os->os_spa));
}
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+EXPORT_SYMBOL(dsl_deleg_get);
+EXPORT_SYMBOL(dsl_deleg_set);
+#endif