grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
* [Patch] Enable libzfs detection on Linux
@ 2011-08-09 17:48 Zachary Bedell
  2011-08-18 16:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 1 reply; 8+ messages in thread
From: Zachary Bedell @ 2011-08-09 17:48 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: text/plain, Size: 1997 bytes --]

Attached is a patch which allows Grub to detect and use libzfs on Linux as provided by the ZfsOnLinux project.  

Most of this work was originally done by Darik Horn (dajhorn on GitHub) against the Grub 1.99 releases as patched by Ubuntu.  I've forward ported the patches to trunk and separated some of the Ubuntu-specific stuff.  These apply against trunk independent of the other ZFS work I've been doing.

Changes include:

configure.ac:  
 * Add check for libspl to bring in Solaris Porting Library for Linux support.
 * Include reference to Linux ZFS's config header to get necessary defines for other ZFS headers on Linux.
 * Add checks for libavl, libefi, libunicode, libzpool -- Linux decomposes these libraries which are lumped into libzfs on other platforms.

getroot.c:
 * Add ref to mnttab.h from libspl to allow getextmntent to work on Linux.
 * Change the order of the grub_find_root_device_from_mountinfo vs find_root_device_from_libzfs calls so that libzfs runs first, falling down to mountinfo if zfs isn't detected.
 * Scan /proc/mounts and /etc/mtab in addition to /etc/mnttab to discover mounted filesystems in grub_find_zpool_from_dir.

grub.d/10_linux.in:
 * Detect ZFS root and include reference to zfsinfo.mod if needed.
 * Detect the bootfs dataset from the zpool attribute.
 * Adjust kernel parameters to omit root= and replace with boot=zfs and reference to the detected bootfs if available.
 * If bootfs isn't available from the pool, delegates to detection (hopefully) present in the initrd.


These patches have been in use by a number of folks using ZfsOnLinux for some time, and they've been robust on those systems.  I've tried to ensure the changes won't impact non-Linux platforms, though I'm not sure I trust my knowledge of autoconf enough to be positive there are no side effects.

The attached patch is intended for trunk, but I also have a version rolled for the 1.99 branch if that would be useful.

Best regards,
Zac Bedell


[-- Attachment #2: grub-zfs-linux.patch --]
[-- Type: application/octet-stream, Size: 5420 bytes --]

diff --git a/configure.ac b/configure.ac
index e6d7265..3137869 100644
--- a/configure.ac
+++ b/configure.ac
@@ -295,9 +295,14 @@ else
   AC_PATH_PROG(HELP2MAN, help2man)
 fi
 
+# The Solaris Portability Layer is required to link grub against zfs-lib on Linux.
+AC_CHECK_LIB([spl], [getextmntent], [ LIBS="$LIBS -pthread -lspl"
+  AC_DEFINE([HAVE_LIBSPL], [1], [Define to 1 if you have the SPL library.])],)
+
 # Check for functions and headers.
 AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent)
-AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h)
+AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h,[],[],[$ac_includes_default
+#include <zfs-linux/zfs_config.h>])
 
 AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
 #include <sys/param.h>
@@ -922,17 +927,19 @@ AC_CHECK_LIB([lzma], [lzma_code],
                         [Define to 1 if you have the LZMA library.])],)
 AC_SUBST([LIBLZMA])
 
-AC_CHECK_LIB([zfs], [libzfs_init],
-             [LIBZFS="-lzfs"
-              AC_DEFINE([HAVE_LIBZFS], [1],
-                        [Define to 1 if you have the ZFS library.])],)
-AC_SUBST([LIBZFS])
+# These libraries and zpool below are external to libzfs on Linux,
+# but usually internal or intrinsic on other platforms.
+AC_CHECK_LIB([avl], [avl_create], [LIBS="$LIBS -lavl"])
+AC_CHECK_LIB([efi], [efi_alloc_and_init], [LIBS="$LIBS -lefi"])
+AC_CHECK_LIB([unicode], [u8_strcmp], [LIBS="$LIBS -lunicode"])
 
-AC_CHECK_LIB([nvpair], [nvlist_print],
-             [LIBNVPAIR="-lnvpair"
-              AC_DEFINE([HAVE_LIBNVPAIR], [1],
-                        [Define to 1 if you have the NVPAIR library.])],)
+AC_CHECK_LIB([nvpair], [nvlist_print], [LIBS="$LIBS -lnvpair" LIBNVPAIR="$LIBS"
+  AC_DEFINE([HAVE_LIBNVPAIR], [1], [Define to 1 if you have the NVPAIR library.])],)
 AC_SUBST([LIBNVPAIR])
