summaryrefslogtreecommitdiffstats
path: root/module/zfs/dsl_prop.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/dsl_prop.c')
-rw-r--r--module/zfs/dsl_prop.c87
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.
*/