X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=cmd%2Fzpool%2Fzpool_vdev.c;h=53c2e60b7dd5edb58465190260588f9c507d73ae;hb=0e5b68e0159e071dae2cac01c2b6783b8e926133;hp=10007c14927f6961051c68e0eed420e6e958b454;hpb=172bb4bd5e4afef721dd4d2972d8680d983f144b;p=zfs.git diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c index 10007c1..53c2e60 100644 --- a/cmd/zpool/zpool_vdev.c +++ b/cmd/zpool/zpool_vdev.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -67,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -1003,8 +1003,8 @@ is_spare(nvlist_t *config, const char *path) return (B_FALSE); } free(name); - (void) close(fd); + verify(nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &guid) == 0); nvlist_free(label); @@ -1028,8 +1028,8 @@ is_spare(nvlist_t *config, const char *path) * the majority of this task. */ static int -check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing, - int isspare) +check_in_use(nvlist_t *config, nvlist_t *nv, boolean_t force, + boolean_t replacing, boolean_t isspare) { nvlist_t **child; uint_t c, children; @@ -1050,13 +1050,14 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing, * hot spare within the same pool. If so, we allow it * regardless of what libdiskmgt or zpool_in_use() says. */ - if (isreplacing) { + if (replacing) { if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &wholedisk) == 0 && wholedisk) (void) snprintf(buf, sizeof (buf), "%ss0", path); else (void) strlcpy(buf, path, sizeof (buf)); + if (is_spare(config, buf)) return (0); } @@ -1072,41 +1073,56 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing, for (c = 0; c < children; c++) if ((ret = check_in_use(config, child[c], force, - isreplacing, B_FALSE)) != 0) + replacing, B_FALSE)) != 0) return (ret); if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, &children) == 0) for (c = 0; c < children; c++) if ((ret = check_in_use(config, child[c], force, - isreplacing, B_TRUE)) != 0) + replacing, B_TRUE)) != 0) return (ret); if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, &child, &children) == 0) for (c = 0; c < children; c++) if ((ret = check_in_use(config, child[c], force, - isreplacing, B_FALSE)) != 0) + replacing, B_FALSE)) != 0) return (ret); return (0); } static const char * -is_grouping(const char *type, int *mindev) +is_grouping(const char *type, int *mindev, int *maxdev) { - if (strcmp(type, "raidz") == 0 || strcmp(type, "raidz1") == 0) { - if (mindev != NULL) - *mindev = 2; - return (VDEV_TYPE_RAIDZ); - } + if (strncmp(type, "raidz", 5) == 0) { + const char *p = type + 5; + char *end; + long nparity; + + if (*p == '\0') { + nparity = 1; + } else if (*p == '0') { + return (NULL); /* no zero prefixes allowed */ + } else { + errno = 0; + nparity = strtol(p, &end, 10); + if (errno != 0 || nparity < 1 || nparity >= 255 || + *end != '\0') + return (NULL); + } - if (strcmp(type, "raidz2") == 0) { if (mindev != NULL) - *mindev = 3; + *mindev = nparity + 1; + if (maxdev != NULL) + *maxdev = 255; return (VDEV_TYPE_RAIDZ); } + if (maxdev != NULL) + *maxdev = INT_MAX; + if (strcmp(type, "mirror") == 0) { if (mindev != NULL) *mindev = 2; @@ -1144,7 +1160,7 @@ nvlist_t * construct_spec(int argc, char **argv) { nvlist_t *nvroot, *nv, **top, **spares, **l2cache; - int t, toplevels, mindev, nspares, nlogs, nl2cache; + int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache; const char *type; uint64_t is_log; boolean_t seen_logs; @@ -1166,7 +1182,7 @@ construct_spec(int argc, char **argv) * If it's a mirror or raidz, the subsequent arguments are * its leaves -- until we encounter the next mirror or raidz. */ - if ((type = is_grouping(argv[0], &mindev)) != NULL) { + if ((type = is_grouping(argv[0], &mindev, &maxdev)) != NULL) { nvlist_t **child = NULL; int c, children = 0; @@ -1223,7 +1239,7 @@ construct_spec(int argc, char **argv) } for (c = 1; c < argc; c++) { - if (is_grouping(argv[c], NULL) != NULL) + if (is_grouping(argv[c], NULL, NULL) != NULL) break; children++; child = realloc(child, @@ -1243,6 +1259,13 @@ construct_spec(int argc, char **argv) return (NULL); } + if (children > maxdev) { + (void) fprintf(stderr, gettext("invalid vdev " + "specification: %s supports no more than " + "%d devices\n"), argv[0], maxdev); + return (NULL); + } + argc -= c; argv += c; @@ -1337,6 +1360,52 @@ construct_spec(int argc, char **argv) return (nvroot); } +nvlist_t * +split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props, + splitflags_t flags, int argc, char **argv) +{ + nvlist_t *newroot = NULL, **child; + uint_t c, children; + + if (argc > 0) { + if ((newroot = construct_spec(argc, argv)) == NULL) { + (void) fprintf(stderr, gettext("Unable to build a " + "pool from the specified devices\n")); + return (NULL); + } + + if (!flags.dryrun && make_disks(zhp, newroot) != 0) { + nvlist_free(newroot); + return (NULL); + } + + /* avoid any tricks in the spec */ + verify(nvlist_lookup_nvlist_array(newroot, + ZPOOL_CONFIG_CHILDREN, &child, &children) == 0); + for (c = 0; c < children; c++) { + char *path; + const char *type; + int min, max; + + verify(nvlist_lookup_string(child[c], + ZPOOL_CONFIG_PATH, &path) == 0); + if ((type = is_grouping(path, &min, &max)) != NULL) { + (void) fprintf(stderr, gettext("Cannot use " + "'%s' as a device for splitting\n"), type); + nvlist_free(newroot); + return (NULL); + } + } + } + + if (zpool_vdev_split(zhp, newname, &newroot, props, flags) != 0) { + if (newroot != NULL) + nvlist_free(newroot); + return (NULL); + } + + return (newroot); +} /* * Get and validate the contents of the given vdev specification. This ensures @@ -1350,7 +1419,7 @@ construct_spec(int argc, char **argv) */ nvlist_t * make_root_vdev(zpool_handle_t *zhp, int force, int check_rep, - boolean_t isreplacing, boolean_t dryrun, int argc, char **argv) + boolean_t replacing, boolean_t dryrun, int argc, char **argv) { nvlist_t *newroot; nvlist_t *poolconfig = NULL; @@ -1373,8 +1442,7 @@ make_root_vdev(zpool_handle_t *zhp, int force, int check_rep, * uses (such as a dedicated dump device) that even '-f' cannot * override. */ - if (check_in_use(poolconfig, newroot, force, isreplacing, - B_FALSE) != 0) { + if (check_in_use(poolconfig, newroot, force, replacing, B_FALSE) != 0) { nvlist_free(newroot); return (NULL); }