From 29c9a2518cec568609c5dae3ab26057150f901d1 Mon Sep 17 00:00:00 2001 From: Brian Behlendorf Date: Fri, 23 Oct 2009 16:25:16 -0700 Subject: [PATCH] Properly handle block devices other the IDE and SCSI disks. Based on the block device type we can expect a specific naming convention. With this in mind update efi_get_info() to be more aware of the type when parsing out the partition number. In, addition be aware that all block device types are not partitionable. Finally, when attempting to lookup a device partition by appending the partition number to the whole device take in to account the kernel naming scheme. If the last character of the device name is a digit the partition will always be 'p#' instead of just '#'. --- cmd/zpool/zpool_vdev.c | 7 ++- lib/libefi/rdwr_efi.c | 93 +++++++++++++++++++++++----------------- lib/libzfs/libzfs_pool.c | 4 +- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c index 113abb6088..25a3c85543 100644 --- a/cmd/zpool/zpool_vdev.c +++ b/cmd/zpool/zpool_vdev.c @@ -61,6 +61,7 @@ */ #include +#include #include #include #include @@ -297,7 +298,8 @@ check_disk(const char *path, blkid_cache cache, int force, "%s%s%d", path, "-part", i+1); else (void) snprintf(slice_path, sizeof (slice_path), - "%s%d", path, i+1); + "%s%s%d", path, isdigit(path[strlen(path)-1]) ? + "p" : "", i+1); err = check_slice(slice_path, cache, force, isspare); if (err) @@ -985,7 +987,8 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv) "%s%s%s", path, "-part", FIRST_SLICE); else (void) snprintf(buf, sizeof (buf), - "%s%s", path, FIRST_SLICE); + "%s%s%s", path, isdigit(path[strlen(path)-1]) ? + "p" : "", FIRST_SLICE); if ((ret = zpool_label_disk_wait(buf, 1000)) != 0) { (void) fprintf(stderr, diff --git a/lib/libefi/rdwr_efi.c b/lib/libefi/rdwr_efi.c index 8df64149eb..de7ddd7777 100644 --- a/lib/libefi/rdwr_efi.c +++ b/lib/libefi/rdwr_efi.c @@ -151,26 +151,67 @@ efi_get_info(int fd, struct dk_cinfo *dki_info) #if defined(__linux__) char path[PATH_MAX]; char *dev_path; - int rval; + int rval = 0; /* * The simplest way to get the partition number under linux is * to parse it out of the /dev/ block device name. * The kernel creates this using the partition number when it - * populates /dev/ so it may be trusted. Another issue is that - * that the libefi API only provides the open fd and not the - * file path. To handle this realpath(3) is used to resolve - * the block device name from /proc/self/fd/. Aside from - * the partition number we collect some additional device info. + * populates /dev/ so it may be trusted. The tricky bit here is + * that the naming convention is based on the block device type. + * So we need to take this in to account when parsing out the + * partition information. Another issue is that the libefi API + * API only provides the open fd and not the file path. To handle + * this realpath(3) is used to resolve the block device name from + * /proc/self/fd/. Aside from the partition number we collect + * some additional device info. */ memset(dki_info, 0, sizeof(*dki_info)); (void) sprintf(path, "/proc/self/fd/%d", fd); if ((dev_path = realpath(path, NULL)) == NULL) goto error; - rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu", - dki_info->dki_dname, - &dki_info->dki_partition); + if ((strncmp(dev_path, "/dev/sd", 7) == 0)) { + strcpy(dki_info->dki_cname, "sd"); + dki_info->dki_ctype = DKC_SCSI_CCS; + rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu", + dki_info->dki_dname, + &dki_info->dki_partition); + } else if ((strncmp(dev_path, "/dev/hd", 7) == 0)) { + strcpy(dki_info->dki_cname, "hd"); + dki_info->dki_ctype = DKC_DIRECT; + rval = sscanf(dev_path, "/dev/%[a-zA-Z]%hu", + dki_info->dki_dname, + &dki_info->dki_partition); + } else if ((strncmp(dev_path, "/dev/md", 7) == 0)) { + strcpy(dki_info->dki_cname, "pseudo"); + dki_info->dki_ctype = DKC_MD; + rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu", + dki_info->dki_dname, + &dki_info->dki_partition); + } else if ((strncmp(dev_path, "/dev/dm-", 8) == 0)) { + strcpy(dki_info->dki_cname, "pseudo"); + dki_info->dki_ctype = DKC_MD; + rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9-]p%hu", + dki_info->dki_dname, + &dki_info->dki_partition); + } else if ((strncmp(dev_path, "/dev/ram", 8) == 0)) { + strcpy(dki_info->dki_cname, "pseudo"); + dki_info->dki_ctype = DKC_PCMCIA_MEM; + rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu", + dki_info->dki_dname, + &dki_info->dki_partition); + } else if ((strncmp(dev_path, "/dev/loop", 9) == 0)) { + strcpy(dki_info->dki_cname, "pseudo"); + dki_info->dki_ctype = DKC_VBD; + rval = sscanf(dev_path, "/dev/%[a-zA-Z0-9]p%hu", + dki_info->dki_dname, + &dki_info->dki_partition); + } else { + strcpy(dki_info->dki_dname, "unknown"); + strcpy(dki_info->dki_cname, "unknown"); + dki_info->dki_ctype = DKC_UNKNOWN; + } switch (rval) { case 0: @@ -180,26 +221,6 @@ efi_get_info(int fd, struct dk_cinfo *dki_info) dki_info->dki_partition = 0; } - if ((strncmp(dki_info->dki_dname, "sd", 2) == 0)) { - strcpy(dki_info->dki_cname, "sd"); - dki_info->dki_ctype = DKC_SCSI_CCS; - } else if ((strncmp(dki_info->dki_dname, "hd", 2) == 0)) { - strcpy(dki_info->dki_cname, "hd"); - dki_info->dki_ctype = DKC_DIRECT; - } else if ((strncmp(dki_info->dki_dname, "md", 2) == 0)) { - strcpy(dki_info->dki_cname, "pseudo"); - dki_info->dki_ctype = DKC_MD; - } else if ((strncmp(dki_info->dki_dname, "ram", 3) == 0)) { - strcpy(dki_info->dki_cname, "pseudo"); - dki_info->dki_ctype = DKC_PCMCIA_MEM; - } else if ((strncmp(dki_info->dki_dname, "loop", 4) == 0)) { - strcpy(dki_info->dki_cname, "pseudo"); - dki_info->dki_ctype = DKC_VBD; - } else { - strcpy(dki_info->dki_cname, "unknown"); - dki_info->dki_ctype = DKC_UNKNOWN; - } - free(dev_path); #else if (ioctl(fd, DKIOCINFO, (caddr_t)dki_info) == -1) @@ -255,22 +276,14 @@ efi_alloc_and_init(int fd, uint32_t nparts, struct dk_gpt **vtoc) return (-1); } - if (dki_info.dki_partition != 0) { - if (efi_debug) - (void) fprintf(stderr, - "can only partition whole devices\n"); + if (dki_info.dki_partition != 0) return (-1); - } if ((dki_info.dki_ctype == DKC_PCMCIA_MEM) || (dki_info.dki_ctype == DKC_VBD) || - (dki_info.dki_ctype == DKC_UNKNOWN)) { - if (efi_debug) - (void) fprintf(stderr, - "unpartitionable device type %d\n", - dki_info.dki_ctype); + (dki_info.dki_ctype == DKC_UNKNOWN) || + (dki_info.dki_ctype == DKC_MD)) return (-1); - } #endif nblocks = NBLOCKS(nparts, lbsize); diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index 2d28c8949b..296acdeba5 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -3261,8 +3261,8 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, char *name) efi_free(vtoc); /* Wait for the first expected slice to appear. */ - (void) snprintf(path, sizeof (path), "%s/%s%s", - DISK_ROOT, name, FIRST_SLICE); + (void) snprintf(path, sizeof (path), "%s/%s%s%s", DISK_ROOT, name, + isdigit(name[strlen(name)-1]) ? "p" : "", FIRST_SLICE); rval = zpool_label_disk_wait(path, 3000); if (rval) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "failed to "