]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Change grub-mkdevicemap to emit /dev/disk/by-id/ names where
authorColin Watson <cjwatson@ubuntu.com>
Mon, 28 Jun 2010 07:55:05 +0000 (08:55 +0100)
committerColin Watson <cjwatson@ubuntu.com>
Mon, 28 Jun 2010 07:55:05 +0000 (08:55 +0100)
possible on Linux.
* util/deviceiter.c (check_device): Rename to ...
(check_device_readable_unique): ... this.  Update all callers.
Maintain and check a list of which devices (by canonicalized name)
have already been seen.
(clear_seen_devices): New function.
(compare_file_names) [__linux__]: New function.
(grub_util_iterate_devices): Clear the list of seen devices on exit
and (just in case) on entry.
(grub_util_iterate_devices) [__linux__]: Iterate over non-partition
devices in /dev/disk/by-id/, in sorted order.  Remove DM-RAID
seen-devices list, superseded by general code in check_device.

ChangeLog
util/deviceiter.c

index 7f0cc8ba59013a8ce234975313fdd7c5c957571e..fe6461760f036e60d58c46887e275987ab7d35f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2010-06-28  Colin Watson  <cjwatson@ubuntu.com>
+
+       Change grub-mkdevicemap to emit /dev/disk/by-id/ names where
+       possible on Linux.
+
+       * util/deviceiter.c (check_device): Rename to ...
+       (check_device_readable_unique): ... this.  Update all callers.
+       Maintain and check a list of which devices (by canonicalized name)
+       have already been seen.
+       (clear_seen_devices): New function.
+       (compare_file_names) [__linux__]: New function.
+       (grub_util_iterate_devices): Clear the list of seen devices on exit
+       and (just in case) on entry.
+       (grub_util_iterate_devices) [__linux__]: Iterate over non-partition
+       devices in /dev/disk/by-id/, in sorted order.  Remove DM-RAID
+       seen-devices list, superseded by general code in check_device.
+
 2010-06-28  Colin Watson  <cjwatson@ubuntu.com>
 
        * commands/cat.c (options): New variable.
index c3bc508dd551812b80b7af199ead33b2a80e483f..e3a0ab76dd1f55894eb50df9ff582c8248585a11 100644 (file)
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <dirent.h>
 
 #include <grub/util/misc.h>
 #include <grub/util/deviceiter.h>
@@ -345,18 +346,37 @@ get_xvd_disk_name (char *name, int unit)
 }
 #endif
 
-/* Check if DEVICE can be read. If an error occurs, return zero,
-   otherwise return non-zero.  */
+static struct seen_device
+{
+  struct seen_device *next;
+  const char *name;
+} *seen;
+
+/* Check if DEVICE can be read.  Skip any DEVICE that we have already seen.
+   If an error occurs, return zero, otherwise return non-zero.  */
 static int
-check_device (const char *device)
+check_device_readable_unique (const char *device)
 {
+  char *real_device;
   char buf[512];
   FILE *fp;
+  struct seen_device *seen_elt;
 
   /* If DEVICE is empty, just return error.  */
   if (*device == 0)
     return 0;
 
+  /* Have we seen this device already?  */
+  real_device = canonicalize_file_name (device);
+  if (! real_device)
+    return 0;
+  if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), real_device))
+    {
+      grub_dprintf ("deviceiter", "Already seen %s (%s)\n",
+                   device, real_device);
+      goto fail;
+    }
+
   fp = fopen (device, "r");
   if (! fp)
     {
@@ -379,7 +399,7 @@ check_device (const char *device)
          break;
        }
       /* Error opening the device.  */
-      return 0;
+      goto fail;
     }
 
   /* Make sure CD-ROMs don't get assigned a BIOS disk number
@@ -387,7 +407,7 @@ check_device (const char *device)
 #ifdef __linux__
 # ifdef CDROM_GET_CAPABILITY
   if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
-    return 0;
+    goto fail;
 # else /* ! CDROM_GET_CAPABILITY */
   /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl.  */
   {
@@ -395,14 +415,14 @@ check_device (const char *device)
     struct stat st;
 
     if (fstat (fileno (fp), &st))
-      return 0;
+      goto fail;
 
     /* If it is a block device and isn't a floppy, check if HDIO_GETGEO
        succeeds.  */
     if (S_ISBLK (st.st_mode)
        && MAJOR (st.st_rdev) != FLOPPY_MAJOR
        && ioctl (fileno (fp), HDIO_GETGEO, &hdg))
-      return 0;
+      goto fail;
   }
 # endif /* ! CDROM_GET_CAPABILITY */
 #endif /* __linux__ */
