grub-devel
[Top][All Lists]
Advanced

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

Re: [PATCH] Split of raid scan code


From: Marco Gerards
Subject: Re: [PATCH] Split of raid scan code
Date: Wed, 13 Aug 2008 12:05:19 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)

Bean <address@hidden> writes:

> On Tue, Aug 12, 2008 at 4:30 AM, Robert Millan <address@hidden> wrote:
>> On Tue, Aug 12, 2008 at 04:24:26AM +0800, Bean wrote:
>>> -     disk/lvm.c disk/raid.c grub_probe_init.c
>>> +     disk/lvm.c disk/raid.c disk/mdraid_linux.c grub_probe_init.c
>>
>> Hi,
>>
>> I haven't tried, but I think this module split would break grub-install &
>> update-grub.  Please check those out before committing!
>
> Hi,
>
> Ok, I make some adjustment, now grub-install & update-grub works for
> raid device.

Great

> If no one objects, I'd commit this soon.
>
> 2008-08-12  Bean  <address@hidden>
>
>       * conf/common.rmk (grub_probe_SOURCES): Add disk/mdraid_linux.c.
>       (grub_fstest_SOURCES): Add disk/mdraid_linux.c and disk/dmraid_nvidia.c.
>       (pkglib_MODULES): Add mdraid.mod and dm_nv.mod.
>       (mdraid_mod_SOURCES): New macro.
>       (mdraid_mod_CFLAGS): Likewise.
>       (mdraid_mod_LDFLAGS): Likewise.
>       (dm_nv_mod_SOURCES): Likewise.
>       (dm_nv_mod_CFLAGS): Likewise.
>       (dm_nv_mod_LDFLAGS): Likewise.
>
>       * conf/i386-pc.rmk (grub_setup_SOURCES): Add disk/mdraid_linux.c.
>       (grub_emu_SOURCES):  Add disk/mdraid_linux.c and disk/dmraid_nvidia.c.
>
>       * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add disk/mdraid_linux.c
>       and disk/dmraid_nvidia.c.
>
>       * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise.
>
>       * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise.
>
>       * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise.
>
>       * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise.
>
>       * disk/mdraid_linux.c: New file.
>
>       * disk/dmraid_nvidia.c: New file.
>
>       * disk/i386/pc/biosdisk.c: Set total_sectors of cdrom device to
>       ULONG_MAX.

For which function?

>       * disk/raid.c (grub_raid_open): Calculate total_sectors of raid0
>       by adding the size of individual disk (they can have different size).
>       (grub_raid_read): Simply raid0 code, also fix a serious bug.
>       (grub_raid_scan_device): Remove code specific to mdraid.
>       (grub_raid_list): New variable.
>       (free_array): New function.
>       (grub_raid_register): Likewise.
>       (grub_raid_unregister): Likewise.
>       (grub_raid_rescan): Likewise.
>       (GRUB_MOD_INIT): Don't iterate device here.
>       (GRUB_MOD_FINI): Use free_array to release resource.
>
>       * include/grub/raid.h: Remove macro and structure specific to mdraid.
>
>       * util/grub-fstest.c: Add #include <grub/raid.h>.
>       (part): Removed.
>       (cmd_hex): Handle partition as well.
>       (fstest): Handle multiple disks.
>       (options): Remove part, raw and long, add root and diskcount.
>       (usage): Change hex, remove -p, -r, -l, add -r and -c.
>       (main): Find the first non option entry and ignore subsequence options,
>       add handling for the new options, support multiple disks.
>
>       * util/grub-probe.c (probe): Add mdraid to abstraction_name.
>
> -- 
> Bean
>
> diff --git a/conf/common.rmk b/conf/common.rmk
> index 95859f7..3876ce4 100644
> --- a/conf/common.rmk
> +++ b/conf/common.rmk
> @@ -15,7 +15,7 @@ grub_probe_SOURCES = util/grub-probe.c      \
>       \
>       partmap/pc.c partmap/apple.c partmap/gpt.c              \
>       kern/fs.c kern/env.c fs/fshelp.c                        \
> -     disk/lvm.c disk/raid.c grub_probe_init.c
> +     disk/lvm.c disk/raid.c disk/mdraid_linux.c grub_probe_init.c
>  
>  ifeq ($(enable_grub_fstest), yes)
>  bin_UTILITIES += grub-fstest
> @@ -35,6 +35,7 @@ grub_fstest_SOURCES = util/grub-fstest.c util/hostfs.c 
> util/misc.c  \
>       \
>       kern/partition.c partmap/pc.c partmap/apple.c partmap/gpt.c     \
>       kern/fs.c kern/env.c fs/fshelp.c disk/lvm.c disk/raid.c \
> +     disk/mdraid_linux.c disk/dmraid_nvidia.c \
>       grub_fstest_init.c
>  
>  # For the parser.
> @@ -264,7 +265,7 @@ gpt_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
>  # Special disk structures
>  
> -pkglib_MODULES += raid.mod lvm.mod
> +pkglib_MODULES += raid.mod lvm.mod mdraid.mod dm_nv.mod
>  
>  # For raid.mod
>  raid_mod_SOURCES = disk/raid.c
> @@ -276,6 +277,16 @@ lvm_mod_SOURCES = disk/lvm.c
>  lvm_mod_CFLAGS = $(COMMON_CFLAGS)
>  lvm_mod_LDFLAGS = $(COMMON_LDFLAGS)
>  
> +# For mdraid.mod
> +mdraid_mod_SOURCES = disk/mdraid_linux.c
> +mdraid_mod_CFLAGS = $(COMMON_CFLAGS)
> +mdraid_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
> +# For dm_nv.mod
> +dm_nv_mod_SOURCES = disk/dmraid_nvidia.c
> +dm_nv_mod_CFLAGS = $(COMMON_CFLAGS)
> +dm_nv_mod_LDFLAGS = $(COMMON_LDFLAGS)
> +
>  # Commands.
>  pkglib_MODULES += hello.mod boot.mod terminal.mod ls.mod     \
>       cmp.mod cat.mod help.mod font.mod search.mod            \
> diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk
> index 606b99c..74808ca 100644
> --- a/conf/i386-coreboot.rmk
> +++ b/conf/i386-coreboot.rmk
> @@ -92,7 +92,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c 
> commands/cmp.c    \
>       util/biosdisk.c util/getroot.c                                  \
>       util/i386/pc/misc.c                                             \
>       \
> -     disk/raid.c disk/lvm.c                                          \
> +     disk/raid.c disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
>       grub_emu_init.c
>  
>  grub_emu_LDFLAGS = $(LIBCURSES)
> diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk
> index 2ce21b1..705e4ef 100644
> --- a/conf/i386-efi.rmk
> +++ b/conf/i386-efi.rmk
> @@ -62,7 +62,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c 
> commands/cmp.c    \
>       util/biosdisk.c util/getroot.c                                  \
>       util/i386/pc/misc.c                                             \
>       \
> -     disk/raid.c disk/lvm.c                                          \
> +     disk/raid.c disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
>       grub_emu_init.c
>  
>  grub_emu_LDFLAGS = $(LIBCURSES)
> diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk
> index a93845e..e996865 100644
> --- a/conf/i386-ieee1275.rmk
> +++ b/conf/i386-ieee1275.rmk
> @@ -90,7 +90,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c 
> commands/cmp.c    \
>       util/biosdisk.c util/getroot.c                                  \
>       util/i386/pc/misc.c                                             \
>       \
> -     disk/raid.c disk/lvm.c                                          \
> +     disk/raid.c disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
>       grub_emu_init.c
>  
>  grub_emu_LDFLAGS = $(LIBCURSES)
> diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
> index c1e4ac4..f3142e4 100644
> --- a/conf/i386-pc.rmk
> +++ b/conf/i386-pc.rmk
> @@ -102,7 +102,7 @@ grub_setup_SOURCES = util/i386/pc/grub-setup.c 
> util/biosdisk.c    \
>       \
>       partmap/pc.c partmap/gpt.c                              \
>       \
> -     disk/raid.c disk/lvm.c                                  \
> +     disk/raid.c disk/mdraid_linux.c disk/lvm.c              \
>       util/raid.c util/lvm.c                                  \
>       grub_setup_init.c
>  
> @@ -142,7 +142,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c 
> commands/cmp.c  \
>       util/biosdisk.c util/getroot.c                                  \
>       util/i386/pc/misc.c                                             \
>       \
> -     disk/raid.c disk/lvm.c                                          \
> +     disk/raid.c disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
>       grub_emu_init.c
>  
>  grub_emu_LDFLAGS = $(LIBCURSES)
> diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk
> index 0ed75f3..15e2fae 100644
> --- a/conf/powerpc-ieee1275.rmk
> +++ b/conf/powerpc-ieee1275.rmk
> @@ -73,7 +73,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c 
> commands/cmp.c    \
>       util/biosdisk.c util/getroot.c                                  \
>       util/powerpc/ieee1275/misc.c                                    \
>       \
> -     disk/raid.c disk/lvm.c                                          \
> +     disk/raid.c disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
>       grub_script.tab.c grub_emu_init.c
>  
>  grub_emu_LDFLAGS = $(LIBCURSES)
> diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk
> index 4f8abba..8553226 100644
> --- a/conf/x86_64-efi.rmk
> +++ b/conf/x86_64-efi.rmk
> @@ -64,7 +64,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c 
> commands/cmp.c    \
>       util/biosdisk.c util/getroot.c                                  \
>       util/i386/pc/misc.c                                             \
>       \
> -     disk/raid.c disk/lvm.c                                          \
> +     disk/raid.c disk/mdraid_linux.c disk/dmraid_nvidia.c disk/lvm.c \
>       grub_emu_init.c
>  
>  grub_emu_LDFLAGS = $(LIBCURSES)
> diff --git a/disk/dmraid_nvidia.c b/disk/dmraid_nvidia.c
> new file mode 100644
> index 0000000..82eb26a
> --- /dev/null
> +++ b/disk/dmraid_nvidia.c
> @@ -0,0 +1,165 @@
> +/* dmraid_nvidia.c - module to handle Nvidia fakeraid.  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2006,2007,2008  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/dl.h>
> +#include <grub/disk.h>
> +#include <grub/mm.h>
> +#include <grub/err.h>
> +#include <grub/misc.h>
> +#include <grub/raid.h>
> +
> +#define NV_SIGNATURES                4
> +
> +#define NV_IDLE                      0
> +#define NV_SCDB_INIT_RAID    2
> +#define NV_SCDB_REBUILD_RAID 3
> +#define NV_SCDB_UPGRADE_RAID 4
> +#define NV_SCDB_SYNC_RAID    5
> +
> +#define NV_LEVEL_UNKNOWN     0x00
> +#define NV_LEVEL_JBOD                0xFF
> +#define NV_LEVEL_0           0x80
> +#define NV_LEVEL_1           0x81
> +#define NV_LEVEL_3           0x83
> +#define NV_LEVEL_5           0x85
> +#define NV_LEVEL_10          0x8a
> +#define NV_LEVEL_1_0         0x8180
> +
> +#define NV_ARRAY_FLAG_BOOT           1 /* BIOS use only.  */
> +#define NV_ARRAY_FLAG_ERROR          2 /* Degraded or offling.  */
> +#define NV_ARRAY_FLAG_PARITY_VALID   4 /* RAID-3/5 parity valid.  */
> +
> +struct grub_raid_nv_array
> +{
> +  grub_uint32_t version;
> +  grub_uint32_t signature[NV_SIGNATURES];
> +  grub_uint8_t raid_job_code;
> +  grub_uint8_t stripe_width;
> +  grub_uint8_t total_volumes;
> +  grub_uint8_t original_width;
> +  grub_uint32_t raid_level;
> +  grub_uint32_t stripe_block_size;
> +  grub_uint32_t stripe_block_size_bytes;
> +  grub_uint32_t stripe_block_size_log2;
> +  grub_uint32_t stripe_mask;
> +  grub_uint32_t stripe_size;
> +  grub_uint32_t stripe_size_bytes;
> +  grub_uint32_t raid_job_mask;
> +  grub_uint32_t original_capacity;
> +  grub_uint32_t flags;
> +};
> +
> +#define NV_ID_LENGTH         8
> +#define NV_ID_STRING         "NVIDIA"
> +#define NV_VERSION           100
> +
> +#define      NV_PRODUCTIDS           16
> +#define      NV_PRODUCTREVISIONS     4
> +
> +struct grub_raid_nv_super
> +{
> +  grub_uint8_t vendor[NV_ID_LENGTH]; /* 0x00 - 0x07 ID string.  */
> +  grub_uint32_t size;                /* 0x08 - 0x0B Size of metadata in 
> dwords.  */
> +  grub_uint32_t chksum;              /* 0x0C - 0x0F Checksum of this struct. 
>  */
> +  grub_uint16_t version;     /* 0x10 - 0x11 NV version.  */
> +  grub_uint8_t unit_number;  /* 0x12 Disk index in array.  */
> +  grub_uint8_t reserved;     /* 0x13.  */
> +  grub_uint32_t capacity;    /* 0x14 - 0x17 Array capacity in sectors.  */
> +  grub_uint32_t sector_size; /* 0x18 - 0x1B Sector size.  */
> +  grub_uint8_t product_id[NV_PRODUCTIDS]; /* 0x1C - 0x2B Array product ID.  
> */
> +  grub_uint8_t product_rev[NV_PRODUCTREVISIONS]; /* 0x2C - 0x2F Array 
> product revision */
> +  grub_uint32_t unit_flags;  /* 0x30 - 0x33 Flags for this disk */
> +  struct grub_raid_nv_array array; /* Array information */
> +} __attribute__ ((packed));


