* grub-core/disk/lvm.c: Add LVM UUIDs.
* util/getroot.c: Use LVM UUIDs whenever possible.
+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
{
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);
}
}
#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 *
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;
}
{
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);
{
struct grub_diskfilter_vg *array;
int i;
+ grub_size_t j;
grub_uint64_t totsize;
struct grub_diskfilter_pv *pv;
grub_err_t err;
array->name = new_name;
}
+
array->extent_size = 1;
array->lvs = grub_zalloc (sizeof (*array->lvs));
if (!array->lvs)
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));
*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;
struct grub_diskfilter_lv {
/* Name used for disk. */
char *fullname;
+ char *idname;
/* Optional. */
char *name;
int number;
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. */
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 *) ":";
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';
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:
{