summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua M. Clulow <josh@sysmgr.org>2022-03-28 16:44:42 -0700
committerJoshua M. Clulow <josh@sysmgr.org>2022-03-28 16:44:42 -0700
commit7d6cab3f0d6a4cea17d062d3a93e223b15de705c (patch)
tree0f1fbc34678b2098bac3ab2558844c0322989897
parentfe07c600e1e51d75e87d45aef001e9d6131ecdb8 (diff)
downloadillumos-joyent-7d6cab3f0d6a4cea17d062d3a93e223b15de705c.tar.gz
14593 zpool online -e hangs forever after 14022
Reviewed by: Andy Fiddaman <andy@omnios.org> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 844582b3c2..6e634a81cb 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -44,6 +44,8 @@
#include <sys/efi_partition.h>
#include <sys/vtoc.h>
#include <sys/zfs_ioctl.h>
+#include <sys/modctl.h>
+#include <sys/mkdev.h>
#include <dlfcn.h>
#include <libzutil.h>
@@ -2799,9 +2801,11 @@ static int
zpool_relabel_disk(libzfs_handle_t *hdl, const char *name, const char *msg)
{
char path[MAXPATHLEN];
- enum dkio_state st;
int fd, error;
int (*_efi_use_whole_disk)(int);
+ char drv[MODMAXNAMELEN];
+ major_t maj;
+ struct stat st;
if ((_efi_use_whole_disk = (int (*)(int))dlsym(RTLD_DEFAULT,
"efi_use_whole_disk")) == NULL)
@@ -2834,9 +2838,18 @@ zpool_relabel_disk(libzfs_handle_t *hdl, const char *name, const char *msg)
* it to be checked by querying the device state, otherwise the
* subsequent vdev_reopen() will very likely fail to read the device
* size, faulting the pool.
+ *
+ * The dkio(4I) ioctls are implemented by the disk driver rather than
+ * some generic framework, so we limit its use here to drivers with
+ * which it has been tested.
*/
- st = DKIO_NONE;
- (void) ioctl(fd, DKIOCSTATE, (caddr_t)&st);
+ if (fstat(fd, &st) == 0 &&
+ (maj = major(st.st_rdev)) != (major_t)NODEV &&
+ modctl(MODGETNAME, drv, sizeof (drv), &maj) == 0 &&
+ (strcmp(drv, "blkdev") == 0 || strcmp(drv, "sd") == 0)) {
+ enum dkio_state dkst = DKIO_NONE;
+ (void) ioctl(fd, DKIOCSTATE, &dkst);
+ }
(void) close(fd);