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 by Delphix. All rights reserved. 24 */ 25 26 #include <sys/zfs_context.h> 27 #include <sys/dmu.h> 28 #include <sys/dmu_objset.h> 29 #include <sys/dmu_tx.h> 30 #include <sys/dsl_dataset.h> 31 #include <sys/dsl_dir.h> 32 #include <sys/dsl_prop.h> 33 #include <sys/dsl_synctask.h> 34 #include <sys/spa.h> 35 #include <sys/zap.h> 36 #include <sys/fs/zfs.h> 37 38 #include "zfs_prop.h" 39 40 #define ZPROP_INHERIT_SUFFIX "$inherit" 41 #define ZPROP_RECVD_SUFFIX "$recvd" 42 43 static int 44 dodefault(const char *propname, int intsz, int numints, void *buf) 45 { 46 zfs_prop_t prop; 47 48 /* 49 * The setonce properties are read-only, BUT they still 50 * have a default value that can be used as the initial 51 * value. 52 */ 53 if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL || 54 (zfs_prop_readonly(prop) && !zfs_prop_setonce(prop))) 55 return (ENOENT); 56 57 if (zfs_prop_get_type(prop) == PROP_TYPE_STRING) { 58 if (intsz != 1) 59 return (EOVERFLOW); 60 (void) strncpy(buf, zfs_prop_default_string(prop), 61 numints); 62 } else { 63 if (intsz != 8 || numints < 1) 64 return (EOVERFLOW); 65 66 *(uint64_t *)buf = zfs_prop_default_numeric(prop); 67 } 68 69 return (0); 70 } 71 72 int 73 dsl_prop_get_dd(dsl_dir_t *dd, const char *propname, 74 int intsz, int numints, void *buf, char *setpoint, boolean_t snapshot) 75 { 76 int err = ENOENT; 77 dsl_dir_t *target = dd; 78 objset_t *mos = dd->dd_pool->dp_meta_objset; 79 zfs_prop_t prop; 80 boolean_t inheritable; 81 boolean_t inheriting = B_FALSE; 82 char *inheritstr; 83 char *recvdstr; 84 85 ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); 86 87 if (setpoint) 88 setpoint[0] = '\0'; 89 90 prop = zfs_name_to_prop(propname); 91 inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); 92 inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); 93 recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); 94 95 /* 96 * Note: dd may become NULL, therefore we shouldn't dereference it 97 * after this loop. 98 */ 99 for (; dd != NULL; dd = dd->dd_parent) { 100 ASSERT(RW_LOCK_HELD(&dd->dd_pool->dp_config_rwlock)); 101 102 if (dd != target || snapshot) { 103 if (!inheritable) 104 break; 105 inheriting = B_TRUE; 106 } 107 108 /* Check for a local value. */ 109 err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, propname, 110 intsz, numints, buf); 111 if (err != ENOENT) { 112 if (setpoint != NULL && err == 0) 113 dsl_dir_name(dd, setpoint); 114 break; 115 } 116 117 /* 118 * Skip the check for a received value if there is an explicit 119 * inheritance entry. 120 */ 121 err = zap_contains(mos, dd->dd_phys->dd_props_zapobj, 122 inheritstr); 123 if (err != 0 && err != ENOENT) 124 break; 125 126 if (err == ENOENT) { 127 /* Check for a received value. */ 128 err = zap_lookup(mos, dd->dd_phys->dd_props_zapobj, 129 recvdstr, intsz, numints, buf); 130 if (err != ENOENT) { 131 if (setpoint != NULL && err == 0) { 132 if (inheriting) { 133 dsl_dir_name(dd, setpoint); 134 } else { 135 (void) strcpy(setpoint, 136 ZPROP_SOURCE_VAL_RECVD); 137 } 138 } 139 break; 140 } 141 } 142 143 /* 144 * If we found an explicit inheritance entry, err is zero even 145 * though we haven't yet found the value, so reinitializing err 146 * at the end of the loop (instead of at the beginning) ensures 147 * that err has a valid post-loop value. 148 */ 149 err = ENOENT; 150 } 151 152 if (err == ENOENT) 153 err = dodefault(propname, intsz, numints, buf); 154 155 strfree(inheritstr); 156 strfree(recvdstr); 157 158 return (err); 159 } 160 161 int 162 dsl_prop_get_ds(dsl_dataset_t *ds, const char *propname, 163 int intsz, int numints, void *buf, char *setpoint) 164 { 165 zfs_prop_t prop = zfs_name_to_prop(propname); 166 boolean_t inheritable; 167 boolean_t snapshot; 168 uint64_t zapobj; 169 170 ASSERT(RW_LOCK_HELD(&ds->ds_dir->dd_pool->dp_config_rwlock)); 171 inheritable = (prop == ZPROP_INVAL || zfs_prop_inheritable(prop)); 172 snapshot = (ds->ds_phys != NULL && dsl_dataset_is_snapshot(ds)); 173 zapobj = (ds->ds_phys == NULL ? 0 : ds->ds_phys->ds_props_obj); 174 175 if (zapobj != 0) { 176 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset; 177 int err; 178 179 ASSERT(snapshot); 180 181 /* Check for a local value. */ 182 err = zap_lookup(mos, zapobj, propname, intsz, numints, buf); 183 if (err != ENOENT) { 184 if (setpoint != NULL && err == 0) 185 dsl_dataset_name(ds, setpoint); 186 return (err); 187 } 188 189 /* 190 * Skip the check for a received value if there is an explicit 191 * inheritance entry. 192 */ 193 if (inheritable) { 194 char *inheritstr = kmem_asprintf("%s%s", propname, 195 ZPROP_INHERIT_SUFFIX); 196 err = zap_contains(mos, zapobj, inheritstr); 197 strfree(inheritstr); 198 if (err != 0 && err != ENOENT) 199 return (err); 200 } 201 202 if (err == ENOENT) { 203 /* Check for a received value. */ 204 char *recvdstr = kmem_asprintf("%s%s", propname, 205 ZPROP_RECVD_SUFFIX); 206 err = zap_lookup(mos, zapobj, recvdstr, 207 intsz, numints, buf); 208 strfree(recvdstr); 209 if (err != ENOENT) { 210 if (setpoint != NULL && err == 0) 211 (void) strcpy(setpoint, 212 ZPROP_SOURCE_VAL_RECVD); 213 return (err); 214 } 215 } 216 } 217 218 return (dsl_prop_get_dd(ds->ds_dir, propname, 219 intsz, numints, buf, setpoint, snapshot)); 220 } 221 222 /* 223 * Register interest in the named property. We'll call the callback 224 * once to notify it of the current property value, and again each time 225 * the property changes, until this callback is unregistered. 226 * 227 * Return 0 on success, errno if the prop is not an integer value. 228 */ 229 int 230 dsl_prop_register(dsl_dataset_t *ds, const char *propname, 231 dsl_prop_changed_cb_t *callback, void *cbarg) 232 { 233 dsl_dir_t *dd = ds->ds_dir; 234 dsl_pool_t *dp = dd->dd_pool; 235 uint64_t value; 236 dsl_prop_cb_record_t *cbr; 237 int err; 238 int need_rwlock; 239 240 need_rwlock = !RW_WRITE_HELD(&dp->dp_config_rwlock); 241 if (need_rwlock) 242 rw_enter(&dp->dp_config_rwlock, RW_READER); 243 244 err = dsl_prop_get_ds(ds, propname, 8, 1, &value, NULL); 245 if (err != 0) { 246 if (need_rwlock) 247 rw_exit(&dp->dp_config_rwlock); 248 return (err); 249 } 250 251 cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP); 252 cbr->cbr_ds = ds; 253 cbr->cbr_propname = kmem_alloc(strlen(propname)+1, KM_SLEEP); 254 (void) strcpy((char *)cbr->cbr_propname, propname); 255 cbr->cbr_func = callback; 256 cbr->cbr_arg = cbarg; 257 mutex_enter(&dd->dd_lock); 258 list_insert_head(&dd->dd_prop_cbs, cbr); 259 mutex_exit(&dd->dd_lock); 260 261 cbr->cbr_func(cbr->cbr_arg, value); 262 263 if (need_rwlock) 264 rw_exit(&dp->dp_config_rwlock); 265 return (0); 266 } 267 268 int 269 dsl_prop_get(const char *dsname, const char *propname, 270 int intsz, int numints, void *buf, char *setpoint) 271 { 272 dsl_dataset_t *ds; 273 int err; 274 275 err = dsl_dataset_hold(dsname, FTAG, &ds); 276 if (err) 277 return (err); 278 279 rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER); 280 err = dsl_prop_get_ds(ds, propname, intsz, numints, buf, setpoint); 281 rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock); 282 283 dsl_dataset_rele(ds, FTAG); 284 return (err); 285 } 286 287 /* 288 * Get the current property value. It may have changed by the time this 289 * function returns, so it is NOT safe to follow up with 290 * dsl_prop_register() and assume that the value has not changed in 291 * between. 292 * 293 * Return 0 on success, ENOENT if ddname is invalid. 294 */ 295 int 296 dsl_prop_get_integer(const char *ddname, const char *propname, 297 uint64_t *valuep, char *setpoint) 298 { 299 return (dsl_prop_get(ddname, propname, 8, 1, valuep, setpoint)); 300 } 301 302 void 303 dsl_prop_setarg_init_uint64(dsl_prop_setarg_t *psa, const char *propname, 304 zprop_source_t source, uint64_t *value) 305 { 306 psa->psa_name = propname; 307 psa->psa_source = source; 308 psa->psa_intsz = 8; 309 psa->psa_numints = 1; 310 psa->psa_value = value; 311 312 psa->psa_effective_value = -1ULL; 313 } 314 315 /* 316 * Predict the effective value of the given special property if it were set with 317 * the given value and source. This is not a general purpose function. It exists 318 * only to handle the special requirements of the quota and reservation 319 * properties. The fact that these properties are non-inheritable greatly 320 * simplifies the prediction logic. 321 * 322 * Returns 0 on success, a positive error code on failure, or -1 if called with 323 * a property not handled by this function. 324 */ 325 int 326 dsl_prop_predict_sync(dsl_dir_t *dd, dsl_prop_setarg_t *psa) 327 { 328 const char *propname = psa->psa_name; 329 zfs_prop_t prop = zfs_name_to_prop(propname); 330 zprop_source_t source = psa->psa_source; 331 objset_t *mos; 332 uint64_t zapobj; 333 uint64_t version; 334 char *recvdstr; 335 int err = 0; 336 337 switch (prop) { 338 case ZFS_PROP_QUOTA: 339 case ZFS_PROP_RESERVATION: 340 case ZFS_PROP_REFQUOTA: 341 case ZFS_PROP_REFRESERVATION: 342 break; 343 default: 344 return (-1); 345 } 346 347 mos = dd->dd_pool->dp_meta_objset; 348 zapobj = dd->dd_phys->dd_props_zapobj; 349 recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); 350 351 version = spa_version(dd->dd_pool->dp_spa); 352 if (version < SPA_VERSION_RECVD_PROPS) { 353 if (source & ZPROP_SRC_NONE) 354 source = ZPROP_SRC_NONE; 355 else if (source & ZPROP_SRC_RECEIVED) 356 source = ZPROP_SRC_LOCAL; 357 } 358 359 switch (source) { 360 case ZPROP_SRC_NONE: 361 /* Revert to the received value, if any. */ 362 err = zap_lookup(mos, zapobj, recvdstr, 8, 1, 363 &psa->psa_effective_value); 364 if (err == ENOENT) 365 psa->psa_effective_value = 0; 366 break; 367 case ZPROP_SRC_LOCAL: 368 psa->psa_effective_value = *(uint64_t *)psa->psa_value; 369 break; 370 case ZPROP_SRC_RECEIVED: 371 /* 372 * If there's no local setting, then the new received value will 373 * be the effective value. 374 */ 375 err = zap_lookup(mos, zapobj, propname, 8, 1, 376 &psa->psa_effective_value); 377 if (err == ENOENT) 378 psa->psa_effective_value = *(uint64_t *)psa->psa_value; 379 break; 380 case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED): 381 /* 382 * We're clearing the received value, so the local setting (if 383 * it exists) remains the effective value. 384 */ 385 err = zap_lookup(mos, zapobj, propname, 8, 1, 386 &psa->psa_effective_value); 387 if (err == ENOENT) 388 psa->psa_effective_value = 0; 389 break; 390 default: 391 cmn_err(CE_PANIC, "unexpected property source: %d", source); 392 } 393 394 strfree(recvdstr); 395 396 if (err == ENOENT) 397 return (0); 398 399 return (err); 400 } 401 402 #ifdef ZFS_DEBUG 403 void 404 dsl_prop_check_prediction(dsl_dir_t *dd, dsl_prop_setarg_t *psa) 405 { 406 zfs_prop_t prop = zfs_name_to_prop(psa->psa_name); 407 uint64_t intval; 408 char setpoint[MAXNAMELEN]; 409 uint64_t version = spa_version(dd->dd_pool->dp_spa); 410 int err; 411 412 if (version < SPA_VERSION_RECVD_PROPS) { 413 switch (prop) { 414 case ZFS_PROP_QUOTA: 415 case ZFS_PROP_RESERVATION: 416 return; 417 } 418 } 419 420 err = dsl_prop_get_dd(dd, psa->psa_name, 8, 1, &intval, 421 setpoint, B_FALSE); 422 if (err == 0 && intval != psa->psa_effective_value) { 423 cmn_err(CE_PANIC, "%s property, source: %x, " 424 "predicted effective value: %llu, " 425 "actual effective value: %llu (setpoint: %s)", 426 psa->psa_name, psa->psa_source, 427 (unsigned long long)psa->psa_effective_value, 428 (unsigned long long)intval, setpoint); 429 } 430 } 431 #endif 432 433 /* 434 * Unregister this callback. Return 0 on success, ENOENT if ddname is 435 * invalid, ENOMSG if no matching callback registered. 436 */ 437 int 438 dsl_prop_unregister(dsl_dataset_t *ds, const char *propname, 439 dsl_prop_changed_cb_t *callback, void *cbarg) 440 { 441 dsl_dir_t *dd = ds->ds_dir; 442 dsl_prop_cb_record_t *cbr; 443 444 mutex_enter(&dd->dd_lock); 445 for (cbr = list_head(&dd->dd_prop_cbs); 446 cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 447 if (cbr->cbr_ds == ds && 448 cbr->cbr_func == callback && 449 cbr->cbr_arg == cbarg && 450 strcmp(cbr->cbr_propname, propname) == 0) 451 break; 452 } 453 454 if (cbr == NULL) { 455 mutex_exit(&dd->dd_lock); 456 return (ENOMSG); 457 } 458 459 list_remove(&dd->dd_prop_cbs, cbr); 460 mutex_exit(&dd->dd_lock); 461 kmem_free((void*)cbr->cbr_propname, strlen(cbr->cbr_propname)+1); 462 kmem_free(cbr, sizeof (dsl_prop_cb_record_t)); 463 464 return (0); 465 } 466 467 /* 468 * Return the number of callbacks that are registered for this dataset. 469 */ 470 int 471 dsl_prop_numcb(dsl_dataset_t *ds) 472 { 473 dsl_dir_t *dd = ds->ds_dir; 474 dsl_prop_cb_record_t *cbr; 475 int num = 0; 476 477 mutex_enter(&dd->dd_lock); 478 for (cbr = list_head(&dd->dd_prop_cbs); 479 cbr; cbr = list_next(&dd->dd_prop_cbs, cbr)) { 480 if (cbr->cbr_ds == ds) 481 num++; 482 } 483 mutex_exit(&dd->dd_lock); 484 485 return (num); 486 } 487 488 static void 489 dsl_prop_changed_notify(dsl_pool_t *dp, uint64_t ddobj, 490 const char *propname, uint64_t value, int first) 491 { 492 dsl_dir_t *dd; 493 dsl_prop_cb_record_t *cbr; 494 objset_t *mos = dp->dp_meta_objset; 495 zap_cursor_t zc; 496 zap_attribute_t *za; 497 int err; 498 499 ASSERT(RW_WRITE_HELD(&dp->dp_config_rwlock)); 500 err = dsl_dir_open_obj(dp, ddobj, NULL, FTAG, &dd); 501 if (err) 502 return; 503 504 if (!first) { 505 /* 506 * If the prop is set here, then this change is not 507 * being inherited here or below; stop the recursion. 508 */ 509 err = zap_contains(mos, dd->dd_phys->dd_props_zapobj, propname); 510 if (err == 0) { 511 dsl_dir_close(dd, FTAG); 512 return; 513 } 514 ASSERT3U(err, ==, ENOENT); 515 } 516 517 mutex_enter(&dd->dd_lock); 518 for (cbr = list_head(&dd->dd_prop_cbs); cbr; 519 cbr = list_next(&dd->dd_prop_cbs, cbr)) { 520 uint64_t propobj = cbr->cbr_ds->ds_phys->ds_props_obj; 521 522 if (strcmp(cbr->cbr_propname, propname) != 0) 523 continue; 524 525 /* 526 * If the property is set on this ds, then it is not 527 * inherited here; don't call the callback. 528 */ 529 if (propobj && 0 == zap_contains(mos, propobj, propname)) 530 continue; 531 532 cbr->cbr_func(cbr->cbr_arg, value); 533 } 534 mutex_exit(&dd->dd_lock); 535 536 za = kmem_alloc(sizeof (zap_attribute_t), KM_SLEEP); 537 for (zap_cursor_init(&zc, mos, 538 dd->dd_phys->dd_child_dir_zapobj); 539 zap_cursor_retrieve(&zc, za) == 0; 540 zap_cursor_advance(&zc)) { 541 dsl_prop_changed_notify(dp, za->za_first_integer, 542 propname, value, FALSE); 543 } 544 kmem_free(za, sizeof (zap_attribute_t)); 545 zap_cursor_fini(&zc); 546 dsl_dir_close(dd, FTAG); 547 } 548 549 void 550 dsl_prop_set_sync(void *arg1, void *arg2, dmu_tx_t *tx) 551 { 552 dsl_dataset_t *ds = arg1; 553 dsl_prop_setarg_t *psa = arg2; 554 objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset; 555 uint64_t zapobj, intval, dummy; 556 int isint; 557 char valbuf[32]; 558 char *valstr = NULL; 559 char *inheritstr; 560 char *recvdstr; 561 char *tbuf = NULL; 562 int err; 563 uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa); 564 const char *propname = psa->psa_name; 565 zprop_source_t source = psa->psa_source; 566 567 isint = (dodefault(propname, 8, 1, &intval) == 0); 568 569 if (ds->ds_phys != NULL && dsl_dataset_is_snapshot(ds)) { 570 ASSERT(version >= SPA_VERSION_SNAP_PROPS); 571 if (ds->ds_phys->ds_props_obj == 0) { 572 dmu_buf_will_dirty(ds->ds_dbuf, tx); 573 ds->ds_phys->ds_props_obj = 574 zap_create(mos, 575 DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx); 576 } 577 zapobj = ds->ds_phys->ds_props_obj; 578 } else { 579 zapobj = ds->ds_dir->dd_phys->dd_props_zapobj; 580 } 581 582 if (version < SPA_VERSION_RECVD_PROPS) { 583 zfs_prop_t prop = zfs_name_to_prop(propname); 584 if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION) 585 return; 586 587 if (source & ZPROP_SRC_NONE) 588 source = ZPROP_SRC_NONE; 589 else if (source & ZPROP_SRC_RECEIVED) 590 source = ZPROP_SRC_LOCAL; 591 } 592 593 inheritstr = kmem_asprintf("%s%s", propname, ZPROP_INHERIT_SUFFIX); 594 recvdstr = kmem_asprintf("%s%s", propname, ZPROP_RECVD_SUFFIX); 595 596 switch (source) { 597 case ZPROP_SRC_NONE: 598 /* 599 * revert to received value, if any (inherit -S) 600 * - remove propname 601 * - remove propname$inherit 602 */ 603 err = zap_remove(mos, zapobj, propname, tx); 604 ASSERT(err == 0 || err == ENOENT); 605 err = zap_remove(mos, zapobj, inheritstr, tx); 606 ASSERT(err == 0 || err == ENOENT); 607 break; 608 case ZPROP_SRC_LOCAL: 609 /* 610 * remove propname$inherit 611 * set propname -> value 612 */ 613 err = zap_remove(mos, zapobj, inheritstr, tx); 614 ASSERT(err == 0 || err == ENOENT); 615 VERIFY(0 == zap_update(mos, zapobj, propname, 616 psa->psa_intsz, psa->psa_numints, psa->psa_value, tx)); 617 break; 618 case ZPROP_SRC_INHERITED: 619 /* 620 * explicitly inherit 621 * - remove propname 622 * - set propname$inherit 623 */ 624 err = zap_remove(mos, zapobj, propname, tx); 625 ASSERT(err == 0 || err == ENOENT); 626 if (version >= SPA_VERSION_RECVD_PROPS && 627 dsl_prop_get_ds(ds, ZPROP_HAS_RECVD, 8, 1, &dummy, 628 NULL) == 0) { 629 dummy = 0; 630 err = zap_update(mos, zapobj, inheritstr, 631 8, 1, &dummy, tx); 632 ASSERT(err == 0); 633 } 634 break; 635 case ZPROP_SRC_RECEIVED: 636 /* 637 * set propname$recvd -> value 638 */ 639 err = zap_update(mos, zapobj, recvdstr, 640 psa->psa_intsz, psa->psa_numints, psa->psa_value, tx); 641 ASSERT(err == 0); 642 break; 643 case (ZPROP_SRC_NONE | ZPROP_SRC_LOCAL | ZPROP_SRC_RECEIVED): 644 /* 645 * clear local and received settings 646 * - remove propname 647 * - remove propname$inherit 648 * - remove propname$recvd 649 */ 650 err = zap_remove(mos, zapobj, propname, tx); 651 ASSERT(err == 0 || err == ENOENT); 652 err = zap_remove(mos, zapobj, inheritstr, tx); 653 ASSERT(err == 0 || err == ENOENT); 654 /* FALLTHRU */ 655 case (ZPROP_SRC_NONE | ZPROP_SRC_RECEIVED): 656 /* 657 * remove propname$recvd 658 */ 659 err = zap_remove(mos, zapobj, recvdstr, tx); 660 ASSERT(err == 0 || err == ENOENT); 661 break; 662 default: 663 cmn_err(CE_PANIC, "unexpected property source: %d", source); 664 } 665 666 strfree(inheritstr); 667 strfree(recvdstr); 668 669 if (isint) { 670 VERIFY(0 == dsl_prop_get_ds(ds, propname, 8, 1, &intval, NULL)); 671 672 if (ds->ds_phys != NULL && dsl_dataset_is_snapshot(ds)) { 673 dsl_prop_cb_record_t *cbr; 674 /* 675 * It's a snapshot; nothing can inherit this 676 * property, so just look for callbacks on this 677 * ds here. 678 */ 679 mutex_enter(&ds->ds_dir->dd_lock); 680 for (cbr = list_head(&ds->ds_dir->dd_prop_cbs); cbr; 681 cbr = list_next(&ds->ds_dir->dd_prop_cbs, cbr)) { 682 if (cbr->cbr_ds == ds && 683 strcmp(cbr->cbr_propname, propname) == 0) 684 cbr->cbr_func(cbr->cbr_arg, intval); 685 } 686 mutex_exit(&ds->ds_dir->dd_lock); 687 } else { 688 dsl_prop_changed_notify(ds->ds_dir->dd_pool, 689 ds->ds_dir->dd_object, propname, intval, TRUE); 690 } 691 692 (void) snprintf(valbuf, sizeof (valbuf), 693 "%lld", (longlong_t)intval); 694 valstr = valbuf; 695 } else { 696 if (source == ZPROP_SRC_LOCAL) { 697 valstr = (char *)psa->psa_value; 698 } else { 699 tbuf = kmem_alloc(ZAP_MAXVALUELEN, KM_SLEEP); 700 if (dsl_prop_get_ds(ds, propname, 1, 701 ZAP_MAXVALUELEN, tbuf, NULL) == 0) 702 valstr = tbuf; 703 } 704 } 705 706 spa_history_log_internal_ds(ds, (source == ZPROP_SRC_NONE || 707 source == ZPROP_SRC_INHERITED) ? "inherit" : "set", tx, 708 "%s=%s", propname, (valstr == NULL ? "" : valstr)); 709 710 if (tbuf != NULL) 711 kmem_free(tbuf, ZAP_MAXVALUELEN); 712 } 713 714 void 715 dsl_props_set_sync(void *arg1, void *arg2, dmu_tx_t *tx) 716 { 717 dsl_dataset_t *ds = arg1; 718 dsl_props_arg_t *pa = arg2; 719 nvlist_t *props = pa->pa_props; 720 dsl_prop_setarg_t psa; 721 nvpair_t *elem = NULL; 722 723 psa.psa_source = pa->pa_source; 724 725 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 726 nvpair_t *pair = elem; 727 728 psa.psa_name = nvpair_name(pair); 729 730 if (nvpair_type(pair) == DATA_TYPE_NVLIST) { 731 /* 732 * dsl_prop_get_all_impl() returns properties in this 733 * format. 734 */ 735 nvlist_t *attrs; 736 VERIFY(nvpair_value_nvlist(pair, &attrs) == 0); 737 VERIFY(nvlist_lookup_nvpair(attrs, ZPROP_VALUE, 738 &pair) == 0); 739 } 740 741 if (nvpair_type(pair) == DATA_TYPE_STRING) { 742 VERIFY(nvpair_value_string(pair, 743 (char **)&psa.psa_value) == 0); 744 psa.psa_intsz = 1; 745 psa.psa_numints = strlen(psa.psa_value) + 1; 746 } else { 747 uint64_t intval; 748 VERIFY(nvpair_value_uint64(pair, &intval) == 0); 749 psa.psa_intsz = sizeof (intval); 750 psa.psa_numints = 1; 751 psa.psa_value = &intval; 752 } 753 dsl_prop_set_sync(ds, &psa, tx); 754 } 755 } 756 757 int 758 dsl_prop_set(const char *dsname, const char *propname, zprop_source_t source, 759 int intsz, int numints, const void *buf) 760 { 761 dsl_dataset_t *ds; 762 uint64_t version; 763 int err; 764 dsl_prop_setarg_t psa; 765 766 /* 767 * We must do these checks before we get to the syncfunc, since 768 * it can't fail. 769 */ 770 if (strlen(propname) >= ZAP_MAXNAMELEN) 771 return (ENAMETOOLONG); 772 773 err = dsl_dataset_hold(dsname, FTAG, &ds); 774 if (err) 775 return (err); 776 777 version = spa_version(ds->ds_dir->dd_pool->dp_spa); 778 if (intsz * numints >= (version < SPA_VERSION_STMF_PROP ? 779 ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) { 780 dsl_dataset_rele(ds, FTAG); 781 return (E2BIG); 782 } 783 if (dsl_dataset_is_snapshot(ds) && 784 version < SPA_VERSION_SNAP_PROPS) { 785 dsl_dataset_rele(ds, FTAG); 786 return (ENOTSUP); 787 } 788 789 psa.psa_name = propname; 790 psa.psa_source = source; 791 psa.psa_intsz = intsz; 792 psa.psa_numints = numints; 793 psa.psa_value = buf; 794 psa.psa_effective_value = -1ULL; 795 796 err = dsl_sync_task_do(ds->ds_dir->dd_pool, 797 NULL, dsl_prop_set_sync, ds, &psa, 2); 798 799 dsl_dataset_rele(ds, FTAG); 800 return (err); 801 } 802 803 int 804 dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props) 805 { 806 dsl_dataset_t *ds; 807 uint64_t version; 808 nvpair_t *elem = NULL; 809 dsl_props_arg_t pa; 810 int err; 811 812 if (err = dsl_dataset_hold(dsname, FTAG, &ds)) 813 return (err); 814 /* 815 * Do these checks before the syncfunc, since it can't fail. 816 */ 817 version = spa_version(ds->ds_dir->dd_pool->dp_spa); 818 while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { 819 if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { 820 dsl_dataset_rele(ds, FTAG); 821 return (ENAMETOOLONG); 822 } 823 if (nvpair_type(elem) == DATA_TYPE_STRING) { 824 char *valstr; 825 VERIFY(nvpair_value_string(elem, &valstr) == 0); 826 if (strlen(valstr) >= (version < 827 SPA_VERSION_STMF_PROP ? 828 ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) { 829 dsl_dataset_rele(ds, FTAG); 830 return (E2BIG); 831 } 832 } 833 } 834 835 if (dsl_dataset_is_snapshot(ds) && 836 version < SPA_VERSION_SNAP_PROPS) { 837 dsl_dataset_rele(ds, FTAG); 838 return (ENOTSUP); 839 } 840 841 pa.pa_props = props; 842 pa.pa_source = source; 843 844 err = dsl_sync_task_do(ds->ds_dir->dd_pool, 845 NULL, dsl_props_set_sync, ds, &pa, 2); 846 847 dsl_dataset_rele(ds, FTAG); 848 return (err); 849 } 850 851 typedef enum dsl_prop_getflags { 852 DSL_PROP_GET_INHERITING = 0x1, /* searching parent of target ds */ 853 DSL_PROP_GET_SNAPSHOT = 0x2, /* snapshot dataset */ 854 DSL_PROP_GET_LOCAL = 0x4, /* local properties */ 855 DSL_PROP_GET_RECEIVED = 0x8 /* received properties */ 856 } dsl_prop_getflags_t; 857 858 static int 859 dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj, 860 const char *setpoint, dsl_prop_getflags_t flags, nvlist_t *nv) 861 { 862 zap_cursor_t zc; 863 zap_attribute_t za; 864 int err = 0; 865 866 for (zap_cursor_init(&zc, mos, propobj); 867 (err = zap_cursor_retrieve(&zc, &za)) == 0; 868 zap_cursor_advance(&zc)) { 869 nvlist_t *propval; 870 zfs_prop_t prop; 871 char buf[ZAP_MAXNAMELEN]; 872 char *valstr; 873 const char *suffix; 874 const char *propname; 875 const char *source; 876 877 suffix = strchr(za.za_name, '$'); 878 879 if (suffix == NULL) { 880 /* 881 * Skip local properties if we only want received 882 * properties. 883 */ 884 if (flags & DSL_PROP_GET_RECEIVED) 885 continue; 886 887 propname = za.za_name; 888 source = setpoint; 889 } else if (strcmp(suffix, ZPROP_INHERIT_SUFFIX) == 0) { 890 /* Skip explicitly inherited entries. */ 891 continue; 892 } else if (strcmp(suffix, ZPROP_RECVD_SUFFIX) == 0) { 893 if (flags & DSL_PROP_GET_LOCAL) 894 continue; 895 896 (void) strncpy(buf, za.za_name, (suffix - za.za_name)); 897 buf[suffix - za.za_name] = '\0'; 898 propname = buf; 899 900 if (!(flags & DSL_PROP_GET_RECEIVED)) { 901 /* Skip if locally overridden. */ 902 err = zap_contains(mos, propobj, propname); 903 if (err == 0) 904 continue; 905 if (err != ENOENT) 906 break; 907 908 /* Skip if explicitly inherited. */ 909 valstr = kmem_asprintf("%s%s", propname, 910 ZPROP_INHERIT_SUFFIX); 911 err = zap_contains(mos, propobj, valstr); 912 strfree(valstr); 913 if (err == 0) 914 continue; 915 if (err != ENOENT) 916 break; 917 } 918 919 source = ((flags & DSL_PROP_GET_INHERITING) ? 920 setpoint : ZPROP_SOURCE_VAL_RECVD); 921 } else { 922 /* 923 * For backward compatibility, skip suffixes we don't 924 * recognize. 925 */ 926 continue; 927 } 928 929 prop = zfs_name_to_prop(propname); 930 931 /* Skip non-inheritable properties. */ 932 if ((flags & DSL_PROP_GET_INHERITING) && prop != ZPROP_INVAL && 933 !zfs_prop_inheritable(prop)) 934 continue; 935 936 /* Skip properties not valid for this type. */ 937 if ((flags & DSL_PROP_GET_SNAPSHOT) && prop != ZPROP_INVAL && 938 !zfs_prop_valid_for_type(prop, ZFS_TYPE_SNAPSHOT)) 939 continue; 940 941 /* Skip properties already defined. */ 942 if (nvlist_exists(nv, propname)) 943 continue; 944 945 VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); 946 if (za.za_integer_length == 1) { 947 /* 948 * String property 949 */ 950 char *tmp = kmem_alloc(za.za_num_integers, 951 KM_SLEEP); 952 err = zap_lookup(mos, propobj, 953 za.za_name, 1, za.za_num_integers, tmp); 954 if (err != 0) { 955 kmem_free(tmp, za.za_num_integers); 956 break; 957 } 958 VERIFY(nvlist_add_string(propval, ZPROP_VALUE, 959 tmp) == 0); 960 kmem_free(tmp, za.za_num_integers); 961 } else { 962 /* 963 * Integer property 964 */ 965 ASSERT(za.za_integer_length == 8); 966 (void) nvlist_add_uint64(propval, ZPROP_VALUE, 967 za.za_first_integer); 968 } 969 970 VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, source) == 0); 971 VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0); 972 nvlist_free(propval); 973 } 974 zap_cursor_fini(&zc); 975 if (err == ENOENT) 976 err = 0; 977 return (err); 978 } 979 980 /* 981 * Iterate over all properties for this dataset and return them in an nvlist. 982 */ 983 static int 984 dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp, 985 dsl_prop_getflags_t flags) 986 { 987 dsl_dir_t *dd = ds->ds_dir; 988 dsl_pool_t *dp = dd->dd_pool; 989 objset_t *mos = dp->dp_meta_objset; 990 int err = 0; 991 char setpoint[MAXNAMELEN]; 992 993 VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 994 995 if (dsl_dataset_is_snapshot(ds)) 996 flags |= DSL_PROP_GET_SNAPSHOT; 997 998 rw_enter(&dp->dp_config_rwlock, RW_READER); 999 1000 if (ds->ds_phys->ds_props_obj != 0) { 1001 ASSERT(flags & DSL_PROP_GET_SNAPSHOT); 1002 dsl_dataset_name(ds, setpoint); 1003 err = dsl_prop_get_all_impl(mos, ds->ds_phys->ds_props_obj, 1004 setpoint, flags, *nvp); 1005 if (err) 1006 goto out; 1007 } 1008 1009 for (; dd != NULL; dd = dd->dd_parent) { 1010 if (dd != ds->ds_dir || (flags & DSL_PROP_GET_SNAPSHOT)) { 1011 if (flags & (DSL_PROP_GET_LOCAL | 1012 DSL_PROP_GET_RECEIVED)) 1013 break; 1014 flags |= DSL_PROP_GET_INHERITING; 1015 } 1016 dsl_dir_name(dd, setpoint); 1017 err = dsl_prop_get_all_impl(mos, dd->dd_phys->dd_props_zapobj, 1018 setpoint, flags, *nvp); 1019 if (err) 1020 break; 1021 } 1022 out: 1023 rw_exit(&dp->dp_config_rwlock); 1024 return (err); 1025 } 1026 1027 boolean_t 1028 dsl_prop_get_hasrecvd(objset_t *os) 1029 { 1030 dsl_dataset_t *ds = os->os_dsl_dataset; 1031 int rc; 1032 uint64_t dummy; 1033 1034 rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER); 1035 rc = dsl_prop_get_ds(ds, ZPROP_HAS_RECVD, 8, 1, &dummy, NULL); 1036 rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock); 1037 ASSERT(rc != 0 || spa_version(os->os_spa) >= SPA_VERSION_RECVD_PROPS); 1038 return (rc == 0); 1039 } 1040 1041 static void 1042 dsl_prop_set_hasrecvd_impl(objset_t *os, zprop_source_t source) 1043 { 1044 dsl_dataset_t *ds = os->os_dsl_dataset; 1045 uint64_t dummy = 0; 1046 dsl_prop_setarg_t psa; 1047 1048 if (spa_version(os->os_spa) < SPA_VERSION_RECVD_PROPS) 1049 return; 1050 1051 dsl_prop_setarg_init_uint64(&psa, ZPROP_HAS_RECVD, source, &dummy); 1052 1053 (void) dsl_sync_task_do(ds->ds_dir->dd_pool, NULL, 1054 dsl_prop_set_sync, ds, &psa, 2); 1055 } 1056 1057 /* 1058 * Call after successfully receiving properties to ensure that only the first 1059 * receive on or after SPA_VERSION_RECVD_PROPS blows away local properties. 1060 */ 1061 void 1062 dsl_prop_set_hasrecvd(objset_t *os) 1063 { 1064 if (dsl_prop_get_hasrecvd(os)) { 1065 ASSERT(spa_version(os->os_spa) >= SPA_VERSION_RECVD_PROPS); 1066 return; 1067 } 1068 dsl_prop_set_hasrecvd_impl(os, ZPROP_SRC_LOCAL); 1069 } 1070 1071 void 1072 dsl_prop_unset_hasrecvd(objset_t *os) 1073 { 1074 dsl_prop_set_hasrecvd_impl(os, ZPROP_SRC_NONE); 1075 } 1076 1077 int 1078 dsl_prop_get_all(objset_t *os, nvlist_t **nvp) 1079 { 1080 return (dsl_prop_get_all_ds(os->os_dsl_dataset, nvp, 0)); 1081 } 1082 1083 int 1084 dsl_prop_get_received(objset_t *os, nvlist_t **nvp) 1085 { 1086 /* 1087 * Received properties are not distinguishable from local properties 1088 * until the dataset has received properties on or after 1089 * SPA_VERSION_RECVD_PROPS. 1090 */ 1091 dsl_prop_getflags_t flags = (dsl_prop_get_hasrecvd(os) ? 1092 DSL_PROP_GET_RECEIVED : DSL_PROP_GET_LOCAL); 1093 return (dsl_prop_get_all_ds(os->os_dsl_dataset, nvp, flags)); 1094 } 1095 1096 void 1097 dsl_prop_nvlist_add_uint64(nvlist_t *nv, zfs_prop_t prop, uint64_t value) 1098 { 1099 nvlist_t *propval; 1100 const char *propname = zfs_prop_to_name(prop); 1101 uint64_t default_value; 1102 1103 if (nvlist_lookup_nvlist(nv, propname, &propval) == 0) { 1104 VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0); 1105 return; 1106 } 1107 1108 VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); 1109 VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0); 1110 /* Indicate the default source if we can. */ 1111 if (dodefault(propname, 8, 1, &default_value) == 0 && 1112 value == default_value) { 1113 VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, "") == 0); 1114 } 1115 VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0); 1116 nvlist_free(propval); 1117 } 1118 1119 void 1120 dsl_prop_nvlist_add_string(nvlist_t *nv, zfs_prop_t prop, const char *value) 1121 { 1122 nvlist_t *propval; 1123 const char *propname = zfs_prop_to_name(prop); 1124 1125 if (nvlist_lookup_nvlist(nv, propname, &propval) == 0) { 1126 VERIFY(nvlist_add_string(propval, ZPROP_VALUE, value) == 0); 1127 return; 1128 } 1129 1130 VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0); 1131 VERIFY(nvlist_add_string(propval, ZPROP_VALUE, value) == 0); 1132 VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0); 1133 nvlist_free(propval); 1134 } 1135