239 lines
7.3 KiB
Diff
239 lines
7.3 KiB
Diff
From cbaa7904a175628a294ed54b4de6c52afa4f830d Mon Sep 17 00:00:00 2001
|
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
|
Date: Mon, 29 May 2023 15:52:36 +0200
|
|
Subject: [PATCH 130/165] imsm: move expand verification code into new function
|
|
|
|
The code here is too complex. Move it to separate function and
|
|
simplify it. Add more error messages.
|
|
|
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
|
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
|
---
|
|
super-intel.c | 187 +++++++++++++++++++++++++++-----------------------
|
|
1 file changed, 101 insertions(+), 86 deletions(-)
|
|
|
|
diff --git a/super-intel.c b/super-intel.c
|
|
index 36171107..5bd70356 100644
|
|
--- a/super-intel.c
|
|
+++ b/super-intel.c
|
|
@@ -11643,6 +11643,102 @@ static void imsm_update_metadata_locally(struct supertype *st,
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * imsm_analyze_expand() - check expand properties and calculate new size.
|
|
+ * @st: imsm supertype.
|
|
+ * @geo: new geometry params.
|
|
+ * @array: array info.
|
|
+ * @direction: reshape direction.
|
|
+ *
|
|
+ * Obtain free space after the &array and verify if expand to requested size is
|
|
+ * possible. If geo->size is set to %MAX_SIZE, assume that max free size is
|
|
+ * requested.
|
|
+ *
|
|
+ * Return:
|
|
+ * On success %IMSM_STATUS_OK is returned, geo->size and geo->raid_disks are
|
|
+ * updated.
|
|
+ * On error, %IMSM_STATUS_ERROR is returned.
|
|
+ */
|
|
+static imsm_status_t imsm_analyze_expand(struct supertype *st,
|
|
+ struct geo_params *geo,
|
|
+ struct mdinfo *array,
|
|
+ int direction)
|
|
+{
|
|
+ struct intel_super *super = st->sb;
|
|
+ struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
|
|
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
|
|
+ int data_disks = imsm_num_data_members(map);
|
|
+
|
|
+ unsigned long long current_size;
|
|
+ unsigned long long free_size;
|
|
+ unsigned long long new_size;
|
|
+ unsigned long long max_size;
|
|
+
|
|
+ const int chunk_kib = geo->chunksize / 1024;
|
|
+ imsm_status_t rv;
|
|
+
|
|
+ if (direction == ROLLBACK_METADATA_CHANGES) {
|
|
+ /**
|
|
+ * Accept size for rollback only.
|
|
+ */
|
|
+ new_size = geo->size * 2;
|
|
+ goto success;
|
|
+ }
|
|
+
|
|
+ if (super->current_vol + 1 != super->anchor->num_raid_devs) {
|
|
+ pr_err("imsm: The last volume in container can be expanded only (%i/%s).\n",
|
|
+ super->current_vol, st->devnm);
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
+ if (data_disks == 0) {
|
|
+ pr_err("imsm: Cannot retrieve data disks.\n");
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+ current_size = array->custom_array_size / data_disks;
|
|
+
|
|
+ rv = imsm_get_free_size(super, dev->vol.map->num_members, 0, chunk_kib, &free_size);
|
|
+ if (rv != IMSM_STATUS_OK) {
|
|
+ pr_err("imsm: Cannot find free space for expand.\n");
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+ max_size = round_member_size_to_mb(free_size + current_size);
|
|
+
|
|
+ if (geo->size == MAX_SIZE)
|
|
+ new_size = max_size;
|
|
+ else
|
|
+ new_size = round_member_size_to_mb(geo->size * 2);
|
|
+
|
|
+ if (new_size == 0) {
|
|
+ pr_err("imsm: Rounded requested size is 0.\n");
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
+ if (new_size > max_size) {
|
|
+ pr_err("imsm: Rounded requested size (%llu) is larger than free space available (%llu).\n",
|
|
+ new_size, max_size);
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
+ if (new_size == current_size) {
|
|
+ pr_err("imsm: Rounded requested size (%llu) is same as current size (%llu).\n",
|
|
+ new_size, current_size);
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
+ if (new_size < current_size) {
|
|
+ pr_err("imsm: Size reduction is not supported, rounded requested size (%llu) is smaller than current (%llu).\n",
|
|
+ new_size, current_size);
|
|
+ return IMSM_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
+success:
|
|
+ dprintf("imsm: New size per member is %llu.\n", new_size);
|
|
+ geo->size = data_disks * new_size;
|
|
+ geo->raid_disks = dev->vol.map->num_members;
|
|
+ return IMSM_STATUS_OK;
|
|
+}
|
|
+
|
|
/***************************************************************************
|
|
* Function: imsm_analyze_change
|
|
* Description: Function analyze change for single volume
|
|
@@ -11663,13 +11759,6 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
|
int devNumChange = 0;
|
|
/* imsm compatible layout value for array geometry verification */
|
|
int imsm_layout = -1;
|
|
- int data_disks;
|
|
- struct imsm_dev *dev;
|
|
- struct imsm_map *map;
|
|
- struct intel_super *super;
|
|
- unsigned long long current_size;
|
|
- unsigned long long free_size;
|
|
- unsigned long long max_size;
|
|
imsm_status_t rv;
|
|
|
|
getinfo_super_imsm_volume(st, &info, NULL);
|
|
@@ -11752,94 +11841,20 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
|
geo->chunksize = info.array.chunk_size;
|
|
}
|
|
|
|
- chunk = geo->chunksize / 1024;
|
|
-
|
|
- super = st->sb;
|
|
- dev = get_imsm_dev(super, super->current_vol);
|
|
- map = get_imsm_map(dev, MAP_0);
|
|
- data_disks = imsm_num_data_members(map);
|
|
- /* compute current size per disk member
|
|
- */
|
|
- current_size = info.custom_array_size / data_disks;
|
|
-
|
|
- if (geo->size > 0 && geo->size != MAX_SIZE) {
|
|
- /* align component size
|
|
- */
|
|
- geo->size = imsm_component_size_alignment_check(
|
|
- get_imsm_raid_level(dev->vol.map),
|
|
- chunk * 1024, super->sector_size,
|
|
- geo->size * 2);
|
|
- if (geo->size == 0) {
|
|
- pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is 0).\n",
|
|
- current_size);
|
|
- goto analyse_change_exit;
|
|
- }
|
|
- }
|
|
-
|
|
- if (current_size != geo->size && geo->size > 0) {
|
|
+ if (geo->size > 0) {
|
|
if (change != -1) {
|
|
pr_err("Error. Size change should be the only one at a time.\n");
|
|
change = -1;
|
|
goto analyse_change_exit;
|
|
}
|
|
- if ((super->current_vol + 1) != super->anchor->num_raid_devs) {
|
|
- pr_err("Error. The last volume in container can be expanded only (%i/%s).\n",
|
|
- super->current_vol, st->devnm);
|
|
- goto analyse_change_exit;
|
|
- }
|
|
- /* check the maximum available size
|
|
- */
|
|
- rv = imsm_get_free_size(super, dev->vol.map->num_members,
|
|
- 0, chunk, &free_size);
|
|
|
|
+ rv = imsm_analyze_expand(st, geo, &info, direction);
|
|
if (rv != IMSM_STATUS_OK)
|
|
- /* Cannot find maximum available space
|
|
- */
|
|
- max_size = 0;
|
|
- else {
|
|
- max_size = free_size + current_size;
|
|
- /* align component size
|
|
- */
|
|
- max_size = imsm_component_size_alignment_check(
|
|
- get_imsm_raid_level(dev->vol.map),
|
|
- chunk * 1024, super->sector_size,
|
|
- max_size);
|
|
- }
|
|
- if (geo->size == MAX_SIZE) {
|
|
- /* requested size change to the maximum available size
|
|
- */
|
|
- if (max_size == 0) {
|
|
- pr_err("Error. Cannot find maximum available space.\n");
|
|
- change = -1;
|
|
- goto analyse_change_exit;
|
|
- } else
|
|
- geo->size = max_size;
|
|
- }
|
|
-
|
|
- if (direction == ROLLBACK_METADATA_CHANGES) {
|
|
- /* accept size for rollback only
|
|
- */
|
|
- } else {
|
|
- /* round size due to metadata compatibility
|
|
- */
|
|
- geo->size = round_member_size_to_mb(geo->size);
|
|
- dprintf("Prepare update for size change to %llu\n",
|
|
- geo->size );
|
|
- if (current_size >= geo->size) {
|
|
- pr_err("Error. Size expansion is supported only (current size is %llu, requested size /rounded/ is %llu).\n",
|
|
- current_size, geo->size);
|
|
- goto analyse_change_exit;
|
|
- }
|
|
- if (max_size && geo->size > max_size) {
|
|
- pr_err("Error. Requested size is larger than maximum available size (maximum available size is %llu, requested size /rounded/ is %llu).\n",
|
|
- max_size, geo->size);
|
|
- goto analyse_change_exit;
|
|
- }
|
|
- }
|
|
- geo->size *= data_disks;
|
|
- geo->raid_disks = dev->vol.map->num_members;
|
|
+ goto analyse_change_exit;
|
|
change = CH_ARRAY_SIZE;
|
|
}
|
|
+
|
|
+ chunk = geo->chunksize / 1024;
|
|
if (!validate_geometry_imsm(st,
|
|
geo->level,
|
|
imsm_layout,
|
|
--
|
|
2.40.1
|
|
|