Compare commits

...

No commits in common. "c8" and "c9-beta" have entirely different histories.
c8 ... c9-beta

94 changed files with 10319 additions and 487 deletions

View File

@ -0,0 +1,69 @@
From 52c67fcdd6dadc4138ecad73e65599551804d445 Mon Sep 17 00:00:00 2001
From: Coly Li <colyli@suse.de>
Date: Tue, 15 Feb 2022 21:34:15 +0800
Subject: [PATCH 012/125] mdadm/systemd: remove KillMode=none from service file
For mdadm's systemd configuration, current systemd KillMode is "none" in
following service files,
- mdadm-grow-continue@.service
- mdmon@.service
This "none" mode is strongly againsted by systemd developers (see man 5
systemd.kill for "KillMode=" section), and is considering to remove in
future systemd version.
As systemd developer explained in disuccsion, the systemd kill process
is,
1. send the signal specified by KillSignal= to the list of processes (if
any), TERM is the default
2. wait until either the target of process(es) exit or a timeout expires
3. if the timeout expires send the signal specified by FinalKillSignal=,
KILL is the default
For "control-group", all remaining processes will receive the SIGTERM
signal (by default) and if there are still processes after a period f
time, they will get the SIGKILL signal.
For "mixed", only the main process will receive the SIGTERM signal, and
if there are still processes after a period of time, all remaining
processes (including the main one) will receive the SIGKILL signal.
From the above comment, currently KillMode=control-group is a proper
kill mode. Since control-gropu is the default kill mode, the fix can be
simply removing KillMode=none line from the service file, then the
default mode will take effect.
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Benjamin Brunner <bbrunner@suse.com>
Cc: Franck Bui <fbui@suse.de>
Cc: Jes Sorensen <jes@trained-monkey.org>
Cc: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Xiao Ni <xni@redhat.com>
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
---
systemd/mdadm-grow-continue@.service | 1 -
systemd/mdmon@.service | 1 -
2 files changed, 2 deletions(-)
diff --git a/systemd/mdadm-grow-continue@.service b/systemd/mdadm-grow-continue@.service
index 5c667d2a..9fdc8ec7 100644
--- a/systemd/mdadm-grow-continue@.service
+++ b/systemd/mdadm-grow-continue@.service
@@ -14,4 +14,3 @@ ExecStart=BINDIR/mdadm --grow --continue /dev/%I
StandardInput=null
StandardOutput=null
StandardError=null
-KillMode=none
diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service
index 85a3a7c5..77533958 100644
--- a/systemd/mdmon@.service
+++ b/systemd/mdmon@.service
@@ -25,4 +25,3 @@ Type=forking
# it out) and systemd will remove it when transitioning from
# initramfs to rootfs.
#PIDFile=/run/mdadm/%I.pid
-KillMode=none
--
2.38.1

View File

@ -0,0 +1,54 @@
From 28a083955c6f58f8e582734c8c82aff909a7d461 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 2 Feb 2023 08:56:31 +0100
Subject: [PATCH 084/125] Revert "mdadm/systemd: remove KillMode=none from
service file"
This reverts commit 52c67fcdd6dadc4138ecad73e65599551804d445.
The functionality is marked as deprecated but we don't have alternative
solution yet. Shutdown hangs if OS is installed on external array:
task:umount state:D stack: 0 pid: 6285 ppid: flags:0x00004084
Call Trace:
__schedule+0x2d1/0x830
? finish_wait+0x80/0x80
schedule+0x35/0xa0
md_write_start+0x14b/0x220
? finish_wait+0x80/0x80
raid1_make_request+0x3c/0x90 [raid1]
md_handle_request+0x128/0x1b0
md_make_request+0x5b/0xb0
generic_make_request_no_check+0x202/0x330
submit_bio+0x3c/0x160
Use it until new solution is implemented.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
systemd/mdadm-grow-continue@.service | 1 +
systemd/mdmon@.service | 1 +
2 files changed, 2 insertions(+)
diff --git a/systemd/mdadm-grow-continue@.service b/systemd/mdadm-grow-continue@.service
index 64b8254a..9ccadca3 100644
--- a/systemd/mdadm-grow-continue@.service
+++ b/systemd/mdadm-grow-continue@.service
@@ -15,3 +15,4 @@ ExecStart=BINDIR/mdadm --grow --continue /dev/%I
StandardInput=null
StandardOutput=null
StandardError=null
+KillMode=none
diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service
index 97a1acd9..cb6482d9 100644
--- a/systemd/mdmon@.service
+++ b/systemd/mdmon@.service
@@ -26,3 +26,4 @@ Type=forking
# it out) and systemd will remove it when transitioning from
# initramfs to rootfs.
#PIDFile=/run/mdadm/%I.pid
+KillMode=none
--
2.38.1

View File

@ -0,0 +1,45 @@
From d07e561810a2e33b667a8a9476edaff42eb119b9 Mon Sep 17 00:00:00 2001
From: Heming Zhao <heming.zhao@suse.com>
Date: Thu, 23 Feb 2023 22:39:39 +0800
Subject: [PATCH 085/125] Grow: fix can't change bitmap type from none to
clustered.
Commit a042210648ed ("disallow create or grow clustered bitmap with
writemostly set") introduced this bug. We should use 'true' logic not
'== 0' to deny setting up clustered array under WRITEMOSTLY condition.
How to trigger
```
~/mdadm # ./mdadm -Ss && ./mdadm --zero-superblock /dev/sd{a,b}
~/mdadm # ./mdadm -C /dev/md0 -l mirror -b clustered -e 1.2 -n 2 \
/dev/sda /dev/sdb --assume-clean
mdadm: array /dev/md0 started.
~/mdadm # ./mdadm --grow /dev/md0 --bitmap=none
~/mdadm # ./mdadm --grow /dev/md0 --bitmap=clustered
mdadm: /dev/md0 disks marked write-mostly are not supported with clustered bitmap
```
Signed-off-by: Heming Zhao <heming.zhao@suse.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Grow.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Grow.c b/Grow.c
index 8f5cf07d..bb5fe45c 100644
--- a/Grow.c
+++ b/Grow.c
@@ -429,7 +429,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s)
dv = map_dev(disk.major, disk.minor, 1);
if (!dv)
continue;
- if (((disk.state & (1 << MD_DISK_WRITEMOSTLY)) == 0) &&
+ if ((disk.state & (1 << MD_DISK_WRITEMOSTLY)) &&
(strcmp(s->bitmap_file, "clustered") == 0)) {
pr_err("%s disks marked write-mostly are not supported with clustered bitmap\n",devname);
free(mdi);
--
2.38.1

View File

@ -0,0 +1,76 @@
From f1f3ef7d2de5e3a726c27b9f9bb20e270a100dab Mon Sep 17 00:00:00 2001
From: Li Xiao Keng <lixiaokeng@huawei.com>
Date: Mon, 27 Feb 2023 11:12:07 +0800
Subject: [PATCH 086/125] Fix NULL dereference in super_by_fd
When we create 100 partitions (major is 259 not 254) in a raid device,
mdadm may coredump:
Core was generated by `/usr/sbin/mdadm --detail --export /dev/md1p7'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 __strlen_avx2_rtm () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:74
74 VPCMPEQ (%rdi), %ymm0, %ymm1
(gdb) bt
#0 __strlen_avx2_rtm () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:74
#1 0x00007fbb9a7e4139 in __strcpy_chk (dest=dest@entry=0x55d55d6a13ac "", src=0x0, destlen=destlen@entry=32) at strcpy_chk.c:28
#2 0x000055d55ba1766d in strcpy (__src=<optimized out>, __dest=0x55d55d6a13ac "") at /usr/include/bits/string_fortified.h:79
#3 super_by_fd (fd=fd@entry=3, subarrayp=subarrayp@entry=0x7fff44dfcc48) at util.c:1289
#4 0x000055d55ba273a6 in Detail (dev=0x7fff44dfef0b "/dev/md1p7", c=0x7fff44dfe440) at Detail.c:101
#5 0x000055d55ba0de61 in misc_list (c=<optimized out>, ss=<optimized out>, dump_directory=<optimized out>, ident=<optimized out>, devlist=<optimized out>) at mdadm.c:1959
#6 main (argc=<optimized out>, argv=<optimized out>) at mdadm.c:1629
The direct cause is fd2devnm returning NULL, so add a check.
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
Signed-off-by: Wu Guang Hao <wuguanghao3@huawei.com>
Acked-by: Coly Li <colyli@suse.de>
Acked-by: Coly Li <colyli@suse.de <mailto:colyli@suse.de>>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mapfile.c | 4 ++++
util.c | 7 ++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/mapfile.c b/mapfile.c
index 6b2207dd..ac351768 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -292,6 +292,10 @@ struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4])
struct map_ent *map_by_devnm(struct map_ent **map, char *devnm)
{
struct map_ent *mp;
+
+ if (!devnm)
+ return NULL;
+
if (!*map)
map_read(map);
diff --git a/util.c b/util.c
index 9cd89fa4..8c7f3fd5 100644
--- a/util.c
+++ b/util.c
@@ -1160,6 +1160,11 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
int i;
char *subarray = NULL;
char container[32] = "";
+ char *devnm = NULL;
+
+ devnm = fd2devnm(fd);
+ if (!devnm)
+ return NULL;
sra = sysfs_read(fd, NULL, GET_VERSION);
@@ -1205,7 +1210,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp)
if (subarrayp)
*subarrayp = subarray;
strcpy(st->container_devnm, container);
- strcpy(st->devnm, fd2devnm(fd));
+ strncpy(st->devnm, devnm, MD_NAME_MAX - 1);
} else
free(subarray);
--
2.38.1

View File

@ -0,0 +1,369 @@
From b301516615c441bd3cc4b512fae73fc066d227f1 Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:26:59 +0100
Subject: [PATCH 087/125] Mdmonitor: Make alert_info global
Move information about --test flag and hostname into alert_info.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 124 +++++++++++++++++++++++++++---------------------------
1 file changed, 61 insertions(+), 63 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 188cb8be..9ef4dab8 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -58,21 +58,20 @@ struct state {
};
struct alert_info {
+ char hostname[HOST_NAME_MAX];
char *mailaddr;
char *mailfrom;
char *alert_cmd;
int dosyslog;
-};
+ int test;
+} info;
static int make_daemon(char *pidfile);
static int check_one_sharer(int scan);
static void write_autorebuild_pid(void);
-static void alert(const char *event, const char *dev, const char *disc, struct alert_info *info);
-static int check_array(struct state *st, struct mdstat_ent *mdstat,
- int test, struct alert_info *info,
- int increments, char *prefer);
-static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
- int test, struct alert_info *info);
-static void try_spare_migration(struct state *statelist, struct alert_info *info);
+static void alert(const char *event, const char *dev, const char *disc);
+static int check_array(struct state *st, struct mdstat_ent *mdstat, int increments, char *prefer);
+static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist);
+static void try_spare_migration(struct state *statelist);
static void link_containers_with_subarrays(struct state *list);
static void free_statelist(struct state *statelist);
#ifndef NO_LIBUDEV
@@ -132,7 +131,6 @@ int Monitor(struct mddev_dev *devlist,
int finished = 0;
struct mdstat_ent *mdstat = NULL;
char *mailfrom;
- struct alert_info info;
struct mddev_ident *mdlist;
int delay_for_event = c->delay;
@@ -166,6 +164,13 @@ int Monitor(struct mddev_dev *devlist,
info.mailaddr = mailaddr;
info.mailfrom = mailfrom;
info.dosyslog = dosyslog;
+ info.test = c->test;
+
+ if (gethostname(info.hostname, sizeof(info.hostname)) != 0) {
+ pr_err("Cannot get hostname.\n");
+ return 1;
+ }
+ info.hostname[sizeof(info.hostname) - 1] = '\0';
if (share){
if (check_one_sharer(c->scan))
@@ -241,8 +246,7 @@ int Monitor(struct mddev_dev *devlist,
mdstat = mdstat_read(oneshot ? 0 : 1, 0);
for (st = statelist; st; st = st->next) {
- if (check_array(st, mdstat, c->test, &info,
- increments, c->prefer))
+ if (check_array(st, mdstat, increments, c->prefer))
anydegraded = 1;
/* for external arrays, metadata is filled for
* containers only
@@ -255,15 +259,14 @@ int Monitor(struct mddev_dev *devlist,
/* now check if there are any new devices found in mdstat */
if (c->scan)
- new_found = add_new_arrays(mdstat, &statelist, c->test,
- &info);
+ new_found = add_new_arrays(mdstat, &statelist);
/* If an array has active < raid && spare == 0 && spare_group != NULL
* Look for another array with spare > 0 and active == raid and same spare_group
* if found, choose a device and hotremove/hotadd
*/
if (share && anydegraded)
- try_spare_migration(statelist, &info);
+ try_spare_migration(statelist);
if (!new_found) {
if (oneshot)
break;
@@ -294,7 +297,7 @@ int Monitor(struct mddev_dev *devlist,
mdstat_close();
}
}
- c->test = 0;
+ info.test = 0;
for (stp = &statelist; (st = *stp) != NULL; ) {
if (st->from_auto && st->err > 5) {
@@ -412,7 +415,7 @@ static void write_autorebuild_pid()
}
}
-static void execute_alert_cmd(const char *event, const char *dev, const char *disc, struct alert_info *info)
+static void execute_alert_cmd(const char *event, const char *dev, const char *disc)
{
int pid = fork();
@@ -424,15 +427,14 @@ static void execute_alert_cmd(const char *event, const char *dev, const char *di
pr_err("Cannot fork to execute alert command");
break;
case 0:
- execl(info->alert_cmd, info->alert_cmd, event, dev, disc, NULL);
+ execl(info.alert_cmd, info.alert_cmd, event, dev, disc, NULL);
exit(2);
}
}
-static void send_event_email(const char *event, const char *dev, const char *disc, struct alert_info *info)
+static void send_event_email(const char *event, const char *dev, const char *disc)
{
FILE *mp, *mdstat;
- char hname[256];
char buf[BUFSIZ];
int n;
@@ -442,14 +444,13 @@ static void send_event_email(const char *event, const char *dev, const char *dis
return;
}
- gethostname(hname, sizeof(hname));
signal(SIGPIPE, SIG_IGN);
- if (info->mailfrom)
- fprintf(mp, "From: %s\n", info->mailfrom);
+ if (info.mailfrom)
+ fprintf(mp, "From: %s\n", info.mailfrom);
else
fprintf(mp, "From: %s monitoring <root>\n", Name);
- fprintf(mp, "To: %s\n", info->mailaddr);
- fprintf(mp, "Subject: %s event on %s:%s\n\n", event, dev, hname);
+ fprintf(mp, "To: %s\n", info.mailaddr);
+ fprintf(mp, "Subject: %s event on %s:%s\n\n", event, dev, info.hostname);
fprintf(mp, "This is an automatically generated mail message. \n");
fprintf(mp, "A %s event had been detected on md device %s.\n\n", event, dev);
@@ -501,37 +502,36 @@ static void log_event_to_syslog(const char *event, const char *dev, const char *
syslog(priority, "%s event detected on md device %s", event, dev);
}
-static void alert(const char *event, const char *dev, const char *disc, struct alert_info *info)
+static void alert(const char *event, const char *dev, const char *disc)
{
- if (!info->alert_cmd && !info->mailaddr && !info->dosyslog) {
+ if (!info.alert_cmd && !info.mailaddr && !info.dosyslog) {
time_t now = time(0);
printf("%1.15s: %s on %s %s\n", ctime(&now) + 4,
event, dev, disc?disc:"unknown device");
}
- if (info->alert_cmd)
- execute_alert_cmd(event, dev, disc, info);
+ if (info.alert_cmd)
+ execute_alert_cmd(event, dev, disc);
- if (info->mailaddr && (strncmp(event, "Fail", 4) == 0 ||
+ if (info.mailaddr && (strncmp(event, "Fail", 4) == 0 ||
strncmp(event, "Test", 4) == 0 ||
strncmp(event, "Spares", 6) == 0 ||
strncmp(event, "Degrade", 7) == 0)) {
- send_event_email(event, dev, disc, info);
+ send_event_email(event, dev, disc);
}
- if (info->dosyslog)
+ if (info.dosyslog)
log_event_to_syslog(event, dev, disc);
}
static int check_array(struct state *st, struct mdstat_ent *mdstat,
- int test, struct alert_info *ainfo,
int increments, char *prefer)
{
/* Update the state 'st' to reflect any changes shown in mdstat,
* or found by directly examining the array, and return
* '1' if the array is degraded, or '0' if it is optimal (or dead).
*/
- struct { int state, major, minor; } info[MAX_DISKS];
+ struct { int state, major, minor; } disks_info[MAX_DISKS];
struct mdinfo *sra = NULL;
mdu_array_info_t array;
struct mdstat_ent *mse = NULL, *mse2;
@@ -545,8 +545,8 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
int is_container = 0;
unsigned long redundancy_only_flags = 0;
- if (test)
- alert("TestMessage", dev, NULL, ainfo);
+ if (info.test)
+ alert("TestMessage", dev, NULL);
retval = 0;
@@ -595,7 +595,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
*/
if (sra->array.level == 0 || sra->array.level == -1) {
if (!st->err && !st->from_config)
- alert("DeviceDisappeared", dev, " Wrong-Level", ainfo);
+ alert("DeviceDisappeared", dev, " Wrong-Level");
st->err++;
goto out;
}
@@ -612,7 +612,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
st->percent = RESYNC_NONE;
new_array = 1;
if (!is_container)
- alert("NewArray", st->devname, NULL, ainfo);
+ alert("NewArray", st->devname, NULL);
}
if (st->utime == array.utime && st->failed == sra->array.failed_disks &&
@@ -625,14 +625,14 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
}
if (st->utime == 0 && /* new array */
mse->pattern && strchr(mse->pattern, '_') /* degraded */)
- alert("DegradedArray", dev, NULL, ainfo);
+ alert("DegradedArray", dev, NULL);
if (st->utime == 0 && /* new array */ st->expected_spares > 0 &&
sra->array.spare_disks < st->expected_spares)
- alert("SparesMissing", dev, NULL, ainfo);
+ alert("SparesMissing", dev, NULL);
if (st->percent < 0 && st->percent != RESYNC_UNKNOWN &&
mse->percent >= 0)
- alert("RebuildStarted", dev, NULL, ainfo);
+ alert("RebuildStarted", dev, NULL);
if (st->percent >= 0 && mse->percent >= 0 &&
(mse->percent / increments) > (st->percent / increments)) {
char percentalert[18];
@@ -647,7 +647,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
snprintf(percentalert, sizeof(percentalert),
"Rebuild%02d", mse->percent);
- alert(percentalert, dev, NULL, ainfo);
+ alert(percentalert, dev, NULL);
}
if (mse->percent == RESYNC_NONE && st->percent >= 0) {
@@ -660,9 +660,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
snprintf(cnt, sizeof(cnt),
" mismatches found: %d (on raid level %d)",
sra->mismatch_cnt, sra->array.level);
- alert("RebuildFinished", dev, cnt, ainfo);
+ alert("RebuildFinished", dev, cnt);
} else
- alert("RebuildFinished", dev, NULL, ainfo);
+ alert("RebuildFinished", dev, NULL);
}
st->percent = mse->percent;
@@ -671,13 +671,13 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
mdu_disk_info_t disc;
disc.number = i;
if (md_get_disk_info(fd, &disc) >= 0) {
- info[i].state = disc.state;
- info[i].major = disc.major;
- info[i].minor = disc.minor;
+ disks_info[i].state = disc.state;
+ disks_info[i].major = disc.major;
+ disks_info[i].minor = disc.minor;
if (disc.major || disc.minor)
remaining_disks --;
} else
- info[i].major = info[i].minor = 0;
+ disks_info[i].major = disks_info[i].minor = 0;
}
last_disk = i;
@@ -700,13 +700,13 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
int change;
char *dv = NULL;
disc.number = i;
- if (i < last_disk && (info[i].major || info[i].minor)) {
- newstate = info[i].state;
- dv = map_dev_preferred(info[i].major, info[i].minor, 1,
+ if (i < last_disk && (disks_info[i].major || disks_info[i].minor)) {
+ newstate = disks_info[i].state;
+ dv = map_dev_preferred(disks_info[i].major, disks_info[i].minor, 1,
prefer);
disc.state = newstate;
- disc.major = info[i].major;
- disc.minor = info[i].minor;
+ disc.major = disks_info[i].major;
+ disc.minor = disks_info[i].minor;
} else
newstate = (1 << MD_DISK_REMOVED);
@@ -716,14 +716,14 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
change = newstate ^ st->devstate[i];
if (st->utime && change && !st->err && !new_array) {
if ((st->devstate[i]&change) & (1 << MD_DISK_SYNC))
- alert("Fail", dev, dv, ainfo);
+ alert("Fail", dev, dv);
else if ((newstate & (1 << MD_DISK_FAULTY)) &&
(disc.major || disc.minor) &&
st->devid[i] == makedev(disc.major,
disc.minor))
- alert("FailSpare", dev, dv, ainfo);
+ alert("FailSpare", dev, dv);
else if ((newstate&change) & (1 << MD_DISK_SYNC))
- alert("SpareActive", dev, dv, ainfo);
+ alert("SpareActive", dev, dv);
}
st->devstate[i] = newstate;
st->devid[i] = makedev(disc.major, disc.minor);
@@ -747,13 +747,12 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
disappeared:
if (!st->err && !is_container)
- alert("DeviceDisappeared", dev, NULL, ainfo);
+ alert("DeviceDisappeared", dev, NULL);
st->err++;
goto out;
}
-static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
- int test, struct alert_info *info)
+static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
{
struct mdstat_ent *mse;
int new_found = 0;
@@ -806,8 +805,8 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist,
} else
st->parent_devnm[0] = 0;
*statelist = st;
- if (test)
- alert("TestMessage", st->devname, NULL, info);
+ if (info.test)
+ alert("TestMessage", st->devname, NULL);
new_found = 1;
}
return new_found;
@@ -971,7 +970,7 @@ static dev_t container_choose_spare(struct state *from, struct state *to,
return dev;
}
-static void try_spare_migration(struct state *statelist, struct alert_info *info)
+static void try_spare_migration(struct state *statelist)
{
struct state *from;
struct state *st;
@@ -1030,8 +1029,7 @@ static void try_spare_migration(struct state *statelist, struct alert_info *info
if (devid > 0 &&
move_spare(from->devname, to->devname,
devid)) {
- alert("MoveSpare", to->devname,
- from->devname, info);
+ alert("MoveSpare", to->devname, from->devname);
break;
}
}
--
2.38.1

View File

@ -0,0 +1,313 @@
From 50232a6ec4a5c46c608181d72d0c633831a03134 Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:27:00 +0100
Subject: [PATCH 088/125] Mdmonitor: Pass events to alert() using enums instead
of strings
Add events enum, and mapping_t struct, that maps them to strings, so
that enums are passed around instead of strings.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 136 +++++++++++++++++++++++++++++++++---------------------
1 file changed, 83 insertions(+), 53 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 9ef4dab8..029e9efd 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -32,6 +32,8 @@
#include <libudev.h>
#endif
+#define EVENT_NAME_MAX 32
+
struct state {
char devname[MD_NAME_MAX + sizeof("/dev/md/")]; /* length of "/dev/md/" + device name + terminating byte*/
char devnm[MD_NAME_MAX]; /* to sync with mdstat info */
@@ -65,10 +67,43 @@ struct alert_info {
int dosyslog;
int test;
} info;
+
+enum event {
+ EVENT_SPARE_ACTIVE = 0,
+ EVENT_NEW_ARRAY,
+ EVENT_MOVE_SPARE,
+ EVENT_TEST_MESSAGE,
+ EVENT_REBUILD_STARTED,
+ EVENT_REBUILD,
+ EVENT_REBUILD_FINISHED,
+ EVENT_SPARES_MISSING,
+ EVENT_DEVICE_DISAPPEARED,
+ EVENT_FAIL,
+ EVENT_FAIL_SPARE,
+ EVENT_DEGRADED_ARRAY,
+ EVENT_UNKNOWN
+};
+
+mapping_t events_map[] = {
+ {"SpareActive", EVENT_SPARE_ACTIVE},
+ {"NewArray", EVENT_NEW_ARRAY},
+ {"MoveSpare", EVENT_MOVE_SPARE},
+ {"TestMessage", EVENT_TEST_MESSAGE},
+ {"RebuildStarted", EVENT_REBUILD_STARTED},
+ {"Rebuild", EVENT_REBUILD},
+ {"RebuildFinished", EVENT_REBUILD_FINISHED},
+ {"SparesMissing", EVENT_SPARES_MISSING},
+ {"DeviceDisappeared", EVENT_DEVICE_DISAPPEARED},
+ {"Fail", EVENT_FAIL},
+ {"FailSpare", EVENT_FAIL_SPARE},
+ {"DegradedArray", EVENT_DEGRADED_ARRAY},
+ {NULL, EVENT_UNKNOWN}
+};
+
static int make_daemon(char *pidfile);
static int check_one_sharer(int scan);
static void write_autorebuild_pid(void);
-static void alert(const char *event, const char *dev, const char *disc);
+static void alert(const enum event event_enum, const unsigned int progress, const char *dev, const char *disc);
static int check_array(struct state *st, struct mdstat_ent *mdstat, int increments, char *prefer);
static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist);
static void try_spare_migration(struct state *statelist);
@@ -415,7 +450,7 @@ static void write_autorebuild_pid()
}
}
-static void execute_alert_cmd(const char *event, const char *dev, const char *disc)
+static void execute_alert_cmd(const char *event_name, const char *dev, const char *disc)
{
int pid = fork();
@@ -427,12 +462,12 @@ static void execute_alert_cmd(const char *event, const char *dev, const char *di
pr_err("Cannot fork to execute alert command");
break;
case 0:
- execl(info.alert_cmd, info.alert_cmd, event, dev, disc, NULL);
+ execl(info.alert_cmd, info.alert_cmd, event_name, dev, disc, NULL);
exit(2);
}
}
-static void send_event_email(const char *event, const char *dev, const char *disc)
+static void send_event_email(const char *event_name, const char *dev, const char *disc)
{
FILE *mp, *mdstat;
char buf[BUFSIZ];
@@ -450,9 +485,9 @@ static void send_event_email(const char *event, const char *dev, const char *dis
else
fprintf(mp, "From: %s monitoring <root>\n", Name);
fprintf(mp, "To: %s\n", info.mailaddr);
- fprintf(mp, "Subject: %s event on %s:%s\n\n", event, dev, info.hostname);
+ fprintf(mp, "Subject: %s event on %s:%s\n\n", event_name, dev, info.hostname);
fprintf(mp, "This is an automatically generated mail message. \n");
- fprintf(mp, "A %s event had been detected on md device %s.\n\n", event, dev);
+ fprintf(mp, "A %s event had been detected on md device %s.\n\n", event_name, dev);
if (disc && disc[0] != ' ')
fprintf(mp,
@@ -474,20 +509,20 @@ static void send_event_email(const char *event, const char *dev, const char *dis
pclose(mp);
}
-static void log_event_to_syslog(const char *event, const char *dev, const char *disc)
+static void log_event_to_syslog(const enum event event_enum, const char *event_name, const char *dev, const char *disc)
{
int priority;
/* Log at a different severity depending on the event.
*
* These are the critical events: */
- if (strncmp(event, "Fail", 4) == 0 ||
- strncmp(event, "Degrade", 7) == 0 ||
- strncmp(event, "DeviceDisappeared", 17) == 0)
+ if (event_enum == EVENT_FAIL ||
+ event_enum == EVENT_DEGRADED_ARRAY ||
+ event_enum == EVENT_DEVICE_DISAPPEARED)
priority = LOG_CRIT;
/* Good to know about, but are not failures: */
- else if (strncmp(event, "Rebuild", 7) == 0 ||
- strncmp(event, "MoveSpare", 9) == 0 ||
- strncmp(event, "Spares", 6) != 0)
+ else if (event_enum == EVENT_REBUILD ||
+ event_enum == EVENT_MOVE_SPARE ||
+ event_enum == EVENT_SPARES_MISSING)
priority = LOG_WARNING;
/* Everything else: */
else
@@ -495,33 +530,37 @@ static void log_event_to_syslog(const char *event, const char *dev, const char *
if (disc && disc[0] != ' ')
syslog(priority,
- "%s event detected on md device %s, component device %s", event, dev, disc);
+ "%s event detected on md device %s, component device %s",
+ event_name, dev, disc);
else if (disc)
- syslog(priority, "%s event detected on md device %s: %s", event, dev, disc);
+ syslog(priority, "%s event detected on md device %s: %s", event_name, dev, disc);
else
- syslog(priority, "%s event detected on md device %s", event, dev);
+ syslog(priority, "%s event detected on md device %s", event_name, dev);
}
-static void alert(const char *event, const char *dev, const char *disc)
+static void alert(const enum event event_enum, const unsigned int progress, const char *dev, const char *disc)
{
- if (!info.alert_cmd && !info.mailaddr && !info.dosyslog) {
- time_t now = time(0);
+ char event_name[EVENT_NAME_MAX];
- printf("%1.15s: %s on %s %s\n", ctime(&now) + 4,
- event, dev, disc?disc:"unknown device");
+ if (event_enum == EVENT_REBUILD) {
+ snprintf(event_name, sizeof(event_name), "%s%02d",
+ map_num_s(events_map, EVENT_REBUILD), progress);
+ } else {
+ snprintf(event_name, sizeof(event_name), "%s", map_num_s(events_map, event_enum));
}
+
if (info.alert_cmd)
- execute_alert_cmd(event, dev, disc);
+ execute_alert_cmd(event_name, dev, disc);
- if (info.mailaddr && (strncmp(event, "Fail", 4) == 0 ||
- strncmp(event, "Test", 4) == 0 ||
- strncmp(event, "Spares", 6) == 0 ||
- strncmp(event, "Degrade", 7) == 0)) {
- send_event_email(event, dev, disc);
+ if (info.mailaddr && (event_enum == EVENT_FAIL ||
+ event_enum == EVENT_TEST_MESSAGE ||
+ event_enum == EVENT_SPARES_MISSING ||
+ event_enum == EVENT_DEGRADED_ARRAY)) {
+ send_event_email(event_name, dev, disc);
}
if (info.dosyslog)
- log_event_to_syslog(event, dev, disc);
+ log_event_to_syslog(event_enum, event_name, dev, disc);
}
static int check_array(struct state *st, struct mdstat_ent *mdstat,
@@ -546,7 +585,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
unsigned long redundancy_only_flags = 0;
if (info.test)
- alert("TestMessage", dev, NULL);
+ alert(EVENT_TEST_MESSAGE, 0, dev, NULL);
retval = 0;
@@ -595,7 +634,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
*/
if (sra->array.level == 0 || sra->array.level == -1) {
if (!st->err && !st->from_config)
- alert("DeviceDisappeared", dev, " Wrong-Level");
+ alert(EVENT_DEVICE_DISAPPEARED, 0, dev, " Wrong-Level");
st->err++;
goto out;
}
@@ -612,7 +651,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
st->percent = RESYNC_NONE;
new_array = 1;
if (!is_container)
- alert("NewArray", st->devname, NULL);
+ alert(EVENT_NEW_ARRAY, 0, st->devname, NULL);
}
if (st->utime == array.utime && st->failed == sra->array.failed_disks &&
@@ -625,29 +664,20 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
}
if (st->utime == 0 && /* new array */
mse->pattern && strchr(mse->pattern, '_') /* degraded */)
- alert("DegradedArray", dev, NULL);
+ alert(EVENT_DEGRADED_ARRAY, 0, dev, NULL);
if (st->utime == 0 && /* new array */ st->expected_spares > 0 &&
sra->array.spare_disks < st->expected_spares)
- alert("SparesMissing", dev, NULL);
+ alert(EVENT_SPARES_MISSING, 0, dev, NULL);
if (st->percent < 0 && st->percent != RESYNC_UNKNOWN &&
mse->percent >= 0)
- alert("RebuildStarted", dev, NULL);
+ alert(EVENT_REBUILD_STARTED, 0, dev, NULL);
if (st->percent >= 0 && mse->percent >= 0 &&
(mse->percent / increments) > (st->percent / increments)) {
- char percentalert[18];
- /*
- * "RebuildNN" (10 chars) or "RebuildStarted" (15 chars)
- */
-
if((mse->percent / increments) == 0)
- snprintf(percentalert, sizeof(percentalert),
- "RebuildStarted");
+ alert(EVENT_REBUILD_STARTED, 0, dev, NULL);
else
- snprintf(percentalert, sizeof(percentalert),
- "Rebuild%02d", mse->percent);
-
- alert(percentalert, dev, NULL);
+ alert(EVENT_REBUILD, mse->percent, dev, NULL);
}
if (mse->percent == RESYNC_NONE && st->percent >= 0) {
@@ -660,9 +690,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
snprintf(cnt, sizeof(cnt),
" mismatches found: %d (on raid level %d)",
sra->mismatch_cnt, sra->array.level);
- alert("RebuildFinished", dev, cnt);
+ alert(EVENT_REBUILD_FINISHED, 0, dev, cnt);
} else
- alert("RebuildFinished", dev, NULL);
+ alert(EVENT_REBUILD_FINISHED, 0, dev, NULL);
}
st->percent = mse->percent;
@@ -716,14 +746,14 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
change = newstate ^ st->devstate[i];
if (st->utime && change && !st->err && !new_array) {
if ((st->devstate[i]&change) & (1 << MD_DISK_SYNC))
- alert("Fail", dev, dv);
+ alert(EVENT_FAIL, 0, dev, dv);
else if ((newstate & (1 << MD_DISK_FAULTY)) &&
(disc.major || disc.minor) &&
st->devid[i] == makedev(disc.major,
disc.minor))
- alert("FailSpare", dev, dv);
+ alert(EVENT_FAIL_SPARE, 0, dev, dv);
else if ((newstate&change) & (1 << MD_DISK_SYNC))
- alert("SpareActive", dev, dv);
+ alert(EVENT_SPARE_ACTIVE, 0, dev, dv);
}
st->devstate[i] = newstate;
st->devid[i] = makedev(disc.major, disc.minor);
@@ -747,7 +777,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
disappeared:
if (!st->err && !is_container)
- alert("DeviceDisappeared", dev, NULL);
+ alert(EVENT_DEVICE_DISAPPEARED, 0, dev, NULL);
st->err++;
goto out;
}
@@ -806,7 +836,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
st->parent_devnm[0] = 0;
*statelist = st;
if (info.test)
- alert("TestMessage", st->devname, NULL);
+ alert(EVENT_TEST_MESSAGE, 0, st->devname, NULL);
new_found = 1;
}
return new_found;
@@ -1029,7 +1059,7 @@ static void try_spare_migration(struct state *statelist)
if (devid > 0 &&
move_spare(from->devname, to->devname,
devid)) {
- alert("MoveSpare", to->devname, from->devname);
+ alert(EVENT_MOVE_SPARE, 0, to->devname, from->devname);
break;
}
}
--
2.38.1

View File

@ -0,0 +1,406 @@
From cc3df167c599d2ee0c132149c86fc0ad70d9f14e Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:27:01 +0100
Subject: [PATCH 089/125] Mdmonitor: Add helper functions
Add functions:
- is_email_event(),
- get_syslog_event_priority(),
- sprint_event_message(),
with kernel style comments containing more detailed descriptions.
Also update event syslog priorities to be consistent with man. MoveSpare event was described in man as priority info, while implemented as warning. Move event data into a struct, so that it is passed between different functions if needed.
Sort function declarations alphabetically and remove redundant alert() declaration.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 228 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 158 insertions(+), 70 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 029e9efd..39598ba0 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -73,10 +73,12 @@ enum event {
EVENT_NEW_ARRAY,
EVENT_MOVE_SPARE,
EVENT_TEST_MESSAGE,
+ __SYSLOG_PRIORITY_WARNING,
EVENT_REBUILD_STARTED,
EVENT_REBUILD,
EVENT_REBUILD_FINISHED,
EVENT_SPARES_MISSING,
+ __SYSLOG_PRIORITY_CRITICAL,
EVENT_DEVICE_DISAPPEARED,
EVENT_FAIL,
EVENT_FAIL_SPARE,
@@ -100,18 +102,31 @@ mapping_t events_map[] = {
{NULL, EVENT_UNKNOWN}
};
-static int make_daemon(char *pidfile);
-static int check_one_sharer(int scan);
-static void write_autorebuild_pid(void);
-static void alert(const enum event event_enum, const unsigned int progress, const char *dev, const char *disc);
-static int check_array(struct state *st, struct mdstat_ent *mdstat, int increments, char *prefer);
+struct event_data {
+ enum event event_enum;
+ /*
+ * @event_name: Rebuild event name must be in form "RebuildXX", where XX is rebuild progress.
+ */
+ char event_name[EVENT_NAME_MAX];
+ char message[BUFSIZ];
+ const char *description;
+ const char *dev;
+ const char *disc;
+};
+
static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist);
static void try_spare_migration(struct state *statelist);
static void link_containers_with_subarrays(struct state *list);
static void free_statelist(struct state *statelist);
+static int check_array(struct state *st, struct mdstat_ent *mdstat, int increments, char *prefer);
+static int check_one_sharer(int scan);
#ifndef NO_LIBUDEV
static int check_udev_activity(void);
#endif
+static void link_containers_with_subarrays(struct state *list);
+static int make_daemon(char *pidfile);
+static void try_spare_migration(struct state *statelist);
+static void write_autorebuild_pid(void);
int Monitor(struct mddev_dev *devlist,
char *mailaddr, char *alert_cmd,
@@ -450,7 +465,80 @@ static void write_autorebuild_pid()
}
}
-static void execute_alert_cmd(const char *event_name, const char *dev, const char *disc)
+#define BASE_MESSAGE "%s event detected on md device %s"
+#define COMPONENT_DEVICE_MESSAGE ", component device %s"
+#define DESCRIPTION_MESSAGE ": %s"
+/*
+ * sprint_event_message() - Writes basic message about detected event to destination ptr.
+ * @dest: message destination, should be at least the size of BUFSIZ
+ * @data: event data
+ *
+ * Return: 0 on success, 1 on error
+ */
+static int sprint_event_message(char *dest, const struct event_data *data)
+{
+ if (!dest || !data)
+ return 1;
+
+ if (data->disc && data->description)
+ snprintf(dest, BUFSIZ, BASE_MESSAGE COMPONENT_DEVICE_MESSAGE DESCRIPTION_MESSAGE,
+ data->event_name, data->dev, data->disc, data->description);
+ else if (data->disc)
+ snprintf(dest, BUFSIZ, BASE_MESSAGE COMPONENT_DEVICE_MESSAGE,
+ data->event_name, data->dev, data->disc);
+ else if (data->description)
+ snprintf(dest, BUFSIZ, BASE_MESSAGE DESCRIPTION_MESSAGE,
+ data->event_name, data->dev, data->description);
+ else
+ snprintf(dest, BUFSIZ, BASE_MESSAGE, data->event_name, data->dev);
+
+ return 0;
+}
+
+/*
+ * get_syslog_event_priority() - Determines event priority.
+ * @event_enum: event to be checked
+ *
+ * Return: LOG_CRIT, LOG_WARNING or LOG_INFO
+ */
+static int get_syslog_event_priority(const enum event event_enum)
+{
+ if (event_enum > __SYSLOG_PRIORITY_CRITICAL)
+ return LOG_CRIT;
+ if (event_enum > __SYSLOG_PRIORITY_WARNING)
+ return LOG_WARNING;
+ return LOG_INFO;
+}
+
+/*
+ * is_email_event() - Determines whether email for event should be sent or not.
+ * @event_enum: event to be checked
+ *
+ * Return: true if email should be sent, false otherwise
+ */
+static bool is_email_event(const enum event event_enum)
+{
+ static const enum event email_events[] = {
+ EVENT_FAIL,
+ EVENT_FAIL_SPARE,
+ EVENT_DEGRADED_ARRAY,
+ EVENT_SPARES_MISSING,
+ EVENT_TEST_MESSAGE
+ };
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(email_events); ++i) {
+ if (event_enum == email_events[i])
+ return true;
+ }
+ return false;
+}
+
+/*
+ * execute_alert_cmd() - Forks and executes command provided as alert_cmd.
+ * @data: event data
+ */
+static void execute_alert_cmd(const struct event_data *data)
{
int pid = fork();
@@ -462,12 +550,16 @@ static void execute_alert_cmd(const char *event_name, const char *dev, const cha
pr_err("Cannot fork to execute alert command");
break;
case 0:
- execl(info.alert_cmd, info.alert_cmd, event_name, dev, disc, NULL);
+ execl(info.alert_cmd, info.alert_cmd, data->event_name, data->dev, data->disc, NULL);
exit(2);
}
}
-static void send_event_email(const char *event_name, const char *dev, const char *disc)
+/*
+ * send_event_email() - Sends an email about event detected by monitor.
+ * @data: event data
+ */
+static void send_event_email(const struct event_data *data)
{
FILE *mp, *mdstat;
char buf[BUFSIZ];
@@ -485,15 +577,9 @@ static void send_event_email(const char *event_name, const char *dev, const char
else
fprintf(mp, "From: %s monitoring <root>\n", Name);
fprintf(mp, "To: %s\n", info.mailaddr);
- fprintf(mp, "Subject: %s event on %s:%s\n\n", event_name, dev, info.hostname);
- fprintf(mp, "This is an automatically generated mail message. \n");
- fprintf(mp, "A %s event had been detected on md device %s.\n\n", event_name, dev);
-
- if (disc && disc[0] != ' ')
- fprintf(mp,
- "It could be related to component device %s.\n\n", disc);
- if (disc && disc[0] == ' ')
- fprintf(mp, "Extra information:%s.\n\n", disc);
+ fprintf(mp, "Subject: %s event on %s:%s\n\n", data->event_name, data->dev, info.hostname);
+ fprintf(mp, "This is an automatically generated mail message.\n");
+ fprintf(mp, "%s\n", data->message);
mdstat = fopen("/proc/mdstat", "r");
if (!mdstat) {
@@ -509,58 +595,60 @@ static void send_event_email(const char *event_name, const char *dev, const char
pclose(mp);
}
-static void log_event_to_syslog(const enum event event_enum, const char *event_name, const char *dev, const char *disc)
+/*
+ * log_event_to_syslog() - Logs an event into syslog.
+ * @data: event data
+ */
+static void log_event_to_syslog(const struct event_data *data)
{
int priority;
- /* Log at a different severity depending on the event.
- *
- * These are the critical events: */
- if (event_enum == EVENT_FAIL ||
- event_enum == EVENT_DEGRADED_ARRAY ||
- event_enum == EVENT_DEVICE_DISAPPEARED)
- priority = LOG_CRIT;
- /* Good to know about, but are not failures: */
- else if (event_enum == EVENT_REBUILD ||
- event_enum == EVENT_MOVE_SPARE ||
- event_enum == EVENT_SPARES_MISSING)
- priority = LOG_WARNING;
- /* Everything else: */
- else
- priority = LOG_INFO;
-
- if (disc && disc[0] != ' ')
- syslog(priority,
- "%s event detected on md device %s, component device %s",
- event_name, dev, disc);
- else if (disc)
- syslog(priority, "%s event detected on md device %s: %s", event_name, dev, disc);
- else
- syslog(priority, "%s event detected on md device %s", event_name, dev);
+
+ priority = get_syslog_event_priority(data->event_enum);
+
+ syslog(priority, "%s\n", data->message);
}
-static void alert(const enum event event_enum, const unsigned int progress, const char *dev, const char *disc)
+/*
+ * alert() - Alerts about the monitor event.
+ * @event_enum: event to be sent
+ * @description: event description
+ * @progress: rebuild progress
+ * @dev: md device name
+ * @disc: component device
+ *
+ * If needed function executes alert command, sends an email or logs event to syslog.
+ */
+static void alert(const enum event event_enum, const char *description, const uint8_t progress,
+ const char *dev, const char *disc)
{
- char event_name[EVENT_NAME_MAX];
+ struct event_data data = {.dev = dev, .disc = disc, .description = description};
+
+ if (!dev)
+ return;
if (event_enum == EVENT_REBUILD) {
- snprintf(event_name, sizeof(event_name), "%s%02d",
+ snprintf(data.event_name, sizeof(data.event_name), "%s%02d",
map_num_s(events_map, EVENT_REBUILD), progress);
} else {
- snprintf(event_name, sizeof(event_name), "%s", map_num_s(events_map, event_enum));
+ snprintf(data.event_name, sizeof(data.event_name), "%s", map_num_s(events_map, event_enum));
}
- if (info.alert_cmd)
- execute_alert_cmd(event_name, dev, disc);
+ data.event_enum = event_enum;
- if (info.mailaddr && (event_enum == EVENT_FAIL ||
- event_enum == EVENT_TEST_MESSAGE ||
- event_enum == EVENT_SPARES_MISSING ||
- event_enum == EVENT_DEGRADED_ARRAY)) {
- send_event_email(event_name, dev, disc);
+ if (sprint_event_message(data.message, &data) != 0) {
+ pr_err("Cannot create event message.\n");
+ return;
}
+ pr_err("%s\n", data.message);
+
+ if (info.alert_cmd)
+ execute_alert_cmd(&data);
+
+ if (info.mailaddr && is_email_event(event_enum))
+ send_event_email(&data);
if (info.dosyslog)
- log_event_to_syslog(event_enum, event_name, dev, disc);
+ log_event_to_syslog(&data);
}
static int check_array(struct state *st, struct mdstat_ent *mdstat,
@@ -585,7 +673,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
unsigned long redundancy_only_flags = 0;
if (info.test)
- alert(EVENT_TEST_MESSAGE, 0, dev, NULL);
+ alert(EVENT_TEST_MESSAGE, NULL, 0, dev, NULL);
retval = 0;
@@ -634,7 +722,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
*/
if (sra->array.level == 0 || sra->array.level == -1) {
if (!st->err && !st->from_config)
- alert(EVENT_DEVICE_DISAPPEARED, 0, dev, " Wrong-Level");
+ alert(EVENT_DEVICE_DISAPPEARED, "Wrong-Level", 0, dev, NULL);
st->err++;
goto out;
}
@@ -651,7 +739,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
st->percent = RESYNC_NONE;
new_array = 1;
if (!is_container)
- alert(EVENT_NEW_ARRAY, 0, st->devname, NULL);
+ alert(EVENT_NEW_ARRAY, NULL, 0, st->devname, NULL);
}
if (st->utime == array.utime && st->failed == sra->array.failed_disks &&
@@ -664,20 +752,20 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
}
if (st->utime == 0 && /* new array */
mse->pattern && strchr(mse->pattern, '_') /* degraded */)
- alert(EVENT_DEGRADED_ARRAY, 0, dev, NULL);
+ alert(EVENT_DEGRADED_ARRAY, NULL, 0, dev, NULL);
if (st->utime == 0 && /* new array */ st->expected_spares > 0 &&
sra->array.spare_disks < st->expected_spares)
- alert(EVENT_SPARES_MISSING, 0, dev, NULL);
+ alert(EVENT_SPARES_MISSING, NULL, 0, dev, NULL);
if (st->percent < 0 && st->percent != RESYNC_UNKNOWN &&
mse->percent >= 0)
- alert(EVENT_REBUILD_STARTED, 0, dev, NULL);
+ alert(EVENT_REBUILD_STARTED, NULL, 0, dev, NULL);
if (st->percent >= 0 && mse->percent >= 0 &&
(mse->percent / increments) > (st->percent / increments)) {
if((mse->percent / increments) == 0)
- alert(EVENT_REBUILD_STARTED, 0, dev, NULL);
+ alert(EVENT_REBUILD_STARTED, NULL, 0, dev, NULL);
else
- alert(EVENT_REBUILD, mse->percent, dev, NULL);
+ alert(EVENT_REBUILD, NULL, mse->percent, dev, NULL);
}
if (mse->percent == RESYNC_NONE && st->percent >= 0) {
@@ -690,9 +778,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
snprintf(cnt, sizeof(cnt),
" mismatches found: %d (on raid level %d)",
sra->mismatch_cnt, sra->array.level);
- alert(EVENT_REBUILD_FINISHED, 0, dev, cnt);
+ alert(EVENT_REBUILD_FINISHED, NULL, 0, dev, cnt);
} else
- alert(EVENT_REBUILD_FINISHED, 0, dev, NULL);
+ alert(EVENT_REBUILD_FINISHED, NULL, 0, dev, NULL);
}
st->percent = mse->percent;
@@ -746,14 +834,14 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
change = newstate ^ st->devstate[i];
if (st->utime && change && !st->err && !new_array) {
if ((st->devstate[i]&change) & (1 << MD_DISK_SYNC))
- alert(EVENT_FAIL, 0, dev, dv);
+ alert(EVENT_FAIL, NULL, 0, dev, dv);
else if ((newstate & (1 << MD_DISK_FAULTY)) &&
(disc.major || disc.minor) &&
st->devid[i] == makedev(disc.major,
disc.minor))
- alert(EVENT_FAIL_SPARE, 0, dev, dv);
+ alert(EVENT_FAIL_SPARE, NULL, 0, dev, dv);
else if ((newstate&change) & (1 << MD_DISK_SYNC))
- alert(EVENT_SPARE_ACTIVE, 0, dev, dv);
+ alert(EVENT_SPARE_ACTIVE, NULL, 0, dev, dv);
}
st->devstate[i] = newstate;
st->devid[i] = makedev(disc.major, disc.minor);
@@ -777,7 +865,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat,
disappeared:
if (!st->err && !is_container)
- alert(EVENT_DEVICE_DISAPPEARED, 0, dev, NULL);
+ alert(EVENT_DEVICE_DISAPPEARED, NULL, 0, dev, NULL);
st->err++;
goto out;
}
@@ -836,7 +924,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
st->parent_devnm[0] = 0;
*statelist = st;
if (info.test)
- alert(EVENT_TEST_MESSAGE, 0, st->devname, NULL);
+ alert(EVENT_TEST_MESSAGE, NULL, 0, st->devname, NULL);
new_found = 1;
}
return new_found;
@@ -1059,7 +1147,7 @@ static void try_spare_migration(struct state *statelist)
if (devid > 0 &&
move_spare(from->devname, to->devname,
devid)) {
- alert(EVENT_MOVE_SPARE, 0, to->devname, from->devname);
+ alert(EVENT_MOVE_SPARE, NULL, 0, to->devname, from->devname);
break;
}
}
--
2.38.1

View File

@ -0,0 +1,83 @@
From ee9dcf9549e8cbfeb51123812776cc87016c95b0 Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:27:02 +0100
Subject: [PATCH 090/125] Add helpers to determine whether directories or files
are soft links
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdadm.h | 2 ++
util.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/mdadm.h b/mdadm.h
index 13f8b4cb..1674ce13 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1777,6 +1777,8 @@ extern void set_dlm_hooks(void);
#define MSEC_TO_NSEC(msec) ((msec) * 1000000)
#define USEC_TO_NSEC(usec) ((usec) * 1000)
extern void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt);
+extern bool is_directory(const char *path);
+extern bool is_file(const char *path);
#define _ROUND_UP(val, base) (((val) + (base) - 1) & ~(base - 1))
#define ROUND_UP(val, base) _ROUND_UP(val, (typeof(val))(base))
diff --git a/util.c b/util.c
index 8c7f3fd5..7fc881bf 100644
--- a/util.c
+++ b/util.c
@@ -2401,3 +2401,48 @@ void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt)
}
} while (!wake_after_interrupt && errno == EINTR);
}
+
+/* is_directory() - Checks if directory provided by path is indeed a regular directory.
+ * @path: directory path to be checked
+ *
+ * Doesn't accept symlinks.
+ *
+ * Return: true if is a directory, false if not
+ */
+bool is_directory(const char *path)
+{
+ struct stat st;
+
+ if (lstat(path, &st) != 0) {
+ pr_err("%s: %s\n", strerror(errno), path);
+ return false;
+ }
+
+ if (!S_ISDIR(st.st_mode))
+ return false;
+
+ return true;
+}
+
+/*
+ * is_file() - Checks if file provided by path is indeed a regular file.
+ * @path: file path to be checked
+ *
+ * Doesn't accept symlinks.
+ *
+ * Return: true if is a file, false if not
+ */
+bool is_file(const char *path)
+{
+ struct stat st;
+
+ if (lstat(path, &st) != 0) {
+ pr_err("%s: %s\n", strerror(errno), path);
+ return false;
+ }
+
+ if (!S_ISREG(st.st_mode))
+ return false;
+
+ return true;
+}
--
2.38.1

View File

@ -0,0 +1,110 @@
From b6a84d4e92f876acd120d3062a8302db5dd2498c Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:27:03 +0100
Subject: [PATCH 091/125] Mdmonitor: Refactor write_autorebuild_pid()
Add better error handling and check for symlinks when opening MDMON_DIR.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 55 ++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 36 insertions(+), 19 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 39598ba0..14a2dfe5 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -33,6 +33,7 @@
#endif
#define EVENT_NAME_MAX 32
+#define AUTOREBUILD_PID_PATH MDMON_DIR "/autorebuild.pid"
struct state {
char devname[MD_NAME_MAX + sizeof("/dev/md/")]; /* length of "/dev/md/" + device name + terminating byte*/
@@ -126,7 +127,7 @@ static int check_udev_activity(void);
static void link_containers_with_subarrays(struct state *list);
static int make_daemon(char *pidfile);
static void try_spare_migration(struct state *statelist);
-static void write_autorebuild_pid(void);
+static int write_autorebuild_pid(void);
int Monitor(struct mddev_dev *devlist,
char *mailaddr, char *alert_cmd,
@@ -234,7 +235,8 @@ int Monitor(struct mddev_dev *devlist,
}
if (share)
- write_autorebuild_pid();
+ if (write_autorebuild_pid() != 0)
+ return 1;
if (devlist == NULL) {
mdlist = conf_get_ident(NULL);
@@ -440,29 +442,44 @@ static int check_one_sharer(int scan)
return 0;
}
-static void write_autorebuild_pid()
+/*
+ * write_autorebuild_pid() - Writes pid to autorebuild.pid file.
+ *
+ * Return: 0 on success, 1 on error
+ */
+static int write_autorebuild_pid(void)
{
- char path[PATH_MAX];
- int pid;
- FILE *fp = NULL;
- sprintf(path, "%s/autorebuild.pid", MDMON_DIR);
+ FILE *fp;
+ int fd;
if (mkdir(MDMON_DIR, 0700) < 0 && errno != EEXIST) {
- pr_err("Can't create autorebuild.pid file\n");
- } else {
- int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0700);
+ pr_err("%s: %s\n", strerror(errno), MDMON_DIR);
+ return 1;
+ }
- if (fd >= 0)
- fp = fdopen(fd, "w");
+ if (!is_directory(MDMON_DIR)) {
+ pr_err("%s is not a regular directory.\n", MDMON_DIR);
+ return 1;
+ }
- if (!fp)
- pr_err("Can't create autorebuild.pid file\n");
- else {
- pid = getpid();
- fprintf(fp, "%d\n", pid);
- fclose(fp);
- }
+ fd = open(AUTOREBUILD_PID_PATH, O_WRONLY | O_CREAT | O_TRUNC, 0700);
+
+ if (fd < 0) {
+ pr_err("Error opening %s file.\n", AUTOREBUILD_PID_PATH);
+ return 1;
}
+
+ fp = fdopen(fd, "w");
+
+ if (!fp) {
+ pr_err("Error opening fd for %s file.\n", AUTOREBUILD_PID_PATH);
+ return 1;
+ }
+
+ fprintf(fp, "%d\n", getpid());
+
+ fclose(fp);
+ return 0;
}
#define BASE_MESSAGE "%s event detected on md device %s"
--
2.38.1

View File

@ -0,0 +1,139 @@
From 0a07dea8d3b78a22a59f4604a5e8da15690f28e3 Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 2 Feb 2023 12:27:04 +0100
Subject: [PATCH 092/125] Mdmonitor: Refactor check_one_sharer() for better
error handling
Also check if autorebuild.pid is a symlink, which we shouldn't accept.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 89 ++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 62 insertions(+), 27 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 14a2dfe5..44918184 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -32,6 +32,7 @@
#include <libudev.h>
#endif
+#define TASK_COMM_LEN 16
#define EVENT_NAME_MAX 32
#define AUTOREBUILD_PID_PATH MDMON_DIR "/autorebuild.pid"
@@ -224,7 +225,7 @@ int Monitor(struct mddev_dev *devlist,
info.hostname[sizeof(info.hostname) - 1] = '\0';
if (share){
- if (check_one_sharer(c->scan))
+ if (check_one_sharer(c->scan) == 2)
return 1;
}
@@ -406,39 +407,73 @@ static int make_daemon(char *pidfile)
return -1;
}
+/*
+ * check_one_sharer() - Checks for other mdmon processes running.
+ *
+ * Return:
+ * 0 - no other processes running,
+ * 1 - warning,
+ * 2 - error, or when scan mode is enabled, and one mdmon process already exists
+ */
static int check_one_sharer(int scan)
{
int pid;
- FILE *comm_fp;
- FILE *fp;
+ FILE *fp, *comm_fp;
char comm_path[PATH_MAX];
- char path[PATH_MAX];
- char comm[20];
-
- sprintf(path, "%s/autorebuild.pid", MDMON_DIR);
- fp = fopen(path, "r");
- if (fp) {
- if (fscanf(fp, "%d", &pid) != 1)
- pid = -1;
- snprintf(comm_path, sizeof(comm_path),
- "/proc/%d/comm", pid);
- comm_fp = fopen(comm_path, "r");
- if (comm_fp) {
- if (fscanf(comm_fp, "%19s", comm) &&
- strncmp(basename(comm), Name, strlen(Name)) == 0) {
- if (scan) {
- pr_err("Only one autorebuild process allowed in scan mode, aborting\n");
- fclose(comm_fp);
- fclose(fp);
- return 1;
- } else {
- pr_err("Warning: One autorebuild process already running.\n");
- }
- }
+ char comm[TASK_COMM_LEN];
+
+ if (!is_directory(MDMON_DIR)) {
+ pr_err("%s is not a regular directory.\n", MDMON_DIR);
+ 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 (fscanf(fp, "%d", &pid) != 1) {
+ pr_err("Cannot read pid from %s file.\n", AUTOREBUILD_PID_PATH);
+ fclose(fp);
+ return 2;
+ }
+
+ snprintf(comm_path, sizeof(comm_path), "/proc/%d/comm", pid);
+
+ comm_fp = fopen(comm_path, "r");
+ if (!comm_fp) {
+ dprintf("Warning: Cannot open %s, continuing\n", comm_path);
+ fclose(fp);
+ return 1;
+ }
+
+ if (fscanf(comm_fp, "%15s", comm) == 0) {
+ dprintf("Warning: Cannot read comm from %s, continuing\n", comm_path);
+ fclose(comm_fp);
+ fclose(fp);
+ return 1;
+ }
+
+ if (strncmp(basename(comm), Name, strlen(Name)) == 0) {
+ if (scan) {
+ pr_err("Only one autorebuild process allowed in scan mode, aborting\n");
fclose(comm_fp);
+ fclose(fp);
+ return 2;
}
- fclose(fp);
+ pr_err("Warning: One autorebuild process already running.\n");
}
+ fclose(comm_fp);
+ fclose(fp);
return 0;
}
--
2.38.1

View File

@ -0,0 +1,41 @@
From a0151041642dffff2421c22e18fb7b02b58787d9 Mon Sep 17 00:00:00 2001
From: Coly Li <colyli@suse.de>
Date: Sat, 4 Mar 2023 00:21:30 +0800
Subject: [PATCH 093/125] util.c: reorder code lines in parse_layout_faulty()
Resort the code lines in parse_layout_faulty() to make it more
comfortable, no logic change.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
util.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/util.c b/util.c
index 7fc881bf..b0b7aec4 100644
--- a/util.c
+++ b/util.c
@@ -421,12 +421,15 @@ int parse_layout_10(char *layout)
int parse_layout_faulty(char *layout)
{
+ int ln, mode;
+ char *m;
+
if (!layout)
return -1;
+
/* Parse the layout string for 'faulty' */
- int ln = strcspn(layout, "0123456789");
- char *m = xstrdup(layout);
- int mode;
+ ln = strcspn(layout, "0123456789");
+ m = xstrdup(layout);
m[ln] = 0;
mode = map_name(faultylayout, m);
if (mode == UnSet)
--
2.38.1

View File

@ -0,0 +1,32 @@
From 06ef619582b47af89eb094c164fc5effd46d6048 Mon Sep 17 00:00:00 2001
From: Wu Guanghao <wuguanghao3@huawei.com>
Date: Sat, 4 Mar 2023 00:21:31 +0800
Subject: [PATCH 094/125] util.c: fix memleak in parse_layout_faulty()
char *m is allocated by xstrdup but not free() before return, will cause
a memory leak
Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
util.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/util.c b/util.c
index b0b7aec4..9f1e1f7c 100644
--- a/util.c
+++ b/util.c
@@ -432,6 +432,8 @@ int parse_layout_faulty(char *layout)
m = xstrdup(layout);
m[ln] = 0;
mode = map_name(faultylayout, m);
+ free(m);
+
if (mode == UnSet)
return -1;
--
2.38.1

View File

@ -0,0 +1,31 @@
From dac0b5121dd77bf1659b95248423445f932dfae4 Mon Sep 17 00:00:00 2001
From: Wu Guanghao <wuguanghao3@huawei.com>
Date: Sat, 4 Mar 2023 00:21:32 +0800
Subject: [PATCH 095/125] Detail.c: fix memleak in Detail()
char *sysdev = xstrdup() but not free() in for loop, will cause memory
leak
Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Detail.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/Detail.c b/Detail.c
index ce7a8445..4ef26460 100644
--- a/Detail.c
+++ b/Detail.c
@@ -303,6 +303,7 @@ int Detail(char *dev, struct context *c)
if (path)
printf("MD_DEVICE_%s_DEV=%s\n",
sysdev, path);
+ free(sysdev);
}
}
goto out;
--
2.38.1

View File

@ -0,0 +1,63 @@
From 50cd06b484bb99bfacdd4f9d2f8ee5e52bfc7bd3 Mon Sep 17 00:00:00 2001
From: Wu Guanghao <wuguanghao3@huawei.com>
Date: Sat, 4 Mar 2023 00:21:33 +0800
Subject: [PATCH 096/125] isuper-intel.c: fix double free in load_imsm_mpb()
In load_imsm_mpb() there is potential double free issue on super->buf.
The first location to free super->buf is from get_super_block() <==
load_and_parse_mpb() <== load_imsm_mpb():
4514 if (posix_memalign(&super->migr_rec_buf, MAX_SECTOR_SIZE,
4515 MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE) != 0) {
4516 pr_err("could not allocate migr_rec buffer\n");
4517 free(super->buf);
4518 return 2;
4519 }
If the above error condition happens, super->buf is freed and value 2
is returned to get_super_block() eventually. Then in the following code
block inside load_imsm_mpb(),
5289 error:
5290 if (!err) {
5291 s->next = *super_list;
5292 *super_list = s;
5293 } else {
5294 if (s)
5295 free_imsm(s);
5296 close_fd(&dfd);
5297 }
at line 5295 when free_imsm() is called, super->buf is freed again from
the call chain free_imsm() <== __free_imsm(), in following code block,
4651 if (super->buf) {
4652 free(super->buf);
4653 super->buf = NULL;
4654 }
This patch sets super->buf as NULL after line 4517 in load_imsm_mpb()
to avoid the potential double free().
(Coly Li helps to re-compose the commit log)
Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/super-intel.c b/super-intel.c
index 89fac626..4a3da847 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -4515,6 +4515,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname)
MIGR_REC_BUF_SECTORS*MAX_SECTOR_SIZE) != 0) {
pr_err("could not allocate migr_rec buffer\n");
free(super->buf);
+ super->buf = NULL;
return 2;
}
super->clean_migration_record_by_mdmon = 0;
--
2.38.1

View File

@ -0,0 +1,39 @@
From 5d2434d18b6bc71bd16678b1a6d1cc3a92f1d415 Mon Sep 17 00:00:00 2001
From: Wu Guanghao <wuguanghao3@huawei.com>
Date: Sat, 4 Mar 2023 00:21:34 +0800
Subject: [PATCH 097/125] super-intel.c: fix memleak in
find_disk_attached_hba()
If disk_path = diskfd_to_devpath(), we need free(disk_path) before
return, otherwise there will be a memory leak
Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 4a3da847..e155a8ae 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -713,12 +713,12 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname)
for (elem = list; elem; elem = elem->next)
if (path_attached_to_hba(disk_path, elem->path))
- return elem;
+ break;
if (disk_path != devname)
free(disk_path);
- return NULL;
+ return elem;
}
static int find_intel_hba_capability(int fd, struct intel_super *super,
--
2.38.1

View File

@ -0,0 +1,46 @@
From 68b90794adf8287fa534cc8f35efb09772b133d0 Mon Sep 17 00:00:00 2001
From: Wu Guanghao <wuguanghao3@huawei.com>
Date: Sat, 4 Mar 2023 00:21:35 +0800
Subject: [PATCH 098/125] super-ddf.c: fix memleak in get_vd_num_of_subarray()
sra = sysfs_read() should be free before return in
get_vd_num_of_subarray()
Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-ddf.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/super-ddf.c b/super-ddf.c
index 309812df..b86c6acd 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1592,15 +1592,20 @@ static unsigned int get_vd_num_of_subarray(struct supertype *st)
sra = sysfs_read(-1, st->devnm, GET_VERSION);
if (!sra || sra->array.major_version != -1 ||
sra->array.minor_version != -2 ||
- !is_subarray(sra->text_version))
+ !is_subarray(sra->text_version)) {
+ if (sra)
+ sysfs_free(sra);
return DDF_NOTFOUND;
+ }
sub = strchr(sra->text_version + 1, '/');
if (sub != NULL)
vcnum = strtoul(sub + 1, &end, 10);
if (sub == NULL || *sub == '\0' || *end != '\0' ||
- vcnum >= be16_to_cpu(ddf->active->max_vd_entries))
+ vcnum >= be16_to_cpu(ddf->active->max_vd_entries)) {
+ sysfs_free(sra);
return DDF_NOTFOUND;
+ }
return vcnum;
}
--
2.38.1

View File

@ -0,0 +1,36 @@
From ba867e2ebaead20e3d9a7e62ef8fd940176c3110 Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:29 -0700
Subject: [PATCH 099/125] Create: goto abort_locked instead of return 1 in
error path
The return 1 after the fstat_is_blkdev() check should be replaced
with an error return that goes through the error path to unlock
resources locked by this function.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Create.c b/Create.c
index 953e7372..2e8203ec 100644
--- a/Create.c
+++ b/Create.c
@@ -939,7 +939,7 @@ int Create(struct supertype *st, char *mddev,
goto abort_locked;
}
if (!fstat_is_blkdev(fd, dv->devname, &rdev))
- return 1;
+ goto abort_locked;
inf->disk.major = major(rdev);
inf->disk.minor = minor(rdev);
}
--
2.38.1

View File

@ -0,0 +1,64 @@
From fb2c0f6183e29b014608e5e1aa4d53cb55887326 Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:30 -0700
Subject: [PATCH 100/125] Create: remove safe_mode_delay local variable
All .getinfo_super() call sets the info.safe_mode_delay variables
to a constant value, so no matter what the current state is
that function will always set it to the same value.
Create() calls .getinfo_super() multiple times while creating the array.
The value is stored in a local variable for every disk in the loop
to add disks (so the last disc call takes precedence). The local
variable is then used in the call to sysfs_set_safemode().
This can be simplified by using info.safe_mode_delay directly. The info
variable had .getinfo_super() called on it early in the function so, by the
reasoning above, it will have the same value as the local variable which
can thus be removed.
Doing this allows for factoring out code from Create() in a subsequent
patch.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/Create.c b/Create.c
index 2e8203ec..8ded81dc 100644
--- a/Create.c
+++ b/Create.c
@@ -137,7 +137,6 @@ int Create(struct supertype *st, char *mddev,
int did_default = 0;
int do_default_layout = 0;
int do_default_chunk = 0;
- unsigned long safe_mode_delay = 0;
char chosen_name[1024];
struct map_ent *map = NULL;
unsigned long long newsize;
@@ -952,7 +951,6 @@ int Create(struct supertype *st, char *mddev,
goto abort_locked;
}
st->ss->getinfo_super(st, inf, NULL);
- safe_mode_delay = inf->safe_mode_delay;
if (have_container && c->verbose > 0)
pr_err("Using %s for device %d\n",
@@ -1065,7 +1063,7 @@ int Create(struct supertype *st, char *mddev,
"readonly");
break;
}
- sysfs_set_safemode(&info, safe_mode_delay);
+ sysfs_set_safemode(&info, info.safe_mode_delay);
if (err) {
pr_err("failed to activate array.\n");
ioctl(mdfd, STOP_ARRAY, NULL);
--
2.38.1

View File

@ -0,0 +1,452 @@
From 8a4ce2c053866ac97feb436c4c85a54446ee0016 Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:31 -0700
Subject: [PATCH 101/125] Create: Factor out add_disks() helpers
The Create function is massive with a very large number of variables.
Reading and understanding the function is almost impossible. To help
with this, factor out the two pass loop that adds the disks to the array.
This moves about 160 lines into three new helper functions and removes
a bunch of local variables from the main Create function. The main new
helper function add_disks() does the two pass loop and calls into
add_disk_to_super() and update_metadata(). Factoring out the
latter two helpers also helps to reduce a ton of indentation.
No functional changes intended.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 382 +++++++++++++++++++++++++++++++------------------------
1 file changed, 213 insertions(+), 169 deletions(-)
diff --git a/Create.c b/Create.c
index 8ded81dc..6a044664 100644
--- a/Create.c
+++ b/Create.c
@@ -91,6 +91,214 @@ int default_layout(struct supertype *st, int level, int verbose)
return layout;
}
+static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
+ struct supertype *st, struct mddev_dev *dv,
+ struct mdinfo *info, int have_container, int major_num)
+{
+ dev_t rdev;
+ int fd;
+
+ if (dv->disposition == 'j') {
+ info->disk.raid_disk = MD_DISK_ROLE_JOURNAL;
+ info->disk.state = (1<<MD_DISK_JOURNAL);
+ } else if (info->disk.raid_disk < s->raiddisks) {
+ info->disk.state = (1<<MD_DISK_ACTIVE) |
+ (1<<MD_DISK_SYNC);
+ } else {
+ info->disk.state = 0;
+ }
+
+ if (dv->writemostly == FlagSet) {
+ if (major_num == BITMAP_MAJOR_CLUSTERED) {
+ pr_err("Can not set %s --write-mostly with a clustered bitmap\n",dv->devname);
+ return 1;
+ } else {
+ info->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
+ }
+
+ }
+
+ if (dv->failfast == FlagSet)
+ info->disk.state |= (1<<MD_DISK_FAILFAST);
+
+ if (have_container) {
+ fd = -1;
+ } else {
+ if (st->ss->external && st->container_devnm[0])
+ fd = open(dv->devname, O_RDWR);
+ else
+ fd = open(dv->devname, O_RDWR|O_EXCL);
+
+ if (fd < 0) {
+ pr_err("failed to open %s after earlier success - aborting\n",
+ dv->devname);
+ return 1;
+ }
+ if (!fstat_is_blkdev(fd, dv->devname, &rdev))
+ return 1;
+ info->disk.major = major(rdev);
+ info->disk.minor = minor(rdev);
+ }
+ if (fd >= 0)
+ remove_partitions(fd);
+ if (st->ss->add_to_super(st, &info->disk, fd, dv->devname,
+ dv->data_offset)) {
+ ioctl(mdfd, STOP_ARRAY, NULL);
+ return 1;
+ }
+ st->ss->getinfo_super(st, info, NULL);
+
+ if (have_container && c->verbose > 0)
+ pr_err("Using %s for device %d\n",
+ map_dev(info->disk.major, info->disk.minor, 0),
+ info->disk.number);
+
+ if (!have_container) {
+ /* getinfo_super might have lost these ... */
+ info->disk.major = major(rdev);
+ info->disk.minor = minor(rdev);
+ }
+
+ return 0;
+}
+
+static int update_metadata(int mdfd, struct shape *s, struct supertype *st,
+ struct map_ent **map, struct mdinfo *info,
+ char *chosen_name)
+{
+ struct mdinfo info_new;
+ struct map_ent *me = NULL;
+
+ /* check to see if the uuid has changed due to these
+ * metadata changes, and if so update the member array
+ * and container uuid. Note ->write_init_super clears
+ * the subarray cursor such that ->getinfo_super once
+ * again returns container info.
+ */
+ st->ss->getinfo_super(st, &info_new, NULL);
+ if (st->ss->external && is_container(s->level) &&
+ !same_uuid(info_new.uuid, info->uuid, 0)) {
+ map_update(map, fd2devnm(mdfd),
+ info_new.text_version,
+ info_new.uuid, chosen_name);
+ me = map_by_devnm(map, st->container_devnm);
+ }
+
+ if (st->ss->write_init_super(st)) {
+ st->ss->free_super(st);
+ return 1;
+ }
+
+ /*
+ * Before activating the array, perform extra steps
+ * required to configure the internal write-intent
+ * bitmap.
+ */
+ if (info_new.consistency_policy == CONSISTENCY_POLICY_BITMAP &&
+ st->ss->set_bitmap && st->ss->set_bitmap(st, info)) {
+ st->ss->free_super(st);
+ return 1;
+ }
+
+ /* update parent container uuid */
+ if (me) {
+ char *path = xstrdup(me->path);
+
+ st->ss->getinfo_super(st, &info_new, NULL);
+ map_update(map, st->container_devnm, info_new.text_version,
+ info_new.uuid, path);
+ free(path);
+ }
+
+ flush_metadata_updates(st);
+ st->ss->free_super(st);
+
+ return 0;
+}
+
+static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
+ struct context *c, struct supertype *st,
+ struct map_ent **map, struct mddev_dev *devlist,
+ int total_slots, int have_container, int insert_point,
+ int major_num, char *chosen_name)
+{
+ struct mddev_dev *moved_disk = NULL;
+ int pass, raid_disk_num, dnum;
+ struct mddev_dev *dv;
+ struct mdinfo *infos;
+ int ret = 0;
+
+ infos = xmalloc(sizeof(*infos) * total_slots);
+ enable_fds(total_slots);
+ for (pass = 1; pass <= 2; pass++) {
+ for (dnum = 0, raid_disk_num = 0, dv = devlist; dv;
+ dv = (dv->next) ? (dv->next) : moved_disk, dnum++) {
+ if (dnum >= total_slots)
+ abort();
+ if (dnum == insert_point) {
+ raid_disk_num += 1;
+ moved_disk = dv;
+ continue;
+ }
+ if (strcasecmp(dv->devname, "missing") == 0) {
+ raid_disk_num += 1;
+ continue;
+ }
+ if (have_container)
+ moved_disk = NULL;
+ if (have_container && dnum < total_slots - 1)
+ /* repeatedly use the container */
+ moved_disk = dv;
+
+ switch(pass) {
+ case 1:
+ infos[dnum] = *info;
+ infos[dnum].disk.number = dnum;
+ infos[dnum].disk.raid_disk = raid_disk_num++;
+
+ if (dv->disposition == 'j')
+ raid_disk_num--;
+
+ ret = add_disk_to_super(mdfd, s, c, st, dv,
+ &infos[dnum], have_container,
+ major_num);
+ if (ret)
+ goto out;
+
+ break;
+ case 2:
+ infos[dnum].errors = 0;
+
+ ret = add_disk(mdfd, st, info, &infos[dnum]);
+ if (ret) {
+ pr_err("ADD_NEW_DISK for %s failed: %s\n",
+ dv->devname, strerror(errno));
+ if (errno == EINVAL &&
+ info->array.level == 0) {
+ pr_err("Possibly your kernel doesn't support RAID0 layouts.\n");
+ pr_err("Either upgrade, or use --layout=dangerous\n");
+ }
+ goto out;
+ }
+ break;
+ }
+ if (!have_container &&
+ dv == moved_disk && dnum != insert_point) break;
+ }
+
+ if (pass == 1) {
+ ret = update_metadata(mdfd, s, st, map, info,
+ chosen_name);
+ if (ret)
+ goto out;
+ }
+ }
+
+out:
+ free(infos);
+ return ret;
+}
+
int Create(struct supertype *st, char *mddev,
char *name, int *uuid,
int subdevs, struct mddev_dev *devlist,
@@ -117,7 +325,7 @@ int Create(struct supertype *st, char *mddev,
unsigned long long minsize = 0, maxsize = 0;
char *mindisc = NULL;
char *maxdisc = NULL;
- int dnum, raid_disk_num;
+ int dnum;
struct mddev_dev *dv;
dev_t rdev;
int fail = 0, warn = 0;
@@ -126,14 +334,13 @@ int Create(struct supertype *st, char *mddev,
int missing_disks = 0;
int insert_point = subdevs * 2; /* where to insert a missing drive */
int total_slots;
- int pass;
int rv;
int bitmap_fd;
int have_container = 0;
int container_fd = -1;
int need_mdmon = 0;
unsigned long long bitmapsize;
- struct mdinfo info, *infos;
+ struct mdinfo info;
int did_default = 0;
int do_default_layout = 0;
int do_default_chunk = 0;
@@ -869,174 +1076,11 @@ int Create(struct supertype *st, char *mddev,
}
}
- infos = xmalloc(sizeof(*infos) * total_slots);
- enable_fds(total_slots);
- for (pass = 1; pass <= 2; pass++) {
- struct mddev_dev *moved_disk = NULL; /* the disk that was moved out of the insert point */
-
- for (dnum = 0, raid_disk_num = 0, dv = devlist; dv;
- dv = (dv->next) ? (dv->next) : moved_disk, dnum++) {
- int fd;
- struct mdinfo *inf = &infos[dnum];
-
- if (dnum >= total_slots)
- abort();
- if (dnum == insert_point) {
- raid_disk_num += 1;
- moved_disk = dv;
- continue;
- }
- if (strcasecmp(dv->devname, "missing") == 0) {
- raid_disk_num += 1;
- continue;
- }
- if (have_container)
- moved_disk = NULL;
- if (have_container && dnum < info.array.raid_disks - 1)
- /* repeatedly use the container */
- moved_disk = dv;
-
- switch(pass) {
- case 1:
- *inf = info;
-
- inf->disk.number = dnum;
- inf->disk.raid_disk = raid_disk_num++;
-
- if (dv->disposition == 'j') {
- inf->disk.raid_disk = MD_DISK_ROLE_JOURNAL;
- inf->disk.state = (1<<MD_DISK_JOURNAL);
- raid_disk_num--;
- } else if (inf->disk.raid_disk < s->raiddisks)
- inf->disk.state = (1<<MD_DISK_ACTIVE) |
- (1<<MD_DISK_SYNC);
- else
- inf->disk.state = 0;
-
- if (dv->writemostly == FlagSet) {
- if (major_num == BITMAP_MAJOR_CLUSTERED) {
- pr_err("Can not set %s --write-mostly with a clustered bitmap\n",dv->devname);
- goto abort_locked;
- } else
- inf->disk.state |= (1<<MD_DISK_WRITEMOSTLY);
- }
- if (dv->failfast == FlagSet)
- inf->disk.state |= (1<<MD_DISK_FAILFAST);
-
- if (have_container)
- fd = -1;
- else {
- if (st->ss->external &&
- st->container_devnm[0])
- fd = open(dv->devname, O_RDWR);
- else
- fd = open(dv->devname, O_RDWR|O_EXCL);
-
- if (fd < 0) {
- pr_err("failed to open %s after earlier success - aborting\n",
- dv->devname);
- goto abort_locked;
- }
- if (!fstat_is_blkdev(fd, dv->devname, &rdev))
- goto abort_locked;
- inf->disk.major = major(rdev);
- inf->disk.minor = minor(rdev);
- }
- if (fd >= 0)
- remove_partitions(fd);
- if (st->ss->add_to_super(st, &inf->disk,
- fd, dv->devname,
- dv->data_offset)) {
- ioctl(mdfd, STOP_ARRAY, NULL);
- goto abort_locked;
- }
- st->ss->getinfo_super(st, inf, NULL);
-
- if (have_container && c->verbose > 0)
- pr_err("Using %s for device %d\n",
- map_dev(inf->disk.major,
- inf->disk.minor,
- 0), dnum);
-
- if (!have_container) {
- /* getinfo_super might have lost these ... */
- inf->disk.major = major(rdev);
- inf->disk.minor = minor(rdev);
- }
- break;
- case 2:
- inf->errors = 0;
-
- rv = add_disk(mdfd, st, &info, inf);
-
- if (rv) {
- pr_err("ADD_NEW_DISK for %s failed: %s\n",
- dv->devname, strerror(errno));
- if (errno == EINVAL &&
- info.array.level == 0) {
- pr_err("Possibly your kernel doesn't support RAID0 layouts.\n");
- pr_err("Either upgrade, or use --layout=dangerous\n");
- }
- goto abort_locked;
- }
- break;
- }
- if (!have_container &&
- dv == moved_disk && dnum != insert_point) break;
- }
- if (pass == 1) {
- struct mdinfo info_new;
- struct map_ent *me = NULL;
-
- /* check to see if the uuid has changed due to these
- * metadata changes, and if so update the member array
- * and container uuid. Note ->write_init_super clears
- * the subarray cursor such that ->getinfo_super once
- * again returns container info.
- */
- st->ss->getinfo_super(st, &info_new, NULL);
- if (st->ss->external && !is_container(s->level) &&
- !same_uuid(info_new.uuid, info.uuid, 0)) {
- map_update(&map, fd2devnm(mdfd),
- info_new.text_version,
- info_new.uuid, chosen_name);
- me = map_by_devnm(&map, st->container_devnm);
- }
-
- if (st->ss->write_init_super(st)) {
- st->ss->free_super(st);
- goto abort_locked;
- }
- /*
- * Before activating the array, perform extra steps
- * required to configure the internal write-intent
- * bitmap.
- */
- if (info_new.consistency_policy ==
- CONSISTENCY_POLICY_BITMAP &&
- st->ss->set_bitmap &&
- st->ss->set_bitmap(st, &info)) {
- st->ss->free_super(st);
- goto abort_locked;
- }
-
- /* update parent container uuid */
- if (me) {
- char *path = xstrdup(me->path);
-
- st->ss->getinfo_super(st, &info_new, NULL);
- map_update(&map, st->container_devnm,
- info_new.text_version,
- info_new.uuid, path);
- free(path);
- }
+ if (add_disks(mdfd, &info, s, c, st, &map, devlist, total_slots,
+ have_container, insert_point, major_num, chosen_name))
+ goto abort_locked;
- flush_metadata_updates(st);
- st->ss->free_super(st);
- }
- }
map_unlock(&map);
- free(infos);
if (is_container(s->level)) {
/* No need to start. But we should signal udev to
--
2.38.1

View File

@ -0,0 +1,72 @@
From 9364dbfb264e89ab9467dfc0d2b813033e320640 Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:32 -0700
Subject: [PATCH 102/125] mdadm: Introduce pr_info()
Feedback was given to avoid informational pr_err() calls that print
to stderr, even though that's done all through out the code.
Using printf() directly doesn't maintain the same format (an "mdadm"
prefix on every line.
So introduce pr_info() which prints to stdout with the same format
and use it for a couple informational pr_err() calls in Create().
Future work can make this call used in more cases.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Acked-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 7 ++++---
mdadm.h | 2 ++
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/Create.c b/Create.c
index 6a044664..4acda30c 100644
--- a/Create.c
+++ b/Create.c
@@ -984,11 +984,12 @@ int Create(struct supertype *st, char *mddev,
mdi = sysfs_read(-1, devnm, GET_VERSION);
- pr_err("Creating array inside %s container %s\n",
+ pr_info("Creating array inside %s container %s\n",
mdi?mdi->text_version:"managed", devnm);
sysfs_free(mdi);
} else
- pr_err("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,
@@ -1145,7 +1146,7 @@ int Create(struct supertype *st, char *mddev,
ioctl(mdfd, RESTART_ARRAY_RW, NULL);
}
if (c->verbose >= 0)
- pr_err("array %s started.\n", mddev);
+ pr_info("array %s started.\n", mddev);
if (st->ss->external && st->container_devnm[0]) {
if (need_mdmon)
start_mdmon(st->container_devnm);
diff --git a/mdadm.h b/mdadm.h
index 1674ce13..4336be4d 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1854,6 +1854,8 @@ static inline int xasprintf(char **strp, const char *fmt, ...) {
#endif
#define cont_err(fmt ...) fprintf(stderr, " " fmt)
+#define pr_info(fmt, args...) printf("%s: "fmt, Name, ##args)
+
void *xmalloc(size_t len);
void *xrealloc(void *ptr, size_t len);
void *xcalloc(size_t num, size_t size);
--
2.38.1

View File

@ -0,0 +1,346 @@
From 577fd10486d8d1472a6b559066f344ac30a3a391 Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:33 -0700
Subject: [PATCH 103/125] mdadm: Add --write-zeros option for Create
Add the --write-zeros option for Create which will send a write zeros
request to all the disks before assembling the array. After zeroing
the array, the disks will be in a known clean state and the initial
sync may be skipped.
Writing zeroes is best used when there is a hardware offload method
to zero the data. But even still, zeroing can take several minutes on
a large device. Because of this, all disks are zeroed in parallel using
their own forked process and a message is printed to the user. The main
process will proceed only after all the zeroing processes have completed
successfully.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
ReadMe.c | 2 +
mdadm.c | 9 +++
mdadm.h | 5 ++
4 files changed, 190 insertions(+), 2 deletions(-)
diff --git a/Create.c b/Create.c
index 4acda30c..bbe9e13d 100644
--- a/Create.c
+++ b/Create.c
@@ -26,6 +26,10 @@
#include "md_u.h"
#include "md_p.h"
#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <sys/wait.h>
static int round_size_and_verify(unsigned long long *size, int chunk)
{
@@ -91,9 +95,149 @@ int default_layout(struct supertype *st, int level, int verbose)
return layout;
}
+static pid_t write_zeroes_fork(int fd, struct shape *s, struct supertype *st,
+ struct mddev_dev *dv)
+
+{
+ const unsigned long long req_size = 1 << 30;
+ unsigned long long offset_bytes, size_bytes, sz;
+ sigset_t sigset;
+ int ret = 0;
+ pid_t pid;
+
+ size_bytes = KIB_TO_BYTES(s->size);
+
+ /*
+ * If size_bytes is zero, this is a zoned raid array where
+ * each disk is of a different size and uses its full
+ * disk. Thus zero the entire disk.
+ */
+ if (!size_bytes && !get_dev_size(fd, dv->devname, &size_bytes))
+ return -1;
+
+ if (dv->data_offset != INVALID_SECTORS)
+ offset_bytes = SEC_TO_BYTES(dv->data_offset);
+ else
+ offset_bytes = SEC_TO_BYTES(st->data_offset);
+
+ pr_info("zeroing data from %lld to %lld on: %s\n",
+ offset_bytes, size_bytes, dv->devname);
+
+ pid = fork();
+ if (pid < 0) {
+ pr_err("Could not fork to zero disks: %s\n", strerror(errno));
+ return pid;
+ } else if (pid != 0) {
+ return pid;
+ }
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+
+ while (size_bytes) {
+ /*
+ * Split requests to the kernel into 1GB chunks seeing the
+ * fallocate() call is not interruptible and blocking a
+ * ctrl-c for several minutes is not desirable.
+ *
+ * 1GB is chosen as a compromise: the user may still have
+ * to wait several seconds if they ctrl-c on devices that
+ * zero slowly, but will reduce the number of requests
+ * required and thus the overhead on devices that perform
+ * better.
+ */
+ sz = size_bytes;
+ if (sz >= req_size)
+ sz = req_size;
+
+ if (fallocate(fd, FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE,
+ offset_bytes, sz)) {
+ pr_err("zeroing %s failed: %s\n", dv->devname,
+ strerror(errno));
+ ret = 1;
+ break;
+ }
+
+ offset_bytes += sz;
+ size_bytes -= sz;
+ }
+
+ exit(ret);
+}
+
+static int wait_for_zero_forks(int *zero_pids, int count)
+{
+ int wstatus, ret = 0, i, sfd, wait_count = 0;
+ struct signalfd_siginfo fdsi;
+ bool interrupted = false;
+ sigset_t sigset;
+ ssize_t s;
+
+ for (i = 0; i < count; i++)
+ if (zero_pids[i])
+ wait_count++;
+ if (!wait_count)
+ return 0;
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigaddset(&sigset, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &sigset, NULL);
+
+ sfd = signalfd(-1, &sigset, 0);
+ if (sfd < 0) {
+ pr_err("Unable to create signalfd: %s\n", strerror(errno));
+ return 1;
+ }
+
+ while (1) {
+ s = read(sfd, &fdsi, sizeof(fdsi));
+ if (s != sizeof(fdsi)) {
+ pr_err("Invalid signalfd read: %s\n", strerror(errno));
+ close(sfd);
+ return 1;
+ }
+
+ if (fdsi.ssi_signo == SIGINT) {
+ printf("\n");
+ pr_info("Interrupting zeroing processes, please wait...\n");
+ interrupted = true;
+ } else if (fdsi.ssi_signo == SIGCHLD) {
+ if (!--wait_count)
+ break;
+ }
+ }
+
+ close(sfd);
+
+ for (i = 0; i < count; i++) {
+ if (!zero_pids[i])
+ continue;
+
+ waitpid(zero_pids[i], &wstatus, 0);
+ zero_pids[i] = 0;
+ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus))
+ ret = 1;
+ }
+
+ if (interrupted) {
+ pr_err("zeroing interrupted!\n");
+ return 1;
+ }
+
+ if (ret)
+ pr_err("zeroing failed!\n");
+ else
+ pr_info("zeroing finished\n");
+
+ return ret;
+}
+
static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
struct supertype *st, struct mddev_dev *dv,
- struct mdinfo *info, int have_container, int major_num)
+ struct mdinfo *info, int have_container, int major_num,
+ int *zero_pid)
{
dev_t rdev;
int fd;
@@ -148,6 +292,14 @@ static int add_disk_to_super(int mdfd, struct shape *s, struct context *c,
}
st->ss->getinfo_super(st, info, NULL);
+ if (fd >= 0 && s->write_zeroes) {
+ *zero_pid = write_zeroes_fork(fd, s, st, dv);
+ if (*zero_pid <= 0) {
+ ioctl(mdfd, STOP_ARRAY, NULL);
+ return 1;
+ }
+ }
+
if (have_container && c->verbose > 0)
pr_err("Using %s for device %d\n",
map_dev(info->disk.major, info->disk.minor, 0),
@@ -224,10 +376,23 @@ static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
{
struct mddev_dev *moved_disk = NULL;
int pass, raid_disk_num, dnum;
+ int zero_pids[total_slots];
struct mddev_dev *dv;
struct mdinfo *infos;
+ sigset_t sigset, orig_sigset;
int ret = 0;
+ /*
+ * Block SIGINT so the main thread will always wait for the
+ * zeroing processes when being interrupted. Otherwise the
+ * zeroing processes will finish their work in the background
+ * keeping the disk busy.
+ */
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigprocmask(SIG_BLOCK, &sigset, &orig_sigset);
+ memset(zero_pids, 0, sizeof(zero_pids));
+
infos = xmalloc(sizeof(*infos) * total_slots);
enable_fds(total_slots);
for (pass = 1; pass <= 2; pass++) {
@@ -261,7 +426,7 @@ static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
ret = add_disk_to_super(mdfd, s, c, st, dv,
&infos[dnum], have_container,
- major_num);
+ major_num, &zero_pids[dnum]);
if (ret)
goto out;
@@ -287,6 +452,10 @@ static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
}
if (pass == 1) {
+ ret = wait_for_zero_forks(zero_pids, total_slots);
+ if (ret)
+ goto out;
+
ret = update_metadata(mdfd, s, st, map, info,
chosen_name);
if (ret)
@@ -295,7 +464,10 @@ static int add_disks(int mdfd, struct mdinfo *info, struct shape *s,
}
out:
+ if (ret)
+ wait_for_zero_forks(zero_pids, total_slots);
free(infos);
+ sigprocmask(SIG_SETMASK, &orig_sigset, NULL);
return ret;
}
diff --git a/ReadMe.c b/ReadMe.c
index bd8d50d2..db251ed2 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -138,6 +138,7 @@ struct option long_options[] = {
{"size", 1, 0, 'z'},
{"auto", 1, 0, Auto}, /* also for --assemble */
{"assume-clean",0,0, AssumeClean },
+ {"write-zeroes",0,0, WriteZeroes },
{"metadata", 1, 0, 'e'}, /* superblock format */
{"bitmap", 1, 0, Bitmap},
{"bitmap-chunk", 1, 0, BitmapChunk},
@@ -390,6 +391,7 @@ char Help_create[] =
" --write-journal= : Specify journal device for RAID-4/5/6 array\n"
" --consistency-policy= : Specify the policy that determines how the array\n"
" -k : maintains consistency in case of unexpected shutdown.\n"
+" --write-zeroes : Write zeroes to the disks before creating. This will bypass initial sync.\n"
"\n"
;
diff --git a/mdadm.c b/mdadm.c
index 57e8e6fa..4685ad6b 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -590,6 +590,10 @@ int main(int argc, char *argv[])
s.assume_clean = 1;
continue;
+ case O(CREATE, WriteZeroes):
+ s.write_zeroes = 1;
+ continue;
+
case O(GROW,'n'):
case O(CREATE,'n'):
case O(BUILD,'n'): /* number of raid disks */
@@ -1251,6 +1255,11 @@ int main(int argc, char *argv[])
}
}
+ if (s.write_zeroes && !s.assume_clean) {
+ pr_info("Disk zeroing requested, setting --assume-clean to skip resync\n");
+ s.assume_clean = 1;
+ }
+
if (!mode && devs_found) {
mode = MISC;
devmode = 'Q';
diff --git a/mdadm.h b/mdadm.h
index 4336be4d..b9127f9a 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -275,6 +275,9 @@ static inline void __put_unaligned32(__u32 val, void *p)
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define KIB_TO_BYTES(x) ((x) << 10)
+#define SEC_TO_BYTES(x) ((x) << 9)
+
extern const char Name[];
struct md_bb_entry {
@@ -435,6 +438,7 @@ extern char Version[], Usage[], Help[], OptionHelp[],
*/
enum special_options {
AssumeClean = 300,
+ WriteZeroes,
BitmapChunk,
WriteBehind,
ReAdd,
@@ -640,6 +644,7 @@ struct shape {
int bitmap_chunk;
char *bitmap_file;
int assume_clean;
+ bool write_zeroes;
int write_behind;
unsigned long long size;
unsigned long long data_offset;
--
2.38.1

View File

@ -0,0 +1,44 @@
From c918cf2af993b55bca9f396c79713e54d3f8b6fb Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:34 -0700
Subject: [PATCH 104/125] tests/00raid5-zero: Introduce test to exercise
--write-zeros.
Attempt to create a raid5 array with --write-zeros. If it is successful
check the array to ensure it is in sync.
If it is unsuccessful and an unsupported error is printed, skip the
test.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/00raid5-zero | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 tests/00raid5-zero
diff --git a/tests/00raid5-zero b/tests/00raid5-zero
new file mode 100644
index 00000000..7d0f05a1
--- /dev/null
+++ b/tests/00raid5-zero
@@ -0,0 +1,12 @@
+
+if mdadm -CfR $md0 -l 5 -n3 $dev0 $dev1 $dev2 --write-zeroes ; then
+ check nosync
+ echo check > /sys/block/md0/md/sync_action;
+ check wait
+elif grep "zeroing [^ ]* failed: Operation not supported" \
+ $targetdir/stderr; then
+ echo "write-zeros not supported, skipping"
+else
+ echo >&2 "ERROR: mdadm return failure without not supported message"
+ exit 1
+fi
--
2.38.1

View File

@ -0,0 +1,56 @@
From 33831d845a48b9a2ac4d1e954c88a3dd8cb15753 Mon Sep 17 00:00:00 2001
From: Logan Gunthorpe <logang@deltatee.com>
Date: Wed, 1 Mar 2023 13:41:35 -0700
Subject: [PATCH 105/125] manpage: Add --write-zeroes option to manpage
Document the new --write-zeroes option in the manpage.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
Acked-by: Kinga Tanska <kinga.tanska@linux.intel.com>
Reviewed-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Acked-by: Coly Li <colyli@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdadm.8.in | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/mdadm.8.in b/mdadm.8.in
index 64f71ed1..6f0f6c13 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -837,6 +837,22 @@ array is resynced at creation. From Linux version 3.0,
.B \-\-assume\-clean
can be used with that command to avoid the automatic resync.
+.TP
+.BR \-\-write-zeroes
+When creating an array, send write zeroes requests to all the block
+devices. This should zero the data area on all disks such that the
+initial sync is not necessary and, if successfull, will behave
+as if
+.B \-\-assume\-clean
+was specified.
+.IP
+This is intended for use with devices that have hardware offload for
+zeroing, but despite this zeroing can still take several minutes for
+large disks. Thus a message is printed before and after zeroing and
+each disk is zeroed in parallel with the others.
+.IP
+This is only meaningful with --create.
+
.TP
.BR \-\-backup\-file=
This is needed when
@@ -1370,7 +1386,7 @@ and
.B layout\-alternate
options are for RAID0 arrays with non-uniform devices size that were in
use before Linux 5.4. If the array was being used with Linux 3.13 or
-earlier, then to assemble the array on a new kernel,
+earlier, then to assemble the array on a new kernel,
.B \-\-update=layout\-original
must be given. If the array was created and used with a kernel from Linux 3.14 to
Linux 5.3, then
--
2.38.1

View File

@ -0,0 +1,53 @@
From 566844b93e6823a04ed65827ba3e03cb123b3a03 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Wed, 18 Jan 2023 00:32:36 -0800
Subject: [PATCH 106/125] Define alignof using _Alignof when using C11 or newer
WG14 N2350 made very clear that it is an UB having type definitions
within "offsetof" [1]. This patch enhances the implementation of macro
alignof_slot to use builtin "_Alignof" to avoid undefined behavior on
when using std=c11 or newer
clang 16+ has started to flag this [2]
Fixes build when using -std >= gnu11 and using clang16+
Older compilers gcc < 4.9 or clang < 8 has buggy _Alignof even though it
may support C11, exclude those compilers too
[1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
[2] https://reviews.llvm.org/D133574
Upstream-Status: Pending
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
sha1.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/sha1.c b/sha1.c
index 89b32f46..1e4ad5d9 100644
--- a/sha1.c
+++ b/sha1.c
@@ -229,7 +229,17 @@ sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
if (len >= 64)
{
#if !_STRING_ARCH_unaligned
-# define alignof(type) offsetof (struct { char c; type x; }, x)
+/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023
+ <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.
+ clang versions < 8.0.0 have the same bug. */
+# if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
+ || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
+ && !defined __clang__) \
+ || (defined __clang__ && __clang_major__ < 8))
+# define alignof(type) offsetof (struct { char c; type x; }, x)
+# else
+# define alignof(type) _Alignof(type)
+# endif
# define UNALIGNED_P(p) (((size_t) p) % alignof (sha1_uint32) != 0)
if (UNALIGNED_P (buffer))
while (len > 64)
--
2.38.1

View File

@ -0,0 +1,41 @@
From eb45d0add7cf2918f838bec2d93d99cf2d9c662f Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Mon, 13 Mar 2023 14:42:58 +1100
Subject: [PATCH 107/125] Use existence of /etc/initrd-release to detect
initrd.
Since v183, systemd has used the existence of /etc/initrd-release to
detect if it is running in an initrd, rather than looking at the magic
number of the root filesystem's device. It is time for mdadm to do the
same.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
util.c | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/util.c b/util.c
index 9f1e1f7c..509fb43e 100644
--- a/util.c
+++ b/util.c
@@ -2227,15 +2227,7 @@ int continue_via_systemd(char *devnm, char *service_name)
int in_initrd(void)
{
- /* This is based on similar function in systemd. */
- struct statfs s;
- /* statfs.f_type is signed long on s390x and MIPS, causing all
- sorts of sign extension problems with RAMFS_MAGIC being
- defined as 0x858458f6 */
- return statfs("/", &s) >= 0 &&
- ((unsigned long)s.f_type == TMPFS_MAGIC ||
- ((unsigned long)s.f_type & 0xFFFFFFFFUL) ==
- ((unsigned long)RAMFS_MAGIC & 0xFFFFFFFFUL));
+ return access("/etc/initrd-release", F_OK) >= 0;
}
void reopen_mddev(int mdfd)
--
2.38.1

View File

@ -0,0 +1,47 @@
From d39fd87e31024804dd7f2c16c03af0379b71f5f1 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Mon, 13 Mar 2023 14:42:58 +1100
Subject: [PATCH 108/125] mdmon: don't test both 'all' and 'container_name'.
If 'all' is not set, then container_name must be NULL, as nothing else
can set it. So simplify the test to ignore container_name.
This makes the purpose of the code more obvious.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdmon.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/mdmon.c b/mdmon.c
index 60ba3182..f8fd2f0f 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -352,7 +352,6 @@ int main(int argc, char *argv[])
}
}
-
if (in_initrd()) {
/*
* set first char of argv[0] to @. This is used by
@@ -362,12 +361,10 @@ int main(int argc, char *argv[])
argv[0][0] = '@';
}
- if (all == 0 && container_name == NULL) {
- if (argv[optind]) {
- container_name = get_md_name(argv[optind]);
- if (!container_name)
- return 1;
- }
+ if (!all && argv[optind]) {
+ container_name = get_md_name(argv[optind]);
+ if (!container_name)
+ return 1;
}
if (container_name == NULL || argc - optind > 1)
--
2.38.1

View File

@ -0,0 +1,33 @@
From 6660e33edde76329bd3b7f03383856c7efee2aa9 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Mon, 13 Mar 2023 14:42:58 +1100
Subject: [PATCH 109/125] mdmon: change systemd unit file to use --foreground
There is no value in mdmon forking when it is running under systemd -
systemd can still track it anyway.
So add --foreground option, and remove "Type=forking".
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
systemd/mdmon@.service | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service
index cb6482d9..bba9b0eb 100644
--- a/systemd/mdmon@.service
+++ b/systemd/mdmon@.service
@@ -20,8 +20,7 @@ Environment=IMSM_NO_PLATFORM=1
# 'takeover'. As the '--offroot --takeover' don't hurt when
# not necessary, are are useful with root-on-md in dracut,
# have them always present.
-ExecStart=BINDIR/mdmon --offroot --takeover %I
-Type=forking
+ExecStart=BINDIR/mdmon --foreground --offroot --takeover %I
# Don't set the PIDFile. It isn't necessary (systemd can work
# it out) and systemd will remove it when transitioning from
# initramfs to rootfs.
--
2.38.1

View File

@ -0,0 +1,55 @@
From 0f9a4b3e11fbe4f8631d20b1f89cf43e9219db55 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Mon, 13 Mar 2023 14:42:58 +1100
Subject: [PATCH 110/125] mdmon: Remove need for KillMode=none
mdmon needs to keep running during the switchroot out of (at boot) and
then back into (at shutdown) the initrd. It runs until a new mdmon
takes over.
Killmode=none is used to achieve this, with the help of --offroot which
sets argv[0][0] to '@' which systemd understands.
This is needed because mdmon is currently run in system-mdmon.slice
which conflicts with shutdown.target so without Killmode=none mdmon
would get killed early in shutdown when system.mdmon.slice is removed.
As described in systemd.service(5), this conflict with shutdown can be
resolved by explicitly requesting system.slice, which is a natural
counterpart to DefaultDependencies=no.
So add that, and also add IgnoreOnIsolate=true to avoid another possible
source of an early death. With these we no longer need KillMode=none
which the systemd developers have marked as "deprecated".
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
systemd/mdmon@.service | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service
index bba9b0eb..303ad05c 100644
--- a/systemd/mdmon@.service
+++ b/systemd/mdmon@.service
@@ -10,6 +10,9 @@ Description=MD Metadata Monitor on /dev/%I
DefaultDependencies=no
Before=initrd-switch-root.target
Documentation=man:mdmon(8)
+# Allow mdmon to keep running after switchroot, until a new
+# instance is started.
+IgnoreOnIsolate=true
[Service]
# mdmon should never complain due to lack of a platform,
@@ -25,4 +28,6 @@ ExecStart=BINDIR/mdmon --foreground --offroot --takeover %I
# it out) and systemd will remove it when transitioning from
# initramfs to rootfs.
#PIDFile=/run/mdadm/%I.pid
-KillMode=none
+# The default slice is system-mdmon.slice which Conflicts
+# with shutdown, causing mdmon to exit early. So use system.slice.
+Slice=system.slice
--
2.38.1

View File

@ -0,0 +1,166 @@
From 723d1df4946eb40337bf494f9b2549500c1399b2 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Mon, 13 Mar 2023 14:42:58 +1100
Subject: [PATCH 111/125] mdmon: Improve switchroot interactions.
We need a new mdmon@mdfoo instance to run in the root filesystem after
switch root, as /sys and /dev are removed from the initrd.
systemd will not start a new unit with the same name running while the
old unit is still active, and we want the two mdmon processes to overlap
in time to avoid any risk of deadlock, which can happen when a write is
attempted with no mdmon running.
So we need a different unit name in the initrd than in the root. Apart
from the name, everything else should be the same.
This is easily achieved using a different instance name as the
mdmon@.service unit file already supports multiple instances (for
different arrays).
So start "mdmon@mdfoo.service" from root, but
"mdmon@initrd-mdfoo.service" from the initrd. udev can tell which
circumstance is the case by looking for /etc/initrd-release.
continue_from_systemd() is enhanced so that the "initrd-" prefix can be
requested.
Teach mdmon that a container name like "initrd/foo" should be treated
just like "foo". Note that systemd passes the instance name
"initrd-foo" as "initrd/foo".
We don't need a similar mechanism at shutdown because dracut runs
"mdmon --takeover --all" when appropriate.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Grow.c | 4 ++--
mdadm.h | 2 +-
mdmon.c | 7 ++++++-
systemd/mdmon@.service | 2 +-
udev-md-raid-arrays.rules | 3 ++-
util.c | 7 ++++---
6 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/Grow.c b/Grow.c
index bb5fe45c..06001f2d 100644
--- a/Grow.c
+++ b/Grow.c
@@ -3516,7 +3516,7 @@ started:
if (!forked)
if (continue_via_systemd(container ?: sra->sys_name,
- GROW_SERVICE)) {
+ GROW_SERVICE, NULL)) {
free(fdlist);
free(offsets);
sysfs_free(sra);
@@ -3714,7 +3714,7 @@ int reshape_container(char *container, char *devname,
ping_monitor(container);
if (!forked && !freeze_reshape)
- if (continue_via_systemd(container, GROW_SERVICE))
+ if (continue_via_systemd(container, GROW_SERVICE, NULL))
return 0;
switch (forked ? 0 : fork()) {
diff --git a/mdadm.h b/mdadm.h
index b9127f9a..1e518276 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1608,7 +1608,7 @@ extern int same_dev(char *one, char *two);
extern int compare_paths (char* path1,char* path2);
extern void enable_fds(int devices);
extern void manage_fork_fds(int close_all);
-extern int continue_via_systemd(char *devnm, char *service_name);
+extern int continue_via_systemd(char *devnm, char *service_name, char *prefix);
extern void ident_init(struct mddev_ident *ident);
diff --git a/mdmon.c b/mdmon.c
index f8fd2f0f..096b4d76 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -362,7 +362,12 @@ int main(int argc, char *argv[])
}
if (!all && argv[optind]) {
- container_name = get_md_name(argv[optind]);
+ static const char prefix[] = "initrd/";
+ container_name = argv[optind];
+ if (strncmp(container_name, prefix,
+ sizeof(prefix) - 1) == 0)
+ container_name += sizeof(prefix)-1;
+ container_name = get_md_name(container_name);
if (!container_name)
return 1;
}
diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service
index 303ad05c..23a375f6 100644
--- a/systemd/mdmon@.service
+++ b/systemd/mdmon@.service
@@ -6,7 +6,7 @@
# (at your option) any later version.
[Unit]
-Description=MD Metadata Monitor on /dev/%I
+Description=MD Metadata Monitor on %I
DefaultDependencies=no
Before=initrd-switch-root.target
Documentation=man:mdmon(8)
diff --git a/udev-md-raid-arrays.rules b/udev-md-raid-arrays.rules
index 2967ace1..4e64b249 100644
--- a/udev-md-raid-arrays.rules
+++ b/udev-md-raid-arrays.rules
@@ -38,7 +38,8 @@ ENV{MD_LEVEL}=="raid[1-9]*", ENV{SYSTEMD_WANTS}+="mdmonitor.service"
# Tell systemd to run mdmon for our container, if we need it.
ENV{MD_LEVEL}=="raid[1-9]*", ENV{MD_CONTAINER}=="?*", PROGRAM="/usr/bin/readlink $env{MD_CONTAINER}", ENV{MD_MON_THIS}="%c"
-ENV{MD_MON_THIS}=="?*", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@%c.service"
+ENV{MD_MON_THIS}=="?*", TEST=="/etc/initrd-release", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@initrd-%c.service"
+ENV{MD_MON_THIS}=="?*", TEST!="/etc/initrd-release", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdmon@%c.service"
ENV{RESHAPE_ACTIVE}=="yes", PROGRAM="/usr/bin/basename $env{MD_MON_THIS}", ENV{SYSTEMD_WANTS}+="mdadm-grow-continue@%c.service"
LABEL="md_end"
diff --git a/util.c b/util.c
index 509fb43e..d70ca43b 100644
--- a/util.c
+++ b/util.c
@@ -1916,6 +1916,7 @@ int start_mdmon(char *devnm)
int len;
pid_t pid;
int status;
+ char *prefix = in_initrd() ? "initrd-" : "";
char pathbuf[1024];
char *paths[4] = {
pathbuf,
@@ -1926,7 +1927,7 @@ int start_mdmon(char *devnm)
if (check_env("MDADM_NO_MDMON"))
return 0;
- if (continue_via_systemd(devnm, MDMON_SERVICE))
+ if (continue_via_systemd(devnm, MDMON_SERVICE, prefix))
return 0;
/* That failed, try running mdmon directly */
@@ -2197,7 +2198,7 @@ void manage_fork_fds(int close_all)
* 1- if systemd service has been started
* 0- otherwise
*/
-int continue_via_systemd(char *devnm, char *service_name)
+int continue_via_systemd(char *devnm, char *service_name, char *prefix)
{
int pid, status;
char pathbuf[1024];
@@ -2209,7 +2210,7 @@ int continue_via_systemd(char *devnm, char *service_name)
case 0:
manage_fork_fds(1);
snprintf(pathbuf, sizeof(pathbuf),
- "%s@%s.service", service_name, devnm);
+ "%s@%s%s.service", service_name, prefix ?: "", devnm);
status = execl("/usr/bin/systemctl", "systemctl", "restart",
pathbuf, NULL);
status = execl("/bin/systemctl", "systemctl", "restart",
--
2.38.1

View File

@ -0,0 +1,40 @@
From 2e10c46d0906b1a1ec40e8f5005ccb63125dcd9e Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Tue, 14 Mar 2023 11:06:25 +1100
Subject: [PATCH 112/125] mdopen: always try create_named_array()
mdopen() will use create_named_array() to ask the kernel to create the
given md array, but only if it is given a number or name.
If it is NOT given a name and is required to choose one itself using
find_free_devnm() it does NOT use create_named_array().
On kernels with CONFIG_BLOCK_LEGACY_AUTOLOAD not set, this can result in
failure to assemble an array. This can particularly seen when the
"name" of the array begins with a host name different to the name of the
host running the command.
So add the missing call to create_named_array().
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217074
Signed-off-by: NeilBrown <neilb@suse.de>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdopen.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/mdopen.c b/mdopen.c
index d18c9319..810f79a3 100644
--- a/mdopen.c
+++ b/mdopen.c
@@ -370,6 +370,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
}
if (block_udev)
udev_block(devnm);
+ create_named_array(devnm);
}
sprintf(devname, "/dev/%s", devnm);
--
2.38.1

View File

@ -0,0 +1,172 @@
From 420dafcd38c5949c2ddb90ad6873e7edd625db30 Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Mon, 20 Mar 2023 14:43:54 +1100
Subject: [PATCH 113/125] Improvements for IMSM_NO_PLATFORM testing.
Factor out IMSM_NO_PLATFORM testing into a single function that caches
the result.
Allow mdmon to explicitly set the result to "1" so that we don't need
the ENV var in the unit file
Check if the kernel command line contains "mdadm.imsm.test=1" and in
that case assert NO_PLATFORM. This simplifies testing in a virtual
machine.
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdadm.8.in | 5 +++++
mdadm.h | 2 ++
mdmon.c | 6 ++++++
super-intel.c | 45 +++++++++++++++++++++++++++++++++++++++---
systemd/mdmon@.service | 3 ---
5 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/mdadm.8.in b/mdadm.8.in
index 6f0f6c13..b7159509 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -3197,6 +3197,11 @@ 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
+.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.
+
.TP
.B MDADM_GROW_ALLOW_OLD
If an array is stopped while it is performing a reshape and that
diff --git a/mdadm.h b/mdadm.h
index 1e518276..0d995445 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1263,6 +1263,8 @@ extern struct superswitch super0, super1;
extern struct superswitch super_imsm, super_ddf;
extern struct superswitch mbr, gpt;
+void imsm_set_no_platform(int v);
+
struct metadata_update {
int len;
char *buf;
diff --git a/mdmon.c b/mdmon.c
index 096b4d76..cef5bbc8 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -318,6 +318,12 @@ int main(int argc, char *argv[])
{NULL, 0, NULL, 0}
};
+ /*
+ * mdmon should never complain due to lack of a platform,
+ * that is mdadm's job if at all.
+ */
+ imsm_set_no_platform(1);
+
while ((opt = getopt_long(argc, argv, "thaF", options, NULL)) != -1) {
switch (opt) {
case 'a':
diff --git a/super-intel.c b/super-intel.c
index e155a8ae..a5c86cb2 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -20,6 +20,7 @@
#define HAVE_STDINT_H 1
#include "mdadm.h"
#include "mdmon.h"
+#include "dlink.h"
#include "sha1.h"
#include "platform-intel.h"
#include <values.h>
@@ -629,6 +630,44 @@ static const char *_sys_dev_type[] = {
[SYS_DEV_VMD] = "VMD"
};
+static int no_platform = -1;
+
+static int check_no_platform(void)
+{
+ static const char search[] = "mdadm.imsm.test=1";
+ FILE *fp;
+
+ if (no_platform >= 0)
+ return no_platform;
+
+ if (check_env("IMSM_NO_PLATFORM")) {
+ no_platform = 1;
+ return 1;
+ }
+ fp = fopen("/proc/cmdline", "r");
+ if (fp) {
+ char *l = conf_line(fp);
+ char *w = l;
+
+ do {
+ if (strcmp(w, search) == 0)
+ no_platform = 1;
+ w = dl_next(w);
+ } while (w != l);
+ free_line(l);
+ fclose(fp);
+ if (no_platform >= 0)
+ return no_platform;
+ }
+ no_platform = 0;
+ return 0;
+}
+
+void imsm_set_no_platform(int v)
+{
+ no_platform = v;
+}
+
const char *get_sys_dev_type(enum sys_dev_type type)
{
if (type >= SYS_DEV_MAX)
@@ -2699,7 +2738,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
int result=1;
if (enumerate_only) {
- if (check_env("IMSM_NO_PLATFORM"))
+ if (check_no_platform())
return 0;
list = find_intel_devices();
if (!list)
@@ -4722,7 +4761,7 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
devname);
return 1;
}
- if (!is_fd_valid(fd) || check_env("IMSM_NO_PLATFORM")) {
+ if (!is_fd_valid(fd) || check_no_platform()) {
super->orom = NULL;
super->hba = NULL;
return 0;
@@ -10697,7 +10736,7 @@ static int imsm_get_allowed_degradation(int level, int raid_disks,
******************************************************************************/
int validate_container_imsm(struct mdinfo *info)
{
- if (check_env("IMSM_NO_PLATFORM"))
+ if (check_no_platform())
return 0;
struct sys_dev *idev;
diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service
index 23a375f6..020cc7e1 100644
--- a/systemd/mdmon@.service
+++ b/systemd/mdmon@.service
@@ -15,9 +15,6 @@ Documentation=man:mdmon(8)
IgnoreOnIsolate=true
[Service]
-# mdmon should never complain due to lack of a platform,
-# that is mdadm's job if at all.
-Environment=IMSM_NO_PLATFORM=1
# The mdmon starting in the initramfs (with dracut at least)
# cannot see sysfs after root is mounted, so we will have to
# 'takeover'. As the '--offroot --takeover' don't hurt when
--
2.38.1

View File

@ -0,0 +1,29 @@
From 9b6e3b43381245cb128ad98bf117a565ce5defe5 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 23 Mar 2023 17:13:18 +0100
Subject: [PATCH 114/125] Revert "Revert "mdadm/systemd: remove KillMode=none
from service file""
This reverts commit 28a083955c6f58f8e582734c8c82aff909a7d461.
Resolved by commit 723d1df4946e ("mdmon: Improve switchroot
interactions.") We are ready to drop it.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
systemd/mdadm-grow-continue@.service | 1 -
1 file changed, 1 deletion(-)
diff --git a/systemd/mdadm-grow-continue@.service b/systemd/mdadm-grow-continue@.service
index 9ccadca3..64b8254a 100644
--- a/systemd/mdadm-grow-continue@.service
+++ b/systemd/mdadm-grow-continue@.service
@@ -15,4 +15,3 @@ ExecStart=BINDIR/mdadm --grow --continue /dev/%I
StandardInput=null
StandardOutput=null
StandardError=null
-KillMode=none
--
2.38.1

View File

@ -0,0 +1,38 @@
From ef6236da232e968dcf08b486178cd20d5ea97e2a Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Thu, 23 Mar 2023 12:50:00 +0100
Subject: [PATCH 115/125] Create: Fix checking for container in update_metadata
The commit 8a4ce2c05386 ("Create: Factor out add_disks() helpers")
introduced a regression that caused timeouts and udev failing to create
links.
Steps to reproduce the issue were as following:
$ mdadm -CR imsm -e imsm -n4 /dev/nvme[0-3]n1
$ mdadm -CR vol -l5 -n4 /dev/nvme[0-3]n1 --assume-clean
I found the check for container was wrong because negation was missing.
Fixes: 8a4ce2c05386 ("Create: Factor out add_disks() helpers")
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Create.c b/Create.c
index bbe9e13d..0911bf92 100644
--- a/Create.c
+++ b/Create.c
@@ -328,7 +328,7 @@ static int update_metadata(int mdfd, struct shape *s, struct supertype *st,
* again returns container info.
*/
st->ss->getinfo_super(st, &info_new, NULL);
- if (st->ss->external && is_container(s->level) &&
+ if (st->ss->external && !is_container(s->level) &&
!same_uuid(info_new.uuid, info->uuid, 0)) {
map_update(map, fd2devnm(mdfd),
info_new.text_version,
--
2.38.1

View File

@ -0,0 +1,43 @@
From 890212d6800646153210ac264ce73035cc7dd5cc Mon Sep 17 00:00:00 2001
From: miaoguanqin <miaoguanqin@huawei.com>
Date: Tue, 4 Apr 2023 19:31:24 +0800
Subject: [PATCH 116/125] Fix null pointer for incremental in mdadm
when we excute mdadm --assemble, udev-md-raid-assembly.rules is triggered.
Then we stop array, we found an coredump for mdadm --incremental.func
stack are as follows:
#0 enough (level=10, raid_disks=4, layout=258, clean=1,
avail=avail@entry=0x0) at util.c:555
#1 0x0000562170c26965 in Incremental (devlist=<optimized out>,
c=<optimized out>, st=0x5621729b6dc0) at Incremental.c:514
#2 0x0000562170bfb6ff in main (argc=<optimized out>,
argv=<optimized out>) at mdadm.c:1762
func enough() use array avail,avail allocate space in func count_active,
it may not alloc space, causing a coredump.We fix this coredump.
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
Signed-off-by: lixiaokeng <lixiaokeng@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Incremental.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Incremental.c b/Incremental.c
index 09b94b9f..49a71f72 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -507,6 +507,9 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
GET_OFFSET | GET_SIZE));
active_disks = count_active(st, sra, mdfd, &avail, &info);
+ if (!avail)
+ goto out_unlock;
+
journal_device_missing = (info.journal_device_required) && (info.journal_clean == 0);
if (info.consistency_policy == CONSISTENCY_POLICY_PPL)
--
2.38.1

View File

@ -0,0 +1,33 @@
From 1c6f2a1dbfe17df14dd5b062fc53a60c5c387e47 Mon Sep 17 00:00:00 2001
From: Hristo Venev <hristo@venev.name>
Date: Sat, 1 Apr 2023 23:01:35 +0300
Subject: [PATCH 117/125] super1: fix truncation check for journal device
The journal device can be smaller than the component devices.
Fixes: 171e9743881e ("super1: report truncated device")
Signed-off-by: Hristo Venev <hristo@venev.name>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super1.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/super1.c b/super1.c
index f7020320..44d6ecad 100644
--- a/super1.c
+++ b/super1.c
@@ -2359,8 +2359,9 @@ static int load_super1(struct supertype *st, int fd, char *devname)
if (st->minor_version >= 1 &&
st->ignore_hw_compat == 0 &&
- (dsize < (__le64_to_cpu(super->data_offset) +
- __le64_to_cpu(super->size))
+ ((role_from_sb(super) != MD_DISK_ROLE_JOURNAL &&
+ dsize < (__le64_to_cpu(super->data_offset) +
+ __le64_to_cpu(super->size)))
||
dsize < (__le64_to_cpu(super->data_offset) +
__le64_to_cpu(super->data_size)))) {
--
2.38.1

View File

@ -0,0 +1,433 @@
From d3bb888d885fc96fc6239fbf6c22c63143eba461 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <jes@trained-monkey.org>
Date: Mon, 10 Apr 2023 11:40:42 -0400
Subject: [PATCH 118/125] Fix some cases eyesore formatting
Summary: No functional change .... just make it more readable.
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super1.c | 117 ++++++++++++++++++++++++++++---------------------------
1 file changed, 60 insertions(+), 57 deletions(-)
diff --git a/super1.c b/super1.c
index 44d6ecad..1d20ef55 100644
--- a/super1.c
+++ b/super1.c
@@ -192,7 +192,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
unsigned int disk_csum, csum;
unsigned long long newcsum;
int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
- unsigned int *isuper = (unsigned int*)sb;
+ unsigned int *isuper = (unsigned int *)sb;
/* make sure I can count... */
if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
@@ -204,7 +204,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
disk_csum = sb->sb_csum;
sb->sb_csum = 0;
newcsum = 0;
- for (; size>=4; size -= 4 ) {
+ for (; size >= 4; size -= 4) {
newcsum += __le32_to_cpu(*isuper);
isuper++;
}
@@ -319,7 +319,7 @@ static inline unsigned int choose_ppl_space(int chunk)
static void examine_super1(struct supertype *st, char *homehost)
{
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
time_t atime;
unsigned int d;
int role;
@@ -343,8 +343,9 @@ static void examine_super1(struct supertype *st, char *homehost)
printf(".0\n");
printf(" Feature Map : 0x%x\n", __le32_to_cpu(sb->feature_map));
printf(" Array UUID : ");
- for (i=0; i<16; i++) {
- if ((i&3)==0 && i != 0) printf(":");
+ for (i = 0; i < 16; i++) {
+ if ((i & 3) == 0 && i != 0)
+ printf(":");
printf("%02x", sb->set_uuid[i]);
}
printf("\n");
@@ -416,11 +417,11 @@ static void examine_super1(struct supertype *st, char *homehost)
UINT64_MAX - info.space_after);
}
printf(" State : %s%s\n",
- (__le64_to_cpu(sb->resync_offset)+1) ? "active":"clean",
+ (__le64_to_cpu(sb->resync_offset) + 1) ? "active":"clean",
(info.space_after > INT64_MAX) ? " TRUNCATED DEVICE" : "");
printf(" Device UUID : ");
- for (i=0; i<16; i++) {
- if ((i&3)==0 && i != 0)
+ for (i = 0; i < 16; i++) {
+ if ((i & 3)==0 && i != 0)
printf(":");
printf("%02x", sb->device_uuid[i]);
}
@@ -546,7 +547,7 @@ static void examine_super1(struct supertype *st, char *homehost)
#if 0
/* This turns out to just be confusing */
printf(" Array Slot : %d (", __le32_to_cpu(sb->dev_number));
- for (i = __le32_to_cpu(sb->max_dev); i> 0 ; i--)
+ for (i = __le32_to_cpu(sb->max_dev); i > 0 ; i--)
if (__le16_to_cpu(sb->dev_roles[i-1]) != MD_DISK_ROLE_SPARE)
break;
for (d = 0; d < i; d++) {
@@ -597,7 +598,7 @@ static void examine_super1(struct supertype *st, char *homehost)
#if 0
/* This is confusing too */
faulty = 0;
- for (i = 0; i< __le32_to_cpu(sb->max_dev); i++) {
+ 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++;
@@ -616,10 +617,12 @@ static void examine_super1(struct supertype *st, char *homehost)
if (inconsistent) {
printf("WARNING Array state is inconsistent - each number should appear only once\n");
for (d = 0; d < __le32_to_cpu(sb->max_dev); d++)
- if (__le16_to_cpu(sb->dev_roles[d]) >= MD_DISK_ROLE_FAULTY)
+ if (__le16_to_cpu(sb->dev_roles[d]) >=
+ MD_DISK_ROLE_FAULTY)
printf(" %d:-", d);
else
- printf(" %d:%d", d, __le16_to_cpu(sb->dev_roles[d]));
+ printf(" %d:%d", d,
+ __le16_to_cpu(sb->dev_roles[d]));
printf("\n");
}
}
@@ -659,7 +662,7 @@ static void brief_examine_super1(struct supertype *st, int verbose)
printf("num-devices=%d ", __le32_to_cpu(sb->raid_disks));
printf("UUID=");
for (i = 0; i < 16; i++) {
- if ((i&3)==0 && i != 0)
+ if ((i & 3)==0 && i != 0)
printf(":");
printf("%02x", sb->set_uuid[i]);
}
@@ -713,7 +716,7 @@ static void export_examine_super1(struct supertype *st)
}
printf("MD_UUID=");
for (i = 0; i < 16; i++) {
- if ((i&3) == 0 && i != 0)
+ if ((i & 3) == 0 && i != 0)
printf(":");
printf("%02x", sb->set_uuid[i]);
}
@@ -722,7 +725,7 @@ static void export_examine_super1(struct supertype *st)
__le64_to_cpu(sb->utime) & 0xFFFFFFFFFFULL);
printf("MD_DEV_UUID=");
for (i = 0; i < 16; i++) {
- if ((i&3) == 0 && i != 0)
+ if ((i & 3) == 0 && i != 0)
printf(":");
printf("%02x", sb->device_uuid[i]);
}
@@ -812,7 +815,7 @@ static int copy_metadata1(struct supertype *st, int from, int to)
/* have the header, can calculate
* correct bitmap bytes */
bitmap_super_t *bms;
- bms = (void*)buf;
+ bms = (void *)buf;
bytes = calc_bitmap_size(bms, 512);
if (n > bytes)
n = bytes;
@@ -867,7 +870,7 @@ err:
static void detail_super1(struct supertype *st, char *homehost, char *subarray)
{
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
int i;
int l = homehost ? strlen(homehost) : 0;
@@ -880,7 +883,7 @@ static void detail_super1(struct supertype *st, char *homehost, char *subarray)
printf("\n Cluster Name : %-64s", bms->cluster_name);
printf("\n UUID : ");
for (i = 0; i < 16; i++) {
- if ((i&3) == 0 && i != 0)
+ if ((i & 3) == 0 && i != 0)
printf(":");
printf("%02x", sb->set_uuid[i]);
}
@@ -939,7 +942,7 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname)
}
size = __le16_to_cpu(sb->bblog_size)* 512;
- if (posix_memalign((void**)&bbl, 4096, size) != 0) {
+ if (posix_memalign((void **)&bbl, 4096, size) != 0) {
pr_err("could not allocate badblocks list\n");
return 0;
}
@@ -987,7 +990,7 @@ static int match_home1(struct supertype *st, char *homehost)
static void uuid_from_super1(struct supertype *st, int uuid[4])
{
struct mdp_superblock_1 *super = st->sb;
- char *cuuid = (char*)uuid;
+ char *cuuid = (char *)uuid;
int i;
for (i = 0; i < 16; i++)
cuuid[i] = super->set_uuid[i];
@@ -996,9 +999,9 @@ static void uuid_from_super1(struct supertype *st, int uuid[4])
static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
{
struct mdp_superblock_1 *sb = st->sb;
- struct bitmap_super_s *bsb = (void*)(((char*)sb)+MAX_SB_SIZE);
+ struct bitmap_super_s *bsb = (void *)(((char *)sb) + MAX_SB_SIZE);
struct misc_dev_info *misc =
- (void*)(((char*)sb)+MAX_SB_SIZE+BM_SUPER_SIZE);
+ (void *)(((char *)sb) + MAX_SB_SIZE+BM_SUPER_SIZE);
int working = 0;
unsigned int i;
unsigned int role;
@@ -1166,7 +1169,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info, char *map)
info->recovery_blocked = info->reshape_active;
if (map)
- for (i=0; i<map_disks; i++)
+ for (i = 0; i < map_disks; i++)
map[i] = 0;
for (i = 0; i < __le32_to_cpu(sb->max_dev); i++) {
role = __le16_to_cpu(sb->dev_roles[i]);
@@ -1217,7 +1220,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
*/
int rv = 0;
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
if (update == UOPT_HOMEHOST && homehost) {
/*
@@ -1228,9 +1231,10 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
update = UOPT_NAME;
c = strchr(sb->set_name, ':');
if (c)
- snprintf(info->name, sizeof(info->name), "%s", c+1);
+ snprintf(info->name, sizeof(info->name), "%s", c + 1);
else
- snprintf(info->name, sizeof(info->name), "%s", sb->set_name);
+ snprintf(info->name, sizeof(info->name), "%s",
+ sb->set_name);
}
switch (update) {
@@ -1331,7 +1335,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
sb->dev_number = __cpu_to_le32(i);
if (i == max)
- sb->max_dev = __cpu_to_le32(max+1);
+ sb->max_dev = __cpu_to_le32(max + 1);
if (i > max)
return -2;
@@ -1350,8 +1354,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
sb->data_size = __cpu_to_le64(
ds - __le64_to_cpu(sb->data_offset));
} else {
- ds -= 8*2;
- ds &= ~(unsigned long long)(4*2-1);
+ ds -= 8 * 2;
+ ds &= ~(unsigned long long)(4 * 2 - 1);
sb->super_offset = __cpu_to_le64(ds);
sb->data_size = __cpu_to_le64(
ds - __le64_to_cpu(sb->data_offset));
@@ -1367,7 +1371,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
if (i > max)
return -2;
if (i == max)
- sb->max_dev = __cpu_to_le32(max+1);
+ sb->max_dev = __cpu_to_le32(max + 1);
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
sb->dev_roles[info->disk.number] =
__cpu_to_le16(info->disk.raid_disk);
@@ -1645,7 +1649,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
char defname[10];
int sbsize;
- if (posix_memalign((void**)&sb, 4096, SUPER1_SIZE) != 0) {
+ if (posix_memalign((void **)&sb, 4096, SUPER1_SIZE) != 0) {
pr_err("could not allocate superblock\n");
return 0;
}
@@ -1679,8 +1683,8 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
name = defname;
}
if (homehost &&
- strchr(name, ':')== NULL &&
- strlen(homehost)+1+strlen(name) < 32) {
+ strchr(name, ':') == NULL &&
+ strlen(homehost) + 1 + strlen(name) < 32) {
strcpy(sb->set_name, homehost);
strcat(sb->set_name, ":");
strcat(sb->set_name, name);
@@ -1759,7 +1763,7 @@ static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
if (dk->number >= (int)__le32_to_cpu(sb->max_dev) &&
__le32_to_cpu(sb->max_dev) < MAX_DEVS)
- sb->max_dev = __cpu_to_le32(dk->number+1);
+ sb->max_dev = __cpu_to_le32(dk->number + 1);
sb->dev_number = __cpu_to_le32(dk->number);
sb->devflags = 0; /* don't copy another disks flags */
@@ -1840,8 +1844,8 @@ static int store_super1(struct supertype *st, int fd)
return 4;
if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
- struct bitmap_super_s *bm = (struct bitmap_super_s*)
- (((char*)sb)+MAX_SB_SIZE);
+ struct bitmap_super_s *bm;
+ bm = (struct bitmap_super_s *)(((char *)sb) + MAX_SB_SIZE);
if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
locate_bitmap1(st, fd, 0);
if (awrite(&afd, bm, sizeof(*bm)) != sizeof(*bm))
@@ -1928,7 +1932,7 @@ static int write_empty_r5l_meta_block(struct supertype *st, int fd)
init_afd(&afd, fd);
- if (posix_memalign((void**)&mb, 4096, META_BLOCK_SIZE) != 0) {
+ if (posix_memalign((void **)&mb, 4096, META_BLOCK_SIZE) != 0) {
pr_err("Could not allocate memory for the meta block.\n");
return 1;
}
@@ -2197,7 +2201,7 @@ static int compare_super1(struct supertype *st, struct supertype *tst,
return 1;
if (!first) {
- if (posix_memalign((void**)&first, 4096, SUPER1_SIZE) != 0) {
+ if (posix_memalign((void **)&first, 4096, SUPER1_SIZE) != 0) {
pr_err("could not allocate superblock\n");
return 1;
}
@@ -2310,7 +2314,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
return 1;
}
- if (posix_memalign((void**)&super, 4096, SUPER1_SIZE) != 0) {
+ if (posix_memalign((void **)&super, 4096, SUPER1_SIZE) != 0) {
pr_err("could not allocate superblock\n");
return 1;
}
@@ -2349,10 +2353,10 @@ static int load_super1(struct supertype *st, int fd, char *devname)
return 2;
}
- bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
+ bsb = (struct bitmap_super_s *)(((char *)super) + MAX_SB_SIZE);
misc = (struct misc_dev_info*)
- (((char*)super)+MAX_SB_SIZE+BM_SUPER_SIZE);
+ (((char *)super) + MAX_SB_SIZE+BM_SUPER_SIZE);
misc->device_size = dsize;
if (st->data_offset == INVALID_SECTORS)
st->data_offset = __le64_to_cpu(super->data_offset);
@@ -2360,9 +2364,8 @@ static int load_super1(struct supertype *st, int fd, char *devname)
if (st->minor_version >= 1 &&
st->ignore_hw_compat == 0 &&
((role_from_sb(super) != MD_DISK_ROLE_JOURNAL &&
- dsize < (__le64_to_cpu(super->data_offset) +
- __le64_to_cpu(super->size)))
- ||
+ dsize < (__le64_to_cpu(super->data_offset) +
+ __le64_to_cpu(super->size))) ||
dsize < (__le64_to_cpu(super->data_offset) +
__le64_to_cpu(super->data_size)))) {
if (devname)
@@ -2391,8 +2394,8 @@ static int load_super1(struct supertype *st, int fd, char *devname)
return 0;
no_bitmap:
- super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map)
- & ~MD_FEATURE_BITMAP_OFFSET);
+ super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) &
+ ~MD_FEATURE_BITMAP_OFFSET);
return 0;
}
@@ -2450,7 +2453,7 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize,
if (__le32_to_cpu(super->feature_map) & MD_FEATURE_BITMAP_OFFSET) {
/* hot-add. allow for actual size of bitmap */
struct bitmap_super_s *bsb;
- bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE);
+ bsb = (struct bitmap_super_s *)(((char *)super) + MAX_SB_SIZE);
bmspace = calc_bitmap_size(bsb, 4096) >> 9;
} else if (md_feature_any_ppl_on(super->feature_map)) {
bmspace = __le16_to_cpu(super->ppl.size);
@@ -2519,7 +2522,7 @@ add_internal_bitmap1(struct supertype *st,
int creating = 0;
int len;
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb) + MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
int uuid[4];
if (__le64_to_cpu(sb->data_size) == 0)
@@ -2607,10 +2610,10 @@ add_internal_bitmap1(struct supertype *st,
max_bits = (room * 512 - sizeof(bitmap_super_t)) * 8;
min_chunk = 4096; /* sub-page chunks don't work yet.. */
- bits = (size*512)/min_chunk +1;
+ bits = (size * 512) / min_chunk + 1;
while (bits > max_bits) {
min_chunk *= 2;
- bits = (bits+1)/2;
+ bits = (bits + 1) / 2;
}
if (chunk == UnSet) {
/* For practical purpose, 64Meg is a good
@@ -2628,8 +2631,8 @@ add_internal_bitmap1(struct supertype *st,
/* start bitmap on a 4K boundary with enough space for
* the bitmap
*/
- bits = (size*512) / chunk + 1;
- room = ((bits+7)/8 + sizeof(bitmap_super_t) +4095)/4096;
+ bits = (size * 512) / chunk + 1;
+ room = ((bits + 7) / 8 + sizeof(bitmap_super_t) + 4095) / 4096;
room *= 8; /* convert 4K blocks to sectors */
offset = -room - bbl_size;
}
@@ -2683,7 +2686,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num)
offset = __le64_to_cpu(sb->super_offset) + (int32_t)__le32_to_cpu(sb->bitmap_offset);
if (node_num) {
- bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
+ bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
bm_sectors_per_node = calc_bitmap_size(bms, 4096) >> 9;
offset += bm_sectors_per_node * node_num;
}
@@ -2696,7 +2699,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num)
static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update)
{
struct mdp_superblock_1 *sb = st->sb;
- bitmap_super_t *bms = (bitmap_super_t*)(((char*)sb)+MAX_SB_SIZE);
+ bitmap_super_t *bms = (bitmap_super_t *)(((char *)sb) + MAX_SB_SIZE);
int rv = 0;
void *buf;
int towrite, n, len;
@@ -2970,16 +2973,16 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0
copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
sprintf(sb->set_name, "%d", sb0->md_minor);
- sb->ctime = __cpu_to_le32(info->array.ctime+1);
+ sb->ctime = __cpu_to_le32(info->array.ctime + 1);
sb->level = __cpu_to_le32(info->array.level);
sb->layout = __cpu_to_le32(info->array.layout);
sb->size = __cpu_to_le64(info->component_size);
- sb->chunksize = __cpu_to_le32(info->array.chunk_size/512);
+ sb->chunksize = __cpu_to_le32(info->array.chunk_size / 512);
sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
if (info->array.level > 0)
sb->data_size = sb->size;
else
- sb->data_size = st->ss->avail_size(st, st->devsize/512, 0);
+ sb->data_size = st->ss->avail_size(st, st->devsize / 512, 0);
sb->resync_offset = MaxSector;
sb->max_dev = __cpu_to_le32(MD_SB_DISKS);
sb->dev_number = __cpu_to_le32(info->disk.number);
--
2.38.1

View File

@ -0,0 +1,136 @@
From f8d2c4286a92b7acb7872271a401ad1efe336096 Mon Sep 17 00:00:00 2001
From: Jes Sorensen <jes@trained-monkey.org>
Date: Mon, 10 Apr 2023 11:45:34 -0400
Subject: [PATCH 119/125] Bump minimum kernel version to 2.6.32
Summary: At this point it probably is reasonable to drop support for
anything prior to 3.10.
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 5 -----
Grow.c | 16 ----------------
Manage.c | 17 -----------------
mdadm.c | 4 ++--
super1.c | 5 -----
5 files changed, 2 insertions(+), 45 deletions(-)
diff --git a/Create.c b/Create.c
index 0911bf92..aa0472dd 100644
--- a/Create.c
+++ b/Create.c
@@ -636,11 +636,6 @@ int Create(struct supertype *st, char *mddev,
break;
case LEVEL_LINEAR:
/* a chunksize of zero 0s perfectly valid (and preferred) since 2.6.16 */
- if (get_linux_version() < 2006016 && s->chunk == 0) {
- s->chunk = 64;
- if (c->verbose > 0)
- pr_err("chunk size defaults to 64K\n");
- }
break;
case 1:
case LEVEL_FAULTY:
diff --git a/Grow.c b/Grow.c
index 06001f2d..8fa97875 100644
--- a/Grow.c
+++ b/Grow.c
@@ -1708,14 +1708,6 @@ char *analyse_change(char *devname, struct mdinfo *info, struct reshape *re)
return NULL;
}
- if (re->after.data_disks == re->before.data_disks &&
- get_linux_version() < 2006032)
- return "in-place reshape is not safe before 2.6.32 - sorry.";
-
- if (re->after.data_disks < re->before.data_disks &&
- get_linux_version() < 2006030)
- return "reshape to fewer devices is not supported before 2.6.30 - sorry.";
-
re->backup_blocks = compute_backup_blocks(
info->new_chunk, info->array.chunk_size,
re->after.data_disks, re->before.data_disks);
@@ -1895,14 +1887,6 @@ int Grow_reshape(char *devname, int fd,
return 1;
}
- if (s->raiddisks && s->raiddisks < array.raid_disks &&
- array.level > 1 && get_linux_version() < 2006032 &&
- !check_env("MDADM_FORCE_FEWER")) {
- pr_err("reducing the number of devices is not safe before Linux 2.6.32\n"
- " Please use a newer kernel\n");
- return 1;
- }
-
if (array.level > 1 && s->size > 1 &&
(unsigned long long) (array.chunk_size / 1024) > s->size) {
pr_err("component size must be larger than chunk size.\n");
diff --git a/Manage.c b/Manage.c
index fde6aba3..f54de7c6 100644
--- a/Manage.c
+++ b/Manage.c
@@ -461,17 +461,6 @@ done:
goto out;
}
- if (get_linux_version() < 2006028) {
- /* prior to 2.6.28, KOBJ_CHANGE was not sent when an md array
- * was stopped, so We'll do it here just to be sure. Drop any
- * partitions as well...
- */
- if (fd >= 0)
- ioctl(fd, BLKRRPART, 0);
- if (mdi)
- sysfs_uevent(mdi, "change");
- }
-
if (devnm[0] && use_udev()) {
struct map_ent *mp = map_by_devnm(&map, devnm);
remove_devices(devnm, mp ? mp->path : NULL);
@@ -621,12 +610,6 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv,
* though.
*/
mdu_disk_info_t disc;
- /* re-add doesn't work for version-1 superblocks
- * before 2.6.18 :-(
- */
- if (array->major_version == 1 &&
- get_linux_version() <= 2006018)
- goto skip_re_add;
disc.number = mdi.disk.number;
if (md_get_disk_info(fd, &disc) != 0 ||
disc.major != 0 || disc.minor != 0)
diff --git a/mdadm.c b/mdadm.c
index 4685ad6b..2296911d 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -107,8 +107,8 @@ int main(int argc, char *argv[])
srandom(time(0) ^ getpid());
- if (get_linux_version() < 2006015) {
- pr_err("This version of mdadm does not support kernels older than 2.6.15\n");
+ if (get_linux_version() < 2006032) {
+ pr_err("This version of mdadm does not support kernels older than 2.6.32\n");
exit(1);
}
diff --git a/super1.c b/super1.c
index 1d20ef55..938c3a68 100644
--- a/super1.c
+++ b/super1.c
@@ -2033,11 +2033,6 @@ static int write_init_super1(struct supertype *st)
/* same array, so preserve events and
* dev_number */
sb->events = refsb->events;
- /* bugs in 2.6.17 and earlier mean the
- * dev_number chosen in Manage must be preserved
- */
- if (get_linux_version() >= 2006018)
- sb->dev_number = refsb->dev_number;
}
free_super1(refst);
}
--
2.38.1

View File

@ -0,0 +1,42 @@
From 76c224c6cfc8ff154bd041d30b9551faecd593c1 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Fri, 7 Apr 2023 08:45:28 +0800
Subject: [PATCH 120/125] Remove the config files in mdcheck_start|continue
service
We set MDADM_CHECK_DURATION in the mdcheck_start|continue.service files.
And mdcheck doesn't use any configs from the config file. So we can remove
the dependencies.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
systemd/mdcheck_continue.service | 2 --
systemd/mdcheck_start.service | 2 --
2 files changed, 4 deletions(-)
diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service
index f5324905..70892a1f 100644
--- a/systemd/mdcheck_continue.service
+++ b/systemd/mdcheck_continue.service
@@ -13,6 +13,4 @@ Documentation=man:mdadm(8)
[Service]
Type=oneshot
Environment="MDADM_CHECK_DURATION=6 hours"
-EnvironmentFile=-/run/sysconfig/mdadm
-ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh
ExecStart=/usr/share/mdadm/mdcheck --continue --duration ${MDADM_CHECK_DURATION}
diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service
index 703a6583..fc4fc438 100644
--- a/systemd/mdcheck_start.service
+++ b/systemd/mdcheck_start.service
@@ -13,6 +13,4 @@ Documentation=man:mdadm(8)
[Service]
Type=oneshot
Environment="MDADM_CHECK_DURATION=6 hours"
-EnvironmentFile=-/run/sysconfig/mdadm
-ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh
ExecStart=/usr/share/mdadm/mdcheck --duration ${MDADM_CHECK_DURATION}
--
2.38.1

View File

@ -0,0 +1,347 @@
From b9ce7ab0218c550488587fdad5708628d6a5ffc2 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 23 Mar 2023 17:50:14 +0100
Subject: [PATCH 121/125] mdadm: define DEV_MD_DIR
It is used many times. Additionally define _LEN to avoid repeated
strlen() calls when length is needed.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Create.c | 7 +++----
Detail.c | 9 ++++-----
Incremental.c | 4 ++--
Monitor.c | 32 ++++++++++++++++++--------------
config.c | 10 +++++-----
lib.c | 2 +-
mapfile.c | 12 ++++++------
mdadm.h | 8 ++++++++
mdopen.c | 6 +++---
super-ddf.c | 2 +-
super-intel.c | 2 +-
super1.c | 3 +--
sysfs.c | 2 +-
13 files changed, 54 insertions(+), 45 deletions(-)
diff --git a/Create.c b/Create.c
index aa0472dd..ea6a4745 100644
--- a/Create.c
+++ b/Create.c
@@ -1024,10 +1024,9 @@ int Create(struct supertype *st, char *mddev,
* it could be in conflict with already existing device
* e.g. container, array
*/
- if (strncmp(chosen_name, "/dev/md/", 8) == 0 &&
- map_by_name(&map, chosen_name+8) != NULL) {
- pr_err("Array name %s is in use already.\n",
- chosen_name);
+ if (strncmp(chosen_name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 &&
+ map_by_name(&map, chosen_name + DEV_MD_DIR_LEN)) {
+ pr_err("Array name %s is in use already.\n", chosen_name);
close(mdfd);
map_unlock(&map);
udev_unblock();
diff --git a/Detail.c b/Detail.c
index 4ef26460..206d88e3 100644
--- a/Detail.c
+++ b/Detail.c
@@ -254,10 +254,9 @@ int Detail(char *dev, struct context *c)
fname_from_uuid(st, info, nbuf, ':');
printf("MD_UUID=%s\n", nbuf + 5);
mp = map_by_uuid(&map, info->uuid);
- if (mp && mp->path &&
- strncmp(mp->path, "/dev/md/", 8) == 0) {
+ if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
printf("MD_DEVNAME=");
- print_escape(mp->path + 8);
+ print_escape(mp->path + DEV_MD_DIR_LEN);
putchar('\n');
}
@@ -273,9 +272,9 @@ int Detail(char *dev, struct context *c)
printf("MD_UUID=%s\n", nbuf+5);
}
if (mp && mp->path &&
- strncmp(mp->path, "/dev/md/", 8) == 0) {
+ strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
printf("MD_DEVNAME=");
- print_escape(mp->path+8);
+ print_escape(mp->path + DEV_MD_DIR_LEN);
putchar('\n');
}
map_free(map);
diff --git a/Incremental.c b/Incremental.c
index 49a71f72..59b850f1 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -460,8 +460,8 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
info.array.working_disks ++;
}
- if (strncmp(chosen_name, "/dev/md/", 8) == 0)
- md_devname = chosen_name+8;
+ if (strncmp(chosen_name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ md_devname = chosen_name + DEV_MD_DIR_LEN;
else
md_devname = chosen_name;
if (c->export) {
diff --git a/Monitor.c b/Monitor.c
index 44918184..3273f2fb 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -36,9 +36,18 @@
#define EVENT_NAME_MAX 32
#define AUTOREBUILD_PID_PATH MDMON_DIR "/autorebuild.pid"
+/**
+ * struct state - external array or container properties.
+ * @devname: has length of %DEV_MD_DIR + device name + terminating byte
+ * @devnm: to sync with mdstat info
+ * @parent_devnm: or subarray, devnm of parent, for others, ""
+ * @subarray: for a container it is a link to first subarray, for a subarray it is a link to next
+ * subarray in the same container
+ * @parent: for a subarray it is a link to its container
+ */
struct state {
- char devname[MD_NAME_MAX + sizeof("/dev/md/")]; /* length of "/dev/md/" + device name + terminating byte*/
- char devnm[MD_NAME_MAX]; /* to sync with mdstat info */
+ char devname[MD_NAME_MAX + sizeof(DEV_MD_DIR)];
+ char devnm[MD_NAME_MAX];
unsigned int utime;
int err;
char *spare_group;
@@ -49,15 +58,10 @@ struct state {
int devstate[MAX_DISKS];
dev_t devid[MAX_DISKS];
int percent;
- char parent_devnm[MD_NAME_MAX]; /* For subarray, devnm of parent.
- * For others, ""
- */
+ char parent_devnm[MD_NAME_MAX];
struct supertype *metadata;
- struct state *subarray;/* for a container it is a link to first subarray
- * for a subarray it is a link to next subarray
- * in the same container */
- struct state *parent; /* for a subarray it is a link to its container
- */
+ struct state *subarray;
+ struct state *parent;
struct state *next;
};
@@ -252,8 +256,8 @@ int Monitor(struct mddev_dev *devlist,
continue;
st = xcalloc(1, sizeof *st);
- snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"),
- "/dev/md/%s", basename(mdlist->devname));
+ snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), DEV_MD_DIR "%s",
+ basename(mdlist->devname));
st->next = statelist;
st->devnm[0] = 0;
st->percent = RESYNC_UNKNOWN;
@@ -274,7 +278,7 @@ int Monitor(struct mddev_dev *devlist,
st = xcalloc(1, sizeof *st);
mdlist = conf_get_ident(dv->devname);
- snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", dv->devname);
+ snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), "%s", dv->devname);
st->next = statelist;
st->devnm[0] = 0;
st->percent = RESYNC_UNKNOWN;
@@ -942,7 +946,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist)
continue;
}
- snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", name);
+ snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), "%s", name);
if ((fd = open(st->devname, O_RDONLY)) < 0 ||
md_get_array_info(fd, &array) < 0) {
/* no such array */
diff --git a/config.c b/config.c
index eeedd0c6..59d5bfb6 100644
--- a/config.c
+++ b/config.c
@@ -405,7 +405,7 @@ void arrayline(char *line)
* or anything that doesn't start '/' or '<'
*/
if (strcasecmp(w, "<ignore>") == 0 ||
- strncmp(w, "/dev/md/", 8) == 0 ||
+ strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
(w[0] != '/' && w[0] != '<') ||
(strncmp(w, "/dev/md", 7) == 0 &&
is_number(w + 7)) ||
@@ -1102,13 +1102,13 @@ int devname_matches(char *name, char *match)
* mdNN with NN
* then just strcmp
*/
- if (strncmp(name, "/dev/md/", 8) == 0)
- name += 8;
+ if (strncmp(name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ name += DEV_MD_DIR_LEN;
else if (strncmp(name, "/dev/", 5) == 0)
name += 5;
- if (strncmp(match, "/dev/md/", 8) == 0)
- match += 8;
+ if (strncmp(match, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ match += DEV_MD_DIR_LEN;
else if (strncmp(match, "/dev/", 5) == 0)
match += 5;
diff --git a/lib.c b/lib.c
index e395b28d..65ea51e0 100644
--- a/lib.c
+++ b/lib.c
@@ -313,7 +313,7 @@ char *map_dev_preferred(int major, int minor, int create,
for (p = devlist; p; p = p->next)
if (p->major == major && p->minor == minor) {
- if (strncmp(p->name, "/dev/md/",8) == 0 ||
+ if (strncmp(p->name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
(prefer && strstr(p->name, prefer))) {
if (preferred == NULL ||
strlen(p->name) < strlen(preferred))
diff --git a/mapfile.c b/mapfile.c
index ac351768..34fea179 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -320,9 +320,9 @@ struct map_ent *map_by_name(struct map_ent **map, char *name)
for (mp = *map ; mp ; mp = mp->next) {
if (!mp->path)
continue;
- if (strncmp(mp->path, "/dev/md/", 8) != 0)
+ if (strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) != 0)
continue;
- if (strcmp(mp->path+8, name) != 0)
+ if (strcmp(mp->path + DEV_MD_DIR_LEN, name) != 0)
continue;
if (!mddev_busy(mp->devnm)) {
mp->bad = 1;
@@ -413,7 +413,7 @@ void RebuildMap(void)
devid = devnm2devid(md->devnm);
path = map_dev(major(devid), minor(devid), 0);
if (path == NULL ||
- strncmp(path, "/dev/md/", 8) != 0) {
+ strncmp(path, DEV_MD_DIR, DEV_MD_DIR_LEN) != 0) {
/* We would really like a name that provides
* an MD_DEVNAME for udev.
* The name needs to be unique both in /dev/md/
@@ -434,7 +434,7 @@ void RebuildMap(void)
if (match && match->devname && match->devname[0] == '/') {
path = match->devname;
if (path[0] != '/') {
- strcpy(namebuf, "/dev/md/");
+ strcpy(namebuf, DEV_MD_DIR);
strcat(namebuf, path);
path = namebuf;
}
@@ -478,10 +478,10 @@ void RebuildMap(void)
while (conflict) {
if (unum >= 0)
- sprintf(namebuf, "/dev/md/%s%s%d",
+ sprintf(namebuf, DEV_MD_DIR "%s%s%d",
name, sep, unum);
else
- sprintf(namebuf, "/dev/md/%s",
+ sprintf(namebuf, DEV_MD_DIR "%s",
name);
unum++;
if (lstat(namebuf, &stb) != 0 &&
diff --git a/mdadm.h b/mdadm.h
index 0d995445..67d73f96 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -100,6 +100,14 @@ struct dlm_lksb {
#define DEFAULT_BITMAP_DELAY 5
#define DEFAULT_MAX_WRITE_BEHIND 256
+/* DEV_MD_DIR points to named MD devices directory.
+ * DEV_MD_DIR_LEN is a length with Null byte excluded.
+ */
+#ifndef DEV_MD_DIR
+#define DEV_MD_DIR "/dev/md/"
+#define DEV_MD_DIR_LEN (sizeof(DEV_MD_DIR) - 1)
+#endif /* DEV_MD_DIR */
+
/* MAP_DIR should be somewhere that persists across the pivotroot
* from early boot to late boot.
* /run seems to have emerged as the best standard.
diff --git a/mdopen.c b/mdopen.c
index 810f79a3..6c3bdb6a 100644
--- a/mdopen.c
+++ b/mdopen.c
@@ -188,12 +188,12 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
parts = autof >> 3;
autof &= 7;
- strcpy(chosen, "/dev/md/");
+ strcpy(chosen, DEV_MD_DIR);
cname = chosen + strlen(chosen);
if (dev) {
- if (strncmp(dev, "/dev/md/", 8) == 0) {
- strcpy(cname, dev+8);
+ if (strncmp(dev, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
+ strcpy(cname, dev + DEV_MD_DIR_LEN);
} else if (strncmp(dev, "/dev/", 5) == 0) {
char *e = dev + strlen(dev);
while (e > dev && isdigit(e[-1]))
diff --git a/super-ddf.c b/super-ddf.c
index b86c6acd..7213284e 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1648,7 +1648,7 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
fname_from_uuid(st, &info, nbuf1, ':');
_ddf_array_name(namebuf, ddf, i);
printf("ARRAY%s%s container=%s member=%d UUID=%s\n",
- namebuf[0] == '\0' ? "" : " /dev/md/", namebuf,
+ namebuf[0] == '\0' ? "" : " " DEV_MD_DIR, namebuf,
nbuf+5, i, nbuf1+5);
}
}
diff --git a/super-intel.c b/super-intel.c
index a5c86cb2..aaf6659e 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2309,7 +2309,7 @@ static void brief_examine_subarrays_imsm(struct supertype *st, int verbose)
super->current_vol = i;
getinfo_super_imsm(st, &info, NULL);
fname_from_uuid(st, &info, nbuf1, ':');
- printf("ARRAY /dev/md/%.16s container=%s member=%d UUID=%s\n",
+ printf("ARRAY " DEV_MD_DIR "%.16s container=%s member=%d UUID=%s\n",
dev->volume, nbuf + 5, i, nbuf1 + 5);
}
}
diff --git a/super1.c b/super1.c
index 938c3a68..856b0208 100644
--- a/super1.c
+++ b/super1.c
@@ -645,8 +645,7 @@ static void brief_examine_super1(struct supertype *st, int verbose)
printf("ARRAY ");
if (nm) {
- printf("/dev/md/");
- print_escape(nm);
+ printf(DEV_MD_DIR "%s", nm);
putchar(' ');
}
if (verbose && c)
diff --git a/sysfs.c b/sysfs.c
index ca1d888f..94d02f53 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -1114,7 +1114,7 @@ void sysfsline(char *line)
if (strncasecmp(w, "name=", 5) == 0) {
char *devname = w + 5;
- if (strncmp(devname, "/dev/md/", 8) == 0) {
+ if (strncmp(devname, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
if (sr->devname)
pr_err("Only give one device per SYSFS line: %s\n",
devname);
--
2.38.1

View File

@ -0,0 +1,73 @@
From 0f8347d4f6588ee6ded55af3e307418cee286a6f Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 23 Mar 2023 17:50:15 +0100
Subject: [PATCH 122/125] mdadm: define DEV_NUM_PREF
Use define instead of inlines. Add _LEN define.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
config.c | 4 ++--
mdadm.h | 8 ++++++++
mdopen.c | 10 +++++-----
3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/config.c b/config.c
index 59d5bfb6..f44cc1d3 100644
--- a/config.c
+++ b/config.c
@@ -407,8 +407,8 @@ void arrayline(char *line)
if (strcasecmp(w, "<ignore>") == 0 ||
strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
(w[0] != '/' && w[0] != '<') ||
- (strncmp(w, "/dev/md", 7) == 0 &&
- is_number(w + 7)) ||
+ (strncmp(w, DEV_NUM_PREF, DEV_NUM_PREF_LEN) == 0 &&
+ is_number(w + DEV_NUM_PREF_LEN)) ||
(strncmp(w, "/dev/md_d", 9) == 0 &&
is_number(w + 9))) {
/* This is acceptable */;
diff --git a/mdadm.h b/mdadm.h
index 67d73f96..f2e70baa 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -100,6 +100,14 @@ struct dlm_lksb {
#define DEFAULT_BITMAP_DELAY 5
#define DEFAULT_MAX_WRITE_BEHIND 256
+/* DEV_NUM_PREF is a subpath to numbered MD devices, e.g. /dev/md1 or directory name.
+ * DEV_NUM_PREF_LEN is a length with Null byte excluded.
+ */
+#ifndef DEV_NUM_PREF
+#define DEV_NUM_PREF "/dev/md"
+#define DEV_NUM_PREF_LEN (sizeof(DEV_NUM_PREF) - 1)
+#endif /* DEV_NUM_PREF */
+
/* DEV_MD_DIR points to named MD devices directory.
* DEV_MD_DIR_LEN is a length with Null byte excluded.
*/
diff --git a/mdopen.c b/mdopen.c
index 6c3bdb6a..d3022a54 100644
--- a/mdopen.c
+++ b/mdopen.c
@@ -412,11 +412,11 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
make_parts(devname, parts);
if (strcmp(chosen, devname) != 0) {
- if (mkdir("/dev/md",0700) == 0) {
- if (chown("/dev/md", ci->uid, ci->gid))
- perror("chown /dev/md");
- if (chmod("/dev/md", ci->mode| ((ci->mode>>2) & 0111)))
- perror("chmod /dev/md");
+ if (mkdir(DEV_NUM_PREF, 0700) == 0) {
+ if (chown(DEV_NUM_PREF, ci->uid, ci->gid))
+ perror("chown " DEV_NUM_PREF);
+ if (chmod(DEV_NUM_PREF, ci->mode | ((ci->mode >> 2) & 0111)))
+ perror("chmod " DEV_NUM_PREF);
}
if (dev && strcmp(chosen, dev) == 0)
--
2.38.1

View File

@ -0,0 +1,133 @@
From 7b3b691ba69b909ea8c172aae693fa2a6938fd14 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 23 Mar 2023 17:50:16 +0100
Subject: [PATCH 123/125] mdadm: define is_devname_ignore()
Use function instead of direct checks across code.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Incremental.c | 6 ++----
Monitor.c | 2 +-
config.c | 16 ++++++++++++++--
mdadm.c | 5 ++---
mdadm.h | 1 +
5 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 59b850f1..f13ce027 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -202,8 +202,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c,
if (!match && rv == 2)
goto out;
- if (match && match->devname &&
- strcasecmp(match->devname, "<ignore>") == 0) {
+ if (match && match->devname && is_devname_ignore(match->devname) == true) {
if (c->verbose >= 0)
pr_err("array containing %s is explicitly ignored by mdadm.conf\n",
devname);
@@ -1567,8 +1566,7 @@ static int Incremental_container(struct supertype *st, char *devname,
break;
}
- if (match && match->devname &&
- strcasecmp(match->devname, "<ignore>") == 0) {
+ if (match && match->devname && is_devname_ignore(match->devname) == true) {
if (c->verbose > 0)
pr_err("array %s/%s is explicitly ignored by mdadm.conf\n",
match->container, match->member);
diff --git a/Monitor.c b/Monitor.c
index 3273f2fb..66175968 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -250,7 +250,7 @@ int Monitor(struct mddev_dev *devlist,
if (mdlist->devname == NULL)
continue;
- if (strcasecmp(mdlist->devname, "<ignore>") == 0)
+ if (is_devname_ignore(mdlist->devname) == true)
continue;
if (!is_mddev(mdlist->devname))
continue;
diff --git a/config.c b/config.c
index f44cc1d3..e61c0496 100644
--- a/config.c
+++ b/config.c
@@ -119,6 +119,18 @@ int match_keyword(char *word)
return -1;
}
+/**
+ * is_devname_ignore() - check if &devname is a special "<ignore>" keyword.
+ */
+bool is_devname_ignore(char *devname)
+{
+ static const char keyword[] = "<ignore>";
+
+ if (strcasecmp(devname, keyword) == 0)
+ return true;
+ return false;
+}
+
/**
* ident_init() - Set defaults.
* @ident: ident pointer, not NULL.
@@ -404,7 +416,7 @@ void arrayline(char *line)
* <ignore>
* or anything that doesn't start '/' or '<'
*/
- if (strcasecmp(w, "<ignore>") == 0 ||
+ if (is_devname_ignore(w) == true ||
strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
(w[0] != '/' && w[0] != '<') ||
(strncmp(w, DEV_NUM_PREF, DEV_NUM_PREF_LEN) == 0 &&
@@ -571,7 +583,7 @@ void homehostline(char *line)
char *w;
for (w = dl_next(line); w != line; w = dl_next(w)) {
- if (strcasecmp(w, "<ignore>") == 0)
+ if (is_devname_ignore(w) == true)
require_homehost = 0;
else if (home_host == NULL) {
if (strcasecmp(w, "<none>") == 0)
diff --git a/mdadm.c b/mdadm.c
index 2296911d..076b45e0 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -154,7 +154,7 @@ int main(int argc, char *argv[])
continue;
case HomeHost:
- if (strcasecmp(optarg, "<ignore>") == 0)
+ if (is_devname_ignore(optarg) == true)
c.require_homehost = 0;
else
c.homehost = optarg;
@@ -1749,8 +1749,7 @@ static int scan_assemble(struct supertype *ss,
int r;
if (a->assembled)
continue;
- if (a->devname &&
- strcasecmp(a->devname, "<ignore>") == 0)
+ if (a->devname && is_devname_ignore(a->devname) == true)
continue;
r = Assemble(ss, a->devname,
diff --git a/mdadm.h b/mdadm.h
index f2e70baa..0932c2d3 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1650,6 +1650,7 @@ extern void print_escape(char *str);
extern int use_udev(void);
extern unsigned long GCD(unsigned long a, unsigned long b);
extern int conf_name_is_free(char *name);
+extern bool is_devname_ignore(char *devname);
extern int conf_verify_devnames(struct mddev_ident *array_list);
extern int devname_matches(char *name, char *match);
extern struct mddev_ident *conf_match(struct supertype *st,
--
2.38.1

View File

@ -0,0 +1,145 @@
From 25aa7329141c0b28d8811671627f0f5c5dc22273 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 23 Mar 2023 17:50:17 +0100
Subject: [PATCH 124/125] mdadm: numbered names verification
New functions added to remove literals and make the code reusable.
Use parse_num() instead of is_numer().
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
config.c | 17 ++---------------
lib.c | 2 +-
mdadm.h | 4 +++-
util.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/config.c b/config.c
index e61c0496..450880e3 100644
--- a/config.c
+++ b/config.c
@@ -385,17 +385,6 @@ void devline(char *line)
struct mddev_ident *mddevlist = NULL;
struct mddev_ident **mddevlp = &mddevlist;
-static int is_number(char *w)
-{
- /* check if there are 1 or more digits and nothing else */
- int digits = 0;
- while (*w && isdigit(*w)) {
- digits++;
- w++;
- }
- return (digits && ! *w);
-}
-
void arrayline(char *line)
{
char *w;
@@ -419,10 +408,8 @@ void arrayline(char *line)
if (is_devname_ignore(w) == true ||
strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
(w[0] != '/' && w[0] != '<') ||
- (strncmp(w, DEV_NUM_PREF, DEV_NUM_PREF_LEN) == 0 &&
- is_number(w + DEV_NUM_PREF_LEN)) ||
- (strncmp(w, "/dev/md_d", 9) == 0 &&
- is_number(w + 9))) {
+ is_devname_md_numbered(w) == true ||
+ is_devname_md_d_numbered(w) == true) {
/* This is acceptable */;
if (mis.devname)
pr_err("only give one device per ARRAY line: %s and %s\n",
diff --git a/lib.c b/lib.c
index 65ea51e0..fe5c8d2c 100644
--- a/lib.c
+++ b/lib.c
@@ -570,7 +570,7 @@ void free_line(char *line)
*
* Return: 0 on success, 1 otherwise.
*/
-int parse_num(int *dest, char *num)
+int parse_num(int *dest, const char *num)
{
char *c = NULL;
long temp;
diff --git a/mdadm.h b/mdadm.h
index 0932c2d3..83f2cf7f 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1601,7 +1601,7 @@ int default_layout(struct supertype *st, int level, int verbose);
extern int is_near_layout_10(int layout);
extern int parse_layout_10(char *layout);
extern int parse_layout_faulty(char *layout);
-extern int parse_num(int *dest, char *num);
+extern int parse_num(int *dest, const char *num);
extern int parse_cluster_confirm_arg(char *inp, char **devname, int *slot);
extern int check_ext2(int fd, char *name);
extern int check_reiser(int fd, char *name);
@@ -1651,6 +1651,8 @@ extern int use_udev(void);
extern unsigned long GCD(unsigned long a, unsigned long b);
extern int conf_name_is_free(char *name);
extern bool is_devname_ignore(char *devname);
+extern bool is_devname_md_numbered(const char *devname);
+extern bool is_devname_md_d_numbered(const char *devname);
extern int conf_verify_devnames(struct mddev_ident *array_list);
extern int devname_matches(char *name, char *match);
extern struct mddev_ident *conf_match(struct supertype *st,
diff --git a/util.c b/util.c
index d70ca43b..fa378eba 100644
--- a/util.c
+++ b/util.c
@@ -973,6 +973,50 @@ dev_t devnm2devid(char *devnm)
return 0;
}
+/**
+ * is_devname_numbered() - helper for numbered devname verification.
+ * @devname: path or name to check.
+ * @pref: expected devname prefix.
+ * @pref_len: prefix len.
+ */
+static bool is_devname_numbered(const char *devname, const char *pref, const int pref_len)
+{
+ int val;
+
+ assert(devname && pref);
+
+ if (strncmp(devname, pref, pref_len) != 0)
+ return false;
+
+ if (parse_num(&val, devname + pref_len) != 0)
+ return false;
+
+ if (val > 127)
+ return false;
+
+ return true;
+}
+
+/**
+ * is_devname_md_numbered() - check if &devname is numbered MD device (md).
+ * @devname: path or name to check.
+ */
+bool is_devname_md_numbered(const char *devname)
+{
+ return is_devname_numbered(devname, DEV_NUM_PREF, DEV_NUM_PREF_LEN);
+}
+
+/**
+ * is_devname_md_d_numbered() - check if &devname is secondary numbered MD device (md_d).
+ * @devname: path or name to check.
+ */
+bool is_devname_md_d_numbered(const char *devname)
+{
+ static const char d_dev[] = DEV_NUM_PREF "_d";
+
+ return is_devname_numbered(devname, d_dev, sizeof(d_dev) - 1);
+}
+
/**
* get_md_name() - Get main dev node of the md device.
* @devnm: Md device name or path.
--
2.38.1

View File

@ -0,0 +1,187 @@
From 75350d87c86001c47076e1f62478079bdc072223 Mon Sep 17 00:00:00 2001
From: Kevin Friedberg <kev.friedberg@gmail.com>
Date: Wed, 15 Feb 2023 23:41:34 -0500
Subject: [PATCH 125/125] enable RAID for SATA under VMD
Detect when a SATA controller has been mapped under Intel Alderlake RST
VMD, so that it can use the VMD controller's RAID capabilities. Create
new device type SYS_DEV_SATA_VMD and list separate controller to prevent
mixing with the NVMe SYS_DEV_VMD devices on the same VMD domain.
Signed-off-by: Kevin Friedberg <kev.friedberg@gmail.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
platform-intel.c | 21 ++++++++++++++++++---
platform-intel.h | 1 +
super-intel.c | 28 ++++++++++++++++++----------
3 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/platform-intel.c b/platform-intel.c
index 757f0b1b..914164c0 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -64,9 +64,10 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
if (strcmp(driver, "isci") == 0)
type = SYS_DEV_SAS;
- else if (strcmp(driver, "ahci") == 0)
+ else if (strcmp(driver, "ahci") == 0) {
+ vmd = find_driver_devices("pci", "vmd");
type = SYS_DEV_SATA;
- else if (strcmp(driver, "nvme") == 0) {
+ } else if (strcmp(driver, "nvme") == 0) {
/* if looking for nvme devs, first look for vmd */
vmd = find_driver_devices("pci", "vmd");
type = SYS_DEV_NVME;
@@ -115,6 +116,17 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
free(rp);
}
+ /* change sata type if under a vmd controller */
+ if (type == SYS_DEV_SATA) {
+ struct sys_dev *dev;
+ char *rp = realpath(path, NULL);
+ for (dev = vmd; dev; dev = dev->next) {
+ if ((strncmp(dev->path, rp, strlen(dev->path)) == 0))
+ type = SYS_DEV_SATA_VMD;
+ }
+ free(rp);
+ }
+
/* if it's not Intel device or mark as VMD connected - skip it. */
if (devpath_to_vendor(path) != 0x8086 || skip == 1)
continue;
@@ -166,7 +178,8 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver)
}
closedir(driver_dir);
- if (vmd) {
+ /* nvme vmd needs a list separate from sata vmd */
+ if (vmd && type == SYS_DEV_NVME) {
if (list)
list->next = vmd;
else
@@ -273,6 +286,7 @@ struct sys_dev *find_intel_devices(void)
free_sys_dev(&intel_devices);
isci = find_driver_devices("pci", "isci");
+ /* Searching for AHCI will return list of SATA and SATA VMD controllers */
ahci = find_driver_devices("pci", "ahci");
/* Searching for NVMe will return list of NVMe and VMD controllers */
nvme = find_driver_devices("pci", "nvme");
@@ -638,6 +652,7 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba)
break;
case SYS_DEV_VMD:
+ case SYS_DEV_SATA_VMD:
for (i = 0; i < ARRAY_SIZE(vmd_efivars); i++) {
if (!read_efi_variable(&orom, sizeof(orom),
vmd_efivars[i], VENDOR_GUID))
diff --git a/platform-intel.h b/platform-intel.h
index 6238d23f..2c0f4e39 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -196,6 +196,7 @@ enum sys_dev_type {
SYS_DEV_SATA,
SYS_DEV_NVME,
SYS_DEV_VMD,
+ SYS_DEV_SATA_VMD,
SYS_DEV_MAX
};
diff --git a/super-intel.c b/super-intel.c
index aaf6659e..ae0f4a8c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -627,7 +627,8 @@ static const char *_sys_dev_type[] = {
[SYS_DEV_SAS] = "SAS",
[SYS_DEV_SATA] = "SATA",
[SYS_DEV_NVME] = "NVMe",
- [SYS_DEV_VMD] = "VMD"
+ [SYS_DEV_VMD] = "VMD",
+ [SYS_DEV_SATA_VMD] = "SATA VMD"
};
static int no_platform = -1;
@@ -2598,6 +2599,8 @@ static void print_found_intel_controllers(struct sys_dev *elem)
if (elem->type == SYS_DEV_VMD)
fprintf(stderr, "VMD domain");
+ else if (elem->type == SYS_DEV_SATA_VMD)
+ fprintf(stderr, "SATA VMD domain");
else
fprintf(stderr, "RAID controller");
@@ -2768,8 +2771,9 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
if (!find_imsm_capability(hba)) {
char buf[PATH_MAX];
pr_err("imsm capabilities not found for controller: %s (type %s)\n",
- hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path,
- get_sys_dev_type(hba->type));
+ hba->type == SYS_DEV_VMD || hba->type == SYS_DEV_SATA_VMD ?
+ vmd_domain_to_controller(hba, buf) :
+ hba->path, get_sys_dev_type(hba->type));
continue;
}
result = 0;
@@ -2822,11 +2826,12 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle
printf(" I/O Controller : %s (%s)\n",
hba->path, get_sys_dev_type(hba->type));
- if (hba->type == SYS_DEV_SATA) {
+ 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 (verbose > 0)
- pr_err("failed to enumerate ports on SATA controller at %s.\n", hba->pci_id);
+ pr_err("failed to enumerate ports on %s controller at %s.\n",
+ get_sys_dev_type(hba->type), hba->pci_id);
result |= 2;
}
}
@@ -2856,7 +2861,8 @@ static int export_detail_platform_imsm(int verbose, char *controller_path)
if (!find_imsm_capability(hba) && verbose > 0) {
char buf[PATH_MAX];
pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",
- hba->type == SYS_DEV_VMD ? vmd_domain_to_controller(hba, buf) : hba->path);
+ hba->type == SYS_DEV_VMD || hba->type == SYS_DEV_SATA_VMD ?
+ vmd_domain_to_controller(hba, buf) : hba->path);
}
else
result = 0;
@@ -2865,7 +2871,7 @@ static int export_detail_platform_imsm(int verbose, char *controller_path)
const struct orom_entry *entry;
for (entry = orom_entries; entry; entry = entry->next) {
- if (entry->type == SYS_DEV_VMD) {
+ if (entry->type == SYS_DEV_VMD || entry->type == SYS_DEV_SATA_VMD) {
for (hba = list; hba; hba = hba->next)
print_imsm_capability_export(&entry->orom);
continue;
@@ -4782,10 +4788,12 @@ static int find_intel_hba_capability(int fd, struct intel_super *super, char *de
" but the container is assigned to Intel(R) %s %s (",
devname,
get_sys_dev_type(hba_name->type),
- hba_name->type == SYS_DEV_VMD ? "domain" : "RAID controller",
+ hba_name->type == SYS_DEV_VMD || hba_name->type == SYS_DEV_SATA_VMD ?
+ "domain" : "RAID controller",
hba_name->pci_id ? : "Err!",
get_sys_dev_type(super->hba->type),
- hba->type == SYS_DEV_VMD ? "domain" : "RAID controller");
+ hba->type == SYS_DEV_VMD || hba_name->type == SYS_DEV_SATA_VMD ?
+ "domain" : "RAID controller");
while (hba) {
fprintf(stderr, "%s", hba->pci_id ? : "Err!");
@@ -11274,7 +11282,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
hba = find_disk_attached_hba(-1, path);
if (hba && hba->type == SYS_DEV_SAS)
drv = "isci";
- else if (hba && hba->type == SYS_DEV_SATA)
+ 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";
--
2.38.1

View File

@ -0,0 +1,33 @@
From cf1577bf54afe76b77ecaa62df25901739ca8ae9 Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Wed, 5 Jul 2023 16:34:56 +0200
Subject: [PATCH 126/165] imsm: Fix possible segfault in check_no_platform()
conf_line() may return NULL, which is not handled and might cause
segfault.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/super-intel.c b/super-intel.c
index ae0f4a8c..4ef33d31 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -650,6 +650,11 @@ static int check_no_platform(void)
char *l = conf_line(fp);
char *w = l;
+ if (l == NULL) {
+ fclose(fp);
+ return 0;
+ }
+
do {
if (strcmp(w, search) == 0)
no_platform = 1;
--
2.40.1

View File

@ -0,0 +1,105 @@
From 9bc426fa1f236b8cad518431574a54fc60718739 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 29 May 2023 15:52:33 +0200
Subject: [PATCH 127/165] imsm: move sum_extents calculations to
merge_extents()
This logic is only used by merge_extents() code, there is no need to pass
it as parameter. Move it up. Add proper description.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 4ef33d31..26b20313 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6882,21 +6882,31 @@ static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
return end - base_start;
}
-static unsigned long long merge_extents(struct intel_super *super, int sum_extents)
+/** merge_extents() - analyze extents and get max common free size.
+ * @super: Intel metadata, not NULL.
+ *
+ * Build a composite disk with all known extents and generate a new maxsize
+ * given the "all disks in an array must share a common start offset"
+ * constraint.
+ *
+ * Return: Max free space or 0 on failure.
+ */
+static unsigned long long merge_extents(struct intel_super *super)
{
- /* build a composite disk with all known extents and generate a new
- * 'maxsize' given the "all disks in an array must share a common start
- * offset" constraint
- */
- struct extent *e = xcalloc(sum_extents, sizeof(*e));
+ struct extent *e;
struct dl *dl;
int i, j;
- int start_extent;
+ int start_extent, sum_extents = 0;
unsigned long long pos;
unsigned long long start = 0;
unsigned long long maxsize;
unsigned long reserve;
+ for (dl = super->disks; dl; dl = dl->next)
+ if (dl->e)
+ sum_extents += dl->extent_cnt;
+ e = xcalloc(sum_extents, sizeof(struct extent));
+
/* coalesce and sort all extents. also, check to see if we need to
* reserve space between member arrays
*/
@@ -7555,13 +7565,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
return 0;
}
- /* count total number of extents for merge */
- i = 0;
- for (dl = super->disks; dl; dl = dl->next)
- if (dl->e)
- i += dl->extent_cnt;
-
- maxsize = merge_extents(super, i);
+ maxsize = merge_extents(super);
if (mpb->num_raid_devs > 0 && size && size != maxsize)
pr_err("attempting to create a second volume with size less then remaining space.\n");
@@ -7615,7 +7619,6 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
struct imsm_super *mpb = super->anchor;
struct dl *dl;
int i;
- int extent_cnt;
struct extent *e;
unsigned long long maxsize;
unsigned long long minsize;
@@ -7624,7 +7627,6 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
/* find the largest common start free region of the possible disks */
used = 0;
- extent_cnt = 0;
cnt = 0;
for (dl = super->disks; dl; dl = dl->next) {
dl->raiddisk = -1;
@@ -7645,11 +7647,10 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
;
dl->e = e;
dl->extent_cnt = i;
- extent_cnt += i;
cnt++;
}
- maxsize = merge_extents(super, extent_cnt);
+ maxsize = merge_extents(super);
minsize = size;
if (size == 0)
/* chunk is in K */
--
2.40.1

View File

@ -0,0 +1,72 @@
From 5f027b9357c011ca0421400e258a777d97f18d17 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 29 May 2023 15:52:34 +0200
Subject: [PATCH 128/165] imsm: imsm_get_free_size() refactor.
Move minsize calculations up. Add error message if free size is too small.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 26b20313..16a30ba7 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -7600,7 +7600,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
* @super: &intel_super pointer, not NULL.
* @raiddisks: number of raid disks.
* @size: requested size, could be 0 (means max size).
- * @chunk: requested chunk.
+ * @chunk: requested chunk size in KiB.
* @freesize: pointer for returned size value.
*
* Return: &IMSM_STATUS_OK or &IMSM_STATUS_ERROR.
@@ -7620,14 +7620,15 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
struct dl *dl;
int i;
struct extent *e;
+ int cnt = 0;
+ int used = 0;
unsigned long long maxsize;
- unsigned long long minsize;
- int cnt;
- int used;
+ unsigned long long minsize = size;
+
+ if (minsize == 0)
+ minsize = chunk * 2;
/* find the largest common start free region of the possible disks */
- used = 0;
- cnt = 0;
for (dl = super->disks; dl; dl = dl->next) {
dl->raiddisk = -1;
@@ -7651,14 +7652,14 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
}
maxsize = merge_extents(super);
- minsize = size;
- if (size == 0)
- /* chunk is in K */
- minsize = chunk * 2;
+ if (maxsize < minsize) {
+ pr_err("imsm: Free space is %llu but must be equal or larger than %llu.\n",
+ maxsize, minsize);
+ return IMSM_STATUS_ERROR;
+ }
- if (cnt < raiddisks || (super->orom && used && used != raiddisks) ||
- maxsize < minsize || maxsize == 0) {
- pr_err("not enough devices with space to create array.\n");
+ if (cnt < raiddisks || (super->orom && used && used != raiddisks)) {
+ pr_err("imsm: Not enough devices with space to create array.\n");
return IMSM_STATUS_ERROR;
}
--
2.40.1

View File

@ -0,0 +1,68 @@
From 78c8028b331c8e281554d43fde4d46e9cb4a227e Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 29 May 2023 15:52:35 +0200
Subject: [PATCH 129/165] imsm: introduce round_member_size_to_mb()
Extract rounding logic to separate function.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 16a30ba7..36171107 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -1644,17 +1644,29 @@ static int is_journal(struct imsm_disk *disk)
return (disk->status & JOURNAL_DISK) == JOURNAL_DISK;
}
-/* round array size down to closest MB and ensure it splits evenly
- * between members
+/**
+ * round_member_size_to_mb()- Round given size to closest MiB.
+ * @size: size to round in sectors.
*/
-static unsigned long long round_size_to_mb(unsigned long long size, unsigned int
- disk_count)
+static inline unsigned long long round_member_size_to_mb(unsigned long long size)
{
- size /= disk_count;
- size = (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
- size *= disk_count;
+ return (size >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
+}
- return size;
+/**
+ * round_size_to_mb()- Round given size.
+ * @array_size: size to round in sectors.
+ * @disk_count: count of data members.
+ *
+ * Get size per each data member and round it to closest MiB to ensure that data
+ * splits evenly between members.
+ *
+ * Return: Array size, rounded down.
+ */
+static inline unsigned long long round_size_to_mb(unsigned long long array_size,
+ unsigned int disk_count)
+{
+ return round_member_size_to_mb(array_size / disk_count) * disk_count;
}
static int able_to_resync(int raid_level, int missing_disks)
@@ -11810,8 +11822,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
} else {
/* round size due to metadata compatibility
*/
- geo->size = (geo->size >> SECT_PER_MB_SHIFT)
- << SECT_PER_MB_SHIFT;
+ geo->size = round_member_size_to_mb(geo->size);
dprintf("Prepare update for size change to %llu\n",
geo->size );
if (current_size >= geo->size) {
--
2.40.1

View File

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

View File

@ -0,0 +1,214 @@
From aa19fdd45b2ba474f6a51a6d4b8f3c44ef19dafd Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Mon, 29 May 2023 15:52:37 +0200
Subject: [PATCH 131/165] imsm: return free space after volume for expand
merge_extends() routine searches for the biggest free space. For expand,
it works only in standard cases where the last volume is expanded and
the free space is determined after the last volume.
Add volume index to extent struct and use that do determine size after
super->current_vol during expand.
Limitation to last volume is no longer needed. It unblocks scenarios
where kill-subarray is used to remove first volume and later it is
recreated (now it is the second volume, even if it is placed before
existing one).
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-intel.c | 71 +++++++++++++++++++++++++++------------------------
1 file changed, 37 insertions(+), 34 deletions(-)
diff --git a/super-intel.c b/super-intel.c
index 5bd70356..e249d925 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -499,8 +499,15 @@ struct intel_disk {
struct intel_disk *next;
};
+/**
+ * struct extent - reserved space details.
+ * @start: start offset.
+ * @size: size of reservation, set to 0 for metadata reservation.
+ * @vol: index of the volume, meaningful if &size is set.
+ */
struct extent {
unsigned long long start, size;
+ int vol;
};
/* definitions of reshape process types */
@@ -1539,9 +1546,10 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
int get_minimal_reservation)
{
/* find a list of used extents on the given physical device */
- struct extent *rv, *e;
- int i;
int memberships = count_memberships(dl, super);
+ struct extent *rv = xcalloc(memberships + 1, sizeof(struct extent));
+ struct extent *e = rv;
+ int i;
__u32 reservation;
/* trim the reserved area for spares, so they can join any array
@@ -1553,9 +1561,6 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
else
reservation = MPB_SECTOR_CNT + IMSM_RESERVED_SECTORS;
- rv = xcalloc(sizeof(struct extent), (memberships + 1));
- e = rv;
-
for (i = 0; i < super->anchor->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
struct imsm_map *map = get_imsm_map(dev, MAP_0);
@@ -1563,6 +1568,7 @@ static struct extent *get_extents(struct intel_super *super, struct dl *dl,
if (get_imsm_disk_slot(map, dl->index) >= 0) {
e->start = pba_of_lba0(map);
e->size = per_dev_array_size(map);
+ e->vol = i;
e++;
}
}
@@ -6894,24 +6900,26 @@ static unsigned long long find_size(struct extent *e, int *idx, int num_extents)
return end - base_start;
}
-/** merge_extents() - analyze extents and get max common free size.
+/** merge_extents() - analyze extents and get free size.
* @super: Intel metadata, not NULL.
+ * @expanding: if set, we are expanding &super->current_vol.
*
- * Build a composite disk with all known extents and generate a new maxsize
- * given the "all disks in an array must share a common start offset"
- * constraint.
+ * Build a composite disk with all known extents and generate a size given the
+ * "all disks in an array must share a common start offset" constraint.
+ * If a volume is expanded, then return free space after the volume.
*
- * Return: Max free space or 0 on failure.
+ * Return: Free space or 0 on failure.
*/
-static unsigned long long merge_extents(struct intel_super *super)
+static unsigned long long merge_extents(struct intel_super *super, const bool expanding)
{
struct extent *e;
struct dl *dl;
- int i, j;
- int start_extent, sum_extents = 0;
- unsigned long long pos;
+ int i, j, pos_vol_idx = -1;
+ int extent_idx = 0;
+ int sum_extents = 0;
+ unsigned long long pos = 0;
unsigned long long start = 0;
- unsigned long long maxsize;
+ unsigned long long maxsize = 0;
unsigned long reserve;
for (dl = super->disks; dl; dl = dl->next)
@@ -6936,26 +6944,26 @@ static unsigned long long merge_extents(struct intel_super *super)
j = 0;
while (i < sum_extents) {
e[j].start = e[i].start;
+ e[j].vol = e[i].vol;
e[j].size = find_size(e, &i, sum_extents);
j++;
if (e[j-1].size == 0)
break;
}
- pos = 0;
- maxsize = 0;
- start_extent = 0;
i = 0;
do {
- unsigned long long esize;
+ unsigned long long esize = e[i].start - pos;
- esize = e[i].start - pos;
- if (esize >= maxsize) {
+ if (expanding ? pos_vol_idx == super->current_vol : esize >= maxsize) {
maxsize = esize;
start = pos;
- start_extent = i;
+ extent_idx = i;
}
+
pos = e[i].start + e[i].size;
+ pos_vol_idx = e[i].vol;
+
i++;
} while (e[i-1].size);
free(e);
@@ -6966,7 +6974,7 @@ static unsigned long long merge_extents(struct intel_super *super)
/* FIXME assumes volume at offset 0 is the first volume in a
* container
*/
- if (start_extent > 0)
+ if (extent_idx > 0)
reserve = IMSM_RESERVED_SECTORS; /* gap between raid regions */
else
reserve = 0;
@@ -7577,7 +7585,7 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level,
return 0;
}
- maxsize = merge_extents(super);
+ maxsize = merge_extents(super, false);
if (mpb->num_raid_devs > 0 && size && size != maxsize)
pr_err("attempting to create a second volume with size less then remaining space.\n");
@@ -7626,7 +7634,8 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
const int raiddisks,
unsigned long long size,
const int chunk,
- unsigned long long *freesize)
+ unsigned long long *freesize,
+ bool expanding)
{
struct imsm_super *mpb = super->anchor;
struct dl *dl;
@@ -7663,7 +7672,7 @@ static imsm_status_t imsm_get_free_size(struct intel_super *super,
cnt++;
}
- maxsize = merge_extents(super);
+ maxsize = merge_extents(super, expanding);
if (maxsize < minsize) {
pr_err("imsm: Free space is %llu but must be equal or larger than %llu.\n",
maxsize, minsize);
@@ -7721,7 +7730,7 @@ static imsm_status_t autolayout_imsm(struct intel_super *super,
int vol_cnt = super->anchor->num_raid_devs;
imsm_status_t rv;
- rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize);
+ rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize, false);
if (rv != IMSM_STATUS_OK)
return IMSM_STATUS_ERROR;
@@ -11685,19 +11694,13 @@ static imsm_status_t imsm_analyze_expand(struct supertype *st,
goto success;
}
- if (super->current_vol + 1 != super->anchor->num_raid_devs) {
- pr_err("imsm: The last volume in container can be expanded only (%i/%s).\n",
- super->current_vol, st->devnm);
- return IMSM_STATUS_ERROR;
- }
-
if (data_disks == 0) {
pr_err("imsm: Cannot retrieve data disks.\n");
return IMSM_STATUS_ERROR;
}
current_size = array->custom_array_size / data_disks;
- rv = imsm_get_free_size(super, dev->vol.map->num_members, 0, chunk_kib, &free_size);
+ rv = imsm_get_free_size(super, dev->vol.map->num_members, 0, chunk_kib, &free_size, true);
if (rv != IMSM_STATUS_OK) {
pr_err("imsm: Cannot find free space for expand.\n");
return IMSM_STATUS_ERROR;
--
2.40.1

View File

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

View File

@ -0,0 +1,124 @@
From 21e622f214a38c048c5689158bc6314a91a46e40 Mon Sep 17 00:00:00 2001
From: Blazej Kucman <blazej.kucman@intel.com>
Date: Fri, 16 Jun 2023 21:45:55 +0200
Subject: [PATCH 133/165] Add secure gethostname() wrapper
gethostname() func does not ensure null-terminated string
if hostname is longer than buffer length.
For security, a function s_gethostname() has been added
to ensure that "\0" is added to the end of the buffer.
Previously this had to be handled in each place
of the gethostname() call.
Signed-off-by: Blazej Kucman <blazej.kucman@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Monitor.c | 3 +--
lib.c | 19 +++++++++++++++++++
mapfile.c | 3 +--
mdadm.c | 3 +--
mdadm.h | 1 +
super-ddf.c | 3 +--
6 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/Monitor.c b/Monitor.c
index 66175968..e74a0558 100644
--- a/Monitor.c
+++ b/Monitor.c
@@ -222,11 +222,10 @@ int Monitor(struct mddev_dev *devlist,
info.dosyslog = dosyslog;
info.test = c->test;
- if (gethostname(info.hostname, sizeof(info.hostname)) != 0) {
+ if (s_gethostname(info.hostname, sizeof(info.hostname)) != 0) {
pr_err("Cannot get hostname.\n");
return 1;
}
- info.hostname[sizeof(info.hostname) - 1] = '\0';
if (share){
if (check_one_sharer(c->scan) == 2)
diff --git a/lib.c b/lib.c
index fe5c8d2c..8a4b48e0 100644
--- a/lib.c
+++ b/lib.c
@@ -585,3 +585,22 @@ int parse_num(int *dest, const char *num)
*dest = temp;
return 0;
}
+
+/**
+ * s_gethostname() - secure get hostname. Assure null-terminated string.
+ *
+ * @buf: buffer for hostname.
+ * @buf_len: buffer length.
+ *
+ * Return: gethostname() result.
+ */
+int s_gethostname(char *buf, int buf_len)
+{
+ assert(buf);
+
+ int ret = gethostname(buf, buf_len);
+
+ buf[buf_len - 1] = 0;
+
+ return ret;
+}
diff --git a/mapfile.c b/mapfile.c
index 34fea179..f1f3ee2c 100644
--- a/mapfile.c
+++ b/mapfile.c
@@ -363,8 +363,7 @@ void RebuildMap(void)
char *homehost = conf_get_homehost(&require_homehost);
if (homehost == NULL || strcmp(homehost, "<system>")==0) {
- if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
- sys_hostname[sizeof(sys_hostname)-1] = 0;
+ if (s_gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
homehost = sys_hostname;
}
}
diff --git a/mdadm.c b/mdadm.c
index 076b45e0..e32598cb 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1340,8 +1340,7 @@ int main(int argc, char *argv[])
if (c.homehost == NULL && c.require_homehost)
c.homehost = conf_get_homehost(&c.require_homehost);
if (c.homehost == NULL || strcasecmp(c.homehost, "<system>") == 0) {
- if (gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
- sys_hostname[sizeof(sys_hostname)-1] = 0;
+ if (s_gethostname(sys_hostname, sizeof(sys_hostname)) == 0) {
c.homehost = sys_hostname;
}
}
diff --git a/mdadm.h b/mdadm.h
index 83f2cf7f..f0ceeb78 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1805,6 +1805,7 @@ extern void set_dlm_hooks(void);
extern void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt);
extern bool is_directory(const char *path);
extern bool is_file(const char *path);
+extern int s_gethostname(char *buf, int buf_len);
#define _ROUND_UP(val, base) (((val) + (base) - 1) & ~(base - 1))
#define ROUND_UP(val, base) _ROUND_UP(val, (typeof(val))(base))
diff --git a/super-ddf.c b/super-ddf.c
index 7213284e..c5242654 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -2364,8 +2364,7 @@ static int init_super_ddf(struct supertype *st,
* Remaining 16 are serial number.... maybe a hostname would do?
*/
memcpy(ddf->controller.guid, T10, sizeof(T10));
- gethostname(hostname, sizeof(hostname));
- hostname[sizeof(hostname) - 1] = 0;
+ s_gethostname(hostname, sizeof(hostname));
hostlen = strlen(hostname);
memcpy(ddf->controller.guid + 24 - hostlen, hostname, hostlen);
for (i = strlen(T10) ; i+hostlen < 24; i++)
--
2.40.1

View File

@ -0,0 +1,41 @@
From 1ab341e5ce0cb01a1533a2c36e5b69eabf12bf95 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Fri, 25 Aug 2023 20:55:41 +0800
Subject: [PATCH 134/165] mdadm: Stop mdcheck_continue timer when mdcheck_start
service can finish check
mdcheck_continue is triggered by mdcheck_start timer. It's used to
continue check action if the raid is too big and mdcheck_start
service can't finish check action. If mdcheck start can finish check
action, it doesn't need to mdcheck continue service anymore. So stop
it when mdcheck start service can finish check action.
Signed-off-by: Xiao Ni <xni@redhat.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
misc/mdcheck | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/misc/mdcheck b/misc/mdcheck
index 700c3e25..f87999d3 100644
--- a/misc/mdcheck
+++ b/misc/mdcheck
@@ -140,7 +140,13 @@ do
echo $a > $fl
any=yes
done
- if [ -z "$any" ]; then exit 0; fi
+ # mdcheck_continue.timer is started by mdcheck_start.timer.
+ # When the check action can be finished in mdcheck_start.service,
+ # it doesn't need mdcheck_continue anymore.
+ if [ -z "$any" ]; then
+ systemctl stop mdcheck_continue.timer
+ exit 0;
+ fi
sleep 120
done
--
2.40.1

View File

@ -0,0 +1,90 @@
From e9fb93af0f769d147a13e86ab4e5d0aeb935e9fc Mon Sep 17 00:00:00 2001
From: Guanqin Miao <miaoguanqin@huawei.com>
Date: Mon, 24 Apr 2023 16:06:34 +0800
Subject: [PATCH 135/165] Fix memory leak in file Assemble
When we test mdadm with asan, we found some memory leaks in Assemble.c
We fix these memory leaks based on code logic.
v2: Set st = NULL before jumping to loop
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Assemble.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 49804941..61e8cd17 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -341,8 +341,10 @@ static int select_devices(struct mddev_dev *devlist,
st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
- if (tst)
+ if (tst) {
tst->ss->free_super(tst);
+ free(tst);
+ }
return -1;
}
@@ -417,6 +419,7 @@ static int select_devices(struct mddev_dev *devlist,
st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
+ free(st);
return -1;
}
if (c->verbose > 0)
@@ -425,6 +428,8 @@ static int select_devices(struct mddev_dev *devlist,
/* make sure we finished the loop */
tmpdev = NULL;
+ free(st);
+ st = NULL;
goto loop;
} else {
content = *contentp;
@@ -533,6 +538,7 @@ static int select_devices(struct mddev_dev *devlist,
st->ss->free_super(st);
dev_policy_free(pol);
domain_free(domains);
+ free(tst);
return -1;
}
tmpdev->used = 1;
@@ -546,8 +552,10 @@ static int select_devices(struct mddev_dev *devlist,
}
dev_policy_free(pol);
pol = NULL;
- if (tst)
+ if (tst) {
tst->ss->free_super(tst);
+ free(tst);
+ }
}
/* Check if we found some imsm spares but no members */
@@ -839,6 +847,7 @@ static int load_devices(struct devs *devices, char *devmap,
close(mdfd);
free(devices);
free(devmap);
+ free(best);
*stp = st;
return -1;
}
@@ -1950,6 +1959,7 @@ out:
} else if (mdfd >= 0)
close(mdfd);
+ free(best);
/* '2' means 'OK, but not started yet' */
if (rv == -1) {
free(devices);
--
2.40.1

View File

@ -0,0 +1,54 @@
From 8fd0c565b09ba449418d7d604ceba66313246152 Mon Sep 17 00:00:00 2001
From: Guanqin Miao <miaoguanqin@huawei.com>
Date: Mon, 24 Apr 2023 16:06:35 +0800
Subject: [PATCH 136/165] Fix memory leak in file Kill
When we test mdadm with asan, we found some memory leaks in Kill.c
We fix these memory leaks based on code logic.
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Kill.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Kill.c b/Kill.c
index bfd0efdc..43c9abed 100644
--- a/Kill.c
+++ b/Kill.c
@@ -41,6 +41,7 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl)
* 4 - failed to find a superblock.
*/
+ bool free_super = false;
int fd, rv = 0;
if (force)
@@ -52,8 +53,10 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl)
dev);
return 2;
}
- if (st == NULL)
+ if (st == NULL) {
st = guess_super(fd);
+ free_super = true;
+ }
if (st == NULL || st->ss->init_super == NULL) {
if (verbose >= 0)
pr_err("Unrecognised md component device - %s\n", dev);
@@ -77,6 +80,10 @@ int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl)
rv = 0;
}
}
+ if (free_super && st) {
+ st->ss->free_super(st);
+ free(st);
+ }
close(fd);
return rv;
}
--
2.40.1

View File

@ -0,0 +1,74 @@
From f6feb3fbb50f48c193e9e4d775a20aa20f7b47b3 Mon Sep 17 00:00:00 2001
From: Guanqin Miao <miaoguanqin@huawei.com>
Date: Mon, 24 Apr 2023 16:06:36 +0800
Subject: [PATCH 137/165] Fix memory leak in file Manage
When we test mdadm with asan, we found some memory leaks in Manage.c
We fix these memory leaks based on code logic.
v2: Fix free() of uninitialized 'tst' in abort path.
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Manage.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/Manage.c b/Manage.c
index f54de7c6..f997b163 100644
--- a/Manage.c
+++ b/Manage.c
@@ -222,6 +222,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry)
if (verbose >= 0)
pr_err("Cannot get exclusive access to %s:Perhaps a running process, mounted filesystem or active volume group?\n",
devname);
+ sysfs_free(mdi);
return 1;
}
/* If this is an mdmon managed array, just write 'inactive'
@@ -801,8 +802,14 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
rdev, update, devname,
verbose, array);
dev_st->ss->free_super(dev_st);
- if (rv)
+ if (rv) {
+ free(dev_st);
return rv;
+ }
+ }
+ if (dev_st) {
+ dev_st->ss->free_super(dev_st);
+ free(dev_st);
}
}
if (dv->disposition == 'M') {
@@ -1362,7 +1369,7 @@ int Manage_subdevs(char *devname, int fd,
unsigned long long array_size;
struct mddev_dev *dv;
int tfd = -1;
- struct supertype *tst;
+ struct supertype *tst = NULL;
char *subarray = NULL;
int sysfd = -1;
int count = 0; /* number of actions taken */
@@ -1699,6 +1706,7 @@ int Manage_subdevs(char *devname, int fd,
break;
}
}
+ free(tst);
if (frozen > 0)
sysfs_set_str(&info, NULL, "sync_action","idle");
if (test && count == 0)
@@ -1706,6 +1714,7 @@ int Manage_subdevs(char *devname, int fd,
return 0;
abort:
+ free(tst);
if (frozen > 0)
sysfs_set_str(&info, NULL, "sync_action","idle");
return !test && busy ? 2 : 1;
--
2.40.1

View File

@ -0,0 +1,34 @@
From e62a561ee8b7157a2390eab215dcef6240bd7b03 Mon Sep 17 00:00:00 2001
From: Guanqin Miao <miaoguanqin@huawei.com>
Date: Mon, 24 Apr 2023 16:06:37 +0800
Subject: [PATCH 138/165] Fix memory leak in file mdadm
When we test mdadm with asan, we found some memory leaks in mdadm.c
We fix these memory leaks based on code logic.
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdadm.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/mdadm.c b/mdadm.c
index e32598cb..22d1c53b 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1708,6 +1708,10 @@ int main(int argc, char *argv[])
autodetect();
break;
}
+ if (ss) {
+ ss->ss->free_super(ss);
+ free(ss);
+ }
if (locked)
cluster_release_dlmlock();
close_fd(&mdfd);
--
2.40.1

View File

@ -0,0 +1,116 @@
From dd5ab40204b1d78ec3bdbcfd5a38a8ffb72bdb50 Mon Sep 17 00:00:00 2001
From: Kinga Tanska <kinga.tanska@intel.com>
Date: Thu, 11 May 2023 04:55:12 +0200
Subject: [PATCH 139/165] Fix unsafe string functions
Add string length limitations where necessary to
avoid buffer overflows.
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
mdmon.c | 6 +++---
mdopen.c | 4 ++--
platform-intel.c | 2 +-
super-intel.c | 6 +++---
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/mdmon.c b/mdmon.c
index cef5bbc8..a2038fe6 100644
--- a/mdmon.c
+++ b/mdmon.c
@@ -240,7 +240,7 @@ static int make_control_sock(char *devname)
return -1;
addr.sun_family = PF_LOCAL;
- strcpy(addr.sun_path, path);
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
umask(077); /* ensure no world write access */
if (bind(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
close(sfd);
@@ -389,7 +389,7 @@ int main(int argc, char *argv[])
if (all) {
struct mdstat_ent *mdstat, *e;
- int container_len = strlen(container_name);
+ int container_len = strnlen(container_name, MD_NAME_MAX);
/* launch an mdmon instance for each container found */
mdstat = mdstat_read(0, 0);
@@ -472,7 +472,7 @@ static int mdmon(char *devnm, int must_fork, int takeover)
pfd[0] = pfd[1] = -1;
container = xcalloc(1, sizeof(*container));
- strcpy(container->devnm, devnm);
+ snprintf(container->devnm, MD_NAME_MAX, "%s", devnm);
container->arrays = NULL;
container->sock = -1;
diff --git a/mdopen.c b/mdopen.c
index d3022a54..3daa71f9 100644
--- a/mdopen.c
+++ b/mdopen.c
@@ -193,14 +193,14 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy,
if (dev) {
if (strncmp(dev, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
- strcpy(cname, dev + DEV_MD_DIR_LEN);
+ snprintf(cname, MD_NAME_MAX, "%s", dev + DEV_MD_DIR_LEN);
} else if (strncmp(dev, "/dev/", 5) == 0) {
char *e = dev + strlen(dev);
while (e > dev && isdigit(e[-1]))
e--;
if (e[0])
num = strtoul(e, NULL, 10);
- strcpy(cname, dev+5);
+ snprintf(cname, MD_NAME_MAX, "%s", dev + 5);
cname[e-(dev+5)] = 0;
/* name *must* be mdXX or md_dXX in this context */
if (num < 0 ||
diff --git a/platform-intel.c b/platform-intel.c
index 914164c0..eb6e1b7e 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -214,7 +214,7 @@ struct sys_dev *device_by_id_and_path(__u16 device_id, const char *path)
static int devpath_to_ll(const char *dev_path, const char *entry, unsigned long long *val)
{
- char path[strlen(dev_path) + strlen(entry) + 2];
+ char path[strnlen(dev_path, PATH_MAX) + strnlen(entry, PATH_MAX) + 2];
int fd;
int n;
diff --git a/super-intel.c b/super-intel.c
index 824c1356..ce813172 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -7043,7 +7043,7 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist,
int fd = -1;
while (dev && !is_fd_valid(fd)) {
char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1);
- num = sprintf(path, "%s%s", "/dev/", dev->name);
+ num = snprintf(path, PATH_MAX, "%s%s", "/dev/", dev->name);
if (num > 0)
fd = open(path, O_RDONLY, 0);
if (num <= 0 || !is_fd_valid(fd)) {
@@ -7935,7 +7935,7 @@ static int kill_subarray_imsm(struct supertype *st, char *subarray_id)
if (i < current_vol)
continue;
- sprintf(subarray, "%u", i);
+ snprintf(subarray, sizeof(subarray), "%u", i);
if (is_subarray_active(subarray, st->devnm)) {
pr_err("deleting subarray-%d would change the UUID of active subarray-%d, aborting\n",
current_vol, i);
@@ -11308,7 +11308,7 @@ static const char *imsm_get_disk_controller_domain(const char *path)
char *drv=NULL;
struct stat st;
- strcpy(disk_path, disk_by_path);
+ strncpy(disk_path, disk_by_path, PATH_MAX);
strncat(disk_path, path, PATH_MAX - strlen(disk_path) - 1);
if (stat(disk_path, &st) == 0) {
struct sys_dev* hba;
--
2.40.1

View File

@ -0,0 +1,55 @@
From 5ccd457b29809bee442749b5f66ac27ebba4a72d Mon Sep 17 00:00:00 2001
From: Kinga Tanska <kinga.tanska@intel.com>
Date: Thu, 11 May 2023 04:55:13 +0200
Subject: [PATCH 140/165] platform-intel: limit guid length
Moving GUID_STR_MAX to header to use it as
a length limitation for snprintf function.
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
platform-intel.c | 3 ---
platform-intel.h | 5 ++++-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/platform-intel.c b/platform-intel.c
index eb6e1b7e..ef90c3fd 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -510,9 +510,6 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba)
return get_orom_by_device_id(hba->dev_id);
}
-#define GUID_STR_MAX 37 /* according to GUID format:
- * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
-
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
((struct efi_guid) \
{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
diff --git a/platform-intel.h b/platform-intel.h
index 2c0f4e39..ba97fb04 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -19,6 +19,9 @@
#include <asm/types.h>
#include <strings.h>
+/* according to GUID format: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */
+#define GUID_STR_MAX 37
+
/* The IMSM Capability (IMSM AHCI and ISCU OROM/EFI variable) Version Table definition */
struct imsm_orom {
__u8 signature[4];
@@ -229,7 +232,7 @@ extern struct orom_entry *orom_entries;
static inline char *guid_str(char *buf, struct efi_guid guid)
{
- sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ snprintf(buf, GUID_STR_MAX, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid.b[3], guid.b[2], guid.b[1], guid.b[0],
guid.b[5], guid.b[4], guid.b[7], guid.b[6],
guid.b[8], guid.b[9], guid.b[10], guid.b[11],
--
2.40.1

View File

@ -0,0 +1,220 @@
From 8d1114be8c0a307d251c24078833b029efabc448 Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Wed, 5 Jul 2023 16:23:17 +0200
Subject: [PATCH 141/165] imsm: Add reading vmd register for finding imsm
capability
Currently mdadm does not find imsm capability when running inside VM.
This patch adds the possibility to read from vmd register and check for
capability, effectively allowing to use mdadm with imsm inside virtual machines.
Additionally refactor find_imsm_capability() to make assignments in new
lines.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
platform-intel.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++-
platform-intel.h | 11 ++++-
super-intel.c | 11 +++--
3 files changed, 130 insertions(+), 6 deletions(-)
diff --git a/platform-intel.c b/platform-intel.c
index ef90c3fd..ac282bc5 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -700,6 +700,106 @@ const struct imsm_orom *find_imsm_nvme(struct sys_dev *hba)
return &nvme_orom->orom;
}
+#define VMD_REGISTER_OFFSET 0x3FC
+#define VMD_REGISTER_SKU_SHIFT 1
+#define VMD_REGISTER_SKU_MASK (0x00000007)
+#define VMD_REGISTER_SKU_PREMIUM 2
+#define MD_REGISTER_VER_MAJOR_SHIFT 4
+#define MD_REGISTER_VER_MAJOR_MASK (0x0000000F)
+#define MD_REGISTER_VER_MINOR_SHIFT 8
+#define MD_REGISTER_VER_MINOR_MASK (0x0000000F)
+
+/*
+ * read_vmd_register() - Reads VMD register and writes contents to buff ptr
+ * @buff: buffer for vmd register data, should be the size of uint32_t
+ *
+ * Return: 0 on success, 1 on error
+ */
+int read_vmd_register(uint32_t *buff, struct sys_dev *hba)
+{
+ int fd;
+ char vmd_pci_config_path[PATH_MAX];
+
+ if (!vmd_domain_to_controller(hba, vmd_pci_config_path))
+ return 1;
+
+ strncat(vmd_pci_config_path, "/config", PATH_MAX - strnlen(vmd_pci_config_path, PATH_MAX));
+
+ fd = open(vmd_pci_config_path, O_RDONLY);
+ if (fd < 0)
+ return 1;
+
+ if (pread(fd, buff, sizeof(uint32_t), VMD_REGISTER_OFFSET) != sizeof(uint32_t)) {
+ close(fd);
+ return 1;
+ }
+ close(fd);
+ return 0;
+}
+
+/*
+ * add_vmd_orom() - Adds VMD orom cap to orom list, writes orom_entry ptr into vmd_orom
+ * @vmd_orom: pointer to orom entry pointer
+ *
+ * Return: 0 on success, 1 on error
+ */
+int add_vmd_orom(struct orom_entry **vmd_orom, struct sys_dev *hba)
+{
+ uint8_t sku;
+ uint32_t vmd_register_data;
+ struct imsm_orom vmd_orom_cap = {
+ .signature = IMSM_VMD_OROM_COMPAT_SIGNATURE,
+ .sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB |
+ IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB |
+ IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB,
+ .dpa = IMSM_OROM_DISKS_PER_ARRAY_NVME,
+ .tds = IMSM_OROM_TOTAL_DISKS_VMD,
+ .vpa = IMSM_OROM_VOLUMES_PER_ARRAY,
+ .vphba = IMSM_OROM_VOLUMES_PER_HBA_VMD,
+ .attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK,
+ .driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem |
+ IMSM_OROM_CAPABILITIES_TPV
+ };
+
+ if (read_vmd_register(&vmd_register_data, hba) != 0)
+ return 1;
+
+ sku = (uint8_t)((vmd_register_data >> VMD_REGISTER_SKU_SHIFT) &
+ VMD_REGISTER_SKU_MASK);
+
+ if (sku == VMD_REGISTER_SKU_PREMIUM)
+ vmd_orom_cap.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
+ IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5;
+ else
+ vmd_orom_cap.rlc = IMSM_OROM_RLC_RAID_CNG;
+
+ vmd_orom_cap.major_ver = (uint8_t)
+ ((vmd_register_data >> MD_REGISTER_VER_MAJOR_SHIFT) &
+ MD_REGISTER_VER_MAJOR_MASK);
+ vmd_orom_cap.minor_ver = (uint8_t)
+ ((vmd_register_data >> MD_REGISTER_VER_MINOR_SHIFT) &
+ MD_REGISTER_VER_MINOR_MASK);
+
+ *vmd_orom = add_orom(&vmd_orom_cap);
+
+ return 0;
+}
+
+const struct imsm_orom *find_imsm_vmd(struct sys_dev *hba)
+{
+ static struct orom_entry *vmd_orom;
+
+ if (hba->type != SYS_DEV_VMD)
+ return NULL;
+
+ if (!vmd_orom && add_vmd_orom(&vmd_orom, hba) != 0)
+ return NULL;
+
+ add_orom_device_id(vmd_orom, hba->dev_id);
+ vmd_orom->type = SYS_DEV_VMD;
+ return &vmd_orom->orom;
+}
+
const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
{
const struct imsm_orom *cap = get_orom_by_device_id(hba->dev_id);
@@ -709,9 +809,19 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
if (hba->type == SYS_DEV_NVME)
return find_imsm_nvme(hba);
- if ((cap = find_imsm_efi(hba)) != NULL)
+
+ cap = find_imsm_efi(hba);
+ if (cap)
return cap;
- if ((cap = find_imsm_hba_orom(hba)) != NULL)
+
+ if (hba->type == SYS_DEV_VMD) {
+ cap = find_imsm_vmd(hba);
+ if (cap)
+ return cap;
+ }
+
+ cap = find_imsm_hba_orom(hba);
+ if (cap)
return cap;
return NULL;
diff --git a/platform-intel.h b/platform-intel.h
index ba97fb04..ce29d3da 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -27,6 +27,7 @@ struct imsm_orom {
__u8 signature[4];
#define IMSM_OROM_SIGNATURE "$VER"
#define IMSM_NVME_OROM_COMPAT_SIGNATURE "$NVM"
+ #define IMSM_VMD_OROM_COMPAT_SIGNATURE "$VMD"
__u8 table_ver_major; /* Currently 2 (can change with future revs) */
__u8 table_ver_minor; /* Currently 2 (can change with future revs) */
__u16 major_ver; /* Example: 8 as in 8.6.0.1020 */
@@ -68,11 +69,13 @@ struct imsm_orom {
__u16 tds; /* Total Disks Supported */
#define IMSM_OROM_TOTAL_DISKS 6
#define IMSM_OROM_TOTAL_DISKS_NVME 12
+ #define IMSM_OROM_TOTAL_DISKS_VMD 48
__u8 vpa; /* # Volumes Per Array supported */
#define IMSM_OROM_VOLUMES_PER_ARRAY 2
__u8 vphba; /* # Volumes Per Host Bus Adapter supported */
#define IMSM_OROM_VOLUMES_PER_HBA 4
#define IMSM_OROM_VOLUMES_PER_HBA_NVME 4
+ #define IMSM_OROM_VOLUMES_PER_HBA_VMD 24
/* Attributes supported. This should map to the
* attributes in the MPB. Also, lower 16 bits
* should match/duplicate RLC bits above.
@@ -185,7 +188,13 @@ static inline int imsm_orom_is_enterprise(const struct imsm_orom *orom)
static inline int imsm_orom_is_nvme(const struct imsm_orom *orom)
{
return memcmp(orom->signature, IMSM_NVME_OROM_COMPAT_SIGNATURE,
- sizeof(orom->signature)) == 0;
+ sizeof(orom->signature)) == 0;
+}
+
+static inline int imsm_orom_is_vmd_without_efi(const struct imsm_orom *orom)
+{
+ return memcmp(orom->signature, IMSM_VMD_OROM_COMPAT_SIGNATURE,
+ sizeof(orom->signature)) == 0;
}
static inline int imsm_orom_has_tpv_support(const struct imsm_orom *orom)
diff --git a/super-intel.c b/super-intel.c
index ce813172..77b0066f 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2672,9 +2672,14 @@ static void print_imsm_capability(const struct imsm_orom *orom)
else
printf("Rapid Storage Technology%s\n",
imsm_orom_is_enterprise(orom) ? " enterprise" : "");
- if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
- printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
- orom->minor_ver, orom->hotfix_ver, orom->build);
+ if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) {
+ if (imsm_orom_is_vmd_without_efi(orom))
+ printf(" Version : %d.%d\n", orom->major_ver,
+ orom->minor_ver);
+ else
+ printf(" Version : %d.%d.%d.%d\n", orom->major_ver,
+ orom->minor_ver, orom->hotfix_ver, orom->build);
+ }
printf(" RAID Levels :%s%s%s%s%s\n",
imsm_orom_has_raid0(orom) ? " raid0" : "",
imsm_orom_has_raid1(orom) ? " raid1" : "",
--
2.40.1

View File

@ -0,0 +1,109 @@
From 55a1150c7438afcb7756fccd49713ede20a58e4a Mon Sep 17 00:00:00 2001
From: Mateusz Grzonka <mateusz.grzonka@intel.com>
Date: Mon, 17 Jul 2023 15:19:10 +0200
Subject: [PATCH 142/165] Add compiler defenses flags
It is essential to avoid buffer overflows and similar bugs as much as
possible.
According to Intel rules we are obligated to verify certain
compiler flags, so it will be much easier if they are added to the
Makefile.
Add gcc flags for prevention of buffer overflows, format string vulnerabilities,
stack protection to prevent stack overwrites and aslr enablement through -fPIE.
Also make the flags configurable.
The changes were verified on gcc versions 7.5, 8.3, 9.2, 10 and 12.2.
Signed-off-by: Mateusz Grzonka <mateusz.grzonka@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Makefile | 41 +++++++++++++++++++++++++++++------------
1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/Makefile b/Makefile
index 5eac1a4e..b3aa36f6 100644
--- a/Makefile
+++ b/Makefile
@@ -30,7 +30,7 @@
# define "CXFLAGS" to give extra flags to CC.
# e.g. make CXFLAGS=-O to optimise
-CXFLAGS ?=-O2
+CXFLAGS ?=-O2 -D_FORTIFY_SOURCE=2
TCC = tcc
UCLIBC_GCC = $(shell for nm in i386-uclibc-linux-gcc i386-uclibc-gcc; do which $$nm > /dev/null && { echo $$nm ; exit; } ; done; echo false No uclibc found )
#DIET_GCC = diet gcc
@@ -50,14 +50,30 @@ ifeq ($(origin CC),default)
CC := $(CROSS_COMPILE)gcc
endif
CXFLAGS ?= -ggdb
-CWFLAGS = -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter
+CWFLAGS ?= -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter -Wformat -Wformat-security -Werror=format-security -fstack-protector-strong -fPIE -Warray-bounds
ifdef WARN_UNUSED
-CWFLAGS += -Wp,-D_FORTIFY_SOURCE=2 -O3
+CWFLAGS += -Wp -O3
endif
-FALLTHROUGH := $(shell gcc -v --help 2>&1 | grep "implicit-fallthrough" | wc -l)
-ifneq "$(FALLTHROUGH)" "0"
-CWFLAGS += -Wimplicit-fallthrough=0
+ifeq ($(origin FALLTHROUGH), undefined)
+ FALLTHROUGH := $(shell gcc -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l)
+ ifneq "$(FALLTHROUGH)" "0"
+ CWFLAGS += -Wimplicit-fallthrough=0
+ endif
+endif
+
+ifeq ($(origin FORMATOVERFLOW), undefined)
+ FORMATOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l)
+ ifneq "$(FORMATOVERFLOW)" "0"
+ CWFLAGS += -Wformat-overflow
+ endif
+endif
+
+ifeq ($(origin STRINGOPOVERFLOW), undefined)
+ STRINGOPOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l)
+ ifneq "$(STRINGOPOVERFLOW)" "0"
+ CWFLAGS += -Wstringop-overflow
+ endif
endif
ifdef DEBIAN
@@ -116,10 +132,12 @@ CFLAGS += -DUSE_PTHREADS
MON_LDFLAGS += -pthread
endif
+LDFLAGS = -Wl,-z,now,-z,noexecstack
+
# If you want a static binary, you might uncomment these
-# LDFLAGS = -static
+# LDFLAGS += -static
# STRIP = -s
-LDLIBS = -ldl
+LDLIBS = -ldl -pie
# To explicitly disable libudev, set -DNO_LIBUDEV in CXFLAGS
ifeq (, $(findstring -DNO_LIBUDEV, $(CXFLAGS)))
@@ -209,14 +227,13 @@ mdadm.Os : $(SRCS) $(INCL)
$(CC) -o mdadm.Os $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -Os $(SRCS) $(LDLIBS)
mdadm.O2 : $(SRCS) $(INCL) mdmon.O2
- $(CC) -o mdadm.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(SRCS) $(LDLIBS)
+ $(CC) -o mdadm.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -DHAVE_STDINT_H -O2 $(SRCS) $(LDLIBS)
mdmon.O2 : $(MON_SRCS) $(INCL) mdmon.h
- $(CC) -o mdmon.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 -D_FORTIFY_SOURCE=2 $(MON_SRCS) $(LDLIBS)
+ $(CC) -o mdmon.O2 $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -DHAVE_STDINT_H -O2 $(MON_SRCS) $(LDLIBS)
-# use '-z now' to guarantee no dynamic linker interactions with the monitor thread
mdmon : $(MON_OBJS) | check_rundir
- $(CC) $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -Wl,-z,now -o mdmon $(MON_OBJS) $(LDLIBS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(MON_LDFLAGS) -o mdmon $(MON_OBJS) $(LDLIBS)
msg.o: msg.c msg.h
test_stripe : restripe.c xmalloc.o mdadm.h
--
2.40.1

View File

@ -0,0 +1,34 @@
From 024d652e16dd9e3bd1ecdfce4d6f7a8cb498ba42 Mon Sep 17 00:00:00 2001
From: Kinga Tanska <kinga.tanska@intel.com>
Date: Tue, 12 Sep 2023 04:27:01 +0200
Subject: [PATCH 143/165] Assemble: fix redundant memory free
Commit e9fb93af0f76 ("Fix memory leak in file Assemble")
fixes few memory leaks in Assemble, but it introduces
problem with assembling RAID volume. It was caused by
clearing metadata too fast, not only on fail in
select_devices() function.
This commit removes redundant memory free.
Signed-off-by: Kinga Tanska <kinga.tanska@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Assemble.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 61e8cd17..5be58e40 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -428,8 +428,6 @@ static int select_devices(struct mddev_dev *devlist,
/* make sure we finished the loop */
tmpdev = NULL;
- free(st);
- st = NULL;
goto loop;
} else {
content = *contentp;
--
2.40.1

View File

@ -0,0 +1,92 @@
From 7fe21767d3ab65a686518d2e36d18a07f535972e Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:19 +0800
Subject: [PATCH 144/165] tests: add a new test for rdev lifetime
This test add and remove a underlying disk to raid concurretly, verify
that the following problem is fixed:
run mdadm test 23rdev-lifetime at Fri Apr 28 03:25:30 UTC 2023
md: could not open device unknown-block(1,0).
sysfs: cannot create duplicate filename '/devices/virtual/block/md0/md/dev-ram0'
CPU: 26 PID: 10521 Comm: test Not tainted 6.3.0-rc2-00134-g7b3a8828043c #115
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/014
Call Trace:
<TASK>
dump_stack_lvl+0xe7/0x180
dump_stack+0x18/0x30
sysfs_warn_dup+0xa2/0xd0
sysfs_create_dir_ns+0x119/0x140
kobject_add_internal+0x143/0x4d0
kobject_add_varg+0x35/0x70
kobject_add+0x64/0xd0
bind_rdev_to_array+0x254/0x840 [md_mod]
new_dev_store+0x14d/0x350 [md_mod]
md_attr_store+0xc1/0x1a0 [md_mod]
sysfs_kf_write+0x51/0x70
kernfs_fop_write_iter+0x188/0x270
vfs_write+0x27e/0x460
ksys_write+0x85/0x180
__x64_sys_write+0x21/0x30
do_syscall_64+0x6c/0xe0
entry_SYSCALL_64_after_hwframe+0x63/0xcd
RIP: 0033:0x7f26bacf5387
Code: 0d 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 84
RSP: 002b:00007ffe98d79e68 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007f26bacf5387
RDX: 0000000000000004 RSI: 000055bd10282bf0 RDI: 0000000000000001
RBP: 000055bd10282bf0 R08: 000000000000000a R09: 00007f26bad8b4e0
R10: 00007f26bad8b3e0 R11: 0000000000000246 R12: 0000000000000004
R13: 00007f26badc8520 R14: 0000000000000004 R15: 00007f26badc8700
</TASK>
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/23rdev-lifetime | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 tests/23rdev-lifetime
diff --git a/tests/23rdev-lifetime b/tests/23rdev-lifetime
new file mode 100644
index 00000000..1750b0db
--- /dev/null
+++ b/tests/23rdev-lifetime
@@ -0,0 +1,34 @@
+devname=${dev0##*/}
+devt=`cat /sys/block/$devname/dev`
+pid=""
+runtime=2
+
+clean_up_test() {
+ pill -9 $pid
+ echo clear > /sys/block/md0/md/array_state
+}
+
+trap 'clean_up_test' EXIT
+
+add_by_sysfs() {
+ while true; do
+ echo $devt > /sys/block/md0/md/new_dev
+ done
+}
+
+remove_by_sysfs(){
+ while true; do
+ echo remove > /sys/block/md0/md/dev-${devname}/state
+ done
+}
+
+echo md0 > /sys/module/md_mod/parameters/new_array || die "create md0 failed"
+
+add_by_sysfs &
+pid="$pid $!"
+
+remove_by_sysfs &
+pid="$pid $!"
+
+sleep $runtime
+exit 0
--
2.40.1

View File

@ -0,0 +1,38 @@
From 0ef9465f6355db612e53afc32e3084721c3dd7c7 Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:20 +0800
Subject: [PATCH 145/165] tests: support to skip checking dmesg
Prepare to add a regression test for raid10 that require error injection
to trigger error path, and kernel will complain about io error, checking
dmesg for error log will make it impossible to pass this test.
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
test | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/test b/test
index 61d9ee83..b244453b 100755
--- a/test
+++ b/test
@@ -107,8 +107,12 @@ do_test() {
echo -ne "$_script... "
if ( set -ex ; . $_script ) &> $targetdir/log
then
- dmesg | grep -iq "error\|call trace\|segfault" &&
- die "dmesg prints errors when testing $_basename!"
+ if [ -f "${_script}.inject_error" ]; then
+ echo "dmesg checking is skipped because test inject error"
+ else
+ dmesg | grep -iq "error\|call trace\|segfault" &&
+ die "dmesg prints errors when testing $_basename!"
+ fi
echo "succeeded"
_fail=0
else
--
2.40.1

View File

@ -0,0 +1,122 @@
From 3973f65293ce69ddd7c19be9a7a796abfe80e370 Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:21 +0800
Subject: [PATCH 146/165] tests: add a regression test for raid10 deadlock
The deadlock is described in [1], it's fixed first by [2], however,
it turns out this commit will trigger other problems[3], hence this
commit will be reverted and the deadlock is supposed to be fixed by [1].
[1] https://lore.kernel.org/linux-raid/20230322064122.2384589-5-yukuai1@huaweicloud.com/
[2] https://lore.kernel.org/linux-raid/20220621031129.24778-1-guoqing.jiang@linux.dev/
[3] https://lore.kernel.org/linux-raid/20230322064122.2384589-2-yukuai1@huaweicloud.com/
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/24raid10deadlock | 88 +++++++++++++++++++++++++++++
tests/24raid10deadlock.inject_error | 0
2 files changed, 88 insertions(+)
create mode 100644 tests/24raid10deadlock
create mode 100644 tests/24raid10deadlock.inject_error
diff --git a/tests/24raid10deadlock b/tests/24raid10deadlock
new file mode 100644
index 00000000..ee330aa9
--- /dev/null
+++ b/tests/24raid10deadlock
@@ -0,0 +1,88 @@
+devs="$dev0 $dev1 $dev2 $dev3"
+runtime=120
+pid=""
+action_pid=""
+
+set_up_injection()
+{
+ echo -1 > /sys/kernel/debug/fail_make_request/times
+ echo 1 > /sys/kernel/debug/fail_make_request/probability
+ echo 0 > /sys/kernel/debug/fail_make_request/verbose
+ echo 1 > /sys/block/${1##*/}/make-it-fail
+}
+
+clean_up_injection()
+{
+ echo 0 > /sys/block/${1##*/}/make-it-fail
+ echo 0 > /sys/kernel/debug/fail_make_request/times
+ echo 0 > /sys/kernel/debug/fail_make_request/probability
+ echo 2 > /sys/kernel/debug/fail_make_request/verbose
+}
+
+test_rdev()
+{
+ while true; do
+ mdadm -f $md0 $1 &> /dev/null
+ mdadm -r $md0 $1 &> /dev/null
+ mdadm --zero-superblock $1 &> /dev/null
+ mdadm -a $md0 $1 &> /dev/null
+ sleep $2
+ done
+}
+
+test_write_action()
+{
+ while true; do
+ echo frozen > /sys/block/md0/md/sync_action
+ echo idle > /sys/block/md0/md/sync_action
+ sleep 0.1
+ done
+}
+
+set_up_test()
+{
+ fio -h &> /dev/null || die "fio not found"
+
+ # create a simple raid10
+ mdadm -Cv -R -n 4 -l10 $md0 $devs || die "create raid10 failed"
+}
+
+clean_up_test()
+{
+ clean_up_injection $dev0
+ pkill -9 fio
+ kill -9 $pid
+ kill -9 $action_pid
+
+ sleep 1
+
+ if ps $action_pid | tail -1 | awk '{print $3}' | grep D; then
+ die "thread that is writing sysfs is stuck in D state, deadlock is triggered"
+ fi
+ mdadm -S $md0
+}
+
+cat /sys/kernel/debug/fail_make_request/times || die "fault injection is not enabled"
+
+trap 'clean_up_test' EXIT
+
+set_up_test || die "set up test failed"
+
+# backgroup io pressure
+fio -filename=$md0 -rw=randwrite -direct=1 -name=test -bs=4k -numjobs=16 -iodepth=16 &
+
+# trigger add/remove device by io failure
+set_up_injection $dev0
+test_rdev $dev0 2 &
+pid="$pid $!"
+
+# add/remove device directly
+test_rdev $dev3 10 &
+pid="$pid $!"
+
+test_write_action &
+action_pid="$!"
+
+sleep $runtime
+
+exit 0
diff --git a/tests/24raid10deadlock.inject_error b/tests/24raid10deadlock.inject_error
new file mode 100644
index 00000000..e69de29b
--
2.40.1

View File

@ -0,0 +1,87 @@
From 9d0fb58f3b1314678564b4ac7bfb19942acc8926 Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:22 +0800
Subject: [PATCH 147/165] tests: add a regression test for raid456 deadlock
The deadlock is described in [1], as the last patch described, it's
fixed first by [2], however this fix will be reverted and the deadlock
is supposed to be fixed by [3].
[1] https://lore.kernel.org/linux-raid/5ed54ffc-ce82-bf66-4eff-390cb23bc1ac@molgen.mpg.de/T/#t
[2] https://lore.kernel.org/linux-raid/20220621031129.24778-1-guoqing.jiang@linux.dev/
[3] https://lore.kernel.org/linux-raid/20230322064122.2384589-5-yukuai1@huaweicloud.com/
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/24raid456deadlock | 58 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
create mode 100644 tests/24raid456deadlock
diff --git a/tests/24raid456deadlock b/tests/24raid456deadlock
new file mode 100644
index 00000000..80e6e97e
--- /dev/null
+++ b/tests/24raid456deadlock
@@ -0,0 +1,58 @@
+devs="$dev0 $dev1 $dev2 $dev3 $dev4 $dev5"
+runtime=120
+pid=""
+old=`cat /proc/sys/vm/dirty_background_ratio`
+
+test_write_action()
+{
+ while true; do
+ echo check > /sys/block/md0/md/sync_action &> /dev/null
+ sleep 0.1
+ echo idle > /sys/block/md0/md/sync_action &> /dev/null
+ done
+}
+
+test_write_back()
+{
+ fio -filename=$md0 -bs=4k -rw=write -numjobs=1 -name=test \
+ -time_based -runtime=$runtime &> /dev/null
+}
+
+set_up_test()
+{
+ fio -h &> /dev/null || die "fio not found"
+
+ # create a simple raid6
+ mdadm -Cv -R -n 6 -l6 $md0 $devs --assume-clean || die "create raid6 failed"
+
+ # trigger dirty pages write back
+ echo 0 > /proc/sys/vm/dirty_background_ratio
+}
+
+clean_up_test()
+{
+ echo $old > /proc/sys/vm/dirty_background_ratio
+
+ pkill -9 fio
+ kill -9 $pid
+
+ sleep 1
+
+ if ps $pid | tail -1 | awk '{print $3}' | grep D; then
+ die "thread that is writing sysfs is stuck in D state, deadlock is triggered"
+ fi
+ mdadm -S $md0
+}
+
+trap 'clean_up_test' EXIT
+
+set_up_test || die "set up test failed"
+
+test_write_back &
+
+test_write_action &
+pid="$!"
+
+sleep $runtime
+
+exit 0
--
2.40.1

View File

@ -0,0 +1,59 @@
From 4db8a3d452daaf2def41ca45c36e36c5781627ac Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:23 +0800
Subject: [PATCH 148/165] tests: add a regression test that raid456 can't
assemble
If recovery is interrupted and reshape is started, then this array can't
assemble anymore. The problem is supposed to be fixed by [1].
[1] https://lore.kernel.org/linux-raid/20230529031045.1760883-1-yukuai1@huaweicloud.com/
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/25raid456-reshape-while-recovery | 32 ++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 tests/25raid456-reshape-while-recovery
diff --git a/tests/25raid456-reshape-while-recovery b/tests/25raid456-reshape-while-recovery
new file mode 100644
index 00000000..b9f871f2
--- /dev/null
+++ b/tests/25raid456-reshape-while-recovery
@@ -0,0 +1,32 @@
+devs="$dev0 $dev1 $dev2"
+
+set_up_test()
+{
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed"
+ mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array"
+ echo 1000 > /sys/block/md0/md/sync_speed_max
+}
+
+clean_up_test()
+{
+ mdadm -S $md0
+}
+
+trap 'clean_up_test' EXIT
+
+set_up_test || die "set up test failed"
+
+# set up replacement
+echo want_replacement > /sys/block/md0/md/rd0/state
+sleep 1
+
+# trigger reshape
+echo frozen > /sys/block/md0/md/sync_action
+mdadm --grow -l 6 $md0
+sleep 1
+
+# reassemeble array
+mdadm -S $md0 || die "can't stop array"
+mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array"
+
+exit 0
--
2.40.1

View File

@ -0,0 +1,58 @@
From 8d45abd0c317d3f4971b779b4f8d1e33b5490dac Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:24 +0800
Subject: [PATCH 149/165] tests: add a regression test that raid456 can't
assemble again
This is a regression test for commit 0aecb06e2249 ("md/raid5: don't allow
replacement while reshape is in progress").
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/25raid456-recovery-while-reshape | 33 ++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 tests/25raid456-recovery-while-reshape
diff --git a/tests/25raid456-recovery-while-reshape b/tests/25raid456-recovery-while-reshape
new file mode 100644
index 00000000..3f6251bf
--- /dev/null
+++ b/tests/25raid456-recovery-while-reshape
@@ -0,0 +1,33 @@
+devs="$dev0 $dev1 $dev2"
+
+set_up_test()
+{
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --assume-clean --size=50M || die "create array failed"
+ mdadm -a $md0 $dev3 $dev4 || die "failed to bind new disk to array"
+ echo 1000 > /sys/block/md0/md/sync_speed_max
+}
+
+clean_up_test()
+{
+ mdadm -S $md0
+}
+
+trap 'clean_up_test' EXIT
+
+set_up_test || die "set up test failed"
+
+# trigger reshape
+mdadm --grow -l 6 $md0
+sleep 1
+
+# set up replacement
+echo frozen > /sys/block/md0/md/sync_action
+echo want_replacement > /sys/block/md0/md/rd0/state
+echo reshape > /sys/block/md0/md/sync_action
+sleep 1
+
+# reassemeble array
+mdadm -S $md0 || die "can't stop array"
+mdadm --assemble $md0 $devs $dev3 $dev4 || die "can't assemble array"
+
+exit 0
--
2.40.1

View File

@ -0,0 +1,60 @@
From 481433482942c2ee2990965af394eff059990901 Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:25 +0800
Subject: [PATCH 150/165] tests: add a regression test that reshape can corrupt
data
This is a regression test for commit 1544e95c6dd8 ("md: fix data
corruption for raid456 when reshape restart while grow up").
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/25raid456-reshape-corrupt-data | 35 ++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 tests/25raid456-reshape-corrupt-data
diff --git a/tests/25raid456-reshape-corrupt-data b/tests/25raid456-reshape-corrupt-data
new file mode 100644
index 00000000..fdb875fb
--- /dev/null
+++ b/tests/25raid456-reshape-corrupt-data
@@ -0,0 +1,35 @@
+devs="$dev0 $dev1 $dev2"
+
+set_up_test()
+{
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed"
+ mdadm -a $md0 $dev3 || die "failed to bind new disk to array"
+ mkfs.xfs -f $md0 || die "mkfs failed"
+ xfs_ncheck $md0 || die "check fs failed"
+}
+
+clean_up_test()
+{
+ mdadm -S $md0
+}
+
+trap 'clean_up_test' EXIT
+
+set_up_test || die "set up test failed"
+
+# trigger reshape
+echo 1000 > /sys/block/md0/md/sync_speed_max
+mdadm --grow -l 6 $md0
+sleep 1
+
+# stop and start reshape
+echo frozen > /sys/block/md0/md/sync_action
+echo system > /sys/block/md0/md/sync_speed_max
+echo reshape > /sys/block/md0/md/sync_action
+
+mdadm -W $md0
+
+# check if data is corrupted
+xfs_ncheck $md0 || die "data is corrupted after reshape"
+
+exit 0
--
2.40.1

View File

@ -0,0 +1,59 @@
From c6c7bce5a3064ac9d2956ae42ecab27f2e33dc2b Mon Sep 17 00:00:00 2001
From: Yu Kuai <yukuai3@huawei.com>
Date: Mon, 29 May 2023 21:28:26 +0800
Subject: [PATCH 151/165] tests: add a regression test for raid456 deadlock
again
This is a regression test for commit ("md/raid5: fix a deadlock in the
case that reshape is interrupted").
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/25raid456-reshape-deadlock | 34 ++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 tests/25raid456-reshape-deadlock
diff --git a/tests/25raid456-reshape-deadlock b/tests/25raid456-reshape-deadlock
new file mode 100644
index 00000000..bfa0cc56
--- /dev/null
+++ b/tests/25raid456-reshape-deadlock
@@ -0,0 +1,34 @@
+devs="$dev0 $dev1 $dev2"
+
+set_up_test()
+{
+ mdadm -Cv -R -n 3 -l5 $md0 $devs --size=50M || die "create array failed"
+ mdadm -a $md0 $dev3 || die "failed to bind new disk to array"
+ echo 1000 > /sys/block/md0/md/sync_speed_max
+}
+
+clean_up_test()
+{
+ echo idle > /sys/block/md0/md/sync_action
+ mdadm -S $md0
+}
+
+trap 'clean_up_test' EXIT
+
+set_up_test || die "set up test failed"
+
+# trigger reshape
+mdadm --grow -l 6 $md0
+sleep 1
+
+# stop reshape
+echo frozen > /sys/block/md0/md/sync_action
+
+# read accross reshape
+dd if=$md0 of=/dev/NULL bs=1m count=100 iflag=direct &> /dev/null &
+sleep 2
+
+# suspend array
+echo 1 > /sys/block/md0/md/suspend_lo
+
+exit 0
--
2.40.1

View File

@ -0,0 +1,193 @@
From d5fee8654e41dc4067dfdc3312542f1f43ebe884 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 1 Jun 2023 09:27:45 +0200
Subject: [PATCH 152/165] tests: create names_template
Create templates directory and names_template. Move code from
00createnames. This code will be reused for 00confnames in next patch.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/00createnames | 86 +++++++---------------------------
tests/templates/names_template | 53 +++++++++++++++++++++
2 files changed, 70 insertions(+), 69 deletions(-)
create mode 100644 tests/templates/names_template
diff --git a/tests/00createnames b/tests/00createnames
index 64b81b92..064eeef2 100644
--- a/tests/00createnames
+++ b/tests/00createnames
@@ -1,93 +1,41 @@
set -x -e
+. tests/templates/names_template
# Test how <devname> and --name= are handled for create mode.
-# We need to check three properties, generated from those parameters:
-# - devnode name
-# - link in /dev/md/ (MD_DEVNAME property from --detail --export)
-# - name in metadata (MD_NAME property from --examine --export)
-
-function _verify() {
- local DEVNODE_NAME="$1"
- local WANTED_LINK="$2"
- local WANTED_NAME="$3"
-
- local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
- if [[ "$?" != "0" ]]; then
- echo "Cannot get details for $DEVNODE_NAME - unexpected devnode."
- exit 1
- fi
-
- if [[ "$WANTED_LINK" != "empty" ]]; then
- local EXPECTED="MD_DEVNAME=$WANTED_LINK"
- if [[ "$RES" != "$EXPECTED" ]]; then
- echo "$RES doesn't match $EXPECTED."
- exit 1
- fi
- fi
-
-
- local RES="$(mdadm -E --export $dev0 | grep MD_NAME)"
- if [[ "$?" != "0" ]]; then
- echo "Cannot get metadata from $dev0."
- exit 1
- fi
-
- local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
- if [[ "$RES" != "$EXPECTED" ]]; then
- echo "$RES doesn't match $EXPECTED."
- exit 1
- fi
-}
-
-function _create() {
- local DEVNAME=$1
- local NAME=$2
-
- if [[ -z "$NAME" ]]; then
- mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
- else
- mdadm -CR "$DEVNAME" --name="$NAME" -l0 -n 1 $dev0 --force
- fi
-
- if [[ "$?" != "0" ]]; then
- echo "Cannot create device."
- exit 1
- fi
-}
# The most trivial case.
-_create "/dev/md/name"
-_verify "/dev/md127" "name" "name"
+names_create "/dev/md/name"
+names_verify "/dev/md127" "name" "name"
mdadm -S "/dev/md127"
-_create "name"
-_verify "/dev/md127" "name" "name"
+names_create "name"
+names_verify "/dev/md127" "name" "name"
mdadm -S "/dev/md127"
# Use 'mdX' as name.
-_create "/dev/md/md0"
-_verify "/dev/md127" "md0" "md0"
+names_create "/dev/md/md0"
+names_verify "/dev/md127" "md0" "md0"
mdadm -S "/dev/md127"
-_create "md0"
-_verify "/dev/md127" "md0" "md0"
+names_create "md0"
+names_verify "/dev/md127" "md0" "md0"
mdadm -S "/dev/md127"
# <devnode> is used to create MD_DEVNAME but, name is used to create MD_NAME.
-_create "/dev/md/devnode" "name"
-_verify "/dev/md127" "devnode" "name"
+names_create "/dev/md/devnode" "name"
+names_verify "/dev/md127" "devnode" "name"
mdadm -S "/dev/md127"
-_create "devnode" "name"
-_verify "/dev/md127" "devnode" "name"
+names_create "devnode" "name"
+names_verify "/dev/md127" "devnode" "name"
mdadm -S "/dev/md127"
# Devnode points to /dev/ directory. MD_DEVNAME doesn't exist.
-_create "/dev/md0"
-_verify "/dev/md0" "empty" "0"
+names_create "/dev/md0"
+names_verify "/dev/md0" "empty" "0"
mdadm -S "/dev/md0"
# Devnode points to /dev/ directory and name is set.
-_create "/dev/md0" "name"
-_verify "/dev/md0" "empty" "name"
+names_create "/dev/md0" "name"
+names_verify "/dev/md0" "empty" "name"
mdadm -S "/dev/md0"
diff --git a/tests/templates/names_template b/tests/templates/names_template
new file mode 100644
index 00000000..9f09be9e
--- /dev/null
+++ b/tests/templates/names_template
@@ -0,0 +1,53 @@
+# NAME is optional. Testing with native 1.2 superblock.
+function names_create() {
+ local DEVNAME=$1
+ local NAME=$2
+
+ if [[ -z "$NAME" ]]; then
+ mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
+ else
+ mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force
+ fi
+
+ if [[ "$?" != "0" ]]; then
+ echo "Cannot create device."
+ exit 1
+ fi
+}
+
+# Three properties to check:
+# - devnode name
+# - link in /dev/md/ (MD_DEVNAME property from --detail --export)
+# - name in metadata (MD_NAME property from --detail --export)- that works only with 1.2 sb.
+function names_verify() {
+ local DEVNODE_NAME="$1"
+ local WANTED_LINK="$2"
+ local WANTED_NAME="$3"
+
+ local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)"
+ if [[ "$?" != "0" ]]; then
+ echo "Cannot get details for $DEVNODE_NAME - unexpected devnode."
+ exit 1
+ fi
+
+ if [[ "$WANTED_LINK" != "empty" ]]; then
+ local EXPECTED="MD_DEVNAME=$WANTED_LINK"
+ fi
+
+ if [[ "$RES" != "$EXPECTED" ]]; then
+ echo "$RES doesn't match $EXPECTED."
+ exit 1
+ fi
+
+ local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_NAME)"
+ if [[ "$?" != "0" ]]; then
+ echo "Cannot get metadata from $dev0."
+ exit 1
+ fi
+
+ local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME"
+ if [[ "$RES" != "$EXPECTED" ]]; then
+ echo "$RES doesn't match $EXPECTED."
+ exit 1
+ fi
+}
--
2.40.1

View File

@ -0,0 +1,164 @@
From 569a23425939e4bfc7b4d7f871d8510bb968f892 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 1 Jun 2023 09:27:46 +0200
Subject: [PATCH 153/165] tests: create 00confnames
The test is an attempt to document current implementation of devnode
and name handling for config entries. It is focused on incremental-
default way of array assembling on boot.
The expectations are aligned to current implementation for native
metadata because it is the most complicated scenario- both variables
can be set.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/00confnames | 107 +++++++++++++++++++++++++++++++++
tests/templates/names_template | 20 ++++++
2 files changed, 127 insertions(+)
create mode 100644 tests/00confnames
diff --git a/tests/00confnames b/tests/00confnames
new file mode 100644
index 00000000..25a7127b
--- /dev/null
+++ b/tests/00confnames
@@ -0,0 +1,107 @@
+set -x -e
+. tests/templates/names_template
+
+# Test how <devname> and <name> from config are handled during Incremental assemblation.
+# 1-6 <devnode> only tests (no <name> in config).
+# 6-10 <devname> and <name> combinations are tested.
+# 11-13 corner cases.
+
+names_create "/dev/md/name"
+local _UUID="$(mdadm -D --export /dev/md127 | grep MD_UUID | cut -d'=' -f2)"
+[[ "$_UUID" == "" ]] && echo "Cannot obtain UUID for $DEVNODE_NAME" && exit 1
+
+
+# 1. <devname> definition consistent with metadata name.
+names_make_conf $_UUID "/dev/md/name" "empty" $config
+mdadm -S "/dev/md127"
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 2. Same as 1, but use short name form of <devname>.
+names_make_conf $_UUID "name" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 3. Same as 1, but use different <devname> than metadata provides.
+names_make_conf $_UUID "/dev/md/other" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "other" "name"
+mdadm -S "/dev/md127"
+
+# 4. Same as 3, but use short name form of <devname>.
+names_make_conf $_UUID "other" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "other" "name"
+mdadm -S "/dev/md127"
+
+# 5. Force particular node creation by setting <devname> to /dev/mdX. Link is not created in this
+# case.
+names_make_conf $_UUID "/dev/md4" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md4" "empty" "name"
+mdadm -S "/dev/md4"
+
+# 6. <devname> set to /dev/mdX, <name> same as in metadata.
+# Metadata name and default node used - controversial. Current behavior documented.
+names_make_conf $_UUID "/dev/md22" "name" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 7. <devname> set to /dev/mdX, <name> different than in metadata.
+# Metadata name and default node used - controversial. Current behavior documented.
+names_make_conf $_UUID "/dev/md8" "other" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 8. Both <devname> and <name> different than in metadata.
+# Metadata name and default node used - controversial. Current behavior documented.
+names_make_conf $_UUID "devnode" "other_name" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 9. <devname> set to metadata name, <name> different than in metadata.
+# Metadata name and default node used - controversial. Current behavior documented.
+names_make_conf $_UUID "name" "other_name" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 10. Bad <devname> set, no <name>.
+# Metadata name and default node used - expected.
+names_make_conf $_UUID "/im/bad/devname" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 11. <devname> with some special symbols and locales, no <name>.
+# It needs to wait a while for timeout because udev cannot create a link - known issue.
+names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "tźż-\.,<>st+-" "name"
+mdadm -S "/dev/md127"
+
+# 12. No <devname> and <name> set.
+# Metadata name and default node used - expected.
+names_make_conf $_UUID "empty" "empty" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 13. No <devname>, <name> set to /dev/mdX.
+# Entry should be ignored, it is not ignored but result is good anyway.
+names_make_conf $_UUID "empty" "/dev/md12" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
+
+# 13. No <devname>, <name> with special symbols and locales.
+# Entry should be ignored, it is not ignored but result is good anyway.
+names_make_conf $_UUID "empty" "./\śćń#&" $config
+mdadm -I $dev0 --config=$config
+names_verify "/dev/md127" "name" "name"
+mdadm -S "/dev/md127"
diff --git a/tests/templates/names_template b/tests/templates/names_template
index 9f09be9e..8d2b5c81 100644
--- a/tests/templates/names_template
+++ b/tests/templates/names_template
@@ -51,3 +51,23 @@ function names_verify() {
exit 1
fi
}
+
+# Generate ARRAYLINE for tested array.
+names_make_conf() {
+ local UUID="$1"
+ local WANTED_DEVNAME="$2"
+ local WANTED_NAME="$3"
+ local CONF="$4"
+
+ local LINE="ARRAY metadata=1.2 UUID=$UUID"
+
+ if [[ "$WANTED_DEVNAME" != "empty" ]]; then
+ LINE="$LINE $WANTED_DEVNAME"
+ fi
+
+ if [[ "$WANTED_NAME" != "empty" ]]; then
+ LINE="$LINE name=$WANTED_NAME"
+ fi
+
+ echo $LINE > $CONF
+}
--
2.40.1

View File

@ -0,0 +1,399 @@
From 330c07f8e4d26f4f2d068e11f09c9df8a3380087 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 1 Jun 2023 09:27:47 +0200
Subject: [PATCH 154/165] mdadm: set ident.devname if applicable
This patch tries to propagate the usage of struct mddev_ident for cmdline
where it is applicable. To avoid regression, this value is derived
from devlist->devname for applicable modes only.
As a result, the whole structure is passed to some functions. It produces
some changes for Build, Create and Assemble.
No functional changes intended.
The goal of the change is to unify devname validation which is done in
next patches.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Build.c | 21 +++++++++------------
Create.c | 35 ++++++++++++++++------------------
mdadm.c | 57 +++++++++++++++++++++++++-------------------------------
mdadm.h | 13 +++++--------
4 files changed, 55 insertions(+), 71 deletions(-)
diff --git a/Build.c b/Build.c
index 8d6f6f58..657ab315 100644
--- a/Build.c
+++ b/Build.c
@@ -24,8 +24,8 @@
#include "mdadm.h"
-int Build(char *mddev, struct mddev_dev *devlist,
- struct shape *s, struct context *c)
+int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
+ struct context *c)
{
/* Build a linear or raid0 arrays without superblocks
* We cannot really do any checks, we just do it.
@@ -75,13 +75,12 @@ int Build(char *mddev, struct mddev_dev *devlist,
/* We need to create the device. It can have no name. */
map_lock(&map);
- mdfd = create_mddev(mddev, NULL, c->autof, LOCAL,
+ mdfd = create_mddev(ident->devname, NULL, c->autof, LOCAL,
chosen_name, 0);
if (mdfd < 0) {
map_unlock(&map);
return 1;
}
- mddev = chosen_name;
map_update(&map, fd2devnm(mdfd), "none", uuid, chosen_name);
map_unlock(&map);
@@ -93,7 +92,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
array.nr_disks = s->raiddisks;
array.raid_disks = s->raiddisks;
array.md_minor = 0;
- if (fstat_is_blkdev(mdfd, mddev, &rdev))
+ if (fstat_is_blkdev(mdfd, chosen_name, &rdev))
array.md_minor = minor(rdev);
array.not_persistent = 1;
array.state = 0; /* not clean, but no errors */
@@ -108,8 +107,7 @@ int Build(char *mddev, struct mddev_dev *devlist,
array.chunk_size = s->chunk*1024;
array.layout = s->layout;
if (md_set_array_info(mdfd, &array)) {
- pr_err("md_set_array_info() failed for %s: %s\n",
- mddev, strerror(errno));
+ pr_err("md_set_array_info() failed for %s: %s\n", chosen_name, strerror(errno));
goto abort;
}
@@ -178,8 +176,8 @@ int Build(char *mddev, struct mddev_dev *devlist,
}
if (bitmap_fd >= 0) {
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
- pr_err("Cannot set bitmap file for %s: %s\n",
- mddev, strerror(errno));
+ pr_err("Cannot set bitmap file for %s: %s\n", chosen_name,
+ strerror(errno));
goto abort;
}
}
@@ -193,9 +191,8 @@ int Build(char *mddev, struct mddev_dev *devlist,
}
if (c->verbose >= 0)
- pr_err("array %s built and started.\n",
- mddev);
- wait_for(mddev, mdfd);
+ pr_err("array %s built and started.\n", chosen_name);
+ wait_for(chosen_name, mdfd);
close(mdfd);
return 0;
diff --git a/Create.c b/Create.c
index ea6a4745..a280c7bc 100644
--- a/Create.c
+++ b/Create.c
@@ -471,11 +471,8 @@ out:
return ret;
}
-int Create(struct supertype *st, char *mddev,
- char *name, int *uuid,
- int subdevs, struct mddev_dev *devlist,
- struct shape *s,
- struct context *c)
+int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
+ struct mddev_dev *devlist, struct shape *s, struct context *c)
{
/*
* Create a new raid array.
@@ -497,6 +494,8 @@ int Create(struct supertype *st, char *mddev,
unsigned long long minsize = 0, maxsize = 0;
char *mindisc = NULL;
char *maxdisc = NULL;
+ char *name = ident->name;
+ int *uuid = ident->uuid_set == 1 ? ident->uuid : NULL;
int dnum;
struct mddev_dev *dv;
dev_t rdev;
@@ -1015,7 +1014,7 @@ int Create(struct supertype *st, char *mddev,
/* We need to create the device */
map_lock(&map);
- mdfd = create_mddev(mddev, name, c->autof, LOCAL, chosen_name, 1);
+ mdfd = create_mddev(ident->devname, ident->name, c->autof, LOCAL, chosen_name, 1);
if (mdfd < 0) {
map_unlock(&map);
return 1;
@@ -1032,7 +1031,6 @@ int Create(struct supertype *st, char *mddev,
udev_unblock();
return 1;
}
- mddev = chosen_name;
memset(&inf, 0, sizeof(inf));
md_get_array_info(mdfd, &inf);
@@ -1050,7 +1048,7 @@ int Create(struct supertype *st, char *mddev,
* with, but it chooses to trust me instead. Sigh
*/
info.array.md_minor = 0;
- if (fstat_is_blkdev(mdfd, mddev, &rdev))
+ if (fstat_is_blkdev(mdfd, chosen_name, &rdev))
info.array.md_minor = minor(rdev);
info.array.not_persistent = 0;
@@ -1102,8 +1100,8 @@ int Create(struct supertype *st, char *mddev,
info.array.layout = s->layout;
info.array.chunk_size = s->chunk*1024;
- if (name == NULL || *name == 0) {
- /* base name on mddev */
+ if (*name == 0) {
+ /* base name on devname */
/* /dev/md0 -> 0
* /dev/md_d0 -> d0
* /dev/md_foo -> foo
@@ -1113,15 +1111,16 @@ int Create(struct supertype *st, char *mddev,
* /dev/mdhome -> home
*/
/* FIXME compare this with rules in create_mddev */
- name = strrchr(mddev, '/');
+ name = strrchr(chosen_name, '/');
+
if (name) {
name++;
if (strncmp(name, "md_", 3) == 0 &&
- strlen(name) > 3 && (name-mddev) == 5 /* /dev/ */)
+ strlen(name) > 3 && (name - chosen_name) == 5 /* /dev/ */)
name += 3;
else if (strncmp(name, "md", 2) == 0 &&
strlen(name) > 2 && isdigit(name[2]) &&
- (name-mddev) == 5 /* /dev/ */)
+ (name - chosen_name) == 5 /* /dev/ */)
name += 2;
}
}
@@ -1215,8 +1214,7 @@ int Create(struct supertype *st, char *mddev,
}
rv = set_array_info(mdfd, st, &info);
if (rv) {
- pr_err("failed to set array info for %s: %s\n",
- mddev, strerror(errno));
+ pr_err("failed to set array info for %s: %s\n", chosen_name, strerror(errno));
goto abort_locked;
}
@@ -1237,8 +1235,7 @@ int Create(struct supertype *st, char *mddev,
goto abort_locked;
}
if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) {
- pr_err("Cannot set bitmap file for %s: %s\n",
- mddev, strerror(errno));
+ pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, strerror(errno));
goto abort_locked;
}
}
@@ -1254,7 +1251,7 @@ int Create(struct supertype *st, char *mddev,
* create links */
sysfs_uevent(&info, "change");
if (c->verbose >= 0)
- pr_err("container %s prepared.\n", mddev);
+ pr_err("container %s prepared.\n", chosen_name);
wait_for(chosen_name, mdfd);
} else if (c->runstop == 1 || subdevs >= s->raiddisks) {
if (st->ss->external) {
@@ -1312,7 +1309,7 @@ int Create(struct supertype *st, char *mddev,
ioctl(mdfd, RESTART_ARRAY_RW, NULL);
}
if (c->verbose >= 0)
- pr_info("array %s started.\n", mddev);
+ pr_info("array %s started.\n", chosen_name);
if (st->ss->external && st->container_devnm[0]) {
if (need_mdmon)
start_mdmon(st->container_devnm);
diff --git a/mdadm.c b/mdadm.c
index 22d1c53b..0a56ed26 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1290,37 +1290,39 @@ int main(int argc, char *argv[])
pr_err("an md device must be given in this mode\n");
exit(2);
}
+ ident.devname = devlist->devname;
+
if ((int)ident.super_minor == -2 && c.autof) {
pr_err("--super-minor=dev is incompatible with --auto\n");
exit(2);
}
if (mode == MANAGE || mode == GROW) {
- mdfd = open_mddev(devlist->devname, 1);
+ mdfd = open_mddev(ident.devname, 1);
if (mdfd < 0)
exit(1);
ret = fstat(mdfd, &stb);
if (ret) {
- pr_err("fstat failed on %s.\n", devlist->devname);
+ pr_err("fstat failed on %s.\n", ident.devname);
exit(1);
}
} else {
- char *bname = basename(devlist->devname);
+ char *bname = basename(ident.devname);
if (strlen(bname) > MD_NAME_MAX) {
- pr_err("Name %s is too long.\n", devlist->devname);
+ pr_err("Name %s is too long.\n", ident.devname);
exit(1);
}
- ret = stat(devlist->devname, &stb);
+ ret = stat(ident.devname, &stb);
if (ident.super_minor == -2 && ret != 0) {
pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
- devlist->devname);
+ ident.devname);
exit(1);
}
if (!ret && !stat_is_md_dev(&stb)) {
- pr_err("device %s exists but is not an md array.\n", devlist->devname);
+ pr_err("device %s exists but is not an md array.\n", ident.devname);
exit(1);
}
}
@@ -1408,17 +1410,17 @@ int main(int argc, char *argv[])
case MANAGE:
/* readonly, add/remove, readwrite, runstop */
if (c.readonly > 0)
- rv = Manage_ro(devlist->devname, mdfd, c.readonly);
+ rv = Manage_ro(ident.devname, mdfd, c.readonly);
if (!rv && devs_found > 1)
- rv = Manage_subdevs(devlist->devname, mdfd,
+ rv = Manage_subdevs(ident.devname, mdfd,
devlist->next, c.verbose,
c.test, c.update, c.force);
if (!rv && c.readonly < 0)
- rv = Manage_ro(devlist->devname, mdfd, c.readonly);
+ rv = Manage_ro(ident.devname, mdfd, c.readonly);
if (!rv && c.runstop > 0)
- rv = Manage_run(devlist->devname, mdfd, &c);
+ rv = Manage_run(ident.devname, mdfd, &c);
if (!rv && c.runstop < 0)
- rv = Manage_stop(devlist->devname, mdfd, c.verbose, 0);
+ rv = Manage_stop(ident.devname, mdfd, c.verbose, 0);
break;
case ASSEMBLE:
if (!c.scan && c.runstop == -1) {
@@ -1428,22 +1430,19 @@ int main(int argc, char *argv[])
ident.super_minor == UnSet && ident.name[0] == 0 &&
!c.scan) {
/* Only a device has been given, so get details from config file */
- struct mddev_ident *array_ident = conf_get_ident(devlist->devname);
+ struct mddev_ident *array_ident = conf_get_ident(ident.devname);
if (array_ident == NULL) {
- pr_err("%s not identified in config file.\n",
- devlist->devname);
+ pr_err("%s not identified in config file.\n", ident.devname);
rv |= 1;
if (mdfd >= 0)
close(mdfd);
} else {
if (array_ident->autof == 0)
array_ident->autof = c.autof;
- rv |= Assemble(ss, devlist->devname, array_ident,
- NULL, &c);
+ rv |= Assemble(ss, ident.devname, array_ident, NULL, &c);
}
} else if (!c.scan)
- rv = Assemble(ss, devlist->devname, &ident,
- devlist->next, &c);
+ rv = Assemble(ss, ident.devname, &ident, devlist->next, &c);
else if (devs_found > 0) {
if (c.update && devs_found > 1) {
pr_err("can only update a single array at a time\n");
@@ -1501,7 +1500,7 @@ int main(int argc, char *argv[])
break;
}
}
- rv = Build(devlist->devname, devlist->next, &s, &c);
+ rv = Build(&ident, devlist->next, &s, &c);
break;
case CREATE:
if (c.delay == 0)
@@ -1538,9 +1537,7 @@ int main(int argc, char *argv[])
break;
}
- rv = Create(ss, devlist->devname,
- ident.name, ident.uuid_set ? ident.uuid : NULL,
- devs_found - 1, devlist->next, &s, &c);
+ rv = Create(ss, &ident, devs_found - 1, devlist->next, &s, &c);
break;
case MISC:
if (devmode == 'E') {
@@ -1637,8 +1634,7 @@ int main(int argc, char *argv[])
break;
}
for (dv = devlist->next; dv; dv = dv->next) {
- rv = Grow_Add_device(devlist->devname, mdfd,
- dv->devname);
+ rv = Grow_Add_device(ident.devname, mdfd, dv->devname);
if (rv)
break;
}
@@ -1651,18 +1647,15 @@ int main(int argc, char *argv[])
}
if (c.delay == 0)
c.delay = DEFAULT_BITMAP_DELAY;
- rv = Grow_addbitmap(devlist->devname, mdfd, &c, &s);
+ rv = Grow_addbitmap(ident.devname, mdfd, &c, &s);
} else if (grow_continue)
- rv = Grow_continue_command(devlist->devname,
- mdfd, c.backup_file,
- c.verbose);
+ rv = Grow_continue_command(ident.devname, mdfd, c.backup_file, c.verbose);
else if (s.size > 0 || s.raiddisks || s.layout_str ||
s.chunk != 0 || s.level != UnSet ||
s.data_offset != INVALID_SECTORS) {
- rv = Grow_reshape(devlist->devname, mdfd,
- devlist->next, &c, &s);
+ rv = Grow_reshape(ident.devname, mdfd, devlist->next, &c, &s);
} else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) {
- rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s);
+ rv = Grow_consistency_policy(ident.devname, mdfd, &c, &s);
} else if (array_size == 0)
pr_err("no changes to --grow\n");
break;
diff --git a/mdadm.h b/mdadm.h
index f0ceeb78..5678eb11 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1531,14 +1531,11 @@ extern int Assemble(struct supertype *st, char *mddev,
struct mddev_dev *devlist,
struct context *c);
-extern int Build(char *mddev, struct mddev_dev *devlist,
- struct shape *s, struct context *c);
-
-extern int Create(struct supertype *st, char *mddev,
- char *name, int *uuid,
- int subdevs, struct mddev_dev *devlist,
- struct shape *s,
- struct context *c);
+extern int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s,
+ struct context *c);
+
+extern int Create(struct supertype *st, struct mddev_ident *ident, int subdevs,
+ struct mddev_dev *devlist, struct shape *s, struct context *c);
extern int Detail(char *dev, struct context *c);
extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path);
--
2.40.1

View File

@ -0,0 +1,253 @@
From 67417d9222c505103357191bb0e0ae300892e8a9 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 1 Jun 2023 09:27:48 +0200
Subject: [PATCH 155/165] mdadm: refactor ident->name handling
Create dedicated setter for name in mddev_ident and propagate it.
Following changes are made:
- move duplicated code from config.c and mdadm.c into new function.
- Add error enum in mdadm.h.
- Use MD_NAME_MAX instead of hardcoded value in mddev_ident.
- Use secure functions.
- Add more detailed verification of the name.
- make error messages reusable for cmdline and config:
- for cmdline, these are errors so use pr_err().
- for config, these are just warnings, so use pr_info().
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
config.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++------
lib.c | 18 +++++++++++++
mdadm.c | 12 +++------
mdadm.h | 20 ++++++++++-----
4 files changed, 104 insertions(+), 23 deletions(-)
diff --git a/config.c b/config.c
index 450880e3..a9a0b4f7 100644
--- a/config.c
+++ b/config.c
@@ -131,6 +131,34 @@ bool is_devname_ignore(char *devname)
return false;
}
+/**
+ * ident_log() - generate and write message to the user.
+ * @param_name: name of the property.
+ * @value: value of the property.
+ * @reason: meaningful description.
+ * @cmdline: context dependent actions, see below.
+ *
+ * The function is made to provide similar error handling for both config and cmdline. The behavior
+ * is configurable via @cmdline. Message has following format:
+ * "Value "@value" cannot be set for @param_name. Reason: @reason."
+ *
+ * If cmdline is on:
+ * - message is written to stderr.
+ * otherwise:
+ * - message is written to stdout.
+ * - "Value ignored" is added at the end of the message.
+ */
+static void ident_log(const char *param_name, const char *value, const char *reason,
+ const bool cmdline)
+{
+ if (cmdline == true)
+ pr_err("Value \"%s\" cannot be set as %s. Reason: %s.\n", value, param_name,
+ reason);
+ else
+ pr_info("Value \"%s\" cannot be set as %s. Reason: %s. Value ignored.\n", value,
+ param_name, reason);
+}
+
/**
* ident_init() - Set defaults.
* @ident: ident pointer, not NULL.
@@ -159,6 +187,46 @@ inline void ident_init(struct mddev_ident *ident)
ident->uuid_set = 0;
}
+/**
+ * _ident_set_name()- set name in &mddev_ident.
+ * @ident: pointer to &mddev_ident.
+ * @name: name to be set.
+ * @cmdline: context dependent actions.
+ *
+ * If criteria passed, set name in @ident.
+ *
+ * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
+ */
+static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *name,
+ const bool cmdline)
+{
+ assert(name);
+ assert(ident);
+
+ const char *prop_name = "name";
+
+ if (ident->name[0]) {
+ ident_log(prop_name, name, "Already defined", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
+ ident_log(prop_name, name, "Too long or empty", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ snprintf(ident->name, MD_NAME_MAX + 1, "%s", name);
+ return MDADM_STATUS_SUCCESS;
+}
+
+/**
+ * ident_set_name()- exported, for cmdline.
+ */
+mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name)
+{
+ return _ident_set_name(ident, name, true);
+}
+
struct conf_dev {
struct conf_dev *next;
char *name;
@@ -444,14 +512,7 @@ void arrayline(char *line)
mis.super_minor = minor;
}
} else if (strncasecmp(w, "name=", 5) == 0) {
- if (mis.name[0])
- pr_err("only specify name once, %s ignored.\n",
- w);
- else if (strlen(w + 5) > 32)
- pr_err("name too long, ignoring %s\n", w);
- else
- strcpy(mis.name, w + 5);
-
+ _ident_set_name(&mis, w + 5, false);
} else if (strncasecmp(w, "bitmap=", 7) == 0) {
if (mis.bitmap_file)
pr_err("only specify bitmap file once. %s ignored\n",
diff --git a/lib.c b/lib.c
index 8a4b48e0..03198e2d 100644
--- a/lib.c
+++ b/lib.c
@@ -27,6 +27,24 @@
#include <ctype.h>
#include <limits.h>
+/**
+ * is_string_lq() - Check if string length with NULL byte is lower or equal to requested.
+ * @str: string to check.
+ * @max_len: max length.
+ *
+ * @str length must be bigger than 0 and be lower or equal @max_len, including termination byte.
+ */
+bool is_string_lq(const char * const str, size_t max_len)
+{
+ assert(str);
+
+ size_t _len = strnlen(str, max_len);
+
+ if (_len > 0 && _len < max_len)
+ return true;
+ return false;
+}
+
bool is_dev_alive(char *path)
{
if (!path)
diff --git a/mdadm.c b/mdadm.c
index 0a56ed26..8bc9304e 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -690,20 +690,14 @@ int main(int argc, char *argv[])
case O(CREATE,'N'):
case O(ASSEMBLE,'N'):
case O(MISC,'N'):
- if (ident.name[0]) {
- pr_err("name cannot be set twice. Second value %s.\n", optarg);
- exit(2);
- }
if (mode == MISC && !c.subarray) {
pr_err("-N/--name only valid with --update-subarray in misc mode\n");
exit(2);
}
- if (strlen(optarg) > 32) {
- pr_err("name '%s' is too long, 32 chars max.\n",
- optarg);
+
+ if (ident_set_name(&ident, optarg) != MDADM_STATUS_SUCCESS)
exit(2);
- }
- strcpy(ident.name, optarg);
+
continue;
case O(ASSEMBLE,'m'): /* super-minor for array */
diff --git a/mdadm.h b/mdadm.h
index 5678eb11..bbf386d6 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -294,6 +294,11 @@ static inline void __put_unaligned32(__u32 val, void *p)
#define KIB_TO_BYTES(x) ((x) << 10)
#define SEC_TO_BYTES(x) ((x) << 9)
+/**
+ * This is true for native and DDF, IMSM allows 16.
+ */
+#define MD_NAME_MAX 32
+
extern const char Name[];
struct md_bb_entry {
@@ -425,6 +430,12 @@ struct spare_criteria {
unsigned int sector_size;
};
+typedef enum mdadm_status {
+ MDADM_STATUS_SUCCESS = 0,
+ MDADM_STATUS_ERROR,
+ MDADM_STATUS_UNDEF,
+} mdadm_status_t;
+
enum mode {
ASSEMBLE=1,
BUILD,
@@ -593,7 +604,7 @@ struct mddev_ident {
int uuid_set;
int uuid[4];
- char name[33];
+ char name[MD_NAME_MAX + 1];
int super_minor;
@@ -1609,6 +1620,7 @@ extern int check_partitions(int fd, char *dname,
extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev);
extern int stat_is_blkdev(char *devname, dev_t *rdev);
+extern bool is_string_lq(const char * const str, size_t max_len);
extern bool is_dev_alive(char *path);
extern int get_mdp_major(void);
extern int get_maj_min(char *dev, int *major, int *minor);
@@ -1626,6 +1638,7 @@ extern void manage_fork_fds(int close_all);
extern int continue_via_systemd(char *devnm, char *service_name, char *prefix);
extern void ident_init(struct mddev_ident *ident);
+extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name);
extern int parse_auto(char *str, char *msg, int config);
extern struct mddev_ident *conf_get_ident(char *dev);
@@ -2002,11 +2015,6 @@ enum r0layout {
/* And another special number needed for --data_offset=variable */
#define VARIABLE_OFFSET 3
-/**
- * This is true for native and DDF, IMSM allows 16.
- */
-#define MD_NAME_MAX 32
-
/**
* is_container() - check if @level is &LEVEL_CONTAINER
* @level: level value
--
2.40.1

View File

@ -0,0 +1,249 @@
From ae5f13a971bc309e0e25087421119b86daf2e510 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 1 Jun 2023 09:27:49 +0200
Subject: [PATCH 156/165] mdadm: define ident_set_devname()
Use dedicated set method for ident->devname. Now, devname validation
is done early for modes where device is created (Build, Create and
Assemble). The rules, used for devname validation are derived from
config file.
It could cause regression with execeptional cases where existing device
has name which doesn't match criteria for Manage and Grow modes. It is
low risk and those modes are not omitted from early devname validation.
Use can used main numbered devnode to avoid this problem.
Messages exposed to user are changed so it might cause a regression
in negative scenarios. Error codes are not changed.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
config.c | 102 +++++++++++++++++++++++++--------
mdadm.c | 10 +---
mdadm.h | 3 +-
tests/00createnames | 3 +
tests/templates/names_template | 7 +++
5 files changed, 92 insertions(+), 33 deletions(-)
diff --git a/config.c b/config.c
index a9a0b4f7..a0424845 100644
--- a/config.c
+++ b/config.c
@@ -122,7 +122,7 @@ int match_keyword(char *word)
/**
* is_devname_ignore() - check if &devname is a special "<ignore>" keyword.
*/
-bool is_devname_ignore(char *devname)
+bool is_devname_ignore(const char *devname)
{
static const char keyword[] = "<ignore>";
@@ -187,6 +187,74 @@ inline void ident_init(struct mddev_ident *ident)
ident->uuid_set = 0;
}
+/**
+ * _ident_set_devname()- verify devname and set it in &mddev_ident.
+ * @ident: pointer to &mddev_ident.
+ * @devname: devname to be set.
+ * @cmdline: context dependent actions. If set, ignore keyword is not allowed.
+ *
+ * @devname can have following forms:
+ * '<ignore>' keyword (if allowed)
+ * /dev/md{number}
+ * /dev/md_d{number} (legacy)
+ * /dev/md_{name}
+ * /dev/md/{name}
+ * {name} - anything that doesn't start from '/' or '<'.
+ *
+ * {name} must follow name's criteria.
+ * If criteria passed, duplicate memory and set devname in @ident.
+ *
+ * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
+ */
+mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname,
+ const bool cmdline)
+{
+ assert(ident);
+ assert(devname);
+
+ static const char named_dev_pref[] = DEV_NUM_PREF "_";
+ static const int named_dev_pref_size = sizeof(named_dev_pref) - 1;
+ const char *prop_name = "devname";
+ const char *name;
+
+ if (ident->devname) {
+ ident_log(prop_name, devname, "Already defined", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (is_devname_ignore(devname) == true) {
+ if (!cmdline)
+ goto pass;
+
+ ident_log(prop_name, devname, "Special keyword is invalid in this context",
+ cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (is_devname_md_numbered(devname) == true || is_devname_md_d_numbered(devname) == true)
+ goto pass;
+
+ if (strncmp(devname, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ name = devname + DEV_MD_DIR_LEN;
+ else if (strncmp(devname, named_dev_pref, named_dev_pref_size) == 0)
+ name = devname + named_dev_pref_size;
+ else
+ name = devname;
+
+ if (*name == '/' || *name == '<') {
+ ident_log(prop_name, devname, "Cannot be started from \'/\' or \'<\'", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (is_string_lq(name, MD_NAME_MAX + 1) == false) {
+ ident_log(prop_name, devname, "Invalid length", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+pass:
+ ident->devname = xstrdup(devname);
+ return MDADM_STATUS_SUCCESS;
+}
+
/**
* _ident_set_name()- set name in &mddev_ident.
* @ident: pointer to &mddev_ident.
@@ -219,6 +287,14 @@ static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *nam
return MDADM_STATUS_SUCCESS;
}
+/**
+ * ident_set_devname()- exported, for cmdline.
+ */
+mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *name)
+{
+ return _ident_set_devname(ident, name, true);
+}
+
/**
* ident_set_name()- exported, for cmdline.
*/
@@ -464,29 +540,7 @@ void arrayline(char *line)
for (w = dl_next(line); w != line; w = dl_next(w)) {
if (w[0] == '/' || strchr(w, '=') == NULL) {
- /* This names the device, or is '<ignore>'.
- * The rules match those in create_mddev.
- * 'w' must be:
- * /dev/md/{anything}
- * /dev/mdNN
- * /dev/md_dNN
- * <ignore>
- * or anything that doesn't start '/' or '<'
- */
- if (is_devname_ignore(w) == true ||
- strncmp(w, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0 ||
- (w[0] != '/' && w[0] != '<') ||
- is_devname_md_numbered(w) == true ||
- is_devname_md_d_numbered(w) == true) {
- /* This is acceptable */;
- if (mis.devname)
- pr_err("only give one device per ARRAY line: %s and %s\n",
- mis.devname, w);
- else
- mis.devname = w;
- }else {
- pr_err("%s is an invalid name for an md device - ignored.\n", w);
- }
+ _ident_set_devname(&mis, w, false);
} else if (strncasecmp(w, "uuid=", 5) == 0) {
if (mis.uuid_set)
pr_err("only specify uuid once, %s ignored.\n",
diff --git a/mdadm.c b/mdadm.c
index 8bc9304e..62f981df 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -1284,7 +1284,8 @@ int main(int argc, char *argv[])
pr_err("an md device must be given in this mode\n");
exit(2);
}
- ident.devname = devlist->devname;
+ if (ident_set_devname(&ident, devlist->devname) != MDADM_STATUS_SUCCESS)
+ exit(1);
if ((int)ident.super_minor == -2 && c.autof) {
pr_err("--super-minor=dev is incompatible with --auto\n");
@@ -1301,13 +1302,6 @@ int main(int argc, char *argv[])
exit(1);
}
} else {
- char *bname = basename(ident.devname);
-
- if (strlen(bname) > MD_NAME_MAX) {
- pr_err("Name %s is too long.\n", ident.devname);
- exit(1);
- }
-
ret = stat(ident.devname, &stb);
if (ident.super_minor == -2 && ret != 0) {
pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n",
diff --git a/mdadm.h b/mdadm.h
index bbf386d6..49422e24 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1638,6 +1638,7 @@ extern void manage_fork_fds(int close_all);
extern int continue_via_systemd(char *devnm, char *service_name, char *prefix);
extern void ident_init(struct mddev_ident *ident);
+extern mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *devname);
extern mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name);
extern int parse_auto(char *str, char *msg, int config);
@@ -1660,7 +1661,7 @@ extern void print_escape(char *str);
extern int use_udev(void);
extern unsigned long GCD(unsigned long a, unsigned long b);
extern int conf_name_is_free(char *name);
-extern bool is_devname_ignore(char *devname);
+extern bool is_devname_ignore(const char *devname);
extern bool is_devname_md_numbered(const char *devname);
extern bool is_devname_md_d_numbered(const char *devname);
extern int conf_verify_devnames(struct mddev_ident *array_list);
diff --git a/tests/00createnames b/tests/00createnames
index 064eeef2..a95e7d2b 100644
--- a/tests/00createnames
+++ b/tests/00createnames
@@ -39,3 +39,6 @@ mdadm -S "/dev/md0"
names_create "/dev/md0" "name"
names_verify "/dev/md0" "empty" "name"
mdadm -S "/dev/md0"
+
+# Devnode is a special ignore keyword. Should be rejected.
+names_create "<ignore>" "name", "true"
diff --git a/tests/templates/names_template b/tests/templates/names_template
index 8d2b5c81..6181bfaa 100644
--- a/tests/templates/names_template
+++ b/tests/templates/names_template
@@ -2,6 +2,7 @@
function names_create() {
local DEVNAME=$1
local NAME=$2
+ local NEG_TEST=$3
if [[ -z "$NAME" ]]; then
mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force
@@ -9,6 +10,12 @@ function names_create() {
mdadm -CR "$DEVNAME" --name="$NAME" --metadata=1.2 -l0 -n 1 $dev0 --force
fi
+ if [[ "$NEG_TEST" == "true" ]]; then
+ [[ "$?" == "0" ]] && return 0
+ echo "Negative verification failed"
+ exit 1
+ fi
+
if [[ "$?" != "0" ]]; then
echo "Cannot create device."
exit 1
--
2.40.1

View File

@ -0,0 +1,471 @@
From e2eb503bd797908f515b58428b274f1ba6a05349 Mon Sep 17 00:00:00 2001
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Date: Thu, 1 Jun 2023 09:27:50 +0200
Subject: [PATCH 157/165] mdadm: Follow POSIX Portable Character Set
When the user creates a device with a name that contains whitespace,
mdadm timeouts and throws an error. This issue is caused by udev, which
truncates /dev/md link until the first whitespace.
This patch introduces prohibition of characters other than A-Za-z0-9.-_
in the device name. Also, it prohibits using leading "-" in device name,
so name won't be confused with cli parameter.
Set of allowed characters is taken from POSIX 3.280 Portable Character
Set. Also, device name length now is limited to NAME_MAX.
In some places, there are other requirements for string length (e.g. size
up to MD_NAME_MAX for device name). This routine is made to follow POSIX
and other, more strict limitations should be checked separately.
We are aware of the risk of regression in exceptional cases (as
escape_devname function is removed) that should be fixed by updating
the array name.
The POSIX validation is added for:
- 'name' parameter in every mode.
- first devlist entry, for Build, Create, Assemble, Manage, Grow.
- config entries, both devname and "name=".
Additionally, some manual cleanups are made.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Detail.c | 17 ++++--------
config.c | 13 ++++++---
lib.c | 58 ++++++++++++++++++++++++++++-----------
mdadm.8.in | 70 ++++++++++++++++++++---------------------------
mdadm.conf.5.in | 4 ---
mdadm.h | 2 +-
super-intel.c | 47 ++++++++++++++++---------------
tests/00confnames | 4 +--
8 files changed, 113 insertions(+), 102 deletions(-)
diff --git a/Detail.c b/Detail.c
index 206d88e3..57ac336f 100644
--- a/Detail.c
+++ b/Detail.c
@@ -254,11 +254,9 @@ int Detail(char *dev, struct context *c)
fname_from_uuid(st, info, nbuf, ':');
printf("MD_UUID=%s\n", nbuf + 5);
mp = map_by_uuid(&map, info->uuid);
- if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
- printf("MD_DEVNAME=");
- print_escape(mp->path + DEV_MD_DIR_LEN);
- putchar('\n');
- }
+
+ if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
if (st->ss->export_detail_super)
st->ss->export_detail_super(st);
@@ -271,12 +269,9 @@ int Detail(char *dev, struct context *c)
__fname_from_uuid(mp->uuid, 0, nbuf, ':');
printf("MD_UUID=%s\n", nbuf+5);
}
- if (mp && mp->path &&
- strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) {
- printf("MD_DEVNAME=");
- print_escape(mp->path + DEV_MD_DIR_LEN);
- putchar('\n');
- }
+ if (mp && mp->path && strncmp(mp->path, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0)
+ printf("MD_DEVNAME=%s\n", mp->path + DEV_MD_DIR_LEN);
+
map_free(map);
}
if (!c->no_devices && sra) {
diff --git a/config.c b/config.c
index a0424845..5f12a1f8 100644
--- a/config.c
+++ b/config.c
@@ -199,9 +199,9 @@ inline void ident_init(struct mddev_ident *ident)
* /dev/md_d{number} (legacy)
* /dev/md_{name}
* /dev/md/{name}
- * {name} - anything that doesn't start from '/' or '<'.
+ * {name}
*
- * {name} must follow name's criteria.
+ * {name} must follow name's criteria and be POSIX compatible.
* If criteria passed, duplicate memory and set devname in @ident.
*
* Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR.
@@ -241,8 +241,8 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname
else
name = devname;
- if (*name == '/' || *name == '<') {
- ident_log(prop_name, devname, "Cannot be started from \'/\' or \'<\'", cmdline);
+ if (is_name_posix_compatible(name) == false) {
+ ident_log(prop_name, name, "Not POSIX compatible", cmdline);
return MDADM_STATUS_ERROR;
}
@@ -283,6 +283,11 @@ static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *nam
return MDADM_STATUS_ERROR;
}
+ if (is_name_posix_compatible(name) == false) {
+ ident_log(prop_name, name, "Not POSIX compatible", cmdline);
+ return MDADM_STATUS_ERROR;
+ }
+
snprintf(ident->name, MD_NAME_MAX + 1, "%s", name);
return MDADM_STATUS_SUCCESS;
}
diff --git a/lib.c b/lib.c
index 03198e2d..7ab59988 100644
--- a/lib.c
+++ b/lib.c
@@ -483,24 +483,50 @@ void print_quoted(char *str)
putchar(q);
}
-void print_escape(char *str)
+/**
+ * is_alphanum() - Check if sign is letter or digit.
+ * @c: char to analyze.
+ *
+ * Similar to isalnum() but additional locales are excluded.
+ *
+ * Return: %true on success, %false otherwise.
+ */
+bool is_alphanum(const char c)
{
- /* print str, but change space and tab to '_'
- * as is suitable for device names
- */
- for (; *str; str++) {
- switch (*str) {
- case ' ':
- case '\t':
- putchar('_');
- break;
- case '/':
- putchar('-');
- break;
- default:
- putchar(*str);
- }
+ if (isupper(c) || islower(c) || isdigit(c) != 0)
+ return true;
+ return false;
+}
+
+/**
+ * is_name_posix_compatible() - Check if name is POSIX compatible.
+ * @name: name to check.
+ *
+ * POSIX portable file name character set contains ASCII letters,
+ * digits, '_', '.', and '-'. Also forbid leading '-'.
+ * The length of the name cannot exceed NAME_MAX - 1 (ensure NULL ending).
+ *
+ * Return: %true on success, %false otherwise.
+ */
+bool is_name_posix_compatible(const char * const name)
+{
+ assert(name);
+
+ char allowed_symbols[] = "-_.";
+ const char *n = name;
+
+ if (!is_string_lq(name, NAME_MAX))
+ return false;
+
+ if (*n == '-')
+ return false;
+
+ while (*n != '\0') {
+ if (!is_alphanum(*n) && !strchr(allowed_symbols, *n))
+ return false;
+ n++;
}
+ return true;
}
int check_env(char *name)
diff --git a/mdadm.8.in b/mdadm.8.in
index b7159509..3142436f 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -364,7 +364,7 @@ Use the Intel(R) Matrix Storage Manager metadata format. This creates a
which is managed in a similar manner to DDF, and is supported by an
option-rom on some platforms:
.IP
-.B https://www.intel.com/content/www/us/en/support/products/122484/memory-and-storage/ssd-software/intel-virtual-raid-on-cpu-intel-vroc.html
+.B https://www.intel.com/content/www/us/en/support/products/122484
.PP
.RE
@@ -932,17 +932,14 @@ option will be ignored.
.BR \-N ", " \-\-name=
Set a
.B name
-for the array. This is currently only effective when creating an
-array with a version-1 superblock, or an array in a DDF container.
-The name is a simple textual string that can be used to identify array
-components when assembling. If name is needed but not specified, it
-is taken from the basename of the device that is being created.
-e.g. when creating
-.I /dev/md/home
-the
-.B name
-will default to
-.IR home .
+for the array. It must be
+.BR "POSIX PORTABLE NAME"
+compatible and cannot be longer than 32 chars. This is effective when creating an array
+with a v1 metadata, or an external array.
+
+If name is needed but not specified, it is taken from the basename of the device
+that is being created. See
+.BR "DEVICE NAMES"
.TP
.BR \-R ", " \-\-run
@@ -1132,8 +1129,10 @@ is much safer.
.TP
.BR \-N ", " \-\-name=
-Specify the name of the array to assemble. This must be the name
-that was specified when creating the array. It must either match
+Specify the name of the array to assemble. It must be
+.BR "POSIX PORTABLE NAME"
+compatible and cannot be longer than 32 chars. This must be the name
+that was specified when creating the array. It must either match
the name stored in the superblock exactly, or it must match
with the current
.I homehost
@@ -2179,14 +2178,17 @@ Usage:
.I md-device
.BI \-\-chunk= X
.BI \-\-level= Y
-.br
.BI \-\-raid\-devices= Z
.I devices
.PP
-This usage will initialise a new md array, associate some devices with
+This usage will initialize a new md array, associate some devices with
it, and activate the array.
+.I md-device
+is a new device. This could be standard name or chosen name. For details see:
+.BR "DEVICE NAMES"
+
The named device will normally not exist when
.I "mdadm \-\-create"
is run, but will be created by
@@ -2227,24 +2229,6 @@ array. This feature can be overridden with the
.B \-\-force
option.
-When creating an array with version-1 metadata a name for the array is
-required.
-If this is not given with the
-.B \-\-name
-option,
-.I mdadm
-will choose a name based on the last component of the name of the
-device being created. So if
-.B /dev/md3
-is being created, then the name
-.B 3
-will be chosen.
-If
-.B /dev/md/home
-is being created, then the name
-.B home
-will be used.
-
When creating a partition based array, using
.I mdadm
with version-1.x metadata, the partition type should be set to
@@ -2429,12 +2413,10 @@ and
The
.B name
-option updates the subarray name in the metadata, it may not affect the
-device node name or the device node symlink until the subarray is
-re\-assembled. If updating
-.B name
-would change the UUID of an active subarray this operation is blocked,
-and the command will end in an error.
+option updates the subarray name in the metadata. It must be
+.BR "POSIX PORTABLE NAME"
+compatible and cannot be longer than 32 chars. If successes, new value will be respected after
+next assembly.
The
.B ppl
@@ -3395,6 +3377,10 @@ When
.B \-\-incremental
mode is used, this file gets a list of arrays currently being created.
+.SH POSIX PORTABLE NAME
+A valid name can only consist of characters "A-Za-z0-9.-_".
+The name cannot start with a leading "-" and cannot exceed 255 chars.
+
.SH DEVICE NAMES
.I mdadm
@@ -3416,6 +3402,10 @@ can be given, or just the suffix of the second sort of name, such as
.I home
can be given.
+In every style, raw name must be compatible with
+.BR "POSIX PORTABLE NAME"
+and has to be no longer than 32 chars.
+
When
.I mdadm
chooses device names during auto-assembly or incremental assembly, it
diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in
index bc2295c2..94e23dd0 100644
--- a/mdadm.conf.5.in
+++ b/mdadm.conf.5.in
@@ -717,10 +717,6 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b
.br
auto=part
.br
-# The name of this array contains a space.
-.br
-ARRAY /dev/md9 name='Data Storage'
-.sp
POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-*
.br
action=spare
diff --git a/mdadm.h b/mdadm.h
index 49422e24..9effb941 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1617,6 +1617,7 @@ extern int check_raid(int fd, char *name);
extern int check_partitions(int fd, char *dname,
unsigned long long freesize,
unsigned long long size);
+extern bool is_name_posix_compatible(const char *path);
extern int fstat_is_blkdev(int fd, char *devname, dev_t *rdev);
extern int stat_is_blkdev(char *devname, dev_t *rdev);
@@ -1657,7 +1658,6 @@ extern int conf_get_monitor_delay(void);
extern char *conf_line(FILE *file);
extern char *conf_word(FILE *file, int allow_key);
extern void print_quoted(char *str);
-extern void print_escape(char *str);
extern int use_udev(void);
extern unsigned long GCD(unsigned long a, unsigned long b);
extern int conf_name_is_free(char *name);
diff --git a/super-intel.c b/super-intel.c
index 77b0066f..05d3b056 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -5561,40 +5561,37 @@ static void imsm_update_version_info(struct intel_super *super)
}
}
-static int check_name(struct intel_super *super, char *name, int quiet)
+/**
+ * imsm_check_name() - check imsm naming criteria.
+ * @super: &intel_super pointer, not NULL.
+ * @name: name to check.
+ * @verbose: verbose level.
+ *
+ * Name must be no longer than &MAX_RAID_SERIAL_LEN and must be unique across volumes.
+ *
+ * Returns: &true if @name matches, &false otherwise.
+ */
+static bool imsm_is_name_allowed(struct intel_super *super, const char * const name,
+ const int verbose)
{
struct imsm_super *mpb = super->anchor;
- char *reason = NULL;
- char *start = name;
- size_t len = strlen(name);
int i;
- if (len > 0) {
- while (isspace(start[len - 1]))
- start[--len] = 0;
- while (*start && isspace(*start))
- ++start, --len;
- memmove(name, start, len + 1);
+ if (is_string_lq(name, MAX_RAID_SERIAL_LEN + 1) == false) {
+ pr_vrb("imsm: Name \"%s\" is too long\n", name);
+ return false;
}
- if (len > MAX_RAID_SERIAL_LEN)
- reason = "must be 16 characters or less";
- else if (len == 0)
- reason = "must be a non-empty string";
-
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
if (strncmp((char *) dev->volume, name, MAX_RAID_SERIAL_LEN) == 0) {
- reason = "already exists";
- break;
+ pr_vrb("imsm: Name \"%s\" already exists\n", name);
+ return false;
}
}
- if (reason && !quiet)
- pr_err("imsm volume name %s\n", reason);
-
- return !reason;
+ return true;
}
static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
@@ -5689,8 +5686,9 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info,
}
}
- if (!check_name(super, name, 0))
+ if (imsm_is_name_allowed(super, name, 1) == false)
return 0;
+
dv = xmalloc(sizeof(*dv));
dev = xcalloc(1, sizeof(*dev) + sizeof(__u32) * (info->raid_disks - 1));
/*
@@ -8018,7 +8016,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray,
char *ep;
int vol;
- if (!check_name(super, name, 0))
+ if (imsm_is_name_allowed(super, name, 1) == false)
return 2;
vol = strtoul(subarray, &ep, 10);
@@ -10345,7 +10343,8 @@ static void imsm_process_update(struct supertype *st,
if (a->info.container_member == target)
break;
dev = get_imsm_dev(super, u->dev_idx);
- if (a || !check_name(super, name, 1)) {
+
+ if (a || !dev || imsm_is_name_allowed(super, name, 0) == false) {
dprintf("failed to rename subarray-%d\n", target);
break;
}
diff --git a/tests/00confnames b/tests/00confnames
index 25a7127b..10823f01 100644
--- a/tests/00confnames
+++ b/tests/00confnames
@@ -79,10 +79,10 @@ names_verify "/dev/md127" "name" "name"
mdadm -S "/dev/md127"
# 11. <devname> with some special symbols and locales, no <name>.
-# It needs to wait a while for timeout because udev cannot create a link - known issue.
+# <devname> should be ignored.
names_make_conf $_UUID "tźż-\.,<>st+-" "empty" $config
mdadm -I $dev0 --config=$config
-names_verify "/dev/md127" "tźż-\.,<>st+-" "name"
+names_verify "/dev/md127" "name" "name"
mdadm -S "/dev/md127"
# 12. No <devname> and <name> set.
--
2.40.1

View File

@ -0,0 +1,128 @@
From ba489abd688bf70c83e70700aaaec5f5e90889c5 Mon Sep 17 00:00:00 2001
From: Coly Li <colyli@suse.de>
Date: Mon, 14 Aug 2023 00:46:13 +0800
Subject: [PATCH 158/165] Incremental: remove obsoleted calls to udisks
Utility udisks is removed from udev upstream, calling this obsoleted
command in run_udisks() doesn't make any sense now.
This patch removes the calls chain of udisks, which includes routines
run_udisk(), force_remove(), and 2 locations where force_remove() are
called. Considering force_remove() is removed with udisks util, it is
fair to remove Manage_stop() inside force_remove() as well.
In the two modifications where calling force_remove() are removed,
the failure from Manage_subdevs() can be safely ignored, because,
1) udisks doesn't exist, no need to check the return value to umount
the file system by udisks and remove the component disk again.
2) After the 'I' inremental remove, there is another 'r' hot remove
following up. The first incremental remove is a best-try effort.
Therefore in this patch, where force_remove() is removed, the return
value of calling Manage_subdevs() is not checked too.
Signed-off-by: Coly Li <colyli@suse.de>
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Cc: Jes Sorensen <jes@trained-monkey.org>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Incremental.c | 64 +++++++++++----------------------------------------
1 file changed, 13 insertions(+), 51 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index f13ce027..05b33c45 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1628,54 +1628,18 @@ release:
return rv;
}
-static void run_udisks(char *arg1, char *arg2)
-{
- int pid = fork();
- int status;
- if (pid == 0) {
- manage_fork_fds(1);
- execl("/usr/bin/udisks", "udisks", arg1, arg2, NULL);
- execl("/bin/udisks", "udisks", arg1, arg2, NULL);
- exit(1);
- }
- while (pid > 0 && wait(&status) != pid)
- ;
-}
-
-static int force_remove(char *devnm, int fd, struct mdinfo *mdi, int verbose)
-{
- int rv;
- int devid = devnm2devid(devnm);
-
- run_udisks("--unmount", map_dev(major(devid), minor(devid), 0));
- rv = Manage_stop(devnm, fd, verbose, 1);
- if (rv) {
- /* At least we can try to trigger a 'remove' */
- sysfs_uevent(mdi, "remove");
- if (verbose)
- pr_err("Fail to stop %s too.\n", devnm);
- }
- return rv;
-}
-
static void remove_from_member_array(struct mdstat_ent *memb,
struct mddev_dev *devlist, int verbose)
{
- int rv;
- struct mdinfo mmdi;
int subfd = open_dev(memb->devnm);
if (subfd >= 0) {
- rv = Manage_subdevs(memb->devnm, subfd, devlist, verbose,
- 0, UOPT_UNDEFINED, 0);
- if (rv & 2) {
- if (sysfs_init(&mmdi, -1, memb->devnm))
- pr_err("unable to initialize sysfs for: %s\n",
- memb->devnm);
- else
- force_remove(memb->devnm, subfd, &mmdi,
- verbose);
- }
+ /*
+ * Ignore the return value because it's necessary
+ * to handle failure condition here.
+ */
+ Manage_subdevs(memb->devnm, subfd, devlist, verbose,
+ 0, UOPT_UNDEFINED, 0);
close(subfd);
}
}
@@ -1758,21 +1722,19 @@ int IncrementalRemove(char *devname, char *id_path, int verbose)
}
free_mdstat(mdstat);
} else {
- rv |= Manage_subdevs(ent->devnm, mdfd, &devlist,
- verbose, 0, UOPT_UNDEFINED, 0);
- if (rv & 2) {
- /* Failed due to EBUSY, try to stop the array.
- * Give udisks a chance to unmount it first.
+ /*
+ * This 'I' incremental remove is a try-best effort,
+ * the failure condition can be safely ignored
+ * because of the following up 'r' remove.
*/
- rv = force_remove(ent->devnm, mdfd, &mdi, verbose);
- goto end;
- }
+ Manage_subdevs(ent->devnm, mdfd, &devlist,
+ verbose, 0, UOPT_UNDEFINED, 0);
}
devlist.disposition = 'r';
rv = Manage_subdevs(ent->devnm, mdfd, &devlist,
verbose, 0, UOPT_UNDEFINED, 0);
-end:
+
close(mdfd);
free_mdstat(ent);
return rv;
--
2.40.1

View File

@ -0,0 +1,31 @@
From 28fc84168646910a9271ebe1a12b1571e14f5900 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Thu, 7 Sep 2023 16:57:44 +0800
Subject: [PATCH 159/165] mdadm/tests: Fix regular expression failure
The test fails because of the regular expression.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/06name | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/06name b/tests/06name
index 4d5e824d..86eaab69 100644
--- a/tests/06name
+++ b/tests/06name
@@ -3,8 +3,8 @@ set -x
# create an array with a name
mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1
-mdadm -E $dev0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1
-mdadm -D $md0 | grep 'Name : [^:]*:Fred ' > /dev/null || exit 1
+mdadm -E $dev0 | grep 'Name : Fred' > /dev/null || exit 1
+mdadm -D $md0 | grep 'Name : Fred' > /dev/null || exit 1
mdadm -S $md0
mdadm -A $md0 --name="Fred" $devlist
--
2.40.1

View File

@ -0,0 +1,141 @@
From ed2c2cb3d440f3bd2692f1896446c4bcc703f05c Mon Sep 17 00:00:00 2001
From: Li Xiao Keng <lixiaokeng@huawei.com>
Date: Thu, 7 Sep 2023 19:37:44 +0800
Subject: [PATCH 160/165] Fix race of "mdadm --add" and "mdadm --incremental"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There is a raid1 with sda and sdb. And we add sdc to this raid,
it may return -EBUSY.
The main process of --add:
1. dev_opensdc) in Manage_add
2. store_super1(st, di->fd) in write_init_super1
3. fsync(fd) in store_super1
4. close(di->fd) in write_init_super1
5. ioctl(ADD_NEW_DISK)
Step 2 and 3 will add sdc to metadata of raid1. There will be
udev(change of sdc) event after step4. Then "/usr/sbin/mdadm
--incremental --export $devnode --offroot $env{DEVLINKS}"
will be run, and the sdc will be added to the raid1. Then
step 5 will return -EBUSY because it checks if device isn't
claimed in md_import_device()->lock_rdev()->blkdev_get_by_dev()
->blkdev_get().
It will be confusing for users because sdc is added first time.
The "incremental" will get map_lock before add sdc to raid1.
So we add map_lock before write_init_super in "mdadm --add"
to fix the race of "add" and "incremental".
Signed-off-by: Li Xiao Keng <lixiaokeng@huawei.com>
Signed-off-by: Guanqin Miao <miaoguanqin@huawei.com>
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Manage.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/Manage.c b/Manage.c
index f997b163..075dd720 100644
--- a/Manage.c
+++ b/Manage.c
@@ -704,6 +704,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
struct supertype *dev_st;
int j;
mdu_disk_info_t disc;
+ struct map_ent *map = NULL;
if (!get_dev_size(tfd, dv->devname, &ldsize)) {
if (dv->disposition == 'M')
@@ -907,6 +908,9 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
disc.raid_disk = 0;
}
+ if (map_lock(&map))
+ pr_err("failed to get exclusive lock on mapfile when add disk\n");
+
if (array->not_persistent==0) {
int dfd;
if (dv->disposition == 'j')
@@ -918,9 +922,9 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
dfd = dev_open(dv->devname, O_RDWR | O_EXCL|O_DIRECT);
if (tst->ss->add_to_super(tst, &disc, dfd,
dv->devname, INVALID_SECTORS))
- return -1;
+ goto unlock;
if (tst->ss->write_init_super(tst))
- return -1;
+ goto unlock;
} else if (dv->disposition == 'A') {
/* this had better be raid1.
* As we are "--re-add"ing we must find a spare slot
@@ -978,14 +982,14 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
pr_err("add failed for %s: could not get exclusive access to container\n",
dv->devname);
tst->ss->free_super(tst);
- return -1;
+ 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);
- return -1;
+ goto unlock;
}
Kill(dv->devname, NULL, 0, -1, 0);
@@ -994,7 +998,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
dv->devname, INVALID_SECTORS)) {
close(dfd);
close(container_fd);
- return -1;
+ goto unlock;
}
if (!mdmon_running(tst->container_devnm))
tst->ss->sync_metadata(tst);
@@ -1005,7 +1009,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
dv->devname);
close(container_fd);
tst->ss->free_super(tst);
- return -1;
+ goto unlock;
}
sra->array.level = LEVEL_CONTAINER;
/* Need to set data_offset and component_size */
@@ -1020,7 +1024,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
pr_err("add new device to external metadata failed for %s\n", dv->devname);
close(container_fd);
sysfs_free(sra);
- return -1;
+ goto unlock;
}
ping_monitor(devnm);
sysfs_free(sra);
@@ -1034,7 +1038,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
else
pr_err("add new device failed for %s as %d: %s\n",
dv->devname, j, strerror(errno));
- return -1;
+ goto unlock;
}
if (dv->disposition == 'j') {
pr_err("Journal added successfully, making %s read-write\n", devname);
@@ -1045,7 +1049,11 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv,
}
if (verbose >= 0)
pr_err("added %s\n", dv->devname);
+ map_unlock(&map);
return 1;
+unlock:
+ map_unlock(&map);
+ return -1;
}
int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv,
--
2.40.1

View File

@ -0,0 +1,32 @@
From c32b4754014c1eec8cc0c025fad2e9b621486164 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Fri, 8 Sep 2023 16:44:35 +0800
Subject: [PATCH 161/165] mdadm/tests: Don't run mknod before losetup
Sometimes it can fail:
losetup: /var/tmp/mdtest0: failed to set up loop device: No such device or address
/dev/loop0 and /var/tmp/mdtest0 are already created before losetup.
Because losetup can create device node by itself. So remove mknod.
Signed-off-by: Xiao Ni <xni@redhat.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
tests/func.sh | 1 -
1 file changed, 1 deletion(-)
diff --git a/tests/func.sh b/tests/func.sh
index 9710a53b..5053b012 100644
--- a/tests/func.sh
+++ b/tests/func.sh
@@ -170,7 +170,6 @@ do_setup() {
dd if=/dev/zero of=$targetdir/mdtest$d count=$sz bs=1K > /dev/null 2>&1
# make sure udev doesn't touch
mdadm --zero $targetdir/mdtest$d 2> /dev/null
- [ -b /dev/loop$d ] || mknod /dev/loop$d b 7 $d
if [ $d -eq 7 ]
then
losetup /dev/loop$d $targetdir/mdtest6 # for multipath use
--
2.40.1

View File

@ -0,0 +1,45 @@
From 246b4b40558f6f7f84882e9c34659f1b582944e2 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Wed, 11 Oct 2023 21:03:32 +0800
Subject: [PATCH 162/165] mdadm/ddf: Abort when raid disk is smaller in
getinfo_super_ddf
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The metadata is corrupted when the raid_disk<0. So abort directly.
This also can avoid a building error:
super-ddf.c:1988:58: error: array subscript -1 is below array bounds of struct phys_disk_entry[0]
Suggested-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Ackedy-by: Xiao Ni <xni@redhat.com>
Acked-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super-ddf.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/super-ddf.c b/super-ddf.c
index c5242654..7571e3b7 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1984,12 +1984,14 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
info->disk.number = be32_to_cpu(ddf->dlist->disk.refnum);
info->disk.raid_disk = find_phys(ddf, ddf->dlist->disk.refnum);
+ if (info->disk.raid_disk < 0)
+ return;
+
info->data_offset = be64_to_cpu(ddf->phys->
entries[info->disk.raid_disk].
config_size);
info->component_size = ddf->dlist->size - info->data_offset;
- if (info->disk.raid_disk >= 0)
- pde = ddf->phys->entries + info->disk.raid_disk;
+ pde = ddf->phys->entries + info->disk.raid_disk;
if (pde &&
!(be16_to_cpu(pde->state) & DDF_Failed) &&
!(be16_to_cpu(pde->state) & DDF_Missing))
--
2.40.1

View File

@ -0,0 +1,75 @@
From 6af520a5b4d91cd0fd32ab6361ff4519505c7f47 Mon Sep 17 00:00:00 2001
From: Xiao Ni <xni@redhat.com>
Date: Tue, 17 Oct 2023 20:35:46 +0800
Subject: [PATCH 163/165] mdadm/super1: Add MD_FEATURE_RAID0_LAYOUT if
kernel>=5.4
After and include kernel v5.4, it adds one feature bit MD_FEATURE_RAID0_LAYOUT.
It must need to specify a layout for raid0 with more than one zone. But for
raid0 with one zone, in fact it also has a defalut layout.
Now for raid0 with one zone, *unknown* layout can be seen when running mdadm -D
command. It's the reason that mdadm doesn't set MD_FEATURE_RAID0_LAYOUT for
raid0 with one zone. Then in kernel space, super_1_validate sets mddev->layout
to -1 because of no MD_FEATURE_RAID0_LAYOUT. In fact, in raid0 io path, it
uses the default layout. Set raid0_need_layout to true if kernel_version<=v5.4.
Fixes: 329dfc28debb ('Create: add support for RAID0 layouts.')
Signed-off-by: Xiao Ni <xni@redhat.com>
Reviewed-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
super1.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/super1.c b/super1.c
index 856b0208..1da71b98 100644
--- a/super1.c
+++ b/super1.c
@@ -1967,6 +1967,14 @@ fail_to_write:
return 1;
}
+static bool has_raid0_layout(struct mdp_superblock_1 *sb)
+{
+ if (sb->level == 0 && sb->layout != 0)
+ return true;
+ else
+ return false;
+}
+
static int write_init_super1(struct supertype *st)
{
struct mdp_superblock_1 *sb = st->sb;
@@ -1978,12 +1986,17 @@ static int write_init_super1(struct supertype *st)
unsigned long long sb_offset;
unsigned long long data_offset;
long bm_offset;
- int raid0_need_layout = 0;
+ bool raid0_need_layout = false;
+
+ /* Since linux kernel v5.4, raid0 always has a layout */
+ if (has_raid0_layout(sb) && get_linux_version() >= 5004000)
+ raid0_need_layout = true;
for (di = st->info; di; di = di->next) {
if (di->disk.state & (1 << MD_DISK_JOURNAL))
sb->feature_map |= __cpu_to_le32(MD_FEATURE_JOURNAL);
- if (sb->level == 0 && sb->layout != 0) {
+ if (has_raid0_layout(sb) && !raid0_need_layout) {
+
struct devinfo *di2 = st->info;
unsigned long long s1, s2;
s1 = di->dev_size;
@@ -1995,7 +2008,7 @@ static int write_init_super1(struct supertype *st)
s2 -= di2->data_offset;
s2 /= __le32_to_cpu(sb->chunksize);
if (s1 != s2)
- raid0_need_layout = 1;
+ raid0_need_layout = true;
}
}
--
2.40.1

View File

@ -0,0 +1,139 @@
From 4dde420fc3e24077ab926f79674eaae1b71de10b Mon Sep 17 00:00:00 2001
From: Pawel Piatkowski <pawel.piatkowski@intel.com>
Date: Thu, 19 Oct 2023 16:35:24 +0200
Subject: [PATCH 164/165] mdadm: remove container_enough logic
Arrays without enough disk count will be assembled but not
started.
Now RAIDs will be assembled always (even if they are failed).
RAID devices in all states will be assembled and exposed
to mdstat.
This change affects only IMSM (for ddf it wasn't used,
container_enough was set to true always).
Removed this logic from incremental_container as well with
runstop checking because runstop condition is being verified
in assemble_container_content function.
Signed-off-by: Pawel Piatkowski <pawel.piatkowski@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Incremental.c | 11 -----------
mdadm.h | 3 ---
super-ddf.c | 1 -
super-intel.c | 32 +-------------------------------
4 files changed, 1 insertion(+), 46 deletions(-)
diff --git a/Incremental.c b/Incremental.c
index 05b33c45..3551c65b 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -1467,17 +1467,6 @@ static int Incremental_container(struct supertype *st, char *devname,
st->ss->getinfo_super(st, &info, NULL);
- if ((c->runstop > 0 && info.container_enough >= 0) ||
- info.container_enough > 0)
- /* pass */;
- else {
- if (c->export) {
- printf("MD_STARTED=no\n");
- } else if (c->verbose)
- pr_err("not enough devices to start the container\n");
- return 0;
- }
-
match = conf_match(st, &info, devname, c->verbose, &rv);
if (match == NULL && rv == 2)
return rv;
diff --git a/mdadm.h b/mdadm.h
index 9effb941..b48e6f86 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -377,9 +377,6 @@ struct mdinfo {
int container_member; /* for assembling external-metatdata arrays
* This is to be used internally by metadata
* handler only */
- int container_enough; /* flag external handlers can set to
- * indicate that subarrays have not enough (-1),
- * enough to start (0), or all expected disks (1) */
char sys_name[32];
struct mdinfo *devs;
struct mdinfo *next;
diff --git a/super-ddf.c b/super-ddf.c
index 7571e3b7..a87e3169 100644
--- a/super-ddf.c
+++ b/super-ddf.c
@@ -1975,7 +1975,6 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
info->array.ctime = DECADE + __be32_to_cpu(*cptr);
info->array.chunk_size = 0;
- info->container_enough = 1;
info->disk.major = 0;
info->disk.minor = 0;
diff --git a/super-intel.c b/super-intel.c
index 05d3b056..6bdd5c4c 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -3806,7 +3806,6 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
struct intel_super *super = st->sb;
struct imsm_disk *disk;
int map_disks = info->array.raid_disks;
- int max_enough = -1;
int i;
struct imsm_super *mpb;
@@ -3848,12 +3847,9 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
for (i = 0; i < mpb->num_raid_devs; i++) {
struct imsm_dev *dev = get_imsm_dev(super, i);
- int failed, enough, j, missing = 0;
+ int j = 0;
struct imsm_map *map;
- __u8 state;
- failed = imsm_count_failed(super, dev, MAP_0);
- state = imsm_check_degraded(super, dev, failed, MAP_0);
map = get_imsm_map(dev, MAP_0);
/* any newly missing disks?
@@ -3868,36 +3864,10 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
if (!(ord & IMSM_ORD_REBUILD) &&
get_imsm_missing(super, idx)) {
- missing = 1;
break;
}
}
-
- if (state == IMSM_T_STATE_FAILED)
- enough = -1;
- else if (state == IMSM_T_STATE_DEGRADED &&
- (state != map->map_state || missing))
- enough = 0;
- else /* we're normal, or already degraded */
- enough = 1;
- if (is_gen_migration(dev) && missing) {
- /* during general migration we need all disks
- * that process is running on.
- * No new missing disk is allowed.
- */
- max_enough = -1;
- enough = -1;
- /* no more checks necessary
- */
- break;
- }
- /* in the missing/failed disk case check to see
- * if at least one array is runnable
- */
- max_enough = max(max_enough, enough);
}
- dprintf("enough: %d\n", max_enough);
- info->container_enough = max_enough;
if (super->disks) {
__u32 reserved = imsm_reserved_sectors(super, super->disks);
--
2.40.1

View File

@ -0,0 +1,49 @@
From d8d09c1633b2f06f88633ab960aa02b41a6bdfb6 Mon Sep 17 00:00:00 2001
From: Pawel Piatkowski <pawel.piatkowski@intel.com>
Date: Thu, 19 Oct 2023 16:35:25 +0200
Subject: [PATCH 165/165] Fix assembling RAID volume by using incremental
After change "mdadm: remove container_enough logic"
IMSM volumes are started immediately. If volume is during
reshape, then it will be blocked by block_subarray() during
first mdadm -I <devname>. Assemble_container_content() for
next disk will see the change because metadata version from
sysfs and metadata doesn't match and will execute
sysfs_set_array again. Then it fails to set same
component_size, it is prohibited by kernel.
If array is frozen then first sign from metadata version
is different ("/" vs "-"), so exclude it from comparison.
All we want is to double check that base properties are set
and we don't need to call sysfs_set_array again.
Signed-off-by: Pawel Piatkowski <pawel.piatkowski@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
---
Assemble.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/Assemble.c b/Assemble.c
index 5be58e40..0557a007 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -1990,12 +1990,10 @@ int assemble_container_content(struct supertype *st, int mdfd,
return 1;
}
- if (strcmp(sra->text_version, content->text_version) != 0) {
- if (content->array.major_version == -1 &&
- content->array.minor_version == -2 &&
- c->readonly &&
- content->text_version[0] == '/')
- content->text_version[0] = '-';
+ /* Fill sysfs properties only if they are not set. Determine it by checking text_version
+ * and ignoring special character on the first place.
+ */
+ if (strcmp(sra->text_version + 1, content->text_version + 1) != 0) {
if (sysfs_set_array(content, 9003) != 0) {
sysfs_free(sra);
return 1;
--
2.40.1

View File

@ -1,11 +0,0 @@
--- mdadm/Makefile.orig 2021-07-28 21:39:23.887433859 +0800
+++ mdadm/Makefile 2021-07-28 21:39:37.989432841 +0800
@@ -50,7 +50,7 @@
CC := $(CROSS_COMPILE)gcc
endif
CXFLAGS ?= -ggdb
-CWFLAGS = -Wall -Werror -Wstrict-prototypes -Wextra -Wno-unused-parameter
+CWFLAGS = -Wall -Wstrict-prototypes -Wextra -Wno-unused-parameter
ifdef WARN_UNUSED
CWFLAGS += -Wp,-D_FORTIFY_SOURCE=2 -O3
endif

View File

@ -0,0 +1,27 @@
#
# Enable/Disable - default is Disabled
# to disable this rule, GOTO="md_end" should be the first active command.
# to enable this rule, Comment out GOTO="md_end".
GOTO="md_end"
# Required: MD arrays must have a bitmap for transient devices to
# be added back in the array.
# mdadm -CR /dev/md0 -l1 -n2 /dev/sd[ab] bitmap=internal
# Don't process any events if anaconda is running as anaconda brings up
# raid devices manually
ENV{ANACONDA}=="?*", GOTO="md_end"
# Also don't process disks that are slated to be a multipath device
ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_end"
# We process add events on block devices (since they are ready as soon as
# they are added to the system)
ACTION!="add", GOTO="md_end"
ENV{ID_FS_TYPE}!="linux_raid_member", GOTO="md_end"
SUBSYSTEM=="block", RUN{program}+="/usr/sbin/md-auto-readd.sh $devnode"
#
# Land here to exit cleanly
LABEL="md_end"

17
SOURCES/md-auto-readd.sh Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/bash
MDADM=/sbin/mdadm
DEVNAME=$1
export $(${MDADM} --examine --export ${DEVNAME})
if [ -z "${MD_UUID}" ]; then
exit 1
fi
UUID_LINK=$(readlink /dev/disk/by-id/md-uuid-${MD_UUID})
MD_DEVNAME=${UUID_LINK##*/}
export $(${MDADM} --detail --export /dev/${MD_DEVNAME})
if [ -z "${MD_METADATA}" ] ; then
exit 1
fi
${MDADM} --manage /dev/${MD_DEVNAME} --re-add ${DEVNAME} --verbose

View File

@ -1,3 +0,0 @@
# Run system wide raid-check once a week on Sunday at 1am by default
0 1 * * Sun root /usr/sbin/raid-check

View File

@ -1,48 +0,0 @@
#!/bin/sh
# extract configuration from /etc/sysconfig/mdadm and write
# environment to /run/sysconfig/mdadm to be used by
# systemd unit files.
MDADM_SCAN="yes"
# Following adapted from /etc/init.d/mdadmd on openSUSE
mdadmd_CONFIG=/etc/sysconfig/mdadm
if test -r $mdadmd_CONFIG; then
. $mdadmd_CONFIG
fi
if [ x$MDADM_DELAY != x"" ]; then
MDADM_DELAY="-d "$MDADM_DELAY;
fi
if [ x$MDADM_MAIL != x"" ]; then
MDADM_MAIL="-m \"$MDADM_MAIL\""
fi
if [ x$MDADM_PROGRAM != x"" ]; then
MDADM_PROGRAM="-p \"$MDADM_PROGRAM\""
fi
if [ x$MDADM_SCAN = x"yes" ]; then
MDADM_SCAN="--scan"
else
MDADM_SCAN=""
fi
if [ x$MDADM_SEND_MAIL_ON_START = x"yes" ]; then
MDADM_SEND_MAIL="-t"
else
MDADM_SEND_MAIL=""
fi
if [ x$MDADM_CONFIG != x"" ]; then
MDADM_CONFIG="-c \"$MDADM_CONFIG\""
fi
mkdir -p /run/sysconfig
echo "MDADM_MONITOR_ARGS=$MDADM_RAIDDEVICES $MDADM_DELAY $MDADM_MAIL $MDADM_PROGRAM $MDADM_SCAN $MDADM_SEND_MAIL $MDADM_CONFIG" > /run/sysconfig/mdadm
if [ -n "$MDADM_CHECK_DURATION" ]; then
echo "MDADM_CHECK_DURATION=$MDADM_CHECK_DURATION" >> /run/sysconfig/mdadm
fi

View File

@ -125,11 +125,13 @@ do
do
eval fl=\$MD_${i}_fl
eval sys=\$MD_${i}_sys
eval dev=\$MD_${i}_dev
if [ -z "$fl" ]; then continue; fi
if [ "`cat $sys/md/sync_action`" != 'check' ]
then
logger -p daemon.info mdcheck finished checking $dev
eval MD_${i}_fl=
rm -f $fl
continue;

View File

@ -1,118 +0,0 @@
#!/bin/bash
#
# mdmonitor This starts, stops, and reloads the mdadm-based
# software RAID monitoring and management facility
#
# chkconfig: 2345 15 85
# description: software RAID monitoring and management
# config: /etc/mdadm.conf
#
# Copyright 2002 Red Hat, Inc.
#
### BEGIN INIT INFO
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start and stop the MD software RAID monitor
# Description: The mdmonitor service checks the status of all software
# RAID arrays on the system. In the event that any of the arrays
# transition into a degraded state, it notifies the system
# administrator. Other options are available, see the mdadm.conf
# and mdadm man pages for possible ways to configure this service.
### END INIT INFO
PIDPATH=/var/run/mdadm
PIDFILE=/var/run/mdadm/mdadm.pid
PATH=/sbin:/usr/sbin:$PATH
RETVAL=0
OPTIONS="--monitor --scan -f --pid-file=$PIDFILE"
prog=mdmonitor
# Source function library.
. /etc/rc.d/init.d/functions
usage ()
{
echo "Usage: service $prog {start|stop|status|restart|try-restart|force-reload}"
RETVAL=1
}
start ()
{
# (Re)start mdmon to take over monitoring of mdmon started from the initrd
for i in /dev/md/*.pid; do
if [ -r $i ]; then
origprog="$prog"; prog="mdmon"
action $"Starting $prog: " /sbin/mdmon --takeover --all
prog="$origprog"
break
fi
done
# Make sure configuration file exists and has information we can use
# MAILADDR or PROGRAM or both must be set in order to run mdadm --monitor
[ -f /etc/mdadm.conf ] || return 6
grep '^\(MAILADDR\|PROGRAM\) .' /etc/mdadm.conf >/dev/null 2>&1 || return 6
# Create our directory if it isn't there yet
if [ ! -d $PIDPATH ]; then
mkdir -m 0700 $PIDPATH >&/dev/null
RC=$?
[ -x /sbin/restorecon ] && /sbin/restorecon $PIDPATH
if [ $RC -ne 0 ]; then
echo -n "Failed to create /var/run/mdadm"
failure
echo
return 1
fi
fi
if [ -f "$PIDFILE" ]; then
checkpid `cat $PIDFILE` && return 0
fi
echo -n $"Starting $prog: "
cd /
daemon --user=root mdadm ${OPTIONS}
ret=$?
[ $ret -eq "0" ] && touch /var/lock/subsys/$prog
echo
return $ret
}
stop ()
{
[ -f /var/lock/subsys/$prog ] || return 0
echo -n "Killing $prog: "
killproc mdadm
echo
rm -f $PIDFILE
rm -f /var/lock/subsys/$prog
}
restart ()
{
stop
start
}
condrestart ()
{
[ -e /var/lock/subsys/$prog ] && restart || return 0
}
case "$1" in
start|stop|restart|condrestart|try-restart|force-reload)
[ `id -u` != "0" ] && exit 4 ;;
esac
case "$1" in
start) start; RETVAL=$? ;;
stop) stop; RETVAL=$? ;;
status) status -p $PIDFILE $prog ; RETVAL=$? ;;
restart) restart; RETVAL=$? ;;
reload) RETVAL=3 ;;
condrestart|try-restart|force-reload) condrestart; RETVAL=$? ;;
*) usage ; RETVAL=2 ;;
esac
exit $RETVAL

View File

@ -4,9 +4,9 @@ ConditionPathExists=/etc/mdadm.conf
[Service]
Type=forking
PIDFile=/var/run/mdadm/mdadm.pid
PIDFile=/run/mdadm/mdadm.pid
EnvironmentFile=-/etc/sysconfig/mdmonitor
ExecStart=/sbin/mdadm --monitor --scan -f --pid-file=/var/run/mdadm/mdadm.pid
ExecStart=/sbin/mdadm --monitor --scan --syslog -f --pid-file=/run/mdadm/mdadm.pid
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,6 @@
[Unit]
Description=RAID setup health check
[Service]
Type=oneshot
ExecStart=/usr/sbin/raid-check

10
SOURCES/raid-check.timer Normal file
View File

@ -0,0 +1,10 @@
[Unit]
Description=Weekly RAID setup health check
[Timer]
OnCalendar=Sun *-*-* 01:00:00
Persistent=true
AccuracySec=24h
[Install]
WantedBy=timers.target

View File

@ -1,19 +1,23 @@
Summary: The mdadm program controls Linux md devices (software RAID arrays)
Name: mdadm
Version: 4.2
# extraversion is used to define rhel internal version
%define extraversion 7
%define extraversion 10
Release: %{extraversion}%{?dist}
Summary: The mdadm program controls Linux md devices (software RAID arrays)
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
License: GPLv2+
Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/mdadm-%{version}%{?subversion:-%{subversion}}.tar.xz
Source1: mdmonitor.init
Source2: raid-check
Source3: mdadm-raid-check-sysconfig
Source4: mdadm-cron
Source5: mdmonitor.service
Source6: mdadm.conf
Source7: mdadm_event.conf
Source1: raid-check
Source2: mdadm-raid-check-sysconfig
Source3: mdmonitor.service
Source4: mdadm.conf
Source5: mdadm_event.conf
Source6: raid-check.timer
Source7: raid-check.service
Source8: mdcheck
Source9: mdadm_env.sh
Source9: md-auto-readd.rule
Source10: md-auto-readd.sh
Patch000: 0001-Unify-error-message.patch
Patch001: 0002-mdadm-Fix-double-free.patch
@ -26,98 +30,172 @@ Patch007: 0008-mdadm-Update-config-man-regarding-default-files-and-.patch
Patch008: 0009-mdadm-Update-config-manual.patch
Patch009: 0010-Create-Build-use-default_layout.patch
Patch010: 0011-mdadm-add-map_num_s.patch
# patch0012 is deleted because of needing KillMode=none
Patch011: 0013-mdmon-Stop-parsing-duplicate-options.patch
Patch012: 0014-Grow-block-n-on-external-volumes.patch
Patch013: 0015-Incremental-Fix-possible-memory-and-resource-leaks.patch
Patch014: 0016-Mdmonitor-Fix-segfault.patch
Patch015: 0017-Mdmonitor-Improve-logging-method.patch
Patch016: 0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch
Patch017: 0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch
Patch018: 0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch
Patch019: 0021-util-replace-ioctl-use-with-function.patch
Patch020: 0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch
Patch021: 0023-imsm-introduce-get_disk_slot_in_dev.patch
Patch022: 0024-imsm-use-same-slot-across-container.patch
Patch023: 0025-imsm-block-changing-slots-during-creation.patch
Patch024: 0026-mdadm-block-update-ppl-for-non-raid456-levels.patch
Patch025: 0027-mdadm-Fix-array-size-mismatch-after-grow.patch
Patch026: 0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch
Patch027: 0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch
Patch028: 0030-Monitor-use-snprintf-to-fill-device-name.patch
Patch029: 0031-Makefile-Don-t-build-static-build-with-everything-an.patch
Patch030: 0032-DDF-Cleanup-validate_geometry_ddf_container.patch
Patch031: 0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch
Patch032: 0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch
Patch033: 0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch
Patch034: 0036-mdadm-Fix-mdadm-r-remove-option-regression.patch
Patch035: 0037-mdadm-Fix-optional-write-behind-parameter.patch
Patch036: 0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch
Patch037: 0039-tests-fix-raid0-tests-for-0.90-metadata.patch
Patch038: 0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch
Patch039: 0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch
Patch040: 0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch
Patch041: 0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch
Patch042: 0044-tests-Add-broken-files-for-all-broken-tests.patch
Patch043: 0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch
Patch044: 0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch
Patch045: 0047-tests-add-test-for-names.patch
Patch046: 0048-mdadm-remove-symlink-option.patch
Patch047: 0049-mdadm-move-data_offset-to-struct-shape.patch
Patch048: 0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch
Patch049: 0051-Grow-Split-Grow_reshape-into-helper-function.patch
Patch050: 0052-Assemble-check-if-device-is-container-before-schedul.patch
Patch051: 0053-super1-report-truncated-device.patch
Patch052: 0054-mdadm-Correct-typos-punctuation-and-grammar-in-man.patch
Patch053: 0055-Manage-Block-unsafe-member-failing.patch
Patch054: 0056-Monitor-Fix-statelist-memory-leaks.patch
Patch055: 0057-mdadm-added-support-for-Intel-Alderlake-RST-on-VMD-p.patch
Patch056: 0058-mdadm-Add-Documentation-entries-to-systemd-services.patch
Patch057: 0059-ReadMe-fix-command-line-help.patch
Patch058: 0060-mdadm-replace-container-level-checking-with-inline.patch
Patch059: 0061-Mdmonitor-Omit-non-md-devices.patch
Patch060: 0062-Mdmonitor-Split-alert-into-separate-functions.patch
Patch061: 0063-Monitor-block-if-monitor-modes-are-combined.patch
Patch062: 0064-Update-mdadm-Monitor-manual.patch
Patch063: 0065-Grow-fix-possible-memory-leak.patch
Patch064: 0066-mdadm-create-ident_init.patch
Patch065: 0067-mdadm-Add-option-validation-for-update-subarray.patch
Patch066: 0068-Fix-update-subarray-on-active-volume.patch
Patch067: 0069-Add-code-specific-update-options-to-enum.patch
Patch068: 0070-super-ddf-Remove-update_super_ddf.patch
Patch069: 0071-super0-refactor-the-code-for-enum.patch
Patch070: 0072-super1-refactor-the-code-for-enum.patch
Patch071: 0073-super-intel-refactor-the-code-for-enum.patch
Patch072: 0074-Change-update-to-enum-in-update_super-and-update_sub.patch
Patch073: 0075-Manage-Incremental-code-refactor-string-to-enum.patch
Patch074: 0076-Change-char-to-enum-in-context-update-refactor-code.patch
Patch075: 0077-mdmon-fix-segfault.patch
Patch076: 0078-util-remove-obsolete-code-from-get_md_name.patch
Patch077: 0079-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch
Patch078: 0080-Manage-do-not-check-array-state-when-drive-is-remove.patch
Patch079: 0081-incremental-manage-do-not-verify-if-remove-is-safe.patch
Patch080: 0082-super-intel-make-freesize-not-required-for-chunk-siz.patch
Patch081: 0083-manage-move-comment-with-function-description.patch
Patch011: 0012-mdadm-systemd-remove-KillMode-none-from-service-file.patch
Patch012: 0013-mdmon-Stop-parsing-duplicate-options.patch
Patch013: 0014-Grow-block-n-on-external-volumes.patch
Patch014: 0015-Incremental-Fix-possible-memory-and-resource-leaks.patch
Patch015: 0016-Mdmonitor-Fix-segfault.patch
Patch016: 0017-Mdmonitor-Improve-logging-method.patch
Patch017: 0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch
Patch018: 0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch
Patch019: 0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch
Patch020: 0021-util-replace-ioctl-use-with-function.patch
Patch021: 0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch
Patch022: 0023-imsm-introduce-get_disk_slot_in_dev.patch
Patch023: 0024-imsm-use-same-slot-across-container.patch
Patch024: 0025-imsm-block-changing-slots-during-creation.patch
Patch025: 0026-mdadm-block-update-ppl-for-non-raid456-levels.patch
Patch026: 0027-mdadm-Fix-array-size-mismatch-after-grow.patch
Patch027: 0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch
Patch028: 0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch
Patch029: 0030-Monitor-use-snprintf-to-fill-device-name.patch
Patch030: 0031-Makefile-Don-t-build-static-build-with-everything-an.patch
Patch031: 0032-DDF-Cleanup-validate_geometry_ddf_container.patch
Patch032: 0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch
Patch033: 0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch
Patch034: 0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch
Patch035: 0036-mdadm-Fix-mdadm-r-remove-option-regression.patch
Patch036: 0037-mdadm-Fix-optional-write-behind-parameter.patch
Patch037: 0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch
Patch038: 0039-tests-fix-raid0-tests-for-0.90-metadata.patch
Patch039: 0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch
Patch040: 0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch
Patch041: 0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch
Patch042: 0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch
Patch043: 0044-tests-Add-broken-files-for-all-broken-tests.patch
Patch044: 0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch
Patch045: 0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch
Patch046: 0047-tests-add-test-for-names.patch
Patch047: 0048-mdadm-remove-symlink-option.patch
Patch048: 0049-mdadm-move-data_offset-to-struct-shape.patch
Patch049: 0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch
Patch050: 0051-Grow-Split-Grow_reshape-into-helper-function.patch
Patch051: 0052-Assemble-check-if-device-is-container-before-schedul.patch
Patch052: 0053-super1-report-truncated-device.patch
Patch053: 0054-mdadm-Correct-typos-punctuation-and-grammar-in-man.patch
Patch054: 0055-Manage-Block-unsafe-member-failing.patch
Patch055: 0056-Monitor-Fix-statelist-memory-leaks.patch
Patch056: 0057-mdadm-added-support-for-Intel-Alderlake-RST-on-VMD-p.patch
Patch057: 0058-mdadm-Add-Documentation-entries-to-systemd-services.patch
Patch058: 0059-ReadMe-fix-command-line-help.patch
Patch059: 0060-mdadm-replace-container-level-checking-with-inline.patch
Patch060: 0061-Mdmonitor-Omit-non-md-devices.patch
Patch061: 0062-Mdmonitor-Split-alert-into-separate-functions.patch
Patch062: 0063-Monitor-block-if-monitor-modes-are-combined.patch
Patch063: 0064-Update-mdadm-Monitor-manual.patch
Patch064: 0065-Grow-fix-possible-memory-leak.patch
Patch065: 0066-mdadm-create-ident_init.patch
Patch066: 0067-mdadm-Add-option-validation-for-update-subarray.patch
Patch067: 0068-Fix-update-subarray-on-active-volume.patch
Patch068: 0069-Add-code-specific-update-options-to-enum.patch
Patch069: 0070-super-ddf-Remove-update_super_ddf.patch
Patch070: 0071-super0-refactor-the-code-for-enum.patch
Patch071: 0072-super1-refactor-the-code-for-enum.patch
Patch072: 0073-super-intel-refactor-the-code-for-enum.patch
Patch073: 0074-Change-update-to-enum-in-update_super-and-update_sub.patch
Patch074: 0075-Manage-Incremental-code-refactor-string-to-enum.patch
Patch075: 0076-Change-char-to-enum-in-context-update-refactor-code.patch
Patch076: 0077-mdmon-fix-segfault.patch
Patch077: 0078-util-remove-obsolete-code-from-get_md_name.patch
Patch078: 0079-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch
Patch079: 0080-Manage-do-not-check-array-state-when-drive-is-remove.patch
Patch080: 0081-incremental-manage-do-not-verify-if-remove-is-safe.patch
Patch081: 0082-super-intel-make-freesize-not-required-for-chunk-siz.patch
Patch082: 0083-manage-move-comment-with-function-description.patch
Patch083: 0084-Revert-mdadm-systemd-remove-KillMode-none-from-servi.patch
Patch084: 0085-Grow-fix-can-t-change-bitmap-type-from-none-to-clust.patch
Patch085: 0086-Fix-NULL-dereference-in-super_by_fd.patch
Patch086: 0087-Mdmonitor-Make-alert_info-global.patch
Patch087: 0088-Mdmonitor-Pass-events-to-alert-using-enums-instead-o.patch
Patch088: 0089-Mdmonitor-Add-helper-functions.patch
Patch089: 0090-Add-helpers-to-determine-whether-directories-or-file.patch
Patch090: 0091-Mdmonitor-Refactor-write_autorebuild_pid.patch
Patch091: 0092-Mdmonitor-Refactor-check_one_sharer-for-better-error.patch
Patch092: 0093-util.c-reorder-code-lines-in-parse_layout_faulty.patch
Patch093: 0094-util.c-fix-memleak-in-parse_layout_faulty.patch
Patch094: 0095-Detail.c-fix-memleak-in-Detail.patch
Patch095: 0096-isuper-intel.c-fix-double-free-in-load_imsm_mpb.patch
Patch096: 0097-super-intel.c-fix-memleak-in-find_disk_attached_hba.patch
Patch097: 0098-super-ddf.c-fix-memleak-in-get_vd_num_of_subarray.patch
Patch098: 0099-Create-goto-abort_locked-instead-of-return-1-in-erro.patch
Patch099: 0100-Create-remove-safe_mode_delay-local-variable.patch
Patch100: 0101-Create-Factor-out-add_disks-helpers.patch
Patch101: 0102-mdadm-Introduce-pr_info.patch
Patch102: 0103-mdadm-Add-write-zeros-option-for-Create.patch
Patch103: 0104-tests-00raid5-zero-Introduce-test-to-exercise-write-.patch
Patch104: 0105-manpage-Add-write-zeroes-option-to-manpage.patch
Patch105: 0106-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch
Patch106: 0107-Use-existence-of-etc-initrd-release-to-detect-initrd.patch
Patch107: 0108-mdmon-don-t-test-both-all-and-container_name.patch
Patch108: 0109-mdmon-change-systemd-unit-file-to-use-foreground.patch
Patch109: 0110-mdmon-Remove-need-for-KillMode-none.patch
Patch110: 0111-mdmon-Improve-switchroot-interactions.patch
Patch111: 0112-mdopen-always-try-create_named_array.patch
Patch112: 0113-Improvements-for-IMSM_NO_PLATFORM-testing.patch
Patch113: 0114-Revert-Revert-mdadm-systemd-remove-KillMode-none-fro.patch
Patch114: 0115-Create-Fix-checking-for-container-in-update_metadata.patch
Patch115: 0116-Fix-null-pointer-for-incremental-in-mdadm.patch
Patch116: 0117-super1-fix-truncation-check-for-journal-device.patch
Patch117: 0118-Fix-some-cases-eyesore-formatting.patch
Patch118: 0119-Bump-minimum-kernel-version-to-2.6.32.patch
Patch119: 0120-Remove-the-config-files-in-mdcheck_start-continue-se.patch
Patch120: 0121-mdadm-define-DEV_MD_DIR.patch
Patch121: 0122-mdadm-define-DEV_NUM_PREF.patch
Patch122: 0123-mdadm-define-is_devname_ignore.patch
Patch123: 0124-mdadm-numbered-names-verification.patch
Patch124: 0125-enable-RAID-for-SATA-under-VMD.patch
Patch125: 0126-imsm-Fix-possible-segfault-in-check_no_platform.patch
Patch126: 0127-imsm-move-sum_extents-calculations-to-merge_extents.patch
Patch127: 0128-imsm-imsm_get_free_size-refactor.patch
Patch128: 0129-imsm-introduce-round_member_size_to_mb.patch
Patch129: 0130-imsm-move-expand-verification-code-into-new-function.patch
Patch130: 0131-imsm-return-free-space-after-volume-for-expand.patch
Patch131: 0132-imsm-fix-free-space-calculations.patch
Patch132: 0133-Add-secure-gethostname-wrapper.patch
Patch133: 0134-mdadm-Stop-mdcheck_continue-timer-when-mdcheck_start.patch
Patch134: 0135-Fix-memory-leak-in-file-Assemble.patch
Patch135: 0136-Fix-memory-leak-in-file-Kill.patch
Patch136: 0137-Fix-memory-leak-in-file-Manage.patch
Patch137: 0138-Fix-memory-leak-in-file-mdadm.patch
Patch138: 0139-Fix-unsafe-string-functions.patch
Patch139: 0140-platform-intel-limit-guid-length.patch
Patch140: 0141-imsm-Add-reading-vmd-register-for-finding-imsm-capab.patch
Patch141: 0142-Add-compiler-defenses-flags.patch
Patch142: 0143-Assemble-fix-redundant-memory-free.patch
Patch143: 0144-tests-add-a-new-test-for-rdev-lifetime.patch
Patch144: 0145-tests-support-to-skip-checking-dmesg.patch
Patch145: 0146-tests-add-a-regression-test-for-raid10-deadlock.patch
Patch146: 0147-tests-add-a-regression-test-for-raid456-deadlock.patch
Patch147: 0148-tests-add-a-regression-test-that-raid456-can-t-assem.patch
Patch148: 0149-tests-add-a-regression-test-that-raid456-can-t-assem.patch
Patch149: 0150-tests-add-a-regression-test-that-reshape-can-corrupt.patch
Patch150: 0151-tests-add-a-regression-test-for-raid456-deadlock-aga.patch
Patch151: 0152-tests-create-names_template.patch
Patch152: 0153-tests-create-00confnames.patch
Patch153: 0154-mdadm-set-ident.devname-if-applicable.patch
Patch154: 0155-mdadm-refactor-ident-name-handling.patch
Patch155: 0156-mdadm-define-ident_set_devname.patch
Patch156: 0157-mdadm-Follow-POSIX-Portable-Character-Set.patch
Patch157: 0158-Incremental-remove-obsoleted-calls-to-udisks.patch
Patch158: 0159-mdadm-tests-Fix-regular-expression-failure.patch
Patch159: 0160-Fix-race-of-mdadm-add-and-mdadm-incremental.patch
Patch160: 0161-mdadm-tests-Don-t-run-mknod-before-losetup.patch
Patch161: 0162-mdadm-ddf-Abort-when-raid-disk-is-smaller-in-getinfo.patch
Patch162: 0163-mdadm-super1-Add-MD_FEATURE_RAID0_LAYOUT-if-kernel-5.patch
Patch163: 0164-mdadm-remove-container_enough-logic.patch
Patch164: 0165-Fix-assembling-RAID-volume-by-using-incremental.patch
# Fedora customization patches
# RHEL customization patches
Patch200: mdadm-udev.patch
Patch201: mdadm-2.5.2-static.patch
Patch202: disable-Werror.patch
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
License: GPLv2+
Group: System Environment/Base
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Obsoletes: mdctl,raidtools
Obsoletes: mdadm-sysvinit
Conflicts: dracut < 034-1
Requires(post): systemd-units chkconfig coreutils
BuildRequires: systemd-units binutils-devel systemd-devel
Requires(preun): systemd-units
Requires(postun): systemd-units coreutils
BuildRequires: make
BuildRequires: systemd-rpm-macros binutils-devel gcc systemd-devel
Requires: libreport-filesystem
%define _hardened_build 1
Requires(post): systemd coreutils
Requires(preun): systemd
Requires(postun): systemd coreutils
%description
The mdadm program is used to create, manage, and monitor Linux MD (software
@ -127,284 +205,186 @@ almost all functions without a configuration file, though a configuration
file can be used to help with some common tasks.
%prep
%setup -q -n %{name}-%{version}%{?subversion:_%{subversion}}
%patch000 -p1 -b .0001
%patch001 -p1 -b .0002
%patch002 -p1 -b .0003
%patch003 -p1 -b .0004
%patch004 -p1 -b .0005
%patch005 -p1 -b .0006
%patch006 -p1 -b .0007
%patch007 -p1 -b .0008
%patch008 -p1 -b .0009
%patch009 -p1 -b .0010
%patch010 -p1 -b .0011
%patch011 -p1 -b .0013
%patch012 -p1 -b .0014
%patch013 -p1 -b .0015
%patch014 -p1 -b .0016
%patch015 -p1 -b .0017
%patch016 -p1 -b .0018
%patch017 -p1 -b .0019
%patch018 -p1 -b .0020
%patch019 -p1 -b .0021
%patch020 -p1 -b .0022
%patch021 -p1 -b .0023
%patch022 -p1 -b .0024
%patch023 -p1 -b .0025
%patch024 -p1 -b .0026
%patch025 -p1 -b .0027
%patch026 -p1 -b .0028
%patch027 -p1 -b .0029
%patch028 -p1 -b .0030
%patch029 -p1 -b .0031
%patch030 -p1 -b .0032
%patch031 -p1 -b .0033
%patch032 -p1 -b .0034
%patch033 -p1 -b .0035
%patch034 -p1 -b .0036
%patch035 -p1 -b .0037
%patch036 -p1 -b .0038
%patch037 -p1 -b .0039
%patch038 -p1 -b .0040
%patch039 -p1 -b .0041
%patch040 -p1 -b .0042
%patch041 -p1 -b .0043
%patch042 -p1 -b .0044
%patch043 -p1 -b .0045
%patch044 -p1 -b .0046
%patch045 -p1 -b .0047
%patch046 -p1 -b .0048
%patch047 -p1 -b .0049
%patch048 -p1 -b .0050
%patch049 -p1 -b .0051
%patch050 -p1 -b .0052
%patch051 -p1 -b .0053
%patch052 -p1 -b .0054
%patch053 -p1 -b .0055
%patch054 -p1 -b .0056
%patch055 -p1 -b .0057
%patch056 -p1 -b .0058
%patch057 -p1 -b .0059
%patch058 -p1 -b .0060
%patch059 -p1 -b .0061
%patch060 -p1 -b .0062
%patch061 -p1 -b .0063
%patch062 -p1 -b .0064
%patch063 -p1 -b .0065
%patch064 -p1 -b .0066
%patch065 -p1 -b .0067
%patch066 -p1 -b .0068
%patch067 -p1 -b .0069
%patch068 -p1 -b .0070
%patch069 -p1 -b .0071
%patch070 -p1 -b .0072
%patch071 -p1 -b .0073
%patch072 -p1 -b .0074
%patch073 -p1 -b .0075
%patch074 -p1 -b .0076
%patch075 -p1 -b .0077
%patch076 -p1 -b .0078
%patch077 -p1 -b .0079
%patch078 -p1 -b .0080
%patch079 -p1 -b .0081
%patch080 -p1 -b .0082
%patch081 -p1 -b .0083
# RHEL customization patches
%patch200 -p1 -b .udev
%patch201 -p1 -b .static
%patch202 -p1 -b .disable
%autosetup -p1 -n %{name}-%{version}%{?subversion:_%{subversion}}
%build
#If extraversion is defined, add EXTRAVERSION="%{extraversion}"
make %{?_smp_mflags} CXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" SYSCONFDIR="%{_sysconfdir}" EXTRAVERSION="%{extraversion}" mdadm mdmon
%install
rm -rf %{buildroot}
make DESTDIR=%{buildroot} MANDIR=%{_mandir} BINDIR=%{_sbindir} SYSTEMD_DIR=%{_unitdir} install install-systemd
install -Dp -m 755 %{SOURCE2} %{buildroot}%{_sbindir}/raid-check
install -Dp -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/sysconfig/raid-check
install -Dp -m 644 %{SOURCE4} %{buildroot}%{_sysconfdir}/cron.d/raid-check
mkdir -p -m 710 %{buildroot}/var/run/mdadm
make DESTDIR=%{buildroot} MANDIR=%{_mandir} BINDIR=%{_sbindir} SYSTEMD_DIR=%{_unitdir} UDEVDIR=/usr/lib/udev/ install install-systemd
install -Dp -m 755 %{SOURCE1} %{buildroot}%{_sbindir}/raid-check
install -Dp -m 644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/raid-check
mkdir -p -m 710 %{buildroot}/run/mdadm
mkdir -p -m 700 %{buildroot}/usr/share/mdadm
mkdir -p -m 700 %{buildroot}/usr/lib/mdadm
install -Dp -m 755 %{SOURCE8} %{buildroot}/usr/share/mdadm/mdcheck
install -Dp -m 755 %{SOURCE9} %{buildroot}/usr/lib/mdadm/mdadm_env.sh
install -Dp -m 644 %{SOURCE9} %{buildroot}%{_udevrulesdir}/66-md-auto-readd.rules
install -Dp -m 755 %{SOURCE10} %{buildroot}%{_sbindir}/md-auto-readd.sh
# systemd
mkdir -p %{buildroot}%{_unitdir}
install -m644 %{SOURCE5} %{buildroot}%{_unitdir}
install -m644 %{SOURCE3} %{buildroot}%{_unitdir}
install -m644 %{SOURCE6} %{buildroot}%{_unitdir}
install -m644 %{SOURCE7} %{buildroot}%{_unitdir}
# tmpfile
mkdir -p %{buildroot}%{_tmpfilesdir}
install -m 0644 %{SOURCE6} %{buildroot}%{_tmpfilesdir}/%{name}.conf
install -m 0644 %{SOURCE4} %{buildroot}%{_tmpfilesdir}/%{name}.conf
mkdir -p %{buildroot}%{_localstatedir}/run/
install -d -m 0710 %{buildroot}%{_localstatedir}/run/%{name}/
install -d -m 0710 %{buildroot}/run/%{name}/
# abrt
mkdir -p %{buildroot}/etc/libreport/events.d
install -m644 %{SOURCE7} %{buildroot}/etc/libreport/events.d
%clean
rm -rf %{buildroot}
install -m644 %{SOURCE5} %{buildroot}/etc/libreport/events.d
%post
%systemd_post mdmonitor.service
/usr/bin/systemctl disable mdmonitor-takeover.service >/dev/null 2>&1 || :
%systemd_post mdmonitor.service raid-check.timer
%{_bindir}/systemctl disable mdmonitor-takeover.service >/dev/null 2>&1 || :
%preun
%systemd_preun mdmonitor.service
%systemd_preun mdmonitor.service raid-check.timer
%postun
%systemd_postun_with_restart mdmonitor.service
%triggerun -- %{name} < 3.2.2-3
%{_bindir}/systemd-sysv-convert --save mdmonitor >/dev/null 2>&1 || :
/bin/systemctl --no-reload enable mdmonitor.service >/dev/null 2>&1 || :
/sbin/chkconfig --del mdmonitor >/dev/null 2>&1 || :
/bin/systemctl try-restart mdmonitor.service >/dev/null 2>&1 || :
%files
%defattr(-,root,root,-)
%doc TODO ChangeLog mdadm.conf-example COPYING misc/*
%license COPYING
%doc mdadm.conf-example misc/*
%{_udevrulesdir}/*
%{_sbindir}/*
%{_unitdir}/*
%{_mandir}/man*/md*
/usr/lib/systemd/system-shutdown/*
%config(noreplace) %{_sysconfdir}/cron.d/*
%{_prefix}/lib/systemd/system-shutdown/*
%config(noreplace) %{_sysconfdir}/sysconfig/*
%dir %{_localstatedir}/run/%{name}/
%dir /run/%{name}/
%config(noreplace) %{_tmpfilesdir}/%{name}.conf
/etc/libreport/events.d/*
/usr/share/mdadm/mdcheck
/usr/lib/mdadm/mdadm_env.sh
%changelog
* Fri Jan 6 2023 Xiao Ni <xni@redhat.com> - 4.2-7
- Update to latest to upstream to fix some bugs
- Resolves rhbz#2149307, rhbz#2149473, rhbz#2151208, rhbz#2127096
* Fri Nov 3 2023 Xiao Ni <xni@redhat.com> - 4.2-10
- Update to latest upstream
- Resolves RHEL-15386
* Thu Sep 8 2022 Xiao Ni <xni@redhat.com> - 4.2-6
- Keep udev rule close to upstream and update to latest upstream
- Resolves rhbz#1991596, rhbz#2129088, rhbz#2107150
* Tue May 16 2023 Xiao Ni <xni@redhat.com> - 4.2-9
- Update to latest upstream and fix mdcheck service bug
- Resolves rhbz#2159923, rhbz#2150865, rhbz#2124071, rhbz#2203859
* Fri Jan 6 2023 Xiao Ni <xni@redhat.com> - 4.2-8
- Update to latest upstream
- Resolves rhbz#2127101, rhbz#2139789, rhbz#2149292, rhbz#2151209, rhbz#2148945
* Tue Nov 15 2022 Xiao Ni <xni@redhat.com> - 4.2-7
- Update to latest upstream and keep udev rule close to upstream
- Resolves rhbz#2107147, rhbz#2129087, rhbz#2126428
* Mon Sep 5 2022 Xiao Ni <xni@redhat.com> - 4.2-6
- Add ddf auto-assemble in mdadm udev rule
- Resolves rhbz#2120690
* Thu Aug 25 2022 Xiao Ni <xni@redhat.com> - 4.2-5
- Update mdadm to latest upstream
- Resolves rhbz#2092326
- Update to latest upstream
- Resolves rhbz#2092330
* Sun Aug 07 2022 Xiao Ni <xni@redhat.com> - 4.2-4
- Add KillMode=none to mdmon systemd service again
- Resolves rhbz#2109397
* Wed Aug 10 2022 Xiao Ni <xni@redhat.com> - 4.2-4
- Add Killmode=none for mdmon systemd service again
- Resolves rhbz#2109042
* Mon May 30 2022 Xiao Ni <xni@redhat.com> - 4.2-3
- Update mdadm to latest upstream
- Resolves rhbz#2052563, rhbz#1991596
- Resolves rhbz#2052029, rhbz#1974184
* Thu Feb 24 2022 Xiao Ni <xni@redhat.com> - 4.2-2
- mdadm re-add fault/removed disk failed
- Resolves rhbz#2046323
- Resolves rhbz#2047567
* Fri Feb 18 2022 Xiao Ni <xni@redhat.com> - 4.2
- Update to 4.2
- Resolves rhbz#2034809
* Fri Dec 31 2021 Xiao Ni <xni@redhat.com> - 4.2
- Update to upstream 4.2
- Resolves rhbz#2026723, rhbz#2026532, rhbz#1995587
* Mon Nov 08 2021 Xiao Ni <xni@redhat.com> - 4.2-rc3
- Update to 4.2-rc3
- Resolves rhbz#1983019, rhbz#1995582, rhbz#1972032, rhbz#1885665
* Fri Aug 13 2021 Xiao Ni <xni@redhat.com> - 4.2-rc2_1.2
- Fix gating test error and rpminspect error
- Resolves rhbz#1870487, rhbz#1880529
* Thu Aug 05 2021 Xiao Ni <xni@redhat.com> - 4.2-rc2
- Update to 4.2-rc2
- Resolves rhbz#1989844
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 4.2-rc2_1.1
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Fri Jul 23 2021 Xiao Ni <xni@redhat.com> - 4.2-rc1-4
- Fix gating test failure
- Resolves rhbz#1984335
* Mon Aug 09 2021 Xiao Ni <xni@redhat.com> - 4.2-rc2_1
- Update to mdadm-4.2-rc2
- Resolves rhbz#1870487, rhbz#1880529
* Tue Jul 20 2021 Xiao Ni <xni@redhat.com> - 4.2-rc1-3
- Fix super1.0 offset problem and super imsm bugs
- Resolves rhbz#1966712 and rhbz#1975449
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 4.1-8
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Thu Jun 10 2021 Xiao Ni <xni@redhat.com> - 4.2-rc1-2
- Fix udev rule syntax error
- Resolves rhbz#1945780
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 4.1-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Fri May 07 2021 Xiao Ni <xni@redhat.com> - 4.2-rc1
- Update to upstream 4.2-rc1
- Resovles rhbz#1920384
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.1-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Jan 11 2021 Xiao Ni <xni@redhat.com> - 4.1.15
- Update to latest upstream
- Resolves rhbz#1838005
* Wed May 27 2020 Xiao Ni <xni@redhat.com> - 4.1-5
- Don't enable raid-check.service to avoid raid check after every boot
- Resolves bz1838409
* Fri Jun 05 2020 Xiao Ni <xni@redhat.com> - 4.1.14
- Update to latest upstream
- Resolves rhbz#1780501
* Sun Mar 08 2020 Peter Robinson <pbrobinson@fedoraproject.org> - 4.1-4
- Fix install location of udev rules (rhbz 1809117)
* Fri Feb 28 2020 Xiao Ni <xni@redhat.com> - 4.1.13
- Remove the unnecessary whitespace in .service file
- Resolves rhbz#1803470
* Fri Feb 07 2020 Alejandro Domínguez Muñoz <adomu@net-c.com> - 4.1-3
- Replace raid-check cron job with systemd timer
* Tue Feb 11 2020 Xiao Ni <xni@redhat.com> - 4.1.12
- Update mdadm to latest upstream && change tmpfiles directory && correct changelog date
- Resolves rhbz#1800521 and rhbz#1657265
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 4.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Sun Feb 09 2020 Xiao Ni <xni@redhat.com> - 4.1.11
- mdcheck start service can't start
- Resolves rhbz#1769823
* Mon Jan 13 2020 Peter Robinson <pbrobinson@fedoraproject.org> 4.1-1
- Update to 4.1 GA
- Spec cleanups and updates
- Update mdadm.pid location (rhbz 1701114, rhbz 1557623, rhbz 1557623)
* Fri Nov 15 2019 Xiao Ni <xni@redhat.com> - 4.1.10
- Update mdadm to latest upstream
- Resolves rhbz#1721937
* Sun Dec 15 2019 Julian Sikorski <belegdol@fedoraproject.org> - 4.1-rc2.0.5.2
- Fix invalid substitution type error
- Resolves bz1740662, bz1749859
* Wed Jul 10 2019 Xiao Ni <xni@redhat.com> - 4.1.9
- Add --incremental for ddf member disk in udev rule
- Resolves rhbz#1693583
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.1-rc2.0.5.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Thu Jun 13 2019 Xiao Ni <xni@redhat.com> - 4.1.8
- Update to latest upstream
- Resolves rhbz#1661203
* Tue Jun 04 2019 Xiao Ni <xni@redhat.com> - 4.1-rc2.0.5
- Update tmpfiles directory to non-legacy location
- Resolves bz1704517
* Wed Jun 12 2019 Xiao Ni <xni@redhat.com> - 4.1.7
- Fix gating test error
- Resolves rhbz#1682396
* Wed Apr 17 2019 Xiao Ni <xni@redhat.com> - 4.1-rc2.0.4
- Change tmpfiles directory to /run/mdadm
- Resovles bz1701821
* Thu May 23 2019 Xiao Ni <xni@redhat.com> - 4.1.6
- Enable raid5 journal
- Resolves rhbz#1691202
* Sat Mar 16 2019 Björn Esser <besser82@fedoraproject.org> - 4.1-rc2.0.3
- Add patch to build without -Werror, fixes FTBFS (#1675363)
* Fri Apr 12 2019 Xiao Ni <xni@redhat.com> - 4.1.5
- add gating tests
- Resolves rhbz#1682396
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 4.1-rc2.0.2.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Fri Jan 11 2019 Xiao Ni <xni@redhat.com> - 4.1.4
- Disable raid5 journal
- Resolves rhbz#1664961
* Thu Sep 13 2018 Adam Williamson <awilliam@redhat.com> - 4.1-rc2.0.2
- Fix multipath check in udev rule, broke array init in F29
- Resolves bz1628192
* Fri Dec 21 2018 Xiao Ni <xni@redhat.com> - 4.1.3
- Recovery isn't noticed while raid10 double degradation
- Resolves rhbz#1654482
* Sun Aug 26 2018 Peter Robinson <pbrobinson@fedoraproject.org> 4.1-rc2.0.1
- Update to 4.1 rc2
* Wed Dec 12 2018 Xiao Ni <xni@redhat.com> - 4.1.2
- Add warning message for using raid1 cluster
- Resolves rhbz#1654482
* Fri Jul 20 2018 Xiao Ni <xni@redhat.com> - 4.1-rc1_1.2
- Add gcc into BuildRequires
- Resolves bz1604811
* Fri Oct 26 2018 Xiao Ni <xni@redhat.com> - 4.1.1
- Update to upstream 4.1
- Resolves rhbz#1642206
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 4.1-rc1_1.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Wed Oct 24 2018 Xiao Ni <xni@redhat.com> - 4.1-rc1-3
- Can't find md device when install rhel8
- Resolves rhbz#1628774
* Mon Jul 09 2018 Xiao Ni <xni@redhat.com> 4.1-rc1-1
- Update to latest upstream version 4.1-rc1
- Resolves bz1556591
* Wed Jul 4 2018 Peter Robinson <pbrobinson@fedoraproject.org> 4.0-7
- Cleanup spec, use %%licenece, drop old sys-v migration bits
* Thu Aug 16 2018 Xiao Ni <xni@redhat.com> - 4.1-rc1-2
- Fix two IMSM bugs
- Resolves rhbz#1602420 and rhbz#1602422
* Fri Jun 22 2018 Xiao Ni <xni@redhat.com> - 4.1-rc1-1
- Upgrade to upstream mdadm-4.1-rc1
- Resolves rhbz#1493605 and rhbz#1494477 and rhbz#1502118
* Thu Feb 08 2018 Fedora Release Engineering <releng@fedoraproject.org> - 4.0-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 4.0-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild