Print this page
NEX-16623 Ability to set properties for multiple datasets/snapshots during single sync-round
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-7822 40Gb Intel XL710 NIC performance data
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-8827 AUTOSNAP: can't register recursive zone when there is a child under autosnappool/volumegrou
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-5987 need to change ssm wearout threshold to 90%
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5925 KRRP: Incorrect collecting of snap-props causes errors during recv
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5341 Race condition causes wrc_004_pos to panic the system
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-5319 Panic trying to rename zvol used as COMSTAR lu
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-5060 WBC: Writecache and deduplication should not be used together
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4934 Add capability to remove special vdev
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-4830 writecache=off leaks data on special vdev (the data will never migrate)
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4608 WRC: Possible deadlock during the disabling of WRC for a dataset
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
6160 /usr/lib/fs/zfs/bootinstall should use bootadm
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Reviewed by: Adam Števko <adam.stevko@gmail.com>
Reviewed by: Josef Sipek <jeffpc@josefsipek.net>
Approved by: Richard Lowe <richlowe@richlowe.net>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (NULL is not an int)
6171 dsl_prop_unregister() slows down dataset eviction.
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Remaining fixes for the illumos merge
re #12619 rb4429 More dp->dp_config_rwlock holds
re #13253 rb4328 ssh: openssl version checking needs updating
re #11441 rb4292 panic in apic_record_rdt_entry on VMware hardware version 9
re #12619, rb4287 Deadlocked zfs txg processing in dsl_sync_task_group_sync()

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dsl_prop.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_prop.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
  24   24   * Copyright (c) 2013 Martin Matuska. All rights reserved.
  25   25   * Copyright 2015, Joyent, Inc.
       26 + * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  26   27   */
  27   28  
  28   29  #include <sys/zfs_context.h>
  29   30  #include <sys/dmu.h>
  30   31  #include <sys/dmu_objset.h>
  31   32  #include <sys/dmu_tx.h>
  32   33  #include <sys/dsl_dataset.h>
  33   34  #include <sys/dsl_dir.h>
  34   35  #include <sys/dsl_prop.h>
  35   36  #include <sys/dsl_synctask.h>
       37 +#include <sys/zfeature.h>
  36   38  #include <sys/spa.h>
  37   39  #include <sys/zap.h>
  38   40  #include <sys/fs/zfs.h>
       41 +#include <sys/wbc.h>
  39   42  
  40   43  #include "zfs_prop.h"
       44 +#include "zfs_errno.h"
  41   45  
  42      -#define ZPROP_INHERIT_SUFFIX "$inherit"
  43      -#define ZPROP_RECVD_SUFFIX "$recvd"
  44      -
  45   46  static int
  46   47  dodefault(zfs_prop_t prop, int intsz, int numints, void *buf)
  47   48  {
  48   49          /*
  49   50           * The setonce properties are read-only, BUT they still
  50   51           * have a default value that can be used as the initial
  51   52           * value.
  52   53           */
  53   54          if (prop == ZPROP_INVAL ||
  54   55              (zfs_prop_readonly(prop) && !zfs_prop_setonce(prop)))
↓ open down ↓ 225 lines elided ↑ open up ↑
 280  281  {
 281  282          dsl_dir_t *dd = ds->ds_dir;
 282  283          dsl_pool_t *dp = dd->dd_pool;
 283  284          uint64_t value;
 284  285          dsl_prop_record_t *pr;
 285  286          dsl_prop_cb_record_t *cbr;
 286  287          int err;
 287  288  
 288  289          ASSERT(dsl_pool_config_held(dp));
 289  290  
 290      -        err = dsl_prop_get_int_ds(ds, propname, &value);
      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 +
 291  301          if (err != 0)
 292  302                  return (err);
 293  303  
 294  304          cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP);
 295  305          cbr->cbr_ds = ds;
 296  306          cbr->cbr_func = callback;
 297  307          cbr->cbr_arg = cbarg;
 298  308  
 299  309          mutex_enter(&dd->dd_lock);
 300  310          pr = dsl_prop_record_find(dd, propname);
↓ open down ↓ 169 lines elided ↑ open up ↑
 470  480          dsl_dir_t *dd = ds->ds_dir;
 471  481          dsl_prop_record_t *pr;
 472  482          dsl_prop_cb_record_t *cbr;
 473  483  
 474  484          mutex_enter(&dd->dd_lock);
 475  485          for (pr = list_head(&dd->dd_props);
 476  486              pr; pr = list_next(&dd->dd_props, pr)) {
 477  487                  for (cbr = list_head(&pr->pr_cbs); cbr;
 478  488                      cbr = list_next(&pr->pr_cbs, cbr)) {
 479  489                          uint64_t value;
      490 +                        const char *propname;
 480  491  
 481  492                          /*
 482  493                           * Callback entries do not have holds on their
 483  494                           * datasets so that datasets with registered
 484  495                           * callbacks are still eligible for eviction.
 485  496                           * Unlike operations to update properties on a
 486  497                           * single dataset, we are performing a recursive
 487  498                           * descent of related head datasets.  The caller
 488  499                           * of this function only has a dataset hold on
 489  500                           * the passed in head dataset, not the snapshots
↓ open down ↓ 7 lines elided ↑ open up ↑
 497  508                           * begun eviction processing and to prevent
 498  509                           * eviction from occurring for the duration of
 499  510                           * the callback.  If the hold attempt fails,
 500  511                           * this object is already being evicted and the
 501  512                           * callback can be safely ignored.
 502  513                           */
 503  514                          if (ds != cbr->cbr_ds &&
 504  515                              !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG))
 505  516                                  continue;
 506  517  
 507      -                        if (dsl_prop_get_ds(cbr->cbr_ds,
 508      -                            cbr->cbr_pr->pr_propname, sizeof (value), 1,
 509      -                            &value, NULL) == 0)
      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) {
 510  529                                  cbr->cbr_func(cbr->cbr_arg, value);
      530 +                        }
 511  531  
 512  532                          if (ds != cbr->cbr_ds)
 513  533                                  dsl_dataset_rele(cbr->cbr_ds, FTAG);
 514  534                  }
 515  535          }
 516  536          mutex_exit(&dd->dd_lock);
 517  537  
 518  538          return (0);
 519  539  }
 520  540  
