Blob Blame History Raw
From 51be3372ec8ba07ef68a409956ea0eefa89fe7c5 Mon Sep 17 00:00:00 2001
From: Nicholas Vinson <nvinson234@gmail.com>
Date: Mon, 16 Apr 2018 22:36:26 -0700
Subject: [PATCH] templates: Update grub script template files

Update grub-mkconfig.in and 10_linux.in to support grub-probe's new
partuuid target.  Update grub.texi documentation.  The following table
shows how GRUB_DISABLE_LINUX_UUID, GRUB_DISABLE_LINUX_PARTUUID, and
initramfs detection interact:

Initramfs  GRUB_DISABLE_LINUX_PARTUUID  GRUB_DISABLE_LINUX_UUID  Linux Root
detected   Set                          Set                      ID Method

false      false                        false                    part UUID
false      false                        true                     part UUID
false      true                         false                    dev name
false      true                         true                     dev name
true       false                        false                    fs UUID
true       false                        true                     part UUID
true       true                         false                    fs UUID
true       true                         true                     dev name

Note: GRUB_DISABLE_LINUX_PARTUUID and GRUB_DISABLE_LINUX_UUID equate to
      'false' when unset or set to any value other than 'true'.
      GRUB_DISABLE_LINUX_PARTUUID defaults to 'true'.

Signed-off-by: Nicholas Vinson <nvinson234@gmail.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
 docs/grub.texi              | 67 ++++++++++++++++++++++++++++++++++++++++++---
 util/grub-mkconfig.in       |  3 ++
 util/grub.d/10_linux.in     | 22 +++++++++++++--
 util/grub.d/20_linux_xen.in | 22 +++++++++++++--
 4 files changed, 104 insertions(+), 10 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 0f2ab91fc69..2adfa97bee8 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1214,10 +1214,11 @@ GRUB is configured using @file{grub.cfg}, usually located under
 need to write the whole thing by hand.
 
 @menu
-* Simple configuration::        Recommended for most users
-* Shell-like scripting::        For power users and developers
-* Multi-boot manual config::    For non-standard multi-OS scenarios
-* Embedded configuration::      Embedding a configuration file into GRUB
+* Simple configuration::            Recommended for most users
+* Root Identifcation Heuristics::   Summary on how the root file system is identified.
+* Shell-like scripting::            For power users and developers
+* Multi-boot manual config::        For non-standard multi-OS scenarios
+* Embedded configuration::          Embedding a configuration file into GRUB
 @end menu
 
 
@@ -1425,6 +1426,17 @@ the Linux kernel, using a @samp{root=UUID=...} kernel parameter.  This is
 usually more reliable, but in some cases it may not be appropriate.  To
 disable the use of UUIDs, set this option to @samp{true}.
 
+@item GRUB_DISABLE_LINUX_PARTUUID
+If @command{grub-mkconfig} cannot identify the root filesystem via its
+universally-unique indentifier (UUID), @command{grub-mkconfig} can use the UUID
+of the partition containing the filesystem to identify the root filesystem to
+the Linux kernel via a @samp{root=PARTUUID=...} kernel parameter.  This is not
+as reliable as using the filesystem UUID, but is more reliable than using the
+Linux device names. When @samp{GRUB_DISABLE_LINUX_PARTUUID} is set to
+@samp{false}, the Linux kernel version must be 2.6.37 (3.10 for systems using
+the MSDOS partition scheme) or newer.  This option defaults to @samp{true}.  To
+enable the use of partition UUIDs, set this option to @samp{false}.
+
 @item GRUB_DISABLE_RECOVERY
 If this option is set to @samp{true}, disable the generation of recovery
 mode menu entries.
@@ -1556,6 +1568,53 @@ edit the scripts in @file{/etc/grub.d} directly.
 menu entries; simply type the menu entries you want to add at the end of
 that file, making sure to leave at least the first two lines intact.
 
