2010-07-30 Robert Millan * conf/common.rmk (grub_mkrelpath_SOURCES): Add 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. * include/grub/emu/misc.h (grub_find_mount_point_from_dir) (grub_find_zpool_from_mount_point): New function prototypes. * kern/emu/getroot.c (find_mount_point_from_dir): Rename to ... (grub_find_mount_point_from_dir): ... this. Remove `static' attribute. (find_root_device_from_libzfs): Split code for finding zpool from mount point into ... (grub_find_zpool_from_mount_point): ... this. * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): When requested path is part of a ZFS pool, use grub_find_zpool_from_mount_point() to detect its filesystem name, and generate a path with `/address@hidden' syntax. === modified file 'conf/common.rmk' --- conf/common.rmk 2010-07-06 18:27:55 +0000 +++ conf/common.rmk 2010-07-30 21:11:07 +0000 @@ -78,7 +78,9 @@ endif # 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 'include/grub/emu/misc.h' --- include/grub/emu/misc.h 2010-07-30 20:01:10 +0000 +++ include/grub/emu/misc.h 2010-07-30 21:11:07 +0000 @@ -44,7 +44,14 @@ extern const char *program_name; void grub_init_all (void); void grub_fini_all (void); -char *grub_make_system_path_relative_to_its_root (const char *path) __attribute__ ((warn_unused_result)); +char *grub_find_mount_point_from_dir (const char *dir) + __attribute__ ((warn_unused_result)); +char *grub_find_zpool_from_mount_point (const char *mnt_point, + char **poolname, char **poolfs) + __attribute__ ((warn_unused_result)); + +char *grub_make_system_path_relative_to_its_root (const char *path) + __attribute__ ((warn_unused_result)); void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result)); void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result)); === modified file 'kern/emu/getroot.c' --- kern/emu/getroot.c 2010-07-30 19:43:12 +0000 +++ kern/emu/getroot.c 2010-07-30 21:11:07 +0000 @@ -97,8 +97,8 @@ xgetcwd (void) return path; } -static char * -find_mount_point_from_dir (const char *dir) +char * +grub_find_mount_point_from_dir (const char *dir) { struct stat st; typeof (st.st_dev) fs; @@ -236,16 +236,12 @@ find_root_device_from_mountinfo (const c #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 +grub_find_zpool_from_mount_point (const char *mnt_point, char **poolname, char **poolfs) { - char *device = NULL; - 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 @@ find_root_device_from_libzfs (const char 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 @@ find_root_device_from_libzfs (const char } #endif - if (! poolname) - return NULL; + if (! *poolname) + return; - slash = strchr (poolname, '/'); + slash = strchr (*poolname, '/'); if (slash) { *slash = '\0'; - poolfs = slash + 1; + *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 = grub_find_mount_point_from_dir (dir); + grub_find_zpool_from_mount_point (mnt_point, &poolname, &poolfs); + if (! poolname) + { + free (mnt_point); + return NULL; } { @@ -310,6 +325,8 @@ find_root_device_from_libzfs (const char } 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-30 21:11:07 +0000 @@ -225,16 +225,24 @@ grub_make_system_path_relative_to_its_ro { 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 = grub_find_mount_point_from_dir (p); + if (mnt_point) + { + grub_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 @@ grub_make_system_path_relative_to_its_ro len--; } - return buf3; + if (poolfs) + { + ret = xasprintf ("/address@hidden", poolfs, buf3); + free (buf3); + } + else + ret = buf3; + + return ret; } #ifdef HAVE_DEVICE_MAPPER