All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick Plenefisch <simonpatp@gmail.com>
To: grub-devel@gnu.org
Subject: [PATCH] LVM Cachevol and Integrity volumes break entire LVM VG
Date: Mon, 29 Jan 2024 16:37:30 -0500	[thread overview]
Message-ID: <CAOCpoWfu3biJrC4uk_geGmskepuO4vP4VFGjnu=nvaEFmRqWrA@mail.gmail.com> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 14839 bytes --]

In an effort to solve
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1061168 for myself, I
implemented basic support for cachevol and integrity volumes in LVM.

This is just an extension of the cachepool support that already existed,
and just like that support, I ignore all of the metadata and just go for
the data. This obviously means that writing to "writeback" cachepools, and
any raidintegrity volumes will cause corruption as before, but as grub only
reads files, I think that should be fine.



diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c
index 21e239511..dc3bd943b 100644
--- a/grub-core/disk/diskfilter.c
+++ b/grub-core/disk/diskfilter.c
@@ -966,8 +966,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg
*vg)

   for (lv = vg->lvs; lv; lv = lv->next)
     {
-      grub_err_t err;
-
       /* RAID 1 and single-disk RAID 0 don't use a chunksize but code
          assumes one so set one. */
       for (i = 0; i < lv->segment_count; i++)
@@ -979,6 +977,10 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg
*vg)
           && lv->segments[i].stripe_size == 0)
         lv->segments[i].stripe_size = 64;
     }
+    }
+  for (lv = vg->lvs; lv; lv = lv->next)
+    {
+      grub_err_t err;

       err = validate_lv(lv);
       if (err)
diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c
index 794248540..b500a41e8 100644
--- a/grub-core/disk/lvm.c
+++ b/grub-core/disk/lvm.c
@@ -34,12 +34,11 @@

 GRUB_MOD_LICENSE ("GPLv3+");

-struct cache_lv
+struct ignored_feature_lv
 {
   struct grub_diskfilter_lv *lv;
-  char *cache_pool;
   char *origin;
-  struct cache_lv *next;
+  struct ignored_feature_lv *next;
 };


@@ -105,30 +104,29 @@ grub_lvm_check_flag (const char *p, const char *str,
const char *flag)
 }

 static void
-grub_lvm_free_cache_lvs (struct cache_lv *cache_lvs)
+grub_lvm_free_ignored_feature_lvs (struct ignored_feature_lv
*ignored_feature_lvs)
 {
-  struct cache_lv *cache;
+  struct ignored_feature_lv *ignored_feature;

-  while ((cache = cache_lvs))
+  while ((ignored_feature = ignored_feature_lvs))
     {
-      cache_lvs = cache_lvs->next;
+      ignored_feature_lvs = ignored_feature_lvs->next;

-      if (cache->lv)
+      if (ignored_feature->lv)
     {
       unsigned int i;

-      for (i = 0; i < cache->lv->segment_count; ++i)
-        if (cache->lv->segments)
-          grub_free (cache->lv->segments[i].nodes);
-      grub_free (cache->lv->segments);
-      grub_free (cache->lv->fullname);
-      grub_free (cache->lv->idname);
-      grub_free (cache->lv->name);
+      for (i = 0; i < ignored_feature->lv->segment_count; ++i)
+        if (ignored_feature->lv->segments)
+          grub_free (ignored_feature->lv->segments[i].nodes);
+      grub_free (ignored_feature->lv->segments);
+      grub_free (ignored_feature->lv->fullname);
+      grub_free (ignored_feature->lv->idname);
+      grub_free (ignored_feature->lv->name);
     }
-      grub_free (cache->lv);
-      grub_free (cache->origin);
-      grub_free (cache->cache_pool);
-      grub_free (cache);
+      grub_free (ignored_feature->lv);
+      grub_free (ignored_feature->origin);
+      grub_free (ignored_feature);
     }
 }

