Update to latest upstream and fix mdcheck service bug

This commit is contained in:
Xiao Ni 2023-05-16 10:25:28 +08:00 committed by Stepan Oksanichenko
parent 02e1f69890
commit e75d57e449
48 changed files with 5570 additions and 73 deletions

1
.mdadm.metadata Normal file
View File

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

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

27
md-auto-readd.rule Normal file
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
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,7 +1,7 @@
Name: mdadm
Version: 4.2
# extraversion is used to define rhel internal version
%define extraversion 8
%define extraversion 9
Release: %{extraversion}%{?dist}
Summary: The mdadm program controls Linux md devices (software RAID arrays)
URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/
@ -15,6 +15,9 @@ Source4: mdadm.conf
Source5: mdadm_event.conf
Source6: raid-check.timer
Source7: raid-check.service
Source8: mdcheck
Source9: md-auto-readd.rule
Source10: md-auto-readd.sh
Patch000: 0001-Unify-error-message.patch
Patch001: 0002-mdadm-Fix-double-free.patch
@ -27,78 +30,120 @@ 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
# Fedora customization patches
@ -133,6 +178,10 @@ make DESTDIR=%{buildroot} MANDIR=%{_mandir} BINDIR=%{_sbindir} SYSTEMD_DIR=%{_un
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
install -Dp -m 755 %{SOURCE8} %{buildroot}/usr/share/mdadm/mdcheck
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}
@ -172,8 +221,13 @@ install -m644 %{SOURCE5} %{buildroot}/etc/libreport/events.d
%dir /run/%{name}/
%config(noreplace) %{_tmpfilesdir}/%{name}.conf
/etc/libreport/events.d/*
/usr/share/mdadm/mdcheck
%changelog
* 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

166
mdcheck Normal file
View File

@ -0,0 +1,166 @@
#!/bin/bash
# Copyright (C) 2014-2017 Neil Brown <neilb@suse.de>
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# Author: Neil Brown
# Email: <neilb@suse.com>
# This script should be run periodically to automatically
# perform a 'check' on any md arrays.
#
# It supports a 'time budget' such that any incomplete 'check'
# will be checkpointed when that time has expired.
# A subsequent invocation can allow the 'check' to continue.
#
# Options are:
# --continue Don't start new checks, only continue old ones.
# --duration This is passed to "date --date=$duration" to find out
# when to finish
#
# To support '--continue', arrays are identified by UUID and the 'sync_completed'
# value is stored in /var/lib/mdcheck/$UUID
# convert a /dev/md name into /sys/.../md equivalent
sysname() {
set `ls -lLd $1`
maj=${5%,}
min=$6
readlink -f /sys/dev/block/$maj:$min
}
args=$(getopt -o hcd: -l help,continue,duration: -n mdcheck -- "$@")
rv=$?
if [ $rv -ne 0 ]; then exit $rv; fi
eval set -- $args
cont=
endtime=
while [ " $1" != " --" ]
do
case $1 in
--help )
echo >&2 'Usage: mdcheck [--continue] [--duration time-offset]'
echo >&2 ' time-offset must be understood by "date --date"'
exit 0
;;
--continue ) cont=yes ;;
--duration ) shift; dur=$1
endtime=$(date --date "$dur" "+%s")
;;
esac
shift
done
shift
# We need a temp file occasionally...
tmp=/var/lib/mdcheck/.md-check-$$
trap 'rm -f "$tmp"' 0 2 3 15
# firstly, clean out really old state files
mkdir -p /var/lib/mdcheck
find /var/lib/mdcheck -name "MD_UUID*" -type f -mtime +180 -exec rm {} \;
# Now look at each md device.
cnt=0
for dev in /dev/md?*
do
[ -e "$dev" ] || continue
sys=`sysname $dev`
if [ ! -f "$sys/md/sync_action" ]
then # cannot check this array
continue
fi
if [ "`cat $sys/md/sync_action`" != 'idle' ]
then # This array is busy
continue
fi
mdadm --detail --export "$dev" | grep '^MD_UUID=' > $tmp || continue
source $tmp
fl="/var/lib/mdcheck/MD_UUID_$MD_UUID"
if [ -z "$cont" ]
then
start=0
logger -p daemon.info mdcheck start checking $dev
elif [ -z "$MD_UUID" -o ! -f "$fl" ]
then
# Nothing to continue here
continue
else
start=`cat "$fl"`
logger -p daemon.info mdcheck continue checking $dev from $start
fi
cnt=$[cnt+1]
eval MD_${cnt}_fl=\$fl
eval MD_${cnt}_sys=\$sys
eval MD_${cnt}_dev=\$dev
echo $start > $fl
echo $start > $sys/md/sync_min
echo check > $sys/md/sync_action
done
if [ -z "$endtime" ]
then
exit 0
fi
while [ `date +%s` -lt $endtime ]
do
any=
for i in `eval echo {1..$cnt}`
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;
fi
read a rest < $sys/md/sync_completed
echo $a > $fl
any=yes
done
if [ -z "$any" ]; then exit 0; fi
sleep 120
done
# We've waited, and there are still checks running.
# Time to stop them.
for i in `eval echo {1..$cnt}`
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
eval MD_${i}_fl=
rm -f $fl
continue;
fi
echo idle > $sys/md/sync_action
cat $sys/md/sync_min > $fl
logger -p daemon.info pause checking $dev at `cat $fl`
done