grub-devel
[Top][All Lists]
Advanced

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

Re: [PATCH 7/7] Add raid6 recovery.


From: Goffredo Baroncelli
Subject: Re: [PATCH 7/7] Add raid6 recovery.
Date: Wed, 9 May 2018 21:40:53 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.7.0

On 05/09/2018 06:58 PM, Daniel Kiper wrote:
> On Tue, Apr 24, 2018 at 09:13:16PM +0200, Goffredo Baroncelli wrote:
>> The code origins from "raid6_recovery.c". The code was changed because the
>> original one assumed that both the disk address and size are multiple of
>> GRUB_DISK_SECTOR_SIZE. This is not true for grub btrfs driver.
>>
>> The code was made more generalized using a function pointer for reading
>> the data from the memory or disk.
>>
>> Signed-off-by: Goffredo Baroncelli <address@hidden>
>> ---
>>  grub-core/fs/btrfs.c | 211 +++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 204 insertions(+), 7 deletions(-)
>>
>> diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
>> index 5c76a68f3..195313a31 100644
>> --- a/grub-core/fs/btrfs.c
>> +++ b/grub-core/fs/btrfs.c
>> @@ -30,6 +30,7 @@
>>  #include <grub/i18n.h>
>>  #include <grub/btrfs.h>
>>  #include <grub/crypto.h>
>> +#include <grub/diskfilter.h>
>>
>>  GRUB_MOD_LICENSE ("GPLv3+");
>>
>> @@ -695,19 +696,215 @@ rebuild_raid5 (struct raid56_buffer *buffers, 
>> grub_uint64_t nstripes,
>>                         csize);
>>  }
>>
>> +
>> +/* copied from raid6_recover */
>> +/* x**y.  */
>> +static grub_uint8_t powx[255 * 2];
>> +/* Such an s that x**s = y */
>> +static unsigned powx_inv[256];
>> +static const grub_uint8_t poly = 0x1d;
> 
> Could you define this as a constant?
In the original code from raid6_recover.c is the same. I prefer to not diverge 
too much.
> 
>> +static void
>> +grub_raid_block_mulx (unsigned mul, char *buf, grub_size_t size)
>> +{
>> +  grub_size_t i;
>> +  grub_uint8_t *p;
>> +
>> +  p = (grub_uint8_t *) buf;
>> +  for (i = 0; i < size; i++, p++)
>> +    if (*p)
>> +      *p = powx[mul + powx_inv[*p]];
>> +}
>> +
>> +static void
>> +grub_raid6_init_table (void)
>> +{
>> +  unsigned i;
>> +
>> +  grub_uint8_t cur = 1;
>> +  for (i = 0; i < 255; i++)
>> +    {
>> +      powx[i] = cur;
>> +      powx[i + 255] = cur;
>> +      powx_inv[cur] = i;
>> +      if (cur & 0x80)
>> +    cur = (cur << 1) ^ poly;
>> +      else
>> +    cur <<= 1;
>> +    }
>> +}
> 
> Could not we do this as a static? It is initialized only once.
Ditto

> 
>> +static unsigned
>> +mod_255 (unsigned x)
>> +{
>> +  while (x > 0xff)
>> +    x = (x >> 8) + (x & 0xff);
>> +  if (x == 0xff)
>> +    return 0;
>> +  return x;
>> +}
>> +
>> +typedef grub_err_t (* raid_recover_read_t)(void *data, int disk_nr,
>> +                                       grub_uint64_t addr, void *dest,
>> +                                       grub_size_t size);
>> +#if 0
>> +/*
>> + * code example to be used in raid6_recover.
>> + */
>> +static grub_err_t
>> +raid_recover_read_diskfilter_array (void *data, int disk_nr,
>> +                                grub_uint64_t sector,
>> +                                void *buf, grub_size_t size)
>> +{
>> +    struct grub_diskfilter_segment *array = data;
>> +    return grub_diskfilter_read_node (&array->nodes[disk_nr],
>> +                                  (grub_disk_addr_t)sector,
>> +                                  size >> GRUB_DISK_SECTOR_BITS, buf);
>> +}
>> +#endif
> 
> Please drop this.
See below

