grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Patch] Enable libzfs detection on Linux


From: Vladimir 'φ-coder/phcoder' Serbinenko
Subject: Re: [Patch] Enable libzfs detection on Linux
Date: Thu, 03 Nov 2011 15:51:01 +0100
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.23) Gecko/20111010 Iceowl/1.0b2 Icedove/3.1.15

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
> address@hidden
> https://lists.gnu.org/mailman/listinfo/grub-devel


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


Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]