diff --git a/0062-Manage-Block-unsafe-member-failing.patch b/0062-Manage-Block-unsafe-member-failing.patch new file mode 100644 index 0000000..efac5bc --- /dev/null +++ b/0062-Manage-Block-unsafe-member-failing.patch @@ -0,0 +1,91 @@ +From fc6fd4063769f4194c3fb8f77b32b2819e140fb9 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Thu, 18 Aug 2022 11:47:21 +0200 +Subject: [PATCH] Manage: Block unsafe member failing + +Kernel may or may not block mdadm from removing member device if it +will cause arrays failed state. It depends on raid personality +implementation in kernel. +Add verification on requested removal path (#mdadm --set-faulty +command). + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Manage.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 52 insertions(+), 1 deletion(-) + +diff --git a/Manage.c b/Manage.c +index a142f8b..b1d0e63 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1285,6 +1285,50 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv, + return -1; + } + ++/** ++ * is_remove_safe() - Check if remove is safe. ++ * @array: Array info. ++ * @fd: Array file descriptor. ++ * @devname: Name of device to remove. ++ * @verbose: Verbose. ++ * ++ * The function determines if array will be operational ++ * after removing &devname. ++ * ++ * Return: True if array will be operational, false otherwise. ++ */ ++bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const int verbose) ++{ ++ dev_t devid = devnm2devid(devname + 5); ++ struct mdinfo *mdi = sysfs_read(fd, NULL, GET_DEVS | GET_DISKS | GET_STATE); ++ ++ if (!mdi) { ++ if (verbose) ++ pr_err("Failed to read sysfs attributes for %s\n", devname); ++ return false; ++ } ++ ++ char *avail = xcalloc(array->raid_disks, sizeof(char)); ++ ++ for (mdi = mdi->devs; mdi; mdi = mdi->next) { ++ if (mdi->disk.raid_disk < 0) ++ continue; ++ if (!(mdi->disk.state & (1 << MD_DISK_SYNC))) ++ continue; ++ if (makedev(mdi->disk.major, mdi->disk.minor) == devid) ++ continue; ++ avail[mdi->disk.raid_disk] = 1; ++ } ++ sysfs_free(mdi); ++ ++ bool is_enough = enough(array->level, array->raid_disks, ++ array->layout, (array->state & 1), ++ avail); ++ ++ free(avail); ++ return is_enough; ++} ++ + int Manage_subdevs(char *devname, int fd, + struct mddev_dev *devlist, int verbose, int test, + char *update, int force) +@@ -1598,7 +1642,14 @@ int Manage_subdevs(char *devname, int fd, + break; + + case 'f': /* set faulty */ +- /* FIXME check current member */ ++ if (!is_remove_safe(&array, fd, dv->devname, verbose)) { ++ pr_err("Cannot remove %s from %s, array will be failed.\n", ++ dv->devname, devname); ++ if (sysfd >= 0) ++ close(sysfd); ++ goto abort; ++ } ++ + if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) || + (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY, + rdev))) { +-- +2.35.3 + diff --git a/0063-Mdmonitor-Split-alert-into-separate-functions.patch b/0063-Mdmonitor-Split-alert-into-separate-functions.patch new file mode 100644 index 0000000..bc39426 --- /dev/null +++ b/0063-Mdmonitor-Split-alert-into-separate-functions.patch @@ -0,0 +1,233 @@ +From 3698867194f27fdd7824b8bdd172d619a2c087cc Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Wed, 7 Sep 2022 14:56:49 +0200 +Subject: [PATCH] Mdmonitor: Split alert() into separate functions + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + Monitor.c | 186 ++++++++++++++++++++++++++++-------------------------- + 1 file changed, 95 insertions(+), 91 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 7d7dc4d..0036e8c 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -66,7 +66,7 @@ struct alert_info { + static int make_daemon(char *pidfile); + static int check_one_sharer(int scan); + static void write_autorebuild_pid(void); +-static void alert(char *event, char *dev, char *disc, struct alert_info *info); ++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); +@@ -407,111 +407,115 @@ static void write_autorebuild_pid() + } + } + +-static void alert(char *event, char *dev, char *disc, struct alert_info *info) ++static void execute_alert_cmd(const char *event, const char *dev, const char *disc, struct alert_info *info) ++{ ++ int pid = fork(); ++ ++ switch (pid) { ++ default: ++ waitpid(pid, NULL, 0); ++ break; ++ case -1: ++ pr_err("Cannot fork to execute alert command"); ++ break; ++ case 0: ++ 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) ++{ ++ FILE *mp, *mdstat; ++ char hname[256]; ++ char buf[BUFSIZ]; ++ int n; ++ ++ mp = popen(Sendmail, "w"); ++ if (!mp) { ++ pr_err("Cannot open pipe stream for sendmail.\n"); ++ return; ++ } ++ ++ gethostname(hname, sizeof(hname)); ++ signal(SIGPIPE, SIG_IGN); ++ if (info->mailfrom) ++ fprintf(mp, "From: %s\n", info->mailfrom); ++ else ++ fprintf(mp, "From: %s monitoring \n", Name); ++ fprintf(mp, "To: %s\n", info->mailaddr); ++ fprintf(mp, "Subject: %s event on %s:%s\n\n", event, dev, hname); ++ 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); ++ ++ 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); ++ ++ mdstat = fopen("/proc/mdstat", "r"); ++ if (!mdstat) { ++ pr_err("Cannot open /proc/mdstat\n"); ++ pclose(mp); ++ return; ++ } ++ ++ fprintf(mp, "The /proc/mdstat file currently contains the following:\n\n"); ++ while ((n = fread(buf, 1, sizeof(buf), mdstat)) > 0) ++ n = fwrite(buf, 1, n, mp); ++ fclose(mdstat); ++ pclose(mp); ++} ++ ++static void log_event_to_syslog(const char *event, 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) ++ 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) ++ 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, dev, disc); ++ else if (disc) ++ syslog(priority, "%s event detected on md device %s: %s", event, dev, disc); ++ else ++ 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) ++{ + 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) { +- int pid = fork(); +- switch(pid) { +- default: +- waitpid(pid, NULL, 0); +- break; +- case -1: +- break; +- case 0: +- execl(info->alert_cmd, info->alert_cmd, +- event, dev, disc, NULL); +- exit(2); +- } +- } ++ if (info->alert_cmd) ++ execute_alert_cmd(event, dev, disc, info); ++ + if (info->mailaddr && (strncmp(event, "Fail", 4) == 0 || + strncmp(event, "Test", 4) == 0 || + strncmp(event, "Spares", 6) == 0 || + strncmp(event, "Degrade", 7) == 0)) { +- FILE *mp = popen(Sendmail, "w"); +- if (mp) { +- FILE *mdstat; +- char hname[256]; +- +- gethostname(hname, sizeof(hname)); +- signal_s(SIGPIPE, SIG_IGN); +- +- if (info->mailfrom) +- fprintf(mp, "From: %s\n", info->mailfrom); +- else +- fprintf(mp, "From: %s monitoring \n", +- Name); +- fprintf(mp, "To: %s\n", info->mailaddr); +- fprintf(mp, "Subject: %s event on %s:%s\n\n", +- event, dev, hname); +- +- fprintf(mp, +- "This is an automatically generated mail message from %s\n", Name); +- fprintf(mp, "running on %s\n\n", hname); +- +- fprintf(mp, +- "A %s event had been detected on md device %s.\n\n", event, 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, "Faithfully yours, etc.\n"); +- +- mdstat = fopen("/proc/mdstat", "r"); +- if (mdstat) { +- char buf[8192]; +- int n; +- fprintf(mp, +- "\nP.S. The /proc/mdstat file currently contains the following:\n\n"); +- while ((n = fread(buf, 1, sizeof(buf), +- mdstat)) > 0) +- n = fwrite(buf, 1, n, mp); +- fclose(mdstat); +- } +- pclose(mp); +- } ++ send_event_email(event, dev, disc, info); + } + +- /* log the event to syslog maybe */ +- if (info->dosyslog) { +- /* 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) +- 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) +- 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, dev, disc); +- else if (disc) +- syslog(priority, +- "%s event detected on md device %s: %s", +- event, dev, disc); +- else +- syslog(priority, +- "%s event detected on md device %s", +- event, dev); +- } ++ if (info->dosyslog) ++ log_event_to_syslog(event, dev, disc); + } + + static int check_array(struct state *st, struct mdstat_ent *mdstat, +-- +2.35.3 + diff --git a/0064-Monitor-block-if-monitor-modes-are-combined.patch b/0064-Monitor-block-if-monitor-modes-are-combined.patch new file mode 100644 index 0000000..241a5bd --- /dev/null +++ b/0064-Monitor-block-if-monitor-modes-are-combined.patch @@ -0,0 +1,41 @@ +From f40ac0e7e6043361ad12e9db97c07e56c3977cf6 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Mon, 19 Dec 2022 11:21:57 +0100 +Subject: [PATCH] Monitor: block if monitor modes are combined. + +Block monitoring start if --scan mode and MD devices list are combined. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + Monitor.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/Monitor.c b/Monitor.c +index 0036e8c..188cb8b 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -123,7 +123,7 @@ int Monitor(struct mddev_dev *devlist, + * and if we can get_disk_info and find a name + * Then we hot-remove and hot-add to the other array + * +- * If devlist is NULL, then we can monitor everything because --scan ++ * If devlist is NULL, then we can monitor everything if --scan + * was given. We get an initial list from config file and add anything + * that appears in /proc/mdstat + */ +@@ -136,6 +136,11 @@ int Monitor(struct mddev_dev *devlist, + struct mddev_ident *mdlist; + int delay_for_event = c->delay; + ++ if (devlist && c->scan) { ++ pr_err("Devices list and --scan option cannot be combined - not monitoring.\n"); ++ return 1; ++ } ++ + if (!mailaddr) + mailaddr = conf_get_mailaddr(); + +-- +2.35.3 + diff --git a/0065-Update-mdadm-Monitor-manual.patch b/0065-Update-mdadm-Monitor-manual.patch new file mode 100644 index 0000000..317c90d --- /dev/null +++ b/0065-Update-mdadm-Monitor-manual.patch @@ -0,0 +1,119 @@ +From 725e37cd14866906ba28c970394b9f7a4cd97413 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Mon, 19 Dec 2022 11:21:58 +0100 +Subject: [PATCH] Update mdadm Monitor manual. + +- describe monitor work modes, +- clarify the turning off condition, +- describe the mdmonitor.service as a prefered management way. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 71 ++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 50 insertions(+), 21 deletions(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index 70c79d1..64f71ed 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -2548,13 +2548,33 @@ Usage: + .I options... devices... + + .PP +-This usage causes ++Monitor option can work in two modes: ++.IP \(bu 4 ++system wide mode, follow all md devices based on ++.B /proc/mdstat, ++.IP \(bu 4 ++follow only specified MD devices in command line. ++.PP ++ ++.B \-\-scan - ++indicates system wide mode. Option causes the ++.I monitor ++to track all md devices that appear in ++.B /proc/mdstat. ++If it is not set, then at least one ++.B device ++must be specified. ++ ++Monitor usage causes + .I mdadm + to periodically poll a number of md arrays and to report on any events + noticed. +-.I mdadm +-will never exit once it decides that there are arrays to be checked, +-so it should normally be run in the background. ++ ++In both modes, ++.I monitor ++will work as long as there is an active array with redundancy and it is defined to follow (for ++.B \-\-scan ++every array is followed). + + As well as reporting events, + .I mdadm +@@ -2565,15 +2585,6 @@ or + .B domain + and if the destination array has a failed drive but no spares. + +-If any devices are listed on the command line, +-.I mdadm +-will only monitor those devices, otherwise, all arrays listed in the +-configuration file will be monitored. Further, if +-.B \-\-scan +-is given, then any other md devices that appear in +-.B /proc/mdstat +-will also be monitored. +- + The result of monitoring the arrays is the generation of events. + These events are passed to a separate program (if specified) and may + be mailed to a given E-mail address. +@@ -2586,16 +2597,34 @@ device if relevant (such as a component device that has failed). + + If + .B \-\-scan +-is given, then a program or an E-mail address must be specified on the +-command line or in the config file. If neither are available, then ++is given, then a ++.B program ++or an ++.B e-mail ++address must be specified on the ++command line or in the config file. If neither are available, then + .I mdadm + will not monitor anything. +-Without +-.B \-\-scan, +-.I mdadm +-will continue monitoring as long as something was found to monitor. If +-no program or email is given, then each event is reported to +-.BR stdout . ++For devices given directly in command line, without ++.B program ++or ++.B email ++specified, each event is reported to ++.BR stdout. ++ ++Note: For systems where ++.If mdadm monitor ++is configured via systemd, ++.B mdmonitor(mdmonitor.service) ++should be configured. The service is designed to be primary solution for array monitoring, ++it is configured to work in system wide mode. ++It is automatically started and stopped according to current state and types of MD arrays in system. ++The service may require additional configuration, like ++.B e-mail ++or ++.B delay. ++That should be done in ++.B mdadm.conf. + + The different events are: + +-- +2.35.3 + diff --git a/0066-mdadm-create-ident_init.patch b/0066-mdadm-create-ident_init.patch new file mode 100644 index 0000000..6a72044 --- /dev/null +++ b/0066-mdadm-create-ident_init.patch @@ -0,0 +1,145 @@ +From 7fcbfd7c620e2dcd3b539d18e93cb503ee3a8a62 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Wed, 21 Dec 2022 12:50:17 +0100 +Subject: [PATCH] mdadm: create ident_init() + +Add a wrapper for repeated initializations in mdadm.c and config.c. +Move includes up. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + config.c | 45 +++++++++++++++++++++++++++++---------------- + mdadm.c | 16 ++-------------- + mdadm.h | 7 +++++-- + 3 files changed, 36 insertions(+), 32 deletions(-) + +Index: mdadm-4.2/config.c +=================================================================== +--- mdadm-4.2.orig/config.c ++++ mdadm-4.2/config.c +@@ -119,6 +119,34 @@ int match_keyword(char *word) + return -1; + } + ++/** ++ * ident_init() - Set defaults. ++ * @ident: ident pointer, not NULL. ++ */ ++inline void ident_init(struct mddev_ident *ident) ++{ ++ assert(ident); ++ ++ ident->assembled = false; ++ ident->autof = 0; ++ ident->bitmap_fd = -1; ++ ident->bitmap_file = NULL; ++ ident->container = NULL; ++ ident->devices = NULL; ++ ident->devname = NULL; ++ ident->level = UnSet; ++ ident->member = NULL; ++ ident->name[0] = 0; ++ ident->next = NULL; ++ ident->raid_disks = UnSet; ++ ident->spare_group = NULL; ++ ident->spare_disks = 0; ++ ident->st = NULL; ++ ident->super_minor = UnSet; ++ ident->uuid[0] = 0; ++ ident->uuid_set = 0; ++} ++ + struct conf_dev { + struct conf_dev *next; + char *name; +@@ -363,22 +391,7 @@ void arrayline(char *line) + struct mddev_ident mis; + struct mddev_ident *mi; + +- mis.uuid_set = 0; +- mis.super_minor = UnSet; +- mis.level = UnSet; +- mis.raid_disks = UnSet; +- mis.spare_disks = 0; +- mis.devices = NULL; +- mis.devname = NULL; +- mis.spare_group = NULL; +- mis.autof = 0; +- mis.next = NULL; +- mis.st = NULL; +- mis.bitmap_fd = -1; +- mis.bitmap_file = NULL; +- mis.name[0] = 0; +- mis.container = NULL; +- mis.member = NULL; ++ ident_init(&mis); + + for (w = dl_next(line); w != line; w = dl_next(w)) { + if (w[0] == '/' || strchr(w, '=') == NULL) { +Index: mdadm-4.2/mdadm.c +=================================================================== +--- mdadm-4.2.orig/mdadm.c ++++ mdadm-4.2/mdadm.c +@@ -107,25 +107,13 @@ int main(int argc, char *argv[]) + + srandom(time(0) ^ getpid()); + +- ident.uuid_set = 0; +- ident.level = UnSet; +- ident.raid_disks = UnSet; +- ident.super_minor = UnSet; +- ident.devices = 0; +- ident.spare_group = NULL; +- ident.autof = 0; +- ident.st = NULL; +- ident.bitmap_fd = -1; +- ident.bitmap_file = NULL; +- ident.name[0] = 0; +- ident.container = NULL; +- ident.member = NULL; +- + if (get_linux_version() < 2006015) { + pr_err("This version of mdadm does not support kernels older than 2.6.15\n"); + exit(1); + } + ++ ident_init(&ident); ++ + while ((option_index = -1), + (opt = getopt_long(argc, argv, shortopt, long_options, + &option_index)) != -1) { +Index: mdadm-4.2/mdadm.h +=================================================================== +--- mdadm-4.2.orig/mdadm.h ++++ mdadm-4.2/mdadm.h +@@ -33,8 +33,10 @@ extern __off64_t lseek64 __P ((int __fd, + # endif + #endif + ++#include + #include + #include ++#include + #include + #include + #include +@@ -1554,6 +1556,8 @@ extern void enable_fds(int devices); + extern void manage_fork_fds(int close_all); + extern int continue_via_systemd(char *devnm, char *service_name, char *prefix); + ++extern void ident_init(struct mddev_ident *ident); ++ + extern int parse_auto(char *str, char *msg, int config); + extern struct mddev_ident *conf_get_ident(char *dev); + extern struct mddev_dev *conf_get_devs(void); +@@ -1781,8 +1785,7 @@ static inline sighandler_t signal_s(int + #define dprintf_cont(fmt, arg...) \ + ({ if (0) fprintf(stderr, fmt, ##arg); 0; }) + #endif +-#include +-#include ++ + static inline int xasprintf(char **strp, const char *fmt, ...) { + va_list ap; + int ret; diff --git a/0067-mdadm-Add-option-validation-for-update-subarray.patch b/0067-mdadm-Add-option-validation-for-update-subarray.patch new file mode 100644 index 0000000..4e3e369 --- /dev/null +++ b/0067-mdadm-Add-option-validation-for-update-subarray.patch @@ -0,0 +1,287 @@ +From 2568ce89ea5c26225e8984733adc2ea7559d853a Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:15 +0100 +Subject: [PATCH] mdadm: Add option validation for --update-subarray + +Subset of options available for "--update" is not same as for "--update-subarray". +Define maps and enum for update options and use them instead of direct comparisons. +Add proper error message. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + ReadMe.c | 31 +++++++++++++++++ + maps.c | 31 +++++++++++++++++ + mdadm.c | 104 +++++++++++++++++-------------------------------------- + mdadm.h | 32 ++++++++++++++++- + 4 files changed, 124 insertions(+), 74 deletions(-) + +diff --git a/ReadMe.c b/ReadMe.c +index 50a5e36..bd8d50d 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -655,3 +655,34 @@ char *mode_help[mode_count] = { + [GROW] = Help_grow, + [INCREMENTAL] = Help_incr, + }; ++ ++/** ++ * fprint_update_options() - Print valid update options depending on the mode. ++ * @outf: File (output stream) ++ * @update_mode: Used to distinguish update and update_subarray ++ */ ++void fprint_update_options(FILE *outf, enum update_opt update_mode) ++{ ++ int counter = UOPT_NAME, breakpoint = UOPT_HELP; ++ mapping_t *map = update_options; ++ ++ if (!outf) ++ return; ++ if (update_mode == UOPT_SUBARRAY_ONLY) { ++ breakpoint = UOPT_SUBARRAY_ONLY; ++ fprintf(outf, "Valid --update options for update-subarray are:\n\t"); ++ } else ++ fprintf(outf, "Valid --update options are:\n\t"); ++ while (map->num) { ++ if (map->num >= breakpoint) ++ break; ++ fprintf(outf, "'%s', ", map->name); ++ if (counter % 5 == 0) ++ fprintf(outf, "\n\t"); ++ counter++; ++ map++; ++ } ++ if ((counter - 1) % 5) ++ fprintf(outf, "\n"); ++ fprintf(outf, "\r"); ++} +diff --git a/maps.c b/maps.c +index 20fcf71..b586679 100644 +--- a/maps.c ++++ b/maps.c +@@ -165,6 +165,37 @@ mapping_t sysfs_array_states[] = { + { "broken", ARRAY_BROKEN }, + { NULL, ARRAY_UNKNOWN_STATE } + }; ++/** ++ * mapping_t update_options - stores supported update options. ++ */ ++mapping_t update_options[] = { ++ { "name", UOPT_NAME }, ++ { "ppl", UOPT_PPL }, ++ { "no-ppl", UOPT_NO_PPL }, ++ { "bitmap", UOPT_BITMAP }, ++ { "no-bitmap", UOPT_NO_BITMAP }, ++ { "sparc2.2", UOPT_SPARC22 }, ++ { "super-minor", UOPT_SUPER_MINOR }, ++ { "summaries", UOPT_SUMMARIES }, ++ { "resync", UOPT_RESYNC }, ++ { "uuid", UOPT_UUID }, ++ { "homehost", UOPT_HOMEHOST }, ++ { "home-cluster", UOPT_HOME_CLUSTER }, ++ { "nodes", UOPT_NODES }, ++ { "devicesize", UOPT_DEVICESIZE }, ++ { "bbl", UOPT_BBL }, ++ { "no-bbl", UOPT_NO_BBL }, ++ { "force-no-bbl", UOPT_FORCE_NO_BBL }, ++ { "metadata", UOPT_METADATA }, ++ { "revert-reshape", UOPT_REVERT_RESHAPE }, ++ { "layout-original", UOPT_LAYOUT_ORIGINAL }, ++ { "layout-alternate", UOPT_LAYOUT_ALTERNATE }, ++ { "layout-unspecified", UOPT_LAYOUT_UNSPECIFIED }, ++ { "byteorder", UOPT_BYTEORDER }, ++ { "help", UOPT_HELP }, ++ { "?", UOPT_HELP }, ++ { NULL, UOPT_UNDEFINED} ++}; + + /** + * map_num_s() - Safer alternative of map_num() function. +diff --git a/mdadm.c b/mdadm.c +index 74fdec3..f5f505f 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -100,7 +100,7 @@ int main(int argc, char *argv[]) + char *dump_directory = NULL; + + int print_help = 0; +- FILE *outf; ++ FILE *outf = NULL; + + int mdfd = -1; + int locked = 0; +@@ -723,7 +723,11 @@ int main(int argc, char *argv[]) + continue; + + case O(ASSEMBLE,'U'): /* update the superblock */ +- case O(MISC,'U'): ++ case O(MISC,'U'): { ++ enum update_opt updateopt = map_name(update_options, c.update); ++ enum update_opt print_mode = UOPT_HELP; ++ const char *error_addon = "update option"; ++ + if (c.update) { + pr_err("Can only update one aspect of superblock, both %s and %s given.\n", + c.update, optarg); +@@ -733,83 +737,37 @@ int main(int argc, char *argv[]) + pr_err("Only subarrays can be updated in misc mode\n"); + exit(2); + } ++ + c.update = optarg; +- if (strcmp(c.update, "sparc2.2") == 0) +- continue; +- if (strcmp(c.update, "super-minor") == 0) +- continue; +- if (strcmp(c.update, "summaries") == 0) +- continue; +- if (strcmp(c.update, "resync") == 0) +- continue; +- if (strcmp(c.update, "uuid") == 0) +- continue; +- if (strcmp(c.update, "name") == 0) +- continue; +- if (strcmp(c.update, "homehost") == 0) +- continue; +- if (strcmp(c.update, "home-cluster") == 0) +- continue; +- if (strcmp(c.update, "nodes") == 0) +- continue; +- if (strcmp(c.update, "devicesize") == 0) +- continue; +- if (strcmp(c.update, "bitmap") == 0) +- continue; +- if (strcmp(c.update, "no-bitmap") == 0) +- continue; +- if (strcmp(c.update, "bbl") == 0) +- continue; +- if (strcmp(c.update, "no-bbl") == 0) +- continue; +- if (strcmp(c.update, "force-no-bbl") == 0) +- continue; +- if (strcmp(c.update, "ppl") == 0) +- continue; +- if (strcmp(c.update, "no-ppl") == 0) +- continue; +- if (strcmp(c.update, "metadata") == 0) +- continue; +- if (strcmp(c.update, "revert-reshape") == 0) +- continue; +- if (strcmp(c.update, "layout-original") == 0 || +- strcmp(c.update, "layout-alternate") == 0 || +- strcmp(c.update, "layout-unspecified") == 0) +- continue; +- if (strcmp(c.update, "byteorder") == 0) { ++ ++ if (devmode == UpdateSubarray) { ++ print_mode = UOPT_SUBARRAY_ONLY; ++ error_addon = "update-subarray option"; ++ ++ if (updateopt > UOPT_SUBARRAY_ONLY && updateopt < UOPT_HELP) ++ updateopt = UOPT_UNDEFINED; ++ } ++ ++ switch (updateopt) { ++ case UOPT_UNDEFINED: ++ pr_err("'--update=%s' is invalid %s. ", ++ c.update, error_addon); ++ outf = stderr; ++ case UOPT_HELP: ++ if (!outf) ++ outf = stdout; ++ fprint_update_options(outf, print_mode); ++ exit(outf == stdout ? 0 : 2); ++ case UOPT_BYTEORDER: + if (ss) { + pr_err("must not set metadata type with --update=byteorder.\n"); + exit(2); + } +- for(i = 0; !ss && superlist[i]; i++) +- ss = superlist[i]->match_metadata_desc( +- "0.swap"); +- if (!ss) { +- pr_err("INTERNAL ERROR cannot find 0.swap\n"); +- exit(2); +- } +- +- continue; ++ default: ++ break; + } +- if (strcmp(c.update,"?") == 0 || +- strcmp(c.update, "help") == 0) { +- outf = stdout; +- fprintf(outf, "%s: ", Name); +- } else { +- outf = stderr; +- fprintf(outf, +- "%s: '--update=%s' is invalid. ", +- Name, c.update); +- } +- fprintf(outf, "Valid --update options are:\n" +- " 'sparc2.2', 'super-minor', 'uuid', 'name', 'nodes', 'resync',\n" +- " 'summaries', 'homehost', 'home-cluster', 'byteorder', 'devicesize',\n" +- " 'bitmap', 'no-bitmap', 'metadata', 'revert-reshape'\n" +- " 'bbl', 'no-bbl', 'force-no-bbl', 'ppl', 'no-ppl'\n" +- " 'layout-original', 'layout-alternate', 'layout-unspecified'\n" +- ); +- exit(outf == stdout ? 0 : 2); +- ++ continue; ++ } + case O(MANAGE,'U'): + /* update=devicesize is allowed with --re-add */ + if (devmode != 'A') { +diff --git a/mdadm.h b/mdadm.h +index 23ffe97..51f1db2 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -497,6 +497,36 @@ enum special_options { + ConsistencyPolicy, + }; + ++enum update_opt { ++ UOPT_NAME = 1, ++ UOPT_PPL, ++ UOPT_NO_PPL, ++ UOPT_BITMAP, ++ UOPT_NO_BITMAP, ++ UOPT_SUBARRAY_ONLY, ++ UOPT_SPARC22, ++ UOPT_SUPER_MINOR, ++ UOPT_SUMMARIES, ++ UOPT_RESYNC, ++ UOPT_UUID, ++ UOPT_HOMEHOST, ++ UOPT_HOME_CLUSTER, ++ UOPT_NODES, ++ UOPT_DEVICESIZE, ++ UOPT_BBL, ++ UOPT_NO_BBL, ++ UOPT_FORCE_NO_BBL, ++ UOPT_METADATA, ++ UOPT_REVERT_RESHAPE, ++ UOPT_LAYOUT_ORIGINAL, ++ UOPT_LAYOUT_ALTERNATE, ++ UOPT_LAYOUT_UNSPECIFIED, ++ UOPT_BYTEORDER, ++ UOPT_HELP, ++ UOPT_UNDEFINED ++}; ++extern void fprint_update_options(FILE *outf, enum update_opt update_mode); ++ + enum prefix_standard { + JEDEC, + IEC +@@ -777,7 +807,7 @@ extern char *map_num(mapping_t *map, int num); + extern int map_name(mapping_t *map, char *name); + extern mapping_t r0layout[], r5layout[], r6layout[], + pers[], modes[], faultylayout[]; +-extern mapping_t consistency_policies[], sysfs_array_states[]; ++extern mapping_t consistency_policies[], sysfs_array_states[], update_options[]; + + extern char *map_dev_preferred(int major, int minor, int create, + char *prefer); +-- +2.35.3 + diff --git a/0068-Fix-update-subarray-on-active-volume.patch b/0068-Fix-update-subarray-on-active-volume.patch new file mode 100644 index 0000000..48de504 --- /dev/null +++ b/0068-Fix-update-subarray-on-active-volume.patch @@ -0,0 +1,54 @@ +From db10eab68e652f141169b7240e057d110d626c3d Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:16 +0100 +Subject: [PATCH] Fix --update-subarray on active volume + +Options: bitmap, ppl and name should not be updated when array is active. +Those features are mutually exclusive and share the same data area in IMSM (danger of overwriting by kernel). +Remove check for active subarrays from super-intel. +Since ddf is not supported, apply it globally for all options. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Manage.c | 7 +++++++ + super-intel.c | 5 ----- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/Manage.c b/Manage.c +index b1d0e63..5a9ea31 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1745,6 +1745,13 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + goto free_super; + } + ++ if (is_subarray_active(subarray, st->devnm)) { ++ if (verbose >= 0) ++ pr_err("Subarray %s in %s is active, cannot update %s\n", ++ subarray, dev, update); ++ goto free_super; ++ } ++ + if (mdmon_running(st->devnm)) + st->update_tail = &st->updates; + +diff --git a/super-intel.c b/super-intel.c +index b056561..5f93f3d 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7914,11 +7914,6 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + char *ep; + int vol; + +- if (is_subarray_active(subarray, st->devnm)) { +- pr_err("Unable to update name of active subarray\n"); +- return 2; +- } +- + if (!check_name(super, name, 0)) + return 2; + +-- +2.35.3 + diff --git a/0069-Add-code-specific-update-options-to-enum.patch b/0069-Add-code-specific-update-options-to-enum.patch new file mode 100644 index 0000000..6be3821 --- /dev/null +++ b/0069-Add-code-specific-update-options-to-enum.patch @@ -0,0 +1,77 @@ +From 2257de106cbf17a7f1df33a10cfd2be0d5a064cb Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:17 +0100 +Subject: [PATCH] Add code specific update options to enum. + +Some of update options aren't taken from user input, but are hard-coded +as strings. +Include those options in enum. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + maps.c | 21 +++++++++++++++++++++ + mdadm.h | 15 +++++++++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/maps.c b/maps.c +index b586679..c59036f 100644 +--- a/maps.c ++++ b/maps.c +@@ -194,6 +194,27 @@ mapping_t update_options[] = { + { "byteorder", UOPT_BYTEORDER }, + { "help", UOPT_HELP }, + { "?", UOPT_HELP }, ++ /* ++ * Those enries are temporary and will be removed in this patchset. ++ * ++ * Before update_super:update can be changed to enum, ++ * all update_super sub-functions must be adapted first. ++ * Update options will be passed as string (as it is for now), ++ * and then mapped, so all options must be handled temporarily. ++ * ++ * Those options code specific and should not be accessible for user. ++ */ ++ { "force-one", UOPT_SPEC_FORCE_ONE }, ++ { "force-array", UOPT_SPEC_FORCE_ARRAY }, ++ { "assemble", UOPT_SPEC_ASSEMBLE }, ++ { "linear-grow-new", UOPT_SPEC_LINEAR_GROW_NEW }, ++ { "linear-grow-update", UOPT_SPEC_LINEAR_GROW_UPDATE }, ++ { "_reshape_progress", UOPT_SPEC__RESHAPE_PROGRESS }, ++ { "writemostly", UOPT_SPEC_WRITEMOSTLY }, ++ { "readwrite", UOPT_SPEC_READWRITE }, ++ { "failfast", UOPT_SPEC_FAILFAST }, ++ { "nofailfast", UOPT_SPEC_NOFAILFAST }, ++ { "revert-reshape-nobackup", UOPT_SPEC_REVERT_RESHAPE_NOBACKUP }, + { NULL, UOPT_UNDEFINED} + }; + +diff --git a/mdadm.h b/mdadm.h +index 51f1db2..31db25f 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -523,6 +523,21 @@ enum update_opt { + UOPT_LAYOUT_UNSPECIFIED, + UOPT_BYTEORDER, + UOPT_HELP, ++ UOPT_USER_ONLY, ++ /* ++ * Code specific options, cannot be set by the user ++ */ ++ UOPT_SPEC_FORCE_ONE, ++ UOPT_SPEC_FORCE_ARRAY, ++ UOPT_SPEC_ASSEMBLE, ++ UOPT_SPEC_LINEAR_GROW_NEW, ++ UOPT_SPEC_LINEAR_GROW_UPDATE, ++ UOPT_SPEC__RESHAPE_PROGRESS, ++ UOPT_SPEC_WRITEMOSTLY, ++ UOPT_SPEC_READWRITE, ++ UOPT_SPEC_FAILFAST, ++ UOPT_SPEC_NOFAILFAST, ++ UOPT_SPEC_REVERT_RESHAPE_NOBACKUP, + UOPT_UNDEFINED + }; + extern void fprint_update_options(FILE *outf, enum update_opt update_mode); +-- +2.35.3 + diff --git a/0070-super-ddf-Remove-update_super_ddf.patch b/0070-super-ddf-Remove-update_super_ddf.patch new file mode 100644 index 0000000..f493f9d --- /dev/null +++ b/0070-super-ddf-Remove-update_super_ddf.patch @@ -0,0 +1,106 @@ +From 35aa44c549290e22f285896684c704acb53b7717 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:18 +0100 +Subject: [PATCH] super-ddf: Remove update_super_ddf. + +This is not supported by ddf. +It hides errors by returning success status for some updates. +Remove update_super_dff(). + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + super-ddf.c | 70 ----------------------------------------------------- + 1 file changed, 70 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index 9d1e3b9..309812d 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -2139,75 +2139,6 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha + } + } + +-static int update_super_ddf(struct supertype *st, struct mdinfo *info, +- char *update, +- char *devname, int verbose, +- int uuid_set, char *homehost) +-{ +- /* For 'assemble' and 'force' we need to return non-zero if any +- * change was made. For others, the return value is ignored. +- * Update options are: +- * force-one : This device looks a bit old but needs to be included, +- * update age info appropriately. +- * assemble: clear any 'faulty' flag to allow this device to +- * be assembled. +- * force-array: Array is degraded but being forced, mark it clean +- * if that will be needed to assemble it. +- * +- * newdev: not used ???? +- * grow: Array has gained a new device - this is currently for +- * linear only +- * resync: mark as dirty so a resync will happen. +- * uuid: Change the uuid of the array to match what is given +- * homehost: update the recorded homehost +- * name: update the name - preserving the homehost +- * _reshape_progress: record new reshape_progress position. +- * +- * Following are not relevant for this version: +- * sparc2.2 : update from old dodgey metadata +- * super-minor: change the preferred_minor number +- * summaries: update redundant counters. +- */ +- int rv = 0; +-// struct ddf_super *ddf = st->sb; +-// struct vd_config *vd = find_vdcr(ddf, info->container_member); +-// struct virtual_entry *ve = find_ve(ddf); +- +- /* we don't need to handle "force-*" or "assemble" as +- * there is no need to 'trick' the kernel. When the metadata is +- * first updated to activate the array, all the implied modifications +- * will just happen. +- */ +- +- if (strcmp(update, "grow") == 0) { +- /* FIXME */ +- } else if (strcmp(update, "resync") == 0) { +-// info->resync_checkpoint = 0; +- } else if (strcmp(update, "homehost") == 0) { +- /* homehost is stored in controller->vendor_data, +- * or it is when we are the vendor +- */ +-// if (info->vendor_is_local) +-// strcpy(ddf->controller.vendor_data, homehost); +- rv = -1; +- } else if (strcmp(update, "name") == 0) { +- /* name is stored in virtual_entry->name */ +-// memset(ve->name, ' ', 16); +-// strncpy(ve->name, info->name, 16); +- rv = -1; +- } else if (strcmp(update, "_reshape_progress") == 0) { +- /* We don't support reshape yet */ +- } else if (strcmp(update, "assemble") == 0 ) { +- /* Do nothing, just succeed */ +- rv = 0; +- } else +- rv = -1; +- +-// update_all_csum(ddf); +- +- return rv; +-} +- + static void make_header_guid(char *guid) + { + be32 stamp; +@@ -5211,7 +5142,6 @@ struct superswitch super_ddf = { + .match_home = match_home_ddf, + .uuid_from_super= uuid_from_super_ddf, + .getinfo_super = getinfo_super_ddf, +- .update_super = update_super_ddf, + + .avail_size = avail_size_ddf, + +-- +2.35.3 + diff --git a/0071-super0-refactor-the-code-for-enum.patch b/0071-super0-refactor-the-code-for-enum.patch new file mode 100644 index 0000000..66f504a --- /dev/null +++ b/0071-super0-refactor-the-code-for-enum.patch @@ -0,0 +1,212 @@ +From 0a9e39383d3bf63e1f5cf10f64200083a1af8091 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:19 +0100 +Subject: [PATCH] super0: refactor the code for enum + +It prepares update_super0 for change context->update to enum. +Change if else statements to switch. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + super0.c | 102 ++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 63 insertions(+), 39 deletions(-) + +diff --git a/super0.c b/super0.c +index 93876e2..d9f5bff 100644 +--- a/super0.c ++++ b/super0.c +@@ -502,19 +502,39 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + int rv = 0; + int uuid[4]; + mdp_super_t *sb = st->sb; ++ enum update_opt update_enum = map_name(update_options, update); + +- if (strcmp(update, "homehost") == 0 && +- homehost) { +- /* note that 'homehost' is special as it is really ++ if (update_enum == UOPT_HOMEHOST && homehost) { ++ /* ++ * note that 'homehost' is special as it is really + * a "uuid" update. + */ + uuid_set = 0; +- update = "uuid"; ++ update_enum = UOPT_UUID; + info->uuid[0] = sb->set_uuid0; + info->uuid[1] = sb->set_uuid1; + } + +- if (strcmp(update, "sparc2.2")==0 ) { ++ switch (update_enum) { ++ case UOPT_UUID: ++ if (!uuid_set && homehost) { ++ char buf[20]; ++ memcpy(info->uuid+2, ++ sha1_buffer(homehost, strlen(homehost), buf), ++ 8); ++ } ++ sb->set_uuid0 = info->uuid[0]; ++ sb->set_uuid1 = info->uuid[1]; ++ sb->set_uuid2 = info->uuid[2]; ++ sb->set_uuid3 = info->uuid[3]; ++ if (sb->state & (1<uuid, uuid, 16); ++ } ++ break; ++ case UOPT_SPARC22: { + /* 2.2 sparc put the events in the wrong place + * So we copy the tail of the superblock + * up 4 bytes before continuing +@@ -527,12 +547,15 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + if (verbose >= 0) + pr_err("adjusting superblock of %s for 2.2/sparc compatibility.\n", + devname); +- } else if (strcmp(update, "super-minor") ==0) { ++ break; ++ } ++ case UOPT_SUPER_MINOR: + sb->md_minor = info->array.md_minor; + if (verbose > 0) + pr_err("updating superblock of %s with minor number %d\n", + devname, info->array.md_minor); +- } else if (strcmp(update, "summaries") == 0) { ++ break; ++ case UOPT_SUMMARIES: { + unsigned int i; + /* set nr_disks, active_disks, working_disks, + * failed_disks, spare_disks based on disks[] +@@ -559,7 +582,9 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + sb->spare_disks++; + } else if (i >= sb->raid_disks && sb->disks[i].number == 0) + sb->disks[i].state = 0; +- } else if (strcmp(update, "force-one")==0) { ++ break; ++ } ++ case UOPT_SPEC_FORCE_ONE: { + /* Not enough devices for a working array, so + * bring this one up-to-date. + */ +@@ -569,7 +594,9 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + if (sb->events_hi != ehi || + sb->events_lo != elo) + rv = 1; +- } else if (strcmp(update, "force-array")==0) { ++ break; ++ } ++ case UOPT_SPEC_FORCE_ARRAY: + /* degraded array and 'force' requested, so + * maybe need to mark it 'clean' + */ +@@ -579,7 +606,8 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + sb->state |= (1 << MD_SB_CLEAN); + rv = 1; + } +- } else if (strcmp(update, "assemble")==0) { ++ break; ++ case UOPT_SPEC_ASSEMBLE: { + int d = info->disk.number; + int wonly = sb->disks[d].state & (1<disks[d].state & (1<reshape_position = info->reshape_progress; + rv = 1; + } +- } else if (strcmp(update, "linear-grow-new") == 0) { ++ break; ++ } ++ case UOPT_SPEC_LINEAR_GROW_NEW: + memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0])); + sb->disks[info->disk.number].number = info->disk.number; + sb->disks[info->disk.number].major = info->disk.major; +@@ -617,7 +647,8 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + sb->disks[info->disk.number].raid_disk = info->disk.raid_disk; + sb->disks[info->disk.number].state = info->disk.state; + sb->this_disk = sb->disks[info->disk.number]; +- } else if (strcmp(update, "linear-grow-update") == 0) { ++ break; ++ case UOPT_SPEC_LINEAR_GROW_UPDATE: + sb->raid_disks = info->array.raid_disks; + sb->nr_disks = info->array.nr_disks; + sb->active_disks = info->array.active_disks; +@@ -628,29 +659,15 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + sb->disks[info->disk.number].minor = info->disk.minor; + sb->disks[info->disk.number].raid_disk = info->disk.raid_disk; + sb->disks[info->disk.number].state = info->disk.state; +- } else if (strcmp(update, "resync") == 0) { +- /* make sure resync happens */ ++ break; ++ case UOPT_RESYNC: ++ /* ++ * make sure resync happens ++ */ + sb->state &= ~(1<recovery_cp = 0; +- } else if (strcmp(update, "uuid") == 0) { +- if (!uuid_set && homehost) { +- char buf[20]; +- char *hash = sha1_buffer(homehost, +- strlen(homehost), +- buf); +- memcpy(info->uuid+2, hash, 8); +- } +- sb->set_uuid0 = info->uuid[0]; +- sb->set_uuid1 = info->uuid[1]; +- sb->set_uuid2 = info->uuid[2]; +- sb->set_uuid3 = info->uuid[3]; +- if (sb->state & (1<uuid, uuid, 16); +- } +- } else if (strcmp(update, "metadata") == 0) { ++ break; ++ case UOPT_METADATA: + /* Create some v1.0 metadata to match ours but make the + * ctime bigger. Also update info->array.*_version. + * We need to arrange that store_super writes out +@@ -670,7 +687,8 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + uuid_from_super0(st, info->uuid); + st->other = super1_make_v0(st, info, st->sb); + } +- } else if (strcmp(update, "revert-reshape") == 0) { ++ break; ++ case UOPT_REVERT_RESHAPE: + rv = -2; + if (sb->minor_version <= 90) + pr_err("No active reshape to revert on %s\n", +@@ -702,16 +720,22 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + sb->new_chunk = sb->chunk_size; + sb->chunk_size = tmp; + } +- } else if (strcmp(update, "no-bitmap") == 0) { ++ break; ++ case UOPT_NO_BITMAP: + sb->state &= ~(1<reshape_position = info->reshape_progress; +- else if (strcmp(update, "writemostly")==0) ++ break; ++ case UOPT_SPEC_WRITEMOSTLY: + sb->state |= (1<state &= ~(1<sb_csum = calc_sb0_csum(sb); + return rv; +-- +2.35.3 + diff --git a/0072-super1-refactor-the-code-for-enum.patch b/0072-super1-refactor-the-code-for-enum.patch new file mode 100644 index 0000000..266b7f0 --- /dev/null +++ b/0072-super1-refactor-the-code-for-enum.patch @@ -0,0 +1,302 @@ +From 7e8daba8b7937716dce8ea28298a4e2e72cb829e Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:20 +0100 +Subject: [PATCH] super1: refactor the code for enum + +It prepares update_super1 for change context->update to enum. +Change if else statements into switch. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + super1.c | 152 +++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 91 insertions(+), 61 deletions(-) + +diff --git a/super1.c b/super1.c +index 0b505a7..b0a9701 100644 +--- a/super1.c ++++ b/super1.c +@@ -1218,30 +1218,55 @@ 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); ++ enum update_opt update_enum = map_name(update_options, update); + +- if (strcmp(update, "homehost") == 0 && +- homehost) { +- /* Note that 'homehost' is special as it is really ++ if (update_enum == UOPT_HOMEHOST && homehost) { ++ /* ++ * Note that 'homehost' is special as it is really + * a "name" update. + */ + char *c; +- update = "name"; ++ update_enum = UOPT_NAME; + c = strchr(sb->set_name, ':'); + if (c) +- strncpy(info->name, c+1, 31 - (c-sb->set_name)); ++ snprintf(info->name, sizeof(info->name), "%s", c+1); + else +- strncpy(info->name, sb->set_name, 32); +- info->name[32] = 0; ++ snprintf(info->name, sizeof(info->name), "%s", sb->set_name); + } + +- if (strcmp(update, "force-one")==0) { ++ switch (update_enum) { ++ case UOPT_NAME: { ++ int namelen; ++ ++ if (!info->name[0]) ++ snprintf(info->name, sizeof(info->name), "%d", info->array.md_minor); ++ memset(sb->set_name, 0, sizeof(sb->set_name)); ++ ++ namelen = strnlen(homehost, MD_NAME_MAX) + 1 + strnlen(info->name, MD_NAME_MAX); ++ if (homehost && ++ strchr(info->name, ':') == NULL && ++ namelen < MD_NAME_MAX) { ++ strcpy(sb->set_name, homehost); ++ strcat(sb->set_name, ":"); ++ strcat(sb->set_name, info->name); ++ } else { ++ namelen = min((int)strnlen(info->name, MD_NAME_MAX), ++ (int)sizeof(sb->set_name) - 1); ++ memcpy(sb->set_name, info->name, namelen); ++ memset(&sb->set_name[namelen], '\0', ++ sizeof(sb->set_name) - namelen); ++ } ++ break; ++ } ++ case UOPT_SPEC_FORCE_ONE: + /* Not enough devices for a working array, + * so bring this one up-to-date + */ + if (sb->events != __cpu_to_le64(info->events)) + rv = 1; + sb->events = __cpu_to_le64(info->events); +- } else if (strcmp(update, "force-array")==0) { ++ break; ++ case UOPT_SPEC_FORCE_ARRAY: + /* Degraded array and 'force' requests to + * maybe need to mark it 'clean'. + */ +@@ -1254,7 +1279,8 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + rv = 1; + sb->resync_offset = MaxSector; + } +- } else if (strcmp(update, "assemble")==0) { ++ break; ++ case UOPT_SPEC_ASSEMBLE: { + int d = info->disk.number; + int want; + if (info->disk.state & (1<reshape_progress); + rv = 1; + } +- } else if (strcmp(update, "linear-grow-new") == 0) { ++ break; ++ } ++ case UOPT_SPEC_LINEAR_GROW_NEW: { + int i; + int fd; + int max = __le32_to_cpu(sb->max_dev); +@@ -1330,7 +1358,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + ds - __le64_to_cpu(sb->data_offset)); + } + } +- } else if (strcmp(update, "linear-grow-update") == 0) { ++ break; ++ } ++ case UOPT_SPEC_LINEAR_GROW_UPDATE: { + int max = __le32_to_cpu(sb->max_dev); + int i = info->disk.number; + if (max > MAX_DEVS || i > MAX_DEVS) +@@ -1342,19 +1372,20 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + sb->raid_disks = __cpu_to_le32(info->array.raid_disks); + sb->dev_roles[info->disk.number] = + __cpu_to_le16(info->disk.raid_disk); +- } else if (strcmp(update, "resync") == 0) { +- /* make sure resync happens */ +- sb->resync_offset = 0ULL; +- } else if (strcmp(update, "uuid") == 0) { ++ break; ++ } ++ case UOPT_UUID: + copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid); + + if (__le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) + memcpy(bms->uuid, sb->set_uuid, 16); +- } else if (strcmp(update, "no-bitmap") == 0) { ++ break; ++ case UOPT_NO_BITMAP: + sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); + if (bms->version == BITMAP_MAJOR_CLUSTERED && !IsBitmapDirty(devname)) + sb->resync_offset = MaxSector; +- } else if (strcmp(update, "bbl") == 0) { ++ break; ++ case UOPT_BBL: { + /* only possible if there is room after the bitmap, or if + * there is no bitmap + */ +@@ -1383,14 +1414,12 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + bb_offset = bitmap_offset + bm_sectors; + while (bb_offset < (long)sb_offset + 8 + 32*2 && + bb_offset + 8+8 <= (long)data_offset) +- /* too close to bitmap, and room to grow */ + bb_offset += 8; + if (bb_offset + 8 <= (long)data_offset) { + sb->bblog_size = __cpu_to_le16(8); + sb->bblog_offset = __cpu_to_le32(bb_offset); + } + } else { +- /* 1.0 - Put bbl just before super block */ + if (bm_sectors && bitmap_offset < 0) + space = -bitmap_offset - bm_sectors; + else +@@ -1401,7 +1430,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + sb->bblog_offset = __cpu_to_le32((unsigned)-8); + } + } +- } else if (strcmp(update, "no-bbl") == 0) { ++ break; ++ } ++ case UOPT_NO_BBL: + if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BAD_BLOCKS)) + pr_err("Cannot remove active bbl from %s\n",devname); + else { +@@ -1409,12 +1440,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + sb->bblog_shift = 0; + sb->bblog_offset = 0; + } +- } else if (strcmp(update, "force-no-bbl") == 0) { ++ break; ++ case UOPT_FORCE_NO_BBL: + sb->feature_map &= ~ __cpu_to_le32(MD_FEATURE_BAD_BLOCKS); + sb->bblog_size = 0; + sb->bblog_shift = 0; + sb->bblog_offset = 0; +- } else if (strcmp(update, "ppl") == 0) { ++ break; ++ case UOPT_PPL: { + unsigned long long sb_offset = __le64_to_cpu(sb->super_offset); + unsigned long long data_offset = __le64_to_cpu(sb->data_offset); + unsigned long long data_size = __le64_to_cpu(sb->data_size); +@@ -1464,37 +1497,26 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + sb->ppl.offset = __cpu_to_le16(offset); + sb->ppl.size = __cpu_to_le16(space); + sb->feature_map |= __cpu_to_le32(MD_FEATURE_PPL); +- } else if (strcmp(update, "no-ppl") == 0) { ++ break; ++ } ++ case UOPT_NO_PPL: + sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_PPL | + MD_FEATURE_MUTLIPLE_PPLS); +- } else if (strcmp(update, "name") == 0) { +- if (info->name[0] == 0) +- sprintf(info->name, "%d", info->array.md_minor); +- memset(sb->set_name, 0, sizeof(sb->set_name)); +- if (homehost && +- strchr(info->name, ':') == NULL && +- strlen(homehost)+1+strlen(info->name) < 32) { +- strcpy(sb->set_name, homehost); +- strcat(sb->set_name, ":"); +- strcat(sb->set_name, info->name); +- } else { +- int namelen; +- +- namelen = min((int)strlen(info->name), +- (int)sizeof(sb->set_name) - 1); +- memcpy(sb->set_name, info->name, namelen); +- memset(&sb->set_name[namelen], '\0', +- sizeof(sb->set_name) - namelen); +- } +- } else if (strcmp(update, "devicesize") == 0 && +- __le64_to_cpu(sb->super_offset) < +- __le64_to_cpu(sb->data_offset)) { +- /* set data_size to device size less data_offset */ ++ break; ++ case UOPT_DEVICESIZE: ++ if (__le64_to_cpu(sb->super_offset) >= ++ __le64_to_cpu(sb->data_offset)) ++ break; ++ /* ++ * set data_size to device size less data_offset ++ */ + struct misc_dev_info *misc = (struct misc_dev_info*) + (st->sb + MAX_SB_SIZE + BM_SUPER_SIZE); + sb->data_size = __cpu_to_le64( + misc->device_size - __le64_to_cpu(sb->data_offset)); +- } else if (strncmp(update, "revert-reshape", 14) == 0) { ++ break; ++ case UOPT_SPEC_REVERT_RESHAPE_NOBACKUP: ++ case UOPT_REVERT_RESHAPE: + rv = -2; + if (!(sb->feature_map & + __cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE))) +@@ -1512,7 +1534,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + * If that couldn't happen, the "-nobackup" version + * will be used. + */ +- if (strcmp(update, "revert-reshape-nobackup") == 0 && ++ if (update_enum == UOPT_SPEC_REVERT_RESHAPE_NOBACKUP && + sb->reshape_position == 0 && + (__le32_to_cpu(sb->delta_disks) > 0 || + (__le32_to_cpu(sb->delta_disks) == 0 && +@@ -1575,32 +1597,40 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + } + done:; + } +- } else if (strcmp(update, "_reshape_progress") == 0) ++ break; ++ case UOPT_SPEC__RESHAPE_PROGRESS: + sb->reshape_position = __cpu_to_le64(info->reshape_progress); +- else if (strcmp(update, "writemostly") == 0) ++ break; ++ case UOPT_SPEC_WRITEMOSTLY: + sb->devflags |= WriteMostly1; +- else if (strcmp(update, "readwrite") == 0) ++ break; ++ case UOPT_SPEC_READWRITE: + sb->devflags &= ~WriteMostly1; +- else if (strcmp(update, "failfast") == 0) ++ break; ++ case UOPT_SPEC_FAILFAST: + sb->devflags |= FailFast1; +- else if (strcmp(update, "nofailfast") == 0) ++ break; ++ case UOPT_SPEC_NOFAILFAST: + sb->devflags &= ~FailFast1; +- else if (strcmp(update, "layout-original") == 0 || +- strcmp(update, "layout-alternate") == 0 || +- strcmp(update, "layout-unspecified") == 0) { ++ break; ++ case UOPT_LAYOUT_ORIGINAL: ++ case UOPT_LAYOUT_ALTERNATE: ++ case UOPT_LAYOUT_UNSPECIFIED: + if (__le32_to_cpu(sb->level) != 0) { + pr_err("%s: %s only supported for RAID0\n", +- devname?:"", update); ++ devname ?: "", map_num(update_options, update_enum)); + rv = -1; +- } else if (strcmp(update, "layout-unspecified") == 0) { ++ } else if (update_enum == UOPT_LAYOUT_UNSPECIFIED) { + sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RAID0_LAYOUT); + sb->layout = 0; + } else { + sb->feature_map |= __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT); +- sb->layout = __cpu_to_le32(update[7] == 'o' ? 1 : 2); ++ sb->layout = __cpu_to_le32(update_enum == UOPT_LAYOUT_ORIGINAL ? 1 : 2); + } +- } else ++ break; ++ default: + rv = -1; ++ } + + sb->sb_csum = calc_sb_1_csum(sb); + +-- +2.35.3 + diff --git a/0073-super-intel-refactor-the-code-for-enum.patch b/0073-super-intel-refactor-the-code-for-enum.patch new file mode 100644 index 0000000..787e28a --- /dev/null +++ b/0073-super-intel-refactor-the-code-for-enum.patch @@ -0,0 +1,106 @@ +From 4345e135c4c7dd04bb15bad140dfc4747f677738 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:21 +0100 +Subject: [PATCH] super-intel: refactor the code for enum + +It prepares super-intel for change context->update to enum. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + super-intel.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 5f93f3d..85fb7f1 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -3930,7 +3930,8 @@ static int update_super_imsm(struct supertype *st, struct mdinfo *info, + + mpb = super->anchor; + +- if (strcmp(update, "uuid") == 0) { ++ switch (map_name(update_options, update)) { ++ case UOPT_UUID: + /* We take this to mean that the family_num should be updated. + * However that is much smaller than the uuid so we cannot really + * allow an explicit uuid to be given. And it is hard to reliably +@@ -3954,10 +3955,14 @@ static int update_super_imsm(struct supertype *st, struct mdinfo *info, + } + if (rv == 0) + mpb->orig_family_num = info->uuid[0]; +- } else if (strcmp(update, "assemble") == 0) ++ break; ++ case UOPT_SPEC_ASSEMBLE: + rv = 0; +- else ++ break; ++ default: + rv = -1; ++ break; ++ } + + /* successful update? recompute checksum */ + if (rv == 0) +@@ -7889,17 +7894,25 @@ static int kill_subarray_imsm(struct supertype *st, char *subarray_id) + return 0; + } + +-static int get_rwh_policy_from_update(char *update) ++/** ++ * get_rwh_policy_from_update() - Get the rwh policy for update option. ++ * @update: Update option. ++ */ ++static int get_rwh_policy_from_update(enum update_opt update) + { +- if (strcmp(update, "ppl") == 0) ++ switch (update) { ++ case UOPT_PPL: + return RWH_MULTIPLE_DISTRIBUTED; +- else if (strcmp(update, "no-ppl") == 0) ++ case UOPT_NO_PPL: + return RWH_MULTIPLE_OFF; +- else if (strcmp(update, "bitmap") == 0) ++ case UOPT_BITMAP: + return RWH_BITMAP; +- else if (strcmp(update, "no-bitmap") == 0) ++ case UOPT_NO_BITMAP: + return RWH_OFF; +- return -1; ++ default: ++ break; ++ } ++ return UOPT_UNDEFINED; + } + + static int update_subarray_imsm(struct supertype *st, char *subarray, +@@ -7909,7 +7922,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + struct intel_super *super = st->sb; + struct imsm_super *mpb = super->anchor; + +- if (strcmp(update, "name") == 0) { ++ if (map_name(update_options, update) == UOPT_NAME) { + char *name = ident->name; + char *ep; + int vol; +@@ -7943,7 +7956,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + } + super->updates_pending++; + } +- } else if (get_rwh_policy_from_update(update) != -1) { ++ } else if (get_rwh_policy_from_update(map_name(update_options, update)) != UOPT_UNDEFINED) { + int new_policy; + char *ep; + int vol = strtoul(subarray, &ep, 10); +@@ -7951,7 +7964,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + if (*ep != '\0' || vol >= super->anchor->num_raid_devs) + return 2; + +- new_policy = get_rwh_policy_from_update(update); ++ new_policy = get_rwh_policy_from_update(map_name(update_options, update)); + + if (st->update_tail) { + struct imsm_update_rwh_policy *u = xmalloc(sizeof(*u)); +-- +2.35.3 + diff --git a/0074-Change-update-to-enum-in-update_super-and-update_sub.patch b/0074-Change-update-to-enum-in-update_super-and-update_sub.patch new file mode 100644 index 0000000..433d914 --- /dev/null +++ b/0074-Change-update-to-enum-in-update_super-and-update_sub.patch @@ -0,0 +1,423 @@ +From 03312b5240438ffc3b63114bdc87e911222f01e5 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:22 +0100 +Subject: [PATCH] Change update to enum in update_super and update_subarray + +Use already existing enum, change update_super and update_subarray +update to enum globally. +Refactor function references also. +Remove code specific options from update_options. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Assemble.c | 14 +++++++++----- + Examine.c | 2 +- + Grow.c | 9 +++++---- + Manage.c | 14 ++++++++------ + maps.c | 21 --------------------- + mdadm.h | 12 +++++++++--- + super-intel.c | 16 ++++++++-------- + super0.c | 9 ++++----- + super1.c | 17 ++++++++--------- + 9 files changed, 52 insertions(+), 62 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 8b0af0c..dba910c 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -695,12 +695,16 @@ static int load_devices(struct devs *devices, char *devmap, + } else if (strcmp(c->update, "revert-reshape") == 0 && + c->invalid_backup) + err = tst->ss->update_super(tst, content, +- "revert-reshape-nobackup", ++ UOPT_SPEC_REVERT_RESHAPE_NOBACKUP, + devname, c->verbose, + ident->uuid_set, + c->homehost); + else +- err = tst->ss->update_super(tst, content, c->update, ++ /* ++ * Mapping is temporary, will be removed in this patchset ++ */ ++ err = tst->ss->update_super(tst, content, ++ map_name(update_options, c->update), + devname, c->verbose, + ident->uuid_set, + c->homehost); +@@ -960,7 +964,7 @@ static int force_array(struct mdinfo *content, + continue; + } + content->events = devices[most_recent].i.events; +- tst->ss->update_super(tst, content, "force-one", ++ tst->ss->update_super(tst, content, UOPT_SPEC_FORCE_ONE, + devices[chosen_drive].devname, c->verbose, + 0, NULL); + +@@ -1788,7 +1792,7 @@ try_again: + if (!(devices[j].i.array.state & 1)) + clean = 0; + +- if (st->ss->update_super(st, &devices[j].i, "assemble", NULL, ++ if (st->ss->update_super(st, &devices[j].i, UOPT_SPEC_ASSEMBLE, NULL, + c->verbose, 0, NULL)) { + if (c->force) { + if (c->verbose >= 0) +@@ -1811,7 +1815,7 @@ try_again: + if (c->force && !clean && !is_container(content->array.level) && + !enough(content->array.level, content->array.raid_disks, + content->array.layout, clean, avail)) { +- change += st->ss->update_super(st, content, "force-array", ++ change += st->ss->update_super(st, content, UOPT_SPEC_FORCE_ARRAY, + devices[chosen_drive].devname, c->verbose, + 0, NULL); + was_forced = 1; +diff --git a/Examine.c b/Examine.c +index 9574a3c..c9605a6 100644 +--- a/Examine.c ++++ b/Examine.c +@@ -117,7 +117,7 @@ int Examine(struct mddev_dev *devlist, + } + + if (c->SparcAdjust) +- st->ss->update_super(st, NULL, "sparc2.2", ++ st->ss->update_super(st, NULL, UOPT_SPARC22, + devlist->devname, 0, 0, NULL); + /* Ok, its good enough to try, though the checksum could be wrong */ + +diff --git a/Grow.c b/Grow.c +index b73ec2a..82d5d2e 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -196,7 +196,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) + info.disk.minor = minor(rdev); + info.disk.raid_disk = d; + info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); +- if (st->ss->update_super(st, &info, "linear-grow-new", newdev, ++ if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_NEW, newdev, + 0, 0, NULL) != 0) { + pr_err("Preparing new metadata failed on %s\n", newdev); + close(nfd); +@@ -254,7 +254,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) + info.array.active_disks = nd+1; + info.array.working_disks = nd+1; + +- if (st->ss->update_super(st, &info, "linear-grow-update", dv, ++ if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_UPDATE, dv, + 0, 0, NULL) != 0) { + pr_err("Updating metadata failed on %s\n", dv); + close(fd2); +@@ -668,7 +668,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + goto free_info; + } + +- ret = st->ss->update_super(st, sra, "ppl", ++ ret = st->ss->update_super(st, sra, UOPT_PPL, + devname, + c->verbose, 0, NULL); + if (ret) { +@@ -4950,7 +4950,8 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, + continue; + st->ss->getinfo_super(st, &dinfo, NULL); + dinfo.reshape_progress = info->reshape_progress; +- st->ss->update_super(st, &dinfo, "_reshape_progress", ++ st->ss->update_super(st, &dinfo, ++ UOPT_SPEC__RESHAPE_PROGRESS, + NULL,0, 0, NULL); + st->ss->store_super(st, fdlist[j]); + st->ss->free_super(st); +diff --git a/Manage.c b/Manage.c +index 5a9ea31..87b8aa0 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -605,6 +605,7 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, + struct mdinfo mdi; + int duuid[4]; + int ouuid[4]; ++ enum update_opt update_enum = map_name(update_options, update); + + dev_st->ss->getinfo_super(dev_st, &mdi, NULL); + dev_st->ss->uuid_from_super(dev_st, ouuid); +@@ -666,23 +667,23 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, + + if (dv->writemostly == FlagSet) + rv = dev_st->ss->update_super( +- dev_st, NULL, "writemostly", ++ dev_st, NULL, UOPT_SPEC_WRITEMOSTLY, + devname, verbose, 0, NULL); + if (dv->writemostly == FlagClear) + rv = dev_st->ss->update_super( +- dev_st, NULL, "readwrite", ++ dev_st, NULL, UOPT_SPEC_READWRITE, + devname, verbose, 0, NULL); + if (dv->failfast == FlagSet) + rv = dev_st->ss->update_super( +- dev_st, NULL, "failfast", ++ dev_st, NULL, UOPT_SPEC_FAILFAST, + devname, verbose, 0, NULL); + if (dv->failfast == FlagClear) + rv = dev_st->ss->update_super( +- dev_st, NULL, "nofailfast", ++ dev_st, NULL, UOPT_SPEC_NOFAILFAST, + devname, verbose, 0, NULL); + if (update) + rv = dev_st->ss->update_super( +- dev_st, NULL, update, ++ dev_st, NULL, update_enum, + devname, verbose, 0, NULL); + if (rv == 0) + rv = dev_st->ss->store_super(dev_st, tfd); +@@ -1731,6 +1732,7 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + struct supertype supertype, *st = &supertype; + int fd, rv = 2; + struct mdinfo *info = NULL; ++ enum update_opt update_enum = map_name(update_options, update); + + memset(st, 0, sizeof(*st)); + +@@ -1762,7 +1764,7 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + goto free_super; + } + +- rv = st->ss->update_subarray(st, subarray, update, ident); ++ rv = st->ss->update_subarray(st, subarray, update_enum, ident); + + if (rv) { + if (verbose >= 0) +diff --git a/maps.c b/maps.c +index c59036f..b586679 100644 +--- a/maps.c ++++ b/maps.c +@@ -194,27 +194,6 @@ mapping_t update_options[] = { + { "byteorder", UOPT_BYTEORDER }, + { "help", UOPT_HELP }, + { "?", UOPT_HELP }, +- /* +- * Those enries are temporary and will be removed in this patchset. +- * +- * Before update_super:update can be changed to enum, +- * all update_super sub-functions must be adapted first. +- * Update options will be passed as string (as it is for now), +- * and then mapped, so all options must be handled temporarily. +- * +- * Those options code specific and should not be accessible for user. +- */ +- { "force-one", UOPT_SPEC_FORCE_ONE }, +- { "force-array", UOPT_SPEC_FORCE_ARRAY }, +- { "assemble", UOPT_SPEC_ASSEMBLE }, +- { "linear-grow-new", UOPT_SPEC_LINEAR_GROW_NEW }, +- { "linear-grow-update", UOPT_SPEC_LINEAR_GROW_UPDATE }, +- { "_reshape_progress", UOPT_SPEC__RESHAPE_PROGRESS }, +- { "writemostly", UOPT_SPEC_WRITEMOSTLY }, +- { "readwrite", UOPT_SPEC_READWRITE }, +- { "failfast", UOPT_SPEC_FAILFAST }, +- { "nofailfast", UOPT_SPEC_NOFAILFAST }, +- { "revert-reshape-nobackup", UOPT_SPEC_REVERT_RESHAPE_NOBACKUP }, + { NULL, UOPT_UNDEFINED} + }; + +diff --git a/mdadm.h b/mdadm.h +index 31db25f..5dc9439 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1011,7 +1011,7 @@ extern struct superswitch { + * it will resume going in the opposite direction. + */ + int (*update_super)(struct supertype *st, struct mdinfo *info, +- char *update, ++ enum update_opt update, + char *devname, int verbose, + int uuid_set, char *homehost); + +@@ -1137,9 +1137,15 @@ extern struct superswitch { + /* Permit subarray's to be deleted from inactive containers */ + int (*kill_subarray)(struct supertype *st, + char *subarray_id); /* optional */ +- /* Permit subarray's to be modified */ ++ /** ++ * update_subarray() - Permit subarray to be modified. ++ * @st: Supertype. ++ * @subarray: Subarray name. ++ * @update: Update option. ++ * @ident: Optional identifiers. ++ */ + int (*update_subarray)(struct supertype *st, char *subarray, +- char *update, struct mddev_ident *ident); /* optional */ ++ enum update_opt update, struct mddev_ident *ident); + /* Check if reshape is supported for this external format. + * st is obtained from super_by_fd() where st->subarray[0] is + * initialized to indicate if reshape is being performed at the +diff --git a/super-intel.c b/super-intel.c +index 85fb7f1..1f5f6ed 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -3893,8 +3893,8 @@ struct mdinfo *getinfo_super_disks_imsm(struct supertype *st) + } + + static int update_super_imsm(struct supertype *st, struct mdinfo *info, +- char *update, char *devname, int verbose, +- int uuid_set, char *homehost) ++ enum update_opt update, char *devname, ++ int verbose, int uuid_set, char *homehost) + { + /* For 'assemble' and 'force' we need to return non-zero if any + * change was made. For others, the return value is ignored. +@@ -3930,7 +3930,7 @@ static int update_super_imsm(struct supertype *st, struct mdinfo *info, + + mpb = super->anchor; + +- switch (map_name(update_options, update)) { ++ switch (update) { + case UOPT_UUID: + /* We take this to mean that the family_num should be updated. + * However that is much smaller than the uuid so we cannot really +@@ -6538,7 +6538,7 @@ static int validate_ppl_imsm(struct supertype *st, struct mdinfo *info, + if (mdmon_running(st->container_devnm)) + st->update_tail = &st->updates; + +- if (st->ss->update_subarray(st, subarray, "ppl", NULL)) { ++ if (st->ss->update_subarray(st, subarray, UOPT_PPL, NULL)) { + pr_err("Failed to update subarray %s\n", + subarray); + } else { +@@ -7916,13 +7916,13 @@ static int get_rwh_policy_from_update(enum update_opt update) + } + + static int update_subarray_imsm(struct supertype *st, char *subarray, +- char *update, struct mddev_ident *ident) ++ enum update_opt update, struct mddev_ident *ident) + { + /* update the subarray currently referenced by ->current_vol */ + struct intel_super *super = st->sb; + struct imsm_super *mpb = super->anchor; + +- if (map_name(update_options, update) == UOPT_NAME) { ++ if (update == UOPT_NAME) { + char *name = ident->name; + char *ep; + int vol; +@@ -7956,7 +7956,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + } + super->updates_pending++; + } +- } else if (get_rwh_policy_from_update(map_name(update_options, update)) != UOPT_UNDEFINED) { ++ } else if (get_rwh_policy_from_update(update) != UOPT_UNDEFINED) { + int new_policy; + char *ep; + int vol = strtoul(subarray, &ep, 10); +@@ -7964,7 +7964,7 @@ static int update_subarray_imsm(struct supertype *st, char *subarray, + if (*ep != '\0' || vol >= super->anchor->num_raid_devs) + return 2; + +- new_policy = get_rwh_policy_from_update(map_name(update_options, update)); ++ new_policy = get_rwh_policy_from_update(update); + + if (st->update_tail) { + struct imsm_update_rwh_policy *u = xmalloc(sizeof(*u)); +diff --git a/super0.c b/super0.c +index d9f5bff..a7c5f81 100644 +--- a/super0.c ++++ b/super0.c +@@ -491,7 +491,7 @@ static struct mdinfo *container_content0(struct supertype *st, char *subarray) + } + + static int update_super0(struct supertype *st, struct mdinfo *info, +- char *update, ++ enum update_opt update, + char *devname, int verbose, + int uuid_set, char *homehost) + { +@@ -502,20 +502,19 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + int rv = 0; + int uuid[4]; + mdp_super_t *sb = st->sb; +- enum update_opt update_enum = map_name(update_options, update); + +- if (update_enum == UOPT_HOMEHOST && homehost) { ++ if (update == UOPT_HOMEHOST && homehost) { + /* + * note that 'homehost' is special as it is really + * a "uuid" update. + */ + uuid_set = 0; +- update_enum = UOPT_UUID; ++ update = UOPT_UUID; + info->uuid[0] = sb->set_uuid0; + info->uuid[1] = sb->set_uuid1; + } + +- switch (update_enum) { ++ switch (update) { + case UOPT_UUID: + if (!uuid_set && homehost) { + char buf[20]; +diff --git a/super1.c b/super1.c +index b0a9701..f702032 100644 +--- a/super1.c ++++ b/super1.c +@@ -1208,7 +1208,7 @@ static struct mdinfo *container_content1(struct supertype *st, char *subarray) + } + + static int update_super1(struct supertype *st, struct mdinfo *info, +- char *update, char *devname, int verbose, ++ enum update_opt update, char *devname, int verbose, + int uuid_set, char *homehost) + { + /* NOTE: for 'assemble' and 'force' we need to return non-zero +@@ -1218,15 +1218,14 @@ 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); +- enum update_opt update_enum = map_name(update_options, update); + +- if (update_enum == UOPT_HOMEHOST && homehost) { ++ if (update == UOPT_HOMEHOST && homehost) { + /* + * Note that 'homehost' is special as it is really + * a "name" update. + */ + char *c; +- update_enum = UOPT_NAME; ++ update = UOPT_NAME; + c = strchr(sb->set_name, ':'); + if (c) + snprintf(info->name, sizeof(info->name), "%s", c+1); +@@ -1234,7 +1233,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + snprintf(info->name, sizeof(info->name), "%s", sb->set_name); + } + +- switch (update_enum) { ++ switch (update) { + case UOPT_NAME: { + int namelen; + +@@ -1534,7 +1533,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + * If that couldn't happen, the "-nobackup" version + * will be used. + */ +- if (update_enum == UOPT_SPEC_REVERT_RESHAPE_NOBACKUP && ++ if (update == UOPT_SPEC_REVERT_RESHAPE_NOBACKUP && + sb->reshape_position == 0 && + (__le32_to_cpu(sb->delta_disks) > 0 || + (__le32_to_cpu(sb->delta_disks) == 0 && +@@ -1618,14 +1617,14 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + case UOPT_LAYOUT_UNSPECIFIED: + if (__le32_to_cpu(sb->level) != 0) { + pr_err("%s: %s only supported for RAID0\n", +- devname ?: "", map_num(update_options, update_enum)); ++ devname ?: "", map_num(update_options, update)); + rv = -1; +- } else if (update_enum == UOPT_LAYOUT_UNSPECIFIED) { ++ } else if (update == UOPT_LAYOUT_UNSPECIFIED) { + sb->feature_map &= ~__cpu_to_le32(MD_FEATURE_RAID0_LAYOUT); + sb->layout = 0; + } else { + sb->feature_map |= __cpu_to_le32(MD_FEATURE_RAID0_LAYOUT); +- sb->layout = __cpu_to_le32(update_enum == UOPT_LAYOUT_ORIGINAL ? 1 : 2); ++ sb->layout = __cpu_to_le32(update == UOPT_LAYOUT_ORIGINAL ? 1 : 2); + } + break; + default: +-- +2.35.3 + diff --git a/0075-Manage-Incremental-code-refactor-string-to-enum.patch b/0075-Manage-Incremental-code-refactor-string-to-enum.patch new file mode 100644 index 0000000..30a09e8 --- /dev/null +++ b/0075-Manage-Incremental-code-refactor-string-to-enum.patch @@ -0,0 +1,279 @@ +From f2e8393bd7223c419aaa33c45feeb5c75440b986 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:23 +0100 +Subject: [PATCH] Manage&Incremental: code refactor, string to enum + +Prepare Manage and Incremental for later changing context->update to enum. +Change update from string to enum in multiple functions and pass enum +where already possible. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Grow.c | 8 ++++---- + Incremental.c | 8 ++++---- + Manage.c | 35 +++++++++++++++++------------------ + mdadm.c | 23 ++++++++++++++++++----- + mdadm.h | 4 ++-- + 5 files changed, 45 insertions(+), 33 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 82d5d2e..8f5cf07 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -605,12 +605,12 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + } + + if (subarray) { +- char *update; ++ enum update_opt update; + + if (s->consistency_policy == CONSISTENCY_POLICY_PPL) +- update = "ppl"; ++ update = UOPT_PPL; + else +- update = "no-ppl"; ++ update = UOPT_NO_PPL; + + sprintf(container_dev, "/dev/%s", st->container_devnm); + +@@ -3243,7 +3243,7 @@ static int reshape_array(char *container, int fd, char *devname, + * level and frozen, we can safely add them. + */ + if (devlist) { +- if (Manage_subdevs(devname, fd, devlist, verbose, 0, NULL, 0)) ++ if (Manage_subdevs(devname, fd, devlist, verbose, 0, UOPT_UNDEFINED, 0)) + goto release; + } + +diff --git a/Incremental.c b/Incremental.c +index 5a5f4c4..ff3548c 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1025,7 +1025,7 @@ static int array_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + close(dfd); + *dfdp = -1; + rv = Manage_subdevs(chosen->sys_name, mdfd, &devlist, +- -1, 0, NULL, 0); ++ -1, 0, UOPT_UNDEFINED, 0); + close(mdfd); + } + if (verbose > 0) { +@@ -1666,7 +1666,7 @@ static void remove_from_member_array(struct mdstat_ent *memb, + + if (subfd >= 0) { + rv = Manage_subdevs(memb->devnm, subfd, devlist, verbose, +- 0, NULL, 0); ++ 0, UOPT_UNDEFINED, 0); + if (rv & 2) { + if (sysfs_init(&mmdi, -1, memb->devnm)) + pr_err("unable to initialize sysfs for: %s\n", +@@ -1758,7 +1758,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + free_mdstat(mdstat); + } else { + rv |= Manage_subdevs(ent->devnm, mdfd, &devlist, +- verbose, 0, NULL, 0); ++ verbose, 0, UOPT_UNDEFINED, 0); + if (rv & 2) { + /* Failed due to EBUSY, try to stop the array. + * Give udisks a chance to unmount it first. +@@ -1770,7 +1770,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + + devlist.disposition = 'r'; + rv = Manage_subdevs(ent->devnm, mdfd, &devlist, +- verbose, 0, NULL, 0); ++ verbose, 0, UOPT_UNDEFINED, 0); + end: + close(mdfd); + free_mdstat(ent); +diff --git a/Manage.c b/Manage.c +index 87b8aa0..594e3d2 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -598,14 +598,12 @@ static void add_set(struct mddev_dev *dv, int fd, char set_char) + + int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, + struct supertype *dev_st, struct supertype *tst, +- unsigned long rdev, +- char *update, char *devname, int verbose, +- mdu_array_info_t *array) ++ unsigned long rdev, enum update_opt update, ++ char *devname, int verbose, mdu_array_info_t *array) + { + struct mdinfo mdi; + int duuid[4]; + int ouuid[4]; +- enum update_opt update_enum = map_name(update_options, update); + + dev_st->ss->getinfo_super(dev_st, &mdi, NULL); + dev_st->ss->uuid_from_super(dev_st, ouuid); +@@ -683,7 +681,7 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, + devname, verbose, 0, NULL); + if (update) + rv = dev_st->ss->update_super( +- dev_st, NULL, update_enum, ++ dev_st, NULL, update, + devname, verbose, 0, NULL); + if (rv == 0) + rv = dev_st->ss->store_super(dev_st, tfd); +@@ -715,8 +713,8 @@ skip_re_add: + int Manage_add(int fd, int tfd, struct mddev_dev *dv, + struct supertype *tst, mdu_array_info_t *array, + int force, int verbose, char *devname, +- char *update, unsigned long rdev, unsigned long long array_size, +- int raid_slot) ++ enum update_opt update, unsigned long rdev, ++ unsigned long long array_size, int raid_slot) + { + unsigned long long ldsize; + struct supertype *dev_st; +@@ -1332,7 +1330,7 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const + + int Manage_subdevs(char *devname, int fd, + struct mddev_dev *devlist, int verbose, int test, +- char *update, int force) ++ enum update_opt update, int force) + { + /* Do something to each dev. + * devmode can be +@@ -1727,12 +1725,13 @@ int autodetect(void) + return rv; + } + +-int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int verbose) ++int Update_subarray(char *dev, char *subarray, enum update_opt update, ++ struct mddev_ident *ident, int verbose) + { + struct supertype supertype, *st = &supertype; + int fd, rv = 2; + struct mdinfo *info = NULL; +- enum update_opt update_enum = map_name(update_options, update); ++ char *update_verb = map_num(update_options, update); + + memset(st, 0, sizeof(*st)); + +@@ -1750,7 +1749,7 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + if (is_subarray_active(subarray, st->devnm)) { + if (verbose >= 0) + pr_err("Subarray %s in %s is active, cannot update %s\n", +- subarray, dev, update); ++ subarray, dev, update_verb); + goto free_super; + } + +@@ -1759,23 +1758,23 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + + info = st->ss->container_content(st, subarray); + +- if (strncmp(update, "ppl", 3) == 0 && !is_level456(info->array.level)) { ++ if (update == UOPT_PPL && !is_level456(info->array.level)) { + pr_err("RWH policy ppl is supported only for raid4, raid5 and raid6.\n"); + goto free_super; + } + +- rv = st->ss->update_subarray(st, subarray, update_enum, ident); ++ rv = st->ss->update_subarray(st, subarray, update, ident); + + if (rv) { + if (verbose >= 0) + pr_err("Failed to update %s of subarray-%s in %s\n", +- update, subarray, dev); ++ update_verb, subarray, dev); + } else if (st->update_tail) + flush_metadata_updates(st); + else + st->ss->sync_metadata(st); + +- if (rv == 0 && strcmp(update, "name") == 0 && verbose >= 0) ++ if (rv == 0 && update == UOPT_NAME && verbose >= 0) + pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n", + subarray, dev); + +@@ -1816,10 +1815,10 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + sprintf(devname, "%d:%d", major(devid), minor(devid)); + + devlist.disposition = 'r'; +- if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, NULL, 0) == 0) { ++ if (Manage_subdevs(from_devname, fd2, &devlist, -1, 0, UOPT_UNDEFINED, 0) == 0) { + devlist.disposition = 'a'; + if (Manage_subdevs(to_devname, fd1, &devlist, -1, 0, +- NULL, 0) == 0) { ++ UOPT_UNDEFINED, 0) == 0) { + /* make sure manager is aware of changes */ + ping_manager(to_devname); + ping_manager(from_devname); +@@ -1829,7 +1828,7 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + } + else + Manage_subdevs(from_devname, fd2, &devlist, +- -1, 0, NULL, 0); ++ -1, 0, UOPT_UNDEFINED, 0); + } + close(fd1); + close(fd2); +diff --git a/mdadm.c b/mdadm.c +index f5f505f..d06e282 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1402,10 +1402,22 @@ int main(int argc, char *argv[]) + /* readonly, add/remove, readwrite, runstop */ + if (c.readonly > 0) + rv = Manage_ro(devlist->devname, mdfd, c.readonly); +- if (!rv && devs_found>1) +- rv = Manage_subdevs(devlist->devname, mdfd, +- devlist->next, c.verbose, c.test, +- c.update, c.force); ++ if (!rv && devs_found > 1) { ++ /* ++ * This is temporary and will be removed in next patches ++ * Null c.update will cause segfault ++ */ ++ if (c.update) ++ rv = Manage_subdevs(devlist->devname, mdfd, ++ devlist->next, c.verbose, c.test, ++ map_name(update_options, c.update), ++ c.force); ++ else ++ rv = Manage_subdevs(devlist->devname, mdfd, ++ devlist->next, c.verbose, c.test, ++ UOPT_UNDEFINED, ++ c.force); ++ } + if (!rv && c.readonly < 0) + rv = Manage_ro(devlist->devname, mdfd, c.readonly); + if (!rv && c.runstop > 0) +@@ -1931,7 +1943,8 @@ static int misc_list(struct mddev_dev *devlist, + continue; + } + rv |= Update_subarray(dv->devname, c->subarray, +- c->update, ident, c->verbose); ++ map_name(update_options, c->update), ++ ident, c->verbose); + continue; + case Dump: + rv |= Dump_metadata(dv->devname, dump_directory, c, ss); +diff --git a/mdadm.h b/mdadm.h +index 5dc9439..924f4b6 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1478,7 +1478,7 @@ extern int Manage_stop(char *devname, int fd, int quiet, + int will_retry); + extern int Manage_subdevs(char *devname, int fd, + struct mddev_dev *devlist, int verbose, int test, +- char *update, int force); ++ enum update_opt update, int force); + extern int autodetect(void); + extern int Grow_Add_device(char *devname, int fd, char *newdev); + extern int Grow_addbitmap(char *devname, int fd, +@@ -1532,7 +1532,7 @@ extern int Monitor(struct mddev_dev *devlist, + + extern int Kill(char *dev, struct supertype *st, int force, int verbose, int noexcl); + extern int Kill_subarray(char *dev, char *subarray, int verbose); +-extern int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident *ident, int quiet); ++extern int Update_subarray(char *dev, char *subarray, enum update_opt update, struct mddev_ident *ident, int quiet); + extern int Wait(char *dev); + extern int WaitClean(char *dev, int verbose); + extern int SetAction(char *dev, char *action); +-- +2.35.3 + diff --git a/0076-Change-char-to-enum-in-context-update-refactor-code.patch b/0076-Change-char-to-enum-in-context-update-refactor-code.patch new file mode 100644 index 0000000..d5af825 --- /dev/null +++ b/0076-Change-char-to-enum-in-context-update-refactor-code.patch @@ -0,0 +1,289 @@ +From 3a87fa67112dc2c2c3664aeecd0b49cb4b6ceaa9 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:24 +0100 +Subject: [PATCH] Change char* to enum in context->update & refactor code + +Storing update option in string is bad for frequent comparisons and +error prone. +Replace char array with enum so already existing enum is passed around +instead of string. +Adapt code to changes. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Assemble.c | 40 +++++++++++++++++----------------------- + mdadm.c | 52 +++++++++++++++++++--------------------------------- + mdadm.h | 2 +- + 3 files changed, 37 insertions(+), 57 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index dba910c..4980494 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -135,17 +135,17 @@ static int ident_matches(struct mddev_ident *ident, + struct mdinfo *content, + struct supertype *tst, + char *homehost, int require_homehost, +- char *update, char *devname) ++ enum update_opt update, char *devname) + { + +- if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) && ++ if (ident->uuid_set && update != UOPT_UUID && + same_uuid(content->uuid, ident->uuid, tst->ss->swapuuid)==0 && + memcmp(content->uuid, uuid_zero, sizeof(int[4])) != 0) { + if (devname) + pr_err("%s has wrong uuid.\n", devname); + return 0; + } +- if (ident->name[0] && (!update || strcmp(update, "name")!= 0) && ++ if (ident->name[0] && update != UOPT_NAME && + name_matches(content->name, ident->name, homehost, require_homehost)==0) { + if (devname) + pr_err("%s has wrong name.\n", devname); +@@ -648,11 +648,10 @@ static int load_devices(struct devs *devices, char *devmap, + int err; + fstat(mdfd, &stb2); + +- if (strcmp(c->update, "uuid") == 0 && !ident->uuid_set) ++ if (c->update == UOPT_UUID && !ident->uuid_set) + random_uuid((__u8 *)ident->uuid); + +- if (strcmp(c->update, "ppl") == 0 && +- ident->bitmap_fd >= 0) { ++ if (c->update == UOPT_PPL && ident->bitmap_fd >= 0) { + pr_err("PPL is not compatible with bitmap\n"); + close(mdfd); + free(devices); +@@ -684,34 +683,30 @@ static int load_devices(struct devs *devices, char *devmap, + strcpy(content->name, ident->name); + content->array.md_minor = minor(stb2.st_rdev); + +- if (strcmp(c->update, "byteorder") == 0) ++ if (c->update == UOPT_BYTEORDER) + err = 0; +- else if (strcmp(c->update, "home-cluster") == 0) { ++ else if (c->update == UOPT_HOME_CLUSTER) { + tst->cluster_name = c->homecluster; + err = tst->ss->write_bitmap(tst, dfd, NameUpdate); +- } else if (strcmp(c->update, "nodes") == 0) { ++ } else if (c->update == UOPT_NODES) { + tst->nodes = c->nodes; + err = tst->ss->write_bitmap(tst, dfd, NodeNumUpdate); +- } else if (strcmp(c->update, "revert-reshape") == 0 && +- c->invalid_backup) ++ } else if (c->update == UOPT_REVERT_RESHAPE && c->invalid_backup) + err = tst->ss->update_super(tst, content, + UOPT_SPEC_REVERT_RESHAPE_NOBACKUP, + devname, c->verbose, + ident->uuid_set, + c->homehost); + else +- /* +- * Mapping is temporary, will be removed in this patchset +- */ + err = tst->ss->update_super(tst, content, +- map_name(update_options, c->update), ++ c->update, + devname, c->verbose, + ident->uuid_set, + c->homehost); + if (err < 0) { + if (err == -1) + pr_err("--update=%s not understood for %s metadata\n", +- c->update, tst->ss->name); ++ map_num(update_options, c->update), tst->ss->name); + tst->ss->free_super(tst); + free(tst); + close(mdfd); +@@ -721,7 +716,7 @@ static int load_devices(struct devs *devices, char *devmap, + *stp = st; + return -1; + } +- if (strcmp(c->update, "uuid")==0 && ++ if (c->update == UOPT_UUID && + !ident->uuid_set) { + ident->uuid_set = 1; + memcpy(ident->uuid, content->uuid, 16); +@@ -730,7 +725,7 @@ static int load_devices(struct devs *devices, char *devmap, + pr_err("Could not re-write superblock on %s.\n", + devname); + +- if (strcmp(c->update, "uuid")==0 && ++ if (c->update == UOPT_UUID && + ident->bitmap_fd >= 0 && !bitmap_done) { + if (bitmap_update_uuid(ident->bitmap_fd, + content->uuid, +@@ -1188,8 +1183,7 @@ static int start_array(int mdfd, + pr_err("%s: Need a backup file to complete reshape of this array.\n", + mddev); + pr_err("Please provided one with \"--backup-file=...\"\n"); +- if (c->update && +- strcmp(c->update, "revert-reshape") == 0) ++ if (c->update == UOPT_REVERT_RESHAPE) + pr_err("(Don't specify --update=revert-reshape again, that part succeeded.)\n"); + return 1; + } +@@ -1487,7 +1481,7 @@ try_again: + */ + if (map_lock(&map)) + pr_err("failed to get exclusive lock on mapfile - continue anyway...\n"); +- if (c->update && strcmp(c->update,"uuid") == 0) ++ if (c->update == UOPT_UUID) + mp = NULL; + else + mp = map_by_uuid(&map, content->uuid); +@@ -1634,7 +1628,7 @@ try_again: + goto out; + } + +- if (c->update && strcmp(c->update, "byteorder")==0) ++ if (c->update == UOPT_BYTEORDER) + st->minor_version = 90; + + st->ss->getinfo_super(st, content, NULL); +@@ -1902,7 +1896,7 @@ try_again: + /* First, fill in the map, so that udev can find our name + * as soon as we become active. + */ +- if (c->update && strcmp(c->update, "metadata")==0) { ++ if (c->update == UOPT_METADATA) { + content->array.major_version = 1; + content->array.minor_version = 0; + strcpy(content->text_version, "1.0"); +diff --git a/mdadm.c b/mdadm.c +index d06e282..57e8e6f 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -724,13 +724,12 @@ int main(int argc, char *argv[]) + + case O(ASSEMBLE,'U'): /* update the superblock */ + case O(MISC,'U'): { +- enum update_opt updateopt = map_name(update_options, c.update); + enum update_opt print_mode = UOPT_HELP; + const char *error_addon = "update option"; + + if (c.update) { + pr_err("Can only update one aspect of superblock, both %s and %s given.\n", +- c.update, optarg); ++ map_num(update_options, c.update), optarg); + exit(2); + } + if (mode == MISC && !c.subarray) { +@@ -738,20 +737,20 @@ int main(int argc, char *argv[]) + exit(2); + } + +- c.update = optarg; ++ c.update = map_name(update_options, optarg); + + if (devmode == UpdateSubarray) { + print_mode = UOPT_SUBARRAY_ONLY; + error_addon = "update-subarray option"; + +- if (updateopt > UOPT_SUBARRAY_ONLY && updateopt < UOPT_HELP) +- updateopt = UOPT_UNDEFINED; ++ if (c.update > UOPT_SUBARRAY_ONLY && c.update < UOPT_HELP) ++ c.update = UOPT_UNDEFINED; + } + +- switch (updateopt) { ++ switch (c.update) { + case UOPT_UNDEFINED: + pr_err("'--update=%s' is invalid %s. ", +- c.update, error_addon); ++ optarg, error_addon); + outf = stderr; + case UOPT_HELP: + if (!outf) +@@ -776,14 +775,14 @@ int main(int argc, char *argv[]) + } + if (c.update) { + pr_err("Can only update one aspect of superblock, both %s and %s given.\n", +- c.update, optarg); ++ map_num(update_options, c.update), optarg); + exit(2); + } +- c.update = optarg; +- if (strcmp(c.update, "devicesize") != 0 && +- strcmp(c.update, "bbl") != 0 && +- strcmp(c.update, "force-no-bbl") != 0 && +- strcmp(c.update, "no-bbl") != 0) { ++ c.update = map_name(update_options, optarg); ++ if (c.update != UOPT_DEVICESIZE && ++ c.update != UOPT_BBL && ++ c.update != UOPT_NO_BBL && ++ c.update != UOPT_FORCE_NO_BBL) { + pr_err("only 'devicesize', 'bbl', 'no-bbl', and 'force-no-bbl' can be updated with --re-add\n"); + exit(2); + } +@@ -1357,7 +1356,7 @@ int main(int argc, char *argv[]) + } + } + +- if (c.update && strcmp(c.update, "nodes") == 0 && c.nodes == 0) { ++ if (c.update && c.update == UOPT_NODES && c.nodes == 0) { + pr_err("Please specify nodes number with --nodes\n"); + exit(1); + } +@@ -1402,22 +1401,10 @@ int main(int argc, char *argv[]) + /* readonly, add/remove, readwrite, runstop */ + if (c.readonly > 0) + rv = Manage_ro(devlist->devname, mdfd, c.readonly); +- if (!rv && devs_found > 1) { +- /* +- * This is temporary and will be removed in next patches +- * Null c.update will cause segfault +- */ +- if (c.update) +- rv = Manage_subdevs(devlist->devname, mdfd, +- devlist->next, c.verbose, c.test, +- map_name(update_options, c.update), +- c.force); +- else +- rv = Manage_subdevs(devlist->devname, mdfd, +- devlist->next, c.verbose, c.test, +- UOPT_UNDEFINED, +- c.force); +- } ++ if (!rv && devs_found > 1) ++ rv = Manage_subdevs(devlist->devname, mdfd, ++ devlist->next, c.verbose, ++ c.test, c.update, c.force); + if (!rv && c.readonly < 0) + rv = Manage_ro(devlist->devname, mdfd, c.readonly); + if (!rv && c.runstop > 0) +@@ -1937,14 +1924,13 @@ static int misc_list(struct mddev_dev *devlist, + rv |= Kill_subarray(dv->devname, c->subarray, c->verbose); + continue; + case UpdateSubarray: +- if (c->update == NULL) { ++ if (!c->update) { + pr_err("-U/--update must be specified with --update-subarray\n"); + rv |= 1; + continue; + } + rv |= Update_subarray(dv->devname, c->subarray, +- map_name(update_options, c->update), +- ident, c->verbose); ++ c->update, ident, c->verbose); + continue; + case Dump: + rv |= Dump_metadata(dv->devname, dump_directory, c, ss); +diff --git a/mdadm.h b/mdadm.h +index 924f4b6..13f8b4c 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -616,7 +616,7 @@ struct context { + int export; + int test; + char *subarray; +- char *update; ++ enum update_opt update; + int scan; + int SparcAdjust; + int autof; +-- +2.35.3 + diff --git a/0077-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch b/0077-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch new file mode 100644 index 0000000..2e8575a --- /dev/null +++ b/0077-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch @@ -0,0 +1,54 @@ +From 24d329fc97a64ec185ef27e59730f3f058c09029 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Thu, 5 Jan 2023 00:29:20 +0800 +Subject: [PATCH] mdadm/udev: Don't handle change event on raw devices + +The raw devices are ready when add event happpens and the raid +can be assembled. So there is no need to handle change events. +And it can cause some inconvenient problems. + +For example, the OS is installed on md0(/root) and md1(/home). +md0 and md1 are created on partitions. When it wants to re-install +OS, anaconda can't clear the storage configure. It deletes one +partition and does some jobs. The change event happens. Now +the raid device is assembled again. It can't delete the other +partitions. + +So in this patch, we don't handle change event on raw devices +anymore. + +Signed-off-by: Xiao Ni +Signed-off-by: Jes Sorensen +--- + udev-md-raid-assembly.rules | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/udev-md-raid-assembly.rules b/udev-md-raid-assembly.rules +index 39b4344..d4a7f0a 100644 +--- a/udev-md-raid-assembly.rules ++++ b/udev-md-raid-assembly.rules +@@ -11,6 +11,11 @@ SUBSYSTEM!="block", GOTO="md_inc_end" + ENV{SYSTEMD_READY}=="0", GOTO="md_inc_end" + + # handle potential components of arrays (the ones supported by md) ++# For member devices which are md/dm devices, we don't need to ++# handle add event. Because md/dm devices need to do some init jobs. ++# Then the change event happens. ++# When adding md/dm devices, ID_FS_TYPE can only be linux_raid_member ++# after change event happens. + ENV{ID_FS_TYPE}=="linux_raid_member", GOTO="md_inc" + + # "noiswmd" on kernel command line stops mdadm from handling +@@ -28,6 +33,9 @@ GOTO="md_inc_end" + + LABEL="md_inc" + ++# Bare disks are ready when add event happens, the raid can be assembled. ++ACTION=="change", KERNEL!="dm-*|md*", GOTO="md_inc_end" ++ + # remember you can limit what gets auto/incrementally assembled by + # mdadm.conf(5)'s 'AUTO' and selectively whitelist using 'ARRAY' + ACTION!="remove", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}" +-- +2.35.3 + diff --git a/0078-Manage-do-not-check-array-state-when-drive-is-remove.patch b/0078-Manage-do-not-check-array-state-when-drive-is-remove.patch new file mode 100644 index 0000000..2987a01 --- /dev/null +++ b/0078-Manage-do-not-check-array-state-when-drive-is-remove.patch @@ -0,0 +1,33 @@ +From b3e7b7eb1dfedd7cbd9a3800e884941f67d94c96 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Tue, 27 Dec 2022 06:50:42 +0100 +Subject: [PATCH] Manage: do not check array state when drive is removed + +Array state doesn't need to be checked when drive is +removed, but until now clean state was required. Result +of the is_remove_safe() function will be independent +from array state. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Manage.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 594e3d2..4d6e54b 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1321,8 +1321,7 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const + sysfs_free(mdi); + + bool is_enough = enough(array->level, array->raid_disks, +- array->layout, (array->state & 1), +- avail); ++ array->layout, 1, avail); + + free(avail); + return is_enough; +-- +2.35.3 + diff --git a/0079-incremental-manage-do-not-verify-if-remove-is-safe.patch b/0079-incremental-manage-do-not-verify-if-remove-is-safe.patch new file mode 100644 index 0000000..e4452fa --- /dev/null +++ b/0079-incremental-manage-do-not-verify-if-remove-is-safe.patch @@ -0,0 +1,59 @@ +From 461fae7e7809670d286cc19aac5bfa861c29f93a Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Tue, 27 Dec 2022 06:50:43 +0100 +Subject: [PATCH] incremental, manage: do not verify if remove is safe + +Function is_remove_safe() was introduced to verify if removing +member device won't cause failed state of the array. This +verification should be used only with set-faulty command. Add +special mode indicating that Incremental removal was executed. +If this mode is used do not execute is_remove_safe() routine. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Incremental.c | 2 +- + Manage.c | 7 ++++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index ff3548c..09b94b9 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1744,7 +1744,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + + memset(&devlist, 0, sizeof(devlist)); + devlist.devname = devname; +- devlist.disposition = 'f'; ++ devlist.disposition = 'I'; + /* for a container, we must fail each member array */ + if (ent->metadata_version && + strncmp(ent->metadata_version, "external:", 9) == 0) { +diff --git a/Manage.c b/Manage.c +index 4d6e54b..6184d3f 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1494,8 +1494,9 @@ int Manage_subdevs(char *devname, int fd, + /* Assume this is a kernel-internal name like 'sda1' */ + int found = 0; + char dname[55]; +- if (dv->disposition != 'r' && dv->disposition != 'f') { +- pr_err("%s only meaningful with -r or -f, not -%c\n", ++ if (dv->disposition != 'r' && dv->disposition != 'f' && ++ dv->disposition != 'I') { ++ pr_err("%s only meaningful with -r, -f or -I, not -%c\n", + dv->devname, dv->disposition); + goto abort; + } +@@ -1647,7 +1648,7 @@ int Manage_subdevs(char *devname, int fd, + close(sysfd); + goto abort; + } +- ++ case 'I': /* incremental fail */ + if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) || + (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY, + rdev))) { +-- +2.35.3 + diff --git a/0080-super-intel-make-freesize-not-required-for-chunk-siz.patch b/0080-super-intel-make-freesize-not-required-for-chunk-siz.patch new file mode 100644 index 0000000..793594d --- /dev/null +++ b/0080-super-intel-make-freesize-not-required-for-chunk-siz.patch @@ -0,0 +1,52 @@ +From 071f839ea549e2a384cd13bba445245cd87e48b1 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Fri, 28 Oct 2022 04:51:17 +0200 +Subject: [PATCH] super-intel: make freesize not required for chunk size + migration + +Freesize is needed to be set for migrations where size of RAID could +be changed - expand. It tells how many free space is determined for +members. In chunk size migartion freesize is not needed to be set, +pointer shouldn't be checked if exists. This commit moves check to +condition which contains size calculations, instead of checking it +always at the first step. +Fix return value when superblock is not set. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + super-intel.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 1f5f6ed..89fac62 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7719,11 +7719,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + struct intel_super *super = st->sb; + + /* +- * Autolayout mode, st->sb and freesize must be set. ++ * Autolayout mode, st->sb must be set. + */ +- if (!super || !freesize) { +- pr_vrb("freesize and superblock must be set for autolayout, aborting\n"); +- return 1; ++ if (!super) { ++ pr_vrb("superblock must be set for autolayout, aborting\n"); ++ return 0; + } + + if (!validate_geometry_imsm_orom(st->sb, level, layout, +@@ -7731,7 +7731,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + verbose)) + return 0; + +- if (super->orom) { ++ if (super->orom && freesize) { + imsm_status_t rv; + int count = count_volumes(super->hba, super->orom->dpa, + verbose); +-- +2.35.3 + diff --git a/0081-manage-move-comment-with-function-description.patch b/0081-manage-move-comment-with-function-description.patch new file mode 100644 index 0000000..d8b6869 --- /dev/null +++ b/0081-manage-move-comment-with-function-description.patch @@ -0,0 +1,105 @@ +From 36a707824eb1dafbb990f5daf1cbbe0e37dbbefb Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Thu, 5 Jan 2023 06:31:25 +0100 +Subject: [PATCH] manage: move comment with function description + +Move the function description from the function body to outside +to obey kernel coding style. + +Signed-off-by: Kinga Tanska +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Manage.c | 72 ++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 44 insertions(+), 28 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 6184d3f..fde6aba 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1327,38 +1327,54 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const + return is_enough; + } + ++/** ++ * Manage_subdevs() - Execute operation depending on devmode. ++ * ++ * @devname: name of the device. ++ * @fd: file descriptor. ++ * @devlist: list of sub-devices to manage. ++ * @verbose: verbose level. ++ * @test: test flag. ++ * @update: type of update. ++ * @force: force flag. ++ * ++ * This function executes operation defined by devmode ++ * for each dev from devlist. ++ * Devmode can be: ++ * 'a' - add the device ++ * 'S' - add the device as a spare - don't try re-add ++ * 'j' - add the device as a journal device ++ * 'A' - re-add the device ++ * 'r' - remove the device: HOT_REMOVE_DISK ++ * device can be 'faulty' or 'detached' in which case all ++ * matching devices are removed. ++ * 'f' - set the device faulty SET_DISK_FAULTY ++ * device can be 'detached' in which case any device that ++ * is inaccessible will be marked faulty. ++ * 'I' - remove device by using incremental fail ++ * which is executed when device is removed surprisingly. ++ * 'R' - mark this device as wanting replacement. ++ * 'W' - this device is added if necessary and activated as ++ * a replacement for a previous 'R' device. ++ * ----- ++ * 'w' - 'W' will be changed to 'w' when it is paired with ++ * a 'R' device. If a 'W' is found while walking the list ++ * it must be unpaired, and is an error. ++ * 'M' - this is created by a 'missing' target. It is a slight ++ * variant on 'A' ++ * 'F' - Another variant of 'A', where the device was faulty ++ * so must be removed from the array first. ++ * 'c' - confirm the device as found (for clustered environments) ++ * ++ * For 'f' and 'r', the device can also be a kernel-internal ++ * name such as 'sdb'. ++ * ++ * Return: 0 on success, otherwise 1 or 2. ++ */ + int Manage_subdevs(char *devname, int fd, + struct mddev_dev *devlist, int verbose, int test, + enum update_opt update, int force) + { +- /* Do something to each dev. +- * devmode can be +- * 'a' - add the device +- * 'S' - add the device as a spare - don't try re-add +- * 'j' - add the device as a journal device +- * 'A' - re-add the device +- * 'r' - remove the device: HOT_REMOVE_DISK +- * device can be 'faulty' or 'detached' in which case all +- * matching devices are removed. +- * 'f' - set the device faulty SET_DISK_FAULTY +- * device can be 'detached' in which case any device that +- * is inaccessible will be marked faulty. +- * 'R' - mark this device as wanting replacement. +- * 'W' - this device is added if necessary and activated as +- * a replacement for a previous 'R' device. +- * ----- +- * 'w' - 'W' will be changed to 'w' when it is paired with +- * a 'R' device. If a 'W' is found while walking the list +- * it must be unpaired, and is an error. +- * 'M' - this is created by a 'missing' target. It is a slight +- * variant on 'A' +- * 'F' - Another variant of 'A', where the device was faulty +- * so must be removed from the array first. +- * 'c' - confirm the device as found (for clustered environments) +- * +- * For 'f' and 'r', the device can also be a kernel-internal +- * name such as 'sdb'. +- */ + mdu_array_info_t array; + unsigned long long array_size; + struct mddev_dev *dv; +-- +2.35.3 + diff --git a/0082-Fix-NULL-dereference-in-super_by_fd.patch b/0082-Fix-NULL-dereference-in-super_by_fd.patch new file mode 100644 index 0000000..636e316 --- /dev/null +++ b/0082-Fix-NULL-dereference-in-super_by_fd.patch @@ -0,0 +1,76 @@ +From f1f3ef7d2de5e3a726c27b9f9bb20e270a100dab Mon Sep 17 00:00:00 2001 +From: Li Xiao Keng +Date: Mon, 27 Feb 2023 11:12:07 +0800 +Subject: [PATCH] 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=, __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=, ss=, dump_directory=, ident=, devlist=) at mdadm.c:1959 +#6 main (argc=, argv=) at mdadm.c:1629 + +The direct cause is fd2devnm returning NULL, so add a check. + +Signed-off-by: Li Xiao Keng +Signed-off-by: Wu Guang Hao +Acked-by: Coly Li +Acked-by: Coly Li > +Signed-off-by: Jes Sorensen +--- + mapfile.c | 4 ++++ + util.c | 7 ++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/mapfile.c b/mapfile.c +index 6b2207d..ac35176 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 9cd89fa..8c7f3fd 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.35.3 + diff --git a/0083-Mdmonitor-Make-alert_info-global.patch b/0083-Mdmonitor-Make-alert_info-global.patch new file mode 100644 index 0000000..95df074 --- /dev/null +++ b/0083-Mdmonitor-Make-alert_info-global.patch @@ -0,0 +1,369 @@ +From b301516615c441bd3cc4b512fae73fc066d227f1 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 2 Feb 2023 12:26:59 +0100 +Subject: [PATCH] Mdmonitor: Make alert_info global + +Move information about --test flag and hostname into alert_info. + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + Monitor.c | 124 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 61 insertions(+), 63 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 188cb8b..9ef4dab 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 \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.35.3 + diff --git a/0084-Mdmonitor-Pass-events-to-alert-using-enums-instead-o.patch b/0084-Mdmonitor-Pass-events-to-alert-using-enums-instead-o.patch new file mode 100644 index 0000000..a07227f --- /dev/null +++ b/0084-Mdmonitor-Pass-events-to-alert-using-enums-instead-o.patch @@ -0,0 +1,313 @@ +From 50232a6ec4a5c46c608181d72d0c633831a03134 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 2 Feb 2023 12:27:00 +0100 +Subject: [PATCH] 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 +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Monitor.c | 136 +++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 83 insertions(+), 53 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 9ef4dab..029e9ef 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -32,6 +32,8 @@ + #include + #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 \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.35.3 + diff --git a/0085-Mdmonitor-Add-helper-functions.patch b/0085-Mdmonitor-Add-helper-functions.patch new file mode 100644 index 0000000..7e34b70 --- /dev/null +++ b/0085-Mdmonitor-Add-helper-functions.patch @@ -0,0 +1,406 @@ +From cc3df167c599d2ee0c132149c86fc0ad70d9f14e Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 2 Feb 2023 12:27:01 +0100 +Subject: [PATCH] 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 +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Monitor.c | 228 +++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 158 insertions(+), 70 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 029e9ef..39598ba 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 \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.35.3 + diff --git a/0086-Add-helpers-to-determine-whether-directories-or-file.patch b/0086-Add-helpers-to-determine-whether-directories-or-file.patch new file mode 100644 index 0000000..359150b --- /dev/null +++ b/0086-Add-helpers-to-determine-whether-directories-or-file.patch @@ -0,0 +1,83 @@ +From ee9dcf9549e8cbfeb51123812776cc87016c95b0 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 2 Feb 2023 12:27:02 +0100 +Subject: [PATCH] Add helpers to determine whether directories or files are + soft links + +Signed-off-by: Mateusz Grzonka +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + mdadm.h | 2 ++ + util.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+) + +diff --git a/mdadm.h b/mdadm.h +index 13f8b4c..1674ce1 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 8c7f3fd..7fc881b 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.35.3 + diff --git a/0087-Mdmonitor-Refactor-write_autorebuild_pid.patch b/0087-Mdmonitor-Refactor-write_autorebuild_pid.patch new file mode 100644 index 0000000..ddcc0d3 --- /dev/null +++ b/0087-Mdmonitor-Refactor-write_autorebuild_pid.patch @@ -0,0 +1,110 @@ +From b6a84d4e92f876acd120d3062a8302db5dd2498c Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 2 Feb 2023 12:27:03 +0100 +Subject: [PATCH] Mdmonitor: Refactor write_autorebuild_pid() + +Add better error handling and check for symlinks when opening MDMON_DIR. + +Signed-off-by: Mateusz Grzonka +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Monitor.c | 55 ++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 36 insertions(+), 19 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 39598ba..14a2dfe 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.35.3 + diff --git a/0088-Mdmonitor-Refactor-check_one_sharer-for-better-error.patch b/0088-Mdmonitor-Refactor-check_one_sharer-for-better-error.patch new file mode 100644 index 0000000..c1976b7 --- /dev/null +++ b/0088-Mdmonitor-Refactor-check_one_sharer-for-better-error.patch @@ -0,0 +1,139 @@ +From 0a07dea8d3b78a22a59f4604a5e8da15690f28e3 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 2 Feb 2023 12:27:04 +0100 +Subject: [PATCH] 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 +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Monitor.c | 89 ++++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 62 insertions(+), 27 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 14a2dfe..4491818 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -32,6 +32,7 @@ + #include + #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.35.3 + diff --git a/0089-util.c-reorder-code-lines-in-parse_layout_faulty.patch b/0089-util.c-reorder-code-lines-in-parse_layout_faulty.patch new file mode 100644 index 0000000..36fa926 --- /dev/null +++ b/0089-util.c-reorder-code-lines-in-parse_layout_faulty.patch @@ -0,0 +1,41 @@ +From a0151041642dffff2421c22e18fb7b02b58787d9 Mon Sep 17 00:00:00 2001 +From: Coly Li +Date: Sat, 4 Mar 2023 00:21:30 +0800 +Subject: [PATCH] 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 +Reviewed-by: Paul Menzel +Signed-off-by: Jes Sorensen +--- + util.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/util.c b/util.c +index 7fc881b..b0b7aec 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.35.3 + diff --git a/0090-util.c-fix-memleak-in-parse_layout_faulty.patch b/0090-util.c-fix-memleak-in-parse_layout_faulty.patch new file mode 100644 index 0000000..bf02436 --- /dev/null +++ b/0090-util.c-fix-memleak-in-parse_layout_faulty.patch @@ -0,0 +1,32 @@ +From 06ef619582b47af89eb094c164fc5effd46d6048 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Sat, 4 Mar 2023 00:21:31 +0800 +Subject: [PATCH] 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 +Acked-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + util.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util.c b/util.c +index b0b7aec..9f1e1f7 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.35.3 + diff --git a/0091-Detail.c-fix-memleak-in-Detail.patch b/0091-Detail.c-fix-memleak-in-Detail.patch new file mode 100644 index 0000000..7f68d7a --- /dev/null +++ b/0091-Detail.c-fix-memleak-in-Detail.patch @@ -0,0 +1,31 @@ +From dac0b5121dd77bf1659b95248423445f932dfae4 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Sat, 4 Mar 2023 00:21:32 +0800 +Subject: [PATCH] Detail.c: fix memleak in Detail() + +char *sysdev = xstrdup() but not free() in for loop, will cause memory +leak + +Signed-off-by: Wu Guanghao +Acked-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Detail.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Detail.c b/Detail.c +index ce7a844..4ef2646 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.35.3 + diff --git a/0092-isuper-intel.c-fix-double-free-in-load_imsm_mpb.patch b/0092-isuper-intel.c-fix-double-free-in-load_imsm_mpb.patch new file mode 100644 index 0000000..0278264 --- /dev/null +++ b/0092-isuper-intel.c-fix-double-free-in-load_imsm_mpb.patch @@ -0,0 +1,63 @@ +From 50cd06b484bb99bfacdd4f9d2f8ee5e52bfc7bd3 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Sat, 4 Mar 2023 00:21:33 +0800 +Subject: [PATCH] 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 +Reviewed-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + super-intel.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/super-intel.c b/super-intel.c +index 89fac62..4a3da84 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.35.3 + diff --git a/0093-super-intel.c-fix-memleak-in-find_disk_attached_hba.patch b/0093-super-intel.c-fix-memleak-in-find_disk_attached_hba.patch new file mode 100644 index 0000000..a1a868c --- /dev/null +++ b/0093-super-intel.c-fix-memleak-in-find_disk_attached_hba.patch @@ -0,0 +1,38 @@ +From 5d2434d18b6bc71bd16678b1a6d1cc3a92f1d415 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Sat, 4 Mar 2023 00:21:34 +0800 +Subject: [PATCH] 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 +Reviewed-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + super-intel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 4a3da84..e155a8a 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.35.3 + diff --git a/0094-super-ddf.c-fix-memleak-in-get_vd_num_of_subarray.patch b/0094-super-ddf.c-fix-memleak-in-get_vd_num_of_subarray.patch new file mode 100644 index 0000000..009223b --- /dev/null +++ b/0094-super-ddf.c-fix-memleak-in-get_vd_num_of_subarray.patch @@ -0,0 +1,46 @@ +From 68b90794adf8287fa534cc8f35efb09772b133d0 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Sat, 4 Mar 2023 00:21:35 +0800 +Subject: [PATCH] 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 +Acked-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + super-ddf.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index 309812d..b86c6ac 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.35.3 + diff --git a/0095-Create-goto-abort_locked-instead-of-return-1-in-erro.patch b/0095-Create-goto-abort_locked-instead-of-return-1-in-erro.patch new file mode 100644 index 0000000..47ce8dd --- /dev/null +++ b/0095-Create-goto-abort_locked-instead-of-return-1-in-erro.patch @@ -0,0 +1,35 @@ +From ba867e2ebaead20e3d9a7e62ef8fd940176c3110 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 1 Mar 2023 13:41:29 -0700 +Subject: [PATCH] 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 +Acked-by: Kinga Tanska +Reviewed-by: Xiao Ni +Reviewed-by: Chaitanya Kulkarni +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Create.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Create.c b/Create.c +index 953e737..2e8203e 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.35.3 + diff --git a/0096-Create-remove-safe_mode_delay-local-variable.patch b/0096-Create-remove-safe_mode_delay-local-variable.patch new file mode 100644 index 0000000..d5b7aa7 --- /dev/null +++ b/0096-Create-remove-safe_mode_delay-local-variable.patch @@ -0,0 +1,64 @@ +From fb2c0f6183e29b014608e5e1aa4d53cb55887326 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 1 Mar 2023 13:41:30 -0700 +Subject: [PATCH] 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 +Acked-by: Kinga Tanska +Reviewed-by: Xiao Ni +Reviewed-by: Chaitanya Kulkarni +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Create.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/Create.c b/Create.c +index 2e8203e..8ded81d 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.35.3 + diff --git a/0097-Create-Factor-out-add_disks-helpers.patch b/0097-Create-Factor-out-add_disks-helpers.patch new file mode 100644 index 0000000..525698c --- /dev/null +++ b/0097-Create-Factor-out-add_disks-helpers.patch @@ -0,0 +1,452 @@ +From 8a4ce2c053866ac97feb436c4c85a54446ee0016 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 1 Mar 2023 13:41:31 -0700 +Subject: [PATCH] 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 +Acked-by: Kinga Tanska +Reviewed-by: Xiao Ni +Reviewed-by: Chaitanya Kulkarni +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Create.c | 382 +++++++++++++++++++++++++++++++------------------------ + 1 file changed, 213 insertions(+), 169 deletions(-) + +diff --git a/Create.c b/Create.c +index 8ded81d..6a04466 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<disk.raid_disk < s->raiddisks) { ++ info->disk.state = (1<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<failfast == FlagSet) ++ info->disk.state |= (1<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<disk.raid_disk < s->raiddisks) +- inf->disk.state = (1<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<failfast == FlagSet) +- inf->disk.state |= (1<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.35.3 + diff --git a/0098-mdadm-Introduce-pr_info.patch b/0098-mdadm-Introduce-pr_info.patch new file mode 100644 index 0000000..ea3a6bb --- /dev/null +++ b/0098-mdadm-Introduce-pr_info.patch @@ -0,0 +1,72 @@ +From 9364dbfb264e89ab9467dfc0d2b813033e320640 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 1 Mar 2023 13:41:32 -0700 +Subject: [PATCH] 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 +Acked-by: Kinga Tanska +Reviewed-by: Xiao Ni +Reviewed-by: Chaitanya Kulkarni +Acked-by: Coly Li +Acked-by: Paul Menzel +Signed-off-by: Jes Sorensen +--- + Create.c | 7 ++++--- + mdadm.h | 2 ++ + 2 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/Create.c b/Create.c +index 6a04466..4acda30 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 1674ce1..4336be4 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.35.3 + diff --git a/0099-mdadm-Add-write-zeros-option-for-Create.patch b/0099-mdadm-Add-write-zeros-option-for-Create.patch new file mode 100644 index 0000000..7344645 --- /dev/null +++ b/0099-mdadm-Add-write-zeros-option-for-Create.patch @@ -0,0 +1,346 @@ +From 577fd10486d8d1472a6b559066f344ac30a3a391 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 1 Mar 2023 13:41:33 -0700 +Subject: [PATCH] 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 +Acked-by: Kinga Tanska +Reviewed-by: Xiao Ni +Reviewed-by: Chaitanya Kulkarni +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + 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 4acda30..bbe9e13 100644 +--- a/Create.c ++++ b/Create.c +@@ -26,6 +26,10 @@ + #include "md_u.h" + #include "md_p.h" + #include ++#include ++#include ++#include ++#include + + 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 bd8d50d..db251ed 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 57e8e6f..4685ad6 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 4336be4..b9127f9 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.35.3 + diff --git a/0100-manpage-Add-write-zeroes-option-to-manpage.patch b/0100-manpage-Add-write-zeroes-option-to-manpage.patch new file mode 100644 index 0000000..faf8e73 --- /dev/null +++ b/0100-manpage-Add-write-zeroes-option-to-manpage.patch @@ -0,0 +1,56 @@ +From 33831d845a48b9a2ac4d1e954c88a3dd8cb15753 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 1 Mar 2023 13:41:35 -0700 +Subject: [PATCH] manpage: Add --write-zeroes option to manpage + +Document the new --write-zeroes option in the manpage. + +Signed-off-by: Logan Gunthorpe +Acked-by: Kinga Tanska +Reviewed-by: Xiao Ni +Reviewed-by: Chaitanya Kulkarni +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index 64f71ed..6f0f6c1 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.35.3 + diff --git a/0101-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch b/0101-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch new file mode 100644 index 0000000..e7f1ea6 --- /dev/null +++ b/0101-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch @@ -0,0 +1,53 @@ +From 566844b93e6823a04ed65827ba3e03cb123b3a03 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Wed, 18 Jan 2023 00:32:36 -0800 +Subject: [PATCH] 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 +Signed-off-by: Jes Sorensen +--- + sha1.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/sha1.c b/sha1.c +index 89b32f4..1e4ad5d 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 ++ . ++ 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.35.3 + diff --git a/0102-Use-existence-of-etc-initrd-release-to-detect-initrd.patch b/0102-Use-existence-of-etc-initrd-release-to-detect-initrd.patch new file mode 100644 index 0000000..0544fd0 --- /dev/null +++ b/0102-Use-existence-of-etc-initrd-release-to-detect-initrd.patch @@ -0,0 +1,40 @@ +From eb45d0add7cf2918f838bec2d93d99cf2d9c662f Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 13 Mar 2023 14:42:58 +1100 +Subject: [PATCH] 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 +Signed-off-by: Jes Sorensen +--- + util.c | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +diff --git a/util.c b/util.c +index 9f1e1f7..509fb43 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.35.3 + diff --git a/0103-Create-Fix-checking-for-container-in-update_metadata.patch b/0103-Create-Fix-checking-for-container-in-update_metadata.patch new file mode 100644 index 0000000..43c6788 --- /dev/null +++ b/0103-Create-Fix-checking-for-container-in-update_metadata.patch @@ -0,0 +1,38 @@ +From ef6236da232e968dcf08b486178cd20d5ea97e2a Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Thu, 23 Mar 2023 12:50:00 +0100 +Subject: [PATCH] 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 +Signed-off-by: Jes Sorensen +--- + Create.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Create.c b/Create.c +index bbe9e13..0911bf9 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.35.3 + diff --git a/mdadm.changes b/mdadm.changes index e62eedf..6a1d905 100644 --- a/mdadm.changes +++ b/mdadm.changes @@ -1,3 +1,100 @@ +------------------------------------------------------------------- +Mon Jan 8 05:32:25 UTC 2024 - Coly Li + +- Update mdadm to latest upstream state upto commit + 582945c2d3bb. (jsc#PED-7542) + 1) The testing changes are not included here. + 2) Code clean up, and more helper routines added for Manage.c, + Monitor.c, mdadm.c, ReadMe.c, super-intel.c, super0.c, super1.c, + Create.c, Incremental.c and so on. + 3) Man page update for mdadm.8.in. + 4) Several memory leak and double free fixes. + 5) Check /etc/initrd-release for whether systemd running on an initrd. + - Manage: Block unsafe member failing + 0062-Manage-Block-unsafe-member-failing.patch + - Mdmonitor: Split alert() into separate functions + 0063-Mdmonitor-Split-alert-into-separate-functions.patch + - Monitor: block if monitor modes are combined. + 0064-Monitor-block-if-monitor-modes-are-combined.patch + - Update mdadm Monitor manual. + 0065-Update-mdadm-Monitor-manual.patch + - mdadm: create ident_init() + 0066-mdadm-create-ident_init.patch + - mdadm: Add option validation for --update-subarray + 0067-mdadm-Add-option-validation-for-update-subarray.patch + - Fix --update-subarray on active volume + 0068-Fix-update-subarray-on-active-volume.patch + - Add code specific update options to enum. + 0069-Add-code-specific-update-options-to-enum.patch + - super-ddf: Remove update_super_ddf. + 0070-super-ddf-Remove-update_super_ddf.patch + - super0: refactor the code for enum + 0071-super0-refactor-the-code-for-enum.patch + - super1: refactor the code for enum + 0072-super1-refactor-the-code-for-enum.patch + - super-intel: refactor the code for enum + 0073-super-intel-refactor-the-code-for-enum.patch + - Change update to enum in update_super and update_subarray + 0074-Change-update-to-enum-in-update_super-and-update_sub.patch + - Manage&Incremental: code refactor, string to enum + 0075-Manage-Incremental-code-refactor-string-to-enum.patch + - Change char* to enum in context->update & refactor code + 0076-Change-char-to-enum-in-context-update-refactor-code.patch + - mdadm/udev: Don't handle change event on raw devices + 0077-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch + - Manage: do not check array state when drive is removed + 0078-Manage-do-not-check-array-state-when-drive-is-remove.patch + - incremental, manage: do not verify if remove is safe + 0079-incremental-manage-do-not-verify-if-remove-is-safe.patch + - super-intel: make freesize not required for chunk size + 0080-super-intel-make-freesize-not-required-for-chunk-siz.patch + - manage: move comment with function description + 0081-manage-move-comment-with-function-description.patch + - Fix NULL dereference in super_by_fd + 0082-Fix-NULL-dereference-in-super_by_fd.patch + - Mdmonitor: Make alert_info global + 0083-Mdmonitor-Make-alert_info-global.patch + - Mdmonitor: Pass events to alert() using enums instead of + 0084-Mdmonitor-Pass-events-to-alert-using-enums-instead-o.patch + - Mdmonitor: Add helper functions + 0085-Mdmonitor-Add-helper-functions.patch + - Add helpers to determine whether directories or files are + 0086-Add-helpers-to-determine-whether-directories-or-file.patch + - Mdmonitor: Refactor write_autorebuild_pid() + 0087-Mdmonitor-Refactor-write_autorebuild_pid.patch + - Mdmonitor: Refactor check_one_sharer() for better error + 0088-Mdmonitor-Refactor-check_one_sharer-for-better-error.patch + - util.c: reorder code lines in parse_layout_faulty() + 0089-util.c-reorder-code-lines-in-parse_layout_faulty.patch + - util.c: fix memleak in parse_layout_faulty() + 0090-util.c-fix-memleak-in-parse_layout_faulty.patch + - Detail.c: fix memleak in Detail() + 0091-Detail.c-fix-memleak-in-Detail.patch + - isuper-intel.c: fix double free in load_imsm_mpb() + 0092-isuper-intel.c-fix-double-free-in-load_imsm_mpb.patch + - super-intel.c: fix memleak in find_disk_attached_hba() + 0093-super-intel.c-fix-memleak-in-find_disk_attached_hba.patch + - super-ddf.c: fix memleak in get_vd_num_of_subarray() + 0094-super-ddf.c-fix-memleak-in-get_vd_num_of_subarray.patch + - Create: goto abort_locked instead of return 1 in error path + 0095-Create-goto-abort_locked-instead-of-return-1-in-erro.patch + - Create: remove safe_mode_delay local variable + 0096-Create-remove-safe_mode_delay-local-variable.patch + - Create: Factor out add_disks() helpers + 0097-Create-Factor-out-add_disks-helpers.patch + - mdadm: Introduce pr_info() + 0098-mdadm-Introduce-pr_info.patch + - mdadm: Add --write-zeros option for Create + 0099-mdadm-Add-write-zeros-option-for-Create.patch + - manpage: Add --write-zeroes option to manpage + 0100-manpage-Add-write-zeroes-option-to-manpage.patch + - Define alignof using _Alignof when using C11 or newer + 0101-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch + - Use existence of /etc/initrd-release to detect initrd. + 0102-Use-existence-of-etc-initrd-release-to-detect-initrd.patch + - Create: Fix checking for container in update_metadata + 0103-Create-Fix-checking-for-container-in-update_metadata.patch + ------------------------------------------------------------------- Fri Nov 17 15:34:31 UTC 2023 - Dominique Leuenberger diff --git a/mdadm.spec b/mdadm.spec index 17793ad..1e1dd2b 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,7 +1,7 @@ # # spec file for package mdadm # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -101,6 +101,48 @@ Patch58: 0058-mdopen-always-try-create_named_array.patch Patch59: 0059-Improvements-for-IMSM_NO_PLATFORM-testing.patch Patch60: 0060-Grow-fix-possible-memory-leak.patch Patch61: 0061-Grow-fix-can-t-change-bitmap-type-from-none-to-clustered.patch +Patch62: 0062-Manage-Block-unsafe-member-failing.patch +Patch63: 0063-Mdmonitor-Split-alert-into-separate-functions.patch +Patch64: 0064-Monitor-block-if-monitor-modes-are-combined.patch +Patch65: 0065-Update-mdadm-Monitor-manual.patch +Patch66: 0066-mdadm-create-ident_init.patch +Patch67: 0067-mdadm-Add-option-validation-for-update-subarray.patch +Patch68: 0068-Fix-update-subarray-on-active-volume.patch +Patch69: 0069-Add-code-specific-update-options-to-enum.patch +Patch70: 0070-super-ddf-Remove-update_super_ddf.patch +Patch71: 0071-super0-refactor-the-code-for-enum.patch +Patch72: 0072-super1-refactor-the-code-for-enum.patch +Patch73: 0073-super-intel-refactor-the-code-for-enum.patch +Patch74: 0074-Change-update-to-enum-in-update_super-and-update_sub.patch +Patch75: 0075-Manage-Incremental-code-refactor-string-to-enum.patch +Patch76: 0076-Change-char-to-enum-in-context-update-refactor-code.patch +Patch77: 0077-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch +Patch78: 0078-Manage-do-not-check-array-state-when-drive-is-remove.patch +Patch79: 0079-incremental-manage-do-not-verify-if-remove-is-safe.patch +Patch80: 0080-super-intel-make-freesize-not-required-for-chunk-siz.patch +Patch81: 0081-manage-move-comment-with-function-description.patch +Patch82: 0082-Fix-NULL-dereference-in-super_by_fd.patch +Patch83: 0083-Mdmonitor-Make-alert_info-global.patch +Patch84: 0084-Mdmonitor-Pass-events-to-alert-using-enums-instead-o.patch +Patch85: 0085-Mdmonitor-Add-helper-functions.patch +Patch86: 0086-Add-helpers-to-determine-whether-directories-or-file.patch +Patch87: 0087-Mdmonitor-Refactor-write_autorebuild_pid.patch +Patch88: 0088-Mdmonitor-Refactor-check_one_sharer-for-better-error.patch +Patch89: 0089-util.c-reorder-code-lines-in-parse_layout_faulty.patch +Patch90: 0090-util.c-fix-memleak-in-parse_layout_faulty.patch +Patch91: 0091-Detail.c-fix-memleak-in-Detail.patch +Patch92: 0092-isuper-intel.c-fix-double-free-in-load_imsm_mpb.patch +Patch93: 0093-super-intel.c-fix-memleak-in-find_disk_attached_hba.patch +Patch94: 0094-super-ddf.c-fix-memleak-in-get_vd_num_of_subarray.patch +Patch95: 0095-Create-goto-abort_locked-instead-of-return-1-in-erro.patch +Patch96: 0096-Create-remove-safe_mode_delay-local-variable.patch +Patch97: 0097-Create-Factor-out-add_disks-helpers.patch +Patch98: 0098-mdadm-Introduce-pr_info.patch +Patch99: 0099-mdadm-Add-write-zeros-option-for-Create.patch +Patch100: 0100-manpage-Add-write-zeroes-option-to-manpage.patch +Patch101: 0101-Define-alignof-using-_Alignof-when-using-C11-or-newe.patch +Patch102: 0102-Use-existence-of-etc-initrd-release-to-detect-initrd.patch +Patch103: 0103-Create-Fix-checking-for-container-in-update_metadata.patch Patch1001: 1001-display-timeout-status.patch Patch1002: 1002-OnCalendar-format-fix-of-mdcheck_start-timer.patch Patch1003: 1003-mdadm-treat-the-Dell-softraid-array-as-local-array.patch @@ -174,6 +216,48 @@ mdadm is a program that can be used to control Linux md devices. %patch59 -p1 %patch60 -p1 %patch61 -p1 +%patch62 -p1 +%patch63 -p1 +%patch64 -p1 +%patch65 -p1 +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 +%patch74 -p1 +%patch75 -p1 +%patch76 -p1 +%patch77 -p1 +%patch78 -p1 +%patch79 -p1 +%patch80 -p1 +%patch81 -p1 +%patch82 -p1 +%patch83 -p1 +%patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 +%patch89 -p1 +%patch90 -p1 +%patch91 -p1 +%patch92 -p1 +%patch93 -p1 +%patch94 -p1 +%patch95 -p1 +%patch96 -p1 +%patch97 -p1 +%patch98 -p1 +%patch99 -p1 +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 %patch1001 -p1 %patch1002 -p1 %patch1003 -p1