From a9600892c190269c25613fede79892a17f0490e0 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 22 Jul 2010 09:38:06 +0100 Subject: [PATCH 01/29] * disk/raid.c (insert_array): Don't count named arrays when looking for unused array numbers. Reported and tested by: maru. --- ChangeLog | 6 ++++++ disk/raid.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c05891b96..e3677b0e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-07-22 Colin Watson + + * disk/raid.c (insert_array): Don't count named arrays when looking + for unused array numbers. + Reported and tested by: maru. + 2010-07-20 Colin Watson * bus/usb/emu/usb.c (grub_usb_poll_devices): Add a dummy diff --git a/disk/raid.c b/disk/raid.c index 43d2a29ff..7dfd4bd81 100644 --- a/disk/raid.c +++ b/disk/raid.c @@ -533,7 +533,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, /* Check whether we don't have multiple arrays with the same number. */ for (p = array_list; p != NULL; p = p->next) { - if (p->number == array->number) + if (! p->name && p->number == array->number) break; } @@ -546,7 +546,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, { for (p = array_list; p != NULL; p = p->next) { - if (p->number == i) + if (! p->name && p->number == i) break; } From 697e053c44e75734ad4ae7520e63a80a83df4059 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 22 Jul 2010 09:44:19 +0100 Subject: [PATCH 02/29] real name for Michael Guntsche --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e3677b0e2..e0c2096bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,7 +2,7 @@ * disk/raid.c (insert_array): Don't count named arrays when looking for unused array numbers. - Reported and tested by: maru. + Reported and tested by: Michael Guntsche. 2010-07-20 Colin Watson From 0ac33bf5eb13bd185c903ac29a3ec36f0502c74f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 21 Jul 2010 06:44:38 +0200 Subject: [PATCH 03/29] * util/grub.d/00_header.in: Remove compatibility with terminal.mod prior to terminal_input/terminal_output separation. It's been over 1.5 years and those versions weren't widely deployed. --- ChangeLog | 6 ++++++ util/grub.d/00_header.in | 12 ++---------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index e0c2096bb..de1edebb1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -29,6 +29,12 @@ (grub_efi_console_fini): New function. (grub_console_term_output): Register init and fini methods. +2010-07-20 Vladimir Serbinenko + + * util/grub.d/00_header.in: Remove compatibility with terminal.mod + prior to terminal_input/terminal_output separation. It's been over 1.5 + years and those versions weren't widely deployed. + 2010-07-20 Vladimir Serbinenko * tests/util/grub-shell-tester.in: Remove bashism and declare as diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 75c8b0fa2..2f39650e9 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -137,11 +137,7 @@ case x${GRUB_TERMINAL_INPUT} in ;; x*) cat << EOF -if terminal_input ${GRUB_TERMINAL_INPUT} ; then true ; else - # For backward compatibility with versions of terminal.mod that don't - # understand terminal_input - terminal ${GRUB_TERMINAL_INPUT} -fi +terminal_input ${GRUB_TERMINAL_INPUT} EOF ;; esac @@ -152,11 +148,7 @@ case x${GRUB_TERMINAL_OUTPUT} in ;; x*) cat << EOF -if terminal_output ${GRUB_TERMINAL_OUTPUT} ; then true ; else - # For backward compatibility with versions of terminal.mod that don't - # understand terminal_output - terminal ${GRUB_TERMINAL_OUTPUT} -fi +terminal_output ${GRUB_TERMINAL_OUTPUT} EOF ;; esac From 463711215f2420d12fad9b45d9a02b8a01668651 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 28 Jul 2010 18:25:48 +0300 Subject: [PATCH 04/29] * util/ieee1275/grub-install.in: Don't use empty grub_device. Reported by: Lennart Sorensen. --- ChangeLog | 17 +++++++++++------ util/ieee1275/grub-install.in | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index de1edebb1..a2b6a2bc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-07-28 Vladimir Serbinenko + + * util/ieee1275/grub-install.in: Don't use empty grub_device. + Reported by: Lennart Sorensen. + +2010-07-20 Vladimir Serbinenko + + * util/grub.d/00_header.in: Remove compatibility with terminal.mod + prior to terminal_input/terminal_output separation. It's been over 1.5 + years and those versions weren't widely deployed. + 2010-07-22 Colin Watson * disk/raid.c (insert_array): Don't count named arrays when looking @@ -29,12 +40,6 @@ (grub_efi_console_fini): New function. (grub_console_term_output): Register init and fini methods. -2010-07-20 Vladimir Serbinenko - - * util/grub.d/00_header.in: Remove compatibility with terminal.mod - prior to terminal_input/terminal_output separation. It's been over 1.5 - years and those versions weren't widely deployed. - 2010-07-20 Vladimir Serbinenko * tests/util/grub-shell-tester.in: Remove bashism and declare as diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in index 98fd5d65a..98de5f348 100644 --- a/util/ieee1275/grub-install.in +++ b/util/ieee1275/grub-install.in @@ -212,7 +212,7 @@ fi # this command is allowed to fail (--target=fs already grants us that the # filesystem will be accessible). partmap_module= -for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do +for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do partmap_module="$partmap_module part_$x"; done From 9f841f5cbfcdf52cb7a5e0f51e5239466f6fd67f Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Thu, 29 Jul 2010 15:06:39 +0200 Subject: [PATCH 05/29] 2010-07-29 Robert Millan * configure.ac: Remove grub-mkisofs checks. --- ChangeLog | 4 ++++ configure.ac | 7 ------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2b6a2bc1..af48d4039 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-07-29 Robert Millan + + * configure.ac: Remove grub-mkisofs checks. + 2010-07-28 Vladimir Serbinenko * util/ieee1275/grub-install.in: Don't use empty grub_device. diff --git a/configure.ac b/configure.ac index 55c2625cb..aa7f3a151 100644 --- a/configure.ac +++ b/configure.ac @@ -249,13 +249,6 @@ fi # Check for functions. AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) -# For grub-mkisofs -AC_HEADER_MAJOR -AC_HEADER_DIRENT -AC_CHECK_FUNCS(memmove sbrk strdup lstat getuid getgid) -AC_CHECK_HEADERS(sys/mkdev.h sys/sysmacros.h malloc.h termios.h sys/types.h) -AC_CHECK_HEADERS(unistd.h string.h strings.h sys/stat.h sys/fcntl.h limits.h) - # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. AC_CHECK_HEADER([util.h], [ From 0806b63c0964c456e667415a1d8d3fa8521ac14b Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Thu, 29 Jul 2010 18:46:42 +0200 Subject: [PATCH 06/29] 2010-07-29 Robert Millan * util/grub-probe.c (PRINT_FS_LABEL): New enum value. (probe): Handle `PRINT_FS_LABEL'. (main): Handle `-t fs_label'. --- ChangeLog | 6 ++++++ util/grub-probe.c | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index af48d4039..94b6741d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-07-29 Robert Millan + + * util/grub-probe.c (PRINT_FS_LABEL): New enum value. + (probe): Handle `PRINT_FS_LABEL'. + (main): Handle `-t fs_label'. + 2010-07-29 Robert Millan * configure.ac: Remove grub-mkisofs checks. diff --git a/util/grub-probe.c b/util/grub-probe.c index dff87907a..56cbc5592 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -50,6 +50,7 @@ enum { PRINT_FS, PRINT_FS_UUID, + PRINT_FS_LABEL, PRINT_DRIVE, PRINT_DEVICE, PRINT_PARTMAP, @@ -291,6 +292,16 @@ probe (const char *path, char *device_name) printf ("%s\n", uuid); } + else if (print == PRINT_FS_LABEL) + { + char *label; + if (! fs->label) + grub_util_error ("%s does not support labels", fs->name); + + fs->label (dev, &label); + + printf ("%s\n", label); + } end: if (dev) @@ -326,7 +337,7 @@ Probe device information for a given path (or device, if the -d option is given) \n\ -d, --device given argument is a system device, not a path\n\ -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -t, --target=(fs|fs_uuid|drive|device|partmap|abstraction)\n\ + -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction)\n\ print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ @@ -375,6 +386,8 @@ main (int argc, char *argv[]) print = PRINT_FS; else if (!strcmp (optarg, "fs_uuid")) print = PRINT_FS_UUID; + else if (!strcmp (optarg, "fs_label")) + print = PRINT_FS_LABEL; else if (!strcmp (optarg, "drive")) print = PRINT_DRIVE; else if (!strcmp (optarg, "device")) From f7790cdd5d0b97b2246478ec15efb25898fbb253 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 30 Jul 2010 11:27:02 +0200 Subject: [PATCH 07/29] 2010-07-30 Robert Millan * include/grub/emu/misc.h (grub_make_system_path_relative_to_its_root) (xmalloc, xrealloc, xstrdup, xasprintf): Add `warn_unused_result' attribute. * include/grub/misc.h (grub_strdup, grub_strndup, grub_strlen) (grub_xasprintf, grub_xvasprintf): Likewise. * include/grub/emu/misc.h (xasprintf): Remove duplicate prototype. --- ChangeLog | 9 +++++++++ include/grub/emu/misc.h | 11 +++++------ include/grub/misc.h | 10 +++++----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 94b6741d3..4026428a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-07-30 Robert Millan + + * include/grub/emu/misc.h (grub_make_system_path_relative_to_its_root) + (xmalloc, xrealloc, xstrdup, xasprintf): Add + `warn_unused_result' attribute. + * include/grub/misc.h (grub_strdup, grub_strndup, grub_strlen) + (grub_xasprintf, grub_xvasprintf): Likewise. + * include/grub/emu/misc.h (xasprintf): Remove duplicate prototype. + 2010-07-29 Robert Millan * util/grub-probe.c (PRINT_FS_LABEL): New enum value. diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index f34cd4287..07257e511 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -26,12 +26,12 @@ 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); +char *grub_make_system_path_relative_to_its_root (const char *path) __attribute__ ((warn_unused_result)); -void * EXPORT_FUNC(xmalloc) (grub_size_t size); -void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size); -char * EXPORT_FUNC(xstrdup) (const char *str); -char * EXPORT_FUNC(xasprintf) (const char *fmt, ...); +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)); +char * EXPORT_FUNC(xstrdup) (const char *str) __attribute__ ((warn_unused_result)); +char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((warn_unused_result)); void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...); void EXPORT_FUNC(grub_util_info) (const char *fmt, ...); @@ -45,7 +45,6 @@ int EXPORT_FUNC(vasprintf) (char **buf, const char *fmt, va_list ap); int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...); #endif -char * EXPORT_FUNC(xasprintf) (const char *fmt, ...); extern char * canonicalize_file_name (const char *path); #ifdef HAVE_DEVICE_MAPPER diff --git a/include/grub/misc.h b/include/grub/misc.h index 9194ca8ad..eab01b0fb 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -231,10 +231,10 @@ grub_strtol (const char *str, char **end, int base) } } -char *EXPORT_FUNC(grub_strdup) (const char *s); -char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n); +char *EXPORT_FUNC(grub_strdup) (const char *s) __attribute__ ((warn_unused_result)); +char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n) __attribute__ ((warn_unused_result)); void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n); -grub_size_t EXPORT_FUNC(grub_strlen) (const char *s); +grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) __attribute__ ((warn_unused_result)); int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); @@ -261,8 +261,8 @@ int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...) int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt, va_list args); char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); -char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args); + __attribute__ ((format (printf, 1, 2))) __attribute__ ((warn_unused_result)); +char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args) __attribute__ ((warn_unused_result)); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, From a184f9c80105bafacccbfaea596d406db3bce362 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 30 Jul 2010 21:43:12 +0200 Subject: [PATCH 08/29] 2010-07-30 Robert Millan Enable `grub-probe -t device' resolution on ZFS. * configure.ac: Check for getfsstat(), libzfs and libnvpair. * include/grub/util/libnvpair.h: New file. * include/grub/util/libzfs.h: New file. * kern/emu/getroot.c: Include `' and `'. [HAVE_LIBZFS && HAVE_LIBNVPAIR]: Include `' and `'. [HAVE_GETFSSTAT]: Include `'. (find_mount_point_from_dir): New static function. [HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_root_device_from_libzfs): New function. [HAVE_LIBZFS && HAVE_LIBNVPAIR] (grub_guess_root_device): Use find_root_device_from_libzfs() before ressorting to find_root_device(). * include/grub/util/misc.h (grub_util_init_libzfs): New function prototype. * util/misc.c: Include `'. (grub_util_init_libzfs): New function. [HAVE_LIBZFS] (libzfs_handle): New global variable. [HAVE_LIBZFS] (fini_libzfs): New static function. (grub_util_init_libzfs): New function. * util/grub-probe.c (main): Call grub_util_init_libzfs(). --- ChangeLog | 28 ++++++ configure.ac | 11 ++- include/grub/util/libnvpair.h | 31 +++++++ include/grub/util/libzfs.h | 39 +++++++++ include/grub/util/misc.h | 1 + kern/emu/getroot.c | 155 ++++++++++++++++++++++++++++++++++ util/grub-probe.c | 1 + util/misc.c | 20 +++++ 8 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 include/grub/util/libnvpair.h create mode 100644 include/grub/util/libzfs.h diff --git a/ChangeLog b/ChangeLog index 4026428a7..041f9cadd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2010-07-30 Robert Millan + + Enable `grub-probe -t device' resolution on ZFS. + + * configure.ac: Check for getfsstat(), libzfs and libnvpair. + * include/grub/util/libnvpair.h: New file. + * include/grub/util/libzfs.h: New file. + + * kern/emu/getroot.c: Include `' and `'. + [HAVE_LIBZFS && HAVE_LIBNVPAIR]: Include `' and + `'. + [HAVE_GETFSSTAT]: Include `'. + + (find_mount_point_from_dir): New static function. + [HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_root_device_from_libzfs): New + function. + [HAVE_LIBZFS && HAVE_LIBNVPAIR] (grub_guess_root_device): Use + find_root_device_from_libzfs() before ressorting to find_root_device(). + + * include/grub/util/misc.h (grub_util_init_libzfs): New function + prototype. + * util/misc.c: Include `'. + (grub_util_init_libzfs): New function. + [HAVE_LIBZFS] (libzfs_handle): New global variable. + [HAVE_LIBZFS] (fini_libzfs): New static function. + (grub_util_init_libzfs): New function. + * util/grub-probe.c (main): Call grub_util_init_libzfs(). + 2010-07-30 Robert Millan * include/grub/emu/misc.h (grub_make_system_path_relative_to_its_root) diff --git a/configure.ac b/configure.ac index aa7f3a151..cc97c7f77 100644 --- a/configure.ac +++ b/configure.ac @@ -247,7 +247,7 @@ else fi # Check for functions. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) +AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat) # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. @@ -799,6 +799,15 @@ if test x"$device_mapper_excuse" = x ; then [device_mapper_excuse="need devmapper library"]) fi +AC_CHECK_LIB([zfs], [libzfs_init], + [LDFLAGS="$LDFLAGS -lzfs" + AC_DEFINE([HAVE_LIBZFS], [1], + [Define to 1 if you have the ZFS library.])],) +AC_CHECK_LIB([nvpair], [nvlist_print], + [LDFLAGS="$LDFLAGS -lnvpair" + AC_DEFINE([HAVE_LIBNVPAIR], [1], + [Define to 1 if you have the NVPAIR library.])],) + AC_SUBST(ASFLAGS) # Output files. diff --git a/include/grub/util/libnvpair.h b/include/grub/util/libnvpair.h new file mode 100644 index 000000000..c4fe174ea --- /dev/null +++ b/include/grub/util/libnvpair.h @@ -0,0 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_LIBNVPAIR_UTIL_HEADER +#define GRUB_LIBNVPAIR_UTIL_HEADER 1 + +#include /* FILE */ + +typedef void nvlist_t; + +int nvlist_lookup_string (nvlist_t *, const char *, char **); +int nvlist_lookup_nvlist (nvlist_t *, const char *, nvlist_t **); +int nvlist_lookup_nvlist_array (nvlist_t *, const char *, nvlist_t ***, unsigned int *); +void nvlist_print (FILE *, nvlist_t *); + +#endif diff --git a/include/grub/util/libzfs.h b/include/grub/util/libzfs.h new file mode 100644 index 000000000..a17c47e20 --- /dev/null +++ b/include/grub/util/libzfs.h @@ -0,0 +1,39 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_LIBZFS_UTIL_HEADER +#define GRUB_LIBZFS_UTIL_HEADER 1 + +#include + +typedef void libzfs_handle_t; +typedef void zpool_handle_t; + +extern libzfs_handle_t *libzfs_init (); +extern void libzfs_fini (libzfs_handle_t *); + +extern zpool_handle_t *zpool_open (libzfs_handle_t *, const char *); +extern void zpool_close (zpool_handle_t *); + +extern int zpool_get_physpath (zpool_handle_t *, const char *); + +extern nvlist_t *zpool_get_config (zpool_handle_t *, nvlist_t **); + +extern libzfs_handle_t *libzfs_handle; + +#endif diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 48dfbb868..699b9cf2c 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -59,5 +59,6 @@ char *make_system_path_relative_to_its_root (const char *path); char *canonicalize_file_name (const char *path); void grub_util_init_nls (void); +void grub_util_init_libzfs (void); #endif /* ! GRUB_UTIL_MISC_HEADER */ diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index 58dbac9b4..f2f6311ff 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -20,11 +20,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -41,6 +43,15 @@ # include #endif +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) +# include +# include +#endif + +#ifdef HAVE_GETFSSTAT +# include +#endif + #include #include #include @@ -86,6 +97,62 @@ xgetcwd (void) return path; } +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 ("/"); + } + } +} + #ifdef __linux__ /* Statting something on a btrfs filesystem always returns a virtual device @@ -166,6 +233,88 @@ 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 *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 + + if (! poolname) + return NULL; + + slash = strchr (poolname, '/'); + if (slash) + { + *slash = '\0'; + poolfs = slash + 1; + } + + { + zpool_handle_t *zpool; + nvlist_t *nvlist; + nvlist_t **nvlist_array; + unsigned int nvlist_count; + + zpool = zpool_open (libzfs_handle, poolname); + nvlist = zpool_get_config (zpool, NULL); + + if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0) + error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")"); + + if (nvlist_lookup_nvlist_array (nvlist, "children", &nvlist_array, &nvlist_count) != 0) + error (1, errno, "nvlist_lookup_nvlist_array (\"children\")"); + + do + { + assert (nvlist_count > 0); + } while (nvlist_lookup_nvlist_array (nvlist_array[0], "children", + &nvlist_array, &nvlist_count) == 0); + + if (nvlist_lookup_string (nvlist_array[0], "path", &device) != 0) + error (1, errno, "nvlist_lookup_string (\"path\")"); + + zpool_close (zpool); + } + + free (poolname); + + return device; +} +#endif + #ifdef __MINGW32__ static char * @@ -458,6 +607,12 @@ grub_guess_root_device (const char *dir) return os_dev; #endif /* __linux__ */ +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + os_dev = find_root_device_from_libzfs (dir); + if (os_dev) + return os_dev; +#endif + if (stat (dir, &st) < 0) grub_util_error ("cannot stat `%s'", dir); diff --git a/util/grub-probe.c b/util/grub-probe.c index 56cbc5592..52f2b3747 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -359,6 +359,7 @@ main (int argc, char *argv[]) set_program_name (argv[0]); grub_util_init_nls (); + grub_util_init_libzfs (); /* Check for options. */ while (1) diff --git a/util/misc.c b/util/misc.c index 91bc25a55..0859197bf 100644 --- a/util/misc.c +++ b/util/misc.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -293,6 +294,25 @@ grub_util_init_nls (void) textdomain (PACKAGE); #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ } + +#ifdef HAVE_LIBZFS +libzfs_handle_t *libzfs_handle; + +static void +fini_libzfs (void) +{ + libzfs_fini (libzfs_handle); +} +#endif + +void +grub_util_init_libzfs (void) +{ +#ifdef HAVE_LIBZFS + libzfs_handle = libzfs_init (); + atexit (fini_libzfs); +#endif +} #endif int From c9a00aeeaa0d9c4d6b254fe2e221b67b951a48e7 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 30 Jul 2010 22:01:10 +0200 Subject: [PATCH 09/29] 2010-07-30 Robert Millan * include/grub/emu/misc.h: Add missing license header. --- ChangeLog | 4 ++++ include/grub/emu/misc.h | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/ChangeLog b/ChangeLog index 041f9cadd..86aba2914 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-07-30 Robert Millan + + * include/grub/emu/misc.h: Add missing license header. + 2010-07-30 Robert Millan Enable `grub-probe -t device' resolution on ZFS. diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index 07257e511..dc48d91a8 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + #ifndef GRUB_EMU_MISC_H #define GRUB_EMU_MISC_H 1 From 3169f4c76a37a1545d7382a5dd483e36d00da5c3 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sat, 31 Jul 2010 12:22:01 +0200 Subject: [PATCH 10/29] 2010-07-31 Robert Millan * configure.ac: Check for `libzfs.h' and `libnvpair.h'. * include/grub/util/libnvpair.h: Include `'. [HAVE_LIBNVPAIR_H]: Include `' instead of declaring libnvpair prototypes ourselves. * include/grub/util/libzfs.h: Include `'. [HAVE_LIBZFS_H]: Include `' instead of declaring libzfs prototypes ourselves. (libzfs_handle): Moved to ... * include/grub/util/misc.h (libzfs_handle): ... here. Include `'. --- ChangeLog | 15 +++++++++++++++ configure.ac | 3 ++- include/grub/util/libnvpair.h | 8 ++++++++ include/grub/util/libzfs.h | 8 +++++++- include/grub/util/misc.h | 3 +++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 86aba2914..58b821da9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2010-07-31 Robert Millan + + * configure.ac: Check for `libzfs.h' and `libnvpair.h'. + + * include/grub/util/libnvpair.h: Include `'. + [HAVE_LIBNVPAIR_H]: Include `' instead of + declaring libnvpair prototypes ourselves. + * include/grub/util/libzfs.h: Include `'. + [HAVE_LIBZFS_H]: Include `' instead of + declaring libzfs prototypes ourselves. + + (libzfs_handle): Moved to ... + * include/grub/util/misc.h (libzfs_handle): ... here. + Include `'. + 2010-07-30 Robert Millan * include/grub/emu/misc.h: Add missing license header. diff --git a/configure.ac b/configure.ac index cc97c7f77..6169a2fb5 100644 --- a/configure.ac +++ b/configure.ac @@ -246,8 +246,9 @@ else AC_PATH_PROG(HELP2MAN, help2man) fi -# Check for functions. +# Check for functions and headers. AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat) +AC_CHECK_HEADERS(libzfs.h libnvpair.h) # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. diff --git a/include/grub/util/libnvpair.h b/include/grub/util/libnvpair.h index c4fe174ea..26f7e9d0f 100644 --- a/include/grub/util/libnvpair.h +++ b/include/grub/util/libnvpair.h @@ -19,6 +19,12 @@ #ifndef GRUB_LIBNVPAIR_UTIL_HEADER #define GRUB_LIBNVPAIR_UTIL_HEADER 1 +#include + +#ifdef HAVE_LIBNVPAIR_H +#include +#else /* ! HAVE_LIBNVPAIR_H */ + #include /* FILE */ typedef void nvlist_t; @@ -28,4 +34,6 @@ int nvlist_lookup_nvlist (nvlist_t *, const char *, nvlist_t **); int nvlist_lookup_nvlist_array (nvlist_t *, const char *, nvlist_t ***, unsigned int *); void nvlist_print (FILE *, nvlist_t *); +#endif /* ! HAVE_LIBNVPAIR_H */ + #endif diff --git a/include/grub/util/libzfs.h b/include/grub/util/libzfs.h index a17c47e20..9fbfd40d1 100644 --- a/include/grub/util/libzfs.h +++ b/include/grub/util/libzfs.h @@ -19,6 +19,12 @@ #ifndef GRUB_LIBZFS_UTIL_HEADER #define GRUB_LIBZFS_UTIL_HEADER 1 +#include + +#ifdef HAVE_LIBZFS_H +#include +#else /* ! HAVE_LIBZFS_H */ + #include typedef void libzfs_handle_t; @@ -34,6 +40,6 @@ extern int zpool_get_physpath (zpool_handle_t *, const char *); extern nvlist_t *zpool_get_config (zpool_handle_t *, nvlist_t **); -extern libzfs_handle_t *libzfs_handle; +#endif /* ! HAVE_LIBZFS_H */ #endif diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 699b9cf2c..3614c79c2 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -29,6 +29,7 @@ #include #include #include +#include char *grub_util_get_path (const char *dir, const char *file); size_t grub_util_get_fp_size (FILE *fp); @@ -59,6 +60,8 @@ char *make_system_path_relative_to_its_root (const char *path); char *canonicalize_file_name (const char *path); void grub_util_init_nls (void); + void grub_util_init_libzfs (void); +extern libzfs_handle_t *libzfs_handle; #endif /* ! GRUB_UTIL_MISC_HEADER */ From 8072efebf210fbc610ae852750e3f400305dfc69 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sat, 31 Jul 2010 18:45:57 +0200 Subject: [PATCH 11/29] 2010-07-31 Robert Millan * kern/emu/misc.c: Add missing license header. --- ChangeLog | 4 ++++ kern/emu/misc.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/ChangeLog b/ChangeLog index 58b821da9..24303ff17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-07-31 Robert Millan + + * kern/emu/misc.c: Add missing license header. + 2010-07-31 Robert Millan * configure.ac: Check for `libzfs.h' and `libnvpair.h'. diff --git a/kern/emu/misc.c b/kern/emu/misc.c index 38395fca8..851da7a07 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + #include #include From 3710bb6b96ba84767e9315b8eecfd31c8b2386de Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 1 Aug 2010 02:14:07 +0200 Subject: [PATCH 12/29] 2010-07-31 Robert Millan * util/grub.d/10_kfreebsd.in: Make module handling more generic. --- ChangeLog | 4 ++++ util/grub.d/10_kfreebsd.in | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 24303ff17..249256083 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-07-31 Robert Millan + + * util/grub.d/10_kfreebsd.in: Make module handling more generic. + 2010-07-31 Robert Millan * kern/emu/misc.c: Add missing license header. diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 9915abdf1..f32da3013 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -51,6 +51,10 @@ kfreebsd_entry () if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi + if [ -z "${prepare_module_dir_cache}" ]; then + prepare_module_dir_cache="$(prepare_grub_to_access_device $(grub-probe -t device "${module_dir}") | sed -e "s/^/\t/")" + fi + printf '%s\n' "${prepare_boot_cache}" cat << EOF echo '$(printf "$(gettext_quoted "Loading kernel of FreeBSD %s ...")" ${version})' @@ -63,9 +67,10 @@ EOF EOF fi - if test -n "${acpi_ko}" ; then + if test -e "${module_dir}/acpi.ko" ; then + printf '%s\n' "${prepare_module_dir_cache}" cat << EOF - kfreebsd_module_elf ${acpi_ko_rel_dirname}/${acpi_ko_basename} + kfreebsd_module_elf ${module_dir_rel}/acpi.ko EOF fi @@ -103,19 +108,17 @@ while [ "x$list" != "x" ] ; do version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"` alt_version=`echo $version | sed -e "s,\.old$,,g"` - acpi_ko= - for i in "/lib/modules/${version}/acpi.ko" "/lib/modules/${alt_version}/acpi.ko" \ - "/boot/kernel/acpi.ko"; do + module_dir= + for i in "/lib/modules/${version}" "/lib/modules/${alt_version}" \ + "/boot/kernel"; do if test -e "$i" ; then - acpi_ko="$i" + module_dir="$i" break fi done - if test -n "${acpi_ko}" ; then - echo "Found ACPI module: ${acpi_ko}" >&2 - acpi_ko_basename=`basename ${acpi_ko}` - acpi_ko_dirname=`dirname ${acpi_ko}` - acpi_ko_rel_dirname=`make_system_path_relative_to_its_root $acpi_ko_dirname` + if test -n "${module_dir}" ; then + echo "Found kernel module directory: ${module_dir}" >&2 + module_dir_rel=$(make_system_path_relative_to_its_root $module_dir) fi kfreebsd_entry "${OS}" "${version}" From ebf53056b8e17487c9f56effe9130f5772a93e02 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 1 Aug 2010 14:47:14 +0200 Subject: [PATCH 13/29] 2010-08-01 Robert Millan * kern/emu/getroot.c: Include `'. --- ChangeLog | 4 ++++ kern/emu/getroot.c | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 249256083..f34ed35c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-08-01 Robert Millan + + * kern/emu/getroot.c: Include `'. + 2010-07-31 Robert Millan * util/grub.d/10_kfreebsd.in: Make module handling more generic. diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index f2f6311ff..6caae08e6 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef __GNU__ #include From ce04ef47e2ef22cc3886b88beba2e58e8d115702 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 1 Aug 2010 08:54:10 -0500 Subject: [PATCH 14/29] * util/grub.d/20_linux_xen.in: Don't use UUID for LVM root (matching util/grub.d/10_linux.in). Fixes Debian bug #591093. --- ChangeLog | 5 +++++ util/grub.d/20_linux_xen.in | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f34ed35c9..abe698574 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-08-01 Colin Watson + + * util/grub.d/20_linux_xen.in: Don't use UUID for LVM root (matching + util/grub.d/10_linux.in). Fixes Debian bug #591093. + 2010-08-01 Robert Millan * kern/emu/getroot.c: Include `'. diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index 8612c96b0..e631c0a4a 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -44,7 +44,8 @@ case ${GRUB_DEVICE} in esac if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ - || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then + || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ + || uses_abstraction "${GRUB_DEVICE}" lvm; then LINUX_ROOT_DEVICE=${GRUB_DEVICE} else LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} From deb0caa38ebc69aa7135d56896a6e61d0642ba3c Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 1 Aug 2010 15:23:44 +0200 Subject: [PATCH 15/29] 2010-08-01 Robert Millan Prevent accidental use of uninitialized libzfs_handle. * util/grub-probe.c (main): Move grub_util_init_libzfs() call to ... * kern/emu/getroot.c (find_root_device_from_libzfs): ... here. * util/misc.c (grub_util_init_libzfs): Make this function idempotent. --- ChangeLog | 8 ++++++++ kern/emu/getroot.c | 2 ++ util/grub-probe.c | 1 - util/misc.c | 7 +++++-- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index abe698574..20094fec8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-08-01 Robert Millan + + Prevent accidental use of uninitialized libzfs_handle. + + * util/grub-probe.c (main): Move grub_util_init_libzfs() call to ... + * kern/emu/getroot.c (find_root_device_from_libzfs): ... here. + * util/misc.c (grub_util_init_libzfs): Make this function idempotent. + 2010-08-01 Colin Watson * util/grub.d/20_linux_xen.in: Don't use UUID for LVM root (matching diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index 6caae08e6..f8eda2294 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -289,6 +289,8 @@ find_root_device_from_libzfs (const char *dir) nvlist_t **nvlist_array; unsigned int nvlist_count; + grub_util_init_libzfs (); + zpool = zpool_open (libzfs_handle, poolname); nvlist = zpool_get_config (zpool, NULL); diff --git a/util/grub-probe.c b/util/grub-probe.c index 52f2b3747..56cbc5592 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -359,7 +359,6 @@ main (int argc, char *argv[]) set_program_name (argv[0]); grub_util_init_nls (); - grub_util_init_libzfs (); /* Check for options. */ while (1) diff --git a/util/misc.c b/util/misc.c index 0859197bf..2eff256bf 100644 --- a/util/misc.c +++ b/util/misc.c @@ -309,8 +309,11 @@ void grub_util_init_libzfs (void) { #ifdef HAVE_LIBZFS - libzfs_handle = libzfs_init (); - atexit (fini_libzfs); + if (! libzfs_handle) + { + libzfs_handle = libzfs_init (); + atexit (fini_libzfs); + } #endif } #endif From 7decd202a72cbed9d1e1d445d6fbea9532703866 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sun, 1 Aug 2010 09:44:36 -0500 Subject: [PATCH 16/29] * kern/misc.c (grub_memset): Optimise to reduce cache stalls. Also-By: Colin Watson --- ChangeLog | 5 +++++ kern/misc.c | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 20094fec8..d00fd9d51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-08-01 Vladimir Serbinenko +2010-08-01 Colin Watson + + * kern/misc.c (grub_memset): Optimise to reduce cache stalls. + 2010-08-01 Robert Millan Prevent accidental use of uninitialized libzfs_handle. diff --git a/kern/misc.c b/kern/misc.c index c13c96e30..b37ef230c 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -518,12 +518,39 @@ grub_strndup (const char *s, grub_size_t n) } void * -grub_memset (void *s, int c, grub_size_t n) +grub_memset (void *s, int c, grub_size_t len) { - unsigned char *p = (unsigned char *) s; + void *p = s; + grub_uint8_t pattern8 = c; - while (n--) - *p++ = (unsigned char) c; + if (len >= 3 * sizeof (unsigned long)) + { + unsigned long patternl = 0; + grub_size_t i; + + for (i = 0; i < sizeof (unsigned long); i++) + patternl |= ((unsigned long) pattern8) << (8 * i); + + while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1))) + { + *(grub_uint8_t *) p = pattern8; + p = (grub_uint8_t *) p + 1; + len--; + } + while (len >= sizeof (unsigned long)) + { + *(unsigned long *) p = patternl; + p = (unsigned long *) p + 1; + len -= sizeof (unsigned long); + } + } + + while (len > 0) + { + *(grub_uint8_t *) p = pattern8; + p = (grub_uint8_t *) p + 1; + len--; + } return s; } From 2cfb45df5ed7be7b55c69dc0f809343e189afdb9 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 1 Aug 2010 11:25:09 -0500 Subject: [PATCH 17/29] * docs/grub.texi (Simple configuration): Document GRUB_CMDLINE_XEN and GRUB_CMDLINE_XEN_DEFAULT. Recommend setting GRUB_GFXPAYLOAD_LINUX=text rather than unsetting it in order to disable gfxpayload. (Shell-like scripting): Add real content. (Serial terminal): Suggest `terminal_input serial; terminal_output serial' rather than putting the two commands on separate lines, since console input will be inoperative after the first command. (menuentry): Document --class, --users, and --hotkey options. (terminfo): Describe what `visually-ordered UTF-8' means (thanks, Vladimir Serbinenko). --- ChangeLog | 14 ++++ docs/grub.texi | 182 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 186 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index d00fd9d51..1c1533841 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2010-08-01 Colin Watson + + * docs/grub.texi (Simple configuration): Document GRUB_CMDLINE_XEN + and GRUB_CMDLINE_XEN_DEFAULT. Recommend setting + GRUB_GFXPAYLOAD_LINUX=text rather than unsetting it in order to + disable gfxpayload. + (Shell-like scripting): Add real content. + (Serial terminal): Suggest `terminal_input serial; terminal_output + serial' rather than putting the two commands on separate lines, + since console input will be inoperative after the first command. + (menuentry): Document --class, --users, and --hotkey options. + (terminfo): Describe what `visually-ordered UTF-8' means (thanks, + Vladimir Serbinenko). + 2010-08-01 Vladimir Serbinenko 2010-08-01 Colin Watson diff --git a/docs/grub.texi b/docs/grub.texi index a191ef9ef..583cf98cb 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1062,6 +1062,11 @@ only to the default menu entry, after those listed in As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for NetBSD. +@item GRUB_CMDLINE_XEN +@itemx GRUB_CMDLINE_XEN_DEFAULT +As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for +Linux and Xen. + @item GRUB_DISABLE_LINUX_UUID Normally, @command{grub-mkconfig} will generate menu entries that use universally-unique identifiers (UUIDs) to identify the root filesystem to @@ -1113,8 +1118,8 @@ try several modes in sequence. Depending on your kernel, your distribution, your graphics card, and the phase of the moon, note that using this option may cause GNU/Linux to suffer from various display problems, particularly during the early part of the -boot sequence. If you have problems, simply unset this option and GRUB will -tell Linux to boot in normal text mode. +boot sequence. If you have problems, set this option to @samp{text} and +GRUB will tell Linux to boot in normal text mode. @item GRUB_DISABLE_OS_PROBER Normally, @command{grub-mkconfig} will try to use the external @@ -1143,6 +1148,142 @@ that file, making sure to leave at least the first two lines intact. @node Shell-like scripting @section Writing full configuration files directly +@c Some of this section is derived from the GNU Bash manual page, also +@c copyrighted by the FSF. + +@file{grub.cfg} is written in GRUB's built-in scripting language, which has +a syntax quite similar to that of GNU Bash and other Bourne shell +derivatives. + +@heading Words + +A @dfn{word} is a sequence of characters considered as a single unit by +GRUB. Words are separated by @dfn{metacharacters}, which are the following +plus space, tab, and newline: + +@example +@{ @} | & $ ; < > +@end example + +Quoting may be used to include metacharacters in words; see below. + +@heading Reserved words + +Reserved words have a special meaning to GRUB. The following words are +recognised as reserved when unquoted and either the first word of a simple +command or the third word of a @code{for} command: + +@example +! [[ ]] @{ @} +case do done elif else esac fi for function +if in menuentry select then time until while +@end example + +Not all of these reserved words have a useful purpose yet; some are reserved +for future expansion. + +@heading Quoting + +Quoting is used to remove the special meaning of certain characters or +words. It can be used to treat metacharacters as part of a word, to prevent +reserved words from being recognised as such, and to prevent variable +expansion. + +There are three quoting mechanisms: the escape character, single quotes, and +double quotes. + +A non-quoted backslash (\) is the @dfn{escape character}. It preserves the +literal value of the next character that follows, with the exception of +newline. + +Enclosing characters in single quotes preserves the literal value of each +character within the quotes. A single quote may not occur between single +quotes, even when preceded by a backslash. + +Enclosing characters in double quotes preserves the literal value of all +characters within the quotes, with the exception of @samp{$} and @samp{\}. +The @samp{$} character retains its special meaning within double quotes. +The backslash retains its special meaning only when followed by one of the +following characters: @samp{$}, @samp{"}, @samp{\}, or newline. A +backslash-newline pair is treated as a line continuation (that is, it is +removed from the input stream and effectively ignored). A double quote may +be quoted within double quotes by preceding it with a backslash. + +@heading Variable expansion + +The @samp{$} character introduces variable expansion. The variable name to +be expanded may be enclosed in braces, which are optional but serve to +protect the variable to be expanded from characters immediately following it +which could be interpreted as part of the name. + +Normal variable names begin with an alphabetic character, followed by zero +or more alphanumeric characters. + +Positional variable names consist of one or more digits. These are reserved +for future expansion. + +The special variable name @samp{?} expands to the exit status of the most +recently executed command. + +@heading Comments + +A word beginning with @samp{#} causes that word and all remaining characters +on that line to be ignored. + +@heading Simple commands + +A @dfn{simple command} is a sequence of words separated by spaces or tabs +and terminated by a semicolon or a newline. The first word specifies the +command to be executed. The remaining words are passed as arguments to the +invoked command. + +The return value of a simple command is its exit status. + +@heading Compound commands + +A @dfn{compound command} is one of the following: + +@table @asis +@item for @var{name} in @var{word} @dots{}; do @var{list}; done +The list of words following @code{in} is expanded, generating a list of +items. The variable @var{name} is set to each element of this list in turn, +and @var{list} is executed each time. The return value is the exit status +of the last command that executes. If the expansion of the items following +@code{in} results in an empty list, no commands are executed, and the return +status is 0. + +@item if @var{list}; then @var{list}; [elif @var{list}; then @var{list};] @dots{} [else @var{list};] fi +The @code{if} @var{list} is executed. If its exit status is zero, the +@code{then} @var{list} is executed. Otherwise, each @code{elif} @var{list} +is executed in turn, and if its exit status is zero, the corresponding +@code{then} @var{list} is executed and the command completes. Otherwise, +the @code{else} @var{list} is executed, if present. The exit status is the +exit status of the last command executed, or zero if no condition tested +true. + +@item while @var{cond}; do @var{list}; done +@itemx until @var{cond}; do @var{list}; done +The @code{while} command continuously executes the @code{do} @var{list} as +long as the last command in @var{cond} returns an exit status of zero. The +@code{until} command is identical to the @code{while} command, except that +the test is negated; the @code{do} @var{list} is executed as long as the +last command in @var{cond} returns a non-zero exit status. The exit status +of the @code{while} and @code{until} commands is the exit status of the last +@code{do} @var{list} command executed, or zero if none was executed. + +@item function @var{name} @{ @var{command}; @dots{} @} +This defines a function named @var{name}. The @dfn{body} of the function is +the list of commands within braces, each of which must be terminated with a +semicolon or a newline. This list of commands will be executed whenever +@var{name} is specified as the name of a simple command. Function +definitions do not affect the exit status in @code{$?}. When executed, the +exit status of a function is the exit status of the last command executed in +the body. + +@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--hotkey=key}] @{ @var{command}; @dots{} @} +@xref{menuentry}. +@end table + @node Embedded configuration @section Embedding a configuration file into GRUB @@ -1308,8 +1449,7 @@ simple. Here is an example: @example @group grub> @kbd{serial --unit=0 --speed=9600} -grub> @kbd{terminal_input serial} -grub> @kbd{terminal_output serial} +grub> @kbd{terminal_input serial; terminal_output serial} @end group @end example @@ -1320,11 +1460,14 @@ command accepts many other options, so please refer to @ref{serial}, for more details. The commands @command{terminal_input} (@pxref{terminal_input}) and -@command{terminal_output} (@pxref{terminal_output} choose which type of +@command{terminal_output} (@pxref{terminal_output}) choose which type of terminal you want to use. In the case above, the terminal will be a serial terminal, but you can also pass @code{console} to the command, as @samp{terminal serial console}. In this case, a terminal in which -you press any key will be selected as a GRUB terminal. +you press any key will be selected as a GRUB terminal. In the example above, +note that you need to put both commands on the same command line, as you +will lose the ability to type commands on the console after the first +command. However, note that GRUB assumes that your terminal emulator is compatible with VT100 by default. This is true for most terminal @@ -1789,9 +1932,26 @@ These commands can only be used in the menu: @node menuentry @subsection menuentry -@deffn Command title name @dots{} -Start a new boot entry, and set its name to the contents of the rest of -the line, starting with the first non-space character. +@deffn Command menuentry @var{title} @ + [@option{--class=class} @dots{}] [@option{--users=users}] @ + [@option{--hotkey=key}] @ + @{ @var{command}; @dots{} @} +This defines a GRUB menu entry named @var{title}. When this entry is +selected from the menu, GRUB will set the @var{chosen} environment variable +to @var{title}, execute the list of commands given within braces, and if the +last command in the list returned successfully and a kernel was loaded it +will execute the @command{boot} command. + +The @option{--class} option may be used any number of times to group menu +entries into classes. Menu themes may display different classes using +different styles. + +The @option{--users} option grants specific users access to specific menu +entries. @xref{Security}. + +The @option{--hotkey} option associates a hotkey with a menu entry. +@var{key} may be a single letter, or one of the aliases @samp{backspace}, +@samp{tab}, or @samp{delete}. @end deffn @@ -1885,7 +2045,9 @@ The @option{-a} (@option{--ascii}), @option{-u} (@option{--utf8}), and @option{-v} (@option{--visual-utf8}) options control how non-ASCII text is displayed. @option{-a} specifies an ASCII-only terminal; @option{-u} specifies logically-ordered UTF-8; and @option{-v} specifies -visually-ordered UTF-8. +"visually-ordered UTF-8" (in other words, arranged such that a terminal +emulator without bidirectional text support will display right-to-left text +in the proper order; this is not really proper UTF-8, but a workaround). If no option or terminal type is specified, the current terminal type is printed. From 6eea041aa4dae2be3ffe42786dce894d8d89dfba Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 1 Aug 2010 11:28:12 -0500 Subject: [PATCH 18/29] * script/yylex.l (NAME): Remove [:digit:], redundant with [:alnum:]. --- ChangeLog | 4 ++++ script/yylex.l | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1c1533841..83ac0b37b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-08-01 Colin Watson + + * script/yylex.l (NAME): Remove [:digit:], redundant with [:alnum:]. + 2010-08-01 Colin Watson * docs/grub.texi (Simple configuration): Document GRUB_CMDLINE_XEN diff --git a/script/yylex.l b/script/yylex.l index 7d4ea9e4e..e9659832b 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -116,7 +116,7 @@ COMMENT #.*$ CHAR [^{}|&$;<> \t\n\'\"\\] DIGITS [[:digit:]]+ -NAME [[:alpha:]_][[:alnum:][:digit:]_]* +NAME [[:alpha:]_][[:alnum:]_]* ESC \\. VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} From ea9be8eadb4d899eb6bc740b360de292695aacf9 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 1 Aug 2010 11:30:03 -0500 Subject: [PATCH 19/29] * util/grub-mkrescue.in: Remove ${efi_dir} after building efi.img. --- ChangeLog | 4 ++++ util/grub-mkrescue.in | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 83ac0b37b..9729f71d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-08-01 Colin Watson + + * util/grub-mkrescue.in: Remove ${efi_dir} after building efi.img. + 2010-08-01 Colin Watson * script/yylex.l (NAME): Remove [:digit:], redundant with [:alnum:]. diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index e498acee7..b7d9eb4eb 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -296,6 +296,7 @@ if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then mformat -C -f 2880 -L 16 -i "${iso9660_dir}"/efi.img :: mcopy -s -i "${iso9660_dir}"/efi.img ${efi_dir}/efi ::/ + rm -rf ${efi_dir} grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img" fi From 8687cf071e646a5c949b7cbcf14f6ea9334ec466 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 1 Aug 2010 16:11:27 +0200 Subject: [PATCH 20/29] * kern/emu/getroot.c (find_mount_point_from_dir): Compile only if [HAVE_LIBZFS && HAVE_LIBNVPAIR] --- ChangeLog | 7 ++++++- kern/emu/getroot.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9729f71d8..2e8c0daa5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-08-01 Vladimir Serbinenko + + * kern/emu/getroot.c (find_mount_point_from_dir): Compile only if + [HAVE_LIBZFS && HAVE_LIBNVPAIR] + 2010-08-01 Colin Watson * util/grub-mkrescue.in: Remove ${efi_dir} after building efi.img. @@ -41,7 +46,7 @@ 2010-08-01 Robert Millan * kern/emu/getroot.c: Include `'. - + 2010-07-31 Robert Millan * util/grub.d/10_kfreebsd.in: Make module handling more generic. diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index f8eda2294..032608d1b 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -98,6 +98,8 @@ xgetcwd (void) return path; } +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + static char * find_mount_point_from_dir (const char *dir) { @@ -154,6 +156,8 @@ find_mount_point_from_dir (const char *dir) } } +#endif + #ifdef __linux__ /* Statting something on a btrfs filesystem always returns a virtual device From 553df63d76cf4a5b6fa63042021320e5b6d6a5d4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 1 Aug 2010 21:01:05 +0200 Subject: [PATCH 21/29] * lib/arg.c (grub_arg_show_help): Add the necessary spacing. --- ChangeLog | 4 ++++ lib/arg.c | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e8c0daa5..bc6b8fd18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-08-01 Vladimir Serbinenko + + * lib/arg.c (grub_arg_show_help): Add the necessary spacing. + 2010-08-01 Vladimir Serbinenko * kern/emu/getroot.c (find_mount_point_from_dir): Compile only if diff --git a/lib/arg.c b/lib/arg.c index 400314d30..a9b8a520e 100644 --- a/lib/arg.c +++ b/lib/arg.c @@ -144,8 +144,10 @@ grub_arg_show_help (grub_extcmd_t cmd) } } - /* FIXME: add spacing back. */ - grub_xputs (_(opt->doc)); + while (spacing--) + grub_xputs (" "); + + grub_printf ("%s\n", _(opt->doc)); switch (opt->shortarg) { From 8bfe31d82b187f4dbaa9df652bd170bd5915c818 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 1 Aug 2010 16:41:46 -0500 Subject: [PATCH 22/29] * include/grub/util/libzfs.h (libzfs_init): Set argument list to (void) rather than () so that this is a proper prototype. --- ChangeLog | 5 +++++ include/grub/util/libzfs.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index bc6b8fd18..daf5517dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-08-01 Colin Watson + + * include/grub/util/libzfs.h (libzfs_init): Set argument list to + (void) rather than () so that this is a proper prototype. + 2010-08-01 Vladimir Serbinenko * lib/arg.c (grub_arg_show_help): Add the necessary spacing. diff --git a/include/grub/util/libzfs.h b/include/grub/util/libzfs.h index 9fbfd40d1..0500f70d7 100644 --- a/include/grub/util/libzfs.h +++ b/include/grub/util/libzfs.h @@ -30,7 +30,7 @@ typedef void libzfs_handle_t; typedef void zpool_handle_t; -extern libzfs_handle_t *libzfs_init (); +extern libzfs_handle_t *libzfs_init (void); extern void libzfs_fini (libzfs_handle_t *); extern zpool_handle_t *zpool_open (libzfs_handle_t *, const char *); From c882acc031c3ee096c01ee73963ab4628155f3cc Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 1 Aug 2010 22:59:02 +0200 Subject: [PATCH 23/29] 2010-08-01 Robert Millan * 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 `' 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. --- ChangeLog | 42 ++++++++++++ include/grub/emu/misc.h | 8 ++- kern/emu/getroot.c | 112 +++----------------------------- kern/emu/misc.c | 140 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 196 insertions(+), 106 deletions(-) diff --git a/ChangeLog b/ChangeLog index daf5517dc..2956129b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2010-08-01 Robert Millan + + * 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 `' 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 * 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 + + * 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 `' 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 Prevent accidental use of uninitialized libzfs_handle. diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index dc48d91a8..5047a9406 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -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)); diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index 032608d1b..32044536d 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -49,10 +49,6 @@ # include #endif -#ifdef HAVE_GETFSSTAT -# include -#endif - #include #include #include @@ -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; } diff --git a/kern/emu/misc.c b/kern/emu/misc.c index 851da7a07..0d71ef3d6 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,15 @@ # include #endif +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) +# include +# include +#endif + +#ifdef HAVE_GETFSSTAT +# include +#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 From f7abdefbdd861ec752cf3df6eda42c26c522cdb9 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 1 Aug 2010 23:12:24 +0200 Subject: [PATCH 24/29] 2010-08-01 Robert Millan Make it even harder to use uninitialized `libzfs_handle' (and make the interface a bit simpler). * include/grub/util/misc.h (grub_util_init_libzfs) (libzfs_handle): Remove. (grub_get_libzfs_handle): New prototype. * util/misc.c [HAVE_LIBZFS] (libzfs_handle): Add `static' attribute. (grub_util_init_libzfs): Remove. (grub_get_libzfs_handle): New function. * kern/emu/getroot.c (find_root_device_from_libzfs): Use grub_get_libzfs_handle() to obtain a libzfs handle instead of accessing `libzfs_handle' directly. --- ChangeLog | 18 ++++++++++++++++++ include/grub/util/misc.h | 3 +-- kern/emu/getroot.c | 4 +--- util/misc.c | 14 +++++++------- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2956129b3..d4a63c4ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2010-08-01 Robert Millan + + Make it even harder to use uninitialized `libzfs_handle' (and + make the interface a bit simpler). + + * include/grub/util/misc.h (grub_util_init_libzfs) + (libzfs_handle): Remove. + (grub_get_libzfs_handle): New prototype. + + * util/misc.c [HAVE_LIBZFS] (libzfs_handle): Add `static' + attribute. + (grub_util_init_libzfs): Remove. + (grub_get_libzfs_handle): New function. + + * kern/emu/getroot.c (find_root_device_from_libzfs): Use + grub_get_libzfs_handle() to obtain a libzfs handle instead of + accessing `libzfs_handle' directly. + 2010-08-01 Robert Millan * include/grub/emu/misc.h (grub_find_mount_point_from_dir) diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 3614c79c2..7ce3d3291 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -61,7 +61,6 @@ char *canonicalize_file_name (const char *path); void grub_util_init_nls (void); -void grub_util_init_libzfs (void); -extern libzfs_handle_t *libzfs_handle; +libzfs_handle_t *grub_get_libzfs_handle (void); #endif /* ! GRUB_UTIL_MISC_HEADER */ diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index 32044536d..ee6e1c7ba 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -197,9 +197,7 @@ find_root_device_from_libzfs (const char *dir) nvlist_t **nvlist_array; unsigned int nvlist_count; - grub_util_init_libzfs (); - - zpool = zpool_open (libzfs_handle, poolname); + zpool = zpool_open (grub_get_libzfs_handle (), poolname); nvlist = zpool_get_config (zpool, NULL); if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0) diff --git a/util/misc.c b/util/misc.c index 2eff256bf..274c182c2 100644 --- a/util/misc.c +++ b/util/misc.c @@ -296,27 +296,27 @@ grub_util_init_nls (void) } #ifdef HAVE_LIBZFS -libzfs_handle_t *libzfs_handle; +static libzfs_handle_t *libzfs_handle; static void fini_libzfs (void) { libzfs_fini (libzfs_handle); } -#endif -void -grub_util_init_libzfs (void) +libzfs_handle_t * +grub_get_libzfs_handle (void) { -#ifdef HAVE_LIBZFS if (! libzfs_handle) { libzfs_handle = libzfs_init (); atexit (fini_libzfs); } -#endif + + return libzfs_handle; } -#endif +#endif /* HAVE_LIBZFS */ +#endif /* GRUB_UTIL */ int grub_dl_ref (grub_dl_t mod) From c7db243b92d530b870bc71ae85e74bb8e3377cf0 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 1 Aug 2010 23:21:09 +0200 Subject: [PATCH 25/29] 2010-08-01 Robert Millan * util/grub.d/10_kfreebsd.in: Initialize ${kfreebsd_device} as the kFreeBSD device name, except on ZFS where the filesystem label is used. (kfreebsd_entry): On ZFS root, load `opensolaris.ko', `zfs.ko' and `/boot/zfs/zpool.cache'. Set mountfrom kernel variable using ${kfreebsd_device}. --- ChangeLog | 9 +++++++++ util/grub.d/10_kfreebsd.in | 26 +++++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d4a63c4ec..65d6cb667 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-08-01 Robert Millan + + * util/grub.d/10_kfreebsd.in: Initialize ${kfreebsd_device} as the + kFreeBSD device name, except on ZFS where the filesystem label is + used. + (kfreebsd_entry): On ZFS root, load `opensolaris.ko', `zfs.ko' and + `/boot/zfs/zpool.cache'. + Set mountfrom kernel variable using ${kfreebsd_device}. + 2010-08-01 Robert Millan Make it even harder to use uninitialized `libzfs_handle' (and diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index f32da3013..bc5201ab9 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -74,8 +74,27 @@ EOF EOF fi + case "${kfreebsd_fs}" in + zfs) + test -e "${module_dir}/opensolaris.ko" + test -e "${module_dir}/zfs.ko" + test -e "${dirname}/zfs/zpool.cache" + + printf '%s\n' "${prepare_module_dir_cache}" + cat << EOF + kfreebsd_module_elf ${module_dir_rel}/opensolaris.ko + kfreebsd_module_elf ${module_dir_rel}/zfs.ko +EOF + + printf '%s\n' "${prepare_boot_cache}" cat << EOF - set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE} + kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache +EOF + ;; + esac + + cat << EOF + set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${kfreebsd_device} set kFreeBSD.vfs.root.mountfrom.options=rw } EOF @@ -105,6 +124,11 @@ while [ "x$list" != "x" ] ; do *) kfreebsd_fs=${GRUB_FS} ;; esac + case ${GRUB_FS} in + zfs) kfreebsd_device=$(grub-probe -t label --device ${GRUB_DEVICE}) ;; + *) kfreebsd_device=${GRUB_DEVICE} ;; + esac + version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"` alt_version=`echo $version | sed -e "s,\.old$,,g"` From a870a783be2eed43b59c7d537a37484ea05a668c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 2 Aug 2010 09:51:23 -0500 Subject: [PATCH 26/29] * disk/raid.c (insert_array): Select unique numbers for named arrays as well, for use as keys in the disk cache. --- ChangeLog | 5 +++++ disk/raid.c | 29 ++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 65d6cb667..83afffca3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-08-02 Colin Watson + + * disk/raid.c (insert_array): Select unique numbers for named arrays + as well, for use as keys in the disk cache. + 2010-08-01 Robert Millan * util/grub.d/10_kfreebsd.in: Initialize ${kfreebsd_device} as the diff --git a/disk/raid.c b/disk/raid.c index 7dfd4bd81..51a4b00e2 100644 --- a/disk/raid.c +++ b/disk/raid.c @@ -528,25 +528,28 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, grub_memset (&array->device, 0, sizeof (array->device)); grub_memset (&array->start_sector, 0, sizeof (array->start_sector)); - if (array->name) - goto skip_duplicate_check; - /* Check whether we don't have multiple arrays with the same number. */ - for (p = array_list; p != NULL; p = p->next) - { - if (! p->name && p->number == array->number) - break; - } + if (! array->name) + { + for (p = array_list; p != NULL; p = p->next) + { + if (! p->name && p->number == array->number) + break; + } + } - if (p) + if (array->name || p) { - /* The number is already in use, so we need to find a new one. */ - int i = 0; + /* The number is already in use, so we need to find a new one. + (Or, in the case of named arrays, the array doesn't have its + own number, but we need one that doesn't clash for use as a key + in the disk cache. */ + int i = array->name ? 0x40000000 : 0; while (1) { for (p = array_list; p != NULL; p = p->next) { - if (! p->name && p->number == i) + if (p->number == i) break; } @@ -560,7 +563,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, i++; } } - skip_duplicate_check: + /* mdraid 1.x superblocks have only a name stored not a number. Use it directly as GRUB device. */ if (! array->name) From c9f7ff97cfa5107da90469beb01058c952a433e4 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Tue, 3 Aug 2010 11:56:36 +0530 Subject: [PATCH 27/29] * script/execute.c (grub_script_execute_cmdline): Check for NULL as command name case. --- ChangeLog | 5 +++++ script/execute.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 83afffca3..d4da9f96c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-08-03 BVK Chaitanya + + * script/execute.c (grub_script_execute_cmdline): Check for NULL + as command name case. + 2010-08-02 Colin Watson * disk/raid.c (insert_array): Select unique numbers for named arrays diff --git a/script/execute.c b/script/execute.c index 40f161267..c45a15d29 100644 --- a/script/execute.c +++ b/script/execute.c @@ -207,7 +207,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) /* Lookup the command. */ args = grub_script_execute_arglist_to_argv (cmdline->arglist, &argcount); - if (!args) + if (! args || ! args[0]) return grub_errno; cmdname = args[0]; From 9dd6fd50b4e69a3e4b68120ece98e5657a453a5b Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Tue, 3 Aug 2010 23:51:48 +0200 Subject: [PATCH 28/29] 2010-08-03 Robert Millan Fix grub-emu build. * include/grub/util/misc.h: Move `' to ... * include/grub/emu/misc.h: ... here. * include/grub/util/misc.h (grub_get_libzfs_handle): Move function ... * include/grub/emu/misc.h (grub_get_libzfs_handle): ... here. * util/misc.c: Remove `'. [HAVE_LIBZFS] (libzfs_handle, fini_libzfs) (grub_get_libzfs_handle): Move to ... * kern/emu/misc.c [HAVE_LIBZFS] (__libzfs_handle, fini_libzfs) (grub_get_libzfs_handle): ... here. --- ChangeLog | 16 ++++++++++++++++ include/grub/emu/misc.h | 3 +++ include/grub/util/misc.h | 3 --- kern/emu/misc.c | 27 ++++++++++++++++++++++++++- util/misc.c | 22 ---------------------- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index d4da9f96c..b3e7bc67f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2010-08-03 Robert Millan + + Fix grub-emu build. + + * include/grub/util/misc.h: Move `' to ... + * include/grub/emu/misc.h: ... here. + + * include/grub/util/misc.h (grub_get_libzfs_handle): Move function ... + * include/grub/emu/misc.h (grub_get_libzfs_handle): ... here. + + * util/misc.c: Remove `'. + [HAVE_LIBZFS] (libzfs_handle, fini_libzfs) + (grub_get_libzfs_handle): Move to ... + * kern/emu/misc.c [HAVE_LIBZFS] (__libzfs_handle, fini_libzfs) + (grub_get_libzfs_handle): ... here. + 2010-08-03 BVK Chaitanya * script/execute.c (grub_script_execute_cmdline): Check for NULL diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index 5047a9406..70cf05e0d 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -21,6 +21,7 @@ #include #include +#include #ifdef __CYGWIN__ # include @@ -75,4 +76,6 @@ extern char * canonicalize_file_name (const char *path); int grub_device_mapper_supported (void); #endif +libzfs_handle_t *grub_get_libzfs_handle (void); + #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 7ce3d3291..48dfbb868 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -29,7 +29,6 @@ #include #include #include -#include char *grub_util_get_path (const char *dir, const char *file); size_t grub_util_get_fp_size (FILE *fp); @@ -61,6 +60,4 @@ char *canonicalize_file_name (const char *path); void grub_util_init_nls (void); -libzfs_handle_t *grub_get_libzfs_handle (void); - #endif /* ! GRUB_UTIL_MISC_HEADER */ diff --git a/kern/emu/misc.c b/kern/emu/misc.c index 0d71ef3d6..0838dc3c0 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -45,8 +45,11 @@ # include #endif -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) +#ifdef HAVE_LIBZFS # include +#endif + +#ifdef HAVE_LIBNVPAIR # include #endif @@ -246,6 +249,28 @@ get_win32_path (const char *path) } #endif +#ifdef HAVE_LIBZFS +static libzfs_handle_t *__libzfs_handle; + +static void +fini_libzfs (void) +{ + libzfs_fini (__libzfs_handle); +} + +libzfs_handle_t * +grub_get_libzfs_handle (void) +{ + if (! __libzfs_handle) + { + __libzfs_handle = libzfs_init (); + atexit (fini_libzfs); + } + + return __libzfs_handle; +} +#endif /* HAVE_LIBZFS */ + #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* Not ZFS-specific in itself, but for now it's only used by ZFS-related code. */ char * diff --git a/util/misc.c b/util/misc.c index 274c182c2..21dd211e1 100644 --- a/util/misc.c +++ b/util/misc.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -295,27 +294,6 @@ grub_util_init_nls (void) #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ } -#ifdef HAVE_LIBZFS -static libzfs_handle_t *libzfs_handle; - -static void -fini_libzfs (void) -{ - libzfs_fini (libzfs_handle); -} - -libzfs_handle_t * -grub_get_libzfs_handle (void) -{ - if (! libzfs_handle) - { - libzfs_handle = libzfs_init (); - atexit (fini_libzfs); - } - - return libzfs_handle; -} -#endif /* HAVE_LIBZFS */ #endif /* GRUB_UTIL */ int From 62858144fe582fe4a908d277842cd50e00eba634 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 4 Aug 2010 00:15:29 +0200 Subject: [PATCH 29/29] 2010-08-04 Robert Millan Support OpenSolaris in ZFS device resolution. * configure.ac: Check for getmntany(). * kern/emu/misc.c [HAVE_GETMNTANY]: Include `'. [HAVE_GETMNTANY] (grub_find_zpool_from_mount_point): Add OpenSolaris support. --- ChangeLog | 9 +++++++++ configure.ac | 2 +- kern/emu/misc.c | 24 +++++++++++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3e7bc67f..958c55c79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-08-04 Robert Millan + + Support OpenSolaris in ZFS device resolution. + + * configure.ac: Check for getmntany(). + * kern/emu/misc.c [HAVE_GETMNTANY]: Include `'. + [HAVE_GETMNTANY] (grub_find_zpool_from_mount_point): Add OpenSolaris + support. + 2010-08-03 Robert Millan Fix grub-emu build. diff --git a/configure.ac b/configure.ac index 6169a2fb5..41072eb4f 100644 --- a/configure.ac +++ b/configure.ac @@ -247,7 +247,7 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat) +AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat getmntany) AC_CHECK_HEADERS(libzfs.h libnvpair.h) # For opendisk() and getrawpartition() on NetBSD. diff --git a/kern/emu/misc.c b/kern/emu/misc.c index 0838dc3c0..5a148c708 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -32,6 +32,10 @@ #include #endif +#ifdef HAVE_GETMNTANY +# include +#endif + #include #include #include @@ -340,7 +344,7 @@ grub_find_zpool_from_mount_point (const char *mnt_point, char **poolname, char * *poolname = *poolfs = NULL; -#ifdef HAVE_GETFSSTAT +#if defined(HAVE_GETFSSTAT) /* FreeBSD and GNU/kFreeBSD */ { int mnt_count = getfsstat (NULL, 0, MNT_WAIT); if (mnt_count == -1) @@ -363,6 +367,24 @@ grub_find_zpool_from_mount_point (const char *mnt_point, char **poolname, char * free (mnt); } +#elif defined(HAVE_GETMNTANY) /* OpenSolaris */ + { + FILE *mnttab = fopen ("/etc/mnttab", "r"); + struct mnttab mp; + struct mnttab mpref = + { + .mnt_special = NULL, + .mnt_mountp = mnt_point, + .mnt_fstype = "zfs", + .mnt_mntopts = NULL, + .mnt_time = NULL, + }; + + if (getmntany (mnttab, &mp, &mpref) == 0) + *poolname = xstrdup (mp.mnt_special); + + fclose (mnttab); + } #endif if (! *poolname)