]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Do not put
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 1 Nov 2010 09:20:58 +0000 (10:20 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 1 Nov 2010 09:20:58 +0000 (10:20 +0100)
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.

ChangeLog
grub-core/disk/mdraid1x_linux.c
grub-core/disk/mdraid_linux.c
grub-core/disk/raid.c
grub-core/disk/raid5_recover.c
grub-core/disk/raid6_recover.c
include/grub/raid.h

index 2e29b4fb244dbcfaa25a15397c5456ae4f8c7229..bd8390286e7a764c6261c40509d774587c677280 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * docs/man/grub-set-default.h2m: Clarify that only saved default entry
index 4a029834731d4382e795e87a758de1a487721d2a..dd60df69567d7983df260c42661502a0b7504d06 100644 (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->disk_size = grub_le_to_cpu64 (real_sb->size);
        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))
-         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! */
+         return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+                            "spares aren't implemented");
+
+       array->index = grub_le_to_cpu16
+         (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
        array->uuid_len = 16;
        array->uuid = grub_malloc (16);
        if (!array->uuid)
index 549d48355c5ea383f83264c56b6cf36830370243..f5cad9dbf6be044f3d8efe803a82f6cd50715a62 100644 (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)
     return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
                       "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->number = sb.md_minor;
index c7c641ebd00e0e8baae1b0b6e20d0ca3f3bfde0b..f1b67a8591b69d538f20e15c08ab55a7559dc008 100644 (file)
@@ -97,10 +97,10 @@ grub_raid_memberlist (grub_disk_t disk)
   unsigned int i;
 
   for (i = 0; i < array->total_devs; i++)
-    if (array->device[i])
+    if (array->members[i].device)
       {
         tmp = grub_malloc (sizeof (*tmp));
-        tmp->disk = array->device[i];
+        tmp->disk = array->members[i].device;
         tmp->next = list;
         list = tmp;
       }
@@ -255,13 +255,13 @@ grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
                 k = disknr;
                 for (j = 0; j < far; j++)
                   {
-                    if (array->device[k])
+                    if (array->members[k].device)
                       {
                         if (grub_errno == GRUB_ERR_READ_ERROR)
                           grub_errno = GRUB_ERR_NONE;
 
-                        err = grub_disk_read (array->device[k],
-                                              array->start_sector[k] +
+                        err = grub_disk_read (array->members[k].device,
+                                              array->members[k].start_sector +
                                                 read_sector + j * far_ofs + b,
                                               0,
                                               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;
 
             e = 0;
-            if (array->device[disknr])
+            if (array->members[disknr].device)
               {
                 /* Reset read error.  */
                 if (grub_errno == GRUB_ERR_READ_ERROR)
                   grub_errno = GRUB_ERR_NONE;
 
-                err = grub_disk_read (array->device[disknr],
-                                      array->start_sector[disknr] +
+                err = grub_disk_read (array->members[disknr].device,
+                                      array->members[disknr].start_sector +
                                         read_sector + b, 0,
                                       read_size << GRUB_DISK_SECTOR_BITS,
                                       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.  */
 
+       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
            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)?!?",
                        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,
              this shouldn't happen.  */
           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
       array->driver = raid;
 #endif
-      grub_memset (&array->device, 0, sizeof (array->device));
-      grub_memset (&array->start_sector, 0, sizeof (array->start_sector));
+      array->allocated_devs = 32;
+      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)
        {
@@ -582,6 +607,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
          array->name = grub_xasprintf ("md%d", array->number);
          if (! array->name)
            {
+             grub_free (array->members);
              grub_free (array->uuid);
              grub_free (array);
 
@@ -597,6 +623,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
 
          if (! new_name)
            {
+             grub_free (array->members);
              grub_free (array->uuid);
              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. */
-  array->device[new_array->index] = disk;
-  array->start_sector[new_array->index] = start_sector;
+  array->members[new_array->index].device = disk;
+  array->members[new_array->index].start_sector = start_sector;
   array->nr_devs++;
 
   return 0;
@@ -639,14 +666,15 @@ free_array (void)
   while (array)
     {
       struct grub_raid_array *p;
-      int i;
+      unsigned int i;
 
       p = array;
       array = array->next;
 
-      for (i = 0; i < GRUB_RAID_MAX_DEVICES; i++)
-        if (p->device[i])
-          grub_disk_close (p->device[i]);
+      for (i = 0; i < p->allocated_devs; i++)
+        if (p->members[i].device)
+          grub_disk_close (p->members[i].device);
+      grub_free (p->members);
 
       grub_free (p->uuid);
       grub_free (p->name);
index 31cef88b13f6f2a15c6b8a9a11d2dea36dab2233..2cda67533f526ab11c95549201087fc95b90d234 100644 (file)
@@ -45,7 +45,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
       if (i == disknr)
         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)
         {
index 550968cebd4e0458a680938a1bac6137ba65b6d8..01daa2c79dae147a7d8999386188f53ef3706a70 100644 (file)
@@ -118,8 +118,9 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
         bad1 = i;
       else
         {
-          if ((array->device[pos]) &&
-              (! grub_disk_read (array->device[pos], sector, 0, size, buf)))
+          if ((array->members[pos].device) &&
+              (! grub_disk_read (array->members[pos].device, sector,
+                                0, size, buf)))
             {
               grub_raid_block_xor (pbuf, 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)
     {
       /* One bad device */
-      if ((array->device[p]) &&
-          (! grub_disk_read (array->device[p], sector, 0, size, buf)))
+      if ((array->members[p].device) &&
+          (! grub_disk_read (array->members[p].device, sector, 0, size, buf)))
         {
           grub_raid_block_xor (buf, pbuf, size);
           goto quit;
         }
 
-      if (! array->device[q])
+      if (! array->members[q].device)
         {
           grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
           goto quit;
         }
 
       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;
 
       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 */
       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");
           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;
 
       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;
 
       grub_raid_block_xor (qbuf, buf, size);
index b7e18b56758087c9b3d99cb8aaed49f91324aeec..d5853639d53edda619f8829fe5ac8b0afa727335 100644 (file)
@@ -22,8 +22,6 @@
 
 #include <grub/types.h>
 
-#define GRUB_RAID_MAX_DEVICES  32
-
 #define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC       0
 #define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC      1
 #define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC                2
 #define GRUB_RAID_LAYOUT_RIGHT_MASK            1
 #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
 {
   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_uint64_t disk_size; /* Size of an individual disk, in 512 byte
                              sectors. */
-  int index;               /* Index of current device.  */
+  unsigned 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. */
-  grub_disk_addr_t start_sector[GRUB_RAID_MAX_DEVICES];
-                          /* Start of each device, in 512 byte sectors. */
+  unsigned int allocated_devs;
+  struct grub_raid_member *members;
   struct grub_raid_array *next;
 
 #ifdef GRUB_UTIL