These lines get very long (too long?).  In general I prefer comments
on the line before the code.

> +static grub_err_t
> +grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array)
> +{
> +  grub_disk_addr_t sector;
> +  struct grub_raid_nv_super sb;
> +  grub_uint32_t *uuid;
> +
> +  if (disk->partition)
> +    return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
> +
> +  sector = grub_disk_get_size (disk) - 2;
> +
> +  if (grub_disk_read (disk, sector, 0, sizeof (sb), (char *) &sb))
> +    return grub_errno;
> +
> +  if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
> +    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
> +
> +  if (sb.version != NV_VERSION)
> +    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> +                       "Unknown version: %d.%d", sb.version);
> +
> +  switch (sb.array.raid_level)
> +    {
> +    case NV_LEVEL_0:
> +      array->level = 0;
> +      array->disk_size = sb.capacity / sb.array.total_volumes;
> +      break;
> +
> +    case NV_LEVEL_1:
> +      array->level = 1;
> +      array->disk_size = sb.capacity;
> +      break;
> +
> +    case NV_LEVEL_5:
> +      array->level = 5;
> +      array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
> +      break;
> +
> +    default:
> +      return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> +                         "Unsupported RAID level: %d", sb.array.raid_level);
> +    }
> +
> +  array->number = 0;
> +  array->total_devs = sb.array.total_volumes;
> +  array->chunk_size = sb.array.stripe_block_size;
> +  array->index = sb.unit_number;
> +  array->uuid_len = sizeof (sb.array.signature);
> +  array->uuid = grub_malloc (sizeof (sb.array.signature));
> +  if (! array->uuid)
> +    return grub_errno;
> +
> +  grub_memcpy (array->uuid, (char *) &sb.array.signature,
> +               sizeof (sb.array.signature));
> +
> +  return 0;
> +}
> +
> +static struct grub_raid grub_dmraid_nv_dev =
> +{
> +  .name = "dmraid_nv",
> +  .detect = grub_dmraid_nv_detect,
> +  .next = 0
> +};
> +
> +GRUB_MOD_INIT(dm_nv)
> +{
> +  grub_raid_register (&grub_dmraid_nv_dev);
> +}
> +
> +GRUB_MOD_FINI(dm_nv)
> +{
> +  grub_raid_register (&grub_dmraid_nv_dev);
> +}
> diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c
> index c8fd142..8b7f5ed 100644
> --- a/disk/i386/pc/biosdisk.c
> +++ b/disk/i386/pc/biosdisk.c
> @@ -120,7 +120,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
>      {
>        data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
>        data->sectors = 32;
> -      total_sectors = 9000000;  /* TODO: get the correct size.  */
> +      total_sectors = ULONG_MAX;  /* TODO: get the correct size.  */

You are cheating here! :-)

