]> git.proxmox.com Git - grub2.git/commitdiff
* grub-core/disk/diskfilter.c: Handle non-md UUIDs.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 20 Sep 2013 18:37:03 +0000 (20:37 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 20 Sep 2013 18:37:03 +0000 (20:37 +0200)
* grub-core/disk/lvm.c: Add LVM UUIDs.
* util/getroot.c: Use LVM UUIDs whenever possible.

ChangeLog
grub-core/disk/diskfilter.c
grub-core/disk/lvm.c
include/grub/diskfilter.h
util/getroot.c

index 708c57e04e475913c705879530a85070cd66cb56..cffa871347c96bf399a1e52faae467f330af5984 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-20  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * grub-core/disk/diskfilter.c: Handle non-md UUIDs.
+       * grub-core/disk/lvm.c: Add LVM UUIDs.
+       * util/getroot.c: Use LVM UUIDs whenever possible.
+
 2013-09-19  Andrey Borzenkov <arvidjaar@gmail.com>
 
        * docs/grub.texi (Networking commands): Add documentation for
index 99bf9e5c34326041362453d3e43e6cec2724b6c3..eef143a1d5eed485946679381fb3aba327c39b3d 100644 (file)
@@ -117,6 +117,7 @@ is_valid_diskfilter_name (const char *name)
 {
   return (grub_memcmp (name, "md", sizeof ("md") - 1) == 0
          || grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0
+         || grub_memcmp (name, "lvmid/", sizeof ("lvmid/") - 1) == 0
          || grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) == 0);
 }
 
@@ -387,16 +388,12 @@ grub_diskfilter_getname (struct grub_disk *disk)
 }
 #endif
 
-static inline int
-ascii2hex (char c)
+static inline char
+hex2ascii (int c)
 {
-  if (c >= '0' && c <= '9')
-    return c - '0';
-  if (c >= 'a' && c <= 'f')
-    return c - 'a' + 10;
-  if (c >= 'A' && c <= 'F')
-    return c - 'A' + 10;
-  return 0;
+  if (c >= 10)
+    return 'a' + c - 10;
+  return c + '0';
 }
 
 static struct grub_diskfilter_lv *
@@ -405,30 +402,12 @@ find_lv (const char *name)
   struct grub_diskfilter_vg *vg;
   struct grub_diskfilter_lv *lv = NULL;
 
-  if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
-    {
-      const char *uuidstr = name + sizeof ("mduuid/") - 1;
-      grub_size_t uuid_len = grub_strlen (uuidstr) / 2;
-      grub_uint8_t uuidbin[uuid_len];
-      unsigned i;
-      for (i = 0; i < uuid_len; i++)
-       uuidbin[i] = ascii2hex (uuidstr[2 * i + 1])
-         | (ascii2hex (uuidstr[2 * i]) << 4);
-
-      for (vg = array_list; vg; vg = vg->next)      
-       {
-         if (uuid_len == vg->uuid_len
-             && grub_memcmp (uuidbin, vg->uuid, uuid_len) == 0)
-           if (is_lv_readable (vg->lvs, 0))
-             return vg->lvs;
-       }
-    }
-
   for (vg = array_list; vg; vg = vg->next)
     {
       if (vg->lvs)
        for (lv = vg->lvs; lv; lv = lv->next)
-         if (lv->fullname && grub_strcmp (lv->fullname, name) == 0
+         if (((lv->fullname && grub_strcmp (lv->fullname, name) == 0)
+              || (lv->idname && grub_strcmp (lv->idname, name) == 0))
              && is_lv_readable (lv, 0))
            return lv;
     }
@@ -440,9 +419,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk)
 {
   struct grub_diskfilter_lv *lv;
 
-  if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0
-      && grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) != 0
-      && grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) != 0)
+  if (!is_valid_diskfilter_name (name))
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown DISKFILTER device %s",
                        name);
 
@@ -929,6 +906,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
 {
   struct grub_diskfilter_vg *array;
   int i;
+  grub_size_t j;
   grub_uint64_t totsize;
   struct grub_diskfilter_pv *pv;
   grub_err_t err;
@@ -995,6 +973,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
 
       array->name = new_name;
     }
+
   array->extent_size = 1;
   array->lvs = grub_zalloc (sizeof (*array->lvs));
   if (!array->lvs)
@@ -1004,6 +983,20 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb,
   array->lvs->name = array->name;
   array->lvs->fullname = array->name;
 
+  array->lvs->idname = grub_malloc (sizeof ("mduuid/") + 2 * uuidlen);
+  if (!array->lvs->idname)
+    goto fail;
+
+  grub_memcpy (array->lvs->idname, "mduuid/", sizeof ("mduuid/") - 1);
+  for (j = 0; j < uuidlen; j++)
+    {
+      array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * j]
+       = hex2ascii (((unsigned char) uuid[j] >> 4));
+      array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * j + 1]
+       = hex2ascii (((unsigned char) uuid[j] & 0xf));
+    }
+  array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * uuidlen] = '\0';
+
   array->lvs->size = totsize;
 
   array->lvs->segments = grub_zalloc (sizeof (*array->lvs->segments));
index 508e94af0c0b50f2892dc2745b198a4c14efd114..4025532c4c49c70dbbc0548c16419002aa15473c 100644 (file)
@@ -387,6 +387,29 @@ grub_lvm_detect (grub_disk_t disk,
                      *optr++ = '-';
                  }
                *optr++ = 0;
+               lv->idname = grub_malloc (sizeof ("lvmid/")
+                                         + 2 * GRUB_LVM_ID_STRLEN + 1);
+               if (!lv->idname)
+                 goto lvs_fail;
+               grub_memcpy (lv->idname, "lvmid/",
+                            sizeof ("lvmid/") - 1);
+               grub_memcpy (lv->idname + sizeof ("lvmid/") - 1,
+                            vg_id, GRUB_LVM_ID_STRLEN);
+               lv->idname[sizeof ("lvmid/") - 1 + GRUB_LVM_ID_STRLEN] = '/';
+
+               p = grub_strstr (q, "id = \"");
+               if (p == NULL)
+                 {
+#ifdef GRUB_UTIL
+                   grub_util_info ("couldn't find ID\n");
+#endif
+                   goto lvs_fail;
+                 }
+               p += sizeof ("id = \"") - 1;
+               grub_memcpy (lv->idname + sizeof ("lvmid/") - 1
+                            + GRUB_LVM_ID_STRLEN + 1,
+                            p, GRUB_LVM_ID_STRLEN);
+               lv->idname[sizeof ("lvmid/") - 1 + 2 * GRUB_LVM_ID_STRLEN + 1] = '\0';
              }
 
              lv->size = 0;
