All of lore.kernel.org
 help / color / mirror / Atom feed
* getroot for ZFS without libzfs?
@ 2011-08-08  1:28 Zachary Bedell
  2011-08-09 11:54 ` Robert Millan
  2011-10-15 16:59 ` Robert Millan
  0 siblings, 2 replies; 17+ messages in thread
From: Zachary Bedell @ 2011-08-08  1:28 UTC (permalink / raw)
  To: grub-devel

Greetings all,

I've been working for the last few weeks with Grub on a Linux system using ZFS drivers from zfsonlinux.org.  One change required to Grub has been in adapting the way the the build process detects and links to libzfs for the code in util/getroot.c.  I'd like to see the changes required included in Grub of course, but I have some concerns about the licensing issues and also accessing the private libzfs.

It appears that existing Grub code already links against libzfs for the benefit of find_root_device_from_libzfs and other functions in getroot.c.  It also appears that libzfs is not used outside this file.  That linkage surprises me a bit as I would have expected GPL Grub linked against CDDL libzfs to create a problem.  Also libzfs is considered a private API and not intended to be linked against, though admittedly what I propose (reading on-disk structures directly) is arguably worse than accessing a private library.

As best I can tell, all of the ZFS-related functionality that getroot.c requires was included in the GPL release that Sun made in Grub 0.97.  I think it should be relatively straight forward to modify getroot.c to use the GPL'd ZFS code to directly access the disk and read the necessary bits out of ZFS that it needs to configure itself.  Assuming that change is made, it should be possible to expunge Grub of all references to libzfs and have its ZFS support operate purely on the GPL'd dump from Sun.

I'd like to dive in and make these changes, but I wanted to solicit thoughts from other Grub devs before starting.  Am I incorrect in my belief that linking libzfs is a GPL problem for Grub?  Is the CDDL/GPL problem not reciprocal and this only a problem for CDDL ZFS using GPL kernel and not the other way around?

Does anyone see an issue with getroot.c reading the on-disk ZFS structures directly?  grub-probe already does this in its search for uberblocks and labels, so I don't think changing getroot.c is making the situation worse.

Any other thoughts would be appreciated.

Best regards,
Zac Bedell



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

* Re: getroot for ZFS without libzfs?
  2011-08-08  1:28 getroot for ZFS without libzfs? Zachary Bedell
@ 2011-08-09 11:54 ` Robert Millan
  2011-08-09 17:34   ` Zachary Bedell
  2011-10-15 16:59 ` Robert Millan
  1 sibling, 1 reply; 17+ messages in thread
From: Robert Millan @ 2011-08-09 11:54 UTC (permalink / raw)
  To: The development of GNU GRUB

Hi Zachary,

2011/8/8 Zachary Bedell <pendorbound@gmail.com>:
> It appears that existing Grub code already links against libzfs for the benefit of find_root_device_from_libzfs and other functions in getroot.c.  It also appears that libzfs is not used outside this file.  That linkage surprises me a bit as I would have expected GPL Grub linked against CDDL libzfs to create a problem.

Not really.  This kind of use falls under the system library
exception, see section 1 of the GPL.

> Also libzfs is considered a private API and not intended to be linked against, though admittedly what I propose (reading on-disk structures directly) is arguably worse than accessing a private library.

I don't think you can figure out the disks corresponding to a zpool
just by reading disk structures.  You can guess, but only the kernel
knows for sure.

The other API that is available to us is /dev/zfs.  But is that device
meant to be used directly?  How stable is this interface?

-- 
Robert Millan


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

* Re: getroot for ZFS without libzfs?
  2011-08-09 11:54 ` Robert Millan
@ 2011-08-09 17:34   ` Zachary Bedell
  2011-08-10 12:22     ` Robert Millan
  0 siblings, 1 reply; 17+ messages in thread
From: Zachary Bedell @ 2011-08-09 17:34 UTC (permalink / raw)
  To: The development of GNU GRUB

On Aug 9, 2011, at 7:54 AM, Robert Millan wrote:
> 2011/8/8 Zachary Bedell <pendorbound@gmail.com>:
>>  Also libzfs is considered a private API and not intended to be linked against, though admittedly what I propose (reading on-disk structures directly) is arguably worse than accessing a private library.
> 
> I don't think you can figure out the disks corresponding to a zpool
> just by reading disk structures.  You can guess, but only the kernel
> knows for sure.

It's all in there, and the structures are pretty well defined & stable.  You'd need to look at all the raw devices to begin with and see which if any has a ZFS label (always in a well known location).  Assuming any does, you get the vdev_tree out of the label's nvlist, and from there you can discover child and parent devices to rebuild the full tree.  It looks like the code in getroot.c is doing pretty much that by calling the various nvlist_lookup_* functions from libzfs.  Doing the same from the pool isn't much more difficult, and the necessary nvlist-related functions are already in zfs.c in Grub at this point.

> The other API that is available to us is /dev/zfs.  But is that device
> meant to be used directly?  How stable is this interface?

/dev/zfs is probably less stable than libzfs, both of which are less stable than the on-disk format.  That said, libzfs is going to be stable for the foreseeable future until/unless Oracle dumps more code.  I do know that the cryptography related work in Solaris 11 changed the on-disk structures slightly, though in theory in a backwards compatible way.  Likewise, the particular functions of libzfs that Grub needs are core enough to ZFS that I doubt they'd be broken in a future release.