>    else if (drive & 0x80)
>      {
> diff --git a/disk/mdraid_linux.c b/disk/mdraid_linux.c
> new file mode 100644
> index 0000000..c77f2e2
> --- /dev/null
> +++ b/disk/mdraid_linux.c
> @@ -0,0 +1,243 @@
> +/* mdraid_linux.c - module to handle linux softraid.  */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2008  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/dl.h>
> +#include <grub/disk.h>
> +#include <grub/mm.h>
> +#include <grub/err.h>
> +#include <grub/misc.h>
> +#include <grub/raid.h>
> +
> +/* Linux RAID on disk structures and constants,
> +   copied from include/linux/raid/md_p.h.  */
> +
> +#define GRUB_RAID_RESERVED_BYTES             (64 * 1024)
> +#define GRUB_RAID_RESERVED_SECTORS           (GRUB_RAID_RESERVED_BYTES / 512)
> +
> +#define GRUB_RAID_NEW_SIZE_SECTORS(x)                ((x & 
> ~(GRUB_RAID_RESERVED_SECTORS - 1)) \
> +                                              - GRUB_RAID_RESERVED_SECTORS)
> +
> +#define GRUB_RAID_SB_BYTES                   4096
> +#define GRUB_RAID_SB_WORDS                   (GRUB_RAID_SB_BYTES / 4)
> +#define GRUB_RAID_SB_SECTORS                 (GRUB_RAID_SB_BYTES / 512)
> +
> +/*
> + * The following are counted in 32-bit words
> + */
> +#define      GRUB_RAID_SB_GENERIC_OFFSET             0
> +
> +#define GRUB_RAID_SB_PERSONALITY_OFFSET      64
> +#define GRUB_RAID_SB_DISKS_OFFSET            128
> +#define GRUB_RAID_SB_DESCRIPTOR_OFFSET               992
> +
> +#define GRUB_RAID_SB_GENERIC_CONSTANT_WORDS  32
> +#define GRUB_RAID_SB_GENERIC_STATE_WORDS     32
> +#define GRUB_RAID_SB_GENERIC_WORDS           
> (GRUB_RAID_SB_GENERIC_CONSTANT_WORDS \
> +                                              + 
> GRUB_RAID_SB_GENERIC_STATE_WORDS)
> +#define GRUB_RAID_SB_PERSONALITY_WORDS               64
> +#define GRUB_RAID_SB_DESCRIPTOR_WORDS                32
> +#define GRUB_RAID_SB_DISKS                   27
> +#define GRUB_RAID_SB_DISKS_WORDS             
> (GRUB_RAID_SB_DISKS*GRUB_RAID_SB_DESCRIPTOR_WORDS)
> +#define GRUB_RAID_SB_RESERVED_WORDS          (1024 - 
> GRUB_RAID_SB_GENERIC_WORDS \
> +                                              - 
> GRUB_RAID_SB_PERSONALITY_WORDS \
> +                                              - GRUB_RAID_SB_DISKS_WORDS \
> +                                              - 
> GRUB_RAID_SB_DESCRIPTOR_WORDS)
> +#define GRUB_RAID_SB_EQUAL_WORDS             (GRUB_RAID_SB_GENERIC_WORDS \
> +                                              + 
> GRUB_RAID_SB_PERSONALITY_WORDS \
> +                                              + GRUB_RAID_SB_DISKS_WORDS)


The lines above are way too long

> +/*
> + * Device "operational" state bits
> + */
> +#define GRUB_RAID_DISK_FAULTY                0 /* disk is faulty / 
> operational */
> +#define GRUB_RAID_DISK_ACTIVE                1 /* disk is running or spare 
> disk */
> +#define GRUB_RAID_DISK_SYNC          2 /* disk is in sync with the raid set 
> */
> +#define GRUB_RAID_DISK_REMOVED               3 /* disk is in sync with the 
> raid set */
> +
> +#define      GRUB_RAID_DISK_WRITEMOSTLY      9 /* disk is "write-mostly" is 
> RAID1 config.
> +                                        * read requests will only be sent 
> here in
> +                                        * dire need
> +                                        */

Can you correctly format comments?  Placing the comments before the
#define makes the lines shorter.  Perhaps they are too long (I didn't check)

The same applies for code below


> +
> +#define GRUB_RAID_SB_MAGIC           0xa92b4efc
> +
> +/*
> + * Superblock state bits
> + */
> +#define GRUB_RAID_SB_CLEAN           0
> +#define GRUB_RAID_SB_ERRORS          1
> +
> +#define      GRUB_RAID_SB_BITMAP_PRESENT     8 /* bitmap may be present 
> nearby */
> +
> +struct grub_raid_disk_09 {
> +  grub_uint32_t number;              /* 0 Device number in the entire set    
>       */
> +  grub_uint32_t major;               /* 1 Device major number                
>       */
> +  grub_uint32_t minor;               /* 2 Device minor number                
>       */
> +  grub_uint32_t raid_disk;   /* 3 The role of the device in the raid set   */
> +  grub_uint32_t state;               /* 4 Operational state                  
>       */
> +  grub_uint32_t reserved[GRUB_RAID_SB_DESCRIPTOR_WORDS - 5];
> +};
> +
> +struct grub_raid_super_09 {
> +  /*
> +   * Constant generic information
> +   */
> +  grub_uint32_t md_magic;    /*  0 MD identifier                           */
> +  grub_uint32_t major_version;       /*  1 major version to which the set 
> conforms */
> +  grub_uint32_t minor_version;       /*  2 minor version ...                 
>       */
> +  grub_uint32_t patch_version;       /*  3 patchlevel version ...            
>       */
> +  grub_uint32_t gvalid_words;        /*  4 Number of used words in this 
> section    */
> +  grub_uint32_t set_uuid0;   /*  5 Raid set identifier                     */
> +  grub_uint32_t ctime;               /*  6 Creation time                     
>       */
> +  grub_uint32_t level;               /*  7 Raid personality                  
>       */
> +  grub_uint32_t size;                /*  8 Apparent size of each individual 
> disk   */
> +  grub_uint32_t nr_disks;    /*  9 total disks in the raid set             */
> +  grub_uint32_t raid_disks;  /* 10 disks in a fully functional raid set    */
> +  grub_uint32_t md_minor;    /* 11 preferred MD minor device number        */
> +  grub_uint32_t not_persistent;      /* 12 does it have a persistent 
> superblock    */
> +  grub_uint32_t set_uuid1;   /* 13 Raid set identifier #2                  */
> +  grub_uint32_t set_uuid2;   /* 14 Raid set identifier #3                  */
> +  grub_uint32_t set_uuid3;   /* 15 Raid set identifier #4                  */
> +  grub_uint32_t gstate_creserved[GRUB_RAID_SB_GENERIC_CONSTANT_WORDS - 16];
> +
> +  /*
> +   * Generic state information
> +   */
> +  grub_uint32_t utime;               /*  0 Superblock update time            
>       */
> +  grub_uint32_t state;               /*  1 State bits (clean, ...)           
>       */
> +  grub_uint32_t active_disks;        /*  2 Number of currently active disks  
>       */
> +  grub_uint32_t working_disks;       /*  3 Number of working disks           
>       */
> +  grub_uint32_t failed_disks;        /*  4 Number of failed disks            
>       */
> +  grub_uint32_t spare_disks; /*  5 Number of spare disks                   */
> +  grub_uint32_t sb_csum;     /*  6 checksum of the whole superblock        */
> +#ifdef GRUB_HOST_WORDS_BIGENDIAN
> +  grub_uint32_t events_hi;   /*  7 high-order of superblock update count   */
> +  grub_uint32_t events_lo;   /*  8 low-order of superblock update count    */
> +  grub_uint32_t cp_events_hi;        /*  9 high-order of checkpoint update 
> count   */
> +  grub_uint32_t cp_events_lo;        /* 10 low-order of checkpoint update 
> count    */
> +#else
> +  grub_uint32_t events_lo;   /*  7 low-order of superblock update count    */
> +  grub_uint32_t events_hi;   /*  8 high-order of superblock update count   */
> +  grub_uint32_t cp_events_lo;        /*  9 low-order of checkpoint update 
> count    */
> +  grub_uint32_t cp_events_hi;        /* 10 high-order of checkpoint update 
> count   */
> +#endif

Why?  We have macros for this :-)

