Print this page
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
        
*** 49,58 ****
--- 49,59 ----
  
  #include <libzfs.h>
  
  #include "zpool_util.h"
  #include "zfs_comutil.h"
+ #include "zfeature_common.h"
  
  #include "statcommon.h"
  
  static int zpool_do_create(int, char **);
  static int zpool_do_destroy(int, char **);
*** 198,208 ****
                  return (gettext("\tattach [-f] <pool> <device> "
                      "<new-device>\n"));
          case HELP_CLEAR:
                  return (gettext("\tclear [-nF] <pool> [device]\n"));
          case HELP_CREATE:
!                 return (gettext("\tcreate [-fn] [-o property=value] ... \n"
                      "\t    [-O file-system-property=value] ... \n"
                      "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
          case HELP_DESTROY:
                  return (gettext("\tdestroy [-f] <pool>\n"));
          case HELP_DETACH:
--- 199,209 ----
                  return (gettext("\tattach [-f] <pool> <device> "
                      "<new-device>\n"));
          case HELP_CLEAR:
                  return (gettext("\tclear [-nF] <pool> [device]\n"));
          case HELP_CREATE:
!                 return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
                      "\t    [-O file-system-property=value] ... \n"
                      "\t    [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
          case HELP_DESTROY:
                  return (gettext("\tdestroy [-f] <pool>\n"));
          case HELP_DETACH:
*** 329,338 ****
--- 330,345 ----
                      "PROPERTY", "EDIT", "VALUES");
  
                  /* Iterate over all properties */
                  (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
                      ZFS_TYPE_POOL);
+ 
+                 (void) fprintf(fp, "\t%-15s   ", "feature@...");
+                 (void) fprintf(fp, "YES   disabled | enabled | active\n");
+ 
+                 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
+                     "appended with a feature name.\nSee zpool-features(5).\n"));
          }
  
          /*
           * See comments at end of main().
           */
*** 395,409 ****
          }
  
          proplist = *props;
  
          if (poolprop) {
!                 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL) {
                          (void) fprintf(stderr, gettext("property '%s' is "
                              "not a valid pool property\n"), propname);
                          return (2);
                  }
                  normnm = zpool_prop_to_name(prop);
          } else {
                  if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
                          normnm = zfs_prop_to_name(fprop);
                  } else {
--- 402,420 ----
          }
  
          proplist = *props;
  
          if (poolprop) {
!                 if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
!                     !zpool_prop_feature(propname)) {
                          (void) fprintf(stderr, gettext("property '%s' is "
                              "not a valid pool property\n"), propname);
                          return (2);
                  }
+                 if (zpool_prop_feature(propname))
+                         normnm = propname;
+                 else
                          normnm = zpool_prop_to_name(prop);
          } else {
                  if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
                          normnm = zfs_prop_to_name(fprop);
                  } else {
*** 572,582 ****
  
          return (ret);
  }
  
  /*
!  * zpool create [-fn] [-o property=value] ...
   *              [-O file-system-property=value] ...
   *              [-R root] [-m mountpoint] <pool> <dev> ...
   *
   *      -f      Force creation, even if devices appear in use
   *      -n      Do not create the pool, but display the resulting layout if it
--- 583,593 ----
  
          return (ret);
  }
  
  /*
!  * zpool create [-fnd] [-o property=value] ...
   *              [-O file-system-property=value] ...
   *              [-R root] [-m mountpoint] <pool> <dev> ...
   *
   *      -f      Force creation, even if devices appear in use
   *      -n      Do not create the pool, but display the resulting layout if it
*** 583,592 ****
--- 594,605 ----
   *              were to be created.
   *      -R      Create a pool under an alternate root
   *      -m      Set default mountpoint for the root dataset.  By default it's
   *              '/<pool>'
   *      -o      Set property=value.
+  *      -d      Don't automatically enable all supported pool features
+  *              (individual features can be enabled with -o).
   *      -O      Set fsproperty=value in the pool's root file system
   *
   * Creates the named pool according to the given vdev specification.  The
   * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c.  Once
   * we get the nvlist back from get_vdev_spec(), we either print out the contents
*** 595,604 ****
--- 608,618 ----
  int
  zpool_do_create(int argc, char **argv)
  {
          boolean_t force = B_FALSE;
          boolean_t dryrun = B_FALSE;
+         boolean_t enable_all_pool_feat = B_TRUE;
          int c;
          nvlist_t *nvroot = NULL;
          char *poolname;
          int ret = 1;
          char *altroot = NULL;
*** 606,623 ****
          nvlist_t *fsprops = NULL;
          nvlist_t *props = NULL;
          char *propval;
  
          /* check options */