@@ -410,7 +430,7 @@ check_device (const char *device)
 #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
 # ifdef CDIOCCLRDEBUG
   if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
-    return 0;
+    goto fail;
 # endif /* CDIOCCLRDEBUG */
 #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
 
@@ -418,21 +438,43 @@ check_device (const char *device)
   if (fread (buf, 1, 512, fp) != 512)
     {
       fclose (fp);
-      return 0;
+      goto fail;
     }
 
+  /* Remember that we've seen this device.  */
+  seen_elt = xmalloc (sizeof (*seen_elt));
+  seen_elt->name = real_device; /* steal memory */
+  grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt));
+
   fclose (fp);
   return 1;
+
+fail:
+  free (real_device);
+  return 0;
+}
+
+static void
+clear_seen_devices (void)
+{
+  while (seen)
+    {
+      struct seen_device *seen_elt = seen;
+      seen = seen->next;
+      free (seen_elt);
+    }
+  seen = NULL;
 }
 
 #ifdef __linux__
-# ifdef HAVE_DEVICE_MAPPER
-struct dmraid_seen
+/* Like strcmp, but doesn't require a cast for use as a qsort comparator.  */
+static int
+compare_file_names (const void *a, const void *b)
 {
-  struct dmraid_seen *next;
-  const char *name;
-};
-# endif /* HAVE_DEVICE_MAPPER */
+  const char *left = *(const char **) a;
+  const char *right = *(const char **) b;
+  return strcmp (left, right);
+}
 #endif /* __linux__ */
 
 void
@@ -441,6 +483,8 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
 {
   int i;
 
+  clear_seen_devices ();
+
   /* Floppies.  */
   for (i = 0; i < floppy_disks; i++)
     {
@@ -450,13 +494,63 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       get_floppy_disk_name (name, i);
       if (stat (name, &st) < 0)
        break;
-      /* In floppies, write the map, whether check_device succeeds
-        or not, because the user just may not insert floppies.  */
+      /* In floppies, write the map, whether check_device_readable_unique
+         succeeds or not, because the user just may not insert floppies.  */
       if (hook (name, 1))
-       return;
+       goto out;
     }
 
 #ifdef __linux__
+  {
+    DIR *dir = opendir ("/dev/disk/by-id");
+
+    if (dir)
+      {
+       struct dirent *entry;
+       char **names;
+       size_t names_len = 0, names_max = 1024, i;
+
+       names = xmalloc (names_max * sizeof (*names));
+
+       /* Dump all the directory entries into names, resizing if
+          necessary.  */
+       for (entry = readdir (dir); entry; entry = readdir (dir))
+         {
+           /* Skip partition entries.  */
+           if (strstr (entry->d_name, "-part"))
+             continue;
+           if (names_len >= names_max)
+             {
+               names_max *= 2;
+               names = xrealloc (names, names_max * sizeof (*names));
+             }
+           names[names_len++] = xasprintf (entry->d_name);
+         }
+
+       /* /dev/disk/by-id/ usually has a few alternative identifications of
+          devices (e.g. ATA vs. SATA).  check_device_readable_unique will
+          ensure that we only get one for any given disk, but sort the list
+          so that the choice of which one we get is stable.  */
+       qsort (names, names_len, sizeof (*names), &compare_file_names);
+
+       closedir (dir);
+
+       /* Now add all the devices in sorted order.  */
+       for (i = 0; i < names_len; ++i)
+         {
+           char *path = xasprintf ("/dev/disk/by-id/%s", names[i]);
+           if (check_device_readable_unique (path))
+             {
+               if (hook (path, 0))
+                 goto out;
+             }
+           free (path);
+           free (names[i]);
+         }
+       free (names);
+      }
+  }
+
   if (have_devfs ())
     {
       i = 0;
@@ -476,10 +570,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            {
              strcat (name, "/disc");
              if (hook (name, 0))
-               return;
+               goto out;
            }
        }
-      return;
+      goto out;
     }
 #endif /* __linux__ */
 
