* Couple more fixes for Linux raid metadata 1.x support
@ 2010-07-24 10:22 Doug Nazar
2010-07-26 17:20 ` Lennart Sorensen
0 siblings, 1 reply; 3+ messages in thread
From: Doug Nazar @ 2010-07-24 10:22 UTC (permalink / raw)
To: grub-devel, Colin Watson, Felix Zielcke, Peter Henn
[-- Attachment #1: Type: text/plain, Size: 442 bytes --]
While doing some in-depth testing came across a few more issues. The
second one really threw me for a loop. The LVM wouldn't come up because
it couldn't find some of the raid arrays but when I hexdumped the raid
arrays it showed the correct uuid. Applies on top of previous patch.
- Ignore spare and faulty drives
- Set a dynamic array->number. It's used for the disk->id and is important
for the cache subsystem that it be unique.
[-- Attachment #2: grub-update-raid-metadata-1x-support-2.diff --]
[-- Type: text/plain, Size: 2931 bytes --]
=== modified file 'disk/mdraid_linux.c'
--- disk/mdraid_linux.c 2010-07-23 05:25:00 +0000
+++ disk/mdraid_linux.c 2010-07-24 05:53:53 +0000
@@ -363,6 +363,19 @@
return grub_error (GRUB_ERR_OUT_OF_RANGE, "csum invalid");
}
+ if (grub_le_to_cpu32 (real_sb->dev_number) <
+ grub_le_to_cpu32 (real_sb->max_dev))
+ array->index = grub_le_to_cpu16
+ (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
+ else
+ array->index = 0xffff; /* disk will be later not used! */
+
+ if (array->index == 0xffff || array->index == 0xfffe)
+ {
+ grub_free (real_sb);
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "spare or faulty drive");
+ }
+
array->name = grub_strdup (real_sb->set_name);
if (! array->name)
{
@@ -375,14 +388,11 @@
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
+ if (!array->disk_size)
+ /* Level 0 doesn't seem to set sb->size */
+ array->disk_size = grub_le_to_cpu64 (real_sb->data_size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
array->freshness = grub_le_to_cpu32(real_sb->events);
- if (grub_le_to_cpu32 (real_sb->dev_number) <
- grub_le_to_cpu32 (real_sb->max_dev))
- array->index = grub_le_to_cpu16
- (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
- else
- array->index = 0xffff; /* disk will be later not used! */
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
=== modified file 'disk/raid.c'
--- disk/raid.c 2010-07-23 05:25:00 +0000
+++ disk/raid.c 2010-07-24 09:57:05 +0000
@@ -555,25 +555,28 @@
grub_memset (&array->device, 0, sizeof (array->device));
grub_memset (&array->start_sector, 0, sizeof (array->start_sector));
+ /* mdraid 1.x superblocks don't have a number but we need a unique id
+ for the cache system. Start numbering down from the top. */
if (array->name)
- goto skip_duplicate_check;
+ array->number = -1;
+
/* Check whether we don't have multiple arrays with the same number. */
for (p = array_list; p != NULL; p = p->next)
{
- if (! p->name && p->number == array->number)
+ if (p->number == array->number)
break;
}
if (p)
{
/* The number is already in use, so we need to find a new one. */
- int i = 0;
+ int i = array->name ? -2 : 0;
while (1)
{
for (p = array_list; p != NULL; p = p->next)
{
- if (! p->name && p->number == i)
+ if (p->number == i)
break;
}
@@ -584,10 +587,10 @@
break;
}
- i++;
+ i += array->name ? -1 : 1;
}
}
- skip_duplicate_check:
+
/* mdraid 1.x superblocks have only a name stored not a number.
Use it directly as GRUB device. */
if (! array->name)
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: Couple more fixes for Linux raid metadata 1.x support 2010-07-24 10:22 Couple more fixes for Linux raid metadata 1.x support Doug Nazar @ 2010-07-26 17:20 ` Lennart Sorensen 2010-07-26 21:07 ` Big Endian fix patch (was: Re: Couple more fixes for Linux raid metadata 1.x support) Lennart Sorensen 0 siblings, 1 reply; 3+ messages in thread From: Lennart Sorensen @ 2010-07-26 17:20 UTC (permalink / raw) To: The development of GNU GRUB; +Cc: Peter Henn, Felix Zielcke, Colin Watson On Sat, Jul 24, 2010 at 06:22:02AM -0400, Doug Nazar wrote: > While doing some in-depth testing came across a few more issues. The > second one really threw me for a loop. The LVM wouldn't come up because > it couldn't find some of the raid arrays but when I hexdumped the raid > arrays it showed the correct uuid. Applies on top of previous patch. > > - Ignore spare and faulty drives > - Set a dynamic array->number. It's used for the disk->id and is important > for the cache subsystem that it be unique. I just tried this patch with a fresh checkout. I still can't get grub to read my 1.x raids (That I just created using the debian installer daily build). If I use 0.9 raid, it seems to work fine. I keep getting errors like: Welcome to GRUB! error: read error on block: 18446744073709551360. error: no such disk. Entering rescue mode... grub rescue> Now this is on a powerpc64 system, so it is big endian. That number by the way is FFFFFFFFFFFFFF00. I wonder if some part of the 1.x raid handling code has an endianess bug. Got any guesses I can try before I just go convert back to 0.9 raids? I really hate giving up on things that ought to work and loose the debugging opportunity. -- Len Sorensen ^ permalink raw reply [flat|nested] 3+ messages in thread
* Big Endian fix patch (was: Re: Couple more fixes for Linux raid metadata 1.x support) 2010-07-26 17:20 ` Lennart Sorensen @ 2010-07-26 21:07 ` Lennart Sorensen 0 siblings, 0 replies; 3+ messages in thread From: Lennart Sorensen @ 2010-07-26 21:07 UTC (permalink / raw) To: The development of GNU GRUB; +Cc: Peter Henn, Felix Zielcke, Colin Watson [-- Attachment #1: Type: text/plain, Size: 941 bytes --] On Mon, Jul 26, 2010 at 01:20:34PM -0400, Lennart Sorensen wrote: > I just tried this patch with a fresh checkout. I still can't get grub > to read my 1.x raids (That I just created using the debian installer > daily build). > > If I use 0.9 raid, it seems to work fine. > > I keep getting errors like: > > Welcome to GRUB! > > error: read error on block: 18446744073709551360. > error: no such disk. > Entering rescue mode... > grub rescue> > > Now this is on a powerpc64 system, so it is big endian. That number by > the way is FFFFFFFFFFFFFF00. > > I wonder if some part of the 1.x raid handling code has an endianess bug. > > Got any guesses I can try before I just go convert back to 0.9 raids? > I really hate giving up on things that ought to work and loose the > debugging opportunity. Turns out it very much was endian issues. Here is a patch that fixes it for me. I am using your two recent patches as well. -- Len Sorensen [-- Attachment #2: md_raid_1x_bigendian_fix.diff --] [-- Type: text/x-diff, Size: 3459 bytes --] --- grub-updates/grub2-1.98+20100726/disk/mdraid_linux.c 2010-07-26 11:53:14.000000000 -0400 +++ grub2-1.98+20100726.working/disk/mdraid_linux.c 2010-07-26 17:03:31.127206219 -0400 @@ -290,7 +290,7 @@ grub_uint32_t disk_csum; grub_uint32_t csum; grub_uint64_t newcsum; - int size = 256 + sb->max_dev*2; + int size = 256 + grub_le_to_cpu32(sb->max_dev)*2; grub_uint32_t *isuper = (grub_uint32_t*)sb; int i; @@ -309,6 +309,12 @@ return csum; } +static grub_uint32_t grub_mdraid_csum_fold(grub_uint32_t csum) +{ + csum = (csum & 0xffff) + (csum >> 16); + return (csum & 0xffff) + (csum >> 16); +} + static grub_err_t grub_mdraid_detect_1x (grub_disk_t disk, grub_disk_addr_t sector, struct grub_raid_super_1x *sb, @@ -318,31 +324,31 @@ grub_uint64_t sb_size; struct grub_raid_super_1x *real_sb; - if (sb->major_version != 1) + if (grub_le_to_cpu32(sb->major_version) != 1) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported RAID version: %d", - sb->major_version); + grub_le_to_cpu32(sb->major_version)); - if (sb->super_offset != sector) + if (grub_le_to_cpu64(sb->super_offset) != sector) /* We're not where we're supposed to be. Usually caused by a 1.0 superblock at the end of a disk with a single large partition. */ return grub_error (GRUB_ERR_OUT_OF_RANGE, "wrong superblock location"); - if (sb->feature_map & MD_FEATURE_RECOVERY_OFFSET) + if (grub_le_to_cpu32(sb->feature_map) & MD_FEATURE_RECOVERY_OFFSET) /* Disk is currently being recovered. Silently ignore it. */ return grub_error (GRUB_ERR_OUT_OF_RANGE, "recovery in progress"); - if (sb->feature_map & MD_FEATURE_RESHAPE_ACTIVE) + if (grub_le_to_cpu32(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "reshape active"); /* Multipath. */ - if ((int) sb->level == -4) + if ((int) grub_le_to_cpu32(sb->level) == -4) sb->level = 1; - if (sb->level != 0 && sb->level != 1 && sb->level != 4 && - sb->level != 5 && sb->level != 6 && sb->level != 10) + if (grub_le_to_cpu32(sb->level) != 0 && grub_le_to_cpu32(sb->level) != 1 && grub_le_to_cpu32(sb->level) != 4 && + grub_le_to_cpu32(sb->level) != 5 && grub_le_to_cpu32(sb->level) != 6 && grub_le_to_cpu32(sb->level) != 10) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Unsupported RAID level: %d", sb->level); + "Unsupported RAID level: %d", grub_le_to_cpu32(sb->level)); /* 1.x superblocks don't have a fixed size on disk. So we have to read it again now that we now the max device count. */ @@ -357,7 +363,7 @@ return grub_errno; } - if (grub_mdraid_calc_csum(real_sb) != real_sb->sb_csum) + if (grub_mdraid_csum_fold(grub_mdraid_calc_csum(real_sb)) != grub_mdraid_csum_fold(real_sb->sb_csum)) { grub_free (real_sb); return grub_error (GRUB_ERR_OUT_OF_RANGE, "csum invalid"); @@ -403,7 +409,7 @@ grub_memcpy (array->uuid, real_sb->set_uuid, 16); - *start_sector = real_sb->data_offset; + *start_sector = grub_le_to_cpu64(real_sb->data_offset); grub_free (real_sb); return 0; @@ -457,9 +463,10 @@ &sb_1x)) return grub_errno; - if (sb_1x.magic == SB_MAGIC) + if (grub_le_to_cpu32(sb_1x.magic) == SB_MAGIC) { return grub_mdraid_detect_1x (disk, sector, &sb_1x, array, start_sector); + } } /* Neither 0.90 nor 1.x. */ ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-07-26 21:07 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-07-24 10:22 Couple more fixes for Linux raid metadata 1.x support Doug Nazar 2010-07-26 17:20 ` Lennart Sorensen 2010-07-26 21:07 ` Big Endian fix patch (was: Re: Couple more fixes for Linux raid metadata 1.x support) Lennart Sorensen
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.