found 483971 1.98+20100804-14 fixed 483971 1.99-12 thanks grub2 1.99-12 (from sid) works fine, but I ran into this upgrading our multipathed lenny machines to squeeze. Attached is the patch from #442382 that fixes this, updated for squeeze's grub2 (1.98+20100804-14).
FWIW, unmodified 1.98+20100804-14 on squeeze fails with: [j...@syslog01.roch.ny:pts/4 ~> sudo dpkg-reconfigure grub-pc Generating core.img /usr/sbin/grub-probe: error: no such disk. Auto-detection of a filesystem of /dev/mapper/rootvol-part1 failed. Please report this together with the output of "/usr/sbin/grub-probe --device-map=/boot/grub/device.map --target=fs -v /boot/grub" to <bug-g...@gnu.org> john -- John Morrissey _o /\ ---- __o j...@horde.net _-< \_ / \ ---- < \, www.horde.net/ __(_)/_(_)________/ \_______(_) /_(_)__
Index: grub2-1.98+20100804/include/grub/emu/getroot.h =================================================================== --- grub2-1.98+20100804.orig/include/grub/emu/getroot.h 2010-06-02 23:13:14.000000000 +0000 +++ grub2-1.98+20100804/include/grub/emu/getroot.h 2011-09-11 00:23:17.522687000 +0000 @@ -19,12 +19,15 @@ #ifndef GRUB_UTIL_GETROOT_HEADER #define GRUB_UTIL_GETROOT_HEADER 1 +#include <sys/types.h> + enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_NONE, GRUB_DEV_ABSTRACTION_LVM, GRUB_DEV_ABSTRACTION_RAID, }; +char *find_root_device (const char *dir, dev_t dev); char *grub_guess_root_device (const char *dir); int grub_util_get_dev_abstraction (const char *os_dev); char *grub_util_get_grub_dev (const char *os_dev); Index: grub2-1.98+20100804/kern/emu/getroot.c =================================================================== --- grub2-1.98+20100804.orig/kern/emu/getroot.c 2011-09-11 00:23:08.292457000 +0000 +++ grub2-1.98+20100804/kern/emu/getroot.c 2011-09-11 00:23:08.909378000 +0000 @@ -32,6 +32,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> @@ -242,7 +246,7 @@ #elif ! defined(__CYGWIN__) -static char * +char * find_root_device (const char *dir, dev_t dev) { DIR *dp; @@ -547,32 +551,66 @@ } 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; + 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, *child; + void *handle; + const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; + struct stat st; - return 0; + 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 @@ -580,9 +618,7 @@ { #ifdef __linux__ /* 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. */ Index: grub2-1.98+20100804/kern/emu/hostdisk.c =================================================================== --- grub2-1.98+20100804.orig/kern/emu/hostdisk.c 2011-09-11 00:23:07.316535000 +0000 +++ grub2-1.98+20100804/kern/emu/hostdisk.c 2011-09-11 00:23:08.916375000 +0000 @@ -23,6 +23,7 @@ #include <grub/types.h> #include <grub/err.h> #include <grub/emu/misc.h> +#include <grub/emu/getroot.h> #include <grub/emu/hostdisk.h> #include <grub/misc.h> #include <grub/i18n.h> @@ -1038,6 +1039,55 @@ 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; + const char *node_name; + 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) { @@ -1198,9 +1248,29 @@ 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, "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 = find_root_device ("/dev", (major << 8) | minor); + return ret; + } + node = NULL; goto devmapper_out; }