+@node Root Identifcation Heuristics
+@section Root Identifcation Heuristics
+If the target operating system uses the Linux kernel, @command{grub-mkconfig}
+attempts to identify the root file system via a heuristic algoirthm.  This
+algorithm selects the identification method of the root file system by
+considering three factors.  The first is if an initrd for the target operating
+system is also present.  The second is @samp{GRUB_DISABLE_LINUX_UUID} and if set
+to @samp{true}, prevents @command{grub-mkconfig} from identifying the root file
+system by its UUID.  The third is @samp{GRUB_DISABLE_LINUX_PARTUUID} and if set
+to @samp{true}, prevents @command{grub-mkconfig} from identifying the root file
+system via the UUID of its enclosing partition.  If the variables are assigned
+any other value, that value is considered equivalent to @samp{false}.  The
+variables are also considered to be set to @samp{false} if they are not set.
+
+When booting, the Linux kernel will delegate the task of mounting the root
+filesystem to the initrd.  Most initrd images determine the root file system by
+checking the Linux kernel's command-line for the @samp{root} key and use its
+value as the identification method of the root file system.  To improve the
+reliability of booting, most initrd images also allow the root file system to be
+identified by its UUID.  Because of this behavior, the @command{grub-mkconfig}
+command will set @samp{root} to @samp{root=UUID=...} to provide the initrd with
+the filesystem UUID of the root file system.
+
+If no initrd is detected or @samp{GRUB_DISABLE_LINUX_UUID} is set to @samp{true}
+then @command{grub-command} will identify the root filesystem by setting the
+kernel command-line variable @samp{root} to @samp{root=PARTUUID=...} unless
+@samp{GRUB_DISABLE_LINUX_PARTUUID} is also set to @samp{true}.  If
+@samp{GRUB_DISABLE_LINUX_PARTUUID} is also set to @samp{true},
+@command{grub-command} will identify by its Linux device name.
+
+The following table summarizes the behavior of the @command{grub-mkconfig}
+command.
+
+@multitable {detected} {GRUB_DISABLE_LINUX_PARTUUID} {GRUB_DISABLE_LINUX_UUID} {Linux Root}
+@headitem Initrd detected @tab GRUB_DISABLE_LINUX_PARTUUID Set To @tab GRUB_DISABLE_LINUX_UUID Set To @tab Linux Root ID Method
+@item false         @tab false                       @tab false                   @tab part UUID
+@item false         @tab false                       @tab true                    @tab part UUID
+@item false         @tab true                        @tab false                   @tab dev name
+@item false         @tab true                        @tab true                    @tab dev name
+@item true          @tab false                       @tab false                   @tab fs UUID
+@item true          @tab false                       @tab true                    @tab part UUID
+@item true          @tab true                        @tab false                   @tab fs UUID
+@item true          @tab true                        @tab true                    @tab dev name
+@end multitable
+
+Remember, @samp{GRUB_DISABLE_LINUX_PARTUUID} and @samp{GRUB_DISABLE_LINUX_UUID}
+are also considered to be set to @samp{false} when they are unset.
 
 @node Shell-like scripting
 @section Writing full configuration files directly
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index 35ef583b05f..33332360eec 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -134,6 +134,7 @@ fi
 # Device containing our userland.  Typically used for root= parameter.
 GRUB_DEVICE="`${grub_probe} --target=device /`"
 GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
+GRUB_DEVICE_PARTUUID="`${grub_probe} --device ${GRUB_DEVICE} --target=partuuid 2> /dev/null`" || true
 
 # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
 GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
@@ -188,6 +189,7 @@ if [ "x${GRUB_ACTUAL_DEFAULT}" = "xsaved" ] ; then GRUB_ACTUAL_DEFAULT="`"${grub
 # override them.
 export GRUB_DEVICE \
   GRUB_DEVICE_UUID \
+  GRUB_DEVICE_PARTUUID \
   GRUB_DEVICE_BOOT \
   GRUB_DEVICE_BOOT_UUID \
   GRUB_FS \
@@ -223,6 +225,7 @@ export GRUB_DEFAULT \
   GRUB_TERMINAL_OUTPUT \
   GRUB_SERIAL_COMMAND \
   GRUB_DISABLE_LINUX_UUID \
+  GRUB_DISABLE_LINUX_PARTUUID \
   GRUB_DISABLE_RECOVERY \
   GRUB_VIDEO_BACKEND \
   GRUB_GFXMODE \
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index faedf74e14e..146499f22fd 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -43,12 +43,22 @@ case ${GRUB_DEVICE} in
   ;;
 esac
 
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
 # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
 # and mounting btrfs requires user space scanning, so force UUID in this case.
-if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
-    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ) \
+    || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+	&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+    || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+	&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
     || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+    || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+  LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
 else
   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
 fi
@@ -242,7 +252,13 @@ while [ "x$list" != "x" ] ; do
   if test -z "${initramfs}" && test -z "${initrd_real}" ; then
     # "UUID=" and "ZFS=" magic is parsed by initrd or initramfs.  Since there's
     # no initrd or builtin initramfs, it can't work here.
-    linux_root_device_thisversion=${GRUB_DEVICE}
+    if [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] \
+	|| [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ]; then
+
+	linux_root_device_thisversion=${GRUB_DEVICE}
+    else
+	linux_root_device_thisversion=PARTUUID=${GRUB_DEVICE_PARTUUID}
+    fi
   fi
 
   if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then
diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in
index 0cb0f4e49b9..e8143b079dc 100644
--- a/util/grub.d/20_linux_xen.in
+++ b/util/grub.d/20_linux_xen.in
@@ -43,12 +43,22 @@ case ${GRUB_DEVICE} in
   ;;
 esac
 
+# Default to disabling partition uuid support to maintian compatibility with
+# older kernels.
+GRUB_DISABLE_LINUX_PARTUUID=${GRUB_DISABLE_LINUX_PARTUUID-true}
+
 # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter
 # and mounting btrfs requires user space scanning, so force UUID in this case.
-if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
-    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \
+    || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+	&& [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \
+    || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
+	&& ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \
     || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then
   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \
+    || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then
+  LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID}
 else
   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
 fi
@@ -246,7 +256,13 @@ while [ "x${xen_list}" != "x" ] ; do
 	    gettext_printf "Found initrd image: %s\n" "${dirname}/${initrd}" >&2
 	else
     # "UUID=" magic is parsed by initrds.  Since there's no initrd, it can't work here.
-	    linux_root_device_thisversion=${GRUB_DEVICE}
+	    if [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] \
+		|| [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ]; then
+
+		linux_root_device_thisversion=${GRUB_DEVICE}
+	    else
+		linux_root_device_thisversion=PARTUUID=${GRUB_DEVICE_PARTUUID}
+	    fi
 	fi
 
 	if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then