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.

=== 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)

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to