+AC_CHECK_LIB([zpool], [zfs_prop_init], [LIBS="$LIBS -lzpool"])
+AC_CHECK_LIB([zfs], [libzfs_init], [LIBS="$LIBS -lzfs" LIBZFS="$LIBS"
+  AC_DEFINE([HAVE_LIBZFS], [1], [Define to 1 if you have the ZFS library.])],)
+AC_SUBST([LIBZFS])
 
 LIBS=""
 
diff --git a/util/getroot.c b/util/getroot.c
index 7106458..0282a3d 100644
--- a/util/getroot.c
+++ b/util/getroot.c
@@ -34,6 +34,17 @@
 #include <stdint.h>
 #include <grub/util/misc.h>
 #include <grub/cryptodisk.h>
+#if defined(HAVE_LIBSPL) && defined(__linux__)
+# include <sys/ioctl.h>
+/*
+ * The Solaris Compatibility Layer provides getextmntent on Linux, which is
+ * required for grub-probe to recognize a native ZFS root filesystem on
+ * a Linux system. This typedef is required because including the SPL
+ * types.h here conflicts with an earlier Linux types.h inclusion.
+ */
+  typedef unsigned int uint_t;
+# include <libspl/sys/mnttab.h>
+#endif
 
 #ifdef HAVE_DEVICE_MAPPER
 # include <libdevmapper.h>
@@ -598,16 +609,16 @@ grub_guess_root_device (const char *dir)
   struct stat st;
   dev_t dev;
 
-#ifdef __linux__
-  if (!os_dev)
-    os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
-#endif /* __linux__ */
-
 #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
   if (!os_dev)
     os_dev = find_root_device_from_libzfs (dir);
 #endif
 
+#ifdef __linux__
+  if (!os_dev)
+    os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
+#endif /* __linux__ */
+
   if (os_dev)
     {
       char *tmp = os_dev;
@@ -1407,7 +1418,15 @@ grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
     if (stat (dir, &st) != 0)
       return;
 
-    FILE *mnttab = fopen ("/etc/mnttab", "r");
+    FILE *mnttab;
+    mnttab = fopen ("/proc/mounts", "r");
+
+    if (! mnttab)
+      mnttab = fopen ("/etc/mtab", "r");
+
+    if (! mnttab)
+      mnttab = fopen ("/etc/mnttab", "r");
+
     if (! mnttab)
       return;
 
diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
index 97e7c65..20b204f 100644
--- a/util/grub.d/10_linux.in
+++ b/util/grub.d/10_linux.in
@@ -51,7 +51,10 @@ else
   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}
 fi
 
-if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`" = xbtrfs ]; then
+LINUX_ROOT_FS=`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`
+LINUX_ROOT_STAT=`stat -f --printf=%T / || true`
+
+if [ "x${LINUX_ROOT_FS}" = xbtrfs ] || [ "x${LINUX_ROOT_STAT}" = xbtrfs ]; then
   rootsubvol="`make_system_path_relative_to_its_root /`"
   rootsubvol="${rootsubvol#/}"
   if [ "x${rootsubvol}" != x ]; then
@@ -59,6 +62,10 @@ if [ "x`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2>/dev/null || true`"
   fi
 fi
 
+if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
+  GRUB_CMDLINE_LINUX="boot=zfs \$bootfs ${GRUB_CMDLINE_LINUX}"
+fi
+
 linux_entry ()
 {
   os="$1"
@@ -113,10 +120,20 @@ EOF
     fi
     printf '%s\n' "${prepare_boot_cache}"
   fi
+  if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
+    cat << EOF
+	insmod zfsinfo
+	zfs-bootfs (\$root) bootfs
+EOF
+    # ZFS doesn't want root=... or read-only.
+    rootentry=""
+  else
+    rootentry="root=${linux_root_device_thisversion} ro"
+  fi
   message="$(gettext_printf "Loading Linux %s ..." ${version})"
   cat << EOF
 	echo	'$message'
-	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
+	linux	${rel_dirname}/${basename} ${rootentry} ${args}
 EOF
   if test -n "${initrd}" ; then
     message="$(gettext_printf "Loading initial ramdisk ...")"

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-11-15 22:38 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-09 17:48 [Patch] Enable libzfs detection on Linux Zachary Bedell
2011-08-18 16:49 ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-09-14 18:39   ` Zachary Bedell
2011-11-03 14:51     ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-11-10 20:02     ` Robert Millan
2011-11-10 20:38       ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-11-10 20:39       ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-11-15 22:37       ` Seth Goldberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).