Hello community, here is the log from the commit of package grub2 for openSUSE:Factory checked in at 2017-05-20 14:28:59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grub2 (Old) and /work/SRC/openSUSE:Factory/.grub2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "grub2" Sat May 20 14:28:59 2017 rev:162 rq:494786 version:2.02 Changes: -------- --- /work/SRC/openSUSE:Factory/grub2/grub2.changes 2017-05-06 20:45:24.786568924 +0200 +++ /work/SRC/openSUSE:Factory/.grub2.new/grub2.changes 2017-05-20 14:29:00.395274446 +0200 @@ -1,0 +2,9 @@ +Thu May 11 08:56:57 UTC 2017 - [email protected] + +- 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 + +------------------------------------------------------------------- New: ---- grub2-btrfs-09-get-default-subvolume.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ grub2.spec ++++++ --- /var/tmp/diff_new_pack.h3PFd5/_old 2017-05-20 14:29:02.710946816 +0200 +++ /var/tmp/diff_new_pack.h3PFd5/_new 2017-05-20 14:29:02.714946251 +0200 @@ -217,6 +217,7 @@ 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 @@ %patch106 -p1 %patch107 -p1 %patch108 -p1 +%patch109 -p1 %patch120 -p1 %patch121 -p1 %patch122 -p1 ++++++ grub2-btrfs-09-get-default-subvolume.patch ++++++ 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, ++++++ grub2-xen-pv-firmware.cfg ++++++ --- /var/tmp/diff_new_pack.h3PFd5/_old 2017-05-20 14:29:03.142885705 +0200 +++ /var/tmp/diff_new_pack.h3PFd5/_new 2017-05-20 14:29:03.146885139 +0200 @@ -3,6 +3,7 @@ insmod search insmod configfile insmod legacy_configfile +insmod lvm set debian_cddev="" set debian_cdarch="" @@ -43,9 +44,6 @@ 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 @@ " 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