My reasons for looking at other options were primarily GPL driven, but given that's not an issue, it's probably moot for now.  It might be slightly more elegant to use pure Grub code given that all of the underlying functionality is there already, but the real benefits are probably minimal.

SO that said…  It probably makes the most sense to withdraw my thoughts of removing libzfs.  In lieu of that, I have a patch which allows ZFS detection to function on Linux.  I'll post that under separate subject momentarily as it's unrelated to libzfs in getroot.c.

Best regards,
Zac



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

* Re: getroot for ZFS without libzfs?
  2011-08-09 17:34   ` Zachary Bedell
@ 2011-08-10 12:22     ` Robert Millan
  2011-08-11  1:04       ` Zachary Bedell
  0 siblings, 1 reply; 17+ messages in thread
From: Robert Millan @ 2011-08-10 12:22 UTC (permalink / raw)
  To: The development of GNU GRUB

2011/8/9 Zachary Bedell <pendorbound@gmail.com>:
> You'd need to look at all the raw devices to begin with and see which if any has a ZFS label

Yes, but how do you know this is the label you wanted?  Consider the
case where there's more than one pool with this name.

>> The other API that is available to us is /dev/zfs.  But is that device
>> meant to be used directly?  How stable is this interface?
>
> /dev/zfs is probably less stable than libzfs

Then I wouldn't use /dev/zfs.  The less stable and standard is the ZFS
API GRUB uses, the more likely is that one can argue it doesn't fall
under the "system library" exception.

Directly accessing on-disk structures is entirely different, since a
data structure itself can't be copyrighted.

> My reasons for looking at other options were primarily GPL driven, but given that's not an issue, it's probably moot for now.  It might be slightly more elegant to use pure Grub code given that all of the underlying functionality is there already,

I agree.  But I'm still concerned about the technical problems.

-- 
Robert Millan


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

* Re: getroot for ZFS without libzfs?
  2011-08-10 12:22     ` Robert Millan
@ 2011-08-11  1:04       ` Zachary Bedell
  2011-08-12 11:29         ` Robert Millan
  2011-08-18 17:05         ` Vladimir 'φ-coder/phcoder' Serbinenko
  0 siblings, 2 replies; 17+ messages in thread
From: Zachary Bedell @ 2011-08-11  1:04 UTC (permalink / raw)
  To: The development of GNU GRUB

On Aug 10, 2011, at 8:22 AM, Robert Millan wrote:
> 2011/8/9 Zachary Bedell <pendorbound@gmail.com>:
>> You'd need to look at all the raw devices to begin with and see which if any has a ZFS label
> 
> Yes, but how do you know this is the label you wanted?  Consider the
> case where there's more than one pool with this name.

The pool can be identified positively via the guid which is in the labels and available via `zpool list -H -o guid <pool name>`.  It's not possible to have two pools imported at once with the same name, so getting the root dataset via parsing /proc/mounts, /etc/mtab, or /etc/mnttab then going to `zpool list` will give you the guid of the root pool definitively.  Then just parse all the device labels until you find a label with a matching guid.  (And probably keep scanning for all of the devices with that guid to install Grub to all of them similar to the MD support, but I'm getting ahead of myself…)

It would also be possible to check the imported status of the pool since a conflicted name couldn't be imported normally (though multiple pools available via SAN fabric would probably invalidate that).  It may also be possible to compare the hostid of the host that has it imported, though I'm not sure it's possible to get the hostid reliably without going to libzfs.  There's logic in the Linux ZFS driver that diverges from both Solaris and FreeBSD a bit as far as how the hostid is calculated from the live system, so that's probably a tough option.

Is calling out to zpool as a helper kosher?  The -H flag to zpool pool is basically Sun's idea of a public API in that it's intended to output only the requested fields with no header information for automated parsing.

>>> The other API that is available to us is /dev/zfs.  But is that device
>>> meant to be used directly?  How stable is this interface?
>> 
>> /dev/zfs is probably less stable than libzfs
> 
> Then I wouldn't use /dev/zfs.  The less stable and standard is the ZFS
> API GRUB uses, the more likely is that one can argue it doesn't fall
> under the "system library" exception.

Definitely agree.  The fact that libzfs is specifically listed as private API not intended for linking against also makes me wonder if the syslib exception is a concern for that.

> Directly accessing on-disk structures is entirely different, since a
> data structure itself can't be copyrighted.

Right.  And a bonus that the on-disk is well documented by Sun with the explicitly stated purpose of interoperability.


Assuming calling out to zpool would be acceptable, I think I'm going to dive in this week and see if I can get it running.  The libzfs related autoconf stuff is the biggest area that Linux is "special" in, and it would be nice to yank that all out.

-Zac



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

* Re: getroot for ZFS without libzfs?
  2011-08-11  1:04       ` Zachary Bedell
@ 2011-08-12 11:29         ` Robert Millan
  2011-08-18 17:05         ` Vladimir 'φ-coder/phcoder' Serbinenko
  1 sibling, 0 replies; 17+ messages in thread
From: Robert Millan @ 2011-08-12 11:29 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Vladimir Serbinenko

2011/8/11 Zachary Bedell <pendorbound@gmail.com>:
> The pool can be identified positively via the guid which is in the labels and available via `zpool list -H -o guid <pool name>`.

I see.  Thanks for the explanation.

