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. Without these patches, a system with /boot on a LV in a VG that also has cachevol or integrity volumes will fail to boot. These patches are also available attached and at https://github.com/byteit101/grub2/commits/grub-lvmintegrity/ This is identical to the previous version, except patch 3 has been split into patches 3,4, and 5. Patrick Plenefisch (6): disk/lvm: Make cache_lv more generic as ignored_feature_lv disk/lvm: Remove unused cache_pool lvm: Match all lvm segments before validation lvm: Add support for integrity lv lvm: add informational messages in error cases of ignored features lvm: Add support for cachevol lv grub-core/disk/diskfilter.c | 6 +- grub-core/disk/lvm.c | 267 ++++++++++++++++++------------------ 2 files changed, 136 insertions(+), 137 deletions(-) -- 2.39.5
From 286a2eca5b69e770682b762b1d895734a124e222 Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch <simonp...@gmail.com> Date: Mon, 11 Nov 2024 13:18:39 -0500 Subject: [PATCH 6/6] lvm: Add support for cachevol lv Mark cachevol lv's as ignored features, which is true only if they are configured as "writethrough". This patch does not let grub boot from "writeback" cache-enabled lv's Signed-off-by: Patrick Plenefisch <simonp...@gmail.com> Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com> --- grub-core/disk/lvm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index abb5b12ae..02e359827 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -811,6 +811,8 @@ grub_lvm_detect (grub_disk_t disk, */ else if (grub_strncmp (p, "cache\"", sizeof ("cache\"") - 1) == 0 + || grub_strncmp (p, "cache+CACHE_USES_CACHEVOL\"", + sizeof ("cache+CACHE_USES_CACHEVOL\"") - 1) == 0 || grub_strncmp (p, "integrity\"", sizeof ("integrity\"") - 1) == 0) { -- 2.39.5
From 3190ae332b194b92e2fb7d0e5a8033f519d7b177 Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch <simonp...@gmail.com> Date: Tue, 13 Aug 2024 20:15:37 -0400 Subject: [PATCH 2/6] disk/lvm: Remove unused cache_pool cache_pool is never read or used, remove it Signed-off-by: Patrick Plenefisch <simonp...@gmail.com> Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com> --- grub-core/disk/lvm.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 36023279f..286132d74 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -37,7 +37,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct ignored_feature_lv { struct grub_diskfilter_lv *lv; - char *cache_pool; char *origin; struct ignored_feature_lv *next; }; @@ -127,7 +126,6 @@ grub_lvm_free_ignored_feature_lvs (struct ignored_feature_lv *ignored_feature_lv } grub_free (ignored_feature->lv); grub_free (ignored_feature->origin); - grub_free (ignored_feature->cache_pool); grub_free (ignored_feature); } } @@ -844,28 +842,6 @@ grub_lvm_detect (grub_disk_t disk, skip_lv = 1; - p2 = grub_strstr (p, "cache_pool = \""); - if (!p2) - goto ignored_feature_lv_fail; - - p2 = grub_strchr (p2, '"'); - if (!p2) - goto ignored_feature_lv_fail; - - p3 = ++p2; - if (p3 == mda_end) - goto ignored_feature_lv_fail; - p3 = grub_strchr (p3, '"'); - if (!p3) - goto ignored_feature_lv_fail; - - sz = p3 - p2; - - ignored_feature->cache_pool = grub_malloc (sz + 1); - if (!ignored_feature->cache_pool) - goto ignored_feature_lv_fail; - grub_memcpy (ignored_feature->cache_pool, p2, sz); - ignored_feature->cache_pool[sz] = '\0'; p2 = grub_strstr (p, "origin = \""); if (!p2) @@ -898,7 +874,6 @@ grub_lvm_detect (grub_disk_t disk, if (ignored_feature) { grub_free (ignored_feature->origin); - grub_free (ignored_feature->cache_pool); if (ignored_feature->lv) { grub_free (ignored_feature->lv->fullname); -- 2.39.5
From bf2c8d37555d3b048830b32c6c7fd37982e8110a Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch <simonp...@gmail.com> Date: Sat, 7 Dec 2024 21:17:35 -0500 Subject: [PATCH 4/6] lvm: Add support for integrity lv lv matching must be done after processing the ignored feature indirections, as integrity volumes & caches may have several levels of indirection that the segments must be shifted through. Signed-off-by: Patrick Plenefisch <simonp...@gmail.com> --- grub-core/disk/lvm.c | 70 ++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 286132d74..9c9386751 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -805,8 +805,14 @@ grub_lvm_detect (grub_disk_t disk, seg->nodes[seg->node_count - 1].name = tmp; } } - else if (grub_memcmp (p, "cache\"", - sizeof ("cache\"") - 1) == 0) + /* + * Cache and integrity LVs have extra parts that + * we can ignore for our read-only access + */ + else if (grub_strncmp (p, "cache\"", + sizeof ("cache\"") - 1) == 0 + || grub_strncmp (p, "integrity\"", + sizeof ("integrity\"") - 1) == 0) { struct ignored_feature_lv *ignored_feature = NULL; @@ -936,36 +942,6 @@ 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; @@ -1017,6 +993,36 @@ grub_lvm_detect (grub_disk_t disk, } } + /* 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; -- 2.39.5
From 204ac11d0769c0e29f0e126023d91268b57d7be1 Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch <simonp...@gmail.com> Date: Sat, 7 Dec 2024 21:19:23 -0500 Subject: [PATCH 5/6] lvm: add informational messages in error cases of ignored features This patch contains a change requested by Daniel Kiper to use a null character instead of an integer zero to terminate strings Signed-off-by: Patrick Plenefisch <simonp...@gmail.com> --- grub-core/disk/lvm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 9c9386751..abb5b12ae 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -818,6 +818,14 @@ grub_lvm_detect (grub_disk_t disk, char *p2, *p3; grub_size_t sz; +#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) @@ -898,7 +906,7 @@ grub_lvm_detect (grub_disk_t disk, char *p2; p2 = grub_strchr (p, '"'); if (p2) - *p2 = 0; + *p2 = '\0'; grub_util_info ("unknown LVM type %s", p); if (p2) *p2 ='"'; @@ -990,6 +998,12 @@ grub_lvm_detect (grub_disk_t disk, 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 + } } } -- 2.39.5
From ff935463bc6847a4f286d70c7054d21b5f0a457f Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch <simonp...@gmail.com> Date: Sat, 7 Dec 2024 21:13:56 -0500 Subject: [PATCH 3/6] lvm: Match all lvm segments before validation pv matching must be completely finished before validating a volume, otherwise referenced raid stripes may not have pv data applied yet This change is required for integrity & cachevol support Signed-off-by: Patrick Plenefisch <simonp...@gmail.com> --- grub-core/disk/diskfilter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c index 606195c26..801b24985 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -979,8 +979,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++) @@ -992,6 +990,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) -- 2.39.5
From 008dc4f4cdefffc49c0c328648c1cd56b0de9a7a Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch <simonp...@gmail.com> Date: Tue, 13 Aug 2024 20:40:02 -0400 Subject: [PATCH 1/6] disk/lvm: Make cache_lv more generic as ignored_feature_lv This patch isn't necessary by itself, but when combined with the next two patchs it enhances readability as ignored_features_lv is then used for multiple types of extra LV's, not just cache LV's Signed-off-by: Patrick Plenefisch <simonp...@gmail.com> Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com> --- grub-core/disk/lvm.c | 176 +++++++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 0c32c95f9..36023279f 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -34,12 +34,12 @@ 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 +105,30 @@ 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->cache_pool); + grub_free (ignored_feature); } } @@ -325,7 +325,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. */ @@ -810,105 +810,105 @@ grub_lvm_detect (grub_disk_t disk, else if (grub_memcmp (p, "cache\"", sizeof ("cache\"") - 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)); + 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; + 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->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'; + ignored_feature->cache_pool = grub_malloc (sz + 1); + if (!ignored_feature->cache_pool) + goto ignored_feature_lv_fail; + grub_memcpy (ignored_feature->cache_pool, p2, sz); + ignored_feature->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); + grub_free (ignored_feature->cache_pool); + 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 @@ -993,56 +993,56 @@ grub_lvm_detect (grub_disk_t disk, } { - struct cache_lv *cache; + struct ignored_feature_lv *ignored_feature; - 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; } } } } - grub_lvm_free_cache_lvs (cache_lvs); + grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs); if (grub_diskfilter_vg_register (vg)) goto fail4; } -- 2.39.5
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel