grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
From: "Vladimir 'φ-coder/phcoder' Serbinenko" <phcoder@gmail.com>
To: grub-devel@gnu.org
Subject: Re: [Patch] Enable libzfs detection on Linux
Date: Thu, 03 Nov 2011 15:51:01 +0100	[thread overview]
Message-ID: <4EB2AA55.60408@gmail.com> (raw)
In-Reply-To: <DC3AA724-559C-4129-BFFC-5AA148E9BAC4@gmail.com>

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

On 14.09.2011 20:39, Zachary Bedell wrote:
> Finally getting back to this & trying address concerns below:
>
> On Aug 18, 2011, at 12:49 PM, Vladimir 'φ-coder/phcoder' Serbinenko wrote:
>> > On 09.08.2011 19:48, Zachary Bedell wrote:
>>> >> 
>>> >> * Scan /proc/mounts and /etc/mtab in addition to /etc/mnttab to discover mounted filesystems in grub_find_zpool_from_dir.
>> > /etc/mtab is just a regular file and in many cases is out-of-sync with real state of affairs. Should be ignored altogether. Use of /etc/mnttab is unfortunate but I know of no other way on other platforms (since I haven't looked into it).
> Easy enough to remove mtab.
>
>>> >> 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.
>>> >> 
>> > You forget the effect of other code changes (below)
>>> >> - FILE *mnttab = fopen ("/etc/mnttab", "r");
>>> >> +    FILE *mnttab;
>>> >> +    mnttab = fopen ("/proc/mounts", "r");
>> > /proc on FreeBSD is very different from Linux one. Don't try
>> > /proc/mounts except if you have Linux.
> If I'm reading the pre-existing ifdef's there, the code added for /proc/mounts wouldn't apply on FreeBSD (assuming the comments there aren't lying).  The ifdef around line 1399:
>
> #if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME)
>   /* FreeBSD and GNU/kFreeBSD.  */
>
> would be hit on BSD and thus exclude the /proc/mounts code.  That said, easy enough to add an extra '#ifdef __linux__' around the proc code so it doesn't fire on Solaris and yank the mtab code.
>
>>> >> -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
>> > This changes logic for btrfs. I don't think it's necessary or good to
>> > just change it.
> Looking back, I think this may have been the result of forward porting this patch from an older Grub codebase.  I've changed it to restore the original btrfs logic from trunk.
>
>>> >> +if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
>>> >> +  GRUB_CMDLINE_LINUX="boot=zfs \$bootfs ${GRUB_CMDLINE_LINUX}"
>>> >> +fi
>>> >> +
>>> >>   fi
>>> >> +  if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
>>> >> +    cat << EOF
>>> >> +	insmod zfsinfo
>>> >> +	zfs-bootfs (\$root) bootfs
>>> >> +EOF
>> > In this place $root refers to whereever kernel is. So if /boot is
>> > separate it will be wrong. Moreover you completely forget the possible
>> > subvolumes. One could have e.g.
>> > FreeBSD in /freebsd/@/...
>> > GNU/Linux in /gnu/linux/@
>> > /boot in /boot/@
>> > In this case $bootfs has to take subvolume into account.
>> > Also nothing guarantees that / is accessible from GRUB proper at all.
>> > The ZFS in question may be on e.g. SAN. You need to figure parameters in
>> > 10_linux, not on boot time.
> Taking a closer look at these, I don't think they're necessary with the initrd scripts used by the current Linux implementations (one in Ubuntu & the Dracut scripts in the ZFSonLinux distribution being the two I'm aware of).  The only thing required in the second half of 10_linux was the change to exclude root=… and the ro attribute for ZFS.  Once grub loads kernel & initrd, the initrd does the work of finding the root pool and importing it using the full ZFS kernel module, so there's no need to use Grub's logic to do the same.
>
> Remixed patch is attached.
>
> grub-zfs-linux.patch
>
>
> 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>])
>  
This will fail on Solaris or FreeBSD due to missing 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"])
>  
Why do you need those libraries? I see no reference to these functions.
> -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..592a02f 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;
> @@ -1399,7 +1410,7 @@ grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
>      *poolname = xstrdup (mnt.f_mntfromname);
>    }
>  #elif defined(HAVE_GETEXTMNTENT)
> -  /* Solaris.  */
> +  /* Solaris and ZFSonLinux (but not FUSE).  */
>    {
>      struct stat st;
>      struct extmnttab mnt;
> @@ -1407,7 +1418,17 @@ 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 = NULL;
> +
> +#ifdef __linux__
> +    /* Look in proc only for Linux.  Solaris (and anything else with 
> +       HAVE_GETEXTMNTENT) won't need it. */
> +    mnttab = fopen ("/proc/mounts", "r");
> +#endif
> +
> +    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..5624607 100644
> --- a/util/grub.d/10_linux.in
> +++ b/util/grub.d/10_linux.in
> @@ -51,12 +51,15 @@ 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`
> +if [ "x${LINUX_ROOT_FS}" = xbtrfs ] ; then
>    rootsubvol="`make_system_path_relative_to_its_root /`"
>    rootsubvol="${rootsubvol#/}"
>    if [ "x${rootsubvol}" != x ]; then
>      GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
>    fi
> +elif [ "x${LINUX_ROOT_FS}" = xzfs ]; then
> +  GRUB_CMDLINE_LINUX="boot=zfs ${GRUB_CMDLINE_LINUX}"
>  fi
>  
>  linux_entry ()
> @@ -113,10 +116,16 @@ EOF
>      fi
>      printf '%s\n' "${prepare_boot_cache}"
>    fi
> +  if [ "x${LINUX_ROOT_FS}" = xzfs ]; then
> +    # 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 ...")"
>
>
>
>
> FWIW, my commit comment locally for this was:
>  * Adjusts autoconf logic to properly detect libzfs on Linux.
>  * Includes additional headers necessary for libspl.
>  * Changes order that filesystems are detected in to allow ZFS a chance to be found.
>  * Add necessary boot parameters & detection logic to grub.d script for Linux.
>
> Sorry for the interminable delay in getting back to this.  Debugging this took a rather "creative" turn as I found a few more cases where pools that worked in the ZFS driver were rejected by Grub.  I have a second patch that fixes a number of these cases which I'll be posting shortly.
>
> Best regards,
> Zac Bedell
>
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


-- 
Regards
Vladimir 'φ-coder/phcoder' Serbinenko



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 294 bytes --]

  reply	other threads:[~2011-11-03 14:53 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4EB2AA55.60408@gmail.com \
    --to=phcoder@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).