grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Use full btrfs bootloader area


From: Daniel Kiper
Subject: Re: [PATCH] Use full btrfs bootloader area
Date: Wed, 1 Dec 2021 17:16:56 +0100
User-agent: NeoMutt/20170113 (1.7.2)

On Tue, Nov 02, 2021 at 04:11:06PM +0800, Michael Chang via Grub-devel wrote:
> Up to now grub can only embed to the first 64 KiB before primary

s/grub/GRUB/

> superblock of btrfs, effectively limiting the size that could
> consequently pose restrictions to feature enablement like advancing zstd

s/advancing/advanced/?

> compression.
>
> This patch attempts to utilize full unused area reserved by btrfs for
> bootloader outlined in the document [1] where this paragraph quoted.
>
> "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 it's tracing.

What do you mean by "it's tracing" here?

> This patch has been tested to provide out of the box support to btrfs
> zstd compression with which grub has been installed to the partition.

s/grub/GRUB/

> [1] 
> https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
>
> Signed-off-by: Michael Chang <mchang@suse.com>
> ---
>  grub-core/fs/btrfs.c | 80 +++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 67 insertions(+), 13 deletions(-)
>
> diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
> index 63203034d..dcd4635f1 100644
> --- a/grub-core/fs/btrfs.c
> +++ b/grub-core/fs/btrfs.c
> @@ -2159,6 +2159,35 @@ grub_btrfs_label (grub_device_t device, char **label)
>  }
>
>  #ifdef GRUB_UTIL
> +
> +struct embed_region {
> +  unsigned int offset;

s/offset/start/

> +  unsigned int len;

s/len/secs/

> +};
> +
> +#define KB_TO_SECTOR(x) ((x) << 1)

I think this macro belongs to the include/grub/disk.h. Additionally, it
should be named, e.g., KiB_TO_GRUB_DISK_SECS and use GRUB_DISK_SECTOR_BITS.

> +/*
> + * 
> https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
> + * The first 1MiB on each device is unused with the exception of primary
> + * superblock that is on the offset 64KiB and spans 4KiB.
> + */
> +
> +static const struct {
> +  struct embed_region available;
> +  struct embed_region used[6];
> +} area = {

s/area/btrfs_head/?

> +  .available = {0, KB_TO_SECTOR(1024)}, /* The first 1MiB */

Missing space between KB_TO_SECTOR and "(".

> +  .used = {
> +    {0, 1},                              /* boot.S */
> +    {KB_TO_SECTOR(64) - 1, 1},           /* overflow guard */

Ditto and below...

> +    {KB_TO_SECTOR(64), KB_TO_SECTOR(4)}, /* 4KiB superblock */
> +    {KB_TO_SECTOR(68), 1},               /* overflow guard */
> +    {KB_TO_SECTOR(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,
> @@ -2166,25 +2195,50 @@ 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;
> +  const struct embed_region *u;
> +  grub_disk_addr_t *map;
> +  unsigned int n = 0;
>
>    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 (area.available.len, sizeof (*map));
> +  if (!map)

if (map == NULL)

>      return grub_errno;
> -  for (i = 0; i < *nsectors; i++)
> -    (*sectors)[i] = i + 1;
> +
> +  for (u = area.used; u->len; ++u)
> +    {
> +      unsigned int end = u->offset + u->len;
> +
> +      if (end > area.available.len)
> +        end = area.available.len;
> +      for (i = u->offset; i < end; ++i)
> +        map[i] = 1;
> +    }
> +
> +  for (i = 0; i < area.available.len; ++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;
> +
> +  for (i = 0, j = 0; i < area.available.len && j < n; ++i)
> +    if (map[i] == 0)
> +      map[j++] = area.available.offset + i;

I am not fully sure what is happening in this loop. In general I would
be happy if you add more comments before each step in the code above.

Daniel



reply via email to

[Prev in Thread] Current Thread [Next in Thread]