btrfs: use full bootloader area
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
parent
46317f98bf
commit
b256068060
163
0213-fs-btrfs-Use-full-btrfs-bootloader-area.patch
Normal file
163
0213-fs-btrfs-Use-full-btrfs-bootloader-area.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From 6e5b9bc2f1d2e3a10096716350fa67f48c199f5d Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Mon, 13 Dec 2021 14:25:49 +0800
|
||||
Subject: [PATCH] fs/btrfs: Use full btrfs bootloader area
|
||||
|
||||
Up to now GRUB can only embed to the first 64 KiB before primary
|
||||
superblock of btrfs, effectively limiting the GRUB core size. That
|
||||
could consequently pose restrictions to feature enablement like
|
||||
advanced zstd compression.
|
||||
|
||||
This patch attempts to utilize full unused area reserved by btrfs for
|
||||
the bootloader outlined in the document [1]:
|
||||
|
||||
The first 1MiB on each device is unused with the exception of primary
|
||||
superblock that is on the offset 64KiB and spans 4KiB.
|
||||
|
||||
Apart from that, adjacent sectors to superblock and first block group
|
||||
are not used for embedding in case of overflow and logged access to
|
||||
adjacent sectors could be useful for tracing it up.
|
||||
|
||||
This patch has been tested to provide out of the box support for btrfs
|
||||
zstd compression with which GRUB has been installed to the partition.
|
||||
|
||||
[1] https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit b0f06a81c6f31b6fa20be67a96b6683bba8210c9)
|
||||
---
|
||||
grub-core/fs/btrfs.c | 90 +++++++++++++++++++++++++++++++++++++-------
|
||||
include/grub/disk.h | 2 +
|
||||
2 files changed, 79 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 4cc86e9b7..07c0ff874 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -2476,6 +2476,33 @@ grub_btrfs_label (grub_device_t device, char **label)
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
+
|
||||
+struct embed_region {
|
||||
+ unsigned int start;
|
||||
+ unsigned int secs;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
|
||||
+ * The first 1 MiB on each device is unused with the exception of primary
|
||||
+ * superblock that is on the offset 64 KiB and spans 4 KiB.
|
||||
+ */
|
||||
+
|
||||
+static const struct {
|
||||
+ struct embed_region available;
|
||||
+ struct embed_region used[6];
|
||||
+} btrfs_head = {
|
||||
+ .available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */
|
||||
+ .used = {
|
||||
+ {0, 1}, /* boot.S. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */
|
||||
+ {0, 0} /* Array terminator. */
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
static grub_err_t
|
||||
grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
|
||||
unsigned int *nsectors,
|
||||
@@ -2483,25 +2510,62 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
|
||||
grub_embed_type_t embed_type,
|
||||
grub_disk_addr_t **sectors)
|
||||
{
|
||||
- unsigned i;
|
||||
+ unsigned int i, j, n = 0;
|
||||
+ const struct embed_region *u;
|
||||
+ grub_disk_addr_t *map;
|
||||
|
||||
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"BtrFS currently supports only PC-BIOS embedding");
|
||||
|
||||
- if (64 * 2 - 1 < *nsectors)
|
||||
- return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
- N_("your core.img is unusually large. "
|
||||
- "It won't fit in the embedding area"));
|
||||
-
|
||||
- *nsectors = 64 * 2 - 1;
|
||||
- if (*nsectors > max_nsectors)
|
||||
- *nsectors = max_nsectors;
|
||||
- *sectors = grub_calloc (*nsectors, sizeof (**sectors));
|
||||
- if (!*sectors)
|
||||
+ map = grub_calloc (btrfs_head.available.secs, sizeof (*map));
|
||||
+ if (map == NULL)
|
||||
return grub_errno;
|
||||
- for (i = 0; i < *nsectors; i++)
|
||||
- (*sectors)[i] = i + 1;
|
||||
+
|
||||
+ /*
|
||||
+ * Populating the map array so that it can be used to index if a disk
|
||||
+ * address is available to embed:
|
||||
+ * - 0: available,
|
||||
+ * - 1: unavailable.
|
||||
+ */
|
||||
+ for (u = btrfs_head.used; u->secs; ++u)
|
||||
+ {
|
||||
+ unsigned int end = u->start + u->secs;
|
||||
+
|
||||
+ if (end > btrfs_head.available.secs)
|
||||
+ end = btrfs_head.available.secs;
|
||||
+ for (i = u->start; i < end; ++i)
|
||||
+ map[i] = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Adding up n until it matches total size of available embedding area. */
|
||||
+ for (i = 0; i < btrfs_head.available.secs; ++i)
|
||||
+ if (map[i] == 0)
|
||||
+ n++;
|
||||
+
|
||||
+ if (n < *nsectors)
|
||||
+ {
|
||||
+ grub_free (map);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ N_("your core.img is unusually large. "
|
||||
+ "It won't fit in the embedding area"));
|
||||
+ }
|
||||
+
|
||||
+ if (n > max_nsectors)
|
||||
+ n = max_nsectors;
|
||||
+
|
||||
+ /*
|
||||
+ * Populating the array so that it can used to index disk block address for
|
||||
+ * an image file's offset to be embedded on disk (the unit is in sectors):
|
||||
+ * - i: The disk block address relative to btrfs_head.available.start,
|
||||
+ * - j: The offset in image file.
|
||||
+ */
|
||||
+ for (i = 0, j = 0; i < btrfs_head.available.secs && j < n; ++i)
|
||||
+ if (map[i] == 0)
|
||||
+ map[j++] = btrfs_head.available.start + i;
|
||||
+
|
||||
+ *nsectors = n;
|
||||
+ *sectors = map;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
diff --git a/include/grub/disk.h b/include/grub/disk.h
|
||||
index f95aca929..06210a704 100644
|
||||
--- a/include/grub/disk.h
|
||||
+++ b/include/grub/disk.h
|
||||
@@ -182,6 +182,8 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
|
||||
/* Return value of grub_disk_native_sectors() in case disk size is unknown. */
|
||||
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
|
||||
|
||||
+#define GRUB_DISK_KiB_TO_SECTORS(x) ((x) << (10 - GRUB_DISK_SECTOR_BITS))
|
||||
+
|
||||
/* Convert sector number from one sector size to another. */
|
||||
static inline grub_disk_addr_t
|
||||
grub_convert_sector (grub_disk_addr_t sector,
|
||||
--
|
||||
2.34.1
|
||||
|
@ -210,3 +210,4 @@ Patch0209: 0209-fs-xfs-Fix-unreadable-filesystem-with-v4-superblock.patch
|
||||
Patch0210: 0210-Print-module-name-on-license-check-failure.patch
|
||||
Patch0211: 0211-powerpc-ieee1275-load-grub-at-4MB-not-2MB.patch
|
||||
Patch0212: 0212-grub-mkconfig-restore-umask-for-grub.cfg.patch
|
||||
Patch0213: 0213-fs-btrfs-Use-full-btrfs-bootloader-area.patch
|
||||
|
@ -14,7 +14,7 @@
|
||||
Name: grub2
|
||||
Epoch: 1
|
||||
Version: 2.06
|
||||
Release: 11%{?dist}
|
||||
Release: 12%{?dist}
|
||||
Summary: Bootloader with support for Linux, Multiboot and more
|
||||
License: GPLv3+
|
||||
URL: http://www.gnu.org/software/grub/
|
||||
@ -523,6 +523,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Jan 06 2022 Robbie Harwood <rharwood@redhat.com> - 2.06-12
|
||||
- btrfs: use full bootloader area
|
||||
|
||||
* Fri Dec 10 2021 Robbie Harwood <rharwood@redhat.com> - 2.06-11
|
||||
- Bump to rerun signing (no code changes)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user