↓ open down ↓ 92 lines elided ↑ open up ↑
 613  633  {
 614  634          objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
 615  635          uint64_t zapobj, intval, dummy;
 616  636          int isint;
 617  637          char valbuf[32];
 618  638          const char *valstr = NULL;
 619  639          char *inheritstr;
 620  640          char *recvdstr;
 621  641          char *tbuf = NULL;
 622  642          int err;
 623      -        uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa);
      643 +        spa_t *spa = ds->ds_dir->dd_pool->dp_spa;
      644 +        uint64_t version = spa_version(spa);
 624  645  
 625  646          isint = (dodefault(zfs_name_to_prop(propname), 8, 1, &intval) == 0);
 626  647  
 627  648          if (ds->ds_is_snapshot) {
 628  649                  ASSERT(version >= SPA_VERSION_SNAP_PROPS);
 629  650                  if (dsl_dataset_phys(ds)->ds_props_obj == 0) {
 630  651                          dmu_buf_will_dirty(ds->ds_dbuf, tx);
 631  652                          dsl_dataset_phys(ds)->ds_props_obj =
 632  653                              zap_create(mos,
 633  654                              DMU_OT_DSL_PROPS, DMU_OT_NONE, 0, tx);
↓ open down ↓ 77 lines elided ↑ open up ↑
 711  732                  err = zap_remove(mos, zapobj, recvdstr, tx);
 712  733                  ASSERT(err == 0 || err == ENOENT);
 713  734                  break;
 714  735          default:
 715  736                  cmn_err(CE_PANIC, "unexpected property source: %d", source);
 716  737          }
 717  738  
 718  739          strfree(inheritstr);
 719  740          strfree(recvdstr);
 720  741  
 721      -        if (isint) {
      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) {
 722  783                  VERIFY0(dsl_prop_get_int_ds(ds, propname, &intval));
 723  784  
 724  785                  if (ds->ds_is_snapshot) {
 725  786                          dsl_prop_cb_record_t *cbr;
 726  787                          /*
 727  788                           * It's a snapshot; nothing can inherit this
 728  789                           * property, so just look for callbacks on this
 729  790                           * ds here.
 730  791                           */
 731  792                          mutex_enter(&ds->ds_dir->dd_lock);
↓ open down ↓ 63 lines elided ↑ open up ↑
 795  856  {
 796  857          nvlist_t *nvl = fnvlist_alloc();
 797  858          int error;
 798  859  
 799  860          fnvlist_add_boolean(nvl, propname);
 800  861          error = dsl_props_set(dsname, source, nvl);
 801  862          fnvlist_free(nvl);
 802  863          return (error);
 803  864  }
 804  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 +
 805  935  typedef struct dsl_props_set_arg {
 806  936          const char *dpsa_dsname;
 807  937          zprop_source_t dpsa_source;
 808  938          nvlist_t *dpsa_props;
 809  939  } dsl_props_set_arg_t;
 810  940  
 811  941  static int
 812  942  dsl_props_set_check(void *arg, dmu_tx_t *tx)
 813  943  {
 814  944          dsl_props_set_arg_t *dpsa = arg;
 815  945          dsl_pool_t *dp = dmu_tx_pool(tx);
 816  946          dsl_dataset_t *ds;
      947 +        objset_t *os = NULL;
 817  948          uint64_t version;
 818  949          nvpair_t *elem = NULL;
 819  950          int err;
 820  951  
 821  952          err = dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds);
 822  953          if (err != 0)
 823  954                  return (err);
 824  955  
      956 +        err = dmu_objset_from_ds(ds, &os);
      957 +        if (err != 0) {
      958 +                dsl_dataset_rele(ds, FTAG);
      959 +                return (err);
      960 +        }
      961 +
 825  962          version = spa_version(ds->ds_dir->dd_pool->dp_spa);
 826  963          while ((elem = nvlist_next_nvpair(dpsa->dpsa_props, elem)) != NULL) {
 827      -                if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
      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) {
 828  968                          dsl_dataset_rele(ds, FTAG);
 829  969                          return (SET_ERROR(ENAMETOOLONG));
 830  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 +
 831 1047                  if (nvpair_type(elem) == DATA_TYPE_STRING) {
 832 1048                          char *valstr = fnvpair_value_string(elem);
 833 1049                          if (strlen(valstr) >= (version <
 834 1050                              SPA_VERSION_STMF_PROP ?
 835 1051                              ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) {
 836 1052                                  dsl_dataset_rele(ds, FTAG);
 837      -                                return (E2BIG);
     1053 +                                return (SET_ERROR(E2BIG));
 838 1054                          }
 839 1055                  }
     1056 +
 840 1057          }
 841 1058  
 842 1059          if (ds->ds_is_snapshot && version < SPA_VERSION_SNAP_PROPS) {
 843 1060                  dsl_dataset_rele(ds, FTAG);
 844 1061                  return (SET_ERROR(ENOTSUP));
 845 1062          }
 846 1063          dsl_dataset_rele(ds, FTAG);
 847 1064          return (0);
 848 1065  }
 849 1066  
 850 1067  void
 851 1068  dsl_props_set_sync_impl(dsl_dataset_t *ds, zprop_source_t source,
 852 1069      nvlist_t *props, dmu_tx_t *tx)
 853 1070  {
 854 1071          nvpair_t *elem = NULL;
 855 1072  
 856 1073          while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
 857 1074                  nvpair_t *pair = elem;
 858      -                const char *name = nvpair_name(pair);
 859 1075  
 860 1076                  if (nvpair_type(pair) == DATA_TYPE_NVLIST) {
 861 1077                          /*
 862      -                         * This usually happens when we reuse the nvlist_t data
 863      -                         * returned by the counterpart dsl_prop_get_all_impl().
 864      -                         * For instance we do this to restore the original
 865      -                         * received properties when an error occurs in the
 866      -                         * zfs_ioc_recv() codepath.
     1078 +                         * dsl_prop_get_all_impl() returns properties in this
     1079 +                         * format.
 867 1080                           */
 868 1081                          nvlist_t *attrs = fnvpair_value_nvlist(pair);
 869 1082                          pair = fnvlist_lookup_nvpair(attrs, ZPROP_VALUE);
 870 1083                  }
 871 1084  
 872 1085                  if (nvpair_type(pair) == DATA_TYPE_STRING) {
 873 1086                          const char *value = fnvpair_value_string(pair);
 874      -                        dsl_prop_set_sync_impl(ds, name,
     1087 +                        dsl_prop_set_sync_impl(ds, nvpair_name(pair),
 875 1088                              source, 1, strlen(value) + 1, value, tx);
 876 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);
 877 1092                          uint64_t intval = fnvpair_value_uint64(pair);
 878      -                        dsl_prop_set_sync_impl(ds, name,
 879      -                            source, sizeof (intval), 1, &intval, tx);
     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 +                        }
 880 1119                  } else if (nvpair_type(pair) == DATA_TYPE_BOOLEAN) {
 881      -                        dsl_prop_set_sync_impl(ds, name,
     1120 +                        dsl_prop_set_sync_impl(ds, nvpair_name(pair),
 882 1121                              source, 0, 0, NULL, tx);
 883 1122                  } else {
 884 1123                          panic("invalid nvpair type");
 885 1124                  }
 886 1125          }
 887 1126  }
 888 1127  
 889 1128  static void
 890 1129  dsl_props_set_sync(void *arg, dmu_tx_t *tx)
 891 1130  {
 892 1131          dsl_props_set_arg_t *dpsa = arg;
 893 1132          dsl_pool_t *dp = dmu_tx_pool(tx);
 894 1133          dsl_dataset_t *ds;
     1134 +        objset_t *os = NULL;
 895 1135  
 896 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));
 897 1147          dsl_props_set_sync_impl(ds, dpsa->dpsa_source, dpsa->dpsa_props, tx);
 898 1148          dsl_dataset_rele(ds, FTAG);
 899 1149  }
 900 1150  
 901 1151  /*
 902 1152   * All-or-nothing; if any prop can't be set, nothing will be modified.
 903 1153   */
 904 1154  int
 905 1155  dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
 906 1156  {
↓ open down ↓ 8 lines elided ↑ open up ↑
 915 1165           * If the source includes NONE, then we will only be removing entries
 916 1166           * from the ZAP object.  In that case don't check for ENOSPC.
 917 1167           */
 918 1168          if ((source & ZPROP_SRC_NONE) == 0)
 919 1169                  nblks = 2 * fnvlist_num_pairs(props);
 920 1170  
 921 1171          return (dsl_sync_task(dsname, dsl_props_set_check, dsl_props_set_sync,
 922 1172              &dpsa, nblks, ZFS_SPACE_CHECK_RESERVED));
 923 1173  }
 924 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 +
 925 1262  typedef enum dsl_prop_getflags {
 926 1263          DSL_PROP_GET_INHERITING = 0x1,  /* searching parent of target ds */
 927 1264          DSL_PROP_GET_SNAPSHOT = 0x2,    /* snapshot dataset */
 928 1265          DSL_PROP_GET_LOCAL = 0x4,       /* local properties */
 929 1266          DSL_PROP_GET_RECEIVED = 0x8     /* received properties */
 930 1267  } dsl_prop_getflags_t;
 931 1268  
 932 1269  static int
 933 1270  dsl_prop_get_all_impl(objset_t *mos, uint64_t propobj,
 934 1271      const char *setpoint, dsl_prop_getflags_t flags, nvlist_t *nv)
