grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] diskfilter: implementation of processing no metadata recorded in


From: Lidong Zhong
Subject: [PATCH] diskfilter: implementation of processing no metadata recorded in PV
Date: Wed, 26 Apr 2017 15:52:40 +0800

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 <address@hidden>
---
 grub-core/disk/diskfilter.c | 100 ++++++++++++++++++++++++++++++++++++++++++++
 grub-core/disk/lvm.c        |  15 ++++---
 include/grub/diskfilter.h   |   9 ++++
 3 files changed, 119 insertions(+), 5 deletions(-)

diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 6f901c0ad..674440576 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -28,11 +28,13 @@
 #include <grub/i18n.h>
 #include <grub/util/misc.h>
 #endif
+#include <grub/lvm.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
 /* Linked list of DISKFILTER arrays. */
 static struct grub_diskfilter_vg *array_list;
+static struct grub_detached_pv *detached_pv_list;
 grub_raid5_recover_func_t grub_raid5_recover_func;
 grub_raid6_recover_func_t grub_raid6_recover_func;
 grub_diskfilter_t grub_diskfilter_list;
@@ -43,6 +45,7 @@ static struct grub_diskfilter_lv *
 find_lv (const char *name);
 static int is_lv_readable (struct grub_diskfilter_lv *lv, int easily);
 
+#define FOR_DETACHED_PVS(var) for (var = detached_pv_list; var; var = 
var->next)
 
 
 static grub_err_t
@@ -132,6 +135,7 @@ scan_disk_partition_iter (grub_disk_t disk, 
grub_partition_t p, void *data)
   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 +172,28 @@ scan_disk_partition_iter (grub_disk_t disk, 
grub_partition_t p, void *data)
            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.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);
+        pv->id.uuidlen = 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 +206,63 @@ scan_disk_partition_iter (grub_disk_t disk, 
grub_partition_t p, void *data)
     }
 
   return 0;
+fail_id:
+  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 standalone 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 standalone 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 +289,9 @@ scan_disk (const char *name, int accept_diskfilter)
   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;
 }
 
@@ -1249,6 +1335,20 @@ insert_array (grub_disk_t disk, const struct 
grub_diskfilter_pv_id *id,
 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;
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 7b265c780..091ed7d5a 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -186,11 +186,16 @@ grub_lvm_detect (grub_disk_t disk,
                     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 fail2;
+      grub_memcpy(id->uuid, pv_id, GRUB_LVM_ID_STRLEN);
+      id->uuidlen = GRUB_LVM_ID_STRLEN;
       goto fail2;
     }
 
diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h
index d89273c1b..6e2138a25 100644
--- a/include/grub/diskfilter.h
+++ b/include/grub/diskfilter.h
@@ -148,6 +148,15 @@ struct grub_diskfilter
 typedef struct grub_diskfilter *grub_diskfilter_t;
 
 extern grub_diskfilter_t grub_diskfilter_list;
+
+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 inline void
 grub_diskfilter_register_front (grub_diskfilter_t diskfilter)
 {
-- 
2.12.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]