* grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Do not put

elements with invlid index.
	* grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise.
	* grub-core/disk/raid.c (insert_array): Automatically reallocate
	members.
	* include/grub/raid.h (grub_raid_member): New struct.
	(grub_raid_array): Transform devices and start_sector into usage of
	grub_raid_member. All users updated
	(allocated_devs): New member.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-11-01 10:20:58 +01:00
parent 71574288a4
commit 3a1197cdb0
7 changed files with 88 additions and 38 deletions

View file

@ -1,3 +1,15 @@
2010-11-01 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Do not put
elements with invlid index.
* grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise.
* grub-core/disk/raid.c (insert_array): Automatically reallocate
members.
* include/grub/raid.h (grub_raid_member): New struct.
(grub_raid_array): Transform devices and start_sector into usage of
grub_raid_member. All users updated
(allocated_devs): New member.
2010-11-01 Vladimir Serbinenko <phcoder@gmail.com> 2010-11-01 Vladimir Serbinenko <phcoder@gmail.com>
* docs/man/grub-set-default.h2m: Clarify that only saved default entry * docs/man/grub-set-default.h2m: Clarify that only saved default entry

View file

@ -188,12 +188,14 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size); array->disk_size = grub_le_to_cpu64 (real_sb->size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) <
if (grub_le_to_cpu32 (real_sb->dev_number) >=
grub_le_to_cpu32 (real_sb->max_dev)) grub_le_to_cpu32 (real_sb->max_dev))
array->index = grub_le_to_cpu16 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); "spares aren't implemented");
else
array->index = 0xffff; /* disk will be later not used! */ array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
array->uuid_len = 16; array->uuid_len = 16;
array->uuid = grub_malloc (16); array->uuid = grub_malloc (16);
if (!array->uuid) if (!array->uuid)

View file

@ -194,6 +194,9 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
sb.level != 5 && sb.level != 6 && sb.level != 10) sb.level != 5 && sb.level != 6 && sb.level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.level); "unsupported RAID level: %d", sb.level);
if (sb.this_disk.number == 0xffff || sb.this_disk.number == 0xfffe)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"spares aren't implemented");
array->name = NULL; array->name = NULL;
array->number = sb.md_minor; array->number = sb.md_minor;

View file

