Hi,

This patch fixes a few bug in lvm.

There can be multiple copies of meta data, it's not an error, ignore
the extra copy instead of quit.

In case of LVM on RAID, the raid device and first disk would have the
same lvm header ! The raid device would be found first, so we don't
replace pv->disk if it has been set.

grub-probe doesn't work in LVM on RAID, as it only assume one layer of
abstraction, the fix is not to rely on os, but uses grub to get the
correct abstraction information.

Fix grub-fstest to support lvm.

-- 
Bean
diff --git a/disk/lvm.c b/disk/lvm.c
index 6707a40..126b494 100644
--- a/disk/lvm.c
+++ b/disk/lvm.c
@@ -271,15 +271,9 @@ grub_lvm_scan_device (const char *name)
   dlocn++;
   mda_offset = grub_le_to_cpu64 (dlocn->offset);
   mda_size = grub_le_to_cpu64 (dlocn->size);
-  dlocn++;
 
-  if (dlocn->offset)
-    {
-      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
-		  "We don't support multiple LVM metadata areas");
-
-      goto fail;
-    }
+  /* It's possible to have multiple copies of metadata areas, we just use the
+     first one.  */
 
   /* Allocate buffer space for the circular worst-case scenario. */
   metadatabuf = grub_malloc (2 * mda_size);
@@ -564,7 +558,10 @@ grub_lvm_scan_device (const char *name)
       {
 	if (! grub_memcmp (pv->id, pv_id, GRUB_LVM_ID_STRLEN))
 	  {
-	    pv->disk = grub_disk_open (name);
+	    /* This could happen to LVM on RAID, pv->disk points to the
+	       raid device, we shouldn't change it.  */
+	    if (! pv->disk)
+	      pv->disk = grub_disk_open (name);
 	    break;
 	  }
       }
diff --git a/util/grub-fstest.c b/util/grub-fstest.c
index 4722269..c39529a 100644
--- a/util/grub-fstest.c
+++ b/util/grub-fstest.c
@@ -294,6 +294,8 @@ fstest (char **images, int num_disks, int cmd, int n, char **args)
     }
 
   grub_raid_rescan ();
+  grub_lvm_fini ();
+  grub_lvm_init ();
   switch (cmd)
     {
     case CMD_LS:
diff --git a/util/grub-probe.c b/util/grub-probe.c
index 97d3860..a187859 100644
--- a/util/grub-probe.c
+++ b/util/grub-probe.c
@@ -106,7 +106,6 @@ probe (const char *path, char *device_name)
   char *drive_name = NULL;
   char *grub_path = NULL;
   char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
-  int abstraction_type;
   grub_device_t dev = NULL;
   grub_fs_t fs;
 
@@ -114,10 +113,10 @@ probe (const char *path, char *device_name)
     {
 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
       if (! grub_util_check_char_device (device_name))
-        grub_util_error ("%s is not a character device.\n", device_name);
+	grub_util_error ("%s is not a character device.\n", device_name);
 #else
       if (! grub_util_check_block_device (device_name))
-        grub_util_error ("%s is not a block device.\n", device_name);
+	grub_util_error ("%s is not a block device.\n", device_name);
 #endif
     }
   else
@@ -132,28 +131,6 @@ probe (const char *path, char *device_name)
       goto end;
     }
 
-  abstraction_type = grub_util_get_dev_abstraction (device_name);
-  /* No need to check for errors; lack of abstraction is permissible.  */
-
-  if (print == PRINT_ABSTRACTION)
-    {
-      char *abstraction_name;
-      switch (abstraction_type)
-	{
-	case GRUB_DEV_ABSTRACTION_LVM:
-	  abstraction_name = "lvm";
-	  break;
-	case GRUB_DEV_ABSTRACTION_RAID:
-	  abstraction_name = "raid mdraid";
-	  break;
-	default:
-	  grub_util_info ("did not find LVM/RAID in %s, assuming raw device", device_name);
-	  goto end;
-	}
-      printf ("%s\n", abstraction_name);
-      goto end;
-    }
-
   drive_name = grub_util_get_grub_dev (device_name);
   if (! drive_name)
     grub_util_error ("Cannot find a GRUB drive for %s.  Check your device.map.\n", device_name);
@@ -169,6 +146,38 @@ probe (const char *path, char *device_name)
   if (! dev)
     grub_util_error ("%s", grub_errmsg);
 
+  if (print == PRINT_ABSTRACTION)
+    {
+      char buf[30];
+      grub_disk_memberlist_t list = NULL, tmp;
+      int is_lvm = 0;
+      int is_raid = 0;
+
+      is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID);
+      is_raid |= (dev->disk->dev->id == GRUB_DISK_DEVICE_RAID_ID);
+
+      if ((is_lvm) && (dev->disk->dev->memberlist))
+	list = dev->disk->dev->memberlist (dev->disk);
+      while (list)
+	{
+	  is_raid |= (list->disk->dev->id == GRUB_DISK_DEVICE_RAID_ID);
+	  tmp = list->next;
+	  free (list);
+	  list = tmp;
+	}
+
+      buf[0] = buf[1] = 0;
+      if (is_raid)
+	strcat (buf, " raid mdraid");
+
+      if (is_lvm)
+	strcat (buf, " lvm");
+
+      printf ("%s\n", &buf[1]);	
+      
+      goto end;
+    }
+
   if (print == PRINT_PARTMAP)
     {
       grub_disk_memberlist_t list = NULL, tmp;
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to