grub-devel
[Top][All Lists]
Advanced

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

Re: [PATCH 3/4] Add ZFS envblock functions


From: Daniel Kiper
Subject: Re: [PATCH 3/4] Add ZFS envblock functions
Date: Tue, 3 Mar 2020 16:26:23 +0100
User-agent: NeoMutt/20170113 (1.7.2)

On Tue, Feb 25, 2020 at 11:26:45AM -0800, Paul Dagnelie wrote:
> This patch adds a ZFS implementation of the new envblock functions,
> storing the data for the envblock in the second padding area of the
> label. This data is protected by an embedded checksum and is stored
> redundantly, so even though it is not part of the block tree it
> provides reasonable reliability.
>
> commit 0f108fee27917afd72d834620db8f8b1e7ca1699
> Author:     Paul Dagnelie <address@hidden>
> AuthorDate: Mon Feb 24 14:29:35 2020 -0800
> Commit:     Paul Dagnelie <address@hidden>
> CommitDate: Tue Feb 25 10:08:08 2020 -0800
>
>     Add ZFS envblock functions
> ---
>  grub-core/fs/zfs/zfs.c       | 129 
> +++++++++++++++++++++++++++++++++++++++----
>  include/grub/zfs/vdev_impl.h |  33 ++++++-----
>  2 files changed, 134 insertions(+), 28 deletions(-)
>
> diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
> index 2f72e42bf..1ee9dd56b 100644
> --- a/grub-core/fs/zfs/zfs.c
> +++ b/grub-core/fs/zfs/zfs.c
> @@ -30,6 +30,7 @@
>   *
>   */
>
> +#include <stddef.h>
>  #include <grub/err.h>
>  #include <grub/file.h>
>  #include <grub/mm.h>
> @@ -1146,7 +1147,6 @@ scan_disk (grub_device_t dev, struct grub_zfs_data 
> *data,
>  {
>    int label = 0;
>    uberblock_phys_t *ub_array, *ubbest = NULL;
> -  vdev_boot_header_t *bh;
>    grub_err_t err;
>    int vdevnum;
>    struct grub_zfs_device_desc desc;
> @@ -1155,13 +1155,6 @@ scan_disk (grub_device_t dev, struct grub_zfs_data 
> *data,
>    if (!ub_array)
>      return grub_errno;
>
> -  bh = grub_malloc (VDEV_BOOT_HEADER_SIZE);
> -  if (!bh)
> -    {
> -      grub_free (ub_array);
> -      return grub_errno;
> -    }
> -
>    vdevnum = VDEV_LABELS;
>
>    desc.dev = dev;
> @@ -1175,7 +1168,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data 
> *data,
>      {
>        desc.vdev_phys_sector
>      = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)
> -    + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT)
> +    + ((VDEV_PAD_SIZE * 2) >> SPA_MINBLOCKSHIFT)
>      + (label < VDEV_LABELS / 2 ? 0 :
>         ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t))
>         - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT));
> @@ -1184,6 +1177,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data 
> *data,
>        err = grub_disk_read (dev->disk, desc.vdev_phys_sector
>                  + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT),
>                  0, VDEV_UBERBLOCK_RING, (char *) ub_array);
> +      if (label == 0)

This change looks strange...

