mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-11-04 01:35:53 +00:00 
			
		
		
		
	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
					
				
							
								
								
									
										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>
 | 
			
		||||
 | 
			
		||||
	* 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.
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
@ -44,7 +44,13 @@ 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));
 | 
			
		||||
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));
 | 
			
		||||
 | 
			
		||||
@ -49,10 +49,6 @@
 | 
			
		||||
# 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>
 | 
			
		||||
@ -98,66 +94,6 @@ xgetcwd (void)
 | 
			
		||||
  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
 | 
			
		||||
@ -239,52 +175,20 @@ find_root_device_from_mountinfo (const char *dir)
 | 
			
		||||
#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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
@ -317,6 +221,8 @@ find_root_device_from_libzfs (const char *dir)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  free (poolname);
 | 
			
		||||
  if (poolfs)
 | 
			
		||||
    free (poolfs);
 | 
			
		||||
 | 
			
		||||
  return device;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										140
									
								
								kern/emu/misc.c
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								kern/emu/misc.c
									
									
									
									
									
								
							@ -19,6 +19,7 @@
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <error.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
@ -44,6 +45,15 @@
 | 
			
		||||
# 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
 | 
			
		||||
@ -236,6 +246,114 @@ get_win32_path (const char *path)
 | 
			
		||||
}
 | 
			
		||||
#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 *
 | 
			
		||||
@ -243,16 +361,26 @@ grub_make_system_path_relative_to_its_root (const char *path)
 | 
			
		||||
{
 | 
			
		||||
  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);
 | 
			
		||||
@ -331,7 +459,15 @@ grub_make_system_path_relative_to_its_root (const char *path)
 | 
			
		||||
      len--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return buf3;
 | 
			
		||||
  if (poolfs)
 | 
			
		||||
    {
 | 
			
		||||
      ret = xasprintf ("/%s@%s", poolfs, buf3);
 | 
			
		||||
      free (buf3);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    ret = buf3;
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_DEVICE_MAPPER
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user