From e88f0420b90c2565637962754cc26fa8a4ed9256 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Tue, 24 Dec 2013 14:16:57 +0100 Subject: [PATCH] Make grub_util_devmapper_part_to_disk and grub_util_find_partition_start follow the same algorithm to avoid method mismatch. Don't assume DMRAID- UUID to mean full disk but instead check that mapping is linear. --- ChangeLog | 6 ++ grub-core/osdep/devmapper/getroot.c | 123 ++------------------------- grub-core/osdep/devmapper/hostdisk.c | 13 +-- grub-core/osdep/linux/hostdisk.c | 9 +- include/grub/emu/hostdisk.h | 2 +- util/getroot.c | 9 +- 6 files changed, 35 insertions(+), 127 deletions(-) diff --git a/ChangeLog b/ChangeLog index 20cc11f67..d08793254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-12-24 Vladimir Serbinenko + + Make grub_util_devmapper_part_to_disk and grub_util_find_partition_start + follow the same algorithm to avoid method mismatch. Don't assume + DMRAID- UUID to mean full disk but instead check that mapping is linear. + 2013-12-24 Vladimir Serbinenko Declare GRUB_EFI_VENDOR_APPLE_GUID. diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c index 2639a71ea..f52b8617b 100644 --- a/grub-core/osdep/devmapper/getroot.c +++ b/grub-core/osdep/devmapper/getroot.c @@ -198,124 +198,17 @@ char * grub_util_devmapper_part_to_disk (struct stat *st, int *is_part, const char *path) { - struct dm_tree *tree; - uint32_t maj, min; - struct dm_tree_node *node = NULL, *child; - void *handle; - const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; + int major, minor; - tree = dm_tree_create (); - if (! tree) + if (grub_util_get_dm_node_linear_info (st->st_rdev, + &major, &minor, 0)) { - grub_util_info ("dm_tree_create failed"); - goto devmapper_out; + *is_part = 1; + return grub_find_device ("/dev", + (major << 8) | minor); } - - maj = major (st->st_rdev); - min = minor (st->st_rdev); - if (! dm_tree_add_dev (tree, maj, min)) - { - grub_util_info ("dm_tree_add_dev failed"); - goto devmapper_out; - } - - node = dm_tree_find_node (tree, maj, min); - if (! node) - { - grub_util_info ("dm_tree_find_node failed"); - goto devmapper_out; - } - reiterate: - node_uuid = dm_tree_node_get_uuid (node); - if (! node_uuid) - { - grub_util_info ("%s has no DM uuid", path); - goto devmapper_out; - } - if (strncmp (node_uuid, "LVM-", 4) == 0) - { - grub_util_info ("%s is an LVM", path); - goto devmapper_out; - } - if (strncmp (node_uuid, "mpath-", 6) == 0) - { - /* Multipath partitions have partN-mpath-* UUIDs, and are - linear mappings so are handled by - grub_util_get_dm_node_linear_info. Multipath disks are not - linear mappings and must be handled specially. */ - grub_util_info ("%s is a multipath disk", path); - goto devmapper_out; - } - if (strncmp (node_uuid, "DMRAID-", 7) != 0) - { - int major, minor; - const char *node_name; - grub_util_info ("%s is not DM-RAID", path); - - if ((node_name = dm_tree_node_get_name (node)) - && grub_util_get_dm_node_linear_info (node_name, - &major, &minor, 0)) - { - *is_part = 1; - if (tree) - dm_tree_free (tree); - char *ret = grub_find_device ("/dev", - (major << 8) | minor); - return ret; - } - - goto devmapper_out; - } - - handle = NULL; - /* Counter-intuitively, device-mapper refers to the disk-like - device containing a DM-RAID partition device as a "child" of - the partition device. */ - child = dm_tree_next_child (&handle, node, 0); - if (! child) - { - grub_util_info ("%s has no DM children", path); - goto devmapper_out; - } - child_uuid = dm_tree_node_get_uuid (child); - if (! child_uuid) - { - grub_util_info ("%s child has no DM uuid", path); - goto devmapper_out; - } - else if (strncmp (child_uuid, "DMRAID-", 7) != 0) - { - grub_util_info ("%s child is not DM-RAID", path); - goto devmapper_out; - } - child_name = dm_tree_node_get_name (child); - if (! child_name) - { - grub_util_info ("%s child has no DM name", path); - goto devmapper_out; - } - mapper_name = child_name; - *is_part = 1; - node = child; - goto reiterate; - - devmapper_out: - if (! mapper_name && node) - { - /* This is a DM-RAID disk, not a partition. */ - mapper_name = dm_tree_node_get_name (node); - if (! mapper_name) - grub_util_info ("%s has no DM name", path); - } - char *ret; - if (mapper_name) - ret = xasprintf ("/dev/mapper/%s", mapper_name); - else - ret = NULL; - - if (tree) - dm_tree_free (tree); - return ret; + *is_part = 0; + return xstrdup (path); } int diff --git a/grub-core/osdep/devmapper/hostdisk.c b/grub-core/osdep/devmapper/hostdisk.c index 1078f3591..d588be54e 100644 --- a/grub-core/osdep/devmapper/hostdisk.c +++ b/grub-core/osdep/devmapper/hostdisk.c @@ -83,7 +83,7 @@ grub_util_device_is_mapped (const char *dev) } int -grub_util_get_dm_node_linear_info (const char *dev, +grub_util_get_dm_node_linear_info (dev_t dev, int *maj, int *min, grub_disk_addr_t *st) { @@ -97,14 +97,16 @@ grub_util_get_dm_node_linear_info (const char *dev, grub_disk_addr_t partstart = 0; const char *node_uuid; + major = major (dev); + minor = minor (dev); + while (1) { dmt = dm_task_create(DM_DEVICE_TABLE); if (!dmt) break; - if (! (first ? dm_task_set_name (dmt, dev) - : dm_task_set_major_minor (dmt, major, minor, 0))) + if (! (dm_task_set_major_minor (dmt, major, minor, 0))) { dm_task_destroy (dmt); break; @@ -117,8 +119,7 @@ grub_util_get_dm_node_linear_info (const char *dev, } node_uuid = dm_task_get_uuid (dmt); if (node_uuid && (strncmp (node_uuid, "LVM-", 4) == 0 - || strncmp (node_uuid, "mpath-", 6) == 0 - || strncmp (node_uuid, "DMRAID-", 7) == 0)) + || strncmp (node_uuid, "mpath-", 6) == 0)) { dm_task_destroy (dmt); break; @@ -190,7 +191,7 @@ grub_util_device_is_mapped (const char *dev __attribute__ ((unused))) } int -grub_util_get_dm_node_linear_info (const char *dev __attribute__ ((unused)), +grub_util_get_dm_node_linear_info (dev_t dev __attribute__ ((unused)), int *maj __attribute__ ((unused)), int *min __attribute__ ((unused)), grub_disk_addr_t *st __attribute__ ((unused))) diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c index 1829bed6e..c96427a56 100644 --- a/grub-core/osdep/linux/hostdisk.c +++ b/grub-core/osdep/linux/hostdisk.c @@ -288,6 +288,7 @@ grub_hostdisk_linux_find_partition (char *dev, grub_disk_addr_t sector) { grub_util_fd_t fd; grub_disk_addr_t start; + struct stat st; sprintf (p, format, i); @@ -300,14 +301,16 @@ grub_hostdisk_linux_find_partition (char *dev, grub_disk_addr_t sector) return 0; } missing = 0; - close (fd); - if (!grub_util_device_is_mapped (real_dev) - || !grub_util_get_dm_node_linear_info (real_dev, 0, 0, &start)) + if (fstat (fd, &st) < 0 + || !grub_util_device_is_mapped_stat (&st) + || !grub_util_get_dm_node_linear_info (st.st_rdev, 0, 0, &start)) start = grub_util_find_partition_start_os (real_dev); /* We don't care about errors here. */ grub_errno = GRUB_ERR_NONE; + close (fd); + if (start == sector) { struct linux_partition_cache *new_cache_item; diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 8aa5403cd..e006f0b38 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -61,7 +61,7 @@ char * grub_util_get_os_disk (const char *os_dev); int -grub_util_get_dm_node_linear_info (const char *dev, +grub_util_get_dm_node_linear_info (dev_t dev, int *maj, int *min, grub_disk_addr_t *st); diff --git a/util/getroot.c b/util/getroot.c index 57162632c..3958105d8 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -77,10 +77,15 @@ grub_disk_addr_t grub_util_find_partition_start (const char *dev) { +#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL + struct stat st; grub_disk_addr_t partition_start; - if (grub_util_device_is_mapped (dev) - && grub_util_get_dm_node_linear_info (dev, 0, 0, &partition_start)) + + if (stat (dev, &st) >= 0 + && grub_util_device_is_mapped_stat (&st) + && grub_util_get_dm_node_linear_info (st.st_rdev, 0, 0, &partition_start)) return partition_start; +#endif return grub_util_find_partition_start_os (dev); }