Print this page
NEX-9989 Changing volume names can result in double imports and data corruption
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5064 On-demand trim should store operation start and stop time
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-3984 On-demand TRIM
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Conflicts:
        usr/src/common/zfs/zpool_prop.c
        usr/src/uts/common/sys/fs/zfs.h
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
        
@@ -19,11 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright 2017 Joyent, Inc.
  */
 
 #include <sys/spa.h>
@@ -54,11 +54,11 @@
  *
  * For each cache file, we have a single nvlist which holds all the
  * configuration information.  When the module loads, we read this information
  * from /etc/zfs/zpool.cache and populate the SPA namespace.  This namespace is
  * maintained independently in spa.c.  Whenever the namespace is modified, or
- * the configuration of a pool is changed, we call spa_write_cachefile(), which
+ * the configuration of a pool is changed, we call spa_config_sync(), which
  * walks through all the active pools and writes the configuration to disk.
  */
 
 static uint64_t spa_config_generation = 1;
 
@@ -120,17 +120,24 @@
          * each one with the specified configuration.
          */
         mutex_enter(&spa_namespace_lock);
         nvpair = NULL;
         while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) {
+                uint64_t guid = 0;
+
                 if (nvpair_type(nvpair) != DATA_TYPE_NVLIST)
                         continue;
 
                 child = fnvpair_value_nvlist(nvpair);
+                /* a zero guid means we simply will ignore the check later */
+                (void) nvlist_lookup_uint64(child, ZPOOL_CONFIG_POOL_GUID,
+                    &guid);
 
-                if (spa_lookup(nvpair_name(nvpair)) != NULL)
+                if (spa_lookup(nvpair_name(nvpair)) != NULL ||
+                    spa_config_guid_exists(guid)) {
                         continue;
+                }
                 (void) spa_add(nvpair_name(nvpair), child, NULL);
         }
         mutex_exit(&spa_namespace_lock);
 
         nvlist_free(nvlist);
@@ -196,15 +203,15 @@
  * Synchronize pool configuration to disk.  This must be called with the
  * namespace lock held. Synchronizing the pool cache is typically done after
  * the configuration has been synced to the MOS. This exposes a window where
  * the MOS config will have been updated but the cache file has not. If
  * the system were to crash at that instant then the cached config may not
- * contain the correct information to open the pool and an explicit import
+ * contain the correct information to open the pool and an explicity import
  * would be required.
  */
 void
-spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent)
+spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
 {
         spa_config_dirent_t *dp, *tdp;
         nvlist_t *nvl;
         boolean_t ccw_failure;
         int error;
@@ -337,11 +344,10 @@
 
 void
 spa_config_set(spa_t *spa, nvlist_t *config)
 {
         mutex_enter(&spa->spa_props_lock);
-        if (spa->spa_config != NULL && spa->spa_config != config)
                 nvlist_free(spa->spa_config);
         spa->spa_config = config;
         mutex_exit(&spa->spa_props_lock);
 }
 
@@ -385,12 +391,19 @@
         if (spa->spa_comment != NULL) {
                 fnvlist_add_string(config, ZPOOL_CONFIG_COMMENT,
                     spa->spa_comment);
         }
 
+#ifdef  _KERNEL
         hostid = zone_get_hostid(NULL);
-
+#else   /* _KERNEL */
+        /*
+         * We're emulating the system's hostid in userland, so we can't use
+         * zone_get_hostid().
+         */
+        (void) ddi_strtoul(hw_serial, NULL, 10, &hostid);
+#endif  /* _KERNEL */
         if (hostid != 0) {
                 fnvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID, hostid);
         }
         fnvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME, utsname.nodename);
 
@@ -402,10 +415,13 @@
                     vd->vdev_guid);
                 if (vd->vdev_isspare) {
                         fnvlist_add_uint64(config,
                             ZPOOL_CONFIG_IS_SPARE, 1ULL);
                 }
+                if (vd->vdev_isspecial)
+                        fnvlist_add_uint64(config,
+                            ZPOOL_CONFIG_IS_SPECIAL, 1ULL);
                 if (vd->vdev_islog) {
                         fnvlist_add_uint64(config,
                             ZPOOL_CONFIG_IS_LOG, 1ULL);
                 }
                 vd = vd->vdev_top;              /* label contains top config */
@@ -441,10 +457,23 @@
 
         nvroot = vdev_config_generate(spa, vd, getstats, config_gen_flags);
         fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot);
         nvlist_free(nvroot);
 
+        /* If we're getting stats, calculate trim progress from leaf vdevs. */
+        if (getstats) {
+                uint64_t prog, rate, start_time, stop_time;
+
+                spa_get_trim_prog(spa, &prog, &rate, &start_time, &stop_time);
+                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_PROG, prog);
+                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_RATE, rate);
+                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_START_TIME,
+                    start_time);
+                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_STOP_TIME,
+                    stop_time);
+        }
+
         /*
          * Store what's necessary for reading the MOS in the label.
          */
         fnvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURES_FOR_READ,
             spa->spa_label_features);
@@ -523,13 +552,11 @@
         txg_wait_synced(spa->spa_dsl_pool, txg);
 
         /*
          * Update the global config cache to reflect the new mosconfig.
          */
-        if (!spa->spa_is_root) {
-                spa_write_cachefile(spa, B_FALSE,
-                    what != SPA_CONFIG_UPDATE_POOL);
-        }
+        if (!spa->spa_is_root)
+                spa_config_sync(spa, B_FALSE, what != SPA_CONFIG_UPDATE_POOL);
 
         if (what == SPA_CONFIG_UPDATE_POOL)
                 spa_config_update(spa, SPA_CONFIG_UPDATE_VDEVS);
 }