SHA256
1
0
forked from pool/grub2

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
This commit is contained in:
Dominique Leuenberger 2017-05-20 12:28:59 +00:00 committed by Git OBS Bridge
parent 6d75b85fc1
commit 8559bdfc6f
4 changed files with 293 additions and 5 deletions

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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