@ -97,10 +97,10 @@ grub_raid_memberlist (grub_disk_t disk)
unsigned int i; unsigned int i;
for (i = 0; i < array->total_devs; i++) for (i = 0; i < array->total_devs; i++)
if (array->device[i]) if (array->members[i].device)
{ {
tmp = grub_malloc (sizeof (*tmp)); tmp = grub_malloc (sizeof (*tmp));
tmp->disk = array->device[i]; tmp->disk = array->members[i].device;
tmp->next = list; tmp->next = list;
list = tmp; list = tmp;
} }
@ -255,13 +255,13 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
k = disknr; k = disknr;
for (j = 0; j < far; j++) for (j = 0; j < far; j++)
{ {
if (array->device[k]) if (array->members[k].device)
{ {
if (grub_errno == GRUB_ERR_READ_ERROR) if (grub_errno == GRUB_ERR_READ_ERROR)
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[k], err = grub_disk_read (array->members[k].device,
array->start_sector[k] + array->members[k].start_sector +
read_sector + j * far_ofs + b, read_sector + j * far_ofs + b,
0, 0,
read_size << GRUB_DISK_SECTOR_BITS, read_size << GRUB_DISK_SECTOR_BITS,
@ -367,14 +367,14 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
read_size = size; read_size = size;
e = 0; e = 0;
if (array->device[disknr]) if (array->members[disknr].device)
{ {
/* Reset read error. */ /* Reset read error. */
if (grub_errno == GRUB_ERR_READ_ERROR) if (grub_errno == GRUB_ERR_READ_ERROR)
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
err = grub_disk_read (array->device[disknr], err = grub_disk_read (array->members[disknr].device,
array->start_sector[disknr] + array->members[disknr].start_sector +
read_sector + b, 0, read_sector + b, 0,
read_size << GRUB_DISK_SECTOR_BITS, read_size << GRUB_DISK_SECTOR_BITS,
buf); buf);
@ -500,6 +500,21 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
/* Do some checks before adding the device to the array. */ /* Do some checks before adding the device to the array. */
if (new_array->index >= array->allocated_devs)
{
void *tmp;
unsigned int newnum = 2 * (new_array->index + 1);
tmp = grub_realloc (array->members, newnum
* sizeof (array->members[0]));
if (!tmp)
return grub_errno;
array->members = tmp;
grub_memset (array->members + array->allocated_devs,
0, (newnum - array->allocated_devs)
* sizeof (array->members[0]));
array->allocated_devs = newnum;
}
/* FIXME: Check whether the update time of the superblocks are /* FIXME: Check whether the update time of the superblocks are
the same. */ the same. */
@ -510,7 +525,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?", grub_dprintf ("raid", "array->nr_devs > array->total_devs (%d)?!?",
array->total_devs); array->total_devs);
if (array->device[new_array->index] != NULL) if (array->members[new_array->index].device != NULL)
/* We found multiple devices with the same number. Again, /* We found multiple devices with the same number. Again,
this shouldn't happen. */ this shouldn't happen. */
grub_dprintf ("raid", "Found two disks with the number %d?!?", grub_dprintf ("raid", "Found two disks with the number %d?!?",
@ -536,8 +551,18 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
array->driver = raid; array->driver = raid;
#endif #endif
grub_memset (&array->device, 0, sizeof (array->device)); array->allocated_devs = 32;
grub_memset (&array->start_sector, 0, sizeof (array->start_sector)); if (new_array->index >= array->allocated_devs)
array->allocated_devs = 2 * (new_array->index + 1);
array->members = grub_zalloc (array->allocated_devs
* sizeof (array->members[0]));
if (!array->members)
{
grub_free (new_array->uuid);
return grub_errno;
}
if (! array->name) if (! array->name)
{ {
@ -582,6 +607,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
array->name = grub_xasprintf ("md%d", array->number); array->name = grub_xasprintf ("md%d", array->number);
if (! array->name) if (! array->name)
{ {
grub_free (array->members);
grub_free (array->uuid); grub_free (array->uuid);
grub_free (array); grub_free (array);
@ -597,6 +623,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
if (! new_name) if (! new_name)
{ {
grub_free (array->members);
grub_free (array->uuid); grub_free (array->uuid);
grub_free (array); grub_free (array);
@ -621,8 +648,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
} }
/* Add the device to the array. */ /* Add the device to the array. */
array->device[new_array->index] = disk; array->members[new_array->index].device = disk;
array->start_sector[new_array->index] = start_sector; array->members[new_array->index].start_sector = start_sector;
array->nr_devs++; array->nr_devs++;
return 0; return 0;
@ -639,14 +666,15 @@ free_array (void)
while (array) while (array)
{ {
struct grub_raid_array *p; struct grub_raid_array *p;
int i; unsigned int i;
p = array; p = array;
array = array->next; array = array->next;
for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++) for (i = 0; i < p->allocated_devs; i++)
if (p->device[i]) if (p->members[i].device)
grub_disk_close (p->device[i]); grub_disk_close (p->members[i].device);
grub_free (p->members);
grub_free (p->uuid); grub_free (p->uuid);
grub_free (p->name); grub_free (p->name);

View file

@ -45,7 +45,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
if (i == disknr) if (i == disknr)
continue; continue;
err = grub_disk_read (array->device[i], sector, 0, size, buf2); err = grub_disk_read (array->members[i].device, sector, 0, size, buf2);
if (err) if (err)
{ {

View file

@ -118,8 +118,9 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
bad1 = i; bad1 = i;
else else
{ {
if ((array->device[pos]) && if ((array->members[pos].device) &&
(! grub_disk_read (array->device[pos], sector, 0, size, buf))) (! grub_disk_read (array->members[pos].device, sector,
0, size, buf)))
{ {
grub_raid_block_xor (pbuf, buf, size); grub_raid_block_xor (pbuf, buf, size);
grub_raid_block_mul (raid6_table2[i][i], buf, size); grub_raid_block_mul (raid6_table2[i][i], buf, size);
@ -148,21 +149,21 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
if (bad2 < 0) if (bad2 < 0)
{ {
/* One bad device */ /* One bad device */
if ((array->device[p]) && if ((array->members[p].device) &&
(! grub_disk_read (array->device[p], sector, 0, size, buf))) (! grub_disk_read (array->members[p].device, sector, 0, size, buf)))
{ {
grub_raid_block_xor (buf, pbuf, size); grub_raid_block_xor (buf, pbuf, size);
goto quit; goto quit;
} }
if (! array->device[q]) if (! array->members[q].device)
{ {
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
goto quit; goto quit;
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
if (grub_disk_read (array->device[q], sector, 0, size, buf)) if (grub_disk_read (array->members[q].device, sector, 0, size, buf))
goto quit; goto quit;
grub_raid_block_xor (buf, qbuf, size); grub_raid_block_xor (buf, qbuf, size);
@ -174,18 +175,18 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
/* Two bad devices */ /* Two bad devices */
grub_uint8_t c; grub_uint8_t c;
if ((! array->device[p]) || (! array->device[q])) if ((! array->members[p].device) || (! array->members[q].device))
{ {
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
goto quit; goto quit;
} }
if (grub_disk_read (array->device[p], sector, 0, size, buf)) if (grub_disk_read (array->members[p].device, sector, 0, size, buf))
goto quit; goto quit;
grub_raid_block_xor (pbuf, buf, size); grub_raid_block_xor (pbuf, buf, size);
if (grub_disk_read (array->device[q], sector, 0, size, buf)) if (grub_disk_read (array->members[q].device, sector, 0, size, buf))
goto quit; goto quit;
grub_raid_block_xor (qbuf, buf, size); grub_raid_block_xor (qbuf, buf, size);

View file

@ -22,8 +22,6 @@
#include <grub/types.h> #include <grub/types.h>
#define GRUB_RAID_MAX_DEVICES 32
#define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC 0 #define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC 0
#define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC 1 #define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC 1
#define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC 2 #define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC 2
@ -32,6 +30,13 @@
#define GRUB_RAID_LAYOUT_RIGHT_MASK 1 #define GRUB_RAID_LAYOUT_RIGHT_MASK 1
#define GRUB_RAID_LAYOUT_SYMMETRIC_MASK 2 #define GRUB_RAID_LAYOUT_SYMMETRIC_MASK 2
struct grub_raid_member
{
grub_disk_t device; /* Array of total_devs devices. */
grub_disk_addr_t start_sector;
/* Start of each device, in 512 byte sectors. */
};
struct grub_raid_array struct grub_raid_array
{ {
int number; /* The device number, taken from md_minor so we int number; /* The device number, taken from md_minor so we
@ -43,16 +48,15 @@ struct grub_raid_array
grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */ 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 grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte
sectors. */ sectors. */
int index; /* Index of current device. */ unsigned int index; /* Index of current device. */
int uuid_len; /* The length of uuid. */ int uuid_len; /* The length of uuid. */
char *uuid; /* The UUID of the device. */ char *uuid; /* The UUID of the device. */
/* The following field is setup by the caller. */ /* The following field is setup by the caller. */
char *name; /* That will be "md<number>". */ char *name; /* That will be "md<number>". */
unsigned int nr_devs; /* The number of devices we've found so far. */ 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. */ unsigned int allocated_devs;
grub_disk_addr_t start_sector[GRUB_RAID_MAX_DEVICES]; struct grub_raid_member *members;
/* Start of each device, in 512 byte sectors. */
struct grub_raid_array *next; struct grub_raid_array *next;
#ifdef GRUB_UTIL #ifdef GRUB_UTIL