diff options
author | Brian Behlendorf <[email protected]> | 2009-07-02 15:44:48 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2009-07-02 15:44:48 -0700 |
commit | 9babb37438b58e77bad04e820d5702e15b79e6a6 (patch) | |
tree | e369da81095eca3fc155b0c02bdd4a9f06506781 /module/zfs/dsl_prop.c | |
parent | d164b2093561a9771db07346e6fffc9ca19427a2 (diff) |
Rebase master to b117
Diffstat (limited to 'module/zfs/dsl_prop.c')
-rw-r--r-- | module/zfs/dsl_prop.c | 87 |
1 files changed, 81 insertions, 6 deletions
diff --git a/module/zfs/dsl_prop.c b/module/zfs/dsl_prop.c index 212acbbc5..664ccff45 100644 --- a/module/zfs/dsl_prop.c +++ b/module/zfs/dsl_prop.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/dmu.h> #include <sys/dmu_objset.h> #include <sys/dmu_tx.h> @@ -416,6 +414,34 @@ dsl_prop_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) } void +dsl_props_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) +{ + dsl_dataset_t *ds = arg1; + nvlist_t *nvl = arg2; + nvpair_t *elem = NULL; + + while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { + struct prop_set_arg psa; + + psa.name = nvpair_name(elem); + + if (nvpair_type(elem) == DATA_TYPE_STRING) { + VERIFY(nvpair_value_string(elem, + (char **)&psa.buf) == 0); + psa.intsz = 1; + psa.numints = strlen(psa.buf) + 1; + } else { + uint64_t intval; + VERIFY(nvpair_value_uint64(elem, &intval) == 0); + psa.intsz = sizeof (intval); + psa.numints = 1; + psa.buf = &intval; + } + dsl_prop_set_sync(ds, &psa, cr, tx); + } +} + +void dsl_prop_set_uint64_sync(dsl_dir_t *dd, const char *name, uint64_t val, cred_t *cr, dmu_tx_t *tx) { @@ -438,6 +464,7 @@ dsl_prop_set(const char *dsname, const char *propname, int intsz, int numints, const void *buf) { dsl_dataset_t *ds; + uint64_t version; int err; struct prop_set_arg psa; @@ -447,15 +474,19 @@ dsl_prop_set(const char *dsname, const char *propname, */ if (strlen(propname) >= ZAP_MAXNAMELEN) return (ENAMETOOLONG); - if (intsz * numints >= ZAP_MAXVALUELEN) - return (E2BIG); err = dsl_dataset_hold(dsname, FTAG, &ds); if (err) return (err); + version = spa_version(ds->ds_dir->dd_pool->dp_spa); + if (intsz * numints >= (version < SPA_VERSION_STMF_PROP ? + ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) { + dsl_dataset_rele(ds, FTAG); + return (E2BIG); + } if (dsl_dataset_is_snapshot(ds) && - spa_version(ds->ds_dir->dd_pool->dp_spa) < SPA_VERSION_SNAP_PROPS) { + version < SPA_VERSION_SNAP_PROPS) { dsl_dataset_rele(ds, FTAG); return (ENOTSUP); } @@ -471,6 +502,50 @@ dsl_prop_set(const char *dsname, const char *propname, return (err); } +int +dsl_props_set(const char *dsname, nvlist_t *nvl) +{ + dsl_dataset_t *ds; + uint64_t version; + nvpair_t *elem = NULL; + int err; + + if (err = dsl_dataset_hold(dsname, FTAG, &ds)) + return (err); + /* + * Do these checks before the syncfunc, since it can't fail. + */ + version = spa_version(ds->ds_dir->dd_pool->dp_spa); + while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { + if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { + dsl_dataset_rele(ds, FTAG); + return (ENAMETOOLONG); + } + if (nvpair_type(elem) == DATA_TYPE_STRING) { + char *valstr; + VERIFY(nvpair_value_string(elem, &valstr) == 0); + if (strlen(valstr) >= (version < + SPA_VERSION_STMF_PROP ? + ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) { + dsl_dataset_rele(ds, FTAG); + return (E2BIG); + } + } + } + + if (dsl_dataset_is_snapshot(ds) && + version < SPA_VERSION_SNAP_PROPS) { + dsl_dataset_rele(ds, FTAG); + return (ENOTSUP); + } + + err = dsl_sync_task_do(ds->ds_dir->dd_pool, + NULL, dsl_props_set_sync, ds, nvl, 2); + + dsl_dataset_rele(ds, FTAG); + return (err); +} + /* * Iterate over all properties for this dataset and return them in an nvlist. */ |