2020-12-09 21:09:06 +00:00
|
|
|
|
From 895ffd992954069e4ea67efb8a85bb0fd72c3707 Mon Sep 17 00:00:00 2001
|
|
|
|
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
|
|
|
|
Date: Tue, 24 Nov 2020 14:15:15 +0100
|
|
|
|
|
Subject: [PATCH 10/17] imsm: update num_data_stripes according to dev_size
|
2021-01-05 21:14:09 +00:00
|
|
|
|
Git-commit: 895ffd992954069e4ea67efb8a85bb0fd72c3707
|
|
|
|
|
References: jsc#SLE-13700
|
2020-12-09 21:09:06 +00:00
|
|
|
|
|
|
|
|
|
If array was created in UEFI there is possibility that
|
|
|
|
|
member size is not rounded to 1MB. After any size reconfiguration
|
|
|
|
|
it will be rounded down to 1MB per each member but the old
|
|
|
|
|
component size will remain in metadata.
|
|
|
|
|
During reshape old array size is calculated from component size because
|
|
|
|
|
dev_size is not a part of map and is bumped to new value quickly.
|
|
|
|
|
It may result in size mismatch if array is assembled during reshape.
|
|
|
|
|
|
|
|
|
|
If difference in calculated size and dev_size is observed try to fix it.
|
|
|
|
|
num_data_stripes value can be safety updated to smaller value if array
|
|
|
|
|
doesn't occuppy whole reserved component space.
|
|
|
|
|
|
|
|
|
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
2021-01-05 21:14:09 +00:00
|
|
|
|
Signed-off-by: Coly Li <colyli@suse.de>
|
|
|
|
|
|
2020-12-09 21:09:06 +00:00
|
|
|
|
---
|
|
|
|
|
super-intel.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++----
|
|
|
|
|
1 file changed, 78 insertions(+), 6 deletions(-)
|
|
|
|
|
|
|
|
|
|
diff --git a/super-intel.c b/super-intel.c
|
|
|
|
|
index 3a73d2b..9562064 100644
|
|
|
|
|
--- a/super-intel.c
|
|
|
|
|
+++ b/super-intel.c
|
|
|
|
|
@@ -3453,7 +3453,6 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
|
|
|
|
|
__u64 blocks_per_unit = blocks_per_migr_unit(super,
|
|
|
|
|
dev);
|
|
|
|
|
__u64 units = current_migr_unit(migr_rec);
|
|
|
|
|
- unsigned long long array_blocks;
|
|
|
|
|
int used_disks;
|
|
|
|
|
|
|
|
|
|
if (__le32_to_cpu(migr_rec->ascending_migr) &&
|
|
|
|
|
@@ -3472,12 +3471,8 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info,
|
|
|
|
|
|
|
|
|
|
used_disks = imsm_num_data_members(prev_map);
|
|
|
|
|
if (used_disks > 0) {
|
|
|
|
|
- array_blocks = per_dev_array_size(map) *
|
|
|
|
|
+ info->custom_array_size = per_dev_array_size(map) *
|
|
|
|
|
used_disks;
|
|
|
|
|
- info->custom_array_size =
|
|
|
|
|
- round_size_to_mb(array_blocks,
|
|
|
|
|
- used_disks);
|
|
|
|
|
-
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case MIGR_VERIFY:
|
|
|
|
|
@@ -11682,6 +11677,68 @@ int imsm_takeover(struct supertype *st, struct geo_params *geo)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* Flush size update if size calculated by num_data_stripes is higher than
|
|
|
|
|
+ * imsm_dev_size to eliminate differences during reshape.
|
|
|
|
|
+ * Mdmon will recalculate them correctly.
|
|
|
|
|
+ * If subarray index is not set then check whole container.
|
|
|
|
|
+ * Returns:
|
|
|
|
|
+ * 0 - no error occurred
|
|
|
|
|
+ * 1 - error detected
|
|
|
|
|
+ */
|
|
|
|
|
+static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index)
|
|
|
|
|
+{
|
|
|
|
|
+ struct intel_super *super = st->sb;
|
|
|
|
|
+ int tmp = super->current_vol;
|
|
|
|
|
+ int ret_val = 1;
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < super->anchor->num_raid_devs; i++) {
|
|
|
|
|
+ if (subarray_index >= 0 && i != subarray_index)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ super->current_vol = i;
|
|
|
|
|
+ struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
|
|
|
|
|
+ struct imsm_map *map = get_imsm_map(dev, MAP_0);
|
|
|
|
|
+ unsigned int disc_count = imsm_num_data_members(map);
|
|
|
|
|
+ struct geo_params geo;
|
|
|
|
|
+ struct imsm_update_size_change *update;
|
|
|
|
|
+ unsigned long long calc_size = per_dev_array_size(map) * disc_count;
|
|
|
|
|
+ unsigned long long d_size = imsm_dev_size(dev);
|
|
|
|
|
+ int u_size;
|
|
|
|
|
+
|
|
|
|
|
+ if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ /* There is a difference, verify that imsm_dev_size is
|
|
|
|
|
+ * rounded correctly and push update.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (d_size != round_size_to_mb(d_size, disc_count)) {
|
|
|
|
|
+ dprintf("imsm: Size of volume %d is not rounded correctly\n",
|
|
|
|
|
+ i);
|
|
|
|
|
+ goto exit;
|
|
|
|
|
+ }
|
|
|
|
|
+ memset(&geo, 0, sizeof(struct geo_params));
|
|
|
|
|
+ geo.size = d_size;
|
|
|
|
|
+ u_size = imsm_create_metadata_update_for_size_change(st, &geo,
|
|
|
|
|
+ &update);
|
|
|
|
|
+ if (u_size < 1) {
|
|
|
|
|
+ dprintf("imsm: Cannot prepare size change update\n");
|
|
|
|
|
+ goto exit;
|
|
|
|
|
+ }
|
|
|
|
|
+ imsm_update_metadata_locally(st, update, u_size);
|
|
|
|
|
+ if (st->update_tail) {
|
|
|
|
|
+ append_metadata_update(st, update, u_size);
|
|
|
|
|
+ flush_metadata_updates(st);
|
|
|
|
|
+ st->update_tail = &st->updates;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ imsm_sync_metadata(st);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ ret_val = 0;
|
|
|
|
|
+exit:
|
|
|
|
|
+ super->current_vol = tmp;
|
|
|
|
|
+ return ret_val;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static int imsm_reshape_super(struct supertype *st, unsigned long long size,
|
|
|
|
|
int level,
|
|
|
|
|
int layout, int chunksize, int raid_disks,
|
|
|
|
|
@@ -11718,6 +11775,11 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
|
|
|
|
|
struct imsm_update_reshape *u = NULL;
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
+ if (imsm_fix_size_mismatch(st, -1)) {
|
|
|
|
|
+ dprintf("imsm: Cannot fix size mismatch\n");
|
|
|
|
|
+ goto exit_imsm_reshape_super;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
len = imsm_create_metadata_update_for_reshape(
|
|
|
|
|
st, &geo, old_raid_disks, &u);
|
|
|
|
|
|
|
|
|
|
@@ -12020,6 +12082,7 @@ static int imsm_manage_reshape(
|
|
|
|
|
unsigned long long start_buf_shift; /* [bytes] */
|
|
|
|
|
int degraded = 0;
|
|
|
|
|
int source_layout = 0;
|
|
|
|
|
+ int subarray_index = -1;
|
|
|
|
|
|
|
|
|
|
if (!sra)
|
|
|
|
|
return ret_val;
|
|
|
|
|
@@ -12033,6 +12096,7 @@ static int imsm_manage_reshape(
|
|
|
|
|
dv->dev->vol.migr_state == 1) {
|
|
|
|
|
dev = dv->dev;
|
|
|
|
|
migr_vol_qan++;
|
|
|
|
|
+ subarray_index = dv->index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Only one volume can migrate at the same time */
|
|
|
|
|
@@ -12217,6 +12281,14 @@ static int imsm_manage_reshape(
|
|
|
|
|
|
|
|
|
|
/* return '1' if done */
|
|
|
|
|
ret_val = 1;
|
|
|
|
|
+
|
|
|
|
|
+ /* After the reshape eliminate size mismatch in metadata.
|
|
|
|
|
+ * Don't update md/component_size here, volume hasn't
|
|
|
|
|
+ * to take whole space. It is allowed by kernel.
|
|
|
|
|
+ * md/component_size will be set propoperly after next assembly.
|
|
|
|
|
+ */
|
|
|
|
|
+ imsm_fix_size_mismatch(st, subarray_index);
|
|
|
|
|
+
|
|
|
|
|
abort:
|
|
|
|
|
free(buf);
|
|
|
|
|
/* See Grow.c: abort_reshape() for further explanation */
|
|
|
|
|
--
|
|
|
|
|
2.26.2
|
|
|
|
|
|