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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/spa_config.c
          +++ new/usr/src/uts/common/fs/zfs/spa_config.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  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  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
       24 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  25   25   * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  26   26   * Copyright 2017 Joyent, Inc.
  27   27   */
  28   28  
  29   29  #include <sys/spa.h>
  30   30  #include <sys/fm/fs/zfs.h>
  31   31  #include <sys/spa_impl.h>
  32   32  #include <sys/nvpair.h>
  33   33  #include <sys/uio.h>
  34   34  #include <sys/fs/zfs.h>
↓ open down ↓ 14 lines elided ↑ open up ↑
  49   49   * Pool configuration is stored as a packed nvlist on the filesystem.  By
  50   50   * default, all pools are stored in /etc/zfs/zpool.cache and loaded on boot
  51   51   * (when the ZFS module is loaded).  Pools can also have the 'cachefile'
  52   52   * property set that allows them to be stored in an alternate location until
  53   53   * the control of external software.
  54   54   *
  55   55   * For each cache file, we have a single nvlist which holds all the
  56   56   * configuration information.  When the module loads, we read this information
  57   57   * from /etc/zfs/zpool.cache and populate the SPA namespace.  This namespace is
  58   58   * maintained independently in spa.c.  Whenever the namespace is modified, or
  59      - * the configuration of a pool is changed, we call spa_write_cachefile(), which
       59 + * the configuration of a pool is changed, we call spa_config_sync(), which
  60   60   * walks through all the active pools and writes the configuration to disk.
  61   61   */
  62   62  
  63   63  static uint64_t spa_config_generation = 1;
  64   64  
  65   65  /*
  66   66   * This can be overridden in userland to preserve an alternate namespace for
  67   67   * userland pools when doing testing.
  68   68   */
  69   69  const char *spa_config_path = ZPOOL_CACHE;
↓ open down ↓ 45 lines elided ↑ open up ↑
 115  115          if (nvlist_unpack(buf, fsize, &nvlist, KM_SLEEP) != 0)
 116  116                  goto out;
 117  117  
 118  118          /*
 119  119           * Iterate over all elements in the nvlist, creating a new spa_t for
 120  120           * each one with the specified configuration.
 121  121           */
 122  122          mutex_enter(&spa_namespace_lock);
 123  123          nvpair = NULL;
 124  124          while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) {
      125 +                uint64_t guid = 0;
      126 +
 125  127                  if (nvpair_type(nvpair) != DATA_TYPE_NVLIST)
 126  128                          continue;
 127  129  
 128  130                  child = fnvpair_value_nvlist(nvpair);
      131 +                /* a zero guid means we simply will ignore the check later */
      132 +                (void) nvlist_lookup_uint64(child, ZPOOL_CONFIG_POOL_GUID,
      133 +                    &guid);
 129  134  
 130      -                if (spa_lookup(nvpair_name(nvpair)) != NULL)
      135 +                if (spa_lookup(nvpair_name(nvpair)) != NULL ||
      136 +                    spa_config_guid_exists(guid)) {
 131  137                          continue;
      138 +                }
 132  139                  (void) spa_add(nvpair_name(nvpair), child, NULL);
 133  140          }
 134  141          mutex_exit(&spa_namespace_lock);
 135  142  
 136  143          nvlist_free(nvlist);
 137  144  
 138  145  out:
 139  146          if (buf != NULL)
 140  147                  kmem_free(buf, fsize);
 141  148  
↓ open down ↓ 49 lines elided ↑ open up ↑
 191  198          kmem_free(temp, MAXPATHLEN);
 192  199          return (err);
 193  200  }
 194  201  
 195  202  /*
 196  203   * Synchronize pool configuration to disk.  This must be called with the
 197  204   * namespace lock held. Synchronizing the pool cache is typically done after
 198  205   * the configuration has been synced to the MOS. This exposes a window where
 199  206   * the MOS config will have been updated but the cache file has not. If
 200  207   * the system were to crash at that instant then the cached config may not
 201      - * contain the correct information to open the pool and an explicit import
      208 + * contain the correct information to open the pool and an explicity import
 202  209   * would be required.
 203  210   */
 204  211  void
 205      -spa_write_cachefile(spa_t *target, boolean_t removing, boolean_t postsysevent)
      212 +spa_config_sync(spa_t *target, boolean_t removing, boolean_t postsysevent)
 206  213  {
 207  214          spa_config_dirent_t *dp, *tdp;
 208  215          nvlist_t *nvl;
 209  216          boolean_t ccw_failure;
 210  217          int error;
 211  218  
 212  219          ASSERT(MUTEX_HELD(&spa_namespace_lock));
 213  220  
 214  221          if (rootdir == NULL || !(spa_mode_global & FWRITE))
 215  222                  return;
↓ open down ↓ 116 lines elided ↑ open up ↑
 332  339          *generation = spa_config_generation;
 333  340          mutex_exit(&spa_namespace_lock);
 334  341  
 335  342          return (pools);
 336  343  }
 337  344  
 338  345  void
 339  346  spa_config_set(spa_t *spa, nvlist_t *config)
 340  347  {
 341  348          mutex_enter(&spa->spa_props_lock);
 342      -        if (spa->spa_config != NULL && spa->spa_config != config)
 343      -                nvlist_free(spa->spa_config);
      349 +        nvlist_free(spa->spa_config);
 344  350          spa->spa_config = config;
 345  351          mutex_exit(&spa->spa_props_lock);
 346  352  }
 347  353  
 348  354  /*
 349  355   * Generate the pool's configuration based on the current in-core state.
 350  356   *
 351  357   * We infer whether to generate a complete config or just one top-level config
 352  358   * based on whether vd is the root vdev.
 353  359   */
