What I needed to do with Grub2 to change my boot disk

April 6, 2013

On my work machine I have been very slowly migrating away from a pair of old drives to a pair of new drives. For quite a while the only thing the old drives have been used for has been booting from and holding /boot; today I finally removed the single surviving old disk and moved to booting off the new disks. It turned out to be somewhat more involved than I expected.

The initial state was /dev/sda as the old drive with /boot as a plain filesystems, /dev/sdb and /dev/sdc as the new drives with /boot-n (the new version of /boot) as a mirrored RAID array and filesystem. My first step (some time ago actually) was to run grub2-install to install the boot blocks on sdb (and sdc, although I have no idea if those work). Unfortunately I forgot to save the exact commands I used to do this. My notes say that I bind-mounted /boot-n on top of /boot during this process so that grub2-install would see the right thing in the right place but I'm not sure how I handled device mappings.

Today I changed my /etc/fstab to fix up the mounts (basically changing /boot-n into /boot), shut the machine down, pulled the old drive, shuffled the cables around, and booted up. The machine started Grub2 but then couldn't boot Linux, ultimately because it couldn't find the kernel and initramfs. This happened because I forgot to update grub.cfg to tell it the new location and UUIDs of the new /boot. Although Grub2 could find the new /boot in order to load grub.cfg, the various kernel stanzas in grub.cfg re-specify where to find the kernel and initramfs with boiler plate like this:

set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  bfe06079-ea84-49cb-a028-d5b1ad47cfba
  search --no-floppy --fs-uuid --set=root bfe06079-ea84-49cb-a028-d5b1ad47cfba
linux /vmlinuz-....

(The complexity of a Grub2 grub.cfg is why I'm not really fond of Grub2. I'm not sure we need a shell script interpreter embedded in the boot system, and if it has to be fully programmable I wish they'd used a better language.)

Since my /boot was no longer (MS-DOS) partition 1 or a filesystem with that UUID, this failed and everything bombed out. To get the machine booted I dropped into the Grub2 command line and used its ls command to see what was there (per the Fedora page on Grub2). After finding that I wanted 'md/13' (I believe) I went back and changed the 'set root=...' line to specify it, then told Grub2 to try booting. This worked, although Grub2 warned me that it still couldn't find the particular UUID.

Fixing this permanently required revising grub.cfg; I actually did this twice, once the hard way and once the easy way. The hard way is to use blkid to look up the new /boot's UUID then carefully edit all of the stanzas to change the set root=... bit to md/13 and change the UUID in the search lines. While this worked I didn't think that all of those --hint-... bits were correct any more and they made me nervous.

The easy way to fix this is to use grub2-mkconfig -o /tmp/foo and then pick through /tmp/foo for the official and proper way to do all of this boiler plate. It turned out to be (for me):

set root='mduuid/<md-uuid>'
search --no-floppy --fs-uuid --set=root --hint='mduuid/<md-uuid>' <fs-uuid>

(grub2-mkconfig looked up the UUIDs for itself.)

(The really easy way would be to just use grub2-mkconfig to regenerate your grub.cfg, but I have an old-style grub.cfg that I happen to like and didn't want to have replaced with the new Fedora 18 grub2-mkconfig version. Also note that the grub.cfg that grub2-mkconfig creates for you may look nothing like the grub.cfg that the Fedora installer creates. This is a complete mess and I hope that Fedora fixes it someday.)

I'm sure that I'm going to need to do this again sometime in the future. In that future, the smart thing to do will be to update grub.cfg before the initial reboot (after the final copy from the old /boot, for obvious reasons). I'm not sure if grub2-mkconfig would give the right results (even with making the new /boot the actual /boot), but clearly I can just look up the UUIDs by hand.

PS: no, I don't know why Grub2 and grub.cfg don't have a final fallback of 'where you got the grub.cfg from'. Probably it's for the same reason that Grub2 needs a shell script interpreter.

Written on 06 April 2013.
« Authoritative, non-recursive DNS servers now need ratelimiting
The apparent source of my Firefox memory bloat problems »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sat Apr 6 02:34:52 2013
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.