+2010-08-01 Robert Millan <rmh@gnu.org>
+
+ * include/grub/emu/misc.h (grub_find_mount_point_from_dir)
+ (grub_find_zpool_from_mount_point): New function prototypes.
+
+ * kern/emu/getroot.c [HAVE_GETFSSTAT]: Move `<sys/mount.h>' to ...
+ * kern/emu/misc.c [HAVE_GETFSSTAT]: ... here.
+
+ * kern/emu/getroot.c (find_mount_point_from_dir): Move to ...
+ * kern/emu/misc.c (grub_find_mount_point_from_dir): ... this. Remove
+ `static' attribute.
+
+ * kern/emu/getroot.c (find_root_device_from_libzfs): Split code for
+ finding zpool from mount point into ...
+ * kern/emu/misc.c (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 `/fsname@path' syntax.
+
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
* include/grub/util/libzfs.h (libzfs_init): Set argument list to
* kern/misc.c (grub_memset): Optimise to reduce cache stalls.
+2010-08-01 Robert Millan <rmh@gnu.org>
+
+ * include/grub/emu/misc.h (grub_find_mount_point_from_dir)
+ (grub_find_zpool_from_mount_point): New function prototypes.
+
+ * kern/emu/getroot.c [HAVE_GETFSSTAT]: Move `<sys/mount.h>' to ...
+ * kern/emu/misc.c [HAVE_GETFSSTAT]: ... here.
+
+ * kern/emu/getroot.c (find_mount_point_from_dir): Move to ...
+ * kern/emu/misc.c (grub_find_mount_point_from_dir): ... this. Remove
+ `static' attribute.
+
+ * kern/emu/getroot.c (find_root_device_from_libzfs): Split code for
+ finding zpool from mount point into ...
+ * kern/emu/misc.c (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 `/fsname@path' syntax.
+
2010-08-01 Robert Millan <rmh@gnu.org>
Prevent accidental use of uninitialized libzfs_handle.
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));
+void grub_find_zpool_from_mount_point (const char *mnt_point,
+ char **poolname, char **poolfs);
+
+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));
# include <grub/util/libnvpair.h>
#endif
-#ifdef HAVE_GETFSSTAT
-# include <sys/mount.h>
-#endif
-
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/emu/misc.h>
return path;
}
-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
-
-static char *
-find_mount_point_from_dir (const char *dir)
-{
- struct stat st;
- typeof (st.st_dev) fs;
- char *prev, *next, *slash, *statdir;
-
- if (stat (dir, &st) == -1)
- error (1, errno, "stat (%s)", dir);
-
- fs = st.st_dev;
-
- prev = xstrdup (dir);
-
- while (1)
- {
- /* Remove last slash. */
- next = xstrdup (prev);
- slash = strrchr (next, '/');
- if (! slash)
- {
- free (next);
- free (prev);
- return NULL;
- }
- *slash = '\0';
-
- /* A next empty string counts as /. */
- if (next[0] == '\0')
- statdir = "/";
- else
- statdir = next;
-
- if (stat (statdir, &st) == -1)
- error (1, errno, "stat (%s)", next);
-
- if (st.st_dev != fs)
- {
- /* Found mount point. */
- free (next);
- return prev;
- }
-
- free (prev);
- prev = next;
-
- /* We've already seen an empty string, which means we
- reached /. Nothing left to do. */
- if (prev[0] == '\0')
- {
- free (prev);
- return xstrdup ("/");
- }
- }
-}
-
-#endif
-
#ifdef __linux__
/* Statting something on a btrfs filesystem always returns a virtual device
#endif /* __linux__ */
#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)
{
- char *device = NULL;
- char *poolname = NULL;
- char *poolfs = NULL;
+ char *device;
+ char *poolname;
+ char *poolfs;
char *mnt_point;
- char *slash;
-
- mnt_point = find_mount_point_from_dir (dir);
-
-#ifdef HAVE_GETFSSTAT
- {
- int mnt_count = getfsstat (NULL, 0, MNT_WAIT);
- if (mnt_count == -1)
- error (1, errno, "getfsstat");
-
- struct statfs *mnt = xmalloc (mnt_count * sizeof (*mnt));
-
- mnt_count = getfsstat (mnt, mnt_count * sizeof (*mnt), MNT_WAIT);
- if (mnt_count == -1)
- error (1, errno, "getfsstat");
-
- unsigned int i;
- for (i = 0; i < (unsigned) mnt_count; i++)
- if (!strcmp (mnt[i].f_fstypename, "zfs")
- && !strcmp (mnt[i].f_mntonname, mnt_point))
- {
- poolname = xstrdup (mnt[i].f_mntfromname);
- break;
- }
-
- free (mnt);
- }
-#endif
+ mnt_point = grub_find_mount_point_from_dir (dir);
+ grub_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;
}
{
}
free (poolname);
+ if (poolfs)
+ free (poolfs);
return device;
}
#include <config.h>
#include <errno.h>
+#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
# include <libdevmapper.h>
#endif
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+# include <grub/util/libzfs.h>
+# include <grub/util/libnvpair.h>
+#endif
+
+#ifdef HAVE_GETFSSTAT
+# include <sys/mount.h>
+#endif
+
int verbosity;
void
}
#endif
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+/* Not ZFS-specific in itself, but for now it's only used by ZFS-related code. */
+char *
+grub_find_mount_point_from_dir (const char *dir)
+{
+ struct stat st;
+ typeof (st.st_dev) fs;
+ char *prev, *next, *slash, *statdir;
+
+ if (stat (dir, &st) == -1)
+ error (1, errno, "stat (%s)", dir);
+
+ fs = st.st_dev;
+
+ prev = xstrdup (dir);
+
+ while (1)
+ {
+ /* Remove last slash. */
+ next = xstrdup (prev);
+ slash = strrchr (next, '/');
+ if (! slash)
+ {
+ free (next);
+ free (prev);
+ return NULL;
+ }
+ *slash = '\0';
+
+ /* A next empty string counts as /. */
+ if (next[0] == '\0')
+ statdir = "/";
+ else
+ statdir = next;
+
+ if (stat (statdir, &st) == -1)
+ error (1, errno, "stat (%s)", next);
+
+ if (st.st_dev != fs)
+ {
+ /* Found mount point. */
+ free (next);
+ return prev;
+ }
+
+ free (prev);
+ prev = next;
+
+ /* We've already seen an empty string, which means we
+ reached /. Nothing left to do. */
+ if (prev[0] == '\0')
+ {
+ free (prev);
+ return xstrdup ("/");
+ }
+ }
+}
+#endif
+
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+
+/* ZFS has similar problems to those of btrfs (see above). */
+void
+grub_find_zpool_from_mount_point (const char *mnt_point, char **poolname, char **poolfs)
+{
+ char *slash;
+
+ *poolname = *poolfs = NULL;
+
+#ifdef HAVE_GETFSSTAT
+ {
+ int mnt_count = getfsstat (NULL, 0, MNT_WAIT);
+ if (mnt_count == -1)
+ error (1, errno, "getfsstat");
+
+ struct statfs *mnt = xmalloc (mnt_count * sizeof (*mnt));
+
+ mnt_count = getfsstat (mnt, mnt_count * sizeof (*mnt), MNT_WAIT);
+ if (mnt_count == -1)
+ error (1, errno, "getfsstat");
+
+ unsigned int i;
+ for (i = 0; i < (unsigned) mnt_count; i++)
+ if (!strcmp (mnt[i].f_fstypename, "zfs")
+ && !strcmp (mnt[i].f_mntonname, mnt_point))
+ {
+ *poolname = xstrdup (mnt[i].f_mntfromname);
+ break;
+ }
+
+ free (mnt);
+ }
+#endif
+
+ if (! *poolname)
+ return;
+
+ slash = strchr (*poolname, '/');
+ if (slash)
+ {
+ *slash = '\0';
+ *poolfs = xstrdup (slash + 1);
+ }
+ else
+ *poolfs = xstrdup ("");
+}
+#endif
+
/* This function never prints trailing slashes (so that its output
can be appended a slash unconditionally). */
char *
{
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);
+#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
+ /* 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);
+ }
+#endif
+
len = strlen (p) + 1;
buf = xstrdup (p);
free (p);
len--;
}
- return buf3;
+ if (poolfs)
+ {
+ ret = xasprintf ("/%s@%s", poolfs, buf3);
+ free (buf3);
+ }
+ else
+ ret = buf3;
+
+ return ret;
}
#ifdef HAVE_DEVICE_MAPPER