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.
This commit is contained in:
parent
8bfe31d82b
commit
c882acc031
4 changed files with 196 additions and 106 deletions
42
ChangeLog
42
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
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>
|
2010-08-01 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
* include/grub/util/libzfs.h (libzfs_init): Set argument list to
|
* include/grub/util/libzfs.h (libzfs_init): Set argument list to
|
||||||
|
@ -39,6 +60,27 @@
|
||||||
|
|
||||||
* kern/misc.c (grub_memset): Optimise to reduce cache stalls.
|
* 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>
|
2010-08-01 Robert Millan <rmh@gnu.org>
|
||||||
|
|
||||||
Prevent accidental use of uninitialized libzfs_handle.
|
Prevent accidental use of uninitialized libzfs_handle.
|
||||||
|
|
|
@ -44,7 +44,13 @@ extern const char *program_name;
|
||||||
void grub_init_all (void);
|
void grub_init_all (void);
|
||||||
void grub_fini_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(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result));
|
||||||
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result));
|
void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result));
|
||||||
|
|
|
@ -49,10 +49,6 @@
|
||||||
# include <grub/util/libnvpair.h>
|
# include <grub/util/libnvpair.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETFSSTAT
|
|
||||||
# include <sys/mount.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/emu/misc.h>
|
#include <grub/emu/misc.h>
|
||||||
|
@ -98,66 +94,6 @@ xgetcwd (void)
|
||||||
return path;
|
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__
|
#ifdef __linux__
|
||||||
|
|
||||||
/* Statting something on a btrfs filesystem always returns a virtual device
|
/* Statting something on a btrfs filesystem always returns a virtual device
|
||||||
|
@ -239,52 +175,20 @@ find_root_device_from_mountinfo (const char *dir)
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||||
|
|
||||||
/* ZFS has similar problems to those of btrfs (see above). */
|
|
||||||
static char *
|
static char *
|
||||||
find_root_device_from_libzfs (const char *dir)
|
find_root_device_from_libzfs (const char *dir)
|
||||||
{
|
{
|
||||||
char *device = NULL;
|
char *device;
|
||||||
char *poolname = NULL;
|
char *poolname;
|
||||||
char *poolfs = NULL;
|
char *poolfs;
|
||||||
char *mnt_point;
|
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)
|
if (! poolname)
|
||||||
return NULL;
|
|
||||||
|
|
||||||
slash = strchr (poolname, '/');
|
|
||||||
if (slash)
|
|
||||||
{
|
{
|
||||||
*slash = '\0';
|
free (mnt_point);
|
||||||
poolfs = slash + 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -317,6 +221,8 @@ find_root_device_from_libzfs (const char *dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
free (poolname);
|
free (poolname);
|
||||||
|
if (poolfs)
|
||||||
|
free (poolfs);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
140
kern/emu/misc.c
140
kern/emu/misc.c
|
@ -19,6 +19,7 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <error.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -44,6 +45,15 @@
|
||||||
# include <libdevmapper.h>
|
# include <libdevmapper.h>
|
||||||
#endif
|
#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;
|
int verbosity;
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -236,6 +246,114 @@ get_win32_path (const char *path)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
/* This function never prints trailing slashes (so that its output
|
||||||
can be appended a slash unconditionally). */
|
can be appended a slash unconditionally). */
|
||||||
char *
|
char *
|
||||||
|
@ -243,16 +361,26 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *p, *buf, *buf2, *buf3;
|
char *p, *buf, *buf2, *buf3;
|
||||||
|
char *mnt_point, *poolname = NULL, *poolfs = NULL, *ret;
|
||||||
uintptr_t offset = 0;
|
uintptr_t offset = 0;
|
||||||
dev_t num;
|
dev_t num;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* canonicalize. */
|
/* canonicalize. */
|
||||||
p = canonicalize_file_name (path);
|
p = canonicalize_file_name (path);
|
||||||
|
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
grub_util_error ("failed to get canonical path of %s", path);
|
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;
|
len = strlen (p) + 1;
|
||||||
buf = xstrdup (p);
|
buf = xstrdup (p);
|
||||||
free (p);
|
free (p);
|
||||||
|
@ -331,7 +459,15 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf3;
|
if (poolfs)
|
||||||
|
{
|
||||||
|
ret = xasprintf ("/%s@%s", poolfs, buf3);
|
||||||
|
free (buf3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = buf3;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DEVICE_MAPPER
|
#ifdef HAVE_DEVICE_MAPPER
|
||||||
|
|
Loading…
Reference in a new issue