Bean <[EMAIL PROTECTED]> writes: > On Tue, Aug 12, 2008 at 4:30 AM, Robert Millan <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> > > * 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 > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel