| --- grub-core/kern/emu/getroot.c 2011-04-21 09:26:29 +0000 |
| +++ grub-core/kern/emu/getroot.c 2011-05-18 07:35:47 +0000 |
| @@ -34,6 +34,10 @@ |
| #include <stdint.h> |
| #include <grub/util/misc.h> |
| |
| +#ifdef HAVE_DEVICE_MAPPER |
| +# include <libdevmapper.h> |
| +#endif |
| + |
| #ifdef __GNU__ |
| #include <hurd.h> |
| #include <hurd/lookup.h> |
| @@ -634,32 +638,65 @@ |
| } |
| |
| static int |
| -grub_util_is_dmraid (const char *os_dev) |
| +grub_util_is_lvm (const char *os_dev) |
| { |
| - if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/isw_", 16)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/via_", 16)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/asr_", 16)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/sil_", 16)) |
| - return 1; |
| - else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17)) |
| - return 1; |
| - |
| - return 0; |
| + if ((strncmp ("/dev/mapper/", os_dev, 12) != 0)) |
| + return 0; |
| + |
| +#ifdef HAVE_DEVICE_MAPPER |
| + { |
| + struct dm_tree *tree; |
| + uint32_t maj, min; |
| + struct dm_tree_node *node = NULL; |
| + const char *node_uuid; |
| + struct stat st; |
| + |
| + if (stat (os_dev, &st) < 0) |
| + return 0; |
| + |
| + tree = dm_tree_create (); |
| + if (! tree) |
| + { |
| + grub_printf ("Failed to create tree\n"); |
| + grub_dprintf ("hostdisk", "dm_tree_create failed\n"); |
| + return 0; |
| + } |
| + |
| + maj = major (st.st_rdev); |
| + min = minor (st.st_rdev); |
| + |
| + if (! dm_tree_add_dev (tree, maj, min)) |
| + { |
| + grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); |
| + dm_tree_free (tree); |
| + return 0; |
| + } |
| + |
| + node = dm_tree_find_node (tree, maj, min); |
| + if (! node) |
| + { |
| + grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); |
| + dm_tree_free (tree); |
| + return 0; |
| + } |
| + node_uuid = dm_tree_node_get_uuid (node); |
| + if (! node_uuid) |
| + { |
| + grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev); |
| + dm_tree_free (tree); |
| + return 0; |
| + } |
| + if (strncmp (node_uuid, "LVM-", 4) != 0) |
| + { |
| + dm_tree_free (tree); |
| + return 0; |
| + } |
| + dm_tree_free (tree); |
| + return 1; |
| + } |
| +#else |
| + return 1; |
| +#endif /* HAVE_DEVICE_MAPPER */ |
| } |
| |
| int |
| @@ -671,13 +708,11 @@ |
| return GRUB_DEV_ABSTRACTION_NONE; |
| |
| /* Check for LVM. */ |
| - if (!strncmp (os_dev, "/dev/mapper/", 12) |
| - && ! grub_util_is_dmraid (os_dev) |
| - && strncmp (os_dev, "/dev/mapper/mpath", 17) != 0) |
| + if (grub_util_is_lvm (os_dev)) |
| return GRUB_DEV_ABSTRACTION_LVM; |
| |
| /* Check for RAID. */ |
| - if (!strncmp (os_dev, "/dev/md", 7)) |
| + if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev)) |
| return GRUB_DEV_ABSTRACTION_RAID; |
| #endif |
| |
| |
| === modified file 'grub-core/kern/emu/hostdisk.c' |
| --- grub-core/kern/emu/hostdisk.c 2011-05-09 16:59:35 +0000 |
| +++ grub-core/kern/emu/hostdisk.c 2011-05-18 07:35:47 +0000 |
| @@ -24,6 +24,7 @@ |
| #include <grub/err.h> |
| #include <grub/emu/misc.h> |
| #include <grub/emu/hostdisk.h> |
| +#include <grub/emu/getroot.h> |
| #include <grub/misc.h> |
| #include <grub/i18n.h> |
| #include <grub/list.h> |
| @@ -331,18 +332,23 @@ |
| return GRUB_ERR_NONE; |
| } |
| |
| +int |
| +grub_util_device_is_mapped (const char *dev) |
| +{ |
| #ifdef HAVE_DEVICE_MAPPER |
| -static int |
| -device_is_mapped (const char *dev) |
| -{ |
| struct stat st; |
| |
| + if (!grub_device_mapper_supported ()) |
| + return 0; |
| + |
| if (stat (dev, &st) < 0) |
| return 0; |
| |
| return dm_is_dm_major (major (st.st_rdev)); |
| +#else |
| + return 0; |
| +#endif /* HAVE_DEVICE_MAPPER */ |
| } |
| -#endif /* HAVE_DEVICE_MAPPER */ |
| |
| #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) |
| /* FIXME: geom actually gives us the whole container hierarchy. |
| @@ -418,7 +424,7 @@ |
| # endif /* !defined(HAVE_DIOCGDINFO) */ |
| |
| # ifdef HAVE_DEVICE_MAPPER |
| - if (grub_device_mapper_supported () && device_is_mapped (dev)) { |
| + if (grub_util_device_is_mapped (dev)) { |
| struct dm_task *task = NULL; |
| grub_uint64_t start, length; |
| char *target_type, *params, *space; |
| @@ -1149,6 +1155,54 @@ |
| return ret; |
| } |
| |
| +#ifdef HAVE_DEVICE_MAPPER |
| +static int |
| +grub_util_get_dm_node_linear_info (const char *dev, |
| + int *maj, int *min) |
| +{ |
| + struct dm_task *dmt; |
| + void *next = NULL; |
| + uint64_t length, start; |
| + char *target, *params; |
| + char *ptr; |
| + int major, minor; |
| + |
| + dmt = dm_task_create(DM_DEVICE_TABLE); |
| + if (!dmt) |
| + return 0; |
| + |
| + if (!dm_task_set_name(dmt, dev)) |
| + return 0; |
| + dm_task_no_open_count(dmt); |
| + if (!dm_task_run(dmt)) |
| + return 0; |
| + next = dm_get_next_target(dmt, next, &start, &length, |
| + &target, ¶ms); |
| + if (grub_strcmp (target, "linear") != 0) |
| + return 0; |
| + major = grub_strtoul (params, &ptr, 10); |
| + if (grub_errno) |
| + { |
| + grub_errno = GRUB_ERR_NONE; |
| + return 0; |
| + } |
| + if (*ptr != ':') |
| + return 0; |
| + ptr++; |
| + minor = grub_strtoul (ptr, 0, 10); |
| + if (grub_errno) |
| + { |
| + grub_errno = GRUB_ERR_NONE; |
| + return 0; |
| + } |
| + if (maj) |
| + *maj = major; |
| + if (min) |
| + *min = minor; |
| + return 1; |
| +} |
| +#endif |
| + |
| static char * |
| convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) |
| { |
| @@ -1325,9 +1379,39 @@ |
| node = NULL; |
| goto devmapper_out; |
| } |
| - else if (strncmp (node_uuid, "DMRAID-", 7) != 0) |
| - { |
| + if (strncmp (node_uuid, "LVM-", 4) == 0) |
| + { |
| + grub_dprintf ("hostdisk", "%s is an LVM\n", path); |
| + node = NULL; |
| + 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_dprintf ("hostdisk", "%s is a multipath disk\n", path); |
| + mapper_name = dm_tree_node_get_name (node); |
| + goto devmapper_out; |
| + } |
| + if (strncmp (node_uuid, "DMRAID-", 7) != 0) |
| + { |
| + int major, minor; |
| + const char *node_name; |
| grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); |
| + |
| + if ((node_name = dm_tree_node_get_name (node)) |
| + && grub_util_get_dm_node_linear_info (node_name, |
| + &major, &minor)) |
| + { |
| + if (tree) |
| + dm_tree_free (tree); |
| + free (path); |
| + char *ret = grub_find_device (NULL, (major << 8) | minor); |
| + return ret; |
| + } |
| + |
| node = NULL; |
| goto devmapper_out; |
| } |
| |
| --- include/grub/emu/misc.h 2010-12-02 13:26:46 +0000 |
| +++ include/grub/emu/misc.h 2011-05-18 07:35:47 +0000 |
| @@ -54,6 +54,8 @@ |
| |
| char *grub_make_system_path_relative_to_its_root (const char *path) |
| __attribute__ ((warn_unused_result)); |
| +int |
| +grub_util_device_is_mapped (const char *dev); |
| |
| void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result)); |
| void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result)); |
| |