> +  grub_uint32_t recovery_cp; /* 11 recovery checkpoint sector count        */
> +  grub_uint32_t gstate_sreserved[GRUB_RAID_SB_GENERIC_STATE_WORDS - 12];
> +
> +  /*
> +   * Personality information
> +   */
> +  grub_uint32_t layout;              /*  0 the array's physical layout       
>       */
> +  grub_uint32_t chunk_size;  /*  1 chunk size in bytes                     */
> +  grub_uint32_t root_pv;     /*  2 LV root PV */
> +  grub_uint32_t root_block;  /*  3 LV root block */
> +  grub_uint32_t pstate_reserved[GRUB_RAID_SB_PERSONALITY_WORDS - 4];
> +
> +  /*
> +   * Disks information
> +   */

/* Disks information.  */

> +  struct grub_raid_disk_09 disks[GRUB_RAID_SB_DISKS];
> +
> +  /*
> +   * Reserved
> +   */

/* Reserved.  */

(I do not like this comment style)

> +  grub_uint32_t reserved[GRUB_RAID_SB_RESERVED_WORDS];
> +
> +  /*
> +   * Active descriptor
> +   */

Same here.

> +  struct grub_raid_disk_09 this_disk;
> +};
> +
> +static grub_err_t
> +grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array)
> +{
> +  grub_disk_addr_t sector;
> +  grub_uint64_t size;
> +  struct grub_raid_super_09 sb;
> +  grub_uint32_t *uuid;
> +
> +  /* The sector where the RAID superblock is stored, if available. */
> +  size = grub_disk_get_size (disk);
> +  sector = GRUB_RAID_NEW_SIZE_SECTORS(size);
> +
> +  if (grub_disk_read (disk, sector, 0, GRUB_RAID_SB_BYTES, (char *) &sb))
> +    return grub_errno;
> +
> +    /* Look whether there is a RAID superblock. */
> +  if (sb.md_magic != GRUB_RAID_SB_MAGIC)
> +    return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");

It looks like the comment is misaligned.

> +  /* FIXME: Also support version 1.0. */
> +  if (sb.major_version != 0 || sb.minor_version != 90)
> +    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> +                       "Unsupported RAID version: %d.%d",
> +                       sb.major_version, sb.minor_version);
> +
> +  /* FIXME: Check the checksum. */
> +
> +  /* FIXME: Support all RAID levels.  */
> +  if (sb.level != 0 && sb.level != 1 && sb.level != 5)
> +    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> +                       "Unsupported RAID level: %d",
> +                       sb.level);
> +
> +  /* FIXME: Support all layouts.  */
> +  if (sb.level == 5 && sb.layout != 2)
> +    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> +                       "Unsupported RAID5 layout: %d",
> +                       sb.layout);
> +
> +  array->number = sb.md_minor;
> +  array->level = sb.level;
> +  array->total_devs = sb.nr_disks;
> +  array->disk_size = (sb.size) ? sb.size * 2 : sector;
> +  array->chunk_size = sb.chunk_size >> 9;
> +  array->index = sb.this_disk.number;
> +  array->uuid_len = 16;
> +  array->uuid = grub_malloc (16);
> +  if (! array->uuid)
> +    return grub_errno;
> +
> +  uuid = (grub_uint32_t *) array->uuid;
> +  uuid[0] = sb.set_uuid0;
> +  uuid[1] = sb.set_uuid1;
> +  uuid[2] = sb.set_uuid2;
> +  uuid[3] = sb.set_uuid3;
> +
> +  return 0;
> +}
> +
> +static struct grub_raid grub_mdraid_dev =
> +{
> +  .name = "mdraid",
> +  .detect = grub_mdraid_detect,
> +  .next = 0
> +};
> +
> +GRUB_MOD_INIT(mdraid)
> +{
> +  grub_raid_register (&grub_mdraid_dev);
> +}
> +
> +GRUB_MOD_FINI(mdraid)
> +{
> +  grub_raid_register (&grub_mdraid_dev);
> +}
> diff --git a/disk/raid.c b/disk/raid.c
> index 731bf1f..3333f4b 100644
> --- a/disk/raid.c
> +++ b/disk/raid.c
> @@ -112,9 +112,15 @@ grub_raid_open (const char *name, grub_disk_t disk)
>    switch (array->level)
>      {
>      case 0:
> -      /* FIXME: RAID0 disks can have different sizes! */
> -      disk->total_sectors = array->total_devs * array->disk_size;
> -      break;
> +      {
> +        unsigned i;
> +
> +        disk->total_sectors = 0;
> +        for (i = 0; i < array->total_devs; i++)
> +          disk->total_sectors += array->device[i]->total_sectors;
> +
> +        break;
> +      }
>  
>      case 1:
>        disk->total_sectors = array->disk_size;
> @@ -152,56 +158,39 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t 
> sector,
>       grub_uint32_t b;
>       unsigned int disknr;
>       grub_disk_addr_t read_sector;
> -     grub_size_t read_size;
>  
>       /* Find the first sector to read. */
> -     a = grub_divmod64 (sector, array->chunk_size, NULL);
> -     grub_divmod64 (a, array->total_devs, &disknr);
> -
> -     a = grub_divmod64 (sector, array->chunk_size * array->total_devs, NULL);
> -     grub_divmod64 (sector, array->chunk_size, &b);
> -     read_sector = a * array->chunk_size + b;
> -
> -     grub_divmod64 (read_sector, array->chunk_size, &b);
> -     read_size = array->chunk_size - b;
> -     
> -     if (read_size > size)
> -       read_size = size;
> +     a = grub_divmod64 (sector, array->chunk_size, &b);
> +     a = grub_divmod64 (a, array->total_devs, &disknr);
> +     read_sector = a * array->chunk_size;
>       
>       while (1)
>         {
> -         grub_uint32_t i;
> +            grub_size_t read_size;
>  
> -         err = grub_disk_read (array->device[disknr], read_sector, 0,
> +            read_size = array->chunk_size - b;
> +            if (read_size > size)
> +              read_size = size;
> +
> +         err = grub_disk_read (array->device[disknr], read_sector + b, 0,
>                                 read_size << GRUB_DISK_SECTOR_BITS, buf);
>           if (err)
>             break;
>  
> -         buf += read_size;
> +         buf += read_size << GRUB_DISK_SECTOR_BITS;
>           size -= read_size;
>           if (! size)
>             break;
>  
> -         if (size > array->chunk_size)
> -           read_size = array->chunk_size;
> -         else
> -           read_size = size;
> -
> -         /* Check whether the sector was aligned on a chunk size
> -            boundary. If this isn't the case, it's the first read
> -            and the next read should be set back to start of the
> -            boundary.  */
> -         grub_divmod64 (read_sector, array->chunk_size, &i);
> -         read_sector -= i;
> -
> +            b = 0;
>           disknr++;
>           /* See whether the disk was the last disk, and start
>              reading from the first disk in that case. */
>           if (disknr == array->total_devs)
> -           {
> -             disknr = 0;
> -             read_sector += array->chunk_size;
> -           }
> +              {
> +                read_sector += array->chunk_size;
> +                disknr = 0;
> +              }
>         }
>        }
>        break;
> @@ -348,169 +337,103 @@ grub_raid_write (grub_disk_t disk __attribute 
> ((unused)),
>    return GRUB_ERR_NOT_IMPLEMENTED_YET;
>  }
>  
> -static int
> -grub_raid_scan_device (const char *name)
> +static grub_err_t
> +insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
> +              const char *scanner_name)
>  {
> -  grub_err_t err;
> -  grub_disk_t disk;
> -  grub_disk_addr_t sector;
> -  grub_uint64_t size;
> -  struct grub_raid_super_09 sb;
> -  struct grub_raid_array *p, *array = NULL;
> -
> -  grub_dprintf ("raid", "Scanning for RAID devices\n");
> -
> -  disk = grub_disk_open (name);
> -  if (!disk)
> -    return 0;
> -
> -  /* The sector where the RAID superblock is stored, if available. */
> -  size = grub_disk_get_size (disk);
> -  sector = GRUB_RAID_NEW_SIZE_SECTORS(size);
> -
> -  err = grub_disk_read (disk, sector, 0, GRUB_RAID_SB_BYTES, (char *) &sb);
> -  grub_disk_close (disk);
> -  if (err)
> -    {
> -      grub_errno = GRUB_ERR_NONE;
> -      return 0;
> -    }
> -
> -  /* Look whether there is a RAID superblock. */
> -  if (sb.md_magic != GRUB_RAID_SB_MAGIC)
> -    return 0;
> -  
> -  /* FIXME: Also support version 1.0. */
> -  if (sb.major_version != 0 || sb.minor_version != 90)
> -    {
> -      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> -               "Unsupported RAID version: %d.%d",
> -               sb.major_version, sb.minor_version);
> -      return 0;
> -    }
> -
> -  /* FIXME: Check the checksum. */
> -
> -  /* FIXME: Support all RAID levels.  */
> -  if (sb.level != 0 && sb.level != 1 && sb.level != 5)
> -    {
> -      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> -               "Unsupported RAID level: %d",
> -               sb.level);
> -      return 0;
> -    }
> -
> -  /* FIXME: Support all layouts.  */
> -  if (sb.level == 5 && sb.layout != 2)
> -    {
> -      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> -               "Unsupported RAID5 layout: %d",
> -               sb.layout);
> -      return 0;
> -    }
> +  struct grub_raid_array *array = 0, *p;
>    
>    /* See whether the device is part of an array we have already seen a
>       device from. */
>    for (p = array_list; p != NULL; p = p->next)
> -    {
> -      if (p->uuid[0] == sb.set_uuid0 && p->uuid[1] == sb.set_uuid1
> -       && p->uuid[2] == sb.set_uuid2 && p->uuid[3] == sb.set_uuid3)
> -     {
> -       array = p;
> -       break;
> -     }
> -    }
> -
> -  /* Do some checks before adding the device to the array.  */
> -  if (array)
> -    {
> -      /* FIXME: Check whether the update time of the superblocks are
> -      the same. */
> -      
> -      if (array->total_devs == array->nr_devs)
> -     {
> -       /* We found more members of the array than the array
> -          actually has according to its superblock.  This shouldn't
> -          happen normally, but what is the sanest things to do in such
> -          a case? */
> -          
> -       grub_error (GRUB_ERR_BAD_NUMBER,
> -                   "array->nr_devs > array->total_devs (%d)?!?",
> -                   array->total_devs);
> -
> -       return 0;
> -     }
> -  
> -      if (array->device[sb.this_disk.number] != NULL)
> -     /* We found multiple devices with the same number. Again,
> -        this shouldn't happen.*/
> -     grub_dprintf ("raid", "Found two disks with the number %d?!?",
> -                   sb.this_disk.number);
> -    }
> +    if ((p->uuid_len == new_array->uuid_len) &&
> +        (! grub_memcmp (p->uuid, new_array->uuid, p->uuid_len)))
> +      {
> +        grub_free (new_array->uuid);
> +        array = p;
> +
> +        /* Do some checks before adding the device to the array.  */
> +
> +        /* FIXME: Check whether the update time of the superblocks are
> +           the same. */
> +
> +        if (array->total_devs == array->nr_devs)
> +          /* We found more members of the array than the array
> +             actually has according to its superblock.  This shouldn't
> +             happen normally, but what is the sanest things to do in such
> +             a case? */
> +          return grub_error (GRUB_ERR_BAD_NUMBER,
> +                             "array->nr_devs > array->total_devs (%d)?!?",
> +                             array->total_devs);
> +
> +        if (array->device[new_array->index] != NULL)
> +          /* We found multiple devices with the same number. Again,
> +             this shouldn't happen.*/
> +          return grub_error (GRUB_ERR_BAD_NUMBER,
> +                             "Found two disks with the number %d?!?",
> +                             new_array->number);
> +
> +        break;
> +      }
>  
>    /* Add an array to the list if we didn't find any.  */
>    if (!array)
>      {
>        array = grub_malloc (sizeof (*array));
>        if (!array)
> -     return 0;
> -      grub_memset (array, 0, sizeof (*array));      
> -      array->number = sb.md_minor;
> -      array->version = sb.major_version;
> -      array->level = sb.level;
> -      array->layout = sb.layout;
> -      array->total_devs = sb.nr_disks;
> +        {
> +          grub_free (new_array->uuid);
> +          return grub_errno;
> +        }
> +
> +      *array = *new_array;
>        array->nr_devs = 0;
> -      array->uuid[0] = sb.set_uuid0;
> -      array->uuid[1] = sb.set_uuid1;
> -      array->uuid[2] = sb.set_uuid2;
> -      array->uuid[3] = sb.set_uuid3;
> -      /* The superblock specifies the size in 1024-byte sectors. */
> -      array->disk_size = sb.size * 2;
> -      array->chunk_size = sb.chunk_size / 512;
> +      grub_memset (&array->device, 0, sizeof (array->device));
>        
>        /* Check whether we don't have multiple arrays with the same number. */
>        for (p = array_list; p != NULL; p = p->next)
> -     {
> -       if (p->number == array->number)
> -         break;
> -     }
> +        {
> +          if (p->number == array->number)
> +            break;
> +        }
>  
>        if (p)
> -     {
> -       /* The number is already in use, so we need to find an new number. */
> -       int i = 0;
> -
> -       while (1)
> -         {
> -           for (p = array_list; p != NULL; p = p->next)
> -             {
> -               if (p->number == i)
> -                 break;
> -             }
> -
> -           if (!p)
> -             {
> -               /* We found an unused number.  */
> -               array->number = i;
> -               break;
> -             }
> -
> -           i++;
> -         }
> -     }
> +        {
> +          /* The number is already in use, so we need to find an new number. 
> */
> +          int i = 0;
> +
> +          while (1)
> +            {
> +              for (p = array_list; p != NULL; p = p->next)
> +                {
> +                  if (p->number == i)
> +                    break;
> +                }
> +
> +              if (!p)
> +                {
> +                  /* We found an unused number.  */
> +                  array->number = i;
> +                  break;
> +                }
> +
> +              i++;
> +            }
> +        }
>  
>        array->name = grub_malloc (13);
>        if (! array->name)
> -     {
> -       grub_free (array);
> +        {
> +          grub_free (array->uuid);
> +          grub_free (array);
>  
> -       return 0;
> -     }
> +          return grub_errno;
> +        }
>  
>        grub_sprintf (array->name, "md%d", array->number);
>  
> -      grub_dprintf ("raid", "Found array: %s\n", array->name);
> +      grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
> +                    scanner_name);
>  
>        /* Add our new array to the list.  */
>        array->next = array_list;
> @@ -518,47 +441,117 @@ grub_raid_scan_device (const char *name)
>      }
>  
>    /* Add the device to the array. */
> -  array->device[sb.this_disk.number] = grub_disk_open (name);
> +  array->device[new_array->index] = disk;
> +  array->nr_devs++;
>  
> -  if (array->disk_size != array->device[sb.this_disk.number]->total_sectors)
> +  return 0;
> +}
> +
> +
> +static grub_raid_t grub_raid_list;
> +
> +static void
> +grub_raid_scan_device (int head_only)
> +{
> +  auto int hook (const char *name);
> +  int hook (const char *name)
>      {
> -      if (array->total_devs == 1)
> -     {
> -       grub_dprintf ("raid", "Array contains only one disk, but its size 
> (0x%llx) "
> -                     "doesn't match with size indicated by superblock 
> (0x%llx).  "
> -                     "Assuming superblock is wrong.\n",
> -                     (unsigned long long) 
> array->device[sb.this_disk.number]->total_sectors,
> -                     (unsigned long long) array->disk_size);
> -       array->disk_size = array->device[sb.this_disk.number]->total_sectors;
> -     }
> -      else if (array->level == 1)
> -     {
> -       grub_dprintf ("raid", "Array is RAID level 1, but the size of disk %d 
> (0x%llx) "
> -                     "doesn't match with size indicated by superblock 
> (0x%llx).  "
> -                     "Assuming superblock is wrong.\n",
> -                     sb.this_disk.number,
> -                     (unsigned long long) 
> array->device[sb.this_disk.number]->total_sectors,
> -                     (unsigned long long) array->disk_size);
> -       array->disk_size = array->device[sb.this_disk.number]->total_sectors;
> -     }
> +      grub_disk_t disk;
> +      struct grub_raid_array array;
> +      struct grub_raid *p;
> +
> +      grub_dprintf ("raid", "Scanning for RAID devices\n");
> +
> +      disk = grub_disk_open (name);
> +      if (!disk)
> +        return 0;
> +
> +      if (disk->total_sectors == ULONG_MAX)

Urgh, can you do this cleaner?

Actually, why do you do this?

> +        {
> +          grub_disk_close (disk);
> +          return 0;
> +        }
> +
> +      for (p = grub_raid_list; p; p = p->next)
> +        {
> +          if (! p->detect (disk, &array))
> +            {
> +              if (! insert_array (disk, &array, p->name))
> +                return 0;
> +
> +              break;
> +            }
> +
> +          /* This error usually means it's not raid, no need to display
> +             it.  */
> +          if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
> +            grub_print_error ();
> +
> +          grub_errno = GRUB_ERR_NONE;
> +          if (head_only)
> +            break;
> +        }
> +
> +      grub_disk_close (disk);
> +
> +      return 0;
>      }
>    
> -  if (! array->device[sb.this_disk.number])
> +  grub_device_iterate (&hook);
> +}
> +
> +static void
> +free_array (void)
> +{
> +  struct grub_raid_array *array;
> +
> +  array = array_list;
> +  while (array)
>      {
> -      /* Remove array from the list if we have just added it. */
> -      if (array->nr_devs == 0)
> -     {
> -       array_list = array->next;
> -       grub_free (array->name);
> -       grub_free (array);
> -     }
> +      struct grub_raid_array *p;
> +      int i;
>         
> -      return 0;
> +      p = array;
> +      array = array->next;
> +
> +      for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++)
> +        if (p->device[i])
> +          grub_disk_close (p->device[i]);
> +
> +      grub_free (p->uuid);
> +      grub_free (p->name);
> +      grub_free (p);
>      }
>  
> -  array->nr_devs++;
> +  array_list = 0;
> +}
>    
> -  return 0;
> +void
> +grub_raid_register (grub_raid_t raid)
> +{
> +  raid->next = grub_raid_list;
> +  grub_raid_list = raid;
> +  grub_raid_scan_device (1);
> +}
> +
> +void
> +grub_raid_unregister (grub_raid_t raid)
> +{
> +  grub_raid_t *p, q;
> +
> +  for (p = &grub_raid_list, q = *p; q; p = &(q->next), q = q->next)
> +    if (q == raid)
> +      {
> +     *p = q->next;
> +     break;
> +      }
> +}
> +
> +void
> +grub_raid_rescan (void)
> +{
> +  free_array ();
> +  grub_raid_scan_device (0);
>  }
>  
>  static struct grub_disk_dev grub_raid_dev =
> @@ -579,12 +572,11 @@ static struct grub_disk_dev grub_raid_dev =
>  
>  GRUB_MOD_INIT(raid)
>  {
> -  grub_device_iterate (&grub_raid_scan_device);
>    grub_disk_dev_register (&grub_raid_dev);
>  }
>  
>  GRUB_MOD_FINI(raid)
>  {
>    grub_disk_dev_unregister (&grub_raid_dev);
> -  /* FIXME: free the array list. */
> +  free_array ();
>  }
> diff --git a/include/grub/raid.h b/include/grub/raid.h
> index 4af97f1..0920f0f 100644
> --- a/include/grub/raid.h
> +++ b/include/grub/raid.h
> @@ -22,165 +22,42 @@
>  
>  #include <grub/types.h>
>  
> +#define GRUB_RAID_MAX_DEVICES        32
> +
>  struct grub_raid_array
>  {
>    int number;              /* The device number, taken from md_minor so we
>                             are consistent with the device name in
>                             Linux. */
> -  int version;             /* 0 = 0.90, 1 = 1.0 */
>    int level;               /* RAID levels, only 0, 1 or 5 at the moment. */
> -  int layout;              /* Only for RAID 5.  */
>    unsigned int total_devs; /* Total number of devices in the array. */
> -  unsigned int nr_devs;    /* The number of devices we've found so far. */
> -  grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */
> -  grub_uint32_t uuid[4];   /* The UUID of the device. */
> -  char *name;              /* That will be "md<number>". */
> +  grub_size_t chunk_size;  /* The size of a chunk, in 512 byte sectors. */
>    grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte
>                             sectors. */
> -  grub_disk_t device[32];  /* Array of total_devs devices. */          
> +  int index;               /* Index of current device.  */
> +  int uuid_len;            /* The length of uuid.  */
> +  char *uuid;              /* The UUID of the device. */
> +
> +  /* The following field is setup by the caller.  */
> +  char *name;              /* That will be "md<number>". */
> +  unsigned int nr_devs;    /* The number of devices we've found so far. */
> +  grub_disk_t device[GRUB_RAID_MAX_DEVICES];  /* Array of total_devs 
> devices. */
>    struct grub_raid_array *next;
>  };
>  
> -/* Linux RAID on disk structures and constants,
> -   copied from include/linux/raid/md_p.h.  */
> -
> -#define GRUB_RAID_RESERVED_BYTES             (64 * 1024)
> -#define GRUB_RAID_RESERVED_SECTORS           (GRUB_RAID_RESERVED_BYTES / 512)
> -
> -#define GRUB_RAID_NEW_SIZE_SECTORS(x)                ((x & 
> ~(GRUB_RAID_RESERVED_SECTORS - 1)) \
> -                                              - GRUB_RAID_RESERVED_SECTORS)
> -
> -#define GRUB_RAID_SB_BYTES                   4096
> -#define GRUB_RAID_SB_WORDS                   (GRUB_RAID_SB_BYTES / 4)
> -#define GRUB_RAID_SB_SECTORS                 (GRUB_RAID_SB_BYTES / 512)
> -
> -/*
> - * The following are counted in 32-bit words
> - */
> -#define      GRUB_RAID_SB_GENERIC_OFFSET             0
> -
> -#define GRUB_RAID_SB_PERSONALITY_OFFSET      64
> -#define GRUB_RAID_SB_DISKS_OFFSET            128
> -#define GRUB_RAID_SB_DESCRIPTOR_OFFSET               992
> -
> -#define GRUB_RAID_SB_GENERIC_CONSTANT_WORDS  32
> -#define GRUB_RAID_SB_GENERIC_STATE_WORDS     32
> -#define GRUB_RAID_SB_GENERIC_WORDS           
> (GRUB_RAID_SB_GENERIC_CONSTANT_WORDS \
> -                                              + 
> GRUB_RAID_SB_GENERIC_STATE_WORDS)
> -#define GRUB_RAID_SB_PERSONALITY_WORDS               64
> -#define GRUB_RAID_SB_DESCRIPTOR_WORDS                32
> -#define GRUB_RAID_SB_DISKS                   27
> -#define GRUB_RAID_SB_DISKS_WORDS             
> (GRUB_RAID_SB_DISKS*GRUB_RAID_SB_DESCRIPTOR_WORDS)
> -#define GRUB_RAID_SB_RESERVED_WORDS          (1024 - 
> GRUB_RAID_SB_GENERIC_WORDS \
> -                                              - 
> GRUB_RAID_SB_PERSONALITY_WORDS \
> -                                              - GRUB_RAID_SB_DISKS_WORDS \
> -                                              - 
> GRUB_RAID_SB_DESCRIPTOR_WORDS)
> -#define GRUB_RAID_SB_EQUAL_WORDS             (GRUB_RAID_SB_GENERIC_WORDS \
> -                                              + 
> GRUB_RAID_SB_PERSONALITY_WORDS \
> -                                              + GRUB_RAID_SB_DISKS_WORDS)
> -
> -/*
> - * Device "operational" state bits
> - */
> -#define GRUB_RAID_DISK_FAULTY                0 /* disk is faulty / 
> operational */
> -#define GRUB_RAID_DISK_ACTIVE                1 /* disk is running or spare 
> disk */
> -#define GRUB_RAID_DISK_SYNC          2 /* disk is in sync with the raid set 
> */
> -#define GRUB_RAID_DISK_REMOVED               3 /* disk is in sync with the 
> raid set */
> -
> -#define      GRUB_RAID_DISK_WRITEMOSTLY      9 /* disk is "write-mostly" is 
> RAID1 config.
> -                                        * read requests will only be sent 
> here in
> -                                        * dire need
> -                                        */
> -
> -
> -#define GRUB_RAID_SB_MAGIC           0xa92b4efc
> -
> -/*
> - * Superblock state bits
> - */
> -#define GRUB_RAID_SB_CLEAN           0
> -#define GRUB_RAID_SB_ERRORS          1
> +struct grub_raid
> +{
> +  const char *name;
>  
> -#define      GRUB_RAID_SB_BITMAP_PRESENT     8 /* bitmap may be present 
> nearby */
> +  grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array);
>  
> -struct grub_raid_disk_09 {
> -  grub_uint32_t number;              /* 0 Device number in the entire set    
>       */
> -  grub_uint32_t major;               /* 1 Device major number                
>       */
> -  grub_uint32_t minor;               /* 2 Device minor number                
>       */
> -  grub_uint32_t raid_disk;   /* 3 The role of the device in the raid set   */
> -  grub_uint32_t state;               /* 4 Operational state                  
>       */
> -  grub_uint32_t reserved[GRUB_RAID_SB_DESCRIPTOR_WORDS - 5];
> +  struct grub_raid *next;
>  };
> +typedef struct grub_raid *grub_raid_t;
>  
> -struct grub_raid_super_09 {
> -  /*
> -   * Constant generic information
> -   */
> -  grub_uint32_t md_magic;    /*  0 MD identifier                           */
> -  grub_uint32_t major_version;       /*  1 major version to which the set 
> conforms */
> -  grub_uint32_t minor_version;       /*  2 minor version ...                 
>       */
> -  grub_uint32_t patch_version;       /*  3 patchlevel version ...            
>       */
> -  grub_uint32_t gvalid_words;        /*  4 Number of used words in this 
> section    */
> -  grub_uint32_t set_uuid0;   /*  5 Raid set identifier                     */
> -  grub_uint32_t ctime;               /*  6 Creation time                     
>       */
> -  grub_uint32_t level;               /*  7 Raid personality                  
>       */
> -  grub_uint32_t size;                /*  8 Apparent size of each individual 
> disk   */
> -  grub_uint32_t nr_disks;    /*  9 total disks in the raid set             */
> -  grub_uint32_t raid_disks;  /* 10 disks in a fully functional raid set    */
> -  grub_uint32_t md_minor;    /* 11 preferred MD minor device number        */
> -  grub_uint32_t not_persistent;      /* 12 does it have a persistent 
> superblock    */
> -  grub_uint32_t set_uuid1;   /* 13 Raid set identifier #2                  */
> -  grub_uint32_t set_uuid2;   /* 14 Raid set identifier #3                  */
> -  grub_uint32_t set_uuid3;   /* 15 Raid set identifier #4                  */
> -  grub_uint32_t gstate_creserved[GRUB_RAID_SB_GENERIC_CONSTANT_WORDS - 16];
> -
> -  /*
> -   * Generic state information
> -   */
> -  grub_uint32_t utime;               /*  0 Superblock update time            
>       */
> -  grub_uint32_t state;               /*  1 State bits (clean, ...)           
>       */
> -  grub_uint32_t active_disks;        /*  2 Number of currently active disks  
>       */
> -  grub_uint32_t working_disks;       /*  3 Number of working disks           
>       */
> -  grub_uint32_t failed_disks;        /*  4 Number of failed disks            
>       */
> -  grub_uint32_t spare_disks; /*  5 Number of spare disks                   */
> -  grub_uint32_t sb_csum;     /*  6 checksum of the whole superblock        */
> -#ifdef GRUB_HOST_WORDS_BIGENDIAN
> -  grub_uint32_t events_hi;   /*  7 high-order of superblock update count   */
> -  grub_uint32_t events_lo;   /*  8 low-order of superblock update count    */
> -  grub_uint32_t cp_events_hi;        /*  9 high-order of checkpoint update 
> count   */
> -  grub_uint32_t cp_events_lo;        /* 10 low-order of checkpoint update 
> count    */
> -#else
> -  grub_uint32_t events_lo;   /*  7 low-order of superblock update count    */
> -  grub_uint32_t events_hi;   /*  8 high-order of superblock update count   */
> -  grub_uint32_t cp_events_lo;        /*  9 low-order of checkpoint update 
> count    */
> -  grub_uint32_t cp_events_hi;        /* 10 high-order of checkpoint update 
> count   */
> -#endif
> -  grub_uint32_t recovery_cp; /* 11 recovery checkpoint sector count        */
> -  grub_uint32_t gstate_sreserved[GRUB_RAID_SB_GENERIC_STATE_WORDS - 12];
> -
> -  /*
> -   * Personality information
> -   */
> -  grub_uint32_t layout;              /*  0 the array's physical layout       
>       */
> -  grub_uint32_t chunk_size;  /*  1 chunk size in bytes                     */
> -  grub_uint32_t root_pv;     /*  2 LV root PV */
> -  grub_uint32_t root_block;  /*  3 LV root block */
> -  grub_uint32_t pstate_reserved[GRUB_RAID_SB_PERSONALITY_WORDS - 4];
> +void grub_raid_register (grub_raid_t raid);
> +void grub_raid_unregister (grub_raid_t raid);
>  
> -  /*
> -   * Disks information
> -   */
> -  struct grub_raid_disk_09 disks[GRUB_RAID_SB_DISKS];
> -
> -  /*
> -   * Reserved
> -   */
> -  grub_uint32_t reserved[GRUB_RAID_SB_RESERVED_WORDS];
> -
> -  /*
> -   * Active descriptor
> -   */
> -  struct grub_raid_disk_09 this_disk;
> -};
> +void grub_raid_rescan (void);
>  
>  #endif /* ! GRUB_RAID_H */
> diff --git a/util/grub-fstest.c b/util/grub-fstest.c
> index 35af6a5..29234ac 100644
> --- a/util/grub-fstest.c
> +++ b/util/grub-fstest.c
> @@ -29,6 +29,7 @@
>  #include <grub/term.h>
>  #include <grub/mm.h>
>  #include <grub/normal.h>
> +#include <grub/raid.h>
>  #include <grub/lib/hexdump.h>
>  
>  #include <grub_fstest_init.h>
> @@ -141,7 +142,6 @@ grub_unregister_command (const char *name __attribute__ 
> ((unused)))
>  #define BUF_SIZE  32256
>  
>  static grub_off_t skip, leng;
> -static char *part;
>  
>  static void
>  read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len))
> @@ -273,32 +273,61 @@ cmd_hex (char *pathname)
>      return 0;
>    }
>  
> -  read_file (pathname, hex_hook);
> +  if (pathname)
> +    read_file (pathname, hex_hook);
> +  else
> +    {
> +      char buf[BUF_SIZE];
> +      grub_device_t dev;
> +
> +      dev = grub_device_open (0);
> +      if ((! dev) || (! dev->disk))
> +        grub_util_error ("Can\'t open device");
> +
> +      if (! leng)
> +        leng = GRUB_DISK_SECTOR_SIZE;
> +
> +      while (leng)
> +        {
> +          grub_size_t len;
> +
> +          len = (leng > BUF_SIZE) ? BUF_SIZE : leng;
> +
> +          if (grub_disk_read (dev->disk, 0, skip, len, buf))
> +            grub_util_error ("Disk read fails at offset %lld, length %d\n",
> +                             skip, len);
> +
> +          hexdump (skip, buf, len);
> +
> +          skip += len;
> +          leng -= len;
> +        }
> +
> +      grub_device_close (dev);
> +    }
>  }
>  
>  static void
> -fstest (char *image_path, int cmd, int n, char **args)
> +fstest (char **images, int num_disks, int cmd, int n, char **args)
>  {
> -  char host_file[7 + grub_strlen (image_path) + 1];
> -  char device_name[(part) ? (6 + grub_strlen (part)) : 5];
> -  char *argv[3] = { "-p", "loop", host_file };
> -
> -
> -  grub_sprintf (host_file, "(host)/%s", image_path);
> +  char host_file[128];
> +  char loop_name[8];
> +  char *argv[3] = { "-p", loop_name, host_file};
> +  int i;
>  
> -  if (execute_command (&cmd_loopback, 3, argv))
> +  for (i = 0; i < num_disks; i++)
>      {
> -      grub_util_error ("loopback command fails.\n");
> -      goto fail;
> -    }
> +      if (grub_strlen (images[i]) + 7 > sizeof (host_file))
> +        grub_util_error ("Pathname %s too long", images[i]);
>  
> -  if (part)
> -    grub_sprintf (device_name, "loop,%s", part);
> -  else
> -    grub_strcpy (device_name, "loop");
> +      grub_sprintf (loop_name, "loop%d", i);
> +      grub_sprintf (host_file, "(host)%s", images[i]);
>  
> -  grub_env_set ("root", device_name);
> +      if (execute_command (&cmd_loopback, 3, argv))
> +        grub_util_error ("loopback command fails.\n");
> +    }
>  
> +  grub_raid_rescan ();
>    switch (cmd)
>      {
>      case CMD_LS:
> @@ -311,31 +340,31 @@ fstest (char *image_path, int cmd, int n, char **args)
>        cmd_cmp (args[0], args[1]);
>        break;
>      case CMD_HEX:
> -      cmd_hex (args[0]);
> +      cmd_hex ((n == 0) ? 0 : args[0]);
>        break;
>      case CMD_BLOCKLIST:
>        execute_command (&cmd_blocklist, n, args);
>        grub_printf ("\n");
>      }
>  
> -fail:
> -
>    argv[0] = "-d";
>  
> -  execute_command (&cmd_loopback, 2, argv);
> +  for (i = 0; i < num_disks; i++)
> +    {
> +      grub_sprintf (loop_name, "loop%d", i);
> +      execute_command (&cmd_loopback, 2, argv);
> +    }
>  }
>  
>  static struct option options[] = {
> -  {"part", required_argument, 0, 'p'},
> +  {"root", required_argument, 0, 'r'},
>    {"skip", required_argument, 0, 's'},
>    {"length", required_argument, 0, 'n'},
> +  {"diskcount", required_argument, 0, 'c'},
>    {"debug", required_argument, 0, 'd'},
> -  {"raw", no_argument, 0, 'r'},
> -  {"long", no_argument, 0, 'l'},
>    {"help", no_argument, 0, 'h'},
>    {"version", no_argument, 0, 'V'},
>    {"verbose", no_argument, 0, 'v'},
> -
>    {0, 0, 0, 0}
>  };
>  
> @@ -353,15 +382,14 @@ Debug tool for filesystem driver.\n\
>    ls PATH                   list files in PATH\n\
>    cp SRC DEST               copy file to local system\n\
>    cmp SRC DEST              compare files\n\
> -  hex FILE                  hex dump FILE\n\
> +  hex [FILE]                Hex dump FILE\n\
>    blocklist FILE            display blocklist of FILE\n\
>  \nOptions:\n\
> -  -p, --part=NUM            select partition NUM\n\
> +  -r, --root=DEVICE_NAME    set root device\n\
>    -s, --skip=N              skip N bytes from output file\n\
>    -n, --length=N            handle N bytes in output file\n\
> +  -c, --diskcount=N         N input files\n\
>    -d, --debug=S             Set debug environment variable\n\
> -  -r, --raw                 disable auto decompression\n\
> -  -l, --long                show long directory list\n\
>    -h, --help                display this message and exit\n\
>    -V, --version             print version information and exit\n\
>    -v, --verbose             print verbose messages\n\
> @@ -374,45 +402,66 @@ Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
>  int
>  main (int argc, char *argv[])
>  {
> -  char *image_path, *debug_str = 0;
> -  int cmd, is_raw = 0, is_long = 0;
> +  char *debug_str = 0, *root = 0, *default_root, *alloc_root;
> +  int i, cmd, num_opts, image_index, num_disks = 1;
>  
>    progname = "grub-fstest";
>  
> +  /* Find the first non option entry.  */
> +  for (num_opts = 1; num_opts < argc; num_opts++)
> +    if (argv[num_opts][0] == '-')
> +      {
> +        if ((argv[num_opts][2] == 0) && (num_opts < argc - 1) &&
> +            ((argv[num_opts][1] == 'r') ||
> +             (argv[num_opts][1] == 's') ||
> +             (argv[num_opts][1] == 'n') ||
> +             (argv[num_opts][1] == 'c') ||
> +             (argv[num_opts][1] == 'd')))
> +            num_opts++;
> +      }
> +    else
> +      break;
> +
>    /* Check for options.  */
>    while (1)
>      {
> -      int c = getopt_long (argc, argv, "p:s:n:d:rlhVv", options, 0);
> +      int c = getopt_long (num_opts, argv, "r:s:n:c:d:hVv", options, 0);
> +      char *p;
>  
>        if (c == -1)
>       break;
>        else
>       switch (c)
>         {
> -       case 'p':
> -         part = optarg;
> +       case 'r':
> +         root = optarg;
>           break;
>  
>         case 's':
> -         skip = grub_strtoul (optarg, NULL, 0);
> +         skip = grub_strtoul (optarg, &p, 0);
> +            if (*p == 's')
> +              skip <<= GRUB_DISK_SECTOR_BITS;
>           break;
>  
>         case 'n':
> -         leng = grub_strtoul (optarg, NULL, 0);
> +         leng = grub_strtoul (optarg, &p, 0);
> +            if (*p == 's')
> +              leng <<= GRUB_DISK_SECTOR_BITS;
>           break;
>  
> +          case 'c':
> +            num_disks = grub_strtoul (optarg, NULL, 0);
> +            if (num_disks < 1)
> +              {
> +                fprintf (stderr, "Invalid disk count.\n");
> +                usage (1);
> +              }
> +            break;
> +
>            case 'd':
>              debug_str = optarg;
>              break;
>  
> -       case 'r':
> -         is_raw = 1;
> -         break;
> -
> -       case 'l':
> -         is_long = 1;
> -         break;
> -
>         case 'h':
>           usage (0);
>           break;
> @@ -432,35 +481,29 @@ main (int argc, char *argv[])
>      }
>  
>    /* Obtain PATH.  */
> -  if (optind >= argc)
> -    {
> -      fprintf (stderr, "No path is specified.\n");
> -      usage (1);
> -    }
> -
> -  image_path = argv[optind];
> -
> -  if (*image_path != '/')
> +  if (optind + num_disks - 1 >= argc)
>      {
> -      fprintf (stderr, "Must use absolute path.\n");
> +      fprintf (stderr, "Not enough pathname.\n");
>        usage (1);
>      }
>  
> -  optind++;
> +  image_index = optind;
> +  for (i = 0; i < num_disks; i++, optind++)
> +    if (argv[optind][0] != '/')
> +      {
> +        fprintf (stderr, "Must use absolute path.\n");
> +        usage (1);
> +      }
>  
>    cmd = 0;
>    if (optind < argc)
>      {
> -      int nparm = 1;
> +      int nparm = 0;
>  
>        if (!grub_strcmp (argv[optind], "ls"))
> -     {
> -       cmd = CMD_LS;
> -       if (is_long)
> -         argv[optind--] = "-l";
> -       else
> -         nparm = 0;
> -     }
> +        {
> +          cmd = CMD_LS;
> +        }
>        else if (!grub_strcmp (argv[optind], "cp"))
>       {
>         cmd = CMD_CP;
> @@ -478,6 +521,7 @@ main (int argc, char *argv[])
>        else if (!grub_strcmp (argv[optind], "blocklist"))
>       {
>         cmd = CMD_BLOCKLIST;
> +          nparm = 1;
>       }
>        else
>       {
> @@ -503,14 +547,31 @@ main (int argc, char *argv[])
>    /* Initialize all modules. */
>    grub_init_all ();
>  
> -  if (is_raw)
> -    grub_env_set ("filehook", "0");
> -
>    if (debug_str)
>      grub_env_set ("debug", debug_str);
>  
> +  default_root = (num_disks == 1) ? "loop0" : "md0";
> +  alloc_root = 0;
> +  if (root)
> +    {
> +      if ((*root >= '0') && (*root <= '9'))
> +        {
> +          alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2);
> +
> +          sprintf (alloc_root, "%s,%s", default_root, root);
> +          root = alloc_root;
> +        }
> +    }
> +  else
> +    root = default_root;
> +
> +  grub_env_set ("root", root);
> +
> +  if (alloc_root)
> +    free (alloc_root);
> +
>    /* Do it.  */
> -  fstest (image_path + 1, cmd, argc - optind, argv + optind);
> +  fstest (argv + image_index, num_disks, cmd, argc - optind, argv + optind);
>  
>    /* Free resources.  */
>    grub_fini_all ();
> diff --git a/util/grub-probe.c b/util/grub-probe.c
> index a4f51e2..ce9cbff 100644
> --- a/util/grub-probe.c
> +++ b/util/grub-probe.c
> @@ -142,7 +142,7 @@ probe (const char *path, char *device_name)
>         abstraction_name = "lvm";
>         break;
>       case GRUB_DEV_ABSTRACTION_RAID:
> -       abstraction_name = "raid";
> +       abstraction_name = "raid mdraid";
>         break;
>       default:
>         grub_util_info ("did not find LVM/RAID in %s, assuming raw device", 
> device_name);
> _______________________________________________
> Grub-devel mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel





reply via email to

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