!         while ((c = getopt(argc, argv, ":fnR:m:o:O:")) != -1) {
                  switch (c) {
                  case 'f':
                          force = B_TRUE;
                          break;
                  case 'n':
                          dryrun = B_TRUE;
                          break;
                  case 'R':
                          altroot = optarg;
                          if (add_prop_list(zpool_prop_to_name(
                              ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
                                  goto errout;
--- 620,640 ----
          nvlist_t *fsprops = NULL;
          nvlist_t *props = NULL;
          char *propval;
  
          /* check options */
!         while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) {
                  switch (c) {
                  case 'f':
                          force = B_TRUE;
                          break;
                  case 'n':
                          dryrun = B_TRUE;
                          break;
+                 case 'd':
+                         enable_all_pool_feat = B_FALSE;
+                         break;
                  case 'R':
                          altroot = optarg;
                          if (add_prop_list(zpool_prop_to_name(
                              ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
                                  goto errout;
*** 641,650 ****
--- 658,682 ----
                          *propval = '\0';
                          propval++;
  
                          if (add_prop_list(optarg, propval, &props, B_TRUE))
                                  goto errout;
+ 
+                         /*
+                          * If the user is creating a pool that doesn't support
+                          * feature flags, don't enable any features.
+                          */
+                         if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
+                                 char *end;
+                                 u_longlong_t ver;
+ 
+                                 ver = strtoull(propval, &end, 10);
+                                 if (*end == '\0' &&
+                                     ver < SPA_VERSION_FEATURES) {
+                                         enable_all_pool_feat = B_FALSE;
+                                 }
+                         }
                          break;
                  case 'O':
                          if ((propval = strchr(optarg, '=')) == NULL) {
                                  (void) fprintf(stderr, gettext("missing "
                                      "'=' for -O option\n"));
*** 706,716 ****
                      "specification: at least one toplevel vdev must be "
                      "specified\n"));
                  goto errout;
          }
  
- 
          if (altroot != NULL && altroot[0] != '/') {
                  (void) fprintf(stderr, gettext("invalid alternate root '%s': "
                      "must be an absolute path\n"), altroot);
                  goto errout;
          }
--- 738,747 ----
*** 788,797 ****
--- 819,849 ----
                  ret = 0;
          } else {
                  /*
                   * Hand off to libzfs.
                   */
+                 if (enable_all_pool_feat) {
+                         int i;
+                         for (i = 0; i < SPA_FEATURES; i++) {
+                                 char propname[MAXPATHLEN];
+                                 zfeature_info_t *feat = &spa_feature_table[i];
+ 
+                                 (void) snprintf(propname, sizeof (propname),
+                                     "feature@%s", feat->fi_uname);
+ 
+                                 /*
+                                  * Skip feature if user specified it manually
+                                  * on the command line.
+                                  */
+                                 if (nvlist_exists(props, propname))
+                                         continue;
+ 
+                                 if (add_prop_list(propname, ZFS_FEATURE_ENABLED,
+                                     &props, B_TRUE) != 0)
+                                         goto errout;
+                         }
+                 }
                  if (zpool_create(g_zfs, poolname,
                      nvroot, props, fsprops) == 0) {
                          zfs_handle_t *pool = zfs_open(g_zfs, poolname,
                              ZFS_TYPE_FILESYSTEM);
                          if (pool != NULL) {
*** 1119,1128 ****
--- 1171,1184 ----
  
                  case VDEV_AUX_VERSION_NEWER:
                          (void) printf(gettext("newer version"));
                          break;
  
+                 case VDEV_AUX_UNSUP_FEAT:
+                         (void) printf(gettext("unsupported feature(s)"));
+                         break;
+ 
                  case VDEV_AUX_SPARED:
                          verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
                              &cb.cb_guid) == 0);
                          if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
                                  if (strcmp(zpool_get_name(cb.cb_zhp),
*** 1236,1245 ****
--- 1292,1305 ----
  
                  case VDEV_AUX_VERSION_NEWER:
                          (void) printf(gettext("newer version"));
                          break;
  
+                 case VDEV_AUX_UNSUP_FEAT:
+                         (void) printf(gettext("unsupported feature(s)"));
+                         break;
+ 
                  case VDEV_AUX_ERR_EXCEEDED:
                          (void) printf(gettext("too many errors"));
                          break;
  
                  default:
*** 1402,1411 ****
--- 1462,1485 ----
          case ZPOOL_STATUS_VERSION_NEWER:
                  (void) printf(gettext(" status: The pool is formatted using an "
                      "incompatible version.\n"));
                  break;
  
+         case ZPOOL_STATUS_UNSUP_FEAT_READ:
+                 (void) printf(gettext("status: The pool uses the following "
+                     "feature(s) not supported on this sytem:\n"));
+                 zpool_print_unsup_feat(config);
+                 break;
+ 
+         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
+                 (void) printf(gettext("status: The pool can only be accessed "
+                     "in read-only mode on this system. It\n\tcannot be "
+                     "accessed in read-write mode because it uses the "
+                     "following\n\tfeature(s) not supported on this system:\n"));
+                 zpool_print_unsup_feat(config);
+                 break;
+ 
          case ZPOOL_STATUS_HOSTID_MISMATCH:
                  (void) printf(gettext(" status: The pool was last accessed by "
                      "another system.\n"));
                  break;
  
*** 1459,1468 ****
--- 1533,1556 ----
                          (void) printf(gettext(" action: The pool cannot be "
                              "imported.  Access the pool on a system running "
                              "newer\n\tsoftware, or recreate the pool from "
                              "backup.\n"));
                          break;
+                 case ZPOOL_STATUS_UNSUP_FEAT_READ:
+                         (void) printf(gettext("action: The pool cannot be "
+                             "imported. Access the pool on a system that "
+                             "supports\n\tthe required feature(s), or recreate "
+                             "the pool from backup.\n"));
+                         break;
+                 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
+                         (void) printf(gettext("action: The pool cannot be "
+                             "imported in read-write mode. Import the pool "
+                             "with\n"
+                             "\t\"-o readonly=on\", access the pool on a system "
+                             "that supports the\n\trequired feature(s), or "
+                             "recreate the pool from backup.\n"));
+                         break;
                  case ZPOOL_STATUS_MISSING_DEV_R:
                  case ZPOOL_STATUS_MISSING_DEV_NR:
                  case ZPOOL_STATUS_BAD_GUID_SUM:
                          (void) printf(gettext(" action: The pool cannot be "
                              "imported. Attach the missing\n\tdevices and try "
*** 1534,1546 ****
  
          verify(nvlist_lookup_uint64(config,
              ZPOOL_CONFIG_POOL_STATE, &state) == 0);
          verify(nvlist_lookup_uint64(config,
              ZPOOL_CONFIG_VERSION, &version) == 0);
!         if (version > SPA_VERSION) {
                  (void) fprintf(stderr, gettext("cannot import '%s': pool "
!                     "is formatted using a newer ZFS version\n"), name);
                  return (1);
          } else if (state != POOL_STATE_EXPORTED &&
              !(flags & ZFS_IMPORT_ANY_HOST)) {
                  uint64_t hostid;
  
--- 1622,1634 ----
  
          verify(nvlist_lookup_uint64(config,
              ZPOOL_CONFIG_POOL_STATE, &state) == 0);
          verify(nvlist_lookup_uint64(config,
              ZPOOL_CONFIG_VERSION, &version) == 0);
!         if (!SPA_VERSION_IS_SUPPORTED(version)) {
                  (void) fprintf(stderr, gettext("cannot import '%s': pool "
!                     "is formatted using an unsupported ZFS version\n"), name);
                  return (1);
          } else if (state != POOL_STATE_EXPORTED &&
              !(flags & ZFS_IMPORT_ANY_HOST)) {
                  uint64_t hostid;
  
*** 2471,2489 ****
   */
  static void
  print_header(list_cbdata_t *cb)
  {
          zprop_list_t *pl = cb->cb_proplist;
          const char *header;
          boolean_t first = B_TRUE;
          boolean_t right_justify;
          size_t width = 0;
  
          for (; pl != NULL; pl = pl->pl_next) {
-                 if (pl->pl_prop == ZPROP_INVAL)
-                         continue;
- 
                  width = pl->pl_width;
                  if (first && cb->cb_verbose) {
                          /*
                           * Reset the width to accommodate the verbose listing
                           * of devices.
--- 2559,2575 ----
   */
  static void
  print_header(list_cbdata_t *cb)
  {
          zprop_list_t *pl = cb->cb_proplist;
+         char headerbuf[ZPOOL_MAXPROPLEN];
          const char *header;
          boolean_t first = B_TRUE;
          boolean_t right_justify;
          size_t width = 0;
  
          for (; pl != NULL; pl = pl->pl_next) {
                  width = pl->pl_width;
                  if (first && cb->cb_verbose) {
                          /*
                           * Reset the width to accommodate the verbose listing
                           * of devices.
*** 2494,2506 ****
--- 2580,2602 ----
                  if (!first)
                          (void) printf("  ");
                  else
                          first = B_FALSE;
  
+                 right_justify = B_FALSE;
+                 if (pl->pl_prop != ZPROP_INVAL) {
                          header = zpool_prop_column_name(pl->pl_prop);
                          right_justify = zpool_prop_align_right(pl->pl_prop);
+                 } else {
+                         int i;
  
+                         for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
+                                 headerbuf[i] = toupper(pl->pl_user_prop[i]);
+                         headerbuf[i] = '\0';
+                         header = headerbuf;
+                 }
+ 
                  if (pl->pl_next == NULL && !right_justify)
                          (void) printf("%s", header);
                  else if (right_justify)
                          (void) printf("%*s", width, header);
                  else
*** 2555,2564 ****
--- 2651,2665 ----
                                  propstr = "-";
                          else
                                  propstr = property;
  
                          right_justify = zpool_prop_align_right(pl->pl_prop);
+                 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
+                     zpool_prop_unsupported(pl->pl_user_prop)) &&
+                     zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
+                     sizeof (property)) == 0) {
+                         propstr = property;
                  } else {
                          propstr = "-";
                  }
  
  
*** 3894,3903 ****
--- 3995,4029 ----
                  (void) printf(gettext("action: Access the pool from a system "
                      "running more recent software, or\n\trestore the pool from "
                      "backup.\n"));
                  break;
  
+         case ZPOOL_STATUS_UNSUP_FEAT_READ:
+                 (void) printf(gettext("status: The pool cannot be accessed on "
+                     "this system because it uses the\n\tfollowing feature(s) "
+                     "not supported on this system:\n"));
+                 zpool_print_unsup_feat(config);
+                 (void) printf("\n");
+                 (void) printf(gettext("action: Access the pool from a system "
+                     "that supports the required feature(s),\n\tor restore the "
+                     "pool from backup.\n"));
+                 break;
+ 
+         case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
+                 (void) printf(gettext("status: The pool can only be accessed "
+                     "in read-only mode on this system. It\n\tcannot be "
+                     "accessed in read-write mode because it uses the "
+                     "following\n\tfeature(s) not supported on this system:\n"));
+                 zpool_print_unsup_feat(config);
+                 (void) printf("\n");
+                 (void) printf(gettext("action: The pool cannot be accessed in "
+                     "read-write mode. Import the pool with\n"
+                     "\t\"-o readonly=on\", access the pool from a system that "
+                     "supports the\n\trequired feature(s), or restore the "
+                     "pool from backup.\n"));
+                 break;
+ 
          case ZPOOL_STATUS_FAULTED_DEV_R:
                  (void) printf(gettext("status: One or more devices are "
                      "faulted in response to persistent errors.\n\tSufficient "
                      "replicas exist for the pool to continue functioning "
                      "in a\n\tdegraded state.\n"));
*** 4118,4128 ****
  
          config = zpool_get_config(zhp, NULL);
          verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
              &version) == 0);
  
!         if (!cbp->cb_newer && version < SPA_VERSION) {
                  if (!cbp->cb_all) {
                          if (cbp->cb_first) {
                                  (void) printf(gettext("The following pools are "
                                      "out of date, and can be upgraded.  After "
                                      "being\nupgraded, these pools will no "
--- 4244,4255 ----
  
          config = zpool_get_config(zhp, NULL);
          verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
              &version) == 0);
  
!         if (!cbp->cb_newer && SPA_VERSION_IS_SUPPORTED(version) &&
!             version != SPA_VERSION) {
                  if (!cbp->cb_all) {
                          if (cbp->cb_first) {
                                  (void) printf(gettext("The following pools are "
                                      "out of date, and can be upgraded.  After "
                                      "being\nupgraded, these pools will no "
*** 4141,4157 ****
                          if (!ret) {
                                  (void) printf(gettext("Successfully upgraded "
                                      "'%s'\n\n"), zpool_get_name(zhp));
                          }
                  }
!         } else if (cbp->cb_newer && version > SPA_VERSION) {
                  assert(!cbp->cb_all);
  
                  if (cbp->cb_first) {
                          (void) printf(gettext("The following pools are "
!                             "formatted using a newer software version and\n"
!                             "cannot be accessed on the current system.\n\n"));
                          (void) printf(gettext("VER  POOL\n"));
                          (void) printf(gettext("---  ------------\n"));
                          cbp->cb_first = B_FALSE;
                  }
  
--- 4268,4285 ----
                          if (!ret) {
                                  (void) printf(gettext("Successfully upgraded "
                                      "'%s'\n\n"), zpool_get_name(zhp));
                          }
                  }
!         } else if (cbp->cb_newer && !SPA_VERSION_IS_SUPPORTED(version)) {
                  assert(!cbp->cb_all);
  
                  if (cbp->cb_first) {
                          (void) printf(gettext("The following pools are "
!                             "formatted using an unsupported software version "
!                             "and\ncannot be accessed on the current "
!                             "system.\n\n"));
                          (void) printf(gettext("VER  POOL\n"));
                          (void) printf(gettext("---  ------------\n"));
                          cbp->cb_first = B_FALSE;
                  }
  
*** 4231,4242 ****
                  case 'v':
                          showversions = B_TRUE;
                          break;
                  case 'V':
                          cb.cb_version = strtoll(optarg, &end, 10);
!                         if (*end != '\0' || cb.cb_version > SPA_VERSION ||
!                             cb.cb_version < SPA_VERSION_1) {
                                  (void) fprintf(stderr,
                                      gettext("invalid version '%s'\n"), optarg);
                                  usage(B_FALSE);
                          }
                          break;
--- 4359,4370 ----
                  case 'v':
                          showversions = B_TRUE;
                          break;
                  case 'V':
                          cb.cb_version = strtoll(optarg, &end, 10);
!                         if (*end != '\0' ||
!                             !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
                                  (void) fprintf(stderr,
                                      gettext("invalid version '%s'\n"), optarg);
                                  usage(B_FALSE);
                          }
                          break;
*** 4277,4288 ****
                              "be used along with a pool name\n"));
                          usage(B_FALSE);
                  }
          }
  
!         (void) printf(gettext("This system is currently running "
!             "ZFS pool version %llu.\n\n"), SPA_VERSION);
          cb.cb_first = B_TRUE;
          if (showversions) {
                  (void) printf(gettext("The following versions are "
                      "supported:\n\n"));
                  (void) printf(gettext("VER  DESCRIPTION\n"));
--- 4405,4416 ----
                              "be used along with a pool name\n"));
                          usage(B_FALSE);
                  }
          }
  
!         (void) printf(gettext("This system supports ZFS pool feature "
!             "flags.\n\n"));
          cb.cb_first = B_TRUE;
          if (showversions) {
                  (void) printf(gettext("The following versions are "
                      "supported:\n\n"));
                  (void) printf(gettext("VER  DESCRIPTION\n"));
*** 4529,4546 ****
                   */
                  if (pl->pl_prop == ZPOOL_PROP_NAME &&
                      pl == cbp->cb_proplist)
                          continue;
  
!                 if (zpool_get_prop(zhp, pl->pl_prop,
!                     value, sizeof (value), &srctype) != 0)
                          continue;
  
                  zprop_print_one_property(zpool_get_name(zhp), cbp,
!                     zpool_prop_to_name(pl->pl_prop), value, srctype, NULL,
!                     NULL);
          }
          return (0);
  }
  
  int
  zpool_do_get(int argc, char **argv)
--- 4657,4687 ----
                   */
                  if (pl->pl_prop == ZPOOL_PROP_NAME &&
                      pl == cbp->cb_proplist)
                          continue;
  
!                 if (pl->pl_prop == ZPROP_INVAL &&
!                     (zpool_prop_feature(pl->pl_user_prop) ||
!                     zpool_prop_unsupported(pl->pl_user_prop))) {
!                         srctype = ZPROP_SRC_LOCAL;
! 
!                         if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
!                             value, sizeof (value)) == 0) {
!                                 zprop_print_one_property(zpool_get_name(zhp),
!                                     cbp, pl->pl_user_prop, value, srctype,
!                                     NULL, NULL);
!                         }
!                 } else {
!                         if (zpool_get_prop(zhp, pl->pl_prop, value,
!                             sizeof (value), &srctype) != 0)
                                  continue;
  
                          zprop_print_one_property(zpool_get_name(zhp), cbp,
!                             zpool_prop_to_name(pl->pl_prop), value, srctype,
!                             NULL, NULL);
                  }
+         }
          return (0);
  }
  
  int
  zpool_do_get(int argc, char **argv)
*** 4547,4558 ****
  {
          zprop_get_cbdata_t cb = { 0 };
          zprop_list_t fake_name = { 0 };
          int ret;
  
!         if (argc < 3)
                  usage(B_FALSE);
  
          cb.cb_first = B_TRUE;
          cb.cb_sources = ZPROP_SRC_ALL;
          cb.cb_columns[0] = GET_COL_NAME;
          cb.cb_columns[1] = GET_COL_PROPERTY;
--- 4688,4702 ----
  {
          zprop_get_cbdata_t cb = { 0 };
          zprop_list_t fake_name = { 0 };
          int ret;
  
!         if (argc < 2) {
!                 (void) fprintf(stderr, gettext("missing property "
!                     "argument\n"));
                  usage(B_FALSE);
+         }
  
          cb.cb_first = B_TRUE;
          cb.cb_sources = ZPROP_SRC_ALL;
          cb.cb_columns[0] = GET_COL_NAME;
          cb.cb_columns[1] = GET_COL_PROPERTY;