@@ -325,7 +323,7 @@ grub_lvm_detect (grub_disk_t disk,

   if (! vg)
     {
-      struct cache_lv *cache_lvs = NULL;
+      struct ignored_feature_lv *ignored_feature_lvs = NULL;

       /* First time we see this volume group. We've to create the
      whole volume group structure. */
@@ -807,108 +805,99 @@ grub_lvm_detect (grub_disk_t disk,
               seg->nodes[seg->node_count - 1].name = tmp;
             }
             }
+          /* Cache and integrity LVs have extra parts that
+             we can ignore for our read-only access */
           else if (grub_memcmp (p, "cache\"",
-                   sizeof ("cache\"") - 1) == 0)
+                   sizeof ("cache\"") - 1) == 0
+                   || grub_memcmp (p, "cache+CACHE_USES_CACHEVOL\"",
+                   sizeof ("cache+CACHE_USES_CACHEVOL\"") - 1) == 0
+                   || grub_memcmp (p, "integrity\"",
+                   sizeof ("integrity\"") - 1) == 0)
             {
-              struct cache_lv *cache = NULL;
+              struct ignored_feature_lv *ignored_feature = NULL;

               char *p2, *p3;
               grub_size_t sz;

-              cache = grub_zalloc (sizeof (*cache));
-              if (!cache)
-            goto cache_lv_fail;
-              cache->lv = grub_zalloc (sizeof (*cache->lv));
-              if (!cache->lv)
-            goto cache_lv_fail;
-              grub_memcpy (cache->lv, lv, sizeof (*cache->lv));
+#ifdef GRUB_UTIL
+              p2 = grub_strchr (p, '"');
+              if (p2)
+            *p2 = 0;
+              grub_util_info ("Ignoring extra metadata type '%s' for %s",
p, lv->name);
+              if (p2)
+            *p2 ='"';
+#endif
+
+              ignored_feature = grub_zalloc (sizeof (*ignored_feature));
+              if (!ignored_feature)
+            goto ignored_feature_lv_fail;
+              ignored_feature->lv = grub_zalloc (sizeof
(*ignored_feature->lv));
+              if (!ignored_feature->lv)
+            goto ignored_feature_lv_fail;
+              grub_memcpy (ignored_feature->lv, lv, sizeof
(*ignored_feature->lv));

               if (lv->fullname)
             {
-              cache->lv->fullname = grub_strdup (lv->fullname);
-              if (!cache->lv->fullname)
-                goto cache_lv_fail;
+              ignored_feature->lv->fullname = grub_strdup (lv->fullname);
+              if (!ignored_feature->lv->fullname)
+                goto ignored_feature_lv_fail;
             }
               if (lv->idname)
             {
-              cache->lv->idname = grub_strdup (lv->idname);
-              if (!cache->lv->idname)
-                goto cache_lv_fail;
+              ignored_feature->lv->idname = grub_strdup (lv->idname);
+              if (!ignored_feature->lv->idname)
+                goto ignored_feature_lv_fail;
             }
               if (lv->name)
             {
-              cache->lv->name = grub_strdup (lv->name);
-              if (!cache->lv->name)
-                goto cache_lv_fail;
+              ignored_feature->lv->name = grub_strdup (lv->name);
+              if (!ignored_feature->lv->name)
+                goto ignored_feature_lv_fail;
             }

               skip_lv = 1;

-              p2 = grub_strstr (p, "cache_pool = \"");
-              if (!p2)
-            goto cache_lv_fail;
-
-              p2 = grub_strchr (p2, '"');
-              if (!p2)
-            goto cache_lv_fail;
-
-              p3 = ++p2;
-              if (p3 == mda_end)
-            goto cache_lv_fail;
-              p3 = grub_strchr (p3, '"');
-              if (!p3)
-            goto cache_lv_fail;
-
-              sz = p3 - p2;
-
-              cache->cache_pool = grub_malloc (sz + 1);
-              if (!cache->cache_pool)
-            goto cache_lv_fail;
-              grub_memcpy (cache->cache_pool, p2, sz);
-              cache->cache_pool[sz] = '\0';
-
               p2 = grub_strstr (p, "origin = \"");
               if (!p2)
-            goto cache_lv_fail;
+            goto ignored_feature_lv_fail;

               p2 = grub_strchr (p2, '"');
               if (!p2)
-            goto cache_lv_fail;
+            goto ignored_feature_lv_fail;

               p3 = ++p2;
               if (p3 == mda_end)
-            goto cache_lv_fail;
+            goto ignored_feature_lv_fail;
               p3 = grub_strchr (p3, '"');
               if (!p3)
-            goto cache_lv_fail;
+            goto ignored_feature_lv_fail;

               sz = p3 - p2;

-              cache->origin = grub_malloc (sz + 1);
-              if (!cache->origin)
-            goto cache_lv_fail;
-              grub_memcpy (cache->origin, p2, sz);
-              cache->origin[sz] = '\0';
+              ignored_feature->origin = grub_malloc (sz + 1);
+              if (!ignored_feature->origin)
+            goto ignored_feature_lv_fail;
+              grub_memcpy (ignored_feature->origin, p2, sz);
+              ignored_feature->origin[sz] = '\0';

-              cache->next = cache_lvs;
-              cache_lvs = cache;
+              ignored_feature->next = ignored_feature_lvs;
+              ignored_feature_lvs = ignored_feature;
               break;

-            cache_lv_fail:
-              if (cache)
+            ignored_feature_lv_fail:
+              if (ignored_feature)
             {
-              grub_free (cache->origin);
-              grub_free (cache->cache_pool);
-              if (cache->lv)
+              grub_free (ignored_feature->origin);
+              if (ignored_feature->lv)
                 {
-                  grub_free (cache->lv->fullname);
-                  grub_free (cache->lv->idname);
-                  grub_free (cache->lv->name);
+                  grub_free (ignored_feature->lv->fullname);
+                  grub_free (ignored_feature->lv->idname);
+                  grub_free (ignored_feature->lv->name);
                 }
-              grub_free (cache->lv);
-              grub_free (cache);
+              grub_free (ignored_feature->lv);
+              grub_free (ignored_feature);
             }
-              grub_lvm_free_cache_lvs (cache_lvs);
+              grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
               goto fail4;
             }
           else