@@ -489,10 +583,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       char name[16];
 
       get_ide_disk_name (name, i);
-      if (check_device (name))
+      if (check_device_readable_unique (name))
        {
          if (hook (name, 0))
-           return;
+           goto out;
        }
     }
 
@@ -503,10 +597,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       char name[16];
 
       get_virtio_disk_name (name, i);
-      if (check_device (name))
+      if (check_device_readable_unique (name))
        {
          if (hook (name, 0))
-           return;
+           goto out;
        }
     }
 
@@ -516,10 +610,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       char name[20];
 
       get_ataraid_disk_name (name, i);
-      if (check_device (name))
+      if (check_device_readable_unique (name))
        {
          if (hook (name, 0))
-           return;
+           goto out;
         }
     }
 
@@ -529,10 +623,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       char name[16];
 
       get_xvd_disk_name (name, i);
-      if (check_device (name))
+      if (check_device_readable_unique (name))
        {
          if (hook (name, 0))
-           return;
+           goto out;
        }
     }
 #endif /* __linux__ */
@@ -543,10 +637,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       char name[16];
 
       get_scsi_disk_name (name, i);
-      if (check_device (name))
+      if (check_device_readable_unique (name))
        {
          if (hook (name, 0))
-           return;
+           goto out;
        }
     }
 
@@ -566,10 +660,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            char name[24];
 
            get_dac960_disk_name (name, controller, drive);
-           if (check_device (name))
+           if (check_device_readable_unique (name))
              {
                if (hook (name, 0))
-                 return;
+                 goto out;
              }
          }
       }
@@ -587,10 +681,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            char name[24];
 
            get_acceleraid_disk_name (name, controller, drive);
-           if (check_device (name))
+           if (check_device_readable_unique (name))
              {
                if (hook (name, 0))
-                 return;
+                 goto out;
              }
          }
       }
@@ -608,10 +702,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            char name[24];
 
            get_cciss_disk_name (name, controller, drive);
-           if (check_device (name))
+           if (check_device_readable_unique (name))
              {
                if (hook (name, 0))
-                 return;
+                 goto out;
              }
          }
       }
@@ -629,10 +723,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            char name[24];
 
            get_ida_disk_name (name, controller, drive);
-           if (check_device (name))
+           if (check_device_readable_unique (name))
              {
                if (hook (name, 0))
-                 return;
+                 goto out;
              }
          }
       }
@@ -647,10 +741,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
        char name[24];
 
        get_i2o_disk_name (name, unit);
-       if (check_device (name))
+       if (check_device_readable_unique (name))
          {
            if (hook (name, 0))
-             return;
+             goto out;
          }
       }
   }
@@ -661,10 +755,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       char name[16];
 
       get_mmc_disk_name (name, i);
-      if (check_device (name))
+      if (check_device_readable_unique (name))
        {
          if (hook (name, 0))
-           return;
+           goto out;
        }
     }
 
@@ -685,7 +779,6 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
       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 ();
@@ -721,7 +814,6 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
            {
              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");
@@ -733,40 +825,21 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
                  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 (check_device_readable_unique (name))
                {
                  if (hook (name, 0))
                    {
                      free (name);
-                     while (seen)
-                       {
-                         struct dmraid_seen *seen_elt = seen;
-                         seen = seen->next;
-                         free (seen_elt);
-                       }
                      if (task)
                        dm_task_destroy (task);
                      if (tree)
                        dm_tree_free (tree);
-                     return;
+                     goto out;
                    }
                }
              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);
            }
@@ -774,12 +847,6 @@ dmraid_next_child:
        }
 
 dmraid_end:
-      while (seen)
-       {
-         struct dmraid_seen *seen_elt = seen;
-         seen = seen->next;
-         free (seen_elt);
-       }
       if (task)
        dm_task_destroy (task);
       if (tree)
@@ -787,5 +854,8 @@ dmraid_end:
     }
 # endif /* HAVE_DEVICE_MAPPER */
 #endif /* __linux__ */
+
+out:
+  clear_seen_devices ();
 }