↓ open down ↓ 87 lines elided ↑ open up ↑
1022 1359                           * String property
1023 1360                           */
1024 1361                          char *tmp = kmem_alloc(za.za_num_integers,
1025 1362                              KM_SLEEP);
1026 1363                          err = zap_lookup(mos, propobj,
1027 1364                              za.za_name, 1, za.za_num_integers, tmp);
1028 1365                          if (err != 0) {
1029 1366                                  kmem_free(tmp, za.za_num_integers);
1030 1367                                  break;
1031 1368                          }
     1369 +
1032 1370                          VERIFY(nvlist_add_string(propval, ZPROP_VALUE,
1033 1371                              tmp) == 0);
1034 1372                          kmem_free(tmp, za.za_num_integers);
1035 1373                  } else {
1036 1374                          /*
1037 1375                           * Integer property
1038 1376                           */
1039 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 +
1040 1397                          (void) nvlist_add_uint64(propval, ZPROP_VALUE,
1041 1398                              za.za_first_integer);
1042 1399                  }
1043 1400  
1044 1401                  VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, source) == 0);
1045 1402                  VERIFY(nvlist_add_nvlist(nv, propname, propval) == 0);
1046 1403                  nvlist_free(propval);
1047 1404          }
1048 1405          zap_cursor_fini(&zc);
1049 1406          if (err == ENOENT)
↓ open down ↓ 161 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX