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

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/zpool/zpool_vdev.c
          +++ new/usr/src/cmd/zpool/zpool_vdev.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 2013 Nexenta Systems, Inc. All rights reserved.
  24   25   * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
  25   26   * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
  26   27   */
  27   28  
  28   29  /*
  29   30   * Functions to convert between a list of vdevs and an nvlist representing the
  30   31   * configuration.  Each entry in the list can be one of:
  31   32   *
  32   33   *      Device vdevs
  33   34   *              disk=(path=..., devid=...)
↓ open down ↓ 346 lines elided ↑ open up ↑
 380  381  /*
 381  382   * Create a leaf vdev.  Determine if this is a file or a device.  If it's a
 382  383   * device, fill in the device id to make a complete nvlist.  Valid forms for a
 383  384   * leaf vdev are:
 384  385   *
 385  386   *      /dev/dsk/xxx    Complete disk path
 386  387   *      /xxx            Full path to file
 387  388   *      xxx             Shorthand for /dev/dsk/xxx
 388  389   */
 389  390  static nvlist_t *
 390      -make_leaf_vdev(const char *arg, uint64_t is_log)
      391 +make_leaf_vdev(const char *arg, uint64_t is_log, uint64_t is_special)
 391  392  {
 392  393          char path[MAXPATHLEN];
 393  394          struct stat64 statbuf;
 394  395          nvlist_t *vdev = NULL;
 395  396          char *type = NULL;
 396  397          boolean_t wholedisk = B_FALSE;
 397  398  
 398  399          /*
 399  400           * Determine what type of vdev this is, and put the full path into
 400  401           * 'path'.  We detect whether this is a device of file afterwards by
↓ open down ↓ 63 lines elided ↑ open up ↑
 464  465  
 465  466          /*
 466  467           * Finally, we have the complete device or file, and we know that it is
 467  468           * acceptable to use.  Construct the nvlist to describe this vdev.  All
 468  469           * vdevs have a 'path' element, and devices also have a 'devid' element.
 469  470           */
 470  471          verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
 471  472          verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
 472  473          verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
 473  474          verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
      475 +        verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_SPECIAL,
      476 +            is_special) == 0);
 474  477          if (strcmp(type, VDEV_TYPE_DISK) == 0)
 475  478                  verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
 476  479                      (uint64_t)wholedisk) == 0);
 477  480  
 478  481          /*
 479  482           * For a whole disk, defer getting its devid until after labeling it.
 480  483           */
 481  484          if (S_ISBLK(statbuf.st_mode) && !wholedisk) {
 482  485                  /*
 483  486                   * Get the devid for the device.
↓ open down ↓ 137 lines elided ↑ open up ↑
 621  624                                  char *childtype;
 622  625                                  int fd, err;
 623  626  
 624  627                                  rep.zprl_children++;
 625  628  
 626  629                                  verify(nvlist_lookup_string(cnv,
 627  630                                      ZPOOL_CONFIG_TYPE, &childtype) == 0);
 628  631  
 629  632                                  /*
 630  633                                   * If this is a replacing or spare vdev, then
 631      -                                 * get the real first child of the vdev: do this
 632      -                                 * in a loop because replacing and spare vdevs
 633      -                                 * can be nested.
      634 +                                 * get the real first child of the vdev.
 634  635                                   */
 635      -                                while (strcmp(childtype,
      636 +                                if (strcmp(childtype,
 636  637                                      VDEV_TYPE_REPLACING) == 0 ||
 637  638                                      strcmp(childtype, VDEV_TYPE_SPARE) == 0) {
 638  639                                          nvlist_t **rchild;
 639  640                                          uint_t rchildren;
 640  641  
 641  642                                          verify(nvlist_lookup_nvlist_array(cnv,
 642  643                                              ZPOOL_CONFIG_CHILDREN, &rchild,
 643  644                                              &rchildren) == 0);
 644  645                                          assert(rchildren == 2);
 645  646                                          cnv = rchild[0];
↓ open down ↓ 530 lines elided ↑ open up ↑
1176 1177                          *mindev = 1;
1177 1178                  return (VDEV_TYPE_LOG);
1178 1179          }
1179 1180  
1180 1181          if (strcmp(type, "cache") == 0) {
1181 1182                  if (mindev != NULL)
1182 1183                          *mindev = 1;
1183 1184                  return (VDEV_TYPE_L2CACHE);
1184 1185          }
1185 1186  
     1187 +        if (strcmp(type, "special") == 0) {
     1188 +                if (mindev != NULL)
     1189 +                        *mindev = 1;
     1190 +                return (VDEV_TYPE_SPECIAL);
     1191 +        }
     1192 +
1186 1193          return (NULL);
1187 1194  }
1188 1195  
1189 1196  /*
1190 1197   * Construct a syntactically valid vdev specification,
1191 1198   * and ensure that all devices and files exist and can be opened.
1192 1199   * Note: we don't bother freeing anything in the error paths
1193 1200   * because the program is just going to exit anyway.
1194 1201   */
1195 1202  nvlist_t *
1196 1203  construct_spec(int argc, char **argv)
1197 1204  {
1198 1205          nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
1199 1206          int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
     1207 +        int nspecial = 0;
1200 1208          const char *type;
1201      -        uint64_t is_log;
1202      -        boolean_t seen_logs;
     1209 +        boolean_t is_log, seen_logs;
     1210 +        boolean_t is_special, seen_special;
1203 1211  
1204 1212          top = NULL;
1205 1213          toplevels = 0;
1206 1214          spares = NULL;
1207 1215          l2cache = NULL;
1208 1216          nspares = 0;
1209 1217          nlogs = 0;
1210 1218          nl2cache = 0;
1211 1219          is_log = B_FALSE;
1212 1220          seen_logs = B_FALSE;
     1221 +        is_special = B_FALSE;
     1222 +        seen_special = B_FALSE;
1213 1223  
1214 1224          while (argc > 0) {
1215 1225                  nv = NULL;
1216 1226  
1217 1227                  /*
1218 1228                   * If it's a mirror or raidz, the subsequent arguments are
1219 1229                   * its leaves -- until we encounter the next mirror or raidz.
1220 1230                   */
1221 1231                  if ((type = is_grouping(argv[0], &mindev, &maxdev)) != NULL) {
1222 1232                          nvlist_t **child = NULL;
↓ open down ↓ 1 lines elided ↑ open up ↑
1224 1234  
1225 1235                          if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
1226 1236                                  if (spares != NULL) {
1227 1237                                          (void) fprintf(stderr,
1228 1238                                              gettext("invalid vdev "
1229 1239                                              "specification: 'spare' can be "
1230 1240                                              "specified only once\n"));
1231 1241                                          return (NULL);
1232 1242                                  }
1233 1243                                  is_log = B_FALSE;
     1244 +                                is_special = B_FALSE;
1234 1245                          }
1235 1246  
1236 1247                          if (strcmp(type, VDEV_TYPE_LOG) == 0) {
1237 1248                                  if (seen_logs) {
1238 1249                                          (void) fprintf(stderr,
1239 1250                                              gettext("invalid vdev "
1240 1251                                              "specification: 'log' can be "
1241 1252                                              "specified only once\n"));
1242 1253                                          return (NULL);
1243 1254                                  }
1244 1255                                  seen_logs = B_TRUE;
1245 1256                                  is_log = B_TRUE;
     1257 +                                is_special = B_FALSE;
1246 1258                                  argc--;
1247 1259                                  argv++;
1248 1260                                  /*
1249 1261                                   * A log is not a real grouping device.
1250 1262                                   * We just set is_log and continue.
1251 1263                                   */
1252 1264                                  continue;
1253 1265                          }
1254 1266  
1255 1267                          if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
1256 1268                                  if (l2cache != NULL) {
1257 1269                                          (void) fprintf(stderr,
1258 1270                                              gettext("invalid vdev "
1259 1271                                              "specification: 'cache' can be "
1260 1272                                              "specified only once\n"));
1261 1273                                          return (NULL);
1262 1274                                  }
1263 1275                                  is_log = B_FALSE;
     1276 +                                is_special = B_FALSE;
1264 1277                          }
1265 1278  
     1279 +                        if (strcmp(type, VDEV_TYPE_SPECIAL) == 0) {
     1280 +                                if (seen_special) {
     1281 +                                        (void) fprintf(stderr,
     1282 +                                            gettext("invalid vdev "
     1283 +                                            "specification: 'special' can be "
     1284 +                                            "specified only once\n"));
     1285 +                                        return (NULL);
     1286 +                                }
     1287 +                                seen_special = B_TRUE;
     1288 +                                is_log = B_FALSE;
     1289 +                                is_special = B_TRUE;
     1290 +                                argc--;
     1291 +                                argv++;
     1292 +                                /*
     1293 +                                 * A special is not a real grouping device.
     1294 +                                 * We just set is_special and continue.
     1295 +                                 */
     1296 +                                continue;
     1297 +                        }
     1298 +
1266 1299                          if (is_log) {
1267 1300                                  if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
1268 1301                                          (void) fprintf(stderr,
1269 1302                                              gettext("invalid vdev "
1270 1303                                              "specification: unsupported 'log' "
1271 1304                                              "device: %s\n"), type);
1272 1305                                          return (NULL);
1273 1306                                  }
1274 1307                                  nlogs++;
1275 1308                          }
1276 1309  
     1310 +                        if (is_special) {
     1311 +                                if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
     1312 +                                        (void) fprintf(stderr,
     1313 +                                            gettext("invalid vdev "
     1314 +                                            "specification: unsupported "
     1315 +                                            "'special' device: %s\n"), type);
     1316 +                                        return (NULL);
     1317 +                                }
     1318 +                                nspecial++;
     1319 +                        }
     1320 +
1277 1321                          for (c = 1; c < argc; c++) {
1278 1322                                  if (is_grouping(argv[c], NULL, NULL) != NULL)
1279 1323                                          break;
1280 1324                                  children++;
1281 1325                                  child = realloc(child,
1282 1326                                      children * sizeof (nvlist_t *));
1283 1327                                  if (child == NULL)
1284 1328                                          zpool_no_memory();
1285      -                                if ((nv = make_leaf_vdev(argv[c], B_FALSE))
1286      -                                    == NULL)
     1329 +                                if ((nv = make_leaf_vdev(argv[c],
     1330 +                                    (uint64_t)B_FALSE,
     1331 +                                    (uint64_t)B_FALSE)) == NULL)
1287 1332                                          return (NULL);
1288 1333                                  child[children - 1] = nv;
1289 1334                          }
1290 1335  
1291 1336                          if (children < mindev) {
1292 1337                                  (void) fprintf(stderr, gettext("invalid vdev "
1293 1338                                      "specification: %s requires at least %d "
1294 1339                                      "devices\n"), argv[0], mindev);
1295 1340                                  return (NULL);
1296 1341                          }
↓ open down ↓ 15 lines elided ↑ open up ↑
1312 1357                          } else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
1313 1358                                  l2cache = child;
1314 1359                                  nl2cache = children;
1315 1360                                  continue;
1316 1361                          } else {
1317 1362                                  verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
1318 1363                                      0) == 0);
1319 1364                                  verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
1320 1365                                      type) == 0);
1321 1366                                  verify(nvlist_add_uint64(nv,
1322      -                                    ZPOOL_CONFIG_IS_LOG, is_log) == 0);
     1367 +                                    ZPOOL_CONFIG_IS_LOG,
     1368 +                                    (uint64_t)is_log) == 0);
     1369 +                                verify(nvlist_add_uint64(nv,
     1370 +                                    ZPOOL_CONFIG_IS_SPECIAL,
     1371 +                                    (uint64_t)is_special) == 0);
1323 1372                                  if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
1324 1373                                          verify(nvlist_add_uint64(nv,
1325 1374                                              ZPOOL_CONFIG_NPARITY,
1326 1375                                              mindev - 1) == 0);
1327 1376                                  }
1328 1377                                  verify(nvlist_add_nvlist_array(nv,
1329 1378                                      ZPOOL_CONFIG_CHILDREN, child,
1330 1379                                      children) == 0);
1331 1380  
1332 1381                                  for (c = 0; c < children; c++)
1333 1382                                          nvlist_free(child[c]);
1334 1383                                  free(child);
1335 1384                          }
1336 1385                  } else {
1337 1386                          /*
1338 1387                           * We have a device.  Pass off to make_leaf_vdev() to
1339 1388                           * construct the appropriate nvlist describing the vdev.
1340 1389                           */
1341      -                        if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
     1390 +                        if ((nv = make_leaf_vdev(argv[0], (uint64_t)is_log,
     1391 +                            (uint64_t)is_special)) == NULL)
1342 1392                                  return (NULL);
1343 1393                          if (is_log)
1344 1394                                  nlogs++;
     1395 +                        if (is_special)
     1396 +                                nspecial++;
1345 1397                          argc--;
1346 1398                          argv++;
1347 1399                  }
1348 1400  
1349 1401                  toplevels++;
1350 1402                  top = realloc(top, toplevels * sizeof (nvlist_t *));
1351 1403                  if (top == NULL)
1352 1404                          zpool_no_memory();
1353 1405                  top[toplevels - 1] = nv;
1354 1406          }
1355 1407  
1356 1408          if (toplevels == 0 && nspares == 0 && nl2cache == 0) {
1357 1409                  (void) fprintf(stderr, gettext("invalid vdev "
1358 1410                      "specification: at least one toplevel vdev must be "
1359 1411                      "specified\n"));
1360 1412                  return (NULL);
1361 1413          }
     1414 +
     1415 +        if (seen_special && nspecial == 0) {
     1416 +                (void) fprintf(stderr, gettext("invalid vdev specification: "
     1417 +                    "special requires at least 1 device\n"));
     1418 +                return (NULL);
     1419 +        }
1362 1420  
1363 1421          if (seen_logs && nlogs == 0) {
1364 1422                  (void) fprintf(stderr, gettext("invalid vdev specification: "
1365 1423                      "log requires at least 1 device\n"));
1366 1424                  return (NULL);
1367 1425          }
1368 1426  
1369 1427          /*
1370 1428           * Finally, create nvroot and add all top-level vdevs to it.
1371 1429           */
↓ open down ↓ 141 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX