220 lines
6.0 KiB
Diff
220 lines
6.0 KiB
Diff
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;
|
||
}
|
||
|