Print this page
NEX-3558 KRRP Integration
OS-195 itadm needs an easily parsable output mode
OS-207 SUP-817 causes lint warnings in zpool_main.c
Reviewed by: Alek Pinchuk <alek.pinchuk@nexena.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Albert Lee <albert.lee@nexenta.com>
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,28 ****
--- 19,29 ----
   * CDDL HEADER END
   */
  
  /*
   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
   * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
   * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
   */
  
  /*
*** 385,395 ****
   *      /dev/dsk/xxx    Complete disk path
   *      /xxx            Full path to file
   *      xxx             Shorthand for /dev/dsk/xxx
   */
  static nvlist_t *
! make_leaf_vdev(const char *arg, uint64_t is_log)
  {
          char path[MAXPATHLEN];
          struct stat64 statbuf;
          nvlist_t *vdev = NULL;
          char *type = NULL;
--- 386,396 ----
   *      /dev/dsk/xxx    Complete disk path
   *      /xxx            Full path to file
   *      xxx             Shorthand for /dev/dsk/xxx
   */
  static nvlist_t *
! make_leaf_vdev(const char *arg, uint64_t is_log, uint64_t is_special)
  {
          char path[MAXPATHLEN];
          struct stat64 statbuf;
          nvlist_t *vdev = NULL;
          char *type = NULL;
*** 469,478 ****
--- 470,481 ----
           */
          verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
          verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
          verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
          verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
+         verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_SPECIAL,
+             is_special) == 0);
          if (strcmp(type, VDEV_TYPE_DISK) == 0)
                  verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
                      (uint64_t)wholedisk) == 0);
  
          /*
*** 626,640 ****
                                  verify(nvlist_lookup_string(cnv,
                                      ZPOOL_CONFIG_TYPE, &childtype) == 0);
  
                                  /*
                                   * If this is a replacing or spare vdev, then
!                                  * get the real first child of the vdev: do this
!                                  * in a loop because replacing and spare vdevs
!                                  * can be nested.
                                   */
!                                 while (strcmp(childtype,
                                      VDEV_TYPE_REPLACING) == 0 ||
                                      strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
                                          nvlist_t **rchild;
                                          uint_t rchildren;
  
--- 629,641 ----
                                  verify(nvlist_lookup_string(cnv,
                                      ZPOOL_CONFIG_TYPE, &childtype) == 0);
  
                                  /*
                                   * If this is a replacing or spare vdev, then
!                                  * get the real first child of the vdev.
                                   */
!                                 if (strcmp(childtype,
                                      VDEV_TYPE_REPLACING) == 0 ||
                                      strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
                                          nvlist_t **rchild;
                                          uint_t rchildren;
  
*** 1181,1190 ****
--- 1182,1197 ----
                  if (mindev != NULL)
                          *mindev = 1;
                  return (VDEV_TYPE_L2CACHE);
          }
  
+         if (strcmp(type, "special") == 0) {
+                 if (mindev != NULL)
+                         *mindev = 1;
+                 return (VDEV_TYPE_SPECIAL);
+         }
+ 
          return (NULL);
  }
  
  /*
   * Construct a syntactically valid vdev specification,
*** 1195,1207 ****
  nvlist_t *
  construct_spec(int argc, char **argv)
  {
          nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
          int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
          const char *type;
!         uint64_t is_log;
!         boolean_t seen_logs;
  
          top = NULL;
          toplevels = 0;
          spares = NULL;
          l2cache = NULL;
--- 1202,1215 ----
  nvlist_t *
  construct_spec(int argc, char **argv)
  {
          nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
          int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
+         int nspecial = 0;
          const char *type;
!         boolean_t is_log, seen_logs;
!         boolean_t is_special, seen_special;
  
          top = NULL;
          toplevels = 0;
          spares = NULL;
          l2cache = NULL;
*** 1208,1217 ****
--- 1216,1227 ----
          nspares = 0;
          nlogs = 0;
          nl2cache = 0;
          is_log = B_FALSE;
          seen_logs = B_FALSE;
+         is_special = B_FALSE;
+         seen_special = B_FALSE;
  
          while (argc > 0) {
                  nv = NULL;
  
                  /*
*** 1229,1238 ****
--- 1239,1249 ----
                                              "specification: 'spare' can be "
                                              "specified only once\n"));
                                          return (NULL);
                                  }
                                  is_log = B_FALSE;
+                                 is_special = B_FALSE;
                          }
  
                          if (strcmp(type, VDEV_TYPE_LOG) == 0) {
                                  if (seen_logs) {
                                          (void) fprintf(stderr,
*** 1241,1250 ****
--- 1252,1262 ----
                                              "specified only once\n"));
                                          return (NULL);
                                  }
                                  seen_logs = B_TRUE;
                                  is_log = B_TRUE;
+                                 is_special = B_FALSE;
                                  argc--;
                                  argv++;
                                  /*
                                   * A log is not a real grouping device.
                                   * We just set is_log and continue.
*** 1259,1270 ****
--- 1271,1303 ----
                                              "specification: 'cache' can be "
                                              "specified only once\n"));
                                          return (NULL);
                                  }
                                  is_log = B_FALSE;
+                                 is_special = B_FALSE;
                          }
  
+                         if (strcmp(type, VDEV_TYPE_SPECIAL) == 0) {
+                                 if (seen_special) {
+                                         (void) fprintf(stderr,
+                                             gettext("invalid vdev "
+                                             "specification: 'special' can be "
+                                             "specified only once\n"));
+                                         return (NULL);
+                                 }
+                                 seen_special = B_TRUE;
+                                 is_log = B_FALSE;
+                                 is_special = B_TRUE;
+                                 argc--;
+                                 argv++;
+                                 /*
+                                  * A special is not a real grouping device.
+                                  * We just set is_special and continue.
+                                  */
+                                 continue;
+                         }
+ 
                          if (is_log) {
                                  if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
                                          (void) fprintf(stderr,
                                              gettext("invalid vdev "
                                              "specification: unsupported 'log' "
*** 1272,1291 ****
                                          return (NULL);
                                  }
                                  nlogs++;
                          }
  
                          for (c = 1; c < argc; c++) {
                                  if (is_grouping(argv[c], NULL, NULL) != NULL)
                                          break;
                                  children++;
                                  child = realloc(child,
                                      children * sizeof (nvlist_t *));
                                  if (child == NULL)
                                          zpool_no_memory();
!                                 if ((nv = make_leaf_vdev(argv[c], B_FALSE))
!                                     == NULL)
                                          return (NULL);
                                  child[children - 1] = nv;
                          }
  
                          if (children < mindev) {
--- 1305,1336 ----
                                          return (NULL);
                                  }
                                  nlogs++;
                          }
  