> 
>> +
>> +static grub_err_t
>> +raid_recover_read_raid56_buffer (void *data, int disk_nr, grub_uint64_t 
>> addr,
>> +                                 void *dest, grub_size_t size)
>> +{
>> +    struct raid56_buffer *buffers = data;
>> +
>> +    (void)addr;
> 
> "grub_uint64_t addr __attribute__ ((unused))" in prototype definition?
It is ugly ! :-)
> 
>> +    grub_memcpy(dest, buffers[disk_nr].buf, size);
>> +
>> +    grub_errno = buffers[disk_nr].ok ? GRUB_ERR_NONE : GRUB_ERR_READ_ERROR;
>> +    return grub_errno;
>> +}
>> +
>> +static grub_err_t
>> +grub_raid6_recover (void *data, grub_uint64_t nstripes, int disknr, int p,
>> +                    char *buf, grub_uint64_t sector, grub_size_t size,
>> +                raid_recover_read_t read_func, int layout)
>> +{
>> +  int i, q, pos;
>> +  int bad1 = -1, bad2 = -1;
>> +  char *pbuf = 0, *qbuf = 0;
>> +  static int table_initializated = 0;
>> +
>> +  if (!table_initializated)
>> +    {
>> +      grub_raid6_init_table();
>> +      table_initializated = 1;
>> +    }
>> +
>> +  pbuf = grub_zalloc (size);
>> +  if (!pbuf)
>> +    goto quit;
>> +
>> +  qbuf = grub_zalloc (size);
>> +  if (!qbuf)
>> +    goto quit;
>> +
>> +  q = p + 1;
>> +  if (q == (int) nstripes)
>> +    q = 0;
>> +
>> +  pos = q + 1;
>> +  if (pos == (int) nstripes)
>> +    pos = 0;
>> +
>> +  for (i = 0; i < (int) nstripes - 2; i++)
>> +    {
>> +      int c;
>> +      if (layout & GRUB_RAID_LAYOUT_MUL_FROM_POS)
>> +    c = pos;
>> +      else
>> +    c = i;
>> +      if (pos == disknr)
>> +        bad1 = c;
>> +      else
>> +        {
>> +      if (!read_func(data, pos, sector, buf, size))
>> +            {
>> +              grub_crypto_xor (pbuf, pbuf, buf, size);
>> +              grub_raid_block_mulx (c, buf, size);
>> +              grub_crypto_xor (qbuf, qbuf, buf, size);
>> +            }
>> +          else
>> +            {
>> +              /* Too many bad devices */
>> +              if (bad2 >= 0)
>> +                goto quit;
>> +
>> +              bad2 = c;
>> +              grub_errno = GRUB_ERR_NONE;
>> +            }
>> +        }
>> +
>> +      pos++;
>> +      if (pos == (int) nstripes)
>> +        pos = 0;
>> +    }
>> +
>> +  /* Invalid disknr or p */
>> +  if (bad1 < 0)
>> +    goto quit;
>> +
>> +  if (bad2 < 0)
>> +    {
>> +      /* One bad device */
>> +      if (!read_func(data, p, sector, buf, size))
>> +        {
>> +          grub_crypto_xor (buf, buf, pbuf, size);
>> +          goto quit;
>> +        }
>> +
>> +      grub_errno = GRUB_ERR_NONE;
>> +      if (read_func(data, q, sector, buf, size))
>> +        goto quit;
>> +
>> +      grub_crypto_xor (buf, buf, qbuf, size);
>> +      grub_raid_block_mulx (255 - bad1, buf,
>> +                           size);
>> +    }
>> +  else
>> +    {
>> +      /* Two bad devices */
>> +      unsigned c;
>> +
>> +      if (read_func(data, p, sector, buf, size))
>> +        goto quit;
>> +
>> +      grub_crypto_xor (pbuf, pbuf, buf, size);
>> +
>> +      if (read_func(data, q, sector, buf, size))
>> +        goto quit;
>> +
>> +      grub_crypto_xor (qbuf, qbuf, buf, size);
>> +
>> +      c = mod_255((255 ^ bad1)
>> +              + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)]));
>> +      grub_raid_block_mulx (c, qbuf, size);
>> +
>> +      c = mod_255((unsigned) bad2 + c);
>> +      grub_raid_block_mulx (c, pbuf, size);
>> +
>> +      grub_crypto_xor (pbuf, pbuf, qbuf, size);
>> +      grub_memcpy (buf, pbuf, size);
>> +    }
>> +
>> +quit:
> 
> One space before the label please?
ok
> 
>> +  grub_free (pbuf);
>> +  grub_free (qbuf);
>> +
>> +  return grub_errno;
>> +}
>> +
>> +/* end copy */
>>  static void
>>  rebuild_raid6 (struct raid56_buffer *buffers, grub_uint64_t nstripes,
>>                 grub_uint64_t csize, grub_uint64_t parities_pos, void *dest,
>>                 grub_uint64_t stripen)
>>
>>  {
>> -  (void)buffers;
>> -  (void)nstripes;
>> -  (void)csize;
>> -  (void)parities_pos;
>> -  (void)dest;
>> -  (void)stripen;
>> -  grub_dprintf ("btrfs", "called rebuild_raid6(), NOT IMPLEMENTED\n");
>> +  grub_raid6_recover (buffers, nstripes, stripen, parities_pos,
>> +                  dest, 0, csize,
>> +                  raid_recover_read_raid56_buffer, 0);
> 
> grub_raid6_recover() should be called directly from right place.

replacing raid_recover_read_raid56_buffer() with 
raid_recover_read_diskfilter_array(), could allow to use grub_raid6_recover() 
even in the grub-core/disk/raid6_recover.c. This is the reason of "double call".


> 
> Daniel
> 


-- 
gpg @keyserver.linux.it: Goffredo Baroncelli <kreijackATinwind.it>
Key fingerprint BBF5 1610 0B64 DAC6 5F7D  17B2 0EDA 9B37 8B82 E0B5



reply via email to

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