diff --git a/debian/changelog b/debian/changelog index 93cd07f7d..598ec7552 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +grub2 (1.99-14) unstable; urgency=low + + * Rewrite no_libzfs.patch using a different approach. (Closes: #648539) + + -- Robert Millan Sun, 13 Nov 2011 00:14:38 +0100 + grub2 (1.99-13) unstable; urgency=low [ Debconf translations ] diff --git a/debian/patches/no_libzfs.patch b/debian/patches/no_libzfs.patch index 66c2a89a7..2c29986a6 100644 --- a/debian/patches/no_libzfs.patch +++ b/debian/patches/no_libzfs.patch @@ -1,216 +1,155 @@ ---- a/grub-core/fs/zfs/zfs.c -+++ b/grub-core/fs/zfs/zfs.c -@@ -53,6 +53,10 @@ - #include - #include - -+#ifdef GRUB_UTIL -+#include -+#endif -+ - GRUB_MOD_LICENSE ("GPLv3+"); - - #define ZPOOL_PROP_BOOTFS "bootfs" -@@ -3039,6 +3043,129 @@ - return GRUB_ERR_NONE; - } - -+struct grub_zfs_vdev -+{ -+ const char *name; -+ struct grub_zfs_vdev *next; -+}; -+ -+struct grub_zfs_pool -+{ -+ grub_uint64_t guid; -+ char *name; -+ struct grub_zfs_vdev *vdev_list; -+ struct grub_zfs_pool *next; -+}; -+ -+static struct grub_zfs_pool *zpool_list; -+ -+static int -+zfs_scan_device (const char *name) -+{ -+ grub_device_t device; -+ struct grub_zfs_data *data; -+ char *nvlist; -+ grub_uint64_t guid; -+ char *label; -+ struct grub_zfs_pool *zpool; -+ struct grub_zfs_vdev *vdev; -+ -+#ifdef GRUB_UTIL -+ grub_util_info ("scanning %s for ZFS", name); -+#endif -+ -+ device = grub_device_open (name); -+ if (! device) -+ return 0; -+ -+ data = zfs_mount (device); -+ if (! data) -+ goto end1; -+ -+ if (zfs_fetch_nvlist (data->device_original, &nvlist)) -+ goto end2; -+ -+ if (! grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid)) -+ goto end3; -+ -+ label = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME); -+ if (! label) -+ goto end3; -+ -+ vdev = grub_zalloc (sizeof (*vdev)); -+ vdev->name = grub_strdup (name); -+ -+ struct grub_zfs_pool *i; -+ for (i = zpool_list; i; i = i->next) -+ { -+ if (guid == i->guid) -+ { -+ /* This vdev belongs to an already-registered pool. */ -+ vdev->next = i->vdev_list; -+ i->vdev_list = vdev; -+ return 0; -+ } -+ } -+ -+ /* Create a new ZFS pool with this vdev. */ -+ zpool = grub_zalloc (sizeof (*zpool)); -+ zpool->guid = guid; -+ zpool->name = grub_xasprintf ("zfs/%s", label); -+ zpool->vdev_list = vdev; -+ -+ /* Insert it to ZFS pool list. */ -+ zpool->next = zpool_list; -+ zpool_list = zpool; -+ -+ end3: -+ grub_free (nvlist); -+ end2: -+ zfs_unmount (data); -+ end1: -+ grub_device_close (device); -+ -+ return 0; -+} -+ -+static int -+grub_zpool_iterate (int (*hook) (const char *name)) -+{ -+ struct grub_zfs_pool *i; -+ for (i = zpool_list; i; i = i->next) -+ { -+ if (hook (i->name)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static grub_err_t -+grub_zpool_open (const char *name, grub_disk_t disk) -+{ -+ struct grub_zfs_pool *i; -+ for (i = zpool_list; i; i = i->next) -+ { -+ if (! grub_strcmp (i->name, name)) -+ { -+ /* For now just pick the first vdev as lower layer. */ -+ grub_disk_t lower = grub_disk_open (i->vdev_list->name); -+ grub_memcpy (disk, lower, sizeof (*disk)); -+ return GRUB_ERR_NONE; -+ } -+ } -+ -+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a ZFS pool"); -+} -+ -+static struct grub_disk_dev grub_zpool_dev = -+ { -+ .name = "zfs", -+ .id = GRUB_DISK_DEVICE_ZFS_ID, -+ .iterate = grub_zpool_iterate, -+ .open = grub_zpool_open, -+ }; -+ - /* - * zfs_open() locates a file in the rootpool by following the - * MOS and places the dnode of the file in the memory address DNODE. -@@ -3490,6 +3617,8 @@ - GRUB_MOD_INIT (zfs) - { - COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE); -+ grub_device_iterate (&zfs_scan_device); -+ grub_disk_dev_register (&grub_zpool_dev); - grub_fs_register (&grub_zfs_fs); - #ifndef GRUB_UTIL - my_mod = mod; -@@ -3498,5 +3627,9 @@ - - GRUB_MOD_FINI (zfs) - { -+ grub_disk_dev_unregister (&grub_zpool_dev); -+ zpool_list = NULL; -+ /* FIXME: free the zpool list. */ -+ - grub_fs_unregister (&grub_zfs_fs); - } ---- a/grub-core/kern/disk.c -+++ b/grub-core/kern/disk.c -@@ -269,6 +269,7 @@ - - for (dev = grub_disk_dev_list; dev; dev = dev->next) - { -+ disk->dev = dev; - if ((dev->open) (raw, disk) == GRUB_ERR_NONE) - break; - else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) -@@ -283,8 +284,6 @@ - goto fail; - } - -- disk->dev = dev; -- - if (p) - { - disk->partition = grub_partition_probe (disk, p + 1); --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c -@@ -626,6 +626,28 @@ - return grub_find_device ("/dev/mapper", dev); - } +@@ -32,6 +32,9 @@ + #include + #include + #include ++#ifdef HAVE_LIMITS_H ++#include ++#endif + #include + #include -+ /* Check for ZFS. */ -+ if (!os_dev) +@@ -238,7 +241,67 @@ + + #endif /* __linux__ */ + +-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) ++static char * ++find_device_from_pool (const char *poolname) ++{ ++ char *device; ++ char *cmd; ++ FILE *fp; ++ int ret; ++ char *line; ++ size_t len; ++ int st; ++ ++ char name[PATH_MAX], state[256], readlen[256], writelen[256], cksum[256], notes[256]; ++ unsigned int dummy; ++ ++ asprintf (&cmd, "zpool status %s", poolname); ++ fp = popen (cmd, "r"); ++ free (cmd); ++ ++ st = 0; ++ while (st < 3) + { -+ char *pool; -+ char *fs; -+ -+ grub_find_zpool_from_dir (dir, &pool, &fs); -+ -+ if (pool) ++ line = NULL; ++ ret = getline (&line, &len, fp); ++ if (ret == -1) + { -+ os_dev = xasprintf ("zfs/%s", pool); -+ free (pool); ++ pclose (fp); ++ return NULL; + } + -+ if (fs) -+ free (fs); ++ if (sscanf (line, " %s %s %s %s %s %s", name, state, readlen, writelen, cksum, notes) >= 5) ++ switch (st) ++ { ++ case 0: ++ if (!strcmp (name, "NAME") ++ && !strcmp (state, "STATE") ++ && !strcmp (readlen, "READ") ++ && !strcmp (writelen, "WRITE") ++ && !strcmp (cksum, "CKSUM")) ++ st++; ++ break; ++ case 1: ++ if (!strcmp (name, poolname)) ++ st++; ++ break; ++ case 2: ++ if (strcmp (name, "mirror") && !sscanf (name, "mirror-%u", &dummy) ++ && !sscanf (name, "raidz%u", &dummy) ++ && !strcmp (state, "ONLINE")) ++ st++; ++ break; ++ } ++ ++ free (line); + } ++ pclose (fp); + -+ if (! strncmp (os_dev, "zfs/", sizeof ("zfs/")-1)) -+ /* This kind of abstraction doesn't provide device nodes. */ -+ return os_dev; ++ asprintf (&device, "/dev/%s", name); + - if (stat (dir, &st) < 0) - grub_util_error ("cannot stat `%s'", dir); ++ return device; ++} ++ + static char * + find_root_device_from_libzfs (const char *dir) + { +@@ -250,49 +313,7 @@ + if (! poolname) + return NULL; -@@ -708,7 +730,7 @@ +- { +- zpool_handle_t *zpool; +- libzfs_handle_t *libzfs; +- nvlist_t *config, *vdev_tree; +- nvlist_t **children, **path; +- unsigned int nvlist_count; +- unsigned int i; +- +- libzfs = grub_get_libzfs_handle (); +- if (! libzfs) +- return NULL; +- +- zpool = zpool_open (libzfs, poolname); +- config = zpool_get_config (zpool, NULL); +- +- if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0) +- error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")"); +- +- if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0) +- error (1, errno, "nvlist_lookup_nvlist_array (\"children\")"); +- assert (nvlist_count > 0); +- +- while (nvlist_lookup_nvlist_array (children[0], "children", +- &children, &nvlist_count) == 0) +- assert (nvlist_count > 0); +- +- for (i = 0; i < nvlist_count; i++) +- { +- if (nvlist_lookup_string (children[i], "path", &device) != 0) +- error (1, errno, "nvlist_lookup_string (\"path\")"); +- +- struct stat st; +- if (stat (device, &st) == 0) +- { +- device = xstrdup (device); +- break; +- } +- +- device = NULL; +- } +- +- zpool_close (zpool); +- } ++ device = find_device_from_pool (poolname); + + free (poolname); + if (poolfs) +@@ -300,7 +321,6 @@ + + return device; + } +-#endif + + #ifdef __MINGW32__ + +@@ -603,10 +623,8 @@ + os_dev = grub_find_root_device_from_mountinfo (dir, NULL); + #endif /* __linux__ */ + +-#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + if (!os_dev) + os_dev = find_root_device_from_libzfs (dir); +-#endif + + if (os_dev) + { +@@ -708,7 +726,7 @@ } int @@ -219,27 +158,6 @@ { #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) /* User explicitly claims that this drive is visible by BIOS. */ -@@ -732,6 +754,9 @@ - return GRUB_DEV_ABSTRACTION_LVM; - #endif - -+ if (!strncmp (os_dev, "zfs/", sizeof ("zfs/")-1)) -+ return GRUB_DEV_ABSTRACTION_ZFS; -+ - /* No abstraction found. */ - return GRUB_DEV_ABSTRACTION_NONE; - } -@@ -948,6 +973,10 @@ - break; - #endif /* __linux__ */ - -+ case GRUB_DEV_ABSTRACTION_ZFS: -+ grub_dev = xstrdup (os_dev); -+ break; -+ - default: /* GRUB_DEV_ABSTRACTION_NONE */ - grub_dev = grub_util_biosdisk_get_grub_dev (os_dev); - } --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -287,7 +287,6 @@ @@ -307,54 +225,3 @@ ret = buf3; return ret; ---- a/include/grub/disk.h -+++ b/include/grub/disk.h -@@ -42,7 +42,8 @@ - GRUB_DISK_DEVICE_PXE_ID, - GRUB_DISK_DEVICE_SCSI_ID, - GRUB_DISK_DEVICE_FILE_ID, -- GRUB_DISK_DEVICE_LUKS_ID -+ GRUB_DISK_DEVICE_LUKS_ID, -+ GRUB_DISK_DEVICE_ZFS_ID, - }; - - struct grub_disk; ---- a/include/grub/emu/getroot.h -+++ b/include/grub/emu/getroot.h -@@ -25,6 +25,7 @@ - GRUB_DEV_ABSTRACTION_NONE, - GRUB_DEV_ABSTRACTION_LVM, - GRUB_DEV_ABSTRACTION_RAID, -+ GRUB_DEV_ABSTRACTION_ZFS, - }; - - char *grub_find_device (const char *dir, dev_t dev); ---- a/util/grub-probe.c -+++ b/util/grub-probe.c -@@ -99,6 +99,8 @@ - - if (path == NULL) - { -+ if (strncmp (device_name, "zfs/", sizeof ("zfs/")-1)) -+ { - #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) - if (! grub_util_check_char_device (device_name)) - grub_util_error ("%s is not a character device", device_name); -@@ -106,6 +108,7 @@ - if (! grub_util_check_block_device (device_name)) - grub_util_error ("%s is not a block device", device_name); - #endif -+ } - } - else - { -@@ -188,6 +191,9 @@ - if (is_lvm) - printf ("lvm "); - -+ if (dev->disk->dev->id == GRUB_DISK_DEVICE_ZFS_ID) -+ printf ("zfs "); -+ - printf ("\n"); - - goto end;