[Top][All Lists]
[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
- Re: [PATCH] Split of raid scan code, (continued)
- Re: [PATCH] Split of raid scan code, Robert Millan, 2008/08/10
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/10
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/10
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/11
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/11
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/11
- Re: [PATCH] Split of raid scan code, Robert Millan, 2008/08/11
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/12
- Re: [PATCH] Split of raid scan code, Felix Zielcke, 2008/08/12
- Re: [PATCH] Split of raid scan code, Robert Millan, 2008/08/12
- Re: [PATCH] Split of raid scan code,
Marco Gerards <=
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/13
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/13
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/16
- Re: [PATCH] Split of raid scan code, Robert Millan, 2008/08/16
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/16
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/17
- Re: [PATCH] Split of raid scan code, Robert Millan, 2008/08/17
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/17
- Re: [PATCH] Split of raid scan code, Robert Millan, 2008/08/17
- Re: [PATCH] Split of raid scan code, Bean, 2008/08/18