X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=cmd%2Fzpool%2Fzpool_vdev.c;h=da121f06fa99a7bb0cddeb5e64240afd6156698f;hb=4588bf57017f5d2693cd7b3f763640fe8cfe5909;hp=d4838ad2dc5d0732742ff7db36a8cfd5426b21ff;hpb=5c1bad0013204d70c5b60713af977bdaa5df1302;p=zfs.git diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c index d4838ad..da121f0 100644 --- a/cmd/zpool/zpool_vdev.c +++ b/cmd/zpool/zpool_vdev.c @@ -188,19 +188,10 @@ check_error(int err) static int check_slice(const char *path, blkid_cache cache, int force, boolean_t isspare) { - struct stat64 statbuf; int err; #ifdef HAVE_LIBBLKID char *value; -#endif /* HAVE_LIBBLKID */ - if (stat64(path, &statbuf) != 0) { - vdev_error(gettext("cannot stat %s: %s\n"), - path, strerror(errno)); - return (-1); - } - -#ifdef HAVE_LIBBLKID /* No valid type detected device is safe to use */ value = blkid_get_tag_value(cache, "TYPE", path); if (value == NULL) @@ -375,32 +366,20 @@ is_whole_disk(const char *path) /* * This may be a shorthand device path or it could be total gibberish. - * Check to see if it's a known device in /dev/, /dev/disk/by-id, - * /dev/disk/by-label, /dev/disk/by-path, /dev/disk/by-uuid, or - * /dev/disk/zpool/. As part of this check, see if we've been given - * an entire disk (minus the slice number). + * Check to see if it is a known device available in zfs_vdev_paths. + * As part of this check, see if we've been given an entire disk + * (minus the slice number). */ static int is_shorthand_path(const char *arg, char *path, struct stat64 *statbuf, boolean_t *wholedisk) { - char dirs[5][9] = {"by-id", "by-label", "by-path", "by-uuid", "zpool"}; - int i, err; - - /* /dev/ */ - (void) snprintf(path, MAXPATHLEN, "%s/%s", DISK_ROOT, arg); - *wholedisk = is_whole_disk(path); - err = stat64(path, statbuf); - if (*wholedisk || err == 0) - return (0); + int error; - /* /dev/disk// */ - for (i = 0; i < 5; i++) { - (void) snprintf(path, MAXPATHLEN, "%s/%s/%s", - UDISK_ROOT, dirs[i], arg); + error = zfs_resolve_shortname(arg, path, MAXPATHLEN); + if (error == 0) { *wholedisk = is_whole_disk(path); - err = stat64(path, statbuf); - if (*wholedisk || err == 0) + if (*wholedisk || (stat64(path, statbuf) == 0)) return (0); } @@ -408,7 +387,7 @@ is_shorthand_path(const char *arg, char *path, memset(statbuf, 0, sizeof(*statbuf)); *wholedisk = B_FALSE; - return (ENOENT); + return (error); } /* @@ -416,12 +395,12 @@ is_shorthand_path(const char *arg, char *path, * device, fill in the device id to make a complete nvlist. Valid forms for a * leaf vdev are: * - * /dev/xxx Complete disk path - * /xxx Full path to file - * xxx Shorthand for /dev/disk/yyy/xxx + * /dev/xxx Complete disk path + * /xxx Full path to file + * xxx Shorthand for /xxx */ static nvlist_t * -make_leaf_vdev(const char *arg, uint64_t is_log) +make_leaf_vdev(nvlist_t *props, const char *arg, uint64_t is_log) { char path[MAXPATHLEN]; struct stat64 statbuf; @@ -513,42 +492,18 @@ make_leaf_vdev(const char *arg, uint64_t is_log) verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK, (uint64_t)wholedisk) == 0); -#if defined(__sun__) || defined(__sun) - /* - * For a whole disk, defer getting its devid until after labeling it. - */ - if (S_ISBLK(statbuf.st_mode) && !wholedisk) { - /* - * Get the devid for the device. - */ - int fd; - ddi_devid_t devid; - char *minor = NULL, *devid_str = NULL; - - if ((fd = open(path, O_RDONLY|O_EXCL)) < 0) { - (void) fprintf(stderr, gettext("cannot open '%s': " - "%s\n"), path, strerror(errno)); - nvlist_free(vdev); - return (NULL); - } + if (props != NULL) { + uint64_t ashift = 0; + char *value = NULL; - if (devid_get(fd, &devid) == 0) { - if (devid_get_minor_name(fd, &minor) == 0 && - (devid_str = devid_str_encode(devid, minor)) != - NULL) { - verify(nvlist_add_string(vdev, - ZPOOL_CONFIG_DEVID, devid_str) == 0); - } - if (devid_str != NULL) - devid_str_free(devid_str); - if (minor != NULL) - devid_str_free(minor); - devid_free(devid); - } + if (nvlist_lookup_string(props, + zpool_prop_to_name(ZPOOL_PROP_ASHIFT), &value) == 0) + zfs_nicestrtonum(NULL, value, &ashift); - (void) close(fd); + if (ashift > 0) + verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_ASHIFT, + ashift) == 0); } -#endif return (vdev); } @@ -960,8 +915,10 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv) nvlist_t **child; uint_t c, children; char *type, *path, *diskname; - char buf[MAXPATHLEN]; + char devpath[MAXPATHLEN]; + char udevpath[MAXPATHLEN]; uint64_t wholedisk; + struct stat64 statbuf; int ret; verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0); @@ -988,51 +945,57 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv) return (ret); } - if (realpath(path, buf) == NULL) { + if (realpath(path, devpath) == NULL) { ret = errno; (void) fprintf(stderr, gettext("cannot resolve path '%s'\n"), path); return (ret); } - diskname = strrchr(buf, '/'); + /* + * Remove any previously existing symlink from a udev path to + * the device before labeling the disk. This makes + * zpool_label_disk_wait() truly wait for the new link to show + * up instead of returning if it finds an old link still in + * place. Otherwise there is a window between when udev + * deletes and recreates the link during which access attempts + * will fail with ENOENT. + */ + strncpy(udevpath, path, MAXPATHLEN); + (void) zfs_append_partition(udevpath, MAXPATHLEN); + + if ((strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT)) == 0) && + (lstat64(udevpath, &statbuf) == 0) && + S_ISLNK(statbuf.st_mode)) + (void) unlink(udevpath); + + diskname = strrchr(devpath, '/'); assert(diskname != NULL); diskname++; if (zpool_label_disk(g_zfs, zhp, diskname) == -1) return (-1); /* - * Now the we've labeled the disk and the partitions have - * been created. We still need to wait for udev to create - * the symlinks to those partitions. If we are accessing - * the devices via a udev disk path, /dev/disk, then wait - * for *-part# to be created. Otherwise just use the normal - * syntax for devices in /dev. + * Now we've labeled the disk and the partitions have been + * created. We still need to wait for udev to create the + * symlinks to those partitions. */ - if (strncmp(path, UDISK_ROOT, strlen(UDISK_ROOT)) == 0) - (void) snprintf(buf, sizeof (buf), - "%s%s%s", path, "-part", FIRST_SLICE); - else - (void) snprintf(buf, sizeof (buf), - "%s%s%s", path, isdigit(path[strlen(path)-1]) ? - "p" : "", FIRST_SLICE); - - if ((ret = zpool_label_disk_wait(buf, 1000)) != 0) { + if ((ret = zpool_label_disk_wait(udevpath, 1000)) != 0) { (void) fprintf(stderr, - gettext( "cannot resolve path '%s'\n"), buf); + gettext( "cannot resolve path '%s'\n"), udevpath); return (-1); } /* - * Update the path to refer to FIRST_SLICE. The presence of + * Update the path to refer to the partition. The presence of * the 'whole_disk' field indicates to the CLI that we should - * chop off the slice number when displaying the device in + * chop off the partition number when displaying the device in * future output. */ - verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, buf) == 0); + verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, udevpath) == 0); /* Just in case this partition already existed. */ - (void) zero_label(buf); + (void) zero_label(udevpath); return (0); } @@ -1240,7 +1203,7 @@ is_grouping(const char *type, int *mindev, int *maxdev) * because the program is just going to exit anyway. */ nvlist_t * -construct_spec(int argc, char **argv) +construct_spec(nvlist_t *props, int argc, char **argv) { nvlist_t *nvroot, *nv, **top, **spares, **l2cache; int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache; @@ -1329,7 +1292,7 @@ construct_spec(int argc, char **argv) children * sizeof (nvlist_t *)); if (child == NULL) zpool_no_memory(); - if ((nv = make_leaf_vdev(argv[c], B_FALSE)) + if ((nv = make_leaf_vdev(props, argv[c], B_FALSE)) == NULL) return (NULL); child[children - 1] = nv; @@ -1385,7 +1348,7 @@ construct_spec(int argc, char **argv) * 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) + if ((nv = make_leaf_vdev(props, argv[0], is_log)) == NULL) return (NULL); if (is_log) nlogs++; @@ -1451,7 +1414,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props, uint_t c, children; if (argc > 0) { - if ((newroot = construct_spec(argc, argv)) == NULL) { + if ((newroot = construct_spec(props, argc, argv)) == NULL) { (void) fprintf(stderr, gettext("Unable to build a " "pool from the specified devices\n")); return (NULL); @@ -1501,7 +1464,7 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props, * added, even if they appear in use. */ nvlist_t * -make_root_vdev(zpool_handle_t *zhp, int force, int check_rep, +make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep, boolean_t replacing, boolean_t dryrun, int argc, char **argv) { nvlist_t *newroot; @@ -1513,7 +1476,7 @@ make_root_vdev(zpool_handle_t *zhp, int force, int check_rep, * that we have a valid specification, and that all devices can be * opened. */ - if ((newroot = construct_spec(argc, argv)) == NULL) + if ((newroot = construct_spec(props, argc, argv)) == NULL) return (NULL); if (zhp && ((poolconfig = zpool_get_config(zhp, NULL)) == NULL))