* xxx Shorthand for /dev/disk/yyy/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;
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);
}
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);
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.
+ */
+ zfs_append_partition(path, udevpath, sizeof (udevpath));
+ 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.
*/
- zfs_append_partition(path, buf, sizeof (buf));
-
- 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);
}
* chop off the slice 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);
}
* 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;
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;
* 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++;
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);
* 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;
* 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))