parent
8cb1d79ccd
commit
d621d90f47
@ -0,0 +1,33 @@
|
||||
From cf1577bf54afe76b77ecaa62df25901739ca8ae9 Mon Sep 17 00:00:00 2001
|
||||
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
|
||||
Date: Wed, 5 Jul 2023 16:34:56 +0200
|
||||
Subject: [PATCH 126/165] imsm: Fix possible segfault in check_no_platform()
|
||||
|
||||
conf_line() may return NULL, which is not handled and might cause
|
||||
segfault.
|
||||
|
||||
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
super-intel.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index ae0f4a8c..4ef33d31 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -650,6 +650,11 @@ static int check_no_platform(void)
|
||||
char *l = conf_line(fp);
|
||||
char *w = l;
|
||||
|
||||
+ if (l == NULL) {
|
||||
+ fclose(fp);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
do {
|
||||
if (strcmp(w, search) == 0)
|
||||
no_platform = 1;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,105 @@
|
||||
From 9bc426fa1f236b8cad518431574a54fc60718739 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Mon, 29 May 2023 15:52:33 +0200
|
||||
Subject: [PATCH 127/165] imsm: move sum_extents calculations to
|
||||
merge_extents()
|
||||
|
||||
This logic is only used by merge_extents() code, there is no need to pass
|
||||
it as parameter. Move it up. Add proper description.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
super-intel.c | 37 +++++++++++++++++++------------------
|
||||
1 file changed, 19 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 4ef33d31..26b20313 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -6882,21 +6882,31 @@ static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
|
||||
return end - base_start;
|
||||
}
|
||||
|
||||
-static unsigned long long merge_extents(struct intel_super *super, int sum_extents)
|
||||
+/** merge_extents() - analyze extents and get max common free size.
|
||||
+ * @super: Intel metadata, not NULL.
|
||||
+ *
|
||||
+ * Build a composite disk with all known extents and generate a new maxsize
|
||||
+ * given the "all disks in an array must share a common start offset"
|
||||
+ * constraint.
|
||||
+ *
|
||||
+ * Return: Max free space or 0 on failure.
|
||||
+ */
|
||||
+static unsigned long long merge_extents(struct intel_super *super)
|
||||
{
|
||||
- /* build a composite disk with all known extents and generate a new
|
||||
- * 'maxsize' given the "all disks in an array must share a common start
|
||||
- * offset" constraint
|
||||
- */
|
||||
- struct extent *e = xcalloc(sum_extents, sizeof(*e));
|
||||
+ struct extent *e;
|
||||
struct dl *dl;
|
||||
int i, j;
|
||||
- int start_extent;
|
||||
+ int start_extent, sum_extents = 0;
|
||||
unsigned long long pos;
|
||||
unsigned long long start = 0;
|
||||
unsigned long long maxsize;
|
||||
unsigned long reserve;
|
||||
|
||||
+ for (dl = super->disks; dl; dl = dl->next)
|
||||
+ if (dl->e)
|
||||
+ sum_extents += dl->extent_cnt;
|
||||
+ e = xcalloc(sum_extents, sizeof(struct extent));
|
||||
+
|
||||
/* coalesce and sort all extents. also, check to see if we need to
|
||||
* reserve space between member arrays
|
||||
*/
|
||||
@@ -7555,13 +7565,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- /* count total number of extents for merge */
|
||||
- i = 0;
|
||||
- for (dl = super->disks; dl; dl = dl->next)
|
||||
- if (dl->e)
|
||||
- i += dl->extent_cnt;
|
||||
-
|
||||
- maxsize = merge_extents(super, i);
|
||||
+ maxsize = merge_extents(super);
|
||||
|
||||
if (mpb->num_raid_devs > 0 && size && size != maxsize)
|
||||
pr_err("attempting to create a second volume with size less then remaining space.\n");
|
||||
@@ -7615,7 +7619,6 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
struct dl *dl;
|
||||
int i;
|
||||
- int extent_cnt;
|
||||
struct extent *e;
|
||||
unsigned long long maxsize;
|
||||
unsigned long long minsize;
|
||||
@@ -7624,7 +7627,6 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
|
||||
/* find the largest common start free region of the possible disks */
|
||||
used = 0;
|
||||
- extent_cnt = 0;
|
||||
cnt = 0;
|
||||
for (dl = super->disks; dl; dl = dl->next) {
|
||||
dl->raiddisk = -1;
|
||||
@@ -7645,11 +7647,10 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
;
|
||||
dl->e = e;
|
||||
dl->extent_cnt = i;
|
||||
- extent_cnt += i;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
- maxsize = merge_extents(super, extent_cnt);
|
||||
+ maxsize = merge_extents(super);
|
||||
minsize = size;
|
||||
if (size == 0)
|
||||
/* chunk is in K */
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,72 @@
|
||||
From 5f027b9357c011ca0421400e258a777d97f18d17 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Mon, 29 May 2023 15:52:34 +0200
|
||||
Subject: [PATCH 128/165] imsm: imsm_get_free_size() refactor.
|
||||
|
||||
Move minsize calculations up. Add error message if free size is too small.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
super-intel.c | 27 ++++++++++++++-------------
|
||||
1 file changed, 14 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 26b20313..16a30ba7 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -7600,7 +7600,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
|
||||
* @super: &intel_super pointer, not NULL.
|
||||
* @raiddisks: number of raid disks.
|
||||
* @size: requested size, could be 0 (means max size).
|
||||
- * @chunk: requested chunk.
|
||||
+ * @chunk: requested chunk size in KiB.
|
||||
* @freesize: pointer for returned size value.
|
||||
*
|
||||
* Return: &IMSM_STATUS_OK or &IMSM_STATUS_ERROR.
|
||||
@@ -7620,14 +7620,15 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
struct dl *dl;
|
||||
int i;
|
||||
struct extent *e;
|
||||
+ int cnt = 0;
|
||||
+ int used = 0;
|
||||
unsigned long long maxsize;
|
||||
- unsigned long long minsize;
|
||||
- int cnt;
|
||||
- int used;
|
||||
+ unsigned long long minsize = size;
|
||||
+
|
||||
+ if (minsize == 0)
|
||||
+ minsize = chunk * 2;
|
||||
|
||||
/* find the largest common start free region of the possible disks */
|
||||
- used = 0;
|
||||
- cnt = 0;
|
||||
for (dl = super->disks; dl; dl = dl->next) {
|
||||
dl->raiddisk = -1;
|
||||
|
||||
@@ -7651,14 +7652,14 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
}
|
||||
|
||||
maxsize = merge_extents(super);
|
||||
- minsize = size;
|
||||
- if (size == 0)
|
||||
- /* chunk is in K */
|
||||
- minsize = chunk * 2;
|
||||
+ if (maxsize < minsize) {
|
||||
+ pr_err("imsm: Free space is %llu but must be equal or larger than %llu.\n",
|
||||
+ maxsize, minsize);
|
||||
+ return IMSM_STATUS_ERROR;
|
||||
+ }
|
||||
|
||||
- if (cnt < raiddisks || (super->orom && used && used != raiddisks) ||
|
||||
- maxsize < minsize || maxsize == 0) {
|
||||
- pr_err("not enough devices with space to create array.\n");
|
||||
+ if (cnt < raiddisks || (super->orom && used && used != raiddisks)) {
|
||||
+ pr_err("imsm: Not enough devices with space to create array.\n");
|
||||
return IMSM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 78c8028b331c8e281554d43fde4d46e9cb4a227e Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Mon, 29 May 2023 15:52:35 +0200
|
||||
Subject: [PATCH 129/165] imsm: introduce round_member_size_to_mb()
|
||||
|
||||
Extract rounding logic to separate function.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
super-intel.c | 31 +++++++++++++++++++++----------
|
||||
1 file changed, 21 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 16a30ba7..36171107 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -1644,17 +1644,29 @@ static int is_journal(struct imsm_disk *disk)
|
||||
return (disk->status & JOURNAL_DISK) == JOURNAL_DISK;
|
||||
}
|
||||
|
||||
-/* round array size down to closest MB and ensure it splits evenly
|
||||
- * between members
|
||||
+/**
|
||||
+ * round_member_size_to_mb()- Round given size to closest MiB.
|
||||
+ * @size: size to round in sectors.
|
||||
*/
|
||||
-static unsigned long long round_size_to_mb(unsigned long long size, unsigned int
|
||||
- disk_count)
|
||||
+static inline unsigned long long round_member_size_to_mb(unsigned long long size)
|
||||
{
|
||||
- size /= disk_count;
|
||||
- size = (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
|
||||
- size *= disk_count;
|
||||
+ return (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
|
||||
+}
|
||||
|
||||
- return size;
|
||||
+/**
|
||||
+ * round_size_to_mb()- Round given size.
|
||||
+ * @array_size: size to round in sectors.
|
||||
+ * @disk_count: count of data members.
|
||||
+ *
|
||||
+ * Get size per each data member and round it to closest MiB to ensure that data
|
||||
+ * splits evenly between members.
|
||||
+ *
|
||||
+ * Return: Array size, rounded down.
|
||||
+ */
|
||||
+static inline unsigned long long round_size_to_mb(unsigned long long array_size,
|
||||
+ unsigned int disk_count)
|
||||
+{
|
||||
+ return round_member_size_to_mb(array_size / disk_count) * disk_count;
|
||||
}
|
||||
|
||||
static int able_to_resync(int raid_level, int missing_disks)
|
||||
@@ -11810,8 +11822,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
|
||||
} else {
|
||||
/* round size due to metadata compatibility
|
||||
*/
|
||||
- geo->size = (geo->size >> SECT_PER_MB_SHIFT)
|
||||
- << SECT_PER_MB_SHIFT;
|
||||
+ 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) {
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,238 @@
|
||||
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
|
||||
|
@ -0,0 +1,214 @@
|
||||
From aa19fdd45b2ba474f6a51a6d4b8f3c44ef19dafd Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Mon, 29 May 2023 15:52:37 +0200
|
||||
Subject: [PATCH 131/165] imsm: return free space after volume for expand
|
||||
|
||||
merge_extends() routine searches for the biggest free space. For expand,
|
||||
it works only in standard cases where the last volume is expanded and
|
||||
the free space is determined after the last volume.
|
||||
Add volume index to extent struct and use that do determine size after
|
||||
super->current_vol during expand.
|
||||
|
||||
Limitation to last volume is no longer needed. It unblocks scenarios
|
||||
where kill-subarray is used to remove first volume and later it is
|
||||
recreated (now it is the second volume, even if it is placed before
|
||||
existing one).
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
super-intel.c | 71 +++++++++++++++++++++++++++------------------------
|
||||
1 file changed, 37 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 5bd70356..e249d925 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -499,8 +499,15 @@ struct intel_disk {
|
||||
struct intel_disk *next;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * struct extent - reserved space details.
|
||||
+ * @start: start offset.
|
||||
+ * @size: size of reservation, set to 0 for metadata reservation.
|
||||
+ * @vol: index of the volume, meaningful if &size is set.
|
||||
+ */
|
||||
struct extent {
|
||||
unsigned long long start, size;
|
||||
+ int vol;
|
||||
};
|
||||
|
||||
/* definitions of reshape process types */
|
||||
@@ -1539,9 +1546,10 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
|
||||
int get_minimal_reservation)
|
||||
{
|
||||
/* find a list of used extents on the given physical device */
|
||||
- struct extent *rv, *e;
|
||||
- int i;
|
||||
int memberships = count_memberships(dl, super);
|
||||
+ struct extent *rv = xcalloc(memberships + 1, sizeof(struct extent));
|
||||
+ struct extent *e = rv;
|
||||
+ int i;
|
||||
__u32 reservation;
|
||||
|
||||
/* trim the reserved area for spares, so they can join any array
|
||||
@@ -1553,9 +1561,6 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
|
||||
else
|
||||
reservation = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
|
||||
|
||||
- rv = xcalloc(sizeof(struct extent), (memberships + 1));
|
||||
- e = rv;
|
||||
-
|
||||
for (i = 0; i < super->anchor->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
struct imsm_map *map = get_imsm_map(dev, MAP_0);
|
||||
@@ -1563,6 +1568,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
|
||||
if (get_imsm_disk_slot(map, dl->index) >= 0) {
|
||||
e->start = pba_of_lba0(map);
|
||||
e->size = per_dev_array_size(map);
|
||||
+ e->vol = i;
|
||||
e++;
|
||||
}
|
||||
}
|
||||
@@ -6894,24 +6900,26 @@ static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
|
||||
return end - base_start;
|
||||
}
|
||||
|
||||
-/** merge_extents() - analyze extents and get max common free size.
|
||||
+/** merge_extents() - analyze extents and get free size.
|
||||
* @super: Intel metadata, not NULL.
|
||||
+ * @expanding: if set, we are expanding &super->current_vol.
|
||||
*
|
||||
- * Build a composite disk with all known extents and generate a new maxsize
|
||||
- * given the "all disks in an array must share a common start offset"
|
||||
- * constraint.
|
||||
+ * Build a composite disk with all known extents and generate a size given the
|
||||
+ * "all disks in an array must share a common start offset" constraint.
|
||||
+ * If a volume is expanded, then return free space after the volume.
|
||||
*
|
||||
- * Return: Max free space or 0 on failure.
|
||||
+ * Return: Free space or 0 on failure.
|
||||
*/
|
||||
-static unsigned long long merge_extents(struct intel_super *super)
|
||||
+static unsigned long long merge_extents(struct intel_super *super, const bool expanding)
|
||||
{
|
||||
struct extent *e;
|
||||
struct dl *dl;
|
||||
- int i, j;
|
||||
- int start_extent, sum_extents = 0;
|
||||
- unsigned long long pos;
|
||||
+ int i, j, pos_vol_idx = -1;
|
||||
+ int extent_idx = 0;
|
||||
+ int sum_extents = 0;
|
||||
+ unsigned long long pos = 0;
|
||||
unsigned long long start = 0;
|
||||
- unsigned long long maxsize;
|
||||
+ unsigned long long maxsize = 0;
|
||||
unsigned long reserve;
|
||||
|
||||
for (dl = super->disks; dl; dl = dl->next)
|
||||
@@ -6936,26 +6944,26 @@ static unsigned long long merge_extents(struct intel_super *super)
|
||||
j = 0;
|
||||
while (i < sum_extents) {
|
||||
e[j].start = e[i].start;
|
||||
+ e[j].vol = e[i].vol;
|
||||
e[j].size = find_size(e, &i, sum_extents);
|
||||
j++;
|
||||
if (e[j-1].size == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
- pos = 0;
|
||||
- maxsize = 0;
|
||||
- start_extent = 0;
|
||||
i = 0;
|
||||
do {
|
||||
- unsigned long long esize;
|
||||
+ unsigned long long esize = e[i].start - pos;
|
||||
|
||||
- esize = e[i].start - pos;
|
||||
- if (esize >= maxsize) {
|
||||
+ if (expanding ? pos_vol_idx == super->current_vol : esize >= maxsize) {
|
||||
maxsize = esize;
|
||||
start = pos;
|
||||
- start_extent = i;
|
||||
+ extent_idx = i;
|
||||
}
|
||||
+
|
||||
pos = e[i].start + e[i].size;
|
||||
+ pos_vol_idx = e[i].vol;
|
||||
+
|
||||
i++;
|
||||
} while (e[i-1].size);
|
||||
free(e);
|
||||
@@ -6966,7 +6974,7 @@ static unsigned long long merge_extents(struct intel_super *super)
|
||||
/* FIXME assumes volume at offset 0 is the first volume in a
|
||||
* container
|
||||
*/
|
||||
- if (start_extent > 0)
|
||||
+ if (extent_idx > 0)
|
||||
reserve = IMSM_RESERVED_SECTORS; /* gap between raid regions */
|
||||
else
|
||||
reserve = 0;
|
||||
@@ -7577,7 +7585,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- maxsize = merge_extents(super);
|
||||
+ maxsize = merge_extents(super, false);
|
||||
|
||||
if (mpb->num_raid_devs > 0 && size && size != maxsize)
|
||||
pr_err("attempting to create a second volume with size less then remaining space.\n");
|
||||
@@ -7626,7 +7634,8 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
const int raiddisks,
|
||||
unsigned long long size,
|
||||
const int chunk,
|
||||
- unsigned long long *freesize)
|
||||
+ unsigned long long *freesize,
|
||||
+ bool expanding)
|
||||
{
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
struct dl *dl;
|
||||
@@ -7663,7 +7672,7 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
|
||||
cnt++;
|
||||
}
|
||||
|
||||
- maxsize = merge_extents(super);
|
||||
+ maxsize = merge_extents(super, expanding);
|
||||
if (maxsize < minsize) {
|
||||
pr_err("imsm: Free space is %llu but must be equal or larger than %llu.\n",
|
||||
maxsize, minsize);
|
||||
@@ -7721,7 +7730,7 @@ static imsm_status_t autolayout_imsm(struct intel_super *super,
|
||||
int vol_cnt = super->anchor->num_raid_devs;
|
||||
imsm_status_t rv;
|
||||
|
||||
- rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize);
|
||||
+ rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize, false);
|
||||
if (rv != IMSM_STATUS_OK)
|
||||
return IMSM_STATUS_ERROR;
|
||||
|
||||
@@ -11685,19 +11694,13 @@ static imsm_status_t imsm_analyze_expand(struct supertype *st,
|
||||
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);
|
||||
+ rv = imsm_get_free_size(super, dev->vol.map->num_members, 0, chunk_kib, &free_size, true);
|
||||
if (rv != IMSM_STATUS_OK) {
|
||||
pr_err("imsm: Cannot find free space for expand.\n");
|
||||
return IMSM_STATUS_ERROR;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,113 @@
|
||||
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
|
||||
|
@ -0,0 +1,124 @@
|
||||
From 21e622f214a38c048c5689158bc6314a91a46e40 Mon Sep 17 00:00:00 2001
|
||||
From: Blazej Kucman <blazej.kucman@intel.com>
|
||||
Date: Fri, 16 Jun 2023 21:45:55 +0200
|
||||
Subject: [PATCH 133/165] Add secure gethostname() wrapper
|
||||
|
||||
gethostname() func does not ensure null-terminated string
|
||||
if hostname is longer than buffer length.
|
||||
For security, a function s_gethostname() has been added
|
||||
to ensure that "\0" is added to the end of the buffer.
|
||||
Previously this had to be handled in each place
|
||||
of the gethostname() call.
|
||||
|
||||
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Monitor.c | 3 +--
|
||||
lib.c | 19 +++++++++++++++++++
|
||||
mapfile.c | 3 +--
|
||||
mdadm.c | 3 +--
|
||||
mdadm.h | 1 +
|
||||
super-ddf.c | 3 +--
|
||||
6 files changed, 24 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/Monitor.c b/Monitor.c
|
||||
index 66175968..e74a0558 100644
|
||||
--- a/Monitor.c
|
||||
+++ b/Monitor.c
|
||||
@@ -222,11 +222,10 @@ int Monitor(struct mddev_dev *devlist,
|
||||
info.dosyslog = dosyslog;
|
||||
info.test = c->test;
|
||||
|
||||
- if (gethostname(info.hostname, sizeof(info.hostname)) != 0) {
|
||||
+ if (s_gethostname(info.hostname, sizeof(info.hostname)) != 0) {
|
||||
pr_err("Cannot get hostname.\n");
|
||||
return 1;
|
||||
}
|
||||
- info.hostname[sizeof(info.hostname) - 1] = '\0';
|
||||
|
||||
if (share){
|
||||
if (check_one_sharer(c->scan) == 2)
|
||||
diff --git a/lib.c b/lib.c
|
||||
index fe5c8d2c..8a4b48e0 100644
|
||||
--- a/lib.c
|
||||
+++ b/lib.c
|
||||
@@ -585,3 +585,22 @@ int parse_num(int *dest, const char *num)
|
||||
*dest = temp;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+/**
|
||||
+ * s_gethostname() - secure get hostname. Assure null-terminated string.
|
||||
+ *
|
||||
+ * @buf: buffer for hostname.
|
||||
+ * @buf_len: buffer length.
|
||||
+ *
|
||||
+ * Return: gethostname() result.
|
||||
+ */
|
||||
+int s_gethostname(char *buf, int buf_len)
|
||||
+{
|
||||
+ assert(buf);
|
||||
+
|
||||
+ int ret = gethostname(buf, buf_len);
|
||||
+
|
||||
+ buf[buf_len - 1] = 0;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/mapfile.c b/mapfile.c
|
||||
index 34fea179..f1f3ee2c 100644
|
||||
--- a/mapfile.c
|
||||
+++ b/mapfile.c
|
||||
@@ -363,8 +363,7 @@ void RebuildMap(void)
|
||||
char *homehost = conf_get_homehost(&require_homehost);
|
||||
|
||||
if (homehost == NULL || strcmp(homehost, "<system>")==0) {
|
||||
- if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
|
||||
- sys_hostname[sizeof(sys_hostname)-1] = 0;
|
||||
+ if (s_gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
|
||||
homehost = sys_hostname;
|
||||
}
|
||||
}
|
||||
diff --git a/mdadm.c b/mdadm.c
|
||||
index 076b45e0..e32598cb 100644
|
||||
--- a/mdadm.c
|
||||
+++ b/mdadm.c
|
||||
@@ -1340,8 +1340,7 @@ int main(int argc, char *argv[])
|
||||
if (c.homehost == NULL && c.require_homehost)
|
||||
c.homehost = conf_get_homehost(&c.require_homehost);
|
||||
if (c.homehost == NULL || strcasecmp(c.homehost, "<system>") == 0) {
|
||||
- if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
|
||||
- sys_hostname[sizeof(sys_hostname)-1] = 0;
|
||||
+ if (s_gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
|
||||
c.homehost = sys_hostname;
|
||||
}
|
||||
}
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index 83f2cf7f..f0ceeb78 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -1805,6 +1805,7 @@ extern void set_dlm_hooks(void);
|
||||
extern void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt);
|
||||
extern bool is_directory(const char *path);
|
||||
extern bool is_file(const char *path);
|
||||
+extern int s_gethostname(char *buf, int buf_len);
|
||||
|
||||
#define _ROUND_UP(val, base) (((val) + (base) - 1) & ~(base - 1))
|
||||
#define ROUND_UP(val, base) _ROUND_UP(val, (typeof(val))(base))
|
||||
diff --git a/super-ddf.c b/super-ddf.c
|
||||
index 7213284e..c5242654 100644
|
||||
--- a/super-ddf.c
|
||||
+++ b/super-ddf.c
|
||||
@@ -2364,8 +2364,7 @@ static int init_super_ddf(struct supertype *st,
|
||||
* Remaining 16 are serial number.... maybe a hostname would do?
|
||||
*/
|
||||
memcpy(ddf->controller.guid, T10, sizeof(T10));
|
||||
- gethostname(hostname, sizeof(hostname));
|
||||
- hostname[sizeof(hostname) - 1] = 0;
|
||||
+ s_gethostname(hostname, sizeof(hostname));
|
||||
hostlen = strlen(hostname);
|
||||
memcpy(ddf->controller.guid + 24 - hostlen, hostname, hostlen);
|
||||
for (i = strlen(T10) ; i+hostlen < 24; i++)
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 1ab341e5ce0cb01a1533a2c36e5b69eabf12bf95 Mon Sep 17 00:00:00 2001
|
||||
From: Xiao Ni <xni@redhat.com>
|
||||
Date: Fri, 25 Aug 2023 20:55:41 +0800
|
||||
Subject: [PATCH 134/165] mdadm: Stop mdcheck_continue timer when mdcheck_start
|
||||
service can finish check
|
||||
|
||||
mdcheck_continue is triggered by mdcheck_start timer. It's used to
|
||||
continue check action if the raid is too big and mdcheck_start
|
||||
service can't finish check action. If mdcheck start can finish check
|
||||
action, it doesn't need to mdcheck continue service anymore. So stop
|
||||
it when mdcheck start service can finish check action.
|
||||
|
||||
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
misc/mdcheck | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/misc/mdcheck b/misc/mdcheck
|
||||
index 700c3e25..f87999d3 100644
|
||||
--- a/misc/mdcheck
|
||||
+++ b/misc/mdcheck
|
||||
@@ -140,7 +140,13 @@ do
|
||||
echo $a > $fl
|
||||
any=yes
|
||||
done
|
||||
- if [ -z "$any" ]; then exit 0; fi
|
||||
+ # mdcheck_continue.timer is started by mdcheck_start.timer.
|
||||
+ # When the check action can be finished in mdcheck_start.service,
|
||||
+ # it doesn't need mdcheck_continue anymore.
|
||||
+ if [ -z "$any" ]; then
|
||||
+ systemctl stop mdcheck_continue.timer
|
||||
+ exit 0;
|
||||
+ fi
|
||||
sleep 120
|
||||
done
|
||||
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,90 @@
|
||||
From e9fb93af0f769d147a13e86ab4e5d0aeb935e9fc Mon Sep 17 00:00:00 2001
|
||||
From: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Date: Mon, 24 Apr 2023 16:06:34 +0800
|
||||
Subject: [PATCH 135/165] Fix memory leak in file Assemble
|
||||
|
||||
When we test mdadm with asan, we found some memory leaks in Assemble.c
|
||||
We fix these memory leaks based on code logic.
|
||||
|
||||
v2: Set st = NULL before jumping to loop
|
||||
|
||||
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
|
||||
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Assemble.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Assemble.c b/Assemble.c
|
||||
index 49804941..61e8cd17 100644
|
||||
--- a/Assemble.c
|
||||
+++ b/Assemble.c
|
||||
@@ -341,8 +341,10 @@ static int select_devices(struct mddev_dev *devlist,
|
||||
st->ss->free_super(st);
|
||||
dev_policy_free(pol);
|
||||
domain_free(domains);
|
||||
- if (tst)
|
||||
+ if (tst) {
|
||||
tst->ss->free_super(tst);
|
||||
+ free(tst);
|
||||
+ }
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -417,6 +419,7 @@ static int select_devices(struct mddev_dev *devlist,
|
||||
st->ss->free_super(st);
|
||||
dev_policy_free(pol);
|
||||
domain_free(domains);
|
||||
+ free(st);
|
||||
return -1;
|
||||
}
|
||||
if (c->verbose > 0)
|
||||
@@ -425,6 +428,8 @@ static int select_devices(struct mddev_dev *devlist,
|
||||
|
||||
/* make sure we finished the loop */
|
||||
tmpdev = NULL;
|
||||
+ free(st);
|
||||
+ st = NULL;
|
||||
goto loop;
|
||||
} else {
|
||||
content = *contentp;
|
||||
@@ -533,6 +538,7 @@ static int select_devices(struct mddev_dev *devlist,
|
||||
st->ss->free_super(st);
|
||||
dev_policy_free(pol);
|
||||
domain_free(domains);
|
||||
+ free(tst);
|
||||
return -1;
|
||||
}
|
||||
tmpdev->used = 1;
|
||||
@@ -546,8 +552,10 @@ static int select_devices(struct mddev_dev *devlist,
|
||||
}
|
||||
dev_policy_free(pol);
|
||||
pol = NULL;
|
||||
- if (tst)
|
||||
+ if (tst) {
|
||||
tst->ss->free_super(tst);
|
||||
+ free(tst);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Check if we found some imsm spares but no members */
|
||||
@@ -839,6 +847,7 @@ static int load_devices(struct devs *devices, char *devmap,
|
||||
close(mdfd);
|
||||
free(devices);
|
||||
free(devmap);
|
||||
+ free(best);
|
||||
*stp = st;
|
||||
return -1;
|
||||
}
|
||||
@@ -1950,6 +1959,7 @@ out:
|
||||
} else if (mdfd >= 0)
|
||||
close(mdfd);
|
||||
|
||||
+ free(best);
|
||||
/* '2' means 'OK, but not started yet' */
|
||||
if (rv == -1) {
|
||||
free(devices);
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,54 @@
|
||||
From 8fd0c565b09ba449418d7d604ceba66313246152 Mon Sep 17 00:00:00 2001
|
||||
From: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Date: Mon, 24 Apr 2023 16:06:35 +0800
|
||||
Subject: [PATCH 136/165] Fix memory leak in file Kill
|
||||
|
||||
When we test mdadm with asan, we found some memory leaks in Kill.c
|
||||
We fix these memory leaks based on code logic.
|
||||
|
||||
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
|
||||
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Kill.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Kill.c b/Kill.c
|
||||
index bfd0efdc..43c9abed 100644
|
||||
--- a/Kill.c
|
||||
+++ b/Kill.c
|
||||
@@ -41,6 +41,7 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl)
|
||||
* 4 - failed to find a superblock.
|
||||
*/
|
||||
|
||||
+ bool free_super = false;
|
||||
int fd, rv = 0;
|
||||
|
||||
if (force)
|
||||
@@ -52,8 +53,10 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl)
|
||||
dev);
|
||||
return 2;
|
||||
}
|
||||
- if (st == NULL)
|
||||
+ if (st == NULL) {
|
||||
st = guess_super(fd);
|
||||
+ free_super = true;
|
||||
+ }
|
||||
if (st == NULL || st->ss->init_super == NULL) {
|
||||
if (verbose >= 0)
|
||||
pr_err("Unrecognised md component device - %s\n", dev);
|
||||
@@ -77,6 +80,10 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl)
|
||||
rv = 0;
|
||||
}
|
||||
}
|
||||
+ if (free_super && st) {
|
||||
+ st->ss->free_super(st);
|
||||
+ free(st);
|
||||
+ }
|
||||
close(fd);
|
||||
return rv;
|
||||
}
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,74 @@
|
||||
From f6feb3fbb50f48c193e9e4d775a20aa20f7b47b3 Mon Sep 17 00:00:00 2001
|
||||
From: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Date: Mon, 24 Apr 2023 16:06:36 +0800
|
||||
Subject: [PATCH 137/165] Fix memory leak in file Manage
|
||||
|
||||
When we test mdadm with asan, we found some memory leaks in Manage.c
|
||||
We fix these memory leaks based on code logic.
|
||||
|
||||
v2: Fix free() of uninitialized 'tst' in abort path.
|
||||
|
||||
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
|
||||
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Manage.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Manage.c b/Manage.c
|
||||
index f54de7c6..f997b163 100644
|
||||
--- a/Manage.c
|
||||
+++ b/Manage.c
|
||||
@@ -222,6 +222,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
|
||||
if (verbose >= 0)
|
||||
pr_err("Cannot get exclusive access to %s:Perhaps a running process, mounted filesystem or active volume group?\n",
|
||||
devname);
|
||||
+ sysfs_free(mdi);
|
||||
return 1;
|
||||
}
|
||||
/* If this is an mdmon managed array, just write 'inactive'
|
||||
@@ -801,8 +802,14 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
|
||||
rdev, update, devname,
|
||||
verbose, array);
|
||||
dev_st->ss->free_super(dev_st);
|
||||
- if (rv)
|
||||
+ if (rv) {
|
||||
+ free(dev_st);
|
||||
return rv;
|
||||
+ }
|
||||
+ }
|
||||
+ if (dev_st) {
|
||||
+ dev_st->ss->free_super(dev_st);
|
||||
+ free(dev_st);
|
||||
}
|
||||
}
|
||||
if (dv->disposition == 'M') {
|
||||
@@ -1362,7 +1369,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||
unsigned long long array_size;
|
||||
struct mddev_dev *dv;
|
||||
int tfd = -1;
|
||||
- struct supertype *tst;
|
||||
+ struct supertype *tst = NULL;
|
||||
char *subarray = NULL;
|
||||
int sysfd = -1;
|
||||
int count = 0; /* number of actions taken */
|
||||
@@ -1699,6 +1706,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ free(tst);
|
||||
if (frozen > 0)
|
||||
sysfs_set_str(&info, NULL, "sync_action","idle");
|
||||
if (test && count == 0)
|
||||
@@ -1706,6 +1714,7 @@ int Manage_subdevs(char *devname, int fd,
|
||||
return 0;
|
||||
|
||||
abort:
|
||||
+ free(tst);
|
||||
if (frozen > 0)
|
||||
sysfs_set_str(&info, NULL, "sync_action","idle");
|
||||
return !test && busy ? 2 : 1;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,34 @@
|
||||
From e62a561ee8b7157a2390eab215dcef6240bd7b03 Mon Sep 17 00:00:00 2001
|
||||
From: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Date: Mon, 24 Apr 2023 16:06:37 +0800
|
||||
Subject: [PATCH 138/165] Fix memory leak in file mdadm
|
||||
|
||||
When we test mdadm with asan, we found some memory leaks in mdadm.c
|
||||
We fix these memory leaks based on code logic.
|
||||
|
||||
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
|
||||
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
|
||||
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
mdadm.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/mdadm.c b/mdadm.c
|
||||
index e32598cb..22d1c53b 100644
|
||||
--- a/mdadm.c
|
||||
+++ b/mdadm.c
|
||||
@@ -1708,6 +1708,10 @@ int main(int argc, char *argv[])
|
||||
autodetect();
|
||||
break;
|
||||
}
|
||||
+ if (ss) {
|
||||
+ ss->ss->free_super(ss);
|
||||
+ free(ss);
|
||||
+ }
|
||||
if (locked)
|
||||
cluster_release_dlmlock();
|
||||
close_fd(&mdfd);
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,116 @@
|
||||
From dd5ab40204b1d78ec3bdbcfd5a38a8ffb72bdb50 Mon Sep 17 00:00:00 2001
|
||||
From: Kinga Tanska <kinga.tanska@intel.com>
|
||||
Date: Thu, 11 May 2023 04:55:12 +0200
|
||||
Subject: [PATCH 139/165] Fix unsafe string functions
|
||||
|
||||
Add string length limitations where necessary to
|
||||
avoid buffer overflows.
|
||||
|
||||
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
mdmon.c | 6 +++---
|
||||
mdopen.c | 4 ++--
|
||||
platform-intel.c | 2 +-
|
||||
super-intel.c | 6 +++---
|
||||
4 files changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/mdmon.c b/mdmon.c
|
||||
index cef5bbc8..a2038fe6 100644
|
||||
--- a/mdmon.c
|
||||
+++ b/mdmon.c
|
||||
@@ -240,7 +240,7 @@ static int make_control_sock(char *devname)
|
||||
return -1;
|
||||
|
||||
addr.sun_family = PF_LOCAL;
|
||||
- strcpy(addr.sun_path, path);
|
||||
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
|
||||
umask(077); /* ensure no world write access */
|
||||
if (bind(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
close(sfd);
|
||||
@@ -389,7 +389,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (all) {
|
||||
struct mdstat_ent *mdstat, *e;
|
||||
- int container_len = strlen(container_name);
|
||||
+ int container_len = strnlen(container_name, MD_NAME_MAX);
|
||||
|
||||
/* launch an mdmon instance for each container found */
|
||||
mdstat = mdstat_read(0, 0);
|
||||
@@ -472,7 +472,7 @@ static int mdmon(char *devnm, int must_fork, int takeover)
|
||||
pfd[0] = pfd[1] = -1;
|
||||
|
||||
container = xcalloc(1, sizeof(*container));
|
||||
- strcpy(container->devnm, devnm);
|
||||
+ snprintf(container->devnm, MD_NAME_MAX, "%s", devnm);
|
||||
container->arrays = NULL;
|
||||
container->sock = -1;
|
||||
|
||||
diff --git a/mdopen.c b/mdopen.c
|
||||
index d3022a54..3daa71f9 100644
|
||||
--- a/mdopen.c
|
||||
+++ b/mdopen.c
|
||||
@@ -193,14 +193,14 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
|
||||
|
||||
if (dev) {
|
||||
if (strncmp(dev, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
|
||||
- strcpy(cname, dev + DEV_MD_DIR_LEN);
|
||||
+ snprintf(cname, MD_NAME_MAX, "%s", dev + DEV_MD_DIR_LEN);
|
||||
} else if (strncmp(dev, "/dev/", 5) == 0) {
|
||||
char *e = dev + strlen(dev);
|
||||
while (e > dev && isdigit(e[-1]))
|
||||
e--;
|
||||
if (e[0])
|
||||
num = strtoul(e, NULL, 10);
|
||||
- strcpy(cname, dev+5);
|
||||
+ snprintf(cname, MD_NAME_MAX, "%s", dev + 5);
|
||||
cname[e-(dev+5)] = 0;
|
||||
/* name *must* be mdXX or md_dXX in this context */
|
||||
if (num < 0 ||
|
||||
diff --git a/platform-intel.c b/platform-intel.c
|
||||
index 914164c0..eb6e1b7e 100644
|
||||
--- a/platform-intel.c
|
||||
+++ b/platform-intel.c
|
||||
@@ -214,7 +214,7 @@ struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path)
|
||||
|
||||
static int devpath_to_ll(const char *dev_path, const char *entry, unsigned long long *val)
|
||||
{
|
||||
- char path[strlen(dev_path) + strlen(entry) + 2];
|
||||
+ char path[strnlen(dev_path, PATH_MAX) + strnlen(entry, PATH_MAX) + 2];
|
||||
int fd;
|
||||
int n;
|
||||
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 824c1356..ce813172 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -7043,7 +7043,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
|
||||
int fd = -1;
|
||||
while (dev && !is_fd_valid(fd)) {
|
||||
char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1);
|
||||
- num = sprintf(path, "%s%s", "/dev/", dev->name);
|
||||
+ num = snprintf(path, PATH_MAX, "%s%s", "/dev/", dev->name);
|
||||
if (num > 0)
|
||||
fd = open(path, O_RDONLY, 0);
|
||||
if (num <= 0 || !is_fd_valid(fd)) {
|
||||
@@ -7935,7 +7935,7 @@ static int kill_subarray_imsm(struct supertype *st, char *subarray_id)
|
||||
|
||||
if (i < current_vol)
|
||||
continue;
|
||||
- sprintf(subarray, "%u", i);
|
||||
+ snprintf(subarray, sizeof(subarray), "%u", i);
|
||||
if (is_subarray_active(subarray, st->devnm)) {
|
||||
pr_err("deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
|
||||
current_vol, i);
|
||||
@@ -11308,7 +11308,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
|
||||
char *drv=NULL;
|
||||
struct stat st;
|
||||
|
||||
- strcpy(disk_path, disk_by_path);
|
||||
+ strncpy(disk_path, disk_by_path, PATH_MAX);
|
||||
strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
|
||||
if (stat(disk_path, &st) == 0) {
|
||||
struct sys_dev* hba;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 5ccd457b29809bee442749b5f66ac27ebba4a72d Mon Sep 17 00:00:00 2001
|
||||
From: Kinga Tanska <kinga.tanska@intel.com>
|
||||
Date: Thu, 11 May 2023 04:55:13 +0200
|
||||
Subject: [PATCH 140/165] platform-intel: limit guid length
|
||||
|
||||
Moving GUID_STR_MAX to header to use it as
|
||||
a length limitation for snprintf function.
|
||||
|
||||
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
platform-intel.c | 3 ---
|
||||
platform-intel.h | 5 ++++-
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/platform-intel.c b/platform-intel.c
|
||||
index eb6e1b7e..ef90c3fd 100644
|
||||
--- a/platform-intel.c
|
||||
+++ b/platform-intel.c
|
||||
@@ -510,9 +510,6 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba)
|
||||
return get_orom_by_device_id(hba->dev_id);
|
||||
}
|
||||
|
||||
-#define GUID_STR_MAX 37 /* according to GUID format:
|
||||
- * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
|
||||
-
|
||||
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
|
||||
((struct efi_guid) \
|
||||
{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
|
||||
diff --git a/platform-intel.h b/platform-intel.h
|
||||
index 2c0f4e39..ba97fb04 100644
|
||||
--- a/platform-intel.h
|
||||
+++ b/platform-intel.h
|
||||
@@ -19,6 +19,9 @@
|
||||
#include <asm/types.h>
|
||||
#include <strings.h>
|
||||
|
||||
+/* according to GUID format: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
|
||||
+#define GUID_STR_MAX 37
|
||||
+
|
||||
/* The IMSM Capability (IMSM AHCI and ISCU OROM/EFI variable) Version Table definition */
|
||||
struct imsm_orom {
|
||||
__u8 signature[4];
|
||||
@@ -229,7 +232,7 @@ extern struct orom_entry *orom_entries;
|
||||
|
||||
static inline char *guid_str(char *buf, struct efi_guid guid)
|
||||
{
|
||||
- sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
+ snprintf(buf, GUID_STR_MAX, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
guid.b[3], guid.b[2], guid.b[1], guid.b[0],
|
||||
guid.b[5], guid.b[4], guid.b[7], guid.b[6],
|
||||
guid.b[8], guid.b[9], guid.b[10], guid.b[11],
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,220 @@
|
||||
From 8d1114be8c0a307d251c24078833b029efabc448 Mon Sep 17 00:00:00 2001
|
||||
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
|
||||
Date: Wed, 5 Jul 2023 16:23:17 +0200
|
||||
Subject: [PATCH 141/165] imsm: Add reading vmd register for finding imsm
|
||||
capability
|
||||
|
||||
Currently mdadm does not find imsm capability when running inside VM.
|
||||
This patch adds the possibility to read from vmd register and check for
|
||||
capability, effectively allowing to use mdadm with imsm inside virtual machines.
|
||||
|
||||
Additionally refactor find_imsm_capability() to make assignments in new
|
||||
lines.
|
||||
|
||||
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
platform-intel.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
platform-intel.h | 11 ++++-
|
||||
super-intel.c | 11 +++--
|
||||
3 files changed, 130 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/platform-intel.c b/platform-intel.c
|
||||
index ef90c3fd..ac282bc5 100644
|
||||
--- a/platform-intel.c
|
||||
+++ b/platform-intel.c
|
||||
@@ -700,6 +700,106 @@ const struct imsm_orom *find_imsm_nvme(struct sys_dev *hba)
|
||||
return &nvme_orom->orom;
|
||||
}
|
||||
|
||||
+#define VMD_REGISTER_OFFSET 0x3FC
|
||||
+#define VMD_REGISTER_SKU_SHIFT 1
|
||||
+#define VMD_REGISTER_SKU_MASK (0x00000007)
|
||||
+#define VMD_REGISTER_SKU_PREMIUM 2
|
||||
+#define MD_REGISTER_VER_MAJOR_SHIFT 4
|
||||
+#define MD_REGISTER_VER_MAJOR_MASK (0x0000000F)
|
||||
+#define MD_REGISTER_VER_MINOR_SHIFT 8
|
||||
+#define MD_REGISTER_VER_MINOR_MASK (0x0000000F)
|
||||
+
|
||||
+/*
|
||||
+ * read_vmd_register() - Reads VMD register and writes contents to buff ptr
|
||||
+ * @buff: buffer for vmd register data, should be the size of uint32_t
|
||||
+ *
|
||||
+ * Return: 0 on success, 1 on error
|
||||
+ */
|
||||
+int read_vmd_register(uint32_t *buff, struct sys_dev *hba)
|
||||
+{
|
||||
+ int fd;
|
||||
+ char vmd_pci_config_path[PATH_MAX];
|
||||
+
|
||||
+ if (!vmd_domain_to_controller(hba, vmd_pci_config_path))
|
||||
+ return 1;
|
||||
+
|
||||
+ strncat(vmd_pci_config_path, "/config", PATH_MAX - strnlen(vmd_pci_config_path, PATH_MAX));
|
||||
+
|
||||
+ fd = open(vmd_pci_config_path, O_RDONLY);
|
||||
+ if (fd < 0)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (pread(fd, buff, sizeof(uint32_t), VMD_REGISTER_OFFSET) != sizeof(uint32_t)) {
|
||||
+ close(fd);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * add_vmd_orom() - Adds VMD orom cap to orom list, writes orom_entry ptr into vmd_orom
|
||||
+ * @vmd_orom: pointer to orom entry pointer
|
||||
+ *
|
||||
+ * Return: 0 on success, 1 on error
|
||||
+ */
|
||||
+int add_vmd_orom(struct orom_entry **vmd_orom, struct sys_dev *hba)
|
||||
+{
|
||||
+ uint8_t sku;
|
||||
+ uint32_t vmd_register_data;
|
||||
+ struct imsm_orom vmd_orom_cap = {
|
||||
+ .signature = IMSM_VMD_OROM_COMPAT_SIGNATURE,
|
||||
+ .sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB |
|
||||
+ IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB |
|
||||
+ IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB,
|
||||
+ .dpa = IMSM_OROM_DISKS_PER_ARRAY_NVME,
|
||||
+ .tds = IMSM_OROM_TOTAL_DISKS_VMD,
|
||||
+ .vpa = IMSM_OROM_VOLUMES_PER_ARRAY,
|
||||
+ .vphba = IMSM_OROM_VOLUMES_PER_HBA_VMD,
|
||||
+ .attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK,
|
||||
+ .driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem |
|
||||
+ IMSM_OROM_CAPABILITIES_TPV
|
||||
+ };
|
||||
+
|
||||
+ if (read_vmd_register(&vmd_register_data, hba) != 0)
|
||||
+ return 1;
|
||||
+
|
||||
+ sku = (uint8_t)((vmd_register_data >> VMD_REGISTER_SKU_SHIFT) &
|
||||
+ VMD_REGISTER_SKU_MASK);
|
||||
+
|
||||
+ if (sku == VMD_REGISTER_SKU_PREMIUM)
|
||||
+ vmd_orom_cap.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
|
||||
+ IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5;
|
||||
+ else
|
||||
+ vmd_orom_cap.rlc = IMSM_OROM_RLC_RAID_CNG;
|
||||
+
|
||||
+ vmd_orom_cap.major_ver = (uint8_t)
|
||||
+ ((vmd_register_data >> MD_REGISTER_VER_MAJOR_SHIFT) &
|
||||
+ MD_REGISTER_VER_MAJOR_MASK);
|
||||
+ vmd_orom_cap.minor_ver = (uint8_t)
|
||||
+ ((vmd_register_data >> MD_REGISTER_VER_MINOR_SHIFT) &
|
||||
+ MD_REGISTER_VER_MINOR_MASK);
|
||||
+
|
||||
+ *vmd_orom = add_orom(&vmd_orom_cap);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+const struct imsm_orom *find_imsm_vmd(struct sys_dev *hba)
|
||||
+{
|
||||
+ static struct orom_entry *vmd_orom;
|
||||
+
|
||||
+ if (hba->type != SYS_DEV_VMD)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!vmd_orom && add_vmd_orom(&vmd_orom, hba) != 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ add_orom_device_id(vmd_orom, hba->dev_id);
|
||||
+ vmd_orom->type = SYS_DEV_VMD;
|
||||
+ return &vmd_orom->orom;
|
||||
+}
|
||||
+
|
||||
const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
|
||||
{
|
||||
const struct imsm_orom *cap = get_orom_by_device_id(hba->dev_id);
|
||||
@@ -709,9 +809,19 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
|
||||
|
||||
if (hba->type == SYS_DEV_NVME)
|
||||
return find_imsm_nvme(hba);
|
||||
- if ((cap = find_imsm_efi(hba)) != NULL)
|
||||
+
|
||||
+ cap = find_imsm_efi(hba);
|
||||
+ if (cap)
|
||||
return cap;
|
||||
- if ((cap = find_imsm_hba_orom(hba)) != NULL)
|
||||
+
|
||||
+ if (hba->type == SYS_DEV_VMD) {
|
||||
+ cap = find_imsm_vmd(hba);
|
||||
+ if (cap)
|
||||
+ return cap;
|
||||
+ }
|
||||
+
|
||||
+ cap = find_imsm_hba_orom(hba);
|
||||
+ if (cap)
|
||||
return cap;
|
||||
|
||||
return NULL;
|
||||
diff --git a/platform-intel.h b/platform-intel.h
|
||||
index ba97fb04..ce29d3da 100644
|
||||
--- a/platform-intel.h
|
||||
+++ b/platform-intel.h
|
||||
@@ -27,6 +27,7 @@ struct imsm_orom {
|
||||
__u8 signature[4];
|
||||
#define IMSM_OROM_SIGNATURE "$VER"
|
||||
#define IMSM_NVME_OROM_COMPAT_SIGNATURE "$NVM"
|
||||
+ #define IMSM_VMD_OROM_COMPAT_SIGNATURE "$VMD"
|
||||
__u8 table_ver_major; /* Currently 2 (can change with future revs) */
|
||||
__u8 table_ver_minor; /* Currently 2 (can change with future revs) */
|
||||
__u16 major_ver; /* Example: 8 as in 8.6.0.1020 */
|
||||
@@ -68,11 +69,13 @@ struct imsm_orom {
|
||||
__u16 tds; /* Total Disks Supported */
|
||||
#define IMSM_OROM_TOTAL_DISKS 6
|
||||
#define IMSM_OROM_TOTAL_DISKS_NVME 12
|
||||
+ #define IMSM_OROM_TOTAL_DISKS_VMD 48
|
||||
__u8 vpa; /* # Volumes Per Array supported */
|
||||
#define IMSM_OROM_VOLUMES_PER_ARRAY 2
|
||||
__u8 vphba; /* # Volumes Per Host Bus Adapter supported */
|
||||
#define IMSM_OROM_VOLUMES_PER_HBA 4
|
||||
#define IMSM_OROM_VOLUMES_PER_HBA_NVME 4
|
||||
+ #define IMSM_OROM_VOLUMES_PER_HBA_VMD 24
|
||||
/* Attributes supported. This should map to the
|
||||
* attributes in the MPB. Also, lower 16 bits
|
||||
* should match/duplicate RLC bits above.
|
||||
@@ -185,7 +188,13 @@ static inline int imsm_orom_is_enterprise(const struct imsm_orom *orom)
|
||||
static inline int imsm_orom_is_nvme(const struct imsm_orom *orom)
|
||||
{
|
||||
return memcmp(orom->signature, IMSM_NVME_OROM_COMPAT_SIGNATURE,
|
||||
- sizeof(orom->signature)) == 0;
|
||||
+ sizeof(orom->signature)) == 0;
|
||||
+}
|
||||
+
|
||||
+static inline int imsm_orom_is_vmd_without_efi(const struct imsm_orom *orom)
|
||||
+{
|
||||
+ return memcmp(orom->signature, IMSM_VMD_OROM_COMPAT_SIGNATURE,
|
||||
+ sizeof(orom->signature)) == 0;
|
||||
}
|
||||
|
||||
static inline int imsm_orom_has_tpv_support(const struct imsm_orom *orom)
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index ce813172..77b0066f 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -2672,9 +2672,14 @@ static void print_imsm_capability(const struct imsm_orom *orom)
|
||||
else
|
||||
printf("Rapid Storage Technology%s\n",
|
||||
imsm_orom_is_enterprise(orom) ? " enterprise" : "");
|
||||
- if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
|
||||
- printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
|
||||
- orom->minor_ver, orom->hotfix_ver, orom->build);
|
||||
+ if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) {
|
||||
+ if (imsm_orom_is_vmd_without_efi(orom))
|
||||
+ printf(" Version : %d.%d\n", orom->major_ver,
|
||||
+ orom->minor_ver);
|
||||
+ else
|
||||
+ printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
|
||||
+ orom->minor_ver, orom->hotfix_ver, orom->build);
|
||||
+ }
|
||||
printf(" RAID Levels :%s%s%s%s%s\n",
|
||||
imsm_orom_has_raid0(orom) ? " raid0" : "",
|
||||
imsm_orom_has_raid1(orom) ? " raid1" : "",
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,109 @@
|
||||
From 55a1150c7438afcb7756fccd49713ede20a58e4a Mon Sep 17 00:00:00 2001
|
||||
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
|
||||
Date: Mon, 17 Jul 2023 15:19:10 +0200
|
||||
Subject: [PATCH 142/165] Add compiler defenses flags
|
||||
|
||||
It is essential to avoid buffer overflows and similar bugs as much as
|
||||
possible.
|
||||
|
||||
According to Intel rules we are obligated to verify certain
|
||||
compiler flags, so it will be much easier if they are added to the
|
||||
Makefile.
|
||||
|
||||
Add gcc flags for prevention of buffer overflows, format string vulnerabilities,
|
||||
stack protection to prevent stack overwrites and aslr enablement through -fPIE.
|
||||
Also make the flags configurable.
|
||||
|
||||
The changes were verified on gcc versions 7.5, 8.3, 9.2, 10 and 12.2.
|
||||
|
||||
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Makefile | 41 +++++++++++++++++++++++++++++------------
|
||||
1 file changed, 29 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 5eac1a4e..b3aa36f6 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
# define "CXFLAGS" to give extra flags to CC.
|
||||
# e.g. make CXFLAGS=-O to optimise
|
||||
-CXFLAGS ?=-O2
|
||||
+CXFLAGS ?=-O2 -D_FORTIFY_SOURCE=2
|
||||
TCC = tcc
|
||||
UCLIBC_GCC = $(shell for nm in i386-uclibc-linux-gcc i386-uclibc-gcc; do which $$nm > /dev/null && { echo $$nm ; exit; } ; done; echo false No uclibc found )
|
||||
#DIET_GCC = diet gcc
|
||||
@@ -50,14 +50,30 @@ ifeq ($(origin CC),default)
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
endif
|
||||
CXFLAGS ?= -ggdb
|
||||
-CWFLAGS = -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter
|
||||
+CWFLAGS ?= -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter -Wformat -Wformat-security -Werror=format-security -fstack-protector-strong -fPIE -Warray-bounds
|
||||
ifdef WARN_UNUSED
|
||||
-CWFLAGS += -Wp,-D_FORTIFY_SOURCE=2 -O3
|
||||
+CWFLAGS += -Wp -O3
|
||||
endif
|
||||
|
||||
-FALLTHROUGH := $(shell gcc -v --help 2>&1 | grep "implicit-fallthrough" | wc -l)
|
||||
-ifneq "$(FALLTHROUGH)" "0"
|
||||
-CWFLAGS += -Wimplicit-fallthrough=0
|
||||
+ifeq ($(origin FALLTHROUGH), undefined)
|
||||
+ FALLTHROUGH := $(shell gcc -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l)
|
||||
+ ifneq "$(FALLTHROUGH)" "0"
|
||||
+ CWFLAGS += -Wimplicit-fallthrough=0
|
||||
+ endif
|
||||
+endif
|
||||
+
|
||||
+ifeq ($(origin FORMATOVERFLOW), undefined)
|
||||
+ FORMATOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l)
|
||||
+ ifneq "$(FORMATOVERFLOW)" "0"
|
||||
+ CWFLAGS += -Wformat-overflow
|
||||
+ endif
|
||||
+endif
|
||||
+
|
||||
+ifeq ($(origin STRINGOPOVERFLOW), undefined)
|
||||
+ STRINGOPOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l)
|
||||
+ ifneq "$(STRINGOPOVERFLOW)" "0"
|
||||
+ CWFLAGS += -Wstringop-overflow
|
||||
+ endif
|
||||
endif
|
||||
|
||||
ifdef DEBIAN
|
||||
@@ -116,10 +132,12 @@ CFLAGS += -DUSE_PTHREADS
|
||||
MON_LDFLAGS += -pthread
|
||||
endif
|
||||
|
||||
+LDFLAGS = -Wl,-z,now,-z,noexecstack
|
||||
+
|
||||
# If you want a static binary, you might uncomment these
|
||||
-# LDFLAGS = -static
|
||||
+# LDFLAGS += -static
|
||||
# STRIP = -s
|
||||
-LDLIBS = -ldl
|
||||
+LDLIBS = -ldl -pie
|
||||
|
||||
# To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
|
||||
ifeq (, $(findstring -DNO_LIBUDEV, $(CXFLAGS)))
|
||||
@@ -209,14 +227,13 @@ mdadm.Os : $(SRCS) $(INCL)
|
||||
$(CC) -o mdadm.Os $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -Os $(SRCS) $(LDLIBS)
|
||||
|
||||
mdadm.O2 : $(SRCS) $(INCL) mdmon.O2
|
||||
- $(CC) -o mdadm.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(SRCS) $(LDLIBS)
|
||||
+ $(CC) -o mdadm.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 $(SRCS) $(LDLIBS)
|
||||
|
||||
mdmon.O2 : $(MON_SRCS) $(INCL) mdmon.h
|
||||
- $(CC) -o mdmon.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(MON_SRCS) $(LDLIBS)
|
||||
+ $(CC) -o mdmon.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 $(MON_SRCS) $(LDLIBS)
|
||||
|
||||
-# use '-z now' to guarantee no dynamic linker interactions with the monitor thread
|
||||
mdmon : $(MON_OBJS) | check_rundir
|
||||
- $(CC) $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -Wl,-z,now -o mdmon $(MON_OBJS) $(LDLIBS)
|
||||
+ $(CC) $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -o mdmon $(MON_OBJS) $(LDLIBS)
|
||||
msg.o: msg.c msg.h
|
||||
|
||||
test_stripe : restripe.c xmalloc.o mdadm.h
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 024d652e16dd9e3bd1ecdfce4d6f7a8cb498ba42 Mon Sep 17 00:00:00 2001
|
||||
From: Kinga Tanska <kinga.tanska@intel.com>
|
||||
Date: Tue, 12 Sep 2023 04:27:01 +0200
|
||||
Subject: [PATCH 143/165] Assemble: fix redundant memory free
|
||||
|
||||
Commit e9fb93af0f76 ("Fix memory leak in file Assemble")
|
||||
fixes few memory leaks in Assemble, but it introduces
|
||||
problem with assembling RAID volume. It was caused by
|
||||
clearing metadata too fast, not only on fail in
|
||||
select_devices() function.
|
||||
This commit removes redundant memory free.
|
||||
|
||||
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Assemble.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/Assemble.c b/Assemble.c
|
||||
index 61e8cd17..5be58e40 100644
|
||||
--- a/Assemble.c
|
||||
+++ b/Assemble.c
|
||||
@@ -428,8 +428,6 @@ static int select_devices(struct mddev_dev *devlist,
|
||||
|
||||
/* make sure we finished the loop */
|
||||
tmpdev = NULL;
|
||||
- free(st);
|
||||
- st = NULL;
|
||||
goto loop;
|
||||
} else {
|
||||
content = *contentp;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,92 @@
|
||||
From 7fe21767d3ab65a686518d2e36d18a07f535972e Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:19 +0800
|
||||
Subject: [PATCH 144/165] tests: add a new test for rdev lifetime
|
||||
|
||||
This test add and remove a underlying disk to raid concurretly, verify
|
||||
that the following problem is fixed:
|
||||
|
||||
run mdadm test 23rdev-lifetime at Fri Apr 28 03:25:30 UTC 2023
|
||||
md: could not open device unknown-block(1,0).
|
||||
sysfs: cannot create duplicate filename '/devices/virtual/block/md0/md/dev-ram0'
|
||||
CPU: 26 PID: 10521 Comm: test Not tainted 6.3.0-rc2-00134-g7b3a8828043c #115
|
||||
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/014
|
||||
Call Trace:
|
||||
<TASK>
|
||||
dump_stack_lvl+0xe7/0x180
|
||||
dump_stack+0x18/0x30
|
||||
sysfs_warn_dup+0xa2/0xd0
|
||||
sysfs_create_dir_ns+0x119/0x140
|
||||
kobject_add_internal+0x143/0x4d0
|
||||
kobject_add_varg+0x35/0x70
|
||||
kobject_add+0x64/0xd0
|
||||
bind_rdev_to_array+0x254/0x840 [md_mod]
|
||||
new_dev_store+0x14d/0x350 [md_mod]
|
||||
md_attr_store+0xc1/0x1a0 [md_mod]
|
||||
sysfs_kf_write+0x51/0x70
|
||||
kernfs_fop_write_iter+0x188/0x270
|
||||
vfs_write+0x27e/0x460
|
||||
ksys_write+0x85/0x180
|
||||
__x64_sys_write+0x21/0x30
|
||||
do_syscall_64+0x6c/0xe0
|
||||
entry_SYSCALL_64_after_hwframe+0x63/0xcd
|
||||
RIP: 0033:0x7f26bacf5387
|
||||
Code: 0d 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 84
|
||||
RSP: 002b:00007ffe98d79e68 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
|
||||
RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007f26bacf5387
|
||||
RDX: 0000000000000004 RSI: 000055bd10282bf0 RDI: 0000000000000001
|
||||
RBP: 000055bd10282bf0 R08: 000000000000000a R09: 00007f26bad8b4e0
|
||||
R10: 00007f26bad8b3e0 R11: 0000000000000246 R12: 0000000000000004
|
||||
R13: 00007f26badc8520 R14: 0000000000000004 R15: 00007f26badc8700
|
||||
</TASK>
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/23rdev-lifetime | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
create mode 100644 tests/23rdev-lifetime
|
||||
|
||||
diff --git a/tests/23rdev-lifetime b/tests/23rdev-lifetime
|
||||
new file mode 100644
|
||||
index 00000000..1750b0db
|
||||
--- /dev/null
|
||||
+++ b/tests/23rdev-lifetime
|
||||
@@ -0,0 +1,34 @@
|
||||
+devname=${dev0##*/}
|
||||
+devt=`cat /sys/block/$devname/dev`
|
||||
+pid=""
|
||||
+runtime=2
|
||||
+
|
||||
+clean_up_test() {
|
||||
+ pill -9 $pid
|
||||
+ echo clear > /sys/block/md0/md/array_state
|
||||
+}
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+add_by_sysfs() {
|
||||
+ while true; do
|
||||
+ echo $devt > /sys/block/md0/md/new_dev
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+remove_by_sysfs(){
|
||||
+ while true; do
|
||||
+ echo remove > /sys/block/md0/md/dev-${devname}/state
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+echo md0 > /sys/module/md_mod/parameters/new_array || die "create md0 failed"
|
||||
+
|
||||
+add_by_sysfs &
|
||||
+pid="$pid $!"
|
||||
+
|
||||
+remove_by_sysfs &
|
||||
+pid="$pid $!"
|
||||
+
|
||||
+sleep $runtime
|
||||
+exit 0
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 0ef9465f6355db612e53afc32e3084721c3dd7c7 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:20 +0800
|
||||
Subject: [PATCH 145/165] tests: support to skip checking dmesg
|
||||
|
||||
Prepare to add a regression test for raid10 that require error injection
|
||||
to trigger error path, and kernel will complain about io error, checking
|
||||
dmesg for error log will make it impossible to pass this test.
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
test | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/test b/test
|
||||
index 61d9ee83..b244453b 100755
|
||||
--- a/test
|
||||
+++ b/test
|
||||
@@ -107,8 +107,12 @@ do_test() {
|
||||
echo -ne "$_script... "
|
||||
if ( set -ex ; . $_script ) &> $targetdir/log
|
||||
then
|
||||
- dmesg | grep -iq "error\|call trace\|segfault" &&
|
||||
- die "dmesg prints errors when testing $_basename!"
|
||||
+ if [ -f "${_script}.inject_error" ]; then
|
||||
+ echo "dmesg checking is skipped because test inject error"
|
||||
+ else
|
||||
+ dmesg | grep -iq "error\|call trace\|segfault" &&
|
||||
+ die "dmesg prints errors when testing $_basename!"
|
||||
+ fi
|
||||
echo "succeeded"
|
||||
_fail=0
|
||||
else
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,122 @@
|
||||
From 3973f65293ce69ddd7c19be9a7a796abfe80e370 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:21 +0800
|
||||
Subject: [PATCH 146/165] tests: add a regression test for raid10 deadlock
|
||||
|
||||
The deadlock is described in [1], it's fixed first by [2], however,
|
||||
it turns out this commit will trigger other problems[3], hence this
|
||||
commit will be reverted and the deadlock is supposed to be fixed by [1].
|
||||
|
||||
[1] https://lore.kernel.org/linux-raid/20230322064122.2384589-5-yukuai1@huaweicloud.com/
|
||||
[2] https://lore.kernel.org/linux-raid/20220621031129.24778-1-guoqing.jiang@linux.dev/
|
||||
[3] https://lore.kernel.org/linux-raid/20230322064122.2384589-2-yukuai1@huaweicloud.com/
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/24raid10deadlock | 88 +++++++++++++++++++++++++++++
|
||||
tests/24raid10deadlock.inject_error | 0
|
||||
2 files changed, 88 insertions(+)
|
||||
create mode 100644 tests/24raid10deadlock
|
||||
create mode 100644 tests/24raid10deadlock.inject_error
|
||||
|
||||
diff --git a/tests/24raid10deadlock b/tests/24raid10deadlock
|
||||
new file mode 100644
|
||||
index 00000000..ee330aa9
|
||||
--- /dev/null
|
||||
+++ b/tests/24raid10deadlock
|
||||
@@ -0,0 +1,88 @@
|
||||
+devs="$dev0 $dev1 $dev2 $dev3"
|
||||
+runtime=120
|
||||
+pid=""
|
||||
+action_pid=""
|
||||
+
|
||||
+set_up_injection()
|
||||
+{
|
||||
+ echo -1 > /sys/kernel/debug/fail_make_request/times
|
||||
+ echo 1 > /sys/kernel/debug/fail_make_request/probability
|
||||
+ echo 0 > /sys/kernel/debug/fail_make_request/verbose
|
||||
+ echo 1 > /sys/block/${1##*/}/make-it-fail
|
||||
+}
|
||||
+
|
||||
+clean_up_injection()
|
||||
+{
|
||||
+ echo 0 > /sys/block/${1##*/}/make-it-fail
|
||||
+ echo 0 > /sys/kernel/debug/fail_make_request/times
|
||||
+ echo 0 > /sys/kernel/debug/fail_make_request/probability
|
||||
+ echo 2 > /sys/kernel/debug/fail_make_request/verbose
|
||||
+}
|
||||
+
|
||||
+test_rdev()
|
||||
+{
|
||||
+ while true; do
|
||||
+ mdadm -f $md0 $1 &> /dev/null
|
||||
+ mdadm -r $md0 $1 &> /dev/null
|
||||
+ mdadm --zero-superblock $1 &> /dev/null
|
||||
+ mdadm -a $md0 $1 &> /dev/null
|
||||
+ sleep $2
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+test_write_action()
|
||||
+{
|
||||
+ while true; do
|
||||
+ echo frozen > /sys/block/md0/md/sync_action
|
||||
+ echo idle > /sys/block/md0/md/sync_action
|
||||
+ sleep 0.1
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+set_up_test()
|
||||
+{
|
||||
+ fio -h &> /dev/null || die "fio not found"
|
||||
+
|
||||
+ # create a simple raid10
|
||||
+ mdadm -Cv -R -n 4 -l10 $md0 $devs || die "create raid10 failed"
|
||||
+}
|
||||
+
|
||||
+clean_up_test()
|
||||
+{
|
||||
+ clean_up_injection $dev0
|
||||
+ pkill -9 fio
|
||||
+ kill -9 $pid
|
||||
+ kill -9 $action_pid
|
||||
+
|
||||
+ sleep 1
|
||||
+
|
||||
+ if ps $action_pid | tail -1 | awk '{print $3}' | grep D; then
|
||||
+ die "thread that is writing sysfs is stuck in D state, deadlock is triggered"
|
||||
+ fi
|
||||
+ mdadm -S $md0
|
||||
+}
|
||||
+
|
||||
+cat /sys/kernel/debug/fail_make_request/times || die "fault injection is not enabled"
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+set_up_test || die "set up test failed"
|
||||
+
|
||||
+# backgroup io pressure
|
||||
+fio -filename=$md0 -rw=randwrite -direct=1 -name=test -bs=4k -numjobs=16 -iodepth=16 &
|
||||
+
|
||||
+# trigger add/remove device by io failure
|
||||
+set_up_injection $dev0
|
||||
+test_rdev $dev0 2 &
|
||||
+pid="$pid $!"
|
||||
+
|
||||
+# add/remove device directly
|
||||
+test_rdev $dev3 10 &
|
||||
+pid="$pid $!"
|
||||
+
|
||||
+test_write_action &
|
||||
+action_pid="$!"
|
||||
+
|
||||
+sleep $runtime
|
||||
+
|
||||
+exit 0
|
||||
diff --git a/tests/24raid10deadlock.inject_error b/tests/24raid10deadlock.inject_error
|
||||
new file mode 100644
|
||||
index 00000000..e69de29b
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,87 @@
|
||||
From 9d0fb58f3b1314678564b4ac7bfb19942acc8926 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:22 +0800
|
||||
Subject: [PATCH 147/165] tests: add a regression test for raid456 deadlock
|
||||
|
||||
The deadlock is described in [1], as the last patch described, it's
|
||||
fixed first by [2], however this fix will be reverted and the deadlock
|
||||
is supposed to be fixed by [3].
|
||||
|
||||
[1] https://lore.kernel.org/linux-raid/5ed54ffc-ce82-bf66-4eff-390cb23bc1ac@molgen.mpg.de/T/#t
|
||||
[2] https://lore.kernel.org/linux-raid/20220621031129.24778-1-guoqing.jiang@linux.dev/
|
||||
[3] https://lore.kernel.org/linux-raid/20230322064122.2384589-5-yukuai1@huaweicloud.com/
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/24raid456deadlock | 58 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 58 insertions(+)
|
||||
create mode 100644 tests/24raid456deadlock
|
||||
|
||||
diff --git a/tests/24raid456deadlock b/tests/24raid456deadlock
|
||||
new file mode 100644
|
||||
index 00000000..80e6e97e
|
||||
--- /dev/null
|
||||
+++ b/tests/24raid456deadlock
|
||||
@@ -0,0 +1,58 @@
|
||||
+devs="$dev0 $dev1 $dev2 $dev3 $dev4 $dev5"
|
||||
+runtime=120
|
||||
+pid=""
|
||||
+old=`cat /proc/sys/vm/dirty_background_ratio`
|
||||
+
|
||||
+test_write_action()
|
||||
+{
|
||||
+ while true; do
|
||||
+ echo check > /sys/block/md0/md/sync_action &> /dev/null
|
||||
+ sleep 0.1
|
||||
+ echo idle > /sys/block/md0/md/sync_action &> /dev/null
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+test_write_back()
|
||||
+{
|
||||
+ fio -filename=$md0 -bs=4k -rw=write -numjobs=1 -name=test \
|
||||
+ -time_based -runtime=$runtime &> /dev/null
|
||||
+}
|
||||
+
|
||||
+set_up_test()
|
||||
+{
|
||||
+ fio -h &> /dev/null || die "fio not found"
|
||||
+
|
||||
+ # create a simple raid6
|
||||
+ mdadm -Cv -R -n 6 -l6 $md0 $devs --assume-clean || die "create raid6 failed"
|
||||
+
|
||||
+ # trigger dirty pages write back
|
||||
+ echo 0 > /proc/sys/vm/dirty_background_ratio
|
||||
+}
|
||||
+
|
||||
+clean_up_test()
|
||||
+{
|
||||
+ echo $old > /proc/sys/vm/dirty_background_ratio
|
||||
+
|
||||
+ pkill -9 fio
|
||||
+ kill -9 $pid
|
||||
+
|
||||
+ sleep 1
|
||||
+
|
||||
+ if ps $pid | tail -1 | awk '{print $3}' | grep D; then
|
||||
+ die "thread that is writing sysfs is stuck in D state, deadlock is triggered"
|
||||
+ fi
|
||||
+ mdadm -S $md0
|
||||
+}
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+set_up_test || die "set up test failed"
|
||||
+
|
||||
+test_write_back &
|
||||
+
|
||||
+test_write_action &
|
||||
+pid="$!"
|
||||
+
|
||||
+sleep $runtime
|
||||
+
|
||||
+exit 0
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,59 @@
|
||||
From 4db8a3d452daaf2def41ca45c36e36c5781627ac Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:23 +0800
|
||||
Subject: [PATCH 148/165] tests: add a regression test that raid456 can't
|
||||
assemble
|
||||
|
||||
If recovery is interrupted and reshape is started, then this array can't
|
||||
assemble anymore. The problem is supposed to be fixed by [1].
|
||||
|
||||
[1] https://lore.kernel.org/linux-raid/20230529031045.1760883-1-yukuai1@huaweicloud.com/
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/25raid456-reshape-while-recovery | 32 ++++++++++++++++++++++++++
|
||||
1 file changed, 32 insertions(+)
|
||||
create mode 100644 tests/25raid456-reshape-while-recovery
|
||||
|
||||
diff --git a/tests/25raid456-reshape-while-recovery b/tests/25raid456-reshape-while-recovery
|
||||
new file mode 100644
|
||||
index 00000000..b9f871f2
|
||||
--- /dev/null
|
||||
+++ b/tests/25raid456-reshape-while-recovery
|
||||
@@ -0,0 +1,32 @@
|
||||
+devs="$dev0 $dev1 $dev2"
|
||||
+
|
||||
+set_up_test()
|
||||
+{
|
||||
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed"
|
||||
+ mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array"
|
||||
+ echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
+}
|
||||
+
|
||||
+clean_up_test()
|
||||
+{
|
||||
+ mdadm -S $md0
|
||||
+}
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+set_up_test || die "set up test failed"
|
||||
+
|
||||
+# set up replacement
|
||||
+echo want_replacement > /sys/block/md0/md/rd0/state
|
||||
+sleep 1
|
||||
+
|
||||
+# trigger reshape
|
||||
+echo frozen > /sys/block/md0/md/sync_action
|
||||
+mdadm --grow -l 6 $md0
|
||||
+sleep 1
|
||||
+
|
||||
+# reassemeble array
|
||||
+mdadm -S $md0 || die "can't stop array"
|
||||
+mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array"
|
||||
+
|
||||
+exit 0
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 8d45abd0c317d3f4971b779b4f8d1e33b5490dac Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:24 +0800
|
||||
Subject: [PATCH 149/165] tests: add a regression test that raid456 can't
|
||||
assemble again
|
||||
|
||||
This is a regression test for commit 0aecb06e2249 ("md/raid5: don't allow
|
||||
replacement while reshape is in progress").
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/25raid456-recovery-while-reshape | 33 ++++++++++++++++++++++++++
|
||||
1 file changed, 33 insertions(+)
|
||||
create mode 100644 tests/25raid456-recovery-while-reshape
|
||||
|
||||
diff --git a/tests/25raid456-recovery-while-reshape b/tests/25raid456-recovery-while-reshape
|
||||
new file mode 100644
|
||||
index 00000000..3f6251bf
|
||||
--- /dev/null
|
||||
+++ b/tests/25raid456-recovery-while-reshape
|
||||
@@ -0,0 +1,33 @@
|
||||
+devs="$dev0 $dev1 $dev2"
|
||||
+
|
||||
+set_up_test()
|
||||
+{
|
||||
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed"
|
||||
+ mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array"
|
||||
+ echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
+}
|
||||
+
|
||||
+clean_up_test()
|
||||
+{
|
||||
+ mdadm -S $md0
|
||||
+}
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+set_up_test || die "set up test failed"
|
||||
+
|
||||
+# trigger reshape
|
||||
+mdadm --grow -l 6 $md0
|
||||
+sleep 1
|
||||
+
|
||||
+# set up replacement
|
||||
+echo frozen > /sys/block/md0/md/sync_action
|
||||
+echo want_replacement > /sys/block/md0/md/rd0/state
|
||||
+echo reshape > /sys/block/md0/md/sync_action
|
||||
+sleep 1
|
||||
+
|
||||
+# reassemeble array
|
||||
+mdadm -S $md0 || die "can't stop array"
|
||||
+mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array"
|
||||
+
|
||||
+exit 0
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,60 @@
|
||||
From 481433482942c2ee2990965af394eff059990901 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:25 +0800
|
||||
Subject: [PATCH 150/165] tests: add a regression test that reshape can corrupt
|
||||
data
|
||||
|
||||
This is a regression test for commit 1544e95c6dd8 ("md: fix data
|
||||
corruption for raid456 when reshape restart while grow up").
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/25raid456-reshape-corrupt-data | 35 ++++++++++++++++++++++++++++
|
||||
1 file changed, 35 insertions(+)
|
||||
create mode 100644 tests/25raid456-reshape-corrupt-data
|
||||
|
||||
diff --git a/tests/25raid456-reshape-corrupt-data b/tests/25raid456-reshape-corrupt-data
|
||||
new file mode 100644
|
||||
index 00000000..fdb875fb
|
||||
--- /dev/null
|
||||
+++ b/tests/25raid456-reshape-corrupt-data
|
||||
@@ -0,0 +1,35 @@
|
||||
+devs="$dev0 $dev1 $dev2"
|
||||
+
|
||||
+set_up_test()
|
||||
+{
|
||||
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed"
|
||||
+ mdadm -a $md0 $dev3 || die "failed to bind new disk to array"
|
||||
+ mkfs.xfs -f $md0 || die "mkfs failed"
|
||||
+ xfs_ncheck $md0 || die "check fs failed"
|
||||
+}
|
||||
+
|
||||
+clean_up_test()
|
||||
+{
|
||||
+ mdadm -S $md0
|
||||
+}
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+set_up_test || die "set up test failed"
|
||||
+
|
||||
+# trigger reshape
|
||||
+echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
+mdadm --grow -l 6 $md0
|
||||
+sleep 1
|
||||
+
|
||||
+# stop and start reshape
|
||||
+echo frozen > /sys/block/md0/md/sync_action
|
||||
+echo system > /sys/block/md0/md/sync_speed_max
|
||||
+echo reshape > /sys/block/md0/md/sync_action
|
||||
+
|
||||
+mdadm -W $md0
|
||||
+
|
||||
+# check if data is corrupted
|
||||
+xfs_ncheck $md0 || die "data is corrupted after reshape"
|
||||
+
|
||||
+exit 0
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,59 @@
|
||||
From c6c7bce5a3064ac9d2956ae42ecab27f2e33dc2b Mon Sep 17 00:00:00 2001
|
||||
From: Yu Kuai <yukuai3@huawei.com>
|
||||
Date: Mon, 29 May 2023 21:28:26 +0800
|
||||
Subject: [PATCH 151/165] tests: add a regression test for raid456 deadlock
|
||||
again
|
||||
|
||||
This is a regression test for commit ("md/raid5: fix a deadlock in the
|
||||
case that reshape is interrupted").
|
||||
|
||||
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/25raid456-reshape-deadlock | 34 ++++++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
create mode 100644 tests/25raid456-reshape-deadlock
|
||||
|
||||
diff --git a/tests/25raid456-reshape-deadlock b/tests/25raid456-reshape-deadlock
|
||||
new file mode 100644
|
||||
index 00000000..bfa0cc56
|
||||
--- /dev/null
|
||||
+++ b/tests/25raid456-reshape-deadlock
|
||||
@@ -0,0 +1,34 @@
|
||||
+devs="$dev0 $dev1 $dev2"
|
||||
+
|
||||
+set_up_test()
|
||||
+{
|
||||
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed"
|
||||
+ mdadm -a $md0 $dev3 || die "failed to bind new disk to array"
|
||||
+ echo 1000 > /sys/block/md0/md/sync_speed_max
|
||||
+}
|
||||
+
|
||||
+clean_up_test()
|
||||
+{
|
||||
+ echo idle > /sys/block/md0/md/sync_action
|
||||
+ mdadm -S $md0
|
||||
+}
|
||||
+
|
||||
+trap 'clean_up_test' EXIT
|
||||
+
|
||||
+set_up_test || die "set up test failed"
|
||||
+
|
||||
+# trigger reshape
|
||||
+mdadm --grow -l 6 $md0
|
||||
+sleep 1
|
||||
+
|
||||
+# stop reshape
|
||||
+echo frozen > /sys/block/md0/md/sync_action
|
||||
+
|
||||
+# read accross reshape
|
||||
+dd if=$md0 of=/dev/NULL bs=1m count=100 iflag=direct &> /dev/null &
|
||||
+sleep 2
|
||||
+
|
||||
+# suspend array
|
||||
+echo 1 > /sys/block/md0/md/suspend_lo
|
||||
+
|
||||
+exit 0
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,193 @@
|
||||
From d5fee8654e41dc4067dfdc3312542f1f43ebe884 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Thu, 1 Jun 2023 09:27:45 +0200
|
||||
Subject: [PATCH 152/165] tests: create names_template
|
||||
|
||||
Create templates directory and names_template. Move code from
|
||||
00createnames. This code will be reused for 00confnames in next patch.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/00createnames | 86 +++++++---------------------------
|
||||
tests/templates/names_template | 53 +++++++++++++++++++++
|
||||
2 files changed, 70 insertions(+), 69 deletions(-)
|
||||
create mode 100644 tests/templates/names_template
|
||||
|
||||
diff --git a/tests/00createnames b/tests/00createnames
|
||||
index 64b81b92..064eeef2 100644
|
||||
--- a/tests/00createnames
|
||||
+++ b/tests/00createnames
|
||||
@@ -1,93 +1,41 @@
|
||||
set -x -e
|
||||
+. tests/templates/names_template
|
||||
|
||||
# Test how <devname> and --name= are handled for create mode.
|
||||
-# We need to check three properties, generated from those parameters:
|
||||
-# - devnode name
|
||||
-# - link in /dev/md/ (MD_DEVNAME property from --detail --export)
|
||||
-# - name in metadata (MD_NAME property from --examine --export)
|
||||
-
|
||||
-function _verify() {
|
||||
- local DEVNODE_NAME="$1"
|
||||
- local WANTED_LINK="$2"
|
||||
- local WANTED_NAME="$3"
|
||||
-
|
||||
- local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
|
||||
- if [[ "$?" != "0" ]]; then
|
||||
- echo "Cannot get details for $DEVNODE_NAME - unexpected devnode."
|
||||
- exit 1
|
||||
- fi
|
||||
-
|
||||
- if [[ "$WANTED_LINK" != "empty" ]]; then
|
||||
- local EXPECTED="MD_DEVNAME=$WANTED_LINK"
|
||||
- if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
- echo "$RES doesn't match $EXPECTED."
|
||||
- exit 1
|
||||
- fi
|
||||
- fi
|
||||
-
|
||||
-
|
||||
- local RES="$(mdadm -E --export $dev0 | grep MD_NAME)"
|
||||
- if [[ "$?" != "0" ]]; then
|
||||
- echo "Cannot get metadata from $dev0."
|
||||
- exit 1
|
||||
- fi
|
||||
-
|
||||
- local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
|
||||
- if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
- echo "$RES doesn't match $EXPECTED."
|
||||
- exit 1
|
||||
- fi
|
||||
-}
|
||||
-
|
||||
-function _create() {
|
||||
- local DEVNAME=$1
|
||||
- local NAME=$2
|
||||
-
|
||||
- if [[ -z "$NAME" ]]; then
|
||||
- mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
|
||||
- else
|
||||
- mdadm -CR "$DEVNAME" --name="$NAME" -l0 -n 1 $dev0 --force
|
||||
- fi
|
||||
-
|
||||
- if [[ "$?" != "0" ]]; then
|
||||
- echo "Cannot create device."
|
||||
- exit 1
|
||||
- fi
|
||||
-}
|
||||
|
||||
# The most trivial case.
|
||||
-_create "/dev/md/name"
|
||||
-_verify "/dev/md127" "name" "name"
|
||||
+names_create "/dev/md/name"
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
-_create "name"
|
||||
-_verify "/dev/md127" "name" "name"
|
||||
+names_create "name"
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# Use 'mdX' as name.
|
||||
-_create "/dev/md/md0"
|
||||
-_verify "/dev/md127" "md0" "md0"
|
||||
+names_create "/dev/md/md0"
|
||||
+names_verify "/dev/md127" "md0" "md0"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
-_create "md0"
|
||||
-_verify "/dev/md127" "md0" "md0"
|
||||
+names_create "md0"
|
||||
+names_verify "/dev/md127" "md0" "md0"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# <devnode> is used to create MD_DEVNAME but, name is used to create MD_NAME.
|
||||
-_create "/dev/md/devnode" "name"
|
||||
-_verify "/dev/md127" "devnode" "name"
|
||||
+names_create "/dev/md/devnode" "name"
|
||||
+names_verify "/dev/md127" "devnode" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
-_create "devnode" "name"
|
||||
-_verify "/dev/md127" "devnode" "name"
|
||||
+names_create "devnode" "name"
|
||||
+names_verify "/dev/md127" "devnode" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# Devnode points to /dev/ directory. MD_DEVNAME doesn't exist.
|
||||
-_create "/dev/md0"
|
||||
-_verify "/dev/md0" "empty" "0"
|
||||
+names_create "/dev/md0"
|
||||
+names_verify "/dev/md0" "empty" "0"
|
||||
mdadm -S "/dev/md0"
|
||||
|
||||
# Devnode points to /dev/ directory and name is set.
|
||||
-_create "/dev/md0" "name"
|
||||
-_verify "/dev/md0" "empty" "name"
|
||||
+names_create "/dev/md0" "name"
|
||||
+names_verify "/dev/md0" "empty" "name"
|
||||
mdadm -S "/dev/md0"
|
||||
diff --git a/tests/templates/names_template b/tests/templates/names_template
|
||||
new file mode 100644
|
||||
index 00000000..9f09be9e
|
||||
--- /dev/null
|
||||
+++ b/tests/templates/names_template
|
||||
@@ -0,0 +1,53 @@
|
||||
+# NAME is optional. Testing with native 1.2 superblock.
|
||||
+function names_create() {
|
||||
+ local DEVNAME=$1
|
||||
+ local NAME=$2
|
||||
+
|
||||
+ if [[ -z "$NAME" ]]; then
|
||||
+ mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
|
||||
+ else
|
||||
+ mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force
|
||||
+ fi
|
||||
+
|
||||
+ if [[ "$?" != "0" ]]; then
|
||||
+ echo "Cannot create device."
|
||||
+ exit 1
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+# Three properties to check:
|
||||
+# - devnode name
|
||||
+# - link in /dev/md/ (MD_DEVNAME property from --detail --export)
|
||||
+# - name in metadata (MD_NAME property from --detail --export)- that works only with 1.2 sb.
|
||||
+function names_verify() {
|
||||
+ local DEVNODE_NAME="$1"
|
||||
+ local WANTED_LINK="$2"
|
||||
+ local WANTED_NAME="$3"
|
||||
+
|
||||
+ local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
|
||||
+ if [[ "$?" != "0" ]]; then
|
||||
+ echo "Cannot get details for $DEVNODE_NAME - unexpected devnode."
|
||||
+ exit 1
|
||||
+ fi
|
||||
+
|
||||
+ if [[ "$WANTED_LINK" != "empty" ]]; then
|
||||
+ local EXPECTED="MD_DEVNAME=$WANTED_LINK"
|
||||
+ fi
|
||||
+
|
||||
+ if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
+ echo "$RES doesn't match $EXPECTED."
|
||||
+ exit 1
|
||||
+ fi
|
||||
+
|
||||
+ local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_NAME)"
|
||||
+ if [[ "$?" != "0" ]]; then
|
||||
+ echo "Cannot get metadata from $dev0."
|
||||
+ exit 1
|
||||
+ fi
|
||||
+
|
||||
+ local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
|
||||
+ if [[ "$RES" != "$EXPECTED" ]]; then
|
||||
+ echo "$RES doesn't match $EXPECTED."
|
||||
+ exit 1
|
||||
+ fi
|
||||
+}
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,164 @@
|
||||
From 569a23425939e4bfc7b4d7f871d8510bb968f892 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Thu, 1 Jun 2023 09:27:46 +0200
|
||||
Subject: [PATCH 153/165] tests: create 00confnames
|
||||
|
||||
The test is an attempt to document current implementation of devnode
|
||||
and name handling for config entries. It is focused on incremental-
|
||||
default way of array assembling on boot.
|
||||
The expectations are aligned to current implementation for native
|
||||
metadata because it is the most complicated scenario- both variables
|
||||
can be set.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/00confnames | 107 +++++++++++++++++++++++++++++++++
|
||||
tests/templates/names_template | 20 ++++++
|
||||
2 files changed, 127 insertions(+)
|
||||
create mode 100644 tests/00confnames
|
||||
|
||||
diff --git a/tests/00confnames b/tests/00confnames
|
||||
new file mode 100644
|
||||
index 00000000..25a7127b
|
||||
--- /dev/null
|
||||
+++ b/tests/00confnames
|
||||
@@ -0,0 +1,107 @@
|
||||
+set -x -e
|
||||
+. tests/templates/names_template
|
||||
+
|
||||
+# Test how <devname> and <name> from config are handled during Incremental assemblation.
|
||||
+# 1-6 <devnode> only tests (no <name> in config).
|
||||
+# 6-10 <devname> and <name> combinations are tested.
|
||||
+# 11-13 corner cases.
|
||||
+
|
||||
+names_create "/dev/md/name"
|
||||
+local _UUID="$(mdadm -D --export /dev/md127 | grep MD_UUID | cut -d'=' -f2)"
|
||||
+[[ "$_UUID" == "" ]] && echo "Cannot obtain UUID for $DEVNODE_NAME" && exit 1
|
||||
+
|
||||
+
|
||||
+# 1. <devname> definition consistent with metadata name.
|
||||
+names_make_conf $_UUID "/dev/md/name" "empty" $config
|
||||
+mdadm -S "/dev/md127"
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 2. Same as 1, but use short name form of <devname>.
|
||||
+names_make_conf $_UUID "name" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 3. Same as 1, but use different <devname> than metadata provides.
|
||||
+names_make_conf $_UUID "/dev/md/other" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "other" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 4. Same as 3, but use short name form of <devname>.
|
||||
+names_make_conf $_UUID "other" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "other" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 5. Force particular node creation by setting <devname> to /dev/mdX. Link is not created in this
|
||||
+# case.
|
||||
+names_make_conf $_UUID "/dev/md4" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md4" "empty" "name"
|
||||
+mdadm -S "/dev/md4"
|
||||
+
|
||||
+# 6. <devname> set to /dev/mdX, <name> same as in metadata.
|
||||
+# Metadata name and default node used - controversial. Current behavior documented.
|
||||
+names_make_conf $_UUID "/dev/md22" "name" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 7. <devname> set to /dev/mdX, <name> different than in metadata.
|
||||
+# Metadata name and default node used - controversial. Current behavior documented.
|
||||
+names_make_conf $_UUID "/dev/md8" "other" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 8. Both <devname> and <name> different than in metadata.
|
||||
+# Metadata name and default node used - controversial. Current behavior documented.
|
||||
+names_make_conf $_UUID "devnode" "other_name" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 9. <devname> set to metadata name, <name> different than in metadata.
|
||||
+# Metadata name and default node used - controversial. Current behavior documented.
|
||||
+names_make_conf $_UUID "name" "other_name" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 10. Bad <devname> set, no <name>.
|
||||
+# Metadata name and default node used - expected.
|
||||
+names_make_conf $_UUID "/im/bad/devname" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 11. <devname> with some special symbols and locales, no <name>.
|
||||
+# It needs to wait a while for timeout because udev cannot create a link - known issue.
|
||||
+names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "tźż-\.,<>st+-" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 12. No <devname> and <name> set.
|
||||
+# Metadata name and default node used - expected.
|
||||
+names_make_conf $_UUID "empty" "empty" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 13. No <devname>, <name> set to /dev/mdX.
|
||||
+# Entry should be ignored, it is not ignored but result is good anyway.
|
||||
+names_make_conf $_UUID "empty" "/dev/md12" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
+
|
||||
+# 13. No <devname>, <name> with special symbols and locales.
|
||||
+# Entry should be ignored, it is not ignored but result is good anyway.
|
||||
+names_make_conf $_UUID "empty" "./\śćń#&" $config
|
||||
+mdadm -I $dev0 --config=$config
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
+mdadm -S "/dev/md127"
|
||||
diff --git a/tests/templates/names_template b/tests/templates/names_template
|
||||
index 9f09be9e..8d2b5c81 100644
|
||||
--- a/tests/templates/names_template
|
||||
+++ b/tests/templates/names_template
|
||||
@@ -51,3 +51,23 @@ function names_verify() {
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
+
|
||||
+# Generate ARRAYLINE for tested array.
|
||||
+names_make_conf() {
|
||||
+ local UUID="$1"
|
||||
+ local WANTED_DEVNAME="$2"
|
||||
+ local WANTED_NAME="$3"
|
||||
+ local CONF="$4"
|
||||
+
|
||||
+ local LINE="ARRAY metadata=1.2 UUID=$UUID"
|
||||
+
|
||||
+ if [[ "$WANTED_DEVNAME" != "empty" ]]; then
|
||||
+ LINE="$LINE $WANTED_DEVNAME"
|
||||
+ fi
|
||||
+
|
||||
+ if [[ "$WANTED_NAME" != "empty" ]]; then
|
||||
+ LINE="$LINE name=$WANTED_NAME"
|
||||
+ fi
|
||||
+
|
||||
+ echo $LINE > $CONF
|
||||
+}
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,399 @@
|
||||
From 330c07f8e4d26f4f2d068e11f09c9df8a3380087 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Thu, 1 Jun 2023 09:27:47 +0200
|
||||
Subject: [PATCH 154/165] mdadm: set ident.devname if applicable
|
||||
|
||||
This patch tries to propagate the usage of struct mddev_ident for cmdline
|
||||
where it is applicable. To avoid regression, this value is derived
|
||||
from devlist->devname for applicable modes only.
|
||||
As a result, the whole structure is passed to some functions. It produces
|
||||
some changes for Build, Create and Assemble.
|
||||
No functional changes intended.
|
||||
|
||||
The goal of the change is to unify devname validation which is done in
|
||||
next patches.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Build.c | 21 +++++++++------------
|
||||
Create.c | 35 ++++++++++++++++------------------
|
||||
mdadm.c | 57 +++++++++++++++++++++++++-------------------------------
|
||||
mdadm.h | 13 +++++--------
|
||||
4 files changed, 55 insertions(+), 71 deletions(-)
|
||||
|
||||
diff --git a/Build.c b/Build.c
|
||||
index 8d6f6f58..657ab315 100644
|
||||
--- a/Build.c
|
||||
+++ b/Build.c
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
#include "mdadm.h"
|
||||
|
||||
-int Build(char *mddev, struct mddev_dev *devlist,
|
||||
- struct shape *s, struct context *c)
|
||||
+int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
|
||||
+ struct context *c)
|
||||
{
|
||||
/* Build a linear or raid0 arrays without superblocks
|
||||
* We cannot really do any checks, we just do it.
|
||||
@@ -75,13 +75,12 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
||||
|
||||
/* We need to create the device. It can have no name. */
|
||||
map_lock(&map);
|
||||
- mdfd = create_mddev(mddev, NULL, c->autof, LOCAL,
|
||||
+ mdfd = create_mddev(ident->devname, NULL, c->autof, LOCAL,
|
||||
chosen_name, 0);
|
||||
if (mdfd < 0) {
|
||||
map_unlock(&map);
|
||||
return 1;
|
||||
}
|
||||
- mddev = chosen_name;
|
||||
|
||||
map_update(&map, fd2devnm(mdfd), "none", uuid, chosen_name);
|
||||
map_unlock(&map);
|
||||
@@ -93,7 +92,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
||||
array.nr_disks = s->raiddisks;
|
||||
array.raid_disks = s->raiddisks;
|
||||
array.md_minor = 0;
|
||||
- if (fstat_is_blkdev(mdfd, mddev, &rdev))
|
||||
+ if (fstat_is_blkdev(mdfd, chosen_name, &rdev))
|
||||
array.md_minor = minor(rdev);
|
||||
array.not_persistent = 1;
|
||||
array.state = 0; /* not clean, but no errors */
|
||||
@@ -108,8 +107,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
||||
array.chunk_size = s->chunk*1024;
|
||||
array.layout = s->layout;
|
||||
if (md_set_array_info(mdfd, &array)) {
|
||||
- pr_err("md_set_array_info() failed for %s: %s\n",
|
||||
- mddev, strerror(errno));
|
||||
+ pr_err("md_set_array_info() failed for %s: %s\n", chosen_name, strerror(errno));
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@@ -178,8 +176,8 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
||||
}
|
||||
if (bitmap_fd >= 0) {
|
||||
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
|
||||
- pr_err("Cannot set bitmap file for %s: %s\n",
|
||||
- mddev, strerror(errno));
|
||||
+ pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
|
||||
+ strerror(errno));
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
@@ -193,9 +191,8 @@ int Build(char *mddev, struct mddev_dev *devlist,
|
||||
}
|
||||
|
||||
if (c->verbose >= 0)
|
||||
- pr_err("array %s built and started.\n",
|
||||
- mddev);
|
||||
- wait_for(mddev, mdfd);
|
||||
+ pr_err("array %s built and started.\n", chosen_name);
|
||||
+ wait_for(chosen_name, mdfd);
|
||||
close(mdfd);
|
||||
return 0;
|
||||
|
||||
diff --git a/Create.c b/Create.c
|
||||
index ea6a4745..a280c7bc 100644
|
||||
--- a/Create.c
|
||||
+++ b/Create.c
|
||||
@@ -471,11 +471,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int Create(struct supertype *st, char *mddev,
|
||||
- char *name, int *uuid,
|
||||
- int subdevs, struct mddev_dev *devlist,
|
||||
- struct shape *s,
|
||||
- struct context *c)
|
||||
+int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
|
||||
+ struct mddev_dev *devlist, struct shape *s, struct context *c)
|
||||
{
|
||||
/*
|
||||
* Create a new raid array.
|
||||
@@ -497,6 +494,8 @@ int Create(struct supertype *st, char *mddev,
|
||||
unsigned long long minsize = 0, maxsize = 0;
|
||||
char *mindisc = NULL;
|
||||
char *maxdisc = NULL;
|
||||
+ char *name = ident->name;
|
||||
+ int *uuid = ident->uuid_set == 1 ? ident->uuid : NULL;
|
||||
int dnum;
|
||||
struct mddev_dev *dv;
|
||||
dev_t rdev;
|
||||
@@ -1015,7 +1014,7 @@ int Create(struct supertype *st, char *mddev,
|
||||
|
||||
/* We need to create the device */
|
||||
map_lock(&map);
|
||||
- mdfd = create_mddev(mddev, name, c->autof, LOCAL, chosen_name, 1);
|
||||
+ mdfd = create_mddev(ident->devname, ident->name, c->autof, LOCAL, chosen_name, 1);
|
||||
if (mdfd < 0) {
|
||||
map_unlock(&map);
|
||||
return 1;
|
||||
@@ -1032,7 +1031,6 @@ int Create(struct supertype *st, char *mddev,
|
||||
udev_unblock();
|
||||
return 1;
|
||||
}
|
||||
- mddev = chosen_name;
|
||||
|
||||
memset(&inf, 0, sizeof(inf));
|
||||
md_get_array_info(mdfd, &inf);
|
||||
@@ -1050,7 +1048,7 @@ int Create(struct supertype *st, char *mddev,
|
||||
* with, but it chooses to trust me instead. Sigh
|
||||
*/
|
||||
info.array.md_minor = 0;
|
||||
- if (fstat_is_blkdev(mdfd, mddev, &rdev))
|
||||
+ if (fstat_is_blkdev(mdfd, chosen_name, &rdev))
|
||||
info.array.md_minor = minor(rdev);
|
||||
info.array.not_persistent = 0;
|
||||
|
||||
@@ -1102,8 +1100,8 @@ int Create(struct supertype *st, char *mddev,
|
||||
info.array.layout = s->layout;
|
||||
info.array.chunk_size = s->chunk*1024;
|
||||
|
||||
- if (name == NULL || *name == 0) {
|
||||
- /* base name on mddev */
|
||||
+ if (*name == 0) {
|
||||
+ /* base name on devname */
|
||||
/* /dev/md0 -> 0
|
||||
* /dev/md_d0 -> d0
|
||||
* /dev/md_foo -> foo
|
||||
@@ -1113,15 +1111,16 @@ int Create(struct supertype *st, char *mddev,
|
||||
* /dev/mdhome -> home
|
||||
*/
|
||||
/* FIXME compare this with rules in create_mddev */
|
||||
- name = strrchr(mddev, '/');
|
||||
+ name = strrchr(chosen_name, '/');
|
||||
+
|
||||
if (name) {
|
||||
name++;
|
||||
if (strncmp(name, "md_", 3) == 0 &&
|
||||
- strlen(name) > 3 && (name-mddev) == 5 /* /dev/ */)
|
||||
+ strlen(name) > 3 && (name - chosen_name) == 5 /* /dev/ */)
|
||||
name += 3;
|
||||
else if (strncmp(name, "md", 2) == 0 &&
|
||||
strlen(name) > 2 && isdigit(name[2]) &&
|
||||
- (name-mddev) == 5 /* /dev/ */)
|
||||
+ (name - chosen_name) == 5 /* /dev/ */)
|
||||
name += 2;
|
||||
}
|
||||
}
|
||||
@@ -1215,8 +1214,7 @@ int Create(struct supertype *st, char *mddev,
|
||||
}
|
||||
rv = set_array_info(mdfd, st, &info);
|
||||
if (rv) {
|
||||
- pr_err("failed to set array info for %s: %s\n",
|
||||
- mddev, strerror(errno));
|
||||
+ pr_err("failed to set array info for %s: %s\n", chosen_name, strerror(errno));
|
||||
goto abort_locked;
|
||||
}
|
||||
|
||||
@@ -1237,8 +1235,7 @@ int Create(struct supertype *st, char *mddev,
|
||||
goto abort_locked;
|
||||
}
|
||||
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
|
||||
- pr_err("Cannot set bitmap file for %s: %s\n",
|
||||
- mddev, strerror(errno));
|
||||
+ pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, strerror(errno));
|
||||
goto abort_locked;
|
||||
}
|
||||
}
|
||||
@@ -1254,7 +1251,7 @@ int Create(struct supertype *st, char *mddev,
|
||||
* create links */
|
||||
sysfs_uevent(&info, "change");
|
||||
if (c->verbose >= 0)
|
||||
- pr_err("container %s prepared.\n", mddev);
|
||||
+ pr_err("container %s prepared.\n", chosen_name);
|
||||
wait_for(chosen_name, mdfd);
|
||||
} else if (c->runstop == 1 || subdevs >= s->raiddisks) {
|
||||
if (st->ss->external) {
|
||||
@@ -1312,7 +1309,7 @@ int Create(struct supertype *st, char *mddev,
|
||||
ioctl(mdfd, RESTART_ARRAY_RW, NULL);
|
||||
}
|
||||
if (c->verbose >= 0)
|
||||
- pr_info("array %s started.\n", mddev);
|
||||
+ pr_info("array %s started.\n", chosen_name);
|
||||
if (st->ss->external && st->container_devnm[0]) {
|
||||
if (need_mdmon)
|
||||
start_mdmon(st->container_devnm);
|
||||
diff --git a/mdadm.c b/mdadm.c
|
||||
index 22d1c53b..0a56ed26 100644
|
||||
--- a/mdadm.c
|
||||
+++ b/mdadm.c
|
||||
@@ -1290,37 +1290,39 @@ int main(int argc, char *argv[])
|
||||
pr_err("an md device must be given in this mode\n");
|
||||
exit(2);
|
||||
}
|
||||
+ ident.devname = devlist->devname;
|
||||
+
|
||||
if ((int)ident.super_minor == -2 && c.autof) {
|
||||
pr_err("--super-minor=dev is incompatible with --auto\n");
|
||||
exit(2);
|
||||
}
|
||||
if (mode == MANAGE || mode == GROW) {
|
||||
- mdfd = open_mddev(devlist->devname, 1);
|
||||
+ mdfd = open_mddev(ident.devname, 1);
|
||||
if (mdfd < 0)
|
||||
exit(1);
|
||||
|
||||
ret = fstat(mdfd, &stb);
|
||||
if (ret) {
|
||||
- pr_err("fstat failed on %s.\n", devlist->devname);
|
||||
+ pr_err("fstat failed on %s.\n", ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
- char *bname = basename(devlist->devname);
|
||||
+ char *bname = basename(ident.devname);
|
||||
|
||||
if (strlen(bname) > MD_NAME_MAX) {
|
||||
- pr_err("Name %s is too long.\n", devlist->devname);
|
||||
+ pr_err("Name %s is too long.\n", ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
- ret = stat(devlist->devname, &stb);
|
||||
+ ret = stat(ident.devname, &stb);
|
||||
if (ident.super_minor == -2 && ret != 0) {
|
||||
pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
|
||||
- devlist->devname);
|
||||
+ ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!ret && !stat_is_md_dev(&stb)) {
|
||||
- pr_err("device %s exists but is not an md array.\n", devlist->devname);
|
||||
+ pr_err("device %s exists but is not an md array.\n", ident.devname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1408,17 +1410,17 @@ int main(int argc, char *argv[])
|
||||
case MANAGE:
|
||||
/* readonly, add/remove, readwrite, runstop */
|
||||
if (c.readonly > 0)
|
||||
- rv = Manage_ro(devlist->devname, mdfd, c.readonly);
|
||||
+ rv = Manage_ro(ident.devname, mdfd, c.readonly);
|
||||
if (!rv && devs_found > 1)
|
||||
- rv = Manage_subdevs(devlist->devname, mdfd,
|
||||
+ rv = Manage_subdevs(ident.devname, mdfd,
|
||||
devlist->next, c.verbose,
|
||||
c.test, c.update, c.force);
|
||||
if (!rv && c.readonly < 0)
|
||||
- rv = Manage_ro(devlist->devname, mdfd, c.readonly);
|
||||
+ rv = Manage_ro(ident.devname, mdfd, c.readonly);
|
||||
if (!rv && c.runstop > 0)
|
||||
- rv = Manage_run(devlist->devname, mdfd, &c);
|
||||
+ rv = Manage_run(ident.devname, mdfd, &c);
|
||||
if (!rv && c.runstop < 0)
|
||||
- rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0);
|
||||
+ rv = Manage_stop(ident.devname, mdfd, c.verbose, 0);
|
||||
break;
|
||||
case ASSEMBLE:
|
||||
if (!c.scan && c.runstop == -1) {
|
||||
@@ -1428,22 +1430,19 @@ int main(int argc, char *argv[])
|
||||
ident.super_minor == UnSet && ident.name[0] == 0 &&
|
||||
!c.scan) {
|
||||
/* Only a device has been given, so get details from config file */
|
||||
- struct mddev_ident *array_ident = conf_get_ident(devlist->devname);
|
||||
+ struct mddev_ident *array_ident = conf_get_ident(ident.devname);
|
||||
if (array_ident == NULL) {
|
||||
- pr_err("%s not identified in config file.\n",
|
||||
- devlist->devname);
|
||||
+ pr_err("%s not identified in config file.\n", ident.devname);
|
||||
rv |= 1;
|
||||
if (mdfd >= 0)
|
||||
close(mdfd);
|
||||
} else {
|
||||
if (array_ident->autof == 0)
|
||||
array_ident->autof = c.autof;
|
||||
- rv |= Assemble(ss, devlist->devname, array_ident,
|
||||
- NULL, &c);
|
||||
+ rv |= Assemble(ss, ident.devname, array_ident, NULL, &c);
|
||||
}
|
||||
} else if (!c.scan)
|
||||
- rv = Assemble(ss, devlist->devname, &ident,
|
||||
- devlist->next, &c);
|
||||
+ rv = Assemble(ss, ident.devname, &ident, devlist->next, &c);
|
||||
else if (devs_found > 0) {
|
||||
if (c.update && devs_found > 1) {
|
||||
pr_err("can only update a single array at a time\n");
|
||||
@@ -1501,7 +1500,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
}
|
||||
- rv = Build(devlist->devname, devlist->next, &s, &c);
|
||||
+ rv = Build(&ident, devlist->next, &s, &c);
|
||||
break;
|
||||
case CREATE:
|
||||
if (c.delay == 0)
|
||||
@@ -1538,9 +1537,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
- rv = Create(ss, devlist->devname,
|
||||
- ident.name, ident.uuid_set ? ident.uuid : NULL,
|
||||
- devs_found - 1, devlist->next, &s, &c);
|
||||
+ rv = Create(ss, &ident, devs_found - 1, devlist->next, &s, &c);
|
||||
break;
|
||||
case MISC:
|
||||
if (devmode == 'E') {
|
||||
@@ -1637,8 +1634,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
for (dv = devlist->next; dv; dv = dv->next) {
|
||||
- rv = Grow_Add_device(devlist->devname, mdfd,
|
||||
- dv->devname);
|
||||
+ rv = Grow_Add_device(ident.devname, mdfd, dv->devname);
|
||||
if (rv)
|
||||
break;
|
||||
}
|
||||
@@ -1651,18 +1647,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (c.delay == 0)
|
||||
c.delay = DEFAULT_BITMAP_DELAY;
|
||||
- rv = Grow_addbitmap(devlist->devname, mdfd, &c, &s);
|
||||
+ rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
|
||||
} else if (grow_continue)
|
||||
- rv = Grow_continue_command(devlist->devname,
|
||||
- mdfd, c.backup_file,
|
||||
- c.verbose);
|
||||
+ rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
|
||||
else if (s.size > 0 || s.raiddisks || s.layout_str ||
|
||||
s.chunk != 0 || s.level != UnSet ||
|
||||
s.data_offset != INVALID_SECTORS) {
|
||||
- rv = Grow_reshape(devlist->devname, mdfd,
|
||||
- devlist->next, &c, &s);
|
||||
+ rv = Grow_reshape(ident.devname, mdfd, devlist->next, &c, &s);
|
||||
} else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) {
|
||||
- rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s);
|
||||
+ rv = Grow_consistency_policy(ident.devname, mdfd, &c, &s);
|
||||
} else if (array_size == 0)
|
||||
pr_err("no changes to --grow\n");
|
||||
break;
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index f0ceeb78..5678eb11 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -1531,14 +1531,11 @@ extern int Assemble(struct supertype *st, char *mddev,
|
||||
struct mddev_dev *devlist,
|
||||
struct context *c);
|
||||
|
||||
-extern int Build(char *mddev, struct mddev_dev *devlist,
|
||||
- struct shape *s, struct context *c);
|
||||
-
|
||||
-extern int Create(struct supertype *st, char *mddev,
|
||||
- char *name, int *uuid,
|
||||
- int subdevs, struct mddev_dev *devlist,
|
||||
- struct shape *s,
|
||||
- struct context *c);
|
||||
+extern int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
|
||||
+ struct context *c);
|
||||
+
|
||||
+extern int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
|
||||
+ struct mddev_dev *devlist, struct shape *s, struct context *c);
|
||||
|
||||
extern int Detail(char *dev, struct context *c);
|
||||
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,253 @@
|
||||
From 67417d9222c505103357191bb0e0ae300892e8a9 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Thu, 1 Jun 2023 09:27:48 +0200
|
||||
Subject: [PATCH 155/165] mdadm: refactor ident->name handling
|
||||
|
||||
Create dedicated setter for name in mddev_ident and propagate it.
|
||||
Following changes are made:
|
||||
- move duplicated code from config.c and mdadm.c into new function.
|
||||
- Add error enum in mdadm.h.
|
||||
- Use MD_NAME_MAX instead of hardcoded value in mddev_ident.
|
||||
- Use secure functions.
|
||||
- Add more detailed verification of the name.
|
||||
- make error messages reusable for cmdline and config:
|
||||
- for cmdline, these are errors so use pr_err().
|
||||
- for config, these are just warnings, so use pr_info().
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
config.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++------
|
||||
lib.c | 18 +++++++++++++
|
||||
mdadm.c | 12 +++------
|
||||
mdadm.h | 20 ++++++++++-----
|
||||
4 files changed, 104 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index 450880e3..a9a0b4f7 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -131,6 +131,34 @@ bool is_devname_ignore(char *devname)
|
||||
return false;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ident_log() - generate and write message to the user.
|
||||
+ * @param_name: name of the property.
|
||||
+ * @value: value of the property.
|
||||
+ * @reason: meaningful description.
|
||||
+ * @cmdline: context dependent actions, see below.
|
||||
+ *
|
||||
+ * The function is made to provide similar error handling for both config and cmdline. The behavior
|
||||
+ * is configurable via @cmdline. Message has following format:
|
||||
+ * "Value "@value" cannot be set for @param_name. Reason: @reason."
|
||||
+ *
|
||||
+ * If cmdline is on:
|
||||
+ * - message is written to stderr.
|
||||
+ * otherwise:
|
||||
+ * - message is written to stdout.
|
||||
+ * - "Value ignored" is added at the end of the message.
|
||||
+ */
|
||||
+static void ident_log(const char *param_name, const char *value, const char *reason,
|
||||
+ const bool cmdline)
|
||||
+{
|
||||
+ if (cmdline == true)
|
||||
+ pr_err("Value \"%s\" cannot be set as %s. Reason: %s.\n", value, param_name,
|
||||
+ reason);
|
||||
+ else
|
||||
+ pr_info("Value \"%s\" cannot be set as %s. Reason: %s. Value ignored.\n", value,
|
||||
+ param_name, reason);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* ident_init() - Set defaults.
|
||||
* @ident: ident pointer, not NULL.
|
||||
@@ -159,6 +187,46 @@ inline void ident_init(struct mddev_ident *ident)
|
||||
ident->uuid_set = 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * _ident_set_name()- set name in &mddev_ident.
|
||||
+ * @ident: pointer to &mddev_ident.
|
||||
+ * @name: name to be set.
|
||||
+ * @cmdline: context dependent actions.
|
||||
+ *
|
||||
+ * If criteria passed, set name in @ident.
|
||||
+ *
|
||||
+ * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
|
||||
+ */
|
||||
+static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *name,
|
||||
+ const bool cmdline)
|
||||
+{
|
||||
+ assert(name);
|
||||
+ assert(ident);
|
||||
+
|
||||
+ const char *prop_name = "name";
|
||||
+
|
||||
+ if (ident->name[0]) {
|
||||
+ ident_log(prop_name, name, "Already defined", cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
|
||||
+ ident_log(prop_name, name, "Too long or empty", cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ snprintf(ident->name, MD_NAME_MAX + 1, "%s", name);
|
||||
+ return MDADM_STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * ident_set_name()- exported, for cmdline.
|
||||
+ */
|
||||
+mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name)
|
||||
+{
|
||||
+ return _ident_set_name(ident, name, true);
|
||||
+}
|
||||
+
|
||||
struct conf_dev {
|
||||
struct conf_dev *next;
|
||||
char *name;
|
||||
@@ -444,14 +512,7 @@ void arrayline(char *line)
|
||||
mis.super_minor = minor;
|
||||
}
|
||||
} else if (strncasecmp(w, "name=", 5) == 0) {
|
||||
- if (mis.name[0])
|
||||
- pr_err("only specify name once, %s ignored.\n",
|
||||
- w);
|
||||
- else if (strlen(w + 5) > 32)
|
||||
- pr_err("name too long, ignoring %s\n", w);
|
||||
- else
|
||||
- strcpy(mis.name, w + 5);
|
||||
-
|
||||
+ _ident_set_name(&mis, w + 5, false);
|
||||
} else if (strncasecmp(w, "bitmap=", 7) == 0) {
|
||||
if (mis.bitmap_file)
|
||||
pr_err("only specify bitmap file once. %s ignored\n",
|
||||
diff --git a/lib.c b/lib.c
|
||||
index 8a4b48e0..03198e2d 100644
|
||||
--- a/lib.c
|
||||
+++ b/lib.c
|
||||
@@ -27,6 +27,24 @@
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
+/**
|
||||
+ * is_string_lq() - Check if string length with NULL byte is lower or equal to requested.
|
||||
+ * @str: string to check.
|
||||
+ * @max_len: max length.
|
||||
+ *
|
||||
+ * @str length must be bigger than 0 and be lower or equal @max_len, including termination byte.
|
||||
+ */
|
||||
+bool is_string_lq(const char * const str, size_t max_len)
|
||||
+{
|
||||
+ assert(str);
|
||||
+
|
||||
+ size_t _len = strnlen(str, max_len);
|
||||
+
|
||||
+ if (_len > 0 && _len < max_len)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
bool is_dev_alive(char *path)
|
||||
{
|
||||
if (!path)
|
||||
diff --git a/mdadm.c b/mdadm.c
|
||||
index 0a56ed26..8bc9304e 100644
|
||||
--- a/mdadm.c
|
||||
+++ b/mdadm.c
|
||||
@@ -690,20 +690,14 @@ int main(int argc, char *argv[])
|
||||
case O(CREATE,'N'):
|
||||
case O(ASSEMBLE,'N'):
|
||||
case O(MISC,'N'):
|
||||
- if (ident.name[0]) {
|
||||
- pr_err("name cannot be set twice. Second value %s.\n", optarg);
|
||||
- exit(2);
|
||||
- }
|
||||
if (mode == MISC && !c.subarray) {
|
||||
pr_err("-N/--name only valid with --update-subarray in misc mode\n");
|
||||
exit(2);
|
||||
}
|
||||
- if (strlen(optarg) > 32) {
|
||||
- pr_err("name '%s' is too long, 32 chars max.\n",
|
||||
- optarg);
|
||||
+
|
||||
+ if (ident_set_name(&ident, optarg) != MDADM_STATUS_SUCCESS)
|
||||
exit(2);
|
||||
- }
|
||||
- strcpy(ident.name, optarg);
|
||||
+
|
||||
continue;
|
||||
|
||||
case O(ASSEMBLE,'m'): /* super-minor for array */
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index 5678eb11..bbf386d6 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -294,6 +294,11 @@ static inline void __put_unaligned32(__u32 val, void *p)
|
||||
#define KIB_TO_BYTES(x) ((x) << 10)
|
||||
#define SEC_TO_BYTES(x) ((x) << 9)
|
||||
|
||||
+/**
|
||||
+ * This is true for native and DDF, IMSM allows 16.
|
||||
+ */
|
||||
+#define MD_NAME_MAX 32
|
||||
+
|
||||
extern const char Name[];
|
||||
|
||||
struct md_bb_entry {
|
||||
@@ -425,6 +430,12 @@ struct spare_criteria {
|
||||
unsigned int sector_size;
|
||||
};
|
||||
|
||||
+typedef enum mdadm_status {
|
||||
+ MDADM_STATUS_SUCCESS = 0,
|
||||
+ MDADM_STATUS_ERROR,
|
||||
+ MDADM_STATUS_UNDEF,
|
||||
+} mdadm_status_t;
|
||||
+
|
||||
enum mode {
|
||||
ASSEMBLE=1,
|
||||
BUILD,
|
||||
@@ -593,7 +604,7 @@ struct mddev_ident {
|
||||
|
||||
int uuid_set;
|
||||
int uuid[4];
|
||||
- char name[33];
|
||||
+ char name[MD_NAME_MAX + 1];
|
||||
|
||||
int super_minor;
|
||||
|
||||
@@ -1609,6 +1620,7 @@ extern int check_partitions(int fd, char *dname,
|
||||
extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev);
|
||||
extern int stat_is_blkdev(char *devname, dev_t *rdev);
|
||||
|
||||
+extern bool is_string_lq(const char * const str, size_t max_len);
|
||||
extern bool is_dev_alive(char *path);
|
||||
extern int get_mdp_major(void);
|
||||
extern int get_maj_min(char *dev, int *major, int *minor);
|
||||
@@ -1626,6 +1638,7 @@ extern void manage_fork_fds(int close_all);
|
||||
extern int continue_via_systemd(char *devnm, char *service_name, char *prefix);
|
||||
|
||||
extern void ident_init(struct mddev_ident *ident);
|
||||
+extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name);
|
||||
|
||||
extern int parse_auto(char *str, char *msg, int config);
|
||||
extern struct mddev_ident *conf_get_ident(char *dev);
|
||||
@@ -2002,11 +2015,6 @@ enum r0layout {
|
||||
/* And another special number needed for --data_offset=variable */
|
||||
#define VARIABLE_OFFSET 3
|
||||
|
||||
-/**
|
||||
- * This is true for native and DDF, IMSM allows 16.
|
||||
- */
|
||||
-#define MD_NAME_MAX 32
|
||||
-
|
||||
/**
|
||||
* is_container() - check if @level is &LEVEL_CONTAINER
|
||||
* @level: level value
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,249 @@
|
||||
From ae5f13a971bc309e0e25087421119b86daf2e510 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Thu, 1 Jun 2023 09:27:49 +0200
|
||||
Subject: [PATCH 156/165] mdadm: define ident_set_devname()
|
||||
|
||||
Use dedicated set method for ident->devname. Now, devname validation
|
||||
is done early for modes where device is created (Build, Create and
|
||||
Assemble). The rules, used for devname validation are derived from
|
||||
config file.
|
||||
|
||||
It could cause regression with execeptional cases where existing device
|
||||
has name which doesn't match criteria for Manage and Grow modes. It is
|
||||
low risk and those modes are not omitted from early devname validation.
|
||||
Use can used main numbered devnode to avoid this problem.
|
||||
Messages exposed to user are changed so it might cause a regression
|
||||
in negative scenarios. Error codes are not changed.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
config.c | 102 +++++++++++++++++++++++++--------
|
||||
mdadm.c | 10 +---
|
||||
mdadm.h | 3 +-
|
||||
tests/00createnames | 3 +
|
||||
tests/templates/names_template | 7 +++
|
||||
5 files changed, 92 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/config.c b/config.c
|
||||
index a9a0b4f7..a0424845 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -122,7 +122,7 @@ int match_keyword(char *word)
|
||||
/**
|
||||
* is_devname_ignore() - check if &devname is a special "<ignore>" keyword.
|
||||
*/
|
||||
-bool is_devname_ignore(char *devname)
|
||||
+bool is_devname_ignore(const char *devname)
|
||||
{
|
||||
static const char keyword[] = "<ignore>";
|
||||
|
||||
@@ -187,6 +187,74 @@ inline void ident_init(struct mddev_ident *ident)
|
||||
ident->uuid_set = 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * _ident_set_devname()- verify devname and set it in &mddev_ident.
|
||||
+ * @ident: pointer to &mddev_ident.
|
||||
+ * @devname: devname to be set.
|
||||
+ * @cmdline: context dependent actions. If set, ignore keyword is not allowed.
|
||||
+ *
|
||||
+ * @devname can have following forms:
|
||||
+ * '<ignore>' keyword (if allowed)
|
||||
+ * /dev/md{number}
|
||||
+ * /dev/md_d{number} (legacy)
|
||||
+ * /dev/md_{name}
|
||||
+ * /dev/md/{name}
|
||||
+ * {name} - anything that doesn't start from '/' or '<'.
|
||||
+ *
|
||||
+ * {name} must follow name's criteria.
|
||||
+ * If criteria passed, duplicate memory and set devname in @ident.
|
||||
+ *
|
||||
+ * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
|
||||
+ */
|
||||
+mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname,
|
||||
+ const bool cmdline)
|
||||
+{
|
||||
+ assert(ident);
|
||||
+ assert(devname);
|
||||
+
|
||||
+ static const char named_dev_pref[] = DEV_NUM_PREF "_";
|
||||
+ static const int named_dev_pref_size = sizeof(named_dev_pref) - 1;
|
||||
+ const char *prop_name = "devname";
|
||||
+ const char *name;
|
||||
+
|
||||
+ if (ident->devname) {
|
||||
+ ident_log(prop_name, devname, "Already defined", cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (is_devname_ignore(devname) == true) {
|
||||
+ if (!cmdline)
|
||||
+ goto pass;
|
||||
+
|
||||
+ ident_log(prop_name, devname, "Special keyword is invalid in this context",
|
||||
+ cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (is_devname_md_numbered(devname) == true || is_devname_md_d_numbered(devname) == true)
|
||||
+ goto pass;
|
||||
+
|
||||
+ if (strncmp(devname, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
|
||||
+ name = devname + DEV_MD_DIR_LEN;
|
||||
+ else if (strncmp(devname, named_dev_pref, named_dev_pref_size) == 0)
|
||||
+ name = devname + named_dev_pref_size;
|
||||
+ else
|
||||
+ name = devname;
|
||||
+
|
||||
+ if (*name == '/' || *name == '<') {
|
||||
+ ident_log(prop_name, devname, "Cannot be started from \'/\' or \'<\'", cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
|
||||
+ ident_log(prop_name, devname, "Invalid length", cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+pass:
|
||||
+ ident->devname = xstrdup(devname);
|
||||
+ return MDADM_STATUS_SUCCESS;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* _ident_set_name()- set name in &mddev_ident.
|
||||
* @ident: pointer to &mddev_ident.
|
||||
@@ -219,6 +287,14 @@ static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *nam
|
||||
return MDADM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ident_set_devname()- exported, for cmdline.
|
||||
+ */
|
||||
+mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *name)
|
||||
+{
|
||||
+ return _ident_set_devname(ident, name, true);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* ident_set_name()- exported, for cmdline.
|
||||
*/
|
||||
@@ -464,29 +540,7 @@ void arrayline(char *line)
|
||||
|
||||
for (w = dl_next(line); w != line; w = dl_next(w)) {
|
||||
if (w[0] == '/' || strchr(w, '=') == NULL) {
|
||||
- /* This names the device, or is '<ignore>'.
|
||||
- * The rules match those in create_mddev.
|
||||
- * 'w' must be:
|
||||
- * /dev/md/{anything}
|
||||
- * /dev/mdNN
|
||||
- * /dev/md_dNN
|
||||
- * <ignore>
|
||||
- * or anything that doesn't start '/' or '<'
|
||||
- */
|
||||
- if (is_devname_ignore(w) == true ||
|
||||
- strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
|
||||
- (w[0] != '/' && w[0] != '<') ||
|
||||
- is_devname_md_numbered(w) == true ||
|
||||
- is_devname_md_d_numbered(w) == true) {
|
||||
- /* This is acceptable */;
|
||||
- if (mis.devname)
|
||||
- pr_err("only give one device per ARRAY line: %s and %s\n",
|
||||
- mis.devname, w);
|
||||
- else
|
||||
- mis.devname = w;
|
||||
- }else {
|
||||
- pr_err("%s is an invalid name for an md device - ignored.\n", w);
|
||||
- }
|
||||
+ _ident_set_devname(&mis, w, false);
|
||||
} else if (strncasecmp(w, "uuid=", 5) == 0) {
|
||||
if (mis.uuid_set)
|
||||
pr_err("only specify uuid once, %s ignored.\n",
|
||||
diff --git a/mdadm.c b/mdadm.c
|
||||
index 8bc9304e..62f981df 100644
|
||||
--- a/mdadm.c
|
||||
+++ b/mdadm.c
|
||||
@@ -1284,7 +1284,8 @@ int main(int argc, char *argv[])
|
||||
pr_err("an md device must be given in this mode\n");
|
||||
exit(2);
|
||||
}
|
||||
- ident.devname = devlist->devname;
|
||||
+ if (ident_set_devname(&ident, devlist->devname) != MDADM_STATUS_SUCCESS)
|
||||
+ exit(1);
|
||||
|
||||
if ((int)ident.super_minor == -2 && c.autof) {
|
||||
pr_err("--super-minor=dev is incompatible with --auto\n");
|
||||
@@ -1301,13 +1302,6 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
- char *bname = basename(ident.devname);
|
||||
-
|
||||
- if (strlen(bname) > MD_NAME_MAX) {
|
||||
- pr_err("Name %s is too long.\n", ident.devname);
|
||||
- exit(1);
|
||||
- }
|
||||
-
|
||||
ret = stat(ident.devname, &stb);
|
||||
if (ident.super_minor == -2 && ret != 0) {
|
||||
pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index bbf386d6..49422e24 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -1638,6 +1638,7 @@ extern void manage_fork_fds(int close_all);
|
||||
extern int continue_via_systemd(char *devnm, char *service_name, char *prefix);
|
||||
|
||||
extern void ident_init(struct mddev_ident *ident);
|
||||
+extern mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *devname);
|
||||
extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name);
|
||||
|
||||
extern int parse_auto(char *str, char *msg, int config);
|
||||
@@ -1660,7 +1661,7 @@ extern void print_escape(char *str);
|
||||
extern int use_udev(void);
|
||||
extern unsigned long GCD(unsigned long a, unsigned long b);
|
||||
extern int conf_name_is_free(char *name);
|
||||
-extern bool is_devname_ignore(char *devname);
|
||||
+extern bool is_devname_ignore(const char *devname);
|
||||
extern bool is_devname_md_numbered(const char *devname);
|
||||
extern bool is_devname_md_d_numbered(const char *devname);
|
||||
extern int conf_verify_devnames(struct mddev_ident *array_list);
|
||||
diff --git a/tests/00createnames b/tests/00createnames
|
||||
index 064eeef2..a95e7d2b 100644
|
||||
--- a/tests/00createnames
|
||||
+++ b/tests/00createnames
|
||||
@@ -39,3 +39,6 @@ mdadm -S "/dev/md0"
|
||||
names_create "/dev/md0" "name"
|
||||
names_verify "/dev/md0" "empty" "name"
|
||||
mdadm -S "/dev/md0"
|
||||
+
|
||||
+# Devnode is a special ignore keyword. Should be rejected.
|
||||
+names_create "<ignore>" "name", "true"
|
||||
diff --git a/tests/templates/names_template b/tests/templates/names_template
|
||||
index 8d2b5c81..6181bfaa 100644
|
||||
--- a/tests/templates/names_template
|
||||
+++ b/tests/templates/names_template
|
||||
@@ -2,6 +2,7 @@
|
||||
function names_create() {
|
||||
local DEVNAME=$1
|
||||
local NAME=$2
|
||||
+ local NEG_TEST=$3
|
||||
|
||||
if [[ -z "$NAME" ]]; then
|
||||
mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
|
||||
@@ -9,6 +10,12 @@ function names_create() {
|
||||
mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force
|
||||
fi
|
||||
|
||||
+ if [[ "$NEG_TEST" == "true" ]]; then
|
||||
+ [[ "$?" == "0" ]] && return 0
|
||||
+ echo "Negative verification failed"
|
||||
+ exit 1
|
||||
+ fi
|
||||
+
|
||||
if [[ "$?" != "0" ]]; then
|
||||
echo "Cannot create device."
|
||||
exit 1
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,471 @@
|
||||
From e2eb503bd797908f515b58428b274f1ba6a05349 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Thu, 1 Jun 2023 09:27:50 +0200
|
||||
Subject: [PATCH 157/165] mdadm: Follow POSIX Portable Character Set
|
||||
|
||||
When the user creates a device with a name that contains whitespace,
|
||||
mdadm timeouts and throws an error. This issue is caused by udev, which
|
||||
truncates /dev/md link until the first whitespace.
|
||||
|
||||
This patch introduces prohibition of characters other than A-Za-z0-9.-_
|
||||
in the device name. Also, it prohibits using leading "-" in device name,
|
||||
so name won't be confused with cli parameter.
|
||||
Set of allowed characters is taken from POSIX 3.280 Portable Character
|
||||
Set. Also, device name length now is limited to NAME_MAX.
|
||||
|
||||
In some places, there are other requirements for string length (e.g. size
|
||||
up to MD_NAME_MAX for device name). This routine is made to follow POSIX
|
||||
and other, more strict limitations should be checked separately.
|
||||
We are aware of the risk of regression in exceptional cases (as
|
||||
escape_devname function is removed) that should be fixed by updating
|
||||
the array name.
|
||||
|
||||
The POSIX validation is added for:
|
||||
- 'name' parameter in every mode.
|
||||
- first devlist entry, for Build, Create, Assemble, Manage, Grow.
|
||||
- config entries, both devname and "name=".
|
||||
|
||||
Additionally, some manual cleanups are made.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Detail.c | 17 ++++--------
|
||||
config.c | 13 ++++++---
|
||||
lib.c | 58 ++++++++++++++++++++++++++++-----------
|
||||
mdadm.8.in | 70 ++++++++++++++++++++---------------------------
|
||||
mdadm.conf.5.in | 4 ---
|
||||
mdadm.h | 2 +-
|
||||
super-intel.c | 47 ++++++++++++++++---------------
|
||||
tests/00confnames | 4 +--
|
||||
8 files changed, 113 insertions(+), 102 deletions(-)
|
||||
|
||||
diff --git a/Detail.c b/Detail.c
|
||||
index 206d88e3..57ac336f 100644
|
||||
--- a/Detail.c
|
||||
+++ b/Detail.c
|
||||
@@ -254,11 +254,9 @@ int Detail(char *dev, struct context *c)
|
||||
fname_from_uuid(st, info, nbuf, ':');
|
||||
printf("MD_UUID=%s\n", nbuf + 5);
|
||||
mp = map_by_uuid(&map, info->uuid);
|
||||
- if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
|
||||
- printf("MD_DEVNAME=");
|
||||
- print_escape(mp->path + DEV_MD_DIR_LEN);
|
||||
- putchar('\n');
|
||||
- }
|
||||
+
|
||||
+ if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
|
||||
+ printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
|
||||
|
||||
if (st->ss->export_detail_super)
|
||||
st->ss->export_detail_super(st);
|
||||
@@ -271,12 +269,9 @@ int Detail(char *dev, struct context *c)
|
||||
__fname_from_uuid(mp->uuid, 0, nbuf, ':');
|
||||
printf("MD_UUID=%s\n", nbuf+5);
|
||||
}
|
||||
- if (mp && mp->path &&
|
||||
- strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
|
||||
- printf("MD_DEVNAME=");
|
||||
- print_escape(mp->path + DEV_MD_DIR_LEN);
|
||||
- putchar('\n');
|
||||
- }
|
||||
+ if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
|
||||
+ printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
|
||||
+
|
||||
map_free(map);
|
||||
}
|
||||
if (!c->no_devices && sra) {
|
||||
diff --git a/config.c b/config.c
|
||||
index a0424845..5f12a1f8 100644
|
||||
--- a/config.c
|
||||
+++ b/config.c
|
||||
@@ -199,9 +199,9 @@ inline void ident_init(struct mddev_ident *ident)
|
||||
* /dev/md_d{number} (legacy)
|
||||
* /dev/md_{name}
|
||||
* /dev/md/{name}
|
||||
- * {name} - anything that doesn't start from '/' or '<'.
|
||||
+ * {name}
|
||||
*
|
||||
- * {name} must follow name's criteria.
|
||||
+ * {name} must follow name's criteria and be POSIX compatible.
|
||||
* If criteria passed, duplicate memory and set devname in @ident.
|
||||
*
|
||||
* Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
|
||||
@@ -241,8 +241,8 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname
|
||||
else
|
||||
name = devname;
|
||||
|
||||
- if (*name == '/' || *name == '<') {
|
||||
- ident_log(prop_name, devname, "Cannot be started from \'/\' or \'<\'", cmdline);
|
||||
+ if (is_name_posix_compatible(name) == false) {
|
||||
+ ident_log(prop_name, name, "Not POSIX compatible", cmdline);
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
@@ -283,6 +283,11 @@ static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *nam
|
||||
return MDADM_STATUS_ERROR;
|
||||
}
|
||||
|
||||
+ if (is_name_posix_compatible(name) == false) {
|
||||
+ ident_log(prop_name, name, "Not POSIX compatible", cmdline);
|
||||
+ return MDADM_STATUS_ERROR;
|
||||
+ }
|
||||
+
|
||||
snprintf(ident->name, MD_NAME_MAX + 1, "%s", name);
|
||||
return MDADM_STATUS_SUCCESS;
|
||||
}
|
||||
diff --git a/lib.c b/lib.c
|
||||
index 03198e2d..7ab59988 100644
|
||||
--- a/lib.c
|
||||
+++ b/lib.c
|
||||
@@ -483,24 +483,50 @@ void print_quoted(char *str)
|
||||
putchar(q);
|
||||
}
|
||||
|
||||
-void print_escape(char *str)
|
||||
+/**
|
||||
+ * is_alphanum() - Check if sign is letter or digit.
|
||||
+ * @c: char to analyze.
|
||||
+ *
|
||||
+ * Similar to isalnum() but additional locales are excluded.
|
||||
+ *
|
||||
+ * Return: %true on success, %false otherwise.
|
||||
+ */
|
||||
+bool is_alphanum(const char c)
|
||||
{
|
||||
- /* print str, but change space and tab to '_'
|
||||
- * as is suitable for device names
|
||||
- */
|
||||
- for (; *str; str++) {
|
||||
- switch (*str) {
|
||||
- case ' ':
|
||||
- case '\t':
|
||||
- putchar('_');
|
||||
- break;
|
||||
- case '/':
|
||||
- putchar('-');
|
||||
- break;
|
||||
- default:
|
||||
- putchar(*str);
|
||||
- }
|
||||
+ if (isupper(c) || islower(c) || isdigit(c) != 0)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * is_name_posix_compatible() - Check if name is POSIX compatible.
|
||||
+ * @name: name to check.
|
||||
+ *
|
||||
+ * POSIX portable file name character set contains ASCII letters,
|
||||
+ * digits, '_', '.', and '-'. Also forbid leading '-'.
|
||||
+ * The length of the name cannot exceed NAME_MAX - 1 (ensure NULL ending).
|
||||
+ *
|
||||
+ * Return: %true on success, %false otherwise.
|
||||
+ */
|
||||
+bool is_name_posix_compatible(const char * const name)
|
||||
+{
|
||||
+ assert(name);
|
||||
+
|
||||
+ char allowed_symbols[] = "-_.";
|
||||
+ const char *n = name;
|
||||
+
|
||||
+ if (!is_string_lq(name, NAME_MAX))
|
||||
+ return false;
|
||||
+
|
||||
+ if (*n == '-')
|
||||
+ return false;
|
||||
+
|
||||
+ while (*n != '\0') {
|
||||
+ if (!is_alphanum(*n) && !strchr(allowed_symbols, *n))
|
||||
+ return false;
|
||||
+ n++;
|
||||
}
|
||||
+ return true;
|
||||
}
|
||||
|
||||
int check_env(char *name)
|
||||
diff --git a/mdadm.8.in b/mdadm.8.in
|
||||
index b7159509..3142436f 100644
|
||||
--- a/mdadm.8.in
|
||||
+++ b/mdadm.8.in
|
||||
@@ -364,7 +364,7 @@ Use the Intel(R) Matrix Storage Manager metadata format. This creates a
|
||||
which is managed in a similar manner to DDF, and is supported by an
|
||||
option-rom on some platforms:
|
||||
.IP
|
||||
-.B https://www.intel.com/content/www/us/en/support/products/122484/memory-and-storage/ssd-software/intel-virtual-raid-on-cpu-intel-vroc.html
|
||||
+.B https://www.intel.com/content/www/us/en/support/products/122484
|
||||
.PP
|
||||
.RE
|
||||
|
||||
@@ -932,17 +932,14 @@ option will be ignored.
|
||||
.BR \-N ", " \-\-name=
|
||||
Set a
|
||||
.B name
|
||||
-for the array. This is currently only effective when creating an
|
||||
-array with a version-1 superblock, or an array in a DDF container.
|
||||
-The name is a simple textual string that can be used to identify array
|
||||
-components when assembling. If name is needed but not specified, it
|
||||
-is taken from the basename of the device that is being created.
|
||||
-e.g. when creating
|
||||
-.I /dev/md/home
|
||||
-the
|
||||
-.B name
|
||||
-will default to
|
||||
-.IR home .
|
||||
+for the array. It must be
|
||||
+.BR "POSIX PORTABLE NAME"
|
||||
+compatible and cannot be longer than 32 chars. This is effective when creating an array
|
||||
+with a v1 metadata, or an external array.
|
||||
+
|
||||
+If name is needed but not specified, it is taken from the basename of the device
|
||||
+that is being created. See
|
||||
+.BR "DEVICE NAMES"
|
||||
|
||||
.TP
|
||||
.BR \-R ", " \-\-run
|
||||
@@ -1132,8 +1129,10 @@ is much safer.
|
||||
|
||||
.TP
|
||||
.BR \-N ", " \-\-name=
|
||||
-Specify the name of the array to assemble. This must be the name
|
||||
-that was specified when creating the array. It must either match
|
||||
+Specify the name of the array to assemble. It must be
|
||||
+.BR "POSIX PORTABLE NAME"
|
||||
+compatible and cannot be longer than 32 chars. This must be the name
|
||||
+that was specified when creating the array. It must either match
|
||||
the name stored in the superblock exactly, or it must match
|
||||
with the current
|
||||
.I homehost
|
||||
@@ -2179,14 +2178,17 @@ Usage:
|
||||
.I md-device
|
||||
.BI \-\-chunk= X
|
||||
.BI \-\-level= Y
|
||||
-.br
|
||||
.BI \-\-raid\-devices= Z
|
||||
.I devices
|
||||
|
||||
.PP
|
||||
-This usage will initialise a new md array, associate some devices with
|
||||
+This usage will initialize a new md array, associate some devices with
|
||||
it, and activate the array.
|
||||
|
||||
+.I md-device
|
||||
+is a new device. This could be standard name or chosen name. For details see:
|
||||
+.BR "DEVICE NAMES"
|
||||
+
|
||||
The named device will normally not exist when
|
||||
.I "mdadm \-\-create"
|
||||
is run, but will be created by
|
||||
@@ -2227,24 +2229,6 @@ array. This feature can be overridden with the
|
||||
.B \-\-force
|
||||
option.
|
||||
|
||||
-When creating an array with version-1 metadata a name for the array is
|
||||
-required.
|
||||
-If this is not given with the
|
||||
-.B \-\-name
|
||||
-option,
|
||||
-.I mdadm
|
||||
-will choose a name based on the last component of the name of the
|
||||
-device being created. So if
|
||||
-.B /dev/md3
|
||||
-is being created, then the name
|
||||
-.B 3
|
||||
-will be chosen.
|
||||
-If
|
||||
-.B /dev/md/home
|
||||
-is being created, then the name
|
||||
-.B home
|
||||
-will be used.
|
||||
-
|
||||
When creating a partition based array, using
|
||||
.I mdadm
|
||||
with version-1.x metadata, the partition type should be set to
|
||||
@@ -2429,12 +2413,10 @@ and
|
||||
|
||||
The
|
||||
.B name
|
||||
-option updates the subarray name in the metadata, it may not affect the
|
||||
-device node name or the device node symlink until the subarray is
|
||||
-re\-assembled. If updating
|
||||
-.B name
|
||||
-would change the UUID of an active subarray this operation is blocked,
|
||||
-and the command will end in an error.
|
||||
+option updates the subarray name in the metadata. It must be
|
||||
+.BR "POSIX PORTABLE NAME"
|
||||
+compatible and cannot be longer than 32 chars. If successes, new value will be respected after
|
||||
+next assembly.
|
||||
|
||||
The
|
||||
.B ppl
|
||||
@@ -3395,6 +3377,10 @@ When
|
||||
.B \-\-incremental
|
||||
mode is used, this file gets a list of arrays currently being created.
|
||||
|
||||
+.SH POSIX PORTABLE NAME
|
||||
+A valid name can only consist of characters "A-Za-z0-9.-_".
|
||||
+The name cannot start with a leading "-" and cannot exceed 255 chars.
|
||||
+
|
||||
.SH DEVICE NAMES
|
||||
|
||||
.I mdadm
|
||||
@@ -3416,6 +3402,10 @@ can be given, or just the suffix of the second sort of name, such as
|
||||
.I home
|
||||
can be given.
|
||||
|
||||
+In every style, raw name must be compatible with
|
||||
+.BR "POSIX PORTABLE NAME"
|
||||
+and has to be no longer than 32 chars.
|
||||
+
|
||||
When
|
||||
.I mdadm
|
||||
chooses device names during auto-assembly or incremental assembly, it
|
||||
diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in
|
||||
index bc2295c2..94e23dd0 100644
|
||||
--- a/mdadm.conf.5.in
|
||||
+++ b/mdadm.conf.5.in
|
||||
@@ -717,10 +717,6 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b
|
||||
.br
|
||||
auto=part
|
||||
.br
|
||||
-# The name of this array contains a space.
|
||||
-.br
|
||||
-ARRAY /dev/md9 name='Data Storage'
|
||||
-.sp
|
||||
POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-*
|
||||
.br
|
||||
action=spare
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index 49422e24..9effb941 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -1617,6 +1617,7 @@ extern int check_raid(int fd, char *name);
|
||||
extern int check_partitions(int fd, char *dname,
|
||||
unsigned long long freesize,
|
||||
unsigned long long size);
|
||||
+extern bool is_name_posix_compatible(const char *path);
|
||||
extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev);
|
||||
extern int stat_is_blkdev(char *devname, dev_t *rdev);
|
||||
|
||||
@@ -1657,7 +1658,6 @@ extern int conf_get_monitor_delay(void);
|
||||
extern char *conf_line(FILE *file);
|
||||
extern char *conf_word(FILE *file, int allow_key);
|
||||
extern void print_quoted(char *str);
|
||||
-extern void print_escape(char *str);
|
||||
extern int use_udev(void);
|
||||
extern unsigned long GCD(unsigned long a, unsigned long b);
|
||||
extern int conf_name_is_free(char *name);
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 77b0066f..05d3b056 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -5561,40 +5561,37 @@ static void imsm_update_version_info(struct intel_super *super)
|
||||
}
|
||||
}
|
||||
|
||||
-static int check_name(struct intel_super *super, char *name, int quiet)
|
||||
+/**
|
||||
+ * imsm_check_name() - check imsm naming criteria.
|
||||
+ * @super: &intel_super pointer, not NULL.
|
||||
+ * @name: name to check.
|
||||
+ * @verbose: verbose level.
|
||||
+ *
|
||||
+ * Name must be no longer than &MAX_RAID_SERIAL_LEN and must be unique across volumes.
|
||||
+ *
|
||||
+ * Returns: &true if @name matches, &false otherwise.
|
||||
+ */
|
||||
+static bool imsm_is_name_allowed(struct intel_super *super, const char * const name,
|
||||
+ const int verbose)
|
||||
{
|
||||
struct imsm_super *mpb = super->anchor;
|
||||
- char *reason = NULL;
|
||||
- char *start = name;
|
||||
- size_t len = strlen(name);
|
||||
int i;
|
||||
|
||||
- if (len > 0) {
|
||||
- while (isspace(start[len - 1]))
|
||||
- start[--len] = 0;
|
||||
- while (*start && isspace(*start))
|
||||
- ++start, --len;
|
||||
- memmove(name, start, len + 1);
|
||||
+ if (is_string_lq(name, MAX_RAID_SERIAL_LEN + 1) == false) {
|
||||
+ pr_vrb("imsm: Name \"%s\" is too long\n", name);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
- if (len > MAX_RAID_SERIAL_LEN)
|
||||
- reason = "must be 16 characters or less";
|
||||
- else if (len == 0)
|
||||
- reason = "must be a non-empty string";
|
||||
-
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
|
||||
if (strncmp((char *) dev->volume, name, MAX_RAID_SERIAL_LEN) == 0) {
|
||||
- reason = "already exists";
|
||||
- break;
|
||||
+ pr_vrb("imsm: Name \"%s\" already exists\n", name);
|
||||
+ return false;
|
||||
}
|
||||
}
|
||||
|
||||
- if (reason && !quiet)
|
||||
- pr_err("imsm volume name %s\n", reason);
|
||||
-
|
||||
- return !reason;
|
||||
+ return true;
|
||||
}
|
||||
|
||||
static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||
@@ -5689,8 +5686,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
|
||||
}
|
||||
}
|
||||
|
||||
- if (!check_name(super, name, 0))
|
||||
+ if (imsm_is_name_allowed(super, name, 1) == false)
|
||||
return 0;
|
||||
+
|
||||
dv = xmalloc(sizeof(*dv));
|
||||
dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
|
||||
/*
|
||||
@@ -8018,7 +8016,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
|
||||
char *ep;
|
||||
int vol;
|
||||
|
||||
- if (!check_name(super, name, 0))
|
||||
+ if (imsm_is_name_allowed(super, name, 1) == false)
|
||||
return 2;
|
||||
|
||||
vol = strtoul(subarray, &ep, 10);
|
||||
@@ -10345,7 +10343,8 @@ static void imsm_process_update(struct supertype *st,
|
||||
if (a->info.container_member == target)
|
||||
break;
|
||||
dev = get_imsm_dev(super, u->dev_idx);
|
||||
- if (a || !check_name(super, name, 1)) {
|
||||
+
|
||||
+ if (a || !dev || imsm_is_name_allowed(super, name, 0) == false) {
|
||||
dprintf("failed to rename subarray-%d\n", target);
|
||||
break;
|
||||
}
|
||||
diff --git a/tests/00confnames b/tests/00confnames
|
||||
index 25a7127b..10823f01 100644
|
||||
--- a/tests/00confnames
|
||||
+++ b/tests/00confnames
|
||||
@@ -79,10 +79,10 @@ names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 11. <devname> with some special symbols and locales, no <name>.
|
||||
-# It needs to wait a while for timeout because udev cannot create a link - known issue.
|
||||
+# <devname> should be ignored.
|
||||
names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config
|
||||
mdadm -I $dev0 --config=$config
|
||||
-names_verify "/dev/md127" "tźż-\.,<>st+-" "name"
|
||||
+names_verify "/dev/md127" "name" "name"
|
||||
mdadm -S "/dev/md127"
|
||||
|
||||
# 12. No <devname> and <name> set.
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,128 @@
|
||||
From ba489abd688bf70c83e70700aaaec5f5e90889c5 Mon Sep 17 00:00:00 2001
|
||||
From: Coly Li <colyli@suse.de>
|
||||
Date: Mon, 14 Aug 2023 00:46:13 +0800
|
||||
Subject: [PATCH 158/165] Incremental: remove obsoleted calls to udisks
|
||||
|
||||
Utility udisks is removed from udev upstream, calling this obsoleted
|
||||
command in run_udisks() doesn't make any sense now.
|
||||
|
||||
This patch removes the calls chain of udisks, which includes routines
|
||||
run_udisk(), force_remove(), and 2 locations where force_remove() are
|
||||
called. Considering force_remove() is removed with udisks util, it is
|
||||
fair to remove Manage_stop() inside force_remove() as well.
|
||||
|
||||
In the two modifications where calling force_remove() are removed,
|
||||
the failure from Manage_subdevs() can be safely ignored, because,
|
||||
1) udisks doesn't exist, no need to check the return value to umount
|
||||
the file system by udisks and remove the component disk again.
|
||||
2) After the 'I' inremental remove, there is another 'r' hot remove
|
||||
following up. The first incremental remove is a best-try effort.
|
||||
|
||||
Therefore in this patch, where force_remove() is removed, the return
|
||||
value of calling Manage_subdevs() is not checked too.
|
||||
|
||||
Signed-off-by: Coly Li <colyli@suse.de>
|
||||
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Cc: Jes Sorensen <jes@trained-monkey.org>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Incremental.c | 64 +++++++++++----------------------------------------
|
||||
1 file changed, 13 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/Incremental.c b/Incremental.c
|
||||
index f13ce027..05b33c45 100644
|
||||
--- a/Incremental.c
|
||||
+++ b/Incremental.c
|
||||
@@ -1628,54 +1628,18 @@ release:
|
||||
return rv;
|
||||
}
|
||||
|
||||
-static void run_udisks(char *arg1, char *arg2)
|
||||
-{
|
||||
- int pid = fork();
|
||||
- int status;
|
||||
- if (pid == 0) {
|
||||
- manage_fork_fds(1);
|
||||
- execl("/usr/bin/udisks", "udisks", arg1, arg2, NULL);
|
||||
- execl("/bin/udisks", "udisks", arg1, arg2, NULL);
|
||||
- exit(1);
|
||||
- }
|
||||
- while (pid > 0 && wait(&status) != pid)
|
||||
- ;
|
||||
-}
|
||||
-
|
||||
-static int force_remove(char *devnm, int fd, struct mdinfo *mdi, int verbose)
|
||||
-{
|
||||
- int rv;
|
||||
- int devid = devnm2devid(devnm);
|
||||
-
|
||||
- run_udisks("--unmount", map_dev(major(devid), minor(devid), 0));
|
||||
- rv = Manage_stop(devnm, fd, verbose, 1);
|
||||
- if (rv) {
|
||||
- /* At least we can try to trigger a 'remove' */
|
||||
- sysfs_uevent(mdi, "remove");
|
||||
- if (verbose)
|
||||
- pr_err("Fail to stop %s too.\n", devnm);
|
||||
- }
|
||||
- return rv;
|
||||
-}
|
||||
-
|
||||
static void remove_from_member_array(struct mdstat_ent *memb,
|
||||
struct mddev_dev *devlist, int verbose)
|
||||
{
|
||||
- int rv;
|
||||
- struct mdinfo mmdi;
|
||||
int subfd = open_dev(memb->devnm);
|
||||
|
||||
if (subfd >= 0) {
|
||||
- rv = Manage_subdevs(memb->devnm, subfd, devlist, verbose,
|
||||
- 0, UOPT_UNDEFINED, 0);
|
||||
- if (rv & 2) {
|
||||
- if (sysfs_init(&mmdi, -1, memb->devnm))
|
||||
- pr_err("unable to initialize sysfs for: %s\n",
|
||||
- memb->devnm);
|
||||
- else
|
||||
- force_remove(memb->devnm, subfd, &mmdi,
|
||||
- verbose);
|
||||
- }
|
||||
+ /*
|
||||
+ * Ignore the return value because it's necessary
|
||||
+ * to handle failure condition here.
|
||||
+ */
|
||||
+ Manage_subdevs(memb->devnm, subfd, devlist, verbose,
|
||||
+ 0, UOPT_UNDEFINED, 0);
|
||||
close(subfd);
|
||||
}
|
||||
}
|
||||
@@ -1758,21 +1722,19 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
|
||||
}
|
||||
free_mdstat(mdstat);
|
||||
} else {
|
||||
- rv |= Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
- verbose, 0, UOPT_UNDEFINED, 0);
|
||||
- if (rv & 2) {
|
||||
- /* Failed due to EBUSY, try to stop the array.
|
||||
- * Give udisks a chance to unmount it first.
|
||||
+ /*
|
||||
+ * This 'I' incremental remove is a try-best effort,
|
||||
+ * the failure condition can be safely ignored
|
||||
+ * because of the following up 'r' remove.
|
||||
*/
|
||||
- rv = force_remove(ent->devnm, mdfd, &mdi, verbose);
|
||||
- goto end;
|
||||
- }
|
||||
+ Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
+ verbose, 0, UOPT_UNDEFINED, 0);
|
||||
}
|
||||
|
||||
devlist.disposition = 'r';
|
||||
rv = Manage_subdevs(ent->devnm, mdfd, &devlist,
|
||||
verbose, 0, UOPT_UNDEFINED, 0);
|
||||
-end:
|
||||
+
|
||||
close(mdfd);
|
||||
free_mdstat(ent);
|
||||
return rv;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 28fc84168646910a9271ebe1a12b1571e14f5900 Mon Sep 17 00:00:00 2001
|
||||
From: Xiao Ni <xni@redhat.com>
|
||||
Date: Thu, 7 Sep 2023 16:57:44 +0800
|
||||
Subject: [PATCH 159/165] mdadm/tests: Fix regular expression failure
|
||||
|
||||
The test fails because of the regular expression.
|
||||
|
||||
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/06name | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/tests/06name b/tests/06name
|
||||
index 4d5e824d..86eaab69 100644
|
||||
--- a/tests/06name
|
||||
+++ b/tests/06name
|
||||
@@ -3,8 +3,8 @@ set -x
|
||||
# create an array with a name
|
||||
|
||||
mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1
|
||||
-mdadm -E $dev0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1
|
||||
-mdadm -D $md0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1
|
||||
+mdadm -E $dev0 | grep 'Name : Fred' > /dev/null || exit 1
|
||||
+mdadm -D $md0 | grep 'Name : Fred' > /dev/null || exit 1
|
||||
mdadm -S $md0
|
||||
|
||||
mdadm -A $md0 --name="Fred" $devlist
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,32 @@
|
||||
From c32b4754014c1eec8cc0c025fad2e9b621486164 Mon Sep 17 00:00:00 2001
|
||||
From: Xiao Ni <xni@redhat.com>
|
||||
Date: Fri, 8 Sep 2023 16:44:35 +0800
|
||||
Subject: [PATCH 161/165] mdadm/tests: Don't run mknod before losetup
|
||||
|
||||
Sometimes it can fail:
|
||||
losetup: /var/tmp/mdtest0: failed to set up loop device: No such device or address
|
||||
/dev/loop0 and /var/tmp/mdtest0 are already created before losetup.
|
||||
|
||||
Because losetup can create device node by itself. So remove mknod.
|
||||
|
||||
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
tests/func.sh | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/tests/func.sh b/tests/func.sh
|
||||
index 9710a53b..5053b012 100644
|
||||
--- a/tests/func.sh
|
||||
+++ b/tests/func.sh
|
||||
@@ -170,7 +170,6 @@ do_setup() {
|
||||
dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1
|
||||
# make sure udev doesn't touch
|
||||
mdadm --zero $targetdir/mdtest$d 2> /dev/null
|
||||
- [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d
|
||||
if [ $d -eq 7 ]
|
||||
then
|
||||
losetup /dev/loop$d $targetdir/mdtest6 # for multipath use
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,75 @@
|
||||
From 6af520a5b4d91cd0fd32ab6361ff4519505c7f47 Mon Sep 17 00:00:00 2001
|
||||
From: Xiao Ni <xni@redhat.com>
|
||||
Date: Tue, 17 Oct 2023 20:35:46 +0800
|
||||
Subject: [PATCH 163/165] mdadm/super1: Add MD_FEATURE_RAID0_LAYOUT if
|
||||
kernel>=5.4
|
||||
|
||||
After and include kernel v5.4, it adds one feature bit MD_FEATURE_RAID0_LAYOUT.
|
||||
It must need to specify a layout for raid0 with more than one zone. But for
|
||||
raid0 with one zone, in fact it also has a defalut layout.
|
||||
|
||||
Now for raid0 with one zone, *unknown* layout can be seen when running mdadm -D
|
||||
command. It's the reason that mdadm doesn't set MD_FEATURE_RAID0_LAYOUT for
|
||||
raid0 with one zone. Then in kernel space, super_1_validate sets mddev->layout
|
||||
to -1 because of no MD_FEATURE_RAID0_LAYOUT. In fact, in raid0 io path, it
|
||||
uses the default layout. Set raid0_need_layout to true if kernel_version<=v5.4.
|
||||
|
||||
Fixes: 329dfc28debb ('Create: add support for RAID0 layouts.')
|
||||
Signed-off-by: Xiao Ni <xni@redhat.com>
|
||||
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
super1.c | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/super1.c b/super1.c
|
||||
index 856b0208..1da71b98 100644
|
||||
--- a/super1.c
|
||||
+++ b/super1.c
|
||||
@@ -1967,6 +1967,14 @@ fail_to_write:
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static bool has_raid0_layout(struct mdp_superblock_1 *sb)
|
||||
+{
|
||||
+ if (sb->level == 0 && sb->layout != 0)
|
||||
+ return true;
|
||||
+ else
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static int write_init_super1(struct supertype *st)
|
||||
{
|
||||
struct mdp_superblock_1 *sb = st->sb;
|
||||
@@ -1978,12 +1986,17 @@ static int write_init_super1(struct supertype *st)
|
||||
unsigned long long sb_offset;
|
||||
unsigned long long data_offset;
|
||||
long bm_offset;
|
||||
- int raid0_need_layout = 0;
|
||||
+ bool raid0_need_layout = false;
|
||||
+
|
||||
+ /* Since linux kernel v5.4, raid0 always has a layout */
|
||||
+ if (has_raid0_layout(sb) && get_linux_version() >= 5004000)
|
||||
+ raid0_need_layout = true;
|
||||
|
||||
for (di = st->info; di; di = di->next) {
|
||||
if (di->disk.state & (1 << MD_DISK_JOURNAL))
|
||||
sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL);
|
||||
- if (sb->level == 0 && sb->layout != 0) {
|
||||
+ if (has_raid0_layout(sb) && !raid0_need_layout) {
|
||||
+
|
||||
struct devinfo *di2 = st->info;
|
||||
unsigned long long s1, s2;
|
||||
s1 = di->dev_size;
|
||||
@@ -1995,7 +2008,7 @@ static int write_init_super1(struct supertype *st)
|
||||
s2 -= di2->data_offset;
|
||||
s2 /= __le32_to_cpu(sb->chunksize);
|
||||
if (s1 != s2)
|
||||
- raid0_need_layout = 1;
|
||||
+ raid0_need_layout = true;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,139 @@
|
||||
From 4dde420fc3e24077ab926f79674eaae1b71de10b Mon Sep 17 00:00:00 2001
|
||||
From: Pawel Piatkowski <pawel.piatkowski@intel.com>
|
||||
Date: Thu, 19 Oct 2023 16:35:24 +0200
|
||||
Subject: [PATCH 164/165] mdadm: remove container_enough logic
|
||||
|
||||
Arrays without enough disk count will be assembled but not
|
||||
started.
|
||||
Now RAIDs will be assembled always (even if they are failed).
|
||||
RAID devices in all states will be assembled and exposed
|
||||
to mdstat.
|
||||
This change affects only IMSM (for ddf it wasn't used,
|
||||
container_enough was set to true always).
|
||||
Removed this logic from incremental_container as well with
|
||||
runstop checking because runstop condition is being verified
|
||||
in assemble_container_content function.
|
||||
|
||||
Signed-off-by: Pawel Piatkowski <pawel.piatkowski@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Incremental.c | 11 -----------
|
||||
mdadm.h | 3 ---
|
||||
super-ddf.c | 1 -
|
||||
super-intel.c | 32 +-------------------------------
|
||||
4 files changed, 1 insertion(+), 46 deletions(-)
|
||||
|
||||
diff --git a/Incremental.c b/Incremental.c
|
||||
index 05b33c45..3551c65b 100644
|
||||
--- a/Incremental.c
|
||||
+++ b/Incremental.c
|
||||
@@ -1467,17 +1467,6 @@ static int Incremental_container(struct supertype *st, char *devname,
|
||||
|
||||
st->ss->getinfo_super(st, &info, NULL);
|
||||
|
||||
- if ((c->runstop > 0 && info.container_enough >= 0) ||
|
||||
- info.container_enough > 0)
|
||||
- /* pass */;
|
||||
- else {
|
||||
- if (c->export) {
|
||||
- printf("MD_STARTED=no\n");
|
||||
- } else if (c->verbose)
|
||||
- pr_err("not enough devices to start the container\n");
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
match = conf_match(st, &info, devname, c->verbose, &rv);
|
||||
if (match == NULL && rv == 2)
|
||||
return rv;
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index 9effb941..b48e6f86 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -377,9 +377,6 @@ struct mdinfo {
|
||||
int container_member; /* for assembling external-metatdata arrays
|
||||
* This is to be used internally by metadata
|
||||
* handler only */
|
||||
- int container_enough; /* flag external handlers can set to
|
||||
- * indicate that subarrays have not enough (-1),
|
||||
- * enough to start (0), or all expected disks (1) */
|
||||
char sys_name[32];
|
||||
struct mdinfo *devs;
|
||||
struct mdinfo *next;
|
||||
diff --git a/super-ddf.c b/super-ddf.c
|
||||
index 7571e3b7..a87e3169 100644
|
||||
--- a/super-ddf.c
|
||||
+++ b/super-ddf.c
|
||||
@@ -1975,7 +1975,6 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
|
||||
info->array.ctime = DECADE + __be32_to_cpu(*cptr);
|
||||
|
||||
info->array.chunk_size = 0;
|
||||
- info->container_enough = 1;
|
||||
|
||||
info->disk.major = 0;
|
||||
info->disk.minor = 0;
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 05d3b056..6bdd5c4c 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -3806,7 +3806,6 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||
struct intel_super *super = st->sb;
|
||||
struct imsm_disk *disk;
|
||||
int map_disks = info->array.raid_disks;
|
||||
- int max_enough = -1;
|
||||
int i;
|
||||
struct imsm_super *mpb;
|
||||
|
||||
@@ -3848,12 +3847,9 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
- int failed, enough, j, missing = 0;
|
||||
+ int j = 0;
|
||||
struct imsm_map *map;
|
||||
- __u8 state;
|
||||
|
||||
- failed = imsm_count_failed(super, dev, MAP_0);
|
||||
- state = imsm_check_degraded(super, dev, failed, MAP_0);
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
|
||||
/* any newly missing disks?
|
||||
@@ -3868,36 +3864,10 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||
|
||||
if (!(ord & IMSM_ORD_REBUILD) &&
|
||||
get_imsm_missing(super, idx)) {
|
||||
- missing = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
-
|
||||
- if (state == IMSM_T_STATE_FAILED)
|
||||
- enough = -1;
|
||||
- else if (state == IMSM_T_STATE_DEGRADED &&
|
||||
- (state != map->map_state || missing))
|
||||
- enough = 0;
|
||||
- else /* we're normal, or already degraded */
|
||||
- enough = 1;
|
||||
- if (is_gen_migration(dev) && missing) {
|
||||
- /* during general migration we need all disks
|
||||
- * that process is running on.
|
||||
- * No new missing disk is allowed.
|
||||
- */
|
||||
- max_enough = -1;
|
||||
- enough = -1;
|
||||
- /* no more checks necessary
|
||||
- */
|
||||
- break;
|
||||
- }
|
||||
- /* in the missing/failed disk case check to see
|
||||
- * if at least one array is runnable
|
||||
- */
|
||||
- max_enough = max(max_enough, enough);
|
||||
}
|
||||
- dprintf("enough: %d\n", max_enough);
|
||||
- info->container_enough = max_enough;
|
||||
|
||||
if (super->disks) {
|
||||
__u32 reserved = imsm_reserved_sectors(super, super->disks);
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,49 @@
|
||||
From d8d09c1633b2f06f88633ab960aa02b41a6bdfb6 Mon Sep 17 00:00:00 2001
|
||||
From: Pawel Piatkowski <pawel.piatkowski@intel.com>
|
||||
Date: Thu, 19 Oct 2023 16:35:25 +0200
|
||||
Subject: [PATCH 165/165] Fix assembling RAID volume by using incremental
|
||||
|
||||
After change "mdadm: remove container_enough logic"
|
||||
IMSM volumes are started immediately. If volume is during
|
||||
reshape, then it will be blocked by block_subarray() during
|
||||
first mdadm -I <devname>. Assemble_container_content() for
|
||||
next disk will see the change because metadata version from
|
||||
sysfs and metadata doesn't match and will execute
|
||||
sysfs_set_array again. Then it fails to set same
|
||||
component_size, it is prohibited by kernel.
|
||||
|
||||
If array is frozen then first sign from metadata version
|
||||
is different ("/" vs "-"), so exclude it from comparison.
|
||||
All we want is to double check that base properties are set
|
||||
and we don't need to call sysfs_set_array again.
|
||||
|
||||
Signed-off-by: Pawel Piatkowski <pawel.piatkowski@intel.com>
|
||||
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
|
||||
---
|
||||
Assemble.c | 10 ++++------
|
||||
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/Assemble.c b/Assemble.c
|
||||
index 5be58e40..0557a007 100644
|
||||
--- a/Assemble.c
|
||||
+++ b/Assemble.c
|
||||
@@ -1990,12 +1990,10 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
- if (strcmp(sra->text_version, content->text_version) != 0) {
|
||||
- if (content->array.major_version == -1 &&
|
||||
- content->array.minor_version == -2 &&
|
||||
- c->readonly &&
|
||||
- content->text_version[0] == '/')
|
||||
- content->text_version[0] = '-';
|
||||
+ /* Fill sysfs properties only if they are not set. Determine it by checking text_version
|
||||
+ * and ignoring special character on the first place.
|
||||
+ */
|
||||
+ if (strcmp(sra->text_version + 1, content->text_version + 1) != 0) {
|
||||
if (sysfs_set_array(content, 9003) != 0) {
|
||||
sysfs_free(sra);
|
||||
return 1;
|
||||
--
|
||||
2.40.1
|
||||
|
@ -0,0 +1,151 @@
|
||||
From 476b00bdeeb6c004b3a758bd842b0fa9e4164508 Mon Sep 17 00:00:00 2001
|
||||
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
Date: Mon, 5 Feb 2024 15:50:29 +0100
|
||||
Subject: [PATCH 1/1] Revert "mdadm: remove container_enough logic"
|
||||
|
||||
Mentioned patch changes way of IMSM member arrays assembling, they are
|
||||
updated by every new drive incremental processes. Previously, member
|
||||
arrays were created and filled once, by last drive incremental process.
|
||||
|
||||
We determined regressions with various impact. Unfortunately, initial
|
||||
testing didn't show them.
|
||||
|
||||
Regressions are connected to drive appearance order and may not be
|
||||
reproducible on every configuration, there are at least two know
|
||||
issues for now:
|
||||
|
||||
- sysfs attributes are filled using old metadata if there is
|
||||
outdated drive and it is enumerated first.
|
||||
|
||||
- rebuild may be aborted and started from beginning after reboot,
|
||||
if drive under rebuild is enumerated as the last one.
|
||||
|
||||
This reverts commit 4dde420fc3e24077ab926f79674eaae1b71de10b. It fixes
|
||||
checkpatch issues and reworks logic to remove empty "if" branch in
|
||||
Incremental.
|
||||
|
||||
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||
---
|
||||
Incremental.c | 9 +++++++++
|
||||
mdadm.h | 7 +++++++
|
||||
super-ddf.c | 1 +
|
||||
super-intel.c | 32 +++++++++++++++++++++++++++++++-
|
||||
4 files changed, 48 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Incremental.c b/Incremental.c
|
||||
index 6cbc164a27b9..30c07c037028 100644
|
||||
--- a/Incremental.c
|
||||
+++ b/Incremental.c
|
||||
@@ -1467,6 +1467,15 @@ static int Incremental_container(struct supertype *st, char *devname,
|
||||
|
||||
st->ss->getinfo_super(st, &info, NULL);
|
||||
|
||||
+ if (info.container_enough < 0 || (info.container_enough == 0 && c->runstop < 1)) {
|
||||
+ if (c->export)
|
||||
+ printf("MD_STARTED=no\n");
|
||||
+ else if (c->verbose)
|
||||
+ pr_err("Not enough devices to start the container.\n");
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
match = conf_match(st, &info, devname, c->verbose, &rv);
|
||||
if (match == NULL && rv == 2)
|
||||
return rv;
|
||||
diff --git a/mdadm.h b/mdadm.h
|
||||
index 709b6104c401..1f28b3e754be 100644
|
||||
--- a/mdadm.h
|
||||
+++ b/mdadm.h
|
||||
@@ -377,6 +377,13 @@ struct mdinfo {
|
||||
int container_member; /* for assembling external-metatdata arrays
|
||||
* This is to be used internally by metadata
|
||||
* handler only */
|
||||
+ /**
|
||||
+ * flag external handlers can set to indicate that subarrays have:
|
||||
+ * - not enough disks to start (-1),
|
||||
+ * - enough disks to start (0),
|
||||
+ * - all expected disks (1).
|
||||
+ */
|
||||
+ int container_enough;
|
||||
char sys_name[32];
|
||||
struct mdinfo *devs;
|
||||
struct mdinfo *next;
|
||||
diff --git a/super-ddf.c b/super-ddf.c
|
||||
index a87e3169d325..7571e3b740c6 100644
|
||||
--- a/super-ddf.c
|
||||
+++ b/super-ddf.c
|
||||
@@ -1975,6 +1975,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
|
||||
info->array.ctime = DECADE + __be32_to_cpu(*cptr);
|
||||
|
||||
info->array.chunk_size = 0;
|
||||
+ info->container_enough = 1;
|
||||
|
||||
info->disk.major = 0;
|
||||
info->disk.minor = 0;
|
||||
diff --git a/super-intel.c b/super-intel.c
|
||||
index 6a664a2e58d3..dbea235dd4bd 100644
|
||||
--- a/super-intel.c
|
||||
+++ b/super-intel.c
|
||||
@@ -3778,6 +3778,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||
struct intel_super *super = st->sb;
|
||||
struct imsm_disk *disk;
|
||||
int map_disks = info->array.raid_disks;
|
||||
+ int max_enough = -1;
|
||||
int i;
|
||||
struct imsm_super *mpb;
|
||||
|
||||
@@ -3819,9 +3820,12 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||
|
||||
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||
- int j = 0;
|
||||
+ int failed, enough, j, missing = 0;
|
||||
struct imsm_map *map;
|
||||
+ __u8 state;
|
||||
|
||||
+ failed = imsm_count_failed(super, dev, MAP_0);
|
||||
+ state = imsm_check_degraded(super, dev, failed, MAP_0);
|
||||
map = get_imsm_map(dev, MAP_0);
|
||||
|
||||
/* any newly missing disks?
|
||||
@@ -3836,11 +3840,37 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||
|
||||
if (!(ord & IMSM_ORD_REBUILD) &&
|
||||
get_imsm_missing(super, idx)) {
|
||||
+ missing = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (state == IMSM_T_STATE_FAILED)
|
||||
+ enough = -1;
|
||||
+ else if (state == IMSM_T_STATE_DEGRADED &&
|
||||
+ (state != map->map_state || missing))
|
||||
+ enough = 0;
|
||||
+ else /* we're normal, or already degraded */
|
||||
+ enough = 1;
|
||||
+ if (is_gen_migration(dev) && missing) {
|
||||
+ /* during general migration we need all disks
|
||||
+ * that process is running on.
|
||||
+ * No new missing disk is allowed.
|
||||
+ */
|
||||
+ max_enough = -1;
|
||||
+ enough = -1;
|
||||
+ /* no more checks necessary
|
||||
+ */
|
||||
+ break;
|
||||
+ }
|
||||
+ /* in the missing/failed disk case check to see
|
||||
+ * if at least one array is runnable
|
||||
+ */
|
||||
+ max_enough = max(max_enough, enough);
|
||||
}
|
||||
|
||||
+ info->container_enough = max_enough;
|
||||
+
|
||||
if (super->disks) {
|
||||
__u32 reserved = imsm_reserved_sectors(super, super->disks);
|
||||
|
||||
--
|
||||
2.32.0 (Apple Git-132)
|
||||
|
@ -1,11 +0,0 @@
|
||||
--- mdadm/Makefile.orig 2021-07-28 21:39:23.887433859 +0800
|
||||
+++ mdadm/Makefile 2021-07-28 21:39:37.989432841 +0800
|
||||
@@ -50,7 +50,7 @@
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
endif
|
||||
CXFLAGS ?= -ggdb
|
||||
-CWFLAGS = -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter
|
||||
+CWFLAGS = -Wall -Wstrict-prototypes -Wextra -Wno-unused-parameter
|
||||
ifdef WARN_UNUSED
|
||||
CWFLAGS += -Wp,-D_FORTIFY_SOURCE=2 -O3
|
||||
endif
|
Loading…
Reference in new issue