1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 227f7322feSeschrock * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/dmu.h> 297f7322feSeschrock #include <sys/dmu_objset.h> 30fa9e4066Sahrens #include <sys/dmu_tx.h> 31fa9e4066Sahrens #include <sys/dsl_dataset.h> 32fa9e4066Sahrens #include <sys/dsl_dir.h> 33fa9e4066Sahrens #include <sys/dsl_prop.h> 34fa9e4066Sahrens #include <sys/spa.h> 35fa9e4066Sahrens #include <sys/zio_checksum.h> /* for the default checksum value */ 36fa9e4066Sahrens #include <sys/zap.h> 37fa9e4066Sahrens #include <sys/fs/zfs.h> 38fa9e4066Sahrens 39fa9e4066Sahrens #include "zfs_prop.h" 40fa9e4066Sahrens 41fa9e4066Sahrens static int 42fa9e4066Sahrens dodefault(const char *propname, int intsz, int numint, void *buf) 43fa9e4066Sahrens { 44fa9e4066Sahrens zfs_prop_t prop; 45fa9e4066Sahrens 46fa9e4066Sahrens if ((prop = zfs_name_to_prop(propname)) == ZFS_PROP_INVAL || 47fa9e4066Sahrens zfs_prop_readonly(prop)) 48fa9e4066Sahrens return (ENOENT); 49fa9e4066Sahrens 50fa9e4066Sahrens if (zfs_prop_get_type(prop) == prop_type_string) { 51fa9e4066Sahrens if (intsz != 1) 52fa9e4066Sahrens return (EOVERFLOW); 537f7322feSeschrock (void) strncpy(buf, zfs_prop_default_string(prop), numint); 54fa9e4066Sahrens } else { 55fa9e4066Sahrens if (intsz != 8 || numint < 1) 56fa9e4066Sahrens return (EOVERFLOW); 57fa9e4066Sahrens 58fa9e4066Sahrens *(uint64_t *)buf = zfs_prop_default_numeric(prop); 59fa9e4066Sahrens } 60fa9e4066Sahrens 61fa9e4066Sahrens return (0); 62fa9e4066Sahrens } 63fa9e4066Sahrens 64fa9e4066Sahrens static int 65*99653d4eSeschrock dsl_prop_get_impl(dsl_dir_t *dd, const char *propname, 66fa9e4066Sahrens int intsz, int numint, void *buf, char *setpoint) 67fa9e4066Sahrens { 68*99653d4eSeschrock int err = ENOENT; 69fa9e4066Sahrens 70fa9e4066Sahrens if (setpoint) 71fa9e4066Sahrens setpoint[0] = '\0'; 72fa9e4066Sahrens 73*99653d4eSeschrock /* 74*99653d4eSeschrock * Note: dd may be NULL, therefore we shouldn't dereference it 75*99653d4eSeschrock * ouside this loop. 76*99653d4eSeschrock */ 77*99653d4eSeschrock for (; dd != NULL; dd = dd->dd_parent) { 78*99653d4eSeschrock objset_t *mos = dd->dd_pool->dp_meta_objset; 79*99653d4eSeschrock ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); 80fa9e4066Sahrens err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, 81fa9e4066Sahrens propname, intsz, numint, buf); 82fa9e4066Sahrens if (err != ENOENT) { 83fa9e4066Sahrens if (setpoint) 84fa9e4066Sahrens dsl_dir_name(dd, setpoint); 85fa9e4066Sahrens break; 86fa9e4066Sahrens } 87fa9e4066Sahrens } 88fa9e4066Sahrens if (err == ENOENT) 89fa9e4066Sahrens err = dodefault(propname, intsz, numint, buf); 90fa9e4066Sahrens 91fa9e4066Sahrens return (err); 92fa9e4066Sahrens } 93fa9e4066Sahrens 94fa9e4066Sahrens /* 95fa9e4066Sahrens * Register interest in the named property. We'll call the callback 96fa9e4066Sahrens * once to notify it of the current property value, and again each time 97fa9e4066Sahrens * the property changes, until this callback is unregistered. 98fa9e4066Sahrens * 99fa9e4066Sahrens * Return 0 on success, errno if the prop is not an integer value. 100fa9e4066Sahrens */ 101fa9e4066Sahrens int 102fa9e4066Sahrens dsl_prop_register(dsl_dataset_t *ds, const char *propname, 103fa9e4066Sahrens dsl_prop_changed_cb_t *callback, void *cbarg) 104fa9e4066Sahrens { 105*99653d4eSeschrock dsl_dir_t *dd = ds->ds_dir; 106fa9e4066Sahrens uint64_t value; 107fa9e4066Sahrens dsl_prop_cb_record_t *cbr; 108fa9e4066Sahrens int err; 109fa9e4066Sahrens 110fa9e4066Sahrens rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 111fa9e4066Sahrens 112*99653d4eSeschrock err = dsl_prop_get_impl(dd, propname, 8, 1, &value, NULL); 113fa9e4066Sahrens if (err != 0) { 114fa9e4066Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 115fa9e4066Sahrens return (err); 116fa9e4066Sahrens } 117fa9e4066Sahrens 118fa9e4066Sahrens cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP); 119*99653d4eSeschrock cbr->cbr_ds = ds; 120fa9e4066Sahrens cbr->cbr_propname = kmem_alloc(strlen(propname)+1, KM_SLEEP); 121fa9e4066Sahrens (void) strcpy((char *)cbr->cbr_propname, propname); 122fa9e4066Sahrens cbr->cbr_func = callback; 123fa9e4066Sahrens cbr->cbr_arg = cbarg; 124fa9e4066Sahrens mutex_enter(&dd->dd_lock); 125fa9e4066Sahrens list_insert_head(&dd->dd_prop_cbs, cbr); 126fa9e4066Sahrens mutex_exit(&dd->dd_lock); 127fa9e4066Sahrens 128fa9e4066Sahrens cbr->cbr_func(cbr->cbr_arg, value); 129fa9e4066Sahrens 130ea8dc4b6Seschrock VERIFY(0 == dsl_dir_open_obj(dd->dd_pool, dd->dd_object, 131ea8dc4b6Seschrock NULL, cbr, &dd)); 132fa9e4066Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 133fa9e4066Sahrens /* Leave dataset open until this callback is unregistered */ 134fa9e4066Sahrens return (0); 135fa9e4066Sahrens } 136fa9e4066Sahrens 137fa9e4066Sahrens int 138fa9e4066Sahrens dsl_prop_get_ds(dsl_dir_t *dd, const char *propname, 139fa9e4066Sahrens int intsz, int numints, void *buf, char *setpoint) 140fa9e4066Sahrens { 141fa9e4066Sahrens int err; 142fa9e4066Sahrens 143fa9e4066Sahrens rw_enter(&dd->dd_pool->dp_config_rwlock, RW_READER); 144*99653d4eSeschrock err = dsl_prop_get_impl(dd, propname, intsz, numints, buf, setpoint); 145fa9e4066Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 146fa9e4066Sahrens 147fa9e4066Sahrens return (err); 148fa9e4066Sahrens } 149fa9e4066Sahrens 150fa9e4066Sahrens int 151fa9e4066Sahrens dsl_prop_get(const char *ddname, const char *propname, 152fa9e4066Sahrens int intsz, int numints, void *buf, char *setpoint) 153fa9e4066Sahrens { 154fa9e4066Sahrens dsl_dir_t *dd; 155fa9e4066Sahrens const char *tail; 156fa9e4066Sahrens int err; 157fa9e4066Sahrens 158ea8dc4b6Seschrock err = dsl_dir_open(ddname, FTAG, &dd, &tail); 159ea8dc4b6Seschrock if (err) 160ea8dc4b6Seschrock return (err); 161fa9e4066Sahrens if (tail && tail[0] != '@') { 162fa9e4066Sahrens dsl_dir_close(dd, FTAG); 163fa9e4066Sahrens return (ENOENT); 164fa9e4066Sahrens } 165fa9e4066Sahrens 166fa9e4066Sahrens err = dsl_prop_get_ds(dd, propname, intsz, numints, buf, setpoint); 167fa9e4066Sahrens 168fa9e4066Sahrens dsl_dir_close(dd, FTAG); 169fa9e4066Sahrens return (err); 170fa9e4066Sahrens } 171fa9e4066Sahrens 172fa9e4066Sahrens /* 173fa9e4066Sahrens * Return 0 on success, ENOENT if ddname is invalid, EOVERFLOW if 174fa9e4066Sahrens * valuelen not big enough. 175fa9e4066Sahrens */ 176fa9e4066Sahrens int 177fa9e4066Sahrens dsl_prop_get_string(const char *ddname, const char *propname, 178fa9e4066Sahrens char *value, int valuelen, char *setpoint) 179fa9e4066Sahrens { 180fa9e4066Sahrens return (dsl_prop_get(ddname, propname, 1, valuelen, value, setpoint)); 181fa9e4066Sahrens } 182fa9e4066Sahrens 183fa9e4066Sahrens /* 184fa9e4066Sahrens * Get the current property value. It may have changed by the time this 185fa9e4066Sahrens * function returns, so it is NOT safe to follow up with 186fa9e4066Sahrens * dsl_prop_register() and assume that the value has not changed in 187fa9e4066Sahrens * between. 188fa9e4066Sahrens * 189fa9e4066Sahrens * Return 0 on success, ENOENT if ddname is invalid. 190fa9e4066Sahrens */ 191fa9e4066Sahrens int 192fa9e4066Sahrens dsl_prop_get_integer(const char *ddname, const char *propname, 193fa9e4066Sahrens uint64_t *valuep, char *setpoint) 194fa9e4066Sahrens { 195fa9e4066Sahrens return (dsl_prop_get(ddname, propname, 8, 1, valuep, setpoint)); 196fa9e4066Sahrens } 197fa9e4066Sahrens 198fa9e4066Sahrens int 199fa9e4066Sahrens dsl_prop_get_ds_integer(dsl_dir_t *dd, const char *propname, 200fa9e4066Sahrens uint64_t *valuep, char *setpoint) 201fa9e4066Sahrens { 202fa9e4066Sahrens return (dsl_prop_get_ds(dd, propname, 8, 1, valuep, setpoint)); 203fa9e4066Sahrens } 204fa9e4066Sahrens 205fa9e4066Sahrens /* 206fa9e4066Sahrens * Unregister this callback. Return 0 on success, ENOENT if ddname is 207fa9e4066Sahrens * invalid, ENOMSG if no matching callback registered. 208fa9e4066Sahrens */ 209fa9e4066Sahrens int 210fa9e4066Sahrens dsl_prop_unregister(dsl_dataset_t *ds, const char *propname, 211fa9e4066Sahrens dsl_prop_changed_cb_t *callback, void *cbarg) 212fa9e4066Sahrens { 213*99653d4eSeschrock dsl_dir_t *dd = ds->ds_dir; 214fa9e4066Sahrens dsl_prop_cb_record_t *cbr; 215fa9e4066Sahrens 216fa9e4066Sahrens mutex_enter(&dd->dd_lock); 217fa9e4066Sahrens for (cbr = list_head(&dd->dd_prop_cbs); 218fa9e4066Sahrens cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 219*99653d4eSeschrock if (cbr->cbr_ds == ds && 220fa9e4066Sahrens cbr->cbr_func == callback && 221*99653d4eSeschrock cbr->cbr_arg == cbarg && 222*99653d4eSeschrock strcmp(cbr->cbr_propname, propname) == 0) 223fa9e4066Sahrens break; 224fa9e4066Sahrens } 225fa9e4066Sahrens 226fa9e4066Sahrens if (cbr == NULL) { 227fa9e4066Sahrens mutex_exit(&dd->dd_lock); 228fa9e4066Sahrens return (ENOMSG); 229fa9e4066Sahrens } 230fa9e4066Sahrens 231fa9e4066Sahrens list_remove(&dd->dd_prop_cbs, cbr); 232fa9e4066Sahrens mutex_exit(&dd->dd_lock); 233fa9e4066Sahrens kmem_free((void*)cbr->cbr_propname, strlen(cbr->cbr_propname)+1); 234fa9e4066Sahrens kmem_free(cbr, sizeof (dsl_prop_cb_record_t)); 235fa9e4066Sahrens 236fa9e4066Sahrens /* Clean up from dsl_prop_register */ 237fa9e4066Sahrens dsl_dir_close(dd, cbr); 238fa9e4066Sahrens return (0); 239fa9e4066Sahrens } 240fa9e4066Sahrens 241*99653d4eSeschrock /* 242*99653d4eSeschrock * Return the number of callbacks that are registered for this dataset. 243*99653d4eSeschrock */ 244*99653d4eSeschrock int 245*99653d4eSeschrock dsl_prop_numcb(dsl_dataset_t *ds) 246*99653d4eSeschrock { 247*99653d4eSeschrock dsl_dir_t *dd = ds->ds_dir; 248*99653d4eSeschrock dsl_prop_cb_record_t *cbr; 249*99653d4eSeschrock int num = 0; 250*99653d4eSeschrock 251*99653d4eSeschrock mutex_enter(&dd->dd_lock); 252*99653d4eSeschrock for (cbr = list_head(&dd->dd_prop_cbs); 253*99653d4eSeschrock cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 254*99653d4eSeschrock if (cbr->cbr_ds == ds) 255*99653d4eSeschrock num++; 256*99653d4eSeschrock } 257*99653d4eSeschrock mutex_exit(&dd->dd_lock); 258*99653d4eSeschrock 259*99653d4eSeschrock return (num); 260*99653d4eSeschrock } 261*99653d4eSeschrock 262fa9e4066Sahrens static void 263fa9e4066Sahrens dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, 264fa9e4066Sahrens const char *propname, uint64_t value, int first) 265fa9e4066Sahrens { 266fa9e4066Sahrens dsl_dir_t *dd; 267fa9e4066Sahrens dsl_prop_cb_record_t *cbr; 268fa9e4066Sahrens objset_t *mos = dp->dp_meta_objset; 269fa9e4066Sahrens int err; 270fa9e4066Sahrens 271fa9e4066Sahrens ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock)); 272ea8dc4b6Seschrock err = dsl_dir_open_obj(dp, ddobj, NULL, FTAG, &dd); 273ea8dc4b6Seschrock if (err) 274ea8dc4b6Seschrock return; 275fa9e4066Sahrens 276fa9e4066Sahrens if (!first) { 277fa9e4066Sahrens /* 278fa9e4066Sahrens * If the prop is set here, then this change is not 279fa9e4066Sahrens * being inherited here or below; stop the recursion. 280fa9e4066Sahrens */ 281fa9e4066Sahrens err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, propname, 282fa9e4066Sahrens 8, 1, &value); 283fa9e4066Sahrens if (err == 0) { 284fa9e4066Sahrens dsl_dir_close(dd, FTAG); 285fa9e4066Sahrens return; 286fa9e4066Sahrens } 287fa9e4066Sahrens ASSERT3U(err, ==, ENOENT); 288fa9e4066Sahrens } 289fa9e4066Sahrens 290fa9e4066Sahrens mutex_enter(&dd->dd_lock); 291fa9e4066Sahrens for (cbr = list_head(&dd->dd_prop_cbs); 292fa9e4066Sahrens cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 293fa9e4066Sahrens if (strcmp(cbr->cbr_propname, propname) == 0) { 294fa9e4066Sahrens cbr->cbr_func(cbr->cbr_arg, value); 295fa9e4066Sahrens } 296fa9e4066Sahrens } 297fa9e4066Sahrens mutex_exit(&dd->dd_lock); 298fa9e4066Sahrens 299fa9e4066Sahrens if (dd->dd_phys->dd_child_dir_zapobj) { 300fa9e4066Sahrens zap_cursor_t zc; 301fa9e4066Sahrens zap_attribute_t za; 302fa9e4066Sahrens 303fa9e4066Sahrens for (zap_cursor_init(&zc, mos, 304fa9e4066Sahrens dd->dd_phys->dd_child_dir_zapobj); 305fa9e4066Sahrens zap_cursor_retrieve(&zc, &za) == 0; 306fa9e4066Sahrens zap_cursor_advance(&zc)) { 307fa9e4066Sahrens /* XXX recursion could blow stack; esp. za! */ 308fa9e4066Sahrens dsl_prop_changed_notify(dp, za.za_first_integer, 309fa9e4066Sahrens propname, value, FALSE); 310fa9e4066Sahrens } 31187e5029aSahrens zap_cursor_fini(&zc); 312fa9e4066Sahrens } 313fa9e4066Sahrens dsl_dir_close(dd, FTAG); 314fa9e4066Sahrens } 315fa9e4066Sahrens 316fa9e4066Sahrens struct prop_set_arg { 317fa9e4066Sahrens const char *name; 318fa9e4066Sahrens int intsz; 319fa9e4066Sahrens int numints; 320fa9e4066Sahrens const void *buf; 321fa9e4066Sahrens }; 322fa9e4066Sahrens 323fa9e4066Sahrens static int 324fa9e4066Sahrens dsl_prop_set_sync(dsl_dir_t *dd, void *arg, dmu_tx_t *tx) 325fa9e4066Sahrens { 326fa9e4066Sahrens struct prop_set_arg *psa = arg; 327fa9e4066Sahrens objset_t *mos = dd->dd_pool->dp_meta_objset; 328fa9e4066Sahrens uint64_t zapobj = dd->dd_phys->dd_props_zapobj; 329fa9e4066Sahrens uint64_t intval; 330fa9e4066Sahrens int err, isint; 331fa9e4066Sahrens 332fa9e4066Sahrens rw_enter(&dd->dd_pool->dp_config_rwlock, RW_WRITER); 333fa9e4066Sahrens 334fa9e4066Sahrens isint = (dodefault(psa->name, 8, 1, &intval) == 0); 335fa9e4066Sahrens 336fa9e4066Sahrens if (psa->numints == 0) { 337fa9e4066Sahrens err = zap_remove(mos, zapobj, psa->name, tx); 338fa9e4066Sahrens if (err == ENOENT) /* that's fine. */ 339fa9e4066Sahrens err = 0; 340fa9e4066Sahrens if (err == 0 && isint) { 341*99653d4eSeschrock err = dsl_prop_get_impl(dd->dd_parent, 342*99653d4eSeschrock psa->name, 8, 1, &intval, NULL); 343fa9e4066Sahrens } 344fa9e4066Sahrens } else { 345fa9e4066Sahrens err = zap_update(mos, zapobj, psa->name, 346fa9e4066Sahrens psa->intsz, psa->numints, psa->buf, tx); 347fa9e4066Sahrens if (isint) 348fa9e4066Sahrens intval = *(uint64_t *)psa->buf; 349fa9e4066Sahrens } 350fa9e4066Sahrens 351fa9e4066Sahrens if (err == 0 && isint) { 352fa9e4066Sahrens dsl_prop_changed_notify(dd->dd_pool, 353fa9e4066Sahrens dd->dd_object, psa->name, intval, TRUE); 354fa9e4066Sahrens } 355fa9e4066Sahrens rw_exit(&dd->dd_pool->dp_config_rwlock); 356fa9e4066Sahrens 357fa9e4066Sahrens return (err); 358fa9e4066Sahrens } 359fa9e4066Sahrens 360fa9e4066Sahrens int 361fa9e4066Sahrens dsl_prop_set(const char *ddname, const char *propname, 362fa9e4066Sahrens int intsz, int numints, const void *buf) 363fa9e4066Sahrens { 364fa9e4066Sahrens dsl_dir_t *dd; 365fa9e4066Sahrens int err; 366fa9e4066Sahrens struct prop_set_arg psa; 367fa9e4066Sahrens 368ea8dc4b6Seschrock err = dsl_dir_open(ddname, FTAG, &dd, NULL); 369ea8dc4b6Seschrock if (err) 370ea8dc4b6Seschrock return (err); 371fa9e4066Sahrens 372fa9e4066Sahrens psa.name = propname; 373fa9e4066Sahrens psa.intsz = intsz; 374fa9e4066Sahrens psa.numints = numints; 375fa9e4066Sahrens psa.buf = buf; 376ea8dc4b6Seschrock err = dsl_dir_sync_task(dd, dsl_prop_set_sync, &psa, 1<<20); 377fa9e4066Sahrens 378fa9e4066Sahrens dsl_dir_close(dd, FTAG); 379fa9e4066Sahrens 380fa9e4066Sahrens return (err); 381fa9e4066Sahrens } 3827f7322feSeschrock 3837f7322feSeschrock /* 3847f7322feSeschrock * Iterate over all properties for this dataset and return them in an nvlist. 3857f7322feSeschrock */ 3867f7322feSeschrock int 3877f7322feSeschrock dsl_prop_get_all(objset_t *os, nvlist_t **nvp) 3887f7322feSeschrock { 3897f7322feSeschrock dsl_dataset_t *ds = os->os->os_dsl_dataset; 390*99653d4eSeschrock dsl_dir_t *dd = ds->ds_dir; 3917f7322feSeschrock int err = 0; 3927f7322feSeschrock dsl_pool_t *dp; 3937f7322feSeschrock objset_t *mos; 3947f7322feSeschrock zap_cursor_t zc; 3957f7322feSeschrock zap_attribute_t za; 3967f7322feSeschrock char setpoint[MAXNAMELEN]; 3977f7322feSeschrock char *tmp; 3987f7322feSeschrock nvlist_t *prop; 3997f7322feSeschrock 4007f7322feSeschrock if (dsl_dataset_is_snapshot(ds)) { 4017f7322feSeschrock VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 4027f7322feSeschrock return (0); 4037f7322feSeschrock } 4047f7322feSeschrock 4057f7322feSeschrock VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 4067f7322feSeschrock 4077f7322feSeschrock dp = dd->dd_pool; 4087f7322feSeschrock mos = dp->dp_meta_objset; 4097f7322feSeschrock 4107f7322feSeschrock rw_enter(&dp->dp_config_rwlock, RW_READER); 411*99653d4eSeschrock for (; dd != NULL; dd = dd->dd_parent) { 4127f7322feSeschrock dsl_dir_name(dd, setpoint); 4137f7322feSeschrock 4147f7322feSeschrock for (zap_cursor_init(&zc, mos, dd->dd_phys->dd_props_zapobj); 4157f7322feSeschrock (err = zap_cursor_retrieve(&zc, &za)) == 0; 4167f7322feSeschrock zap_cursor_advance(&zc)) { 4177f7322feSeschrock if (nvlist_lookup_nvlist(*nvp, za.za_name, &prop) == 0) 4187f7322feSeschrock continue; 4197f7322feSeschrock 4207f7322feSeschrock VERIFY(nvlist_alloc(&prop, NV_UNIQUE_NAME, 4217f7322feSeschrock KM_SLEEP) == 0); 4227f7322feSeschrock if (za.za_integer_length == 1) { 4237f7322feSeschrock /* 4247f7322feSeschrock * String property 4257f7322feSeschrock */ 4267f7322feSeschrock tmp = kmem_alloc(za.za_num_integers, KM_SLEEP); 4277f7322feSeschrock err = zap_lookup(mos, 4287f7322feSeschrock dd->dd_phys->dd_props_zapobj, 4297f7322feSeschrock za.za_name, 1, za.za_num_integers, 4307f7322feSeschrock tmp); 4317f7322feSeschrock if (err != 0) { 4327f7322feSeschrock kmem_free(tmp, za.za_num_integers); 4337f7322feSeschrock break; 4347f7322feSeschrock } 4357f7322feSeschrock VERIFY(nvlist_add_string(prop, 4367f7322feSeschrock ZFS_PROP_VALUE, tmp) == 0); 4377f7322feSeschrock kmem_free(tmp, za.za_num_integers); 4387f7322feSeschrock } else { 4397f7322feSeschrock /* 4407f7322feSeschrock * Integer property 4417f7322feSeschrock */ 4427f7322feSeschrock ASSERT(za.za_integer_length == 8); 4437f7322feSeschrock (void) nvlist_add_uint64(prop, ZFS_PROP_VALUE, 4447f7322feSeschrock za.za_first_integer); 4457f7322feSeschrock } 4467f7322feSeschrock 4477f7322feSeschrock VERIFY(nvlist_add_string(prop, 4487f7322feSeschrock ZFS_PROP_SOURCE, setpoint) == 0); 4497f7322feSeschrock VERIFY(nvlist_add_nvlist(*nvp, za.za_name, 4507f7322feSeschrock prop) == 0); 4517f7322feSeschrock nvlist_free(prop); 4527f7322feSeschrock } 4537f7322feSeschrock zap_cursor_fini(&zc); 4547f7322feSeschrock 455*99653d4eSeschrock if (err != ENOENT) 4567f7322feSeschrock break; 457*99653d4eSeschrock err = 0; 4587f7322feSeschrock } 4597f7322feSeschrock rw_exit(&dp->dp_config_rwlock); 4607f7322feSeschrock 4617f7322feSeschrock return (err); 4627f7322feSeschrock } 463