]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2010-01-26 Colin Watson <cjwatson@ubuntu.com>
authorColin Watson <cjwatson@ubuntu.com>
Tue, 26 Jan 2010 14:26:16 +0000 (14:26 +0000)
committerColin Watson <cjwatson@ubuntu.com>
Tue, 26 Jan 2010 14:26:16 +0000 (14:26 +0000)
* conf/common.rmk (grub_mkdevicemap_SOURCES): Add kern/env.c,
kern/err.c, kern/list.c, and kern/misc.c.
* util/deviceiter.c [__linux__]: Define MINOR.
(grub_util_iterate_devices): Add support for DM-RAID disk devices.
* util/mkdevicemap.c (grub_putchar): New function.
(grub_getkey): New function.
(grub_refresh): New function.
(main): Set debug=all if -v -v is used.

ChangeLog.dmraid-probe
conf/common.rmk
util/deviceiter.c
util/grub-mkdevicemap.c

index 8b8f255335affee45f5c8b09b8740bf584e8efa3..505cf7ba4b08404699035e0840305dcff8cc3b36 100644 (file)
@@ -1,6 +1,7 @@
-2010-01-25  Colin Watson  <cjwatson@ubuntu.com>
+2010-01-26  Colin Watson  <cjwatson@ubuntu.com>
 
        * configure.ac: Check for Linux device-mapper support.
+
        * util/hostdisk.c (device_is_mapped): New function.
        (find_partition_start): New function, partly broken out from
        linux_find_partition and grub_util_biosdisk_get_grub_dev but with
        (grub_util_biosdisk_get_grub_dev): Pass stat result to
        find_system_device and convert_system_partition_to_system_disk.  Use
        find_partition_start.
+
+       * conf/common.rmk (grub_mkdevicemap_SOURCES): Add kern/env.c,
+       kern/err.c, kern/list.c, and kern/misc.c.
+       * util/deviceiter.c [__linux__]: Define MINOR.
+       (grub_util_iterate_devices): Add support for DM-RAID disk devices.
+       * util/mkdevicemap.c (grub_putchar): New function.
+       (grub_getkey): New function.
+       (grub_refresh): New function.
+       (main): Set debug=all if -v -v is used.
index 2ea8ebd5a09a3b6768588701852befa68604c586..94a96a313dfdf92c390d38aa10544d99126f94c3 100644 (file)
@@ -3,7 +3,8 @@
 sbin_UTILITIES += grub-mkdevicemap
 grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \
        util/deviceiter.c \
-       util/misc.c
+       util/misc.c \
+       kern/env.c kern/err.c kern/list.c kern/misc.c
 
 ifeq ($(target_cpu)-$(platform), sparc64-ieee1275)
 grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c
index b0a9e1388721f832295124f919d413bd9949fa70..03813bc7da10d9b61438005fc0de4f8291dda91d 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <grub/util/misc.h>
 #include <grub/util/deviceiter.h>
+#include <grub/list.h>
+#include <grub/misc.h>
 
 #ifdef __linux__
 # if !defined(__GLIBC__) || \
@@ -62,12 +64,23 @@ struct hd_geometry
                  | ((unsigned int) (__dev >> 32) & ~0xfff); \
   })
 # endif /* ! MAJOR */
+# ifndef MINOR
+#  define MINOR(dev)   \
+  ({ \
+     unsigned long long __dev = (dev); \
+     (unsigned) (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); \
+  })
+# endif /* ! MINOR */
 # ifndef CDROM_GET_CAPABILITY
 #  define CDROM_GET_CAPABILITY 0x5331  /* get capabilities */
 # endif /* ! CDROM_GET_CAPABILITY */
 # ifndef BLKGETSIZE
 #  define BLKGETSIZE   _IO(0x12,96)    /* return device size */
 # endif /* ! BLKGETSIZE */
+
+#ifdef HAVE_DEVICE_MAPPER
+# include <libdevmapper.h>
+#endif
 #endif /* __linux__ */
 
 /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
@@ -411,6 +424,16 @@ check_device (const char *device)
   return 1;
 }
 
+#ifdef __linux__
+# ifdef HAVE_DEVICE_MAPPER
+struct dmraid_seen
+{
+  struct dmraid_seen *next;
+  const char *name;
+};
+# endif /* HAVE_DEVICE_MAPPER */
+#endif /* __linux__ */
+
 void
 grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
                           int floppy_disks)
@@ -643,6 +666,123 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            return;
        }
     }
