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