New patch to fix partmap detection in LVM/RAID.  Changes in comparison to
previous patch:
  - Add LVM detection.
  - Rename the structures/functions to make them more descriptive.
  - Fix a minor memleak.

This is only known to work on proof-of-concept test systems.  *Please* anyone
who was affected on real, production systems, test it (against latest CVS) and
send feedback.  The problem was that:

  grub-probe -t partmap /some_path

is unable to detect the partition map when /some_path was part of some LVM or
RAID abstraction.

Note for those of you using Debian packages: for testing this on CVS, you don't
need to install it, just build and run ./grub-probe in-tree.

Thanks

-- 
Robert Millan

<GPLv2> I know my rights; I want my phone call!
<DRM> What use is a phone call… if you are unable to speak?
(as seen on /.)
	* disk/lvm.c [GRUB_UTIL] (grub_lvm_memberlist): New function.  Construct
	and return a grub_diskmemberlist_t composed of LVM physical volumes.
	[GRUB_UTIL] (grub_lvm_dev): Add `memberlist' member.

	* disk/raid.c [GRUB_UTIL] (grub_raid_memberlist): New function.  Construct
	and return a grub_diskmemberlist_t composed of physical array members.
	[GRUB_UTIL] (grub_raid_dev): Add `memberlist' member.

	* include/grub/disk.h [GRUB_UTIL] (grub_disk_memberlist): New struct
	prototype.
	[GRUB_UTIL] (struct grub_disk_dev): Add `memberlist' function pointer.
	[GRUB_UTIL] (struct grub_disk_memberlist): New struct declaration.
	[GRUB_UTIL] (grub_disk_memberlist_t): New typedef.

	* util/grub-probe.c (probe): Move partmap probing code from here ...
	(probe_partmap): ... to here.
	(probe): Use probe_partmap() once for the disk we're probing, and
	additionally, when such disk contains a memberlist() struct member,
	once for each disk that is contained in the structure returned by
	memberlist().

diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/disk/lvm.c ./disk/lvm.c
--- ../grub2/disk/lvm.c	2007-07-22 01:32:20.000000000 +0200
+++ ./disk/lvm.c	2008-02-08 15:37:27.000000000 +0100
@@ -52,6 +52,26 @@ grub_lvm_iterate (int (*hook) (const cha
   return 0;
 }
 
+#ifdef GRUB_UTIL
+static grub_disk_memberlist_t
+grub_lvm_memberlist (grub_disk_t disk)
+{
+  struct grub_lvm_lv *lv = disk->data;
+  grub_disk_memberlist_t list = NULL, tmp;
+  struct grub_lvm_pv *pv;
+
+  for (pv = lv->vg->pvs; pv; pv = pv->next)
+    {
+      tmp = grub_malloc (sizeof (*tmp));
+      tmp->disk = pv->disk;
+      tmp->next = list;
+      list = tmp;
+    }
+
+  return list;
+}
+#endif
+
 static grub_err_t
 grub_lvm_open (const char *name, grub_disk_t disk)
 {
@@ -479,6 +499,9 @@ static struct grub_disk_dev grub_lvm_dev
     .close = grub_lvm_close,
     .read = grub_lvm_read,
     .write = grub_lvm_write,
+#ifdef GRUB_UTIL
+    .memberlist = grub_lvm_memberlist,
+#endif
     .next = 0
   };
 
diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/disk/raid.c ./disk/raid.c
--- ../grub2/disk/raid.c	2008-02-08 13:35:05.000000000 +0100
+++ ./disk/raid.c	2008-02-08 15:37:05.000000000 +0100
@@ -67,6 +67,26 @@ grub_raid_iterate (int (*hook) (const ch
   return 0;
 }
 
+#ifdef GRUB_UTIL
+static grub_disk_memberlist_t
+grub_raid_memberlist (grub_disk_t disk)
+{
+  struct grub_raid_array *array = disk->data;
+  grub_disk_memberlist_t list = NULL, tmp;
+  int i;
+  
+  for (i = 0; i < array->total_devs; i++)
+    {
+      tmp = grub_malloc (sizeof (*tmp));
+      tmp->disk = array->device[i];
+      tmp->next = list;
+      list = tmp;
+    }
+  
+  return list;
+}
+#endif
+
 static grub_err_t
 grub_raid_open (const char *name, grub_disk_t disk)
 {
@@ -531,6 +551,9 @@ static struct grub_disk_dev grub_raid_de
     .close = grub_raid_close,
     .read = grub_raid_read,
     .write = grub_raid_write,
+#ifdef GRUB_UTIL
+    .memberlist = grub_raid_memberlist,
+#endif
     .next = 0
   };
 
diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/include/grub/disk.h ./include/grub/disk.h
--- ../grub2/include/grub/disk.h	2008-01-21 00:20:36.000000000 +0100
+++ ./include/grub/disk.h	2008-02-08 15:37:05.000000000 +0100
@@ -40,6 +40,9 @@ enum grub_disk_dev_id
   };
 
 struct grub_disk;
+#ifdef GRUB_UTIL
+struct grub_disk_memberlist;
+#endif
 
 /* Disk device.  */
 struct grub_disk_dev
@@ -67,6 +70,10 @@ struct grub_disk_dev
   grub_err_t (*write) (struct grub_disk *disk, grub_disk_addr_t sector,
 		       grub_size_t size, const char *buf);
 
+#ifdef GRUB_UTIL
+  struct grub_disk_memberlist *(*memberlist) (struct grub_disk *disk);
+#endif
+
   /* The next disk device.  */
   struct grub_disk_dev *next;
 };
@@ -105,6 +112,15 @@ struct grub_disk
 };
 typedef struct grub_disk *grub_disk_t;
 
+#ifdef GRUB_UTIL
+struct grub_disk_memberlist
+{
+  grub_disk_t disk;
+  struct grub_disk_memberlist *next;
+};
+typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
+#endif
+
 /* The sector size.  */
 #define GRUB_DISK_SECTOR_SIZE	0x200
 #define GRUB_DISK_SECTOR_BITS	9
diff -x configure -x config.h.in -x CVS -x '*~' -x '*.mk' -urp ../grub2/util/grub-probe.c ./util/grub-probe.c
--- ../grub2/util/grub-probe.c	2008-02-06 22:07:49.000000000 +0100
+++ ./util/grub-probe.c	2008-02-08 15:37:05.000000000 +0100
@@ -75,6 +75,31 @@ grub_refresh (void)
 }
 
 static void
+probe_partmap (grub_disk_t disk)
+{
+  char *name;
+  char *underscore;
+  
+  if (disk->partition == NULL)
+    {
+      grub_util_info ("No partition map found for %s", disk->name);
+      return;
+    }
+  
+  name = strdup (disk->partition->partmap->name);
+  if (! name)
+    grub_util_error ("Not enough memory");
+  
+  underscore = strchr (name, '_');
+  if (! underscore)
+    grub_util_error ("Invalid partition map %s", name);
+  
+  *underscore = '\0';
+  printf ("%s\n", name);
+  free (name);
+}
+
+static void
 probe (const char *path)
 {
   char *device_name;
@@ -133,23 +158,19 @@ probe (const char *path)
 
   if (print == PRINT_PARTMAP)
     {
-      char *name;
-      char *underscore;
-      
-      if (dev->disk->partition == NULL)
-        grub_util_error ("Cannot detect partition map for %s", drive_name);
-
-      name = strdup (dev->disk->partition->partmap->name);
-      if (! name)
-	grub_util_error ("not enough memory");
-
-      underscore = strchr (name, '_');
-      if (! underscore)
-	grub_util_error ("Invalid partition map %s", name);
-
-      *underscore = '\0';
-      printf ("%s\n", name);
-      free (name);
+      grub_disk_memberlist_t list = NULL, tmp;
+      /* Check if dev->disk itself is contained in a partmap.  */
+      probe_partmap (dev->disk);
+      /* In case of LVM/RAID, check the member devices as well.  */
+      if (dev->disk->dev->memberlist)
+	list = dev->disk->dev->memberlist (dev->disk);
+      while (list)
+	{
+	  probe_partmap (list->disk);
+	  tmp = list->next;
+	  free (list);
+	  list = tmp;
+	}
       goto end;
     }
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to