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()

*** 21,30 **** --- 21,31 ---- /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015 by Delphix. All rights reserved. * Copyright (c) 2013 Martin Matuska. All rights reserved. * Copyright 2015, Joyent, Inc. + * Copyright 2016 Nexenta Systems, Inc. All rights reserved. */ #include <sys/zfs_context.h> #include <sys/dmu.h> #include <sys/dmu_objset.h>
*** 31,49 **** #include <sys/dmu_tx.h> #include <sys/dsl_dataset.h> #include <sys/dsl_dir.h> #include <sys/dsl_prop.h> #include <sys/dsl_synctask.h> #include <sys/spa.h> #include <sys/zap.h> #include <sys/fs/zfs.h> #include "zfs_prop.h" - #define ZPROP_INHERIT_SUFFIX "$inherit" - #define ZPROP_RECVD_SUFFIX "$recvd" - static int dodefault(zfs_prop_t prop, int intsz, int numints, void *buf) { /* * The setonce properties are read-only, BUT they still --- 32,50 ---- #include <sys/dmu_tx.h> #include <sys/dsl_dataset.h> #include <sys/dsl_dir.h> #include <sys/dsl_prop.h> #include <sys/dsl_synctask.h> + #include <sys/zfeature.h> #include <sys/spa.h> #include <sys/zap.h> #include <sys/fs/zfs.h> + #include <sys/wbc.h> #include "zfs_prop.h" + #include "zfs_errno.h" static int dodefault(zfs_prop_t prop, int intsz, int numints, void *buf) { /* * The setonce properties are read-only, BUT they still
*** 285,295 **** --- 286,305 ---- dsl_prop_cb_record_t *cbr; int err; ASSERT(dsl_pool_config_held(dp)); + if (zfs_name_to_prop(propname) == ZFS_PROP_WBC_MODE) { + wbc_mode_prop_val_t val; + + err = dsl_prop_get_ds(ds, propname, 8, + WBC_MODE_PROP_VAL_SZ, &val, NULL); + if (err == 0) + value = (uintptr_t)((void *)&val); + } else err = dsl_prop_get_int_ds(ds, propname, &value); + if (err != 0) return (err); cbr = kmem_alloc(sizeof (dsl_prop_cb_record_t), KM_SLEEP); cbr->cbr_ds = ds;
*** 475,484 **** --- 485,495 ---- for (pr = list_head(&dd->dd_props); pr; pr = list_next(&dd->dd_props, pr)) { for (cbr = list_head(&pr->pr_cbs); cbr; cbr = list_next(&pr->pr_cbs, cbr)) { uint64_t value; + const char *propname; /* * Callback entries do not have holds on their * datasets so that datasets with registered * callbacks are still eligible for eviction.
*** 502,515 **** */ if (ds != cbr->cbr_ds && !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) continue; ! if (dsl_prop_get_ds(cbr->cbr_ds, ! cbr->cbr_pr->pr_propname, sizeof (value), 1, ! &value, NULL) == 0) cbr->cbr_func(cbr->cbr_arg, value); if (ds != cbr->cbr_ds) dsl_dataset_rele(cbr->cbr_ds, FTAG); } } --- 513,535 ---- */ if (ds != cbr->cbr_ds && !dsl_dataset_try_add_ref(dp, cbr->cbr_ds, FTAG)) continue; ! propname = cbr->cbr_pr->pr_propname; ! if (zfs_name_to_prop(propname) == ZFS_PROP_WBC_MODE) { ! wbc_mode_prop_val_t val; ! ! if (dsl_prop_get_ds(cbr->cbr_ds, propname, 8, ! WBC_MODE_PROP_VAL_SZ, &val, NULL) == 0) { ! value = (uintptr_t)((void *)&val); cbr->cbr_func(cbr->cbr_arg, value); + } + } else if (dsl_prop_get_ds(cbr->cbr_ds, propname, + sizeof (value), 1, &value, NULL) == 0) { + cbr->cbr_func(cbr->cbr_arg, value); + } if (ds != cbr->cbr_ds) dsl_dataset_rele(cbr->cbr_ds, FTAG); } }
*** 618,628 **** const char *valstr = NULL; char *inheritstr; char *recvdstr; char *tbuf = NULL; int err; ! uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa); isint = (dodefault(zfs_name_to_prop(propname), 8, 1, &intval) == 0); if (ds->ds_is_snapshot) { ASSERT(version >= SPA_VERSION_SNAP_PROPS); --- 638,649 ---- const char *valstr = NULL; char *inheritstr; char *recvdstr; char *tbuf = NULL; int err; ! spa_t *spa = ds->ds_dir->dd_pool->dp_spa; ! uint64_t version = spa_version(spa); isint = (dodefault(zfs_name_to_prop(propname), 8, 1, &intval) == 0); if (ds->ds_is_snapshot) { ASSERT(version >= SPA_VERSION_SNAP_PROPS);
*** 716,726 **** } strfree(inheritstr); strfree(recvdstr); ! if (isint) { VERIFY0(dsl_prop_get_int_ds(ds, propname, &intval)); if (ds->ds_is_snapshot) { dsl_prop_cb_record_t *cbr; /* --- 737,787 ---- } strfree(inheritstr); strfree(recvdstr); ! if (zfs_name_to_prop(propname) == ZFS_PROP_WBC_MODE) { ! wbc_mode_prop_val_t val; ! ! VERIFY0(dsl_prop_get_ds(ds, propname, 8, ! WBC_MODE_PROP_VAL_SZ, &val, NULL)); ! ! dsl_prop_changed_notify(ds->ds_dir->dd_pool, ! ds->ds_dir->dd_object, propname, ! (uintptr_t)((void *)&val), TRUE); ! ! /* ! * Flow diagram of ZFS_PROP_WBC_MODE states ! * ! * off (root_ds_object == 0, txg_off == 0) ! * (user sees wbc_mode=off, source=default) ! * ! * user operation "set on" ==>> ! * ! * on (root_ds_object != 0, txg_off == 0) ! * (user sees wbc_mode=on, source=local) ! * ! * user operation "set off" ==>> ! * ! * off_delayed (root_ds_object != 0, txg_off != 0) ! * (user sees wbc_mode=off, source=local) ! * ! * internal operation "inherit" ==>> ! * ! * off (root_ds_object == 0, txg_off == 0) ! * (user sees wbc_mode=off, source=default) ! */ ! if (val.root_ds_object == 0) ! spa_feature_decr(spa, SPA_FEATURE_WBC, tx); ! else if (val.txg_off == 0) ! spa_feature_incr(spa, SPA_FEATURE_WBC, tx); ! ! (void) snprintf(valbuf, sizeof (valbuf), ! "%s", (val.root_ds_object != 0 && ! val.txg_off == 0) ? "on" : "off"); ! valstr = valbuf; ! } else if (isint) { VERIFY0(dsl_prop_get_int_ds(ds, propname, &intval)); if (ds->ds_is_snapshot) { dsl_prop_cb_record_t *cbr; /*
*** 800,809 **** --- 861,939 ---- error = dsl_props_set(dsname, source, nvl); fnvlist_free(nvl); return (error); } + /* ARGSUSED */ + static int + dsl_prop_wbc_mode_check_child_cb(dsl_pool_t *dp, + dsl_dataset_t *ds, void *arg) + { + int err; + zfs_prop_t *prop = arg; + objset_t *os = NULL; + + err = dmu_objset_from_ds(ds, &os); + if (err != 0) + return (err); + + if (*prop == ZFS_PROP_DEDUP) { + /* + * User tries to set ZFS_PROP_DEDUP. + * In this case we just check that + * the target DS and its children + * do not use writecache + */ + if (os->os_wbc_mode != ZFS_WBC_MODE_OFF) + return (SET_ERROR(EKZFS_WBCCONFLICT)); + } else { + ASSERT3U(*prop, ==, ZFS_PROP_WBC_MODE); + + /* + * User tries to set ZFS_PROP_WBC_MODE. + * In this case we need check that + * the target DS and its children + * do not use writecache and dedup + */ + if (os->os_wbc_mode != ZFS_WBC_MODE_OFF) + return (SET_ERROR(EKZFS_WBCCHILD)); + + if (os->os_dedup_checksum != ZIO_CHECKSUM_OFF) + return (SET_ERROR(EKZFS_WBCCONFLICT)); + } + + return (0); + } + + static int + dsl_prop_wbc_mode_check(dsl_dataset_t *ds, objset_t *os) + { + int err = 0; + zfs_prop_t prop = ZFS_PROP_WBC_MODE; + + if (os->os_wbc_mode != ZFS_WBC_MODE_OFF) { + /* + * ZFS_PROP_WBC_MODE cannot be set for + * a child DS if the prop was set for + * the parent + */ + if (os->os_wbc_root_ds_obj != ds->ds_object) + return (SET_ERROR(EKZFS_WBCPARENT)); + } else { + /* + * Is not allowed to change wbc_mode for parent + * if its children already have the changed prop + */ + err = dmu_objset_find_dp(ds->ds_dir->dd_pool, + ds->ds_dir->dd_object, + dsl_prop_wbc_mode_check_child_cb, &prop, + DS_FIND_CHILDREN); + } + + return (err); + } + typedef struct dsl_props_set_arg { const char *dpsa_dsname; zprop_source_t dpsa_source; nvlist_t *dpsa_props; } dsl_props_set_arg_t;
*** 812,844 **** dsl_props_set_check(void *arg, dmu_tx_t *tx) { dsl_props_set_arg_t *dpsa = arg; dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dataset_t *ds; uint64_t version; nvpair_t *elem = NULL; int err; err = dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds); if (err != 0) return (err); version = spa_version(ds->ds_dir->dd_pool->dp_spa); while ((elem = nvlist_next_nvpair(dpsa->dpsa_props, elem)) != NULL) { ! if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(ENAMETOOLONG)); } if (nvpair_type(elem) == DATA_TYPE_STRING) { char *valstr = fnvpair_value_string(elem); if (strlen(valstr) >= (version < SPA_VERSION_STMF_PROP ? ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) { dsl_dataset_rele(ds, FTAG); ! return (E2BIG); } } } if (ds->ds_is_snapshot && version < SPA_VERSION_SNAP_PROPS) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(ENOTSUP)); --- 942,1061 ---- dsl_props_set_check(void *arg, dmu_tx_t *tx) { dsl_props_set_arg_t *dpsa = arg; dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dataset_t *ds; + objset_t *os = NULL; uint64_t version; nvpair_t *elem = NULL; int err; err = dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds); if (err != 0) return (err); + err = dmu_objset_from_ds(ds, &os); + if (err != 0) { + dsl_dataset_rele(ds, FTAG); + return (err); + } + version = spa_version(ds->ds_dir->dd_pool->dp_spa); while ((elem = nvlist_next_nvpair(dpsa->dpsa_props, elem)) != NULL) { ! const char *prop_name = nvpair_name(elem); ! zfs_prop_t prop = zfs_name_to_prop(prop_name); ! ! if (strlen(prop_name) >= ZAP_MAXNAMELEN) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(ENAMETOOLONG)); } + + /* + * Deduplication and WBC cannot be used together + * This code returns error also for case when + * WBC is ON, DEDUP is off and a user tries + * to do DEDUP=off, because in this case the code + * will be more complex, but benefit is too small + */ + if (prop == ZFS_PROP_DEDUP) { + if (os->os_wbc_root_ds_obj != 0) { + dsl_dataset_rele(ds, FTAG); + return (SET_ERROR(EKZFS_WBCCONFLICT)); + } + + /* + * Need to be sure that children DS + * do not use writecache + */ + err = dmu_objset_find_dp(ds->ds_dir->dd_pool, + ds->ds_dir->dd_object, + dsl_prop_wbc_mode_check_child_cb, &prop, + DS_FIND_CHILDREN); + if (err != 0) { + dsl_dataset_rele(ds, FTAG); + return (err); + } + } + + if (prop == ZFS_PROP_WBC_MODE) { + uint64_t wbc_mode_new = 0; + data_type_t elem_type = nvpair_type(elem); + + if (elem_type == DATA_TYPE_UINT64) + wbc_mode_new = fnvpair_value_uint64(elem); + + if (os->os_wbc_root_ds_obj == ds->ds_object && + elem_type == DATA_TYPE_UINT64) { + + /* + * ZFS_WBC_MODE_OFF_DELAYED means that + * the coresponding wbc_instance is in + * transition state: from ON to OFF + * so ON/OFF is not permitted + */ + if (os->os_wbc_mode == + ZFS_WBC_MODE_OFF_DELAYED) { + dsl_dataset_rele(ds, FTAG); + return (SET_ERROR(EINPROGRESS)); + } + + ASSERT3U(os->os_wbc_mode, ==, ZFS_WBC_MODE_ON); + + /* Check for double ON */ + if (wbc_mode_new == ZFS_WBC_MODE_ON) { + dsl_dataset_rele(ds, FTAG); + return (SET_ERROR(EALREADY)); + } + } + + err = dsl_prop_wbc_mode_check(ds, os); + if (err != 0) { + dsl_dataset_rele(ds, FTAG); + return (err); + } + + /* Check for double OFF */ + if (os->os_wbc_root_ds_obj == 0 && + elem_type == DATA_TYPE_UINT64 && + wbc_mode_new == ZFS_WBC_MODE_OFF) { + dsl_dataset_rele(ds, FTAG); + return (SET_ERROR(EALREADY)); + } + + continue; + } + if (nvpair_type(elem) == DATA_TYPE_STRING) { char *valstr = fnvpair_value_string(elem); if (strlen(valstr) >= (version < SPA_VERSION_STMF_PROP ? ZAP_OLDMAXVALUELEN : ZAP_MAXVALUELEN)) { dsl_dataset_rele(ds, FTAG); ! return (SET_ERROR(E2BIG)); } } + } if (ds->ds_is_snapshot && version < SPA_VERSION_SNAP_PROPS) { dsl_dataset_rele(ds, FTAG); return (SET_ERROR(ENOTSUP));
*** 853,886 **** { nvpair_t *elem = NULL; while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { nvpair_t *pair = elem; - const char *name = nvpair_name(pair); if (nvpair_type(pair) == DATA_TYPE_NVLIST) { /* ! * This usually happens when we reuse the nvlist_t data ! * returned by the counterpart dsl_prop_get_all_impl(). ! * For instance we do this to restore the original ! * received properties when an error occurs in the ! * zfs_ioc_recv() codepath. */ nvlist_t *attrs = fnvpair_value_nvlist(pair); pair = fnvlist_lookup_nvpair(attrs, ZPROP_VALUE); } if (nvpair_type(pair) == DATA_TYPE_STRING) { const char *value = fnvpair_value_string(pair); ! dsl_prop_set_sync_impl(ds, name, source, 1, strlen(value) + 1, value, tx); } else if (nvpair_type(pair) == DATA_TYPE_UINT64) { uint64_t intval = fnvpair_value_uint64(pair); ! dsl_prop_set_sync_impl(ds, name, source, sizeof (intval), 1, &intval, tx); } else if (nvpair_type(pair) == DATA_TYPE_BOOLEAN) { ! dsl_prop_set_sync_impl(ds, name, source, 0, 0, NULL, tx); } else { panic("invalid nvpair type"); } } --- 1070,1125 ---- { nvpair_t *elem = NULL; while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { nvpair_t *pair = elem; if (nvpair_type(pair) == DATA_TYPE_NVLIST) { /* ! * dsl_prop_get_all_impl() returns properties in this ! * format. */ nvlist_t *attrs = fnvpair_value_nvlist(pair); pair = fnvlist_lookup_nvpair(attrs, ZPROP_VALUE); } if (nvpair_type(pair) == DATA_TYPE_STRING) { const char *value = fnvpair_value_string(pair); ! dsl_prop_set_sync_impl(ds, nvpair_name(pair), source, 1, strlen(value) + 1, value, tx); } else if (nvpair_type(pair) == DATA_TYPE_UINT64) { + const char *propname = nvpair_name(pair); + zfs_prop_t prop = zfs_name_to_prop(propname); uint64_t intval = fnvpair_value_uint64(pair); ! ! if (prop == ZFS_PROP_WBC_MODE) { ! wbc_mode_prop_val_t val; ! ! /* ! * Disabling WBC involves the following: ! * 1) all the subsequent data writes will ! * stop using special vdev ! * 2) already WriteBackCached data blocks ! * (with TXG <= txg_off below) will gradually ! * migrated from special vdev ! * ! * To handle this need to remember TXG. ! * WBC will be completely disabled for this DS, ! * after WBC-window cross this TXG ! */ ! val.txg_off = (intval == 0) ? tx->tx_txg : 0; ! val.root_ds_object = ds->ds_object; ! val.flags = 0; ! ! dsl_prop_set_sync_impl(ds, nvpair_name(pair), ! source, 8, WBC_MODE_PROP_VAL_SZ, &val, tx); ! } else { ! dsl_prop_set_sync_impl(ds, nvpair_name(pair), source, sizeof (intval), 1, &intval, tx); + } } else if (nvpair_type(pair) == DATA_TYPE_BOOLEAN) { ! dsl_prop_set_sync_impl(ds, nvpair_name(pair), source, 0, 0, NULL, tx); } else { panic("invalid nvpair type"); } }
*** 890,901 **** --- 1129,1151 ---- dsl_props_set_sync(void *arg, dmu_tx_t *tx) { dsl_props_set_arg_t *dpsa = arg; dsl_pool_t *dp = dmu_tx_pool(tx); dsl_dataset_t *ds; + objset_t *os = NULL; VERIFY0(dsl_dataset_hold(dp, dpsa->dpsa_dsname, FTAG, &ds)); + /* + * Need to initialize os, to be sure that non-mounted datasets and + * non-exposed zvols will receive notification about modified + * properties. + * During the initialization a property can register its callback + * that will be called if the property is changed. + * dsl_props_set_sync_impl() calls dsl_prop_changed_notify() + * that calls the required callback if it exists. + */ + VERIFY0(dmu_objset_from_ds(ds, &os)); dsl_props_set_sync_impl(ds, dpsa->dpsa_source, dpsa->dpsa_props, tx); dsl_dataset_rele(ds, FTAG); } /*
*** 920,929 **** --- 1170,1266 ---- return (dsl_sync_task(dsname, dsl_props_set_check, dsl_props_set_sync, &dpsa, nblks, ZFS_SPACE_CHECK_RESERVED)); } + static void + dsl_props_mds_set_sync(void *arg, dmu_tx_t *tx) + { + dsl_props_set_arg_t *top_dpsa = arg; + dsl_pool_t *dp = dmu_tx_pool(tx); + nvlist_t *dss_props = top_dpsa->dpsa_props; + nvpair_t *pair = NULL; + + while ((pair = nvlist_next_nvpair(dss_props, pair)) != NULL) { + dsl_props_set_arg_t dpsa; + dsl_dataset_t *ds = NULL; + const char *ds_name; + + ds_name = nvpair_name(pair); + VERIFY0(dsl_dataset_hold(dp, ds_name, FTAG, &ds)); + + dpsa.dpsa_dsname = ds_name; + dpsa.dpsa_source = ZPROP_SRC_LOCAL; + dpsa.dpsa_props = fnvpair_value_nvlist(pair); + + dsl_props_set_sync(&dpsa, tx); + dsl_dataset_rele(ds, FTAG); + } + } + + static int + dsl_props_mds_set_check(void *arg, dmu_tx_t *tx) + { + dsl_props_set_arg_t *top_dpsa = arg; + dsl_pool_t *dp = dmu_tx_pool(tx); + nvlist_t *dss_props = top_dpsa->dpsa_props; + nvpair_t *pair = NULL; + + while ((pair = nvlist_next_nvpair(dss_props, pair)) != NULL) { + dsl_props_set_arg_t dpsa; + dsl_dataset_t *ds = NULL; + const char *ds_name; + int err; + + ds_name = nvpair_name(pair); + err = dsl_dataset_hold(dp, ds_name, FTAG, &ds); + if (err != 0) + return (err); + + if (nvpair_type(pair) != DATA_TYPE_NVLIST) { + dsl_dataset_rele(ds, FTAG); + return (SET_ERROR(EINVAL)); + } + + dpsa.dpsa_dsname = ds_name; + dpsa.dpsa_source = ZPROP_SRC_LOCAL; + dpsa.dpsa_props = fnvpair_value_nvlist(pair); + + err = dsl_props_set_check(&dpsa, tx); + dsl_dataset_rele(ds, FTAG); + if (err != 0) + return (err); + } + + return (0); + } + + + /* + * The given 'dss_props' nvlist represents the following struct: + * ds1 -> prop1:value + * -> prop3:value + * ds2 -> prop1:value + * -> prop2:value + * + * All-or-nothing: if any prop can't be set, nothing will be modified. + */ + int + dsl_props_set_mds(const char *pool_name, nvlist_t *dss_props, + size_t num_props) + { + dsl_props_set_arg_t dpsa; + + dpsa.dpsa_dsname = pool_name; + dpsa.dpsa_source = ZPROP_SRC_LOCAL; + dpsa.dpsa_props = dss_props; + + return (dsl_sync_task(pool_name, dsl_props_mds_set_check, + dsl_props_mds_set_sync, &dpsa, 2 * num_props, + ZFS_SPACE_CHECK_RESERVED)); + } + typedef enum dsl_prop_getflags { DSL_PROP_GET_INHERITING = 0x1, /* searching parent of target ds */ DSL_PROP_GET_SNAPSHOT = 0x2, /* snapshot dataset */ DSL_PROP_GET_LOCAL = 0x4, /* local properties */ DSL_PROP_GET_RECEIVED = 0x8 /* received properties */
*** 1027,1044 **** --- 1364,1401 ---- za.za_name, 1, za.za_num_integers, tmp); if (err != 0) { kmem_free(tmp, za.za_num_integers); break; } + VERIFY(nvlist_add_string(propval, ZPROP_VALUE, tmp) == 0); kmem_free(tmp, za.za_num_integers); } else { /* * Integer property */ ASSERT(za.za_integer_length == 8); + + if (prop == ZFS_PROP_WBC_MODE) { + wbc_mode_prop_val_t val; + + ASSERT(za.za_num_integers == + WBC_MODE_PROP_VAL_SZ); + + err = zap_lookup(mos, propobj, + za.za_name, 8, za.za_num_integers, &val); + if (err != 0) + break; + + if (val.root_ds_object != 0 && + val.txg_off == 0) + za.za_first_integer = ZFS_WBC_MODE_ON; + else + za.za_first_integer = ZFS_WBC_MODE_OFF; + } + (void) nvlist_add_uint64(propval, ZPROP_VALUE, za.za_first_integer); } VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, source) == 0);