From: Vladimir 'phcoder' Serbinenko Date: Fri, 20 Sep 2013 18:37:03 +0000 (+0200) Subject: * grub-core/disk/diskfilter.c: Handle non-md UUIDs. X-Git-Tag: grub-2.02-beta1~843 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=63653cfdae32648c93870fd36b2925346aa8ff36;p=thirdparty%2Fgrub.git * 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. --- diff --git a/ChangeLog b/ChangeLog index 708c57e04..cffa87134 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-09-20 Vladimir Serbinenko + + * 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 * docs/grub.texi (Networking commands): Add documentation for diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c index 99bf9e5c3..eef143a1d 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -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)); diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 508e94af0..4025532c4 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -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; diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h index b25807eee..3ed806326 100644 --- a/include/grub/diskfilter.h +++ b/include/grub/diskfilter.h @@ -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; diff --git a/util/getroot.c b/util/getroot.c index 88bbf6afc..69e04dc90 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -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: {