[libvirt] [PATCH 0/1] RFC: Canonicalize block device paths

I had a look at the problem of finding the devices representing the partitions of a block device, and it's a messy problem. There are a lot of different conventions that are used depending on what kind of device is partitioned. The following patch seems like a promising approach, but before I spend a bunch of time testing that it works in a variety of cases, I thought I should send it out for comment. Dave David Allan (1): RFC: Canonicalize block device paths src/Makefile.am | 9 +++++++-- src/storage/parthelper.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-)

There are many naming conventions for partitions associated with a block device. Some of the major ones are: /dev/foo -> /dev/foo1 /dev/foo1 -> /dev/foo1p1 /dev/mapper/foo -> /dev/mapper/foop1 /dev/disk/by-path/foo -> /dev/disk/by-path/foo-part1 The universe of possible conventions isn't clear. Rather than trying to understand all possible conventions, this patch divides devices into two groups, device mapper devices and everything else. Device mapper devices seem always to follow the convention of device -> devicep1; everything else is canonicalized. --- src/Makefile.am | 9 +++++++-- src/storage/parthelper.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index ece18a6..c8fad28 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1037,8 +1037,13 @@ libexec_PROGRAMS += libvirt_parthelper libvirt_parthelper_SOURCES = $(STORAGE_HELPER_DISK_SOURCES) libvirt_parthelper_LDFLAGS = $(WARN_LDFLAGS) $(COVERAGE_LDFLAGS) -libvirt_parthelper_LDADD = $(LIBPARTED_LIBS) ../gnulib/lib/libgnu.la -libvirt_parthelper_CFLAGS = $(LIBPARTED_CFLAGS) +libvirt_parthelper_LDADD = \ + $(LIBPARTED_LIBS) \ + $(DEVMAPPER_LIBS) \ + libvirt_util.la \ + ../gnulib/lib/libgnu.la + +libvirt_parthelper_CFLAGS = $(LIBPARTED_CFLAGS) $(DEVMAPPER_CFLAGS) endif endif EXTRA_DIST += $(STORAGE_HELPER_DISK_SOURCES) diff --git a/src/storage/parthelper.c b/src/storage/parthelper.c index ca74456..2a70250 100644 --- a/src/storage/parthelper.c +++ b/src/storage/parthelper.c @@ -35,7 +35,12 @@ #include <parted/parted.h> #include <stdio.h> #include <string.h> +#include <libdevmapper.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "util.h" #include "c-ctype.h" /* we don't need to include the full internal.h just for this */ @@ -52,6 +57,18 @@ enum diskCommand { DISK_GEOMETRY }; +static int +is_dm_device(const char *devname) +{ + struct stat buf; + + if (devname && !stat(devname, &buf) && dm_is_dm_major(major(buf.st_rdev))) { + return 1; + } + + return 0; +} + int main(int argc, char **argv) { PedDevice *dev; @@ -59,6 +76,7 @@ int main(int argc, char **argv) PedPartition *part; int cmd = DISK_LAYOUT; const char *path; + char *canonical_path; const char *partsep; if (argc == 3 && STREQ(argv[2], "-g")) { @@ -69,7 +87,20 @@ int main(int argc, char **argv) } path = argv[1]; - partsep = *path && c_isdigit(path[strlen(path)-1]) ? "p" : ""; + if (is_dm_device(path)) { + partsep = "p"; + canonical_path = strdup(path); + if (canonical_path == NULL) { + return 2; + } + } else { + if (virFileResolveLink(path, &canonical_path) != 0) { + return 2; + } + + partsep = *canonical_path && + c_isdigit(canonical_path[strlen(canonical_path)-1]) ? "p" : ""; + } if ((dev = ped_device_get(path)) == NULL) { fprintf(stderr, "unable to access device %s\n", path); @@ -125,7 +156,7 @@ int main(int argc, char **argv) */ if (part->num != -1) { printf("%s%s%d%c%s%c%s%c%llu%c%llu%c%llu%c", - path, partsep, + canonical_path, partsep, part->num, '\0', type, '\0', content, '\0', -- 1.7.1.1

On Thu, Jul 08, 2010 at 07:37:03PM -0400, David Allan wrote:
There are many naming conventions for partitions associated with a block device. Some of the major ones are:
/dev/foo -> /dev/foo1 /dev/foo1 -> /dev/foo1p1 /dev/mapper/foo -> /dev/mapper/foop1 /dev/disk/by-path/foo -> /dev/disk/by-path/foo-part1
The universe of possible conventions isn't clear. Rather than trying to understand all possible conventions, this patch divides devices into two groups, device mapper devices and everything else. Device mapper devices seem always to follow the convention of device -> devicep1; everything else is canonicalized.
This starts to be a bit messy, I have no objection to the code but it would be good to start entering this in the test suite one way or another, so that is we need to change it again, we make sure to not break any of the expected behaviour for previous cases. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On Thu, Jul 08, 2010 at 07:37:03PM -0400, David Allan wrote:
There are many naming conventions for partitions associated with a block device. Some of the major ones are:
/dev/foo -> /dev/foo1 /dev/foo1 -> /dev/foo1p1 /dev/mapper/foo -> /dev/mapper/foop1 /dev/disk/by-path/foo -> /dev/disk/by-path/foo-part1
The universe of possible conventions isn't clear. Rather than trying to understand all possible conventions, this patch divides devices into two groups, device mapper devices and everything else. Device mapper devices seem always to follow the convention of device -> devicep1; everything else is canonicalized. --- src/Makefile.am | 9 +++++++-- src/storage/parthelper.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-)
ACK, it may not be perfect, but it looks incrementally better than what we have now. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
David Allan