index b25807eeef1ee775163b07494eec35950031377b..3ed806326921a170a98ce0e27b7d8abba2df758f 100644 (file)
@@ -80,6 +80,7 @@ struct grub_diskfilter_pv {
 struct grub_diskfilter_lv {
   /* Name used for disk.  */
   char *fullname;
+  char *idname;
   /* Optional.  */
   char *name;
   int number;
index 88bbf6afc8c868fe283cc6edc8c754f1e0f70050..69e04dc907d5b739c37397206981729f2bf7c702 100644 (file)
@@ -1333,26 +1333,55 @@ pull_lvm_by_command (const char *os_dev)
   FILE *mdadm;
   char *buf = NULL;
   size_t len = 0;
-  char *vgname;
+  char *vgname = NULL;
   const char *iptr;
   char *optr;
+  char *vgid = NULL;
+  grub_size_t vgidlen = 0;
 
-  if (strncmp (os_dev, "/dev/mapper/", sizeof ("/dev/mapper/") - 1)
-      != 0)
-    return;
+#ifdef HAVE_DEVICE_MAPPER
+  char *uuid;
 
-  vgname = xmalloc (strlen (os_dev + sizeof ("/dev/mapper/") - 1) + 1);
-  for (iptr = os_dev + sizeof ("/dev/mapper/") - 1, optr = vgname; *iptr; )
-    if (*iptr != '-')
-      *optr++ = *iptr++;
-    else if (iptr[0] == '-' && iptr[1] == '-')
-      {
-       iptr += 2;
-       *optr++ = '-';
-      }
-    else
-      break;
-  *optr = '\0';
+  uuid = get_dm_uuid (os_dev);
+  if (uuid)
+    {
+      int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32};
+      unsigned i;
+      vgid = xmalloc (grub_strlen (uuid));
+      optr = vgid;
+      for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++)
+         {
+           memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i],
+                   dashes[i+1] - dashes[i]);
+           optr += dashes[i+1] - dashes[i];
+           *optr++ = '-';
+         }
+      optr--;
+      *optr = '\0';
+      vgidlen = optr - vgid;
+    }
+#endif
+
+  if (!vgid)
+    {
+      if (strncmp (os_dev, LVM_DEV_MAPPER_STRING,
+                  sizeof (LVM_DEV_MAPPER_STRING) - 1)
+         != 0)
+       return;
+
+      vgname = xmalloc (strlen (os_dev + sizeof (LVM_DEV_MAPPER_STRING) - 1) + 1);
+      for (iptr = os_dev + sizeof (LVM_DEV_MAPPER_STRING) - 1, optr = vgname; *iptr; )
+       if (*iptr != '-')
+         *optr++ = *iptr++;
+       else if (iptr[0] == '-' && iptr[1] == '-')
+         {
+           iptr += 2;
+           *optr++ = '-';
+         }
+       else
+         break;
+      *optr = '\0';
+    }
 
   /* execvp has inconvenient types, hence the casts.  None of these
      strings will actually be modified.  */
@@ -1361,7 +1390,10 @@ pull_lvm_by_command (const char *os_dev)
      alignment. We have a single field, so separator itself is not output */
   argv[0] = (char *) "vgs";
   argv[1] = (char *) "--options";
-  argv[2] = (char *) "pv_name";
+  if (vgid)
+    argv[2] = (char *) "vg_uuid,pv_name";
+  else
+    argv[2] = (char *) "pv_name";
   argv[3] = (char *) "--noheadings";
   argv[4] = (char *) "--separator";
   argv[5] = (char *) ":";
@@ -1388,6 +1420,12 @@ pull_lvm_by_command (const char *os_dev)
       char *ptr;
       /* LVM adds two spaces as standard prefix */
       for (ptr = buf; ptr < buf + 2 && *ptr == ' '; ptr++);
+
+      if (vgid && (grub_strncmp (vgid, ptr, vgidlen) != 0
+                  || ptr[vgidlen] != ':'))
+       continue;
+      if (vgid)
+       ptr += vgidlen + 1;
       if (*ptr == '\0')
        continue;
       *(ptr + strlen (ptr) - 1) = '\0';
@@ -2534,7 +2572,32 @@ grub_util_get_grub_dev (const char *os_dev)
 
   switch (grub_util_get_dev_abstraction (os_dev))
     {
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#ifdef HAVE_DEVICE_MAPPER
+    case GRUB_DEV_ABSTRACTION_LVM:
+      {
+       char *uuid, *optr;
+       unsigned i;
+       int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32, 38, 42, 46, 50, 54, 58};
+       uuid = get_dm_uuid (os_dev);
+       if (!uuid)
+         break;
+       grub_dev = xmalloc (grub_strlen (uuid) + 40);
+       optr = grub_stpcpy (grub_dev, "lvmid/");
+       for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++)
+         {
+           memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i],
+                   dashes[i+1] - dashes[i]);
+           optr += dashes[i+1] - dashes[i];
+           *optr++ = '-';
+         }
+       optr = stpcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i]);
+       *optr = '\0';
+       grub_dev[sizeof("lvmid/xxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxxxx") - 1]
+         = '/';
+       free (uuid);
+      }
+      break;
+#elif defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
     case GRUB_DEV_ABSTRACTION_LVM:
 
       {