From 8559bdfc6f101e5ded69635fe8babd70414b6297a42d57ba9e013de55350c69a Mon Sep 17 00:00:00 2001 From: Dominique Leuenberger Date: Sat, 20 May 2017 12:28:59 +0000 Subject: [PATCH] Accepting request 494786 from Base:System 1 OBS-URL: https://build.opensuse.org/request/show/494786 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=162 --- grub2-btrfs-09-get-default-subvolume.patch | 263 +++++++++++++++++++++ grub2-xen-pv-firmware.cfg | 24 +- grub2.changes | 9 + grub2.spec | 2 + 4 files changed, 293 insertions(+), 5 deletions(-) create mode 100644 grub2-btrfs-09-get-default-subvolume.patch diff --git a/grub2-btrfs-09-get-default-subvolume.patch b/grub2-btrfs-09-get-default-subvolume.patch new file mode 100644 index 0000000..2fb991f --- /dev/null +++ b/grub2-btrfs-09-get-default-subvolume.patch @@ -0,0 +1,263 @@ +Index: grub-2.02~beta2/grub-core/fs/btrfs.c +=================================================================== +--- grub-2.02~beta2.orig/grub-core/fs/btrfs.c ++++ grub-2.02~beta2/grub-core/fs/btrfs.c +@@ -2439,6 +2439,238 @@ out: + return 0; + } + ++static grub_err_t ++grub_btrfs_get_parent_subvol_path (struct grub_btrfs_data *data, ++ grub_uint64_t child_id, ++ const char *child_path, ++ grub_uint64_t *parent_id, ++ char **path_out) ++{ ++ grub_uint64_t fs_root = 0; ++ struct grub_btrfs_key key_in = { ++ .object_id = child_id, ++ .type = GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF, ++ .offset = 0, ++ }, key_out; ++ struct grub_btrfs_root_ref *ref; ++ char *buf; ++ struct grub_btrfs_leaf_descriptor desc; ++ grub_size_t elemsize; ++ grub_disk_addr_t elemaddr; ++ grub_err_t err; ++ char *parent_path; ++ ++ *parent_id = 0; ++ *path_out = 0; ++ ++ err = lower_bound(data, &key_in, &key_out, data->sblock.root_tree, ++ &elemaddr, &elemsize, &desc, 0); ++ if (err) ++ return err; ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF || elemaddr == 0) ++ next(data, &desc, &elemaddr, &elemsize, &key_out); ++ ++ if (key_out.type != GRUB_BTRFS_ITEM_TYPE_ROOT_BACKREF) ++ { ++ free_iterator(&desc); ++ return grub_error(GRUB_ERR_FILE_NOT_FOUND, N_("can't find root backrefs")); ++ } ++ ++ buf = grub_malloc(elemsize + 1); ++ if (!buf) ++ { ++ free_iterator(&desc); ++ return grub_errno; ++ } ++ ++ err = grub_btrfs_read_logical(data, elemaddr, buf, elemsize, 0); ++ if (err) ++ { ++ grub_free(buf); ++ free_iterator(&desc); ++ return err; ++ } ++ ++ buf[elemsize] = 0; ++ ref = (struct grub_btrfs_root_ref *)buf; ++ ++ err = get_fs_root(data, data->sblock.root_tree, grub_le_to_cpu64 (key_out.offset), ++ 0, &fs_root); ++ if (err) ++ { ++ grub_free(buf); ++ free_iterator(&desc); ++ return err; ++ } ++ ++ find_pathname(data, grub_le_to_cpu64 (ref->dirid), fs_root, ref->name, &parent_path); ++ ++ if (child_path) ++ { ++ *path_out = grub_xasprintf ("%s/%s", parent_path, child_path); ++ grub_free (parent_path); ++ } ++ else ++ *path_out = parent_path; ++ ++ *parent_id = grub_le_to_cpu64 (key_out.offset); ++ ++ grub_free(buf); ++ free_iterator(&desc); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_btrfs_get_default_subvolume_id (struct grub_btrfs_data *data, grub_uint64_t *id) ++{ ++ grub_err_t err; ++ grub_disk_addr_t elemaddr; ++ grub_size_t elemsize; ++ struct grub_btrfs_key key, key_out; ++ struct grub_btrfs_dir_item *direl = NULL; ++ const char *ctoken = "default"; ++ grub_size_t ctokenlen = sizeof ("default") - 1; ++ ++ *id = 0; ++ key.object_id = data->sblock.root_dir_objectid; ++ key.type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; ++ key.offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen)); ++ err = lower_bound (data, &key, &key_out, data->sblock.root_tree, &elemaddr, &elemsize, ++ NULL, 0); ++ if (err) ++ return err; ++ ++ if (key_cmp (&key, &key_out) != 0) ++ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); ++ ++ struct grub_btrfs_dir_item *cdirel; ++ direl = grub_malloc (elemsize + 1); ++ err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize, 0); ++ if (err) ++ { ++ grub_free (direl); ++ return err; ++ } ++ for (cdirel = direl; ++ (grub_uint8_t *) cdirel - (grub_uint8_t *) direl ++ < (grub_ssize_t) elemsize; ++ cdirel = (void *) ((grub_uint8_t *) (direl + 1) ++ + grub_le_to_cpu16 (cdirel->n) ++ + grub_le_to_cpu16 (cdirel->m))) ++ { ++ if (ctokenlen == grub_le_to_cpu16 (cdirel->n) ++ && grub_memcmp (cdirel->name, ctoken, ctokenlen) == 0) ++ break; ++ } ++ if ((grub_uint8_t *) cdirel - (grub_uint8_t *) direl ++ >= (grub_ssize_t) elemsize) ++ { ++ grub_free (direl); ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); ++ return err; ++ } ++ ++ if (cdirel->key.type != GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM) ++ { ++ grub_free (direl); ++ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file not found")); ++ return err; ++ } ++ ++ *id = grub_le_to_cpu64 (cdirel->key.object_id); ++ return GRUB_ERR_NONE; ++} ++ ++static grub_err_t ++grub_cmd_btrfs_get_default_subvol (struct grub_extcmd_context *ctxt, ++ int argc, char **argv) ++{ ++ char *devname; ++ grub_device_t dev; ++ struct grub_btrfs_data *data; ++ grub_err_t err; ++ grub_uint64_t id; ++ char *subvol = NULL; ++ grub_uint64_t subvolid = 0; ++ char *varname = NULL; ++ char *output = NULL; ++ int path_only = ctxt->state[1].set; ++ int num_only = ctxt->state[2].set; ++ ++ if (ctxt->state[0].set) ++ varname = ctxt->state[0].arg; ++ ++ if (argc < 1) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); ++ ++ devname = grub_file_get_device_name(argv[0]); ++ if (!devname) ++ return grub_errno; ++ ++ dev = grub_device_open (devname); ++ grub_free (devname); ++ if (!dev) ++ return grub_errno; ++ ++ data = grub_btrfs_mount(dev); ++ if (!data) ++ { ++ grub_device_close (dev); ++ grub_dprintf ("btrfs", "failed to open fs\n"); ++ grub_errno = GRUB_ERR_NONE; ++ return 0; ++ } ++ ++ err = grub_btrfs_get_default_subvolume_id (data, &subvolid); ++ if (err) ++ { ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ return err; ++ } ++ ++ id = subvolid; ++ while (id != GRUB_BTRFS_ROOT_VOL_OBJECTID) ++ { ++ grub_uint64_t parent_id; ++ char *path_out; ++ ++ err = grub_btrfs_get_parent_subvol_path (data, grub_cpu_to_le64 (id), subvol, &parent_id, &path_out); ++ if (err) ++ { ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ return err; ++ } ++ ++ if (subvol) ++ grub_free (subvol); ++ subvol = path_out; ++ id = parent_id; ++ } ++ ++ if (num_only && path_only) ++ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T" /%s", subvolid, subvol); ++ else if (num_only) ++ output = grub_xasprintf ("%"PRIuGRUB_UINT64_T, subvolid); ++ else ++ output = grub_xasprintf ("/%s", subvol); ++ ++ if (varname) ++ grub_env_set(varname, output); ++ else ++ grub_printf ("%s\n", output); ++ ++ grub_free (output); ++ grub_free (subvol); ++ ++ grub_btrfs_unmount (data); ++ grub_device_close (dev); ++ ++ return GRUB_ERR_NONE; ++} ++ + static struct grub_fs grub_btrfs_fs = { + .name = "btrfs", + .dir = grub_btrfs_dir, +@@ -2457,6 +2689,7 @@ static struct grub_fs grub_btrfs_fs = { + static grub_command_t cmd_info; + static grub_command_t cmd_mount_subvol; + static grub_extcmd_t cmd_list_subvols; ++static grub_extcmd_t cmd_get_default_subvol; + + static char * + subvolid_set_env (struct grub_env_var *var __attribute__ ((unused)), +@@ -2527,6 +2760,11 @@ GRUB_MOD_INIT (btrfs) + "[-p|-n] [-o var] DEVICE", + "Print list of BtrFS subvolumes on " + "DEVICE.", options); ++ cmd_get_default_subvol = grub_register_extcmd("btrfs-get-default-subvol", ++ grub_cmd_btrfs_get_default_subvol, 0, ++ "[-p|-n] [-o var] DEVICE", ++ "Print default BtrFS subvolume on " ++ "DEVICE.", options); + grub_register_variable_hook ("btrfs_subvol", subvol_get_env, + subvol_set_env); + grub_register_variable_hook ("btrfs_subvolid", subvolid_get_env, diff --git a/grub2-xen-pv-firmware.cfg b/grub2-xen-pv-firmware.cfg index f793389..1d6c078 100644 --- a/grub2-xen-pv-firmware.cfg +++ b/grub2-xen-pv-firmware.cfg @@ -3,6 +3,7 @@ insmod part_gpt insmod search insmod configfile insmod legacy_configfile +insmod lvm set debian_cddev="" set debian_cdarch="" @@ -43,9 +44,6 @@ fi set hdcfg_list="\ /boot/grub2/grub.cfg \ -/@/boot/grub2/grub.cfg \ -/@/.snapshots/1/snapshot/boot/grub2/grub.cfg \ -/.snapshots/1/snapshot/boot/grub2/grub.cfg \ /grub2/grub.cfg\ " @@ -55,25 +53,41 @@ set hdlst_list="\ " for c in ${hdcfg_list}; do + btrfs_relative_path=1 if search -s hddev -f "${c}"; then + btrfs_relative_path=0 menuentry "${hddev} Boot From Hard Disk (${c})" "${hddev}" "${c}" { set root="${2}" set cfg="${3}" - configfile "${cfg}" + btrfs-get-default-subvol -p -o btrfs_default_subvol ($root) + if [ -n "${btrfs_default_subvol}" ]; then + configfile "${btrfs_default_subvol}${cfg}" + else + configfile "${cfg}" + fi } break fi + btrfs_relative_path=0 done for c in ${hdlst_list}; do + btrfs_relative_path=1 if search -s hddev -f "${c}"; then + btrfs_relative_path=0 menuentry "${hddev} Boot From Hard Disk (${c})" "${hddev}" "${c}" { set root="${2}" set cfg="${3}" - legacy_configfile "${cfg}" + btrfs-get-default-subvol -p -o btrfs_default_subvol ($root) + if [ -n "${btrfs_default_subvol}" ]; then + legacy_configfile "${btrfs_default_subvol}${cfg}" + else + legacy_configfile "${cfg}" + fi } break fi + btrfs_relative_path=0 done set timeout=0 diff --git a/grub2.changes b/grub2.changes index e9704bc..edfa131 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Thu May 11 08:56:57 UTC 2017 - mchang@suse.com + +- grub2-xen-pv-firmware.cfg: insmod lvm module as it's not auto-loaded + to support booting from lvm volume (bsc#1004324) +- Grub not working correctly with xen and btrfs snapshots (bsc#1026511) + * Add grub2-btrfs-09-get-default-subvolume.patch + * grub2-xen-pv-firmware.cfg : search path in default subvolume + ------------------------------------------------------------------- Thu Apr 27 18:39:21 UTC 2017 - arvidjaar@gmail.com diff --git a/grub2.spec b/grub2.spec index ac9b1a9..ecb77c2 100644 --- a/grub2.spec +++ b/grub2.spec @@ -217,6 +217,7 @@ Patch105: grub2-btrfs-05-grub2-mkconfig.patch Patch106: grub2-btrfs-06-subvol-mount.patch Patch107: grub2-btrfs-07-subvol-fallback.patch Patch108: grub2-btrfs-08-workaround-snapshot-menu-default-entry.patch +Patch109: grub2-btrfs-09-get-default-subvolume.patch # Support EFI xen loader Patch120: grub2-efi-xen-chainload.patch Patch121: grub2-efi-chainloader-root.patch @@ -478,6 +479,7 @@ swap partition while in resuming %patch106 -p1 %patch107 -p1 %patch108 -p1 +%patch109 -p1 %patch120 -p1 %patch121 -p1 %patch122 -p1