summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2009-10-21 12:04:19 -0700
committerBrian Behlendorf <[email protected]>2009-10-21 12:04:19 -0700
commite0e0bac5a665feec58d42d74edfebd836643c300 (patch)
tree8abfd7a7322d5d8100036a30d4d569c917a42dba
parentc9e138c366039aa3fd3a39ae8918cb5daf2626bd (diff)
parent6367f93602c33690e64388159872023f2759b532 (diff)
Merge branch 'linux-user-disk' into refs/top-bases/linux-zfs-branch
-rw-r--r--cmd/zpool/zpool_vdev.c57
-rw-r--r--lib/libzfs/include/libzfs.h3
-rw-r--r--lib/libzfs/libzfs_pool.c54
3 files changed, 55 insertions, 59 deletions
diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c
index 661946cef..7d4d87ede 100644
--- a/cmd/zpool/zpool_vdev.c
+++ b/cmd/zpool/zpool_vdev.c
@@ -279,7 +279,7 @@ check_disk(const char *path, blkid_cache cache, int force,
* label at the end of the device is intact. Rather than use this
* label we should play it safe and treat this as a non efi device.
*/
- if (vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
+ if (!force && vtoc->efi_flags & EFI_GPT_PRIMARY_CORRUPT) {
vdev_error(gettext(
"%s contains a corrupt primary efi partition table. "
"If you are\nsure you want to use this device use "
@@ -938,12 +938,7 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
char *type, *path, *diskname;
char buf[MAXPATHLEN];
uint64_t wholedisk;
- int fd;
int ret;
-#if defined(__sun__) || defined(__sun)
- ddi_devid_t devid;
- char *minor = NULL, *devid_str = NULL;
-#endif
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
@@ -983,50 +978,34 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
return (-1);
/*
- * 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.
+ * 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.
*/
- (void) snprintf(buf, sizeof (buf), "%s%s", path, FIRST_SLICE);
- if ((fd = open(buf, O_RDONLY)) < 0) {
-
- (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 (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", path, FIRST_SLICE);
-#if defined(__sun__) || defined(__sun)
- 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(nv,
- 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 ((ret = zpool_label_disk_wait(buf, 1000)) != 0) {
+ (void) fprintf(stderr,
+ gettext( "cannot resolve path '%s'\n"), buf);
+ return (-1);
}
-#endif
/*
- * Update the path to refer to the 's0' slice. The presence of
+ * Update the path to refer to FIRST_SLICE. The presence of
* the 'whole_disk' field indicates to the CLI that we should
* chop off the slice number when displaying the device in
* future output.
*/
verify(nvlist_add_string(nv, ZPOOL_CONFIG_PATH, buf) == 0);
- (void) close(fd);
-
/* Just in case this partition already existed. */
(void) zero_label(buf);
diff --git a/lib/libzfs/include/libzfs.h b/lib/libzfs/include/libzfs.h
index 37d95d92b..e3da385d2 100644
--- a/lib/libzfs/include/libzfs.h
+++ b/lib/libzfs/include/libzfs.h
@@ -56,6 +56,7 @@ extern "C" {
#if defined(__sun__) || defined(__sun)
#define DISK_ROOT "/dev/dsk"
#define RDISK_ROOT "/dev/rdsk"
+#define UDISK_ROOT RDISK_ROOT
#define FIRST_SLICE "s0"
#define BACKUP_SLICE "s2"
#endif
@@ -63,6 +64,7 @@ extern "C" {
#ifdef __linux__
#define DISK_ROOT "/dev"
#define RDISK_ROOT DISK_ROOT
+#define UDISK_ROOT "/dev/disk"
#define FIRST_SLICE "1"
#define BACKUP_SLICE ""
#endif
@@ -253,6 +255,7 @@ extern nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
boolean_t *, boolean_t *);
extern nvlist_t *zpool_find_vdev_by_physpath(zpool_handle_t *, const char *,
boolean_t *, boolean_t *, boolean_t *);
+extern int zpool_label_disk_wait(char *, int);
extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *);
/*
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c
index 0c35b8599..12c4f7704 100644
--- a/lib/libzfs/libzfs_pool.c
+++ b/lib/libzfs/libzfs_pool.c
@@ -3118,6 +3118,33 @@ find_start_block(nvlist_t *config)
return (MAXOFFSET_T);
}
+int
+zpool_label_disk_wait(char *path, int timeout)
+{
+#if defined(__linux__)
+ struct stat64 statbuf;
+ int i;
+
+ /*
+ * Wait timeout miliseconds for a newly created device to be available
+ * from the given path. There is a small window when a /dev/ device
+ * will exist and the udev link will not, so we must wait for the
+ * symlink. Depending on the udev rules this may take a few seconds.
+ */
+ for (i = 0; i < timeout; i++) {
+ usleep(1000);
+
+ errno = 0;
+ if ((stat64(path, &statbuf) == 0) && (errno == 0))
+ return (0);
+ }
+
+ return (ENOENT);
+#else
+ return (0);
+#endif
+}
+
/*
* Label an individual disk. The name provided is the short name,
* stripped of any leading /dev path.
@@ -3132,10 +3159,7 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
uint64_t slice_size;
diskaddr_t start_block;
char errbuf[1024];
-#if defined(__linux__)
- struct stat64 statbuf;
- int i;
-#endif
+
/* prepare an error message just in case */
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot label '%s'"), name);
@@ -3235,23 +3259,13 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name)
efi_free(vtoc);
#if defined(__linux__)
- /*
- * The efi partition table has been successfully written and the
- * kernel notified. However, it still may take a moment for udev
- * to notice the devfs update and properly populate /dev/. We will
- * wait up to 3 seconds which is far far far longer than needed.
- */
- (void) snprintf(path, sizeof (path), "%s/%s%s", RDISK_ROOT, name,
- FIRST_SLICE);
- for (i = 0; i < 3000; i++) {
- if (stat64(path, &statbuf) == 0 || errno != ENOENT)
- break;
-
- usleep(1000);
- }
-#endif
-
+ /* Wait for the first expected slice to appear */
+ (void) snprintf(path, sizeof (path), "%s/%s%s",
+ DISK_ROOT, name, FIRST_SLICE);
+ return zpool_label_disk_wait(path, 3000);
+#else
return (0);
+#endif
}
static boolean_t