This patch is a proof of concept for solving the ZFS "(dev)/foo@/"
pathname problem at the lowest possible level: a small change in
grub_make_system_path_relative_to_its_root() propagates into
all the places in grub-install and grub-mkconfig that are affected
by the problem.

It factors some of the code in my previous patch, so that it can be
reused to extract the zpool filesystem names.

(It still needs some polish like adding function prototypes)

Comments?
=== modified file 'conf/common.rmk'
--- conf/common.rmk	2010-07-06 18:27:55 +0000
+++ conf/common.rmk	2010-07-29 16:06:55 +0000
@@ -78,7 +78,9 @@
 
 # For grub-mkrelpath.
 bin_UTILITIES += grub-mkrelpath
-grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c kern/emu/misc.c
+grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c kern/emu/misc.c \
+	kern/emu/getroot.c kern/emu/hostdisk.c kern/err.c kern/misc.c kern/emu/mm.c \
+	kern/env.c kern/term.c kern/disk.c kern/partition.c
 
 bin_UTILITIES += grub-bin2h
 grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c

=== modified file 'kern/emu/getroot.c'
--- kern/emu/getroot.c	2010-07-29 15:49:20 +0000
+++ kern/emu/getroot.c	2010-07-29 16:15:27 +0000
@@ -97,7 +97,7 @@
   return path;
 }
 
-static char *
+char *
 find_mount_point_from_dir (const char *dir)
 {
   struct stat st;
@@ -236,16 +236,12 @@
 #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
 
 /* ZFS has similar problems to those of btrfs (see above).  */
-static char *
-find_root_device_from_libzfs (const char *dir)
+
+void
+find_zpool_from_mount_point (const char *mnt_point, char **poolname, char **poolfs)
 {
-  char *device;
-  char *poolname = NULL;
-  char *poolfs = NULL;
-  char *mnt_point;
   char *slash;
-
-  mnt_point = find_mount_point_from_dir (dir);
+  *poolname = *poolfs = NULL;
 
 #ifdef HAVE_GETFSSTAT
   {
@@ -264,7 +260,7 @@
       if (!strcmp (mnt[i].f_fstypename, "zfs")
 	  && !strcmp (mnt[i].f_mntonname, mnt_point))
 	{
-	  poolname = xstrdup (mnt[i].f_mntfromname);
+	  *poolname = xstrdup (mnt[i].f_mntfromname);
 	  break;
 	}
 
@@ -272,14 +268,33 @@
   }
 #endif
 
+  if (! *poolname)
+    return;
+
+  slash = strchr (*poolname, '/');
+  if (slash)
+    {
+      *slash = '\0';
+      *poolfs = xstrdup (slash + 1);
+    }
+  else
+    *poolfs = xstrdup ("");
+}
+
+static char *
+find_root_device_from_libzfs (const char *dir)
+{
+  char *device;
+  char *poolname;
+  char *poolfs;
+  char *mnt_point;
+
+  mnt_point = find_mount_point_from_dir (dir);
+  find_zpool_from_mount_point (mnt_point, &poolname, &poolfs);
   if (! poolname)
-    return NULL;
-
-  slash = strchr (poolname, '/');
-  if (slash)
     {
-      *slash = '\0';
-      poolfs = slash + 1;
+      free (mnt_point);
+      return NULL;
     }
 
   {
@@ -300,6 +315,8 @@
   }
 
   free (poolname);
+  if (poolfs)
+    free (poolfs);
 
   return device;
 }

=== modified file 'kern/emu/misc.c'
--- kern/emu/misc.c	2010-06-07 21:41:55 +0000
+++ kern/emu/misc.c	2010-07-29 16:14:02 +0000
@@ -225,16 +225,24 @@
 {
   struct stat st;
   char *p, *buf, *buf2, *buf3;
+  char *mnt_point, *poolname = NULL, *poolfs = NULL, *ret;
   uintptr_t offset = 0;
   dev_t num;
   size_t len;
 
   /* canonicalize.  */
   p = canonicalize_file_name (path);
-
   if (p == NULL)
     grub_util_error ("failed to get canonical path of %s", path);
 
+  /* For ZFS sub-pool filesystems, could be extended to others (btrfs?).  */
+  mnt_point = find_mount_point_from_dir (p);
+  if (mnt_point)
+    {
+      find_zpool_from_mount_point (mnt_point, &poolname, &poolfs);
+      free (mnt_point);
+    }
+
   len = strlen (p) + 1;
   buf = xstrdup (p);
   free (p);
@@ -313,7 +321,15 @@
       len--;
     }
 
-  return buf3;
+  if (poolfs)
+    {
+      ret = xasprintf ("/%...@%s", poolfs, buf3);
+      free (buf3);
+    }
+  else
+    ret = buf3;
+
+  return ret;
 }
 
 #ifdef HAVE_DEVICE_MAPPER

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to