> Is calling out to zpool as a helper kosher?  The -H flag to zpool pool is basically Sun's idea of a public API in that it's intended to output only the requested fields with no header information for automated parsing.

I think -H output looks sane enough (and more stable, so all the better).

> Definitely agree.  The fact that libzfs is specifically listed as private API not intended for linking against also makes me wonder if the syslib exception is a concern for that.

But SUN/Oracle has linked GRUB with libzfs. This is a good indication
that they trust this method to be safe (it's our copyright which would
be infringed by them, not theirs by us).

-- 
Robert Millan


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

* Re: getroot for ZFS without libzfs?
  2011-08-11  1:04       ` Zachary Bedell
  2011-08-12 11:29         ` Robert Millan
@ 2011-08-18 17:05         ` Vladimir 'φ-coder/phcoder' Serbinenko
  2011-08-25  5:35           ` Seth Goldberg
  1 sibling, 1 reply; 17+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-08-18 17:05 UTC (permalink / raw)
  To: grub-devel

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

On 11.08.2011 03:04, Zachary Bedell wrote:
> On Aug 10, 2011, at 8:22 AM, Robert Millan wrote:
>> 2011/8/9 Zachary Bedell <pendorbound@gmail.com>:
>>> You'd need to look at all the raw devices to begin with and see which if any has a ZFS label
>> Yes, but how do you know this is the label you wanted?  Consider the
>> case where there's more than one pool with this name.
> The pool can be identified positively via the guid which is in the labels and available via `zpool list -H -o guid <pool name>`.  It's not possible to have two pools imported at once with the same name,
If you can't import 2 pools with same name in the same time then it's a
bug. It's like not being able to mount 2 disks with same label. And so
as such I expect it to be fixed in future and so I don't rely on this.

> (And probably keep scanning for all of the devices with that guid to install Grub to all of them similar to the MD support, but I'm getting ahead of myself…)
>
This would be inappropriate. Install is done to the disk, not to FS. So
if user tells to install to one disk, you have to obey, not guess what
user might have wanted.
> It would also be possible to check the imported status of the pool since a conflicted name couldn't be imported normally (though multiple pools available via SAN fabric would probably invalidate that).
The status of the pool in on-disk structures may be "IMPORTED" even if
the pool currently isn't. For instance FreeBSD keeps the state to
"IMPORTED" on shutdown and so it would appear as imported if booted into
another OS.
>   It may also be possible to compare the hostid of the host that has it imported, though I'm not sure it's possible to get the hostid reliably without going to libzfs.  There's logic in the Linux ZFS driver that diverges from both Solaris and FreeBSD a bit as far as how the hostid is calculated from the live system, so that's probably a tough option.
>
and unreliable as well.
> Is calling out to zpool as a helper kosher?
English translation of "kosher" ("כשר") is "appropriate". Why not stick
to English?
>   The -H flag to zpool pool is basically Sun's idea of a public API in that it's intended to output only the requested fields with no header information for automated parsing.
But probably using unusual symbols in zpool names will make the parsing
go haywire anyway.
@Seth: any comment on what Sun considers a public API?
>>
>> Then I wouldn't use /dev/zfs.  The less stable and standard is the ZFS
>> API GRUB uses, the more likely is that one can argue it doesn't fall
>> under the "system library" exception.
We don't need system library exception to read /dev/zfs. It's not a
library but a way to speak with kernel which is definitely interprocess
communication.
>> Directly accessing on-disk structures is entirely different, since a
>> data structure itself can't be copyrighted.
> Right.  And a bonus that the on-disk is well documented by Sun with the explicitly stated purpose of interoperability.
>
>
> Assuming calling out to zpool would be acceptable, I think I'm going to dive in this week and see if I can get it running.  The libzfs related autoconf stuff is the biggest area that Linux is "special" in, and it would be nice to yank that all out.
>
> -Zac
>
>
> _______________________________________________
> 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 --]

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

* Re: getroot for ZFS without libzfs?
  2011-08-18 17:05         ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2011-08-25  5:35           ` Seth Goldberg
  0 siblings, 0 replies; 17+ messages in thread
From: Seth Goldberg @ 2011-08-25  5:35 UTC (permalink / raw)
  To: The development of GNU GRUB

Hi,

> @Seth: any comment on what Sun considers a public API?
>>> 

  As far as I know, libzfs is not a publicly documented API.  I don't think I can give any assurances about its stability.

>>> Then I wouldn't use /dev/zfs.  The less stable and standard is the ZFS
>>> API GRUB uses, the more likely is that one can argue it doesn't fall
>>> under the "system library" exception.
> We don't need system library exception to read /dev/zfs. It's not a
> library but a way to speak with kernel which is definitely interprocess
> communication.

  My gut reaction to that would be that it would probably be easier for the ioctl interface to change than the libzfs interface, but that's my personal opinion :).

  If you do decide to make changes for other systems, it would be nice to leave in the libzfs code that exists for platforms that have it, if that's allowable/possible.

 --S



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

* Re: getroot for ZFS without libzfs?
  2011-08-08  1:28 getroot for ZFS without libzfs? Zachary Bedell
  2011-08-09 11:54 ` Robert Millan
