1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  24  * Copyright (c) 2013 Martin Matuska. All rights reserved.
  25  * Copyright 2015, Joyent, Inc.
  26  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  27  */
  28 
  29 #include <sys/zfs_context.h>
  30 #include <sys/dmu.h>
  31 #include <sys/dmu_objset.h>
  32 #include <sys/dmu_tx.h>
  33 #include <sys/dsl_dataset.h>
  34 #include <sys/dsl_dir.h>
  35 #include <sys/dsl_prop.h>
  36 #include <sys/dsl_synctask.h>
  37 #include <sys/zfeature.h>
  38 #include <sys/spa.h>
  39 #include <sys/zap.h>
  40 #include <sys/fs/zfs.h>
  41 #include <sys/wbc.h>
  42 
  43 #include "zfs_prop.h"
  44 #include "zfs_errno.h"
  45 
  46 static int
  47 dodefault(zfs_prop_t prop, int intsz, int numints, void *buf)
  48 {
  49         /*
  50          * The setonce properties are read-only, BUT they still
  51          * have a default value that can be used as the initial
  52          * value.
  53          */
  54         if (prop == ZPROP_INVAL ||
  55             (zfs_prop_readonly(prop) && !zfs_prop_setonce(prop)))
  56                 return (SET_ERROR(ENOENT));
  57 
  58         if (zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
  59                 if (intsz != 1)
  60                         return (SET_ERROR(EOVERFLOW));
  61                 (void) strncpy(buf, zfs_prop_default_string(prop),
  62                     numints);
  63         } else {
  64                 if (intsz != 8 || numints < 1)
  65                         return (SET_ERROR(EOVERFLOW));
  66 
  67                 *(uint64_t *)buf = zfs_prop_default_numeric(prop);
  68         }
  69 
  70         return (0);
  71 }
  72 
  73 int
  74 dsl_prop_get_dd(dsl_dir_t *dd, const char *propname,
  75     int intsz, int numints, void *buf, char *setpoint, boolean_t snapshot)
  76 {
  77         int err = ENOENT;
  78         dsl_dir_t *target = dd;
  79         objset_t *mos = dd->dd_pool->dp_meta_objset;
  80         zfs_prop_t prop;
  81         boolean_t inheritable;
  82         boolean_t inheriting = B_FALSE;
  83         char *inheritstr;
  84         char *recvdstr;
  85 
  86         ASSERT(dsl_pool_config_held(dd->dd_pool));
  87 
  88         if (setpoint)
  89                 setpoint[0] = '\0';
  90 
  91         prop = zfs_name_to_prop(propname);
  92         inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop));
  93         inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX);
  94         recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX);
  95 
  96         /*
  97          * Note: dd may become NULL, therefore we shouldn't dereference it
  98          * after this loop.
  99          */
 100         for (; dd != NULL; dd = dd->dd_parent) {
 101                 if (dd != target || snapshot) {
 102                         if (!inheritable)
 103                                 break;
 104                         inheriting = B_TRUE;
 105                 }
 106 
 107                 /* Check for a local value. */
 108                 err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj,
 109                     propname, intsz, numints, buf);
 110                 if (err != ENOENT) {
 111                         if (setpoint != NULL && err == 0)
 112                                 dsl_dir_name(dd, setpoint);
 113                         break;
 114                 }
 115 
 116                 /*
 117                  * Skip the check for a received value if there is an explicit
 118                  * inheritance entry.
 119                  */
 120                 err = zap_contains(mos, dsl_dir_phys(dd)->dd_props_zapobj,
 121                     inheritstr);
 122                 if (err != 0 && err != ENOENT)
 123                         break;
 124 
 125                 if (err == ENOENT) {
 126                         /* Check for a received value. */
 127                         err = zap_lookup(mos, dsl_dir_phys(dd)->dd_props_zapobj,
 128                             recvdstr, intsz, numints, buf);
 129                         if (err != ENOENT) {
 130                                 if (setpoint != NULL && err == 0) {
 131                                         if (inheriting) {
 132                                                 dsl_dir_name(dd, setpoint);
 133                                         } else {
 134                                                 (void) strcpy(setpoint,
 135                                                     ZPROP_SOURCE_VAL_RECVD);
 136                                         }
 137                                 }
 138                                 break;
 139                         }
 140                 }
 141 
 142                 /*
 143                  * If we found an explicit inheritance entry, err is zero even
 144                  * though we haven't yet found the value, so reinitializing err
 145                  * at the end of the loop (instead of at the beginning) ensures
 146                  * that err has a valid post-loop value.
 147                  */
 148                 err = SET_ERROR(ENOENT);
 149         }
 150 
 151         if (err == ENOENT)
 152                 err = dodefault(prop, intsz, numints, buf);
 153 
 154         strfree(inheritstr);
 155         strfree(recvdstr);
 156 
 157         return (err);
 158 }
 159 
 160 int
 161 dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname,
 162     int intsz, int numints, void *buf, char *setpoint)
 163 {
 164         zfs_prop_t prop = zfs_name_to_prop(propname);
 165         boolean_t inheritable;
 166         uint64_t zapobj;
 167 
 168         ASSERT(dsl_pool_config_held(ds->ds_dir->dd_pool));
 169         inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop));
 170         zapobj = dsl_dataset_phys(ds)->ds_props_obj;
 171 
 172         if (zapobj != 0) {
 173                 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
 174                 int err;
 175 
 176                 ASSERT(ds->ds_is_snapshot);
 177 
 178                 /* Check for a local value. */
 179                 err = zap_lookup(mos, zapobj, propname, intsz, numints, buf);
 180                 if (err != ENOENT) {
 181                         if (setpoint != NULL && err == 0)
 182                                 dsl_dataset_name(ds, setpoint);
 183                         return (err);
 184                 }
 185 
 186                 /*
 187                  * Skip the check for a received value if there is an explicit
 188                  * inheritance entry.
 189                  */
 190                 if (inheritable) {
 191                         char *inheritstr = kmem_asprintf("%s%s", propname,
 192                             ZPROP_INHERIT_SUFFIX);
 193                         err = zap_contains(mos, zapobj, inheritstr);
 194                         strfree(inheritstr);
 195                         if (err != 0 && err != ENOENT)
 196                                 return (err);
 197                 }
 198 
 199                 if (err == ENOENT) {
 200                         /* Check for a received value. */
 201                         char *recvdstr = kmem_asprintf("%s%s", propname,
 202                             ZPROP_RECVD_SUFFIX);
 203                         err = zap_lookup(mos, zapobj, recvdstr,
 204                             intsz, numints, buf);
 205                         strfree(recvdstr);
 206                         if (err != ENOENT) {
 207                                 if (setpoint != NULL && err == 0)
 208                                         (void) strcpy(setpoint,
 209                                             ZPROP_SOURCE_VAL_RECVD);
 210                                 return (err);
 211                         }
 212                 }
 213         }
 214 
 215         return (dsl_prop_get_dd(ds->ds_dir, propname,
 216             intsz, numints, buf, setpoint, ds->ds_is_snapshot));
 217 }
 218 
 219 static dsl_prop_record_t *
 220 dsl_prop_record_find(dsl_dir_t *dd, const char *propname)
 221 {
 222         dsl_prop_record_t *pr = NULL;
 223 
 224         ASSERT(MUTEX_HELD(&dd->dd_lock));
 225 
 226         for (pr = list_head(&dd->dd_props);
 227             pr != NULL; pr = list_next(&dd->dd_props, pr)) {
 228                 if (strcmp(pr->pr_propname, propname) == 0)
 229                         break;
 230         }
 231 
 232         return (pr);
 233 }
 234 
 235 static dsl_prop_record_t *
 236 dsl_prop_record_create(dsl_dir_t *dd, const char *propname)
 237 {
 238         dsl_prop_record_t *pr;
 239 
 240         ASSERT(MUTEX_HELD(&dd->dd_lock));
 241 
 242         pr = kmem_alloc(sizeof (dsl_prop_record_t), KM_SLEEP);
 243         pr->pr_propname = spa_strdup(propname);
 244         list_create(&pr->pr_cbs, sizeof (dsl_prop_cb_record_t),
 245             offsetof(dsl_prop_cb_record_t, cbr_pr_node));
 246         list_insert_head(&dd->dd_props, pr);
 247 
 248         return (pr);
 249 }
 250 
 251 void
 252 dsl_prop_init(dsl_dir_t *dd)
 253 {
 254         list_create(&dd->dd_props, sizeof (dsl_prop_record_t),
 255             offsetof(dsl_prop_record_t, pr_node));
 256 }
 257 
 258 void
 259 dsl_prop_fini(dsl_dir_t *dd)
 260 {
 261         dsl_prop_record_t *pr;
 262 
 263         while ((pr = list_remove_head(&dd->dd_props)) != NULL) {
 264                 list_destroy(&pr->pr_cbs);
 265                 strfree((char *)pr->pr_propname);
 266                 kmem_free(pr, sizeof (dsl_prop_record_t));
 267         }
 268         list_destroy(&dd->dd_props);
 269 }
 270 
 271 /*
 272  * Register interest in the named property.  We'll call the callback
 273  * once to notify it of the current property value, and again each time
 274  * the property changes, until this callback is unregistered.
 275  *
 276  * Return 0 on success, errno if the prop is not an integer value.
 277  */
 278 int
 279 dsl_prop_register(dsl_dataset_t *ds, const char *propname,
 280     dsl_prop_changed_cb_t *callback, void *cbarg)
 281 {
 282         dsl_dir_t *dd = ds->ds_dir;
 283         dsl_pool_t *dp = dd->dd_pool;
 284         uint64_t value;
 285         dsl_prop_record_t *pr;
 286         dsl_prop_cb_record_t *cbr;
 287         int err;
 288 
 289         ASSERT(dsl_pool_config_held(dp));
 290 
 291         if (zfs_name_to_prop(propname) == ZFS_PROP_WBC_MODE) {
 292                 wbc_mode_prop_val_t val;
 293 
 294                 err = dsl_prop_get_ds(ds, propname, 8,
 295                     WBC_MODE_PROP_VAL_SZ, &val, NULL);
 296                 if (err == 0)
 297                         value = (uintptr_t)((void *)&val);
 298         } else
 299                 err = dsl_prop_get_int_ds(ds, propname, &value);
 300 
 301         if (err != 0)
 302                 return (err);
 303 
 304         cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP);
 305         cbr->cbr_ds = ds;
 306         cbr->cbr_func = callback;
 307         cbr->cbr_arg = cbarg;
 308 
 309         mutex_enter(&dd->dd_lock);
 310         pr = dsl_prop_record_find(dd, propname);
 311         if (pr == NULL)
 312                 pr = dsl_prop_record_create(dd, propname);
 313         cbr->cbr_pr = pr;
 314         list_insert_head(&pr->pr_cbs, cbr);
 315         list_insert_head(&ds->ds_prop_cbs, cbr);
 316         mutex_exit(&dd->dd_lock);
 317 
 318         cbr->cbr_func(cbr->cbr_arg, value);
 319         return (0);
 320 }
 321 
 322 int
 323 dsl_prop_get(const char *dsname, const char *propname,
 324     int intsz, int numints, void *buf, char *setpoint)
 325 {
 326         objset_t *os;
 327         int error;
 328 
 329         error = dmu_objset_hold(dsname, FTAG, &os);
 330         if (error != 0)
 331                 return (error);
 332 
 333         error = dsl_prop_get_ds(dmu_objset_ds(os), propname,
 334             intsz, numints, buf, setpoint);
 335 
 336         dmu_objset_rele(os, FTAG);
 337         return (error);
 338 }
 339 
 340 /*
 341  * Get the current property value.  It may have changed by the time this
 342  * function returns, so it is NOT safe to follow up with
 343  * dsl_prop_register() and assume that the value has not changed in
 344  * between.
 345  *
 346  * Return 0 on success, ENOENT if ddname is invalid.
 347  */
 348 int
 349 dsl_prop_get_integer(const char *ddname, const char *propname,
 350     uint64_t *valuep, char *setpoint)
 351 {
 352         return (dsl_prop_get(ddname, propname, 8, 1, valuep, setpoint));
 353 }
 354 
 355 int
 356 dsl_prop_get_int_ds(dsl_dataset_t *ds, const char *propname,
 357     uint64_t *valuep)
 358 {
 359         return (dsl_prop_get_ds(ds, propname, 8, 1, valuep, NULL));
 360 }
 361 
 362 /*
 363  * Predict the effective value of the given special property if it were set with
 364  * the given value and source. This is not a general purpose function. It exists
 365  * only to handle the special requirements of the quota and reservation
 366  * properties. The fact that these properties are non-inheritable greatly
 367  * simplifies the prediction logic.
 368  *
 369  * Returns 0 on success, a positive error code on failure, or -1 if called with
 370  * a property not handled by this function.
 371  */
 372 int
 373 dsl_prop_predict(dsl_dir_t *dd, const char *propname,
 374     zprop_source_t source, uint64_t value, uint64_t *newvalp)
 375 {
 376         zfs_prop_t prop = zfs_name_to_prop(propname);
 377         objset_t *mos;
 378         uint64_t zapobj;
 379         uint64_t version;
 380         char *recvdstr;
 381         int err = 0;
 382 
 383         switch (prop) {
 384         case ZFS_PROP_QUOTA:
 385         case ZFS_PROP_RESERVATION:
 386         case ZFS_PROP_REFQUOTA:
 387         case ZFS_PROP_REFRESERVATION:
 388                 break;
 389         default:
 390                 return (-1);
 391         }
 392 
 393         mos = dd->dd_pool->dp_meta_objset;
 394         zapobj = dsl_dir_phys(dd)->dd_props_zapobj;
 395         recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX);
 396 
 397         version = spa_version(dd->dd_pool->dp_spa);
 398         if (version < SPA_VERSION_RECVD_PROPS) {
 399                 if (source & ZPROP_SRC_NONE)
 400                         source = ZPROP_SRC_NONE;
 401                 else if (source & ZPROP_SRC_RECEIVED)
 402                         source = ZPROP_SRC_LOCAL;
 403         }
 404 
 405         switch (source) {
 406         case ZPROP_SRC_NONE:
 407                 /* Revert to the received value, if any. */
 408                 err = zap_lookup(mos, zapobj, recvdstr, 8, 1, newvalp);
 409                 if (err == ENOENT)
 410                         *newvalp = 0;
 411                 break;
 412         case ZPROP_SRC_LOCAL:
 413                 *newvalp = value;
 414                 break;
 415         case ZPROP_SRC_RECEIVED:
 416                 /*
 417                  * If there's no local setting, then the new received value will
 418                  * be the effective value.
 419                  */
 420                 err = zap_lookup(mos, zapobj, propname, 8, 1, newvalp);
 421                 if (err == ENOENT)
 422                         *newvalp = value;
 423                 break;
 424         case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED):
 425                 /*
 426                  * We're clearing the received value, so the local setting (if
 427                  * it exists) remains the effective value.
 428                  */
 429                 err = zap_lookup(mos, zapobj, propname, 8, 1, newvalp);
 430                 if (err == ENOENT)
 431                         *newvalp = 0;
 432                 break;
 433         default:
 434                 panic("unexpected property source: %d", source);
 435         }
 436 
 437         strfree(recvdstr);
 438 
 439         if (err == ENOENT)
 440                 return (0);
 441 
 442         return (err);
 443 }
 444 
 445 /*
 446  * Unregister all callbacks that are registered with the
 447  * given callback argument.
 448  */
 449 void
 450 dsl_prop_unregister_all(dsl_dataset_t *ds, void *cbarg)
 451 {
 452         dsl_prop_cb_record_t *cbr, *next_cbr;
 453 
 454         dsl_dir_t *dd = ds->ds_dir;
 455 
 456         mutex_enter(&dd->dd_lock);
 457         next_cbr = list_head(&ds->ds_prop_cbs);
 458         while (next_cbr != NULL) {
 459                 cbr = next_cbr;
 460                 next_cbr = list_next(&ds->ds_prop_cbs, cbr);
 461                 if (cbr->cbr_arg == cbarg) {
 462                         list_remove(&ds->ds_prop_cbs, cbr);
 463                         list_remove(&cbr->cbr_pr->pr_cbs, cbr);
 464                         kmem_free(cbr, sizeof (dsl_prop_cb_record_t));
 465                 }
 466         }
 467         mutex_exit(&dd->dd_lock);
 468 }
 469 
 470 boolean_t
 471 dsl_prop_hascb(dsl_dataset_t *ds)
 472 {
 473         return (!list_is_empty(&ds->ds_prop_cbs));
 474 }
 475 
 476 /* ARGSUSED */
 477 static int
 478 dsl_prop_notify_all_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
 479 {
 480         dsl_dir_t *dd = ds->ds_dir;
 481         dsl_prop_record_t *pr;
 482         dsl_prop_cb_record_t *cbr;
 483 
 484         mutex_enter(&dd->dd_lock);
 485         for (pr = list_head(&dd->dd_props);
 486             pr; pr = list_next(&dd->dd_props, pr)) {
 487                 for (cbr = list_head(&pr->pr_cbs); cbr;
 488                     cbr = list_next(&pr->pr_cbs, cbr)) {
 489                         uint64_t value;
 490                         const char *propname;
 491 
 492                         /*
 493                          * Callback entries do not have holds on their
 494                          * datasets so that datasets with registered
 495                          * callbacks are still eligible for eviction.
 496                          * Unlike operations to update properties on a
 497                          * single dataset, we are performing a recursive
 498                          * descent of related head datasets.  The caller
 499                          * of this function only has a dataset hold on
 500                          * the passed in head dataset, not the snapshots
 501                          * associated with this dataset.  Without a hold,
 502                          * the dataset pointer within callback records
 503                          * for snapshots can be invalidated by eviction
 504                          * at any time.
 505                          *
 506                          * Use dsl_dataset_try_add_ref() to verify
 507                          * that the dataset for a snapshot has not
 508                          * begun eviction processing and to prevent
 509                          * eviction from occurring for the duration of
 510                          * the callback.  If the hold attempt fails,
 511                          * this object is already being evicted and the
 512                          * callback can be safely ignored.
 513                          */
 514                         if (ds != cbr->cbr_ds &&
 515                             !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG))
 516                                 continue;
 517 
 518                         propname = cbr->cbr_pr->pr_propname;
 519                         if (zfs_name_to_prop(propname) == ZFS_PROP_WBC_MODE) {
 520                                 wbc_mode_prop_val_t val;
 521 
 522                                 if (dsl_prop_get_ds(cbr->cbr_ds, propname, 8,
 523                                     WBC_MODE_PROP_VAL_SZ, &val, NULL) == 0) {
 524                                         value = (uintptr_t)((void *)&val);
 525                                         cbr->cbr_func(cbr->cbr_arg, value);
 526                                 }
 527                         } else if (dsl_prop_get_ds(cbr->cbr_ds, propname,
 528                             sizeof (value), 1, &value, NULL) == 0) {
 529                                 cbr->cbr_func(cbr->cbr_arg, value);
 530                         }
 531 
 532                         if (ds != cbr->cbr_ds)
 533                                 dsl_dataset_rele(cbr->cbr_ds, FTAG);
 534                 }
 535         }
 536         mutex_exit(&dd->dd_lock);
 537 
 538         return (0);
 539 }
 540 
 541 /*
 542  * Update all property values for ddobj & its descendants.  This is used
 543  * when renaming the dir.
 544  */
 545 void
 546 dsl_prop_notify_all(dsl_dir_t *dd)
 547 {
 548         dsl_pool_t *dp = dd->dd_pool;
 549         ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
 550         (void) dmu_objset_find_dp(dp, dd->dd_object, dsl_prop_notify_all_cb,
 551             NULL, DS_FIND_CHILDREN);
 552 }
 553 
 554 static void
 555 dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj,
 556     const char *propname, uint64_t value, int first)
 557 {
 558         dsl_dir_t *dd;
 559         dsl_prop_record_t *pr;
 560         dsl_prop_cb_record_t *cbr;
 561         objset_t *mos = dp->dp_meta_objset;
 562         zap_cursor_t zc;
 563         zap_attribute_t *za;
 564         int err;
 565 
 566         ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
 567         err = dsl_dir_hold_obj(dp, ddobj, NULL, FTAG, &dd);
 568         if (err)
 569                 return;
 570 
 571         if (!first) {
 572                 /*
 573                  * If the prop is set here, then this change is not
 574                  * being inherited here or below; stop the recursion.
 575                  */
 576                 err = zap_contains(mos, dsl_dir_phys(dd)->dd_props_zapobj,
 577                     propname);
 578                 if (err == 0) {
 579                         dsl_dir_rele(dd, FTAG);
 580                         return;
 581                 }
 582                 ASSERT3U(err, ==, ENOENT);
 583         }
 584 
 585         mutex_enter(&dd->dd_lock);
 586         pr = dsl_prop_record_find(dd, propname);
 587         if (pr != NULL) {
 588                 for (cbr = list_head(&pr->pr_cbs); cbr;
 589                     cbr = list_next(&pr->pr_cbs, cbr)) {
 590                         uint64_t propobj;
 591 
 592                         /*
 593                          * cbr->cbr_ds may be invalidated due to eviction,
 594                          * requiring the use of dsl_dataset_try_add_ref().
 595                          * See comment block in dsl_prop_notify_all_cb()
 596                          * for details.
 597                          */
 598                         if (!dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG))
 599                                 continue;
 600 
 601                         propobj = dsl_dataset_phys(cbr->cbr_ds)->ds_props_obj;
 602 
 603                         /*
 604                          * If the property is not set on this ds, then it is
 605                          * inherited here; call the callback.
 606                          */
 607                         if (propobj == 0 ||
 608                             zap_contains(mos, propobj, propname) != 0)
 609                                 cbr->cbr_func(cbr->cbr_arg, value);
 610 
 611                         dsl_dataset_rele(cbr->cbr_ds, FTAG);
 612                 }
 613         }
 614         mutex_exit(&dd->dd_lock);
 615 
 616         za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP);
 617         for (zap_cursor_init(&zc, mos,
 618             dsl_dir_phys(dd)->dd_child_dir_zapobj);
 619             zap_cursor_retrieve(&zc, za) == 0;
 620             zap_cursor_advance(&zc)) {
 621                 dsl_prop_changed_notify(dp, za->za_first_integer,
 622                     propname, value, FALSE);
 623         }
 624         kmem_free(za, sizeof (zap_attribute_t));
 625         zap_cursor_fini(&zc);
 626         dsl_dir_rele(dd, FTAG);
 627 }
 628 
 629 void
 630 dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname,
 631     zprop_source_t source, int intsz, int numints, const void *value,
 632     dmu_tx_t *tx)
 633 {
 634         objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
 635         uint64_t zapobj, intval, dummy;
 636         int isint;
 637         char valbuf[32];
 638         const char *valstr = NULL;
 639         char *inheritstr;
 640         char *recvdstr;
 641         char *tbuf = NULL;
 642         int err;
 643         spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
 644         uint64_t version = spa_version(spa);
 645 
 646         isint = (dodefault(zfs_name_to_prop(propname), 8, 1, &intval) == 0);
 647 
 648         if (ds->ds_is_snapshot) {
 649                 ASSERT(version >= SPA_VERSION_SNAP_PROPS);
 650                 if (dsl_dataset_phys(ds)->ds_props_obj == 0) {
 651                         dmu_buf_will_dirty(ds->ds_dbuf, tx);
 652                         dsl_dataset_phys(ds)->ds_props_obj =
 653                             zap_create(mos,
 654                             DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx);
 655                 }
 656                 zapobj = dsl_dataset_phys(ds)->ds_props_obj;
 657         } else {
 658                 zapobj = dsl_dir_phys(ds->ds_dir)->dd_props_zapobj;
 659         }
 660 
 661         if (version < SPA_VERSION_RECVD_PROPS) {
 662                 if (source & ZPROP_SRC_NONE)
 663                         source = ZPROP_SRC_NONE;
 664                 else if (source & ZPROP_SRC_RECEIVED)
 665                         source = ZPROP_SRC_LOCAL;
 666         }
 667 
 668         inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX);
 669         recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX);
 670 
 671         switch (source) {
 672         case ZPROP_SRC_NONE:
 673                 /*
 674                  * revert to received value, if any (inherit -S)
 675                  * - remove propname
 676                  * - remove propname$inherit
 677                  */
 678                 err = zap_remove(mos, zapobj, propname, tx);
 679                 ASSERT(err == 0 || err == ENOENT);
 680                 err = zap_remove(mos, zapobj, inheritstr, tx);
 681                 ASSERT(err == 0 || err == ENOENT);
 682                 break;
 683         case ZPROP_SRC_LOCAL:
 684                 /*
 685                  * remove propname$inherit
 686                  * set propname -> value
 687                  */
 688                 err = zap_remove(mos, zapobj, inheritstr, tx);
 689                 ASSERT(err == 0 || err == ENOENT);
 690                 VERIFY0(zap_update(mos, zapobj, propname,
 691                     intsz, numints, value, tx));
 692                 break;
 693         case ZPROP_SRC_INHERITED:
 694                 /*
 695                  * explicitly inherit
 696                  * - remove propname
 697                  * - set propname$inherit
 698                  */
 699                 err = zap_remove(mos, zapobj, propname, tx);
 700                 ASSERT(err == 0 || err == ENOENT);
 701                 if (version >= SPA_VERSION_RECVD_PROPS &&
 702                     dsl_prop_get_int_ds(ds, ZPROP_HAS_RECVD, &dummy) == 0) {
 703                         dummy = 0;
 704                         VERIFY0(zap_update(mos, zapobj, inheritstr,
 705                             8, 1, &dummy, tx));
 706                 }
 707                 break;
 708         case ZPROP_SRC_RECEIVED:
 709                 /*
 710                  * set propname$recvd -> value
 711                  */
 712                 err = zap_update(mos, zapobj, recvdstr,
 713                     intsz, numints, value, tx);
 714                 ASSERT(err == 0);
 715                 break;
 716         case (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED):
 717                 /*
 718                  * clear local and received settings
 719                  * - remove propname
 720                  * - remove propname$inherit
 721                  * - remove propname$recvd
 722                  */
 723                 err = zap_remove(mos, zapobj, propname, tx);
 724                 ASSERT(err == 0 || err == ENOENT);
 725                 err = zap_remove(mos, zapobj, inheritstr, tx);
 726                 ASSERT(err == 0 || err == ENOENT);
 727                 /* FALLTHRU */
 728         case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED):
 729                 /*
 730                  * remove propname$recvd
 731                  */
 732                 err = zap_remove(mos, zapobj, recvdstr, tx);
 733                 ASSERT(err == 0 || err == ENOENT);
 734                 break;
 735         default:
 736                 cmn_err(CE_PANIC, "unexpected property source: %d", source);
 737         }
 738 
 739         strfree(inheritstr);
 740         strfree(recvdstr);
 741 
 742         if (zfs_name_to_prop(propname) == ZFS_PROP_WBC_MODE) {
 743                 wbc_mode_prop_val_t val;
 744 
 745                 VERIFY0(dsl_prop_get_ds(ds, propname, 8,
 746                     WBC_MODE_PROP_VAL_SZ, &val, NULL));
 747 
 748                 dsl_prop_changed_notify(ds->ds_dir->dd_pool,
 749                     ds->ds_dir->dd_object, propname,
 750                     (uintptr_t)((void *)&val), TRUE);
 751 
 752                 /*
 753                  * Flow diagram of ZFS_PROP_WBC_MODE states
 754                  *
 755                  * off (root_ds_object == 0, txg_off == 0)
 756                  *      (user sees wbc_mode=off, source=default)
 757                  *
 758                  *      user operation "set on" ==>>
 759                  *
 760                  * on (root_ds_object != 0, txg_off == 0)
 761                  *      (user sees wbc_mode=on, source=local)
 762                  *
 763                  *      user operation "set off" ==>>
 764                  *
 765                  * off_delayed (root_ds_object != 0, txg_off != 0)
 766                  *      (user sees wbc_mode=off, source=local)
 767                  *
 768                  *      internal operation "inherit" ==>>
 769                  *
 770                  * off (root_ds_object == 0, txg_off == 0)
 771                  *      (user sees wbc_mode=off, source=default)
 772                  */
 773                 if (val.root_ds_object == 0)
 774                         spa_feature_decr(spa, SPA_FEATURE_WBC, tx);
 775                 else if (val.txg_off == 0)
 776                         spa_feature_incr(spa, SPA_FEATURE_WBC, tx);
 777 
 778                 (void) snprintf(valbuf, sizeof (valbuf),
 779                     "%s", (val.root_ds_object != 0 &&
 780                     val.txg_off == 0) ? "on" : "off");
 781                 valstr = valbuf;
 782         } else if (isint) {
 783                 VERIFY0(dsl_prop_get_int_ds(ds, propname, &intval));
 784 
 785                 if (ds->ds_is_snapshot) {
 786                         dsl_prop_cb_record_t *cbr;
 787                         /*
 788                          * It's a snapshot; nothing can inherit this
 789                          * property, so just look for callbacks on this
 790                          * ds here.
 791                          */
 792                         mutex_enter(&ds->ds_dir->dd_lock);
 793                         for (cbr = list_head(&ds->ds_prop_cbs); cbr;
 794                             cbr = list_next(&ds->ds_prop_cbs, cbr)) {
 795                                 if (strcmp(cbr->cbr_pr->pr_propname,
 796                                     propname) == 0)
 797                                         cbr->cbr_func(cbr->cbr_arg, intval);
 798                         }
 799                         mutex_exit(&ds->ds_dir->dd_lock);
 800                 } else {
 801                         dsl_prop_changed_notify(ds->ds_dir->dd_pool,
 802                             ds->ds_dir->dd_object, propname, intval, TRUE);
 803                 }
 804 
 805                 (void) snprintf(valbuf, sizeof (valbuf),
 806                     "%lld", (longlong_t)intval);
 807                 valstr = valbuf;
 808         } else {
 809                 if (source == ZPROP_SRC_LOCAL) {
 810                         valstr = value;
 811                 } else {
 812                         tbuf = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP);
 813                         if (dsl_prop_get_ds(ds, propname, 1,
 814                             ZAP_MAXVALUELEN, tbuf, NULL) == 0)
 815                                 valstr = tbuf;
 816                 }
 817         }
 818 
 819         spa_history_log_internal_ds(ds, (source == ZPROP_SRC_NONE ||
 820             source == ZPROP_SRC_INHERITED) ? "inherit" : "set", tx,
 821             "%s=%s", propname, (valstr == NULL ? "" : valstr));
 822 
 823         if (tbuf != NULL)
 824                 kmem_free(tbuf, ZAP_MAXVALUELEN);
 825 }
 826 
 827 int
 828 dsl_prop_set_int(const char *dsname, const char *propname,
 829     zprop_source_t source, uint64_t value)
 830 {
 831         nvlist_t *nvl = fnvlist_alloc();
 832         int error;
 833 
 834         fnvlist_add_uint64(nvl, propname, value);
 835         error = dsl_props_set(dsname, source, nvl);
 836         fnvlist_free(nvl);
 837         return (error);
 838 }
 839 
 840 int
 841 dsl_prop_set_string(const char *dsname, const char *propname,
 842     zprop_source_t source, const char *value)
 843 {
 844         nvlist_t *nvl = fnvlist_alloc();
 845         int error;
 846 
 847         fnvlist_add_string(nvl, propname, value);
 848         error = dsl_props_set(dsname, source, nvl);
 849         fnvlist_free(nvl);
 850         return (error);
 851 }
 852 
 853 int
 854 dsl_prop_inherit(const char *dsname, const char *propname,
 855     zprop_source_t source)
 856 {
 857         nvlist_t *nvl = fnvlist_alloc();
 858         int error;
 859 
 860         fnvlist_add_boolean(nvl, propname);
 861         error = dsl_props_set(dsname, source, nvl);
 862         fnvlist_free(nvl);
 863         return (error);
 864 }
 865 
 866 /* ARGSUSED */
 867 static int
 868 dsl_prop_wbc_mode_check_child_cb(dsl_pool_t *dp,
 869     dsl_dataset_t *ds, void *arg)
 870 {
 871         int err;
 872         zfs_prop_t *prop = arg;
 873         objset_t *os = NULL;
 874 
 875         err = dmu_objset_from_ds(ds, &os);
 876         if (err != 0)
 877                 return (err);
 878 
 879         if (*prop == ZFS_PROP_DEDUP) {
 880                 /*
 881                  * User tries to set ZFS_PROP_DEDUP.
 882                  * In this case we just check that
 883                  * the target DS and its children
 884                  * do not use writecache
 885                  */
 886                 if (os->os_wbc_mode != ZFS_WBC_MODE_OFF)
 887                         return (SET_ERROR(EKZFS_WBCCONFLICT));
 888         } else {
 889                 ASSERT3U(*prop, ==, ZFS_PROP_WBC_MODE);
 890 
 891                 /*
 892                  * User tries to set ZFS_PROP_WBC_MODE.
 893                  * In this case we need check that
 894                  * the target DS and its children
 895                  * do not use writecache and dedup
 896                  */
 897                 if (os->os_wbc_mode != ZFS_WBC_MODE_OFF)
 898                         return (SET_ERROR(EKZFS_WBCCHILD));
 899 
 900                 if (os->os_dedup_checksum != ZIO_CHECKSUM_OFF)
 901                         return (SET_ERROR(EKZFS_WBCCONFLICT));
 902         }
 903 
 904         return (0);
 905 }
 906 
 907 static int
 908 dsl_prop_wbc_mode_check(dsl_dataset_t *ds, objset_t *os)
 909 {
 910         int err = 0;
 911         zfs_prop_t prop = ZFS_PROP_WBC_MODE;
 912 
 913         if (os->os_wbc_mode != ZFS_WBC_MODE_OFF) {
 914                 /*
 915                  * ZFS_PROP_WBC_MODE cannot be set for
 916                  * a child DS if the prop was set for
 917                  * the parent
 918                  */
 919                 if (os->os_wbc_root_ds_obj != ds->ds_object)
 920                         return (SET_ERROR(EKZFS_WBCPARENT));
 921         } else {
 922                 /*
 923                  * Is not allowed to change wbc_mode for parent
 924                  * if its children already have the changed prop
 925                  */
 926                 err = dmu_objset_find_dp(ds->ds_dir->dd_pool,
 927                     ds->ds_dir->dd_object,
 928                     dsl_prop_wbc_mode_check_child_cb, &prop,
 929                     DS_FIND_CHILDREN);
 930         }
 931 
 932         return (err);
 933 }
 934 
 935 typedef struct dsl_props_set_arg {
 936         const char *dpsa_dsname;
 937         zprop_source_t dpsa_source;
 938         nvlist_t *dpsa_props;
 939 } dsl_props_set_arg_t;
 940 
 941 static int
 942 dsl_props_set_check(void *arg, dmu_tx_t *tx)
 943 {
 944         dsl_props_set_arg_t *dpsa = arg;
 945         dsl_pool_t *dp = dmu_tx_pool(tx);
 946         dsl_dataset_t *ds;
 947         objset_t *os = NULL;
 948         uint64_t version;
 949         nvpair_t *elem = NULL;
 950         int err;
 951 
 952         err = dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds);
 953         if (err != 0)
 954                 return (err);
 955 
 956         err = dmu_objset_from_ds(ds, &os);
 957         if (err != 0) {
 958                 dsl_dataset_rele(ds, FTAG);
 959                 return (err);
 960         }
 961 
 962         version = spa_version(ds->ds_dir->dd_pool->dp_spa);
 963         while ((elem = nvlist_next_nvpair(dpsa->dpsa_props, elem)) != NULL) {
 964                 const char *prop_name = nvpair_name(elem);
 965                 zfs_prop_t prop = zfs_name_to_prop(prop_name);
 966 
 967                 if (strlen(prop_name) >= ZAP_MAXNAMELEN) {
 968                         dsl_dataset_rele(ds, FTAG);
 969                         return (SET_ERROR(ENAMETOOLONG));
 970                 }
 971 
 972                 /*
 973                  * Deduplication and WBC cannot be used together
 974                  * This code returns error also for case when
 975                  * WBC is ON, DEDUP is off and a user tries
 976                  * to do DEDUP=off, because in this case the code
 977                  * will be more complex, but benefit is too small
 978                  */
 979                 if (prop == ZFS_PROP_DEDUP) {
 980                         if (os->os_wbc_root_ds_obj != 0) {
 981                                 dsl_dataset_rele(ds, FTAG);
 982                                 return (SET_ERROR(EKZFS_WBCCONFLICT));
 983                         }
 984 
 985                         /*
 986                          * Need to be sure that children DS
 987                          * do not use writecache
 988                          */
 989                         err = dmu_objset_find_dp(ds->ds_dir->dd_pool,
 990                             ds->ds_dir->dd_object,
 991                             dsl_prop_wbc_mode_check_child_cb, &prop,
 992                             DS_FIND_CHILDREN);
 993                         if (err != 0) {
 994                                 dsl_dataset_rele(ds, FTAG);
 995                                 return (err);
 996                         }
 997                 }
 998 
 999                 if (prop == ZFS_PROP_WBC_MODE) {
1000                         uint64_t wbc_mode_new = 0;
1001                         data_type_t elem_type = nvpair_type(elem);
1002 
1003                         if (elem_type == DATA_TYPE_UINT64)
1004                                 wbc_mode_new = fnvpair_value_uint64(elem);
1005 
1006                         if (os->os_wbc_root_ds_obj == ds->ds_object &&
1007                             elem_type == DATA_TYPE_UINT64) {
1008 
1009                                 /*
1010                                  * ZFS_WBC_MODE_OFF_DELAYED means that
1011                                  * the coresponding wbc_instance is in
1012                                  * transition state: from ON to OFF
1013                                  * so ON/OFF is not permitted
1014                                  */
1015                                 if (os->os_wbc_mode ==
1016                                     ZFS_WBC_MODE_OFF_DELAYED) {
1017                                         dsl_dataset_rele(ds, FTAG);
1018                                         return (SET_ERROR(EINPROGRESS));
1019                                 }
1020 
1021                                 ASSERT3U(os->os_wbc_mode, ==, ZFS_WBC_MODE_ON);
1022 
1023                                 /* Check for double ON */
1024                                 if (wbc_mode_new == ZFS_WBC_MODE_ON) {
1025                                         dsl_dataset_rele(ds, FTAG);
1026                                         return (SET_ERROR(EALREADY));
1027                                 }
1028                         }
1029 
1030                         err = dsl_prop_wbc_mode_check(ds, os);
1031                         if (err != 0) {
1032                                 dsl_dataset_rele(ds, FTAG);
1033                                 return (err);
1034                         }
1035 
1036                         /* Check for double OFF */
1037                         if (os->os_wbc_root_ds_obj == 0 &&
1038                             elem_type == DATA_TYPE_UINT64 &&
1039                             wbc_mode_new == ZFS_WBC_MODE_OFF) {
1040                                 dsl_dataset_rele(ds, FTAG);
1041                                 return (SET_ERROR(EALREADY));
1042                         }
1043 
1044                         continue;
1045                 }
1046 
1047                 if (nvpair_type(elem) == DATA_TYPE_STRING) {
1048                         char *valstr = fnvpair_value_string(elem);
1049                         if (strlen(valstr) >= (version <
1050                             SPA_VERSION_STMF_PROP ?
1051                             ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) {
1052                                 dsl_dataset_rele(ds, FTAG);
1053                                 return (SET_ERROR(E2BIG));
1054                         }
1055                 }
1056 
1057         }
1058 
1059         if (ds->ds_is_snapshot && version < SPA_VERSION_SNAP_PROPS) {
1060                 dsl_dataset_rele(ds, FTAG);
1061                 return (SET_ERROR(ENOTSUP));
1062         }
1063         dsl_dataset_rele(ds, FTAG);
1064         return (0);
1065 }
1066 
1067 void
1068 dsl_props_set_sync_impl(dsl_dataset_t *ds, zprop_source_t source,
1069     nvlist_t *props, dmu_tx_t *tx)
1070 {
1071         nvpair_t *elem = NULL;
1072 
1073         while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
1074                 nvpair_t *pair = elem;
1075 
1076                 if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
1077                         /*
1078                          * dsl_prop_get_all_impl() returns properties in this
1079                          * format.
1080                          */
1081                         nvlist_t *attrs = fnvpair_value_nvlist(pair);
1082                         pair = fnvlist_lookup_nvpair(attrs, ZPROP_VALUE);
1083                 }
1084 
1085                 if (nvpair_type(pair) == DATA_TYPE_STRING) {
1086                         const char *value = fnvpair_value_string(pair);
1087                         dsl_prop_set_sync_impl(ds, nvpair_name(pair),
1088                             source, 1, strlen(value) + 1, value, tx);
1089                 } else if (nvpair_type(pair) == DATA_TYPE_UINT64) {
1090                         const char *propname = nvpair_name(pair);
1091                         zfs_prop_t prop = zfs_name_to_prop(propname);
1092                         uint64_t intval = fnvpair_value_uint64(pair);
1093 
1094                         if (prop == ZFS_PROP_WBC_MODE) {
1095                                 wbc_mode_prop_val_t val;
1096 
1097                                 /*
1098                                  * Disabling WBC involves the following:
1099                                  * 1) all the subsequent data writes will
1100                                  * stop using special vdev
1101                                  * 2) already WriteBackCached data blocks
1102                                  * (with TXG <= txg_off below) will gradually
1103                                  * migrated from special vdev
1104                                  *
1105                                  * To handle this need to remember TXG.
1106                                  * WBC will be completely disabled for this DS,
1107                                  * after WBC-window cross this TXG
1108                                  */
1109                                 val.txg_off = (intval == 0) ? tx->tx_txg : 0;
1110                                 val.root_ds_object = ds->ds_object;
1111                                 val.flags = 0;
1112 
1113                                 dsl_prop_set_sync_impl(ds, nvpair_name(pair),
1114                                     source, 8, WBC_MODE_PROP_VAL_SZ, &val, tx);
1115                         } else {
1116                                 dsl_prop_set_sync_impl(ds, nvpair_name(pair),
1117                                     source, sizeof (intval), 1, &intval, tx);
1118                         }
1119                 } else if (nvpair_type(pair) == DATA_TYPE_BOOLEAN) {
1120                         dsl_prop_set_sync_impl(ds, nvpair_name(pair),
1121                             source, 0, 0, NULL, tx);
1122                 } else {
1123                         panic("invalid nvpair type");
1124                 }
1125         }
1126 }
1127 
1128 static void
1129 dsl_props_set_sync(void *arg, dmu_tx_t *tx)
1130 {
1131         dsl_props_set_arg_t *dpsa = arg;
1132         dsl_pool_t *dp = dmu_tx_pool(tx);
1133         dsl_dataset_t *ds;
1134         objset_t *os = NULL;
1135 
1136         VERIFY0(dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds));
1137         /*
1138          * Need to initialize os, to be sure that non-mounted datasets and
1139          * non-exposed zvols will receive notification about modified
1140          * properties.
1141          * During the initialization a property can register its callback
1142          * that will be called if the property is changed.
1143          * dsl_props_set_sync_impl() calls dsl_prop_changed_notify()
1144          * that calls the required callback if it exists.
1145          */
1146         VERIFY0(dmu_objset_from_ds(ds, &os));
1147         dsl_props_set_sync_impl(ds, dpsa->dpsa_source, dpsa->dpsa_props, tx);
1148         dsl_dataset_rele(ds, FTAG);
1149 }
1150 
1151 /*
1152  * All-or-nothing; if any prop can't be set, nothing will be modified.
1153  */
1154 int
1155 dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
1156 {
1157         dsl_props_set_arg_t dpsa;
1158         int nblks = 0;
1159 
1160         dpsa.dpsa_dsname = dsname;
1161         dpsa.dpsa_source = source;
1162         dpsa.dpsa_props = props;
1163 
1164         /*
1165          * If the source includes NONE, then we will only be removing entries
1166          * from the ZAP object.  In that case don't check for ENOSPC.
1167          */
1168         if ((source & ZPROP_SRC_NONE) == 0)
1169                 nblks = 2 * fnvlist_num_pairs(props);
1170 
1171         return (dsl_sync_task(dsname, dsl_props_set_check, dsl_props_set_sync,
1172             &dpsa, nblks, ZFS_SPACE_CHECK_RESERVED));
1173 }
1174 
1175 static void
1176 dsl_props_mds_set_sync(void *arg, dmu_tx_t *tx)
1177 {
1178         dsl_props_set_arg_t *top_dpsa = arg;
1179         dsl_pool_t *dp = dmu_tx_pool(tx);
1180         nvlist_t *dss_props = top_dpsa->dpsa_props;
1181         nvpair_t *pair = NULL;
1182 
1183         while ((pair = nvlist_next_nvpair(dss_props, pair)) != NULL) {
1184                 dsl_props_set_arg_t dpsa;
1185                 dsl_dataset_t *ds = NULL;
1186                 const char *ds_name;
1187 
1188                 ds_name = nvpair_name(pair);
1189                 VERIFY0(dsl_dataset_hold(dp, ds_name, FTAG, &ds));
1190 
1191                 dpsa.dpsa_dsname = ds_name;
1192                 dpsa.dpsa_source = ZPROP_SRC_LOCAL;
1193                 dpsa.dpsa_props = fnvpair_value_nvlist(pair);
1194 
1195                 dsl_props_set_sync(&dpsa, tx);
1196                 dsl_dataset_rele(ds, FTAG);
1197         }
1198 }
1199 
1200 static int
1201 dsl_props_mds_set_check(void *arg, dmu_tx_t *tx)
1202 {
1203         dsl_props_set_arg_t *top_dpsa = arg;
1204         dsl_pool_t *dp = dmu_tx_pool(tx);
1205         nvlist_t *dss_props = top_dpsa->dpsa_props;
1206         nvpair_t *pair = NULL;
1207 
1208         while ((pair = nvlist_next_nvpair(dss_props, pair)) != NULL) {
1209                 dsl_props_set_arg_t dpsa;
1210                 dsl_dataset_t *ds = NULL;
1211                 const char *ds_name;
1212                 int err;
1213 
1214                 ds_name = nvpair_name(pair);
1215                 err = dsl_dataset_hold(dp, ds_name, FTAG, &ds);
1216                 if (err != 0)
1217                         return (err);
1218 
1219                 if (nvpair_type(pair) != DATA_TYPE_NVLIST) {
1220                         dsl_dataset_rele(ds, FTAG);
1221                         return (SET_ERROR(EINVAL));
1222                 }
1223 
1224                 dpsa.dpsa_dsname = ds_name;
1225                 dpsa.dpsa_source = ZPROP_SRC_LOCAL;
1226                 dpsa.dpsa_props = fnvpair_value_nvlist(pair);
1227 
1228                 err = dsl_props_set_check(&dpsa, tx);
1229                 dsl_dataset_rele(ds, FTAG);
1230                 if (err != 0)
1231                         return (err);
1232         }
1233 
1234         return (0);
1235 }
1236 
1237 
1238 /*
1239  * The given 'dss_props' nvlist represents the following struct:
1240  *  ds1 -> prop1:value
1241  *      -> prop3:value
1242  *  ds2 -> prop1:value
1243  *      -> prop2:value
1244  *
1245  * All-or-nothing: if any prop can't be set, nothing will be modified.
1246  */
1247 int
1248 dsl_props_set_mds(const char *pool_name, nvlist_t *dss_props,
1249     size_t num_props)
1250 {
1251         dsl_props_set_arg_t dpsa;
1252 
1253         dpsa.dpsa_dsname = pool_name;
1254         dpsa.dpsa_source = ZPROP_SRC_LOCAL;
1255         dpsa.dpsa_props = dss_props;
1256 
1257         return (dsl_sync_task(pool_name, dsl_props_mds_set_check,
1258             dsl_props_mds_set_sync, &dpsa, 2 * num_props,
1259             ZFS_SPACE_CHECK_RESERVED));
1260 }
1261 
1262 typedef enum dsl_prop_getflags {
1263         DSL_PROP_GET_INHERITING = 0x1,  /* searching parent of target ds */
1264         DSL_PROP_GET_SNAPSHOT = 0x2,    /* snapshot dataset */
1265         DSL_PROP_GET_LOCAL = 0x4,       /* local properties */
1266         DSL_PROP_GET_RECEIVED = 0x8     /* received properties */
1267 } dsl_prop_getflags_t;
1268 
1269 static int
1270 dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj,
1271     const char *setpoint, dsl_prop_getflags_t flags, nvlist_t *nv)
1272 {
1273         zap_cursor_t zc;
1274         zap_attribute_t za;
1275         int err = 0;
1276 
1277         for (zap_cursor_init(&zc, mos, propobj);
1278             (err = zap_cursor_retrieve(&zc, &za)) == 0;
1279             zap_cursor_advance(&zc)) {
1280                 nvlist_t *propval;
1281                 zfs_prop_t prop;
1282                 char buf[ZAP_MAXNAMELEN];
1283                 char *valstr;
1284                 const char *suffix;
1285                 const char *propname;
1286                 const char *source;
1287 
1288                 suffix = strchr(za.za_name, '$');
1289 
1290                 if (suffix == NULL) {
1291                         /*
1292                          * Skip local properties if we only want received
1293                          * properties.
1294                          */
1295                         if (flags & DSL_PROP_GET_RECEIVED)
1296                                 continue;
1297 
1298                         propname = za.za_name;
1299                         source = setpoint;
1300                 } else if (strcmp(suffix, ZPROP_INHERIT_SUFFIX) == 0) {
1301                         /* Skip explicitly inherited entries. */
1302                         continue;
1303                 } else if (strcmp(suffix, ZPROP_RECVD_SUFFIX) == 0) {
1304                         if (flags & DSL_PROP_GET_LOCAL)
1305                                 continue;
1306 
1307                         (void) strncpy(buf, za.za_name, (suffix - za.za_name));
1308                         buf[suffix - za.za_name] = '\0';
1309                         propname = buf;
1310 
1311                         if (!(flags & DSL_PROP_GET_RECEIVED)) {
1312                                 /* Skip if locally overridden. */
1313                                 err = zap_contains(mos, propobj, propname);
1314                                 if (err == 0)
1315                                         continue;
1316                                 if (err != ENOENT)
1317                                         break;
1318 
1319                                 /* Skip if explicitly inherited. */
1320                                 valstr = kmem_asprintf("%s%s", propname,
1321                                     ZPROP_INHERIT_SUFFIX);
1322                                 err = zap_contains(mos, propobj, valstr);
1323                                 strfree(valstr);
1324                                 if (err == 0)
1325                                         continue;
1326                                 if (err != ENOENT)
1327                                         break;
1328                         }
1329 
1330                         source = ((flags & DSL_PROP_GET_INHERITING) ?
1331                             setpoint : ZPROP_SOURCE_VAL_RECVD);
1332                 } else {
1333                         /*
1334                          * For backward compatibility, skip suffixes we don't
1335                          * recognize.
1336                          */
1337                         continue;
1338                 }
1339 
1340                 prop = zfs_name_to_prop(propname);
1341 
1342                 /* Skip non-inheritable properties. */
1343                 if ((flags & DSL_PROP_GET_INHERITING) && prop != ZPROP_INVAL &&
1344                     !zfs_prop_inheritable(prop))
1345                         continue;
1346 
1347                 /* Skip properties not valid for this type. */
1348                 if ((flags & DSL_PROP_GET_SNAPSHOT) && prop != ZPROP_INVAL &&
1349                     !zfs_prop_valid_for_type(prop, ZFS_TYPE_SNAPSHOT))
1350                         continue;
1351 
1352                 /* Skip properties already defined. */
1353                 if (nvlist_exists(nv, propname))
1354                         continue;
1355 
1356                 VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1357                 if (za.za_integer_length == 1) {
1358                         /*
1359                          * String property
1360                          */
1361                         char *tmp = kmem_alloc(za.za_num_integers,
1362                             KM_SLEEP);
1363                         err = zap_lookup(mos, propobj,
1364                             za.za_name, 1, za.za_num_integers, tmp);
1365                         if (err != 0) {
1366                                 kmem_free(tmp, za.za_num_integers);
1367                                 break;
1368                         }
1369 
1370                         VERIFY(nvlist_add_string(propval, ZPROP_VALUE,
1371                             tmp) == 0);
1372                         kmem_free(tmp, za.za_num_integers);
1373                 } else {
1374                         /*
1375                          * Integer property
1376                          */
1377                         ASSERT(za.za_integer_length == 8);
1378 
1379                         if (prop == ZFS_PROP_WBC_MODE) {
1380                                 wbc_mode_prop_val_t val;
1381 
1382                                 ASSERT(za.za_num_integers ==
1383                                     WBC_MODE_PROP_VAL_SZ);
1384 
1385                                 err = zap_lookup(mos, propobj,
1386                                     za.za_name, 8, za.za_num_integers, &val);
1387                                 if (err != 0)
1388                                         break;
1389 
1390                                 if (val.root_ds_object != 0 &&
1391                                     val.txg_off == 0)
1392                                         za.za_first_integer = ZFS_WBC_MODE_ON;
1393                                 else
1394                                         za.za_first_integer = ZFS_WBC_MODE_OFF;
1395                         }
1396 
1397                         (void) nvlist_add_uint64(propval, ZPROP_VALUE,
1398                             za.za_first_integer);
1399                 }
1400 
1401                 VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, source) == 0);
1402                 VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0);
1403                 nvlist_free(propval);
1404         }
1405         zap_cursor_fini(&zc);
1406         if (err == ENOENT)
1407                 err = 0;
1408         return (err);
1409 }
1410 
1411 /*
1412  * Iterate over all properties for this dataset and return them in an nvlist.
1413  */
1414 static int
1415 dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp,
1416     dsl_prop_getflags_t flags)
1417 {
1418         dsl_dir_t *dd = ds->ds_dir;
1419         dsl_pool_t *dp = dd->dd_pool;
1420         objset_t *mos = dp->dp_meta_objset;
1421         int err = 0;
1422         char setpoint[ZFS_MAX_DATASET_NAME_LEN];
1423 
1424         VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1425 
1426         if (ds->ds_is_snapshot)
1427                 flags |= DSL_PROP_GET_SNAPSHOT;
1428 
1429         ASSERT(dsl_pool_config_held(dp));
1430 
1431         if (dsl_dataset_phys(ds)->ds_props_obj != 0) {
1432                 ASSERT(flags & DSL_PROP_GET_SNAPSHOT);
1433                 dsl_dataset_name(ds, setpoint);
1434                 err = dsl_prop_get_all_impl(mos,
1435                     dsl_dataset_phys(ds)->ds_props_obj, setpoint, flags, *nvp);
1436                 if (err)
1437                         goto out;
1438         }
1439 
1440         for (; dd != NULL; dd = dd->dd_parent) {
1441                 if (dd != ds->ds_dir || (flags & DSL_PROP_GET_SNAPSHOT)) {
1442                         if (flags & (DSL_PROP_GET_LOCAL |
1443                             DSL_PROP_GET_RECEIVED))
1444                                 break;
1445                         flags |= DSL_PROP_GET_INHERITING;
1446                 }
1447                 dsl_dir_name(dd, setpoint);
1448                 err = dsl_prop_get_all_impl(mos,
1449                     dsl_dir_phys(dd)->dd_props_zapobj, setpoint, flags, *nvp);
1450                 if (err)
1451                         break;
1452         }
1453 out:
1454         return (err);
1455 }
1456 
1457 boolean_t
1458 dsl_prop_get_hasrecvd(const char *dsname)
1459 {
1460         uint64_t dummy;
1461 
1462         return (0 ==
1463             dsl_prop_get_integer(dsname, ZPROP_HAS_RECVD, &dummy, NULL));
1464 }
1465 
1466 static int
1467 dsl_prop_set_hasrecvd_impl(const char *dsname, zprop_source_t source)
1468 {
1469         uint64_t version;
1470         spa_t *spa;
1471         int error = 0;
1472 
1473         VERIFY0(spa_open(dsname, &spa, FTAG));
1474         version = spa_version(spa);
1475         spa_close(spa, FTAG);
1476 
1477         if (version >= SPA_VERSION_RECVD_PROPS)
1478                 error = dsl_prop_set_int(dsname, ZPROP_HAS_RECVD, source, 0);
1479         return (error);
1480 }
1481 
1482 /*
1483  * Call after successfully receiving properties to ensure that only the first
1484  * receive on or after SPA_VERSION_RECVD_PROPS blows away local properties.
1485  */
1486 int
1487 dsl_prop_set_hasrecvd(const char *dsname)
1488 {
1489         int error = 0;
1490         if (!dsl_prop_get_hasrecvd(dsname))
1491                 error = dsl_prop_set_hasrecvd_impl(dsname, ZPROP_SRC_LOCAL);
1492         return (error);
1493 }
1494 
1495 void
1496 dsl_prop_unset_hasrecvd(const char *dsname)
1497 {
1498         VERIFY0(dsl_prop_set_hasrecvd_impl(dsname, ZPROP_SRC_NONE));
1499 }
1500 
1501 int
1502 dsl_prop_get_all(objset_t *os, nvlist_t **nvp)
1503 {
1504         return (dsl_prop_get_all_ds(os->os_dsl_dataset, nvp, 0));
1505 }
1506 
1507 int
1508 dsl_prop_get_received(const char *dsname, nvlist_t **nvp)
1509 {
1510         objset_t *os;
1511         int error;
1512 
1513         /*
1514          * Received properties are not distinguishable from local properties
1515          * until the dataset has received properties on or after
1516          * SPA_VERSION_RECVD_PROPS.
1517          */
1518         dsl_prop_getflags_t flags = (dsl_prop_get_hasrecvd(dsname) ?
1519             DSL_PROP_GET_RECEIVED : DSL_PROP_GET_LOCAL);
1520 
1521         error = dmu_objset_hold(dsname, FTAG, &os);
1522         if (error != 0)
1523                 return (error);
1524         error = dsl_prop_get_all_ds(os->os_dsl_dataset, nvp, flags);
1525         dmu_objset_rele(os, FTAG);
1526         return (error);
1527 }
1528 
1529 void
1530 dsl_prop_nvlist_add_uint64(nvlist_t *nv, zfs_prop_t prop, uint64_t value)
1531 {
1532         nvlist_t *propval;
1533         const char *propname = zfs_prop_to_name(prop);
1534         uint64_t default_value;
1535 
1536         if (nvlist_lookup_nvlist(nv, propname, &propval) == 0) {
1537                 VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0);
1538                 return;
1539         }
1540 
1541         VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1542         VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0);
1543         /* Indicate the default source if we can. */
1544         if (dodefault(prop, 8, 1, &default_value) == 0 &&
1545             value == default_value) {
1546                 VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, "") == 0);
1547         }
1548         VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0);
1549         nvlist_free(propval);
1550 }
1551 
1552 void
1553 dsl_prop_nvlist_add_string(nvlist_t *nv, zfs_prop_t prop, const char *value)
1554 {
1555         nvlist_t *propval;
1556         const char *propname = zfs_prop_to_name(prop);
1557 
1558         if (nvlist_lookup_nvlist(nv, propname, &propval) == 0) {
1559                 VERIFY(nvlist_add_string(propval, ZPROP_VALUE, value) == 0);
1560                 return;
1561         }
1562 
1563         VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1564         VERIFY(nvlist_add_string(propval, ZPROP_VALUE, value) == 0);
1565         VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0);
1566         nvlist_free(propval);
1567 }