Always preserve the passed path at creation time so udev may be used
After spending considerable time thinking about this I've come to the conclusion that on Linux systems we don't need Solaris style devid support. Instead was can simply use udev if we are careful, there are even some advantages. The Solaris style devid's are designed to provide a mechanism by which a device can be opened reliably regardless of it's location in the system. This is exactly what udev provides us on Linux, a flexible mechanism for consistently identifing the same devices regardless of probing order. We just need to be careful to always open the device by the path provided at creation time, this path must be stored in ZPOOL_CONFIG_PATH. This in fact has certain advantages. For example, if in your system you always want the zpool to be able to locate the disk regardless of physical location you can create the pool using /dev/disk/by-id/. This is perhaps what you'ld want on a desktop system where the exact location is not that important. It's more critical that all the disks can be found. However, in an enterprise setup there's a good chace that the physical location of each drive is important. You have like set things up such that your raid groups span multiple hosts adapters, such that you can lose an adapter without downtime. In this case you would want to use the /dev/disk/by-path/ path to ensure the path information is preserved and you always open the disks at the right physical locations. This would ensure your system never gets accidently misconfigured and still just works because the zpool was still able to locate the disk. Finally, if you want to get really fancy you can always create your own udev rules. This way you could implement whatever lookup sceme you wanted in user space for your drives. This would include nice cosmetic things like being able to control the device names in tools like zpool status, since the name as just based of the device names. I've yet to come up with a good reason to implement devid support on Linux since we have udev. But I've still just commented it out for now because somebody might come up with a really good I forgot.
This commit is contained in:
parent
58d6f53677
commit
5be28776fb
|
@ -192,7 +192,7 @@ check_slice(const char *path, blkid_cache cache, int force, boolean_t isspare)
|
|||
int err;
|
||||
|
||||
if (stat64(path, &statbuf) != 0) {
|
||||
vdev_error(gettext("cannot open %s: %s\n"),
|
||||
vdev_error(gettext("cannot stat %s: %s\n"),
|
||||
path, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
@ -295,7 +295,15 @@ check_disk(const char *path, blkid_cache cache, int force,
|
|||
uuid_is_null((uchar_t *)&vtoc->efi_parts[i].p_guid))
|
||||
continue;
|
||||
|
||||
sprintf(slice_path, "%s%d", path, i+1);
|
||||
/* Resolve possible symlink to safely append partition */
|
||||
if (realpath(path, slice_path) == NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot resolve path '%s'\n"), slice_path);
|
||||
err = errno;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(slice_path, "%s%d", slice_path, i+1);
|
||||
err = check_slice(slice_path, cache, force, isspare);
|
||||
if (err)
|
||||
break;
|
||||
|
@ -400,7 +408,9 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
|||
* Complete device or file path. Exact type is determined by
|
||||
* examining the file descriptor afterwards. Symbolic links
|
||||
* are resolved to their real paths for the is_whole_disk()
|
||||
* and S_ISBLK/S_ISREG type checks.
|
||||
* and S_ISBLK/S_ISREG type checks. However, we are careful
|
||||
* to store the given path as ZPOOL_CONFIG_PATH to ensure we
|
||||
* can leverage udev's persistent device labels.
|
||||
*/
|
||||
if (realpath(arg, path) == NULL) {
|
||||
(void) fprintf(stderr,
|
||||
|
@ -415,6 +425,9 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
|||
path, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* After is_whole_disk() check restore original passed path */
|
||||
strlcpy(path, arg, MAXPATHLEN);
|
||||
} else {
|
||||
/*
|
||||
* This may be a short path for a device, or it could be total
|
||||
|
@ -476,6 +489,7 @@ 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.
|
||||
*/
|
||||
|
@ -510,6 +524,7 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
|||
|
||||
(void) close(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (vdev);
|
||||
}
|
||||
|
@ -954,21 +969,36 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
diskname = strrchr(path, '/');
|
||||
if (realpath(path, buf) == NULL) {
|
||||
ret = errno;
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot resolve path '%s'\n"), path);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
diskname = strrchr(buf, '/');
|
||||
assert(diskname != NULL);
|
||||
diskname++;
|
||||
if (zpool_label_disk(g_zfs, zhp, diskname) == -1)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Fill in the devid, now that we've labeled the disk.
|
||||
* Fill in the devid, now that we've labeled the disk. We
|
||||
* attempt to open the new zfs slice first by appending the
|
||||
* slice number. If that fails this may be a Linux udev
|
||||
* path in which case the -part# convention is tried.
|
||||
*/
|
||||
(void) snprintf(buf, sizeof (buf), "%s%s", path, FIRST_SLICE);
|
||||
if ((fd = open(buf, O_RDONLY)) < 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': %s\n"),
|
||||
buf, strerror(errno));
|
||||
return (-1);
|
||||
|
||||
(void) snprintf(buf, sizeof (buf), "%s%s%s",
|
||||
path, "-part", FIRST_SLICE);
|
||||
if ((fd = open(buf, O_RDONLY)) < 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': %s\n"),
|
||||
buf, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__sun__) || defined(__sun)
|
||||
|
|
|
@ -2617,12 +2617,11 @@ set_path(zpool_handle_t *zhp, nvlist_t *nv, const char *path)
|
|||
char *
|
||||
zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
|
||||
{
|
||||
char *path, *devid;
|
||||
char *path, *devid, *type;
|
||||
uint64_t value;
|
||||
char buf[64];
|
||||
vdev_stat_t *vs;
|
||||
uint_t vsc;
|
||||
size_t droot_len = strlen(DISK_ROOT) + 1;
|
||||
|
||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
|
||||
&value) == 0) {
|
||||
|
@ -2632,7 +2631,6 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
|
|||
(u_longlong_t)value);
|
||||
path = buf;
|
||||
} else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
|
||||
|
||||
/*
|
||||
* If the device is dead (faulted, offline, etc) then don't
|
||||
* bother opening it. Otherwise we may be forcing the user to
|
||||
|
@ -2671,13 +2669,18 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv)
|
|||
devid_str_free(newdevid);
|
||||
}
|
||||
|
||||
if (strncmp(path, DISK_ROOT "/", droot_len) == 0)
|
||||
path += droot_len;
|
||||
/*
|
||||
* For a block device only use the name.
|
||||
*/
|
||||
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0) {
|
||||
path = strrchr(path, '/');
|
||||
path++;
|
||||
}
|
||||
|
||||
#if defined(__sun__) || defined(__sun)
|
||||
/*
|
||||
* The following code strips the slice from the device path.
|
||||
* This is only meaningful in Solaris.
|
||||
*/
|
||||
if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
&value) == 0 && value) {
|
||||
|
|
Loading…
Reference in New Issue