80 lines
2.5 KiB
Diff
80 lines
2.5 KiB
Diff
From b9b28ee11adc8aba0fe11dda56a88b3cfc8d6b41 Mon Sep 17 00:00:00 2001
|
|
From: heinzm <heinzm@redhat.com>
|
|
Date: Wed, 10 May 2023 18:22:11 +0200
|
|
Subject: [PATCH 07/12] Fix "multisegment RAID1, allocator uses one disk for
|
|
both legs"
|
|
|
|
In case of e.g. 3 PVs, creating or extending a RaidLV causes SubLV
|
|
collocation thus putting segments of diffent rimage (and potentially
|
|
larger rmeta) SubLVs onto the same PV. For redundant RaidLVs this'll
|
|
compromise redundancy. Fix by detecting such bogus allocation on
|
|
lvcreate/lvextend and reject the request.
|
|
|
|
(cherry picked from commit 05c2b10c5d0a99993430ffbcef684a099ba810ad)
|
|
---
|
|
lib/metadata/lv_manip.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 41 insertions(+)
|
|
|
|
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
|
|
index 0a51e0315..24d8adc18 100644
|
|
--- a/lib/metadata/lv_manip.c
|
|
+++ b/lib/metadata/lv_manip.c
|
|
@@ -4454,6 +4454,38 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
|
|
return 1;
|
|
}
|
|
|
|
+/* Check either RAID images and metas are being allocated redundantly. */
|
|
+static int _lv_raid_redundant(struct logical_volume *lv,
|
|
+ struct dm_list *allocatable_pvs, int meta)
|
|
+{
|
|
+ uint32_t nlvs, s;
|
|
+ struct lv_segment *seg = first_seg(lv);
|
|
+ struct pv_list *pvl;
|
|
+
|
|
+ if (meta && !seg->meta_areas)
|
|
+ return 1;
|
|
+
|
|
+ dm_list_iterate_items(pvl, allocatable_pvs) {
|
|
+ nlvs = 0;
|
|
+
|
|
+ for (s = 0; s < seg->area_count; s++) {
|
|
+ struct logical_volume *slv = meta ? seg_metalv(seg, s) : seg_lv(seg, s);
|
|
+
|
|
+ if (slv && lv_is_on_pv(slv, pvl->pv) && nlvs++)
|
|
+ return 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+/* Check both RAID images and metas are being allocated redundantly. */
|
|
+static int _lv_raid_redundant_allocation(struct logical_volume *lv, struct dm_list *allocatable_pvs)
|
|
+{
|
|
+ return _lv_raid_redundant(lv, allocatable_pvs, 0) &&
|
|
+ _lv_raid_redundant(lv, allocatable_pvs, 1);
|
|
+}
|
|
+
|
|
/*
|
|
* Entry point for single-step LV allocation + extension.
|
|
* Extents is the number of logical extents to append to the LV unless
|
|
@@ -4556,6 +4588,15 @@ int lv_extend(struct logical_volume *lv,
|
|
mirrors, stripes, stripe_size)))
|
|
goto_out;
|
|
|
|
+ if (segtype_is_raid(segtype) &&
|
|
+ alloc != ALLOC_ANYWHERE &&
|
|
+ !(r = _lv_raid_redundant_allocation(lv, allocatable_pvs))) {
|
|
+ log_error("Insufficient suitable allocatable extents for logical volume %s", display_lvname(lv));
|
|
+ if (!lv_remove(lv) || !vg_write(lv->vg) || !vg_commit(lv->vg))
|
|
+ return_0;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (lv_raid_has_integrity(lv)) {
|
|
if (!lv_extend_integrity_in_raid(lv, allocatable_pvs)) {
|
|
r = 0;
|
|
--
|
|
2.43.0
|
|
|