>        if (err)
>      {
>        grub_errno = GRUB_ERR_NONE;
> @@ -1219,12 +1213,10 @@ scan_disk (grub_device_t dev, struct
> grub_zfs_data *data,
>      continue;
>  #endif
>        grub_free (ub_array);
> -      grub_free (bh);
>        return GRUB_ERR_NONE;
>      }
>
>    grub_free (ub_array);
> -  grub_free (bh);
>
>    return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
>  }
> @@ -3765,6 +3757,58 @@ zfs_mtime (grub_device_t device, grub_int32_t *mt)
>    return GRUB_ERR_NONE;
>  }
>
> +static grub_err_t
> +zfs_devs_read_zbt (struct grub_zfs_data *data, grub_uint64_t offset,
> char *buf, grub_size_t len)
> +{
> +  grub_err_t err = GRUB_ERR_NONE;
> +  zio_cksum_t zc;
> +  unsigned int i;
> +  ZIO_SET_CHECKSUM(&zc, offset, 0, 0, 0);
> +
> +  for (i = 0; i < data->n_devices_attached; i++)
> +    {
> +      err = grub_disk_read (data->devices_attached[i].dev->disk,
> +                offset >> SPA_MINBLOCKSHIFT,
> +                offset & ((1 << SPA_MINBLOCKSHIFT) - 1),
> +                len, buf);
> +      if (err)
> +    continue;
> +      ZIO_SET_CHECKSUM(&zc, offset, 0, 0, 0);
> +      err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL,
> GRUB_ZFS_LITTLE_ENDIAN,
> +                 buf, len);
> +      if (!err)
> +    return GRUB_ERR_NONE;
> +    }
> +  return err;
> +}
> +
> +static grub_err_t
> +grub_zfs_envblk_open (struct grub_file *file)
> +{
> +  grub_err_t err;
> +  struct grub_zfs_data *data;
> +  vdev_boot_envblock_t *vbe;
> +  int l;

Please add empty line here...

> +  file->offset = 0;
> +  data = zfs_mount (file->device);
> +  file->data = data;
> +  data->file_buf = grub_malloc (sizeof (vdev_boot_envblock_t));
> +  for (l = 0; l < VDEV_LABELS / 2; l++)
> +    {
> +      grub_uint64_t offset = l * sizeof (vdev_label_t) + offsetof
> (vdev_label_t, vl_be);

Ditto...

> +      err = zfs_devs_read_zbt (data, offset, data->file_buf,
> +                   sizeof (vdev_boot_envblock_t));

Why does open read?

> +      if (err == GRUB_ERR_NONE)
> +    {
> +      vbe = (vdev_boot_envblock_t *)data->file_buf;
> +      file->size = grub_strlen (vbe->vbe_bootenv);
> +      return err;
> +    }
> +    }
> +  zfs_unmount (data);
> +  return err;
> +}
> +
>  /*
>   * zfs_open() locates a file in the rootpool by following the
>   * MOS and places the dnode of the file in the memory address DNODE.
> @@ -3850,6 +3894,19 @@ grub_zfs_open (struct grub_file *file, const
> char *fsfilename)
>    return GRUB_ERR_NONE;
>  }
>
> +static grub_ssize_t
> +grub_zfs_envblk_read (grub_file_t file, char *buf, grub_size_t len)
> +{
> +  struct grub_zfs_data *data = (struct grub_zfs_data *) file->data;
> +  grub_ssize_t olen = len;
> +  grub_uint64_t offset = file->offset + offsetof
> (vdev_boot_envblock_t, vbe_bootenv);
> +
> +  if (len + file->offset > file->size)
> +    olen = file->size - file->offset;
> +  grub_memmove (buf, data->file_buf + offset, olen);

I think that read should happen here...

> +  return olen;
> +}
> +
>  static grub_ssize_t
>  grub_zfs_read (grub_file_t file, char *buf, grub_size_t len)
>  {
> @@ -3859,6 +3916,9 @@ grub_zfs_read (grub_file_t file, char *buf,
> grub_size_t len)
>    grub_size_t read;
>    grub_err_t err;
>
> +  if (grub_file_envblk (file))
> +      return grub_zfs_envblk_read (file, buf, len);

Is it regular ZFS read? If it is I think that it should return contents
of regular envblk file on the file system even if special region is used
for that.

> +
>    /*
>     * If offset is in memory, move it into the buffer provided and return.
>     */
> @@ -3924,6 +3984,49 @@ grub_zfs_read (grub_file_t file, char *buf,
> grub_size_t len)
>    return len;
>  }
>
> +static grub_err_t
> +grub_zfs_envblk_write (struct grub_file *file, char *buf, grub_size_t len)
> +{
> +  grub_uint64_t offset = file->offset + offsetof
> (vdev_boot_envblock_t, vbe_bootenv);
> +  grub_err_t err = GRUB_ERR_NONE;
> +  struct grub_zfs_data *data = file->data;
> +  unsigned int i, l;
> +  zio_cksum_t cksum;
> +  vdev_boot_envblock_t *vbe = (vdev_boot_envblock_t *)data->file_buf;
> +  if (len + file->offset > file->size)
> +    return GRUB_ERR_OUT_OF_RANGE;
> +
> +  grub_memmove (data->file_buf + offset, buf, len);
> +
> +  for (l = 0; l < VDEV_LABELS / 2; l++)
> +    {
> +      offset = l * sizeof (vdev_label_t) + offsetof (vdev_label_t, vl_be);
> +      vbe->vbe_zbt.zec_magic = ZEC_MAGIC;
> +      ZIO_SET_CHECKSUM(&vbe->vbe_zbt.zec_cksum, offset, 0, 0, 0);
> +      vbe->vbe_zbt.zec_magic = ZEC_MAGIC;
> +      zio_checksum_SHA256(vbe, VDEV_PAD_SIZE, GRUB_ZFS_LITTLE_ENDIAN, 
> &cksum);
> +      vbe->vbe_zbt.zec_cksum = cksum;
> +
> +      for (i = 0; i < data->n_devices_attached; i++)
> +    {
> +      struct grub_zfs_device_desc *desc = &data->devices_attached[i];
> +      int num_sectors = VDEV_PAD_SIZE >> desc->ashift;
> +      int label_seek = l * sizeof (vdev_label_t) >> desc->ashift;
> +      int j;

Empty line here...

Daniel



reply via email to

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