grub2/grub2-diskfilter-support-pv-without-metadatacopies.patch

220 lines
6.0 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From a28bc19400b4e70725ce5532bc5e4c374c72d7a9 Mon Sep 17 00:00:00 2001
From: Lidong Zhong <lzhong@suse.com>
Date: Wed, 26 Apr 2017 15:52:40 +0800
Subject: [PATCH] diskfilter: implementation of processing no metadata recorded
in PV
If one PV underlying the root LV is created with no metadata, such as
pvcreate --metadatacopies 0 /dev/sda
then we could get a lot of error messages when generating a new
configuration file.
Generating grub configuration file ...
error: unknown LVM metadata header.
error: unknown LVM metadata header.
/usr/sbin/grub2-probe: warning: Couldn't find physical volume `pv1'.
Some modules may be missing from core image..
(For details, please refer to
https://bugzilla.suse.com/show_bug.cgi?id=1027526)
When one labelled PV which dose not have any metadata is found, we put
it into a global grub_detached_pv list. and we search all the PVs in the
current array list to check if it is a member of grub_detached_pv list.
So we can know if the PV is really missing or just without metadata.
Signed-off-by: Lidong Zhong <lzhong@suse.com>
---
grub-core/disk/diskfilter.c | 112 +++++++++++++++++++++++++++++++++++++++++++-
grub-core/disk/lvm.c | 15 ++++--
2 files changed, 121 insertions(+), 6 deletions(-)
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -28,6 +28,7 @@
#include <grub/i18n.h>
#include <grub/util/misc.h>
#endif
+#include <grub/lvm.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -43,7 +44,17 @@
find_lv (const char *name);
static int is_lv_readable (struct grub_diskfilter_lv *lv, int easily);
-
+struct grub_detached_pv {
+ struct grub_detached_pv *next;
+ struct grub_detached_pv **prev;
+ struct grub_diskfilter_pv_id id;
+ grub_disk_t disk;
+ grub_diskfilter_t diskfilter;
+} ;
+
+static struct grub_detached_pv *detached_pv_list;
+
+#define FOR_DETACHED_PVS(var) for (var = detached_pv_list; var; var = var->next)
static grub_err_t
is_node_readable (const struct grub_diskfilter_node *node, int easily)
@@ -132,6 +143,7 @@
grub_disk_addr_t start_sector;
struct grub_diskfilter_pv_id id;
grub_diskfilter_t diskfilter;
+ struct grub_detached_pv *pv;
grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
name);
@@ -168,6 +180,28 @@
grub_free (id.uuid);
return 0;
}
+ /*insert the special LVM PV into detached_pv_list*/
+ if (!arr && (id.uuidlen > 0) && (grub_strcmp(diskfilter->name, "lvm") == 0))
+ {
+ pv = grub_zalloc(sizeof(*pv));
+ if (!pv)
+ return 1;
+ pv->id.uuidlen = GRUB_LVM_ID_STRLEN;
+ pv->id.uuid = grub_malloc(GRUB_LVM_ID_STRLEN);
+ if (!pv->id.uuid)
+ goto fail_id;
+ grub_memcpy(pv->id.uuid, id.uuid, GRUB_LVM_ID_STRLEN);
+ /*It's safe to save disk into this standalone pv list*/
+ pv->disk = grub_disk_open(name);
+ if (!pv->disk)
+ goto fail_id;
+ pv->diskfilter = diskfilter;
+ grub_list_push (GRUB_AS_LIST_P (&detached_pv_list),
+ GRUB_AS_LIST(pv));
+#ifdef GRUB_UTIL
+ grub_util_info ("adding disk %s into detached pv list", name);
+#endif
+ }
if (arr && id.uuidlen)
grub_free (id.uuid);
@@ -180,6 +214,65 @@
}
return 0;
+fail_id:
+ if (pv->id.uuidlen)
+ grub_free(pv->id.uuid);
+ grub_free(pv);
+ return 1;
+}
+
+static int
+process_detached_pv_list(void)
+{
+ struct grub_diskfilter_vg *arr;
+ struct grub_diskfilter_pv *pv1;
+ struct grub_detached_pv *pv2;
+ unsigned found = 0;
+
+ for (arr = array_list; arr != NULL; arr = arr->next)
+ {
+ for (pv1 = arr->pvs; pv1; pv1 = pv1->next)
+ {
+ if (pv1->disk)
+ continue;
+ FOR_DETACHED_PVS(pv2)
+ {
+ if (pv2->id.uuidlen == pv1->id.uuidlen &&
+ !grub_memcmp(pv2->id.uuid, pv1->id.uuid, pv1->id.uuidlen))
+ {
+ if (insert_array(pv2->disk, &(pv2->id), arr, -1, pv2->diskfilter))
+ return grub_errno;
+ else
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("found disk %s in detached pv list", pv1->disk->name);
+#endif
+ found = 1;
+ break;
+ }
+ }
+ }
+ /*remove pv2 from the list*/
+ if (found)
+ {
+#ifdef GRUB_UTIL
+ grub_util_info ("removing disk %s from detached pv list", pv1->disk->name);
+#endif
+ grub_list_remove(GRUB_AS_LIST (pv2));
+ if (pv2->id.uuidlen)
+ {
+ pv2->id.uuidlen = 0;
+ grub_free(pv2->id.uuid);
+ }
+ grub_disk_close(pv2->disk);
+ grub_free(pv2);
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ return 0;
}
static int
@@ -206,6 +299,9 @@
grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name);
grub_disk_close (disk);
scan_depth--;
+
+ /*process the detached_pv_list*/
+ process_detached_pv_list();
return 0;
}
@@ -1287,6 +1383,20 @@
static void
free_array (void)
{
+ while(detached_pv_list)
+ {
+ struct grub_detached_pv *pv;
+ pv = detached_pv_list;
+ detached_pv_list = detached_pv_list->next;
+#ifdef GRUB_UTIL
+ grub_util_warn (_("Couldn't find disk for physical volume `%s'."
+ "Some LVs may not work normally."),pv->disk->name);
+#endif
+ if (pv->id.uuidlen)
+ grub_free(pv->id.uuid);
+ grub_disk_close(pv->disk);
+ grub_free(pv);
+ }
while (array_list)
{
struct grub_diskfilter_vg *vg;
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -235,11 +235,16 @@
sizeof (mdah->magic)))
|| (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION))
{
- grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
- "unknown LVM metadata header");
-#ifdef GRUB_UTIL
- grub_util_info ("unknown LVM metadata header");
-#endif
+ /*
+ * It's not necessarily an error. There is no metadata recorded when
+ * PV is created with pvmetadatacopies set to zero. We need to process
+ * this kind of PV seperately.
+ */
+ id->uuid = grub_malloc(GRUB_LVM_ID_STRLEN);
+ if (!id->uuid)
+ goto fail;
+ grub_memcpy(id->uuid, pv_id, GRUB_LVM_ID_STRLEN);
+ id->uuidlen = GRUB_LVM_ID_STRLEN;
goto fail;
}