]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/zfs_ioctl.c
Rebase master to b108
[mirror_zfs.git] / module / zfs / zfs_ioctl.c
index 49ee5526520e2ad1263327e13bc08ea37fa5729e..d032648b54ebdb1850b4cb3cc5e4a7dc53aa12a4 100644 (file)
@@ -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: