diff options
author | Brian Behlendorf <[email protected]> | 2009-10-21 12:04:19 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2009-10-21 12:04:19 -0700 |
commit | e0e0bac5a665feec58d42d74edfebd836643c300 (patch) | |
tree | 8abfd7a7322d5d8100036a30d4d569c917a42dba | |
parent | c9e138c366039aa3fd3a39ae8918cb5daf2626bd (diff) | |
parent | 6367f93602c33690e64388159872023f2759b532 (diff) |
Merge branch 'linux-user-disk' into refs/top-bases/linux-zfs-branch
-rw-r--r-- | cmd/zpool/zpool_vdev.c | 57 | ||||
-rw-r--r-- | lib/libzfs/include/libzfs.h | 3 | ||||
-rw-r--r-- | lib/libzfs/libzfs_pool.c | 54 |
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 |