+                         if (is_special) {
+                                 if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
+                                         (void) fprintf(stderr,
+                                             gettext("invalid vdev "
+                                             "specification: unsupported "
+                                             "'special' device: %s\n"), type);
+                                         return (NULL);
+                                 }
+                                 nspecial++;
+                         }
+ 
                          for (c = 1; c < argc; c++) {
                                  if (is_grouping(argv[c], NULL, NULL) != NULL)
                                          break;
                                  children++;
                                  child = realloc(child,
                                      children * sizeof (nvlist_t *));
                                  if (child == NULL)
                                          zpool_no_memory();
!                                 if ((nv = make_leaf_vdev(argv[c],
!                                     (uint64_t)B_FALSE,
!                                     (uint64_t)B_FALSE)) == NULL)
                                          return (NULL);
                                  child[children - 1] = nv;
                          }
  
                          if (children < mindev) {
*** 1317,1327 ****
                                  verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
                                      0) == 0);
                                  verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
                                      type) == 0);
                                  verify(nvlist_add_uint64(nv,
!                                     ZPOOL_CONFIG_IS_LOG, is_log) == 0);
                                  if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
                                          verify(nvlist_add_uint64(nv,
                                              ZPOOL_CONFIG_NPARITY,
                                              mindev - 1) == 0);
                                  }
--- 1362,1376 ----
                                  verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
                                      0) == 0);
                                  verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
                                      type) == 0);
                                  verify(nvlist_add_uint64(nv,
!                                     ZPOOL_CONFIG_IS_LOG,
!                                     (uint64_t)is_log) == 0);
!                                 verify(nvlist_add_uint64(nv,
!                                     ZPOOL_CONFIG_IS_SPECIAL,
!                                     (uint64_t)is_special) == 0);
                                  if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
                                          verify(nvlist_add_uint64(nv,
                                              ZPOOL_CONFIG_NPARITY,
                                              mindev - 1) == 0);
                                  }
*** 1336,1349 ****
                  } else {
                          /*
                           * We have a device.  Pass off to make_leaf_vdev() to
                           * construct the appropriate nvlist describing the vdev.
                           */
!                         if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
                                  return (NULL);
                          if (is_log)
                                  nlogs++;
                          argc--;
                          argv++;
                  }
  
                  toplevels++;
--- 1385,1401 ----
                  } else {
                          /*
                           * We have a device.  Pass off to make_leaf_vdev() to
                           * construct the appropriate nvlist describing the vdev.
                           */
!                         if ((nv = make_leaf_vdev(argv[0], (uint64_t)is_log,
!                             (uint64_t)is_special)) == NULL)
                                  return (NULL);
                          if (is_log)
                                  nlogs++;
+                         if (is_special)
+                                 nspecial++;
                          argc--;
                          argv++;
                  }
  
                  toplevels++;
*** 1357,1366 ****
--- 1409,1424 ----
                  (void) fprintf(stderr, gettext("invalid vdev "
                      "specification: at least one toplevel vdev must be "
                      "specified\n"));
                  return (NULL);
          }
+ 
+         if (seen_special && nspecial == 0) {
+                 (void) fprintf(stderr, gettext("invalid vdev specification: "
+                     "special requires at least 1 device\n"));
+                 return (NULL);
+         }
  
          if (seen_logs && nlogs == 0) {
                  (void) fprintf(stderr, gettext("invalid vdev specification: "
                      "log requires at least 1 device\n"));
                  return (NULL);