Comment 6 for bug 1501015

Revision history for this message
bugproxy (bugproxy) wrote : Comment bridged from LTC Bugzilla

------- Comment From <email address hidden> 2015-10-02 19:57 EDT-------
There's a different function path that's relevant here.
It seems the previous one only effects a config or something.
(I couldn't verify at install time w/ gdb yet, but per the call to 'nvram', it's likely to be correct now.)

The analysis points to ofpathname called w/ a /dev/mapper/mpathX path, which it can't work with.
So, the options are still handling this in either grub-installer or grub2.

It should be simpler to handle errors in grub-installer rather than grub2
(even accounting for checks of working/online paths, retries in case of errors, etc).

Function path and comments:
---------------------------------------

The boot device settings are modified here:

main()
@ grub-install.c
...
dev = grub_util_get_os_disk (install_device);
grub_install_register_ieee1275 (0, dev, partno,
"\\\\BootX");
...
grub_install_register_ieee1275 (1, grub_util_get_os_disk (install_device),
0, NULL);
...

There are 2 relevant functions:
- grub_install_register_ieee1275()
- grub_util_get_os_disk()

First,

grub_install_register_ieee1275()
@ grub-core/osdep/unix/platform.c

char *boot_device;
...
ofpath = get_ofpathname (install_device);
...
ptr = grub_stpcpy (boot_device, ofpath);
...
boot_device = get_ofpathname (install_device);
...
if (strcmp (grub_install_get_default_powerpc_machtype (), "chrp_ibm") == 0)
{
char *arg = xasprintf ("boot-device=%s", boot_device);
if (grub_util_exec ((const char * []){ "nvram",
"--update-config", arg, NULL }))
...

which runs 'nvram --update-config boot-device=' with the value printed by 'ofpathname' for that device.

get_ofpathname()
@ grub-core/osdep/unix/platform.c
...
pid = grub_util_exec_pipe ((const char * []){ "ofpathname", dev, NULL }, &fd);
...

Second, 'that device' is obtained by:

grub_util_get_os_disk
@ util/getroot.c
...
return convert_system_partition_to_system_disk (os_dev, &is_part);
...

convert_system_partition_to_system_disk()
@ util/getroot.c
...
if (grub_util_device_is_mapped_stat (&st))
return grub_util_devmapper_part_to_disk (&st, is_part, os_dev);
...

grub_util_devmapper_part_to_disk()
@ grub-core/osdep/devmapper/getroot.c
...
if (grub_util_get_dm_node_linear_info (st->st_rdev,
&major, &minor, 0))
{
*is_part = 1;
return grub_find_device ("/dev",
(major << 8) | minor);
}
*is_part = 0;
return xstrdup (path);

But grub_util_get_dm_node_linear_info() doesn't understand mpath/LVM devmapper targets, only linear.
If it's linear, then it sets major and minor.

grub_util_get_dm_node_linear_info()
@ grub-core/osdep/devmapper/hostdisk.c
...
if (node_uuid && (strncmp (node_uuid, "LVM-", 4) == 0
|| strncmp (node_uuid, "mpath-", 6) == 0))
{
dm_task_destroy (dmt);
break;
}
...
if (grub_strcmp (target, "linear") != 0)
{
dm_task_destroy (dmt);
break;
}
...
major = grub_strtoul (params, &ptr, 10);
...
minor = grub_strtoul (ptr, &ptr, 10);

Otherwise, later on:
return 1;

Which makes grub_util_devmapper_part_to_disk() not to call grub_find_device(),
returning the same path it received.

This path is not understandable by ofpathname, so nvram probably ends up updating something incorrectly.