@ 2011-10-15 16:59 ` Robert Millan
  2011-10-15 17:47   ` Seth Goldberg
                     ` (2 more replies)
  1 sibling, 3 replies; 17+ messages in thread
From: Robert Millan @ 2011-10-15 16:59 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: Arno Töll, Zachary Bedell

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

Hi,

Please test / comment on proof-of-concept attached patch, it gets rid
of libzfs dependency in GRUB.

The approach is to implement a disk abstraction, like LVM does, but in
this case a very simple one (passthrough).  Then grub-probe et al can
obtain their information from this abstraction layer like they
currently do with LVM or mdRAID, but they don't need the device node
list anymore (since it's filled with a full scan, as with LVM).

-- 
Robert Millan

[-- Attachment #2: zfs.diff --]
[-- Type: text/x-diff, Size: 12924 bytes --]

=== modified file 'configure.ac'
--- configure.ac	2011-08-19 20:49:48 +0000
+++ configure.ac	2011-10-15 16:42:10 +0000
@@ -916,18 +916,6 @@ 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])
-
-AC_CHECK_LIB([nvpair], [nvlist_print],
-             [LIBNVPAIR="-lnvpair"
-              AC_DEFINE([HAVE_LIBNVPAIR], [1],
-                        [Define to 1 if you have the NVPAIR library.])],)
-AC_SUBST([LIBNVPAIR])
-
 LIBS=""
 
 pkglibrootdir='$(libdir)'/`echo $PACKAGE | sed "$program_transform_name"`

=== modified file 'grub-core/fs/zfs/zfs.c'
--- grub-core/fs/zfs/zfs.c	2011-06-23 22:31:29 +0000
+++ grub-core/fs/zfs/zfs.c	2011-10-15 16:42:10 +0000
@@ -53,6 +53,10 @@
 #include <grub/zfs/dsl_dataset.h>
 #include <grub/deflate.h>
 
+#ifdef GRUB_UTIL
+#include <grub/emu/misc.h>
+#endif
+
 GRUB_MOD_LICENSE ("GPLv3+");
 
 #define	ZPOOL_PROP_BOOTFS		"bootfs"
@@ -2179,6 +2183,130 @@ zfs_uuid (grub_device_t device, char **u
   return GRUB_ERR_NONE;
 }
 
+struct grub_zfs_vdev
+{
+  const char *name;
+  struct grub_zfs_vdev *next;
+};
+
+struct grub_zfs_pool
+{
+  grub_uint64_t guid;
+  char *name;
+  struct grub_zfs_vdev *vdev_list;
+  struct grub_zfs_pool *next;
+};
+
+static struct grub_zfs_pool *zpool_list;
+
+static int
+zfs_scan_device (const char *name)
+{
+  grub_device_t device;
+  struct grub_zfs_data *data;
+  char *nvlist;
+  grub_uint64_t guid;
+  char *label;
+  struct grub_zfs_pool *zpool;
+  struct grub_zfs_vdev *vdev;
+
+#ifdef GRUB_UTIL
+  grub_util_info ("scanning %s for ZFS", name);
+#endif
+
+  device = grub_device_open (name);
+  if (! device)
+    return 0;
+
+  data = zfs_mount (device);
+  if (! data)
+    goto end1;
+
+  if (zfs_fetch_nvlist (data, &nvlist))
+    goto end2;
+
+  if (! grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid))
+    goto end3;
+
+  label = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME);
+  if (! label)
+    goto end3;
+
+  vdev = grub_zalloc (sizeof (*vdev));
+  vdev->name = grub_strdup (name);
+
+  struct grub_zfs_pool *i;
+  for (i = zpool_list; i; i = i->next)
+    {
+      if (guid == i->guid)
+	{
+	  /* This vdev belongs to an already-registered pool.  */
+	  vdev->next = i->vdev_list;
+	  i->vdev_list = vdev;
+	  return 0;
+	}
+    }
+
+  /* Create a new ZFS pool with this vdev.  */
+  zpool = grub_zalloc (sizeof (*zpool));
+  zpool->guid = guid;
+  zpool->name = grub_xasprintf ("zfs/%s", label);
+  zpool->vdev_list = vdev;
+
+  /* Insert it to ZFS pool list.  */
+  zpool->next = zpool_list;
+  zpool_list = zpool;
+
+ end3:
+  grub_free (nvlist);
+ end2:
+  zfs_unmount (data);
+ end1:
+  grub_device_close (device);
+
+  return 0;
+}
+
+static int 
+grub_zpool_iterate (int (*hook) (const char *name),
+		    grub_disk_pull_t pull __attribute__ ((unused)))
+{
+  struct grub_zfs_pool *i;
+  for (i = zpool_list; i; i = i->next)
+    {
+      if (hook (i->name))
+	return 1;
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_zpool_open (const char *name, grub_disk_t disk)
+{
+  struct grub_zfs_pool *i;
+  for (i = zpool_list; i; i = i->next)
+    {
+      if (! grub_strcmp (i->name, name))
+	{
+	  /* For now just pick the first vdev as lower layer.  */
+	  grub_disk_t lower = grub_disk_open (i->vdev_list->name);
+	  grub_memcpy (disk, lower, sizeof (*disk));
+	  return GRUB_ERR_NONE;
+	}
+    }
+
+  return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a ZFS pool");
+}
+
+static struct grub_disk_dev grub_zpool_dev =
+  {
+    .name = "zfs",
+    .id = GRUB_DISK_DEVICE_ZFS_ID,
+    .iterate = grub_zpool_iterate,
+    .open = grub_zpool_open, 
+  };
+
 /*
  * zfs_open() locates a file in the rootpool by following the
  * MOS and places the dnode of the file in the memory address DNODE.
@@ -2556,6 +2684,9 @@ static struct grub_fs grub_zfs_fs = {
 
 GRUB_MOD_INIT (zfs)
 {
+  grub_device_iterate (&zfs_scan_device);
+  grub_disk_dev_register (&grub_zpool_dev);
+
   grub_fs_register (&grub_zfs_fs);
 #ifndef GRUB_UTIL
   my_mod = mod;
@@ -2564,5 +2695,9 @@ GRUB_MOD_INIT (zfs)
 
 GRUB_MOD_FINI (zfs)
 {
+  grub_disk_dev_unregister (&grub_zpool_dev);
+  zpool_list = NULL;
+  /* FIXME: free the zpool list. */
+
   grub_fs_unregister (&grub_zfs_fs);
 }

=== modified file 'grub-core/kern/disk.c'
--- grub-core/kern/disk.c	2011-08-13 13:00:48 +0000
+++ grub-core/kern/disk.c	2011-10-15 16:42:10 +0000
@@ -267,6 +267,7 @@ grub_disk_open (const char *name)
 
   for (dev = grub_disk_dev_list; dev; dev = dev->next)
     {
+      disk->dev = dev;
       if ((dev->open) (raw, disk) == GRUB_ERR_NONE)
 	break;
       else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
@@ -289,8 +290,6 @@ grub_disk_open (const char *name)
       goto fail;
     }
 
-  disk->dev = dev;
-
   if (p)
     {
       disk->partition = grub_partition_probe (disk, p + 1);

=== modified file 'include/grub/disk.h'
--- include/grub/disk.h	2011-08-13 13:00:48 +0000
+++ include/grub/disk.h	2011-10-15 16:42:10 +0000
@@ -44,6 +44,7 @@ enum grub_disk_dev_id
     GRUB_DISK_DEVICE_FILE_ID,
     GRUB_DISK_DEVICE_CRYPTODISK_ID,
     GRUB_DISK_DEVICE_ARCDISK_ID,
+    GRUB_DISK_DEVICE_ZFS_ID,
   };
 
 struct grub_disk;

=== modified file 'include/grub/emu/getroot.h'
--- include/grub/emu/getroot.h	2011-04-25 12:52:07 +0000
+++ include/grub/emu/getroot.h	2011-10-15 16:42:10 +0000
@@ -27,6 +27,7 @@ enum grub_dev_abstraction_types {
   GRUB_DEV_ABSTRACTION_RAID,
   GRUB_DEV_ABSTRACTION_LUKS,
   GRUB_DEV_ABSTRACTION_GELI,
+  GRUB_DEV_ABSTRACTION_ZFS,
 };
 
 char *grub_find_device (const char *dir, dev_t dev);

=== modified file 'util/getroot.c'
--- util/getroot.c	2011-10-15 16:37:55 +0000
+++ util/getroot.c	2011-10-15 16:44:12 +0000
@@ -243,69 +243,6 @@ grub_find_root_device_from_mountinfo (co
 
 #endif /* __linux__ */
 
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
-static char *
-find_root_device_from_libzfs (const char *dir)
-{
-  char *device = NULL;
-  char *poolname;
-  char *poolfs;
-
-  grub_find_zpool_from_dir (dir, &poolname, &poolfs);
-  if (! poolname)
-    return NULL;
-
-  {
-    zpool_handle_t *zpool;
-    libzfs_handle_t *libzfs;
-    nvlist_t *config, *vdev_tree;
-    nvlist_t **children, **path;
-    unsigned int nvlist_count;
-    unsigned int i;
-
-    libzfs = grub_get_libzfs_handle ();
-    if (! libzfs)
-      return NULL;
-
-    zpool = zpool_open (libzfs, poolname);
-    config = zpool_get_config (zpool, NULL);
-
-    if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0)
-      error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")");
-
-    if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0)
-      error (1, errno, "nvlist_lookup_nvlist_array (\"children\")");
-    assert (nvlist_count > 0);
-
-    while (nvlist_lookup_nvlist_array (children[0], "children",
-				       &children, &nvlist_count) == 0)
-      assert (nvlist_count > 0);
-
-    for (i = 0; i < nvlist_count; i++)
-      {
-	if (nvlist_lookup_string (children[i], "path", &device) != 0)
-	  error (1, errno, "nvlist_lookup_string (\"path\")");
-
-	struct stat st;
-	if (stat (device, &st) == 0)
-	  {
-	    device = xstrdup (device);
-	    break;
-	  }
-
-	device = NULL;
-      }
-
-    zpool_close (zpool);
-  }
-
-  free (poolname);
-  if (poolfs)
-    free (poolfs);
-
-  return device;
-}
-#endif
 
 #ifdef __MINGW32__
 
@@ -608,11 +545,6 @@ grub_guess_root_device (const char *dir)
     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
-
   if (os_dev)
     {
       char *tmp = os_dev;
@@ -635,6 +567,28 @@ grub_guess_root_device (const char *dir)
       free (os_dev);
     }
 
+  /* Check for ZFS.  */
+  if (!os_dev)
+    {
+      char *pool;
+      char *fs;
+
+      grub_find_zpool_from_dir (dir, &pool, &fs);
+
+      if (pool)
+	{
+	  os_dev = xasprintf ("zfs/%s", pool);
+	  free (pool);
+	}
+
+      if (fs)
+	free (fs);
+    }
+
+  if (grub_util_check_nodeless_device (os_dev))
+    /* This kind of abstraction doesn't provide device nodes.  */
+    return os_dev;
+
   if (stat (dir, &st) < 0)
     grub_util_error ("cannot stat `%s'", dir);
 
