1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 224543Smarks * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens #include <sys/dmu.h> 291356Seschrock #include <sys/dmu_objset.h> 30789Sahrens #include <sys/dmu_tx.h> 31789Sahrens #include <sys/dsl_dataset.h> 32789Sahrens #include <sys/dsl_dir.h> 33789Sahrens #include <sys/dsl_prop.h> 342199Sahrens #include <sys/dsl_synctask.h> 35789Sahrens #include <sys/spa.h> 36789Sahrens #include <sys/zio_checksum.h> /* for the default checksum value */ 37789Sahrens #include <sys/zap.h> 38789Sahrens #include <sys/fs/zfs.h> 39789Sahrens 40789Sahrens #include "zfs_prop.h" 41789Sahrens 42789Sahrens static int 43789Sahrens dodefault(const char *propname, int intsz, int numint, void *buf) 44789Sahrens { 45789Sahrens zfs_prop_t prop; 46789Sahrens 47*5094Slling if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL || 48789Sahrens zfs_prop_readonly(prop)) 49789Sahrens return (ENOENT); 50789Sahrens 514787Sahrens if (zfs_prop_get_type(prop) == PROP_TYPE_STRING) { 52789Sahrens if (intsz != 1) 53789Sahrens return (EOVERFLOW); 54*5094Slling (void) strncpy(buf, zfs_prop_default_string(prop), 55*5094Slling numint); 56789Sahrens } else { 57789Sahrens if (intsz != 8 || numint < 1) 58789Sahrens return (EOVERFLOW); 59789Sahrens 60789Sahrens *(uint64_t *)buf = zfs_prop_default_numeric(prop); 61789Sahrens } 62789Sahrens 63789Sahrens return (0); 64789Sahrens } 65789Sahrens 66789Sahrens static int 672082Seschrock dsl_prop_get_impl(dsl_dir_t *dd, const char *propname, 68789Sahrens int intsz, int numint, void *buf, char *setpoint) 69789Sahrens { 702082Seschrock int err = ENOENT; 712676Seschrock zfs_prop_t prop; 72789Sahrens 73789Sahrens if (setpoint) 74789Sahrens setpoint[0] = '\0'; 75789Sahrens 762676Seschrock prop = zfs_name_to_prop(propname); 772676Seschrock 782082Seschrock /* 792082Seschrock * Note: dd may be NULL, therefore we shouldn't dereference it 802082Seschrock * ouside this loop. 812082Seschrock */ 822082Seschrock for (; dd != NULL; dd = dd->dd_parent) { 832082Seschrock objset_t *mos = dd->dd_pool->dp_meta_objset; 842082Seschrock ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); 85789Sahrens err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, 86789Sahrens propname, intsz, numint, buf); 87789Sahrens if (err != ENOENT) { 88789Sahrens if (setpoint) 89789Sahrens dsl_dir_name(dd, setpoint); 90789Sahrens break; 91789Sahrens } 922676Seschrock 932676Seschrock /* 942676Seschrock * Break out of this loop for non-inheritable properties. 952676Seschrock */ 96*5094Slling if (prop != ZPROP_INVAL && 972676Seschrock !zfs_prop_inheritable(prop)) 982676Seschrock break; 99789Sahrens } 100789Sahrens if (err == ENOENT) 101789Sahrens err = dodefault(propname, intsz, numint, buf); 102789Sahrens 103789Sahrens return (err); 104789Sahrens } 105789Sahrens 106789Sahrens /* 107789Sahrens * Register interest in the named property. We'll call the callback 108789Sahrens * once to notify it of the current property value, and again each time 109789Sahrens * the property changes, until this callback is unregistered. 110789Sahrens * 111789Sahrens * Return 0 on success, errno if the prop is not an integer value. 112789Sahrens */ 113789Sahrens int 114789Sahrens dsl_prop_register(dsl_dataset_t *ds, const char *propname, 115789Sahrens dsl_prop_changed_cb_t *callback, void *cbarg) 116789Sahrens { 1172082Seschrock dsl_dir_t *dd = ds->ds_dir; 118789Sahrens uint64_t value; 119789Sahrens dsl_prop_cb_record_t *cbr; 120789Sahrens int err; 1212199Sahrens int need_rwlock; 122789Sahrens 1232199Sahrens need_rwlock = !RW_WRITE_HELD(&dd->dd_pool->dp_config_rwlock); 1242199Sahrens if (need_rwlock) 1252199Sahrens rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 126789Sahrens 1272082Seschrock err = dsl_prop_get_impl(dd, propname, 8, 1, &value, NULL); 128789Sahrens if (err != 0) { 129789Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 130789Sahrens return (err); 131789Sahrens } 132789Sahrens 133789Sahrens cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP); 1342082Seschrock cbr->cbr_ds = ds; 135789Sahrens cbr->cbr_propname = kmem_alloc(strlen(propname)+1, KM_SLEEP); 136789Sahrens (void) strcpy((char *)cbr->cbr_propname, propname); 137789Sahrens cbr->cbr_func = callback; 138789Sahrens cbr->cbr_arg = cbarg; 139789Sahrens mutex_enter(&dd->dd_lock); 140789Sahrens list_insert_head(&dd->dd_prop_cbs, cbr); 141789Sahrens mutex_exit(&dd->dd_lock); 142789Sahrens 143789Sahrens cbr->cbr_func(cbr->cbr_arg, value); 144789Sahrens 1451544Seschrock VERIFY(0 == dsl_dir_open_obj(dd->dd_pool, dd->dd_object, 1461544Seschrock NULL, cbr, &dd)); 1472199Sahrens if (need_rwlock) 1482199Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 149789Sahrens /* Leave dataset open until this callback is unregistered */ 150789Sahrens return (0); 151789Sahrens } 152789Sahrens 153789Sahrens int 154789Sahrens dsl_prop_get_ds(dsl_dir_t *dd, const char *propname, 155789Sahrens int intsz, int numints, void *buf, char *setpoint) 156789Sahrens { 157789Sahrens int err; 158789Sahrens 159789Sahrens rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 1602082Seschrock err = dsl_prop_get_impl(dd, propname, intsz, numints, buf, setpoint); 161789Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 162789Sahrens 163789Sahrens return (err); 164789Sahrens } 165789Sahrens 1664543Smarks /* 1674543Smarks * Get property when config lock is already held. 1684543Smarks */ 1694543Smarks int dsl_prop_get_ds_locked(dsl_dir_t *dd, const char *propname, 1704543Smarks int intsz, int numints, void *buf, char *setpoint) 1714543Smarks { 1724543Smarks ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); 1734543Smarks return (dsl_prop_get_impl(dd, propname, intsz, numints, buf, setpoint)); 1744543Smarks } 1754543Smarks 176789Sahrens int 177789Sahrens dsl_prop_get(const char *ddname, const char *propname, 178789Sahrens int intsz, int numints, void *buf, char *setpoint) 179789Sahrens { 180789Sahrens dsl_dir_t *dd; 181789Sahrens const char *tail; 182789Sahrens int err; 183789Sahrens 1841544Seschrock err = dsl_dir_open(ddname, FTAG, &dd, &tail); 1851544Seschrock if (err) 1861544Seschrock return (err); 187789Sahrens if (tail && tail[0] != '@') { 188789Sahrens dsl_dir_close(dd, FTAG); 189789Sahrens return (ENOENT); 190789Sahrens } 191789Sahrens 192789Sahrens err = dsl_prop_get_ds(dd, propname, intsz, numints, buf, setpoint); 193789Sahrens 194789Sahrens dsl_dir_close(dd, FTAG); 195789Sahrens return (err); 196789Sahrens } 197789Sahrens 198789Sahrens /* 199789Sahrens * Get the current property value. It may have changed by the time this 200789Sahrens * function returns, so it is NOT safe to follow up with 201789Sahrens * dsl_prop_register() and assume that the value has not changed in 202789Sahrens * between. 203789Sahrens * 204789Sahrens * Return 0 on success, ENOENT if ddname is invalid. 205789Sahrens */ 206789Sahrens int 207789Sahrens dsl_prop_get_integer(const char *ddname, const char *propname, 208789Sahrens uint64_t *valuep, char *setpoint) 209789Sahrens { 210789Sahrens return (dsl_prop_get(ddname, propname, 8, 1, valuep, setpoint)); 211789Sahrens } 212789Sahrens 213789Sahrens /* 214789Sahrens * Unregister this callback. Return 0 on success, ENOENT if ddname is 215789Sahrens * invalid, ENOMSG if no matching callback registered. 216789Sahrens */ 217789Sahrens int 218789Sahrens dsl_prop_unregister(dsl_dataset_t *ds, const char *propname, 219789Sahrens dsl_prop_changed_cb_t *callback, void *cbarg) 220789Sahrens { 2212082Seschrock dsl_dir_t *dd = ds->ds_dir; 222789Sahrens dsl_prop_cb_record_t *cbr; 223789Sahrens 224789Sahrens mutex_enter(&dd->dd_lock); 225789Sahrens for (cbr = list_head(&dd->dd_prop_cbs); 226789Sahrens cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 2272082Seschrock if (cbr->cbr_ds == ds && 228789Sahrens cbr->cbr_func == callback && 2292082Seschrock cbr->cbr_arg == cbarg && 2302082Seschrock strcmp(cbr->cbr_propname, propname) == 0) 231789Sahrens break; 232789Sahrens } 233789Sahrens 234789Sahrens if (cbr == NULL) { 235789Sahrens mutex_exit(&dd->dd_lock); 236789Sahrens return (ENOMSG); 237789Sahrens } 238789Sahrens 239789Sahrens list_remove(&dd->dd_prop_cbs, cbr); 240789Sahrens mutex_exit(&dd->dd_lock); 241789Sahrens kmem_free((void*)cbr->cbr_propname, strlen(cbr->cbr_propname)+1); 242789Sahrens kmem_free(cbr, sizeof (dsl_prop_cb_record_t)); 243789Sahrens 244789Sahrens /* Clean up from dsl_prop_register */ 245789Sahrens dsl_dir_close(dd, cbr); 246789Sahrens return (0); 247789Sahrens } 248789Sahrens 2492082Seschrock /* 2502082Seschrock * Return the number of callbacks that are registered for this dataset. 2512082Seschrock */ 2522082Seschrock int 2532082Seschrock dsl_prop_numcb(dsl_dataset_t *ds) 2542082Seschrock { 2552082Seschrock dsl_dir_t *dd = ds->ds_dir; 2562082Seschrock dsl_prop_cb_record_t *cbr; 2572082Seschrock int num = 0; 2582082Seschrock 2592082Seschrock mutex_enter(&dd->dd_lock); 2602082Seschrock for (cbr = list_head(&dd->dd_prop_cbs); 2612082Seschrock cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 2622082Seschrock if (cbr->cbr_ds == ds) 2632082Seschrock num++; 2642082Seschrock } 2652082Seschrock mutex_exit(&dd->dd_lock); 2662082Seschrock 2672082Seschrock return (num); 2682082Seschrock } 2692082Seschrock 270789Sahrens static void 271789Sahrens dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, 272789Sahrens const char *propname, uint64_t value, int first) 273789Sahrens { 274789Sahrens dsl_dir_t *dd; 275789Sahrens dsl_prop_cb_record_t *cbr; 276789Sahrens objset_t *mos = dp->dp_meta_objset; 2772199Sahrens zap_cursor_t zc; 2782199Sahrens zap_attribute_t za; 279789Sahrens int err; 280789Sahrens 281789Sahrens ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock)); 2821544Seschrock err = dsl_dir_open_obj(dp, ddobj, NULL, FTAG, &dd); 2831544Seschrock if (err) 2841544Seschrock return; 285789Sahrens 286789Sahrens if (!first) { 287789Sahrens /* 288789Sahrens * If the prop is set here, then this change is not 289789Sahrens * being inherited here or below; stop the recursion. 290789Sahrens */ 291789Sahrens err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, propname, 292789Sahrens 8, 1, &value); 293789Sahrens if (err == 0) { 294789Sahrens dsl_dir_close(dd, FTAG); 295789Sahrens return; 296789Sahrens } 297789Sahrens ASSERT3U(err, ==, ENOENT); 298789Sahrens } 299789Sahrens 300789Sahrens mutex_enter(&dd->dd_lock); 301789Sahrens for (cbr = list_head(&dd->dd_prop_cbs); 302789Sahrens cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 303789Sahrens if (strcmp(cbr->cbr_propname, propname) == 0) { 304789Sahrens cbr->cbr_func(cbr->cbr_arg, value); 305789Sahrens } 306789Sahrens } 307789Sahrens mutex_exit(&dd->dd_lock); 308789Sahrens 3092199Sahrens for (zap_cursor_init(&zc, mos, 3102199Sahrens dd->dd_phys->dd_child_dir_zapobj); 3112199Sahrens zap_cursor_retrieve(&zc, &za) == 0; 3122199Sahrens zap_cursor_advance(&zc)) { 3132199Sahrens /* XXX recursion could blow stack; esp. za! */ 3142199Sahrens dsl_prop_changed_notify(dp, za.za_first_integer, 3152199Sahrens propname, value, FALSE); 316789Sahrens } 3172199Sahrens zap_cursor_fini(&zc); 318789Sahrens dsl_dir_close(dd, FTAG); 319789Sahrens } 320789Sahrens 321789Sahrens struct prop_set_arg { 322789Sahrens const char *name; 323789Sahrens int intsz; 324789Sahrens int numints; 325789Sahrens const void *buf; 326789Sahrens }; 327789Sahrens 3282199Sahrens 3292199Sahrens static void 3304543Smarks dsl_prop_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 331789Sahrens { 3322199Sahrens dsl_dir_t *dd = arg1; 3332199Sahrens struct prop_set_arg *psa = arg2; 334789Sahrens objset_t *mos = dd->dd_pool->dp_meta_objset; 335789Sahrens uint64_t zapobj = dd->dd_phys->dd_props_zapobj; 336789Sahrens uint64_t intval; 3372199Sahrens int isint; 3384543Smarks char valbuf[32]; 3394543Smarks char *valstr; 340789Sahrens 341789Sahrens isint = (dodefault(psa->name, 8, 1, &intval) == 0); 342789Sahrens 343789Sahrens if (psa->numints == 0) { 3442199Sahrens int err = zap_remove(mos, zapobj, psa->name, tx); 3452199Sahrens ASSERT(err == 0 || err == ENOENT); 3462199Sahrens if (isint) { 3472199Sahrens VERIFY(0 == dsl_prop_get_impl(dd->dd_parent, 3482199Sahrens psa->name, 8, 1, &intval, NULL)); 349789Sahrens } 350789Sahrens } else { 3512199Sahrens VERIFY(0 == zap_update(mos, zapobj, psa->name, 3522199Sahrens psa->intsz, psa->numints, psa->buf, tx)); 353789Sahrens if (isint) 354789Sahrens intval = *(uint64_t *)psa->buf; 355789Sahrens } 356789Sahrens 3572199Sahrens if (isint) { 358789Sahrens dsl_prop_changed_notify(dd->dd_pool, 359789Sahrens dd->dd_object, psa->name, intval, TRUE); 360789Sahrens } 3614543Smarks if (isint) { 3624543Smarks (void) snprintf(valbuf, sizeof (valbuf), 3634543Smarks "%lld", (longlong_t)intval); 3644543Smarks valstr = valbuf; 3654543Smarks } else { 3664543Smarks valstr = (char *)psa->buf; 3674543Smarks } 3684543Smarks spa_history_internal_log((psa->numints == 0) ? LOG_DS_INHERIT : 3694543Smarks LOG_DS_PROPSET, dd->dd_pool->dp_spa, tx, cr, 3704543Smarks "%s=%s dataset = %llu", psa->name, valstr, 3714543Smarks dd->dd_phys->dd_head_dataset_obj); 372789Sahrens } 373789Sahrens 374789Sahrens int 3752885Sahrens dsl_prop_set_dd(dsl_dir_t *dd, const char *propname, 3762885Sahrens int intsz, int numints, const void *buf) 3772885Sahrens { 3782885Sahrens struct prop_set_arg psa; 3792885Sahrens 3802885Sahrens psa.name = propname; 3812885Sahrens psa.intsz = intsz; 3822885Sahrens psa.numints = numints; 3832885Sahrens psa.buf = buf; 3842885Sahrens 3852885Sahrens return (dsl_sync_task_do(dd->dd_pool, 3862885Sahrens NULL, dsl_prop_set_sync, dd, &psa, 2)); 3872885Sahrens } 3882885Sahrens 3892885Sahrens int 390789Sahrens dsl_prop_set(const char *ddname, const char *propname, 391789Sahrens int intsz, int numints, const void *buf) 392789Sahrens { 393789Sahrens dsl_dir_t *dd; 394789Sahrens int err; 395789Sahrens 3962641Sahrens /* 3972641Sahrens * We must do these checks before we get to the syncfunc, since 3982641Sahrens * it can't fail. 3992641Sahrens */ 4002641Sahrens if (strlen(propname) >= ZAP_MAXNAMELEN) 4012641Sahrens return (ENAMETOOLONG); 4022641Sahrens if (intsz * numints >= ZAP_MAXVALUELEN) 4032641Sahrens return (E2BIG); 4042641Sahrens 4051544Seschrock err = dsl_dir_open(ddname, FTAG, &dd, NULL); 4061544Seschrock if (err) 4071544Seschrock return (err); 4082885Sahrens err = dsl_prop_set_dd(dd, propname, intsz, numints, buf); 409789Sahrens dsl_dir_close(dd, FTAG); 410789Sahrens return (err); 411789Sahrens } 4121356Seschrock 4131356Seschrock /* 4141356Seschrock * Iterate over all properties for this dataset and return them in an nvlist. 4151356Seschrock */ 4161356Seschrock int 4171356Seschrock dsl_prop_get_all(objset_t *os, nvlist_t **nvp) 4181356Seschrock { 4191356Seschrock dsl_dataset_t *ds = os->os->os_dsl_dataset; 4202082Seschrock dsl_dir_t *dd = ds->ds_dir; 4211356Seschrock int err = 0; 4221356Seschrock dsl_pool_t *dp; 4231356Seschrock objset_t *mos; 4241356Seschrock 4251356Seschrock if (dsl_dataset_is_snapshot(ds)) { 4261356Seschrock VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 4271356Seschrock return (0); 4281356Seschrock } 4291356Seschrock 4301356Seschrock VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 4311356Seschrock 4321356Seschrock dp = dd->dd_pool; 4331356Seschrock mos = dp->dp_meta_objset; 4341356Seschrock 4351356Seschrock rw_enter(&dp->dp_config_rwlock, RW_READER); 4362082Seschrock for (; dd != NULL; dd = dd->dd_parent) { 4372885Sahrens char setpoint[MAXNAMELEN]; 4382885Sahrens zap_cursor_t zc; 4392885Sahrens zap_attribute_t za; 4402885Sahrens 4411356Seschrock dsl_dir_name(dd, setpoint); 4421356Seschrock 4431356Seschrock for (zap_cursor_init(&zc, mos, dd->dd_phys->dd_props_zapobj); 4441356Seschrock (err = zap_cursor_retrieve(&zc, &za)) == 0; 4451356Seschrock zap_cursor_advance(&zc)) { 4462885Sahrens nvlist_t *propval; 4472885Sahrens zfs_prop_t prop; 4482676Seschrock /* 4492676Seschrock * Skip non-inheritable properties. 4502676Seschrock */ 4512676Seschrock if ((prop = zfs_name_to_prop(za.za_name)) != 452*5094Slling ZPROP_INVAL && !zfs_prop_inheritable(prop) && 4532676Seschrock dd != ds->ds_dir) 4541356Seschrock continue; 4551356Seschrock 4562676Seschrock if (nvlist_lookup_nvlist(*nvp, za.za_name, 4572676Seschrock &propval) == 0) 4582676Seschrock continue; 4592676Seschrock 4602676Seschrock VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, 4611356Seschrock KM_SLEEP) == 0); 4621356Seschrock if (za.za_integer_length == 1) { 4631356Seschrock /* 4641356Seschrock * String property 4651356Seschrock */ 4662885Sahrens char *tmp = kmem_alloc(za.za_num_integers, 4672885Sahrens KM_SLEEP); 4681356Seschrock err = zap_lookup(mos, 4691356Seschrock dd->dd_phys->dd_props_zapobj, 4701356Seschrock za.za_name, 1, za.za_num_integers, 4711356Seschrock tmp); 4721356Seschrock if (err != 0) { 4731356Seschrock kmem_free(tmp, za.za_num_integers); 4741356Seschrock break; 4751356Seschrock } 476*5094Slling VERIFY(nvlist_add_string(propval, ZPROP_VALUE, 477*5094Slling tmp) == 0); 4781356Seschrock kmem_free(tmp, za.za_num_integers); 4791356Seschrock } else { 4801356Seschrock /* 4811356Seschrock * Integer property 4821356Seschrock */ 4831356Seschrock ASSERT(za.za_integer_length == 8); 484*5094Slling (void) nvlist_add_uint64(propval, ZPROP_VALUE, 485*5094Slling za.za_first_integer); 4861356Seschrock } 4871356Seschrock 488*5094Slling VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, 489*5094Slling setpoint) == 0); 4901356Seschrock VERIFY(nvlist_add_nvlist(*nvp, za.za_name, 4912676Seschrock propval) == 0); 4922676Seschrock nvlist_free(propval); 4931356Seschrock } 4941356Seschrock zap_cursor_fini(&zc); 4951356Seschrock 4962082Seschrock if (err != ENOENT) 4971356Seschrock break; 4982082Seschrock err = 0; 4991356Seschrock } 5001356Seschrock rw_exit(&dp->dp_config_rwlock); 5011356Seschrock 5021356Seschrock return (err); 5031356Seschrock } 5042885Sahrens 5052885Sahrens void 5062885Sahrens dsl_prop_nvlist_add_uint64(nvlist_t *nv, zfs_prop_t prop, uint64_t value) 5072885Sahrens { 5082885Sahrens nvlist_t *propval; 5092885Sahrens 5102885Sahrens VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); 511*5094Slling VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0); 5122885Sahrens VERIFY(nvlist_add_nvlist(nv, zfs_prop_to_name(prop), propval) == 0); 5132885Sahrens nvlist_free(propval); 5142885Sahrens } 5152885Sahrens 5162885Sahrens void 5172885Sahrens dsl_prop_nvlist_add_string(nvlist_t *nv, zfs_prop_t prop, const char *value) 5182885Sahrens { 5192885Sahrens nvlist_t *propval; 5202885Sahrens 5212885Sahrens VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); 522*5094Slling VERIFY(nvlist_add_string(propval, ZPROP_VALUE, value) == 0); 5232885Sahrens VERIFY(nvlist_add_nvlist(nv, zfs_prop_to_name(prop), propval) == 0); 5242885Sahrens nvlist_free(propval); 5252885Sahrens } 526