Merge branch 'linux-user-disk' into refs/top-bases/linux-zfs-branch

This commit is contained in:
Brian Behlendorf 2009-10-21 12:04:19 -07:00
commit e0e0bac5a6
3 changed files with 55 additions and 59 deletions

View File

@ -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) {
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);
(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 ((ret = zpool_label_disk_wait(buf, 1000)) != 0) {
(void) fprintf(stderr,
gettext( "cannot resolve path '%s'\n"), buf);
return (-1);
}
#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);
}
#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);

View File

@ -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 *);
/*

View File

@ -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