@@ -884,7 +838,6 @@ grub_util_get_dev_abstraction (const cha
 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
   const char *abs;
   abs = grub_util_get_geom_abstraction (os_dev);
-  grub_util_info ("abstraction of %s is %s", os_dev, abs);
   if (abs && grub_strcasecmp (abs, "eli") == 0)
     return GRUB_DEV_ABSTRACTION_GELI;
 
@@ -893,6 +846,9 @@ grub_util_get_dev_abstraction (const cha
     return GRUB_DEV_ABSTRACTION_LVM;
 #endif
 
+  if (!strncmp (os_dev, "zfs/", sizeof ("zfs/")-1))
+    return GRUB_DEV_ABSTRACTION_ZFS;
+
   /* No abstraction found.  */
   return GRUB_DEV_ABSTRACTION_NONE;
 }
@@ -1107,6 +1063,9 @@ grub_util_pull_device (const char *os_de
 #endif
       return;
 
+    case GRUB_DEV_ABSTRACTION_ZFS:
+      return;
+
     default:  /* GRUB_DEV_ABSTRACTION_NONE */
       grub_util_biosdisk_get_grub_dev (os_dev);
       return;
@@ -1139,6 +1098,12 @@ grub_util_get_grub_dev (const char *os_d
       break;
 #endif
 
+    case GRUB_DEV_ABSTRACTION_ZFS:
+      {
+	grub_dev = xstrdup (os_dev);
+      }
+      break;
+
 #ifdef __linux__
     case GRUB_DEV_ABSTRACTION_LUKS:
       {
@@ -1317,6 +1282,13 @@ grub_util_get_grub_dev (const char *os_d
   return grub_dev;
 }
 
+const int
+grub_util_check_nodeless_device (const char *dev)
+{
+  /* Only ZFS for now.  Btrfs might fit here.  */
+  return ! strncmp (dev, "zfs/", sizeof ("zfs/")-1);
+}
+
 const char *
 grub_util_check_block_device (const char *blk_dev)
 {
@@ -1366,32 +1338,6 @@ get_win32_path (const char *path)
 }
 #endif
 
-#ifdef HAVE_LIBZFS
-static libzfs_handle_t *__libzfs_handle;
-
-static void
-fini_libzfs (void)
-{
-  libzfs_fini (__libzfs_handle);
-}
-
-libzfs_handle_t *
-grub_get_libzfs_handle (void)
-{
-  if (! __libzfs_handle)
-    {
-      __libzfs_handle = libzfs_init ();
-
-      if (__libzfs_handle)
-	atexit (fini_libzfs);
-    }
-
-  return __libzfs_handle;
-}
-#endif /* HAVE_LIBZFS */
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
-/* ZFS has similar problems to those of btrfs (see above).  */
 void
 grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
 {
@@ -1451,7 +1397,6 @@ grub_find_zpool_from_dir (const char *di
   else
     *poolfs = xstrdup ("");
 }
-#endif
 
 /* This function never prints trailing slashes (so that its output
    can be appended a slash unconditionally).  */
@@ -1463,23 +1408,18 @@ grub_make_system_path_relative_to_its_ro
   uintptr_t offset = 0;
   dev_t num;
   size_t len;
-
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
   char *poolfs = NULL;
-#endif
 
   /* canonicalize.  */
   p = canonicalize_file_name (path);
   if (p == NULL)
     grub_util_error ("failed to get canonical path of %s", path);
 
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
   /* For ZFS sub-pool filesystems, could be extended to others (btrfs?).  */
   {
     char *dummy;
     grub_find_zpool_from_dir (p, &dummy, &poolfs);
   }
-#endif
 
   len = strlen (p) + 1;
   buf = xstrdup (p);
@@ -1531,10 +1471,8 @@ grub_make_system_path_relative_to_its_ro
 	      }
 #endif
 	      free (buf2);
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
 	      if (poolfs)
 		return xasprintf ("/%s/@", poolfs);
-#endif
 	      return xstrdup ("");
 	    }
 	  else

=== modified file 'util/grub-probe.c'
--- util/grub-probe.c	2011-08-15 22:30:11 +0000
+++ util/grub-probe.c	2011-10-15 16:42:10 +0000
@@ -144,6 +144,9 @@ probe_abstraction (grub_disk_t disk)
   if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID)
     printf ("lvm ");
 
+  if (disk->dev->id == GRUB_DISK_DEVICE_ZFS_ID)
+    printf ("zfs ");
+
   if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
     grub_util_cryptodisk_print_abstraction (disk);
 
@@ -171,13 +174,16 @@ probe (const char *path, char *device_na
 
   if (path == NULL)
     {
+      if (! grub_util_check_nodeless_device (device_name))
+	{
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
-      if (! grub_util_check_char_device (device_name))
-        grub_util_error ("%s is not a character device", device_name);
+	  if (! grub_util_check_char_device (device_name))
+	    grub_util_error ("%s is not a character device", device_name);
 #else
-      if (! grub_util_check_block_device (device_name))
-        grub_util_error ("%s is not a block device", device_name);
+	  if (! grub_util_check_block_device (device_name))
+	    grub_util_error ("%s is not a block device", device_name);
 #endif
+	}
     }
   else
     {


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

* Re: getroot for ZFS without libzfs?
  2011-10-15 16:59 ` Robert Millan
@ 2011-10-15 17:47   ` Seth Goldberg
  2011-10-16  9:27     ` Robert Millan
  2011-10-15 17:51   ` Seth Goldberg
  2011-10-24 10:01   ` Vladimir 'φ-coder/phcoder' Serbinenko
  2 siblings, 1 reply; 17+ messages in thread
From: Seth Goldberg @ 2011-10-15 17:47 UTC (permalink / raw)
  To: The development of GNU GRUB

Hi,

  Have you tested this with phcoder's experimental zfs branch that has mirroring support?  What is the device node list used for? To list devices that each need grub installed, or for something else?

  --S

On Oct 15, 2011, at 9:59 AM, Robert Millan <rmh@gnu.org> wrote:

> Hi,
> 
> Please test / comment on proof-of-concept attached patch, it gets rid
> of libzfs dependency in GRUB.
> 
> The approach is to implement a disk abstraction, like LVM does, but in
> this case a very simple one (passthrough).  Then grub-probe et al can
> obtain their information from this abstraction layer like they
> currently do with LVM or mdRAID, but they don't need the device node
> list anymore (since it's filled with a full scan, as with LVM).
> 
> -- 
> Robert Millan
> <zfs.diff>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


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

* Re: getroot for ZFS without libzfs?
  2011-10-15 16:59 ` Robert Millan
  2011-10-15 17:47   ` Seth Goldberg
@ 2011-10-15 17:51   ` Seth Goldberg
  2011-10-16  3:18     ` Seth Goldberg
  2011-10-16  9:31     ` Robert Millan
  2011-10-24 10:01   ` Vladimir 'φ-coder/phcoder' Serbinenko
  2 siblings, 2 replies; 17+ messages in thread
From: Seth Goldberg @ 2011-10-15 17:51 UTC (permalink / raw)
  To: The development of GNU GRUB

Hi again,

  Also: can we please retain the liners usage for those platforms that actually have it and that would rather use it?  I can certainly understand the desire to eliminate it for platforms that don't have or don't want to port it, but eliminating it from all platforms is overkill.

  Thanks,
  --S

On Oct 15, 2011, at 9:59 AM, Robert Millan <rmh@gnu.org> wrote:

> Hi,
> 
> Please test / comment on proof-of-concept attached patch, it gets rid
> of libzfs dependency in GRUB.
> 
> The approach is to implement a disk abstraction, like LVM does, but in
> this case a very simple one (passthrough).  Then grub-probe et al can
> obtain their information from this abstraction layer like they
> currently do with LVM or mdRAID, but they don't need the device node
> list anymore (since it's filled with a full scan, as with LVM).
> 
> -- 
> Robert Millan
> <zfs.diff>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel


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

* Re: getroot for ZFS without libzfs?
  2011-10-15 17:51   ` Seth Goldberg
@ 2011-10-16  3:18     ` Seth Goldberg
  2011-10-16  9:31     ` Robert Millan
  1 sibling, 0 replies; 17+ messages in thread
From: Seth Goldberg @ 2011-10-16  3:18 UTC (permalink / raw)
  To: The development of GNU GRUB


On Oct 15, 2011, at 10:51 AM, Seth Goldberg wrote:

> Hi again,
> 
>  Also: can we please retain the liners usage

  Sorry -- that should have read libzfs, not liners.

 --S


> for those platforms that actually have it and that would rather use it?  I can certainly understand the desire to eliminate it for platforms that don't have or don't want to port it, but eliminating it from all platforms is overkill.
> 
>  Thanks,
>  --S
> 
> On Oct 15, 2011, at 9:59 AM, Robert Millan <rmh@gnu.org> wrote:
> 
>> Hi,
>> 
>> Please test / comment on proof-of-concept attached patch, it gets rid
>> of libzfs dependency in GRUB.
>> 
>> The approach is to implement a disk abstraction, like LVM does, but in
>> this case a very simple one (passthrough).  Then grub-probe et al can
>> obtain their information from this abstraction layer like they
>> currently do with LVM or mdRAID, but they don't need the device node
>> list anymore (since it's filled with a full scan, as with LVM).
>> 
>> -- 
>> Robert Millan
>> <zfs.diff>
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> https://lists.gnu.org/mailman/listinfo/grub-devel
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



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

* Re: getroot for ZFS without libzfs?
  2011-10-15 17:47   ` Seth Goldberg
@ 2011-10-16  9:27     ` Robert Millan
  2011-10-16  9:33       ` Robert Millan
  0 siblings, 1 reply; 17+ messages in thread
From: Robert Millan @ 2011-10-16  9:27 UTC (permalink / raw)
  To: The development of GNU GRUB

2011/10/15 Seth Goldberg <seth.goldberg@oracle.com>:
> Hi,
>
>  Have you tested this with phcoder's experimental zfs branch that has mirroring support?

No.  I guess I might have duplicated some work; where's that branch?
I'll try to rebase my patch.

> What is the device node list used for? To list devices that each need grub installed, or for something else?

grub-probe internally needs access to the raw devices because it wants
to use GRUB codepaths to obtain fs_uuid and such.

-- 
Robert Millan


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

* Re: getroot for ZFS without libzfs?
  2011-10-15 17:51   ` Seth Goldberg
  2011-10-16  3:18     ` Seth Goldberg
@ 2011-10-16  9:31     ` Robert Millan
  2011-10-17  2:57       ` Seth Goldberg
  1 sibling, 1 reply; 17+ messages in thread
From: Robert Millan @ 2011-10-16  9:31 UTC (permalink / raw)
  To: The development of GNU GRUB

2011/10/15 Seth Goldberg <seth.goldberg@oracle.com>:
> Hi again,
>
>  Also: can we please retain the libzfs usage for those platforms that actually have it and that would rather use it?

What for?  libzfs is only needed for a single operation (determining
physical device list).  With my patch that operation is no longer
required.

> I can certainly understand the desire to eliminate it for platforms that don't have or don't want to port it, but eliminating it from all platforms is overkill.

It's not a portability problem.  It seems libzfs isn't really meant to
be used externally.  ABI changes without notice, there's no soname
update and no versioning information.  See:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=645305

-- 
Robert Millan


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

* Re: getroot for ZFS without libzfs?
  2011-10-16  9:27     ` Robert Millan
@ 2011-10-16  9:33       ` Robert Millan
  0 siblings, 0 replies; 17+ messages in thread
From: Robert Millan @ 2011-10-16  9:33 UTC (permalink / raw)
  To: The development of GNU GRUB

2011/10/16 Robert Millan <rmh@gnu.org>:
>> What is the device node list used for? To list devices that each need grub installed, or for something else?
>
> grub-probe internally needs access to the raw devices because it wants
> to use GRUB codepaths to obtain fs_uuid and such.

In other words: to use same ZFS codepaths directly on raw device as
they will be used when real GRUB boots.

-- 
Robert Millan


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

* Re: getroot for ZFS without libzfs?
  2011-10-16  9:31     ` Robert Millan
@ 2011-10-17  2:57       ` Seth Goldberg
  0 siblings, 0 replies; 17+ messages in thread
From: Seth Goldberg @ 2011-10-17  2:57 UTC (permalink / raw)
  To: The development of GNU GRUB

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1422 bytes --]



Quoting Robert Millan, who wrote the following on Sun, 16 Oct 2011:

> 2011/10/15 Seth Goldberg <seth.goldberg@oracle.com>:
>> Hi again,
>>
>>  Also: can we please retain the libzfs usage for those platforms that actually have it and that would rather use it?
>
> What for?  libzfs is only needed for a single operation (determining
> physical device list).  With my patch that operation is no longer
> required.

   Ah, ok -- I missed that :).

>
>> I can certainly understand the desire to eliminate it for platforms that don't have or don't want to port it, but eliminating it from all platforms is overkill.
>
> It's not a portability problem.  It seems libzfs isn't really meant to
> be used externally.  ABI changes without notice, there's no soname
> update and no versioning information.  See:
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=645305

   That's true, though in practice there hasn't been much churn.  I like the 
idea of using the code that will be running at boot time anyway to do all 
operations required.  And I really like the abstraction -- I think that's 
what's been missing as a precursor to mirroring support (or raidzX support), 
so thanks for doing the work!

  --S


>
> -- 
> Robert Millan
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel

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

* Re: getroot for ZFS without libzfs?
  2011-10-15 16:59 ` Robert Millan
  2011-10-15 17:47   ` Seth Goldberg
  2011-10-15 17:51   ` Seth Goldberg
@ 2011-10-24 10:01   ` Vladimir 'φ-coder/phcoder' Serbinenko
  2 siblings, 0 replies; 17+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2011-10-24 10:01 UTC (permalink / raw)
  To: grub-devel

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

On 15.10.2011 18:59, Robert Millan wrote:
> Hi,
>
> Please test / comment on proof-of-concept attached patch, it gets rid
> of libzfs dependency in GRUB.
>
It looks like this patch would map all zpools with the same name to the
same device. That's a problem since system may have several
identically-named pools or misdetect a pool somewhere where there is none.
> The approach is to implement a disk abstraction, like LVM does, but in
> this case a very simple one (passthrough).  Then grub-probe et al can
> obtain their information from this abstraction layer like they
> currently do with LVM or mdRAID, but they don't need the device node
> list anymore (since it's filled with a full scan, as with LVM).
>
>
>
> _______________________________________________
> 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 --]

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

end of thread, other threads:[~2011-10-24 10:01 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-08-08  1:28 getroot for ZFS without libzfs? Zachary Bedell
2011-08-09 11:54 ` Robert Millan
2011-08-09 17:34   ` Zachary Bedell
2011-08-10 12:22     ` Robert Millan
2011-08-11  1:04       ` Zachary Bedell
2011-08-12 11:29         ` Robert Millan
2011-08-18 17:05         ` Vladimir 'φ-coder/phcoder' Serbinenko
2011-08-25  5:35           ` Seth Goldberg
2011-10-15 16:59 ` Robert Millan
2011-10-15 17:47   ` Seth Goldberg
2011-10-16  9:27     ` Robert Millan
2011-10-16  9:33       ` Robert Millan
2011-10-15 17:51   ` Seth Goldberg
2011-10-16  3:18     ` Seth Goldberg
2011-10-16  9:31     ` Robert Millan
2011-10-17  2:57       ` Seth Goldberg
2011-10-24 10:01   ` Vladimir 'φ-coder/phcoder' Serbinenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.