+
+# ifdef HAVE_DEVICE_MAPPER
+#  define dmraid_check(cond, ...) \
+  if (! (cond)) \
+    { \
+      grub_dprintf ("deviceiter", __VA_ARGS__); \
+      goto dmraid_end; \
+    }
+
+  /* DM-RAID.  */
+  {
+    struct dm_tree *tree = NULL;
+    struct dm_task *task = NULL;
+    struct dm_names *names = NULL;
+    unsigned int next = 0;
+    void *top_handle, *second_handle;
+    struct dm_tree_node *root, *top, *second;
+    struct dmraid_seen *seen = NULL;
+
+    /* Build DM tree for all devices.  */
+    tree = dm_tree_create ();
+    dmraid_check (tree, "dm_tree_create failed\n");
+    task = dm_task_create (DM_DEVICE_LIST);
+    dmraid_check (task, "dm_task_create failed\n");
+    dmraid_check (dm_task_run (task), "dm_task_run failed\n");
+    names = dm_task_get_names (task);
+    dmraid_check (names, "dm_task_get_names failed\n");
+    dmraid_check (names->dev, "No DM devices found\n");
+    do
+      {
+       names = (void *) names + next;
+       dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev),
+                                      MINOR (names->dev)),
+                        "dm_tree_add_dev (%s) failed\n", names->name);
+       next = names->next;
+      }
+    while (next);
+
+    /* Walk the second-level children of the inverted tree; that is, devices
+       which are directly composed of non-DM devices such as hard disks.
+       This class includes all DM-RAID disks and excludes all DM-RAID
+       partitions.  */
+    root = dm_tree_find_node (tree, 0, 0);
+    top_handle = NULL;
+    top = dm_tree_next_child (&top_handle, root, 1);
+    while (top)
+      {
+       second_handle = NULL;
+       second = dm_tree_next_child (&second_handle, top, 1);
+       while (second)
+         {
+           const char *node_name, *node_uuid;
+           char *name;
+           struct dmraid_seen *seen_elt;
+
+           node_name = dm_tree_node_get_name (second);
+           dmraid_check (node_name, "dm_tree_node_get_name failed\n");
+           node_uuid = dm_tree_node_get_uuid (second);
+           dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n");
+           if (strncmp (node_uuid, "DMRAID-", 7) != 0)
+             {
+               grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name);
+               goto dmraid_next_child;
+             }
+
+           /* Have we already seen this node?  There are typically very few
+              DM-RAID disks, so a list should be fast enough.  */
+           if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), node_name))
+             {
+               grub_dprintf ("deviceiter", "Already seen DM device %s\n",
+                             node_name);
+               goto dmraid_next_child;
+             }
+
+           name = xasprintf ("/dev/mapper/%s", node_name);
+           if (check_device (name))
+             {
+               if (hook (name, 0))
+                 {
+                   free (name);
+                   while (seen)
+                     {
+                       struct dmraid_seen *seen_elt =
+                         grub_list_pop (GRUB_AS_LIST_P (&seen));
+                       free (seen_elt);
+                     }
+                   if (task)
+                     dm_task_destroy (task);
+                   if (tree)
+                     dm_tree_free (tree);
+                   return;
+                 }
+             }
+           free (name);
+
+           seen_elt = xmalloc (sizeof *seen_elt);
+           seen_elt->name = node_name;
+           grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt));
+
+dmraid_next_child:
+           second = dm_tree_next_child (&second_handle, top, 1);
+         }
+       top = dm_tree_next_child (&top_handle, root, 1);
+      }
+
+dmraid_end:
+    while (seen)
+      {
+       struct dmraid_seen *seen_elt = grub_list_pop (GRUB_AS_LIST_P (&seen));
+       free (seen_elt);
+      }
+    if (task)
+      dm_task_destroy (task);
+    if (tree)
+      dm_tree_free (tree);
+  }
+# endif /* HAVE_DEVICE_MAPPER */
 #endif /* __linux__ */
 }
 
index c68482af1d8ac4ef855705637084b3bbd1487103..db37f99e61de807835062b0afaaeef159483bc78 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <grub/util/misc.h>
 #include <grub/util/deviceiter.h>
+#include <grub/env.h>
 #include <grub/i18n.h>
 
 #define _GNU_SOURCE    1
 
 #include "progname.h"
 
+void
+grub_putchar (int c)
+{
+  putchar (c);
+}
+
+int
+grub_getkey (void)
+{
+  return -1;
+}
+
+void
+grub_refresh (void)
+{
+  fflush (stdout);
+}
+
 static void
 make_device_map (const char *device_map, int floppy_disks)
 {
@@ -158,6 +177,9 @@ main (int argc, char *argv[])
          }
     }
 
+  if (verbosity > 1)
+    grub_env_set ("debug", "all");
+
   make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
 
   free (dev_map);