@@ -961,88 +950,95 @@ grub_lvm_detect (grub_disk_t disk,
         }
     }

-      /* Match lvs.  */
       {
-    struct grub_diskfilter_lv *lv1;
-    struct grub_diskfilter_lv *lv2;
-    for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
-      for (i = 0; i < lv1->segment_count; i++)
-        for (j = 0; j < lv1->segments[i].node_count; j++)
-          {
-        if (vg->pvs)
-          for (pv = vg->pvs; pv; pv = pv->next)
-            {
-              if (! grub_strcmp (pv->name,
-                     lv1->segments[i].nodes[j].name))
-            {
-              lv1->segments[i].nodes[j].pv = pv;
-              break;
-            }
-            }
-        if (lv1->segments[i].nodes[j].pv == NULL)
-          for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
-            {
-              if (lv1 == lv2)
-                continue;
-              if (grub_strcmp (lv2->name,
-                       lv1->segments[i].nodes[j].name) == 0)
-            lv1->segments[i].nodes[j].lv = lv2;
-            }
-          }
+    struct ignored_feature_lv *ignored_feature;

-      }
-
-      {
-    struct cache_lv *cache;
-
-    for (cache = cache_lvs; cache; cache = cache->next)
+    for (ignored_feature = ignored_feature_lvs; ignored_feature;
ignored_feature = ignored_feature->next)
       {
         struct grub_diskfilter_lv *lv;

         for (lv = vg->lvs; lv; lv = lv->next)
-          if (grub_strcmp (lv->name, cache->origin) == 0)
+          if (grub_strcmp (lv->name, ignored_feature->origin) == 0)
         break;
         if (lv)
           {
-        cache->lv->segments = grub_calloc (lv->segment_count, sizeof
(*lv->segments));
-        if (!cache->lv->segments)
+        ignored_feature->lv->segments = grub_calloc (lv->segment_count,
sizeof (*lv->segments));
+        if (!ignored_feature->lv->segments)
           {
-            grub_lvm_free_cache_lvs (cache_lvs);
+            grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
             goto fail4;
           }
-        grub_memcpy (cache->lv->segments, lv->segments, lv->segment_count
* sizeof (*lv->segments));
+        grub_memcpy (ignored_feature->lv->segments, lv->segments,
lv->segment_count * sizeof (*lv->segments));

         for (i = 0; i < lv->segment_count; ++i)
           {
             struct grub_diskfilter_node *nodes = lv->segments[i].nodes;
             grub_size_t node_count = lv->segments[i].node_count;

-            cache->lv->segments[i].nodes = grub_calloc (node_count, sizeof
(*nodes));
-            if (!cache->lv->segments[i].nodes)
+            ignored_feature->lv->segments[i].nodes = grub_calloc
(node_count, sizeof (*nodes));
+            if (!ignored_feature->lv->segments[i].nodes)
               {
             for (j = 0; j < i; ++j)
-              grub_free (cache->lv->segments[j].nodes);
-            grub_free (cache->lv->segments);
-            cache->lv->segments = NULL;
-            grub_lvm_free_cache_lvs (cache_lvs);
+              grub_free (ignored_feature->lv->segments[j].nodes);
+            grub_free (ignored_feature->lv->segments);
+            ignored_feature->lv->segments = NULL;
+            grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
             goto fail4;
               }
-            grub_memcpy (cache->lv->segments[i].nodes, nodes, node_count *
sizeof (*nodes));
+            grub_memcpy (ignored_feature->lv->segments[i].nodes, nodes,
node_count * sizeof (*nodes));
           }

-        if (cache->lv->segments)
+        if (ignored_feature->lv->segments)
           {
-            cache->lv->segment_count = lv->segment_count;
-            cache->lv->vg = vg;
-            cache->lv->next = vg->lvs;
-            vg->lvs = cache->lv;
-            cache->lv = NULL;
+            ignored_feature->lv->segment_count = lv->segment_count;
+            ignored_feature->lv->vg = vg;
+            ignored_feature->lv->next = vg->lvs;
+            vg->lvs = ignored_feature->lv;
+            ignored_feature->lv = NULL;
           }
           }
+          else
+          {
+
+#ifdef GRUB_UTIL
+              grub_util_info ("Couldn't find LVM part of ignored feature
on %s", ignored_feature->origin);
+#endif
+          }
       }
       }

-      grub_lvm_free_cache_lvs (cache_lvs);
+      /* Match lvs. Must be done after cache and integrity are found  */
+      {
+    struct grub_diskfilter_lv *lv1;
+    struct grub_diskfilter_lv *lv2;
+    for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
+      for (i = 0; i < lv1->segment_count; i++)
+        for (j = 0; j < lv1->segments[i].node_count; j++)
+          {
+        if (vg->pvs)
+          for (pv = vg->pvs; pv; pv = pv->next)
+            {
+              if (! grub_strcmp (pv->name,
+                     lv1->segments[i].nodes[j].name))
+            {
+              lv1->segments[i].nodes[j].pv = pv;
+              break;
+            }
+            }
+        if (lv1->segments[i].nodes[j].pv == NULL)
+          for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
+            {
+              if (lv1 == lv2)
+                continue;
+              if (grub_strcmp (lv2->name,
+                       lv1->segments[i].nodes[j].name) == 0)
+            lv1->segments[i].nodes[j].lv = lv2;
+            }
+          }
+
+      }
+
+      grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs);
       if (grub_diskfilter_vg_register (vg))
     goto fail4;
     }

[-- Attachment #1.2: Type: text/html, Size: 19246 bytes --]

[-- Attachment #2: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

             reply	other threads:[~2024-01-29 21:38 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-29 21:37 Patrick Plenefisch [this message]
2024-02-08 16:57 ` [PATCH] LVM Cachevol and Integrity volumes break entire LVM VG Daniel Kiper
2024-02-08 19:52   ` Patrick Plenefisch
2024-02-08 20:05     ` Daniel Kiper
2024-02-19  2:00       ` Patrick Plenefisch
2024-04-26 23:10         ` Glenn Washburn
2024-04-26 23:13           ` Glenn Washburn
2024-04-27  1:02             ` Patrick Plenefisch
2024-04-27  9:25               ` Glenn Washburn
2024-04-27 19:26                 ` Patrick Plenefisch

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAOCpoWfu3biJrC4uk_geGmskepuO4vP4VFGjnu=nvaEFmRqWrA@mail.gmail.com' \
    --to=simonpatp@gmail.com \
    --cc=grub-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.