summaryrefslogtreecommitdiffstats
path: root/cmd/zpool/zpool_vdev.c
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2016-04-19 11:19:12 -0700
committerBrian Behlendorf <[email protected]>2016-04-25 11:13:20 -0700
commit2d82ea8b111103b28b8c9ad0f69dd88736248804 (patch)
treec132339412ce0ed9b8f04c6ccb6471317755f59c /cmd/zpool/zpool_vdev.c
parent5b4136bd499a892f65c86af8fd39fa21e05c9148 (diff)
Use udev for partition detection
When ZFS partitions a block device it must wait for udev to create both a device node and all the device symlinks. This process takes a variable length of time and depends on factors such how many links must be created, the complexity of the rules, etc. Complicating the situation further it is not uncommon for udev to create and then remove a link multiple times while processing the udev rules. Given the above, the existing scheme of waiting for an expected partition to appear by name isn't 100% reliable. At this point udev may still remove and recreate think link resulting in the kernel modules being unable to open the device. In order to address this the zpool_label_disk_wait() function has been updated to use libudev. Until the registered system device acknowledges that it in fully initialized the function will wait. Once fully initialized all device links are checked and allowed to settle for 50ms. This makes it far more likely that all the device nodes will exist when the kernel modules need to open them. For systems without libudev an alternate zpool_label_disk_wait() was updated to include a settle time. In addition, the kernel modules were updated to include retry logic for this ENOENT case. Due to the improved checks in the utilities it is unlikely this logic will be invoked. However, if the rare event it is needed it will prevent a failure. Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: Tony Hutter <[email protected]> Signed-off-by: Richard Laager <[email protected]> Closes #4523 Closes #3708 Closes #4077 Closes #4144 Closes #4214 Closes #4517
Diffstat (limited to 'cmd/zpool/zpool_vdev.c')
-rw-r--r--cmd/zpool/zpool_vdev.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c
index 8bbbf6615..cf87554d5 100644
--- a/cmd/zpool/zpool_vdev.c
+++ b/cmd/zpool/zpool_vdev.c
@@ -1198,12 +1198,10 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
/*
* 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.
+ * the device before labeling the disk. This ensures that
+ * only newly created links are used. 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);
@@ -1227,6 +1225,8 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
* and then block until udev creates the new link.
*/
if (!is_exclusive || !is_spare(NULL, udevpath)) {
+ char *devnode = strrchr(devpath, '/') + 1;
+
ret = strncmp(udevpath, UDISK_ROOT, strlen(UDISK_ROOT));
if (ret == 0) {
ret = lstat64(udevpath, &statbuf);
@@ -1234,18 +1234,29 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
(void) unlink(udevpath);
}
- if (zpool_label_disk(g_zfs, zhp,
- strrchr(devpath, '/') + 1) == -1)
+ /*
+ * When labeling a pool the raw device node name
+ * is provided as it appears under /dev/.
+ */
+ if (zpool_label_disk(g_zfs, zhp, devnode) == -1)
return (-1);
+ /*
+ * Wait for udev to signal the device is available
+ * by the provided path.
+ */
ret = zpool_label_disk_wait(udevpath, DISK_LABEL_WAIT);
if (ret) {
- (void) fprintf(stderr, gettext("cannot "
- "resolve path '%s': %d\n"), udevpath, ret);
- return (-1);
+ (void) fprintf(stderr,
+ gettext("missing link: %s was "
+ "partitioned but %s is missing\n"),
+ devnode, udevpath);
+ return (ret);
}
- (void) zero_label(udevpath);
+ ret = zero_label(udevpath);
+ if (ret)
+ return (ret);
}
/*
@@ -1259,8 +1270,7 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
/*
* Update device id strings for whole disks (Linux only)
*/
- if (wholedisk)
- update_vdev_config_dev_strs(nv);
+ update_vdev_config_dev_strs(nv);
return (0);
}