114 lines
3.6 KiB
Diff
114 lines
3.6 KiB
Diff
|
From 1dea84ae38288fbefa04d9fda2b3f36c21a9e1bd Mon Sep 17 00:00:00 2001
|
||
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||
|
Date: Mon, 29 May 2023 15:52:38 +0200
|
||
|
Subject: [PATCH 132/165] imsm: fix free space calculations
|
||
|
|
||
|
Between two volumes or between last volume and metadata at least
|
||
|
IMSM_RESERVED_SECTORS gap must exist. Currently the gap can be doubled
|
||
|
because metadata reservation contains IMSM_RESERVED_SECTORS too.
|
||
|
|
||
|
Divide reserve variable into pre_reservation and post_reservation to be
|
||
|
more flexible and decide separately if each reservation is needed.
|
||
|
|
||
|
Pre_reservation is needed only when a volume is created and it is not a
|
||
|
real first volume in a container (we can check that by extent_idx).
|
||
|
This type of reservation is not needed for expand.
|
||
|
|
||
|
Post_reservation is not needed only if real last volume is created or
|
||
|
expanded because reservation is done with the metadata.
|
||
|
|
||
|
The volume index in metadata cannot be trusted, because the real volume
|
||
|
order can be reversed. It is safer to use extent table, it is sorted by
|
||
|
start position.
|
||
|
|
||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||
|
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||
|
---
|
||
|
super-intel.c | 50 ++++++++++++++++++++++++++++++--------------------
|
||
|
1 file changed, 30 insertions(+), 20 deletions(-)
|
||
|
|
||
|
diff --git a/super-intel.c b/super-intel.c
|
||
|
index e249d925..824c1356 100644
|
||
|
--- a/super-intel.c
|
||
|
+++ b/super-intel.c
|
||
|
@@ -6919,8 +6919,11 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
|
||
|
int sum_extents = 0;
|
||
|
unsigned long long pos = 0;
|
||
|
unsigned long long start = 0;
|
||
|
- unsigned long long maxsize = 0;
|
||
|
- unsigned long reserve;
|
||
|
+ unsigned long long free_size = 0;
|
||
|
+
|
||
|
+ unsigned long pre_reservation = 0;
|
||
|
+ unsigned long post_reservation = IMSM_RESERVED_SECTORS;
|
||
|
+ unsigned long reservation_size;
|
||
|
|
||
|
for (dl = super->disks; dl; dl = dl->next)
|
||
|
if (dl->e)
|
||
|
@@ -6955,8 +6958,8 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
|
||
|
do {
|
||
|
unsigned long long esize = e[i].start - pos;
|
||
|
|
||
|
- if (expanding ? pos_vol_idx == super->current_vol : esize >= maxsize) {
|
||
|
- maxsize = esize;
|
||
|
+ if (expanding ? pos_vol_idx == super->current_vol : esize >= free_size) {
|
||
|
+ free_size = esize;
|
||
|
start = pos;
|
||
|
extent_idx = i;
|
||
|
}
|
||
|
@@ -6966,28 +6969,35 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
|
||
|
|
||
|
i++;
|
||
|
} while (e[i-1].size);
|
||
|
- free(e);
|
||
|
|
||
|
- if (maxsize == 0)
|
||
|
+ if (free_size == 0) {
|
||
|
+ dprintf("imsm: Cannot find free size.\n");
|
||
|
+ free(e);
|
||
|
return 0;
|
||
|
+ }
|
||
|
|
||
|
- /* FIXME assumes volume at offset 0 is the first volume in a
|
||
|
- * container
|
||
|
- */
|
||
|
- if (extent_idx > 0)
|
||
|
- reserve = IMSM_RESERVED_SECTORS; /* gap between raid regions */
|
||
|
- else
|
||
|
- reserve = 0;
|
||
|
+ if (!expanding && extent_idx != 0)
|
||
|
+ /*
|
||
|
+ * Not a real first volume in a container is created, pre_reservation is needed.
|
||
|
+ */
|
||
|
+ pre_reservation = IMSM_RESERVED_SECTORS;
|
||
|
|
||
|
- if (maxsize < reserve)
|
||
|
- return 0;
|
||
|
+ if (e[extent_idx].size == 0)
|
||
|
+ /*
|
||
|
+ * extent_idx points to the metadata, post_reservation is allready done.
|
||
|
+ */
|
||
|
+ post_reservation = 0;
|
||
|
+ free(e);
|
||
|
|
||
|
- super->create_offset = ~((unsigned long long) 0);
|
||
|
- if (start + reserve > super->create_offset)
|
||
|
- return 0; /* start overflows create_offset */
|
||
|
- super->create_offset = start + reserve;
|
||
|
+ reservation_size = pre_reservation + post_reservation;
|
||
|
+
|
||
|
+ if (free_size < reservation_size) {
|
||
|
+ dprintf("imsm: Reservation size is greater than free space.\n");
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
|
||
|
- return maxsize - reserve;
|
||
|
+ super->create_offset = start + pre_reservation;
|
||
|
+ return free_size - reservation_size;
|
||
|
}
|
||
|
|
||
|
static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
|
||
|
--
|
||
|
2.40.1
|
||
|
|