aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_ioctl.c')
-rw-r--r--module/zfs/zfs_ioctl.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 49ee55265..d032648b5 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -90,7 +90,7 @@ typedef struct zfs_ioc_vec {
boolean_t zvec_his_log;
} zfs_ioc_vec_t;
-static void clear_props(char *dataset, nvlist_t *props);
+static void clear_props(char *dataset, nvlist_t *props, nvlist_t *newprops);
static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
boolean_t *);
int zfs_set_prop_nvlist(const char *, nvlist_t *);
@@ -1322,6 +1322,14 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc)
(void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name));
p = zc->zc_name + strlen(zc->zc_name);
+ if (zc->zc_cookie == 0) {
+ uint64_t cookie = 0;
+ int len = sizeof (zc->zc_name) - (p - zc->zc_name);
+
+ while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0)
+ dmu_objset_prefetch(p, NULL);
+ }
+
do {
error = dmu_dir_list_next(os,
sizeof (zc->zc_name) - (p - zc->zc_name), p,
@@ -1365,6 +1373,9 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
if (error)
return (error == ENOENT ? ESRCH : error);
+ if (zc->zc_cookie == 0)
+ dmu_objset_find(zc->zc_name, dmu_objset_prefetch,
+ NULL, DS_FIND_SNAPSHOTS);
/*
* A dataset name of maximum length cannot have any snapshots,
* so exit immediately.
@@ -1606,7 +1617,7 @@ zfs_ioc_set_prop(zfs_cmd_t *zc)
if (dmu_objset_open(zc->zc_name, DMU_OST_ANY,
DS_MODE_USER | DS_MODE_READONLY, &os) == 0) {
if (dsl_prop_get_all(os, &origprops, TRUE) == 0) {
- clear_props(zc->zc_name, origprops);
+ clear_props(zc->zc_name, origprops, nvl);
nvlist_free(origprops);
}
dmu_objset_close(os);
@@ -1640,11 +1651,30 @@ zfs_ioc_pool_set_props(zfs_cmd_t *zc)
nvlist_t *props;
spa_t *spa;
int error;
+ nvpair_t *elem;
if ((error = get_nvlist(zc->zc_nvlist_src, zc->zc_nvlist_src_size,
&props)))
return (error);
+ /*
+ * If the only property is the configfile, then just do a spa_lookup()
+ * to handle the faulted case.
+ */
+ elem = nvlist_next_nvpair(props, NULL);
+ if (elem != NULL && strcmp(nvpair_name(elem),
+ zpool_prop_to_name(ZPOOL_PROP_CACHEFILE)) == 0 &&
+ nvlist_next_nvpair(props, elem) == NULL) {
+ mutex_enter(&spa_namespace_lock);
+ if ((spa = spa_lookup(zc->zc_name)) != NULL) {
+ spa_configfile_set(spa, props, B_FALSE);
+ spa_config_sync(spa, B_FALSE, B_TRUE);
+ }
+ mutex_exit(&spa_namespace_lock);
+ if (spa != NULL)
+ return (0);
+ }
+
if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
nvlist_free(props);
return (error);
@@ -1665,20 +1695,27 @@ zfs_ioc_pool_get_props(zfs_cmd_t *zc)
int error;
nvlist_t *nvp = NULL;
- if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0)
- return (error);
-
- error = spa_prop_get(spa, &nvp);
+ if ((error = spa_open(zc->zc_name, &spa, FTAG)) != 0) {
+ /*
+ * If the pool is faulted, there may be properties we can still
+ * get (such as altroot and cachefile), so attempt to get them
+ * anyway.
+ */
+ mutex_enter(&spa_namespace_lock);
+ if ((spa = spa_lookup(zc->zc_name)) != NULL)
+ error = spa_prop_get(spa, &nvp);
+ mutex_exit(&spa_namespace_lock);
+ } else {
+ error = spa_prop_get(spa, &nvp);
+ spa_close(spa, FTAG);
+ }
if (error == 0 && zc->zc_nvlist_dst != NULL)
error = put_nvlist(zc, nvp);
else
error = EFAULT;
- spa_close(spa, FTAG);
-
- if (nvp)
- nvlist_free(nvp);
+ nvlist_free(nvp);
return (error);
}
@@ -2385,7 +2422,7 @@ zfs_ioc_rename(zfs_cmd_t *zc)
}
static void
-clear_props(char *dataset, nvlist_t *props)
+clear_props(char *dataset, nvlist_t *props, nvlist_t *newprops)
{
zfs_cmd_t *zc;
nvpair_t *prop;
@@ -2396,6 +2433,9 @@ clear_props(char *dataset, nvlist_t *props)
(void) strcpy(zc->zc_name, dataset);
for (prop = nvlist_next_nvpair(props, NULL); prop;
prop = nvlist_next_nvpair(props, prop)) {
+ if (newprops != NULL &&
+ nvlist_exists(newprops, nvpair_name(prop)))
+ continue;
(void) strcpy(zc->zc_value, nvpair_name(prop));
if (zfs_secpolicy_inherit(zc, CRED()) == 0)
(void) zfs_ioc_inherit_prop(zc);
@@ -2503,7 +2543,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
* so that the properties are applied to the new data.
*/
if (props) {
- clear_props(tofs, origprops);
+ clear_props(tofs, origprops, props);
/*
* XXX - Note, this is all-or-nothing; should be best-effort.
*/
@@ -2542,7 +2582,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
* On error, restore the original props.
*/
if (error && props) {
- clear_props(tofs, props);
+ clear_props(tofs, props, NULL);
(void) zfs_set_prop_nvlist(tofs, origprops);
}
out: