Compare commits

...

No commits in common. "c8" and "c10s" have entirely different histories.
c8 ... c10s

351 changed files with 22418 additions and 22689 deletions

6
.gitignore vendored
View File

@ -1 +1,5 @@
SOURCES/mdadm-4.2.tar.xz
.build*
clog
*.src.rpm
*/
/mdadm-4.*.tar.xz

View File

@ -1 +0,0 @@
27f240cff200e00c28a486a028bcdb14f67f8790 SOURCES/mdadm-4.2.tar.xz

View File

@ -0,0 +1,64 @@
From aec3b907de48be54106600a1ecb69d1231f4801d Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Thu, 18 Jan 2024 11:30:15 +0100
Subject: [PATCH 01/41] Remove hardcoded checkpoint interval checking
Mdmon assumes that kernel marks checkpoint every 1/16 of the volume size
and that the checkpoints are equal in size. This is not true, kernel may
mark checkpoints more frequently depending on several factors, including
sync speed. This results in checkpoints reported by mdadm --examine
falling behind the one reported by kernel.
Remove hardcoded checkpoint interval checking.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
monitor.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/monitor.c b/monitor.c
index 4acec678..b8d9e881 100644
--- a/monitor.c
+++ b/monitor.c
@@ -564,22 +564,10 @@ static int read_and_act(struct active_array *a, fd_set *fds)
}
}
- /* Check for recovery checkpoint notifications. We need to be a
- * minimum distance away from the last checkpoint to prevent
- * over checkpointing. Note reshape checkpointing is handled
- * in the second branch.
+ /* Handle reshape checkpointing
*/
- if (sync_completed > a->last_checkpoint &&
- sync_completed - a->last_checkpoint > a->info.component_size >> 4 &&
- a->curr_action > reshape) {
- /* A (non-reshape) sync_action has reached a checkpoint.
- * Record the updated position in the metadata
- */
- a->last_checkpoint = sync_completed;
- a->container->ss->set_array_state(a, a->curr_state <= clean);
- } else if ((a->curr_action == idle && a->prev_action == reshape) ||
- (a->curr_action == reshape &&
- sync_completed > a->last_checkpoint)) {
+ if ((a->curr_action == idle && a->prev_action == reshape) ||
+ (a->curr_action == reshape && sync_completed > a->last_checkpoint)) {
/* Reshape has progressed or completed so we need to
* update the array state - and possibly the array size
*/
@@ -607,8 +595,10 @@ static int read_and_act(struct active_array *a, fd_set *fds)
a->last_checkpoint = sync_completed;
}
- if (sync_completed > a->last_checkpoint)
+ if (sync_completed > a->last_checkpoint) {
a->last_checkpoint = sync_completed;
+ a->container->ss->set_array_state(a, a->curr_state <= clean);
+ }
if (sync_completed >= a->info.component_size)
a->last_checkpoint = 0;
--
2.40.1

View File

@ -0,0 +1,96 @@
From cf87fe75fd83dac008ea116c2c52ec69783fdf6a Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Thu, 18 Jan 2024 11:30:16 +0100
Subject: [PATCH 02/41] monitor: refactor checkpoint update
"if" statements of checkpoint updates have too many responsibilties.
This results in unclear code flow and duplicated code.
Refactor checkpoint update code and simplify "if" statements.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
monitor.c | 51 +++++++++++++++++++++++++--------------------------
1 file changed, 25 insertions(+), 26 deletions(-)
diff --git a/monitor.c b/monitor.c
index b8d9e881..be0bec78 100644
--- a/monitor.c
+++ b/monitor.c
@@ -412,6 +412,7 @@ static int read_and_act(struct active_array *a, fd_set *fds)
int ret = 0;
int count = 0;
struct timeval tv;
+ bool write_checkpoint = false;
a->next_state = bad_word;
a->next_action = bad_action;
@@ -564,40 +565,38 @@ static int read_and_act(struct active_array *a, fd_set *fds)
}
}
- /* Handle reshape checkpointing
- */
- if ((a->curr_action == idle && a->prev_action == reshape) ||
- (a->curr_action == reshape && sync_completed > a->last_checkpoint)) {
- /* Reshape has progressed or completed so we need to
- * update the array state - and possibly the array size
- */
+ /* Update reshape checkpoint, depending if it finished or progressed */
+ if (a->curr_action == idle && a->prev_action == reshape) {
+ char buf[SYSFS_MAX_BUF_SIZE];
+
if (sync_completed != 0)
a->last_checkpoint = sync_completed;
- /* We might need to update last_checkpoint depending on
- * the reason that reshape finished.
- * if array reshape is really finished:
- * set check point to the end, this allows
- * set_array_state() to finalize reshape in metadata
- * if reshape if broken: do not set checkpoint to the end
- * this allows for reshape restart from checkpoint
+
+ /*
+ * If reshape really finished, set checkpoint to the end to finalize it.
+ * Do not set checkpoint if reshape is broken.
+ * Reshape will restart from last checkpoint.
*/
- if ((a->curr_action != reshape) &&
- (a->prev_action == reshape)) {
- char buf[SYSFS_MAX_BUF_SIZE];
- if ((sysfs_get_str(&a->info, NULL,
- "reshape_position",
- buf,
- sizeof(buf)) >= 0) &&
- str_is_none(buf) == true)
+ if (sysfs_get_str(&a->info, NULL, "reshape_position", buf, sizeof(buf)) >= 0)
+ if (str_is_none(buf) == true)
a->last_checkpoint = a->info.component_size;
- }
- a->container->ss->set_array_state(a, a->curr_state <= clean);
- a->last_checkpoint = sync_completed;
+
+ write_checkpoint = true;
}
- if (sync_completed > a->last_checkpoint) {
+ if (a->curr_action >= reshape && sync_completed > a->last_checkpoint) {
+ /* Update checkpoint if neither reshape nor idle action */
a->last_checkpoint = sync_completed;
+
+ write_checkpoint = true;
+ }
+
+ /* Save checkpoint */
+ if (write_checkpoint) {
a->container->ss->set_array_state(a, a->curr_state <= clean);
+
+ if (a->curr_action <= reshape)
+ a->last_checkpoint = sync_completed;
}
if (sync_completed >= a->info.component_size)
--
2.40.1

View File

@ -0,0 +1,47 @@
From fdb7e802f4cf64d067c3abaafa35056e2bc1ed43 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Thu, 18 Jan 2024 11:30:17 +0100
Subject: [PATCH 03/41] Super-intel: Fix first checkpoint restart
When imsm based array is stopped after reaching first checkpoint and
then assembled, first checkpoint is reported as 0.
This behaviour is valid only for initial checkpoint, if the array was
stopped while performing some action.
Last checkpoint value is not taken from metadata but always starts
with 0 and it's incremented when sync_completed in sysfs changes.
In simplification, read_and_act() is responsible for checkpoint updates
and is executed each time sysfs checkpoint update happens. For first
checkpoint it is executed twice and due to marking checkpoint before
triggering any action on the array, it is impossible to read
sync_completed from sysfs in just two iterations.
The workaround to this is not marking any checkpoint for first
sysfs checkpoint after RAID assembly, to preserve checkpoint value
stored in metadata.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/super-intel.c b/super-intel.c
index dbea235d..e61f3f6f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -8771,6 +8771,9 @@ static int imsm_set_array_state(struct active_array *a, int consistent)
super->updates_pending++;
}
+ if (a->prev_action == idle)
+ goto skip_mark_checkpoint;
+
mark_checkpoint:
/* skip checkpointing for general migration,
* it is controlled in mdadm
--
2.40.1

View File

@ -0,0 +1,61 @@
From ea2ca7ed3dbbf881ce08d80fe371f2aaf05011c3 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Thu, 18 Jan 2024 11:30:18 +0100
Subject: [PATCH 04/41] Grow: Move update_tail assign to Grow_reshape()
Due to e919fb0af245 ("FIX: Enable metadata updates for raid0") code
can't enter super-intel.c:3415, resulting in checkpoint not being
saved to metadata for second volume in matrix raid array.
This results in checkpoint being stuck at last value for the
first volume.
Move st->update_tail to Grow_reshape() so it is assigned for each
volume.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Grow.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/Grow.c b/Grow.c
index f95dae82..5498e54f 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2085,9 +2085,10 @@ int Grow_reshape(char *devname, int fd,
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(container);
- if (mdmon_running(st->container_devnm) &&
- st->update_tail == NULL)
- st->update_tail = &st->updates;
+ if (mdmon_running(st->container_devnm) == false) {
+ pr_err("No mdmon found. Grow cannot continue.\n");
+ goto release;
+ }
}
if (s->size == MAX_SIZE)
@@ -3048,6 +3049,8 @@ static int reshape_array(char *container, int fd, char *devname,
dprintf("Cannot get array information.\n");
goto release;
}
+ if (st->update_tail == NULL)
+ st->update_tail = &st->updates;
if (array.level == 0 && info->component_size == 0) {
get_dev_size(fd, NULL, &array_size);
info->component_size = array_size / array.raid_disks;
@@ -5152,9 +5155,7 @@ int Grow_continue_command(char *devname, int fd,
start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(container))
- st->update_tail = &st->updates;
- else {
+ if (mdmon_running(container) == false) {
pr_err("No mdmon found. Grow cannot continue.\n");
ret_val = 1;
goto Grow_continue_command_exit;
--
2.40.1

View File

@ -0,0 +1,56 @@
From 37eeae381a8ed07a1fabb64184fe45d95a861496 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Thu, 18 Jan 2024 11:30:19 +0100
Subject: [PATCH 05/41] Add understanding output section in man
Add new section in man for explaining mdadm outputs.
Describe checkpoint entry.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.8.in | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/mdadm.8.in b/mdadm.8.in
index 96a4a08e..9ba66825 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -3179,7 +3179,7 @@ environment. This can be useful for testing or for disaster
recovery. You should be aware that interoperability may be
compromised by setting this value.
-These change can also be suppressed by adding
+These change can also be suppressed by adding
.B mdadm.imsm.test=1
to the kernel command line. This makes it easy to test IMSM
code in a virtual machine that doesn't have IMSM virtual hardware.
@@ -3454,6 +3454,25 @@ is any string. These names are supported by
since version 3.3 provided they are enabled in
.IR mdadm.conf .
+.SH UNDERSTANDING OUTPUT
+
+.TP
+EXAMINE
+
+.TP
+.B checkpoint
+Checkpoint value is reported when array is performing some action including
+resync, recovery or reshape. Checkpoints allow resuming action from certain
+point if it was interrupted.
+
+Checkpoint is reported as combination of two values: current migration unit
+and number of blocks per unit. By multiplying those values and dividing by
+array size checkpoint progress percentage can be obtained in relation to
+current progress reported in /proc/mdstat. Checkpoint is also related to (and
+sometimes based on) sysfs entry sync_completed but depending on action units
+may differ. Even if units are the same, it should not be expected that
+checkpoint and sync_completed will be exact match nor updated simultaneously.
+
.SH NOTE
.I mdadm
was previously known as
--
2.40.1

View File

@ -0,0 +1,48 @@
From b8f5523a795b8f7e56dfbc139ce7f64728b67726 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 11:56:07 +0100
Subject: [PATCH 06/41] Create: add_disk_to_super() fix resource leak
Fixes resource leak in add_disk_to_super().
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Create.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Create.c b/Create.c
index 8082f54a..7e9170b6 100644
--- a/Create.c
+++ b/Create.c
@@ -279,8 +279,10 @@ static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
dv->devname);
return 1;
}
- if (!fstat_is_blkdev(fd, dv->devname, &rdev))
+ if (!fstat_is_blkdev(fd, dv->devname, &rdev)) {
+ close(fd);
return 1;
+ }
info->disk.major = major(rdev);
info->disk.minor = minor(rdev);
}
@@ -289,6 +291,7 @@ static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
if (st->ss->add_to_super(st, &info->disk, fd, dv->devname,
dv->data_offset)) {
ioctl(mdfd, STOP_ARRAY, NULL);
+ close(fd);
return 1;
}
st->ss->getinfo_super(st, info, NULL);
@@ -297,6 +300,7 @@ static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
*zero_pid = write_zeroes_fork(fd, s, st, dv);
if (*zero_pid <= 0) {
ioctl(mdfd, STOP_ARRAY, NULL);
+ close(fd);
return 1;
}
}
--
2.40.1

View File

@ -0,0 +1,35 @@
From 38cb95dd28fa790ae6d90b169f1fd2b1d09a02f2 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 11:56:08 +0100
Subject: [PATCH 07/41] mdadm: signal_s() init variables
Init sigaction structs in signal_s().
This approach might throw warnings for GCC 4.x and lower.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index 1f28b3e7..75c887e4 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1856,11 +1856,10 @@ static inline char *to_subarray(struct mdstat_ent *ent, char *container)
*/
static inline sighandler_t signal_s(int sig, sighandler_t handler)
{
- struct sigaction new_act;
- struct sigaction old_act;
+ struct sigaction new_act = {0};
+ struct sigaction old_act = {0};
new_act.sa_handler = handler;
- new_act.sa_flags = 0;
if (sigaction(sig, &new_act, &old_act) == 0)
return old_act.sa_handler;
--
2.40.1

View File

@ -0,0 +1,48 @@
From b7d7837128e90c8b496ebc3d88eda1a8ff477392 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 11:56:09 +0100
Subject: [PATCH 08/41] Monitor: open file before check in check_one_sharer()
Open file before performing checks in check_one_sharer() to avoid
file tampering.
Remove redundant access check.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Monitor.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 824a69fc..7cee95d4 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -451,20 +451,17 @@ static int check_one_sharer(int scan)
return 2;
}
- if (access(AUTOREBUILD_PID_PATH, F_OK) != 0)
- return 0;
-
- if (!is_file(AUTOREBUILD_PID_PATH)) {
- pr_err("%s is not a regular file.\n", AUTOREBUILD_PID_PATH);
- return 2;
- }
-
fp = fopen(AUTOREBUILD_PID_PATH, "r");
if (!fp) {
pr_err("Cannot open %s file.\n", AUTOREBUILD_PID_PATH);
return 2;
}
+ if (!is_file(AUTOREBUILD_PID_PATH)) {
+ pr_err("%s is not a regular file.\n", AUTOREBUILD_PID_PATH);
+ return 2;
+ }
+
if (fscanf(fp, "%d", &pid) != 1) {
pr_err("Cannot read pid from %s file.\n", AUTOREBUILD_PID_PATH);
fclose(fp);
--
2.40.1

View File

@ -0,0 +1,34 @@
From e44d13f466e30c018887cd5aaf1212ed9f510813 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 11:56:10 +0100
Subject: [PATCH 09/41] Grow: remove dead condition in Grow_reshape()
Remove dead "if" condition from Grow_reshape(). Sysfs read check is
performed earlier in the code.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Grow.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/Grow.c b/Grow.c
index 5498e54f..c69a342d 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2098,11 +2098,7 @@ int Grow_reshape(char *devname, int fd,
/* got truncated to 32bit, write to
* component_size instead
*/
- if (sra)
- rv = sysfs_set_num(sra, NULL,
- "component_size", s->size);
- else
- rv = -1;
+ rv = sysfs_set_num(sra, NULL, "component_size", s->size);
} else {
rv = md_set_array_info(fd, &array);
--
2.40.1

View File

@ -0,0 +1,34 @@
From 7ccf947eb595c1bb729c32ba18ce171dada76a68 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 11:56:11 +0100
Subject: [PATCH 10/41] super1: check fd before passing to get_dev_size() in
add_to_super1()
Check if file descriptor is valid before passing it to get_dev_size() in
add_to_super().
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super1.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/super1.c b/super1.c
index 871d19f0..5439b7bb 100644
--- a/super1.c
+++ b/super1.c
@@ -1752,7 +1752,10 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
di->devname = devname;
di->disk = *dk;
di->data_offset = data_offset;
- get_dev_size(fd, NULL, &di->dev_size);
+
+ if (is_fd_valid(fd))
+ get_dev_size(fd, NULL, &di->dev_size);
+
di->next = NULL;
*dip = di;
--
2.40.1

View File

@ -0,0 +1,66 @@
From c8772da4b53307546a9a374507bcec3398fc82c4 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 11:56:12 +0100
Subject: [PATCH 11/41] mdmon: refactor md device name check in main()
Refactor mdmon main function to verify if fd is valid prior to checking
device name. This is due to static code analysis complaining after
change b938519e7719 ("util: remove obsolete code from get_md_name").
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdmon.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/mdmon.c b/mdmon.c
index a2038fe6..5fdb5cdb 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -302,12 +302,12 @@ static int mdmon(char *devnm, int must_fork, int takeover);
int main(int argc, char *argv[])
{
char *container_name = NULL;
- char *devnm = NULL;
int status = 0;
int opt;
int all = 0;
int takeover = 0;
int dofork = 1;
+ int mdfd = -1;
bool help = false;
static struct option options[] = {
{"all", 0, NULL, 'a'},
@@ -410,19 +410,20 @@ int main(int argc, char *argv[])
free_mdstat(mdstat);
return status;
- } else {
- int mdfd = open_mddev(container_name, 0);
- devnm = fd2devnm(mdfd);
+ }
+
+ mdfd = open_mddev(container_name, 0);
+ if (is_fd_valid(mdfd)) {
+ char *devnm = fd2devnm(mdfd);
close(mdfd);
- }
- if (!devnm) {
- pr_err("%s is not a valid md device name\n",
- container_name);
- return 1;
+ if (devnm)
+ return mdmon(devnm, dofork && do_fork(), takeover);
}
- return mdmon(devnm, dofork && do_fork(), takeover);
+
+ pr_err("%s is not a valid md device name\n", container_name);
+ return 1;
}
static int mdmon(char *devnm, int must_fork, int takeover)
--
2.40.1

View File

@ -0,0 +1,138 @@
From 4c12714d1ca06533fe7a887966df2558fd2f96b2 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 20 Feb 2024 17:04:44 +0100
Subject: [PATCH 12/41] test: run tests on system level mdadm
The tests run with MDADM_NO_SYSTEMCTL flag by default, however it has
no effect on udev. In case of external metadata, even if flag is set,
udev will trigger systemd to launch mdmon.
This commit changes test execution level, so the tests are run on system
level mdadm, meaning local build must be installed prior to running
tests.
Add warning that the tests are run on system level mdadm and local
build must be installed first.
Do not call mdadm with "quiet" as it makes it not display critical
messages necessary for debug.
Remove forcing speed_limit and add restoring system speed_limit_max
after test execution.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 27 ++++++++++++++++++---------
tests/func.sh | 1 -
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/test b/test
index 49a36c3b..338c2db4 100755
--- a/test
+++ b/test
@@ -1,11 +1,12 @@
#!/bin/bash
#
# run test suite for mdadm
-mdadm=$PWD/mdadm
+mdadm=`which mdadm`
targetdir="/var/tmp"
logdir="$targetdir"
config=/tmp/mdadm.conf
testdir=$PWD/tests
+system_speed_limit=`cat /proc/sys/dev/raid/speed_limit_max`
devlist=
savelogs=0
@@ -20,9 +21,6 @@ DEVTYPE=loop
INTEGRITY=yes
LVM_VOLGROUP=mdtest
-# make sure to test local mdmon, not system one
-export MDADM_NO_SYSTEMCTL=1
-
# assume md0, md1, md2 exist in /dev
md0=/dev/md0
md1=/dev/md1
@@ -41,7 +39,10 @@ ctrl_c() {
ctrl_c_error=1
}
-# mdadm always adds --quiet, and we want to see any unexpected messages
+restore_system_speed_limit() {
+ echo $system_speed_limit > /proc/sys/dev/raid/speed_limit_max
+}
+
mdadm() {
rm -f $targetdir/stderr
case $* in
@@ -63,10 +64,10 @@ mdadm() {
$mdadm --zero $args > /dev/null
}
done
- $mdadm 2> $targetdir/stderr --quiet "$@" --auto=yes
+ $mdadm 2> $targetdir/stderr "$@" --auto=yes
;;
* )
- $mdadm 2> $targetdir/stderr --quiet "$@"
+ $mdadm 2> $targetdir/stderr "$@"
;;
esac
rv=$?
@@ -99,8 +100,6 @@ do_test() {
fi
rm -f $targetdir/stderr
- # this might have been reset: restore the default.
- echo 2000 > /proc/sys/dev/raid/speed_limit_max
do_clean
# source script in a subshell, so it has access to our
# namespace, but cannot change it.
@@ -122,6 +121,7 @@ do_test() {
echo " (KNOWN BROKEN TEST: $_broken_msg)"
fi
fi
+ restore_system_speed_limit
[ "$savelogs" == "1" ] &&
mv -f $targetdir/log $logdir/$_basename.log
[ "$ctrl_c_error" == "1" ] && exit 1
@@ -299,7 +299,15 @@ parse_args() {
done
}
+print_warning() {
+ cat <<-EOF
+ Warning! Tests are performed on system level mdadm!
+ If you want to test local build, you need to install it first!
+ EOF
+}
+
main() {
+ print_warning
do_setup
echo "Testing on linux-$(uname -r) kernel"
@@ -329,6 +337,7 @@ main() {
break
fi
done
+
exit 0
}
diff --git a/tests/func.sh b/tests/func.sh
index 1c1a28a2..b474442b 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -213,7 +213,6 @@ do_setup() {
path1=$dev7
ulimit -c unlimited
[ -f /proc/mdstat ] || modprobe md_mod
- echo 2000 > /proc/sys/dev/raid/speed_limit_max
echo 0 > /sys/module/md_mod/parameters/start_ro
}
--
2.40.1

View File

@ -0,0 +1,43 @@
From 3c3ddeeccc1eb4accb62ce9920de430a564be806 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Wed, 28 Feb 2024 16:37:20 +0100
Subject: [PATCH 13/41] Monitor: Allow no PID in check_one_sharer()
Commit 5fb5479ad100 ("Monitor: open file before check in
check_one_sharer()") introduced a regression that prohibits monitor
from starting if PID file does not exist.
Add check for no PID file.
Add missing fclose().
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Monitor.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/Monitor.c b/Monitor.c
index 7cee95d4..9be2b528 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -453,12 +453,17 @@ static int check_one_sharer(int scan)
fp = fopen(AUTOREBUILD_PID_PATH, "r");
if (!fp) {
+ /* PID file does not exist */
+ if (errno == ENOENT)
+ return 0;
+
pr_err("Cannot open %s file.\n", AUTOREBUILD_PID_PATH);
return 2;
}
if (!is_file(AUTOREBUILD_PID_PATH)) {
pr_err("%s is not a regular file.\n", AUTOREBUILD_PID_PATH);
+ fclose(fp);
return 2;
}
--
2.40.1

View File

@ -0,0 +1,47 @@
From d1cd231ae41d98b2555dbff08d0c79876b5059fe Mon Sep 17 00:00:00 2001
From: Kinga Tanska <kinga.tanska@intel.com>
Date: Tue, 27 Feb 2024 07:36:39 +0100
Subject: [PATCH 14/41] super-intel: respect IMSM_DEVNAME_AS_SERIAL flag
IMSM_DEVNAME_AS_SERIAL flag was respected only when searching
serial using nvme or scsi device wasn't successful. This
flag shall be applied first, to have user settings with
the highest priority.
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index e61f3f6f..4babec9f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -4174,17 +4174,17 @@ static int imsm_read_serial(int fd, char *devname,
memset(buf, 0, sizeof(buf));
+ if (check_env("IMSM_DEVNAME_AS_SERIAL")) {
+ memset(serial, 0, serial_buf_len);
+ fd2devname(fd, (char *) serial);
+ return 0;
+ }
+
rv = nvme_get_serial(fd, buf, sizeof(buf));
if (rv)
rv = scsi_get_serial(fd, buf, sizeof(buf));
- if (rv && check_env("IMSM_DEVNAME_AS_SERIAL")) {
- memset(serial, 0, MAX_RAID_SERIAL_LEN);
- fd2devname(fd, (char *) serial);
- return 0;
- }
-
if (rv != 0) {
if (devname)
pr_err("Failed to retrieve serial for %s\n",
--
2.40.1

View File

@ -0,0 +1,236 @@
From a944da4e1a56cd926e6b21f5aaebc13198265419 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Fri, 23 Feb 2024 15:51:42 +0100
Subject: [PATCH 15/41] mdadm: remove TODO
This file is not updated in 16 years.
No reasons to keep it. Remove it.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
TODO | 213 -----------------------------------------------------------
1 file changed, 213 deletions(-)
delete mode 100644 TODO
diff --git a/TODO b/TODO
deleted file mode 100644
index 279d20db..00000000
--- a/TODO
+++ /dev/null
@@ -1,213 +0,0 @@
- - add 'name' field to metadata type and use it.
- - use validate_geometry more
- - metadata should be able to check/reject bitmap stuff.
-
-DDF:
- Three new metadata types:
- ddf - used only to create a container.
- ddf-bvd - used to create an array in a container
- ddf-svd - used to create a secondary array from bvds.
-
- Usage:
- mdadm -C /dev/ddf1 /dev/sd[abcdef]
- mdadm -C /dev/md1 -e ddf /dev/sd[a-f]
- mdadm -C /dev/md1 -l container /dev/sd[a-f]
-
- Each of these create a new ddf container using all those
- devices. The name 'ddf*' signals that ddf metadata should be used.
- '-e ddf' only supports one level - 'container'. 'container' is only
- supported by ddf.
-
- mdadm -C /dev/md1 -l0 -n4 /dev/ddf1 # or maybe not ???
- mdadm -C /dev/md1 -l1 -n2 /dev/sda /dev/sdb
- If exactly one device is given, and it is a container, we select
- devices from that container.
- If devices are given that are already in use, they must be in use by
- a container, and the array is created in the container.
- If devices given are bvds, we slip under the hood to make
- the svd arrays.
-
- mdadm -A /dev/ddf ......
- base drives make a container. Anything in that container is started
- auto-read-only.
- if /dev/ddf is already assembled, we assemble bvds and svds inside it.
-
-
-2005-dec-20
- Want an incremental assembly mode to work nicely with udev.
- Core usage would be something like
- mdadm --incr-assemble /dev/newdevice
- This would
- - examine the device to determine uuid etc.
- - look for a match in /etc/mdadm.conf, abort if not found
- - find that device and collect current contents
- - perform an 'assemble' analysis to make sure we have the best set of devices.
- - remove or add devices as appropriate
- - possibly start the array if it was complete
-
- Other usages could involve
- - specify which array to auto-add to.
- This requires an existing array for uuid matching... is there any point?
-
- -
-
-
-2004-june-02
- * Don't print 'errors' flag, it is meaningless. DONE
- * Handle new superblock format
- * create device file on demand, particularly partitionable devices. DONE
- BUT figure a way to create the partition devices.
- auto=partN
- * Use Event: interface to listen for events. DONE, untested
- * Make sure mdadm -As can assemble multi-level RAIDs ok.
- * --build to build raid1 or multipath arrays
- clean or not ???
-
-----------------------------------------------------------------------------
-* mdadm --monitor to monitor failed multipath paths and re-instate them.
-
-* Maybe make "--help" fit in 80x24 and have a --long-help with more info. DONE
-
-
-* maybe "missing" instead of <bold>missing</> in doco DONE
-* possibly wait for resync to start, or even finish while assembling.- NO
-
-* -Db should have a devices= entry if possible. - DONE
-* when assembling multipath arrays, ignore any error indicators. - DONE
-* rationalise --monitor usage:
- mdadm --monitor
- doesn't do as expected. DONE
-
-* --assemble could have a --update option. - DONE
- following word can be:
- sparc2.2
- super-minor
-
-* mdadm /dev/md11, where md11 is raid0 can segfault, particularly when looking in the
- [UU_UUU] string ... which doesn't exist !
-It should be more sensible. DONE
-
-Example:
-
-from Raimund Sacherer <raimund.sacherer@ngit.at>
-
-mke2fs -m0 -q /dev/ram1 300
-mount -n -t ext2 /dev/ram1 /tmp
-echo DEVICE /dev/[sh]* >> /tmp/mdadm.conf
-mdadm -Esb /dev/[sh]* 2>/dev/null >> /tmp/mdadm.conf
-mdadm -ARsc /tmp/mdadm.conf
-umount /tmp
-
-
-?? Allow -S /dev/md? - current complains subsequent not a/d/r - DONE
-
-* new "Query" mode to subsume --detail and --examine.
- --query or -Q, takes a device and tells if it is an MD device,
- and also tells in a raid superblock is found.
- DONE
-
-* write mdstat.c to parse /proc/mdstat file
- Build list of arrays: name, rebuild-percent
- DONE
-
-* parse /proc/partitions and map major/minor into /dev/* names,
- and use that for default DEVICE list ????
-
-* --detail --scan to read /proc/mdstat, and then iterate over these,
- but assume --brief. --verbose can override
- check each subdevice to see if it is in conf_get_devs.
- Warn if not.
- DONE, but don't warn yet...
-
-* Support multipath ... maybe...
- maybe DONE
-
-* --follow to syslog
-
-* --follow to move spares around DONE
-
-* --follow to notice other events: DONE
- rebuild started
- spare activated
- spare removed
- spare added
-
-------------------------------------
-- --examine --scan scans all drives and build an mdadm.conf file DONE
-
-- check superblock checksum in examine DONE
-- report "chunk" or "rounding" depending on raid level DONE
-- report "linear" instead of "-1" for raid level DONE
-- decode ayout depending on raid level DONE
-- --verbose and --force flags. DONE
-
-- set md_minor, *_disks for Create - DONE
-- for create raid5, how to choose between
- all working, but not insync
- one missing, one spare, insync DONE (--force)
-- and for raid1 - some failed drives... (missing)
-
-- when RUN_ARRAY, make sure *_disks counts are right
-
-- get --detail to extract extra stuff from superblock,
- like uuid DONE
-- --detail --brief to give a config file line DONE
-- parse config file. DONE
-- test...
-
-- when --assemble --scan, if an underlying device is an md device,
- then try to assemble that device first.
-
-
-- mdadm -S /dev/md0 /dev/md1 gives internal error FIXED
-
-- mdadm --detail --scan print summary of what it can find? DONE
-
-
----------
-Assemble doesn't add spares. - DONE
-Create to allow "missing" name for devices.
-Create to accept "--force" for do exactly what is requested
-- get Assemble to upgrade devices if force flag.
-ARRAY lines in config file to have super_minor=n
-ARRAY lines in config file to have device=pattern, and only accept
- those devices
- If UUID given, insist on that
- If not, but super_minor given, require all found with that minor
- to have same uuid
- If only device given, all valid supers on those devices must have
- same uuid
-allow /dev/mdX as first argument before any options
-Possible --dry-run option for create and assemble--force
-
-Assemble to check that all devices mentioned in superblock
- are present.
-
-New mode: --Monitor (or --Follow)
- Periodically check status of all arrays (listed in config file).
- Log every event and apparent cause - or differences
- Email and alert - or run a program - for important events
- Move spares around if necessary.
-
- An Array line can have a spare-group= field that indicates that
- the array shares spares with other arrays with the same
- spare-group name.
- If an array has a failed and no spares, then check all other
- arrays in the spare group. If one has no failures and a spare,
- then consider that spare.
- Choose the smallest considered spare that is large enough.
- If there is one, then hot-remove it from it's home, and
- hot-add it to the array in question.
-
- --mail-to address
- --alert-handler program
-
- Will also extract information from /proc/mdstat if present,
- and consider 20% marks in rebuild as events.
-
- Events are:
- drive fails - causes mail to be sent
- rebuild started
- spare activated
- spare removed
- spare added
--
2.40.1

View File

@ -0,0 +1,119 @@
From 84d5e05d6fa6bbe6f4a3bdbdb1165dcc463b5207 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Fri, 23 Feb 2024 15:51:43 +0100
Subject: [PATCH 16/41] mdadm: remove makedist
Archives are generated kernel.org automation, no need to submit
them manually, so remove legacy solution.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
makedist | 96 --------------------------------------------------------
1 file changed, 96 deletions(-)
delete mode 100755 makedist
diff --git a/makedist b/makedist
deleted file mode 100755
index 0c4b39eb..00000000
--- a/makedist
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-# avoid silly sorting
-export LANG=C
-arg=$1
-target=~/public_html/source/mdadm
-if [ " $arg" = " test" ]
-then
- target=/tmp/mdadm-test
- rm -rf $target
- mkdir -p $target
-fi
-if [ -d $target ]
-then :
-else echo $target is not a directory
- exit 2
-fi
-set `grep '^#define VERSION' ReadMe.c `
-version=`echo $3 | sed -e 's/"//g'`
-grep "^.TH MDADM 8 .. v$version" mdadm.8.in > /dev/null 2>&1 ||
- {
- echo mdadm.8.in does not mention version $version.
- exit 1
- }
-grep "^.TH MDMON 8 .. v$version" mdmon.8 > /dev/null 2>&1 ||
- {
- echo mdmon.8 does not mention version $version.
- exit 1
- }
-rpmv=`echo $version | tr - _`
-grep "^Version: *$rpmv$" mdadm.spec > /dev/null 2>&1 ||
- {
- echo mdadm.spec does not mention version $version.
- exit 1
- }
-if [ -f ANNOUNCE-$version ]
-then :
-else
- echo ANNOUNCE-$version does not exist
- exit 1
-fi
-if grep "^ANNOUNCE-$version\$" inventory
-then :
-else { cat inventory ; echo ANNOUNCE-$version ; } | sort -o inventory
-fi
-
-echo version = $version
-base=mdadm-$rpmv.tar.gz
-if [ " $arg" != " diff" ]
-then
- if [ -f $target/$base ]
- then
- echo $target/$base exists.
- exit 1
- fi
- trap "rm $target/$base; exit" 1 2 3
- git archive --prefix=mdadm-$rpmv/ HEAD | gzip --best > $target/$base
- chmod a+r $target/$base
- ls -l $target/$base
- if tar tzf $target/$base | sed 's,[^/]*/,,' | sort | diff -u inventory -
- then : correct files found
- else echo "Extra files, or inventory is out-of-date"
- rm $target/$base
- exit 1
- fi
- rpmbuild -ta $target/$base || exit 1
- find ~/rpmbuild/RPMS -name "*mdadm-$version-*" \
- -exec cp {} $target/RPM \;
- cp ANNOUNCE-$version $target/ANNOUNCE
- cp ChangeLog $target/ChangeLog
- if [ " $arg" != " test" ]
- then
- echo -n "Confirm signing this release? "
- read a
- if [ " $a" != " y" ]; then echo OK - bye. ; exit 1; fi
- if zcat $target/$base | gpg -ba > $target/$base.sign && gpg -ba $target/ANNOUNCE
- then
- kup put $target/$base $target/$base.sign \
- /pub/linux/utils/raid/mdadm/mdadm-$version.tar.gz
- kup put $target/ANNOUNCE $target/ANNOUNCE.asc /pub/linux/utils/raid/mdadm/ANNOUNCE
- else
- echo signing failed
- exit 1
- fi
- fi
-else
- if [ ! -f $target/$base ]
- then
- echo $target/$base does not exist.
- exit 1
- fi
- ( cd .. ; ln -s mdadm.v2 mdadm-$version ; tar chf - --exclude=.git --exclude="TAGS" --exclude='*,v' --exclude='*~' --exclude='*.o' --exclude mdadm --exclude=mdadm'.[^ch0-9]' --exclude=RCS mdadm-$version ; rm mdadm-$version ) | gzip --best > /var/tmp/mdadm-new.tgz
- mkdir /var/tmp/mdadm-old ; zcat $target/$base | ( cd /var/tmp/mdadm-old ; tar xf - )
- mkdir /var/tmp/mdadm-new ; zcat /var/tmp/mdadm-new.tgz | ( cd /var/tmp/mdadm-new ; tar xf - )
- diff -ru /var/tmp/mdadm-old /var/tmp/mdadm-new
- rm -rf /var/tmp/mdadm-old /var/tmp/mdadm-new /var/tmp/mdadm-new.tgz
-fi
--
2.40.1

View File

@ -0,0 +1,69 @@
From 9cdcc193cec92c624841d5b70f1b96daafdc4314 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Fri, 23 Feb 2024 15:51:44 +0100
Subject: [PATCH 17/41] mdadm: remove mdadm.spec
This file is outdated, distributions have their own specs.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.spec | 47 -----------------------------------------------
1 file changed, 47 deletions(-)
delete mode 100644 mdadm.spec
diff --git a/mdadm.spec b/mdadm.spec
deleted file mode 100644
index 12e7859a..00000000
--- a/mdadm.spec
+++ /dev/null
@@ -1,47 +0,0 @@
-Summary: mdadm is used for controlling Linux md devices (aka RAID arrays)
-Name: mdadm
-Version: 4.3
-Release: 1
-Source: https://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}.tar.gz
-URL: https://neil.brown.name/blog/mdadm
-License: GPL
-Group: Utilities/System
-BuildRoot: %{_tmppath}/%{name}-root
-Obsoletes: mdctl
-
-%description
-mdadm is a program that can be used to create, manage, and monitor
-Linux MD (Software RAID) devices.
-
-%prep
-%setup -q
-# we want to install in /sbin, not /usr/sbin...
-%define _exec_prefix %{nil}
-
-%build
-# This is a debatable issue. The author of this RPM spec file feels that
-# people who install RPMs (especially given that the default RPM options
-# will strip the binary) are not going to be running gdb against the
-# program.
-make CXFLAGS="$RPM_OPT_FLAGS" SYSCONFDIR="%{_sysconfdir}"
-
-%install
-make DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir} BINDIR=%{_sbindir} install
-install -D -m644 mdadm.conf-example $RPM_BUILD_ROOT/%{_sysconfdir}/mdadm.conf
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-%doc TODO ChangeLog mdadm.conf-example COPYING
-%{_sbindir}/mdadm
-%{_sbindir}/mdmon
-/usr/lib/udev/rules.d/01-md-raid-creating.rules
-/usr/lib/udev/rules.d/63-md-raid-arrays.rules
-/usr/lib/udev/rules.d/64-md-raid-assembly.rules
-/usr/lib/udev/rules.d/69-md-clustered-confirm-device.rules
-%config(noreplace,missingok)/%{_sysconfdir}/mdadm.conf
-%{_mandir}/man*/md*
-
-%changelog
--
2.40.1

View File

@ -0,0 +1,209 @@
From 9282e1169f19676553a82dd49f780285a16e3b9a Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Fri, 23 Feb 2024 15:51:45 +0100
Subject: [PATCH 18/41] mdadm: remove mkinitramfs stuff
This script uses mdadm.static which is known to not be abandoned
(probably not working) from years. Mdadm is integrated with dracut
and mkinitramfs these days.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
README.initramfs | 122 -----------------------------------------------
mkinitramfs | 55 ---------------------
2 files changed, 177 deletions(-)
delete mode 100644 README.initramfs
delete mode 100644 mkinitramfs
diff --git a/README.initramfs b/README.initramfs
deleted file mode 100644
index c5fa6680..00000000
--- a/README.initramfs
+++ /dev/null
@@ -1,122 +0,0 @@
-Assembling md arrays at boot time.
----------------------------------
-December 2005
-
-These notes apply to 2.6 kernels only and, in some cases,
-to 2.6.15 or later.
-
-Md arrays can be assembled at boot time using the 'autodetect' functionality
-which is triggered by storing components of an array in partitions of type
-'fd' - Linux Raid Autodetect.
-They can also be assembled by specifying the component devices in a
-kernel parameter such as
- md=0,/dev/sda,/dev/sdb
-In this case, /dev/md0 will be assembled (because of the 0) from the listed
-devices.
-
-These mechanisms, while useful, do not provide complete functionality
-and are unlikely to be extended. The preferred way to assemble md
-arrays at boot time is using 'mdadm'. To assemble an array which
-contains the root filesystem, mdadm needs to be run before that
-filesystem is mounted, and so needs to be run from an initial-ram-fs.
-It is how this can work that is the primary focus of this document.
-
-It should be noted up front that only the array containing the root
-filesystem should be assembled from the initramfs. Any other arrays
-should be assembled under the control of files on the main filesystem
-as this enhanced flexibility and maintainability.
-
-A minimal initramfs for assembling md arrays can be created using 3
-files and one directory. These are:
-
-/bin Directory
-/bin/mdadm statically linked mdadm binary
-/bin/busybox statically linked busybox binary
-/bin/sh hard link to /bin/busybox
-/init a shell script which call mdadm appropriately.
-
-An example init script is:
-
-==============================================
-#!/bin/sh
-
-echo 'Auto-assembling boot md array'
-mkdir /proc
-mount -t proc proc /proc
-if [ -n "$rootuuid" ]
-then arg=--uuid=$rootuuid
-elif [ -n "$mdminor" ]
-then arg=--super-minor=$mdminor
-else arg=--super-minor=0
-fi
-echo "Using $arg"
-mdadm -Acpartitions $arg --auto=part /dev/mda
-cd /
-mount /dev/mda1 /root || mount /dev/mda /root
-umount /proc
-cd /root
-exec chroot . /sbin/init < /dev/console > /dev/console 2>&1
-=============================================
-
-This could certainly be extended, or merged into a larger init script.
-Though tested and in production use, it is not presented here as
-"The Right Way" to do it, but as a useful example.
-Some key points are:
-
- /proc needs to be mounted so that /proc/partitions can be accessed
- by mdadm, and so that /proc/filesystems can be accessed by mount.
-
- The uuid of the array can be passed in as a kernel parameter
- (rootuuid). As the kernel doesn't use this value, it is made available
- in the environment for /init
-
- If no uuid is given, we default to md0, (--super-minor=0) which is a
- commonly used to store the root filesystem. This may not work in
- all situations.
-
- We assemble the array as a partitionable array (/dev/mda) even if we
- end up using the whole array. There is no cost in using the partitionable
- interface, and in this context it is simpler.
-
- We try mounting both /dev/mda1 and /dev/mda as they are the most like
- part of the array to contain the root filesystem.
-
- The --auto flag is given to mdadm so that it will create /dev/md*
- files automatically. This is needed as /dev will not contain
- and md files, and udev will not create them (as udev only created device
- files after the device exists, and mdadm need the device file to create
- the device). Note that the created md files may not exist in /dev
- of the mounted root filesystem. This needs to be deal with separately
- from mdadm - possibly using udev.
-
- We do not need to create device files for the components which will
- be assembled into /dev/mda. mdadm finds the major/minor numbers from
- /proc/partitions and creates a temporary /dev file if one doesn't already
- exist.
-
-The script "mkinitramfs" which is included with the mdadm distribution
-can be used to create a minimal initramfs. It creates a file called
-'init.cpio.gz' which can be specified as an 'initrd' to lilo or grub
-(or whatever boot loader is being used).
-
-
-
-
-Resume from an md array
------------------------
-
-If you want to make use of the suspend-to-disk/resume functionality in Linux,
-and want to have swap on an md array, you will need to assemble the array
-before resume is possible.
-However, because the array is active in the resumed image, you do not want
-anything written to any drives during the resume process, such as superblock
-updates or array resync.
-
-This can be achieved in 2.6.15-rc1 and later kernels using the
-'start_readonly' module parameter.
-Simply include the command
- echo 1 > /sys/module/md_mod/parameters/start_ro
-before assembling the array with 'mdadm'.
-You can then echo
- 9:0
-or whatever is appropriate to /sys/power/resume to trigger the resume.
diff --git a/mkinitramfs b/mkinitramfs
deleted file mode 100644
index c6275ddb..00000000
--- a/mkinitramfs
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-
-# make sure we are being run in the right directory...
-if [ -f mkinitramfs ]
-then :
-else
- echo >&2 mkinitramfs must be run from the mdadm source directory.
- exit 1
-fi
-if [ -f /bin/busybox ]
-then : good, it exists
- case `file /bin/busybox` in
- *statically* ) : good ;;
- * ) echo >&2 mkinitramfs: /bin/busybox is not statically linked: cannot proceed.
- exit 1
- esac
-else
- echo >&2 "mkinitramfs: /bin/busybox doesn't exist - please install it statically linked."
- exit 1
-fi
-
-rm -rf initramfs
-mkdir initramfs
-mkdir initramfs/bin
-make mdadm.static
-cp mdadm.static initramfs/bin/mdadm
-cp /bin/busybox initramfs/bin/busybox
-ln initramfs/bin/busybox initramfs/bin/sh
-cat <<- END > initramfs/init
- #!/bin/sh
-
- echo 'Auto-assembling boot md array'
- mkdir /proc
- mount -t proc proc /proc
- if [ -n "$rootuuid" ]
- then arg=--uuid=$rootuuid
- elif [ -n "$mdminor" ]
- then arg=--super-minor=$mdminor
- else arg=--super-minor=0
- fi
- echo "Using $arg"
- mdadm -Acpartitions $arg --auto=part /dev/mda
- cd /
- mount /dev/mda1 /root || mount /dev/mda /root
- umount /proc
- cd /root
- exec chroot . /sbin/init < /dev/console > /dev/console 2>&1
-END
-chmod +x initramfs/init
-
-(cd initramfs
- find init bin | cpio -o -H newc | gzip --best
-) > init.cpio.gz
-rm -rf initramfs
-ls -l init.cpio.gz
--
2.40.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
From 60c19530dd7cc6b38a75695a0a3d004bbe60d430 Mon Sep 17 00:00:00 2001
From: Kinga Tanska <kinga.tanska@intel.com>
Date: Tue, 27 Feb 2024 03:36:14 +0100
Subject: [PATCH 20/41] Detail: remove duplicated code
Remove duplicated code from Detail(), where MD_UUID and MD_DEVNAME
are being set. Superblock is no longer required to print system
properties. Now it tries to obtain map in two ways.
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Detail.c | 33 +++++++++++++--------------------
1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/Detail.c b/Detail.c
index aaa3dd6e..f23ec16f 100644
--- a/Detail.c
+++ b/Detail.c
@@ -226,6 +226,9 @@ int Detail(char *dev, struct context *c)
str = map_num(pers, array.level);
if (c->export) {
+ char nbuf[64];
+ struct map_ent *mp = NULL, *map = NULL;
+
if (array.raid_disks) {
if (str)
printf("MD_LEVEL=%s\n", str);
@@ -247,32 +250,22 @@ int Detail(char *dev, struct context *c)
array.minor_version);
}
- if (st && st->sb && info) {
- char nbuf[64];
- struct map_ent *mp, *map = NULL;
-
- fname_from_uuid(st, info, nbuf, ':');
- printf("MD_UUID=%s\n", nbuf + 5);
+ if (info)
mp = map_by_uuid(&map, info->uuid);
+ if (!mp)
+ mp = map_by_devnm(&map, fd2devnm(fd));
- if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ if (mp) {
+ __fname_from_uuid(mp->uuid, 0, nbuf, ':');
+ printf("MD_UUID=%s\n", nbuf + 5);
+ if (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 (st && st->sb) {
if (st->ss->export_detail_super)
st->ss->export_detail_super(st);
- map_free(map);
- } else {
- struct map_ent *mp, *map = NULL;
- char nbuf[64];
- mp = map_by_devnm(&map, fd2devnm(fd));
- if (mp) {
- __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=%s\n", mp->path + DEV_MD_DIR_LEN);
-
- map_free(map);
}
if (!c->no_devices && sra) {
struct mdinfo *mdi;
--
2.40.1

View File

@ -0,0 +1,286 @@
From 0c0f09cb035b6a27a1d11c54836742a9945a5014 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:05 +0100
Subject: [PATCH 21/41] mdadm: Add functions for spare criteria verification
It is done similar way in few places. As a result, two almost identical
functions (dev_size_from_id() and dev_sector_size_from_id()) are
removed. Now, it uses same file descriptor to send two ioctls.
Two extern functions are added, in next patches
disk_fd_matches_criteria() is used.
Next optimization is inline zeroing struct spare_criteria. With that,
we don't need to reset values in get_spare_criteria_imsm().
Dedicated boolean field for checking if criteria are filled is added.
We don't need to execute the code if it is not set.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Incremental.c | 2 +-
Monitor.c | 14 +------
mdadm.h | 6 ++-
super-intel.c | 4 +-
util.c | 112 ++++++++++++++++++++++++++------------------------
5 files changed, 67 insertions(+), 71 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 30c07c03..2b5a5859 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -874,7 +874,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
struct domainlist *dl = NULL;
struct mdinfo *sra;
unsigned long long devsize, freesize = 0;
- struct spare_criteria sc = {0, 0};
+ struct spare_criteria sc = {0};
if (is_subarray(mp->metadata))
continue;
diff --git a/Monitor.c b/Monitor.c
index 9be2b528..1ece8712 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -1070,22 +1070,12 @@ static dev_t choose_spare(struct state *from, struct state *to,
for (d = from->raid; !dev && d < MAX_DISKS; d++) {
if (from->devid[d] > 0 && from->devstate[d] == 0) {
struct dev_policy *pol;
- unsigned long long dev_size;
- unsigned int dev_sector_size;
if (to->metadata->ss->external &&
test_partition_from_id(from->devid[d]))
continue;
- if (sc->min_size &&
- dev_size_from_id(from->devid[d], &dev_size) &&
- dev_size < sc->min_size)
- continue;
-
- if (sc->sector_size &&
- dev_sector_size_from_id(from->devid[d],
- &dev_sector_size) &&
- sc->sector_size != dev_sector_size)
+ if (devid_matches_criteria(from->devid[d], sc) == false)
continue;
pol = devid_policy(from->devid[d]);
@@ -1170,12 +1160,12 @@ static void try_spare_migration(struct state *statelist)
{
struct state *from;
struct state *st;
- struct spare_criteria sc;
link_containers_with_subarrays(statelist);
for (st = statelist; st; st = st->next)
if (st->active < st->raid && st->spare == 0 && !st->err) {
struct domainlist *domlist = NULL;
+ struct spare_criteria sc = {0};
int d;
struct state *to = st;
diff --git a/mdadm.h b/mdadm.h
index 75c887e4..e8abd730 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -430,6 +430,7 @@ struct createinfo {
};
struct spare_criteria {
+ bool criteria_set;
unsigned long long min_size;
unsigned int sector_size;
};
@@ -1368,8 +1369,6 @@ extern struct supertype *dup_super(struct supertype *st);
extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
extern int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep);
extern int must_be_container(int fd);
-extern int dev_size_from_id(dev_t id, unsigned long long *size);
-extern int dev_sector_size_from_id(dev_t id, unsigned int *size);
void wait_for(char *dev, int fd);
/*
@@ -1708,6 +1707,9 @@ extern int assemble_container_content(struct supertype *st, int mdfd,
#define INCR_UNSAFE 2
#define INCR_ALREADY 4
#define INCR_YES 8
+
+extern bool devid_matches_criteria(dev_t devid, struct spare_criteria *sc);
+extern bool disk_fd_matches_criteria(int disk_fd, struct spare_criteria *sc);
extern struct mdinfo *container_choose_spares(struct supertype *st,
struct spare_criteria *criteria,
struct domainlist *domlist,
diff --git a/super-intel.c b/super-intel.c
index 4babec9f..39ec4754 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1748,9 +1748,6 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
int i;
unsigned long long size = 0;
- c->min_size = 0;
- c->sector_size = 0;
-
if (!super)
return -EINVAL;
/* find first active disk in array */
@@ -1774,6 +1771,7 @@ int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
c->min_size = size * 512;
c->sector_size = super->sector_size;
+ c->criteria_set = true;
return 0;
}
diff --git a/util.c b/util.c
index b1454473..041e78cf 100644
--- a/util.c
+++ b/util.c
@@ -1266,40 +1266,6 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
return st;
}
-int dev_size_from_id(dev_t id, unsigned long long *size)
-{
- char buf[20];
- int fd;
-
- sprintf(buf, "%d:%d", major(id), minor(id));
- fd = dev_open(buf, O_RDONLY);
- if (fd < 0)
- return 0;
- if (get_dev_size(fd, NULL, size)) {
- close(fd);
- return 1;
- }
- close(fd);
- return 0;
-}
-
-int dev_sector_size_from_id(dev_t id, unsigned int *size)
-{
- char buf[20];
- int fd;
-
- sprintf(buf, "%d:%d", major(id), minor(id));
- fd = dev_open(buf, O_RDONLY);
- if (fd < 0)
- return 0;
- if (get_dev_sector_size(fd, NULL, size)) {
- close(fd);
- return 1;
- }
- close(fd);
- return 0;
-}
-
struct supertype *dup_super(struct supertype *orig)
{
struct supertype *st;
@@ -2088,6 +2054,60 @@ void append_metadata_update(struct supertype *st, void *buf, int len)
unsigned int __invalid_size_argument_for_IOC = 0;
#endif
+/**
+ * disk_fd_matches_criteria() - check if device matches spare criteria.
+ * @disk_fd: file descriptor of the disk.
+ * @sc: criteria to test.
+ *
+ * Return: true if disk matches criteria, false otherwise.
+ */
+bool disk_fd_matches_criteria(int disk_fd, struct spare_criteria *sc)
+{
+ unsigned int dev_sector_size = 0;
+ unsigned long long dev_size = 0;
+
+ if (!sc->criteria_set)
+ return true;
+
+ if (!get_dev_size(disk_fd, NULL, &dev_size) || dev_size < sc->min_size)
+ return false;
+
+ if (!get_dev_sector_size(disk_fd, NULL, &dev_sector_size) ||
+ sc->sector_size != dev_sector_size)
+ return false;
+
+ return true;
+}
+
+/**
+ * devid_matches_criteria() - check if device referenced by devid matches spare criteria.
+ * @devid: devid of the device to check.
+ * @sc: criteria to test.
+ *
+ * Return: true if disk matches criteria, false otherwise.
+ */
+bool devid_matches_criteria(dev_t devid, struct spare_criteria *sc)
+{
+ char buf[NAME_MAX];
+ bool ret;
+ int fd;
+
+ if (!sc->criteria_set)
+ return true;
+
+ snprintf(buf, NAME_MAX, "%d:%d", major(devid), minor(devid));
+
+ fd = dev_open(buf, O_RDONLY);
+ if (!is_fd_valid(fd))
+ return false;
+
+ /* Error code inherited */
+ ret = disk_fd_matches_criteria(fd, sc);
+
+ close(fd);
+ return ret;
+}
+
/* Pick all spares matching given criteria from a container
* if min_size == 0 do not check size
* if domlist == NULL do not check domains
@@ -2111,28 +2131,13 @@ struct mdinfo *container_choose_spares(struct supertype *st,
dp = &disks->devs;
disks->array.spare_disks = 0;
while (*dp) {
- int found = 0;
+ bool found = false;
+
d = *dp;
if (d->disk.state == 0) {
- /* check if size is acceptable */
- unsigned long long dev_size;
- unsigned int dev_sector_size;
- int size_valid = 0;
- int sector_size_valid = 0;
-
dev_t dev = makedev(d->disk.major,d->disk.minor);
- if (!criteria->min_size ||
- (dev_size_from_id(dev, &dev_size) &&
- dev_size >= criteria->min_size))
- size_valid = 1;
-
- if (!criteria->sector_size ||
- (dev_sector_size_from_id(dev, &dev_sector_size) &&
- criteria->sector_size == dev_sector_size))
- sector_size_valid = 1;
-
- found = size_valid && sector_size_valid;
+ found = devid_matches_criteria(dev, criteria);
/* check if domain matches */
if (found && domlist) {
@@ -2141,7 +2146,8 @@ struct mdinfo *container_choose_spares(struct supertype *st,
pol_add(&pol, pol_domain,
spare_group, NULL);
if (domain_test(domlist, pol, metadata) != 1)
- found = 0;
+ found = false;
+
dev_policy_free(pol);
}
}
--
2.40.1

View File

@ -0,0 +1,357 @@
From f656201188d73cdc2726265f1348f8ffbf7587be Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:06 +0100
Subject: [PATCH 22/41] mdadm: drop get_required_spare_criteria()
Only IMSM implements get_spare_criteria, so load_super() in
get_required_spare_criteria() is dead code. It is moved inside
metadata handler, because only IMSM implements it.
Give possibility to provide devnode to be opened. With that we can hide
load_container() used only to fill spare criteria inside handler
and simplify implementation in generic code.
Add helper function for testing spare criteria in Incremental and
error messages.
File descriptor in get_spare_criteria_imsm() is always opened on purpose.
New functionality added in next patches will require it. For the same
reason, function is moved to other place.
No functional changes.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Incremental.c | 77 ++++++++++++++++++++++----------
Monitor.c | 35 +++------------
mdadm.h | 5 +--
super-intel.c | 120 +++++++++++++++++++++++++++++++++-----------------
4 files changed, 140 insertions(+), 97 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 2b5a5859..66c2cc86 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -833,6 +833,53 @@ container_members_max_degradation(struct map_ent *map, struct map_ent *me)
return max_degraded;
}
+/**
+ * incremental_external_test_spare_criteria() - helper to test spare criteria.
+ * @st: supertype, must be not NULL, it is duplicated here.
+ * @container_devnm: devnm of the container.
+ * @disk_fd: file descriptor of device to tested.
+ * @verbose: verbose flag.
+ *
+ * The function is used on new drive verification path to check if it can be added to external
+ * container. To test spare criteria, metadata must be loaded. It duplicates super to not mess in
+ * original one.
+ * Function is executed if superblock supports get_spare_criteria(), otherwise success is returned.
+ */
+mdadm_status_t incremental_external_test_spare_criteria(struct supertype *st, char *container_devnm,
+ int disk_fd, int verbose)
+{
+ mdadm_status_t rv = MDADM_STATUS_ERROR;
+ char container_devname[PATH_MAX];
+ struct spare_criteria sc = {0};
+ struct supertype *dup;
+
+ if (!st->ss->get_spare_criteria)
+ return MDADM_STATUS_SUCCESS;
+
+ dup = dup_super(st);
+ snprintf(container_devname, PATH_MAX, "/dev/%s", container_devnm);
+
+ if (dup->ss->get_spare_criteria(dup, container_devname, &sc) != 0) {
+ if (verbose > 1)
+ pr_err("Failed to get spare criteria for %s\n", container_devname);
+ goto out;
+ }
+
+ if (!disk_fd_matches_criteria(disk_fd, &sc)) {
+ if (verbose > 1)
+ pr_err("Disk does not match spare criteria for %s\n", container_devname);
+ goto out;
+ }
+
+ rv = MDADM_STATUS_SUCCESS;
+
+out:
+ dup->ss->free_super(dup);
+ free(dup);
+
+ return rv;
+}
+
static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
struct map_ent *target, int bare,
struct supertype *st, int verbose)
@@ -873,8 +920,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
struct supertype *st2;
struct domainlist *dl = NULL;
struct mdinfo *sra;
- unsigned long long devsize, freesize = 0;
- struct spare_criteria sc = {0};
+ unsigned long long freesize = 0;
if (is_subarray(mp->metadata))
continue;
@@ -925,34 +971,19 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol,
if (sra->array.failed_disks == -1)
sra->array.failed_disks = container_members_max_degradation(map, mp);
- get_dev_size(dfd, NULL, &devsize);
if (sra->component_size == 0) {
- /* true for containers, here we must read superblock
- * to obtain minimum spare size */
- struct supertype *st3 = dup_super(st2);
- int mdfd = open_dev(mp->devnm);
- if (mdfd < 0) {
- free(st3);
+ /* true for containers */
+ if (incremental_external_test_spare_criteria(st2, mp->devnm, dfd, verbose))
goto next;
- }
- if (st3->ss->load_container &&
- !st3->ss->load_container(st3, mdfd, mp->path)) {
- if (st3->ss->get_spare_criteria)
- st3->ss->get_spare_criteria(st3, &sc);
- st3->ss->free_super(st3);
- }
- free(st3);
- close(mdfd);
}
- if ((sra->component_size > 0 &&
- st2->ss->validate_geometry(st2, sra->array.level, sra->array.layout,
+
+ if (sra->component_size > 0 &&
+ st2->ss->validate_geometry(st2, sra->array.level, sra->array.layout,
sra->array.raid_disks, &sra->array.chunk_size,
sra->component_size,
sra->devs ? sra->devs->data_offset : INVALID_SECTORS,
devname, &freesize, sra->consistency_policy,
- 0) &&
- freesize < sra->component_size) ||
- (sra->component_size == 0 && devsize < sc.min_size)) {
+ 0) && freesize < sra->component_size) {
if (verbose > 1)
pr_err("not adding %s to %s as it is too small\n",
devname, mp->path);
diff --git a/Monitor.c b/Monitor.c
index 1ece8712..6b4560ae 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -1008,34 +1008,6 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
return new_found;
}
-static int get_required_spare_criteria(struct state *st,
- struct spare_criteria *sc)
-{
- int fd;
-
- if (!st->metadata || !st->metadata->ss->get_spare_criteria) {
- sc->min_size = 0;
- sc->sector_size = 0;
- return 0;
- }
-
- fd = open(st->devname, O_RDONLY);
- if (fd < 0)
- return 1;
- if (st->metadata->ss->external)
- st->metadata->ss->load_container(st->metadata, fd, st->devname);
- else
- st->metadata->ss->load_super(st->metadata, fd, st->devname);
- close(fd);
- if (!st->metadata->sb)
- return 1;
-
- st->metadata->ss->get_spare_criteria(st->metadata, sc);
- st->metadata->ss->free_super(st->metadata);
-
- return 0;
-}
-
static int check_donor(struct state *from, struct state *to)
{
struct state *sub;
@@ -1178,8 +1150,11 @@ static void try_spare_migration(struct state *statelist)
/* member of a container */
to = to->parent;
- if (get_required_spare_criteria(to, &sc))
- continue;
+ if (to->metadata->ss->get_spare_criteria)
+ if (to->metadata->ss->get_spare_criteria(to->metadata, to->devname,
+ &sc))
+ continue;
+
if (to->metadata->ss->external) {
/* We must make sure there is
* no suitable spare in container already.
diff --git a/mdadm.h b/mdadm.h
index e8abd730..cbc586f5 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1116,10 +1116,9 @@ extern struct superswitch {
* Return spare criteria for array:
* - minimum disk size can be used in array;
* - sector size can be used in array.
- * Return values: 0 - for success and -EINVAL on error.
*/
- int (*get_spare_criteria)(struct supertype *st,
- struct spare_criteria *sc);
+ mdadm_status_t (*get_spare_criteria)(struct supertype *st, char *mddev_path,
+ struct spare_criteria *sc);
/* Find somewhere to put a bitmap - possibly auto-size it - and
* update the metadata to record this. The array may be newly
* created, in which case data_size may be updated, or it might
diff --git a/super-intel.c b/super-intel.c
index 39ec4754..7ad391ac 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1736,46 +1736,6 @@ static __u32 imsm_min_reserved_sectors(struct intel_super *super)
return (remainder < rv) ? remainder : rv;
}
-/*
- * Return minimum size of a spare and sector size
- * that can be used in this array
- */
-int get_spare_criteria_imsm(struct supertype *st, struct spare_criteria *c)
-{
- struct intel_super *super = st->sb;
- struct dl *dl;
- struct extent *e;
- int i;
- unsigned long long size = 0;
-
- if (!super)
- return -EINVAL;
- /* find first active disk in array */
- dl = super->disks;
- while (dl && (is_failed(&dl->disk) || dl->index == -1))
- dl = dl->next;
- if (!dl)
- return -EINVAL;
- /* find last lba used by subarrays */
- e = get_extents(super, dl, 0);
- if (!e)
- return -EINVAL;
- for (i = 0; e[i].size; i++)
- continue;
- if (i > 0)
- size = e[i-1].start + e[i-1].size;
- free(e);
-
- /* add the amount of space needed for metadata */
- size += imsm_min_reserved_sectors(super);
-
- c->min_size = size * 512;
- c->sector_size = super->sector_size;
- c->criteria_set = true;
-
- return 0;
-}
-
static bool is_gen_migration(struct imsm_dev *dev);
#define IMSM_4K_DIV 8
@@ -11295,6 +11255,84 @@ static const char *imsm_get_disk_controller_domain(const char *path)
return drv;
}
+/**
+ * get_spare_criteria_imsm() - set spare criteria.
+ * @st: supertype.
+ * @mddev_path: path to md device devnode, it must be container.
+ * @c: spare_criteria struct to fill, not NULL.
+ *
+ * If superblock is not loaded, use mddev_path to load_container. It must be given in this case.
+ * Filles size and sector size accordingly to superblock.
+ */
+mdadm_status_t get_spare_criteria_imsm(struct supertype *st, char *mddev_path,
+ struct spare_criteria *c)
+{
+ mdadm_status_t ret = MDADM_STATUS_ERROR;
+ bool free_superblock = false;
+ unsigned long long size = 0;
+ struct intel_super *super;
+ struct extent *e;
+ struct dl *dl;
+ int i;
+
+ /* If no superblock and no mddev_path, we cannot load superblock. */
+ assert(st->sb || mddev_path);
+
+ if (mddev_path) {
+ int fd = open(mddev_path, O_RDONLY);
+
+ if (!is_fd_valid(fd))
+ return MDADM_STATUS_ERROR;
+
+ if (!st->sb) {
+ if (load_container_imsm(st, fd, st->devnm)) {
+ close(fd);
+ return MDADM_STATUS_ERROR;
+ }
+ free_superblock = true;
+ }
+ close(fd);
+ }
+
+ super = st->sb;
+
+ /* find first active disk in array */
+ dl = super->disks;
+ while (dl && (is_failed(&dl->disk) || dl->index == -1))
+ dl = dl->next;
+
+ if (!dl)
+ goto out;
+
+ /* find last lba used by subarrays */
+ e = get_extents(super, dl, 0);
+ if (!e)
+ goto out;
+
+ for (i = 0; e[i].size; i++)
+ continue;
+ if (i > 0)
+ size = e[i - 1].start + e[i - 1].size;
+ free(e);
+
+ /* add the amount of space needed for metadata */
+ size += imsm_min_reserved_sectors(super);
+
+ c->min_size = size * 512;
+ c->sector_size = super->sector_size;
+ c->criteria_set = true;
+ ret = MDADM_STATUS_SUCCESS;
+
+out:
+ if (free_superblock)
+ free_super_imsm(st);
+
+ if (ret != MDADM_STATUS_SUCCESS)
+ c->criteria_set = false;
+
+ return ret;
+}
+
static char *imsm_find_array_devnm_by_subdev(int subdev, char *container)
{
static char devnm[32];
@@ -11425,7 +11463,7 @@ static struct mdinfo *get_spares_for_grow(struct supertype *st)
{
struct spare_criteria sc;
- get_spare_criteria_imsm(st, &sc);
+ get_spare_criteria_imsm(st, NULL, &sc);
return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
}
--
2.40.1

View File

@ -0,0 +1,64 @@
From e97ca3583c96591af0e4863c12c394074a51c84d Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:07 +0100
Subject: [PATCH 23/41] Manage: fix check after dereference issue
The code dereferences dev_st earlier without checking, it gives SAST
problem.
dev_st is needed for attempt_re_add(), but it is executed only if
dv->disposition != 'S', so move disposition check up.
tst is a must to reach this place, dup_super() have to return valid
pointer, all it needs to check is if load_super() returns superblock.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Manage.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/Manage.c b/Manage.c
index 30302ac8..77b79cf5 100644
--- a/Manage.c
+++ b/Manage.c
@@ -794,25 +794,23 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
* simply re-add it.
*/
- if (array->not_persistent == 0) {
+ if (array->not_persistent == 0 && dv->disposition != 'S') {
+ int rv = 0;
+
dev_st = dup_super(tst);
dev_st->ss->load_super(dev_st, tfd, NULL);
- if (dev_st->sb && dv->disposition != 'S') {
- int rv;
- rv = attempt_re_add(fd, tfd, dv, dev_st, tst,
- rdev, update, devname,
- verbose, array);
- dev_st->ss->free_super(dev_st);
- if (rv) {
- free(dev_st);
- return rv;
- }
- }
- if (dev_st) {
+ if (dev_st->sb) {
+ rv = attempt_re_add(fd, tfd, dv, dev_st, tst, rdev, update,
+ devname, verbose, array);
+
dev_st->ss->free_super(dev_st);
- free(dev_st);
}
+
+ free(dev_st);
+
+ if (rv)
+ return rv;
}
if (dv->disposition == 'M') {
if (verbose > 0)
--
2.40.1

View File

@ -0,0 +1,184 @@
From 29273f606542d915a3ddf37bb084f4eff54fcc3b Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:08 +0100
Subject: [PATCH 24/41] Manage: implement manage_add_external()
Move external add code to separate function. It is easier to control
error path now. Error messages are adjusted.
No functional changes.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Manage.c | 147 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 86 insertions(+), 61 deletions(-)
diff --git a/Manage.c b/Manage.c
index 77b79cf5..b3e216cb 100644
--- a/Manage.c
+++ b/Manage.c
@@ -695,6 +695,91 @@ skip_re_add:
return 0;
}
+/**
+ * manage_add_external() - Add disk to external container.
+ * @st: external supertype pointer, must not be NULL, superblock is released here.
+ * @fd: container file descriptor, must not have O_EXCL mode.
+ * @disk_fd: device to add file descriptor.
+ * @disk_name: name of the device to add.
+ * @disc: disk info.
+ *
+ * Superblock is released here because any open fd with O_EXCL will block sysfs_add_disk().
+ */
+mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name,
+ mdu_disk_info_t *disc)
+{
+ mdadm_status_t rv = MDADM_STATUS_ERROR;
+ char container_devpath[MD_NAME_MAX];
+ struct mdinfo new_mdi;
+ struct mdinfo *sra = NULL;
+ int container_fd;
+ int disk_fd = -1;
+
+ snprintf(container_devpath, MD_NAME_MAX, "%s", fd2devnm(fd));
+
+ container_fd = open_dev_excl(container_devpath);
+ if (!is_fd_valid(container_fd)) {
+ pr_err("Failed to get exclusive access to container %s\n", container_devpath);
+ return MDADM_STATUS_ERROR;
+ }
+
+ /* Check if metadata handler is able to accept the drive */
+ if (!st->ss->validate_geometry(st, LEVEL_CONTAINER, 0, 1, NULL, 0, 0, disk_name, NULL,
+ 0, 1))
+ goto out;
+
+ Kill(disk_name, NULL, 0, -1, 0);
+
+ disk_fd = dev_open(disk_name, O_RDWR | O_EXCL | O_DIRECT);
+ if (!is_fd_valid(disk_fd)) {
+ pr_err("Failed to exclusively open %s\n", disk_name);
+ goto out;
+ }
+
+ if (st->ss->add_to_super(st, disc, disk_fd, disk_name, INVALID_SECTORS))
+ goto out;
+
+ if (!mdmon_running(st->container_devnm))
+ st->ss->sync_metadata(st);
+
+ sra = sysfs_read(container_fd, NULL, 0);
+ if (!sra) {
+ pr_err("Failed to read sysfs for %s\n", disk_name);
+ goto out;
+ }
+
+ sra->array.level = LEVEL_CONTAINER;
+ /* Need to set data_offset and component_size */
+ st->ss->getinfo_super(st, &new_mdi, NULL);
+ new_mdi.disk.major = disc->major;
+ new_mdi.disk.minor = disc->minor;
+ new_mdi.recovery_start = 0;
+
+ st->ss->free_super(st);
+
+ if (sysfs_add_disk(sra, &new_mdi, 0) != 0) {
+ pr_err("Failed to add %s to container %s\n", disk_name, container_devpath);
+ goto out;
+ }
+ ping_monitor(container_devpath);
+ rv = MDADM_STATUS_SUCCESS;
+
+out:
+ close(container_fd);
+
+ if (sra)
+ sysfs_free(sra);
+
+ if (rv != MDADM_STATUS_SUCCESS && is_fd_valid(disk_fd))
+ /* Metadata handler records this descriptor, so release it only on failure. */
+ close(disk_fd);
+
+ if (st->sb)
+ st->ss->free_super(st);
+
+ return rv;
+}
+
int Manage_add(int fd, int tfd, struct mddev_dev *dv,
struct supertype *tst, mdu_array_info_t *array,
int force, int verbose, char *devname,
@@ -966,68 +1051,8 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
if (dv->failfast == FlagSet)
disc.state |= (1 << MD_DISK_FAILFAST);
if (tst->ss->external) {
- /* add a disk
- * to an external metadata container */
- struct mdinfo new_mdi;
- struct mdinfo *sra;
- int container_fd;
- char devnm[32];
- int dfd;
-
- strcpy(devnm, fd2devnm(fd));
-
- container_fd = open_dev_excl(devnm);
- if (container_fd < 0) {
- pr_err("add failed for %s: could not get exclusive access to container\n",
- dv->devname);
- tst->ss->free_super(tst);
+ if (manage_add_external(tst, fd, dv->devname, &disc) != MDADM_STATUS_SUCCESS)
goto unlock;
- }
-
- /* Check if metadata handler is able to accept the drive */
- if (!tst->ss->validate_geometry(tst, LEVEL_CONTAINER, 0, 1, NULL,
- 0, 0, dv->devname, NULL, 0, 1)) {
- close(container_fd);
- goto unlock;
- }
-
- Kill(dv->devname, NULL, 0, -1, 0);
- dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
- if (tst->ss->add_to_super(tst, &disc, dfd,
- dv->devname, INVALID_SECTORS)) {
- close(dfd);
- close(container_fd);
- goto unlock;
- }
- if (!mdmon_running(tst->container_devnm))
- tst->ss->sync_metadata(tst);
-
- sra = sysfs_read(container_fd, NULL, 0);
- if (!sra) {
- pr_err("add failed for %s: sysfs_read failed\n",
- dv->devname);
- close(container_fd);
- tst->ss->free_super(tst);
- goto unlock;
- }
- sra->array.level = LEVEL_CONTAINER;
- /* Need to set data_offset and component_size */
- tst->ss->getinfo_super(tst, &new_mdi, NULL);
- new_mdi.disk.major = disc.major;
- new_mdi.disk.minor = disc.minor;
- new_mdi.recovery_start = 0;
- /* Make sure fds are closed as they are O_EXCL which
- * would block add_disk */
- tst->ss->free_super(tst);
- if (sysfs_add_disk(sra, &new_mdi, 0) != 0) {
- pr_err("add new device to external metadata failed for %s\n", dv->devname);
- close(container_fd);
- sysfs_free(sra);
- goto unlock;
- }
- ping_monitor(devnm);
- sysfs_free(sra);
- close(container_fd);
} else {
tst->ss->free_super(tst);
if (ioctl(fd, ADD_NEW_DISK, &disc)) {
--
2.40.1

View File

@ -0,0 +1,138 @@
From 14a8657940be34a781222b4b715bd09eb80d1057 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:09 +0100
Subject: [PATCH 25/41] mdadm: introduce sysfs_get_container_devnm()
There at least two places where it is done directly, so replace them
with function. Print message about creating external array, add "/dev/"
prefix to refer directly to devnode.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Create.c | 21 ++++++++++-----------
Manage.c | 14 ++++----------
mdadm.h | 2 ++
sysfs.c | 23 +++++++++++++++++++++++
4 files changed, 39 insertions(+), 21 deletions(-)
diff --git a/Create.c b/Create.c
index 7e9170b6..0b776266 100644
--- a/Create.c
+++ b/Create.c
@@ -1142,24 +1142,23 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
if (did_default && c->verbose >= 0) {
if (is_subarray(info.text_version)) {
- char devnm[32];
- char *ep;
+ char devnm[MD_NAME_MAX];
struct mdinfo *mdi;
- strncpy(devnm, info.text_version+1, 32);
- devnm[31] = 0;
- ep = strchr(devnm, '/');
- if (ep)
- *ep = 0;
+ sysfs_get_container_devnm(&info, devnm);
mdi = sysfs_read(-1, devnm, GET_VERSION);
+ if (!mdi) {
+ pr_err("Cannot open sysfs for container %s\n", devnm);
+ goto abort_locked;
+ }
+
+ pr_info("Creating array inside %s container /dev/%s\n", mdi->text_version,
+ devnm);
- pr_info("Creating array inside %s container %s\n",
- mdi?mdi->text_version:"managed", devnm);
sysfs_free(mdi);
} else
- pr_info("Defaulting to version %s metadata\n",
- info.text_version);
+ pr_info("Defaulting to version %s metadata\n", info.text_version);
}
map_update(&map, fd2devnm(mdfd), info.text_version,
diff --git a/Manage.c b/Manage.c
index b3e216cb..969d0ea9 100644
--- a/Manage.c
+++ b/Manage.c
@@ -178,7 +178,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
struct map_ent *map = NULL;
struct mdinfo *mdi;
char devnm[32];
- char container[32];
+ char container[MD_NAME_MAX] = {0};
int err;
int count;
char buf[SYSFS_MAX_BUF_SIZE];
@@ -192,15 +192,9 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
* to stop is probably a bad idea.
*/
mdi = sysfs_read(fd, NULL, GET_LEVEL|GET_COMPONENT|GET_VERSION);
- if (mdi && is_subarray(mdi->text_version)) {
- char *sl;
- strncpy(container, mdi->text_version+1, sizeof(container));
- container[sizeof(container)-1] = 0;
- sl = strchr(container, '/');
- if (sl)
- *sl = 0;
- } else
- container[0] = 0;
+ if (mdi && is_subarray(mdi->text_version))
+ sysfs_get_container_devnm(mdi, container);
+
close(fd);
count = 5;
while (((fd = ((devname[0] == '/')
diff --git a/mdadm.h b/mdadm.h
index cbc586f5..39b86bd0 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -777,6 +777,8 @@ enum sysfs_read_flags {
#define SYSFS_MAX_BUF_SIZE 64
+extern void sysfs_get_container_devnm(struct mdinfo *mdi, char *buf);
+
/* If fd >= 0, get the array it is open on,
* else use devnm.
*/
diff --git a/sysfs.c b/sysfs.c
index f95ef701..230b842e 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -74,6 +74,29 @@ void sysfs_free(struct mdinfo *sra)
}
}
+/**
+ * sysfs_get_container_devnm() - extract container device name.
+ * @mdi: md_info describes member array, with GET_VERSION option.
+ * @buf: buf to fill, must be MD_NAME_MAX.
+ *
+ * External array version is in format {/,-}<container_devnm>/<array_index>
+ * Extract container_devnm from it and safe it in @buf.
+ */
+void sysfs_get_container_devnm(struct mdinfo *mdi, char *buf)
+{
+ char *p;
+
+ assert(is_subarray(mdi->text_version));
+
+ /* Skip first special sign */
+ snprintf(buf, MD_NAME_MAX, "%s", mdi->text_version + 1);
+
+ /* Remove array index */
+ p = strchr(buf, '/');
+ if (p)
+ *p = 0;
+}
+
int sysfs_open(char *devnm, char *devname, char *attr)
{
char fname[MAX_SYSFS_PATH_LEN];
--
2.40.1

View File

@ -0,0 +1,115 @@
From 1fef0c6ff54c2710f75a239dd8a5e0ffb0068e86 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:10 +0100
Subject: [PATCH 26/41] mdadm.h: Introduce custom device policies
The approach proposed here is to test drive policies outside
validate_geometry() separately per every drive and add determined
policies to list. The implementation reuses dev_policy we have in
mdadm.
This concept addresses following problems:
- test drives if they fit together to criteria required by metadata
handler,
- test all drives assigned to the container even if some of them are not
target of the request, mdmon is free to use any drive in the same
container,
- extensibility, new policies can be added to handler easy,
- fix issues related to imsm controller domain verifying.
Add superswitch function. It is used in next patches.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 54 ++++++++++++++++++++++++++++++++++++------------------
1 file changed, 36 insertions(+), 18 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index 39b86bd0..889f4a0f 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -940,6 +940,23 @@ struct reshape {
unsigned long long new_size; /* New size of array in sectors */
};
+/**
+ * struct dev_policy - Data structure for policy management.
+ * @next: pointer to next dev_policy.
+ * @name: policy name, category.
+ * @metadata: the metadata type it affects.
+ * @value: value of the policy.
+ *
+ * The functions to manipulate dev_policy lists do not free elements, so they must be statically
+ * allocated. @name and @metadata can be compared by address.
+ */
+typedef struct dev_policy {
+ struct dev_policy *next;
+ char *name;
+ const char *metadata;
+ const char *value;
+} dev_policy_t;
+
/* A superswitch provides entry point to a metadata handler.
*
* The superswitch primarily operates on some "metadata" that
@@ -1168,6 +1185,25 @@ extern struct superswitch {
char *subdev, unsigned long long *freesize,
int consistency_policy, int verbose);
+ /**
+ * test_and_add_drive_policies() - test new and add custom policies from metadata handler.
+ * @pols: list of currently recorded policies.
+ * @disk_fd: file descriptor of the device to check.
+ * @verbose: verbose flag.
+ *
+ * Used by IMSM to verify all drives in container/array, against requirements not recored
+ * in superblock, like controller type for IMSM. It should check all drives even if
+ * they are not actually used, because mdmon or kernel are free to use any drive assigned to
+ * container automatically.
+ *
+ * Generating and comparison methods belong to metadata handler. It is not mandatory to be
+ * implemented.
+ *
+ * Return: MDADM_STATUS_SUCCESS is expected on success.
+ */
+ mdadm_status_t (*test_and_add_drive_policies)(dev_policy_t **pols, int disk_fd,
+ const int verbose);
+
/* Return a linked list of 'mdinfo' structures for all arrays
* in the container. For non-containers, it is like
* getinfo_super with an allocated mdinfo.*/
@@ -1372,23 +1408,6 @@ extern int get_dev_sector_size(int fd, char *dname, unsigned int *sectsizep);
extern int must_be_container(int fd);
void wait_for(char *dev, int fd);
-/*
- * Data structures for policy management.
- * Each device can have a policy structure that lists
- * various name/value pairs each possibly with a metadata associated.
- * The policy list is sorted by name/value/metadata
- */
-struct dev_policy {
- struct dev_policy *next;
- char *name; /* None of these strings are allocated. They are
- * all just references to strings which are known
- * to exist elsewhere.
- * name and metadata can be compared by address equality.
- */
- const char *metadata;
- const char *value;
-};
-
extern char pol_act[], pol_domain[], pol_metadata[], pol_auto[];
/* iterate over the sublist starting at list, having the same
@@ -1430,7 +1449,6 @@ extern struct dev_policy *disk_policy(struct mdinfo *disk);
extern struct dev_policy *devid_policy(int devid);
extern void dev_policy_free(struct dev_policy *p);
-//extern void pol_new(struct dev_policy **pol, char *name, char *val, char *metadata);
extern void pol_add(struct dev_policy **pol, char *name, char *val, char *metadata);
extern struct dev_policy *pol_find(struct dev_policy *pol, char *name);
--
2.40.1

View File

@ -0,0 +1,144 @@
From 5a2e194cb31569880a26356b8594ddca6e3b3828 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:11 +0100
Subject: [PATCH 27/41] mdadm: test_and_add device policies implementation
Add support for three scenarios:
- obtaining array wide policies via fd,
- obtaining array wide policies via struct mdinfo,
- getting policies for particular drive from the request.
Add proper functions and make them extern. These functions are used
in next patches.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 7 +++++
policy.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/mdadm.h b/mdadm.h
index 889f4a0f..af2bc714 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1452,6 +1452,13 @@ extern void dev_policy_free(struct dev_policy *p);
extern void pol_add(struct dev_policy **pol, char *name, char *val, char *metadata);
extern struct dev_policy *pol_find(struct dev_policy *pol, char *name);
+extern mdadm_status_t drive_test_and_add_policies(struct supertype *st, dev_policy_t **pols,
+ int fd, const int verbose);
+extern mdadm_status_t sysfs_test_and_add_drive_policies(struct supertype *st, dev_policy_t **pols,
+ struct mdinfo *mdi, const int verbose);
+extern mdadm_status_t mddev_test_and_add_drive_policies(struct supertype *st, dev_policy_t **pols,
+ int array_fd, const int verbose);
+
enum policy_action {
act_default,
act_include,
diff --git a/policy.c b/policy.c
index eee9ef63..4b85f62d 100644
--- a/policy.c
+++ b/policy.c
@@ -397,6 +397,99 @@ struct dev_policy *path_policy(char **paths, char *type)
return pol;
}
+/**
+ * drive_test_and_add_policies() - get policies for drive and add them to pols.
+ * @st: supertype.
+ * @pols: pointer to pointer of first list entry, cannot be NULL, may point to NULL.
+ * @fd: device descriptor.
+ * @verbose: verbose flag.
+ *
+ * If supertype doesn't support this functionality return success. Use metadata handler to get
+ * policies.
+ */
+mdadm_status_t drive_test_and_add_policies(struct supertype *st, dev_policy_t **pols, int fd,
+ const int verbose)
+{
+ if (!st->ss->test_and_add_drive_policies)
+ return MDADM_STATUS_SUCCESS;
+
+ if (st->ss->test_and_add_drive_policies(pols, fd, verbose) == MDADM_STATUS_SUCCESS) {
+ /* After successful call list cannot be empty */
+ assert(*pols);
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ return MDADM_STATUS_ERROR;
+}
+
+/**
+ * sysfs_test_and_add_policies() - get policies for mddev and add them to pols.
+ * @st: supertype.
+ * @pols: pointer to pointer of first list entry, cannot be NULL, may point to NULL.
+ * @mdi: mdinfo describes the MD array, must have GET_DISKS option.
+ * @verbose: verbose flag.
+ *
+ * If supertype doesn't support this functionality return success. To get policies, all disks
+ * connected to mddev are analyzed.
+ */
+mdadm_status_t sysfs_test_and_add_drive_policies(struct supertype *st, dev_policy_t **pols,
+ struct mdinfo *mdi, const int verbose)
+{
+ struct mdinfo *sd;
+
+ if (!st->ss->test_and_add_drive_policies)
+ return MDADM_STATUS_SUCCESS;
+
+ for (sd = mdi->devs; sd; sd = sd->next) {
+ char *devpath = map_dev(sd->disk.major, sd->disk.minor, 0);
+ int fd = dev_open(devpath, O_RDONLY);
+ int rv;
+
+ if (!is_fd_valid(fd)) {
+ pr_err("Cannot open fd for %s\n", devpath);
+ return MDADM_STATUS_ERROR;
+ }
+
+ rv = drive_test_and_add_policies(st, pols, fd, verbose);
+ close(fd);
+
+ if (rv)
+ return MDADM_STATUS_ERROR;
+ }
+
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * mddev_test_and_add_policies() - get policies for mddev and add them to pols.
+ * @st: supertype.
+ * @pols: pointer to pointer of first list entry, cannot be NULL, may point to NULL.
+ * @array_fd: MD device descriptor.
+ * @verbose: verbose flag.
+ *
+ * If supertype doesn't support this functionality return success. Use fd to extract disks.
+ */
+mdadm_status_t mddev_test_and_add_drive_policies(struct supertype *st, dev_policy_t **pols,
+ int array_fd, const int verbose)
+{
+ struct mdinfo *sra;
+ int ret;
+
+ if (!st->ss->test_and_add_drive_policies)
+ return MDADM_STATUS_SUCCESS;
+
+ sra = sysfs_read(array_fd, NULL, GET_DEVS);
+ if (!sra) {
+ pr_err("Cannot load sysfs for %s\n", fd2devnm(array_fd));
+ return MDADM_STATUS_ERROR;
+ }
+
+ ret = sysfs_test_and_add_drive_policies(st, pols, sra, verbose);
+
+ sysfs_free(sra);
+ return ret;
+}
+
void pol_add(struct dev_policy **pol,
char *name, char *val,
char *metadata)
--
2.40.1

View File

@ -0,0 +1,124 @@
From f5a39b66f794322f30828389ddd488d17f578ad5 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:12 +0100
Subject: [PATCH 28/41] Create: Use device policies
Generate and compare policies, abort if policies do not match.
It is tested for both create modes, with container and disk list
specified directly. It is used if supertype supports it.
For a case when disk list is specified, container may contain more
devices, so additional check on container is done to analyze all disks.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Create.c | 31 +++++++++++++++++++++++++------
1 file changed, 25 insertions(+), 6 deletions(-)
diff --git a/Create.c b/Create.c
index 0b776266..4397ff49 100644
--- a/Create.c
+++ b/Create.c
@@ -497,6 +497,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
*/
int mdfd;
unsigned long long minsize = 0, maxsize = 0;
+ dev_policy_t *custom_pols = NULL;
char *mindisc = NULL;
char *maxdisc = NULL;
char *name = ident->name;
@@ -588,6 +589,9 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
first_missing = subdevs * 2;
second_missing = subdevs * 2;
insert_point = subdevs * 2;
+
+ if (mddev_test_and_add_drive_policies(st, &custom_pols, fd, 1))
+ exit(1);
}
}
if (fd >= 0)
@@ -739,7 +743,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
close(dfd);
exit(2);
}
- close(dfd);
+
info.array.working_disks++;
if (dnum < s->raiddisks && dv->disposition != 'j')
info.array.active_disks++;
@@ -812,6 +816,11 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
}
}
+ if (drive_test_and_add_policies(st, &custom_pols, dfd, 1))
+ exit(1);
+
+ close(dfd);
+
if (dv->disposition == 'j')
goto skip_size_check; /* skip write journal for size check */
@@ -886,6 +895,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
close(fd);
}
}
+
if (missing_disks == dnum && !have_container) {
pr_err("Subdevs can't be all missing\n");
return 1;
@@ -1140,25 +1150,30 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
goto abort_locked;
}
- if (did_default && c->verbose >= 0) {
+ if (did_default) {
if (is_subarray(info.text_version)) {
char devnm[MD_NAME_MAX];
struct mdinfo *mdi;
sysfs_get_container_devnm(&info, devnm);
- mdi = sysfs_read(-1, devnm, GET_VERSION);
+ mdi = sysfs_read(-1, devnm, GET_VERSION | GET_DEVS);
if (!mdi) {
pr_err("Cannot open sysfs for container %s\n", devnm);
goto abort_locked;
}
- pr_info("Creating array inside %s container /dev/%s\n", mdi->text_version,
- devnm);
+ if (sysfs_test_and_add_drive_policies(st, &custom_pols, mdi, 1))
+ goto abort_locked;
+
+ if (c->verbose >= 0)
+ pr_info("Creating array inside %s container /dev/%s\n",
+ mdi->text_version, devnm);
sysfs_free(mdi);
- } else
+ } else if (c->verbose >= 0) {
pr_info("Defaulting to version %s metadata\n", info.text_version);
+ }
}
map_update(&map, fd2devnm(mdfd), info.text_version,
@@ -1328,6 +1343,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
udev_unblock();
close(mdfd);
sysfs_uevent(&info, "change");
+ dev_policy_free(custom_pols);
+
return 0;
abort:
@@ -1339,5 +1356,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
if (mdfd >= 0)
close(mdfd);
+
+ dev_policy_free(custom_pols);
return 1;
}
--
2.40.1

View File

@ -0,0 +1,60 @@
From 1251db34616bf4890d86664abc5186e9106e9073 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:13 +0100
Subject: [PATCH 29/41] Manage: check device policies in manage_add_external()
Only IMSM is going to use device policies so it is added to
manage_add_external(). Test policies before adding the drive to
container.
The change blocks adding new device to the container which already
contains not matching devices
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Manage.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Manage.c b/Manage.c
index 969d0ea9..96e5ee54 100644
--- a/Manage.c
+++ b/Manage.c
@@ -704,6 +704,7 @@ mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name
{
mdadm_status_t rv = MDADM_STATUS_ERROR;
char container_devpath[MD_NAME_MAX];
+ struct dev_policy *pols = NULL;
struct mdinfo new_mdi;
struct mdinfo *sra = NULL;
int container_fd;
@@ -722,6 +723,9 @@ mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name
0, 1))
goto out;
+ if (mddev_test_and_add_drive_policies(st, &pols, container_fd, 1))
+ goto out;
+
Kill(disk_name, NULL, 0, -1, 0);
disk_fd = dev_open(disk_name, O_RDWR | O_EXCL | O_DIRECT);
@@ -730,6 +734,9 @@ mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name
goto out;
}
+ if (drive_test_and_add_policies(st, &pols, disk_fd, 1))
+ goto out;
+
if (st->ss->add_to_super(st, disc, disk_fd, disk_name, INVALID_SECTORS))
goto out;
@@ -760,6 +767,7 @@ mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name
out:
close(container_fd);
+ dev_policy_free(pols);
if (sra)
sysfs_free(sra);
--
2.40.1

View File

@ -0,0 +1,142 @@
From 51a9f2fc5e982f3bcbf88fe1bf30c0bf55bfd49c Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:14 +0100
Subject: [PATCH 30/41] Monitor, Incremental: use device policies
spare_criteria is expanded to contain policies which will be generated
by handler's get_spare_criteria() function. It provides a way to
test device for metadata specific policies earlier than during
add_do_super(), when device is already removed from previous
array/container for Monitor.
For Incremental, it ensures that all criteria are tested when trying
spare. It is not tested when device contains valid metadata.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Incremental.c | 2 +-
Monitor.c | 3 ++-
mdadm.h | 5 +++--
util.c | 13 +++++++++----
4 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 66c2cc86..958ba9ba 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -865,7 +865,7 @@ mdadm_status_t incremental_external_test_spare_criteria(struct supertype *st, ch
goto out;
}
- if (!disk_fd_matches_criteria(disk_fd, &sc)) {
+ if (!disk_fd_matches_criteria(dup, disk_fd, &sc)) {
if (verbose > 1)
pr_err("Disk does not match spare criteria for %s\n", container_devname);
goto out;
diff --git a/Monitor.c b/Monitor.c
index 6b4560ae..9b016bc3 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -1047,7 +1047,7 @@ static dev_t choose_spare(struct state *from, struct state *to,
test_partition_from_id(from->devid[d]))
continue;
- if (devid_matches_criteria(from->devid[d], sc) == false)
+ if (devid_matches_criteria(to->metadata, from->devid[d], sc) == false)
continue;
pol = devid_policy(from->devid[d]);
@@ -1195,6 +1195,7 @@ static void try_spare_migration(struct state *statelist)
}
}
domain_free(domlist);
+ dev_policy_free(sc.pols);
}
}
diff --git a/mdadm.h b/mdadm.h
index af2bc714..cfa11391 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -433,6 +433,7 @@ struct spare_criteria {
bool criteria_set;
unsigned long long min_size;
unsigned int sector_size;
+ struct dev_policy *pols;
};
typedef enum mdadm_status {
@@ -1734,8 +1735,8 @@ extern int assemble_container_content(struct supertype *st, int mdfd,
#define INCR_ALREADY 4
#define INCR_YES 8
-extern bool devid_matches_criteria(dev_t devid, struct spare_criteria *sc);
-extern bool disk_fd_matches_criteria(int disk_fd, struct spare_criteria *sc);
+extern bool devid_matches_criteria(struct supertype *st, dev_t devid, struct spare_criteria *sc);
+extern bool disk_fd_matches_criteria(struct supertype *st, int disk_fd, struct spare_criteria *sc);
extern struct mdinfo *container_choose_spares(struct supertype *st,
struct spare_criteria *criteria,
struct domainlist *domlist,
diff --git a/util.c b/util.c
index 041e78cf..05ad3343 100644
--- a/util.c
+++ b/util.c
@@ -2056,12 +2056,13 @@ unsigned int __invalid_size_argument_for_IOC = 0;
/**
* disk_fd_matches_criteria() - check if device matches spare criteria.
+ * @st: supertype, not NULL.
* @disk_fd: file descriptor of the disk.
* @sc: criteria to test.
*
* Return: true if disk matches criteria, false otherwise.
*/
-bool disk_fd_matches_criteria(int disk_fd, struct spare_criteria *sc)
+bool disk_fd_matches_criteria(struct supertype *st, int disk_fd, struct spare_criteria *sc)
{
unsigned int dev_sector_size = 0;
unsigned long long dev_size = 0;
@@ -2076,17 +2077,21 @@ bool disk_fd_matches_criteria(int disk_fd, struct spare_criteria *sc)
sc->sector_size != dev_sector_size)
return false;
+ if (drive_test_and_add_policies(st, &sc->pols, disk_fd, 0))
+ return false;
+
return true;
}
/**
* devid_matches_criteria() - check if device referenced by devid matches spare criteria.
+ * @st: supertype, not NULL.
* @devid: devid of the device to check.
* @sc: criteria to test.
*
* Return: true if disk matches criteria, false otherwise.
*/
-bool devid_matches_criteria(dev_t devid, struct spare_criteria *sc)
+bool devid_matches_criteria(struct supertype *st, dev_t devid, struct spare_criteria *sc)
{
char buf[NAME_MAX];
bool ret;
@@ -2102,7 +2107,7 @@ bool devid_matches_criteria(dev_t devid, struct spare_criteria *sc)
return false;
/* Error code inherited */
- ret = disk_fd_matches_criteria(fd, sc);
+ ret = disk_fd_matches_criteria(st, fd, sc);
close(fd);
return ret;
@@ -2137,7 +2142,7 @@ struct mdinfo *container_choose_spares(struct supertype *st,
if (d->disk.state == 0) {
dev_t dev = makedev(d->disk.major,d->disk.minor);
- found = devid_matches_criteria(dev, criteria);
+ found = devid_matches_criteria(st, dev, criteria);
/* check if domain matches */
if (found && domlist) {
--
2.40.1

View File

@ -0,0 +1,187 @@
From e21aea08eb706939a38f7dc5cf9509a9afd45f8a Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:15 +0100
Subject: [PATCH 31/41] imsm: test_and_add_device_policies() implementation
This patch removes get_disk_controller_domain_imsm() in favour of
test_and_add_device_policies_imsm(). It is used by
create, add and mdmonitor.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
platform-intel.h | 1 -
super-intel.c | 123 ++++++++++++++++++++++++++++++++++-------------
2 files changed, 90 insertions(+), 34 deletions(-)
diff --git a/platform-intel.h b/platform-intel.h
index ce29d3da..3c2bc595 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -262,7 +262,6 @@ int disk_attached_to_hba(int fd, const char *hba_path);
int devt_attached_to_hba(dev_t dev, const char *hba_path);
char *devt_to_devpath(dev_t dev, int dev_level, char *buf);
int path_attached_to_hba(const char *disk_path, const char *hba_path);
-const char *get_sys_dev_type(enum sys_dev_type);
const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id);
const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
struct sys_dev *device_by_id(__u16 device_id);
diff --git a/super-intel.c b/super-intel.c
index 7ad391ac..77140455 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -11220,39 +11220,90 @@ abort:
return retval;
}
-static char disk_by_path[] = "/dev/disk/by-path/";
-
-static const char *imsm_get_disk_controller_domain(const char *path)
-{
- char disk_path[PATH_MAX];
- char *drv=NULL;
- struct stat st;
-
- 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;
- char *path;
-
- path = devt_to_devpath(st.st_rdev, 1, NULL);
- if (path == NULL)
- return "unknown";
- hba = find_disk_attached_hba(-1, path);
- if (hba && hba->type == SYS_DEV_SAS)
- drv = "isci";
- else if (hba && (hba->type == SYS_DEV_SATA || hba->type == SYS_DEV_SATA_VMD))
- drv = "ahci";
- else if (hba && hba->type == SYS_DEV_VMD)
- drv = "vmd";
- else if (hba && hba->type == SYS_DEV_NVME)
- drv = "nvme";
- else
- drv = "unknown";
- dprintf("path: %s hba: %s attached: %s\n",
- path, (hba) ? hba->path : "NULL", drv);
- free(path);
+/**
+ * test_and_add_drive_controller_policy_imsm() - add disk controller to policies list.
+ * @type: Policy type to search on list.
+ * @pols: List of currently recorded policies.
+ * @disk_fd: File descriptor of the device to check.
+ * @hba: The hba disk is attached, could be NULL if verification is disabled.
+ * @verbose: verbose flag.
+ *
+ * IMSM cares about drive physical placement. If @hba is not set, it adds unknown policy.
+ * If there is no controller policy on pols we are free to add first one. If there is a policy then,
+ * new must be the same - no controller mixing allowed.
+ */
+static mdadm_status_t
+test_and_add_drive_controller_policy_imsm(const char * const type, dev_policy_t **pols, int disk_fd,
+ struct sys_dev *hba, const int verbose)
+{
+ const char *controller_policy = get_sys_dev_type(SYS_DEV_UNKNOWN);
+ struct dev_policy *pol = pol_find(*pols, (char *)type);
+ char devname[MAX_RAID_SERIAL_LEN];
+
+ if (hba)
+ controller_policy = get_sys_dev_type(hba->type);
+
+ if (!pol) {
+ pol_add(pols, (char *)type, (char *)controller_policy, "imsm");
+ return MDADM_STATUS_SUCCESS;
}
- return drv;
+
+ if (strcmp(pol->value, controller_policy) == 0)
+ return MDADM_STATUS_SUCCESS;
+
+ fd2devname(disk_fd, devname);
+ pr_vrb("Intel(R) raid controller \"%s\" found for %s, but \"%s\" was detected earlier\n",
+ controller_policy, devname, pol->value);
+ pr_vrb("Disks under different controllers cannot be used, aborting\n");
+
+ return MDADM_STATUS_ERROR;
+}
+
+struct imsm_drive_policy {
+ char *type;
+ mdadm_status_t (*test_and_add_drive_policy)(const char * const type,
+ struct dev_policy **pols, int disk_fd,
+ struct sys_dev *hba, const int verbose);
+};
+
+struct imsm_drive_policy imsm_policies[] = {
+ {"controller", test_and_add_drive_controller_policy_imsm},
+};
+
+mdadm_status_t test_and_add_drive_policies_imsm(struct dev_policy **pols, int disk_fd,
+ const int verbose)
+{
+ struct imsm_drive_policy *imsm_pol;
+ struct sys_dev *hba = NULL;
+ char path[PATH_MAX];
+ mdadm_status_t ret;
+ unsigned int i;
+
+ /* If imsm platform verification is disabled, do not search for hba. */
+ if (check_no_platform() != 1) {
+ if (!diskfd_to_devpath(disk_fd, 1, path)) {
+ pr_vrb("IMSM: Failed to retrieve device path by file descriptor.\n");
+ return MDADM_STATUS_ERROR;
+ }
+
+ hba = find_disk_attached_hba(disk_fd, path);
+ if (!hba) {
+ pr_vrb("IMSM: Failed to find hba for %s\n", path);
+ return MDADM_STATUS_ERROR;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(imsm_policies); i++) {
+ imsm_pol = &imsm_policies[i];
+
+ ret = imsm_pol->test_and_add_drive_policy(imsm_pol->type, pols, disk_fd, hba,
+ verbose);
+ if (ret != MDADM_STATUS_SUCCESS)
+ /* Inherit error code */
+ return ret;
+ }
+
+ return MDADM_STATUS_SUCCESS;
}
/**
@@ -11280,6 +11331,7 @@ mdadm_status_t get_spare_criteria_imsm(struct supertype *st, char *mddev_path,
if (mddev_path) {
int fd = open(mddev_path, O_RDONLY);
+ mdadm_status_t rv;
if (!is_fd_valid(fd))
return MDADM_STATUS_ERROR;
@@ -11291,7 +11343,12 @@ mdadm_status_t get_spare_criteria_imsm(struct supertype *st, char *mddev_path,
}
free_superblock = true;
}
+
+ rv = mddev_test_and_add_drive_policies(st, &c->pols, fd, 0);
close(fd);
+
+ if (rv != MDADM_STATUS_SUCCESS)
+ goto out;
}
super = st->sb;
@@ -13026,7 +13083,7 @@ struct superswitch super_imsm = {
.update_subarray = update_subarray_imsm,
.load_container = load_container_imsm,
.default_geometry = default_geometry_imsm,
- .get_disk_controller_domain = imsm_get_disk_controller_domain,
+ .test_and_add_drive_policies = test_and_add_drive_policies_imsm,
.reshape_super = imsm_reshape_super,
.manage_reshape = imsm_manage_reshape,
.recover_backup = recover_backup_imsm,
--
2.40.1

View File

@ -0,0 +1,75 @@
From e492d2ac143e7f02d6c262130d42a4422e8295d5 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:16 +0100
Subject: [PATCH 32/41] mdadm: drop get_disk_controller_domain()
This function is unused now. Drop it.
Controller for IMSM is a device policy and is separated from user defined
domains.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 15 ---------------
policy.c | 13 -------------
2 files changed, 28 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index cfa11391..3fedca48 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1286,21 +1286,6 @@ extern struct superswitch {
*/
struct mdinfo *(*activate_spare)(struct active_array *a,
struct metadata_update **updates);
- /*
- * Return statically allocated string that represents metadata specific
- * controller domain of the disk. The domain is used in disk domain
- * matching functions. Disks belong to the same domain if the they have
- * the same domain from mdadm.conf and belong the same metadata domain.
- * Returning NULL or not providing this handler means that metadata
- * does not distinguish the differences between disks that belong to
- * different controllers. They are in the domain specified by
- * configuration file (mdadm.conf).
- * In case when the metadata has the notion of domains based on disk
- * it shall return NULL for disks that do not belong to the controller
- * the supported domains. Such disks will form another domain and won't
- * be mixed with supported ones.
- */
- const char *(*get_disk_controller_domain)(const char *path);
/* for external backup area */
int (*recover_backup)(struct supertype *st, struct mdinfo *info);
diff --git a/policy.c b/policy.c
index 4b85f62d..404f9b5d 100644
--- a/policy.c
+++ b/policy.c
@@ -365,7 +365,6 @@ struct dev_policy *path_policy(char **paths, char *type)
{
struct pol_rule *rules;
struct dev_policy *pol = NULL;
- int i;
rules = config_rules;
@@ -380,18 +379,6 @@ struct dev_policy *path_policy(char **paths, char *type)
rules = rules->next;
}
- /* Now add any metadata-specific internal knowledge
- * about this path
- */
- for (i=0; paths && paths[0] && superlist[i]; i++)
- if (superlist[i]->get_disk_controller_domain) {
- const char *d =
- superlist[i]->get_disk_controller_domain(
- paths[0]);
- if (d)
- pol_new(&pol, pol_domain, d, superlist[i]->name);
- }
-
pol_sort(&pol);
pol_dedup(pol);
return pol;
--
2.40.1

View File

@ -0,0 +1,42 @@
From 933bb500b80cca6f4e9237382f7d8ac852978471 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 29 Feb 2024 12:52:17 +0100
Subject: [PATCH 33/41] Revert "policy.c: Avoid to take spare without defined
domain by imsm"
This reverts commit 3bf9495270d7 ("policy.c: Avoid to take spare without
defined domain by imsm").
IMSM does not require to be special now because it doesn't create disk
controller domain.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
policy.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/policy.c b/policy.c
index 404f9b5d..dfaafdc0 100644
--- a/policy.c
+++ b/policy.c
@@ -759,7 +759,6 @@ int domain_test(struct domainlist *dom, struct dev_policy *pol,
* 1: has domains, all match
*/
int found_any = -1;
- int has_one_domain = 1;
struct dev_policy *p;
pol = pol_find(pol, pol_domain);
@@ -769,9 +768,6 @@ int domain_test(struct domainlist *dom, struct dev_policy *pol,
dom = dom->next;
if (!dom || strcmp(dom->dom, p->value) != 0)
return 0;
- if (has_one_domain && metadata && strcmp(metadata, "imsm") == 0)
- found_any = -1;
- has_one_domain = 0;
}
return found_any;
}
--
2.40.1

View File

@ -0,0 +1,307 @@
From 9c63130e8974033969569fb9d0b373d1d1478cf7 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Wed, 6 Mar 2024 13:45:53 +0100
Subject: [PATCH 34/41] mdadm: remove inventory file
It is a file with repo content list. It is outdated already.
Remove it.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
inventory | 284 ------------------------------------------------------
1 file changed, 284 deletions(-)
delete mode 100755 inventory
diff --git a/inventory b/inventory
deleted file mode 100755
index c4801b49..00000000
--- a/inventory
+++ /dev/null
@@ -1,284 +0,0 @@
-
-.gitignore
-ANNOUNCE-3.0
-ANNOUNCE-3.0.1
-ANNOUNCE-3.0.2
-ANNOUNCE-3.0.3
-ANNOUNCE-3.1
-ANNOUNCE-3.1.1
-ANNOUNCE-3.1.2
-ANNOUNCE-3.1.3
-ANNOUNCE-3.1.4
-ANNOUNCE-3.1.5
-ANNOUNCE-3.2
-ANNOUNCE-3.2.1
-ANNOUNCE-3.2.2
-ANNOUNCE-3.2.3
-ANNOUNCE-3.2.4
-ANNOUNCE-3.2.5
-ANNOUNCE-3.2.6
-ANNOUNCE-3.3
-ANNOUNCE-3.3.1
-ANNOUNCE-3.3.2
-ANNOUNCE-3.3.3
-ANNOUNCE-3.3.4
-ANNOUNCE-3.4
-ANNOUNCE-4.0
-ANNOUNCE-4.1
-ANNOUNCE-4.2
-Assemble.c
-Build.c
-COPYING
-ChangeLog
-Create.c
-Detail.c
-Dump.c
-Examine.c
-Grow.c
-INSTALL
-Incremental.c
-Kill.c
-Makefile
-Manage.c
-Monitor.c
-Query.c
-README.initramfs
-ReadMe.c
-TODO
-bitmap.c
-bitmap.h
-clustermd_tests/
-clustermd_tests/00r10_Create
-clustermd_tests/00r1_Create
-clustermd_tests/01r10_Grow_bitmap-switch
-clustermd_tests/01r10_Grow_resize
-clustermd_tests/01r1_Grow_add
-clustermd_tests/01r1_Grow_bitmap-switch
-clustermd_tests/01r1_Grow_resize
-clustermd_tests/02r10_Manage_add
-clustermd_tests/02r10_Manage_add-spare
-clustermd_tests/02r10_Manage_re-add
-clustermd_tests/02r1_Manage_add
-clustermd_tests/02r1_Manage_add-spare
-clustermd_tests/02r1_Manage_re-add
-clustermd_tests/03r10_switch-recovery
-clustermd_tests/03r10_switch-resync
-clustermd_tests/03r1_switch-recovery
-clustermd_tests/03r1_switch-resync
-clustermd_tests/cluster_conf
-clustermd_tests/func.sh
-config.c
-coverity-gcc-hack.h
-crc32.c
-crc32.h
-crc32c.c
-dlink.c
-dlink.h
-external-reshape-design.txt
-inventory
-lib.c
-makedist
-managemon.c
-mapfile.c
-maps.c
-md.4
-md5.h
-md_p.h
-md_u.h
-mdadm.8.in
-mdadm.c
-mdadm.conf-example
-mdadm.conf.5
-mdadm.h
-mdadm.spec
-mdmon-design.txt
-mdmon.8
-mdmon.c
-mdmon.h
-mdopen.c
-mdstat.c
-misc/
-misc/mdcheck
-misc/syslog-events
-mkinitramfs
-monitor.c
-msg.c
-msg.h
-part.h
-platform-intel.c
-platform-intel.h
-policy.c
-probe_roms.c
-probe_roms.h
-pwgr.c
-raid5extend.c
-raid6check.8
-raid6check.c
-restripe.c
-sg_io.c
-sha1.c
-sha1.h
-super-ddf.c
-super-gpt.c
-super-intel.c
-super-mbr.c
-super0.c
-super1.c
-swap_super.c
-sysfs.c
-systemd/
-systemd/SUSE-mdadm_env.sh
-systemd/mdadm-grow-continue@.service
-systemd/mdadm-last-resort@.service
-systemd/mdadm-last-resort@.timer
-systemd/mdadm.shutdown
-systemd/mdcheck_continue.service
-systemd/mdcheck_continue.timer
-systemd/mdcheck_start.service
-systemd/mdcheck_start.timer
-systemd/mdmon@.service
-systemd/mdmonitor-oneshot.service
-systemd/mdmonitor-oneshot.timer
-systemd/mdmonitor.service
-test
-tests/
-tests/00linear
-tests/00multipath
-tests/00names
-tests/00raid0
-tests/00raid1
-tests/00raid10
-tests/00raid4
-tests/00raid5
-tests/00raid6
-tests/00readonly
-tests/01r1fail
-tests/01r5fail
-tests/01r5integ
-tests/01raid6integ
-tests/01replace
-tests/02lineargrow
-tests/02r1add
-tests/02r1grow
-tests/02r5grow
-tests/02r6grow
-tests/03assem-incr
-tests/03r0assem
-tests/03r5assem
-tests/03r5assem-failed
-tests/03r5assemV1
-tests/04r0update
-tests/04r1update
-tests/04r5swap
-tests/04update-metadata
-tests/04update-uuid
-tests/05r1-add-internalbitmap
-tests/05r1-add-internalbitmap-v1a
-tests/05r1-add-internalbitmap-v1b
-tests/05r1-add-internalbitmap-v1c
-tests/05r1-bitmapfile
-tests/05r1-failfast
-tests/05r1-grow-external
-tests/05r1-grow-internal
-tests/05r1-grow-internal-1
-tests/05r1-internalbitmap
-tests/05r1-internalbitmap-v1a
-tests/05r1-internalbitmap-v1b
-tests/05r1-internalbitmap-v1c
-tests/05r1-n3-bitmapfile
-tests/05r1-re-add
-tests/05r1-re-add-nosuper
-tests/05r1-remove-internalbitmap
-tests/05r1-remove-internalbitmap-v1a
-tests/05r1-remove-internalbitmap-v1b
-tests/05r1-remove-internalbitmap-v1c
-tests/05r5-bitmapfile
-tests/05r5-internalbitmap
-tests/05r6-bitmapfile
-tests/05r6tor0
-tests/06name
-tests/06sysfs
-tests/06wrmostly
-tests/07autoassemble
-tests/07autodetect
-tests/07changelevelintr
-tests/07changelevels
-tests/07layouts
-tests/07reshape5intr
-tests/07revert-grow
-tests/07revert-inplace
-tests/07revert-shrink
-tests/07testreshape5
-tests/09imsm-assemble
-tests/09imsm-create-fail-rebuild
-tests/09imsm-overlap
-tests/10ddf-assemble-missing
-tests/10ddf-create
-tests/10ddf-create-fail-rebuild
-tests/10ddf-fail-create-race
-tests/10ddf-fail-readd
-tests/10ddf-fail-readd-readonly
-tests/10ddf-fail-spare
-tests/10ddf-fail-stop-readd
-tests/10ddf-fail-twice
-tests/10ddf-fail-two-spares
-tests/10ddf-geometry
-tests/10ddf-incremental-wrong-order
-tests/10ddf-sudden-degraded
-tests/11spare-migration
-tests/12imsm-r0_2d-grow-r0_3d
-tests/12imsm-r0_2d-grow-r0_4d
-tests/12imsm-r0_2d-grow-r0_5d
-tests/12imsm-r0_3d-grow-r0_4d
-tests/12imsm-r5_3d-grow-r5_4d
-tests/12imsm-r5_3d-grow-r5_5d
-tests/13imsm-r0_r0_2d-grow-r0_r0_4d
-tests/13imsm-r0_r0_2d-grow-r0_r0_5d
-tests/13imsm-r0_r0_3d-grow-r0_r0_4d
-tests/13imsm-r0_r5_3d-grow-r0_r5_4d
-tests/13imsm-r0_r5_3d-grow-r0_r5_5d
-tests/13imsm-r5_r0_3d-grow-r5_r0_4d
-tests/13imsm-r5_r0_3d-grow-r5_r0_5d
-tests/14imsm-r0_3d-r5_3d-migrate-r5_4d-r5_4d
-tests/14imsm-r0_3d_no_spares-migrate-r5_3d
-tests/14imsm-r0_r0_2d-takeover-r10_4d
-tests/14imsm-r10_4d-grow-r10_5d
-tests/14imsm-r10_r5_4d-takeover-r0_2d
-tests/14imsm-r1_2d-grow-r1_3d
-tests/14imsm-r1_2d-takeover-r0_2d
-tests/14imsm-r5_3d-grow-r5_5d-no-spares
-tests/14imsm-r5_3d-migrate-r4_3d
-tests/15imsm-r0_3d_64k-migrate-r0_3d_256k
-tests/15imsm-r5_3d_4k-migrate-r5_3d_256k
-tests/15imsm-r5_3d_64k-migrate-r5_3d_256k
-tests/15imsm-r5_6d_4k-migrate-r5_6d_256k
-tests/15imsm-r5_r0_3d_64k-migrate-r5_r0_3d_256k
-tests/16imsm-r0_3d-migrate-r5_4d
-tests/16imsm-r0_5d-migrate-r5_6d
-tests/16imsm-r5_3d-migrate-r0_3d
-tests/16imsm-r5_5d-migrate-r0_5d
-tests/18imsm-1d-takeover-r0_1d
-tests/18imsm-1d-takeover-r1_2d
-tests/18imsm-r0_2d-takeover-r10_4d
-tests/18imsm-r10_4d-takeover-r0_2d
-tests/18imsm-r1_2d-takeover-r0_1d
-tests/19raid6auto-repair
-tests/19raid6check
-tests/19raid6repair
-tests/19repair-does-not-destroy
-tests/20raid5journal
-tests/21raid5cache
-tests/ToTest
-tests/env-ddf-template
-tests/env-imsm-template
-tests/func.sh
-tests/imsm-grow-template
-tests/utils
-udev-md-clustered-confirm-device.rules
-udev-md-raid-arrays.rules
-udev-md-raid-assembly.rules
-udev-md-raid-creating.rules
-udev-md-raid-safe-timeouts.rules
-util.c
-uuid.c
-xmalloc.c
--
2.40.1

View File

@ -0,0 +1,31 @@
From 1750758c7ff526e3560433f6235e5cfa35cf646a Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Wed, 6 Mar 2024 15:50:55 +0100
Subject: [PATCH 35/41] udev.c: Do not require libudev.h if DNO_LIBUDEV
libudev may not be presented at all, do not require it.
Reported-by: Boian Bonev <bbonev@ipacct.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
udev.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/udev.c b/udev.c
index bc4722b0..066e6ab1 100644
--- a/udev.c
+++ b/udev.c
@@ -26,7 +26,10 @@
#include <signal.h>
#include <limits.h>
#include <syslog.h>
+
+#ifndef NO_LIBUDEV
#include <libudev.h>
+#endif
static char *unblock_path;
--
2.40.1

View File

@ -0,0 +1,29 @@
From 8bda86099089b44129ef6206764f9de47a45f0db Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex@linutronix.de>
Date: Tue, 12 Mar 2024 11:01:50 +0100
Subject: [PATCH 36/41] util.c: add limits.h include for NAME_MAX definition
Add limits.h include for NAME_MAX definition.
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util.c b/util.c
index 05ad3343..49a9c6e2 100644
--- a/util.c
+++ b/util.c
@@ -36,7 +36,7 @@
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
-
+#include <limits.h>
/*
* following taken from linux/blkpg.h because they aren't
--
2.40.1

View File

@ -0,0 +1,59 @@
From 1c8327950566449e206e613c11c8232032f26787 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 18 Mar 2024 16:19:29 +0100
Subject: [PATCH 37/41] mdadm: set swapuuid in all handlers
It is not set, so it should be 0 but it may vary on compilation
settings. Set it always to 0.
metadata should care to set UUID and read in proper endianness so it
doesn't follow super1 concept of swapuuid to depend on endianness.
It is not an attempt to fix endianness issues.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-ddf.c | 1 +
super-intel.c | 1 +
super0.c | 2 ++
3 files changed, 4 insertions(+)
diff --git a/super-ddf.c b/super-ddf.c
index 7571e3b7..94ac5ff3 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -5162,6 +5162,7 @@ struct superswitch super_ddf = {
.default_geometry = default_geometry_ddf,
.external = 1,
+ .swapuuid = 0,
/* for mdmon */
.open_new = ddf_open_new,
diff --git a/super-intel.c b/super-intel.c
index 77140455..e1754f29 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -13116,6 +13116,7 @@ struct superswitch super_imsm = {
.validate_ppl = validate_ppl_imsm,
.external = 1,
+ .swapuuid = 0,
.name = "imsm",
/* for mdmon */
diff --git a/super0.c b/super0.c
index a7c5f813..9b8a1bd6 100644
--- a/super0.c
+++ b/super0.c
@@ -1369,5 +1369,7 @@ struct superswitch super0 = {
.locate_bitmap = locate_bitmap0,
.write_bitmap = write_bitmap0,
.free_super = free_super0,
+
+ .swapuuid = 0,
.name = "0.90",
};
--
2.40.1

View File

@ -0,0 +1,247 @@
From ba65d917d121dfb9876053e6f62dbd4ebf2e028c Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 18 Mar 2024 16:19:30 +0100
Subject: [PATCH 38/41] mdadm: Fix native --detail --export
Mentioned commit (see Fixes) causes that UUID is not swapped as expected
for native superblock. Fix this problem.
For detail, we should avoid superblock calls, we can have information
about supertype from map, use that.
Simplify fname_from_uuid() by removing dependencies to metadata
handler, it is not needed. Decision is taken at compile time, expect
super1 but this function is not used by super1. Add warning about that.
Remove separator, it is always ':'.
Fixes: 60c19530dd7c ("Detail: remove duplicated code")
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Detail.c | 26 +++++++++++++++++++++++++-
mdadm.h | 3 +--
super-ddf.c | 10 +++++-----
super-intel.c | 16 ++++++++--------
util.c | 24 +++++++++++++-----------
5 files changed, 52 insertions(+), 27 deletions(-)
diff --git a/Detail.c b/Detail.c
index f23ec16f..55a086d3 100644
--- a/Detail.c
+++ b/Detail.c
@@ -49,6 +49,30 @@ static int add_device(const char *dev, char ***p_devices,
return n_devices + 1;
}
+/**
+ * detail_fname_from_uuid() - generate uuid string with special super1 handling.
+ * @mp: map entry to parse.
+ * @buf: buf to write.
+ *
+ * Hack to workaround an issue with super1 superblocks. It swapuuid set in order for assembly
+ * to work, but can't have it set if we want this printout to match all the other uuid printouts
+ * in super1.c, so we force swapuuid to 1 to make our printout match the rest of super1.
+ *
+ * Always convert uuid if host is big endian.
+ */
+char *detail_fname_from_uuid(struct map_ent *mp, char *buf)
+{
+#if __BYTE_ORDER == BIG_ENDIAN
+ bool swap = true;
+#else
+ bool swap = false;
+#endif
+ if (strncmp(mp->metadata, "1.", 2) == 0)
+ swap = true;
+
+ return __fname_from_uuid(mp->uuid, swap, buf, ':');
+}
+
int Detail(char *dev, struct context *c)
{
/*
@@ -256,7 +280,7 @@ int Detail(char *dev, struct context *c)
mp = map_by_devnm(&map, fd2devnm(fd));
if (mp) {
- __fname_from_uuid(mp->uuid, 0, nbuf, ':');
+ detail_fname_from_uuid(mp, nbuf);
printf("MD_UUID=%s\n", nbuf + 5);
if (mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
diff --git a/mdadm.h b/mdadm.h
index 3fedca48..a363708a 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1696,8 +1696,7 @@ extern const int uuid_zero[4];
extern int same_uuid(int a[4], int b[4], int swapuuid);
extern void copy_uuid(void *a, int b[4], int swapuuid);
extern char *__fname_from_uuid(int id[4], int swap, char *buf, char sep);
-extern char *fname_from_uuid(struct supertype *st,
- struct mdinfo *info, char *buf, char sep);
+extern char *fname_from_uuid(struct mdinfo *info, char *buf);
extern unsigned long calc_csum(void *super, int bytes);
extern int enough(int level, int raid_disks, int layout, int clean,
char *avail);
diff --git a/super-ddf.c b/super-ddf.c
index 94ac5ff3..21426c75 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1617,7 +1617,7 @@ static void brief_examine_super_ddf(struct supertype *st, int verbose)
struct mdinfo info;
char nbuf[64];
getinfo_super_ddf(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
}
@@ -1632,7 +1632,7 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
unsigned int i;
char nbuf[64];
getinfo_super_ddf(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
for (i = 0; i < be16_to_cpu(ddf->virt->max_vdes); i++) {
struct virtual_entry *ve = &ddf->virt->entries[i];
@@ -1645,7 +1645,7 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
ddf->currentconf =&vcl;
vcl.vcnum = i;
uuid_from_super_ddf(st, info.uuid);
- fname_from_uuid(st, &info, nbuf1, ':');
+ fname_from_uuid(&info, nbuf1);
_ddf_array_name(namebuf, ddf, i);
printf("ARRAY%s%s container=%s member=%d UUID=%s\n",
namebuf[0] == '\0' ? "" : " " DEV_MD_DIR, namebuf,
@@ -1658,7 +1658,7 @@ static void export_examine_super_ddf(struct supertype *st)
struct mdinfo info;
char nbuf[64];
getinfo_super_ddf(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf("MD_METADATA=ddf\n");
printf("MD_LEVEL=container\n");
printf("MD_UUID=%s\n", nbuf+5);
@@ -1798,7 +1798,7 @@ static void brief_detail_super_ddf(struct supertype *st, char *subarray)
return;
else
uuid_of_ddf_subarray(ddf, vcnum, info.uuid);
- fname_from_uuid(st, &info, nbuf,':');
+ fname_from_uuid(&info, nbuf);
printf(" UUID=%s", nbuf + 5);
}
diff --git a/super-intel.c b/super-intel.c
index e1754f29..ff2590fe 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2217,7 +2217,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
else
printf("not supported\n");
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf(" UUID : %s\n", nbuf + 5);
sum = __le32_to_cpu(mpb->check_sum);
printf(" Checksum : %08x %s\n", sum,
@@ -2242,7 +2242,7 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
super->current_vol = i;
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
print_imsm_dev(super, dev, nbuf + 5, super->disks->index);
}
for (i = 0; i < mpb->num_disks; i++) {
@@ -2267,7 +2267,7 @@ static void brief_examine_super_imsm(struct supertype *st, int verbose)
char nbuf[64];
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf("ARRAY metadata=imsm UUID=%s\n", nbuf + 5);
}
@@ -2284,13 +2284,13 @@ static void brief_examine_subarrays_imsm(struct supertype *st, int verbose)
return;
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
for (i = 0; i < super->anchor->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
super->current_vol = i;
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf1, ':');
+ fname_from_uuid(&info, nbuf1);
printf("ARRAY " DEV_MD_DIR "%.16s container=%s member=%d UUID=%s\n",
dev->volume, nbuf + 5, i, nbuf1 + 5);
}
@@ -2304,7 +2304,7 @@ static void export_examine_super_imsm(struct supertype *st)
char nbuf[64];
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf("MD_METADATA=imsm\n");
printf("MD_LEVEL=container\n");
printf("MD_UUID=%s\n", nbuf+5);
@@ -2324,7 +2324,7 @@ static void detail_super_imsm(struct supertype *st, char *homehost,
super->current_vol = strtoul(subarray, NULL, 10);
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf("\n UUID : %s\n", nbuf + 5);
super->current_vol = temp_vol;
@@ -2341,7 +2341,7 @@ static void brief_detail_super_imsm(struct supertype *st, char *subarray)
super->current_vol = strtoul(subarray, NULL, 10);
getinfo_super_imsm(st, &info, NULL);
- fname_from_uuid(st, &info, nbuf, ':');
+ fname_from_uuid(&info, nbuf);
printf(" UUID=%s", nbuf + 5);
super->current_vol = temp_vol;
diff --git a/util.c b/util.c
index 49a9c6e2..03336d6f 100644
--- a/util.c
+++ b/util.c
@@ -589,19 +589,21 @@ char *__fname_from_uuid(int id[4], int swap, char *buf, char sep)
}
-char *fname_from_uuid(struct supertype *st, struct mdinfo *info,
- char *buf, char sep)
-{
- // dirty hack to work around an issue with super1 superblocks...
- // super1 superblocks need swapuuid set in order for assembly to
- // work, but can't have it set if we want this printout to match
- // all the other uuid printouts in super1.c, so we force swapuuid
- // to 1 to make our printout match the rest of super1
+/**
+ * fname_from_uuid() - generate uuid string. Should not be used with super1.
+ * @info: info with uuid
+ * @buf: buf to fill.
+ *
+ * This routine should not be used with super1. See detail_fname_from_uuid() for details. It does
+ * not use superswitch swapuuid as it should be 0 but it has to do UUID conversion if host is big
+ * endian- left for backward compatibility.
+ */
+char *fname_from_uuid(struct mdinfo *info, char *buf)
+{
#if __BYTE_ORDER == BIG_ENDIAN
- return __fname_from_uuid(info->uuid, 1, buf, sep);
+ return __fname_from_uuid(info->uuid, true, buf, ':');
#else
- return __fname_from_uuid(info->uuid, (st->ss == &super1) ? 1 :
- st->ss->swapuuid, buf, sep);
+ return __fname_from_uuid(info->uuid, false, buf, ':');
#endif
}
--
2.40.1

View File

@ -0,0 +1,87 @@
From de23e12a39cfc94575e1173293fe9e15337ee999 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 18 Mar 2024 16:53:31 +0100
Subject: [PATCH 39/41] sysfs: remove vers parameter from sysfs_set_array
9003 was passed directly to sysfs_set_array() since md_get_version()
always returned this value. md_get_version() was removed long ago.
Remove dead version check from sysfs_set_array().
Remove "vers" argument and fix function calls.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Assemble.c | 2 +-
mdadm.h | 2 +-
sysfs.c | 6 ++----
util.c | 3 +--
4 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 9d042055..f6c5b99e 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1988,7 +1988,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
* 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) {
+ if (sysfs_set_array(content) != 0) {
sysfs_free(sra);
return 1;
}
diff --git a/mdadm.h b/mdadm.h
index a363708a..ae2106a2 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -811,7 +811,7 @@ extern int sysfs_attribute_available(struct mdinfo *sra, struct mdinfo *dev,
extern int sysfs_get_str(struct mdinfo *sra, struct mdinfo *dev,
char *name, char *val, int size);
extern int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms);
-extern int sysfs_set_array(struct mdinfo *info, int vers);
+extern int sysfs_set_array(struct mdinfo *info);
extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume);
extern int sysfs_disk_to_scsi_id(int fd, __u32 *id);
extern int sysfs_unique_holder(char *devnm, long rdev);
diff --git a/sysfs.c b/sysfs.c
index 230b842e..4ded1672 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -678,7 +678,7 @@ int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms)
return sysfs_set_str(sra, NULL, "safe_mode_delay", delay);
}
-int sysfs_set_array(struct mdinfo *info, int vers)
+int sysfs_set_array(struct mdinfo *info)
{
int rv = 0;
char ver[100];
@@ -702,9 +702,7 @@ int sysfs_set_array(struct mdinfo *info, int vers)
if (strlen(buf) >= 9 && buf[9] == '-')
ver[9] = '-';
- if ((vers % 100) < 2 ||
- sysfs_set_str(info, NULL, "metadata_version",
- ver) < 0) {
+ if (sysfs_set_str(info, NULL, "metadata_version", ver) < 0) {
pr_err("This kernel does not support external metadata.\n");
return 1;
}
diff --git a/util.c b/util.c
index 03336d6f..9e837045 100644
--- a/util.c
+++ b/util.c
@@ -1867,8 +1867,7 @@ int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info)
int rv;
if (st->ss->external)
- return sysfs_set_array(info, 9003);
-
+ return sysfs_set_array(info);
memset(&inf, 0, sizeof(inf));
inf.major_version = info->array.major_version;
inf.minor_version = info->array.minor_version;
--
2.40.1

View File

@ -0,0 +1,55 @@
From ae996e81232b8ba991e763dfa15577a0af358358 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 18 Mar 2024 17:28:42 +0100
Subject: [PATCH 40/41] mdadm: fix grow segfault for IMSM
If sc is not initialized, there is possibility that sc.pols is not zeroed
and it causes segfault.
Add missing initialization.
Add missing dev_policy_free() in two places.
Fixes: f656201188d7 ("mdadm: drop get_required_spare_criteria()")
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Incremental.c | 1 +
super-intel.c | 9 +++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 958ba9ba..83db0712 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -874,6 +874,7 @@ mdadm_status_t incremental_external_test_spare_criteria(struct supertype *st, ch
rv = MDADM_STATUS_SUCCESS;
out:
+ dev_policy_free(sc.pols);
dup->ss->free_super(dup);
free(dup);
diff --git a/super-intel.c b/super-intel.c
index ff2590fe..70f3c4ef 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -11518,10 +11518,15 @@ static int imsm_reshape_is_allowed_on_container(struct supertype *st,
*/
static struct mdinfo *get_spares_for_grow(struct supertype *st)
{
- struct spare_criteria sc;
+ struct spare_criteria sc = {0};
+ struct mdinfo *spares;
get_spare_criteria_imsm(st, NULL, &sc);
- return container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
+ spares = container_choose_spares(st, &sc, NULL, NULL, NULL, 0);
+
+ dev_policy_free(sc.pols);
+
+ return spares;
}
/******************************************************************************
--
2.40.1

View File

@ -0,0 +1,85 @@
From da4d58b6d01ed8b0149b777eba7818861fde8c80 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Tue, 19 Mar 2024 11:15:29 +0100
Subject: [PATCH 41/41] Remove all "if zeros" pt.2
Commit e15e8b00cbce ("Remove all "if zeros"") did not remove all "if 0"
code blocks.
This commit is cleanup for that commit.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Build.c | 6 ------
Grow.c | 13 +------------
super1.c | 11 -----------
3 files changed, 1 insertion(+), 29 deletions(-)
diff --git a/Build.c b/Build.c
index 1fbf8596..1be90e41 100644
--- a/Build.c
+++ b/Build.c
@@ -156,12 +156,6 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
bitmap_fd = open(s->bitmap_file, O_RDWR);
if (bitmap_fd < 0) {
int major = BITMAP_MAJOR_HI;
-#if 0
- if (s->bitmap_chunk == UnSet) {
- pr_err("%s cannot be opened.\n", s->bitmap_file);
- goto abort;
- }
-#endif
bitmapsize = s->size >> 9; /* FIXME wrong for RAID10 */
if (CreateBitmap(s->bitmap_file, 1, NULL,
s->bitmap_chunk, c->delay,
diff --git a/Grow.c b/Grow.c
index c69a342d..074f1995 100644
--- a/Grow.c
+++ b/Grow.c
@@ -4413,19 +4413,8 @@ static void validate(int afd, int bfd, unsigned long long offset)
lseek64(afd, __le64_to_cpu(bsb2.arraystart)*512, 0);
if ((unsigned long long)read(afd, abuf, len) != len)
fail("read first from array failed");
- if (memcmp(bbuf, abuf, len) != 0) {
-#if 0
- int i;
- printf("offset=%llu len=%llu\n",
- (unsigned long long)__le64_to_cpu(bsb2.arraystart)*512, len);
- for (i=0; i<len; i++)
- if (bbuf[i] != abuf[i]) {
- printf("first diff byte %d\n", i);
- break;
- }
-#endif
+ if (memcmp(bbuf, abuf, len) != 0)
fail("data1 compare failed");
- }
}
if (bsb2.length2) {
unsigned long long len = __le64_to_cpu(bsb2.length2)*512;
diff --git a/super1.c b/super1.c
index 5439b7bb..81d29a65 100644
--- a/super1.c
+++ b/super1.c
@@ -575,17 +575,6 @@ static void examine_super1(struct supertype *st, char *homehost)
inconsistent = 1;
}
}
-#if 0
- /* This is confusing too */
- faulty = 0;
- for (i = 0; i < __le32_to_cpu(sb->max_dev); i++) {
- int role = __le16_to_cpu(sb->dev_roles[i]);
- if (role == MD_DISK_ROLE_FAULTY)
- faulty++;
- }
- if (faulty)
- printf(" %d failed", faulty);
-#endif
printf(" ('A' == active, '.' == missing, 'R' == replacing)");
printf("\n");
for (d = 0; d < __le32_to_cpu(sb->max_dev); d++) {
--
2.40.1

View File

@ -0,0 +1,44 @@
From cc75b0faaa016e54d569486c9a7abe6c39cb883a Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 22 Mar 2024 12:51:15 +0100
Subject: [PATCH 42/66] mdadm: Move pr_vrb define to mdadm.h
Move pr_vrb define from super-intel.c to mdadm.h to make it widely
available. This change will be used in the next patches.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 2 ++
super-intel.c | 2 --
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index ae2106a2..fbb161ba 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1911,6 +1911,8 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
#define pr_info(fmt, args...) printf("%s: "fmt, Name, ##args)
+#define pr_vrb(fmt, arg...) ((void)(verbose && pr_err(fmt, ##arg)))
+
void *xmalloc(size_t len);
void *xrealloc(void *ptr, size_t len);
void *xcalloc(size_t num, size_t size);
diff --git a/super-intel.c b/super-intel.c
index 70f3c4ef..212387ec 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -393,8 +393,6 @@ struct md_list {
struct md_list *next;
};
-#define pr_vrb(fmt, arg...) (void) (verbose && pr_err(fmt, ##arg))
-
static __u8 migr_type(struct imsm_dev *dev)
{
if (dev->vol.migr_type == MIGR_VERIFY &&
--
2.41.0

View File

@ -0,0 +1,463 @@
From cc48406887b3bc439e3462e8e4d20f992e81b87e Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 22 Mar 2024 12:51:16 +0100
Subject: [PATCH 43/66] Add reading Opal NVMe encryption information
For NVMe devices with Opal support, encryption information, status and
ability are determined based on Opal Level 0 discovery response. Technical
documentation used is given in the implementation.
Ability in general describes what type of encryption is supported, Status
describes in what state the disk with encryption support is. The current
patch includes only the implementation of reading encryption information,
functions will be used in one of the next patches.
Motivation for adding this functionality is to block mixing of disks in
IMSM arrays with encryption enabled and disabled. The main goal is to not
allow stealing data by rebuilding array to not encrypted drive which can be
read elsewhere.
Value ENA_OTHER from enum encryption_ability will be used in the next
patch.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Makefile | 4 +-
drive_encryption.c | 362 +++++++++++++++++++++++++++++++++++++++++++++
drive_encryption.h | 32 ++++
3 files changed, 396 insertions(+), 2 deletions(-)
create mode 100644 drive_encryption.c
create mode 100644 drive_encryption.h
diff --git a/Makefile b/Makefile
index cbdba49a..7c221a89 100644
--- a/Makefile
+++ b/Makefile
@@ -170,7 +170,7 @@ OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o uuid.o util.o maps.o lib.o u
mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \
super-mbr.o super-gpt.o \
restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o xmalloc.o \
- platform-intel.o probe_roms.o crc32c.o
+ platform-intel.o probe_roms.o crc32c.o drive_encryption.o
CHECK_OBJS = restripe.o uuid.o sysfs.o maps.o lib.o xmalloc.o dlink.o
@@ -183,7 +183,7 @@ MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o c
Kill.o sg_io.o dlink.o ReadMe.o super-intel.o \
super-mbr.o super-gpt.o \
super-ddf.o sha1.o crc32.o msg.o bitmap.o xmalloc.o \
- platform-intel.o probe_roms.o crc32c.o
+ platform-intel.o probe_roms.o crc32c.o drive_encryption.o
MON_SRCS = $(patsubst %.o,%.c,$(MON_OBJS))
diff --git a/drive_encryption.c b/drive_encryption.c
new file mode 100644
index 00000000..b44585a7
--- /dev/null
+++ b/drive_encryption.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Read encryption information for Opal and ATA devices.
+ *
+ * Copyright (C) 2024 Intel Corporation
+ * Author: Blazej Kucman <blazej.kucman@intel.com>
+ */
+
+#include "mdadm.h"
+
+#include <asm/types.h>
+#include <linux/nvme_ioctl.h>
+#include "drive_encryption.h"
+
+/*
+ * Opal defines
+ * TCG Storage Opal SSC 2.01 chapter 3.3.3
+ * NVM ExpressTM Revision 1.4c, chapter 5
+ */
+#define TCG_SECP_01 (0x01)
+#define TCG_SECP_00 (0x00)
+#define OPAL_DISCOVERY_COMID (0x0001)
+#define OPAL_LOCKING_FEATURE (0x0002)
+#define OPAL_IO_BUFFER_LEN 2048
+#define OPAL_DISCOVERY_FEATURE_HEADER_LEN (4)
+
+/*
+ * NVMe defines
+ * NVM ExpressTM Revision 1.4c, chapter 5
+ */
+#define NVME_SECURITY_RECV (0x82)
+#define NVME_IDENTIFY (0x06)
+#define NVME_IDENTIFY_RESPONSE_LEN 4096
+#define NVME_OACS_BYTE_POSITION (256)
+#define NVME_IDENTIFY_CONTROLLER_DATA (1)
+
+typedef enum drive_feature_support_status {
+ /* Drive feature is supported. */
+ DRIVE_FEAT_SUP_ST = 0,
+ /* Drive feature is not supported. */
+ DRIVE_FEAT_NOT_SUP_ST,
+ /* Drive feature support check failed. */
+ DRIVE_FEAT_CHECK_FAILED_ST
+} drive_feat_sup_st;
+
+/* TCG Storage Opal SSC 2.01 chapter 3.1.1.3 */
+typedef struct opal_locking_feature {
+ /* feature header */
+ __u16 feature_code;
+ __u8 reserved : 4;
+ __u8 version : 4;
+ __u8 description_length;
+ /* feature description */
+ __u8 locking_supported : 1;
+ __u8 locking_enabled : 1;
+ __u8 locked : 1;
+ __u8 media_encryption : 1;
+ __u8 mbr_enabled : 1;
+ __u8 mbr_done : 1;
+ __u8 mbr_shadowing_not_supported : 1;
+ __u8 hw_reset_for_dor_supported : 1;
+ __u8 reserved1[11];
+} __attribute__((__packed__)) opal_locking_feature_t;
+
+/* TCG Storage Opal SSC 2.01 chapter 3.1.1.1 */
+typedef struct opal_level0_header {
+ __u32 length;
+ __u32 version;
+ __u64 reserved;
+ __u8 vendor_specific[32];
+} opal_level0_header_t;
+
+/**
+ * NVM ExpressTM Revision 1.4c, Figure 249
+ * Structure specifies only OACS filed, which is needed in the current use case.
+ */
+typedef struct nvme_identify_ctrl {
+ __u8 reserved[255];
+ __u16 oacs;
+ __u8 reserved2[3839];
+} nvme_identify_ctrl_t;
+
+/* SCSI Primary Commands - 4 (SPC-4), Table 512 */
+typedef struct supported_security_protocols {
+ __u8 reserved[6];
+ __u16 list_length;
+ __u8 list[504];
+} supported_security_protocols_t;
+
+/**
+ * get_opal_locking_feature_description() - get opal locking feature description.
+ * @response: response from Opal Discovery Level 0.
+ *
+ * Based on the documentation TCG Storage Opal SSC 2.01 chapter 3.1.1,
+ * a Locking feature is searched for in Opal Level 0 Discovery response.
+ *
+ * Return: if locking feature is found, pointer to struct %opal_locking_feature_t, NULL otherwise.
+ */
+static opal_locking_feature_t *get_opal_locking_feature_description(__u8 *response)
+{
+ opal_level0_header_t *response_header = (opal_level0_header_t *)response;
+ int features_length = __be32_to_cpu(response_header->length);
+ int current_position = sizeof(*response_header);
+
+ while (current_position < features_length) {
+ opal_locking_feature_t *feature;
+
+ feature = (opal_locking_feature_t *)(response + current_position);
+
+ if (__be16_to_cpu(feature->feature_code) == OPAL_LOCKING_FEATURE)
+ return feature;
+
+ current_position += feature->description_length + OPAL_DISCOVERY_FEATURE_HEADER_LEN;
+ }
+
+ return NULL;
+}
+
+/**
+ * nvme_security_recv_ioctl() - nvme security receive ioctl.
+ * @disk_fd: a disk file descriptor.
+ * @sec_protocol: security protocol.
+ * @comm_id: command id.
+ * @response_buffer: response buffer to fill out.
+ * @buf_size: response buffer size.
+ * @verbose: verbose flag.
+ *
+ * Based on the documentations TCG Storage Opal SSC 2.01 chapter 3.3.3 and
+ * NVM ExpressTM Revision 1.4c, chapter 5.25,
+ * read security receive command via ioctl().
+ * On success, @response_buffer is completed.
+ *
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
+ */
+static mdadm_status_t
+nvme_security_recv_ioctl(int disk_fd, __u8 sec_protocol, __u16 comm_id, void *response_buffer,
+ size_t buf_size, const int verbose)
+{
+ struct nvme_admin_cmd nvme_cmd = {0};
+ int status;
+
+ nvme_cmd.opcode = NVME_SECURITY_RECV;
+ nvme_cmd.cdw10 = sec_protocol << 24 | comm_id << 8;
+ nvme_cmd.cdw11 = buf_size;
+ nvme_cmd.data_len = buf_size;
+ nvme_cmd.addr = (__u64)response_buffer;
+
+ status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
+ if (status != 0) {
+ pr_vrb("Failed to read NVMe security receive ioctl() for device /dev/%s, status: %d\n",
+ fd2kname(disk_fd), status);
+ return MDADM_STATUS_ERROR;
+ }
+
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * nvme_identify_ioctl() - NVMe identify ioctl.
+ * @disk_fd: a disk file descriptor.
+ * @response_buffer: response buffer to fill out.
+ * @buf_size: response buffer size.
+ * @verbose: verbose flag.
+ *
+ * Based on the documentations TCG Storage Opal SSC 2.01 chapter 3.3.3 and
+ * NVM ExpressTM Revision 1.4c, chapter 5.25,
+ * read NVMe identify via ioctl().
+ * On success, @response_buffer will be completed.
+ *
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
+ */
+static mdadm_status_t
+nvme_identify_ioctl(int disk_fd, void *response_buffer, size_t buf_size, const int verbose)
+{
+ struct nvme_admin_cmd nvme_cmd = {0};
+ int status;
+
+ nvme_cmd.opcode = NVME_IDENTIFY;
+ nvme_cmd.cdw10 = NVME_IDENTIFY_CONTROLLER_DATA;
+ nvme_cmd.data_len = buf_size;
+ nvme_cmd.addr = (__u64)response_buffer;
+
+ status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
+ if (status != 0) {
+ pr_vrb("Failed to read NVMe identify ioctl() for device /dev/%s, status: %d\n",
+ fd2kname(disk_fd), status);
+ return MDADM_STATUS_ERROR;
+ }
+
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * is_sec_prot_01h_supported() - check if security protocol 01h supported.
+ * @security_protocols: struct with response from disk (NVMe, SATA) describing supported
+ * security protocols.
+ *
+ * Return: true if TCG_SECP_01 found, false otherwise.
+ */
+static bool is_sec_prot_01h_supported(supported_security_protocols_t *security_protocols)
+{
+ int list_length = be16toh(security_protocols->list_length);
+ int index;
+
+ for (index = 0 ; index < list_length; index++) {
+ if (security_protocols->list[index] == TCG_SECP_01)
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * is_sec_prot_01h_supported_nvme() - check if security protocol 01h supported for given NVMe disk.
+ * @disk_fd: a disk file descriptor.
+ * @verbose: verbose flag.
+ *
+ * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
+ * %DRIVE_FEAT_CHECK_FAILED_ST if failed to check.
+ */
+static drive_feat_sup_st is_sec_prot_01h_supported_nvme(int disk_fd, const int verbose)
+{
+ supported_security_protocols_t security_protocols = {0};
+
+ /* security_protocol: TCG_SECP_00, comm_id: not applicable */
+ if (nvme_security_recv_ioctl(disk_fd, TCG_SECP_00, 0x0, &security_protocols,
+ sizeof(security_protocols), verbose))
+ return DRIVE_FEAT_CHECK_FAILED_ST;
+
+ if (is_sec_prot_01h_supported(&security_protocols))
+ return DRIVE_FEAT_SUP_ST;
+
+ return DRIVE_FEAT_NOT_SUP_ST;
+}
+
+/**
+ * is_nvme_sec_send_recv_supported() - check if Security Send and Security Receive is supported.
+ * @disk_fd: a disk file descriptor.
+ * @verbose: verbose flag.
+ *
+ * Check if "Optional Admin Command Support" bit 0 is set in NVMe identify.
+ * Bit 0 set to 1 means controller supports the Security Send and Security Receive commands.
+ *
+ * Return: %DRIVE_FEAT_SUP_ST if security send/receive supported,
+ * %DRIVE_FEAT_NOT_SUP_ST if not supported, %DRIVE_FEAT_CHECK_FAILED_ST if check failed.
+ */
+static drive_feat_sup_st is_nvme_sec_send_recv_supported(int disk_fd, const int verbose)
+{
+ nvme_identify_ctrl_t nvme_identify = {0};
+ int status = 0;
+
+ status = nvme_identify_ioctl(disk_fd, &nvme_identify, sizeof(nvme_identify), verbose);
+ if (status)
+ return DRIVE_FEAT_CHECK_FAILED_ST;
+
+ if ((__le16_to_cpu(nvme_identify.oacs) & 0x1) == 0x1)
+ return DRIVE_FEAT_SUP_ST;
+
+ return DRIVE_FEAT_NOT_SUP_ST;
+}
+
+/**
+ * get_opal_encryption_information() - get Opal encryption information.
+ * @buffer: buffer with Opal Level 0 Discovery response.
+ * @information: struct to fill out, describing encryption status of disk.
+ *
+ * If Locking feature frame is in response from Opal Level 0 discovery, &encryption_information_t
+ * structure is completed with status and ability otherwise the status is set to &None.
+ * For possible encryption statuses and abilities,
+ * please refer to enums &encryption_status and &encryption_ability.
+ *
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
+ */
+static mdadm_status_t get_opal_encryption_information(__u8 *buffer,
+ encryption_information_t *information)
+{
+ opal_locking_feature_t *opal_locking_feature =
+ get_opal_locking_feature_description(buffer);
+
+ if (!opal_locking_feature)
+ return MDADM_STATUS_ERROR;
+
+ if (opal_locking_feature->locking_supported == 1) {
+ information->ability = ENC_ABILITY_SED;
+
+ if (opal_locking_feature->locking_enabled == 0)
+ information->status = ENC_STATUS_UNENCRYPTED;
+ else if (opal_locking_feature->locked == 1)
+ information->status = ENC_STATUS_LOCKED;
+ else
+ information->status = ENC_STATUS_UNLOCKED;
+ } else {
+ information->ability = ENC_ABILITY_NONE;
+ information->status = ENC_STATUS_UNENCRYPTED;
+ }
+
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * get_nvme_opal_encryption_information() - get NVMe Opal encryption information.
+ * @disk_fd: a disk file descriptor.
+ * @information: struct to fill out, describing encryption status of disk.
+ * @verbose: verbose flag.
+ *
+ * In case the disk supports Opal Level 0 discovery, &encryption_information_t structure
+ * is completed with status and ability based on ioctl response,
+ * otherwise the ability is set to %ENC_ABILITY_NONE and &status to %ENC_STATUS_UNENCRYPTED.
+ * As the current use case does not need the knowledge of Opal support, if there is no support,
+ * %MDADM_STATUS_SUCCESS will be returned, with the values described above.
+ * For possible encryption statuses and abilities,
+ * please refer to enums &encryption_status and &encryption_ability.
+ *
+ * %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise.
+ */
+mdadm_status_t
+get_nvme_opal_encryption_information(int disk_fd, encryption_information_t *information,
+ const int verbose)
+{
+ __u8 buffer[OPAL_IO_BUFFER_LEN];
+ int sec_send_recv_supported = 0;
+ int protocol_01h_supported = 0;
+ mdadm_status_t status;
+
+ information->ability = ENC_ABILITY_NONE;
+ information->status = ENC_STATUS_UNENCRYPTED;
+
+ sec_send_recv_supported = is_nvme_sec_send_recv_supported(disk_fd, verbose);
+ if (sec_send_recv_supported == DRIVE_FEAT_CHECK_FAILED_ST)
+ return MDADM_STATUS_ERROR;
+
+ /* Opal not supported */
+ if (sec_send_recv_supported == DRIVE_FEAT_NOT_SUP_ST)
+ return MDADM_STATUS_SUCCESS;
+
+ /**
+ * sec_send_recv_supported determine that it should be possible to read
+ * supported sec protocols
+ */
+ protocol_01h_supported = is_sec_prot_01h_supported_nvme(disk_fd, verbose);
+ if (protocol_01h_supported == DRIVE_FEAT_CHECK_FAILED_ST)
+ return MDADM_STATUS_ERROR;
+
+ /* Opal not supported */
+ if (sec_send_recv_supported == DRIVE_FEAT_SUP_ST &&
+ protocol_01h_supported == DRIVE_FEAT_NOT_SUP_ST)
+ return MDADM_STATUS_SUCCESS;
+
+ if (nvme_security_recv_ioctl(disk_fd, TCG_SECP_01, OPAL_DISCOVERY_COMID, (void *)&buffer,
+ OPAL_IO_BUFFER_LEN, verbose))
+ return MDADM_STATUS_ERROR;
+
+ status = get_opal_encryption_information((__u8 *)&buffer, information);
+ if (status)
+ pr_vrb("Locking feature description not found in Level 0 discovery response. Device /dev/%s.\n",
+ fd2kname(disk_fd));
+
+ if (information->ability == ENC_ABILITY_NONE)
+ assert(information->status == ENC_STATUS_UNENCRYPTED);
+
+ return status;
+}
diff --git a/drive_encryption.h b/drive_encryption.h
new file mode 100644
index 00000000..82c2c624
--- /dev/null
+++ b/drive_encryption.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Read encryption information for Opal and ATA devices.
+ *
+ * Copyright (C) 2024 Intel Corporation
+ * Author: Blazej Kucman <blazej.kucman@intel.com>
+ */
+
+typedef enum encryption_status {
+ /* The drive is not currently encrypted. */
+ ENC_STATUS_UNENCRYPTED = 0,
+ /* The drive is encrypted and the data is not accessible. */
+ ENC_STATUS_LOCKED,
+ /* The drive is encrypted but the data is accessible in unencrypted form. */
+ ENC_STATUS_UNLOCKED
+} encryption_status_t;
+
+typedef enum encryption_ability {
+ ENC_ABILITY_NONE = 0,
+ ENC_ABILITY_OTHER,
+ /* Self encrypted drive */
+ ENC_ABILITY_SED
+} encryption_ability_t;
+
+typedef struct encryption_information {
+ encryption_ability_t ability;
+ encryption_status_t status;
+} encryption_information_t;
+
+mdadm_status_t
+get_nvme_opal_encryption_information(int disk_fd, struct encryption_information *information,
+ const int verbose);
--
2.41.0

View File

@ -0,0 +1,459 @@
From df38df3052c3386c0fd076e0d534b4f688b5c8a4 Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 22 Mar 2024 12:51:17 +0100
Subject: [PATCH 44/66] Add reading SATA encryption information
Functionality reads information about SATA disk encryption. Technical
documentation used is given in the implementation.
The implementation is able to recognized two encryption standards for SATA
drives, OPAL and ATA security.
If the SATA drive supports OPAL, encryption status and ability are
determined based on Opal Level 0 discovery response, for ATA security,
based on ATA identify response. If SATA supports OPAL, ability is set to
"SED", for ATA security to "Other".
SED(Self-Encrypting Drive) is commonly used to describe drive which using
OPAL or Enterprise standards developed by Trusted Computing Group. Ability
"Other" is used for ATA security because we rely only on information from
ATA identify which describe the overall state of encryption.
It is allowed to mix disks with different encryption ability such as "SED"
and "Other" and it is not security gap.
Motivation for adding this functionality is to block mixing of disks in
IMSM arrays with encryption enabled and disabled. The main goal is to not
allow stealing data by rebuilding array to not encrypted drive which can be
read elsewhere.
For SATA Opal drives, libata allow_tmp parameter enabled is required, which
is necessary for Opal Security commands to work, therefore, if the
parameter is not enabled, SATA Opal disk cannot be used in case the
encryption will be checked by metadata.
Implemented functions will be used in one of the next patches. In one of
the next patches, a flag will be added to enable disabling SATA Opal
encryption checking due to allow_tpm kernel setting dependency.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
drive_encryption.c | 318 +++++++++++++++++++++++++++++++++++++++++++++
drive_encryption.h | 3 +
mdadm.h | 1 +
sysfs.c | 29 +++++
4 files changed, 351 insertions(+)
diff --git a/drive_encryption.c b/drive_encryption.c
index b44585a7..d520f0c7 100644
--- a/drive_encryption.c
+++ b/drive_encryption.c
@@ -10,8 +10,12 @@
#include <asm/types.h>
#include <linux/nvme_ioctl.h>
+#include <scsi/sg.h>
+#include <scsi/scsi.h>
#include "drive_encryption.h"
+#define DEFAULT_SECTOR_SIZE (512)
+
/*
* Opal defines
* TCG Storage Opal SSC 2.01 chapter 3.3.3
@@ -34,6 +38,35 @@
#define NVME_OACS_BYTE_POSITION (256)
#define NVME_IDENTIFY_CONTROLLER_DATA (1)
+/*
+ * ATA defines
+ * ATA/ATAPI Command Set ATA8-ACS
+ * SCSI / ATA Translation - 3 (SAT-3)
+ * SCSI Primary Commands - 4 (SPC-4)
+ * AT Attachment-8 - ATA Serial Transport (ATA8-AST)
+ * ATA Command Pass-Through
+ */
+#define ATA_IDENTIFY (0xec)
+#define ATA_TRUSTED_RECEIVE (0x5c)
+#define ATA_SECURITY_WORD_POSITION (128)
+#define HDIO_DRIVE_CMD (0x031f)
+#define ATA_TRUSTED_COMPUTING_POS (48)
+#define ATA_PASS_THROUGH_12 (0xa1)
+#define ATA_IDENTIFY_RESPONSE_LEN (512)
+#define ATA_PIO_DATA_IN (4)
+#define SG_CHECK_CONDITION (0x02)
+#define ATA_STATUS_RETURN_DESCRIPTOR (0x09)
+#define ATA_PT_INFORMATION_AVAILABLE_ASCQ (0x1d)
+#define ATA_PT_INFORMATION_AVAILABLE_ASC (0x00)
+#define ATA_INQUIRY_LENGTH (0x0c)
+#define SG_INTERFACE_ID 'S'
+#define SG_IO_TIMEOUT (60000)
+#define SG_SENSE_SIZE (32)
+#define SENSE_DATA_CURRENT_FIXED (0x70)
+#define SENSE_DATA_CURRENT_DESC (0x72)
+#define SENSE_CURRENT_RES_DESC_POS (8)
+#define SG_DRIVER_SENSE (0x08)
+
typedef enum drive_feature_support_status {
/* Drive feature is supported. */
DRIVE_FEAT_SUP_ST = 0,
@@ -87,6 +120,27 @@ typedef struct supported_security_protocols {
__u8 list[504];
} supported_security_protocols_t;
+/* ATA/ATAPI Command Set - 3 (ACS-3), Table 45 */
+typedef struct ata_security_status {
+ __u16 security_supported : 1;
+ __u16 security_enabled : 1;
+ __u16 security_locked : 1;
+ __u16 security_frozen : 1;
+ __u16 security_count_expired : 1;
+ __u16 enhanced_security_erase_supported : 1;
+ __u16 reserved1 : 2;
+ __u16 security_level : 1;
+ __u16 reserved2 : 7;
+} __attribute__((__packed__)) ata_security_status_t;
+
+/* ATA/ATAPI Command Set - 3 (ACS-3), Table 45 */
+typedef struct ata_trusted_computing {
+ __u16 tc_feature :1;
+ __u16 reserved : 13;
+ __u16 var1 : 1;
+ __u16 var2 : 1;
+} __attribute__((__packed__)) ata_trusted_computing_t;
+
/**
* get_opal_locking_feature_description() - get opal locking feature description.
* @response: response from Opal Discovery Level 0.
@@ -360,3 +414,267 @@ get_nvme_opal_encryption_information(int disk_fd, encryption_information_t *info
return status;
}
+
+/**
+ * ata_pass_through12_ioctl() - ata pass through12 ioctl.
+ * @disk_fd: a disk file descriptor.
+ * @ata_command: ata command.
+ * @sec_protocol: security protocol.
+ * @comm_id: additional command id.
+ * @response_buffer: response buffer to fill out.
+ * @buf_size: response buffer size.
+ * @verbose: verbose flag.
+ *
+ * Based on the documentations ATA Command Pass-Through, chapter 13.2.2 and
+ * ATA Translation - 3 (SAT-3), send read ata pass through 12 command via ioctl().
+ * On success, @response_buffer will be completed.
+ *
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
+ */
+static mdadm_status_t
+ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u16 comm_id,
+ void *response_buffer, size_t buf_size, const int verbose)
+{
+ __u8 cdb[ATA_INQUIRY_LENGTH] = {0};
+ __u8 sense[SG_SENSE_SIZE] = {0};
+ __u8 *sense_desc = NULL;
+ sg_io_hdr_t sg = {0};
+
+ /*
+ * ATA Command Pass-Through, chapter 13.2.2
+ * SCSI Primary Commands - 4 (SPC-4)
+ * ATA Translation - 3 (SAT-3)
+ */
+ cdb[0] = ATA_PASS_THROUGH_12;
+ /* protocol, bits 1-4 */
+ cdb[1] = ATA_PIO_DATA_IN << 1;
+ /* Bytes: CK_COND=1, T_DIR = 1, BYTE_BLOCK = 1, Length in Sector Count = 2 */
+ cdb[2] = 0x2E;
+ cdb[3] = sec_protocol;
+ /* Sector count */
+ cdb[4] = buf_size / DEFAULT_SECTOR_SIZE;
+ cdb[6] = (comm_id) & 0xFF;
+ cdb[7] = (comm_id >> 8) & 0xFF;
+ cdb[9] = ata_command;
+
+ sg.interface_id = SG_INTERFACE_ID;
+ sg.cmd_len = sizeof(cdb);
+ sg.mx_sb_len = sizeof(sense);
+ sg.dxfer_direction = SG_DXFER_FROM_DEV;
+ sg.dxfer_len = buf_size;
+ sg.dxferp = response_buffer;
+ sg.cmdp = cdb;
+ sg.sbp = sense;
+ sg.timeout = SG_IO_TIMEOUT;
+ sg.usr_ptr = NULL;
+
+ if (ioctl(disk_fd, SG_IO, &sg) < 0) {
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
+ return MDADM_STATUS_ERROR;
+ }
+
+ if ((sg.status && sg.status != SG_CHECK_CONDITION) || sg.host_status ||
+ (sg.driver_status && sg.driver_status != SG_DRIVER_SENSE)) {
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
+ pr_vrb("SG_IO error: ATA_12 Status: %d Host Status: %d, Driver Status: %d\n",
+ sg.status, sg.host_status, sg.driver_status);
+ return MDADM_STATUS_ERROR;
+ }
+
+ /* verify expected sense response code */
+ if (!(sense[0] == SENSE_DATA_CURRENT_DESC || sense[0] == SENSE_DATA_CURRENT_FIXED)) {
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd));
+ return MDADM_STATUS_ERROR;
+ }
+
+ sense_desc = sense + SENSE_CURRENT_RES_DESC_POS;
+ /* verify sense data current response with descriptor format */
+ if (sense[0] == SENSE_DATA_CURRENT_DESC &&
+ !(sense_desc[0] == ATA_STATUS_RETURN_DESCRIPTOR &&
+ sense_desc[1] == ATA_INQUIRY_LENGTH)) {
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
+ fd2kname(disk_fd), sense[2], sense[3]);
+ return MDADM_STATUS_ERROR;
+ }
+
+ /* verify sense data current response with fixed format */
+ if (sense[0] == SENSE_DATA_CURRENT_FIXED &&
+ !(sense[12] == ATA_PT_INFORMATION_AVAILABLE_ASC &&
+ sense[13] == ATA_PT_INFORMATION_AVAILABLE_ASCQ)) {
+ pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n",
+ fd2kname(disk_fd), sense[12], sense[13]);
+ return MDADM_STATUS_ERROR;
+ }
+
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * is_sec_prot_01h_supported_ata() - check if security protocol 01h supported for given SATA disk.
+ * @disk_fd: a disk file descriptor.
+ * @verbose: verbose flag.
+ *
+ * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
+ * %DRIVE_FEAT_CHECK_FAILED_ST if failed.
+ */
+static drive_feat_sup_st is_sec_prot_01h_supported_ata(int disk_fd, const int verbose)
+{
+ supported_security_protocols_t security_protocols;
+
+ mdadm_status_t result = ata_pass_through12_ioctl(disk_fd, ATA_TRUSTED_RECEIVE, TCG_SECP_00,
+ 0x0, &security_protocols,
+ sizeof(security_protocols), verbose);
+ if (result)
+ return DRIVE_FEAT_CHECK_FAILED_ST;
+
+ if (is_sec_prot_01h_supported(&security_protocols))
+ return DRIVE_FEAT_SUP_ST;
+
+ return DRIVE_FEAT_NOT_SUP_ST;
+}
+
+/**
+ * is_ata_trusted_computing_supported() - check if ata trusted computing supported.
+ * @buffer: buffer with ATA identify response, not NULL.
+ *
+ * Return: true if trusted computing bit set, false otherwise.
+ */
+bool is_ata_trusted_computing_supported(__u16 *buffer)
+{
+ /* Added due to warnings from the compiler about a possible uninitialized variable below. */
+ assert(buffer);
+
+ __u16 security_tc_frame = __le16_to_cpu(buffer[ATA_TRUSTED_COMPUTING_POS]);
+ ata_trusted_computing_t *security_tc = (ata_trusted_computing_t *)&security_tc_frame;
+
+ if (security_tc->tc_feature == 1)
+ return true;
+
+ return false;
+}
+
+/**
+ * get_ata_standard_security_status() - get ATA disk encryption information from ATA identify.
+ * @buffer: buffer with response from ATA identify, not NULL.
+ * @information: struct to fill out, describing encryption status of disk.
+ *
+ * The function based on the Security status frame from ATA identify,
+ * completed encryption information.
+ * For possible encryption statuses and abilities,
+ * please refer to enums &encryption_status and &encryption_ability.
+ *
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
+ */
+static mdadm_status_t get_ata_standard_security_status(__u16 *buffer,
+ struct encryption_information *information)
+{
+ /* Added due to warnings from the compiler about a possible uninitialized variable below. */
+ assert(buffer);
+
+ __u16 security_status_frame = __le16_to_cpu(buffer[ATA_SECURITY_WORD_POSITION]);
+ ata_security_status_t *security_status = (ata_security_status_t *)&security_status_frame;
+
+ if (!security_status->security_supported) {
+ information->ability = ENC_ABILITY_NONE;
+ information->status = ENC_STATUS_UNENCRYPTED;
+
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ information->ability = ENC_ABILITY_OTHER;
+
+ if (security_status->security_enabled == 0)
+ information->status = ENC_STATUS_UNENCRYPTED;
+ else if (security_status->security_locked == 1)
+ information->status = ENC_STATUS_LOCKED;
+ else
+ information->status = ENC_STATUS_UNLOCKED;
+
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * is_ata_opal() - check if SATA disk support Opal.
+ * @disk_fd: a disk file descriptor.
+ * @buffer: buffer with ATA identify response.
+ * @verbose: verbose flag.
+ *
+ * Return: %DRIVE_FEAT_SUP_ST if TCG_SECP_01 supported, %DRIVE_FEAT_NOT_SUP_ST if not supported,
+ * %DRIVE_FEAT_CHECK_FAILED_ST if failed to check.
+ */
+static drive_feat_sup_st is_ata_opal(int disk_fd, __u16 *buffer_identify, const int verbose)
+{
+ bool tc_status = is_ata_trusted_computing_supported(buffer_identify);
+ drive_feat_sup_st tcg_sec_prot_status;
+
+ if (!tc_status)
+ return DRIVE_FEAT_NOT_SUP_ST;
+
+ tcg_sec_prot_status = is_sec_prot_01h_supported_ata(disk_fd, verbose);
+
+ if (tcg_sec_prot_status == DRIVE_FEAT_CHECK_FAILED_ST) {
+ pr_vrb("Failed to verify if security protocol 01h supported. Device /dev/%s.\n",
+ fd2kname(disk_fd));
+ return DRIVE_FEAT_CHECK_FAILED_ST;
+ }
+
+ if (tc_status && tcg_sec_prot_status == DRIVE_FEAT_SUP_ST)
+ return DRIVE_FEAT_SUP_ST;
+
+ return DRIVE_FEAT_NOT_SUP_ST;
+}
+
+/**
+ * get_ata_encryption_information() - get ATA disk encryption information.
+ * @disk_fd: a disk file descriptor.
+ * @information: struct to fill out, describing encryption status of disk.
+ * @verbose: verbose flag.
+ *
+ * The function reads information about encryption, if the disk supports Opal,
+ * the information is completed based on Opal Level 0 discovery, otherwise,
+ * based on ATA security status frame from ATA identification response.
+ * For possible encryption statuses and abilities,
+ * please refer to enums &encryption_status and &encryption_ability.
+ *
+ * Based on the documentations ATA/ATAPI Command Set ATA8-ACS and
+ * AT Attachment-8 - ATA Serial Transport (ATA8-AST).
+ *
+ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR on fail.
+ */
+mdadm_status_t
+get_ata_encryption_information(int disk_fd, struct encryption_information *information,
+ const int verbose)
+{
+ __u8 buffer_opal_level0_discovery[OPAL_IO_BUFFER_LEN] = {0};
+ __u16 buffer_identify[ATA_IDENTIFY_RESPONSE_LEN] = {0};
+ drive_feat_sup_st ata_opal_status;
+ mdadm_status_t status;
+
+ /* Get disk ATA identification */
+ status = ata_pass_through12_ioctl(disk_fd, ATA_IDENTIFY, 0x0, 0x0, buffer_identify,
+ sizeof(buffer_identify), verbose);
+ if (status == MDADM_STATUS_ERROR)
+ return MDADM_STATUS_ERROR;
+
+ if (is_ata_trusted_computing_supported(buffer_identify) &&
+ !sysfs_is_libata_allow_tpm_enabled(verbose)) {
+ pr_vrb("For SATA with Trusted Computing support, required libata.tpm_enabled=1.\n");
+ return MDADM_STATUS_ERROR;
+ }
+
+ ata_opal_status = is_ata_opal(disk_fd, buffer_identify, verbose);
+ if (ata_opal_status == DRIVE_FEAT_CHECK_FAILED_ST)
+ return MDADM_STATUS_ERROR;
+
+ if (ata_opal_status == DRIVE_FEAT_NOT_SUP_ST)
+ return get_ata_standard_security_status(buffer_identify, information);
+
+ /* SATA Opal */
+ status = ata_pass_through12_ioctl(disk_fd, ATA_TRUSTED_RECEIVE, TCG_SECP_01,
+ OPAL_DISCOVERY_COMID, buffer_opal_level0_discovery,
+ OPAL_IO_BUFFER_LEN, verbose);
+ if (status != MDADM_STATUS_SUCCESS)
+ return MDADM_STATUS_ERROR;
+
+ return get_opal_encryption_information(buffer_opal_level0_discovery, information);
+}
diff --git a/drive_encryption.h b/drive_encryption.h
index 82c2c624..77c7f10f 100644
--- a/drive_encryption.h
+++ b/drive_encryption.h
@@ -30,3 +30,6 @@ typedef struct encryption_information {
mdadm_status_t
get_nvme_opal_encryption_information(int disk_fd, struct encryption_information *information,
const int verbose);
+mdadm_status_t
+get_ata_encryption_information(int disk_fd, struct encryption_information *information,
+ const int verbose);
diff --git a/mdadm.h b/mdadm.h
index fbb161ba..52a66b9a 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -853,6 +853,7 @@ extern int restore_stripes(int *dest, unsigned long long *offsets,
int source, unsigned long long read_offset,
unsigned long long start, unsigned long long length,
char *src_buf);
+extern bool sysfs_is_libata_allow_tpm_enabled(const int verbose);
#ifndef Sendmail
#define Sendmail "/usr/lib/sendmail -t"
diff --git a/sysfs.c b/sysfs.c
index 4ded1672..20fe1e9e 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -1121,3 +1121,32 @@ void sysfsline(char *line)
sr->next = sysfs_rules;
sysfs_rules = sr;
}
+
+/**
+ * sysfs_is_libata_allow_tpm_enabled() - check if libata allow_tmp is enabled.
+ * @verbose: verbose flag.
+ *
+ * Check if libata allow_tmp flag is set, this is required for SATA Opal Security commands to work.
+ *
+ * Return: true if allow_tpm enable, false otherwise.
+ */
+bool sysfs_is_libata_allow_tpm_enabled(const int verbose)
+{
+ const char *path = "/sys/module/libata/parameters/allow_tpm";
+ const char *expected_value = "1";
+ int fd = open(path, O_RDONLY);
+ char buf[3];
+
+ if (!is_fd_valid(fd)) {
+ pr_vrb("Failed open file descriptor to %s. Cannot check libata allow_tpm param.\n",
+ path);
+ return false;
+ }
+
+ sysfs_fd_get_str(fd, buf, sizeof(buf));
+ close(fd);
+
+ if (strncmp(buf, expected_value, 1) == 0)
+ return true;
+ return false;
+}
--
2.41.0

View File

@ -0,0 +1,163 @@
From 336e13fc5ef43bc5b4633a9dadac5f7208e6c241 Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 22 Mar 2024 12:51:18 +0100
Subject: [PATCH 45/66] Add key ENCRYPTION_NO_VERIFY to conf
Add ENCRYPTION_NO_VERIFY config key and allow to disable checking
encryption status for given type of drives.
The key is introduced because of SATA Opal disks for which TPM commands
must be enabled in libata kernel module, (libata.allow_tpm=1), otherwise
it is impossible to verify encryption status. TPM commands are disabled by
default.
Currently the key only supports the "sata_opal" value, if necessary,
the functionality is ready to support more types of disks. This
functionality will be used in the next patches.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
config.c | 25 ++++++++++++++++++++++++-
drive_encryption.c | 16 ++++++++++++----
mdadm.conf.5.in | 13 +++++++++++++
mdadm.h | 1 +
4 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/config.c b/config.c
index 44f7dd2f..b46d71cb 100644
--- a/config.c
+++ b/config.c
@@ -81,7 +81,7 @@ char DefaultAltConfDir[] = CONFFILE2 ".d";
enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev,
Homehost, HomeCluster, AutoMode, Policy, PartPolicy, Sysfs,
- MonitorDelay, LTEnd };
+ MonitorDelay, EncryptionNoVerify, LTEnd };
char *keywords[] = {
[Devices] = "devices",
[Array] = "array",
@@ -96,6 +96,7 @@ char *keywords[] = {
[PartPolicy]="part-policy",
[Sysfs] = "sysfs",
[MonitorDelay] = "monitordelay",
+ [EncryptionNoVerify] = "ENCRYPTION_NO_VERIFY",
[LTEnd] = NULL
};
@@ -729,6 +730,19 @@ void monitordelayline(char *line)
}
}
+static bool sata_opal_encryption_no_verify;
+void encryption_no_verify_line(char *line)
+{
+ char *word;
+
+ for (word = dl_next(line); word != line; word = dl_next(word)) {
+ if (strcasecmp(word, "sata_opal") == 0)
+ sata_opal_encryption_no_verify = true;
+ else
+ pr_err("unrecognised word on ENCRYPTION_NO_VERIFY line: %s\n", word);
+ }
+}
+
char auto_yes[] = "yes";
char auto_no[] = "no";
char auto_homehost[] = "homehost";
@@ -913,6 +927,9 @@ void conf_file(FILE *f)
case MonitorDelay:
monitordelayline(line);
break;
+ case EncryptionNoVerify:
+ encryption_no_verify_line(line);
+ break;
default:
pr_err("Unknown keyword %s\n", line);
}
@@ -1075,6 +1092,12 @@ int conf_get_monitor_delay(void)
return monitor_delay;
}
+bool conf_get_sata_opal_encryption_no_verify(void)
+{
+ load_conffile();
+ return sata_opal_encryption_no_verify;
+}
+
struct createinfo *conf_get_create_info(void)
{
load_conffile();
diff --git a/drive_encryption.c b/drive_encryption.c
index d520f0c7..6b2bd358 100644
--- a/drive_encryption.c
+++ b/drive_encryption.c
@@ -656,10 +656,18 @@ get_ata_encryption_information(int disk_fd, struct encryption_information *infor
if (status == MDADM_STATUS_ERROR)
return MDADM_STATUS_ERROR;
- if (is_ata_trusted_computing_supported(buffer_identify) &&
- !sysfs_is_libata_allow_tpm_enabled(verbose)) {
- pr_vrb("For SATA with Trusted Computing support, required libata.tpm_enabled=1.\n");
- return MDADM_STATUS_ERROR;
+ /* Possible OPAL support, further checks require tpm_enabled.*/
+ if (is_ata_trusted_computing_supported(buffer_identify)) {
+ /* OPAL SATA encryption checking disabled. */
+ if (conf_get_sata_opal_encryption_no_verify())
+ return MDADM_STATUS_SUCCESS;
+
+ if (!sysfs_is_libata_allow_tpm_enabled(verbose)) {
+ pr_vrb("Detected SATA drive /dev/%s with Trusted Computing support.\n",
+ fd2kname(disk_fd));
+ pr_vrb("Cannot verify encryption state. Requires libata.tpm_enabled=1.\n");
+ return MDADM_STATUS_ERROR;
+ }
}
ata_opal_status = is_ata_opal(disk_fd, buffer_identify, verbose);
diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in
index 787e51e9..afb0a296 100644
--- a/mdadm.conf.5.in
+++ b/mdadm.conf.5.in
@@ -636,6 +636,17 @@ If multiple
.B MINITORDELAY
lines are provided, only first non-zero value is considered.
+.TP
+.B ENCRYPTION_NO_VERIFY
+The
+.B ENCRYPTION_NO_VERIFY
+disables encryption verification for devices with particular encryption support detected.
+Currently, only verification of SATA OPAL encryption can be disabled.
+It does not disable ATA security encryption verification.
+Available parameter
+.I "sata_opal".
+
+
.SH FILES
.SS {CONFFILE}
@@ -744,6 +755,8 @@ SYSFS uuid=bead5eb6:31c17a27:da120ba2:7dfda40d group_thread_cnt=4
sync_speed_max=1000000
.br
MONITORDELAY 60
+.br
+ENCRYPTION_NO_VERIFY sata_opal
.SH SEE ALSO
.BR mdadm (8),
diff --git a/mdadm.h b/mdadm.h
index 52a66b9a..2640b396 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1673,6 +1673,7 @@ extern char *conf_get_program(void);
extern char *conf_get_homehost(int *require_homehostp);
extern char *conf_get_homecluster(void);
extern int conf_get_monitor_delay(void);
+extern bool conf_get_sata_opal_encryption_no_verify(void);
extern char *conf_line(FILE *file);
extern char *conf_word(FILE *file, int allow_key);
extern void print_quoted(char *str);
--
2.41.0

View File

@ -0,0 +1,217 @@
From bf62ed5d9642aa60abf4ac2d1d89f173bd66ae48 Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 22 Mar 2024 12:51:19 +0100
Subject: [PATCH 46/66] imsm: print disk encryption information
Print SATA/NVMe disk encryption information in --detail-platform.
Encryption Ability and Status will be printed for each disk.
There is one exception, Opal SATA drives encryption is not checked when
ENCRYPTION_NO_VERIFY key with "sata_opal" value is set in conf, for this
reason such drives are treated as without encryption support.
To test this feature, drives SATA/NVMe with Opal support or SATA drives
with encryption support have to be used.
Example outputs of --detail-platform:
Non Opal, encryption enabled, SATA drive:
Port0 : /dev/sdc (CVPR050600G3120LGN)
Encryption(Ability|Status): Other|Unlocked
NVMe drive without Opal support:
NVMe under VMD : /dev/nvme2n1 (PHLF737302GB1P0GGN)
Encryption(Ability|Status): None|Unencrypted
Unencrypted SATA drive with OPAL support:
- default allow_tpm, we will get an error from mdadm:
Port6 : /dev/sdi (CVTS4246015V180IGN)
mdadm: Detected SATA drive /dev/sdi with Trusted Computing support.
mdadm: Cannot verify encryption state. Requires libata.tpm_enabled=1.
mdadm: Failed to get drive encrytpion information.
- default "allow_tpm" and config entry "ENCRYPTION_NO_VERIFY sata_opal":
Port6 : /dev/sdi (CVTS4246015V180IGN)
Encryption(Ability|Status): None|Unencrypted
- added "libata.allow_tpm=1" to boot parameters(requires reboot),
the status will be read correctly:
Port6 : /dev/sdi (CVTS4246015V180IGN)
Encryption(Ability|Status): SED|Unencrypted
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
drive_encryption.c | 36 ++++++++++++++++++++++++++++++++++++
drive_encryption.h | 2 ++
mdadm.conf.5.in | 3 +++
super-intel.c | 42 ++++++++++++++++++++++++++++++++++++++----
4 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/drive_encryption.c b/drive_encryption.c
index 6b2bd358..27da9621 100644
--- a/drive_encryption.c
+++ b/drive_encryption.c
@@ -141,6 +141,42 @@ typedef struct ata_trusted_computing {
__u16 var2 : 1;
} __attribute__((__packed__)) ata_trusted_computing_t;
+mapping_t encryption_ability_map[] = {
+ { "None", ENC_ABILITY_NONE },
+ { "Other", ENC_ABILITY_OTHER },
+ { "SED", ENC_ABILITY_SED },
+ { NULL, UnSet }
+};
+
+mapping_t encryption_status_map[] = {
+ { "Unencrypted", ENC_STATUS_UNENCRYPTED },
+ { "Locked", ENC_STATUS_LOCKED },
+ { "Unlocked", ENC_STATUS_UNLOCKED },
+ { NULL, UnSet }
+};
+
+/**
+ * get_encryption_ability_string() - get encryption ability name string.
+ * @ability: encryption ability enum.
+ *
+ * Return: encryption ability string.
+ */
+const char *get_encryption_ability_string(enum encryption_ability ability)
+{
+ return map_num_s(encryption_ability_map, ability);
+}
+
+/**
+ * get_encryption_status_string() - get encryption status name string.
+ * @ability: encryption status enum.
+ *
+ * Return: encryption status string.
+ */
+const char *get_encryption_status_string(enum encryption_status status)
+{
+ return map_num_s(encryption_status_map, status);
+}
+
/**
* get_opal_locking_feature_description() - get opal locking feature description.
* @response: response from Opal Discovery Level 0.
diff --git a/drive_encryption.h b/drive_encryption.h
index 77c7f10f..0cb8ff1b 100644
--- a/drive_encryption.h
+++ b/drive_encryption.h
@@ -33,3 +33,5 @@ get_nvme_opal_encryption_information(int disk_fd, struct encryption_information
mdadm_status_t
get_ata_encryption_information(int disk_fd, struct encryption_information *information,
const int verbose);
+const char *get_encryption_ability_string(enum encryption_ability ability);
+const char *get_encryption_status_string(enum encryption_status status);
diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in
index afb0a296..14302a91 100644
--- a/mdadm.conf.5.in
+++ b/mdadm.conf.5.in
@@ -643,6 +643,9 @@ The
disables encryption verification for devices with particular encryption support detected.
Currently, only verification of SATA OPAL encryption can be disabled.
It does not disable ATA security encryption verification.
+Currently effective only for
+.I IMSM
+metadata.
Available parameter
.I "sata_opal".
diff --git a/super-intel.c b/super-intel.c
index 212387ec..fbd1c11f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -27,6 +27,7 @@
#include <scsi/sg.h>
#include <ctype.h>
#include <dirent.h>
+#include "drive_encryption.h"
/* MPB == Metadata Parameter Block */
#define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. "
@@ -2349,12 +2350,41 @@ static int imsm_read_serial(int fd, char *devname, __u8 *serial,
size_t serial_buf_len);
static void fd2devname(int fd, char *name);
-static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_base, int verbose)
+void print_encryption_information(int disk_fd, enum sys_dev_type hba_type)
+{
+ struct encryption_information information = {0};
+ mdadm_status_t status = MDADM_STATUS_SUCCESS;
+ const char *indent = " ";
+
+ switch (hba_type) {
+ case SYS_DEV_VMD:
+ case SYS_DEV_NVME:
+ status = get_nvme_opal_encryption_information(disk_fd, &information, 1);
+ break;
+ case SYS_DEV_SATA:
+ case SYS_DEV_SATA_VMD:
+ status = get_ata_encryption_information(disk_fd, &information, 1);
+ break;
+ default:
+ return;
+ }
+
+ if (status) {
+ pr_err("Failed to get drive encryption information.\n");
+ return;
+ }
+
+ printf("%sEncryption(Ability|Status): %s|%s\n", indent,
+ get_encryption_ability_string(information.ability),
+ get_encryption_status_string(information.status));
+}
+
+static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_base, int verbose)
{
/* dump an unsorted list of devices attached to AHCI Intel storage
* controller, as well as non-connected ports
*/
- int hba_len = strlen(hba_path) + 1;
+ int hba_len = strlen(hba->path) + 1;
struct dirent *ent;
DIR *dir;
char *path = NULL;
@@ -2390,7 +2420,7 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
path = devt_to_devpath(makedev(major, minor), 1, NULL);
if (!path)
continue;
- if (!path_attached_to_hba(path, hba_path)) {
+ if (!path_attached_to_hba(path, hba->path)) {
free(path);
path = NULL;
continue;
@@ -2493,6 +2523,8 @@ static int ahci_enumerate_ports(const char *hba_path, int port_count, int host_b
printf(" (%s)\n", buf);
else
printf(" ()\n");
+
+ print_encryption_information(fd, hba->type);
close(fd);
}
free(path);
@@ -2557,6 +2589,8 @@ static int print_nvme_info(struct sys_dev *hba)
else
printf("()\n");
+ print_encryption_information(fd, hba->type);
+
skip:
close_fd(&fd);
}
@@ -2812,7 +2846,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
hba->path, get_sys_dev_type(hba->type));
if (hba->type == SYS_DEV_SATA || hba->type == SYS_DEV_SATA_VMD) {
host_base = ahci_get_port_count(hba->path, &port_count);
- if (ahci_enumerate_ports(hba->path, port_count, host_base, verbose)) {
+ if (ahci_enumerate_ports(hba, port_count, host_base, verbose)) {
if (verbose > 0)
pr_err("failed to enumerate ports on %s controller at %s.\n",
get_sys_dev_type(hba->type), hba->pci_id);
--
2.41.0

View File

@ -0,0 +1,114 @@
From acb8f13be88c224eb1e01f72c1e1fda955bc80ba Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 22 Mar 2024 12:51:20 +0100
Subject: [PATCH 47/66] imsm: drive encryption policy implementation
IMSM cares about drive encryption state. It is not allowed to mix disks
with different encryption state within one md device. This policy will
verify that attempt to use disks with different encryption states will
fail. Verification is performed for devices NVMe/SATA Opal and SATA.
There is one exception, Opal SATA drives encryption is not checked when
ENCRYPTION_NO_VERIFY key with "sata_opal" value is set in conf, for this
reason such drives are treated as without encryption support.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/super-intel.c b/super-intel.c
index fbd1c11f..1faab607 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -11291,6 +11291,78 @@ test_and_add_drive_controller_policy_imsm(const char * const type, dev_policy_t
return MDADM_STATUS_ERROR;
}
+/**
+ * test_and_add_drive_encryption_policy_imsm() - add disk encryption to policies list.
+ * @type: policy type to search in the list.
+ * @pols: list of currently recorded policies.
+ * @disk_fd: file descriptor of the device to check.
+ * @hba: The hba to which the drive is attached, could be NULL if verification is disabled.
+ * @verbose: verbose flag.
+ *
+ * IMSM cares about drive encryption state. It is not allowed to mix disks with different
+ * encryption state within one md device.
+ * If there is no encryption policy on pols we are free to add first one.
+ * If there is a policy then, new must be the same.
+ */
+static mdadm_status_t
+test_and_add_drive_encryption_policy_imsm(const char * const type, dev_policy_t **pols, int disk_fd,
+ struct sys_dev *hba, const int verbose)
+{
+ struct dev_policy *expected_policy = pol_find(*pols, (char *)type);
+ struct encryption_information information = {0};
+ char *encryption_state = "Unknown";
+ int status = MDADM_STATUS_SUCCESS;
+ bool encryption_checked = true;
+ char devname[PATH_MAX];
+
+ if (!hba)
+ goto check_policy;
+
+ switch (hba->type) {
+ case SYS_DEV_NVME:
+ case SYS_DEV_VMD:
+ status = get_nvme_opal_encryption_information(disk_fd, &information, verbose);
+ break;
+ case SYS_DEV_SATA:
+ case SYS_DEV_SATA_VMD:
+ status = get_ata_encryption_information(disk_fd, &information, verbose);
+ break;
+ default:
+ encryption_checked = false;
+ }
+
+ if (status) {
+ fd2devname(disk_fd, devname);
+ pr_vrb("Failed to read encryption information of device %s\n", devname);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (encryption_checked) {
+ if (information.status == ENC_STATUS_LOCKED) {
+ fd2devname(disk_fd, devname);
+ pr_vrb("Device %s is in Locked state, cannot use. Aborting.\n", devname);
+ return MDADM_STATUS_ERROR;
+ }
+ encryption_state = (char *)get_encryption_status_string(information.status);
+ }
+
+check_policy:
+ if (expected_policy) {
+ if (strcmp(expected_policy->value, encryption_state) == 0)
+ return MDADM_STATUS_SUCCESS;
+
+ fd2devname(disk_fd, devname);
+ pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected eariler.\n",
+ encryption_state, devname, expected_policy->value);
+ pr_vrb("Disks with different encryption status cannot be used.\n");
+ return MDADM_STATUS_ERROR;
+ }
+
+ pol_add(pols, (char *)type, encryption_state, "imsm");
+
+ return MDADM_STATUS_SUCCESS;
+}
+
struct imsm_drive_policy {
char *type;
mdadm_status_t (*test_and_add_drive_policy)(const char * const type,
@@ -11300,6 +11372,7 @@ struct imsm_drive_policy {
struct imsm_drive_policy imsm_policies[] = {
{"controller", test_and_add_drive_controller_policy_imsm},
+ {"encryption", test_and_add_drive_encryption_policy_imsm}
};
mdadm_status_t test_and_add_drive_policies_imsm(struct dev_policy **pols, int disk_fd,
--
2.41.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,66 @@
From 21d6c5d96a5a467b5877ba1d38106b3746005bcc Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Tue, 26 Mar 2024 13:21:11 +0100
Subject: [PATCH 49/66] mdadm: Add MAINTAINERS.md
Describe rules maintainer should follow.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
MAINTAINERS.md | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
create mode 100644 MAINTAINERS.md
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
new file mode 100644
index 00000000..9c79ba87
--- /dev/null
+++ b/MAINTAINERS.md
@@ -0,0 +1,44 @@
+# Maintainer tools
+
+Useful tools used in daily routines:
+- [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html)
+- [kup](https://korg.docs.kernel.org/kup.html)
+- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer)
+- [b4](https://b4.docs.kernel.org/en/latest/)
+
+# Checklist before applying patch
+
+We don't have CI testing yet, so all those steps must be performed manually:
+- Style check with [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html):
+
+ This is the current code style follows. We are not strict to all rules. It must be run
+ by **checkpatch --no-tree**, see README.md.
+
+- [Commit style](https://www.kernel.org/doc/html/v4.10/process/submitting-patches.html):
+
+ It doesn't need to be followed as strictly as is in kernel but changes should be logically
+ separated. Submitter should care at least to mention "It is used in next patches" if unused
+ externs/files are added in patch. We love: *Reported-by:*, *Suggested-by:*, *Fixes:* tags.
+
+- Compilation, ideally on various gcc versions.
+- Mdadm test suite execution.
+- Consider requesting new tests from submitter, especially for new functionalities.
+- Ensure that maintainer *sign-off* is added, before pushing.
+
+# Making a release
+
+Assuming that maintainer is certain that release is safe, following steps must be done:
+
+- Update versions strings in release commit, please refer to previous releases for examples.
+
+- Create GPG signed tag and push it to repo. Use same format as was used previously, prefixed by
+ **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**.
+
+- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer):
+
+ Adopt script to our release tag model. When ready, push signed note to repository. If it is done
+ correctly, then *(sig)* is added to the package automatically generated by kernel.org automation.
+ There is no need to upload archive manually.
+
+- Update CHANGELOG.md.
+- Write "ANNOUNCE" mail to linux-raid@kernel.org to notify community.
--
2.41.0

View File

@ -0,0 +1,106 @@
From 256edaef3d43a112356762aaea4a48f021f45aec Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Tue, 26 Mar 2024 13:21:12 +0100
Subject: [PATCH 50/66] mdadm: Add README.md
Describe supported metadata types, add step-by-step patch sending
instruction, mention minimally supported kernel version and licensing.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
create mode 100644 README.md
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..64f2ecec
--- /dev/null
+++ b/README.md
@@ -0,0 +1,83 @@
+**mdadm** is a utility used to create and manage **software RAID** devices implemented through
+**Multiple devices driver (MD)** in kernel. It supports following RAID metadata formats:
+
+* [Linux native RAID](https://raid.wiki.kernel.org/index.php/RAID_superblock_formats):
+
+ Known as **native** or **native RAID**. First and default metadata format. Metadata management
+ is implemented in **MD driver**.
+
+* Matrix Storage Manager Support (no reference, metadata format documentation is proprietary).
+
+ Known as **IMSM**. Metadata format developed and maintained by **Intel®** as a part of **VROC**
+ solution. There are some functional differences between **native** and **imsm**. The most
+ important difference is that the metadata is managed from userspace.
+
+ **CAUTION:** **imsm** is compatible with **Intel RST**, however it is not officially supported.
+ You are using it on your own risk.
+
+* [Common RAID DDF Specification Revision](https://www.snia.org/sites/default/files/SNIA_DDF_Technical_Position_v2.0.pdf)
+
+ **IMPORTANT:** DDF is in **maintenance only** mode. There is no active development around it.
+ Please do not use it in new solutions.
+
+# How to Contribute
+
+ **mdadm** is hosted on [kernel.org](https://kernel.org/). You can access repository
+[here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git).
+
+It is maintained similarly to kernel, using *mailing list*. Patches must be send through email.
+Please familiarize with general kernel
+[submitting patches](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html)
+documentation. Formatting, tags and commit message guidelines applies to **mdadm**.
+
+## Sending patches step-by-step
+
+To maximize change of patches being taken, follow this instruction when submitting:
+
+1. Create possibly logically separated commits and generate patches:
+
+ Use ``git format-patch --cover-letter --signoff -v <nr>`` to create patches:
+ * ``--cover-letter`` can be skipped if it is only one patch;
+ * ``--signoff`` adds sign-off tag;
+ * ``-v <nr>`` indicates review revision number, sender should increment it before resending.
+
+2. Check style of every patch with kernel
+ [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script:
+
+ It is important to keep same coding style that is why in **mdadm**
+ [kernel coding style](https://www.kernel.org/doc/html/v4.10/process/coding-style.html)
+ is preferred. ``checkpath --no-tree <patch_file>`` can be used to verify patches.
+ Following checkpatch issues can be ignored:
+ - New typedefs.
+ - comparing with *True/False*.
+ - kernel *MAINTAINERS* file warning.
+ - *extern* keyword in headers.
+
+3. Send patches using ``git send-mail --to=linux-raid@vger.kernel.org <cover-letter> <patch1> <patch2> (...)``
+
+# Maintainers
+
+It is good practice to add **mdadm maintainers** to recipients for patches:
+
+- Jes Sorensen <jes@trained-monkey.org>;
+- Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>;
+
+Adding **MD maintainers** could be reasonable, especially if patches may affect MD driver:
+
+- Song Liu <song@kernel.org>;
+- Yu Kuai <yukuai3@huawei.com>;
+
+# Reviewers
+
+**mdadm** utility is not part of kernel tree, so there is no certificated *Reviewers* list. Everyone
+can comment on mailing list, last decision (and merging) belongs to maintainers.
+
+# Minimal supported kernel version
+
+We do not support kernel versions below **v3.10**. Please be aware that maintainers may remove
+workarounds and fixes for legacy issues.
+
+# License
+
+It is released under the terms of the **GNU General Public License version 2** as published
+by the **Free Software Foundation**.
--
2.41.0

View File

@ -0,0 +1,41 @@
From 52bead95d2957437c691891fcdc49bd6afccdd49 Mon Sep 17 00:00:00 2001
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Date: Fri, 12 Apr 2024 18:45:13 +0200
Subject: [PATCH 51/66] Create.c: fix uclibc build
Define FALLOC_FL_ZERO_RANGE if needed as FALLOC_FL_ZERO_RANGE is only
defined for aarch64 on uclibc-ng resulting in the following or1k build
failure since commit 577fd10486d8d1472a6b559066f344ac30a3a391:
Create.c: In function 'write_zeroes_fork':
Create.c:155:35: error: 'FALLOC_FL_ZERO_RANGE' undeclared (first use in this function)
155 | if (fallocate(fd, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
| ^~~~~~~~~~~~~~~~~~~~
Fixes:
- http://autobuild.buildroot.org/results/0e04bcdb591ca5642053e1f7e31384f06581e989
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Create.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Create.c b/Create.c
index 4397ff49..d94253b1 100644
--- a/Create.c
+++ b/Create.c
@@ -32,6 +32,10 @@
#include <sys/signalfd.h>
#include <sys/wait.h>
+#ifndef FALLOC_FL_ZERO_RANGE
+#define FALLOC_FL_ZERO_RANGE 16
+#endif
+
static int round_size_and_verify(unsigned long long *size, int chunk)
{
if (*size == 0)
--
2.41.0

View File

@ -0,0 +1,309 @@
From bdc2c56998abf76141294b04facf20217cfd1911 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:13 +0200
Subject: [PATCH 52/66] mdadm: pass struct context for external reshapes
This patch alters mutiple functions calls so the context is passed to
external reshape functions.
There are two main reasons behind it:
- reduces number of arguments passed and unifies them,
- imsm code will make use of context in incoming patches.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Assemble.c | 7 ++----
Grow.c | 68 +++++++++++++++++++++------------------------------
mdadm.c | 2 +-
mdadm.h | 11 +++------
super-intel.c | 6 ++---
5 files changed, 37 insertions(+), 57 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index f6c5b99e..f5e9ab1f 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1197,9 +1197,7 @@ static int start_array(int mdfd,
rv = sysfs_set_str(content, NULL,
"array_state", "readonly");
if (rv == 0)
- rv = Grow_continue(mdfd, st, content,
- c->backup_file, 0,
- c->freeze_reshape);
+ rv = Grow_continue(mdfd, st, content, 0, c);
} else if (c->readonly &&
sysfs_attribute_available(content, NULL,
"array_state")) {
@@ -2180,8 +2178,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
st->update_tail = &st->updates;
}
- err = Grow_continue(mdfd, st, content, c->backup_file,
- 0, c->freeze_reshape);
+ err = Grow_continue(mdfd, st, content, 0, c);
} else switch(content->array.level) {
case LEVEL_LINEAR:
case LEVEL_MULTIPATH:
diff --git a/Grow.c b/Grow.c
index 074f1995..f477b438 100644
--- a/Grow.c
+++ b/Grow.c
@@ -864,8 +864,7 @@ static void wait_reshape(struct mdinfo *sra)
static int reshape_super(struct supertype *st, unsigned long long size,
int level, int layout, int chunksize, int raid_disks,
- int delta_disks, char *backup_file, char *dev,
- int direction, int verbose)
+ int delta_disks, char *dev, int direction, struct context *c)
{
/* nothing extra to check in the native case */
if (!st->ss->external)
@@ -876,9 +875,8 @@ static int reshape_super(struct supertype *st, unsigned long long size,
return 1;
}
- return st->ss->reshape_super(st, size, level, layout, chunksize,
- raid_disks, delta_disks, backup_file, dev,
- direction, verbose);
+ return st->ss->reshape_super(st, size, level, layout, chunksize, raid_disks,
+ delta_disks, dev, direction, c);
}
static void sync_metadata(struct supertype *st)
@@ -1764,9 +1762,8 @@ static int reshape_container(char *container, char *devname,
int mdfd,
struct supertype *st,
struct mdinfo *info,
- int force,
- char *backup_file, int verbose,
- int forked, int restart, int freeze_reshape);
+ struct context *c,
+ int forked, int restart);
/**
* prepare_external_reshape() - prepares update on external metadata if supported.
@@ -2004,9 +2001,8 @@ int Grow_reshape(char *devname, int fd,
goto release;
}
- if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
- devname, APPLY_METADATA_CHANGES,
- c->verbose > 0)) {
+ if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet,
+ devname, APPLY_METADATA_CHANGES, c)) {
rv = 1;
goto release;
}
@@ -2124,10 +2120,8 @@ size_change_error:
int err = errno;
/* restore metadata */
- if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
- UnSet, NULL, devname,
- ROLLBACK_METADATA_CHANGES,
- c->verbose) == 0)
+ if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, UnSet,
+ devname, ROLLBACK_METADATA_CHANGES, c) == 0)
sync_metadata(st);
pr_err("Cannot set device size for %s: %s\n",
devname, strerror(err));
@@ -2338,8 +2332,7 @@ size_change_error:
*/
close_fd(&fd);
rv = reshape_container(container, devname, -1, st, &info,
- c->force, c->backup_file, c->verbose,
- 0, 0, 0);
+ c, 0, 0);
frozen = 0;
} else {
/* get spare devices from external metadata
@@ -2356,13 +2349,13 @@ size_change_error:
}
/* Impose these changes on a single array. First
- * check that the metadata is OK with the change. */
+ * check that the metadata is OK with the change.
+ */
if (reshape_super(st, 0, info.new_level,
info.new_layout, info.new_chunk,
info.array.raid_disks, info.delta_disks,
- c->backup_file, devname,
- APPLY_METADATA_CHANGES, c->verbose)) {
+ devname, APPLY_METADATA_CHANGES, c)) {
rv = 1;
goto release;
}
@@ -3668,9 +3661,8 @@ int reshape_container(char *container, char *devname,
int mdfd,
struct supertype *st,
struct mdinfo *info,
- int force,
- char *backup_file, int verbose,
- int forked, int restart, int freeze_reshape)
+ struct context *c,
+ int forked, int restart)
{
struct mdinfo *cc = NULL;
int rv = restart;
@@ -3683,8 +3675,7 @@ int reshape_container(char *container, char *devname,
reshape_super(st, 0, info->new_level,
info->new_layout, info->new_chunk,
info->array.raid_disks, info->delta_disks,
- backup_file, devname, APPLY_METADATA_CHANGES,
- verbose)) {
+ devname, APPLY_METADATA_CHANGES, c)) {
unfreeze(st);
return 1;
}
@@ -3695,7 +3686,7 @@ int reshape_container(char *container, char *devname,
*/
ping_monitor(container);
- if (!forked && !freeze_reshape)
+ if (!forked && !c->freeze_reshape)
if (continue_via_systemd(container, GROW_SERVICE, NULL))
return 0;
@@ -3705,7 +3696,7 @@ int reshape_container(char *container, char *devname,
unfreeze(st);
return 1;
default: /* parent */
- if (!freeze_reshape)
+ if (!c->freeze_reshape)
printf("%s: multi-array reshape continues in background\n", Name);
return 0;
case 0: /* child */
@@ -3802,12 +3793,12 @@ int reshape_container(char *container, char *devname,
flush_mdmon(container);
rv = reshape_array(container, fd, adev, st,
- content, force, NULL, INVALID_SECTORS,
- backup_file, verbose, 1, restart,
- freeze_reshape);
+ content, c->force, NULL, INVALID_SECTORS,
+ c->backup_file, c->verbose, 1, restart,
+ c->freeze_reshape);
close(fd);
- if (freeze_reshape) {
+ if (c->freeze_reshape) {
sysfs_free(cc);
exit(0);
}
@@ -4970,8 +4961,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist,
return 1;
}
-int Grow_continue_command(char *devname, int fd,
- char *backup_file, int verbose)
+int Grow_continue_command(char *devname, int fd, struct context *c)
{
int ret_val = 0;
struct supertype *st = NULL;
@@ -5157,7 +5147,7 @@ int Grow_continue_command(char *devname, int fd,
/* continue reshape
*/
- ret_val = Grow_continue(fd, st, content, backup_file, 1, 0);
+ ret_val = Grow_continue(fd, st, content, 1, c);
Grow_continue_command_exit:
if (cfd > -1)
@@ -5171,7 +5161,7 @@ Grow_continue_command_exit:
}
int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
- char *backup_file, int forked, int freeze_reshape)
+ int forked, struct context *c)
{
int ret_val = 2;
@@ -5187,14 +5177,12 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
st->ss->load_container(st, cfd, st->container_devnm);
close(cfd);
ret_val = reshape_container(st->container_devnm, NULL, mdfd,
- st, info, 0, backup_file, 0,
- forked, 1 | info->reshape_active,
- freeze_reshape);
+ st, info, c, forked, 1 | info->reshape_active);
} else
ret_val = reshape_array(NULL, mdfd, "array", st, info, 1,
- NULL, INVALID_SECTORS, backup_file,
+ NULL, INVALID_SECTORS, c->backup_file,
0, forked, 1 | info->reshape_active,
- freeze_reshape);
+ c->freeze_reshape);
return ret_val;
}
diff --git a/mdadm.c b/mdadm.c
index 3f191288..d18619db 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1636,7 +1636,7 @@ int main(int argc, char *argv[])
c.delay = DEFAULT_BITMAP_DELAY;
rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
} else if (grow_continue)
- rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
+ rv = Grow_continue_command(ident.devname, mdfd, &c);
else if (s.size > 0 || s.raiddisks || s.layout_str ||
s.chunk != 0 || s.level != UnSet ||
s.data_offset != INVALID_SECTORS) {
diff --git a/mdadm.h b/mdadm.h
index 2640b396..0ade4beb 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1235,9 +1235,8 @@ extern struct superswitch {
int (*reshape_super)(struct supertype *st,
unsigned long long size, int level,
int layout, int chunksize, int raid_disks,
- int delta_disks, char *backup, char *dev,
- int direction,
- int verbose); /* optional */
+ int delta_disks, char *dev, int direction,
+ struct context *c);
int (*manage_reshape)( /* optional */
int afd, struct mdinfo *sra, struct reshape *reshape,
struct supertype *st, unsigned long blocks,
@@ -1541,8 +1540,7 @@ extern int Grow_reshape(char *devname, int fd,
extern int Grow_restart(struct supertype *st, struct mdinfo *info,
int *fdlist, int cnt, char *backup_file, int verbose);
extern int Grow_continue(int mdfd, struct supertype *st,
- struct mdinfo *info, char *backup_file,
- int forked, int freeze_reshape);
+ struct mdinfo *info, int forked, struct context *c);
extern int Grow_consistency_policy(char *devname, int fd,
struct context *c, struct shape *s);
@@ -1552,8 +1550,7 @@ extern int restore_backup(struct supertype *st,
int spares,
char **backup_filep,
int verbose);
-extern int Grow_continue_command(char *devname, int fd,
- char *backup_file, int verbose);
+extern int Grow_continue_command(char *devname, int fd, struct context *c);
extern int Assemble(struct supertype *st, char *mddev,
struct mddev_ident *ident,
diff --git a/super-intel.c b/super-intel.c
index 1faab607..417da267 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -12153,10 +12153,8 @@ exit:
}
static int imsm_reshape_super(struct supertype *st, unsigned long long size,
- int level,
- int layout, int chunksize, int raid_disks,
- int delta_disks, char *backup, char *dev,
- int direction, int verbose)
+ int level, int layout, int chunksize, int raid_disks,
+ int delta_disks, char *dev, int direction, struct context *c)
{
int ret_val = 1;
struct geo_params geo;
--
2.41.0

View File

@ -0,0 +1,296 @@
From 0acda7053df653022e46fa3b7caf1f4d4ba31a66 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:14 +0200
Subject: [PATCH 53/66] mdadm: use struct context in reshape_super()
reshape_super() takes too many arguments. Change passing params in
favor of single struct.
Add devname pointer and change direction members to struct shape
and use it for reshape_super().
Create reshape_array_size() and reshape_array_non_size() to handle
reshape_super() calls.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Grow.c | 93 +++++++++++++++++++++++++++++++++++++--------------
mdadm.h | 18 +++++-----
super-intel.c | 43 +++++++++++++++---------
3 files changed, 105 insertions(+), 49 deletions(-)
diff --git a/Grow.c b/Grow.c
index f477b438..87ed9214 100644
--- a/Grow.c
+++ b/Grow.c
@@ -862,9 +862,7 @@ static void wait_reshape(struct mdinfo *sra)
close(fd);
}
-static int reshape_super(struct supertype *st, unsigned long long size,
- int level, int layout, int chunksize, int raid_disks,
- int delta_disks, char *dev, int direction, struct context *c)
+static int reshape_super(struct supertype *st, struct shape *shape, struct context *c)
{
/* nothing extra to check in the native case */
if (!st->ss->external)
@@ -875,8 +873,65 @@ static int reshape_super(struct supertype *st, unsigned long long size,
return 1;
}
- return st->ss->reshape_super(st, size, level, layout, chunksize, raid_disks,
- delta_disks, dev, direction, c);
+ return st->ss->reshape_super(st, shape, c);
+}
+
+/**
+ * reshape_super_size() - Reshape array, size only.
+ *
+ * @st: supertype.
+ * @devname: device name.
+ * @size: component size.
+ * @dir metadata changes direction
+ * Returns: 0 on success, 1 otherwise.
+ *
+ * This function is solely used to change size of the volume.
+ * Setting size is not valid for container.
+ * Size is only change that can be rolled back, thus the @dir param.
+ */
+static int reshape_super_size(struct supertype *st, char *devname,
+ unsigned long long size, change_dir_t direction,
+ struct context *c)
+{
+ struct shape shape = {0};
+
+ shape.level = UnSet;
+ shape.layout = UnSet;
+ shape.delta_disks = UnSet;
+ shape.dev = devname;
+ shape.size = size;
+ shape.direction = direction;
+
+ return reshape_super(st, &shape, c);
+}
+
+/**
+ * reshape_super_non_size() - Reshape array, non size changes.
+ *
+ * @st: supertype.
+ * @devname: device name.
+ * @info: superblock info.
+ * Returns: 0 on success, 1 otherwise.
+ *
+ * This function is used for any external array changes but size.
+ * It handles both volumes and containers.
+ * For changes other than size, rollback is not possible.
+ */
+static int reshape_super_non_size(struct supertype *st, char *devname,
+ struct mdinfo *info, struct context *c)
+{
+ struct shape shape = {0};
+ /* Size already set to zero, not updating size */
+ shape.level = info->new_level;
+ shape.layout = info->new_layout;
+ shape.chunk = info->new_chunk;
+ shape.raiddisks = info->array.raid_disks;
+ shape.delta_disks = info->delta_disks;
+ shape.dev = devname;
+ /* Rollback not possible for non size changes */
+ shape.direction = APPLY_METADATA_CHANGES;
+
+ return reshape_super(st, &shape, c);
}
static void sync_metadata(struct supertype *st)
@@ -1979,9 +2034,8 @@ int Grow_reshape(char *devname, int fd,
}
/* ========= set size =============== */
- if (s->size > 0 &&
- (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
- unsigned long long orig_size = get_component_size(fd)/2;
+ if (s->size > 0 && (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
+ unsigned long long orig_size = get_component_size(fd) / 2;
unsigned long long min_csize;
struct mdinfo *mdi;
int raid0_takeover = 0;
@@ -2001,8 +2055,7 @@ int Grow_reshape(char *devname, int fd,
goto release;
}
- if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet,
- devname, APPLY_METADATA_CHANGES, c)) {
+ if (reshape_super_size(st, devname, s->size, APPLY_METADATA_CHANGES, c)) {
rv = 1;
goto release;
}
@@ -2120,8 +2173,8 @@ size_change_error:
int err = errno;
/* restore metadata */
- if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0, UnSet,
- devname, ROLLBACK_METADATA_CHANGES, c) == 0)
+ if (reshape_super_size(st, devname, orig_size,
+ ROLLBACK_METADATA_CHANGES, c) == 0)
sync_metadata(st);
pr_err("Cannot set device size for %s: %s\n",
devname, strerror(err));
@@ -2351,11 +2404,7 @@ size_change_error:
/* Impose these changes on a single array. First
* check that the metadata is OK with the change.
*/
-
- if (reshape_super(st, 0, info.new_level,
- info.new_layout, info.new_chunk,
- info.array.raid_disks, info.delta_disks,
- devname, APPLY_METADATA_CHANGES, c)) {
+ if (reshape_super_non_size(st, devname, &info, c)) {
rv = 1;
goto release;
}
@@ -3668,14 +3717,8 @@ int reshape_container(char *container, char *devname,
int rv = restart;
char last_devnm[32] = "";
- /* component_size is not meaningful for a container,
- * so pass '0' meaning 'no change'
- */
- if (!restart &&
- reshape_super(st, 0, info->new_level,
- info->new_layout, info->new_chunk,
- info->array.raid_disks, info->delta_disks,
- devname, APPLY_METADATA_CHANGES, c)) {
+ /* component_size is not meaningful for a container */
+ if (!restart && reshape_super_non_size(st, devname, info, c)) {
unfreeze(st);
return 1;
}
diff --git a/mdadm.h b/mdadm.h
index 0ade4beb..2ff3e463 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -594,6 +594,11 @@ enum flag_mode {
FlagDefault, FlagSet, FlagClear,
};
+typedef enum {
+ ROLLBACK_METADATA_CHANGES,
+ APPLY_METADATA_CHANGES
+} change_dir_t;
+
/* structures read from config file */
/* List of mddevice names and identifiers
* Identifiers can be:
@@ -667,7 +672,9 @@ struct context {
};
struct shape {
+ char *dev;
int raiddisks;
+ int delta_disks;
int sparedisks;
int journaldisks;
int level;
@@ -682,6 +689,7 @@ struct shape {
unsigned long long size;
unsigned long long data_offset;
int consistency_policy;
+ change_dir_t direction;
};
/* List of device names - wildcards expanded */
@@ -1229,14 +1237,8 @@ extern struct superswitch {
* initialized to indicate if reshape is being performed at the
* container or subarray level
*/
-#define APPLY_METADATA_CHANGES 1
-#define ROLLBACK_METADATA_CHANGES 0
-
- int (*reshape_super)(struct supertype *st,
- unsigned long long size, int level,
- int layout, int chunksize, int raid_disks,
- int delta_disks, char *dev, int direction,
- struct context *c);
+
+ int (*reshape_super)(struct supertype *st, struct shape *shape, struct context *c);
int (*manage_reshape)( /* optional */
int afd, struct mdinfo *sra, struct reshape *reshape,
struct supertype *st, unsigned long blocks,
diff --git a/super-intel.c b/super-intel.c
index 417da267..1a8a7b12 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -12152,26 +12152,37 @@ exit:
return ret_val;
}
-static int imsm_reshape_super(struct supertype *st, unsigned long long size,
- int level, int layout, int chunksize, int raid_disks,
- int delta_disks, char *dev, int direction, struct context *c)
+/**
+ * shape_to_geo() - fill geo_params from shape.
+ *
+ * @shape: array details.
+ * @geo: new geometry params.
+ * Returns: 0 on success, 1 otherwise.
+ */
+static void shape_to_geo(struct shape *shape, struct geo_params *geo)
+{
+ assert(shape);
+ assert(geo);
+
+ geo->dev_name = shape->dev;
+ geo->size = shape->size;
+ geo->level = shape->level;
+ geo->layout = shape->layout;
+ geo->chunksize = shape->chunk;
+ geo->raid_disks = shape->raiddisks;
+}
+
+static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct context *c)
{
int ret_val = 1;
- struct geo_params geo;
+ struct geo_params geo = {0};
dprintf("(enter)\n");
- memset(&geo, 0, sizeof(struct geo_params));
-
- geo.dev_name = dev;
+ shape_to_geo(shape, &geo);
strcpy(geo.devnm, st->devnm);
- geo.size = size;
- geo.level = level;
- geo.layout = layout;
- geo.chunksize = chunksize;
- geo.raid_disks = raid_disks;
- if (delta_disks != UnSet)
- geo.raid_disks += delta_disks;
+ if (shape->delta_disks != UnSet)
+ geo.raid_disks += shape->delta_disks;
dprintf("for level : %i\n", geo.level);
dprintf("for raid_disks : %i\n", geo.raid_disks);
@@ -12182,7 +12193,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
int old_raid_disks = 0;
if (imsm_reshape_is_allowed_on_container(
- st, &geo, &old_raid_disks, direction)) {
+ st, &geo, &old_raid_disks, shape->direction)) {
struct imsm_update_reshape *u = NULL;
int len;
@@ -12236,7 +12247,7 @@ static int imsm_reshape_super(struct supertype *st, unsigned long long size,
goto exit_imsm_reshape_super;
}
super->current_vol = dev->index;
- change = imsm_analyze_change(st, &geo, direction);
+ change = imsm_analyze_change(st, &geo, shape->direction);
switch (change) {
case CH_TAKEOVER:
ret_val = imsm_takeover(st, &geo);
--
2.41.0

View File

@ -0,0 +1,184 @@
From 27550b13297adbdefe42fe4eb785b7fde1c0ed91 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:15 +0200
Subject: [PATCH 54/66] imsm: add support for literal RAID 10
As for now, IMSM supports only 4 drive RAID 1+0. This patch is first in
series to add support for literal RAID 10 (with more than 4 drives) to
imsm.
Allow setting RAID 10 as raid level for imsm arrays.
Add update_imsm_raid_level() to handle raid level updates. Set RAID10 as
default level for imsm R0 to R10 migrations. Replace magic numbers with
defined values for RAID level checks/assigns.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 67 ++++++++++++++++++++++++++++++++++++---------------
1 file changed, 48 insertions(+), 19 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 1a8a7b12..a7efc8df 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -166,7 +166,8 @@ struct imsm_map {
__u8 raid_level;
#define IMSM_T_RAID0 0
#define IMSM_T_RAID1 1
-#define IMSM_T_RAID5 5 /* since metadata version 1.2.02 ? */
+#define IMSM_T_RAID5 5
+#define IMSM_T_RAID10 10
__u8 num_members; /* number of member disks */
__u8 num_domains; /* number of parity domains */
__u8 failed_disk_num; /* valid only when state is degraded */
@@ -1259,14 +1260,42 @@ static int get_imsm_disk_slot(struct imsm_map *map, const unsigned int idx)
return IMSM_STATUS_ERROR;
}
+/**
+ * update_imsm_raid_level() - update raid level appropriately in &imsm_map.
+ * @map: &imsm_map pointer.
+ * @new_level: MD style level.
+ *
+ * For backward compatibility reasons we need to differentiate RAID10.
+ * In the past IMSM RAID10 was presented as RAID1.
+ * Keep compatibility unless it is not explicitly updated by UEFI driver.
+ *
+ * Routine needs num_members to be set and (optionally) raid_level.
+ */
+static void update_imsm_raid_level(struct imsm_map *map, int new_level)
+{
+ if (new_level != IMSM_T_RAID10) {
+ map->raid_level = new_level;
+ return;
+ }
+
+ if (map->num_members == 4) {
+ if (map->raid_level == IMSM_T_RAID10 || map->raid_level == IMSM_T_RAID1)
+ return;
+
+ map->raid_level = IMSM_T_RAID1;
+ return;
+ }
+
+ map->raid_level = IMSM_T_RAID10;
+}
static int get_imsm_raid_level(struct imsm_map *map)
{
- if (map->raid_level == 1) {
+ if (map->raid_level == IMSM_T_RAID1) {
if (map->num_members == 2)
- return 1;
+ return IMSM_T_RAID1;
else
- return 10;
+ return IMSM_T_RAID10;
}
return map->raid_level;
@@ -5678,7 +5707,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
set_pba_of_lba0(map, super->create_offset);
map->blocks_per_strip = __cpu_to_le16(info_to_blocks_per_strip(info));
map->failed_disk_num = ~0;
- if (info->level > 0)
+ if (info->level > IMSM_T_RAID0)
map->map_state = (info->state ? IMSM_T_STATE_NORMAL
: IMSM_T_STATE_UNINITIALIZED);
else
@@ -5686,16 +5715,15 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
IMSM_T_STATE_NORMAL;
map->ddf = 1;
- if (info->level == 1 && info->raid_disks > 2) {
+ if (info->level == IMSM_T_RAID1 && info->raid_disks > 2) {
free(dev);
free(dv);
- pr_err("imsm does not support more than 2 disksin a raid1 volume\n");
+ pr_err("imsm does not support more than 2 disks in a raid1 volume\n");
return 0;
}
+ map->num_members = info->raid_disks;
- map->raid_level = info->level;
- if (info->level == 10)
- map->raid_level = 1;
+ update_imsm_raid_level(map, info->level);
set_num_domains(map);
size_per_member += NUM_BLOCKS_DIRTY_STRIPE_REGION;
@@ -5703,7 +5731,6 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
size_per_member /
BLOCKS_PER_KB));
- map->num_members = info->raid_disks;
update_num_data_stripes(map, array_blocks);
for (i = 0; i < map->num_members; i++) {
/* initialized in add_to_super */
@@ -8275,7 +8302,7 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
info_d->data_offset = pba_of_lba0(map);
info_d->component_size = calc_component_size(map, dev);
- if (map->raid_level == 5) {
+ if (map->raid_level == IMSM_T_RAID5) {
info_d->ppl_sector = this->ppl_sector;
info_d->ppl_size = this->ppl_size;
if (this->consistency_policy == CONSISTENCY_POLICY_PPL &&
@@ -9533,7 +9560,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
}
to_state = map->map_state;
- if ((u->new_level == 5) && (map->raid_level == 0)) {
+ if ((u->new_level == IMSM_T_RAID5) && (map->raid_level == IMSM_T_RAID0)) {
map->num_members++;
/* this should not happen */
if (u->new_disks[0] < 0) {
@@ -9544,11 +9571,13 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
to_state = IMSM_T_STATE_NORMAL;
}
migrate(new_dev, super, to_state, MIGR_GEN_MIGR);
+
if (u->new_level > -1)
- map->raid_level = u->new_level;
+ update_imsm_raid_level(map, u->new_level);
+
migr_map = get_imsm_map(new_dev, MAP_1);
- if ((u->new_level == 5) &&
- (migr_map->raid_level == 0)) {
+ if ((u->new_level == IMSM_T_RAID5) &&
+ (migr_map->raid_level == IMSM_T_RAID0)) {
int ord = map->num_members - 1;
migr_map->num_members--;
if (u->new_disks[0] < 0)
@@ -9584,7 +9613,7 @@ static int apply_reshape_migration_update(struct imsm_update_reshape_migration *
/* add disk
*/
- if (u->new_level != 5 || migr_map->raid_level != 0 ||
+ if (u->new_level != IMSM_T_RAID5 || migr_map->raid_level != IMSM_T_RAID0 ||
migr_map->raid_level == map->raid_level)
goto skip_disk_add;
@@ -9963,7 +9992,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
/* update map */
map->num_members /= map->num_domains;
map->map_state = IMSM_T_STATE_NORMAL;
- map->raid_level = 0;
+ update_imsm_raid_level(map, IMSM_T_RAID0);
set_num_domains(map);
update_num_data_stripes(map, imsm_dev_size(dev));
map->failed_disk_num = -1;
@@ -10007,7 +10036,7 @@ static int apply_takeover_update(struct imsm_update_takeover *u,
map = get_imsm_map(dev_new, MAP_0);
map->map_state = IMSM_T_STATE_DEGRADED;
- map->raid_level = 1;
+ update_imsm_raid_level(map, IMSM_T_RAID10);
set_num_domains(map);
map->num_members = map->num_members * map->num_domains;
update_num_data_stripes(map, imsm_dev_size(dev));
--
2.41.0

View File

@ -0,0 +1,345 @@
From 191e6ddb1388236c5c54baf5020a87c996be941f Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:16 +0200
Subject: [PATCH 55/66] imsm: refactor RAID level handling
Add imsm_level_ops struct for better handling and unifying raid level
support. Add helper methods and move "orom_has_raid[...]" methods from
header to source file.
RAID 1e is not supported under Linux, remove RAID 1e associated code.
Refactor imsm_analyze_change() and is_raid_level_supported().
Remove hardcoded check for 4 drives and make devNumChange a multiplier
for RAID 10.
Refactor printing supported raid levels.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
platform-intel.c | 57 ++++++++++++++++++++++++
platform-intel.h | 32 ++++++--------
super-intel.c | 111 ++++++++++++++++++++++++++++-------------------
3 files changed, 138 insertions(+), 62 deletions(-)
diff --git a/platform-intel.c b/platform-intel.c
index ac282bc5..40e8fb82 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -32,6 +32,63 @@
#define NVME_SUBSYS_PATH "/sys/devices/virtual/nvme-subsystem/"
+static bool imsm_orom_has_raid0(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID0);
+}
+
+static bool imsm_orom_has_raid1(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID1);
+}
+
+static bool imsm_orom_has_raid10(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID10);
+}
+
+static bool imsm_orom_has_raid5(const struct imsm_orom *orom)
+{
+ return imsm_rlc_has_bit(orom, IMSM_OROM_RLC_RAID5);
+}
+
+/* IMSM platforms do not define how many disks are allowed for each level,
+ * but there are some global limitations we need to follow.
+ */
+static bool imsm_orom_support_raid_disks_count_raid0(const int raid_disks)
+{
+ return true;
+}
+
+static bool imsm_orom_support_raid_disks_count_raid1(const int raid_disks)
+{
+ if (raid_disks == 2)
+ return true;
+ return false;
+}
+
+static bool imsm_orom_support_raid_disks_count_raid5(const int raid_disks)
+{
+ if (raid_disks > 2)
+ return true;
+ return false;
+}
+
+static bool imsm_orom_support_raid_disks_count_raid10(const int raid_disks)
+{
+ if (raid_disks == 4)
+ return true;
+ return false;
+}
+
+struct imsm_level_ops imsm_level_ops[] = {
+ {0, imsm_orom_has_raid0, imsm_orom_support_raid_disks_count_raid0, "raid0"},
+ {1, imsm_orom_has_raid1, imsm_orom_support_raid_disks_count_raid1, "raid1"},
+ {5, imsm_orom_has_raid5, imsm_orom_support_raid_disks_count_raid5, "raid5"},
+ {10, imsm_orom_has_raid10, imsm_orom_support_raid_disks_count_raid10, "raid10"},
+ {-1, NULL, NULL, NULL}
+};
+
static int devpath_to_ll(const char *dev_path, const char *entry,
unsigned long long *val);
diff --git a/platform-intel.h b/platform-intel.h
index 3c2bc595..dcc5aaa7 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -109,25 +109,21 @@ struct imsm_orom {
#define IMSM_OROM_CAPABILITIES_TPV (1 << 10)
} __attribute__((packed));
-static inline int imsm_orom_has_raid0(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID0);
-}
-static inline int imsm_orom_has_raid1(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID1);
-}
-static inline int imsm_orom_has_raid1e(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID1E);
-}
-static inline int imsm_orom_has_raid10(const struct imsm_orom *orom)
-{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID10);
-}
-static inline int imsm_orom_has_raid5(const struct imsm_orom *orom)
+/* IMSM metadata requirements for each level */
+struct imsm_level_ops {
+ int level;
+ bool (*is_level_supported)(const struct imsm_orom *);
+ bool (*is_raiddisks_count_supported)(const int);
+ char *name;
+};
+
+extern struct imsm_level_ops imsm_level_ops[];
+
+static inline bool imsm_rlc_has_bit(const struct imsm_orom *orom, const unsigned short bit)
{
- return !!(orom->rlc & IMSM_OROM_RLC_RAID5);
+ if (orom->rlc & bit)
+ return true;
+ return false;
}
/**
diff --git a/super-intel.c b/super-intel.c
index a7efc8df..da17265d 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2681,6 +2681,15 @@ static int ahci_get_port_count(const char *hba_path, int *port_count)
return host_base;
}
+static void print_imsm_level_capability(const struct imsm_orom *orom)
+{
+ int idx;
+
+ for (idx = 0; imsm_level_ops[idx].name; idx++)
+ if (imsm_level_ops[idx].is_level_supported(orom))
+ printf("%s ", imsm_level_ops[idx].name);
+}
+
static void print_imsm_capability(const struct imsm_orom *orom)
{
printf(" Platform : Intel(R) ");
@@ -2699,12 +2708,11 @@ static void print_imsm_capability(const struct imsm_orom *orom)
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" : "",
- imsm_orom_has_raid1e(orom) ? " raid1e" : "",
- imsm_orom_has_raid10(orom) ? " raid10" : "",
- imsm_orom_has_raid5(orom) ? " raid5" : "");
+
+ printf(" RAID Levels : ");
+ print_imsm_level_capability(orom);
+ printf("\n");
+
printf(" Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
imsm_orom_has_chunk(orom, 2) ? " 2k" : "",
imsm_orom_has_chunk(orom, 4) ? " 4k" : "",
@@ -2739,12 +2747,11 @@ static void print_imsm_capability_export(const struct imsm_orom *orom)
if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
orom->hotfix_ver, orom->build);
- printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n",
- imsm_orom_has_raid0(orom) ? "raid0 " : "",
- imsm_orom_has_raid1(orom) ? "raid1 " : "",
- imsm_orom_has_raid1e(orom) ? "raid1e " : "",
- imsm_orom_has_raid5(orom) ? "raid10 " : "",
- imsm_orom_has_raid10(orom) ? "raid5 " : "");
+
+ printf("IMSM_SUPPORTED_RAID_LEVELS=");
+ print_imsm_level_capability(orom);
+ printf("\n");
+
printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
imsm_orom_has_chunk(orom, 2) ? "2k " : "",
imsm_orom_has_chunk(orom, 4) ? "4k " : "",
@@ -6992,26 +6999,41 @@ static unsigned long long merge_extents(struct intel_super *super, const bool ex
return free_size - reservation_size;
}
-static int is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
+/**
+ * is_raid_level_supported() - check if this count of drives and level is supported by platform.
+ * @orom: hardware properties, could be NULL.
+ * @level: requested raid level.
+ * @raiddisks: requested disk count.
+ *
+ * IMSM UEFI/OROM does not provide information about supported count of raid disks
+ * for particular level. That is why it is hardcoded.
+ * It is recommended to not allow of usage other levels than supported,
+ * IMSM code is not tested against different level implementations.
+ *
+ * Return: true if supported, false otherwise.
+ */
+static bool is_raid_level_supported(const struct imsm_orom *orom, int level, int raiddisks)
{
- if (level < 0 || level == 6 || level == 4)
- return 0;
+ int idx;
- /* if we have an orom prevent invalid raid levels */
- if (orom)
- switch (level) {
- case 0: return imsm_orom_has_raid0(orom);
- case 1:
- if (raiddisks > 2)
- return imsm_orom_has_raid1e(orom);
- return imsm_orom_has_raid1(orom) && raiddisks == 2;
- case 10: return imsm_orom_has_raid10(orom) && raiddisks == 4;
- case 5: return imsm_orom_has_raid5(orom) && raiddisks > 2;
- }
- else
- return 1; /* not on an Intel RAID platform so anything goes */
+ for (idx = 0; imsm_level_ops[idx].name; idx++) {
+ if (imsm_level_ops[idx].level == level)
+ break;
+ }
- return 0;
+ if (!imsm_level_ops[idx].name)
+ return false;
+
+ if (!imsm_level_ops[idx].is_raiddisks_count_supported(raiddisks))
+ return false;
+
+ if (!orom)
+ return true;
+
+ if (imsm_level_ops[idx].is_level_supported(orom))
+ return true;
+
+ return false;
}
static int
@@ -11962,18 +11984,17 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
int change = -1;
int check_devs = 0;
int chunk;
- /* number of added/removed disks in operation result */
- int devNumChange = 0;
/* imsm compatible layout value for array geometry verification */
int imsm_layout = -1;
+ int raid_disks = geo->raid_disks;
imsm_status_t rv;
getinfo_super_imsm_volume(st, &info, NULL);
- if (geo->level != info.array.level && geo->level >= 0 &&
+ if (geo->level != info.array.level && geo->level >= IMSM_T_RAID0 &&
geo->level != UnSet) {
switch (info.array.level) {
- case 0:
- if (geo->level == 5) {
+ case IMSM_T_RAID0:
+ if (geo->level == IMSM_T_RAID5) {
change = CH_MIGRATION;
if (geo->layout != ALGORITHM_LEFT_ASYMMETRIC) {
pr_err("Error. Requested Layout not supported (left-asymmetric layout is supported only)!\n");
@@ -11982,20 +12003,20 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
}
imsm_layout = geo->layout;
check_devs = 1;
- devNumChange = 1; /* parity disk added */
- } else if (geo->level == 10) {
+ raid_disks += 1; /* parity disk added */
+ } else if (geo->level == IMSM_T_RAID10) {
change = CH_TAKEOVER;
check_devs = 1;
- devNumChange = 2; /* two mirrors added */
+ raid_disks *= 2; /* mirrors added */
imsm_layout = 0x102; /* imsm supported layout */
}
break;
- case 1:
- case 10:
+ case IMSM_T_RAID1:
+ case IMSM_T_RAID10:
if (geo->level == 0) {
change = CH_TAKEOVER;
check_devs = 1;
- devNumChange = -(geo->raid_disks/2);
+ raid_disks /= 2;
imsm_layout = 0; /* imsm raid0 layout */
}
break;
@@ -12011,10 +12032,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
if (geo->layout != info.array.layout &&
(geo->layout != UnSet && geo->layout != -1)) {
change = CH_MIGRATION;
- if (info.array.layout == 0 && info.array.level == 5 &&
+ if (info.array.layout == 0 && info.array.level == IMSM_T_RAID5 &&
geo->layout == 5) {
/* reshape 5 -> 4 */
- } else if (info.array.layout == 5 && info.array.level == 5 &&
+ } else if (info.array.layout == 5 && info.array.level == IMSM_T_RAID5 &&
geo->layout == 0) {
/* reshape 4 -> 5 */
geo->layout = 0;
@@ -12033,7 +12054,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
if (geo->chunksize > 0 && geo->chunksize != UnSet &&
geo->chunksize != info.array.chunk_size) {
- if (info.array.level == 10) {
+ if (info.array.level == IMSM_T_RAID10) {
pr_err("Error. Chunk size change for RAID 10 is not supported.\n");
change = -1;
goto analyse_change_exit;
@@ -12058,14 +12079,16 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
rv = imsm_analyze_expand(st, geo, &info, direction);
if (rv != IMSM_STATUS_OK)
goto analyse_change_exit;
+ raid_disks = geo->raid_disks;
change = CH_ARRAY_SIZE;
}
chunk = geo->chunksize / 1024;
+
if (!validate_geometry_imsm(st,
geo->level,
imsm_layout,
- geo->raid_disks + devNumChange,
+ raid_disks,
&chunk,
geo->size, INVALID_SECTORS,
0, 0, info.consistency_policy, 1))
--
2.41.0

View File

@ -0,0 +1,180 @@
From ec7e873ba6643a9e5e74311b00ede66a3d2e36c9 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:17 +0200
Subject: [PATCH 56/66] imsm: bump minimal version
IMSM version 1.3 (called ATTRIBS) brought attributes used to define array
properties which require support in driver. The goal of this change was
to avoid changing version when adding new features.
For some reasons migration has never been completed and currently (after
10 years of implementing) IMSM can use older versions.
It is right time to finally switch it. There is no point in using old
versions, use 1.3.00 as minimal one.
Define JD_VERSION used by Windows driver.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 87 ++++++++++++++++++++++-----------------------------
1 file changed, 38 insertions(+), 49 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index da17265d..4b168add 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -32,14 +32,19 @@
/* MPB == Metadata Parameter Block */
#define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. "
#define MPB_SIG_LEN (strlen(MPB_SIGNATURE))
-#define MPB_VERSION_RAID0 "1.0.00"
-#define MPB_VERSION_RAID1 "1.1.00"
-#define MPB_VERSION_MANY_VOLUMES_PER_ARRAY "1.2.00"
-#define MPB_VERSION_3OR4_DISK_ARRAY "1.2.01"
-#define MPB_VERSION_RAID5 "1.2.02"
-#define MPB_VERSION_5OR6_DISK_ARRAY "1.2.04"
-#define MPB_VERSION_CNG "1.2.06"
+
+/* Legacy IMSM versions:
+ * MPB_VERSION_RAID0 1.0.00
+ * MPB_VERSION_RAID1 1.1.00
+ * MPB_VERSION_MANY_VOLUMES_PER_ARRAY 1.2.00
+ * MPB_VERSION_3OR4_DISK_ARRAY 1.2.01
+ * MPB_VERSION_RAID5 1.2.02
+ * MPB_VERSION_5OR6_DISK_ARRAY 1.2.04
+ * MPB_VERSION_CNG 1.2.06
+ */
+
#define MPB_VERSION_ATTRIBS "1.3.00"
+#define MPB_VERSION_ATTRIBS_JD "2.0.00"
#define MAX_SIGNATURE_LENGTH 32
#define MAX_RAID_SERIAL_LEN 16
@@ -5512,51 +5517,46 @@ static unsigned long long info_to_blocks_per_member(mdu_array_info_t *info,
return (size * 2) & ~(info_to_blocks_per_strip(info) - 1);
}
+static void imsm_write_signature(struct imsm_super *mpb)
+{
+ /* It is safer to eventually truncate version rather than left it not NULL ended */
+ snprintf((char *) mpb->sig, MAX_SIGNATURE_LENGTH, MPB_SIGNATURE MPB_VERSION_ATTRIBS);
+}
+
static void imsm_update_version_info(struct intel_super *super)
{
/* update the version and attributes */
struct imsm_super *mpb = super->anchor;
- char *version;
struct imsm_dev *dev;
struct imsm_map *map;
int i;
+ mpb->attributes |= MPB_ATTRIB_CHECKSUM_VERIFY;
+
for (i = 0; i < mpb->num_raid_devs; i++) {
dev = get_imsm_dev(super, i);
map = get_imsm_map(dev, MAP_0);
+
if (__le32_to_cpu(dev->size_high) > 0)
mpb->attributes |= MPB_ATTRIB_2TB;
- /* FIXME detect when an array spans a port multiplier */
- #if 0
- mpb->attributes |= MPB_ATTRIB_PM;
- #endif
-
- if (mpb->num_raid_devs > 1 ||
- mpb->attributes != MPB_ATTRIB_CHECKSUM_VERIFY) {
- version = MPB_VERSION_ATTRIBS;
- switch (get_imsm_raid_level(map)) {
- case 0: mpb->attributes |= MPB_ATTRIB_RAID0; break;
- case 1: mpb->attributes |= MPB_ATTRIB_RAID1; break;
- case 10: mpb->attributes |= MPB_ATTRIB_RAID10; break;
- case 5: mpb->attributes |= MPB_ATTRIB_RAID5; break;
- }
- } else {
- if (map->num_members >= 5)
- version = MPB_VERSION_5OR6_DISK_ARRAY;
- else if (dev->status == DEV_CLONE_N_GO)
- version = MPB_VERSION_CNG;
- else if (get_imsm_raid_level(map) == 5)
- version = MPB_VERSION_RAID5;
- else if (map->num_members >= 3)
- version = MPB_VERSION_3OR4_DISK_ARRAY;
- else if (get_imsm_raid_level(map) == 1)
- version = MPB_VERSION_RAID1;
- else
- version = MPB_VERSION_RAID0;
+ switch (get_imsm_raid_level(map)) {
+ case IMSM_T_RAID0:
+ mpb->attributes |= MPB_ATTRIB_RAID0;
+ break;
+ case IMSM_T_RAID1:
+ mpb->attributes |= MPB_ATTRIB_RAID1;
+ break;
+ case IMSM_T_RAID5:
+ mpb->attributes |= MPB_ATTRIB_RAID5;
+ break;
+ case IMSM_T_RAID10:
+ mpb->attributes |= MPB_ATTRIB_RAID10;
+ break;
}
- strcpy(((char *) mpb->sig) + strlen(MPB_SIGNATURE), version);
}
+
+ imsm_write_signature(mpb);
}
/**
@@ -5785,7 +5785,6 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
struct intel_super *super;
struct imsm_super *mpb;
size_t mpb_size;
- char *version;
if (data_offset != INVALID_SECTORS) {
pr_err("data-offset not supported by imsm\n");
@@ -5828,13 +5827,7 @@ static int init_super_imsm(struct supertype *st, mdu_array_info_t *info,
return 0;
}
- mpb->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
-
- version = (char *) mpb->sig;
- strcpy(version, MPB_SIGNATURE);
- version += strlen(MPB_SIGNATURE);
- strcpy(version, MPB_VERSION_RAID0);
-
+ imsm_update_version_info(super);
return 1;
}
@@ -6208,7 +6201,6 @@ static union {
static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
{
- struct imsm_super *mpb = super->anchor;
struct imsm_super *spare = &spare_record.anchor;
__u32 sum;
@@ -6217,14 +6209,11 @@ static int write_super_imsm_spare(struct intel_super *super, struct dl *d)
spare->mpb_size = __cpu_to_le32(sizeof(struct imsm_super));
spare->generation_num = __cpu_to_le32(1UL);
- spare->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
spare->num_disks = 1;
spare->num_raid_devs = 0;
- spare->cache_size = mpb->cache_size;
spare->pwr_cycle_count = __cpu_to_le32(1);
- snprintf((char *) spare->sig, MAX_SIGNATURE_LENGTH,
- MPB_SIGNATURE MPB_VERSION_RAID0);
+ imsm_write_signature(spare);
spare->disk[0] = d->disk;
if (__le32_to_cpu(d->disk.total_blocks_hi) > 0)
--
2.41.0

View File

@ -0,0 +1,67 @@
From 610fc2ee6fc09e828b14e8fa221b3f4f70fc7b2b Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:18 +0200
Subject: [PATCH 57/66] imsm: define RAID_10 attribute
Add MPB_ATTRIB_RAID10_EXT attribute to support RAID 10
with more than 4 drives.
Allow more than 4 drives in imsm_orom_support_raid_disks_raid10().
This is one of last patches for introducing R10D4+ to imsm.
Only small adjustments in reshape behaviours are needed.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
platform-intel.c | 3 ++-
super-intel.c | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/platform-intel.c b/platform-intel.c
index 40e8fb82..15a9fa5a 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -76,7 +76,8 @@ static bool imsm_orom_support_raid_disks_count_raid5(const int raid_disks)
static bool imsm_orom_support_raid_disks_count_raid10(const int raid_disks)
{
- if (raid_disks == 4)
+ /* raid_disks count must be higher than 4 and even */
+ if (raid_disks >= 4 && (raid_disks & 1) == 0)
return true;
return false;
}
diff --git a/super-intel.c b/super-intel.c
index 4b168add..2d309316 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -62,6 +62,8 @@
#define MPB_ATTRIB_RAIDCNG __cpu_to_le32(0x00000020)
/* supports expanded stripe sizes of 256K, 512K and 1MB */
#define MPB_ATTRIB_EXP_STRIPE_SIZE __cpu_to_le32(0x00000040)
+/* supports RAID10 with more than 4 drives */
+#define MPB_ATTRIB_RAID10_EXT __cpu_to_le32(0x00000080)
/* The OROM Support RST Caching of Volumes */
#define MPB_ATTRIB_NVM __cpu_to_le32(0x02000000)
@@ -89,6 +91,7 @@
MPB_ATTRIB_RAID10 | \
MPB_ATTRIB_RAID5 | \
MPB_ATTRIB_EXP_STRIPE_SIZE | \
+ MPB_ATTRIB_RAID10_EXT | \
MPB_ATTRIB_BBM)
/* Define attributes that are unused but not harmful */
@@ -5552,6 +5555,8 @@ static void imsm_update_version_info(struct intel_super *super)
break;
case IMSM_T_RAID10:
mpb->attributes |= MPB_ATTRIB_RAID10;
+ if (map->num_members > 4)
+ mpb->attributes |= MPB_ATTRIB_RAID10_EXT;
break;
}
}
--
2.41.0

View File

@ -0,0 +1,153 @@
From e0e56f4b2ed514f5049eb96b4ff8f7fdf30a4c49 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:19 +0200
Subject: [PATCH 58/66] imsm: simplify imsm_check_attributes()
imsm_check_attributes() is too complex for that it really does.
Remove repeating code and simplify the function.
Fix function calls.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 106 ++++++++------------------------------------------
1 file changed, 16 insertions(+), 90 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 2d309316..d60915e8 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2135,91 +2135,18 @@ void convert_from_4k(struct intel_super *super)
mpb->check_sum = __gen_imsm_checksum(mpb);
}
-/*******************************************************************************
- * function: imsm_check_attributes
- * Description: Function checks if features represented by attributes flags
- * are supported by mdadm.
- * Parameters:
- * attributes - Attributes read from metadata
- * Returns:
- * 0 - passed attributes contains unsupported features flags
- * 1 - all features are supported
- ******************************************************************************/
-static int imsm_check_attributes(__u32 attributes)
+/**
+ * imsm_check_attributes() - Check if features represented by attributes flags are supported.
+ *
+ * @attributes: attributes read from metadata.
+ * Returns: true if all features are supported, false otherwise.
+ */
+static bool imsm_check_attributes(__u32 attributes)
{
- int ret_val = 1;
- __u32 not_supported = MPB_ATTRIB_SUPPORTED^0xffffffff;
-
- not_supported &= ~MPB_ATTRIB_IGNORED;
-
- not_supported &= attributes;
- if (not_supported) {
- pr_err("(IMSM): Unsupported attributes : %x\n",
- (unsigned)__le32_to_cpu(not_supported));
- if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
- dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY \n");
- not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
- }
- if (not_supported & MPB_ATTRIB_2TB) {
- dprintf("\t\tMPB_ATTRIB_2TB\n");
- not_supported ^= MPB_ATTRIB_2TB;
- }
- if (not_supported & MPB_ATTRIB_RAID0) {
- dprintf("\t\tMPB_ATTRIB_RAID0\n");
- not_supported ^= MPB_ATTRIB_RAID0;
- }
- if (not_supported & MPB_ATTRIB_RAID1) {
- dprintf("\t\tMPB_ATTRIB_RAID1\n");
- not_supported ^= MPB_ATTRIB_RAID1;
- }
- if (not_supported & MPB_ATTRIB_RAID10) {
- dprintf("\t\tMPB_ATTRIB_RAID10\n");
- not_supported ^= MPB_ATTRIB_RAID10;
- }
- if (not_supported & MPB_ATTRIB_RAID1E) {
- dprintf("\t\tMPB_ATTRIB_RAID1E\n");
- not_supported ^= MPB_ATTRIB_RAID1E;
- }
- if (not_supported & MPB_ATTRIB_RAID5) {
- dprintf("\t\tMPB_ATTRIB_RAID5\n");
- not_supported ^= MPB_ATTRIB_RAID5;
- }
- if (not_supported & MPB_ATTRIB_RAIDCNG) {
- dprintf("\t\tMPB_ATTRIB_RAIDCNG\n");
- not_supported ^= MPB_ATTRIB_RAIDCNG;
- }
- if (not_supported & MPB_ATTRIB_BBM) {
- dprintf("\t\tMPB_ATTRIB_BBM\n");
- not_supported ^= MPB_ATTRIB_BBM;
- }
- if (not_supported & MPB_ATTRIB_CHECKSUM_VERIFY) {
- dprintf("\t\tMPB_ATTRIB_CHECKSUM_VERIFY (== MPB_ATTRIB_LEGACY)\n");
- not_supported ^= MPB_ATTRIB_CHECKSUM_VERIFY;
- }
- if (not_supported & MPB_ATTRIB_EXP_STRIPE_SIZE) {
- dprintf("\t\tMPB_ATTRIB_EXP_STRIP_SIZE\n");
- not_supported ^= MPB_ATTRIB_EXP_STRIPE_SIZE;
- }
- if (not_supported & MPB_ATTRIB_2TB_DISK) {
- dprintf("\t\tMPB_ATTRIB_2TB_DISK\n");
- not_supported ^= MPB_ATTRIB_2TB_DISK;
- }
- if (not_supported & MPB_ATTRIB_NEVER_USE2) {
- dprintf("\t\tMPB_ATTRIB_NEVER_USE2\n");
- not_supported ^= MPB_ATTRIB_NEVER_USE2;
- }
- if (not_supported & MPB_ATTRIB_NEVER_USE) {
- dprintf("\t\tMPB_ATTRIB_NEVER_USE\n");
- not_supported ^= MPB_ATTRIB_NEVER_USE;
- }
-
- if (not_supported)
- dprintf("(IMSM): Unknown attributes : %x\n", not_supported);
-
- ret_val = 0;
- }
+ if ((attributes & (MPB_ATTRIB_SUPPORTED | MPB_ATTRIB_IGNORED)) == attributes)
+ return true;
- return ret_val;
+ return false;
}
static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *map);
@@ -2247,11 +2174,10 @@ static void examine_super_imsm(struct supertype *st, char *homehost)
creation_time = __le64_to_cpu(mpb->creation_time);
printf(" Creation Time : %.24s\n",
creation_time ? ctime(&creation_time) : "Unknown");
- printf(" Attributes : ");
- if (imsm_check_attributes(mpb->attributes))
- printf("All supported\n");
- else
- printf("not supported\n");
+
+ printf(" Attributes : %08x (%s)\n", mpb->attributes,
+ imsm_check_attributes(mpb->attributes) ? "supported" : "not supported");
+
getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(&info, nbuf);
printf(" UUID : %s\n", nbuf + 5);
@@ -8182,9 +8108,9 @@ static struct mdinfo *container_content_imsm(struct supertype *st, char *subarra
int current_vol = super->current_vol;
/* do not assemble arrays when not all attributes are supported */
- if (imsm_check_attributes(mpb->attributes) == 0) {
+ if (imsm_check_attributes(mpb->attributes) == false) {
sb_errors = 1;
- pr_err("Unsupported attributes in IMSM metadata.Arrays activation is blocked.\n");
+ pr_err("Unsupported attributes in IMSM metadata. Arrays activation is blocked.\n");
}
/* count spare devices, not used in maps
--
2.41.0

View File

@ -0,0 +1,168 @@
From 44463edeb303a464c4a44fcea184b267aeb53302 Mon Sep 17 00:00:00 2001
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
Date: Mon, 29 Apr 2024 15:07:20 +0200
Subject: [PATCH 59/66] imsm: support RAID 10 with more than 4 drives
VROC UEFI driver does not support RAID 10 with more than 4 drives.
Add user prompts if such layout is being created and for R0->R10
reshapes.
Refactor ask() function:
- simplify the code,
- remove dialog reattempts,
- do no pass '?' sign on function calls,
- highlight default option on output.
This patch completes adding support for R10D4+ to IMSM.
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Create.c | 9 ++++++++-
super-intel.c | 14 ++++++++++++--
util.c | 39 +++++++++++++++++++++++++--------------
3 files changed, 45 insertions(+), 17 deletions(-)
diff --git a/Create.c b/Create.c
index d94253b1..d033eb68 100644
--- a/Create.c
+++ b/Create.c
@@ -965,6 +965,13 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
return 1;
}
+ if (st->ss == &super_imsm && s->level == 10 && s->raiddisks > 4) {
+ /* Print no matter runstop was specifed */
+ pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n");
+ pr_err("Array won't be suitable as boot device.\n");
+ warn = 1;
+ }
+
if (!have_container && s->level > 0 && ((maxsize-s->size)*100 > maxsize)) {
if (c->runstop != 1 || c->verbose >= 0)
pr_err("largest drive (%s) exceeds size (%lluK) by more than 1%%\n",
@@ -984,7 +991,7 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
if (warn) {
if (c->runstop!= 1) {
- if (!ask("Continue creating array? ")) {
+ if (!ask("Continue creating array")) {
pr_err("create aborted.\n");
return 1;
}
diff --git a/super-intel.c b/super-intel.c
index d60915e8..2b8b6fda 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -523,6 +523,7 @@ enum imsm_reshape_type {
CH_TAKEOVER,
CH_MIGRATION,
CH_ARRAY_SIZE,
+ CH_ABORT
};
/* definition of messages passed to imsm_process_update */
@@ -11898,7 +11899,7 @@ success:
****************************************************************************/
enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
struct geo_params *geo,
- int direction)
+ int direction, struct context *c)
{
struct mdinfo info;
int change = -1;
@@ -11925,6 +11926,14 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
check_devs = 1;
raid_disks += 1; /* parity disk added */
} else if (geo->level == IMSM_T_RAID10) {
+ if (geo->level == IMSM_T_RAID10 && geo->raid_disks > 2 &&
+ !c->force) {
+ pr_err("Warning! VROC UEFI driver does not support RAID10 in requested layout.\n");
+ pr_err("Array won't be suitable as boot device.\n");
+ pr_err("Note: You can omit this check with \"--force\"\n");
+ if (ask("Do you want to continue") < 1)
+ return CH_ABORT;
+ }
change = CH_TAKEOVER;
check_devs = 1;
raid_disks *= 2; /* mirrors added */
@@ -12219,7 +12228,7 @@ static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct
goto exit_imsm_reshape_super;
}
super->current_vol = dev->index;
- change = imsm_analyze_change(st, &geo, shape->direction);
+ change = imsm_analyze_change(st, &geo, shape->direction, c);
switch (change) {
case CH_TAKEOVER:
ret_val = imsm_takeover(st, &geo);
@@ -12262,6 +12271,7 @@ static int imsm_reshape_super(struct supertype *st, struct shape *shape, struct
free(u);
}
break;
+ case CH_ABORT:
default:
ret_val = 1;
}
diff --git a/util.c b/util.c
index 9e837045..4fbf11c4 100644
--- a/util.c
+++ b/util.c
@@ -725,23 +725,33 @@ int stat_is_blkdev(char *devname, dev_t *rdev)
return 1;
}
+/**
+ * ask() - prompt user for "yes/no" dialog.
+ * @mesg: message to be printed, without '?' sign.
+ * Returns: 1 if 'Y/y', 0 otherwise.
+ *
+ * The default value is 'N/n', thus the caps on "N" on prompt.
+ */
int ask(char *mesg)
{
- char *add = "";
- int i;
- for (i = 0; i < 5; i++) {
- char buf[100];
- fprintf(stderr, "%s%s", mesg, add);
- fflush(stderr);
- if (fgets(buf, 100, stdin)==NULL)
- return 0;
- if (buf[0]=='y' || buf[0]=='Y')
- return 1;
- if (buf[0]=='n' || buf[0]=='N')
- return 0;
- add = "(y/n) ";
+ char buf[3] = {0};
+
+ fprintf(stderr, "%s [y/N]? ", mesg);
+ fflush(stderr);
+ if (fgets(buf, 3, stdin) == NULL)
+ return 0;
+ if (strlen(buf) == 1) {
+ pr_err("assuming no.\n");
+ return 0;
}
- pr_err("assuming 'no'\n");
+ if (buf[1] != '\n')
+ goto bad_option;
+ if (toupper(buf[0]) == 'Y')
+ return 1;
+ if (toupper(buf[0]) == 'N')
+ return 0;
+bad_option:
+ pr_err("bad option.\n");
return 0;
}
@@ -1868,6 +1878,7 @@ int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info)
if (st->ss->external)
return sysfs_set_array(info);
+
memset(&inf, 0, sizeof(inf));
inf.major_version = info->array.major_version;
inf.minor_version = info->array.minor_version;
--
2.41.0

View File

@ -0,0 +1,41 @@
From d399c494c6364a6b6d0f965c08443fdc79d1e248 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Thu, 18 Apr 2024 18:23:19 +0800
Subject: [PATCH 60/66] tests/01r5fail enhance
After removing dev0, the recovery starts because it already has a spare
disk. It's good to check recovery. But it's not right to check recovery
after adding dev3. Because the recovery may finish. It depends on the
recovery performance of the testing machine. If the recovery finishes,
it will fail. But dev3 is only added as a spare disk, we can't expect
there is a recovery happens.
So remove the codes about adding dev3.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/01r5fail | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/tests/01r5fail b/tests/01r5fail
index 873dba58..c210d6e7 100644
--- a/tests/01r5fail
+++ b/tests/01r5fail
@@ -17,11 +17,7 @@ check wait
mdadm $md0 --fail $dev0
mdadm $md0 --remove $dev3 $dev0
check recovery
-check state _UUU
-
-mdadm $md0 -a $dev3
-check recovery
check wait
check state UUUU
-mdadm -S $md0
\ No newline at end of file
+mdadm -S $md0
--
2.41.0

View File

@ -0,0 +1,32 @@
From a20cb3872c02241e4f0f7cc26933a43bac7d1cbb Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Thu, 18 Apr 2024 18:23:20 +0800
Subject: [PATCH 61/66] tests/01r5integ.broken
01r5integ can be run successfully 152 times without error with
kernel 6.9.0-rc4 and mdadm - v4.3-51-g52bead95. So remove this
one broken case.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/01r5integ.broken | 7 -------
1 file changed, 7 deletions(-)
delete mode 100644 tests/01r5integ.broken
diff --git a/tests/01r5integ.broken b/tests/01r5integ.broken
deleted file mode 100644
index 20737637..00000000
--- a/tests/01r5integ.broken
+++ /dev/null
@@ -1,7 +0,0 @@
-fails rarely
-
-Fails about 1 in every 30 runs with a sha mismatch error:
-
- c49ab26e1b01def7874af9b8a6d6d0c29fdfafe6 /dev/md0 does not match
- 15dc2f73262f811ada53c65e505ceec9cf025cb9 /dev/md0 with /dev/loop3
- missing
--
2.41.0

View File

@ -0,0 +1,31 @@
From 896948b14ad26f15590269dce50ac4896284dc29 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Thu, 18 Apr 2024 18:23:21 +0800
Subject: [PATCH 62/66] tests/01raid6integ.broken can be removed
01raid6integ can be run successfully with kernel 6.9.0-rc3.
So remove 01raid6integ.broken.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/01raid6integ.broken | 7 -------
1 file changed, 7 deletions(-)
delete mode 100644 tests/01raid6integ.broken
diff --git a/tests/01raid6integ.broken b/tests/01raid6integ.broken
deleted file mode 100644
index 1df735f0..00000000
--- a/tests/01raid6integ.broken
+++ /dev/null
@@ -1,7 +0,0 @@
-fails infrequently
-
-Fails about 1 in 5 with a sha mismatch:
-
- 8286c2bc045ae2cfe9f8b7ae3a898fa25db6926f /dev/md0 does not match
- a083a0738b58caab37fd568b91b177035ded37df /dev/md0 with /dev/loop2 and
- /dev/loop3 missing
--
2.41.0

View File

@ -0,0 +1,38 @@
From 893a55831e5abbcd15b171db66fa1f389fb61506 Mon Sep 17 00:00:00 2001
From: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Date: Tue, 7 May 2024 19:32:16 +0200
Subject: [PATCH 63/66] Makefile: Move -pie to LDFLAGS
Move -pie from LDLIBS to LDFLAGS and make LDFLAGS configurable to allow
the user to drop it by setting their own LDFLAGS (e.g. PIE could be
enabled or disabled by the buildsystem such as buildroot).
Suggested-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 7c221a89..adac7905 100644
--- a/Makefile
+++ b/Makefile
@@ -132,12 +132,12 @@ CFLAGS += -DUSE_PTHREADS
MON_LDFLAGS += -pthread
endif
-LDFLAGS = -Wl,-z,now,-z,noexecstack
+LDFLAGS ?= -pie -Wl,-z,now,-z,noexecstack
# If you want a static binary, you might uncomment these
# LDFLAGS += -static
# STRIP = -s
-LDLIBS = -ldl -pie
+LDLIBS = -ldl
# To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
ifeq (, $(findstring -DNO_LIBUDEV, $(CXFLAGS)))
--
2.41.0

View File

@ -0,0 +1,30 @@
From a0174749426f49a04f11ae0e728cb0a681bfa465 Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Thu, 9 May 2024 09:10:59 +0800
Subject: [PATCH 64/66] tests/23rdev-lifetime: fix a typo
"pill" was wrong, while it should be "kill", test will still pass while
test thread will not be cleaned up.
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/23rdev-lifetime | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/23rdev-lifetime b/tests/23rdev-lifetime
index 1750b0db..03b61de4 100644
--- a/tests/23rdev-lifetime
+++ b/tests/23rdev-lifetime
@@ -4,7 +4,7 @@ pid=""
runtime=2
clean_up_test() {
- pill -9 $pid
+ kill -9 $pid
echo clear > /sys/block/md0/md/array_state
}
--
2.41.0

View File

@ -0,0 +1,55 @@
From b0f4e8e30f38d83f7e3f53d01d72d4cb3b4d42d7 Mon Sep 17 00:00:00 2001
From: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
Date: Tue, 7 May 2024 05:38:55 +0200
Subject: [PATCH 65/66] util.c: change devnm to const in mdmon functions
Devnm shall not be changed inside mdmon_running()
and mdmon_pid() functions, change this parameter to const.
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 4 ++--
util.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index 2ff3e463..1ba541fc 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1768,8 +1768,8 @@ extern int is_subarray_active(char *subarray, char *devname);
extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet);
extern struct superswitch *version_to_superswitch(char *vers);
-extern int mdmon_running(char *devnm);
-extern int mdmon_pid(char *devnm);
+extern int mdmon_running(const char *devnm);
+extern int mdmon_pid(const char *devnm);
extern int check_env(char *name);
extern __u32 random32(void);
extern void random_uuid(__u8 *buf);
diff --git a/util.c b/util.c
index 4fbf11c4..e2b490e1 100644
--- a/util.c
+++ b/util.c
@@ -1902,7 +1902,7 @@ unsigned long long min_recovery_start(struct mdinfo *array)
return recovery_start;
}
-int mdmon_pid(char *devnm)
+int mdmon_pid(const char *devnm)
{
char path[100];
char pid[10];
@@ -1922,7 +1922,7 @@ int mdmon_pid(char *devnm)
return atoi(pid);
}
-int mdmon_running(char *devnm)
+int mdmon_running(const char *devnm)
{
int pid = mdmon_pid(devnm);
if (pid <= 0)
--
2.41.0

View File

@ -0,0 +1,121 @@
From aa1cc5815d2b14a8b47add18cfaa8264e19c10ce Mon Sep 17 00:00:00 2001
From: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
Date: Tue, 7 May 2024 05:38:56 +0200
Subject: [PATCH 66/66] Wait for mdmon when it is stared via systemd
When mdmon is being started it may need few seconds to start.
For now, we didn't wait for it. Introduce wait_for_mdmon()
function, which waits up to 5 seconds for mdmon to start completely.
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Assemble.c | 4 ++--
Grow.c | 7 ++++---
mdadm.h | 2 ++
util.c | 29 +++++++++++++++++++++++++++++
4 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index f5e9ab1f..83dced19 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -2173,8 +2173,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(st->container_devnm);
- if (mdmon_running(st->container_devnm) &&
- st->update_tail == NULL)
+ if (wait_for_mdmon(st->container_devnm) == MDADM_STATUS_SUCCESS &&
+ !st->update_tail)
st->update_tail = &st->updates;
}
diff --git a/Grow.c b/Grow.c
index 87ed9214..1923c27c 100644
--- a/Grow.c
+++ b/Grow.c
@@ -2134,7 +2134,7 @@ int Grow_reshape(char *devname, int fd,
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(container);
- if (mdmon_running(st->container_devnm) == false) {
+ if (wait_for_mdmon(st->container_devnm) != MDADM_STATUS_SUCCESS) {
pr_err("No mdmon found. Grow cannot continue.\n");
goto release;
}
@@ -3218,7 +3218,8 @@ static int reshape_array(char *container, int fd, char *devname,
if (!mdmon_running(container))
start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(container) && st->update_tail == NULL)
+ if (wait_for_mdmon(container) == MDADM_STATUS_SUCCESS &&
+ !st->update_tail)
st->update_tail = &st->updates;
}
}
@@ -5173,7 +5174,7 @@ int Grow_continue_command(char *devname, int fd, struct context *c)
start_mdmon(container);
ping_monitor(container);
- if (mdmon_running(container) == false) {
+ if (wait_for_mdmon(container) != MDADM_STATUS_SUCCESS) {
pr_err("No mdmon found. Grow cannot continue.\n");
ret_val = 1;
goto Grow_continue_command_exit;
diff --git a/mdadm.h b/mdadm.h
index 1ba541fc..b71d7b32 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1770,6 +1770,8 @@ extern struct superswitch *version_to_superswitch(char *vers);
extern int mdmon_running(const char *devnm);
extern int mdmon_pid(const char *devnm);
+extern mdadm_status_t wait_for_mdmon(const char *devnm);
+
extern int check_env(char *name);
extern __u32 random32(void);
extern void random_uuid(__u8 *buf);
diff --git a/util.c b/util.c
index e2b490e1..bf79742f 100644
--- a/util.c
+++ b/util.c
@@ -1932,6 +1932,35 @@ int mdmon_running(const char *devnm)
return 0;
}
+/*
+ * wait_for_mdmon() - Waits for mdmon within specified time.
+ * @devnm: Device for which mdmon should start.
+ *
+ * Function waits for mdmon to start. It may need few seconds
+ * to start, we set timeout to 5, it should be sufficient.
+ * Do not wait if mdmon has been started.
+ *
+ * Return: MDADM_STATUS_SUCCESS if mdmon is running, error code otherwise.
+ */
+mdadm_status_t wait_for_mdmon(const char *devnm)
+{
+ const time_t mdmon_timeout = 5;
+ time_t start_time = time(0);
+
+ if (mdmon_running(devnm))
+ return MDADM_STATUS_SUCCESS;
+
+ pr_info("Waiting for mdmon to start\n");
+ while (time(0) - start_time < mdmon_timeout) {
+ sleep_for(0, MSEC_TO_NSEC(200), true);
+ if (mdmon_running(devnm))
+ return MDADM_STATUS_SUCCESS;
+ };
+
+ pr_err("Timeout waiting for mdmon\n");
+ return MDADM_STATUS_ERROR;
+}
+
int start_mdmon(char *devnm)
{
int i;
--
2.41.0

View File

@ -0,0 +1,62 @@
From c5879860eac64ddd7bec4ba50c9adbfebcbf1d2e Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Wed, 15 May 2024 13:26:28 +0200
Subject: [PATCH 1/1] mdadm: Fix compilation for 32-bit arch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Casting void pointer to __u64 works for 64-bit arch but fails to compile
on 32-bit arch like i686.
Fail on i686 platform:
drive_encryption.c: In function nvme_security_recv_ioctl:
drive_encryption.c:236:25: error: cast from pointer to integer of
different size [-Werror=pointer-to-int-cast]
236 | nvme_cmd.addr = (__u64)response_buffer;
| ^
drive_encryption.c: In function nvme_identify_ioctl:
drive_encryption.c:271:25: error: cast from pointer to integer of
different size [-Werror=pointer-to-int-cast]
271 | nvme_cmd.addr = (__u64)response_buffer;
| ^
cc1: all warnings being treated as errors
make: *** [Makefile:211: drive_encryption.o] Error 1
This change adds cast void pointer to uintptr_t first to ensure that
proper pointer size is used for casting from pointer type. Then is safe to
cast it to __u64 because it is tracked as u_int, regardless it is 32-bit
or 64-bit arch.
Reported-by: Xiao Ni <xni@redhat.com>
Fixes: cc48406887b3 ("Add reading Opal NVMe encryption information")
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
---
drive_encryption.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drive_encryption.c b/drive_encryption.c
index 27da9621..a4ad799f 100644
--- a/drive_encryption.c
+++ b/drive_encryption.c
@@ -233,7 +233,7 @@ nvme_security_recv_ioctl(int disk_fd, __u8 sec_protocol, __u16 comm_id, void *re
nvme_cmd.cdw10 = sec_protocol << 24 | comm_id << 8;
nvme_cmd.cdw11 = buf_size;
nvme_cmd.data_len = buf_size;
- nvme_cmd.addr = (__u64)response_buffer;
+ nvme_cmd.addr = (__u64)(uintptr_t)response_buffer;
status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
if (status != 0) {
@@ -268,7 +268,7 @@ nvme_identify_ioctl(int disk_fd, void *response_buffer, size_t buf_size, const i
nvme_cmd.opcode = NVME_IDENTIFY;
nvme_cmd.cdw10 = NVME_IDENTIFY_CONTROLLER_DATA;
nvme_cmd.data_len = buf_size;
- nvme_cmd.addr = (__u64)response_buffer;
+ nvme_cmd.addr = (__u64)(uintptr_t)response_buffer;
status = ioctl(disk_fd, NVME_IOCTL_ADMIN_CMD, &nvme_cmd);
if (status != 0) {
--
2.41.0

View File

@ -0,0 +1,267 @@
From 95673c7d83c8ac7f2aeb91a34ead2971ba30e96e Mon Sep 17 00:00:00 2001
From: Nigel Croxon <ncroxon@redhat.com>
Date: Mon, 20 May 2024 09:36:50 -0400
Subject: [PATCH 070/157] add checking of return status on fstat calls
There are a few places we don't check the return status when
calling fstat for success. Clean up the calls by adding a
check before continuing.
Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
---
Assemble.c | 41 +++++++++++++++++++++++------------------
Dump.c | 11 +++++++++--
Grow.c | 12 ++++++++----
config.c | 3 ++-
mdstat.c | 3 ++-
super-ddf.c | 8 ++++++--
super-intel.c | 8 ++++++--
7 files changed, 56 insertions(+), 30 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 83dced19..58dc2c5e 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -652,7 +652,9 @@ static int load_devices(struct devs *devices, char *devmap,
/* prepare useful information in info structures */
struct stat stb2;
int err;
- fstat(mdfd, &stb2);
+
+ if (fstat(mdfd, &stb2) != 0)
+ goto error;
if (c->update == UOPT_UUID && !ident->uuid_set)
random_uuid((__u8 *)ident->uuid);
@@ -675,13 +677,10 @@ static int load_devices(struct devs *devices, char *devmap,
devname);
if (dfd >= 0)
close(dfd);
- close(mdfd);
- free(devices);
- free(devmap);
tst->ss->free_super(tst);
free(tst);
*stp = st;
- return -1;
+ goto error;
}
tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks);
@@ -715,12 +714,9 @@ static int load_devices(struct devs *devices, char *devmap,
map_num(update_options, c->update), tst->ss->name);
tst->ss->free_super(tst);
free(tst);
- close(mdfd);
close(dfd);
- free(devices);
- free(devmap);
*stp = st;
- return -1;
+ goto error;
}
if (c->update == UOPT_UUID &&
!ident->uuid_set) {
@@ -751,18 +747,23 @@ static int load_devices(struct devs *devices, char *devmap,
devname);
if (dfd >= 0)
close(dfd);
- close(mdfd);
- free(devices);
- free(devmap);
tst->ss->free_super(tst);
free(tst);
*stp = st;
- return -1;
+ goto error;
}
tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks);
}
- fstat(dfd, &stb);
+ if (fstat(dfd, &stb) != 0) {
+ close(dfd);
+ free(devices);
+ free(devmap);
+ tst->ss->free_super(tst);
+ free(tst);
+ *stp = st;
+ return -1;
+ }
close(dfd);
if (c->verbose > 0)
@@ -842,12 +843,9 @@ static int load_devices(struct devs *devices, char *devmap,
inargv ? "the list" :
"the\n DEVICE list in mdadm.conf"
);
- close(mdfd);
- free(devices);
- free(devmap);
free(best);
*stp = st;
- return -1;
+ goto error;
}
if (best[i] == -1 || (devices[best[i]].i.events
< devices[devcnt].i.events))
@@ -863,6 +861,13 @@ static int load_devices(struct devs *devices, char *devmap,
*bestp = best;
*stp = st;
return devcnt;
+
+error:
+ close(mdfd);
+ free(devices);
+ free(devmap);
+ return -1;
+
}
static int force_array(struct mdinfo *content,
diff --git a/Dump.c b/Dump.c
index 736bcb60..81b94940 100644
--- a/Dump.c
+++ b/Dump.c
@@ -37,6 +37,7 @@ int Dump_metadata(char *dev, char *dir, struct context *c,
unsigned long long size;
DIR *dirp;
struct dirent *de;
+ int ret = 0;
if (stat(dir, &stb) != 0 ||
(S_IFMT & stb.st_mode) != S_IFDIR) {
@@ -112,9 +113,15 @@ int Dump_metadata(char *dev, char *dir, struct context *c,
}
if (c->verbose >= 0)
printf("%s saved as %s.\n", dev, fname);
- fstat(fd, &dstb);
- close(fd);
+
close(fl);
+ ret = fstat(fd, &dstb);
+ close(fd);
+ if (ret) {
+ unlink(fname);
+ free(fname);
+ return 1;
+ }
if ((dstb.st_mode & S_IFMT) != S_IFBLK) {
/* Not a block device, so cannot create links */
free(fname);
diff --git a/Grow.c b/Grow.c
index 1923c27c..963792d0 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1223,13 +1223,14 @@ int reshape_open_backup_file(char *backup_file,
* way this will not notice, but it is better than
* nothing.
*/
- fstat(*fdlist, &stb);
+ if (fstat(*fdlist, &stb) != 0)
+ goto error;
dev = stb.st_dev;
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ goto error;
if (stb.st_rdev == dev) {
pr_err("backup file must NOT be on the array being reshaped.\n");
- close(*fdlist);
- return 0;
+ goto error;
}
memset(buf, 0, 512);
@@ -1255,6 +1256,9 @@ int reshape_open_backup_file(char *backup_file,
}
return 1;
+error:
+ close(*fdlist);
+ return 0;
}
unsigned long compute_backup_blocks(int nchunk, int ochunk,
diff --git a/config.c b/config.c
index b46d71cb..612e700d 100644
--- a/config.c
+++ b/config.c
@@ -949,7 +949,8 @@ void conf_file_or_dir(FILE *f)
struct dirent *dp;
struct fname *list = NULL;
- fstat(fileno(f), &st);
+ if (fstat(fileno(f), &st) != 0)
+ return;
if (S_ISREG(st.st_mode))
conf_file(f);
else if (!S_ISDIR(st.st_mode))
diff --git a/mdstat.c b/mdstat.c
index 2fd792c5..e233f094 100644
--- a/mdstat.c
+++ b/mdstat.c
@@ -348,7 +348,8 @@ void mdstat_wait_fd(int fd, const sigset_t *sigmask)
if (fd >= 0) {
struct stat stb;
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ return;
if ((stb.st_mode & S_IFMT) == S_IFREG)
/* Must be a /proc or /sys fd, so expect
* POLLPRI
diff --git a/super-ddf.c b/super-ddf.c
index 21426c75..311001c1 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1053,7 +1053,10 @@ static int load_ddf_local(int fd, struct ddf_super *super,
0);
dl->devname = devname ? xstrdup(devname) : NULL;
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0) {
+ free(dl);
+ return 1;
+ }
dl->major = major(stb.st_rdev);
dl->minor = minor(stb.st_rdev);
dl->next = super->dlist;
@@ -2786,7 +2789,8 @@ static int add_to_super_ddf(struct supertype *st,
/* This is device numbered dk->number. We need to create
* a phys_disk entry and a more detailed disk_data entry.
*/
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ return 1;
n = find_unused_pde(ddf);
if (n == DDF_NOTFOUND) {
pr_err("No free slot in array, cannot add disk\n");
diff --git a/super-intel.c b/super-intel.c
index 2b8b6fda..4d257371 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -4239,7 +4239,10 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd)
dl = xcalloc(1, sizeof(*dl));
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0) {
+ free(dl);
+ return 1;
+ }
dl->major = major(stb.st_rdev);
dl->minor = minor(stb.st_rdev);
dl->next = super->disks;
@@ -5981,7 +5984,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk,
if (super->current_vol >= 0)
return add_to_super_imsm_volume(st, dk, fd, devname);
- fstat(fd, &stb);
+ if (fstat(fd, &stb) != 0)
+ return 1;
dd = xcalloc(sizeof(*dd), 1);
dd->major = major(stb.st_rdev);
dd->minor = minor(stb.st_rdev);
--
2.41.0

View File

@ -0,0 +1,28 @@
From c7790592bb7d050a990a9accb50de8f584879169 Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Wed, 22 May 2024 11:13:17 +0200
Subject: [PATCH 071/157] super-intel: fix typo in error msg
Fix typo in encryption policy error msg.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
---
super-intel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/super-intel.c b/super-intel.c
index 4d257371..95856322 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -11328,7 +11328,7 @@ check_policy:
return MDADM_STATUS_SUCCESS;
fd2devname(disk_fd, devname);
- pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected eariler.\n",
+ pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected earlier.\n",
encryption_state, devname, expected_policy->value);
pr_vrb("Disks with different encryption status cannot be used.\n");
return MDADM_STATUS_ERROR;
--
2.41.0

View File

@ -0,0 +1,45 @@
From 49145d4f574b21a6c0612ce691f255732cb91832 Mon Sep 17 00:00:00 2001
From: Nigel Croxon <ncroxon@redhat.com>
Date: Wed, 22 May 2024 16:05:25 -0400
Subject: [PATCH 072/157] mdadm: super-intel remove dead code
Execution cannot reach this statement: "while (devlist) { dv = de...".
Local variable "err" is assigned only once, to a constant value,
making it effectively constant throughout its scope.
Remove dead code.
Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
---
super-intel.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 95856322..d1b737c7 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -7046,7 +7046,6 @@ get_devices(const char *hba_path)
struct md_list *dv;
struct dirent *ent;
DIR *dir;
- int err = 0;
#if DEBUG_LOOP
devlist = get_loop_devices();
@@ -7088,14 +7087,6 @@ get_devices(const char *hba_path)
dv->next = devlist;
devlist = dv;
}
- if (err) {
- while(devlist) {
- dv = devlist;
- devlist = devlist->next;
- free(dv->devname);
- free(dv);
- }
- }
closedir(dir);
return devlist;
}
--
2.41.0

View File

@ -0,0 +1,55 @@
From 5c30864146412fcdfdcfddcdd94c5c449d9ddbed Mon Sep 17 00:00:00 2001
From: Nigel Croxon <ncroxon@redhat.com>
Date: Wed, 22 May 2024 16:53:22 -0400
Subject: [PATCH 073/157] mdadm: super-intel fix bad shift
In the expression "1 << i", left shifting by more than 31 bits has undefined behavior.
The shift amount, "i", is as much as 63. The operand has type "int" (32 bits) and will
be shifted as an "int". The fix is to change to a 64 bit int.
Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
---
super-intel.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index d1b737c7..0287a618 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2343,7 +2343,8 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type)
get_encryption_status_string(information.status));
}
-static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_base, int verbose)
+static int ahci_enumerate_ports(struct sys_dev *hba, unsigned long port_count, int host_base,
+ int verbose)
{
/* dump an unsorted list of devices attached to AHCI Intel storage
* controller, as well as non-connected ports
@@ -2357,7 +2358,7 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba
if (port_count > (int)sizeof(port_mask) * 8) {
if (verbose > 0)
- pr_err("port_count %d out of range\n", port_count);
+ pr_err("port_count %ld out of range\n", port_count);
return 2;
}
@@ -2499,11 +2500,11 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba
if (dir)
closedir(dir);
if (err == 0) {
- int i;
+ unsigned long i;
for (i = 0; i < port_count; i++)
- if (port_mask & (1 << i))
- printf(" Port%d : - no device attached -\n", i);
+ if (port_mask & (1L << i))
+ printf(" Port%ld : - no device attached -\n", i);
}
return err;
--
2.41.0

View File

@ -0,0 +1,438 @@
From 50b100768a115526f5029113af957658ef76b383 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Fri, 29 Mar 2024 15:21:54 +0100
Subject: [PATCH 074/157] mdadm: deprecate bitmap custom file
This option has been deprecated in kernel by Christoph in commit
0ae1c9d38426 ("md: deprecate bitmap file support"). Do the same in
mdadm.
With this change, user must acknowledge it, it is not
skippable. The implementation of custom bitmap file looks like it's
abandoned. It cannot be done by Incremental so it is not respected by
any udev based system and it seems to not be recorded by metadata.
User must assemble such volume manually.
Tests for bitmap custom file are removed because now they will not
pass because interaction with user is mandatory.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.8.in | 34 +++++++++----------
mdadm.c | 70 +++++++++++++++++++++++++++-------------
tests/05r1-bitmapfile | 49 ----------------------------
tests/05r1-grow-external | 33 -------------------
tests/05r1-n3-bitmapfile | 53 ------------------------------
tests/05r5-bitmapfile | 49 ----------------------------
tests/05r6-bitmapfile | 49 ----------------------------
7 files changed, 62 insertions(+), 275 deletions(-)
delete mode 100644 tests/05r1-bitmapfile
delete mode 100644 tests/05r1-grow-external
delete mode 100644 tests/05r1-n3-bitmapfile
delete mode 100644 tests/05r5-bitmapfile
delete mode 100644 tests/05r6-bitmapfile
diff --git a/mdadm.8.in b/mdadm.8.in
index 9ba66825..aa0c5403 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -727,29 +727,25 @@ same as
.TP
.BR \-b ", " \-\-bitmap=
-Specify a file to store a write-intent bitmap in. The file should not
-exist unless
-.B \-\-force
-is also given. The same file should be provided
-when assembling the array. If the word
-.B "internal"
-is given, then the bitmap is stored with the metadata on the array,
-and so is replicated on all devices. If the word
-.B "none"
-is given with
-.B \-\-grow
-mode, then any bitmap that is present is removed. If the word
-.B "clustered"
-is given, the array is created for a clustered environment. One bitmap
-is created for each node as defined by the
+Specify how to store a write-intent bitmap. Following values are supported:
+
+.B internal
+- the bitmap is stored with the metadata on the array and so is replicated on all devices.
+
+.B clustered
+- the array is created for a clustered environment. One bitmap is created for each node as defined
+by the
.B \-\-nodes
parameter and are stored internally.
-To help catch typing errors, the filename must contain at least one
-slash ('/') if it is a real file (not 'internal' or 'none').
+.B none
+- create array with no bitmap or remove any present bitmap (grow mode).
-Note: external bitmaps are only known to work on ext2 and ext3.
-Storing bitmap files on other filesystems may result in serious problems.
+Setting bitmap for file is deprecated and should not be used. The file should not exist unless
+.B \-\-force
+is also given. The same file should be provided when assembling the array. The file name must
+contain at least one slash ('/'). Bitmap files are only known to work on ext2 and ext3. Storing
+bitmap files on other filesystems may result in serious problems.
When creating an array on devices which are 100G or larger,
.I mdadm
diff --git a/mdadm.c b/mdadm.c
index d18619db..0b99fad4 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -29,6 +29,51 @@
#include "md_p.h"
#include <ctype.h>
+/**
+ * set_bitmap_value() - set bitmap value.
+ * @s: Shape.
+ * @c: Context.
+ * @val: value to set.
+ *
+ * Validate and set bitmap. Context is needed for setting nodes for clustered bitmap.
+ */
+static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char *val)
+{
+ if (s->bitmap_file) {
+ pr_err("--bitmap cannot be set twice. Second value: \"%s\".\n", val);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (strcmp(val, "internal") == 0 || strcmp(optarg, STR_COMMON_NONE) == 0) {
+ s->bitmap_file = val;
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ if (strcmp(val, "clustered") == 0) {
+ s->bitmap_file = val;
+ /* Set the default number of cluster nodes
+ * to 4 if not already set by user
+ */
+ if (c->nodes < 1)
+ c->nodes = 4;
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ if (strchr(val, '/')) {
+ pr_info("Custom write-intent bitmap file option is deprecated.\n");
+ if (ask("Do you want to continue? (y/n)")) {
+ s->bitmap_file = val;
+ return MDADM_STATUS_SUCCESS;
+ }
+
+ return MDADM_STATUS_ERROR;
+ }
+
+ pr_err("--bitmap value must contain a '/' or be 'internal', 'clustered' or 'none'\n");
+ pr_err("Current value is \"%s\"", val);
+ return MDADM_STATUS_ERROR;
+}
+
static int scan_assemble(struct supertype *ss,
struct context *c,
struct mddev_ident *ident);
@@ -1094,30 +1139,9 @@ int main(int argc, char *argv[])
case O(CREATE,Bitmap): /* here we create the bitmap */
case O(GROW,'b'):
case O(GROW,Bitmap):
- if (s.bitmap_file) {
- pr_err("bitmap cannot be set twice. Second value: %s.\n", optarg);
+ if (set_bitmap_value(&s, &c, optarg))
exit(2);
- }
- if (strcmp(optarg, "internal") == 0 ||
- strcmp(optarg, STR_COMMON_NONE) == 0 ||
- strchr(optarg, '/') != NULL) {
- s.bitmap_file = optarg;
- continue;
- }
- if (strcmp(optarg, "clustered") == 0) {
- s.bitmap_file = optarg;
- /* Set the default number of cluster nodes
- * to 4 if not already set by user
- */
- if (c.nodes < 1)
- c.nodes = 4;
- continue;
- }
- /* probable typo */
- pr_err("bitmap file must contain a '/', or be 'internal', or be 'clustered', or 'none'\n"
- " not '%s'\n", optarg);
- exit(2);
-
+ continue;
case O(GROW,BitmapChunk):
case O(BUILD,BitmapChunk):
case O(CREATE,BitmapChunk): /* bitmap chunksize */
diff --git a/tests/05r1-bitmapfile b/tests/05r1-bitmapfile
deleted file mode 100644
index f384f0ea..00000000
--- a/tests/05r1-bitmapfile
+++ /dev/null
@@ -1,49 +0,0 @@
-
-#
-# create a raid1 with a bitmap file
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create --run $md0 --level=1 -n2 --delay=1 --bitmap $bmf $dev1 $dev2
-check wait
-testdev $md0 1 $mdsize1a 64
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2
-testdev $md0 1 $mdsize1a 64
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev1
-testdev $md0 1 $mdsize1a 64
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev2
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-mdadm --zero $dev1 # force --add, not --re-add
-mdadm $md0 --add $dev1
-#it is too fast# check recovery
-
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
diff --git a/tests/05r1-grow-external b/tests/05r1-grow-external
deleted file mode 100644
index 69da3e90..00000000
--- a/tests/05r1-grow-external
+++ /dev/null
@@ -1,33 +0,0 @@
-
-#
-# create a raid1 array, add an external bitmap
-#
-mdadm --create --run $md0 -l 1 -n 2 $dev1 $dev2
-check wait
-testdev $md0 1 $mdsize1a 64
-
-bmf=$targetdir/bm
-rm -f $bmf
-#mdadm -E $dev1
-mdadm --grow $md0 --bitmap=$bmf --delay=1 || { mdadm -X $bmf ; exit 1; }
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-testdev $md0 1 $mdsize1a 64
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-#echo $dirty1 $dirty2 $dirty3 $dirty4
-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ]
-then
- echo bad dirty counts
- exit 1
-fi
-
-# now to remove the bitmap
-check bitmap
-mdadm --grow $md0 --bitmap=none
-check nobitmap
-mdadm -S $md0
diff --git a/tests/05r1-n3-bitmapfile b/tests/05r1-n3-bitmapfile
deleted file mode 100644
index f1c3f1ee..00000000
--- a/tests/05r1-n3-bitmapfile
+++ /dev/null
@@ -1,53 +0,0 @@
-
-#
-# create a raid1 with 3 devices and a bitmap file
-# make sure resync does right thing.
-#
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create -e0.90 --run $md0 --level=1 -n3 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3
-check wait
-testdev $md0 1 $mdsize0 64
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3
-testdev $md0 1 $mdsize0 64
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev2
-testdev $md0 1 $mdsize0 64
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev1 $dev3
-check nosync
-mdadm --zero-superblock $dev2
-mdadm $md0 --add $dev2
-check recovery
-
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
-exit 0
diff --git a/tests/05r5-bitmapfile b/tests/05r5-bitmapfile
deleted file mode 100644
index 6d173d88..00000000
--- a/tests/05r5-bitmapfile
+++ /dev/null
@@ -1,49 +0,0 @@
-
-#
-# create a raid1 with a bitmap file
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create --run $md0 --level=5 -n3 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3
-check wait
-testdev $md0 2 $mdsize1 512
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3
-testdev $md0 2 $mdsize1 512
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev1
-testdev $md0 2 $mdsize1 512
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev2 $dev3
-mdadm --zero $dev1 # force add, not re-add
-mdadm $md0 --add $dev1
-check recovery
-
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
diff --git a/tests/05r6-bitmapfile b/tests/05r6-bitmapfile
deleted file mode 100644
index d11896db..00000000
--- a/tests/05r6-bitmapfile
+++ /dev/null
@@ -1,49 +0,0 @@
-
-#
-# create a raid1 with a bitmap file
-#
-bmf=$targetdir/bitmap
-rm -f $bmf
-mdadm --create --run $md0 --level=6 -n4 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3 $dev4
-check wait
-testdev $md0 2 $mdsize1 512
-mdadm -S $md0
-
-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3 $dev4
-testdev $md0 2 $mdsize1 512
-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-sleep 4
-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
- exit 1
-fi
-mdadm $md0 -f $dev3
-testdev $md0 2 $mdsize1 512
-sleep 4
-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
- exit 2
-fi
-
-mdadm -S $md0
-
-mdadm --assemble -R $md0 --bitmap=$bmf $dev1 $dev2 $dev4
-mdadm --zero $dev3 # force --add, not --re-add
-mdadm $md0 --add $dev3
-check recovery
-
-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-check wait
-sleep 4
-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
- exit 1
-fi
-
-mdadm -S $md0
--
2.41.0

View File

@ -0,0 +1,31 @@
From 906922ee321d64e2ce8458147e67d4892696fb58 Mon Sep 17 00:00:00 2001
From: Valery Ushakov <valery.ushakov@bell-sw.com>
Date: Wed, 22 May 2024 17:07:38 +0300
Subject: [PATCH 075/157] Makefile: fix make -s detection
Only check the first word of MAKEFLAGS for 's', that's where all the
single letter options are collected.
MAKEFLAGS contains _all_ make flags, so if any command line argument
contains a letter 's', the silent test will be false positive. Think
e.g. make 'DESTDIR=.../aports/main/mdadm/pkg/mdadm' install
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index adac7905..446710bd 100644
--- a/Makefile
+++ b/Makefile
@@ -157,7 +157,7 @@ ifndef UDEVDIR
UDEVDIR = /lib/udev
endif
-ifeq (,$(findstring s,$(MAKEFLAGS)))
+ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS))))
ECHO=echo
else
ECHO=:
--
2.41.0

View File

@ -0,0 +1,81 @@
From 13a0e92a3ed70c52246a0f0572dee61203994327 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:38 +0800
Subject: [PATCH 076/157] Change some error messages to info level
These logs are not error logs. Change them to info level.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Assemble.c | 16 ++++++----------
Manage.c | 2 +-
util.c | 4 ++--
3 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 58dc2c5e..0e6da593 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1214,23 +1214,19 @@ static int start_array(int mdfd,
if (rv == 0) {
sysfs_rules_apply(mddev, content);
if (c->verbose >= 0) {
- pr_err("%s has been started with %d drive%s",
+ pr_info("%s has been started with %d drive%s",
mddev, okcnt, okcnt==1?"":"s");
if (okcnt < (unsigned)content->array.raid_disks)
- fprintf(stderr, " (out of %d)",
- content->array.raid_disks);
+ printf(" (out of %d)", content->array.raid_disks);
if (rebuilding_cnt)
- fprintf(stderr, "%s %d rebuilding",
- sparecnt?",":" and",
+ printf("%s %d rebuilding", sparecnt?",":" and",
rebuilding_cnt);
if (sparecnt)
- fprintf(stderr, " and %d spare%s",
- sparecnt,
+ printf(" and %d spare%s", sparecnt,
sparecnt == 1 ? "" : "s");
if (content->journal_clean)
- fprintf(stderr, " and %d journal",
- journalcnt);
- fprintf(stderr, ".\n");
+ printf(" and %d journal", journalcnt);
+ printf(".\n");
}
if (content->reshape_active &&
is_level456(content->array.level)) {
diff --git a/Manage.c b/Manage.c
index 96e5ee54..5db72b77 100644
--- a/Manage.c
+++ b/Manage.c
@@ -463,7 +463,7 @@ done:
}
if (verbose >= 0)
- pr_err("stopped %s\n", devname);
+ pr_info("stopped %s\n", devname);
map_lock(&map);
map_remove(&map, devnm);
map_unlock(&map);
diff --git a/util.c b/util.c
index bf79742f..48c97545 100644
--- a/util.c
+++ b/util.c
@@ -633,9 +633,9 @@ int check_ext2(int fd, char *name)
bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8;
size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8;
size <<= bsize;
- pr_err("%s appears to contain an ext2fs file system\n",
+ pr_info("%s appears to contain an ext2fs file system\n",
name);
- cont_err("size=%lluK mtime=%s", size, ctime(&mtime));
+ pr_info("size=%lluK mtime=%s", size, ctime(&mtime));
return 1;
}
--
2.41.0

View File

@ -0,0 +1,40 @@
From 296398299391b10650bdd79d986b115588e60590 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:39 +0800
Subject: [PATCH 077/157] mdadm: Start update_opt from 0
Before f2e8393bd722 ('Manage&Incremental: code refactor, string to enum'), it uses
NULL to represent it doesn't need to update. So init UOPT_UNDEFINED to 0. This
problem is found by test case 05r6tor0.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mdadm.h b/mdadm.h
index b71d7b32..40818941 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -535,7 +535,8 @@ enum special_options {
};
enum update_opt {
- UOPT_NAME = 1,
+ UOPT_UNDEFINED = 0,
+ UOPT_NAME,
UOPT_PPL,
UOPT_NO_PPL,
UOPT_BITMAP,
@@ -575,7 +576,6 @@ enum update_opt {
UOPT_SPEC_FAILFAST,
UOPT_SPEC_NOFAILFAST,
UOPT_SPEC_REVERT_RESHAPE_NOBACKUP,
- UOPT_UNDEFINED
};
extern void fprint_update_options(FILE *outf, enum update_opt update_mode);
--
2.41.0

View File

@ -0,0 +1,49 @@
From f79f7189aa25b9da51736f2c578a51c2c4fe7706 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:40 +0800
Subject: [PATCH 078/157] Don't control reshape speed in daemon
It tries to set the max sync speed in reshape. This should be done by
administrators by control interfaces /proc/sys/dev/raid/speed_limit_max/min.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
Grow.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/Grow.c b/Grow.c
index 963792d0..b135930d 100644
--- a/Grow.c
+++ b/Grow.c
@@ -4488,7 +4488,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
*/
char *buf;
int degraded = -1;
- unsigned long long speed;
unsigned long long suspend_point, array_size;
unsigned long long backup_point, wait_point;
unsigned long long reshape_completed;
@@ -4544,10 +4543,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
if (posix_memalign((void**)&buf, 4096, disks * chunk))
/* Don't start the 'reshape' */
return 0;
- if (reshape->before.data_disks == reshape->after.data_disks) {
- sysfs_get_ll(sra, NULL, "sync_speed_min", &speed);
- sysfs_set_num(sra, NULL, "sync_speed_min", 200000);
- }
if (increasing) {
array_size = sra->component_size * reshape->after.data_disks;
@@ -4680,8 +4675,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
sysfs_set_num(sra, NULL, "suspend_lo", 0);
sysfs_set_num(sra, NULL, "sync_min", 0);
- if (reshape->before.data_disks == reshape->after.data_disks)
- sysfs_set_num(sra, NULL, "sync_speed_min", speed);
free(buf);
return done;
}
--
2.41.0

View File

@ -0,0 +1,119 @@
From 6e8af9475cf0ac22f7ac167040dbf92fbfdd97ab Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:41 +0800
Subject: [PATCH 079/157] mdadm/tests: test enhance
There are two changes.
First, if md module is not loaded, it gives error when reading
speed_limit_max. So read the value after loading md module which
is done in do_setup
Second, sometimes the test reports error sync action doesn't
happen. But dmesg shows sync action is done. So limit the sync
speed before test. It doesn't affect the test run time. Because
check wait sets the max speed before waiting sync action. And
recording speed_limit_max/min in do_setup.
Fixes: 4c12714d1ca0 ('test: run tests on system level mdadm')
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 10 +++++-----
tests/func.sh | 26 +++++++++++++++++++++++---
2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/test b/test
index 338c2db4..ff403293 100755
--- a/test
+++ b/test
@@ -6,7 +6,10 @@ targetdir="/var/tmp"
logdir="$targetdir"
config=/tmp/mdadm.conf
testdir=$PWD/tests
-system_speed_limit=`cat /proc/sys/dev/raid/speed_limit_max`
+system_speed_limit_max=0
+system_speed_limit_min=0
+test_speed_limit_min=100
+test_speed_limit_max=500
devlist=
savelogs=0
@@ -39,10 +42,6 @@ ctrl_c() {
ctrl_c_error=1
}
-restore_system_speed_limit() {
- echo $system_speed_limit > /proc/sys/dev/raid/speed_limit_max
-}
-
mdadm() {
rm -f $targetdir/stderr
case $* in
@@ -103,6 +102,7 @@ do_test() {
do_clean
# source script in a subshell, so it has access to our
# namespace, but cannot change it.
+ control_system_speed_limit
echo -ne "$_script... "
if ( set -ex ; . $_script ) &> $targetdir/log
then
diff --git a/tests/func.sh b/tests/func.sh
index b474442b..221cff15 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -136,6 +136,23 @@ check_env() {
fi
}
+record_system_speed_limit() {
+ system_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max`
+ system_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min`
+}
+
+# To avoid sync action finishes before checking it, it needs to limit
+# the sync speed
+control_system_speed_limit() {
+ echo $test_speed_limit_min > /proc/sys/dev/raid/speed_limit_min
+ echo $test_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
+}
+
+restore_system_speed_limit() {
+ echo $system_speed_limit_min > /proc/sys/dev/raid/speed_limit_max
+ echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
+}
+
do_setup() {
trap cleanup 0 1 3 15
trap ctrl_c 2
@@ -214,6 +231,7 @@ do_setup() {
ulimit -c unlimited
[ -f /proc/mdstat ] || modprobe md_mod
echo 0 > /sys/module/md_mod/parameters/start_ro
+ record_system_speed_limit
}
# check various things
@@ -265,15 +283,17 @@ check() {
fi
;;
wait )
- p=`cat /proc/sys/dev/raid/speed_limit_max`
- echo 2000000 > /proc/sys/dev/raid/speed_limit_max
+ min=`cat /proc/sys/dev/raid/speed_limit_min`
+ max=`cat /proc/sys/dev/raid/speed_limit_max`
+ echo 200000 > /proc/sys/dev/raid/speed_limit_max
sleep 0.1
while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat ||
grep -v idle > /dev/null /sys/block/md*/md/sync_action
do
sleep 0.5
done
- echo $p > /proc/sys/dev/raid/speed_limit_max
+ echo $min > /proc/sys/dev/raid/speed_limit_min
+ echo $max > /proc/sys/dev/raid/speed_limit_max
;;
state )
grep -sq "blocks.*\[$2\]\$" /proc/mdstat ||
--
2.41.0

View File

@ -0,0 +1,31 @@
From 73ba062ef93d0a57360a2d5200bc7a8f8781e7b6 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:42 +0800
Subject: [PATCH 080/157] mdadm/tests: test don't fail when systemd reports
error
Sometimes systemd reports error in dmesg and test fails. Add
a condition to avoid this failure.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test b/test
index ff403293..3da53f87 100755
--- a/test
+++ b/test
@@ -109,7 +109,7 @@ do_test() {
if [ -f "${_script}.inject_error" ]; then
echo "dmesg checking is skipped because test inject error"
else
- dmesg | grep -iq "error\|call trace\|segfault" &&
+ dmesg | grep -iq "error\|call trace\|segfault" | grep -v "systemd" &&
die "dmesg prints errors when testing $_basename!"
fi
echo "succeeded"
--
2.41.0

View File

@ -0,0 +1,109 @@
From 41706a91568472d10153bf4ada3c3f0d93ef327a Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:43 +0800
Subject: [PATCH 081/157] mdadm/tests: names_template enhance
For super1, if the length of hostname is >= 32, it doesn't add hostname
in metadata name. Fix this problem by checking the length of hostname.
Because other cases may use need to check this, so do the check in
do_setup.
And this patch adds a check if link /dev/md/name exists.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 5 +++++
tests/func.sh | 13 +++++++++++++
tests/templates/names_template | 14 ++++++++++++--
3 files changed, 30 insertions(+), 2 deletions(-)
diff --git a/test b/test
index 3da53f87..814ce199 100755
--- a/test
+++ b/test
@@ -11,6 +11,11 @@ system_speed_limit_min=0
test_speed_limit_min=100
test_speed_limit_max=500
devlist=
+# If super1 metadata name doesn't have the same hostname with machine,
+# it's treated as foreign.
+# For example, /dev/md0 is created, stops it, then assemble it, the
+# device node will be /dev/md127 (127 is choosed by mdadm autumatically)
+is_foreign="no"
savelogs=0
exitonerror=1
diff --git a/tests/func.sh b/tests/func.sh
index 221cff15..cfe83e55 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -153,6 +153,18 @@ restore_system_speed_limit() {
echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max
}
+is_raid_foreign() {
+
+ # If the length of hostname is >= 32, super1 doesn't use
+ # hostname in metadata
+ hostname=$(hostname)
+ if [ `expr length $(hostname)` -lt 32 ]; then
+ is_foreign="no"
+ else
+ is_foreign="yes"
+ fi
+}
+
do_setup() {
trap cleanup 0 1 3 15
trap ctrl_c 2
@@ -232,6 +244,7 @@ do_setup() {
[ -f /proc/mdstat ] || modprobe md_mod
echo 0 > /sys/module/md_mod/parameters/start_ro
record_system_speed_limit
+ is_raid_foreign
}
# check various things
diff --git a/tests/templates/names_template b/tests/templates/names_template
index 1b6cd14b..88ad5b8c 100644
--- a/tests/templates/names_template
+++ b/tests/templates/names_template
@@ -30,6 +30,7 @@ function names_verify() {
local DEVNODE_NAME="$1"
local WANTED_LINK="$2"
local WANTED_NAME="$3"
+ local EXPECTED=""
local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
if [[ "$?" != "0" ]]; then
@@ -38,7 +39,12 @@ function names_verify() {
fi
if [[ "$WANTED_LINK" != "empty" ]]; then
- local EXPECTED="MD_DEVNAME=$WANTED_LINK"
+ EXPECTED="MD_DEVNAME=$WANTED_LINK"
+
+ if [ ! -b /dev/md/$WANTED_LINK ]; then
+ echo "/dev/md/$WANTED_LINK doesn't exit"
+ exit 1
+ fi
fi
if [[ "$RES" != "$EXPECTED" ]]; then
@@ -52,7 +58,11 @@ function names_verify() {
exit 1
fi
- local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
+ if [ $is_foreign == "no" ]; then
+ EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
+ else
+ EXPECTED="MD_NAME=$WANTED_NAME"
+ fi
if [[ "$RES" != "$EXPECTED" ]]; then
echo "$RES doesn't match $EXPECTED."
exit 1
--
2.41.0

View File

@ -0,0 +1,67 @@
From 23f45965a0abe3506885c8e8005ee79473a66422 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:44 +0800
Subject: [PATCH 082/157] mdadm/tests: 03assem-incr enhance
It fails when hostname lenght > 32. Because the super1 metadata name
doesn't include hostname when hostname length > 32. Then mdadm thinks
the array is a foreign array if no device link is specified when
assembling the array. It chooses a minor number from 127.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 3 +++
tests/03assem-incr | 20 +++++++++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/test b/test
index 814ce199..1fce6be2 100755
--- a/test
+++ b/test
@@ -33,6 +33,9 @@ LVM_VOLGROUP=mdtest
md0=/dev/md0
md1=/dev/md1
md2=/dev/md2
+# if user doesn't specify minor number, mdadm chooses minor number
+# automatically from 127.
+md127=/dev/md127
mdp0=/dev/md_d0
mdp1=/dev/md_d1
diff --git a/tests/03assem-incr b/tests/03assem-incr
index 38880a7f..21215a34 100644
--- a/tests/03assem-incr
+++ b/tests/03assem-incr
@@ -9,15 +9,21 @@ set -x -e
levels=(raid0 raid1 raid5)
if [ "$LINEAR" == "yes" ]; then
- levels+=( linear )
+ levels+=( linear )
fi
for l in ${levels[@]}
do
- mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean
- mdadm -S md0
- mdadm -I $dev1
- mdadm -I $dev3
- mdadm -A /dev/md0 $dev0 $dev1 $dev2 $dev3 $dev4
- mdadm -S /dev/md0
+ mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean
+ mdadm -S $md0
+ mdadm -I $dev1
+ mdadm -I $dev3
+ mdadm -A $md0 $dev0 $dev1 $dev2 $dev3 $dev4
+ # If one array is foreign (metadata name doesn't have the machine's
+ # hostname), mdadm chooses a minor number automatically from 127
+ if [ $is_foreign == "no" ]; then
+ mdadm -S $md0
+ else
+ mdadm -S $md127
+ fi
done
--
2.41.0

View File

@ -0,0 +1,38 @@
From f136d9a8b7d8fdfd7539b96707bc9a03528754aa Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:45 +0800
Subject: [PATCH 083/157] mdadm/tests 03r0assem enhance
dcc22ae74a864 ('super1: remove support for name= in config') already
removes name= support. So remove related test codes in 03r0assem.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/03r0assem | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/tests/03r0assem b/tests/03r0assem
index f7c29e8c..4bf8b9e8 100644
--- a/tests/03r0assem
+++ b/tests/03r0assem
@@ -33,16 +33,6 @@ mdadm -As -c $conf $md2
$tst
mdadm -S $md2
-{
- echo DEVICE $devlist
- echo array $md2 name=2
-} > $conf
-
-mdadm -As -c $conf $md2
-$tst
-mdadm -S $md2
-
-
{
echo DEVICE $devlist
echo array $md2 devices=$dev0,$dev1,$dev2
--
2.41.0

View File

@ -0,0 +1,35 @@
From 5c1133ba8d026d65362953f25178fbf974b78ce9 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:46 +0800
Subject: [PATCH 084/157] mdadm/tests: remove 03r5assem-failed
03r5assem can run successfully with kernel 6.9.0-rc4
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/03r5assem-failed | 12 ------------
1 file changed, 12 deletions(-)
delete mode 100644 tests/03r5assem-failed
diff --git a/tests/03r5assem-failed b/tests/03r5assem-failed
deleted file mode 100644
index d38241df..00000000
--- a/tests/03r5assem-failed
+++ /dev/null
@@ -1,12 +0,0 @@
-
-# Create an array, fail one device while array is active, stop array,
-# then re-assemble listing the failed device first.
-
-mdadm -CR $md1 -l5 -n4 $dev0 $dev1 $dev2 $dev3
-check wait
-
-echo 2000 > /sys/block/md1/md/safe_mode_delay
-mkfs $md1
-mdadm $md1 -f $dev0
-mdadm -S $md1
-mdadm -A $md1 $dev0 $dev1 $dev2 $dev3 || exit 1
--
2.41.0

View File

@ -0,0 +1,52 @@
From 6077e9248acda8c70df58fabc8de23195c19a0cf Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:47 +0800
Subject: [PATCH 085/157] mdadm/tests: 03r5assemV1
dcc22ae74a864 ('super1: remove support for name= in config') already
removes name= support. So remove related test codes in 03r5assemV1.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/03r5assemV1 | 17 -----------------
1 file changed, 17 deletions(-)
diff --git a/tests/03r5assemV1 b/tests/03r5assemV1
index bca0c583..6026011e 100644
--- a/tests/03r5assemV1
+++ b/tests/03r5assemV1
@@ -31,14 +31,6 @@ conf=$targetdir/mdadm.conf
mdadm -As -c $conf $md1
eval $tst
-{
- echo DEVICE $devlist
- echo array $md1 name=one
-} > $conf
-
-mdadm -As -c $conf
-eval $tst
-
{
echo DEVICE $devlist
echo array $md1 devices=$dev0,$dev1,$dev2,$dev3,$dev4
@@ -88,15 +80,6 @@ mdadm -As -c $conf $md1
check state U_U
eval $tst
-{
- echo DEVICE $devlist
- echo array $md1 name=one
-} > $conf
-
-mdadm -As -c $conf
-check state U_U
-eval $tst
-
{
echo DEVICE $devlist
echo array $md1 devices=$dev0,$dev1,$dev2
--
2.41.0

View File

@ -0,0 +1,30 @@
From b9b8eaef49e075ce68846abb7cf0ca47c1ba9f2f Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:48 +0800
Subject: [PATCH 086/157] mdadm/tests: remove 04r5swap.broken
04r5swap can run successfully with kernel 6.9.0-rc4
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/04r5swap.broken | 7 -------
1 file changed, 7 deletions(-)
delete mode 100644 tests/04r5swap.broken
diff --git a/tests/04r5swap.broken b/tests/04r5swap.broken
deleted file mode 100644
index e38987db..00000000
--- a/tests/04r5swap.broken
+++ /dev/null
@@ -1,7 +0,0 @@
-always fails
-
-Fails with errors:
-
- mdadm: /dev/loop0 has no superblock - assembly aborted
-
- ERROR: no recovery happening
--
2.41.0

View File

@ -0,0 +1,116 @@
From 9808f110c5aea5454e9f56b2b660612a57adb347 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:49 +0800
Subject: [PATCH 087/157] tests/04update-metadata skip linear
Add one check that if kernel doesn't support linear/multipath, it can
skip linear/multipath testing.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 3 +++
tests/04update-metadata | 35 ++++++++++++++++++++---------------
tests/func.sh | 2 ++
3 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/test b/test
index 1fce6be2..f09994e7 100755
--- a/test
+++ b/test
@@ -17,6 +17,9 @@ devlist=
# device node will be /dev/md127 (127 is choosed by mdadm autumatically)
is_foreign="no"
+skipping_linear="no"
+skipping_multipath="no"
+
savelogs=0
exitonerror=1
ctrl_c_error=0
diff --git a/tests/04update-metadata b/tests/04update-metadata
index 2b72a303..c748770c 100644
--- a/tests/04update-metadata
+++ b/tests/04update-metadata
@@ -8,24 +8,29 @@ set -xe
dlist="$dev0 $dev1 $dev2 $dev3"
-for ls in linear/4 raid1/1 raid5/3 raid6/2
+if [ $skipping_linear == "yes" ]; then
+ level_list="raid1/1 raid5/3 raid6/2"
+else
+ level_list="linear/4 raid1/1 raid5/3 raid6/2"
+fi
+for ls in $level_list
do
- s=${ls#*/} l=${ls%/*}
- if [[ $l == 'raid1' ]]; then
- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist
- else
- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist
- fi
- testdev $md0 $s 19904 64
- mdadm -S $md0
- mdadm -A $md0 --update=metadata $dlist
- testdev $md0 $s 19904 64 check
- mdadm -S $md0
+ s=${ls#*/} l=${ls%/*}
+ if [[ $l == 'raid1' ]]; then
+ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist
+ else
+ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist
+ fi
+ testdev $md0 $s 19904 64
+ mdadm -S $md0
+ mdadm -A $md0 --update=metadata $dlist
+ testdev $md0 $s 19904 64 check
+ mdadm -S $md0
done
if mdadm -A $md0 --update=metadata $dlist
then echo >&2 should fail with v1.0 metadata
- exit 1
+ exit 1
fi
mdadm -CR -e 0.90 $md0 --level=6 -n4 -c32 $dlist
@@ -33,7 +38,7 @@ mdadm -S $md0
if mdadm -A $md0 --update=metadata $dlist
then echo >&2 should fail during resync
- exit 1
+ exit 1
fi
mdadm -A $md0 $dlist
mdadm --wait $md0 || true
@@ -48,5 +53,5 @@ mdadm -S $md0
if mdadm -A $md0 --update=metadata $dlist
then echo >&2 should fail when bitmap present
- exit 1
+ exit 1
fi
diff --git a/tests/func.sh b/tests/func.sh
index cfe83e55..db55542d 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -125,6 +125,7 @@ check_env() {
MULTIPATH="yes"
if [ "$MULTIPATH" != "yes" ]; then
echo "test: skipping tests for multipath, which is removed in upstream 6.8+ kernels"
+ skipping_multipath="yes"
fi
# Check whether to run linear tests
@@ -133,6 +134,7 @@ check_env() {
LINEAR="yes"
if [ "$LINEAR" != "yes" ]; then
echo "test: skipping tests for linear, which is removed in upstream 6.8+ kernels"
+ skipping_linear="yes"
fi
}
--
2.41.0

View File

@ -0,0 +1,68 @@
From 7664a3851476cfcda931d35f495d03f51707bac9 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:50 +0800
Subject: [PATCH 088/157] mdadm/tests: 05r5-internalbitmap
It's not right to compare bitmap bits with a number after io comes.
Because maybe those bits are already flused. Remove the related
tests.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/05r5-internalbitmap | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/tests/05r5-internalbitmap b/tests/05r5-internalbitmap
index 13dc5921..1a64482f 100644
--- a/tests/05r5-internalbitmap
+++ b/tests/05r5-internalbitmap
@@ -9,21 +9,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2 $dev3
testdev $md0 2 $mdsize1 512
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 2 $mdsize1 512
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -lt 400 ]
then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+ echo >&2 "ERROR dirty count $dirty2 is too small"
exit 2
fi
@@ -33,14 +32,12 @@ mdadm --assemble -R $md0 $dev2 $dev3
mdadm --zero $dev1 # force --add, not --re-add
mdadm $md0 --add $dev1
check recovery
-
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty3"
exit 1
fi
--
2.41.0

View File

@ -0,0 +1,38 @@
From 6e7d850a57d40e18d525d0739a4f4226f6057d91 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:52 +0800
Subject: [PATCH 089/157] mdadm/tests: 06name enhance
It needs to check hostname in metadata name if one array is
local. Add the check in this case.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/06name | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/tests/06name b/tests/06name
index 86eaab69..c3213f6c 100644
--- a/tests/06name
+++ b/tests/06name
@@ -3,8 +3,14 @@ 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
+
+if [ $is_foreign == "no" ]; then
+ mdadm -E $dev0 | grep "Name : $(hostname):Fred" > /dev/null || exit 1
+ mdadm -D $md0 | grep "Name : $(hostname):Fred" > /dev/null || exit 1
+else
+ mdadm -E $dev0 | grep "Name : Fred" > /dev/null || exit 1
+ mdadm -D $md0 | grep "Name : Fred" > /dev/null || exit 1
+fi
mdadm -S $md0
mdadm -A $md0 --name="Fred" $devlist
--
2.41.0

View File

@ -0,0 +1,108 @@
From 63e99a49cc02cbe4d1777b477719078897fc8308 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:53 +0800
Subject: [PATCH 090/157] mdadm/tests: 07autoassemble
This test is used to test stacked array auto assemble.
There are two different cases depends on if array is foreign or not.
If the array is foreign, the stacked array (md0 is on md1 and md2)
can't be assembled with name md0. Because udev rule will run when md1
and md2 are assembled and mdadm -I doesn't specify homehost. So it
will treat stacked array (md0) as foreign array and choose md127 as
the device node name (/dev/md127)
Add the case that stacked array is local.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 2 ++
tests/07autoassemble | 37 +++++++++++++++++++++++++++++++++++--
tests/07autoassemble.broken | 8 --------
3 files changed, 37 insertions(+), 10 deletions(-)
delete mode 100644 tests/07autoassemble.broken
diff --git a/test b/test
index f09994e7..4a88de58 100755
--- a/test
+++ b/test
@@ -39,6 +39,8 @@ md2=/dev/md2
# if user doesn't specify minor number, mdadm chooses minor number
# automatically from 127.
md127=/dev/md127
+md126=/dev/md126
+md125=/dev/md125
mdp0=/dev/md_d0
mdp1=/dev/md_d1
diff --git a/tests/07autoassemble b/tests/07autoassemble
index e689be7c..9dc78149 100644
--- a/tests/07autoassemble
+++ b/tests/07autoassemble
@@ -10,7 +10,14 @@ mdadm -Ss
mdadm -As -c /dev/null --homehost=testing -vvv
testdev $md1 1 $mdsize1a 64
testdev $md2 1 $mdsize1a 64
-testdev $md0 2 $mdsize11a 512
+# md1 and md2 will be incremental assemble by udev rule. And
+# the testing machines' hostname is not testing. The md0 will
+# be considered as a foreign array. It can use 0 as metadata
+# name. md127 will be used
+testdev $md127 2 $mdsize11a 512
+mdadm --stop $md127
+mdadm --zero-superblock $md1
+mdadm --zero-superblock $md2
mdadm -Ss
mdadm --zero-superblock $dev0 $dev1 $dev2 $dev3
@@ -20,5 +27,31 @@ mdadm -CR $md0 -l0 -n2 $md1 $dev2 --homehost=testing
mdadm -Ss
mdadm -As -c /dev/null --homehost=testing -vvv
testdev $md1 1 $mdsize1a 64
-testdev $md0 1 $[mdsize1a+mdsize11a] 512
+testdev $md127 1 $[mdsize1a+mdsize11a] 512
+mdadm --stop $md127
+mdadm --zero-superblock $md1
+mdadm -Ss
+
+# Don't specify homehost when creating raid and use the test
+# machine's homehost. For super1.2, if homehost name's length
+# is > 32, it doesn't use homehost name in metadata name and
+# the array will be treated as foreign array
+mdadm --zero-superblock $dev0 $dev1 $dev2 $dev3
+mdadm -CR $md1 -l1 -n2 $dev0 $dev1
+mdadm -CR $md2 -l1 -n2 $dev2 $dev3
+mdadm -CR $md0 -l0 -n2 $md1 $md2
+mdadm -Ss
+mdadm -As -c /dev/null
+if [ $is_foreign == "yes" ]; then
+ # md127 is md1
+ testdev $md127 1 $mdsize1a 64
+ # md126 is md0, udev rule incremental assemble it
+ testdev $md126 2 $mdsize11a 512
+ # md125 is md2
+ testdev $md125 1 $mdsize1a 64
+else
+ testdev $md1 1 $mdsize1a 64
+ testdev $md2 1 $mdsize1a 64
+ testdev $md0 2 $mdsize11a 512
+fi
mdadm -Ss
diff --git a/tests/07autoassemble.broken b/tests/07autoassemble.broken
deleted file mode 100644
index 8be09407..00000000
--- a/tests/07autoassemble.broken
+++ /dev/null
@@ -1,8 +0,0 @@
-always fails
-
-Prints lots of messages, but the array doesn't assemble. Error
-possibly related to:
-
- mdadm: /dev/md/1 is busy - skipping
- mdadm: no recogniseable superblock on /dev/md/testing:0
- mdadm: /dev/md/2 is busy - skipping
--
2.41.0

View File

@ -0,0 +1,28 @@
From 1d0c61f4baa49bc218687017ccb2e3a664351390 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:54 +0800
Subject: [PATCH 091/157] mdadm/tests: 07autodetect.broken can be removed
07autodetect can run successfully without error in kernel 6.9.0-rc5.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/07autodetect.broken | 5 -----
1 file changed, 5 deletions(-)
delete mode 100644 tests/07autodetect.broken
diff --git a/tests/07autodetect.broken b/tests/07autodetect.broken
deleted file mode 100644
index 294954a1..00000000
--- a/tests/07autodetect.broken
+++ /dev/null
@@ -1,5 +0,0 @@
-always fails
-
-Fails with error:
-
- ERROR: no resync happening
--
2.41.0

View File

@ -0,0 +1,73 @@
From cd3b2350bef136b20c81190371fb0b60d62a0365 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:55 +0800
Subject: [PATCH 092/157] mdadm/tests: 07changelevelintr
It needs to specify a 2 powered array size when updating array size.
If not, it can't change chunksize.
And sometimes it reports error reshape doesn't happen. In fact the
reshape has finished. It doesn't need to wait before checking
reshape action. Because check function waits itself.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/07changelevelintr | 9 +++++----
tests/07changelevelintr.broken | 9 ---------
2 files changed, 5 insertions(+), 13 deletions(-)
delete mode 100644 tests/07changelevelintr.broken
diff --git a/tests/07changelevelintr b/tests/07changelevelintr
index 18c63092..d921f2b2 100644
--- a/tests/07changelevelintr
+++ b/tests/07changelevelintr
@@ -27,11 +27,9 @@ checkgeo() {
}
restart() {
- sleep 0.5
check reshape
mdadm -S $md0
mdadm -A $md0 $devs --backup-file=$bu
- sleep 0.5
check reshape
}
@@ -49,13 +47,16 @@ mdadm -G $md0 --layout rs --backup-file=$bu
restart
checkgeo md0 raid5 5 $[128*1024] 3
-mdadm -G $md0 --array-size 58368
+# It needs to shrink array size first. Choose a value that
+# is power of 2 for array size. If not, it can't change
+# chunk size.
+mdadm -G $md0 --array-size 51200
mdadm -G $md0 --raid-disks 4 -c 64 --backup-file=$bu
restart
checkgeo md0 raid5 4 $[64*1024] 3
devs="$dev0 $dev1 $dev2 $dev3"
-mdadm -G $md0 --array-size 19456
+mdadm -G $md0 --array-size 18432
mdadm -G $md0 -n 2 -c 256 --backup-file=$bu
restart
checkgeo md0 raid5 2 $[256*1024] 3
diff --git a/tests/07changelevelintr.broken b/tests/07changelevelintr.broken
deleted file mode 100644
index 284b4906..00000000
--- a/tests/07changelevelintr.broken
+++ /dev/null
@@ -1,9 +0,0 @@
-always fails
-
-Fails with errors:
-
- mdadm: this change will reduce the size of the array.
- use --grow --array-size first to truncate array.
- e.g. mdadm --grow /dev/md0 --array-size 56832
-
- ERROR: no reshape happening
--
2.41.0

View File

@ -0,0 +1,68 @@
From b914aa25ee1fe3e0bd97f58bdf2bfdd185992a79 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 22 May 2024 16:50:56 +0800
Subject: [PATCH 093/157] mdadm/tests: disable selinux
Sometimes systemd service fails because selinux. Disable selinux
during testing now. We can enable it in future when having a better
method.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
test | 3 +++
tests/func.sh | 10 ++++++++++
2 files changed, 13 insertions(+)
diff --git a/test b/test
index 4a88de58..47f53ad7 100755
--- a/test
+++ b/test
@@ -16,6 +16,8 @@ devlist=
# For example, /dev/md0 is created, stops it, then assemble it, the
# device node will be /dev/md127 (127 is choosed by mdadm autumatically)
is_foreign="no"
+#disable selinux
+sys_selinux="Permissive"
skipping_linear="no"
skipping_multipath="no"
@@ -351,6 +353,7 @@ main() {
fi
done
+ restore_selinux
exit 0
}
diff --git a/tests/func.sh b/tests/func.sh
index db55542d..b2e4d122 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -167,6 +167,15 @@ is_raid_foreign() {
fi
}
+record_selinux() {
+ sys_selinux=`getenforce`
+ setenforce Permissive
+}
+
+restore_selinux() {
+ setenforce $sys_selinux
+}
+
do_setup() {
trap cleanup 0 1 3 15
trap ctrl_c 2
@@ -247,6 +256,7 @@ do_setup() {
echo 0 > /sys/module/md_mod/parameters/start_ro
record_system_speed_limit
is_raid_foreign
+ record_selinux
}
# check various things
--
2.41.0

View File

@ -0,0 +1,44 @@
From 827e1870f320545796d907f50af594e901399417 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Tue, 28 May 2024 16:44:39 +0800
Subject: [PATCH 094/157] mdadm/platform-intel: buffer overflow detected
mdadm -CR /dev/md0 -l1 -n2 /dev/nvme0n1 /dev/nvme2n1
*** buffer overflow detected ***: terminated
Aborted (core dumped)
It doesn't happen 100% and it depends on the building environment.
It can be fixed by replacing sprintf with snprintf.
Fixes: d835518b6b53 ('imsm: nvme multipath support')
Reported-by: Guang Wu <guazhang@redhat.com>
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
platform-intel.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/platform-intel.c b/platform-intel.c
index 15a9fa5a..d6a53533 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -907,14 +907,14 @@ char *get_nvme_multipath_dev_hw_path(const char *dev_path)
return NULL;
for (ent = readdir(dir); ent; ent = readdir(dir)) {
- char buf[strlen(dev_path) + strlen(ent->d_name) + 1];
+ char buf[PATH_MAX];
/* Check if dir is a controller, ignore namespaces*/
if (!(strncmp(ent->d_name, "nvme", 4) == 0) ||
(strrchr(ent->d_name, 'n') != &ent->d_name[0]))
continue;
- sprintf(buf, "%s/%s", dev_path, ent->d_name);
+ snprintf(buf, PATH_MAX, "%s/%s", dev_path, ent->d_name);
rp = realpath(buf, NULL);
break;
}
--
2.41.0

View File

@ -0,0 +1,279 @@
From c006602b313e2f6062b51aad37d93dccd29649de Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Tue, 28 May 2024 21:51:47 +0800
Subject: [PATCH 095/157] mdadm/tests: bitmap cases enhance
It fails because bitmap dirty number is smaller than 400 sometimes. It's not
good to compare bitmap dirty bits with a number. It depends on the test
machine, it can flush soon before checking the number. So remove related codes.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/05r1-grow-internal | 11 ++++-------
tests/05r1-grow-internal-1 | 12 ++++--------
tests/05r1-internalbitmap | 22 ++++++++++------------
tests/05r1-internalbitmap-v1a | 22 ++++++++++------------
tests/05r1-internalbitmap-v1b | 23 ++++++++++-------------
tests/05r1-internalbitmap-v1c | 22 ++++++++++------------
6 files changed, 48 insertions(+), 64 deletions(-)
diff --git a/tests/05r1-grow-internal b/tests/05r1-grow-internal
index 24b3aece..f7fff989 100644
--- a/tests/05r1-grow-internal
+++ b/tests/05r1-grow-internal
@@ -8,18 +8,15 @@ testdev $md0 1 $mdsize1a 64
#mdadm -E $dev1
mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1 || { mdadm -X $dev2 ; exit 1; }
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
testdev $md0 1 $mdsize1a 64
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-#echo $dirty1 $dirty2 $dirty3 $dirty4
-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ]
-then
+if [ $dirty1 -ne 0 -o $dirty2 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: dirty1 $dirty1, dirty2 $dirty2"
echo bad dirty counts
exit 1
fi
diff --git a/tests/05r1-grow-internal-1 b/tests/05r1-grow-internal-1
index 2f0d8237..f0f8349f 100644
--- a/tests/05r1-grow-internal-1
+++ b/tests/05r1-grow-internal-1
@@ -8,19 +8,15 @@ testdev $md0 1 $mdsize1b 64
#mdadm -E $dev1
mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
testdev $md0 1 $mdsize1b 64
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-#echo $dirty1 $dirty2 $dirty3 $dirty4
-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ]
-then
- echo bad dirty counts
+if [ $dirty1 -ne 0 -o $dirty2 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: dirty1 $dirty1, dirty2 $dirty2"
exit 1
fi
diff --git a/tests/05r1-internalbitmap b/tests/05r1-internalbitmap
index dd7232a7..f1a2843e 100644
--- a/tests/05r1-internalbitmap
+++ b/tests/05r1-internalbitmap
@@ -9,21 +9,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
testdev $md0 1 $mdsize0 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize0 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -34,13 +33,12 @@ mdadm --zero-superblock $dev1
mdadm $md0 --add $dev1
check recovery
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-internalbitmap-v1a b/tests/05r1-internalbitmap-v1a
index 3ddc082f..cf3f3972 100644
--- a/tests/05r1-internalbitmap-v1a
+++ b/tests/05r1-internalbitmap-v1a
@@ -10,21 +10,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
testdev $md0 1 $mdsize1b 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize1b 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -35,13 +34,12 @@ mdadm --assemble -R $md0 $dev2
mdadm $md0 --add $dev1
check recovery
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-internalbitmap-v1b b/tests/05r1-internalbitmap-v1b
index 40f7abea..4952887e 100644
--- a/tests/05r1-internalbitmap-v1b
+++ b/tests/05r1-internalbitmap-v1b
@@ -11,21 +11,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
check bitmap
testdev $md0 1 $mdsize11 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize11 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -35,14 +34,12 @@ mdadm --zero-superblock $dev1
mdadm --assemble -R $md0 $dev2
mdadm $md0 --add $dev1
check recovery
-
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
diff --git a/tests/05r1-internalbitmap-v1c b/tests/05r1-internalbitmap-v1c
index 2eaea59b..e1e4472f 100644
--- a/tests/05r1-internalbitmap-v1c
+++ b/tests/05r1-internalbitmap-v1c
@@ -10,21 +10,20 @@ mdadm -S $md0
mdadm --assemble $md0 $dev1 $dev2
testdev $md0 1 $mdsize12 64
-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
sleep 4
-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ]
-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2"
+if [ $dirty1 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty1"
exit 1
fi
mdadm $md0 -f $dev1
testdev $md0 1 $mdsize12 64
sleep 4
-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty3 -lt 400 ]
-then
- echo >&2 "ERROR dirty count $dirty3 is too small"
+total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'`
+dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+if [ $dirty2 -ne $total ]
+then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2"
exit 2
fi
@@ -35,13 +34,12 @@ mdadm --assemble -R $md0 $dev2
mdadm $md0 --add $dev1
check recovery
-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
check wait
sleep 4
-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
+dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'`
-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ]
-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5"
+if [ $dirty3 -ne 0 ]
+then echo >&2 "ERROR bad 'dirty' counts: $dirty3"
exit 1
fi
--
2.41.0

View File

@ -0,0 +1,39 @@
From 19cde79fda386329f69ead15ca6ae26527fab707 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Tue, 28 May 2024 21:51:48 +0800
Subject: [PATCH 096/157] mdadm/tests: 04update-uuid
Patch 50b100768a11('mdadm: deprecate bitmap custom file') needs to confirm when
creating raid device with bitmap file.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/04update-uuid | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/04update-uuid b/tests/04update-uuid
index a4409e78..25314ab5 100644
--- a/tests/04update-uuid
+++ b/tests/04update-uuid
@@ -25,7 +25,7 @@ mdadm -S /dev/md0
# now if we have a bitmap, that needs updating too.
rm -f $targetdir/bitmap
-mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
+yes | mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
mdadm -S /dev/md0
mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2
no_errors
@@ -41,7 +41,7 @@ mdadm -S /dev/md0
# and bitmap for version1
rm -f $targetdir/bitmap
-mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
+yes | mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2
mdadm -S /dev/md0
mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2
no_errors
--
2.41.0

View File

@ -0,0 +1,30 @@
From c36477fac2e485fd294e5cb48d411b548c654f30 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Tue, 28 May 2024 21:51:49 +0800
Subject: [PATCH 097/157] mdadm/tests: 05r1-re-add-nosuper
Patch 50b100768a11('mdadm: deprecate bitmap custom file') needs to confirm when
creating raid device with bitmap file.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/05r1-re-add-nosuper | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/05r1-re-add-nosuper b/tests/05r1-re-add-nosuper
index 058d602d..7d41fd7b 100644
--- a/tests/05r1-re-add-nosuper
+++ b/tests/05r1-re-add-nosuper
@@ -6,7 +6,7 @@
#
bmf=$targetdir/bitmap2
rm -f $bmf
-mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2
+yes | mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2
check resync
check wait
testdev $md0 1 $size 1
--
2.41.0

View File

@ -0,0 +1,44 @@
From c5a4fe7874f94b3f172027043f9a94b037f4d4dd Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Tue, 28 May 2024 21:51:50 +0800
Subject: [PATCH 098/157] mdadm/tests: remove strace test
Some tests will fail if the test env doesn't have strace
commands. So remove the dependency.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
tests/07revert-grow | 2 +-
tests/07revert-inplace | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/07revert-grow b/tests/07revert-grow
index c8c4e855..333483dc 100644
--- a/tests/07revert-grow
+++ b/tests/07revert-grow
@@ -43,7 +43,7 @@ testdev $md0 2 $mdsize1 512
mdadm -G $md0 -n 5
sleep 3
mdadm -S $md0
-strace -o /tmp/str ./mdadm -A $md0 --update=revert-reshape $devlist4
+mdadm -A $md0 --update=revert-reshape $devlist4
check wait
check raid10
testdev $md0 2 $mdsize1 512
diff --git a/tests/07revert-inplace b/tests/07revert-inplace
index a73eb977..776324ac 100644
--- a/tests/07revert-inplace
+++ b/tests/07revert-inplace
@@ -37,7 +37,7 @@ testdev $md0 3 $mdsize1 64
mdadm -G $md0 -c 32
sleep 2
mdadm -S $md0
-strace -o /tmp/str ./mdadm -A $md0 --update=revert-reshape $devlist5
+mdadm -A $md0 --update=revert-reshape $devlist5
check wait
check raid10
testdev $md0 3 $mdsize1 64
--
2.41.0

View File

@ -0,0 +1,37 @@
From 9dbd11e091f84eb0bf9d717283774816c4c4453d Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Tue, 21 May 2024 16:26:33 +0200
Subject: [PATCH 099/157] mdadm.h: provide basename if GLIBC is not avialable
If GNU basename is not avilable, define it. It is safer to use that
rather than include libgen.h with XPG basename() definition.
Fixes:#12
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
mdadm.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/mdadm.h b/mdadm.h
index 40818941..e9f764a2 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -223,6 +223,14 @@ struct dlm_lksb {
struct __una_u16 { __u16 x; } __attribute__ ((packed));
struct __una_u32 { __u32 x; } __attribute__ ((packed));
+/*
+ * Ensure GNU basename behavior on GLIBC less systems.
+ */
+#ifndef __GLIBC__
+#define basename(path) \
+ (strrchr((path), '/') ? strrchr((path),'/') + 1 : (path))
+#endif
+
static inline __u16 __get_unaligned16(const void *p)
{
const struct __una_u16 *ptr = (const struct __una_u16 *)p;
--
2.41.0

View File

@ -0,0 +1,79 @@
From 46f19270265fe54cda1c728cb156b755273b4ab6 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 23 May 2024 12:06:36 +0200
Subject: [PATCH 100/157] imsm: fix first volume autolayout with
IMSM_NO_PLATFORM
Autolayout_imsm() is not executed if IMSM_NO_PLATFORM=1 is set.
This causes that first volume cannot be created. Disk for new volume are
never configured.
Fix it by making autolayout_imsm() independent from super->orom because
NULL there means that IMSM_NO_PLATFORM=1 is set. There are not platform
restrictions to create volume, we just analyze drives. It is safe.
Fixes: 6d4d9ab295de ("imsm: use same slot across container")
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
---
super-intel.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 0287a618..29652196 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -7706,9 +7706,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
char *dev, unsigned long long *freesize,
int consistency_policy, int verbose)
{
- int fd, cfd;
+ struct intel_super *super = st->sb;
struct mdinfo *sra;
int is_member = 0;
+ imsm_status_t rv;
+ int fd, cfd;
/* load capability
* if given unused devices create a container
@@ -7733,11 +7735,10 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
}
if (!dev) {
- struct intel_super *super = st->sb;
-
/*
* Autolayout mode, st->sb must be set.
*/
+
if (!super) {
pr_vrb("superblock must be set for autolayout, aborting\n");
return 0;
@@ -7749,20 +7750,19 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout,
return 0;
if (super->orom && freesize) {
- imsm_status_t rv;
- int count = count_volumes(super->hba, super->orom->dpa,
- verbose);
+ int count = count_volumes(super->hba, super->orom->dpa, verbose);
+
if (super->orom->vphba <= count) {
pr_vrb("platform does not support more than %d raid volumes.\n",
super->orom->vphba);
return 0;
}
+ }
- rv = autolayout_imsm(super, raiddisks, size, *chunk,
- freesize);
+ rv = autolayout_imsm(super, raiddisks, size, *chunk, freesize);
if (rv != IMSM_STATUS_OK)
return 0;
- }
+
return 1;
}
if (st->sb) {
--
2.41.0

Some files were not shown because too many files have changed in this diff Show More