↓ open down ↓ 26 lines elided ↑ open up ↑
 380  386          fnvlist_add_uint64(config, ZPOOL_CONFIG_VERSION, spa_version(spa));
 381  387          fnvlist_add_string(config, ZPOOL_CONFIG_POOL_NAME, spa_name(spa));
 382  388          fnvlist_add_uint64(config, ZPOOL_CONFIG_POOL_STATE, spa_state(spa));
 383  389          fnvlist_add_uint64(config, ZPOOL_CONFIG_POOL_TXG, txg);
 384  390          fnvlist_add_uint64(config, ZPOOL_CONFIG_POOL_GUID, spa_guid(spa));
 385  391          if (spa->spa_comment != NULL) {
 386  392                  fnvlist_add_string(config, ZPOOL_CONFIG_COMMENT,
 387  393                      spa->spa_comment);
 388  394          }
 389  395  
      396 +#ifdef  _KERNEL
 390  397          hostid = zone_get_hostid(NULL);
 391      -
      398 +#else   /* _KERNEL */
      399 +        /*
      400 +         * We're emulating the system's hostid in userland, so we can't use
      401 +         * zone_get_hostid().
      402 +         */
      403 +        (void) ddi_strtoul(hw_serial, NULL, 10, &hostid);
      404 +#endif  /* _KERNEL */
 392  405          if (hostid != 0) {
 393  406                  fnvlist_add_uint64(config, ZPOOL_CONFIG_HOSTID, hostid);
 394  407          }
 395  408          fnvlist_add_string(config, ZPOOL_CONFIG_HOSTNAME, utsname.nodename);
 396  409  
 397  410          int config_gen_flags = 0;
 398  411          if (vd != rvd) {
 399  412                  fnvlist_add_uint64(config, ZPOOL_CONFIG_TOP_GUID,
 400  413                      vd->vdev_top->vdev_guid);
 401  414                  fnvlist_add_uint64(config, ZPOOL_CONFIG_GUID,
 402  415                      vd->vdev_guid);
 403  416                  if (vd->vdev_isspare) {
 404  417                          fnvlist_add_uint64(config,
 405  418                              ZPOOL_CONFIG_IS_SPARE, 1ULL);
 406  419                  }
      420 +                if (vd->vdev_isspecial)
      421 +                        fnvlist_add_uint64(config,
      422 +                            ZPOOL_CONFIG_IS_SPECIAL, 1ULL);
 407  423                  if (vd->vdev_islog) {
 408  424                          fnvlist_add_uint64(config,
 409  425                              ZPOOL_CONFIG_IS_LOG, 1ULL);
 410  426                  }
 411  427                  vd = vd->vdev_top;              /* label contains top config */
 412  428          } else {
 413  429                  /*
 414  430                   * Only add the (potentially large) split information
 415  431                   * in the mos config, and not in the vdev labels
 416  432                   */
↓ open down ↓ 19 lines elided ↑ open up ↑
 436  452              nvlist_lookup_uint64(spa->spa_config_splitting,
 437  453              ZPOOL_CONFIG_SPLIT_GUID, &split_guid) == 0) {
 438  454                  fnvlist_add_uint64(config, ZPOOL_CONFIG_SPLIT_GUID,
 439  455                      split_guid);
 440  456          }
 441  457  
 442  458          nvroot = vdev_config_generate(spa, vd, getstats, config_gen_flags);
 443  459          fnvlist_add_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, nvroot);
 444  460          nvlist_free(nvroot);
 445  461  
      462 +        /* If we're getting stats, calculate trim progress from leaf vdevs. */
      463 +        if (getstats) {
      464 +                uint64_t prog, rate, start_time, stop_time;
      465 +
      466 +                spa_get_trim_prog(spa, &prog, &rate, &start_time, &stop_time);
      467 +                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_PROG, prog);
      468 +                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_RATE, rate);
      469 +                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_START_TIME,
      470 +                    start_time);
      471 +                fnvlist_add_uint64(config, ZPOOL_CONFIG_TRIM_STOP_TIME,
      472 +                    stop_time);
      473 +        }
      474 +
 446  475          /*
 447  476           * Store what's necessary for reading the MOS in the label.
 448  477           */
 449  478          fnvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURES_FOR_READ,
 450  479              spa->spa_label_features);
 451  480  
 452  481          if (getstats && spa_load_state(spa) == SPA_LOAD_NONE) {
 453  482                  ddt_histogram_t *ddh;
 454  483                  ddt_stat_t *dds;
 455  484                  ddt_object_t *ddo;
↓ open down ↓ 62 lines elided ↑ open up ↑
 518  547          spa_config_exit(spa, SCL_ALL, FTAG);
 519  548  
 520  549          /*
 521  550           * Wait for the mosconfig to be regenerated and synced.
 522  551           */
 523  552          txg_wait_synced(spa->spa_dsl_pool, txg);
 524  553  
 525  554          /*
 526  555           * Update the global config cache to reflect the new mosconfig.
 527  556           */
 528      -        if (!spa->spa_is_root) {
 529      -                spa_write_cachefile(spa, B_FALSE,
 530      -                    what != SPA_CONFIG_UPDATE_POOL);
 531      -        }
      557 +        if (!spa->spa_is_root)
      558 +                spa_config_sync(spa, B_FALSE, what != SPA_CONFIG_UPDATE_POOL);
 532  559  
 533  560          if (what == SPA_CONFIG_UPDATE_POOL)
 534  561                  spa_config_update(spa, SPA_CONFIG_UPDATE_VDEVS);
 535  562  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX