diff --git a/0001-Unify-error-message.patch b/0001-Unify-error-message.patch new file mode 100644 index 0000000..14dc69c --- /dev/null +++ b/0001-Unify-error-message.patch @@ -0,0 +1,47 @@ +From f1cc8ab9ab6a92c3cd94ab7590b46285e214681e Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Tue, 15 Mar 2022 09:30:30 +0100 +Subject: [PATCH 01/83] Unify error message. + +Provide the same error message for the same error that can occur in Grow.c and super-intel.c. + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + Grow.c | 4 ++-- + super-intel.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 9c6fc95e..9a947204 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1001,8 +1001,8 @@ int remove_disks_for_takeover(struct supertype *st, + rv = 1; + sysfs_free(arrays); + if (rv) { +- pr_err("Error. Cannot perform operation on /dev/%s\n", st->devnm); +- pr_err("For this operation it MUST be single array in container\n"); ++ pr_err("Error. Cannot perform operation on %s- for this operation " ++ "it MUST be single array in container\n", st->devnm); + return rv; + } + } +diff --git a/super-intel.c b/super-intel.c +index d5fad102..5ffa7636 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -11683,8 +11683,8 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + struct imsm_super *mpb = super->anchor; + + if (mpb->num_raid_devs > 1) { +- pr_err("Error. Cannot perform operation on %s- for this operation it MUST be single array in container\n", +- geo->dev_name); ++ pr_err("Error. Cannot perform operation on %s- for this operation " ++ "it MUST be single array in container\n", geo->dev_name); + change = -1; + } + } +-- +2.38.1 + diff --git a/0002-mdadm-Fix-double-free.patch b/0002-mdadm-Fix-double-free.patch new file mode 100644 index 0000000..e6b7d37 --- /dev/null +++ b/0002-mdadm-Fix-double-free.patch @@ -0,0 +1,33 @@ +From 5ce5a15f0bf007e850e15259bba4f53736605fb2 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 25 Mar 2022 12:48:59 +0100 +Subject: [PATCH 02/83] mdadm: Fix double free + +If there was a size mismatch after creation it would get fixed on grow +in imsm_fix_size_mismatch(), but due to double free "double free or corruption (fasttop)" +error occurs and grow cannot proceed. + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + super-intel.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 5ffa7636..6ff336ee 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -11783,9 +11783,8 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index) + st->update_tail = &st->updates; + } else { + imsm_sync_metadata(st); ++ free(update); + } +- +- free(update); + } + ret_val = 0; + exit: +-- +2.38.1 + diff --git a/0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch b/0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch new file mode 100644 index 0000000..e43cdaa --- /dev/null +++ b/0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch @@ -0,0 +1,83 @@ +From fea026b4849182fc8413014c81456e7215af28d9 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Wed, 23 Mar 2022 15:05:19 +0100 +Subject: [PATCH 03/83] Grow_reshape: Add r0 grow size error message and update + man + +Grow size on r0 is not supported for imsm and native metadata. +Add proper error message. +Update man for proper use of --size. +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Grow.c | 6 ++++++ + mdadm.8.in | 19 ++++++++++++------- + 2 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 9a947204..aa72490b 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1998,6 +1998,12 @@ int Grow_reshape(char *devname, int fd, + goto release; + } + ++ if (array.level == 0) { ++ pr_err("Component size change is not supported for RAID0\n"); ++ rv = 1; ++ goto release; ++ } ++ + if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL, + devname, APPLY_METADATA_CHANGES, + c->verbose > 0)) { +diff --git a/mdadm.8.in b/mdadm.8.in +index be902dba..e2a42425 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -459,7 +459,8 @@ number of spare devices. + + .TP + .BR \-z ", " \-\-size= +-Amount (in Kilobytes) of space to use from each drive in RAID levels 1/4/5/6. ++Amount (in Kilobytes) of space to use from each drive in RAID levels 1/4/5/6/10 ++and for RAID 0 on external metadata. + This must be a multiple of the chunk size, and must leave about 128Kb + of space at the end of the drive for the RAID superblock. + If this is not specified +@@ -478,10 +479,19 @@ To guard against this it can be useful to set the initial size + slightly smaller than the smaller device with the aim that it will + still be larger than any replacement. + ++This option can be used with ++.B \-\-create ++for determining initial size of an array. For external metadata, ++it can be used on a volume, but not on a container itself. ++Setting initial size of ++.B RAID 0 ++array is only valid for external metadata. ++ + This value can be set with + .B \-\-grow +-for RAID level 1/4/5/6 though ++for RAID level 1/4/5/6/10 though + DDF arrays may not be able to support this. ++RAID 0 array size cannot be changed. + If the array was created with a size smaller than the currently + active drives, the extra space can be accessed using + .BR \-\-grow . +@@ -501,11 +511,6 @@ problems the array can be made bigger again with no loss with another + .B "\-\-grow \-\-size=" + command. + +-This value cannot be used when creating a +-.B CONTAINER +-such as with DDF and IMSM metadata, though it perfectly valid when +-creating an array inside a container. +- + .TP + .BR \-Z ", " \-\-array\-size= + This is only meaningful with +-- +2.38.1 + diff --git a/0004-udev-adapt-rules-to-systemd-v247.patch b/0004-udev-adapt-rules-to-systemd-v247.patch new file mode 100644 index 0000000..a755c53 --- /dev/null +++ b/0004-udev-adapt-rules-to-systemd-v247.patch @@ -0,0 +1,67 @@ +From cf9a109209aad285372b67306d54118af6fc522b Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 14 Jan 2022 16:44:33 +0100 +Subject: [PATCH 04/83] udev: adapt rules to systemd v247 + +New events have been added in kernel 4.14 ("bind" and "unbind"). +Systemd maintainer suggests to modify "add|change" branches. +This patches implements their suggestions. There is no issue yet because +new event types are not used in md. + +Please see systemd announcement for details[1]. + +[1] https://lists.freedesktop.org/archives/systemd-devel/2020-November/045646.html + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + udev-md-raid-arrays.rules | 2 +- + udev-md-raid-assembly.rules | 5 +++-- + udev-md-raid-safe-timeouts.rules | 2 +- + 3 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/udev-md-raid-arrays.rules b/udev-md-raid-arrays.rules +index 13c9076e..2967ace1 100644 +--- a/udev-md-raid-arrays.rules ++++ b/udev-md-raid-arrays.rules +@@ -3,7 +3,7 @@ + SUBSYSTEM!="block", GOTO="md_end" + + # handle md arrays +-ACTION!="add|change", GOTO="md_end" ++ACTION=="remove", GOTO="md_end" + KERNEL!="md*", GOTO="md_end" + + # partitions have no md/{array_state,metadata_version}, but should not +diff --git a/udev-md-raid-assembly.rules b/udev-md-raid-assembly.rules +index d668cddd..39b4344b 100644 +--- a/udev-md-raid-assembly.rules ++++ b/udev-md-raid-assembly.rules +@@ -30,8 +30,9 @@ LABEL="md_inc" + + # remember you can limit what gets auto/incrementally assembled by + # mdadm.conf(5)'s 'AUTO' and selectively whitelist using 'ARRAY' +-ACTION=="add|change", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}" +-ACTION=="add|change", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer" ++ACTION!="remove", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}" ++ACTION!="remove", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer" ++ + ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="BINDIR/mdadm -If $name --path $env{ID_PATH}" + ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="BINDIR/mdadm -If $name" + +diff --git a/udev-md-raid-safe-timeouts.rules b/udev-md-raid-safe-timeouts.rules +index 12bdcaa8..2e185cee 100644 +--- a/udev-md-raid-safe-timeouts.rules ++++ b/udev-md-raid-safe-timeouts.rules +@@ -50,7 +50,7 @@ ENV{DEVTYPE}!="partition", GOTO="md_timeouts_end" + + IMPORT{program}="/sbin/mdadm --examine --export $devnode" + +-ACTION=="add|change", \ ++ACTION!="remove", \ + ENV{ID_FS_TYPE}=="linux_raid_member", \ + ENV{MD_LEVEL}=="raid[1-9]*", \ + TEST=="/sys/block/$parent/device/timeout", \ +-- +2.38.1 + diff --git a/0005-Replace-error-prone-signal-with-sigaction.patch b/0005-Replace-error-prone-signal-with-sigaction.patch new file mode 100644 index 0000000..dd04b8c --- /dev/null +++ b/0005-Replace-error-prone-signal-with-sigaction.patch @@ -0,0 +1,252 @@ +From 83a379cfbd283b387919fe05d44eb4c49e155ad6 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Mon, 21 Feb 2022 13:05:20 +0100 +Subject: [PATCH 05/83] Replace error prone signal() with sigaction() + +Up to this date signal() was used which implementation could vary [1]. +Sigaction() call is preferred. This commit introduces replacement +from signal() to sigaction() by the use of signal_s() wrapper. +Also remove redundant signal.h header includes. + +[1] https://man7.org/linux/man-pages/man2/signal.2.html + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + Grow.c | 4 ++-- + Monitor.c | 5 +++-- + managemon.c | 1 - + mdadm.h | 22 ++++++++++++++++++++++ + mdmon.c | 1 - + monitor.c | 1 - + probe_roms.c | 6 +++--- + raid6check.c | 25 +++++++++++++++---------- + util.c | 1 - + 9 files changed, 45 insertions(+), 21 deletions(-) + +diff --git a/Grow.c b/Grow.c +index aa72490b..18c5719b 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + #include + + #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN) +@@ -3566,7 +3565,8 @@ started: + fd = -1; + mlockall(MCL_FUTURE); + +- signal(SIGTERM, catch_term); ++ if (signal_s(SIGTERM, catch_term) == SIG_ERR) ++ goto release; + + if (st->ss->external) { + /* metadata handler takes it from here */ +diff --git a/Monitor.c b/Monitor.c +index 30c031a2..c0ab5412 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -26,7 +26,6 @@ + #include "md_p.h" + #include "md_u.h" + #include +-#include + #include + #include + #ifndef NO_LIBUDEV +@@ -435,8 +434,10 @@ static void alert(char *event, char *dev, char *disc, struct alert_info *info) + if (mp) { + FILE *mdstat; + char hname[256]; ++ + gethostname(hname, sizeof(hname)); +- signal(SIGPIPE, SIG_IGN); ++ signal_s(SIGPIPE, SIG_IGN); ++ + if (info->mailfrom) + fprintf(mp, "From: %s\n", info->mailfrom); + else +diff --git a/managemon.c b/managemon.c +index bb7334cf..0e9bdf00 100644 +--- a/managemon.c ++++ b/managemon.c +@@ -106,7 +106,6 @@ + #include "mdmon.h" + #include + #include +-#include + + static void close_aa(struct active_array *aa) + { +diff --git a/mdadm.h b/mdadm.h +index c7268a71..26e7e5cd 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -46,6 +46,7 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); + #include + #include + #include ++#include + /* Newer glibc requires sys/sysmacros.h directly for makedev() */ + #include + #ifdef __dietlibc__ +@@ -1729,6 +1730,27 @@ static inline char *to_subarray(struct mdstat_ent *ent, char *container) + return &ent->metadata_version[10+strlen(container)+1]; + } + ++/** ++ * signal_s() - Wrapper for sigaction() with signal()-like interface. ++ * @sig: The signal to set the signal handler to. ++ * @handler: The signal handler. ++ * ++ * Return: previous handler or SIG_ERR on failure. ++ */ ++static inline sighandler_t signal_s(int sig, sighandler_t handler) ++{ ++ struct sigaction new_act; ++ struct sigaction old_act; ++ ++ new_act.sa_handler = handler; ++ new_act.sa_flags = 0; ++ ++ if (sigaction(sig, &new_act, &old_act) == 0) ++ return old_act.sa_handler; ++ ++ return SIG_ERR; ++} ++ + #ifdef DEBUG + #define dprintf(fmt, arg...) \ + fprintf(stderr, "%s: %s: "fmt, Name, __func__, ##arg) +diff --git a/mdmon.c b/mdmon.c +index c71e62c6..5570574b 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -56,7 +56,6 @@ + #include + #include + #include +-#include + #include + #ifdef USE_PTHREADS + #include +diff --git a/monitor.c b/monitor.c +index e0d3be67..b877e595 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -22,7 +22,6 @@ + #include "mdmon.h" + #include + #include +-#include + + static char *array_states[] = { + "clear", "inactive", "suspended", "readonly", "read-auto", +diff --git a/probe_roms.c b/probe_roms.c +index 7ea04c7a..94c80c2c 100644 +--- a/probe_roms.c ++++ b/probe_roms.c +@@ -22,7 +22,6 @@ + #include "probe_roms.h" + #include "mdadm.h" + #include +-#include + #include + #include + #include +@@ -69,7 +68,8 @@ static int probe_address16(const __u16 *ptr, __u16 *val) + + void probe_roms_exit(void) + { +- signal(SIGBUS, SIG_DFL); ++ signal_s(SIGBUS, SIG_DFL); ++ + if (rom_fd >= 0) { + close(rom_fd); + rom_fd = -1; +@@ -98,7 +98,7 @@ int probe_roms_init(unsigned long align) + if (roms_init()) + return -1; + +- if (signal(SIGBUS, sigbus) == SIG_ERR) ++ if (signal_s(SIGBUS, sigbus) == SIG_ERR) + rc = -1; + if (rc == 0) { + fd = open("/dev/mem", O_RDONLY); +diff --git a/raid6check.c b/raid6check.c +index a8e6005b..99477761 100644 +--- a/raid6check.c ++++ b/raid6check.c +@@ -24,7 +24,6 @@ + + #include "mdadm.h" + #include +-#include + #include + + #define CHECK_PAGE_BITS (12) +@@ -130,30 +129,36 @@ void raid6_stats(int *disk, int *results, int raid_disks, int chunk_size) + } + + int lock_stripe(struct mdinfo *info, unsigned long long start, +- int chunk_size, int data_disks, sighandler_t *sig) { ++ int chunk_size, int data_disks, sighandler_t *sig) ++{ + int rv; ++ ++ sig[0] = signal_s(SIGTERM, SIG_IGN); ++ sig[1] = signal_s(SIGINT, SIG_IGN); ++ sig[2] = signal_s(SIGQUIT, SIG_IGN); ++ ++ if (sig[0] == SIG_ERR || sig[1] == SIG_ERR || sig[2] == SIG_ERR) ++ return 1; ++ + if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { + return 2; + } + +- sig[0] = signal(SIGTERM, SIG_IGN); +- sig[1] = signal(SIGINT, SIG_IGN); +- sig[2] = signal(SIGQUIT, SIG_IGN); +- + rv = sysfs_set_num(info, NULL, "suspend_lo", start * chunk_size * data_disks); + rv |= sysfs_set_num(info, NULL, "suspend_hi", (start + 1) * chunk_size * data_disks); + return rv * 256; + } + +-int unlock_all_stripes(struct mdinfo *info, sighandler_t *sig) { ++int unlock_all_stripes(struct mdinfo *info, sighandler_t *sig) ++{ + int rv; + rv = sysfs_set_num(info, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL); + rv |= sysfs_set_num(info, NULL, "suspend_hi", 0); + rv |= sysfs_set_num(info, NULL, "suspend_lo", 0); + +- signal(SIGQUIT, sig[2]); +- signal(SIGINT, sig[1]); +- signal(SIGTERM, sig[0]); ++ signal_s(SIGQUIT, sig[2]); ++ signal_s(SIGINT, sig[1]); ++ signal_s(SIGTERM, sig[0]); + + if(munlockall() != 0) + return 3; +diff --git a/util.c b/util.c +index 3d05d074..cc94f96e 100644 +--- a/util.c ++++ b/util.c +@@ -35,7 +35,6 @@ + #include + #include + #include +-#include + #include + + +-- +2.38.1 + diff --git a/0006-mdadm-Respect-config-file-location-in-man.patch b/0006-mdadm-Respect-config-file-location-in-man.patch new file mode 100644 index 0000000..bee28ac --- /dev/null +++ b/0006-mdadm-Respect-config-file-location-in-man.patch @@ -0,0 +1,1533 @@ +From e9dd5644843e2013a7dd1a8a5da2b9fa35837416 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 18 Mar 2022 09:26:04 +0100 +Subject: [PATCH 06/83] mdadm: Respect config file location in man + +Default config file location could differ depending on OS (e.g. Debian family). +This patch takes default config file into consideration when creating mdadm.man +file as well as mdadm.conf.man. + +Rename mdadm.conf.5 to mdadm.conf.5.in. Now mdadm.conf.5 is generated automatically. + +Signed-off-by: Lukasz Florczak +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + .gitignore | 1 + + Makefile | 7 +- + mdadm.8.in | 16 +- + mdadm.conf.5 | 706 ------------------------------------------------ + mdadm.conf.5.in | 706 ++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 721 insertions(+), 715 deletions(-) + delete mode 100644 mdadm.conf.5 + create mode 100644 mdadm.conf.5.in + +diff --git a/.gitignore b/.gitignore +index 217fe76d..8d791c6f 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -3,6 +3,7 @@ + /*-stamp + /mdadm + /mdadm.8 ++/mdadm.conf.5 + /mdadm.udeb + /mdassemble + /mdmon +diff --git a/Makefile b/Makefile +index 2a51d813..bf126033 100644 +--- a/Makefile ++++ b/Makefile +@@ -227,7 +227,12 @@ raid6check : raid6check.o mdadm.h $(CHECK_OBJS) + + mdadm.8 : mdadm.8.in + sed -e 's/{DEFAULT_METADATA}/$(DEFAULT_METADATA)/g' \ +- -e 's,{MAP_PATH},$(MAP_PATH),g' mdadm.8.in > mdadm.8 ++ -e 's,{MAP_PATH},$(MAP_PATH),g' -e 's,{CONFFILE},$(CONFFILE),g' \ ++ -e 's,{CONFFILE2},$(CONFFILE2),g' mdadm.8.in > mdadm.8 ++ ++mdadm.conf.5 : mdadm.conf.5.in ++ sed -e 's,{CONFFILE},$(CONFFILE),g' \ ++ -e 's,{CONFFILE2},$(CONFFILE2),g' mdadm.conf.5.in > mdadm.conf.5 + + mdadm.man : mdadm.8 + man -l mdadm.8 > mdadm.man +diff --git a/mdadm.8.in b/mdadm.8.in +index e2a42425..8b21ffd4 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -267,13 +267,13 @@ the exact meaning of this option in different contexts. + .TP + .BR \-c ", " \-\-config= + Specify the config file or directory. Default is to use +-.B /etc/mdadm.conf ++.B {CONFFILE} + and +-.BR /etc/mdadm.conf.d , ++.BR {CONFFILE}.d , + or if those are missing then +-.B /etc/mdadm/mdadm.conf ++.B {CONFFILE2} + and +-.BR /etc/mdadm/mdadm.conf.d . ++.BR {CONFFILE2}.d . + If the config file given is + .B "partitions" + then nothing will be read, but +@@ -2014,9 +2014,9 @@ The config file is only used if explicitly named with + or requested with (a possibly implicit) + .BR \-\-scan . + In the later case, +-.B /etc/mdadm.conf ++.B {CONFFILE} + or +-.B /etc/mdadm/mdadm.conf ++.B {CONFFILE2} + is used. + + If +@@ -3344,7 +3344,7 @@ uses this to find arrays when + is given in Misc mode, and to monitor array reconstruction + on Monitor mode. + +-.SS /etc/mdadm.conf ++.SS {CONFFILE} (or {CONFFILE2}) + + The config file lists which devices may be scanned to see if + they contain MD super block, and gives identifying information +@@ -3352,7 +3352,7 @@ they contain MD super block, and gives identifying information + .BR mdadm.conf (5) + for more details. + +-.SS /etc/mdadm.conf.d ++.SS {CONFFILE}.d (or {CONFFILE2}.d) + + A directory containing configuration files which are read in lexical + order. +diff --git a/mdadm.conf.5 b/mdadm.conf.5 +deleted file mode 100644 +index 74a21c5f..00000000 +--- a/mdadm.conf.5 ++++ /dev/null +@@ -1,706 +0,0 @@ +-.\" Copyright Neil Brown and others. +-.\" This program is free software; you can redistribute it and/or modify +-.\" it under the terms of the GNU General Public License as published by +-.\" the Free Software Foundation; either version 2 of the License, or +-.\" (at your option) any later version. +-.\" See file COPYING in distribution for details. +-.TH MDADM.CONF 5 +-.SH NAME +-mdadm.conf \- configuration for management of Software RAID with mdadm +-.SH SYNOPSIS +-/etc/mdadm.conf +-.SH DESCRIPTION +-.PP +-.I mdadm +-is a tool for creating, managing, and monitoring RAID devices using the +-.B md +-driver in Linux. +-.PP +-Some common tasks, such as assembling all arrays, can be simplified +-by describing the devices and arrays in this configuration file. +- +-.SS SYNTAX +-The file should be seen as a collection of words separated by white +-space (space, tab, or newline). +-Any word that beings with a hash sign (#) starts a comment and that +-word together with the remainder of the line is ignored. +- +-Spaces can be included in a word using quotation characters. Either +-single quotes +-.RB ( ' ) +-or double quotes (\fB"\fP) +-may be used. All the characters from one quotation character to +-next identical character are protected and will not be used to +-separate words to start new quoted strings. To include a single quote +-it must be between double quotes. To include a double quote it must +-be between single quotes. +- +-Any line that starts with white space (space or tab) is treated as +-though it were a continuation of the previous line. +- +-Empty lines are ignored, but otherwise each (non continuation) line +-must start with a keyword as listed below. The keywords are case +-insensitive and can be abbreviated to 3 characters. +- +-The keywords are: +-.TP +-.B DEVICE +-A +-.B device +-line lists the devices (whole devices or partitions) that might contain +-a component of an MD array. When looking for the components of an +-array, +-.I mdadm +-will scan these devices (or any devices listed on the command line). +- +-The +-.B device +-line may contain a number of different devices (separated by spaces) +-and each device name can contain wild cards as defined by +-.BR glob (7). +- +-Also, there may be several device lines present in the file. +- +-Alternatively, a +-.B device +-line can contain either or both of the words +-.B containers +-and +-.BR partitions . +-The word +-.B containers +-will cause +-.I mdadm +-to look for assembled CONTAINER arrays and included them as a source +-for assembling further arrays. +- +-The word +-.I partitions +-will cause +-.I mdadm +-to read +-.I /proc/partitions +-and include all devices and partitions found therein. +-.I mdadm +-does not use the names from +-.I /proc/partitions +-but only the major and minor device numbers. It scans +-.I /dev +-to find the name that matches the numbers. +- +-If no DEVICE line is present, then "DEVICE partitions containers" is assumed. +- +-For example: +-.IP +-DEVICE /dev/hda* /dev/hdc* +-.br +-DEV /dev/sd* +-.br +-DEVICE /dev/disk/by-path/pci* +-.br +-DEVICE partitions +- +-.TP +-.B ARRAY +-The ARRAY lines identify actual arrays. The second word on the line +-may be the name of the device where the array is normally +-assembled, such as +-.B /dev/md1 +-or +-.BR /dev/md/backup . +-If the name does not start with a slash +-.RB (' / '), +-it is treated as being in +-.BR /dev/md/ . +-Alternately the word +-.B +-(complete with angle brackets) can be given in which case any array +-which matches the rest of the line will never be automatically assembled. +-If no device name is given, +-.I mdadm +-will use various heuristics to determine an appropriate name. +- +-Subsequent words identify the array, or identify the array as a member +-of a group. If multiple identities are given, +-then a component device must match ALL identities to be considered a +-match. Each identity word has a tag, and equals sign, and some value. +-The tags are: +-.RS 4 +-.TP +-.B uuid= +-The value should be a 128 bit uuid in hexadecimal, with punctuation +-interspersed if desired. This must match the uuid stored in the +-superblock. +-.TP +-.B name= +-The value should be a simple textual name as was given to +-.I mdadm +-when the array was created. This must match the name stored in the +-superblock on a device for that device to be included in the array. +-Not all superblock formats support names. +-.TP +-.B super\-minor= +-The value is an integer which indicates the minor number that was +-stored in the superblock when the array was created. When an array is +-created as /dev/mdX, then the minor number X is stored. +-.TP +-.B devices= +-The value is a comma separated list of device names or device name +-patterns. +-Only devices with names which match one entry in the list will be used +-to assemble the array. Note that the devices +-listed there must also be listed on a DEVICE line. +-.TP +-.B level= +-The value is a RAID level. This is not normally used to +-identify an array, but is supported so that the output of +- +-.B "mdadm \-\-examine \-\-scan" +- +-can be use directly in the configuration file. +-.TP +-.B num\-devices= +-The value is the number of devices in a complete active array. As with +-.B level= +-this is mainly for compatibility with the output of +- +-.BR "mdadm \-\-examine \-\-scan" . +- +-.TP +-.B spares= +-The value is a number of spare devices to expect the array to have. +-The sole use of this keyword and value is as follows: +-.B mdadm \-\-monitor +-will report an array if it is found to have fewer than this number of +-spares when +-.B \-\-monitor +-starts or when +-.B \-\-oneshot +-is used. +- +-.TP +-.B spare\-group= +-The value is a textual name for a group of arrays. All arrays with +-the same +-.B spare\-group +-name are considered to be part of the same group. The significance of +-a group of arrays is that +-.I mdadm +-will, when monitoring the arrays, move a spare drive from one array in +-a group to another array in that group if the first array had a failed +-or missing drive but no spare. +- +-.TP +-.B auto= +-This option is rarely needed with mdadm-3.0, particularly if use with +-the Linux kernel v2.6.28 or later. +-It tells +-.I mdadm +-whether to use partitionable array or non-partitionable arrays and, +-in the absence of +-.IR udev , +-how many partition devices to create. From 2.6.28 all md array +-devices are partitionable, hence this option is not needed. +- +-The value of this option can be "yes" or "md" to indicate that a +-traditional, non-partitionable md array should be created, or "mdp", +-"part" or "partition" to indicate that a partitionable md array (only +-available in linux 2.6 and later) should be used. This later set can +-also have a number appended to indicate how many partitions to create +-device files for, e.g. +-.BR auto=mdp5 . +-The default is 4. +- +-.TP +-.B bitmap= +-The option specifies a file in which a write-intent bitmap should be +-found. When assembling the array, +-.I mdadm +-will provide this file to the +-.B md +-driver as the bitmap file. This has the same function as the +-.B \-\-bitmap\-file +-option to +-.BR \-\-assemble . +- +-.TP +-.B metadata= +-Specify the metadata format that the array has. This is mainly +-recognised for comparability with the output of +-.BR "mdadm \-Es" . +- +-.TP +-.B container= +-Specify that this array is a member array of some container. The +-value given can be either a path name in /dev, or a UUID of the +-container array. +- +-.TP +-.B member= +-Specify that this array is a member array of some container. Each +-type of container has some way to enumerate member arrays, often a +-simple sequence number. The value identifies which member of a +-container the array is. It will usually accompany a "container=" word. +-.RE +- +-.TP +-.B MAILADDR +-The +-.B mailaddr +-line gives an E-mail address that alerts should be +-sent to when +-.I mdadm +-is running in +-.B \-\-monitor +-mode (and was given the +-.B \-\-scan +-option). There should only be one +-.B MAILADDR +-line and it should have only one address. Any subsequent addresses +-are silently ignored. +- +-.TP +-.B MAILFROM +-The +-.B mailfrom +-line (which can only be abbreviated to at least 5 characters) gives an +-address to appear in the "From" address for alert mails. This can be +-useful if you want to explicitly set a domain, as the default from +-address is "root" with no domain. All words on this line are +-catenated with spaces to form the address. +- +-Note that this value cannot be set via the +-.I mdadm +-commandline. It is only settable via the config file. +- +-.TP +-.B PROGRAM +-The +-.B program +-line gives the name of a program to be run when +-.B "mdadm \-\-monitor" +-detects potentially interesting events on any of the arrays that it +-is monitoring. This program gets run with two or three arguments, they +-being the Event, the md device, and possibly the related component +-device. +- +-There should only be one +-.B program +-line and it should be give only one program. +- +- +-.TP +-.B CREATE +-The +-.B create +-line gives default values to be used when creating arrays, new members +-of arrays, and device entries for arrays. +-These include: +- +-.RS 4 +-.TP +-.B owner= +-.TP +-.B group= +-These can give user/group ids or names to use instead of system +-defaults (root/wheel or root/disk). +-.TP +-.B mode= +-An octal file mode such as 0660 can be given to override the default +-of 0600. +-.TP +-.B auto= +-This corresponds to the +-.B \-\-auto +-flag to mdadm. Give +-.BR yes , +-.BR md , +-.BR mdp , +-.B part +-\(em possibly followed by a number of partitions \(em to indicate how +-missing device entries should be created. +- +-.TP +-.B metadata= +-The name of the metadata format to use if none is explicitly given. +-This can be useful to impose a system-wide default of version-1 superblocks. +- +-.TP +-.B symlinks=no +-Normally when creating devices in +-.B /dev/md/ +-.I mdadm +-will create a matching symlink from +-.B /dev/ +-with a name starting +-.B md +-or +-.BR md_ . +-Give +-.B symlinks=no +-to suppress this symlink creation. +- +-.TP +-.B names=yes +-Since Linux 2.6.29 it has been possible to create +-.B md +-devices with a name like +-.B md_home +-rather than just a number, like +-.BR md3 . +-.I mdadm +-will use the numeric alternative by default as other tools that interact +-with md arrays may expect only numbers. +-If +-.B names=yes +-is given in +-.I mdadm.conf +-then +-.I mdadm +-will use a name when appropriate. +-If +-.B names=no +-is given, then non-numeric +-.I md +-device names will not be used even if the default changes in a future +-release of +-.IR mdadm . +- +-.TP +-.B bbl=no +-By default, +-.I mdadm +-will reserve space for a bad block list (bbl) on all devices +-included in or added to any array that supports them. Setting +-.B bbl=no +-will prevent this, so newly added devices will not have a bad +-block log. +-.RE +- +-.TP +-.B HOMEHOST +-The +-.B homehost +-line gives a default value for the +-.B \-\-homehost= +-option to mdadm. There should normally be only one other word on the line. +-It should either be a host name, or one of the special words +-.BR , +-.B +-and +-.BR . +-If +-.B +-is given, then the +-.BR gethostname ( 2 ) +-systemcall is used to get the host name. This is the default. +- +-If +-.B +-is given, then a flag is set so that when arrays are being +-auto-assembled the checking of the recorded +-.I homehost +-is disabled. +-If +-.B +-is given it is also possible to give an explicit name which will be +-used when creating arrays. This is the only case when there can be +-more that one other word on the +-.B HOMEHOST +-line. If there are other words, or other +-.B HOMEHOST +-lines, they are silently ignored. +- +-If +-.B +-is given, then the default of using +-.BR gethostname ( 2 ) +-is over-ridden and no homehost name is assumed. +- +-When arrays are created, this host name will be stored in the +-metadata. When arrays are assembled using auto-assembly, arrays which +-do not record the correct homehost name in their metadata will be +-assembled using a "foreign" name. A "foreign" name alway ends with a +-digit string preceded by an underscore to differentiate it +-from any possible local name. e.g. +-.B /dev/md/1_1 +-or +-.BR /dev/md/home_0 . +-.TP +-.B AUTO +-A list of names of metadata format can be given, each preceded by a +-plus or minus sign. Also the word +-.I homehost +-is allowed as is +-.I all +-preceded by plus or minus sign. +-.I all +-is usually last. +- +-When +-.I mdadm +-is auto-assembling an array, either via +-.I \-\-assemble +-or +-.I \-\-incremental +-and it finds metadata of a given type, it checks that metadata type +-against those listed in this line. The first match wins, where +-.I all +-matches anything. +-If a match is found that was preceded by a plus sign, the auto +-assembly is allowed. If the match was preceded by a minus sign, the +-auto assembly is disallowed. If no match is found, the auto assembly +-is allowed. +- +-If the metadata indicates that the array was created for +-.I this +-host, and the word +-.I homehost +-appears before any other match, then the array is treated as a valid +-candidate for auto-assembly. +- +-This can be used to disable all auto-assembly (so that only arrays +-explicitly listed in mdadm.conf or on the command line are assembled), +-or to disable assembly of certain metadata types which might be +-handled by other software. It can also be used to disable assembly of +-all foreign arrays - normally such arrays are assembled but given a +-non-deterministic name in +-.BR /dev/md/ . +- +-The known metadata types are +-.BR 0.90 , +-.BR 1.x , +-.BR ddf , +-.BR imsm . +- +-.B AUTO +-should be given at most once. Subsequent lines are silently ignored. +-Thus an earlier config file in a config directory will over-ride +-the setting in a later config file. +- +-.TP +-.B POLICY +-This is used to specify what automatic behavior is allowed on devices +-newly appearing in the system and provides a way of marking spares that can +-be moved to other arrays as well as the migration domains. +-.I Domain +-can be defined through +-.I policy +-line by specifying a domain name for a number of paths from +-.BR /dev/disk/by-path/ . +-A device may belong to several domains. The domain of an array is a union +-of domains of all devices in that array. A spare can be automatically +-moved from one array to another if the set of the destination array's +-.I domains +-contains all the +-.I domains +-of the new disk or if both arrays have the same +-.IR spare-group . +- +-To update hot plug configuration it is necessary to execute +-.B mdadm \-\-udev\-rules +-command after changing the config file +- +-Keywords used in the +-.I POLICY +-line and supported values are: +- +-.RS 4 +-.TP +-.B domain= +-any arbitrary string +-.TP +-.B metadata= +-0.9 1.x ddf or imsm +-.TP +-.B path= +-file glob matching anything from +-.B /dev/disk/by-path +-.TP +-.B type= +-either +-.B disk +-or +-.BR part . +-.TP +-.B action= +-include, re-add, spare, spare-same-slot, or force-spare +-.TP +-.B auto= +-yes, no, or homehost. +- +-.P +-The +-.I action +-item determines the automatic behavior allowed for devices matching the +-.I path +-and +-.I type +-in the same line. If a device matches several lines with different +-.I actions +-then the most permissive will apply. The ordering of policy lines +-is irrelevant to the end result. +-.TP +-.B include +-allows adding a disk to an array if metadata on that disk matches that array +-.TP +-.B re\-add +-will include the device in the array if it appears to be a current member +-or a member that was recently removed and the array has a +-write-intent-bitmap to allow the +-.B re\-add +-functionality. +-.TP +-.B spare +-as above and additionally: if the device is bare it can +-become a spare if there is any array that it is a candidate for based +-on domains and metadata. +-.TP +-.B spare\-same\-slot +-as above and additionally if given slot was used by an array that went +-degraded recently and the device plugged in has no metadata then it will +-be automatically added to that array (or it's container) +-.TP +-.B force\-spare +-as above and the disk will become a spare in remaining cases +-.RE +- +-.TP +-.B PART-POLICY +-This is similar to +-.B POLICY +-and accepts the same keyword assignments. It allows a consistent set +-of policies to applied to each of the partitions of a device. +- +-A +-.B PART-POLICY +-line should set +-.I type=disk +-and identify the path to one or more disk devices. Each partition on +-these disks will be treated according to the +-.I action= +-setting from this line. If a +-.I domain +-is set in the line, then the domain associated with each patition will +-be based on the domain, but with +-.RB \(dq -part N\(dq +-appended, when N is the partition number for the partition that was +-found. +- +-.TP +-.B SYSFS +-The +-.B SYSFS +-line lists custom values of MD device's sysfs attributes which will be +-stored in sysfs after the array is assembled. Multiple lines are allowed and each +-line has to contain the uuid or the name of the device to which it relates. +-.RS 4 +-.TP +-.B uuid= +-hexadecimal identifier of MD device. This has to match the uuid stored in the +-superblock. +-.TP +-.B name= +-name of the MD device as was given to +-.I mdadm +-when the array was created. It will be ignored if +-.B uuid +-is not empty. +-.RE +- +-.TP +-.B MONITORDELAY +-The +-.B monitordelay +-line gives a delay in seconds +-.I mdadm +-shall wait before pooling md arrays +-when +-.I mdadm +-is running in +-.B \-\-monitor +-mode. +-.B \-d/\-\-delay +-command line argument takes precedence over the config file +- +-.SH EXAMPLE +-DEVICE /dev/sd[bcdjkl]1 +-.br +-DEVICE /dev/hda1 /dev/hdb1 +- +-# /dev/md0 is known by its UUID. +-.br +-ARRAY /dev/md0 UUID=3aaa0122:29827cfa:5331ad66:ca767371 +-.br +-# /dev/md1 contains all devices with a minor number of +-.br +-# 1 in the superblock. +-.br +-ARRAY /dev/md1 superminor=1 +-.br +-# /dev/md2 is made from precisely these two devices +-.br +-ARRAY /dev/md2 devices=/dev/hda1,/dev/hdb1 +- +-# /dev/md4 and /dev/md5 are a spare-group and spares +-.br +-# can be moved between them +-.br +-ARRAY /dev/md4 uuid=b23f3c6d:aec43a9f:fd65db85:369432df +-.br +- spare\-group=group1 +-.br +-ARRAY /dev/md5 uuid=19464854:03f71b1b:e0df2edd:246cc977 +-.br +- spare\-group=group1 +-.br +-# /dev/md/home is created if need to be a partitionable md array +-.br +-# any spare device number is allocated. +-.br +-ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b +-.br +- auto=part +-.br +-# The name of this array contains a space. +-.br +-ARRAY /dev/md9 name='Data Storage' +-.sp +-POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-* +-.br +- action=spare +-.br +-POLICY domain=domain1 metadata=imsm path=pci-0000:04:00.0-scsi-[01]* +-.br +- action=include +-.br +-# One domain comprising of devices attached to specified paths is defined. +-.br +-# Bare device matching first path will be made an imsm spare on hot plug. +-.br +-# If more than one array is created on devices belonging to domain1 and +-.br +-# one of them becomes degraded, then any imsm spare matching any path for +-.br +-# given domain name can be migrated. +-.br +-MAILADDR root@mydomain.tld +-.br +-PROGRAM /usr/sbin/handle\-mdadm\-events +-.br +-CREATE group=system mode=0640 auto=part\-8 +-.br +-HOMEHOST +-.br +-AUTO +1.x homehost \-all +-.br +-SYSFS name=/dev/md/raid5 group_thread_cnt=4 sync_speed_max=1000000 +-.br +-SYSFS uuid=bead5eb6:31c17a27:da120ba2:7dfda40d group_thread_cnt=4 +-sync_speed_max=1000000 +-.br +-MONITORDELAY 60 +- +-.SH SEE ALSO +-.BR mdadm (8), +-.BR md (4). +diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in +new file mode 100644 +index 00000000..83edd008 +--- /dev/null ++++ b/mdadm.conf.5.in +@@ -0,0 +1,706 @@ ++.\" Copyright Neil Brown and others. ++.\" This program is free software; you can redistribute it and/or modify ++.\" it under the terms of the GNU General Public License as published by ++.\" the Free Software Foundation; either version 2 of the License, or ++.\" (at your option) any later version. ++.\" See file COPYING in distribution for details. ++.TH MDADM.CONF 5 ++.SH NAME ++mdadm.conf \- configuration for management of Software RAID with mdadm ++.SH SYNOPSIS ++{CONFFILE} ++.SH DESCRIPTION ++.PP ++.I mdadm ++is a tool for creating, managing, and monitoring RAID devices using the ++.B md ++driver in Linux. ++.PP ++Some common tasks, such as assembling all arrays, can be simplified ++by describing the devices and arrays in this configuration file. ++ ++.SS SYNTAX ++The file should be seen as a collection of words separated by white ++space (space, tab, or newline). ++Any word that beings with a hash sign (#) starts a comment and that ++word together with the remainder of the line is ignored. ++ ++Spaces can be included in a word using quotation characters. Either ++single quotes ++.RB ( ' ) ++or double quotes (\fB"\fP) ++may be used. All the characters from one quotation character to ++next identical character are protected and will not be used to ++separate words to start new quoted strings. To include a single quote ++it must be between double quotes. To include a double quote it must ++be between single quotes. ++ ++Any line that starts with white space (space or tab) is treated as ++though it were a continuation of the previous line. ++ ++Empty lines are ignored, but otherwise each (non continuation) line ++must start with a keyword as listed below. The keywords are case ++insensitive and can be abbreviated to 3 characters. ++ ++The keywords are: ++.TP ++.B DEVICE ++A ++.B device ++line lists the devices (whole devices or partitions) that might contain ++a component of an MD array. When looking for the components of an ++array, ++.I mdadm ++will scan these devices (or any devices listed on the command line). ++ ++The ++.B device ++line may contain a number of different devices (separated by spaces) ++and each device name can contain wild cards as defined by ++.BR glob (7). ++ ++Also, there may be several device lines present in the file. ++ ++Alternatively, a ++.B device ++line can contain either or both of the words ++.B containers ++and ++.BR partitions . ++The word ++.B containers ++will cause ++.I mdadm ++to look for assembled CONTAINER arrays and included them as a source ++for assembling further arrays. ++ ++The word ++.I partitions ++will cause ++.I mdadm ++to read ++.I /proc/partitions ++and include all devices and partitions found therein. ++.I mdadm ++does not use the names from ++.I /proc/partitions ++but only the major and minor device numbers. It scans ++.I /dev ++to find the name that matches the numbers. ++ ++If no DEVICE line is present, then "DEVICE partitions containers" is assumed. ++ ++For example: ++.IP ++DEVICE /dev/hda* /dev/hdc* ++.br ++DEV /dev/sd* ++.br ++DEVICE /dev/disk/by-path/pci* ++.br ++DEVICE partitions ++ ++.TP ++.B ARRAY ++The ARRAY lines identify actual arrays. The second word on the line ++may be the name of the device where the array is normally ++assembled, such as ++.B /dev/md1 ++or ++.BR /dev/md/backup . ++If the name does not start with a slash ++.RB (' / '), ++it is treated as being in ++.BR /dev/md/ . ++Alternately the word ++.B ++(complete with angle brackets) can be given in which case any array ++which matches the rest of the line will never be automatically assembled. ++If no device name is given, ++.I mdadm ++will use various heuristics to determine an appropriate name. ++ ++Subsequent words identify the array, or identify the array as a member ++of a group. If multiple identities are given, ++then a component device must match ALL identities to be considered a ++match. Each identity word has a tag, and equals sign, and some value. ++The tags are: ++.RS 4 ++.TP ++.B uuid= ++The value should be a 128 bit uuid in hexadecimal, with punctuation ++interspersed if desired. This must match the uuid stored in the ++superblock. ++.TP ++.B name= ++The value should be a simple textual name as was given to ++.I mdadm ++when the array was created. This must match the name stored in the ++superblock on a device for that device to be included in the array. ++Not all superblock formats support names. ++.TP ++.B super\-minor= ++The value is an integer which indicates the minor number that was ++stored in the superblock when the array was created. When an array is ++created as /dev/mdX, then the minor number X is stored. ++.TP ++.B devices= ++The value is a comma separated list of device names or device name ++patterns. ++Only devices with names which match one entry in the list will be used ++to assemble the array. Note that the devices ++listed there must also be listed on a DEVICE line. ++.TP ++.B level= ++The value is a RAID level. This is not normally used to ++identify an array, but is supported so that the output of ++ ++.B "mdadm \-\-examine \-\-scan" ++ ++can be use directly in the configuration file. ++.TP ++.B num\-devices= ++The value is the number of devices in a complete active array. As with ++.B level= ++this is mainly for compatibility with the output of ++ ++.BR "mdadm \-\-examine \-\-scan" . ++ ++.TP ++.B spares= ++The value is a number of spare devices to expect the array to have. ++The sole use of this keyword and value is as follows: ++.B mdadm \-\-monitor ++will report an array if it is found to have fewer than this number of ++spares when ++.B \-\-monitor ++starts or when ++.B \-\-oneshot ++is used. ++ ++.TP ++.B spare\-group= ++The value is a textual name for a group of arrays. All arrays with ++the same ++.B spare\-group ++name are considered to be part of the same group. The significance of ++a group of arrays is that ++.I mdadm ++will, when monitoring the arrays, move a spare drive from one array in ++a group to another array in that group if the first array had a failed ++or missing drive but no spare. ++ ++.TP ++.B auto= ++This option is rarely needed with mdadm-3.0, particularly if use with ++the Linux kernel v2.6.28 or later. ++It tells ++.I mdadm ++whether to use partitionable array or non-partitionable arrays and, ++in the absence of ++.IR udev , ++how many partition devices to create. From 2.6.28 all md array ++devices are partitionable, hence this option is not needed. ++ ++The value of this option can be "yes" or "md" to indicate that a ++traditional, non-partitionable md array should be created, or "mdp", ++"part" or "partition" to indicate that a partitionable md array (only ++available in linux 2.6 and later) should be used. This later set can ++also have a number appended to indicate how many partitions to create ++device files for, e.g. ++.BR auto=mdp5 . ++The default is 4. ++ ++.TP ++.B bitmap= ++The option specifies a file in which a write-intent bitmap should be ++found. When assembling the array, ++.I mdadm ++will provide this file to the ++.B md ++driver as the bitmap file. This has the same function as the ++.B \-\-bitmap\-file ++option to ++.BR \-\-assemble . ++ ++.TP ++.B metadata= ++Specify the metadata format that the array has. This is mainly ++recognised for comparability with the output of ++.BR "mdadm \-Es" . ++ ++.TP ++.B container= ++Specify that this array is a member array of some container. The ++value given can be either a path name in /dev, or a UUID of the ++container array. ++ ++.TP ++.B member= ++Specify that this array is a member array of some container. Each ++type of container has some way to enumerate member arrays, often a ++simple sequence number. The value identifies which member of a ++container the array is. It will usually accompany a "container=" word. ++.RE ++ ++.TP ++.B MAILADDR ++The ++.B mailaddr ++line gives an E-mail address that alerts should be ++sent to when ++.I mdadm ++is running in ++.B \-\-monitor ++mode (and was given the ++.B \-\-scan ++option). There should only be one ++.B MAILADDR ++line and it should have only one address. Any subsequent addresses ++are silently ignored. ++ ++.TP ++.B MAILFROM ++The ++.B mailfrom ++line (which can only be abbreviated to at least 5 characters) gives an ++address to appear in the "From" address for alert mails. This can be ++useful if you want to explicitly set a domain, as the default from ++address is "root" with no domain. All words on this line are ++catenated with spaces to form the address. ++ ++Note that this value cannot be set via the ++.I mdadm ++commandline. It is only settable via the config file. ++ ++.TP ++.B PROGRAM ++The ++.B program ++line gives the name of a program to be run when ++.B "mdadm \-\-monitor" ++detects potentially interesting events on any of the arrays that it ++is monitoring. This program gets run with two or three arguments, they ++being the Event, the md device, and possibly the related component ++device. ++ ++There should only be one ++.B program ++line and it should be give only one program. ++ ++ ++.TP ++.B CREATE ++The ++.B create ++line gives default values to be used when creating arrays, new members ++of arrays, and device entries for arrays. ++These include: ++ ++.RS 4 ++.TP ++.B owner= ++.TP ++.B group= ++These can give user/group ids or names to use instead of system ++defaults (root/wheel or root/disk). ++.TP ++.B mode= ++An octal file mode such as 0660 can be given to override the default ++of 0600. ++.TP ++.B auto= ++This corresponds to the ++.B \-\-auto ++flag to mdadm. Give ++.BR yes , ++.BR md , ++.BR mdp , ++.B part ++\(em possibly followed by a number of partitions \(em to indicate how ++missing device entries should be created. ++ ++.TP ++.B metadata= ++The name of the metadata format to use if none is explicitly given. ++This can be useful to impose a system-wide default of version-1 superblocks. ++ ++.TP ++.B symlinks=no ++Normally when creating devices in ++.B /dev/md/ ++.I mdadm ++will create a matching symlink from ++.B /dev/ ++with a name starting ++.B md ++or ++.BR md_ . ++Give ++.B symlinks=no ++to suppress this symlink creation. ++ ++.TP ++.B names=yes ++Since Linux 2.6.29 it has been possible to create ++.B md ++devices with a name like ++.B md_home ++rather than just a number, like ++.BR md3 . ++.I mdadm ++will use the numeric alternative by default as other tools that interact ++with md arrays may expect only numbers. ++If ++.B names=yes ++is given in ++.I mdadm.conf ++then ++.I mdadm ++will use a name when appropriate. ++If ++.B names=no ++is given, then non-numeric ++.I md ++device names will not be used even if the default changes in a future ++release of ++.IR mdadm . ++ ++.TP ++.B bbl=no ++By default, ++.I mdadm ++will reserve space for a bad block list (bbl) on all devices ++included in or added to any array that supports them. Setting ++.B bbl=no ++will prevent this, so newly added devices will not have a bad ++block log. ++.RE ++ ++.TP ++.B HOMEHOST ++The ++.B homehost ++line gives a default value for the ++.B \-\-homehost= ++option to mdadm. There should normally be only one other word on the line. ++It should either be a host name, or one of the special words ++.BR , ++.B ++and ++.BR . ++If ++.B ++is given, then the ++.BR gethostname ( 2 ) ++systemcall is used to get the host name. This is the default. ++ ++If ++.B ++is given, then a flag is set so that when arrays are being ++auto-assembled the checking of the recorded ++.I homehost ++is disabled. ++If ++.B ++is given it is also possible to give an explicit name which will be ++used when creating arrays. This is the only case when there can be ++more that one other word on the ++.B HOMEHOST ++line. If there are other words, or other ++.B HOMEHOST ++lines, they are silently ignored. ++ ++If ++.B ++is given, then the default of using ++.BR gethostname ( 2 ) ++is over-ridden and no homehost name is assumed. ++ ++When arrays are created, this host name will be stored in the ++metadata. When arrays are assembled using auto-assembly, arrays which ++do not record the correct homehost name in their metadata will be ++assembled using a "foreign" name. A "foreign" name alway ends with a ++digit string preceded by an underscore to differentiate it ++from any possible local name. e.g. ++.B /dev/md/1_1 ++or ++.BR /dev/md/home_0 . ++.TP ++.B AUTO ++A list of names of metadata format can be given, each preceded by a ++plus or minus sign. Also the word ++.I homehost ++is allowed as is ++.I all ++preceded by plus or minus sign. ++.I all ++is usually last. ++ ++When ++.I mdadm ++is auto-assembling an array, either via ++.I \-\-assemble ++or ++.I \-\-incremental ++and it finds metadata of a given type, it checks that metadata type ++against those listed in this line. The first match wins, where ++.I all ++matches anything. ++If a match is found that was preceded by a plus sign, the auto ++assembly is allowed. If the match was preceded by a minus sign, the ++auto assembly is disallowed. If no match is found, the auto assembly ++is allowed. ++ ++If the metadata indicates that the array was created for ++.I this ++host, and the word ++.I homehost ++appears before any other match, then the array is treated as a valid ++candidate for auto-assembly. ++ ++This can be used to disable all auto-assembly (so that only arrays ++explicitly listed in mdadm.conf or on the command line are assembled), ++or to disable assembly of certain metadata types which might be ++handled by other software. It can also be used to disable assembly of ++all foreign arrays - normally such arrays are assembled but given a ++non-deterministic name in ++.BR /dev/md/ . ++ ++The known metadata types are ++.BR 0.90 , ++.BR 1.x , ++.BR ddf , ++.BR imsm . ++ ++.B AUTO ++should be given at most once. Subsequent lines are silently ignored. ++Thus an earlier config file in a config directory will over-ride ++the setting in a later config file. ++ ++.TP ++.B POLICY ++This is used to specify what automatic behavior is allowed on devices ++newly appearing in the system and provides a way of marking spares that can ++be moved to other arrays as well as the migration domains. ++.I Domain ++can be defined through ++.I policy ++line by specifying a domain name for a number of paths from ++.BR /dev/disk/by-path/ . ++A device may belong to several domains. The domain of an array is a union ++of domains of all devices in that array. A spare can be automatically ++moved from one array to another if the set of the destination array's ++.I domains ++contains all the ++.I domains ++of the new disk or if both arrays have the same ++.IR spare-group . ++ ++To update hot plug configuration it is necessary to execute ++.B mdadm \-\-udev\-rules ++command after changing the config file ++ ++Keywords used in the ++.I POLICY ++line and supported values are: ++ ++.RS 4 ++.TP ++.B domain= ++any arbitrary string ++.TP ++.B metadata= ++0.9 1.x ddf or imsm ++.TP ++.B path= ++file glob matching anything from ++.B /dev/disk/by-path ++.TP ++.B type= ++either ++.B disk ++or ++.BR part . ++.TP ++.B action= ++include, re-add, spare, spare-same-slot, or force-spare ++.TP ++.B auto= ++yes, no, or homehost. ++ ++.P ++The ++.I action ++item determines the automatic behavior allowed for devices matching the ++.I path ++and ++.I type ++in the same line. If a device matches several lines with different ++.I actions ++then the most permissive will apply. The ordering of policy lines ++is irrelevant to the end result. ++.TP ++.B include ++allows adding a disk to an array if metadata on that disk matches that array ++.TP ++.B re\-add ++will include the device in the array if it appears to be a current member ++or a member that was recently removed and the array has a ++write-intent-bitmap to allow the ++.B re\-add ++functionality. ++.TP ++.B spare ++as above and additionally: if the device is bare it can ++become a spare if there is any array that it is a candidate for based ++on domains and metadata. ++.TP ++.B spare\-same\-slot ++as above and additionally if given slot was used by an array that went ++degraded recently and the device plugged in has no metadata then it will ++be automatically added to that array (or it's container) ++.TP ++.B force\-spare ++as above and the disk will become a spare in remaining cases ++.RE ++ ++.TP ++.B PART-POLICY ++This is similar to ++.B POLICY ++and accepts the same keyword assignments. It allows a consistent set ++of policies to applied to each of the partitions of a device. ++ ++A ++.B PART-POLICY ++line should set ++.I type=disk ++and identify the path to one or more disk devices. Each partition on ++these disks will be treated according to the ++.I action= ++setting from this line. If a ++.I domain ++is set in the line, then the domain associated with each patition will ++be based on the domain, but with ++.RB \(dq -part N\(dq ++appended, when N is the partition number for the partition that was ++found. ++ ++.TP ++.B SYSFS ++The ++.B SYSFS ++line lists custom values of MD device's sysfs attributes which will be ++stored in sysfs after the array is assembled. Multiple lines are allowed and each ++line has to contain the uuid or the name of the device to which it relates. ++.RS 4 ++.TP ++.B uuid= ++hexadecimal identifier of MD device. This has to match the uuid stored in the ++superblock. ++.TP ++.B name= ++name of the MD device as was given to ++.I mdadm ++when the array was created. It will be ignored if ++.B uuid ++is not empty. ++.RE ++ ++.TP ++.B MONITORDELAY ++The ++.B monitordelay ++line gives a delay in seconds ++.I mdadm ++shall wait before pooling md arrays ++when ++.I mdadm ++is running in ++.B \-\-monitor ++mode. ++.B \-d/\-\-delay ++command line argument takes precedence over the config file ++ ++.SH EXAMPLE ++DEVICE /dev/sd[bcdjkl]1 ++.br ++DEVICE /dev/hda1 /dev/hdb1 ++ ++# /dev/md0 is known by its UUID. ++.br ++ARRAY /dev/md0 UUID=3aaa0122:29827cfa:5331ad66:ca767371 ++.br ++# /dev/md1 contains all devices with a minor number of ++.br ++# 1 in the superblock. ++.br ++ARRAY /dev/md1 superminor=1 ++.br ++# /dev/md2 is made from precisely these two devices ++.br ++ARRAY /dev/md2 devices=/dev/hda1,/dev/hdb1 ++ ++# /dev/md4 and /dev/md5 are a spare-group and spares ++.br ++# can be moved between them ++.br ++ARRAY /dev/md4 uuid=b23f3c6d:aec43a9f:fd65db85:369432df ++.br ++ spare\-group=group1 ++.br ++ARRAY /dev/md5 uuid=19464854:03f71b1b:e0df2edd:246cc977 ++.br ++ spare\-group=group1 ++.br ++# /dev/md/home is created if need to be a partitionable md array ++.br ++# any spare device number is allocated. ++.br ++ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b ++.br ++ auto=part ++.br ++# The name of this array contains a space. ++.br ++ARRAY /dev/md9 name='Data Storage' ++.sp ++POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-* ++.br ++ action=spare ++.br ++POLICY domain=domain1 metadata=imsm path=pci-0000:04:00.0-scsi-[01]* ++.br ++ action=include ++.br ++# One domain comprising of devices attached to specified paths is defined. ++.br ++# Bare device matching first path will be made an imsm spare on hot plug. ++.br ++# If more than one array is created on devices belonging to domain1 and ++.br ++# one of them becomes degraded, then any imsm spare matching any path for ++.br ++# given domain name can be migrated. ++.br ++MAILADDR root@mydomain.tld ++.br ++PROGRAM /usr/sbin/handle\-mdadm\-events ++.br ++CREATE group=system mode=0640 auto=part\-8 ++.br ++HOMEHOST ++.br ++AUTO +1.x homehost \-all ++.br ++SYSFS name=/dev/md/raid5 group_thread_cnt=4 sync_speed_max=1000000 ++.br ++SYSFS uuid=bead5eb6:31c17a27:da120ba2:7dfda40d group_thread_cnt=4 ++sync_speed_max=1000000 ++.br ++MONITORDELAY 60 ++ ++.SH SEE ALSO ++.BR mdadm (8), ++.BR md (4). +-- +2.38.1 + diff --git a/0007-mdadm-Update-ReadMe.patch b/0007-mdadm-Update-ReadMe.patch new file mode 100644 index 0000000..a143a22 --- /dev/null +++ b/0007-mdadm-Update-ReadMe.patch @@ -0,0 +1,48 @@ +From c23400377bb3d8e98e810cd92dba478dac1dff82 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 18 Mar 2022 09:26:05 +0100 +Subject: [PATCH 07/83] mdadm: Update ReadMe + +Instead of hardcoded config file path give reference to config manual. + +Add missing monitordelay and homecluster parameters. + +Signed-off-by: Lukasz Florczak +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + ReadMe.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/ReadMe.c b/ReadMe.c +index 81399765..8f873c48 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -613,7 +613,6 @@ char Help_incr[] = + ; + + char Help_config[] = +-"The /etc/mdadm.conf config file:\n\n" + " The config file contains, apart from blank lines and comment lines that\n" + " start with a hash(#), array lines, device lines, and various\n" + " configuration lines.\n" +@@ -636,10 +635,12 @@ char Help_config[] = + " than a device must match all of them to be considered.\n" + "\n" + " Other configuration lines include:\n" +-" mailaddr, mailfrom, program used for --monitor mode\n" +-" create, auto used when creating device names in /dev\n" +-" homehost, policy, part-policy used to guide policy in various\n" +-" situations\n" ++" mailaddr, mailfrom, program, monitordelay used for --monitor mode\n" ++" create, auto used when creating device names in /dev\n" ++" homehost, homecluster, policy, part-policy used to guide policy in various\n" ++" situations\n" ++"\n" ++"For more details see mdadm.conf(5).\n" + "\n" + ; + +-- +2.38.1 + diff --git a/0008-mdadm-Update-config-man-regarding-default-files-and-.patch b/0008-mdadm-Update-config-man-regarding-default-files-and-.patch new file mode 100644 index 0000000..0109e9a --- /dev/null +++ b/0008-mdadm-Update-config-man-regarding-default-files-and-.patch @@ -0,0 +1,203 @@ +From 24e075c659d0a8718aabefe5af4c97195a188af7 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 18 Mar 2022 09:26:06 +0100 +Subject: [PATCH 08/83] mdadm: Update config man regarding default files and + multi-keyword behavior + +Simplify default and alternative config file and directory location references +from mdadm(8) as references to mdadm.conf(5). Add FILE section in config man +and explain order and conditions in which default and alternative config files +and directories are used. + +Update config man behavior regarding parsing order when multiple keywords/config +files are involved. + +Signed-off-by: Lukasz Florczak +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 30 +++++++++-------------- + mdadm.conf.5.in | 65 ++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 71 insertions(+), 24 deletions(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index 8b21ffd4..0be02e4a 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -266,14 +266,11 @@ the exact meaning of this option in different contexts. + + .TP + .BR \-c ", " \-\-config= +-Specify the config file or directory. Default is to use +-.B {CONFFILE} +-and +-.BR {CONFFILE}.d , +-or if those are missing then +-.B {CONFFILE2} +-and +-.BR {CONFFILE2}.d . ++Specify the config file or directory. If not specified, default config file ++and default conf.d directory will be used. See ++.BR mdadm.conf (5) ++for more details. ++ + If the config file given is + .B "partitions" + then nothing will be read, but +@@ -2013,11 +2010,9 @@ The config file is only used if explicitly named with + .B \-\-config + or requested with (a possibly implicit) + .BR \-\-scan . +-In the later case, +-.B {CONFFILE} +-or +-.B {CONFFILE2} +-is used. ++In the later case, default config file is used. See ++.BR mdadm.conf (5) ++for more details. + + If + .B \-\-scan +@@ -3346,16 +3341,15 @@ on Monitor mode. + + .SS {CONFFILE} (or {CONFFILE2}) + +-The config file lists which devices may be scanned to see if +-they contain MD super block, and gives identifying information +-(e.g. UUID) about known MD arrays. See ++Default config file. See + .BR mdadm.conf (5) + for more details. + + .SS {CONFFILE}.d (or {CONFFILE2}.d) + +-A directory containing configuration files which are read in lexical +-order. ++Default directory containing configuration files. See ++.BR mdadm.conf (5) ++for more details. + + .SS {MAP_PATH} + When +diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in +index 83edd008..dd331a6a 100644 +--- a/mdadm.conf.5.in ++++ b/mdadm.conf.5.in +@@ -88,7 +88,8 @@ but only the major and minor device numbers. It scans + .I /dev + to find the name that matches the numbers. + +-If no DEVICE line is present, then "DEVICE partitions containers" is assumed. ++If no DEVICE line is present in any config file, ++then "DEVICE partitions containers" is assumed. + + For example: + .IP +@@ -272,6 +273,10 @@ catenated with spaces to form the address. + Note that this value cannot be set via the + .I mdadm + commandline. It is only settable via the config file. ++There should only be one ++.B MAILADDR ++line and it should have only one address. Any subsequent addresses ++are silently ignored. + + .TP + .B PROGRAM +@@ -286,7 +291,8 @@ device. + + There should only be one + .B program +-line and it should be give only one program. ++line and it should be given only one program. Any subsequent programs ++are silently ignored. + + + .TP +@@ -295,7 +301,14 @@ The + .B create + line gives default values to be used when creating arrays, new members + of arrays, and device entries for arrays. +-These include: ++ ++There should only be one ++.B create ++line. Any subsequent lines will override the previous settings. ++ ++Keywords used in the ++.I CREATE ++line and supported values are: + + .RS 4 + .TP +@@ -475,8 +488,8 @@ The known metadata types are + + .B AUTO + should be given at most once. Subsequent lines are silently ignored. +-Thus an earlier config file in a config directory will over-ride +-the setting in a later config file. ++Thus a later config file in a config directory will not overwrite ++the setting in an earlier config file. + + .TP + .B POLICY +@@ -594,6 +607,7 @@ The + line lists custom values of MD device's sysfs attributes which will be + stored in sysfs after the array is assembled. Multiple lines are allowed and each + line has to contain the uuid or the name of the device to which it relates. ++Lines are applied in reverse order. + .RS 4 + .TP + .B uuid= +@@ -621,7 +635,46 @@ is running in + .B \-\-monitor + mode. + .B \-d/\-\-delay +-command line argument takes precedence over the config file ++command line argument takes precedence over the config file. ++ ++If multiple ++.B MINITORDELAY ++lines are provided, only first non-zero value is considered. ++ ++.SH FILES ++ ++.SS {CONFFILE} ++ ++The default config file location, used when ++.I mdadm ++is running without --config option. ++ ++.SS {CONFFILE}.d ++ ++The default directory with config files. Used when ++.I mdadm ++is running without --config option, after successful reading of the ++.B {CONFFILE} ++default config file. Files in that directory ++are read in lexical order. ++ ++ ++.SS {CONFFILE2} ++ ++Alternative config file that is read, when ++.I mdadm ++is running without --config option and the ++.B {CONFFILE} ++default config file was not opened successfully. ++ ++.SS {CONFFILE2}.d ++ ++The alternative directory with config files. Used when ++.I mdadm ++is runninng without --config option, after reading the ++.B {CONFFILE2} ++alternative config file whether it was successful or not. Files in ++that directory are read in lexical order. + + .SH EXAMPLE + DEVICE /dev/sd[bcdjkl]1 +-- +2.38.1 + diff --git a/0009-mdadm-Update-config-manual.patch b/0009-mdadm-Update-config-manual.patch new file mode 100644 index 0000000..08599d5 --- /dev/null +++ b/0009-mdadm-Update-config-manual.patch @@ -0,0 +1,45 @@ +From c33bbda5b0e127bb161fd4ad44bcfaa2a5daf153 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 18 Mar 2022 09:26:07 +0100 +Subject: [PATCH 09/83] mdadm: Update config manual + +Add missing HOMECLUSTER keyword description. + +Signed-off-by: Lukasz Florczak +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + mdadm.conf.5.in | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in +index dd331a6a..cd4e6a9d 100644 +--- a/mdadm.conf.5.in ++++ b/mdadm.conf.5.in +@@ -439,6 +439,23 @@ from any possible local name. e.g. + .B /dev/md/1_1 + or + .BR /dev/md/home_0 . ++ ++.TP ++.B HOMECLUSTER ++The ++.B homcluster ++line gives a default value for the ++.B \-\-homecluster= ++option to mdadm. It specifies the cluster name for the md device. ++The md device can be assembled only on the cluster which matches ++the name specified. If ++.B homcluster ++is not provided, mdadm tries to detect the cluster name automatically. ++ ++There should only be one ++.B homecluster ++line. Any subsequent lines will be silently ignored. ++ + .TP + .B AUTO + A list of names of metadata format can be given, each preceded by a +-- +2.38.1 + diff --git a/0010-Create-Build-use-default_layout.patch b/0010-Create-Build-use-default_layout.patch new file mode 100644 index 0000000..7f9791b --- /dev/null +++ b/0010-Create-Build-use-default_layout.patch @@ -0,0 +1,153 @@ +From 913f07d1db4a0078acc26d6ccabe1c315cf9273c Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 20 Jan 2022 13:18:32 +0100 +Subject: [PATCH 10/83] Create, Build: use default_layout() + +This code is duplicated for Build mode so make default_layout() extern +and use it. Simplify the function structure. + +It introduced change for Build mode, now for raid0 RAID0_ORIG_LAYOUT +will be returned same as for Create. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Build.c | 23 +------------------ + Create.c | 67 ++++++++++++++++++++++++++++++++++---------------------- + mdadm.h | 1 + + 3 files changed, 43 insertions(+), 48 deletions(-) + +diff --git a/Build.c b/Build.c +index 962c2e37..8d6f6f58 100644 +--- a/Build.c ++++ b/Build.c +@@ -71,28 +71,7 @@ int Build(char *mddev, struct mddev_dev *devlist, + } + + if (s->layout == UnSet) +- switch(s->level) { +- default: /* no layout */ +- s->layout = 0; +- break; +- case 10: +- s->layout = 0x102; /* near=2, far=1 */ +- if (c->verbose > 0) +- pr_err("layout defaults to n1\n"); +- break; +- case 5: +- case 6: +- s->layout = map_name(r5layout, "default"); +- if (c->verbose > 0) +- pr_err("layout defaults to %s\n", map_num(r5layout, s->layout)); +- break; +- case LEVEL_FAULTY: +- s->layout = map_name(faultylayout, "default"); +- +- if (c->verbose > 0) +- pr_err("layout defaults to %s\n", map_num(faultylayout, s->layout)); +- break; +- } ++ s->layout = default_layout(NULL, s->level, c->verbose); + + /* We need to create the device. It can have no name. */ + map_lock(&map); +diff --git a/Create.c b/Create.c +index 0ff1922d..9ea19de0 100644 +--- a/Create.c ++++ b/Create.c +@@ -39,39 +39,54 @@ static int round_size_and_verify(unsigned long long *size, int chunk) + return 0; + } + +-static int default_layout(struct supertype *st, int level, int verbose) ++/** ++ * default_layout() - Get default layout for level. ++ * @st: metadata requested, could be NULL. ++ * @level: raid level requested. ++ * @verbose: verbose level. ++ * ++ * Try to ask metadata handler first, otherwise use global defaults. ++ * ++ * Return: Layout or &UnSet, return value meaning depends of level used. ++ */ ++int default_layout(struct supertype *st, int level, int verbose) + { + int layout = UnSet; ++ mapping_t *layout_map = NULL; ++ char *layout_name = NULL; + + if (st && st->ss->default_geometry) + st->ss->default_geometry(st, &level, &layout, NULL); + +- if (layout == UnSet) +- switch(level) { +- default: /* no layout */ +- layout = 0; +- break; +- case 0: +- layout = RAID0_ORIG_LAYOUT; +- break; +- case 10: +- layout = 0x102; /* near=2, far=1 */ +- if (verbose > 0) +- pr_err("layout defaults to n2\n"); +- break; +- case 5: +- case 6: +- layout = map_name(r5layout, "default"); +- if (verbose > 0) +- pr_err("layout defaults to %s\n", map_num(r5layout, layout)); +- break; +- case LEVEL_FAULTY: +- layout = map_name(faultylayout, "default"); ++ if (layout != UnSet) ++ return layout; + +- if (verbose > 0) +- pr_err("layout defaults to %s\n", map_num(faultylayout, layout)); +- break; +- } ++ switch (level) { ++ default: /* no layout */ ++ layout = 0; ++ break; ++ case 0: ++ layout = RAID0_ORIG_LAYOUT; ++ break; ++ case 10: ++ layout = 0x102; /* near=2, far=1 */ ++ layout_name = "n2"; ++ break; ++ case 5: ++ case 6: ++ layout_map = r5layout; ++ break; ++ case LEVEL_FAULTY: ++ layout_map = faultylayout; ++ break; ++ } ++ ++ if (layout_map) { ++ layout = map_name(layout_map, "default"); ++ layout_name = map_num(layout_map, layout); ++ } ++ if (layout_name && verbose > 0) ++ pr_err("layout defaults to %s\n", layout_name); + + return layout; + } +diff --git a/mdadm.h b/mdadm.h +index 26e7e5cd..cd72e711 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1512,6 +1512,7 @@ extern int get_linux_version(void); + extern int mdadm_version(char *version); + extern unsigned long long parse_size(char *size); + extern int parse_uuid(char *str, int uuid[4]); ++int default_layout(struct supertype *st, int level, int verbose); + extern int is_near_layout_10(int layout); + extern int parse_layout_10(char *layout); + extern int parse_layout_faulty(char *layout); +-- +2.38.1 + diff --git a/0011-mdadm-add-map_num_s.patch b/0011-mdadm-add-map_num_s.patch new file mode 100644 index 0000000..ee2c755 --- /dev/null +++ b/0011-mdadm-add-map_num_s.patch @@ -0,0 +1,382 @@ +From 5f21d67472ad08c1e96b4385254adba79aa1c467 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 20 Jan 2022 13:18:33 +0100 +Subject: [PATCH 11/83] mdadm: add map_num_s() + +map_num() returns NULL if key is not defined. This patch adds +alternative, non NULL version for cases where NULL is not expected. + +There are many printf() calls where map_num() is called on variable +without NULL verification. It works, even if NULL is passed because +gcc is able to ignore NULL argument quietly but the behavior is +undefined. For safety reasons such usages will use map_num_s() now. +It is a potential point of regression. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Assemble.c | 6 ++---- + Create.c | 2 +- + Detail.c | 4 ++-- + Grow.c | 16 ++++++++-------- + Query.c | 4 ++-- + maps.c | 24 ++++++++++++++++++++++++ + mdadm.c | 20 ++++++++++---------- + mdadm.h | 2 +- + super-ddf.c | 6 +++--- + super-intel.c | 2 +- + super0.c | 2 +- + super1.c | 2 +- + sysfs.c | 9 +++++---- + 13 files changed, 61 insertions(+), 38 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 704b8293..9eac9ce0 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -63,7 +63,7 @@ static void set_array_assembly_status(struct context *c, + struct assembly_array_info *arr) + { + int raid_disks = arr->preexist_cnt + arr->new_cnt; +- char *status_msg = map_num(assemble_statuses, status); ++ char *status_msg = map_num_s(assemble_statuses, status); + + if (c->export && result) + *result |= status; +@@ -77,9 +77,7 @@ static void set_array_assembly_status(struct context *c, + fprintf(stderr, " (%d new)", arr->new_cnt); + if (arr->exp_cnt) + fprintf(stderr, " ( + %d for expansion)", arr->exp_cnt); +- if (status_msg) +- fprintf(stderr, " %s", status_msg); +- fprintf(stderr, ".\n"); ++ fprintf(stderr, " %s.\n", status_msg); + } + + static int name_matches(char *found, char *required, char *homehost, int require_homehost) +diff --git a/Create.c b/Create.c +index 9ea19de0..c84c1ac8 100644 +--- a/Create.c ++++ b/Create.c +@@ -83,7 +83,7 @@ int default_layout(struct supertype *st, int level, int verbose) + + if (layout_map) { + layout = map_name(layout_map, "default"); +- layout_name = map_num(layout_map, layout); ++ layout_name = map_num_s(layout_map, layout); + } + if (layout_name && verbose > 0) + pr_err("layout defaults to %s\n", layout_name); +diff --git a/Detail.c b/Detail.c +index 95d4cc70..ce7a8445 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -495,8 +495,8 @@ int Detail(char *dev, struct context *c) + if (array.state & (1 << MD_SB_CLEAN)) { + if ((array.level == 0) || + (array.level == LEVEL_LINEAR)) +- arrayst = map_num(sysfs_array_states, +- sra->array_state); ++ arrayst = map_num_s(sysfs_array_states, ++ sra->array_state); + else + arrayst = "clean"; + } else { +diff --git a/Grow.c b/Grow.c +index 18c5719b..8a242b0f 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -547,7 +547,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + if (s->consistency_policy != CONSISTENCY_POLICY_RESYNC && + s->consistency_policy != CONSISTENCY_POLICY_PPL) { + pr_err("Operation not supported for consistency policy %s\n", +- map_num(consistency_policies, s->consistency_policy)); ++ map_num_s(consistency_policies, s->consistency_policy)); + return 1; + } + +@@ -578,14 +578,14 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + + if (sra->consistency_policy == (unsigned)s->consistency_policy) { + pr_err("Consistency policy is already %s\n", +- map_num(consistency_policies, s->consistency_policy)); ++ map_num_s(consistency_policies, s->consistency_policy)); + ret = 1; + goto free_info; + } else if (sra->consistency_policy != CONSISTENCY_POLICY_RESYNC && + sra->consistency_policy != CONSISTENCY_POLICY_PPL) { + pr_err("Current consistency policy is %s, cannot change to %s\n", +- map_num(consistency_policies, sra->consistency_policy), +- map_num(consistency_policies, s->consistency_policy)); ++ map_num_s(consistency_policies, sra->consistency_policy), ++ map_num_s(consistency_policies, s->consistency_policy)); + ret = 1; + goto free_info; + } +@@ -704,8 +704,8 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha + } + + ret = sysfs_set_str(sra, NULL, "consistency_policy", +- map_num(consistency_policies, +- s->consistency_policy)); ++ map_num_s(consistency_policies, ++ s->consistency_policy)); + if (ret) + pr_err("Failed to change array consistency policy\n"); + +@@ -2241,7 +2241,7 @@ size_change_error: + info.new_layout = UnSet; + if (info.array.level == 6 && info.new_level == UnSet) { + char l[40], *h; +- strcpy(l, map_num(r6layout, info.array.layout)); ++ strcpy(l, map_num_s(r6layout, info.array.layout)); + h = strrchr(l, '-'); + if (h && strcmp(h, "-6") == 0) { + *h = 0; +@@ -2266,7 +2266,7 @@ size_change_error: + info.new_layout = info.array.layout; + else if (info.array.level == 5 && info.new_level == 6) { + char l[40]; +- strcpy(l, map_num(r5layout, info.array.layout)); ++ strcpy(l, map_num_s(r5layout, info.array.layout)); + strcat(l, "-6"); + info.new_layout = map_name(r6layout, l); + } else { +diff --git a/Query.c b/Query.c +index 23fbf8aa..adcd231e 100644 +--- a/Query.c ++++ b/Query.c +@@ -93,7 +93,7 @@ int Query(char *dev) + else { + printf("%s: %s %s %d devices, %d spare%s. Use mdadm --detail for more detail.\n", + dev, human_size_brief(larray_size,IEC), +- map_num(pers, level), raid_disks, ++ map_num_s(pers, level), raid_disks, + spare_disks, spare_disks == 1 ? "" : "s"); + } + st = guess_super(fd); +@@ -131,7 +131,7 @@ int Query(char *dev) + dev, + info.disk.number, info.array.raid_disks, + activity, +- map_num(pers, info.array.level), ++ map_num_s(pers, info.array.level), + mddev); + if (st->ss == &super0) + put_md_name(mddev); +diff --git a/maps.c b/maps.c +index a4fd2797..20fcf719 100644 +--- a/maps.c ++++ b/maps.c +@@ -166,6 +166,30 @@ mapping_t sysfs_array_states[] = { + { NULL, ARRAY_UNKNOWN_STATE } + }; + ++/** ++ * map_num_s() - Safer alternative of map_num() function. ++ * @map: map to search. ++ * @num: key to match. ++ * ++ * Shall be used only if key existence is quaranted. ++ * ++ * Return: Pointer to name of the element. ++ */ ++char *map_num_s(mapping_t *map, int num) ++{ ++ char *ret = map_num(map, num); ++ ++ assert(ret); ++ return ret; ++} ++ ++/** ++ * map_num() - get element name by key. ++ * @map: map to search. ++ * @num: key to match. ++ * ++ * Return: Pointer to name of the element or NULL. ++ */ + char *map_num(mapping_t *map, int num) + { + while (map->name) { +diff --git a/mdadm.c b/mdadm.c +index 26299b2e..be40686c 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -280,8 +280,8 @@ int main(int argc, char *argv[]) + else + fprintf(stderr, "-%c", opt); + fprintf(stderr, " would set mdadm mode to \"%s\", but it is already set to \"%s\".\n", +- map_num(modes, newmode), +- map_num(modes, mode)); ++ map_num_s(modes, newmode), ++ map_num_s(modes, mode)); + exit(2); + } else if (!mode && newmode) { + mode = newmode; +@@ -544,7 +544,7 @@ int main(int argc, char *argv[]) + switch(s.level) { + default: + pr_err("layout not meaningful for %s arrays.\n", +- map_num(pers, s.level)); ++ map_num_s(pers, s.level)); + exit(2); + case UnSet: + pr_err("raid level must be given before layout.\n"); +@@ -1248,10 +1248,10 @@ int main(int argc, char *argv[]) + if (option_index > 0) + pr_err(":option --%s not valid in %s mode\n", + long_options[option_index].name, +- map_num(modes, mode)); ++ map_num_s(modes, mode)); + else + pr_err("option -%c not valid in %s mode\n", +- opt, map_num(modes, mode)); ++ opt, map_num_s(modes, mode)); + exit(2); + + } +@@ -1276,7 +1276,7 @@ int main(int argc, char *argv[]) + if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN && + s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) { + pr_err("--write-journal is not supported with consistency policy: %s\n", +- map_num(consistency_policies, s.consistency_policy)); ++ map_num_s(consistency_policies, s.consistency_policy)); + exit(2); + } + } +@@ -1285,12 +1285,12 @@ int main(int argc, char *argv[]) + s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) { + if (s.level <= 0) { + pr_err("--consistency-policy not meaningful with level %s.\n", +- map_num(pers, s.level)); ++ map_num_s(pers, s.level)); + exit(2); + } else if (s.consistency_policy == CONSISTENCY_POLICY_JOURNAL && + !s.journaldisks) { + pr_err("--write-journal is required for consistency policy: %s\n", +- map_num(consistency_policies, s.consistency_policy)); ++ map_num_s(consistency_policies, s.consistency_policy)); + exit(2); + } else if (s.consistency_policy == CONSISTENCY_POLICY_PPL && + s.level != 5) { +@@ -1300,14 +1300,14 @@ int main(int argc, char *argv[]) + (!s.bitmap_file || + strcmp(s.bitmap_file, "none") == 0)) { + pr_err("--bitmap is required for consistency policy: %s\n", +- map_num(consistency_policies, s.consistency_policy)); ++ map_num_s(consistency_policies, s.consistency_policy)); + exit(2); + } else if (s.bitmap_file && + strcmp(s.bitmap_file, "none") != 0 && + s.consistency_policy != CONSISTENCY_POLICY_BITMAP && + s.consistency_policy != CONSISTENCY_POLICY_JOURNAL) { + pr_err("--bitmap is not compatible with consistency policy: %s\n", +- map_num(consistency_policies, s.consistency_policy)); ++ map_num_s(consistency_policies, s.consistency_policy)); + exit(2); + } + } +diff --git a/mdadm.h b/mdadm.h +index cd72e711..09915a00 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -770,7 +770,7 @@ extern int restore_stripes(int *dest, unsigned long long *offsets, + #endif + + #define SYSLOG_FACILITY LOG_DAEMON +- ++extern char *map_num_s(mapping_t *map, int num); + extern char *map_num(mapping_t *map, int num); + extern int map_name(mapping_t *map, char *name); + extern mapping_t r0layout[], r5layout[], r6layout[], +diff --git a/super-ddf.c b/super-ddf.c +index 3f304cdc..8cda23a7 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -1477,13 +1477,13 @@ static void examine_vds(struct ddf_super *sb) + printf("\n"); + printf(" unit[%d] : %d\n", i, be16_to_cpu(ve->unit)); + printf(" state[%d] : %s, %s%s\n", i, +- map_num(ddf_state, ve->state & 7), ++ map_num_s(ddf_state, ve->state & 7), + (ve->state & DDF_state_morphing) ? "Morphing, ": "", + (ve->state & DDF_state_inconsistent)? "Not Consistent" : "Consistent"); + printf(" init state[%d] : %s\n", i, +- map_num(ddf_init_state, ve->init_state&DDF_initstate_mask)); ++ map_num_s(ddf_init_state, ve->init_state & DDF_initstate_mask)); + printf(" access[%d] : %s\n", i, +- map_num(ddf_access, (ve->init_state & DDF_access_mask) >> 6)); ++ map_num_s(ddf_access, (ve->init_state & DDF_access_mask) >> 6)); + printf(" Name[%d] : %.16s\n", i, ve->name); + examine_vd(i, sb, ve->guid); + } +diff --git a/super-intel.c b/super-intel.c +index 6ff336ee..ba3bd41f 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5625,7 +5625,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + free(dev); + free(dv); + pr_err("imsm does not support consistency policy %s\n", +- map_num(consistency_policies, s->consistency_policy)); ++ map_num_s(consistency_policies, s->consistency_policy)); + return 0; + } + +diff --git a/super0.c b/super0.c +index b79b97a9..61c9ec1d 100644 +--- a/super0.c ++++ b/super0.c +@@ -288,7 +288,7 @@ static void export_examine_super0(struct supertype *st) + { + mdp_super_t *sb = st->sb; + +- printf("MD_LEVEL=%s\n", map_num(pers, sb->level)); ++ printf("MD_LEVEL=%s\n", map_num_s(pers, sb->level)); + printf("MD_DEVICES=%d\n", sb->raid_disks); + if (sb->minor_version >= 90) + printf("MD_UUID=%08x:%08x:%08x:%08x\n", +diff --git a/super1.c b/super1.c +index a12a5bc8..e3e2f954 100644 +--- a/super1.c ++++ b/super1.c +@@ -671,7 +671,7 @@ static void export_examine_super1(struct supertype *st) + int len = 32; + int layout; + +- printf("MD_LEVEL=%s\n", map_num(pers, __le32_to_cpu(sb->level))); ++ printf("MD_LEVEL=%s\n", map_num_s(pers, __le32_to_cpu(sb->level))); + printf("MD_DEVICES=%d\n", __le32_to_cpu(sb->raid_disks)); + for (i = 0; i < 32; i++) + if (sb->set_name[i] == '\n' || sb->set_name[i] == '\0') { +diff --git a/sysfs.c b/sysfs.c +index 2995713d..0d98a65f 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -689,7 +689,7 @@ int sysfs_set_array(struct mdinfo *info, int vers) + if (info->array.level < 0) + return 0; /* FIXME */ + rv |= sysfs_set_str(info, NULL, "level", +- map_num(pers, info->array.level)); ++ map_num_s(pers, info->array.level)); + if (info->reshape_active && info->delta_disks != UnSet) + raid_disks -= info->delta_disks; + rv |= sysfs_set_num(info, NULL, "raid_disks", raid_disks); +@@ -724,9 +724,10 @@ int sysfs_set_array(struct mdinfo *info, int vers) + } + + if (info->consistency_policy == CONSISTENCY_POLICY_PPL) { +- if (sysfs_set_str(info, NULL, "consistency_policy", +- map_num(consistency_policies, +- info->consistency_policy))) { ++ char *policy = map_num_s(consistency_policies, ++ info->consistency_policy); ++ ++ if (sysfs_set_str(info, NULL, "consistency_policy", policy)) { + pr_err("This kernel does not support PPL. Falling back to consistency-policy=resync.\n"); + info->consistency_policy = CONSISTENCY_POLICY_RESYNC; + } +-- +2.38.1 + diff --git a/0013-mdmon-Stop-parsing-duplicate-options.patch b/0013-mdmon-Stop-parsing-duplicate-options.patch new file mode 100644 index 0000000..77324cf --- /dev/null +++ b/0013-mdmon-Stop-parsing-duplicate-options.patch @@ -0,0 +1,122 @@ +From 1066ab83dbe9a4cc20f7db44a40aa2cbb9d5eed6 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 13 May 2022 09:19:42 +0200 +Subject: [PATCH 13/83] mdmon: Stop parsing duplicate options + +Introduce new function is_duplicate_opt() to check if given option +was already used and prevent setting it again along with an error +message. + +Move parsing above in_initrd() check to be able to detect --offroot +option duplicates. + +Now help option is executed after parsing to prevent executing commands +like: 'mdmon --help --ndlksnlksajndfjksndafasj'. + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + mdmon.c | 44 +++++++++++++++++++++++++++++++++++--------- + 1 file changed, 35 insertions(+), 9 deletions(-) + +diff --git a/mdmon.c b/mdmon.c +index 5570574b..c057da63 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -288,6 +288,15 @@ void usage(void) + exit(2); + } + ++static bool is_duplicate_opt(const int opt, const int set_val, const char *long_name) ++{ ++ if (opt == set_val) { ++ pr_err("--%s option duplicated!\n", long_name); ++ return true; ++ } ++ return false; ++} ++ + static int mdmon(char *devnm, int must_fork, int takeover); + + int main(int argc, char *argv[]) +@@ -299,6 +308,7 @@ int main(int argc, char *argv[]) + int all = 0; + int takeover = 0; + int dofork = 1; ++ bool help = false; + static struct option options[] = { + {"all", 0, NULL, 'a'}, + {"takeover", 0, NULL, 't'}, +@@ -308,37 +318,50 @@ int main(int argc, char *argv[]) + {NULL, 0, NULL, 0} + }; + +- if (in_initrd()) { +- /* +- * set first char of argv[0] to @. This is used by +- * systemd to signal that the task was launched from +- * initrd/initramfs and should be preserved during shutdown +- */ +- argv[0][0] = '@'; +- } +- + while ((opt = getopt_long(argc, argv, "thaF", options, NULL)) != -1) { + switch (opt) { + case 'a': ++ if (is_duplicate_opt(all, 1, "all")) ++ exit(1); + container_name = argv[optind-1]; + all = 1; + break; + case 't': ++ if (is_duplicate_opt(takeover, 1, "takeover")) ++ exit(1); + takeover = 1; + break; + case 'F': ++ if (is_duplicate_opt(dofork, 0, "foreground")) ++ exit(1); + dofork = 0; + break; + case OffRootOpt: ++ if (is_duplicate_opt(argv[0][0], '@', "offroot")) ++ exit(1); + argv[0][0] = '@'; + break; + case 'h': ++ if (is_duplicate_opt(help, true, "help")) ++ exit(1); ++ help = true; ++ break; + default: + usage(); + break; + } + } + ++ ++ if (in_initrd()) { ++ /* ++ * set first char of argv[0] to @. This is used by ++ * systemd to signal that the task was launched from ++ * initrd/initramfs and should be preserved during shutdown ++ */ ++ argv[0][0] = '@'; ++ } ++ + if (all == 0 && container_name == NULL) { + if (argv[optind]) + container_name = argv[optind]; +@@ -353,6 +376,9 @@ int main(int argc, char *argv[]) + if (strcmp(container_name, "/proc/mdstat") == 0) + all = 1; + ++ if (help) ++ usage(); ++ + if (all) { + struct mdstat_ent *mdstat, *e; + int container_len = strlen(container_name); +-- +2.38.1 + diff --git a/0014-Grow-block-n-on-external-volumes.patch b/0014-Grow-block-n-on-external-volumes.patch new file mode 100644 index 0000000..4e6a874 --- /dev/null +++ b/0014-Grow-block-n-on-external-volumes.patch @@ -0,0 +1,41 @@ +From 20e114e334ed6ed3280c37a9a08fb95578393d1a Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Thu, 19 May 2022 09:16:08 +0200 +Subject: [PATCH 14/83] Grow: block -n on external volumes. + +Performing --raid-devices on external metadata volume should be blocked +as it causes unwanted behaviour. + +Eg. Performing +mdadm -G /dev/md/volume -l10 -n4 +on r0_d2 inside 4 disk container, returns +mdadm: Need 2 spares to avoid degraded array, only have 0. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Grow.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/Grow.c b/Grow.c +index 8a242b0f..f6efbc48 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1892,6 +1892,14 @@ int Grow_reshape(char *devname, int fd, + + if (retval) { + pr_err("Cannot read superblock for %s\n", devname); ++ close(cfd); ++ free(subarray); ++ return 1; ++ } ++ ++ if (s->raiddisks && subarray) { ++ pr_err("--raid-devices operation can be performed on a container only\n"); ++ close(cfd); + free(subarray); + return 1; + } +-- +2.38.1 + diff --git a/0015-Incremental-Fix-possible-memory-and-resource-leaks.patch b/0015-Incremental-Fix-possible-memory-and-resource-leaks.patch new file mode 100644 index 0000000..51a9e0f --- /dev/null +++ b/0015-Incremental-Fix-possible-memory-and-resource-leaks.patch @@ -0,0 +1,90 @@ +From de064c93e3819d72720e4fba6575265ba10e1553 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Mon, 13 Jun 2022 12:11:25 +0200 +Subject: [PATCH 15/83] Incremental: Fix possible memory and resource leaks + +map allocated through map_by_uuid() is not freed if mdfd is invalid. +In addition mdfd is not closed, and mdinfo list is not freed too. + +Signed-off-by: Mateusz Grzonka +Change-Id: I25e726f0e2502cf7e8ce80c2bd7944b3b1e2b9dc +Signed-off-by: Jes Sorensen +--- + Incremental.c | 32 +++++++++++++++++++++++--------- + 1 file changed, 23 insertions(+), 9 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index a57fc323..4d0cd9d6 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1499,7 +1499,7 @@ static int Incremental_container(struct supertype *st, char *devname, + return 0; + } + for (ra = list ; ra ; ra = ra->next) { +- int mdfd; ++ int mdfd = -1; + char chosen_name[1024]; + struct map_ent *mp; + struct mddev_ident *match = NULL; +@@ -1514,6 +1514,12 @@ static int Incremental_container(struct supertype *st, char *devname, + + if (mp) { + mdfd = open_dev(mp->devnm); ++ if (!is_fd_valid(mdfd)) { ++ pr_err("failed to open %s: %s.\n", ++ mp->devnm, strerror(errno)); ++ rv = 2; ++ goto release; ++ } + if (mp->path) + strcpy(chosen_name, mp->path); + else +@@ -1573,21 +1579,25 @@ static int Incremental_container(struct supertype *st, char *devname, + c->autof, + trustworthy, + chosen_name, 0); ++ ++ if (!is_fd_valid(mdfd)) { ++ pr_err("create_mddev failed with chosen name %s: %s.\n", ++ chosen_name, strerror(errno)); ++ rv = 2; ++ goto release; ++ } + } +- if (only && (!mp || strcmp(mp->devnm, only) != 0)) +- continue; + +- if (mdfd < 0) { +- pr_err("failed to open %s: %s.\n", +- chosen_name, strerror(errno)); +- return 2; ++ if (only && (!mp || strcmp(mp->devnm, only) != 0)) { ++ close_fd(&mdfd); ++ continue; + } + + assemble_container_content(st, mdfd, ra, c, + chosen_name, &result); + map_free(map); + map = NULL; +- close(mdfd); ++ close_fd(&mdfd); + } + if (c->export && result) { + char sep = '='; +@@ -1610,7 +1620,11 @@ static int Incremental_container(struct supertype *st, char *devname, + } + printf("\n"); + } +- return 0; ++ ++release: ++ map_free(map); ++ sysfs_free(list); ++ return rv; + } + + static void run_udisks(char *arg1, char *arg2) +-- +2.38.1 + diff --git a/0016-Mdmonitor-Fix-segfault.patch b/0016-Mdmonitor-Fix-segfault.patch new file mode 100644 index 0000000..61c64ab --- /dev/null +++ b/0016-Mdmonitor-Fix-segfault.patch @@ -0,0 +1,98 @@ +From e702f392959d1c2ad2089e595b52235ed97b4e18 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Mon, 6 Jun 2022 12:32:12 +0200 +Subject: [PATCH 16/83] Mdmonitor: Fix segfault + +Mdadm with "--monitor" parameter requires md device +as an argument to be monitored. If given argument is +not a md device, error shall be returned. Previously +it was not checked and invalid argument caused +segmentation fault. This commit adds checking +that devices passed to mdmonitor are md devices. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Monitor.c | 10 +++++++++- + mdadm.h | 1 + + mdopen.c | 17 +++++++++++++++++ + 3 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/Monitor.c b/Monitor.c +index c0ab5412..4e5802b5 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -182,6 +182,7 @@ int Monitor(struct mddev_dev *devlist, + continue; + if (strcasecmp(mdlist->devname, "") == 0) + continue; ++ + st = xcalloc(1, sizeof *st); + if (mdlist->devname[0] == '/') + st->devname = xstrdup(mdlist->devname); +@@ -190,6 +191,8 @@ int Monitor(struct mddev_dev *devlist, + strcpy(strcpy(st->devname, "/dev/md/"), + mdlist->devname); + } ++ if (!is_mddev(mdlist->devname)) ++ return 1; + st->next = statelist; + st->devnm[0] = 0; + st->percent = RESYNC_UNKNOWN; +@@ -203,7 +206,12 @@ int Monitor(struct mddev_dev *devlist, + struct mddev_dev *dv; + + for (dv = devlist; dv; dv = dv->next) { +- struct state *st = xcalloc(1, sizeof *st); ++ struct state *st; ++ ++ if (!is_mddev(dv->devname)) ++ return 1; ++ ++ st = xcalloc(1, sizeof *st); + mdlist = conf_get_ident(dv->devname); + st->devname = xstrdup(dv->devname); + st->next = statelist; +diff --git a/mdadm.h b/mdadm.h +index 09915a00..d53df169 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1636,6 +1636,7 @@ extern int create_mddev(char *dev, char *name, int autof, int trustworthy, + #define FOREIGN 2 + #define METADATA 3 + extern int open_mddev(char *dev, int report_errors); ++extern int is_mddev(char *dev); + extern int open_container(int fd); + extern int metadata_container_matches(char *metadata, char *devnm); + extern int metadata_subdev_matches(char *metadata, char *devnm); +diff --git a/mdopen.c b/mdopen.c +index 245be537..d18c9319 100644 +--- a/mdopen.c ++++ b/mdopen.c +@@ -475,6 +475,23 @@ int open_mddev(char *dev, int report_errors) + return mdfd; + } + ++/** ++ * is_mddev() - check that file name passed is an md device. ++ * @dev: file name that has to be checked. ++ * Return: 1 if file passed is an md device, 0 if not. ++ */ ++int is_mddev(char *dev) ++{ ++ int fd = open_mddev(dev, 1); ++ ++ if (fd >= 0) { ++ close(fd); ++ return 1; ++ } ++ ++ return 0; ++} ++ + char *find_free_devnm(int use_partitions) + { + static char devnm[32]; +-- +2.38.1 + diff --git a/0017-Mdmonitor-Improve-logging-method.patch b/0017-Mdmonitor-Improve-logging-method.patch new file mode 100644 index 0000000..3c7eed2 --- /dev/null +++ b/0017-Mdmonitor-Improve-logging-method.patch @@ -0,0 +1,61 @@ +From f5ff2988761625b43eb15555993f2797af29f166 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Mon, 6 Jun 2022 12:32:13 +0200 +Subject: [PATCH 17/83] Mdmonitor: Improve logging method + +Change logging, and as a result, mdmonitor in verbose +mode will report its configuration. + +Signed-off-by: Kinga Tanska +Signed-off-by: Oleksandr Shchirskyi +Signed-off-by: Jes Sorensen +--- + Monitor.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 4e5802b5..6ca1ebe5 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -136,24 +136,27 @@ int Monitor(struct mddev_dev *devlist, + struct mddev_ident *mdlist; + int delay_for_event = c->delay; + +- if (!mailaddr) { ++ if (!mailaddr) + mailaddr = conf_get_mailaddr(); +- if (mailaddr && ! c->scan) +- pr_err("Monitor using email address \"%s\" from config file\n", +- mailaddr); +- } +- mailfrom = conf_get_mailfrom(); + +- if (!alert_cmd) { ++ if (!alert_cmd) + alert_cmd = conf_get_program(); +- if (alert_cmd && !c->scan) +- pr_err("Monitor using program \"%s\" from config file\n", +- alert_cmd); +- } ++ ++ mailfrom = conf_get_mailfrom(); ++ + if (c->scan && !mailaddr && !alert_cmd && !dosyslog) { + pr_err("No mail address or alert command - not monitoring.\n"); + return 1; + } ++ ++ if (c->verbose) { ++ pr_err("Monitor is started with delay %ds\n", c->delay); ++ if (mailaddr) ++ pr_err("Monitor using email address %s\n", mailaddr); ++ if (alert_cmd) ++ pr_err("Monitor using program %s\n", alert_cmd); ++ } ++ + info.alert_cmd = alert_cmd; + info.mailaddr = mailaddr; + info.mailfrom = mailfrom; +-- +2.38.1 + diff --git a/0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch b/0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch new file mode 100644 index 0000000..24db49f --- /dev/null +++ b/0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch @@ -0,0 +1,73 @@ +From 626bc45396c4959f2c4685c2faa7c4f553f4efdf Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Mon, 13 Jun 2022 11:59:34 +0200 +Subject: [PATCH 18/83] Fix possible NULL ptr dereferences and memory leaks + +In Assemble there was a NULL check for sra variable, +which effectively didn't stop the execution in every case. +That might have resulted in a NULL pointer dereference. + +Also in super-ddf, mu variable was set to NULL for some condition, +and then immidiately dereferenced. +Additionally some memory wasn't freed as well. + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + Assemble.c | 7 ++++++- + super-ddf.c | 9 +++++++-- + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 9eac9ce0..4b213560 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1982,7 +1982,12 @@ int assemble_container_content(struct supertype *st, int mdfd, + } + + sra = sysfs_read(mdfd, NULL, GET_VERSION|GET_DEVS); +- if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) { ++ if (sra == NULL) { ++ pr_err("Failed to read sysfs parameters\n"); ++ return 1; ++ } ++ ++ if (strcmp(sra->text_version, content->text_version) != 0) { + if (content->array.major_version == -1 && + content->array.minor_version == -2 && + c->readonly && +diff --git a/super-ddf.c b/super-ddf.c +index 8cda23a7..abbc8b09 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -5125,13 +5125,16 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, + */ + vc = find_vdcr(ddf, a->info.container_member, rv->disk.raid_disk, + &n_bvd, &vcl); +- if (vc == NULL) ++ if (vc == NULL) { ++ free(rv); + return NULL; ++ } + + mu = xmalloc(sizeof(*mu)); + if (posix_memalign(&mu->space, 512, sizeof(struct vcl)) != 0) { + free(mu); +- mu = NULL; ++ free(rv); ++ return NULL; + } + + mu->len = ddf->conf_rec_len * 512 * vcl->conf.sec_elmnt_count; +@@ -5161,6 +5164,8 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a, + pr_err("BUG: can't find disk %d (%d/%d)\n", + di->disk.raid_disk, + di->disk.major, di->disk.minor); ++ free(mu); ++ free(rv); + return NULL; + } + vc->phys_refnum[i_prim] = ddf->phys->entries[dl->pdnum].refnum; +-- +2.38.1 + diff --git a/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch b/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch new file mode 100644 index 0000000..12dd070 --- /dev/null +++ b/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch @@ -0,0 +1,301 @@ +From 756a15f32338fdf0c562678694bc8991ad6afb90 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Mon, 13 Jun 2022 12:00:09 +0200 +Subject: [PATCH 19/83] imsm: Remove possibility for get_imsm_dev to return + NULL + +Returning NULL from get_imsm_dev or __get_imsm_dev will cause segfault. +Guarantee that it never happens. + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + super-intel.c | 153 +++++++++++++++++++++++++------------------------- + 1 file changed, 78 insertions(+), 75 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index ba3bd41f..3788feb9 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -851,6 +851,21 @@ static struct disk_info *get_disk_info(struct imsm_update_create_array *update) + return inf; + } + ++/** ++ * __get_imsm_dev() - Get device with index from imsm_super. ++ * @mpb: &imsm_super pointer, not NULL. ++ * @index: Device index. ++ * ++ * Function works as non-NULL, aborting in such a case, ++ * when NULL would be returned. ++ * ++ * Device index should be in range 0 up to num_raid_devs. ++ * Function assumes the index was already verified. ++ * Index must be valid, otherwise abort() is called. ++ * ++ * Return: Pointer to corresponding imsm_dev. ++ * ++ */ + static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index) + { + int offset; +@@ -858,30 +873,47 @@ static struct imsm_dev *__get_imsm_dev(struct imsm_super *mpb, __u8 index) + void *_mpb = mpb; + + if (index >= mpb->num_raid_devs) +- return NULL; ++ goto error; + + /* devices start after all disks */ + offset = ((void *) &mpb->disk[mpb->num_disks]) - _mpb; + +- for (i = 0; i <= index; i++) ++ for (i = 0; i <= index; i++, offset += sizeof_imsm_dev(_mpb + offset, 0)) + if (i == index) + return _mpb + offset; +- else +- offset += sizeof_imsm_dev(_mpb + offset, 0); +- +- return NULL; ++error: ++ pr_err("cannot find imsm_dev with index %u in imsm_super\n", index); ++ abort(); + } + ++/** ++ * get_imsm_dev() - Get device with index from intel_super. ++ * @super: &intel_super pointer, not NULL. ++ * @index: Device index. ++ * ++ * Function works as non-NULL, aborting in such a case, ++ * when NULL would be returned. ++ * ++ * Device index should be in range 0 up to num_raid_devs. ++ * Function assumes the index was already verified. ++ * Index must be valid, otherwise abort() is called. ++ * ++ * Return: Pointer to corresponding imsm_dev. ++ * ++ */ + static struct imsm_dev *get_imsm_dev(struct intel_super *super, __u8 index) + { + struct intel_dev *dv; + + if (index >= super->anchor->num_raid_devs) +- return NULL; ++ goto error; ++ + for (dv = super->devlist; dv; dv = dv->next) + if (dv->index == index) + return dv->dev; +- return NULL; ++error: ++ pr_err("cannot find imsm_dev with index %u in intel_super\n", index); ++ abort(); + } + + static inline unsigned long long __le48_to_cpu(const struct bbm_log_block_addr +@@ -4364,8 +4396,7 @@ int check_mpb_migr_compatibility(struct intel_super *super) + for (i = 0; i < super->anchor->num_raid_devs; i++) { + struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i); + +- if (dev_iter && +- dev_iter->vol.migr_state == 1 && ++ if (dev_iter->vol.migr_state == 1 && + dev_iter->vol.migr_type == MIGR_GEN_MIGR) { + /* This device is migrating */ + map0 = get_imsm_map(dev_iter, MAP_0); +@@ -4514,8 +4545,6 @@ static void clear_hi(struct intel_super *super) + } + for (i = 0; i < mpb->num_raid_devs; ++i) { + struct imsm_dev *dev = get_imsm_dev(super, i); +- if (!dev) +- return; + for (n = 0; n < 2; ++n) { + struct imsm_map *map = get_imsm_map(dev, n); + if (!map) +@@ -5836,7 +5865,7 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, + struct imsm_dev *_dev = __get_imsm_dev(mpb, 0); + + _disk = __get_imsm_disk(mpb, dl->index); +- if (!_dev || !_disk) { ++ if (!_disk) { + pr_err("BUG mpb setup error\n"); + return 1; + } +@@ -6171,10 +6200,10 @@ static int write_super_imsm(struct supertype *st, int doclose) + for (i = 0; i < mpb->num_raid_devs; i++) { + struct imsm_dev *dev = __get_imsm_dev(mpb, i); + struct imsm_dev *dev2 = get_imsm_dev(super, i); +- if (dev && dev2) { +- imsm_copy_dev(dev, dev2); +- mpb_size += sizeof_imsm_dev(dev, 0); +- } ++ ++ imsm_copy_dev(dev, dev2); ++ mpb_size += sizeof_imsm_dev(dev, 0); ++ + if (is_gen_migration(dev2)) + clear_migration_record = 0; + } +@@ -9033,29 +9062,26 @@ static int imsm_rebuild_allowed(struct supertype *cont, int dev_idx, int failed) + __u8 state; + + dev2 = get_imsm_dev(cont->sb, dev_idx); +- if (dev2) { +- state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0); +- if (state == IMSM_T_STATE_FAILED) { +- map = get_imsm_map(dev2, MAP_0); +- if (!map) +- return 1; +- for (slot = 0; slot < map->num_members; slot++) { +- /* +- * Check if failed disks are deleted from intel +- * disk list or are marked to be deleted +- */ +- idx = get_imsm_disk_idx(dev2, slot, MAP_X); +- idisk = get_imsm_dl_disk(cont->sb, idx); +- /* +- * Do not rebuild the array if failed disks +- * from failed sub-array are not removed from +- * container. +- */ +- if (idisk && +- is_failed(&idisk->disk) && +- (idisk->action != DISK_REMOVE)) +- return 0; +- } ++ ++ state = imsm_check_degraded(cont->sb, dev2, failed, MAP_0); ++ if (state == IMSM_T_STATE_FAILED) { ++ map = get_imsm_map(dev2, MAP_0); ++ for (slot = 0; slot < map->num_members; slot++) { ++ /* ++ * Check if failed disks are deleted from intel ++ * disk list or are marked to be deleted ++ */ ++ idx = get_imsm_disk_idx(dev2, slot, MAP_X); ++ idisk = get_imsm_dl_disk(cont->sb, idx); ++ /* ++ * Do not rebuild the array if failed disks ++ * from failed sub-array are not removed from ++ * container. ++ */ ++ if (idisk && ++ is_failed(&idisk->disk) && ++ (idisk->action != DISK_REMOVE)) ++ return 0; + } + } + return 1; +@@ -10089,7 +10115,6 @@ static void imsm_process_update(struct supertype *st, + int victim = u->dev_idx; + struct active_array *a; + struct intel_dev **dp; +- struct imsm_dev *dev; + + /* sanity check that we are not affecting the uuid of + * active arrays, or deleting an active array +@@ -10105,8 +10130,7 @@ static void imsm_process_update(struct supertype *st, + * is active in the container, so checking + * mpb->num_raid_devs is just extra paranoia + */ +- dev = get_imsm_dev(super, victim); +- if (a || !dev || mpb->num_raid_devs == 1) { ++ if (a || mpb->num_raid_devs == 1 || victim >= super->anchor->num_raid_devs) { + dprintf("failed to delete subarray-%d\n", victim); + break; + } +@@ -10140,7 +10164,7 @@ static void imsm_process_update(struct supertype *st, + if (a->info.container_member == target) + break; + dev = get_imsm_dev(super, u->dev_idx); +- if (a || !dev || !check_name(super, name, 1)) { ++ if (a || !check_name(super, name, 1)) { + dprintf("failed to rename subarray-%d\n", target); + break; + } +@@ -10169,10 +10193,6 @@ static void imsm_process_update(struct supertype *st, + struct imsm_update_rwh_policy *u = (void *)update->buf; + int target = u->dev_idx; + struct imsm_dev *dev = get_imsm_dev(super, target); +- if (!dev) { +- dprintf("could not find subarray-%d\n", target); +- break; +- } + + if (dev->rwh_policy != u->new_policy) { + dev->rwh_policy = u->new_policy; +@@ -11397,8 +11417,10 @@ static int imsm_create_metadata_update_for_migration( + { + struct intel_super *super = st->sb; + int update_memory_size; ++ int current_chunk_size; + struct imsm_update_reshape_migration *u; +- struct imsm_dev *dev; ++ struct imsm_dev *dev = get_imsm_dev(super, super->current_vol); ++ struct imsm_map *map = get_imsm_map(dev, MAP_0); + int previous_level = -1; + + dprintf("(enter) New Level = %i\n", geo->level); +@@ -11415,23 +11437,15 @@ static int imsm_create_metadata_update_for_migration( + u->new_disks[0] = -1; + u->new_chunksize = -1; + +- dev = get_imsm_dev(super, u->subdev); +- if (dev) { +- struct imsm_map *map; ++ current_chunk_size = __le16_to_cpu(map->blocks_per_strip) / 2; + +- map = get_imsm_map(dev, MAP_0); +- if (map) { +- int current_chunk_size = +- __le16_to_cpu(map->blocks_per_strip) / 2; +- +- if (geo->chunksize != current_chunk_size) { +- u->new_chunksize = geo->chunksize / 1024; +- dprintf("imsm: chunk size change from %i to %i\n", +- current_chunk_size, u->new_chunksize); +- } +- previous_level = map->raid_level; +- } ++ if (geo->chunksize != current_chunk_size) { ++ u->new_chunksize = geo->chunksize / 1024; ++ dprintf("imsm: chunk size change from %i to %i\n", ++ current_chunk_size, u->new_chunksize); + } ++ previous_level = map->raid_level; ++ + if (geo->level == 5 && previous_level == 0) { + struct mdinfo *spares = NULL; + +@@ -12519,9 +12533,6 @@ static int validate_internal_bitmap_imsm(struct supertype *st) + unsigned long long offset; + struct dl *d; + +- if (!dev) +- return -1; +- + if (dev->rwh_policy != RWH_BITMAP) + return 0; + +@@ -12567,16 +12578,8 @@ static int add_internal_bitmap_imsm(struct supertype *st, int *chunkp, + return -1; + + dev = get_imsm_dev(super, vol_idx); +- +- if (!dev) { +- dprintf("cannot find the device for volume index %d\n", +- vol_idx); +- return -1; +- } + dev->rwh_policy = RWH_BITMAP; +- + *chunkp = calculate_bitmap_chunksize(st, dev); +- + return 0; + } + +-- +2.38.1 + diff --git a/0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch b/0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch new file mode 100644 index 0000000..f51c730 --- /dev/null +++ b/0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch @@ -0,0 +1,85 @@ +From 190dc029b141c423e724566cbed5d5afbb10b05a Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Mon, 18 Apr 2022 13:44:23 -0400 +Subject: [PATCH 20/83] Revert "mdadm: fix coredump of mdadm --monitor -r" + +This reverts commit 546047688e1c64638f462147c755b58119cabdc8. + +The change from commit mdadm: fix coredump of mdadm +--monitor -r broke the printing of the return message when +passing -r to mdadm --manage, the removal of a device from +an array. + +If the current code reverts this commit, both issues are +still fixed. + +The original problem reported that the fix tried to address +was: The --monitor -r option requires a parameter, +otherwise a null pointer will be manipulated when +converting to integer data, and a core dump will appear. + +The original problem was really fixed with: +60815698c0a Refactor parse_num and use it to parse optarg. +Which added a check for NULL in 'optarg' before moving it +to the 'increments' variable. + +New issue: When trying to remove a device using the short +argument -r, instead of the long argument --remove, the +output is empty. The problem started when commit +546047688e1c was added. + +Steps to Reproduce: +1. create/assemble /dev/md0 device +2. mdadm --manage /dev/md0 -r /dev/vdxx + +Actual results: +Nothing, empty output, nothing happens, the device is still +connected to the array. + +The output should have stated "mdadm: hot remove failed +for /dev/vdxx: Device or resource busy", if the device was +still active. Or it should remove the device and print +a message: + +mdadm: set /dev/vdd faulty in /dev/md0 +mdadm: hot removed /dev/vdd from /dev/md0 + +The following commit should be reverted as it breaks +mdadm --manage -r. + +commit 546047688e1c64638f462147c755b58119cabdc8 +Author: Wu Guanghao +Date: Mon Aug 16 15:24:51 2021 +0800 +mdadm: fix coredump of mdadm --monitor -r + +-Nigel + +Signed-off-by: Nigel Croxon +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + ReadMe.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ReadMe.c b/ReadMe.c +index 8f873c48..bec1be9a 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -81,11 +81,11 @@ char Version[] = "mdadm - v" VERSION " - " VERS_DATE EXTRAVERSION "\n"; + * found, it is started. + */ + +-char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:r:n:x:u:c:d:z:U:N:safRSow1tye:k"; ++char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; + char short_bitmap_options[]= +- "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:r:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; ++ "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; + char short_bitmap_auto_options[]= +- "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:r:n:x:u:c:d:z:U:N:sa:rfRSow1tye:k:"; ++ "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sa:rfRSow1tye:k:"; + + struct option long_options[] = { + {"manage", 0, 0, ManageOpt}, +-- +2.38.1 + diff --git a/0021-util-replace-ioctl-use-with-function.patch b/0021-util-replace-ioctl-use-with-function.patch new file mode 100644 index 0000000..56ee5e8 --- /dev/null +++ b/0021-util-replace-ioctl-use-with-function.patch @@ -0,0 +1,31 @@ +From 953cc7e5a485a91ddec7312c7a5d7779749fad5f Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Tue, 21 Jun 2022 00:10:39 +0800 +Subject: [PATCH 21/83] util: replace ioctl use with function + +Replace using of ioctl calling to get md array info with +special function prepared to it. + +Signed-off-by: Kinga Tanska +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util.c b/util.c +index cc94f96e..38f0420e 100644 +--- a/util.c ++++ b/util.c +@@ -267,7 +267,7 @@ int md_array_active(int fd) + * GET_ARRAY_INFO doesn't provide access to the proper state + * information, so fallback to a basic check for raid_disks != 0 + */ +- ret = ioctl(fd, GET_ARRAY_INFO, &array); ++ ret = md_get_array_info(fd, &array); + } + + return !ret; +-- +2.38.1 + diff --git a/0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch b/0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch new file mode 100644 index 0000000..88bba83 --- /dev/null +++ b/0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch @@ -0,0 +1,110 @@ +From 63902857b98c37c8ac4b837bb01d006b327a4532 Mon Sep 17 00:00:00 2001 +From: Heming Zhao +Date: Tue, 21 Jun 2022 00:10:40 +0800 +Subject: [PATCH 22/83] mdadm/super1: restore commit 45a87c2f31335 to fix + clustered slot issue + +Commit 9d67f6496c71 ("mdadm:check the nodes when operate clustered +array") modified assignment logic for st->nodes in write_bitmap1(), +which introduced bitmap slot issue: + +load_super1 didn't set up supertype.nodes, which made spare disk only +have one slot info. Then it triggered kernel md_bitmap_load_sb to get +wrong bitmap slot data. + +For fixing this issue, there are two methods: + +1> revert the related code of commit 9d67f6496c71. and restore the code + from former commit 45a87c2f31335 ("super1: add more checks for + NodeNumUpdate option"). + st->nodes value would be 0 & 1 under current code logic. i.e. + When adding a spare disk, there is no place to init st->nodes, and + the value is ZERO. + +2> keep 9d67f6496c71, add additional ->nodes handling in load_super1(), + let load_super1 to set st->nodes when bitmap is BITMAP_MAJOR_CLUSTERED. + Under current mdadm code logic, load_super1 will be called many + times, any new code in load_super1 will cost mdadm running more time. + And more reason is I prefer as much as possible to limit clustered + code spreading in every corner. + +So I used method <1> to fix this issue. + +How to trigger: + +dd if=/dev/zero bs=1M count=1 oflag=direct of=/dev/sda +dd if=/dev/zero bs=1M count=1 oflag=direct of=/dev/sdb +dd if=/dev/zero bs=1M count=1 oflag=direct of=/dev/sdc +mdadm -C /dev/md0 -b clustered -e 1.2 -n 2 -l mirror /dev/sda /dev/sdb +mdadm -a /dev/md0 /dev/sdc +mdadm /dev/md0 --fail /dev/sda +mdadm /dev/md0 --remove /dev/sda +mdadm -Ss +mdadm -A /dev/md0 /dev/sdb /dev/sdc + +the output of current "mdadm -X /dev/sdc": +(there should be (by default) 4 slot info for correct output) +``` + Filename : /dev/sdc + Magic : 6d746962 + Version : 5 + UUID : a74642f8:a6b1fba8:58e1f8db:cfe7b082 + Events : 29 + Events Cleared : 0 + State : OK + Chunksize : 64 MB + Daemon : 5s flush period + Write Mode : Normal + Sync Size : 306176 (299.00 MiB 313.52 MB) + Bitmap : 5 bits (chunks), 5 dirty (100.0%) +``` + +And mdadm later operations will trigger kernel output error message: +(triggered by "mdadm -A /dev/md0 /dev/sdb /dev/sdc") +``` +kernel: md0: invalid bitmap file superblock: bad magic +kernel: md_bitmap_copy_from_slot can't get bitmap from slot 1 +kernel: md-cluster: Could not gather bitmaps from slot 1 +kernel: md0: invalid bitmap file superblock: bad magic +kernel: md_bitmap_copy_from_slot can't get bitmap from slot 2 +kernel: md-cluster: Could not gather bitmaps from slot 2 +kernel: md0: invalid bitmap file superblock: bad magic +kernel: md_bitmap_copy_from_slot can't get bitmap from slot 3 +kernel: md-cluster: Could not gather bitmaps from slot 3 +kernel: md-cluster: failed to gather all resyn infos +kernel: md0: detected capacity change from 0 to 612352 +``` + +Acked-by: Coly Li +Signed-off-by: Heming Zhao +Signed-off-by: Jes Sorensen +--- + super1.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/super1.c b/super1.c +index e3e2f954..3a0c69fd 100644 +--- a/super1.c ++++ b/super1.c +@@ -2674,7 +2674,17 @@ static int write_bitmap1(struct supertype *st, int fd, enum bitmap_update update + } + + if (bms->version == BITMAP_MAJOR_CLUSTERED) { +- if (__cpu_to_le32(st->nodes) < bms->nodes) { ++ if (st->nodes == 1) { ++ /* the parameter for nodes is not valid */ ++ pr_err("Warning: cluster-md at least needs two nodes\n"); ++ return -EINVAL; ++ } else if (st->nodes == 0) { ++ /* ++ * parameter "--nodes" is not specified, (eg, add a disk to ++ * clustered raid) ++ */ ++ break; ++ } else if (__cpu_to_le32(st->nodes) < bms->nodes) { + /* + * Since the nodes num is not increased, no + * need to check the space enough or not, +-- +2.38.1 + diff --git a/0023-imsm-introduce-get_disk_slot_in_dev.patch b/0023-imsm-introduce-get_disk_slot_in_dev.patch new file mode 100644 index 0000000..ca1d015 --- /dev/null +++ b/0023-imsm-introduce-get_disk_slot_in_dev.patch @@ -0,0 +1,122 @@ +From 76c152ca9851e9fcdf52e8f6e7e6c09b936bdd14 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 21 Jun 2022 00:10:41 +0800 +Subject: [PATCH 23/83] imsm: introduce get_disk_slot_in_dev() + +The routine was added to remove unnecessary get_imsm_dev() and +get_imsm_map() calls, used only to determine disk slot. + +Additionally, enum for IMSM return statues was added for further usage. + +Signed-off-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + super-intel.c | 47 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 36 insertions(+), 11 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 3788feb9..cd1f1e3d 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -366,6 +366,18 @@ struct migr_record { + }; + ASSERT_SIZE(migr_record, 128) + ++/** ++ * enum imsm_status - internal IMSM return values representation. ++ * @STATUS_OK: function succeeded. ++ * @STATUS_ERROR: General error ocurred (not specified). ++ * ++ * Typedefed to imsm_status_t. ++ */ ++typedef enum imsm_status { ++ IMSM_STATUS_ERROR = -1, ++ IMSM_STATUS_OK = 0, ++} imsm_status_t; ++ + struct md_list { + /* usage marker: + * 1: load metadata +@@ -1183,7 +1195,7 @@ static void set_imsm_ord_tbl_ent(struct imsm_map *map, int slot, __u32 ord) + map->disk_ord_tbl[slot] = __cpu_to_le32(ord); + } + +-static int get_imsm_disk_slot(struct imsm_map *map, unsigned idx) ++static int get_imsm_disk_slot(struct imsm_map *map, const unsigned int idx) + { + int slot; + __u32 ord; +@@ -1194,7 +1206,7 @@ static int get_imsm_disk_slot(struct imsm_map *map, unsigned idx) + return slot; + } + +- return -1; ++ return IMSM_STATUS_ERROR; + } + + static int get_imsm_raid_level(struct imsm_map *map) +@@ -1209,6 +1221,23 @@ static int get_imsm_raid_level(struct imsm_map *map) + return map->raid_level; + } + ++/** ++ * get_disk_slot_in_dev() - retrieve disk slot from &imsm_dev. ++ * @super: &intel_super pointer, not NULL. ++ * @dev_idx: imsm device index. ++ * @idx: disk index. ++ * ++ * Return: Slot on success, IMSM_STATUS_ERROR otherwise. ++ */ ++static int get_disk_slot_in_dev(struct intel_super *super, const __u8 dev_idx, ++ const unsigned int idx) ++{ ++ struct imsm_dev *dev = get_imsm_dev(super, dev_idx); ++ struct imsm_map *map = get_imsm_map(dev, MAP_0); ++ ++ return get_imsm_disk_slot(map, idx); ++} ++ + static int cmp_extent(const void *av, const void *bv) + { + const struct extent *a = av; +@@ -1225,13 +1254,9 @@ static int count_memberships(struct dl *dl, struct intel_super *super) + int memberships = 0; + int i; + +- for (i = 0; i < super->anchor->num_raid_devs; i++) { +- struct imsm_dev *dev = get_imsm_dev(super, i); +- struct imsm_map *map = get_imsm_map(dev, MAP_0); +- +- if (get_imsm_disk_slot(map, dl->index) >= 0) ++ for (i = 0; i < super->anchor->num_raid_devs; i++) ++ if (get_disk_slot_in_dev(super, i, dl->index) >= 0) + memberships++; +- } + + return memberships; + } +@@ -1941,6 +1966,7 @@ void examine_migr_rec_imsm(struct intel_super *super) + + /* first map under migration */ + map = get_imsm_map(dev, MAP_0); ++ + if (map) + slot = get_imsm_disk_slot(map, super->disks->index); + if (map == NULL || slot > 1 || slot < 0) { +@@ -9655,10 +9681,9 @@ static int apply_update_activate_spare(struct imsm_update_activate_spare *u, + /* count arrays using the victim in the metadata */ + found = 0; + for (a = active_array; a ; a = a->next) { +- dev = get_imsm_dev(super, a->info.container_member); +- map = get_imsm_map(dev, MAP_0); ++ int dev_idx = a->info.container_member; + +- if (get_imsm_disk_slot(map, victim) >= 0) ++ if (get_disk_slot_in_dev(super, dev_idx, victim) >= 0) + found++; + } + +-- +2.38.1 + diff --git a/0024-imsm-use-same-slot-across-container.patch b/0024-imsm-use-same-slot-across-container.patch new file mode 100644 index 0000000..dc23b3c --- /dev/null +++ b/0024-imsm-use-same-slot-across-container.patch @@ -0,0 +1,252 @@ +From 6d4d9ab295de165e57b5c30e044028dbffb8f297 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 21 Jun 2022 00:10:42 +0800 +Subject: [PATCH 24/83] imsm: use same slot across container + +Autolayout relies on drives order on super->disks list, but +it is not quaranted by readdir() in sysfs_read(). As a result +drive could be put in different slot in second volume. + +Make it consistent by reffering to first volume, if exists. + +Use enum imsm_status to unify error handling. + +Signed-off-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + super-intel.c | 169 ++++++++++++++++++++++++++++++++------------------ + 1 file changed, 108 insertions(+), 61 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index cd1f1e3d..deef7c87 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7522,11 +7522,27 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, + return 1; + } + +-static int imsm_get_free_size(struct supertype *st, int raiddisks, +- unsigned long long size, int chunk, +- unsigned long long *freesize) ++/** ++ * imsm_get_free_size() - get the biggest, common free space from members. ++ * @super: &intel_super pointer, not NULL. ++ * @raiddisks: number of raid disks. ++ * @size: requested size, could be 0 (means max size). ++ * @chunk: requested chunk. ++ * @freesize: pointer for returned size value. ++ * ++ * Return: &IMSM_STATUS_OK or &IMSM_STATUS_ERROR. ++ * ++ * @freesize is set to meaningful value, this can be @size, or calculated ++ * max free size. ++ * super->create_offset value is modified and set appropriately in ++ * merge_extends() for further creation. ++ */ ++static imsm_status_t imsm_get_free_size(struct intel_super *super, ++ const int raiddisks, ++ unsigned long long size, ++ const int chunk, ++ unsigned long long *freesize) + { +- struct intel_super *super = st->sb; + struct imsm_super *mpb = super->anchor; + struct dl *dl; + int i; +@@ -7570,12 +7586,10 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks, + /* chunk is in K */ + minsize = chunk * 2; + +- if (cnt < raiddisks || +- (super->orom && used && used != raiddisks) || +- maxsize < minsize || +- maxsize == 0) { ++ if (cnt < raiddisks || (super->orom && used && used != raiddisks) || ++ maxsize < minsize || maxsize == 0) { + pr_err("not enough devices with space to create array.\n"); +- return 0; /* No enough free spaces large enough */ ++ return IMSM_STATUS_ERROR; + } + + if (size == 0) { +@@ -7588,37 +7602,69 @@ static int imsm_get_free_size(struct supertype *st, int raiddisks, + } + if (mpb->num_raid_devs > 0 && size && size != maxsize) + pr_err("attempting to create a second volume with size less then remaining space.\n"); +- cnt = 0; +- for (dl = super->disks; dl; dl = dl->next) +- if (dl->e) +- dl->raiddisk = cnt++; +- + *freesize = size; + + dprintf("imsm: imsm_get_free_size() returns : %llu\n", size); + +- return 1; ++ return IMSM_STATUS_OK; + } + +-static int reserve_space(struct supertype *st, int raiddisks, +- unsigned long long size, int chunk, +- unsigned long long *freesize) ++/** ++ * autolayout_imsm() - automatically layout a new volume. ++ * @super: &intel_super pointer, not NULL. ++ * @raiddisks: number of raid disks. ++ * @size: requested size, could be 0 (means max size). ++ * @chunk: requested chunk. ++ * @freesize: pointer for returned size value. ++ * ++ * We are being asked to automatically layout a new volume based on the current ++ * contents of the container. If the parameters can be satisfied autolayout_imsm ++ * will record the disks, start offset, and will return size of the volume to ++ * be created. See imsm_get_free_size() for details. ++ * add_to_super() and getinfo_super() detect when autolayout is in progress. ++ * If first volume exists, slots are set consistently to it. ++ * ++ * Return: &IMSM_STATUS_OK on success, &IMSM_STATUS_ERROR otherwise. ++ * ++ * Disks are marked for creation via dl->raiddisk. ++ */ ++static imsm_status_t autolayout_imsm(struct intel_super *super, ++ const int raiddisks, ++ unsigned long long size, const int chunk, ++ unsigned long long *freesize) + { +- struct intel_super *super = st->sb; +- struct dl *dl; +- int cnt; +- int rv = 0; ++ int curr_slot = 0; ++ struct dl *disk; ++ int vol_cnt = super->anchor->num_raid_devs; ++ imsm_status_t rv; + +- rv = imsm_get_free_size(st, raiddisks, size, chunk, freesize); +- if (rv) { +- cnt = 0; +- for (dl = super->disks; dl; dl = dl->next) +- if (dl->e) +- dl->raiddisk = cnt++; +- rv = 1; ++ rv = imsm_get_free_size(super, raiddisks, size, chunk, freesize); ++ if (rv != IMSM_STATUS_OK) ++ return IMSM_STATUS_ERROR; ++ ++ for (disk = super->disks; disk; disk = disk->next) { ++ if (!disk->e) ++ continue; ++ ++ if (curr_slot == raiddisks) ++ break; ++ ++ if (vol_cnt == 0) { ++ disk->raiddisk = curr_slot; ++ } else { ++ int _slot = get_disk_slot_in_dev(super, 0, disk->index); ++ ++ if (_slot == -1) { ++ pr_err("Disk %s is not used in first volume, aborting\n", ++ disk->devname); ++ return IMSM_STATUS_ERROR; ++ } ++ disk->raiddisk = _slot; ++ } ++ curr_slot++; + } + +- return rv; ++ return IMSM_STATUS_OK; + } + + static int validate_geometry_imsm(struct supertype *st, int level, int layout, +@@ -7654,35 +7700,35 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + } + + if (!dev) { +- if (st->sb) { +- struct intel_super *super = st->sb; +- if (!validate_geometry_imsm_orom(st->sb, level, layout, +- raiddisks, chunk, size, +- verbose)) ++ struct intel_super *super = st->sb; ++ ++ /* ++ * Autolayout mode, st->sb and freesize must be set. ++ */ ++ if (!super || !freesize) { ++ pr_vrb("freesize and superblock must be set for autolayout, aborting\n"); ++ return 1; ++ } ++ ++ if (!validate_geometry_imsm_orom(st->sb, level, layout, ++ raiddisks, chunk, size, ++ verbose)) ++ return 0; ++ ++ if (super->orom) { ++ imsm_status_t rv; ++ int count = count_volumes(super->hba, super->orom->dpa, ++ verbose); ++ if (super->orom->vphba <= count) { ++ pr_vrb("platform does not support more than %d raid volumes.\n", ++ super->orom->vphba); + return 0; +- /* we are being asked to automatically layout a +- * new volume based on the current contents of +- * the container. If the the parameters can be +- * satisfied reserve_space will record the disks, +- * start offset, and size of the volume to be +- * created. add_to_super and getinfo_super +- * detect when autolayout is in progress. +- */ +- /* assuming that freesize is always given when array is +- created */ +- if (super->orom && freesize) { +- int count; +- count = count_volumes(super->hba, +- super->orom->dpa, verbose); +- if (super->orom->vphba <= count) { +- pr_vrb("platform does not support more than %d raid volumes.\n", +- super->orom->vphba); +- return 0; +- } + } +- if (freesize) +- return reserve_space(st, raiddisks, size, +- *chunk, freesize); ++ ++ rv = autolayout_imsm(super, raiddisks, size, *chunk, ++ freesize); ++ if (rv != IMSM_STATUS_OK) ++ return 0; + } + return 1; + } +@@ -11538,7 +11584,7 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + unsigned long long current_size; + unsigned long long free_size; + unsigned long long max_size; +- int rv; ++ imsm_status_t rv; + + getinfo_super_imsm_volume(st, &info, NULL); + if (geo->level != info.array.level && geo->level >= 0 && +@@ -11657,9 +11703,10 @@ enum imsm_reshape_type imsm_analyze_change(struct supertype *st, + } + /* check the maximum available size + */ +- rv = imsm_get_free_size(st, dev->vol.map->num_members, +- 0, chunk, &free_size); +- if (rv == 0) ++ rv = imsm_get_free_size(super, dev->vol.map->num_members, ++ 0, chunk, &free_size); ++ ++ if (rv != IMSM_STATUS_OK) + /* Cannot find maximum available space + */ + max_size = 0; +-- +2.38.1 + diff --git a/0025-imsm-block-changing-slots-during-creation.patch b/0025-imsm-block-changing-slots-during-creation.patch new file mode 100644 index 0000000..4c3b918 --- /dev/null +++ b/0025-imsm-block-changing-slots-during-creation.patch @@ -0,0 +1,122 @@ +From 9a7df595bbe360132cb37c8b39aa1fd9ac24b43f Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 21 Jun 2022 00:10:43 +0800 +Subject: [PATCH 25/83] imsm: block changing slots during creation + +If user specifies drives for array creation, then slot order across +volumes is not preserved. +Ideally, it should be checked in validate_geometry() but it is not +possible in current implementation (order is determined later). +Add verification in add_to_super_imsm_volume() and throw error if +mismatch is detected. +IMSM allows to use only same members within container. +This is not hardware dependency but metadata limitation. +Therefore, 09-imsm-overlap test is removed. Testing it is pointless. +After this patch, creation in this scenario is blocked. Offset +verification is covered in other tests. + +Signed-off-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + super-intel.c | 33 ++++++++++++++++++++++----------- + tests/09imsm-overlap | 28 ---------------------------- + 2 files changed, 22 insertions(+), 39 deletions(-) + delete mode 100644 tests/09imsm-overlap + +diff --git a/super-intel.c b/super-intel.c +index deef7c87..8ffe485c 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5789,6 +5789,10 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, + struct imsm_map *map; + struct dl *dl, *df; + int slot; ++ int autolayout = 0; ++ ++ if (!is_fd_valid(fd)) ++ autolayout = 1; + + dev = get_imsm_dev(super, super->current_vol); + map = get_imsm_map(dev, MAP_0); +@@ -5799,25 +5803,32 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, + return 1; + } + +- if (!is_fd_valid(fd)) { +- /* we're doing autolayout so grab the pre-marked (in +- * validate_geometry) raid_disk +- */ +- for (dl = super->disks; dl; dl = dl->next) ++ for (dl = super->disks; dl ; dl = dl->next) { ++ if (autolayout) { + if (dl->raiddisk == dk->raid_disk) + break; +- } else { +- for (dl = super->disks; dl ; dl = dl->next) +- if (dl->major == dk->major && +- dl->minor == dk->minor) +- break; ++ } else if (dl->major == dk->major && dl->minor == dk->minor) ++ break; + } + + if (!dl) { +- pr_err("%s is not a member of the same container\n", devname); ++ if (!autolayout) ++ pr_err("%s is not a member of the same container.\n", ++ devname); + return 1; + } + ++ if (!autolayout && super->current_vol > 0) { ++ int _slot = get_disk_slot_in_dev(super, 0, dl->index); ++ ++ if (_slot != dk->raid_disk) { ++ pr_err("Member %s is in %d slot for the first volume, but is in %d slot for a new volume.\n", ++ dl->devname, _slot, dk->raid_disk); ++ pr_err("Raid members are in different order than for the first volume, aborting.\n"); ++ return 1; ++ } ++ } ++ + if (mpb->num_disks == 0) + if (!get_dev_sector_size(dl->fd, dl->devname, + &super->sector_size)) +diff --git a/tests/09imsm-overlap b/tests/09imsm-overlap +deleted file mode 100644 +index ff5d2093..00000000 +--- a/tests/09imsm-overlap ++++ /dev/null +@@ -1,28 +0,0 @@ +- +-. tests/env-imsm-template +- +-# create raid arrays with varying degress of overlap +-mdadm -CR $container -e imsm -n 6 $dev0 $dev1 $dev2 $dev3 $dev4 $dev5 +-imsm_check container 6 +- +-size=1024 +-level=1 +-num_disks=2 +-mdadm -CR $member0 $dev0 $dev1 -n $num_disks -l $level -z $size +-mdadm -CR $member1 $dev1 $dev2 -n $num_disks -l $level -z $size +-mdadm -CR $member2 $dev2 $dev3 -n $num_disks -l $level -z $size +-mdadm -CR $member3 $dev3 $dev4 -n $num_disks -l $level -z $size +-mdadm -CR $member4 $dev4 $dev5 -n $num_disks -l $level -z $size +- +-udevadm settle +- +-offset=0 +-imsm_check member $member0 $num_disks $level $size 1024 $offset +-offset=$((offset+size+4096)) +-imsm_check member $member1 $num_disks $level $size 1024 $offset +-offset=$((offset+size+4096)) +-imsm_check member $member2 $num_disks $level $size 1024 $offset +-offset=$((offset+size+4096)) +-imsm_check member $member3 $num_disks $level $size 1024 $offset +-offset=$((offset+size+4096)) +-imsm_check member $member4 $num_disks $level $size 1024 $offset +-- +2.38.1 + diff --git a/0026-mdadm-block-update-ppl-for-non-raid456-levels.patch b/0026-mdadm-block-update-ppl-for-non-raid456-levels.patch new file mode 100644 index 0000000..d593669 --- /dev/null +++ b/0026-mdadm-block-update-ppl-for-non-raid456-levels.patch @@ -0,0 +1,177 @@ +From 70f1ff4291b0388adca1f4c91918ce1175e8b360 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Wed, 15 Jun 2022 14:28:39 +0200 +Subject: [PATCH 26/83] mdadm: block update=ppl for non raid456 levels + +Option ppl should be used only for raid levels 4, 5 and 6. Cancel update +for other levels. + +Applied globally for imsm and ddf format. + +Additionally introduce is_level456() helper function. + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + Assemble.c | 11 +++++------ + Grow.c | 2 +- + Manage.c | 14 ++++++++++++-- + mdadm.h | 11 +++++++++++ + super0.c | 2 +- + super1.c | 3 +-- + 6 files changed, 31 insertions(+), 12 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 4b213560..6df6bfbc 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -906,8 +906,7 @@ static int force_array(struct mdinfo *content, + * devices in RAID4 or last devices in RAID4/5/6. + */ + delta = devices[j].i.delta_disks; +- if (devices[j].i.array.level >= 4 && +- devices[j].i.array.level <= 6 && ++ if (is_level456(devices[j].i.array.level) && + i/2 >= content->array.raid_disks - delta) + /* OK */; + else if (devices[j].i.array.level == 4 && +@@ -1226,8 +1225,7 @@ static int start_array(int mdfd, + fprintf(stderr, ".\n"); + } + if (content->reshape_active && +- content->array.level >= 4 && +- content->array.level <= 6) { ++ is_level456(content->array.level)) { + /* might need to increase the size + * of the stripe cache - default is 256 + */ +@@ -1974,7 +1972,8 @@ int assemble_container_content(struct supertype *st, int mdfd, + int start_reshape; + char *avail; + int err; +- int is_raid456, is_clean, all_disks; ++ int is_clean, all_disks; ++ bool is_raid456; + + if (sysfs_init(content, mdfd, NULL)) { + pr_err("Unable to initialize sysfs\n"); +@@ -2107,7 +2106,7 @@ int assemble_container_content(struct supertype *st, int mdfd, + content->array.state |= 1; + } + +- is_raid456 = (content->array.level >= 4 && content->array.level <= 6); ++ is_raid456 = is_level456(content->array.level); + is_clean = content->array.state & 1; + + if (enough(content->array.level, content->array.raid_disks, +diff --git a/Grow.c b/Grow.c +index f6efbc48..8c520d42 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -2944,7 +2944,7 @@ static int impose_level(int fd, int level, char *devname, int verbose) + } + + md_get_array_info(fd, &array); +- if (level == 0 && (array.level >= 4 && array.level <= 6)) { ++ if (level == 0 && is_level456(array.level)) { + /* To convert to RAID0 we need to fail and + * remove any non-data devices. */ + int found = 0; +diff --git a/Manage.c b/Manage.c +index f789e0c1..e5e6abe4 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -307,7 +307,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + * - unfreeze reshape + * - wait on 'sync_completed' for that point to be reached. + */ +- if (mdi && (mdi->array.level >= 4 && mdi->array.level <= 6) && ++ if (mdi && is_level456(mdi->array.level) && + sysfs_attribute_available(mdi, NULL, "sync_action") && + sysfs_attribute_available(mdi, NULL, "reshape_direction") && + sysfs_get_str(mdi, NULL, "sync_action", buf, 20) > 0 && +@@ -1679,6 +1679,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; + + memset(st, 0, sizeof(*st)); + +@@ -1696,6 +1697,13 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + if (mdmon_running(st->devnm)) + st->update_tail = &st->updates; + ++ info = st->ss->container_content(st, subarray); ++ ++ if (strncmp(update, "ppl", 3) == 0 && !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, ident); + + if (rv) { +@@ -1711,7 +1719,9 @@ int Update_subarray(char *dev, char *subarray, char *update, struct mddev_ident + pr_err("Updated subarray-%s name from %s, UUIDs may have changed\n", + subarray, dev); + +- free_super: ++free_super: ++ if (info) ++ free(info); + st->ss->free_super(st); + close(fd); + +diff --git a/mdadm.h b/mdadm.h +index d53df169..974415b9 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -796,6 +796,17 @@ static inline int is_fd_valid(int fd) + return (fd > -1); + } + ++/** ++ * is_level456() - check whether given level is between inclusive 4 and 6. ++ * @level: level to check. ++ * ++ * Return: true if condition is met, false otherwise ++ */ ++static inline bool is_level456(int level) ++{ ++ return (level >= 4 && level <= 6); ++} ++ + /** + * close_fd() - verify, close and unset file descriptor. + * @fd: pointer to file descriptor. +diff --git a/super0.c b/super0.c +index 61c9ec1d..37f595ed 100644 +--- a/super0.c ++++ b/super0.c +@@ -683,7 +683,7 @@ static int update_super0(struct supertype *st, struct mdinfo *info, + int parity = sb->level == 6 ? 2 : 1; + rv = 0; + +- if (sb->level >= 4 && sb->level <= 6 && ++ if (is_level456(sb->level) && + sb->reshape_position % ( + sb->new_chunk/512 * + (sb->raid_disks - sb->delta_disks - parity))) { +diff --git a/super1.c b/super1.c +index 3a0c69fd..71af860c 100644 +--- a/super1.c ++++ b/super1.c +@@ -1530,8 +1530,7 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + * So we reject a revert-reshape unless the + * alignment is good. + */ +- if (__le32_to_cpu(sb->level) >= 4 && +- __le32_to_cpu(sb->level) <= 6) { ++ if (is_level456(__le32_to_cpu(sb->level))) { + reshape_sectors = + __le64_to_cpu(sb->reshape_position); + reshape_chunk = __le32_to_cpu(sb->new_chunk); +-- +2.38.1 + diff --git a/0027-mdadm-Fix-array-size-mismatch-after-grow.patch b/0027-mdadm-Fix-array-size-mismatch-after-grow.patch new file mode 100644 index 0000000..02bdf9c --- /dev/null +++ b/0027-mdadm-Fix-array-size-mismatch-after-grow.patch @@ -0,0 +1,30 @@ +From 42e02e613fb0b4a2c0c0d984b9e6e2933875bb44 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 22 Jul 2022 08:43:47 +0200 +Subject: [PATCH 27/83] mdadm: Fix array size mismatch after grow + +imsm_fix_size_mismatch() is invoked to fix the problem, but it couldn't +proceed due to migration check. This patch allows for intended behavior. + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + super-intel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/super-intel.c b/super-intel.c +index 8ffe485c..76b947f5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -11854,7 +11854,7 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index) + unsigned long long d_size = imsm_dev_size(dev); + int u_size; + +- if (calc_size == d_size || dev->vol.migr_type == MIGR_GEN_MIGR) ++ if (calc_size == d_size) + continue; + + /* There is a difference, confirm that imsm_dev_size is +-- +2.38.1 + diff --git a/0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch b/0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch new file mode 100644 index 0000000..08688dd --- /dev/null +++ b/0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch @@ -0,0 +1,34 @@ +From 751757620afb25a4c02746bf8368a7b5f22352ec Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Fri, 22 Jul 2022 08:43:48 +0200 +Subject: [PATCH 28/83] mdadm: Remove dead code in imsm_fix_size_mismatch + +imsm_create_metadata_update_for_size_change() that returns u_size value +could return 0 in the past. As its behavior changed, and returned value +is always the size of imsm_update_size_change structure, check for +u_size is no longer needed. + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + super-intel.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 76b947f5..4ddfcf94 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -11869,10 +11869,6 @@ static int imsm_fix_size_mismatch(struct supertype *st, int subarray_index) + geo.size = d_size; + u_size = imsm_create_metadata_update_for_size_change(st, &geo, + &update); +- if (u_size < 1) { +- dprintf("imsm: Cannot prepare size change update\n"); +- goto exit; +- } + imsm_update_metadata_locally(st, update, u_size); + if (st->update_tail) { + append_metadata_update(st, update, u_size); +-- +2.38.1 + diff --git a/0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch b/0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch new file mode 100644 index 0000000..f337ff0 --- /dev/null +++ b/0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch @@ -0,0 +1,40 @@ +From c8d1c398505b62d9129a4e711f17e4469f4327ff Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Thu, 14 Jul 2022 09:02:10 +0200 +Subject: [PATCH 29/83] Monitor: use devname as char array instead of pointer + +Device name wasn't filled properly due to incorrect use of strcpy. +Strcpy was used twice. Firstly to fill devname with "/dev/md/" +and then to add chosen name. First strcpy result was overwritten by +second one (as a result instead of "/dev/md/" +was assigned). This commit changes this implementation to use snprintf +and devname with fixed size. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Monitor.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 6ca1ebe5..a5b11ae2 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -190,9 +190,11 @@ int Monitor(struct mddev_dev *devlist, + if (mdlist->devname[0] == '/') + st->devname = xstrdup(mdlist->devname); + else { +- st->devname = xmalloc(8+strlen(mdlist->devname)+1); +- strcpy(strcpy(st->devname, "/dev/md/"), +- mdlist->devname); ++ /* length of "/dev/md/" + device name + terminating byte */ ++ size_t _len = sizeof("/dev/md/") + strnlen(mdlist->devname, PATH_MAX); ++ ++ st->devname = xcalloc(_len, sizeof(char)); ++ snprintf(st->devname, _len, "/dev/md/%s", mdlist->devname); + } + if (!is_mddev(mdlist->devname)) + return 1; +-- +2.38.1 + diff --git a/0030-Monitor-use-snprintf-to-fill-device-name.patch b/0030-Monitor-use-snprintf-to-fill-device-name.patch new file mode 100644 index 0000000..7d3b4bc --- /dev/null +++ b/0030-Monitor-use-snprintf-to-fill-device-name.patch @@ -0,0 +1,133 @@ +From 84d969be8f6d8a345b75f558fad26e4f62a558f6 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Thu, 14 Jul 2022 09:02:11 +0200 +Subject: [PATCH 30/83] Monitor: use snprintf to fill device name + +Safe string functions are propagated in Monitor.c. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Monitor.c | 37 ++++++++++++++----------------------- + 1 file changed, 14 insertions(+), 23 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index a5b11ae2..93f36ac0 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -33,8 +33,8 @@ + #endif + + struct state { +- char *devname; +- char devnm[32]; /* to sync with mdstat info */ ++ 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 */ + unsigned int utime; + int err; + char *spare_group; +@@ -45,9 +45,9 @@ struct state { + int devstate[MAX_DISKS]; + dev_t devid[MAX_DISKS]; + int percent; +- char parent_devnm[32]; /* For subarray, devnm of parent. +- * For others, "" +- */ ++ char parent_devnm[MD_NAME_MAX]; /* For subarray, devnm of parent. ++ * For others, "" ++ */ + struct supertype *metadata; + struct state *subarray;/* for a container it is a link to first subarray + * for a subarray it is a link to next subarray +@@ -187,15 +187,8 @@ int Monitor(struct mddev_dev *devlist, + continue; + + st = xcalloc(1, sizeof *st); +- if (mdlist->devname[0] == '/') +- st->devname = xstrdup(mdlist->devname); +- else { +- /* length of "/dev/md/" + device name + terminating byte */ +- size_t _len = sizeof("/dev/md/") + strnlen(mdlist->devname, PATH_MAX); +- +- st->devname = xcalloc(_len, sizeof(char)); +- snprintf(st->devname, _len, "/dev/md/%s", mdlist->devname); +- } ++ snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), ++ "/dev/md/%s", basename(mdlist->devname)); + if (!is_mddev(mdlist->devname)) + return 1; + st->next = statelist; +@@ -218,7 +211,7 @@ int Monitor(struct mddev_dev *devlist, + + st = xcalloc(1, sizeof *st); + mdlist = conf_get_ident(dv->devname); +- st->devname = xstrdup(dv->devname); ++ snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", dv->devname); + st->next = statelist; + st->devnm[0] = 0; + st->percent = RESYNC_UNKNOWN; +@@ -301,7 +294,6 @@ int Monitor(struct mddev_dev *devlist, + for (stp = &statelist; (st = *stp) != NULL; ) { + if (st->from_auto && st->err > 5) { + *stp = st->next; +- free(st->devname); + free(st->spare_group); + free(st); + } else +@@ -554,7 +546,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, + goto disappeared; + + if (st->devnm[0] == 0) +- strcpy(st->devnm, fd2devnm(fd)); ++ snprintf(st->devnm, MD_NAME_MAX, "%s", fd2devnm(fd)); + + for (mse2 = mdstat; mse2; mse2 = mse2->next) + if (strcmp(mse2->devnm, st->devnm) == 0) { +@@ -684,7 +676,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, + strncmp(mse->metadata_version, "external:", 9) == 0 && + is_subarray(mse->metadata_version+9)) { + char *sl; +- strcpy(st->parent_devnm, mse->metadata_version + 10); ++ snprintf(st->parent_devnm, MD_NAME_MAX, "%s", mse->metadata_version + 10); + sl = strchr(st->parent_devnm, '/'); + if (sl) + *sl = 0; +@@ -772,14 +764,13 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist, + continue; + } + +- st->devname = xstrdup(name); ++ snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), "%s", name); + if ((fd = open(st->devname, O_RDONLY)) < 0 || + md_get_array_info(fd, &array) < 0) { + /* no such array */ + if (fd >= 0) + close(fd); + put_md_name(st->devname); +- free(st->devname); + if (st->metadata) { + st->metadata->ss->free_super(st->metadata); + free(st->metadata); +@@ -791,7 +782,7 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist, + st->next = *statelist; + st->err = 1; + st->from_auto = 1; +- strcpy(st->devnm, mse->devnm); ++ snprintf(st->devnm, MD_NAME_MAX, "%s", mse->devnm); + st->percent = RESYNC_UNKNOWN; + st->expected_spares = -1; + if (mse->metadata_version && +@@ -799,8 +790,8 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist, + "external:", 9) == 0 && + is_subarray(mse->metadata_version+9)) { + char *sl; +- strcpy(st->parent_devnm, +- mse->metadata_version+10); ++ snprintf(st->parent_devnm, MD_NAME_MAX, ++ "%s", mse->metadata_version + 10); + sl = strchr(st->parent_devnm, '/'); + *sl = 0; + } else +-- +2.38.1 + diff --git a/0031-Makefile-Don-t-build-static-build-with-everything-an.patch b/0031-Makefile-Don-t-build-static-build-with-everything-an.patch new file mode 100644 index 0000000..de5e49e --- /dev/null +++ b/0031-Makefile-Don-t-build-static-build-with-everything-an.patch @@ -0,0 +1,42 @@ +From 14ae4c37bce9a53da08d59d6c2d7e0946e9c9f47 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:06 -0600 +Subject: [PATCH 31/83] Makefile: Don't build static build with everything and + everything-test + +Running the test suite requires building everything, but it seems to be +difficult to build the static version of mdadm now seeing there +is no readily available static udev library. + +The test suite doesn't need the static binary so just don't build it +with the everything or everything-test targets. + +Leave the mdadm.static and install-static targets in place in case +someone still has a use case for the static binary. + +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index bf126033..ec1f99ed 100644 +--- a/Makefile ++++ b/Makefile +@@ -182,9 +182,9 @@ check_rundir: + echo "***** or set CHECK_RUN_DIR=0"; exit 1; \ + fi + +-everything: all mdadm.static swap_super test_stripe raid6check \ ++everything: all swap_super test_stripe raid6check \ + mdadm.Os mdadm.O2 man +-everything-test: all mdadm.static swap_super test_stripe \ ++everything-test: all swap_super test_stripe \ + mdadm.Os mdadm.O2 man + # mdadm.uclibc doesn't work on x86-64 + # mdadm.tcc doesn't work.. +-- +2.38.1 + diff --git a/0032-DDF-Cleanup-validate_geometry_ddf_container.patch b/0032-DDF-Cleanup-validate_geometry_ddf_container.patch new file mode 100644 index 0000000..ec2954d --- /dev/null +++ b/0032-DDF-Cleanup-validate_geometry_ddf_container.patch @@ -0,0 +1,141 @@ +From 679bd9508a30b2a0a1baecc9a21dd6c7d8d8d7dc Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:07 -0600 +Subject: [PATCH 32/83] DDF: Cleanup validate_geometry_ddf_container() + +Move the function up so that the function declaration is not necessary +and remove the unused arguments to the function. + +No functional changes are intended but will help with a bug fix in the +next patch. + +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + super-ddf.c | 88 ++++++++++++++++++++++++----------------------------- + 1 file changed, 39 insertions(+), 49 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index abbc8b09..9d867f69 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -503,13 +503,6 @@ struct ddf_super { + static int load_super_ddf_all(struct supertype *st, int fd, + void **sbp, char *devname); + static int get_svd_state(const struct ddf_super *, const struct vcl *); +-static int +-validate_geometry_ddf_container(struct supertype *st, +- int level, int layout, int raiddisks, +- int chunk, unsigned long long size, +- unsigned long long data_offset, +- char *dev, unsigned long long *freesize, +- int verbose); + + static int validate_geometry_ddf_bvd(struct supertype *st, + int level, int layout, int raiddisks, +@@ -3322,6 +3315,42 @@ static int reserve_space(struct supertype *st, int raiddisks, + return 1; + } + ++static int ++validate_geometry_ddf_container(struct supertype *st, ++ int level, int raiddisks, ++ unsigned long long data_offset, ++ char *dev, unsigned long long *freesize, ++ int verbose) ++{ ++ int fd; ++ unsigned long long ldsize; ++ ++ if (level != LEVEL_CONTAINER) ++ return 0; ++ if (!dev) ++ return 1; ++ ++ fd = dev_open(dev, O_RDONLY|O_EXCL); ++ if (fd < 0) { ++ if (verbose) ++ pr_err("ddf: Cannot open %s: %s\n", ++ dev, strerror(errno)); ++ return 0; ++ } ++ if (!get_dev_size(fd, dev, &ldsize)) { ++ close(fd); ++ return 0; ++ } ++ close(fd); ++ if (freesize) { ++ *freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS); ++ if (*freesize == 0) ++ return 0; ++ } ++ ++ return 1; ++} ++ + static int validate_geometry_ddf(struct supertype *st, + int level, int layout, int raiddisks, + int *chunk, unsigned long long size, +@@ -3347,11 +3376,9 @@ static int validate_geometry_ddf(struct supertype *st, + level = LEVEL_CONTAINER; + if (level == LEVEL_CONTAINER) { + /* Must be a fresh device to add to a container */ +- return validate_geometry_ddf_container(st, level, layout, +- raiddisks, *chunk, +- size, data_offset, dev, +- freesize, +- verbose); ++ return validate_geometry_ddf_container(st, level, raiddisks, ++ data_offset, dev, ++ freesize, verbose); + } + + if (!dev) { +@@ -3449,43 +3476,6 @@ static int validate_geometry_ddf(struct supertype *st, + return 1; + } + +-static int +-validate_geometry_ddf_container(struct supertype *st, +- int level, int layout, int raiddisks, +- int chunk, unsigned long long size, +- unsigned long long data_offset, +- char *dev, unsigned long long *freesize, +- int verbose) +-{ +- int fd; +- unsigned long long ldsize; +- +- if (level != LEVEL_CONTAINER) +- return 0; +- if (!dev) +- return 1; +- +- fd = dev_open(dev, O_RDONLY|O_EXCL); +- if (fd < 0) { +- if (verbose) +- pr_err("ddf: Cannot open %s: %s\n", +- dev, strerror(errno)); +- return 0; +- } +- if (!get_dev_size(fd, dev, &ldsize)) { +- close(fd); +- return 0; +- } +- close(fd); +- if (freesize) { +- *freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS); +- if (*freesize == 0) +- return 0; +- } +- +- return 1; +-} +- + static int validate_geometry_ddf_bvd(struct supertype *st, + int level, int layout, int raiddisks, + int *chunk, unsigned long long size, +-- +2.38.1 + diff --git a/0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch b/0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch new file mode 100644 index 0000000..3a53577 --- /dev/null +++ b/0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch @@ -0,0 +1,49 @@ +From 2b93288a5650bb811932836f67f30d63c5ddcfbd Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:08 -0600 +Subject: [PATCH 33/83] DDF: Fix NULL pointer dereference in + validate_geometry_ddf() + +A relatively recent patch added a call to validate_geometry() in +Manage_add() that has level=LEVEL_CONTAINER and chunk=NULL. + +This causes some ddf tests to segfault which aborts the test suite. + +To fix this, avoid dereferencing chunk when the level is +LEVEL_CONTAINER or LEVEL_NONE. + +Fixes: 1f5d54a06df0 ("Manage: Call validate_geometry when adding drive to external container") +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + super-ddf.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index 9d867f69..949e7d15 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -3369,9 +3369,6 @@ static int validate_geometry_ddf(struct supertype *st, + * If given BVDs, we make an SVD, changing all the GUIDs in the process. + */ + +- if (*chunk == UnSet) +- *chunk = DEFAULT_CHUNK; +- + if (level == LEVEL_NONE) + level = LEVEL_CONTAINER; + if (level == LEVEL_CONTAINER) { +@@ -3381,6 +3378,9 @@ static int validate_geometry_ddf(struct supertype *st, + freesize, verbose); + } + ++ if (*chunk == UnSet) ++ *chunk = DEFAULT_CHUNK; ++ + if (!dev) { + mdu_array_info_t array = { + .level = level, +-- +2.38.1 + diff --git a/0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch b/0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch new file mode 100644 index 0000000..2695f67 --- /dev/null +++ b/0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch @@ -0,0 +1,85 @@ +From 548e9b916f86c06e2cdb50d8f49633f9bec66c7e Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:09 -0600 +Subject: [PATCH 34/83] mdadm/Grow: Fix use after close bug by closing after + fork + +The test 07reshape-grow fails most of the time. But it succeeds around +1 in 5 times. When it does succeed, it causes the tests to die because +mdadm has segfaulted. + +The segfault was caused by mdadm attempting to repoen a file +descriptor that was already closed. The backtrace of the segfault +was: + + #0 __strncmp_avx2 () at ../sysdeps/x86_64/multiarch/strcmp-avx2.S:101 + #1 0x000056146e31d44b in devnm2devid (devnm=0x0) at util.c:956 + #2 0x000056146e31dab4 in open_dev_flags (devnm=0x0, flags=0) + at util.c:1072 + #3 0x000056146e31db22 in open_dev (devnm=0x0) at util.c:1079 + #4 0x000056146e3202e8 in reopen_mddev (mdfd=4) at util.c:2244 + #5 0x000056146e329f36 in start_array (mdfd=4, + mddev=0x7ffc55342450 "/dev/md0", content=0x7ffc55342860, + st=0x56146fc78660, ident=0x7ffc55342f70, best=0x56146fc6f5d0, + bestcnt=10, chosen_drive=0, devices=0x56146fc706b0, okcnt=5, + sparecnt=0, rebuilding_cnt=0, journalcnt=0, c=0x7ffc55342e90, + clean=1, avail=0x56146fc78720 "\001\001\001\001\001", + start_partial_ok=0, err_ok=0, was_forced=0) + at Assemble.c:1206 + #6 0x000056146e32c36e in Assemble (st=0x56146fc78660, + mddev=0x7ffc55342450 "/dev/md0", ident=0x7ffc55342f70, + devlist=0x56146fc6e2d0, c=0x7ffc55342e90) + at Assemble.c:1914 + #7 0x000056146e312ac9 in main (argc=11, argv=0x7ffc55343238) + at mdadm.c:1510 + +The file descriptor was closed early in Grow_continue(). The noted commit +moved the close() call to close the fd above the fork which caused the +parent process to return with a closed fd. + +This meant reshape_array() and Grow_continue() would return in the parent +with the fd forked. The fd would eventually be passed to reopen_mddev() +which returned an unhandled NULL from fd2devnm() which would then be +dereferenced in devnm2devid. + +Fix this by moving the close() call below the fork. This appears to +fix the 07revert-grow test. While we're at it, switch to using +close_fd() to invalidate the file descriptor. + +Fixes: 77b72fa82813 ("mdadm/Grow: prevent md's fd from being occupied during delayed time") +Cc: Alex Wu +Cc: BingJing Chang +Cc: Danny Shih +Cc: ChangSyun Peng +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Grow.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index 8c520d42..97f22c75 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -3514,7 +3514,6 @@ started: + return 0; + } + +- close(fd); + /* Now we just need to kick off the reshape and watch, while + * handling backups of the data... + * This is all done by a forked background process. +@@ -3535,6 +3534,9 @@ started: + break; + } + ++ /* Close unused file descriptor in the forked process */ ++ close_fd(&fd); ++ + /* If another array on the same devices is busy, the + * reshape will wait for them. This would mean that + * the first section that we suspend will stay suspended +-- +2.38.1 + diff --git a/0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch b/0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch new file mode 100644 index 0000000..ed09288 --- /dev/null +++ b/0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch @@ -0,0 +1,36 @@ +From 9ae62977b51dab0f4bb46b1c8ea5ebd1705b2f4d Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:10 -0600 +Subject: [PATCH 35/83] monitor: Avoid segfault when calling NULL + get_bad_blocks + +Not all struct superswitch implement a get_bad_blocks() function, +yet mdmon seems to call it without checking for NULL and thus +occasionally segfaults in the test 10ddf-geometry. + +Fix this by checking for NULL before calling it. + +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + monitor.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/monitor.c b/monitor.c +index b877e595..820a93d0 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -311,6 +311,9 @@ static int check_for_cleared_bb(struct active_array *a, struct mdinfo *mdi) + struct md_bb *bb; + int i; + ++ if (!ss->get_bad_blocks) ++ return -1; ++ + /* + * Get a list of bad blocks for an array, then read list of + * acknowledged bad blocks from kernel and compare it against metadata +-- +2.38.1 + diff --git a/0036-mdadm-Fix-mdadm-r-remove-option-regression.patch b/0036-mdadm-Fix-mdadm-r-remove-option-regression.patch new file mode 100644 index 0000000..f091c64 --- /dev/null +++ b/0036-mdadm-Fix-mdadm-r-remove-option-regression.patch @@ -0,0 +1,78 @@ +From 6c9d9260633f2c8491985b0782cf0fbd7e51651b Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:11 -0600 +Subject: [PATCH 36/83] mdadm: Fix mdadm -r remove option regression + +The commit noted below globally adds a parameter to the -r option but missed +the fact that -r is used for another purpose: --remove. + +After that commit, a command such as: + + mdadm /dev/md0 -r /dev/loop0 + +will do nothing seeing the device parameter will be consumed as a +argument to the -r option; thus, there will only be one device +seen one the command line, devs_found will only be 1 and nothing will +happen. + +This caused the 01r5integ and 01raid6integ tests to hang indefinitely +as mdadm did not remove the failed device. With the device not removed, +it would not be readded. Then the loop waiting for the array status to +change would loop forever. + +This commit was recently reverted, but the legitimate fix for the +monitor operations was still not fixed. So add specific monitor +short ops to re-fix the --monitor -r option. + +Fixes: 546047688e1c ("mdadm: fix coredump of mdadm --monitor -r") +Fixes: 190dc029b141 ("Revert "mdadm: fix coredump of mdadm --monitor -r"") +Cc: Wu Guanghao +Cc: Mariusz Tkaczyk +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + ReadMe.c | 1 + + mdadm.c | 1 + + mdadm.h | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/ReadMe.c b/ReadMe.c +index bec1be9a..7518a32a 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -82,6 +82,7 @@ char Version[] = "mdadm - v" VERSION " - " VERS_DATE EXTRAVERSION "\n"; + */ + + char short_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; ++char short_monitor_options[]="-ABCDEFGIQhVXYWZ:vqbc:i:l:p:m:r:n:x:u:c:d:z:U:N:safRSow1tye:k:"; + char short_bitmap_options[]= + "-ABCDEFGIQhVXYWZ:vqb:c:i:l:p:m:n:x:u:c:d:z:U:N:sarfRSow1tye:k:"; + char short_bitmap_auto_options[]= +diff --git a/mdadm.c b/mdadm.c +index be40686c..d0c5e6de 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -227,6 +227,7 @@ int main(int argc, char *argv[]) + shortopt = short_bitmap_auto_options; + break; + case 'F': newmode = MONITOR; ++ shortopt = short_monitor_options; + break; + case 'G': newmode = GROW; + shortopt = short_bitmap_options; +diff --git a/mdadm.h b/mdadm.h +index 974415b9..163f4a49 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -419,6 +419,7 @@ enum mode { + }; + + extern char short_options[]; ++extern char short_monitor_options[]; + extern char short_bitmap_options[]; + extern char short_bitmap_auto_options[]; + extern struct option long_options[]; +-- +2.38.1 + diff --git a/0037-mdadm-Fix-optional-write-behind-parameter.patch b/0037-mdadm-Fix-optional-write-behind-parameter.patch new file mode 100644 index 0000000..60cafdb --- /dev/null +++ b/0037-mdadm-Fix-optional-write-behind-parameter.patch @@ -0,0 +1,42 @@ +From 41edf6f45895193f4a523cb0a08d639c9ff9ccc9 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:12 -0600 +Subject: [PATCH 37/83] mdadm: Fix optional --write-behind parameter + +The commit noted below changed the behaviour of --write-behind to +require an argument. This broke the 06wrmostly test with the error: + + mdadm: Invalid value for maximum outstanding write-behind writes: (null). + Must be between 0 and 16383. + +To fix this, check if optarg is NULL before parising it, as the origial +code did. + +Fixes: 60815698c0ac ("Refactor parse_num and use it to parse optarg.") +Cc: Mateusz Grzonka +Signed-off-by: Logan Gunthorpe +Acked-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + mdadm.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/mdadm.c b/mdadm.c +index d0c5e6de..56722ed9 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1201,8 +1201,9 @@ int main(int argc, char *argv[]) + case O(BUILD, WriteBehind): + case O(CREATE, WriteBehind): + s.write_behind = DEFAULT_MAX_WRITE_BEHIND; +- if (parse_num(&s.write_behind, optarg) != 0 || +- s.write_behind < 0 || s.write_behind > 16383) { ++ if (optarg && ++ (parse_num(&s.write_behind, optarg) != 0 || ++ s.write_behind < 0 || s.write_behind > 16383)) { + pr_err("Invalid value for maximum outstanding write-behind writes: %s.\n\tMust be between 0 and 16383.\n", + optarg); + exit(2); +-- +2.38.1 + diff --git a/0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch b/0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch new file mode 100644 index 0000000..7794e18 --- /dev/null +++ b/0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch @@ -0,0 +1,38 @@ +From 7539254342bc591717b0051734cc6c09c1b88640 Mon Sep 17 00:00:00 2001 +From: Sudhakar Panneerselvam +Date: Wed, 22 Jun 2022 14:25:13 -0600 +Subject: [PATCH 38/83] tests/00raid0: add a test that validates raid0 with + layout fails for 0.9 + +329dfc28debb disallows the creation of raid0 with layouts for 0.9 +metadata. This test confirms the new behavior. + +Signed-off-by: Sudhakar Panneerselvam +Signed-off-by: Himanshu Madhani +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + tests/00raid0 | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/tests/00raid0 b/tests/00raid0 +index 8bc18985..e6b21cc4 100644 +--- a/tests/00raid0 ++++ b/tests/00raid0 +@@ -6,11 +6,9 @@ check raid0 + testdev $md0 3 $mdsize2_l 512 + mdadm -S $md0 + +-# now with version-0.90 superblock ++# verify raid0 with layouts fail for 0.90 + mdadm -CR $md0 -e0.90 -l0 -n4 $dev0 $dev1 $dev2 $dev3 +-check raid0 +-testdev $md0 4 $mdsize0 512 +-mdadm -S $md0 ++check opposite_result + + # now with no superblock + mdadm -B $md0 -l0 -n5 $dev0 $dev1 $dev2 $dev3 $dev4 +-- +2.38.1 + diff --git a/0039-tests-fix-raid0-tests-for-0.90-metadata.patch b/0039-tests-fix-raid0-tests-for-0.90-metadata.patch new file mode 100644 index 0000000..d897fb1 --- /dev/null +++ b/0039-tests-fix-raid0-tests-for-0.90-metadata.patch @@ -0,0 +1,99 @@ +From 14c2161edb77d7294199e8aa7daa9f9d1d0ad5d7 Mon Sep 17 00:00:00 2001 +From: Sudhakar Panneerselvam +Date: Wed, 22 Jun 2022 14:25:14 -0600 +Subject: [PATCH 39/83] tests: fix raid0 tests for 0.90 metadata + +Some of the test cases fail because raid0 creation fails with the error, +"0.90 metadata does not support layouts for RAID0" added by commit, +329dfc28debb. Fix some of the test cases by switching from raid0 to +linear level for 0.9 metadata where possible. + +Signed-off-by: Sudhakar Panneerselvam +Signed-off-by: Himanshu Madhani +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + tests/00raid0 | 4 ++-- + tests/00readonly | 4 ++++ + tests/03r0assem | 6 +++--- + tests/04r0update | 4 ++-- + tests/04update-metadata | 2 +- + 5 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/tests/00raid0 b/tests/00raid0 +index e6b21cc4..9b8896cb 100644 +--- a/tests/00raid0 ++++ b/tests/00raid0 +@@ -20,8 +20,8 @@ mdadm -S $md0 + # now same again with different chunk size + for chunk in 4 32 256 + do +- mdadm -CR $md0 -e0.90 -l raid0 --chunk $chunk -n3 $dev0 $dev1 $dev2 +- check raid0 ++ mdadm -CR $md0 -e0.90 -l linear --chunk $chunk -n3 $dev0 $dev1 $dev2 ++ check linear + testdev $md0 3 $mdsize0 $chunk + mdadm -S $md0 + +diff --git a/tests/00readonly b/tests/00readonly +index 28b0fa13..39202487 100644 +--- a/tests/00readonly ++++ b/tests/00readonly +@@ -4,6 +4,10 @@ for metadata in 0.9 1.0 1.1 1.2 + do + for level in linear raid0 raid1 raid4 raid5 raid6 raid10 + do ++ if [[ $metadata == "0.9" && $level == "raid0" ]]; ++ then ++ continue ++ fi + mdadm -CR $md0 -l $level -n 4 --metadata=$metadata \ + $dev1 $dev2 $dev3 $dev4 --assume-clean + check nosync +diff --git a/tests/03r0assem b/tests/03r0assem +index 6744e322..44df0645 100644 +--- a/tests/03r0assem ++++ b/tests/03r0assem +@@ -68,9 +68,9 @@ mdadm -S $md2 + ### Now for version 0... + + mdadm --zero-superblock $dev0 $dev1 $dev2 +-mdadm -CR $md2 -l0 --metadata=0.90 -n3 $dev0 $dev1 $dev2 +-check raid0 +-tst="testdev $md2 3 $mdsize0 512" ++mdadm -CR $md2 -llinear --metadata=0.90 -n3 $dev0 $dev1 $dev2 ++check linear ++tst="testdev $md2 3 $mdsize0 1" + $tst + + uuid=`mdadm -Db $md2 | sed 's/.*UUID=//'` +diff --git a/tests/04r0update b/tests/04r0update +index 73ee3b9f..b95efb06 100644 +--- a/tests/04r0update ++++ b/tests/04r0update +@@ -1,7 +1,7 @@ + + # create a raid0, re-assemble with a different super-minor +-mdadm -CR -e 0.90 $md0 -l0 -n3 $dev0 $dev1 $dev2 +-testdev $md0 3 $mdsize0 512 ++mdadm -CR -e 0.90 $md0 -llinear -n3 $dev0 $dev1 $dev2 ++testdev $md0 3 $mdsize0 1 + minor1=`mdadm -E $dev0 | sed -n -e 's/.*Preferred Minor : //p'` + mdadm -S /dev/md0 + +diff --git a/tests/04update-metadata b/tests/04update-metadata +index 232fc1ff..08c14af7 100644 +--- a/tests/04update-metadata ++++ b/tests/04update-metadata +@@ -8,7 +8,7 @@ set -xe + + dlist="$dev0 $dev1 $dev2 $dev3" + +-for ls in raid0/4 linear/4 raid1/1 raid5/3 raid6/2 ++for ls in linear/4 raid1/1 raid5/3 raid6/2 + do + s=${ls#*/} l=${ls%/*} + mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist +-- +2.38.1 + diff --git a/0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch b/0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch new file mode 100644 index 0000000..12b291b --- /dev/null +++ b/0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch @@ -0,0 +1,39 @@ +From de045db607b1ac4b70fc2a8878463e029c2ab1dc Mon Sep 17 00:00:00 2001 +From: Sudhakar Panneerselvam +Date: Wed, 22 Jun 2022 14:25:15 -0600 +Subject: [PATCH 40/83] tests/04update-metadata: avoid passing chunk size to + raid1 + +'04update-metadata' test fails with error, "specifying chunk size is +forbidden for this level" added by commit, 5b30a34aa4b5e. Hence, +correcting the test to ignore passing chunk size to raid1. + +Signed-off-by: Sudhakar Panneerselvam +Signed-off-by: Himanshu Madhani +[logang@deltatee.com: fix if/then style and dropped unrelated hunk] +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + tests/04update-metadata | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tests/04update-metadata b/tests/04update-metadata +index 08c14af7..2b72a303 100644 +--- a/tests/04update-metadata ++++ b/tests/04update-metadata +@@ -11,7 +11,11 @@ dlist="$dev0 $dev1 $dev2 $dev3" + for ls in linear/4 raid1/1 raid5/3 raid6/2 + do + s=${ls#*/} l=${ls%/*} +- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist ++ if [[ $l == 'raid1' ]]; then ++ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist ++ else ++ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist ++ fi + testdev $md0 $s 19904 64 + mdadm -S $md0 + mdadm -A $md0 --update=metadata $dlist +-- +2.38.1 + diff --git a/0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch b/0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch new file mode 100644 index 0000000..e6b9bba --- /dev/null +++ b/0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch @@ -0,0 +1,31 @@ +From a2c832465fc75202e244327b2081231dfa974617 Mon Sep 17 00:00:00 2001 +From: Sudhakar Panneerselvam +Date: Wed, 22 Jun 2022 14:25:16 -0600 +Subject: [PATCH 41/83] tests/02lineargrow: clear the superblock at every + iteration + +This fixes 02lineargrow test as prior metadata causes --add operation +to misbehave. + +Signed-off-by: Sudhakar Panneerselvam +Signed-off-by: Himanshu Madhani +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + tests/02lineargrow | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tests/02lineargrow b/tests/02lineargrow +index e05c219d..595bf9f2 100644 +--- a/tests/02lineargrow ++++ b/tests/02lineargrow +@@ -20,4 +20,6 @@ do + testdev $md0 3 $sz 1 + + mdadm -S $md0 ++ mdadm --zero /dev/loop2 ++ mdadm --zero /dev/loop3 + done +-- +2.38.1 + diff --git a/0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch b/0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch new file mode 100644 index 0000000..63f72dc --- /dev/null +++ b/0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch @@ -0,0 +1,88 @@ +From a7bfcc716e235664dfb3b6c5a9590273e611ac72 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:17 -0600 +Subject: [PATCH 42/83] mdadm/test: Add a mode to repeat specified tests + +Many tests fail infrequently or rarely. To help find these, add +an option to run the tests multiple times by specifying --loop=N. + +If --loop=0 is specified, the test will be looped forever. + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + test | 36 ++++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/test b/test +index 711a3c7a..da6db5e0 100755 +--- a/test ++++ b/test +@@ -10,6 +10,7 @@ devlist= + + savelogs=0 + exitonerror=1 ++loop=1 + prefix='[0-9][0-9]' + + # use loop devices by default if doesn't specify --dev +@@ -117,6 +118,7 @@ do_help() { + --logdir=directory Directory to save all logfiles in + --save-logs Usually use with --logdir together + --keep-going | --no-error Don't stop on error, ie. run all tests ++ --loop=N Run tests N times (0 to run forever) + --dev=loop|lvm|ram|disk Use loop devices (default), LVM, RAM or disk + --disks= Provide a bunch of physical devices for test + --volgroup=name LVM volume group for LVM test +@@ -211,6 +213,9 @@ parse_args() { + --keep-going | --no-error ) + exitonerror=0 + ;; ++ --loop=* ) ++ loop="${i##*=}" ++ ;; + --disable-multipath ) + unset MULTIPATH + ;; +@@ -263,19 +268,26 @@ main() { + echo "Testing on linux-$(uname -r) kernel" + [ "$savelogs" == "1" ] && + echo "Saving logs to $logdir" +- if [ "x$TESTLIST" != "x" ] +- then +- for script in ${TESTLIST[@]} +- do +- do_test $testdir/$script +- done +- else +- for script in $testdir/$prefix $testdir/$prefix*[^~] +- do +- do_test $script +- done +- fi + ++ while true; do ++ if [ "x$TESTLIST" != "x" ] ++ then ++ for script in ${TESTLIST[@]} ++ do ++ do_test $testdir/$script ++ done ++ else ++ for script in $testdir/$prefix $testdir/$prefix*[^~] ++ do ++ do_test $script ++ done ++ fi ++ ++ let loop=$loop-1 ++ if [ "$loop" == "0" ]; then ++ break ++ fi ++ done + exit 0 + } + +-- +2.38.1 + diff --git a/0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch b/0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch new file mode 100644 index 0000000..52fd3e9 --- /dev/null +++ b/0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch @@ -0,0 +1,120 @@ +From 28520bf114b3b0515a48ff44fff4ecbe9ed6dfad Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:18 -0600 +Subject: [PATCH 43/83] mdadm/test: Mark and ignore broken test failures + +Add functionality to continue if a test marked as broken fails. + +To mark a test as broken, a file with the same name but with the suffix +'.broken' should exist. The first line in the file will be printed with +a KNOWN BROKEN message; the rest of the file can describe the how the +test is broken. + +Also adds --skip-broken and --skip-always-broken to skip all the tests +that have a .broken file or to skip all tests whose .broken file's first +line contains the keyword always. + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + test | 37 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 35 insertions(+), 2 deletions(-) + +diff --git a/test b/test +index da6db5e0..61d9ee83 100755 +--- a/test ++++ b/test +@@ -10,6 +10,8 @@ devlist= + + savelogs=0 + exitonerror=1 ++ctrl_c_error=0 ++skipbroken=0 + loop=1 + prefix='[0-9][0-9]' + +@@ -36,6 +38,7 @@ die() { + + ctrl_c() { + exitonerror=1 ++ ctrl_c_error=1 + } + + # mdadm always adds --quiet, and we want to see any unexpected messages +@@ -80,8 +83,21 @@ mdadm() { + do_test() { + _script=$1 + _basename=`basename $_script` ++ _broken=0 ++ + if [ -f "$_script" ] + then ++ if [ -f "${_script}.broken" ]; then ++ _broken=1 ++ _broken_msg=$(head -n1 "${_script}.broken" | tr -d '\n') ++ if [ "$skipbroken" == "all" ]; then ++ return ++ elif [ "$skipbroken" == "always" ] && ++ [[ "$_broken_msg" == *always* ]]; then ++ return ++ fi ++ fi ++ + rm -f $targetdir/stderr + # this might have been reset: restore the default. + echo 2000 > /proc/sys/dev/raid/speed_limit_max +@@ -98,10 +114,15 @@ do_test() { + else + save_log fail + _fail=1 ++ if [ "$_broken" == "1" ]; then ++ echo " (KNOWN BROKEN TEST: $_broken_msg)" ++ fi + fi + [ "$savelogs" == "1" ] && + mv -f $targetdir/log $logdir/$_basename.log +- [ "$_fail" == "1" -a "$exitonerror" == "1" ] && exit 1 ++ [ "$ctrl_c_error" == "1" ] && exit 1 ++ [ "$_fail" == "1" -a "$exitonerror" == "1" \ ++ -a "$_broken" == "0" ] && exit 1 + fi + } + +@@ -119,6 +140,8 @@ do_help() { + --save-logs Usually use with --logdir together + --keep-going | --no-error Don't stop on error, ie. run all tests + --loop=N Run tests N times (0 to run forever) ++ --skip-broken Skip tests that are known to be broken ++ --skip-always-broken Skip tests that are known to always fail + --dev=loop|lvm|ram|disk Use loop devices (default), LVM, RAM or disk + --disks= Provide a bunch of physical devices for test + --volgroup=name LVM volume group for LVM test +@@ -216,6 +239,12 @@ parse_args() { + --loop=* ) + loop="${i##*=}" + ;; ++ --skip-broken ) ++ skipbroken=all ++ ;; ++ --skip-always-broken ) ++ skipbroken=always ++ ;; + --disable-multipath ) + unset MULTIPATH + ;; +@@ -279,7 +308,11 @@ main() { + else + for script in $testdir/$prefix $testdir/$prefix*[^~] + do +- do_test $script ++ case $script in ++ *.broken) ;; ++ *) ++ do_test $script ++ esac + done + fi + +-- +2.38.1 + diff --git a/0044-tests-Add-broken-files-for-all-broken-tests.patch b/0044-tests-Add-broken-files-for-all-broken-tests.patch new file mode 100644 index 0000000..2484e1b --- /dev/null +++ b/0044-tests-Add-broken-files-for-all-broken-tests.patch @@ -0,0 +1,447 @@ +From daa86d6634761796ada1f535c13e47fdd3cc95eb Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 22 Jun 2022 14:25:19 -0600 +Subject: [PATCH 44/83] tests: Add broken files for all broken tests + +Each broken file contains the rough frequency of brokeness as well +as a brief explanation of what happens when it breaks. Estimates +of failure rates are not statistically significant and can vary +run to run. + +This is really just a view from my window. Tests were done on a +small VM with the default loop devices, not real hardware. We've +seen different kernel configurations can cause bugs to appear as well +(ie. different block schedulers). It may also be that different race +conditions will be seen on machines with different performance +characteristics. + +These annotations were done with the kernel currently in md/md-next: + + facef3b96c5b ("md: Notify sysfs sync_completed in md_reap_sync_thread()") + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + tests/01r5integ.broken | 7 ++++ + tests/01raid6integ.broken | 7 ++++ + tests/04r5swap.broken | 7 ++++ + tests/07autoassemble.broken | 8 ++++ + tests/07autodetect.broken | 5 +++ + tests/07changelevelintr.broken | 9 +++++ + tests/07changelevels.broken | 9 +++++ + tests/07reshape5intr.broken | 45 ++++++++++++++++++++++ + tests/07revert-grow.broken | 31 +++++++++++++++ + tests/07revert-shrink.broken | 9 +++++ + tests/07testreshape5.broken | 12 ++++++ + tests/09imsm-assemble.broken | 6 +++ + tests/09imsm-create-fail-rebuild.broken | 5 +++ + tests/09imsm-overlap.broken | 7 ++++ + tests/10ddf-assemble-missing.broken | 6 +++ + tests/10ddf-fail-create-race.broken | 7 ++++ + tests/10ddf-fail-two-spares.broken | 5 +++ + tests/10ddf-incremental-wrong-order.broken | 9 +++++ + tests/14imsm-r1_2d-grow-r1_3d.broken | 5 +++ + tests/14imsm-r1_2d-takeover-r0_2d.broken | 6 +++ + tests/18imsm-r10_4d-takeover-r0_2d.broken | 5 +++ + tests/18imsm-r1_2d-takeover-r0_1d.broken | 6 +++ + tests/19raid6auto-repair.broken | 5 +++ + tests/19raid6repair.broken | 5 +++ + 24 files changed, 226 insertions(+) + create mode 100644 tests/01r5integ.broken + create mode 100644 tests/01raid6integ.broken + create mode 100644 tests/04r5swap.broken + create mode 100644 tests/07autoassemble.broken + create mode 100644 tests/07autodetect.broken + create mode 100644 tests/07changelevelintr.broken + create mode 100644 tests/07changelevels.broken + create mode 100644 tests/07reshape5intr.broken + create mode 100644 tests/07revert-grow.broken + create mode 100644 tests/07revert-shrink.broken + create mode 100644 tests/07testreshape5.broken + create mode 100644 tests/09imsm-assemble.broken + create mode 100644 tests/09imsm-create-fail-rebuild.broken + create mode 100644 tests/09imsm-overlap.broken + create mode 100644 tests/10ddf-assemble-missing.broken + create mode 100644 tests/10ddf-fail-create-race.broken + create mode 100644 tests/10ddf-fail-two-spares.broken + create mode 100644 tests/10ddf-incremental-wrong-order.broken + create mode 100644 tests/14imsm-r1_2d-grow-r1_3d.broken + create mode 100644 tests/14imsm-r1_2d-takeover-r0_2d.broken + create mode 100644 tests/18imsm-r10_4d-takeover-r0_2d.broken + create mode 100644 tests/18imsm-r1_2d-takeover-r0_1d.broken + create mode 100644 tests/19raid6auto-repair.broken + create mode 100644 tests/19raid6repair.broken + +diff --git a/tests/01r5integ.broken b/tests/01r5integ.broken +new file mode 100644 +index 00000000..20737637 +--- /dev/null ++++ b/tests/01r5integ.broken +@@ -0,0 +1,7 @@ ++fails rarely ++ ++Fails about 1 in every 30 runs with a sha mismatch error: ++ ++ c49ab26e1b01def7874af9b8a6d6d0c29fdfafe6 /dev/md0 does not match ++ 15dc2f73262f811ada53c65e505ceec9cf025cb9 /dev/md0 with /dev/loop3 ++ missing +diff --git a/tests/01raid6integ.broken b/tests/01raid6integ.broken +new file mode 100644 +index 00000000..1df735f0 +--- /dev/null ++++ b/tests/01raid6integ.broken +@@ -0,0 +1,7 @@ ++fails infrequently ++ ++Fails about 1 in 5 with a sha mismatch: ++ ++ 8286c2bc045ae2cfe9f8b7ae3a898fa25db6926f /dev/md0 does not match ++ a083a0738b58caab37fd568b91b177035ded37df /dev/md0 with /dev/loop2 and ++ /dev/loop3 missing +diff --git a/tests/04r5swap.broken b/tests/04r5swap.broken +new file mode 100644 +index 00000000..e38987db +--- /dev/null ++++ b/tests/04r5swap.broken +@@ -0,0 +1,7 @@ ++always fails ++ ++Fails with errors: ++ ++ mdadm: /dev/loop0 has no superblock - assembly aborted ++ ++ ERROR: no recovery happening +diff --git a/tests/07autoassemble.broken b/tests/07autoassemble.broken +new file mode 100644 +index 00000000..8be09407 +--- /dev/null ++++ b/tests/07autoassemble.broken +@@ -0,0 +1,8 @@ ++always fails ++ ++Prints lots of messages, but the array doesn't assemble. Error ++possibly related to: ++ ++ mdadm: /dev/md/1 is busy - skipping ++ mdadm: no recogniseable superblock on /dev/md/testing:0 ++ mdadm: /dev/md/2 is busy - skipping +diff --git a/tests/07autodetect.broken b/tests/07autodetect.broken +new file mode 100644 +index 00000000..294954a1 +--- /dev/null ++++ b/tests/07autodetect.broken +@@ -0,0 +1,5 @@ ++always fails ++ ++Fails with error: ++ ++ ERROR: no resync happening +diff --git a/tests/07changelevelintr.broken b/tests/07changelevelintr.broken +new file mode 100644 +index 00000000..284b4906 +--- /dev/null ++++ b/tests/07changelevelintr.broken +@@ -0,0 +1,9 @@ ++always fails ++ ++Fails with errors: ++ ++ mdadm: this change will reduce the size of the array. ++ use --grow --array-size first to truncate array. ++ e.g. mdadm --grow /dev/md0 --array-size 56832 ++ ++ ERROR: no reshape happening +diff --git a/tests/07changelevels.broken b/tests/07changelevels.broken +new file mode 100644 +index 00000000..9b930d93 +--- /dev/null ++++ b/tests/07changelevels.broken +@@ -0,0 +1,9 @@ ++always fails ++ ++Fails with errors: ++ ++ mdadm: /dev/loop0 is smaller than given size. 18976K < 19968K + metadata ++ mdadm: /dev/loop1 is smaller than given size. 18976K < 19968K + metadata ++ mdadm: /dev/loop2 is smaller than given size. 18976K < 19968K + metadata ++ ++ ERROR: /dev/md0 isn't a block device. +diff --git a/tests/07reshape5intr.broken b/tests/07reshape5intr.broken +new file mode 100644 +index 00000000..efe52a66 +--- /dev/null ++++ b/tests/07reshape5intr.broken +@@ -0,0 +1,45 @@ ++always fails ++ ++This patch, recently added to md-next causes the test to always fail: ++ ++7e6ba434cc60 ("md: don't unregister sync_thread with reconfig_mutex ++held") ++ ++The new error is simply: ++ ++ ERROR: no reshape happening ++ ++Before the patch, the error seen is below. ++ ++-- ++ ++fails infrequently ++ ++Fails roughly 1 in 4 runs with errors: ++ ++ mdadm: Merging with already-assembled /dev/md/0 ++ mdadm: cannot re-read metadata from /dev/loop6 - aborting ++ ++ ERROR: no reshape happening ++ ++Also have seen a random deadlock: ++ ++ INFO: task mdadm:109702 blocked for more than 30 seconds. ++ Not tainted 5.18.0-rc3-eid-vmlocalyes-dbg-00095-g3c2b5427979d #2040 ++ "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. ++ task:mdadm state:D stack: 0 pid:109702 ppid: 1 flags:0x00004000 ++ Call Trace: ++ ++ __schedule+0x67e/0x13b0 ++ schedule+0x82/0x110 ++ mddev_suspend+0x2e1/0x330 ++ suspend_lo_store+0xbd/0x140 ++ md_attr_store+0xcb/0x130 ++ sysfs_kf_write+0x89/0xb0 ++ kernfs_fop_write_iter+0x202/0x2c0 ++ new_sync_write+0x222/0x330 ++ vfs_write+0x3bc/0x4d0 ++ ksys_write+0xd9/0x180 ++ __x64_sys_write+0x43/0x50 ++ do_syscall_64+0x3b/0x90 ++ entry_SYSCALL_64_after_hwframe+0x44/0xae +diff --git a/tests/07revert-grow.broken b/tests/07revert-grow.broken +new file mode 100644 +index 00000000..9b6db86f +--- /dev/null ++++ b/tests/07revert-grow.broken +@@ -0,0 +1,31 @@ ++always fails ++ ++This patch, recently added to md-next causes the test to always fail: ++ ++7e6ba434cc60 ("md: don't unregister sync_thread with reconfig_mutex held") ++ ++The errors are: ++ ++ mdadm: No active reshape to revert on /dev/loop0 ++ ERROR: active raid5 not found ++ ++Before the patch, the error seen is below. ++ ++-- ++ ++fails rarely ++ ++Fails about 1 in every 30 runs with errors: ++ ++ mdadm: Merging with already-assembled /dev/md/0 ++ mdadm: backup file /tmp/md-backup inaccessible: No such file or directory ++ mdadm: failed to add /dev/loop1 to /dev/md/0: Invalid argument ++ mdadm: failed to add /dev/loop2 to /dev/md/0: Invalid argument ++ mdadm: failed to add /dev/loop3 to /dev/md/0: Invalid argument ++ mdadm: failed to add /dev/loop0 to /dev/md/0: Invalid argument ++ mdadm: /dev/md/0 assembled from 1 drive - need all 5 to start it ++ (use --run to insist). ++ ++ grep: /sys/block/md*/md/sync_action: No such file or directory ++ ++ ERROR: active raid5 not found +diff --git a/tests/07revert-shrink.broken b/tests/07revert-shrink.broken +new file mode 100644 +index 00000000..c33c39ec +--- /dev/null ++++ b/tests/07revert-shrink.broken +@@ -0,0 +1,9 @@ ++always fails ++ ++Fails with errors: ++ ++ mdadm: this change will reduce the size of the array. ++ use --grow --array-size first to truncate array. ++ e.g. mdadm --grow /dev/md0 --array-size 53760 ++ ++ ERROR: active raid5 not found +diff --git a/tests/07testreshape5.broken b/tests/07testreshape5.broken +new file mode 100644 +index 00000000..a8ce03e4 +--- /dev/null ++++ b/tests/07testreshape5.broken +@@ -0,0 +1,12 @@ ++always fails ++ ++Test seems to run 'test_stripe' at $dir directory, but $dir is never ++set. If $dir is adjusted to $PWD, the test still fails with: ++ ++ mdadm: /dev/loop2 is not suitable for this array. ++ mdadm: create aborted ++ ++ return 1 ++ ++ cmp -s -n 8192 /dev/md0 /tmp/RandFile ++ ++ echo cmp failed ++ cmp failed ++ ++ exit 2 +diff --git a/tests/09imsm-assemble.broken b/tests/09imsm-assemble.broken +new file mode 100644 +index 00000000..a6d4d5cf +--- /dev/null ++++ b/tests/09imsm-assemble.broken +@@ -0,0 +1,6 @@ ++fails infrequently ++ ++Fails roughly 1 in 10 runs with errors: ++ ++ mdadm: /dev/loop2 is still in use, cannot remove. ++ /dev/loop2 removal from /dev/md/container should have succeeded +diff --git a/tests/09imsm-create-fail-rebuild.broken b/tests/09imsm-create-fail-rebuild.broken +new file mode 100644 +index 00000000..40c4b294 +--- /dev/null ++++ b/tests/09imsm-create-fail-rebuild.broken +@@ -0,0 +1,5 @@ ++always fails ++ ++Fails with error: ++ ++ **Error**: Array size mismatch - expected 3072, actual 16384 +diff --git a/tests/09imsm-overlap.broken b/tests/09imsm-overlap.broken +new file mode 100644 +index 00000000..e7ccab76 +--- /dev/null ++++ b/tests/09imsm-overlap.broken +@@ -0,0 +1,7 @@ ++always fails ++ ++Fails with errors: ++ ++ **Error**: Offset mismatch - expected 15360, actual 0 ++ **Error**: Offset mismatch - expected 15360, actual 0 ++ /dev/md/vol3 failed check +diff --git a/tests/10ddf-assemble-missing.broken b/tests/10ddf-assemble-missing.broken +new file mode 100644 +index 00000000..bfd8d103 +--- /dev/null ++++ b/tests/10ddf-assemble-missing.broken +@@ -0,0 +1,6 @@ ++always fails ++ ++Fails with errors: ++ ++ ERROR: /dev/md/vol0 has unexpected state on /dev/loop10 ++ ERROR: unexpected number of online disks on /dev/loop10 +diff --git a/tests/10ddf-fail-create-race.broken b/tests/10ddf-fail-create-race.broken +new file mode 100644 +index 00000000..6c0df023 +--- /dev/null ++++ b/tests/10ddf-fail-create-race.broken +@@ -0,0 +1,7 @@ ++usually fails ++ ++Fails about 9 out of 10 times with many errors: ++ ++ mdadm: cannot open MISSING: No such file or directory ++ ERROR: non-degraded array found ++ ERROR: disk 0 not marked as failed in meta data +diff --git a/tests/10ddf-fail-two-spares.broken b/tests/10ddf-fail-two-spares.broken +new file mode 100644 +index 00000000..eeea56d9 +--- /dev/null ++++ b/tests/10ddf-fail-two-spares.broken +@@ -0,0 +1,5 @@ ++fails infrequently ++ ++Fails roughly 1 in 3 with error: ++ ++ ERROR: /dev/md/vol1 should be optimal in meta data +diff --git a/tests/10ddf-incremental-wrong-order.broken b/tests/10ddf-incremental-wrong-order.broken +new file mode 100644 +index 00000000..a5af3bab +--- /dev/null ++++ b/tests/10ddf-incremental-wrong-order.broken +@@ -0,0 +1,9 @@ ++always fails ++ ++Fails with errors: ++ ERROR: sha1sum of /dev/md/vol0 has changed ++ ERROR: /dev/md/vol0 has unexpected state on /dev/loop10 ++ ERROR: unexpected number of online disks on /dev/loop10 ++ ERROR: /dev/md/vol0 has unexpected state on /dev/loop8 ++ ERROR: unexpected number of online disks on /dev/loop8 ++ ERROR: sha1sum of /dev/md/vol0 has changed +diff --git a/tests/14imsm-r1_2d-grow-r1_3d.broken b/tests/14imsm-r1_2d-grow-r1_3d.broken +new file mode 100644 +index 00000000..4ef1d406 +--- /dev/null ++++ b/tests/14imsm-r1_2d-grow-r1_3d.broken +@@ -0,0 +1,5 @@ ++always fails ++ ++Fails with error: ++ ++ mdadm/tests/func.sh: line 325: dvsize/chunk: division by 0 (error token is "chunk") +diff --git a/tests/14imsm-r1_2d-takeover-r0_2d.broken b/tests/14imsm-r1_2d-takeover-r0_2d.broken +new file mode 100644 +index 00000000..89cd4e57 +--- /dev/null ++++ b/tests/14imsm-r1_2d-takeover-r0_2d.broken +@@ -0,0 +1,6 @@ ++always fails ++ ++Fails with error: ++ ++ tests/func.sh: line 325: dvsize/chunk: division by 0 (error token ++ is "chunk") +diff --git a/tests/18imsm-r10_4d-takeover-r0_2d.broken b/tests/18imsm-r10_4d-takeover-r0_2d.broken +new file mode 100644 +index 00000000..a27399f5 +--- /dev/null ++++ b/tests/18imsm-r10_4d-takeover-r0_2d.broken +@@ -0,0 +1,5 @@ ++fails rarely ++ ++Fails about 1 run in 100 with message: ++ ++ ERROR: size is wrong for /dev/md/vol0: 2 * 5120 (chunk=128) = 20480, not 0 +diff --git a/tests/18imsm-r1_2d-takeover-r0_1d.broken b/tests/18imsm-r1_2d-takeover-r0_1d.broken +new file mode 100644 +index 00000000..aa1982e6 +--- /dev/null ++++ b/tests/18imsm-r1_2d-takeover-r0_1d.broken +@@ -0,0 +1,6 @@ ++always fails ++ ++Fails with error: ++ ++ tests/func.sh: line 325: dvsize/chunk: division by 0 (error token ++ is "chunk") +diff --git a/tests/19raid6auto-repair.broken b/tests/19raid6auto-repair.broken +new file mode 100644 +index 00000000..e91a1425 +--- /dev/null ++++ b/tests/19raid6auto-repair.broken +@@ -0,0 +1,5 @@ ++always fails ++ ++Fails with: ++ ++ "should detect errors" +diff --git a/tests/19raid6repair.broken b/tests/19raid6repair.broken +new file mode 100644 +index 00000000..e91a1425 +--- /dev/null ++++ b/tests/19raid6repair.broken +@@ -0,0 +1,5 @@ ++always fails ++ ++Fails with: ++ ++ "should detect errors" +-- +2.38.1 + diff --git a/0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch b/0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch new file mode 100644 index 0000000..74bf834 --- /dev/null +++ b/0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch @@ -0,0 +1,316 @@ +From 239b3cc0b5da87e966746533b1873c439db54b16 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Fri, 12 Aug 2022 16:36:02 +0200 +Subject: [PATCH 45/83] mdadm: Replace obsolete usleep with nanosleep + +According to POSIX.1-2001, usleep is considered obsolete. +Replace it with a wrapper that uses nanosleep, as recommended in man. +Add handy macros for conversions between msec, usec and nsec. + +Signed-off-by: Mateusz Grzonka +Signed-off-by: Jes Sorensen +--- + Assemble.c | 2 +- + Grow.c | 4 ++-- + Manage.c | 10 +++++----- + managemon.c | 8 ++++---- + mdadm.h | 4 ++++ + mdmon.c | 4 ++-- + super-intel.c | 6 +++--- + util.c | 42 +++++++++++++++++++++++++++++++++--------- + 8 files changed, 54 insertions(+), 26 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 6df6bfbc..be2160b4 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1947,7 +1947,7 @@ out: + break; + close(mdfd); + } +- usleep(usecs); ++ sleep_for(0, USEC_TO_NSEC(usecs), true); + usecs <<= 1; + } + } +diff --git a/Grow.c b/Grow.c +index 97f22c75..5780635a 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -954,7 +954,7 @@ int start_reshape(struct mdinfo *sra, int already_running, + err = sysfs_set_str(sra, NULL, "sync_action", + "reshape"); + if (err) +- sleep(1); ++ sleep_for(1, 0, true); + } while (err && errno == EBUSY && cnt-- > 0); + } + return err; +@@ -5058,7 +5058,7 @@ int Grow_continue_command(char *devname, int fd, + } + st->ss->getinfo_super(st, content, NULL); + if (!content->reshape_active) +- sleep(3); ++ sleep_for(3, 0, true); + else + break; + } while (cnt-- > 0); +diff --git a/Manage.c b/Manage.c +index e5e6abe4..a142f8bd 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -244,7 +244,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + "array_state", + "inactive")) < 0 && + errno == EBUSY) { +- usleep(200000); ++ sleep_for(0, MSEC_TO_NSEC(200), true); + count--; + } + if (err) { +@@ -328,7 +328,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + sysfs_get_ll(mdi, NULL, "sync_max", &old_sync_max) == 0) { + /* must be in the critical section - wait a bit */ + delay -= 1; +- usleep(100000); ++ sleep_for(0, MSEC_TO_NSEC(100), true); + } + + if (sysfs_set_str(mdi, NULL, "sync_action", "frozen") != 0) +@@ -405,7 +405,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + * quite started yet. Wait a bit and + * check 'sync_action' to see. + */ +- usleep(10000); ++ sleep_for(0, MSEC_TO_NSEC(10), true); + sysfs_get_str(mdi, NULL, "sync_action", buf, sizeof(buf)); + if (strncmp(buf, "reshape", 7) != 0) + break; +@@ -447,7 +447,7 @@ done: + count = 25; err = 0; + while (count && fd >= 0 && + (err = ioctl(fd, STOP_ARRAY, NULL)) < 0 && errno == EBUSY) { +- usleep(200000); ++ sleep_for(0, MSEC_TO_NSEC(200), true); + count --; + } + if (fd >= 0 && err) { +@@ -1105,7 +1105,7 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, + ret = sysfs_unique_holder(devnm, rdev); + if (ret < 2) + break; +- usleep(100 * 1000); /* 100ms */ ++ sleep_for(0, MSEC_TO_NSEC(100), true); + } while (--count > 0); + + if (ret == 0) { +diff --git a/managemon.c b/managemon.c +index 0e9bdf00..a7bfa8f6 100644 +--- a/managemon.c ++++ b/managemon.c +@@ -207,7 +207,7 @@ static void replace_array(struct supertype *container, + remove_old(); + while (pending_discard) { + while (discard_this == NULL) +- sleep(1); ++ sleep_for(1, 0, true); + remove_old(); + } + pending_discard = old; +@@ -568,7 +568,7 @@ static void manage_member(struct mdstat_ent *mdstat, + updates = NULL; + while (update_queue_pending || update_queue) { + check_update_queue(container); +- usleep(15*1000); ++ sleep_for(0, MSEC_TO_NSEC(15), true); + } + replace_array(container, a, newa); + if (sysfs_set_str(&a->info, NULL, +@@ -822,7 +822,7 @@ static void handle_message(struct supertype *container, struct metadata_update * + if (msg->len <= 0) + while (update_queue_pending || update_queue) { + check_update_queue(container); +- usleep(15*1000); ++ sleep_for(0, MSEC_TO_NSEC(15), true); + } + + if (msg->len == 0) { /* ping_monitor */ +@@ -836,7 +836,7 @@ static void handle_message(struct supertype *container, struct metadata_update * + wakeup_monitor(); + + while (monitor_loop_cnt - cnt < 0) +- usleep(10 * 1000); ++ sleep_for(0, MSEC_TO_NSEC(10), true); + } else if (msg->len == -1) { /* ping_manager */ + struct mdstat_ent *mdstat = mdstat_read(1, 0); + +diff --git a/mdadm.h b/mdadm.h +index 163f4a49..add9c0b6 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1720,6 +1720,10 @@ extern int cluster_get_dlmlock(void); + extern int cluster_release_dlmlock(void); + 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); ++ + #define _ROUND_UP(val, base) (((val) + (base) - 1) & ~(base - 1)) + #define ROUND_UP(val, base) _ROUND_UP(val, (typeof(val))(base)) + #define ROUND_UP_PTR(ptr, base) ((typeof(ptr)) \ +diff --git a/mdmon.c b/mdmon.c +index c057da63..e9d035eb 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -99,7 +99,7 @@ static int clone_monitor(struct supertype *container) + if (rc) + return rc; + while (mon_tid == -1) +- usleep(10); ++ sleep_for(0, USEC_TO_NSEC(10), true); + pthread_attr_destroy(&attr); + + mgr_tid = syscall(SYS_gettid); +@@ -209,7 +209,7 @@ static void try_kill_monitor(pid_t pid, char *devname, int sock) + rv = kill(pid, SIGUSR1); + if (rv < 0) + break; +- usleep(200000); ++ sleep_for(0, MSEC_TO_NSEC(200), true); + } + } + +diff --git a/super-intel.c b/super-intel.c +index 4ddfcf94..4d82af3d 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5275,7 +5275,7 @@ static int get_super_block(struct intel_super **super_list, char *devnm, char *d + /* retry the load if we might have raced against mdmon */ + if (err == 3 && devnm && mdmon_running(devnm)) + for (retry = 0; retry < 3; retry++) { +- usleep(3000); ++ sleep_for(0, MSEC_TO_NSEC(3), true); + err = load_and_parse_mpb(dfd, s, NULL, keep_fd); + if (err != 3) + break; +@@ -5377,7 +5377,7 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname) + + if (mdstat && mdmon_running(mdstat->devnm) && getpid() != mdmon_pid(mdstat->devnm)) { + for (retry = 0; retry < 3; retry++) { +- usleep(3000); ++ sleep_for(0, MSEC_TO_NSEC(3), true); + rv = load_and_parse_mpb(fd, super, devname, 0); + if (rv != 3) + break; +@@ -12084,7 +12084,7 @@ int wait_for_reshape_imsm(struct mdinfo *sra, int ndata) + close(fd); + return 1; + } +- usleep(30000); ++ sleep_for(0, MSEC_TO_NSEC(30), true); + } else + break; + } while (retry--); +diff --git a/util.c b/util.c +index 38f0420e..ca48d976 100644 +--- a/util.c ++++ b/util.c +@@ -166,7 +166,7 @@ retry: + pr_err("error %d when get PW mode on lock %s\n", errno, str); + /* let's try several times if EAGAIN happened */ + if (dlm_lock_res->lksb.sb_status == EAGAIN && retry_count < 10) { +- sleep(10); ++ sleep_for(10, 0, true); + retry_count++; + goto retry; + } +@@ -1085,7 +1085,7 @@ int open_dev_excl(char *devnm) + int i; + int flags = O_RDWR; + dev_t devid = devnm2devid(devnm); +- long delay = 1000; ++ unsigned int delay = 1; // miliseconds + + sprintf(buf, "%d:%d", major(devid), minor(devid)); + for (i = 0; i < 25; i++) { +@@ -1098,8 +1098,8 @@ int open_dev_excl(char *devnm) + } + if (errno != EBUSY) + return fd; +- usleep(delay); +- if (delay < 200000) ++ sleep_for(0, MSEC_TO_NSEC(delay), true); ++ if (delay < 200) + delay *= 2; + } + return -1; +@@ -1123,7 +1123,7 @@ void wait_for(char *dev, int fd) + { + int i; + struct stat stb_want; +- long delay = 1000; ++ unsigned int delay = 1; // miliseconds + + if (fstat(fd, &stb_want) != 0 || + (stb_want.st_mode & S_IFMT) != S_IFBLK) +@@ -1135,8 +1135,8 @@ void wait_for(char *dev, int fd) + (stb.st_mode & S_IFMT) == S_IFBLK && + (stb.st_rdev == stb_want.st_rdev)) + return; +- usleep(delay); +- if (delay < 200000) ++ sleep_for(0, MSEC_TO_NSEC(delay), true); ++ if (delay < 200) + delay *= 2; + } + if (i == 25) +@@ -1821,7 +1821,7 @@ int hot_remove_disk(int mdfd, unsigned long dev, int force) + while ((ret = ioctl(mdfd, HOT_REMOVE_DISK, dev)) == -1 && + errno == EBUSY && + cnt-- > 0) +- usleep(10000); ++ sleep_for(0, MSEC_TO_NSEC(10), true); + + return ret; + } +@@ -1834,7 +1834,7 @@ int sys_hot_remove_disk(int statefd, int force) + while ((ret = write(statefd, "remove", 6)) == -1 && + errno == EBUSY && + cnt-- > 0) +- usleep(10000); ++ sleep_for(0, MSEC_TO_NSEC(10), true); + return ret == 6 ? 0 : -1; + } + +@@ -2375,3 +2375,27 @@ out: + close(fd_zero); + return ret; + } ++ ++/** ++ * sleep_for() - Sleeps for specified time. ++ * @sec: Seconds to sleep for. ++ * @nsec: Nanoseconds to sleep for, has to be less than one second. ++ * @wake_after_interrupt: If set, wake up if interrupted. ++ * ++ * Function immediately returns if error different than EINTR occurs. ++ */ ++void sleep_for(unsigned int sec, long nsec, bool wake_after_interrupt) ++{ ++ struct timespec delay = {.tv_sec = sec, .tv_nsec = nsec}; ++ ++ assert(nsec < MSEC_TO_NSEC(1000)); ++ ++ do { ++ errno = 0; ++ nanosleep(&delay, &delay); ++ if (errno != 0 && errno != EINTR) { ++ pr_err("Error sleeping for %us %ldns: %s\n", sec, nsec, strerror(errno)); ++ return; ++ } ++ } while (!wake_after_interrupt && errno == EINTR); ++} +-- +2.38.1 + diff --git a/0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch b/0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch new file mode 100644 index 0000000..5872416 --- /dev/null +++ b/0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch @@ -0,0 +1,36 @@ +From 39b381252c32275079344d30de18b76fda4bba26 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 27 Jul 2022 15:52:45 -0600 +Subject: [PATCH 46/83] tests/00readonly: Run udevadm settle before setting ro + +In some recent kernel versions, 00readonly fails with: + + mdadm: failed to set readonly for /dev/md0: Device or resource busy + ERROR: array is not read-only! + +This was traced down to a race condition with udev holding a reference +to the block device at the same time as trying to set it read only. + +To fix this, call udevadm settle before setting the array read only. + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + tests/00readonly | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/00readonly b/tests/00readonly +index 39202487..afe243b3 100644 +--- a/tests/00readonly ++++ b/tests/00readonly +@@ -12,6 +12,7 @@ do + $dev1 $dev2 $dev3 $dev4 --assume-clean + check nosync + check $level ++ udevadm settle + mdadm -ro $md0 + check readonly + state=$(cat /sys/block/md0/md/array_state) +-- +2.38.1 + diff --git a/0047-tests-add-test-for-names.patch b/0047-tests-add-test-for-names.patch new file mode 100644 index 0000000..03aee00 --- /dev/null +++ b/0047-tests-add-test-for-names.patch @@ -0,0 +1,119 @@ +From b7671c82010ffc04dfaecff2dd19ef8b2283e2b6 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 19 Jul 2022 14:48:21 +0200 +Subject: [PATCH 47/83] tests: add test for names + +Current behavior is not documented and tested. This test is a base for +future improvements. It is enough to test it only with native metadata, +because it is generic code. Generated properties are passed to metadata +handler. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + tests/00createnames | 93 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 93 insertions(+) + create mode 100644 tests/00createnames + +diff --git a/tests/00createnames b/tests/00createnames +new file mode 100644 +index 00000000..64b81b92 +--- /dev/null ++++ b/tests/00createnames +@@ -0,0 +1,93 @@ ++set -x -e ++ ++# Test how and --name= are handled for create mode. ++# We need to check three properties, generated from those parameters: ++# - devnode name ++# - link in /dev/md/ (MD_DEVNAME property from --detail --export) ++# - name in metadata (MD_NAME property from --examine --export) ++ ++function _verify() { ++ local DEVNODE_NAME="$1" ++ local WANTED_LINK="$2" ++ local WANTED_NAME="$3" ++ ++ local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" ++ if [[ "$?" != "0" ]]; then ++ echo "Cannot get details for $DEVNODE_NAME - unexpected devnode." ++ exit 1 ++ fi ++ ++ if [[ "$WANTED_LINK" != "empty" ]]; then ++ local EXPECTED="MD_DEVNAME=$WANTED_LINK" ++ if [[ "$RES" != "$EXPECTED" ]]; then ++ echo "$RES doesn't match $EXPECTED." ++ exit 1 ++ fi ++ fi ++ ++ ++ local RES="$(mdadm -E --export $dev0 | grep MD_NAME)" ++ if [[ "$?" != "0" ]]; then ++ echo "Cannot get metadata from $dev0." ++ exit 1 ++ fi ++ ++ local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" ++ if [[ "$RES" != "$EXPECTED" ]]; then ++ echo "$RES doesn't match $EXPECTED." ++ exit 1 ++ fi ++} ++ ++function _create() { ++ local DEVNAME=$1 ++ local NAME=$2 ++ ++ if [[ -z "$NAME" ]]; then ++ mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force ++ else ++ mdadm -CR "$DEVNAME" --name="$NAME" -l0 -n 1 $dev0 --force ++ fi ++ ++ if [[ "$?" != "0" ]]; then ++ echo "Cannot create device." ++ exit 1 ++ fi ++} ++ ++# The most trivial case. ++_create "/dev/md/name" ++_verify "/dev/md127" "name" "name" ++mdadm -S "/dev/md127" ++ ++_create "name" ++_verify "/dev/md127" "name" "name" ++mdadm -S "/dev/md127" ++ ++# Use 'mdX' as name. ++_create "/dev/md/md0" ++_verify "/dev/md127" "md0" "md0" ++mdadm -S "/dev/md127" ++ ++_create "md0" ++_verify "/dev/md127" "md0" "md0" ++mdadm -S "/dev/md127" ++ ++# is used to create MD_DEVNAME but, name is used to create MD_NAME. ++_create "/dev/md/devnode" "name" ++_verify "/dev/md127" "devnode" "name" ++mdadm -S "/dev/md127" ++ ++_create "devnode" "name" ++_verify "/dev/md127" "devnode" "name" ++mdadm -S "/dev/md127" ++ ++# Devnode points to /dev/ directory. MD_DEVNAME doesn't exist. ++_create "/dev/md0" ++_verify "/dev/md0" "empty" "0" ++mdadm -S "/dev/md0" ++ ++# Devnode points to /dev/ directory and name is set. ++_create "/dev/md0" "name" ++_verify "/dev/md0" "empty" "name" ++mdadm -S "/dev/md0" +-- +2.38.1 + diff --git a/0048-mdadm-remove-symlink-option.patch b/0048-mdadm-remove-symlink-option.patch new file mode 100644 index 0000000..1956e2b --- /dev/null +++ b/0048-mdadm-remove-symlink-option.patch @@ -0,0 +1,176 @@ +From e4a030a0d3a953b8e74c118200e58dc83c2fc608 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 19 Jul 2022 14:48:22 +0200 +Subject: [PATCH 48/83] mdadm: remove symlink option + +The option is not used. Remove it from code. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + ReadMe.c | 1 - + config.c | 7 +------ + mdadm.8.in | 9 --------- + mdadm.c | 20 -------------------- + mdadm.conf.5.in | 15 --------------- + mdadm.h | 2 -- + 6 files changed, 1 insertion(+), 53 deletions(-) + +diff --git a/ReadMe.c b/ReadMe.c +index 7518a32a..7f94847e 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -147,7 +147,6 @@ struct option long_options[] = { + {"nofailfast",0, 0, NoFailFast}, + {"re-add", 0, 0, ReAdd}, + {"homehost", 1, 0, HomeHost}, +- {"symlinks", 1, 0, Symlinks}, + {"data-offset",1, 0, DataOffset}, + {"nodes",1, 0, Nodes}, /* also for --assemble */ + {"home-cluster",1, 0, ClusterName}, +diff --git a/config.c b/config.c +index 9c725457..dc1620c1 100644 +--- a/config.c ++++ b/config.c +@@ -194,7 +194,6 @@ struct mddev_dev *load_containers(void) + + struct createinfo createinfo = { + .autof = 2, /* by default, create devices with standard names */ +- .symlinks = 1, + .names = 0, /* By default, stick with numbered md devices. */ + .bblist = 1, /* Use a bad block list by default */ + #ifdef DEBIAN +@@ -310,11 +309,7 @@ static void createline(char *line) + if (!createinfo.supertype) + pr_err("metadata format %s unknown, ignoring\n", + w+9); +- } else if (strncasecmp(w, "symlinks=yes", 12) == 0) +- createinfo.symlinks = 1; +- else if (strncasecmp(w, "symlinks=no", 11) == 0) +- createinfo.symlinks = 0; +- else if (strncasecmp(w, "names=yes", 12) == 0) ++ } else if (strncasecmp(w, "names=yes", 12) == 0) + createinfo.names = 1; + else if (strncasecmp(w, "names=no", 11) == 0) + createinfo.names = 0; +diff --git a/mdadm.8.in b/mdadm.8.in +index 0be02e4a..f2736226 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -1048,11 +1048,6 @@ simultaneously. If not specified, this defaults to 4. + Specify journal device for the RAID-4/5/6 array. The journal device + should be a SSD with reasonable lifetime. + +-.TP +-.BR \-\-symlinks +-Auto creation of symlinks in /dev to /dev/md, option --symlinks must +-be 'no' or 'yes' and work with --create and --build. +- + .TP + .BR \-k ", " \-\-consistency\-policy= + Specify how the array maintains consistency in case of unexpected shutdown. +@@ -1405,10 +1400,6 @@ Reshape can be continued later using the + .B \-\-continue + option for the grow command. + +-.TP +-.BR \-\-symlinks +-See this option under Create and Build options. +- + .SH For Manage mode: + + .TP +diff --git a/mdadm.c b/mdadm.c +index 56722ed9..180f7a9c 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -59,7 +59,6 @@ int main(int argc, char *argv[]) + struct mddev_dev *dv; + mdu_array_info_t array; + int devs_found = 0; +- char *symlinks = NULL; + int grow_continue = 0; + /* autof indicates whether and how to create device node. + * bottom 3 bits are style. Rest (when shifted) are number of parts +@@ -663,13 +662,6 @@ int main(int argc, char *argv[]) + case O(ASSEMBLE,Auto): /* auto-creation of device node */ + c.autof = parse_auto(optarg, "--auto flag", 0); + continue; +- +- case O(CREATE,Symlinks): +- case O(BUILD,Symlinks): +- case O(ASSEMBLE,Symlinks): /* auto creation of symlinks in /dev to /dev/md */ +- symlinks = optarg; +- continue; +- + case O(BUILD,'f'): /* force honouring '-n 1' */ + case O(BUILD,Force): /* force honouring '-n 1' */ + case O(GROW,'f'): /* ditto */ +@@ -1325,18 +1317,6 @@ int main(int argc, char *argv[]) + exit(2); + } + +- if (symlinks) { +- struct createinfo *ci = conf_get_create_info(); +- +- if (strcasecmp(symlinks, "yes") == 0) +- ci->symlinks = 1; +- else if (strcasecmp(symlinks, "no") == 0) +- ci->symlinks = 0; +- else { +- pr_err("option --symlinks must be 'no' or 'yes'\n"); +- exit(2); +- } +- } + /* Ok, got the option parsing out of the way + * hopefully it's mostly right but there might be some stuff + * missing +diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in +index cd4e6a9d..bc2295c2 100644 +--- a/mdadm.conf.5.in ++++ b/mdadm.conf.5.in +@@ -338,21 +338,6 @@ missing device entries should be created. + The name of the metadata format to use if none is explicitly given. + This can be useful to impose a system-wide default of version-1 superblocks. + +-.TP +-.B symlinks=no +-Normally when creating devices in +-.B /dev/md/ +-.I mdadm +-will create a matching symlink from +-.B /dev/ +-with a name starting +-.B md +-or +-.BR md_ . +-Give +-.B symlinks=no +-to suppress this symlink creation. +- + .TP + .B names=yes + Since Linux 2.6.29 it has been possible to create +diff --git a/mdadm.h b/mdadm.h +index add9c0b6..93e72786 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -394,7 +394,6 @@ struct createinfo { + int gid; + int autof; + int mode; +- int symlinks; + int names; + int bblist; + struct supertype *supertype; +@@ -442,7 +441,6 @@ enum special_options { + BackupFile, + HomeHost, + AutoHomeHost, +- Symlinks, + AutoDetect, + Waitclean, + DetailPlatform, +-- +2.38.1 + diff --git a/0049-mdadm-move-data_offset-to-struct-shape.patch b/0049-mdadm-move-data_offset-to-struct-shape.patch new file mode 100644 index 0000000..5dca508 --- /dev/null +++ b/0049-mdadm-move-data_offset-to-struct-shape.patch @@ -0,0 +1,232 @@ +From ae5dfc56b7a96805d5a0b50eaf93b9fec8604298 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 19 Jul 2022 14:48:23 +0200 +Subject: [PATCH 49/83] mdadm: move data_offset to struct shape + +Data offset is a shape property so move it there to remove additional +parameter from some functions. + +Signed-off-by: Mariusz Tkaczyk +Signed-off-by: Jes Sorensen +--- + Create.c | 16 ++++++++-------- + Grow.c | 7 +++---- + mdadm.c | 20 +++++++++----------- + mdadm.h | 5 ++--- + 4 files changed, 22 insertions(+), 26 deletions(-) + +diff --git a/Create.c b/Create.c +index c84c1ac8..e06ec2ae 100644 +--- a/Create.c ++++ b/Create.c +@@ -95,7 +95,7 @@ int Create(struct supertype *st, char *mddev, + char *name, int *uuid, + int subdevs, struct mddev_dev *devlist, + struct shape *s, +- struct context *c, unsigned long long data_offset) ++ struct context *c) + { + /* + * Create a new raid array. +@@ -288,7 +288,7 @@ int Create(struct supertype *st, char *mddev, + newsize = s->size * 2; + if (st && ! st->ss->validate_geometry(st, s->level, s->layout, s->raiddisks, + &s->chunk, s->size*2, +- data_offset, NULL, ++ s->data_offset, NULL, + &newsize, s->consistency_policy, + c->verbose >= 0)) + return 1; +@@ -323,10 +323,10 @@ int Create(struct supertype *st, char *mddev, + info.array.working_disks = 0; + dnum = 0; + for (dv = devlist; dv; dv = dv->next) +- if (data_offset == VARIABLE_OFFSET) ++ if (s->data_offset == VARIABLE_OFFSET) + dv->data_offset = INVALID_SECTORS; + else +- dv->data_offset = data_offset; ++ dv->data_offset = s->data_offset; + + for (dv=devlist; dv && !have_container; dv=dv->next, dnum++) { + char *dname = dv->devname; +@@ -342,7 +342,7 @@ int Create(struct supertype *st, char *mddev, + missing_disks ++; + continue; + } +- if (data_offset == VARIABLE_OFFSET) { ++ if (s->data_offset == VARIABLE_OFFSET) { + doff = strchr(dname, ':'); + if (doff) { + *doff++ = 0; +@@ -350,7 +350,7 @@ int Create(struct supertype *st, char *mddev, + } else + dv->data_offset = INVALID_SECTORS; + } else +- dv->data_offset = data_offset; ++ dv->data_offset = s->data_offset; + + dfd = open(dname, O_RDONLY); + if (dfd < 0) { +@@ -535,7 +535,7 @@ int Create(struct supertype *st, char *mddev, + if (!st->ss->validate_geometry(st, s->level, s->layout, + s->raiddisks, + &s->chunk, minsize*2, +- data_offset, ++ s->data_offset, + NULL, NULL, + s->consistency_policy, 0)) { + pr_err("devices too large for RAID level %d\n", s->level); +@@ -754,7 +754,7 @@ int Create(struct supertype *st, char *mddev, + } + } + if (!st->ss->init_super(st, &info.array, s, name, c->homehost, uuid, +- data_offset)) ++ s->data_offset)) + goto abort_locked; + + total_slots = info.array.nr_disks; +diff --git a/Grow.c b/Grow.c +index 5780635a..868bdc3a 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1775,7 +1775,6 @@ static int reshape_container(char *container, char *devname, + + int Grow_reshape(char *devname, int fd, + struct mddev_dev *devlist, +- unsigned long long data_offset, + struct context *c, struct shape *s) + { + /* Make some changes in the shape of an array. +@@ -1821,7 +1820,7 @@ int Grow_reshape(char *devname, int fd, + return 1; + } + +- if (data_offset != INVALID_SECTORS && array.level != 10 && ++ if (s->data_offset != INVALID_SECTORS && array.level != 10 && + (array.level < 4 || array.level > 6)) { + pr_err("--grow --data-offset not yet supported\n"); + return 1; +@@ -2179,7 +2178,7 @@ size_change_error: + if ((s->level == UnSet || s->level == array.level) && + (s->layout_str == NULL) && + (s->chunk == 0 || s->chunk == array.chunk_size) && +- data_offset == INVALID_SECTORS && ++ s->data_offset == INVALID_SECTORS && + (s->raiddisks == 0 || s->raiddisks == array.raid_disks)) { + /* Nothing more to do */ + if (!changed && c->verbose >= 0) +@@ -2379,7 +2378,7 @@ size_change_error: + } + sync_metadata(st); + rv = reshape_array(container, fd, devname, st, &info, c->force, +- devlist, data_offset, c->backup_file, ++ devlist, s->data_offset, c->backup_file, + c->verbose, 0, 0, 0); + frozen = 0; + } +diff --git a/mdadm.c b/mdadm.c +index 180f7a9c..845e4466 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -49,7 +49,6 @@ int main(int argc, char *argv[]) + int i; + + unsigned long long array_size = 0; +- unsigned long long data_offset = INVALID_SECTORS; + struct mddev_ident ident; + char *configfile = NULL; + int devmode = 0; +@@ -79,6 +78,7 @@ int main(int argc, char *argv[]) + .layout = UnSet, + .bitmap_chunk = UnSet, + .consistency_policy = CONSISTENCY_POLICY_UNKNOWN, ++ .data_offset = INVALID_SECTORS, + }; + + char sys_hostname[256]; +@@ -479,15 +479,15 @@ int main(int argc, char *argv[]) + + case O(CREATE,DataOffset): + case O(GROW,DataOffset): +- if (data_offset != INVALID_SECTORS) { ++ if (s.data_offset != INVALID_SECTORS) { + pr_err("data-offset may only be specified one. Second value is %s.\n", optarg); + exit(2); + } + if (mode == CREATE && strcmp(optarg, "variable") == 0) +- data_offset = VARIABLE_OFFSET; ++ s.data_offset = VARIABLE_OFFSET; + else +- data_offset = parse_size(optarg); +- if (data_offset == INVALID_SECTORS) { ++ s.data_offset = parse_size(optarg); ++ if (s.data_offset == INVALID_SECTORS) { + pr_err("invalid data-offset: %s\n", + optarg); + exit(2); +@@ -1416,7 +1416,7 @@ int main(int argc, char *argv[]) + exit(1); + } + +- if (c.backup_file && data_offset != INVALID_SECTORS) { ++ if (c.backup_file && s.data_offset != INVALID_SECTORS) { + pr_err("--backup-file and --data-offset are incompatible\n"); + exit(2); + } +@@ -1587,8 +1587,7 @@ int main(int argc, char *argv[]) + + rv = Create(ss, devlist->devname, + ident.name, ident.uuid_set ? ident.uuid : NULL, +- devs_found-1, devlist->next, +- &s, &c, data_offset); ++ devs_found - 1, devlist->next, &s, &c); + break; + case MISC: + if (devmode == 'E') { +@@ -1706,10 +1705,9 @@ int main(int argc, char *argv[]) + c.verbose); + else if (s.size > 0 || s.raiddisks || s.layout_str || + s.chunk != 0 || s.level != UnSet || +- data_offset != INVALID_SECTORS) { ++ s.data_offset != INVALID_SECTORS) { + rv = Grow_reshape(devlist->devname, mdfd, +- devlist->next, +- data_offset, &c, &s); ++ devlist->next, &c, &s); + } else if (s.consistency_policy != CONSISTENCY_POLICY_UNKNOWN) { + rv = Grow_consistency_policy(devlist->devname, mdfd, &c, &s); + } else if (array_size == 0) +diff --git a/mdadm.h b/mdadm.h +index 93e72786..adb7cdaa 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -595,6 +595,7 @@ struct shape { + int assume_clean; + int write_behind; + unsigned long long size; ++ unsigned long long data_offset; + int consistency_policy; + }; + +@@ -1431,7 +1432,6 @@ extern int Grow_addbitmap(char *devname, int fd, + struct context *c, struct shape *s); + extern int Grow_reshape(char *devname, int fd, + struct mddev_dev *devlist, +- unsigned long long data_offset, + struct context *c, struct shape *s); + extern int Grow_restart(struct supertype *st, struct mdinfo *info, + int *fdlist, int cnt, char *backup_file, int verbose); +@@ -1462,8 +1462,7 @@ extern int Create(struct supertype *st, char *mddev, + char *name, int *uuid, + int subdevs, struct mddev_dev *devlist, + struct shape *s, +- struct context *c, +- unsigned long long data_offset); ++ struct context *c); + + extern int Detail(char *dev, struct context *c); + extern int Detail_Platform(struct superswitch *ss, int scan, int verbose, int export, char *controller_path); +-- +2.38.1 + diff --git a/0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch b/0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch new file mode 100644 index 0000000..c319da2 --- /dev/null +++ b/0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch @@ -0,0 +1,162 @@ +From 27ad4900501c615b7c6b266bf23948e5606dba53 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Wed, 27 Jul 2022 15:52:46 -0600 +Subject: [PATCH 50/83] mdadm: Don't open md device for CREATE and ASSEMBLE + +The mdadm command tries to open the md device for most modes, first +thing, no matter what. When running to create or assemble an array, +in most cases, the md device will not exist, the open call will fail +and everything will proceed correctly. + +However, when running tests, a create or assembly command may be run +shortly after stopping an array and the old md device file may still +be around. Then, if create_on_open is set in the kernel, a new md +device will be created when mdadm does its initial open. + +When mdadm gets around to creating the new device with the new_array +parameter it issues this error: + + mdadm: Fail to create md0 when using + /sys/module/md_mod/parameters/new_array, fallback to creation via node + +This is because an mddev was already created by the kernel with the +earlier open() call and thus the new one being created will fail with +EEXIST. The mdadm command will still successfully be created due to +falling back to the node creation method. However, the error message +itself will fail any test that's running it. + +This issue is a race condition that is very rare, but a recent change +in the kernel caused this to happen more frequently: about 1 in 50 +times. + +To fix this, don't bother trying to open the md device for CREATE, +ASSEMBLE and BUILD commands, as the file descriptor will never be used +anyway even if it is successfully openned. The mdfd has not been used +for these commands since: + + 7f91af49ad09 ("Delay creation of array devices for assemble/build/create") + +The checks that were done on the open device can be changed to being +done with stat. + +Side note: it would be nice to disable create_on_open as well to help +solve this, but it seems the work for this was never finished. By default, +mdadm will create using the old node interface when a name is specified +unless the user specifically puts names=yes in a config file, which +doesn't seem to be common or desirable to require this.. + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Jes Sorensen +--- + lib.c | 12 ++++++++++++ + mdadm.c | 40 ++++++++++++++++++++-------------------- + mdadm.h | 1 + + 3 files changed, 33 insertions(+), 20 deletions(-) + +diff --git a/lib.c b/lib.c +index 7e3e3d47..e395b28d 100644 +--- a/lib.c ++++ b/lib.c +@@ -164,6 +164,18 @@ char *stat2devnm(struct stat *st) + return devid2devnm(st->st_rdev); + } + ++bool stat_is_md_dev(struct stat *st) ++{ ++ if ((S_IFMT & st->st_mode) != S_IFBLK) ++ return false; ++ if (major(st->st_rdev) == MD_MAJOR) ++ return true; ++ if (major(st->st_rdev) == (unsigned)get_mdp_major()) ++ return true; ++ ++ return false; ++} ++ + char *fd2devnm(int fd) + { + struct stat stb; +diff --git a/mdadm.c b/mdadm.c +index 845e4466..972adb52 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1329,6 +1329,9 @@ int main(int argc, char *argv[]) + + if (mode == MANAGE || mode == BUILD || mode == CREATE || + mode == GROW || (mode == ASSEMBLE && ! c.scan)) { ++ struct stat stb; ++ int ret; ++ + if (devs_found < 1) { + pr_err("an md device must be given in this mode\n"); + exit(2); +@@ -1341,6 +1344,12 @@ int main(int argc, char *argv[]) + mdfd = open_mddev(devlist->devname, 1); + if (mdfd < 0) + exit(1); ++ ++ ret = fstat(mdfd, &stb); ++ if (ret) { ++ pr_err("fstat failed on %s.\n", devlist->devname); ++ exit(1); ++ } + } else { + char *bname = basename(devlist->devname); + +@@ -1348,30 +1357,21 @@ int main(int argc, char *argv[]) + pr_err("Name %s is too long.\n", devlist->devname); + exit(1); + } +- /* non-existent device is OK */ +- mdfd = open_mddev(devlist->devname, 0); +- } +- if (mdfd == -2) { +- pr_err("device %s exists but is not an md array.\n", devlist->devname); +- exit(1); +- } +- if ((int)ident.super_minor == -2) { +- struct stat stb; +- if (mdfd < 0) { ++ ++ ret = stat(devlist->devname, &stb); ++ if (ident.super_minor == -2 && ret != 0) { + pr_err("--super-minor=dev given, and listed device %s doesn't exist.\n", +- devlist->devname); ++ devlist->devname); ++ exit(1); ++ } ++ ++ if (!ret && !stat_is_md_dev(&stb)) { ++ pr_err("device %s exists but is not an md array.\n", devlist->devname); + exit(1); + } +- fstat(mdfd, &stb); +- ident.super_minor = minor(stb.st_rdev); +- } +- if (mdfd >= 0 && mode != MANAGE && mode != GROW) { +- /* We don't really want this open yet, we just might +- * have wanted to check some things +- */ +- close(mdfd); +- mdfd = -1; + } ++ if (ident.super_minor == -2) ++ ident.super_minor = minor(stb.st_rdev); + } + + if (s.raiddisks) { +diff --git a/mdadm.h b/mdadm.h +index adb7cdaa..8208b81e 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1672,6 +1672,7 @@ void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0 + extern char *stat2kname(struct stat *st); + extern char *fd2kname(int fd); + extern char *stat2devnm(struct stat *st); ++bool stat_is_md_dev(struct stat *st); + extern char *fd2devnm(int fd); + extern void udev_block(char *devnm); + extern void udev_unblock(void); +-- +2.38.1 + diff --git a/0051-Grow-Split-Grow_reshape-into-helper-function.patch b/0051-Grow-Split-Grow_reshape-into-helper-function.patch new file mode 100644 index 0000000..8fe5894 --- /dev/null +++ b/0051-Grow-Split-Grow_reshape-into-helper-function.patch @@ -0,0 +1,231 @@ +From 7211116c295ba1f9e1fcbdc2dd2d3762855062e1 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Thu, 28 Jul 2022 20:20:53 +0800 +Subject: [PATCH 51/83] Grow: Split Grow_reshape into helper function + +Grow_reshape should be split into helper functions given its size. +- Add helper function for preparing reshape on external metadata. +- Close cfd file descriptor. + +Signed-off-by: Mateusz Kusiak +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Grow.c | 125 ++++++++++++++++++++++++++++++-------------------------- + mdadm.h | 1 + + util.c | 14 +++++++ + 3 files changed, 81 insertions(+), 59 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 868bdc3a..0f07a894 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1773,6 +1773,65 @@ static int reshape_container(char *container, char *devname, + char *backup_file, int verbose, + int forked, int restart, int freeze_reshape); + ++/** ++ * prepare_external_reshape() - prepares update on external metadata if supported. ++ * @devname: Device name. ++ * @subarray: Subarray. ++ * @st: Supertype. ++ * @container: Container. ++ * @cfd: Container file descriptor. ++ * ++ * Function checks that the requested reshape is supported on external metadata, ++ * and performs an initial check that the container holds the pre-requisite ++ * spare devices (mdmon owns final validation). ++ * ++ * Return: 0 on success, else 1 ++ */ ++static int prepare_external_reshape(char *devname, char *subarray, ++ struct supertype *st, char *container, ++ const int cfd) ++{ ++ struct mdinfo *cc = NULL; ++ struct mdinfo *content = NULL; ++ ++ if (st->ss->load_container(st, cfd, NULL)) { ++ pr_err("Cannot read superblock for %s\n", devname); ++ return 1; ++ } ++ ++ if (!st->ss->container_content) ++ return 1; ++ ++ cc = st->ss->container_content(st, subarray); ++ for (content = cc; content ; content = content->next) { ++ /* ++ * check if reshape is allowed based on metadata ++ * indications stored in content.array.status ++ */ ++ if (is_bit_set(&content->array.state, MD_SB_BLOCK_VOLUME) || ++ is_bit_set(&content->array.state, MD_SB_BLOCK_CONTAINER_RESHAPE)) { ++ pr_err("Cannot reshape arrays in container with unsupported metadata: %s(%s)\n", ++ devname, container); ++ goto error; ++ } ++ if (content->consistency_policy == CONSISTENCY_POLICY_PPL) { ++ pr_err("Operation not supported when ppl consistency policy is enabled\n"); ++ goto error; ++ } ++ if (content->consistency_policy == CONSISTENCY_POLICY_BITMAP) { ++ pr_err("Operation not supported when write-intent bitmap consistency policy is enabled\n"); ++ goto error; ++ } ++ } ++ sysfs_free(cc); ++ if (mdmon_running(container)) ++ st->update_tail = &st->updates; ++ return 0; ++error: ++ sysfs_free(cc); ++ return 1; ++} ++ + int Grow_reshape(char *devname, int fd, + struct mddev_dev *devlist, + struct context *c, struct shape *s) +@@ -1799,7 +1858,7 @@ int Grow_reshape(char *devname, int fd, + struct supertype *st; + char *subarray = NULL; + +- int frozen; ++ int frozen = 0; + int changed = 0; + char *container = NULL; + int cfd = -1; +@@ -1808,7 +1867,7 @@ int Grow_reshape(char *devname, int fd, + int added_disks; + + struct mdinfo info; +- struct mdinfo *sra; ++ struct mdinfo *sra = NULL; + + if (md_get_array_info(fd, &array) < 0) { + pr_err("%s is not an active md array - aborting\n", +@@ -1865,13 +1924,7 @@ int Grow_reshape(char *devname, int fd, + } + } + +- /* in the external case we need to check that the requested reshape is +- * supported, and perform an initial check that the container holds the +- * pre-requisite spare devices (mdmon owns final validation) +- */ + if (st->ss->external) { +- int retval; +- + if (subarray) { + container = st->container_devnm; + cfd = open_dev_excl(st->container_devnm); +@@ -1887,13 +1940,12 @@ int Grow_reshape(char *devname, int fd, + return 1; + } + +- retval = st->ss->load_container(st, cfd, NULL); +- +- if (retval) { +- pr_err("Cannot read superblock for %s\n", devname); +- close(cfd); ++ rv = prepare_external_reshape(devname, subarray, st, ++ container, cfd); ++ if (rv > 0) { + free(subarray); +- return 1; ++ close(cfd); ++ goto release; + } + + if (s->raiddisks && subarray) { +@@ -1902,51 +1954,6 @@ int Grow_reshape(char *devname, int fd, + free(subarray); + return 1; + } +- +- /* check if operation is supported for metadata handler */ +- if (st->ss->container_content) { +- struct mdinfo *cc = NULL; +- struct mdinfo *content = NULL; +- +- cc = st->ss->container_content(st, subarray); +- for (content = cc; content ; content = content->next) { +- int allow_reshape = 1; +- +- /* check if reshape is allowed based on metadata +- * indications stored in content.array.status +- */ +- if (content->array.state & +- (1 << MD_SB_BLOCK_VOLUME)) +- allow_reshape = 0; +- if (content->array.state & +- (1 << MD_SB_BLOCK_CONTAINER_RESHAPE)) +- allow_reshape = 0; +- if (!allow_reshape) { +- pr_err("cannot reshape arrays in container with unsupported metadata: %s(%s)\n", +- devname, container); +- sysfs_free(cc); +- free(subarray); +- return 1; +- } +- if (content->consistency_policy == +- CONSISTENCY_POLICY_PPL) { +- pr_err("Operation not supported when ppl consistency policy is enabled\n"); +- sysfs_free(cc); +- free(subarray); +- return 1; +- } +- if (content->consistency_policy == +- CONSISTENCY_POLICY_BITMAP) { +- pr_err("Operation not supported when write-intent bitmap is enabled\n"); +- sysfs_free(cc); +- free(subarray); +- return 1; +- } +- } +- sysfs_free(cc); +- } +- if (mdmon_running(container)) +- st->update_tail = &st->updates; + } + + added_disks = 0; +diff --git a/mdadm.h b/mdadm.h +index 8208b81e..941a5f38 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1539,6 +1539,7 @@ extern int stat_is_blkdev(char *devname, dev_t *rdev); + extern bool is_dev_alive(char *path); + extern int get_mdp_major(void); + extern int get_maj_min(char *dev, int *major, int *minor); ++extern bool is_bit_set(int *val, unsigned char index); + extern int dev_open(char *dev, int flags); + extern int open_dev(char *devnm); + extern void reopen_mddev(int mdfd); +diff --git a/util.c b/util.c +index ca48d976..26ffdcea 100644 +--- a/util.c ++++ b/util.c +@@ -1027,6 +1027,20 @@ int get_maj_min(char *dev, int *major, int *minor) + *e == 0); + } + ++/** ++ * is_bit_set() - get bit value by index. ++ * @val: value. ++ * @index: index of the bit (LSB numbering). ++ * ++ * Return: bit value. ++ */ ++bool is_bit_set(int *val, unsigned char index) ++{ ++ if ((*val) & (1 << index)) ++ return true; ++ return false; ++} ++ + int dev_open(char *dev, int flags) + { + /* like 'open', but if 'dev' matches %d:%d, create a temp +-- +2.38.1 + diff --git a/0052-Assemble-check-if-device-is-container-before-schedul.patch b/0052-Assemble-check-if-device-is-container-before-schedul.patch new file mode 100644 index 0000000..52d08b8 --- /dev/null +++ b/0052-Assemble-check-if-device-is-container-before-schedul.patch @@ -0,0 +1,36 @@ +From 5c3c3df646dd3b7e8df81152f08e9ac4ddccc671 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Fri, 19 Aug 2022 02:55:46 +0200 +Subject: [PATCH 52/83] Assemble: check if device is container before + scheduling force-clean update + +Up to now using assemble with force flag making each array as clean. +Force-clean should not be done for the container. This commit add +check if device is different than container before cleaning. + +Signed-off-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + Assemble.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index be2160b4..1dd82a8c 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1809,10 +1809,9 @@ try_again: + } + #endif + } +- if (c->force && !clean && ++ if (c->force && !clean && content->array.level != LEVEL_CONTAINER && + !enough(content->array.level, content->array.raid_disks, +- content->array.layout, clean, +- avail)) { ++ content->array.layout, clean, avail)) { + change += st->ss->update_super(st, content, "force-array", + devices[chosen_drive].devname, c->verbose, + 0, NULL); +-- +2.38.1 + diff --git a/0053-super1-report-truncated-device.patch b/0053-super1-report-truncated-device.patch new file mode 100644 index 0000000..35cbd4b --- /dev/null +++ b/0053-super1-report-truncated-device.patch @@ -0,0 +1,112 @@ +From 171e9743881edf2dfb163ddff483566fbf913ccd Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Fri, 26 Aug 2022 08:55:56 +1000 +Subject: [PATCH 53/83] super1: report truncated device + +When the metadata is at the start of the device, it is possible that it +describes a device large than the one it is actually stored on. When +this happens, report it loudly in --examine. + +.... + Unused Space : before=1968 sectors, after=-2047 sectors DEVICE TOO SMALL + State : clean TRUNCATED DEVICE +.... + +Also report in --assemble so that the failure which the kernel will +report will be explained. + +mdadm: Device /dev/sdb is not large enough for data described in superblock +mdadm: no RAID superblock on /dev/sdb +mdadm: /dev/sdb has no superblock - assembly aborted + +Scenario can be demonstrated as follows: + +mdadm: Note: this array has metadata at the start and + may not be suitable as a boot device. If you plan to + store '/boot' on this device please ensure that + your boot-loader understands md/v1.x metadata, or use + --metadata=0.90 +mdadm: Defaulting to version 1.2 metadata +mdadm: array /dev/md/test started. +mdadm: stopped /dev/md/test + Unused Space : before=1968 sectors, after=-2047 sectors DEVICE TOO SMALL + State : clean TRUNCATED DEVICE + Unused Space : before=1968 sectors, after=-2047 sectors DEVICE TOO SMALL + State : clean TRUNCATED DEVICE + +Signed-off-by: NeilBrown +Signed-off-by: Jes Sorensen +--- + super1.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/super1.c b/super1.c +index 71af860c..58345e68 100644 +--- a/super1.c ++++ b/super1.c +@@ -406,12 +406,18 @@ static void examine_super1(struct supertype *st, char *homehost) + + st->ss->getinfo_super(st, &info, NULL); + if (info.space_after != 1 && +- !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET)) +- printf(" Unused Space : before=%llu sectors, after=%llu sectors\n", +- info.space_before, info.space_after); +- +- printf(" State : %s\n", +- (__le64_to_cpu(sb->resync_offset)+1)? "active":"clean"); ++ !(__le32_to_cpu(sb->feature_map) & MD_FEATURE_NEW_OFFSET)) { ++ printf(" Unused Space : before=%llu sectors, ", ++ info.space_before); ++ if (info.space_after < INT64_MAX) ++ printf("after=%llu sectors\n", info.space_after); ++ else ++ printf("after=-%llu sectors DEVICE TOO SMALL\n", ++ UINT64_MAX - info.space_after); ++ } ++ printf(" State : %s%s\n", ++ (__le64_to_cpu(sb->resync_offset)+1) ? "active":"clean", ++ (info.space_after > INT64_MAX) ? " TRUNCATED DEVICE" : ""); + printf(" Device UUID : "); + for (i=0; i<16; i++) { + if ((i&3)==0 && i != 0) +@@ -2206,6 +2212,7 @@ static int load_super1(struct supertype *st, int fd, char *devname) + tst.ss = &super1; + for (tst.minor_version = 0; tst.minor_version <= 2; + tst.minor_version++) { ++ tst.ignore_hw_compat = st->ignore_hw_compat; + switch(load_super1(&tst, fd, devname)) { + case 0: super = tst.sb; + if (bestvers == -1 || +@@ -2312,7 +2319,6 @@ static int load_super1(struct supertype *st, int fd, char *devname) + free(super); + return 2; + } +- st->sb = super; + + bsb = (struct bitmap_super_s *)(((char*)super)+MAX_SB_SIZE); + +@@ -2322,6 +2328,21 @@ static int load_super1(struct supertype *st, int fd, char *devname) + if (st->data_offset == INVALID_SECTORS) + st->data_offset = __le64_to_cpu(super->data_offset); + ++ if (st->minor_version >= 1 && ++ st->ignore_hw_compat == 0 && ++ (dsize < (__le64_to_cpu(super->data_offset) + ++ __le64_to_cpu(super->size)) ++ || ++ dsize < (__le64_to_cpu(super->data_offset) + ++ __le64_to_cpu(super->data_size)))) { ++ if (devname) ++ pr_err("Device %s is not large enough for data described in superblock\n", ++ devname); ++ free(super); ++ return 2; ++ } ++ st->sb = super; ++ + /* Now check on the bitmap superblock */ + if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0) + return 0; +-- +2.38.1 + diff --git a/0054-mdadm-Correct-typos-punctuation-and-grammar-in-man.patch b/0054-mdadm-Correct-typos-punctuation-and-grammar-in-man.patch new file mode 100644 index 0000000..c37276f --- /dev/null +++ b/0054-mdadm-Correct-typos-punctuation-and-grammar-in-man.patch @@ -0,0 +1,616 @@ +From 1a386f804d8392b849b3362da6b0157b0db83091 Mon Sep 17 00:00:00 2001 +From: Mateusz Grzonka +Date: Fri, 12 Aug 2022 16:52:12 +0200 +Subject: [PATCH 54/83] mdadm: Correct typos, punctuation and grammar in man + +Signed-off-by: Mateusz Grzonka +Reviewed-by: Wol +Signed-off-by: Jes Sorensen +--- + mdadm.8.in | 178 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 88 insertions(+), 90 deletions(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index f2736226..70c79d1e 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -158,7 +158,7 @@ adding new spares and removing faulty devices. + .B Misc + This is an 'everything else' mode that supports operations on active + arrays, operations on component devices such as erasing old superblocks, and +-information gathering operations. ++information-gathering operations. + .\"This mode allows operations on independent devices such as examine MD + .\"superblocks, erasing old superblocks and stopping active arrays. + +@@ -231,12 +231,12 @@ mode to be assumed. + + .TP + .BR \-h ", " \-\-help +-Display general help message or, after one of the above options, a ++Display a general help message or, after one of the above options, a + mode-specific help message. + + .TP + .B \-\-help\-options +-Display more detailed help about command line parsing and some commonly ++Display more detailed help about command-line parsing and some commonly + used options. + + .TP +@@ -266,7 +266,7 @@ the exact meaning of this option in different contexts. + + .TP + .BR \-c ", " \-\-config= +-Specify the config file or directory. If not specified, default config file ++Specify the config file or directory. If not specified, the default config file + and default conf.d directory will be used. See + .BR mdadm.conf (5) + for more details. +@@ -379,7 +379,7 @@ When creating an array, the + .B homehost + will be recorded in the metadata. For version-1 superblocks, it will + be prefixed to the array name. For version-0.90 superblocks, part of +-the SHA1 hash of the hostname will be stored in the later half of the ++the SHA1 hash of the hostname will be stored in the latter half of the + UUID. + + When reporting information about an array, any array which is tagged +@@ -388,7 +388,7 @@ for the given homehost will be reported as such. + When using Auto-Assemble, only arrays tagged for the given homehost + will be allowed to use 'local' names (i.e. not ending in '_' followed + by a digit string). See below under +-.BR "Auto Assembly" . ++.BR "Auto-Assembly" . + + The special name "\fBany\fP" can be used as a wild card. If an array + is created with +@@ -403,7 +403,7 @@ When + .I mdadm + needs to print the name for a device it normally finds the name in + .B /dev +-which refers to the device and is shortest. When a path component is ++which refers to the device and is the shortest. When a path component is + given with + .B \-\-prefer + .I mdadm +@@ -478,9 +478,9 @@ still be larger than any replacement. + + This option can be used with + .B \-\-create +-for determining initial size of an array. For external metadata, ++for determining the initial size of an array. For external metadata, + it can be used on a volume, but not on a container itself. +-Setting initial size of ++Setting the initial size of + .B RAID 0 + array is only valid for external metadata. + +@@ -545,20 +545,20 @@ Clustered arrays do not support this parameter yet. + + .TP + .BR \-c ", " \-\-chunk= +-Specify chunk size of kilobytes. The default when creating an ++Specify chunk size in kilobytes. The default when creating an + array is 512KB. To ensure compatibility with earlier versions, the + default when building an array with no persistent metadata is 64KB. + This is only meaningful for RAID0, RAID4, RAID5, RAID6, and RAID10. + + RAID4, RAID5, RAID6, and RAID10 require the chunk size to be a power +-of 2. In any case it must be a multiple of 4KB. ++of 2, with minimal chunk size being 4KB. + + A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes, + Megabytes, Gigabytes or Terabytes respectively. + + .TP + .BR \-\-rounding= +-Specify rounding factor for a Linear array. The size of each ++Specify the rounding factor for a Linear array. The size of each + component will be rounded down to a multiple of this size. + This is a synonym for + .B \-\-chunk +@@ -655,7 +655,8 @@ option to set subsequent failure modes. + and "flush" will clear any persistent faults. + + The layout options for RAID10 are one of 'n', 'o' or 'f' followed +-by a small number. The default is 'n2'. The supported options are: ++by a small number signifying the number of copies of each datablock. ++The default is 'n2'. The supported options are: + + .I 'n' + signals 'near' copies. Multiple copies of one data block are at +@@ -673,7 +674,7 @@ signals 'far' copies + (multiple copies have very different offsets). + See md(4) for more detail about 'near', 'offset', and 'far'. + +-The number is the number of copies of each datablock. 2 is normal, 3 ++As for the number of copies of each data block, 2 is normal, 3 + can be useful. This number can be at most equal to the number of + devices in the array. It does not need to divide evenly into that + number (e.g. it is perfectly legal to have an 'n2' layout for an array +@@ -684,7 +685,7 @@ A bug introduced in Linux 3.14 means that RAID0 arrays + started using a different layout. This could lead to + data corruption. Since Linux 5.4 (and various stable releases that received + backports), the kernel will not accept such an array unless +-a layout is explictly set. It can be set to ++a layout is explicitly set. It can be set to + .RB ' original ' + or + .RB ' alternate '. +@@ -760,13 +761,13 @@ or by selecting a different consistency policy with + + .TP + .BR \-\-bitmap\-chunk= +-Set the chunksize of the bitmap. Each bit corresponds to that many ++Set the chunk size of the bitmap. Each bit corresponds to that many + Kilobytes of storage. +-When using a file based bitmap, the default is to use the smallest +-size that is at-least 4 and requires no more than 2^21 chunks. ++When using a file-based bitmap, the default is to use the smallest ++size that is at least 4 and requires no more than 2^21 chunks. + When using an + .B internal +-bitmap, the chunksize defaults to 64Meg, or larger if necessary to ++bitmap, the chunk size defaults to 64Meg, or larger if necessary to + fit the bitmap into the available space. + + A suffix of 'K', 'M', 'G' or 'T' can be given to indicate Kilobytes, +@@ -840,7 +841,7 @@ can be used with that command to avoid the automatic resync. + .BR \-\-backup\-file= + This is needed when + .B \-\-grow +-is used to increase the number of raid-devices in a RAID5 or RAID6 if ++is used to increase the number of raid devices in a RAID5 or RAID6 if + there are no spare devices available, or to shrink, change RAID level + or layout. See the GROW MODE section below on RAID\-DEVICES CHANGES. + The file must be stored on a separate device, not on the RAID array +@@ -879,7 +880,7 @@ When creating an array, + .B \-\-data\-offset + can be specified as + .BR variable . +-In the case each member device is expected to have a offset appended ++In the case each member device is expected to have an offset appended + to the name, separated by a colon. This makes it possible to recreate + exactly an array which has varying data offsets (as can happen when + different versions of +@@ -943,7 +944,7 @@ Insist that + .I mdadm + accept the geometry and layout specified without question. Normally + .I mdadm +-will not allow creation of an array with only one device, and will try ++will not allow the creation of an array with only one device, and will try + to create a RAID5 array with one missing drive (as this makes the + initial resync work faster). With + .BR \-\-force , +@@ -1004,7 +1005,7 @@ number added, e.g. + If the md device name is in a 'standard' format as described in DEVICE + NAMES, then it will be created, if necessary, with the appropriate + device number based on that name. If the device name is not in one of these +-formats, then a unused device number will be allocated. The device ++formats, then an unused device number will be allocated. The device + number will be considered unused if there is no active array for that + number, and there is no entry in /dev for that number and with a + non-standard name. Names that are not in 'standard' format are only +@@ -1032,25 +1033,25 @@ then + .B \-\-add + can be used to add some extra devices to be included in the array. + In most cases this is not needed as the extra devices can be added as +-spares first, and then the number of raid-disks can be changed. +-However for RAID0, it is not possible to add spares. So to increase ++spares first, and then the number of raid disks can be changed. ++However, for RAID0 it is not possible to add spares. So to increase + the number of devices in a RAID0, it is necessary to set the new + number of devices, and to add the new devices, in the same command. + + .TP + .BR \-\-nodes +-Only works when the array is for clustered environment. It specifies ++Only works when the array is created for a clustered environment. It specifies + the maximum number of nodes in the cluster that will use this device + simultaneously. If not specified, this defaults to 4. + + .TP + .BR \-\-write-journal + Specify journal device for the RAID-4/5/6 array. The journal device +-should be a SSD with reasonable lifetime. ++should be an SSD with a reasonable lifetime. + + .TP + .BR \-k ", " \-\-consistency\-policy= +-Specify how the array maintains consistency in case of unexpected shutdown. ++Specify how the array maintains consistency in the case of an unexpected shutdown. + Only relevant for RAID levels with redundancy. + Currently supported options are: + .RS +@@ -1058,7 +1059,7 @@ Currently supported options are: + .TP + .B resync + Full resync is performed and all redundancy is regenerated when the array is +-started after unclean shutdown. ++started after an unclean shutdown. + + .TP + .B bitmap +@@ -1067,8 +1068,8 @@ Resync assisted by a write-intent bitmap. Implicitly selected when using + + .TP + .B journal +-For RAID levels 4/5/6, journal device is used to log transactions and replay +-after unclean shutdown. Implicitly selected when using ++For RAID levels 4/5/6, the journal device is used to log transactions and replay ++after an unclean shutdown. Implicitly selected when using + .BR \-\-write\-journal . + + .TP +@@ -1237,7 +1238,7 @@ This can be useful if + reports a different "Preferred Minor" to + .BR \-\-detail . + In some cases this update will be performed automatically +-by the kernel driver. In particular the update happens automatically ++by the kernel driver. In particular, the update happens automatically + at the first write to an array with redundancy (RAID level 1 or + greater) on a 2.6 (or later) kernel. + +@@ -1277,7 +1278,7 @@ For version-1 superblocks, this involves updating the name. + The + .B home\-cluster + option will change the cluster name as recorded in the superblock and +-bitmap. This option only works for clustered environment. ++bitmap. This option only works for a clustered environment. + + The + .B resync +@@ -1390,10 +1391,10 @@ This option should be used with great caution. + + .TP + .BR \-\-freeze\-reshape +-Option is intended to be used in start-up scripts during initrd boot phase. +-When array under reshape is assembled during initrd phase, this option +-stops reshape after reshape critical section is being restored. This happens +-before file system pivot operation and avoids loss of file system context. ++This option is intended to be used in start-up scripts during the initrd boot phase. ++When the array under reshape is assembled during the initrd phase, this option ++stops the reshape after the reshape-critical section has been restored. This happens ++before the file system pivot operation and avoids loss of filesystem context. + Losing file system context would cause reshape to be broken. + + Reshape can be continued later using the +@@ -1437,9 +1438,9 @@ re\-add a device that was previously removed from an array. + If the metadata on the device reports that it is a member of the + array, and the slot that it used is still vacant, then the device will + be added back to the array in the same position. This will normally +-cause the data for that device to be recovered. However based on the ++cause the data for that device to be recovered. However, based on the + event count on the device, the recovery may only require sections that +-are flagged a write-intent bitmap to be recovered or may not require ++are flagged by a write-intent bitmap to be recovered or may not require + any recovery at all. + + When used on an array that has no metadata (i.e. it was built with +@@ -1447,13 +1448,12 @@ When used on an array that has no metadata (i.e. it was built with + it will be assumed that bitmap-based recovery is enough to make the + device fully consistent with the array. + +-When used with v1.x metadata, + .B \-\-re\-add +-can be accompanied by ++can also be accompanied by + .BR \-\-update=devicesize , + .BR \-\-update=bbl ", or" + .BR \-\-update=no\-bbl . +-See the description of these option when used in Assemble mode for an ++See descriptions of these options when used in Assemble mode for an + explanation of their use. + + If the device name given is +@@ -1480,7 +1480,7 @@ Add a device as a spare. This is similar to + except that it does not attempt + .B \-\-re\-add + first. The device will be added as a spare even if it looks like it +-could be an recent member of the array. ++could be a recent member of the array. + + .TP + .BR \-r ", " \-\-remove +@@ -1497,12 +1497,12 @@ and names like + .B set-A + can be given to + .BR \-\-remove . +-The first causes all failed device to be removed. The second causes ++The first causes all failed devices to be removed. The second causes + any device which is no longer connected to the system (i.e an 'open' + returns + .BR ENXIO ) + to be removed. +-The third will remove a set as describe below under ++The third will remove a set as described below under + .BR \-\-fail . + + .TP +@@ -1519,7 +1519,7 @@ For RAID10 arrays where the number of copies evenly divides the number + of devices, the devices can be conceptually divided into sets where + each set contains a single complete copy of the data on the array. + Sometimes a RAID10 array will be configured so that these sets are on +-separate controllers. In this case all the devices in one set can be ++separate controllers. In this case, all the devices in one set can be + failed by giving a name like + .B set\-A + or +@@ -1549,9 +1549,9 @@ This can follow a list of + .B \-\-replace + devices. The devices listed after + .B \-\-with +-will be preferentially used to replace the devices listed after ++will preferentially be used to replace the devices listed after + .BR \-\-replace . +-These device must already be spare devices in the array. ++These devices must already be spare devices in the array. + + .TP + .BR \-\-write\-mostly +@@ -1574,8 +1574,8 @@ the device is found or :missing in case the device is not found. + + .TP + .BR \-\-add-journal +-Add journal to an existing array, or recreate journal for RAID-4/5/6 array +-that lost a journal device. To avoid interrupting on-going write opertions, ++Add a journal to an existing array, or recreate journal for a RAID-4/5/6 array ++that lost a journal device. To avoid interrupting ongoing write operations, + .B \-\-add-journal + only works for array in Read-Only state. + +@@ -1631,9 +1631,9 @@ Print details of one or more md devices. + .TP + .BR \-\-detail\-platform + Print details of the platform's RAID capabilities (firmware / hardware +-topology) for a given metadata format. If used without argument, mdadm ++topology) for a given metadata format. If used without an argument, mdadm + will scan all controllers looking for their capabilities. Otherwise, mdadm +-will only look at the controller specified by the argument in form of an ++will only look at the controller specified by the argument in the form of an + absolute filepath or a link, e.g. + .IR /sys/devices/pci0000:00/0000:00:1f.2 . + +@@ -1742,8 +1742,8 @@ the block where the superblock would be is overwritten even if it + doesn't appear to be valid. + + .B Note: +-Be careful to call \-\-zero\-superblock with clustered raid, make sure +-array isn't used or assembled in other cluster node before execute it. ++Be careful when calling \-\-zero\-superblock with clustered raid. Make sure ++the array isn't used or assembled in another cluster node before executing it. + + .TP + .B \-\-kill\-subarray= +@@ -1790,7 +1790,7 @@ For each md device given, or each device in /proc/mdstat if + is given, arrange for the array to be marked clean as soon as possible. + .I mdadm + will return with success if the array uses external metadata and we +-successfully waited. For native arrays this returns immediately as the ++successfully waited. For native arrays, this returns immediately as the + kernel handles dirty-clean transitions at shutdown. No action is taken + if safe-mode handling is disabled. + +@@ -1830,7 +1830,7 @@ uses to help track which arrays are currently being assembled. + + .TP + .BR \-\-run ", " \-R +-Run any array assembled as soon as a minimal number of devices are ++Run any array assembled as soon as a minimal number of devices is + available, rather than waiting until all expected devices are present. + + .TP +@@ -1860,7 +1860,7 @@ Only used with \-\-fail. The 'path' given will be recorded so that if + a new device appears at the same location it can be automatically + added to the same array. This allows the failed device to be + automatically replaced by a new device without metadata if it appears +-at specified path. This option is normally only set by a ++at specified path. This option is normally only set by an + .I udev + script. + +@@ -1961,7 +1961,7 @@ Usage: + .PP + This usage assembles one or more RAID arrays from pre-existing components. + For each array, mdadm needs to know the md device, the identity of the +-array, and a number of component-devices. These can be found in a number of ways. ++array, and the number of component devices. These can be found in a number of ways. + + In the first usage example (without the + .BR \-\-scan ) +@@ -2001,7 +2001,7 @@ The config file is only used if explicitly named with + .B \-\-config + or requested with (a possibly implicit) + .BR \-\-scan . +-In the later case, default config file is used. See ++In the latter case, the default config file is used. See + .BR mdadm.conf (5) + for more details. + +@@ -2039,14 +2039,14 @@ detects that udev is not configured, it will create the devices in + .B /dev + itself. + +-In Linux kernels prior to version 2.6.28 there were two distinctly +-different types of md devices that could be created: one that could be ++In Linux kernels prior to version 2.6.28 there were two distinct ++types of md devices that could be created: one that could be + partitioned using standard partitioning tools and one that could not. +-Since 2.6.28 that distinction is no longer relevant as both type of ++Since 2.6.28 that distinction is no longer relevant as both types of + devices can be partitioned. + .I mdadm + will normally create the type that originally could not be partitioned +-as it has a well defined major number (9). ++as it has a well-defined major number (9). + + Prior to 2.6.28, it is important that mdadm chooses the correct type + of array device to use. This can be controlled with the +@@ -2066,7 +2066,7 @@ can also be given in the configuration file as a word starting + .B auto= + on the ARRAY line for the relevant array. + +-.SS Auto Assembly ++.SS Auto-Assembly + When + .B \-\-assemble + is used with +@@ -2122,11 +2122,11 @@ See + .IR mdadm.conf (5) + for further details. + +-Note: Auto assembly cannot be used for assembling and activating some ++Note: Auto-assembly cannot be used for assembling and activating some + arrays which are undergoing reshape. In particular as the + .B backup\-file +-cannot be given, any reshape which requires a backup-file to continue +-cannot be started by auto assembly. An array which is growing to more ++cannot be given, any reshape which requires a backup file to continue ++cannot be started by auto-assembly. An array which is growing to more + devices and has passed the critical section can be assembled using + auto-assembly. + +@@ -2233,7 +2233,7 @@ When creating a partition based array, using + .I mdadm + with version-1.x metadata, the partition type should be set to + .B 0xDA +-(non fs-data). This type selection allows for greater precision since ++(non fs-data). This type of selection allows for greater precision since + using any other [RAID auto-detect (0xFD) or a GNU/Linux partition (0x83)], + might create problems in the event of array recovery through a live cdrom. + +@@ -2249,7 +2249,7 @@ when creating a v0.90 array will silently override any + setting. + .\"If the + .\".B \-\-size +-.\"option is given, it is not necessary to list any component-devices in this command. ++.\"option is given, it is not necessary to list any component devices in this command. + .\"They can be added later, before a + .\".B \-\-run. + .\"If no +@@ -2263,7 +2263,7 @@ requested with the + .B \-\-bitmap + option or a different consistency policy is selected with the + .B \-\-consistency\-policy +-option. In any case space for a bitmap will be reserved so that one ++option. In any case, space for a bitmap will be reserved so that one + can be added later with + .BR "\-\-grow \-\-bitmap=internal" . + +@@ -2313,7 +2313,7 @@ will firstly mark + as faulty in + .B /dev/md0 + and will then remove it from the array and finally add it back +-in as a spare. However only one md array can be affected by a single ++in as a spare. However, only one md array can be affected by a single + command. + + When a device is added to an active array, mdadm checks to see if it +@@ -2458,14 +2458,14 @@ config file to be examined. + If the device contains RAID metadata, a file will be created in the + .I directory + and the metadata will be written to it. The file will be the same +-size as the device and have the metadata written in the file at the +-same locate that it exists in the device. However the file will be "sparse" so ++size as the device and will have the metadata written at the ++same location as it exists in the device. However, the file will be "sparse" so + that only those blocks containing metadata will be allocated. The + total space used will be small. + +-The file name used in the ++The filename used in the + .I directory +-will be the base name of the device. Further if any links appear in ++will be the base name of the device. Further, if any links appear in + .I /dev/disk/by-id + which point to the device, then hard links to the file will be created + in +@@ -2567,7 +2567,7 @@ 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 ++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 +@@ -2624,10 +2624,10 @@ check, repair). (syslog priority: Warning) + .BI Rebuild NN + Where + .I NN +-is a two-digit number (ie. 05, 48). This indicates that rebuild +-has passed that many percent of the total. The events are generated +-with fixed increment since 0. Increment size may be specified with +-a commandline option (default is 20). (syslog priority: Warning) ++is a two-digit number (eg. 05, 48). This indicates that the rebuild ++has reached that percentage of the total. The events are generated ++at a fixed increment from 0. The increment size may be specified with ++a command-line option (the default is 20). (syslog priority: Warning) + + .TP + .B RebuildFinished +@@ -2735,8 +2735,8 @@ When + detects that an array in a spare group has fewer active + devices than necessary for the complete array, and has no spare + devices, it will look for another array in the same spare group that +-has a full complement of working drive and a spare. It will then +-attempt to remove the spare from the second drive and add it to the ++has a full complement of working drives and a spare. It will then ++attempt to remove the spare from the second array and add it to the + first. + If the removal succeeds but the adding fails, then it is added back to + the original array. +@@ -2750,10 +2750,8 @@ and then follow similar steps as above if a matching spare is found. + .SH GROW MODE + The GROW mode is used for changing the size or shape of an active + array. +-For this to work, the kernel must support the necessary change. +-Various types of growth are being added during 2.6 development. + +-Currently the supported changes include ++During the kernel 2.6 era the following changes were added: + .IP \(bu 4 + change the "size" attribute for RAID1, RAID4, RAID5 and RAID6. + .IP \(bu 4 +@@ -2796,8 +2794,8 @@ use more than half of a spare device for backup space. + + .SS SIZE CHANGES + Normally when an array is built the "size" is taken from the smallest +-of the drives. If all the small drives in an arrays are, one at a +-time, removed and replaced with larger drives, then you could have an ++of the drives. If all the small drives in an arrays are, over time, ++removed and replaced with larger drives, then you could have an + array of large drives with only a small amount used. In this + situation, changing the "size" with "GROW" mode will allow the extra + space to start being used. If the size is increased in this way, a +@@ -2812,7 +2810,7 @@ after growing, or to reduce its size + .B prior + to shrinking the array. + +-Also the size of an array cannot be changed while it has an active ++Also, the size of an array cannot be changed while it has an active + bitmap. If an array has a bitmap, it must be removed before the size + can be changed. Once the change is complete a new bitmap can be created. + +@@ -2892,7 +2890,7 @@ long time. A + is required. If the array is not simultaneously being grown or + shrunk, so that the array size will remain the same - for example, + reshaping a 3-drive RAID5 into a 4-drive RAID6 - the backup file will +-be used not just for a "cricital section" but throughout the reshape ++be used not just for a "critical section" but throughout the reshape + operation, as described below under LAYOUT CHANGES. + + .SS CHUNK-SIZE AND LAYOUT CHANGES +@@ -2910,7 +2908,7 @@ slowly. + If the reshape is interrupted for any reason, this backup file must be + made available to + .B "mdadm --assemble" +-so the array can be reassembled. Consequently the file cannot be ++so the array can be reassembled. Consequently, the file cannot be + stored on the device being reshaped. + + +-- +2.38.1 + diff --git a/0055-Manage-Block-unsafe-member-failing.patch b/0055-Manage-Block-unsafe-member-failing.patch new file mode 100644 index 0000000..290c56f --- /dev/null +++ b/0055-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 55/83] 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 a142f8bd..b1d0e630 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.38.1 + diff --git a/0056-Monitor-Fix-statelist-memory-leaks.patch b/0056-Monitor-Fix-statelist-memory-leaks.patch new file mode 100644 index 0000000..ad36a25 --- /dev/null +++ b/0056-Monitor-Fix-statelist-memory-leaks.patch @@ -0,0 +1,112 @@ +From 55c10e4de13abe3e6934895e1fff7d2d20d0b2c2 Mon Sep 17 00:00:00 2001 +From: Pawel Baldysiak +Date: Thu, 1 Sep 2022 11:20:31 +0200 +Subject: [PATCH 56/83] Monitor: Fix statelist memory leaks + +Free statelist in error path in Monitor initialization. + +Signed-off-by: Pawel Baldysiak +Signed-off-by: Jes Sorensen +--- + Monitor.c | 40 +++++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 9 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 93f36ac0..b4e954c6 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -74,6 +74,7 @@ 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 link_containers_with_subarrays(struct state *list); ++static void free_statelist(struct state *statelist); + #ifndef NO_LIBUDEV + static int check_udev_activity(void); + #endif +@@ -128,7 +129,6 @@ int Monitor(struct mddev_dev *devlist, + */ + + struct state *statelist = NULL; +- struct state *st2; + int finished = 0; + struct mdstat_ent *mdstat = NULL; + char *mailfrom; +@@ -185,12 +185,14 @@ int Monitor(struct mddev_dev *devlist, + continue; + if (strcasecmp(mdlist->devname, "") == 0) + continue; ++ if (!is_mddev(mdlist->devname)) { ++ free_statelist(statelist); ++ return 1; ++ } + + st = xcalloc(1, sizeof *st); + snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), + "/dev/md/%s", basename(mdlist->devname)); +- if (!is_mddev(mdlist->devname)) +- return 1; + st->next = statelist; + st->devnm[0] = 0; + st->percent = RESYNC_UNKNOWN; +@@ -206,8 +208,10 @@ int Monitor(struct mddev_dev *devlist, + for (dv = devlist; dv; dv = dv->next) { + struct state *st; + +- if (!is_mddev(dv->devname)) ++ if (!is_mddev(dv->devname)) { ++ free_statelist(statelist); + return 1; ++ } + + st = xcalloc(1, sizeof *st); + mdlist = conf_get_ident(dv->devname); +@@ -294,16 +298,16 @@ int Monitor(struct mddev_dev *devlist, + for (stp = &statelist; (st = *stp) != NULL; ) { + if (st->from_auto && st->err > 5) { + *stp = st->next; +- free(st->spare_group); ++ if (st->spare_group) ++ free(st->spare_group); ++ + free(st); + } else + stp = &st->next; + } + } +- for (st2 = statelist; st2; st2 = statelist) { +- statelist = st2->next; +- free(st2); +- } ++ ++ free_statelist(statelist); + + if (pidfile) + unlink(pidfile); +@@ -1056,6 +1060,24 @@ static void link_containers_with_subarrays(struct state *list) + } + } + ++/** ++ * free_statelist() - Frees statelist. ++ * @statelist: statelist to free ++ */ ++static void free_statelist(struct state *statelist) ++{ ++ struct state *tmp = NULL; ++ ++ while (statelist) { ++ if (statelist->spare_group) ++ free(statelist->spare_group); ++ ++ tmp = statelist; ++ statelist = statelist->next; ++ free(tmp); ++ } ++} ++ + #ifndef NO_LIBUDEV + /* function: check_udev_activity + * Description: Function waits for udev to finish +-- +2.38.1 + diff --git a/0057-mdadm-added-support-for-Intel-Alderlake-RST-on-VMD-p.patch b/0057-mdadm-added-support-for-Intel-Alderlake-RST-on-VMD-p.patch new file mode 100644 index 0000000..79a3262 --- /dev/null +++ b/0057-mdadm-added-support-for-Intel-Alderlake-RST-on-VMD-p.patch @@ -0,0 +1,64 @@ +From ea7a02a3294aae223e1329aed5da7f4aa3ac05c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Old=C5=99ich=20Jedli=C4=8Dka?= +Date: Wed, 31 Aug 2022 19:57:29 +0200 +Subject: [PATCH 57/83] mdadm: added support for Intel Alderlake RST on VMD + platform +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Alderlake RST on VMD uses RstVmdV UEFI variable name, so detect it. + +Signed-off-by: Oldřich Jedlička +Reviewed-by: Kinga Tanska +Signed-off-by: Jes Sorensen +--- + platform-intel.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 5a8729e7..757f0b1b 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -512,7 +512,8 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + #define AHCI_PROP "RstSataV" + #define AHCI_SSATA_PROP "RstsSatV" + #define AHCI_TSATA_PROP "RsttSatV" +-#define VMD_PROP "RstUefiV" ++#define VROC_VMD_PROP "RstUefiV" ++#define RST_VMD_PROP "RstVmdV" + + #define VENDOR_GUID \ + EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, 0x1a, 0x04, 0xc6) +@@ -605,6 +606,7 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + struct orom_entry *ret; + static const char * const sata_efivars[] = {AHCI_PROP, AHCI_SSATA_PROP, + AHCI_TSATA_PROP}; ++ static const char * const vmd_efivars[] = {VROC_VMD_PROP, RST_VMD_PROP}; + unsigned long i; + + if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI")) +@@ -636,10 +638,16 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + + break; + case SYS_DEV_VMD: +- if (!read_efi_variable(&orom, sizeof(orom), VMD_PROP, +- VENDOR_GUID)) +- break; +- return NULL; ++ for (i = 0; i < ARRAY_SIZE(vmd_efivars); i++) { ++ if (!read_efi_variable(&orom, sizeof(orom), ++ vmd_efivars[i], VENDOR_GUID)) ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(vmd_efivars)) ++ return NULL; ++ ++ break; + default: + return NULL; + } +-- +2.38.1 + diff --git a/0058-mdadm-Add-Documentation-entries-to-systemd-services.patch b/0058-mdadm-Add-Documentation-entries-to-systemd-services.patch new file mode 100644 index 0000000..6e1a179 --- /dev/null +++ b/0058-mdadm-Add-Documentation-entries-to-systemd-services.patch @@ -0,0 +1,111 @@ +From ea109700563d93704ebdc540c7770d874369f667 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 9 Sep 2022 15:50:33 +0200 +Subject: [PATCH 58/83] mdadm: Add Documentation entries to systemd services + +Add documentation section. +Copied from Debian. + +Cc: Felix Lechner +Signed-off-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + systemd/mdadm-grow-continue@.service | 1 + + systemd/mdadm-last-resort@.service | 1 + + systemd/mdcheck_continue.service | 3 ++- + systemd/mdcheck_start.service | 1 + + systemd/mdmon@.service | 1 + + systemd/mdmonitor-oneshot.service | 1 + + systemd/mdmonitor.service | 1 + + 7 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/systemd/mdadm-grow-continue@.service b/systemd/mdadm-grow-continue@.service +index 9fdc8ec7..64b8254a 100644 +--- a/systemd/mdadm-grow-continue@.service ++++ b/systemd/mdadm-grow-continue@.service +@@ -8,6 +8,7 @@ + [Unit] + Description=Manage MD Reshape on /dev/%I + DefaultDependencies=no ++Documentation=man:mdadm(8) + + [Service] + ExecStart=BINDIR/mdadm --grow --continue /dev/%I +diff --git a/systemd/mdadm-last-resort@.service b/systemd/mdadm-last-resort@.service +index efeb3f63..e9381125 100644 +--- a/systemd/mdadm-last-resort@.service ++++ b/systemd/mdadm-last-resort@.service +@@ -2,6 +2,7 @@ + Description=Activate md array %I even though degraded + DefaultDependencies=no + ConditionPathExists=!/sys/devices/virtual/block/%i/md/sync_action ++Documentation=man:mdadm(8) + + [Service] + Type=oneshot +diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service +index 854317f1..f5324905 100644 +--- a/systemd/mdcheck_continue.service ++++ b/systemd/mdcheck_continue.service +@@ -7,7 +7,8 @@ + + [Unit] + Description=MD array scrubbing - continuation +-ConditionPathExistsGlob = /var/lib/mdcheck/MD_UUID_* ++ConditionPathExistsGlob=/var/lib/mdcheck/MD_UUID_* ++Documentation=man:mdadm(8) + + [Service] + Type=oneshot +diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service +index 3bb3d130..703a6583 100644 +--- a/systemd/mdcheck_start.service ++++ b/systemd/mdcheck_start.service +@@ -8,6 +8,7 @@ + [Unit] + Description=MD array scrubbing + Wants=mdcheck_continue.timer ++Documentation=man:mdadm(8) + + [Service] + Type=oneshot +diff --git a/systemd/mdmon@.service b/systemd/mdmon@.service +index 77533958..97a1acd9 100644 +--- a/systemd/mdmon@.service ++++ b/systemd/mdmon@.service +@@ -9,6 +9,7 @@ + Description=MD Metadata Monitor on /dev/%I + DefaultDependencies=no + Before=initrd-switch-root.target ++Documentation=man:mdmon(8) + + [Service] + # mdmon should never complain due to lack of a platform, +diff --git a/systemd/mdmonitor-oneshot.service b/systemd/mdmonitor-oneshot.service +index 373955a2..ba86b44e 100644 +--- a/systemd/mdmonitor-oneshot.service ++++ b/systemd/mdmonitor-oneshot.service +@@ -7,6 +7,7 @@ + + [Unit] + Description=Reminder for degraded MD arrays ++Documentation=man:mdadm(8) + + [Service] + Environment=MDADM_MONITOR_ARGS=--scan +diff --git a/systemd/mdmonitor.service b/systemd/mdmonitor.service +index 46f7b880..9c364785 100644 +--- a/systemd/mdmonitor.service ++++ b/systemd/mdmonitor.service +@@ -8,6 +8,7 @@ + [Unit] + Description=MD array monitor + DefaultDependencies=no ++Documentation=man:mdadm(8) + + [Service] + Environment= MDADM_MONITOR_ARGS=--scan +-- +2.38.1 + diff --git a/0059-ReadMe-fix-command-line-help.patch b/0059-ReadMe-fix-command-line-help.patch new file mode 100644 index 0000000..837a339 --- /dev/null +++ b/0059-ReadMe-fix-command-line-help.patch @@ -0,0 +1,32 @@ +From f7cbd810b639eb946ba1b3bddb1faefb9696de42 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 9 Sep 2022 15:50:34 +0200 +Subject: [PATCH 59/83] ReadMe: fix command-line help + +Make command-line help consistent with manual page. +Copied from Debian. + +Cc: Felix Lechner +Signed-off-by: Mariusz Tkaczyk +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + ReadMe.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ReadMe.c b/ReadMe.c +index 7f94847e..50a5e36d 100644 +--- a/ReadMe.c ++++ b/ReadMe.c +@@ -477,7 +477,7 @@ char Help_assemble[] = + ; + + char Help_manage[] = +-"Usage: mdadm arraydevice options component devices...\n" ++"Usage: mdadm [mode] arraydevice [options] \n" + "\n" + "This usage is for managing the component devices within an array.\n" + "The --manage option is not needed and is assumed if the first argument\n" +-- +2.38.1 + diff --git a/0060-mdadm-replace-container-level-checking-with-inline.patch b/0060-mdadm-replace-container-level-checking-with-inline.patch new file mode 100644 index 0000000..7b2b6b2 --- /dev/null +++ b/0060-mdadm-replace-container-level-checking-with-inline.patch @@ -0,0 +1,257 @@ +From 6f2af6a48c541f207cb727a31fb86de2cd04fc21 Mon Sep 17 00:00:00 2001 +From: Kinga Tanska +Date: Fri, 2 Sep 2022 08:49:23 +0200 +Subject: [PATCH 60/83] mdadm: replace container level checking with inline + +To unify all containers checks in code, is_container() function is +added and propagated. + +Signed-off-by: Kinga Tanska +Acked-by: Coly Li +Signed-off-by: Jes Sorensen +--- + Assemble.c | 7 +++---- + Create.c | 6 +++--- + Grow.c | 6 +++--- + Incremental.c | 4 ++-- + mdadm.h | 14 ++++++++++++++ + super-ddf.c | 6 +++--- + super-intel.c | 4 ++-- + super0.c | 2 +- + super1.c | 2 +- + sysfs.c | 2 +- + 10 files changed, 33 insertions(+), 20 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 1dd82a8c..8b0af0c9 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1120,7 +1120,7 @@ static int start_array(int mdfd, + i/2, mddev); + } + +- if (content->array.level == LEVEL_CONTAINER) { ++ if (is_container(content->array.level)) { + sysfs_rules_apply(mddev, content); + if (c->verbose >= 0) { + pr_err("Container %s has been assembled with %d drive%s", +@@ -1549,8 +1549,7 @@ try_again: + */ + trustworthy = LOCAL; + +- if (name[0] == 0 && +- content->array.level == LEVEL_CONTAINER) { ++ if (!name[0] && is_container(content->array.level)) { + name = content->text_version; + trustworthy = METADATA; + } +@@ -1809,7 +1808,7 @@ try_again: + } + #endif + } +- if (c->force && !clean && content->array.level != LEVEL_CONTAINER && ++ 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", +diff --git a/Create.c b/Create.c +index e06ec2ae..953e7372 100644 +--- a/Create.c ++++ b/Create.c +@@ -487,7 +487,7 @@ int Create(struct supertype *st, char *mddev, + st->minor_version >= 1) + /* metadata at front */ + warn |= check_partitions(fd, dname, 0, 0); +- else if (s->level == 1 || s->level == LEVEL_CONTAINER || ++ else if (s->level == 1 || is_container(s->level) || + (s->level == 0 && s->raiddisks == 1)) + /* partitions could be meaningful */ + warn |= check_partitions(fd, dname, freesize*2, s->size*2); +@@ -997,7 +997,7 @@ int Create(struct supertype *st, char *mddev, + * again returns container info. + */ + st->ss->getinfo_super(st, &info_new, NULL); +- if (st->ss->external && s->level != LEVEL_CONTAINER && ++ 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, +@@ -1040,7 +1040,7 @@ int Create(struct supertype *st, char *mddev, + map_unlock(&map); + free(infos); + +- if (s->level == LEVEL_CONTAINER) { ++ if (is_container(s->level)) { + /* No need to start. But we should signal udev to + * create links */ + sysfs_uevent(&info, "change"); +diff --git a/Grow.c b/Grow.c +index 0f07a894..e362403a 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -2175,7 +2175,7 @@ size_change_error: + devname, s->size); + } + changed = 1; +- } else if (array.level != LEVEL_CONTAINER) { ++ } else if (!is_container(array.level)) { + s->size = get_component_size(fd)/2; + if (s->size == 0) + s->size = array.size; +@@ -2231,7 +2231,7 @@ size_change_error: + info.component_size = s->size*2; + info.new_level = s->level; + info.new_chunk = s->chunk * 1024; +- if (info.array.level == LEVEL_CONTAINER) { ++ if (is_container(info.array.level)) { + info.delta_disks = UnSet; + info.array.raid_disks = s->raiddisks; + } else if (s->raiddisks) +@@ -2344,7 +2344,7 @@ size_change_error: + printf("layout for %s set to %d\n", + devname, array.layout); + } +- } else if (array.level == LEVEL_CONTAINER) { ++ } else if (is_container(array.level)) { + /* This change is to be applied to every array in the + * container. This is only needed when the metadata imposes + * restraints of the various arrays in the container. +diff --git a/Incremental.c b/Incremental.c +index 4d0cd9d6..5a5f4c4c 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -244,7 +244,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + c->autof = ci->autof; + + name_to_use = info.name; +- if (name_to_use[0] == 0 && info.array.level == LEVEL_CONTAINER) { ++ if (name_to_use[0] == 0 && is_container(info.array.level)) { + name_to_use = info.text_version; + trustworthy = METADATA; + } +@@ -472,7 +472,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + + /* 7/ Is there enough devices to possibly start the array? */ + /* 7a/ if not, finish with success. */ +- if (info.array.level == LEVEL_CONTAINER) { ++ if (is_container(info.array.level)) { + char devnm[32]; + /* Try to assemble within the container */ + sysfs_uevent(sra, "change"); +diff --git a/mdadm.h b/mdadm.h +index 941a5f38..3673494e 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1924,3 +1924,17 @@ enum r0layout { + * This is true for native and DDF, IMSM allows 16. + */ + #define MD_NAME_MAX 32 ++ ++/** ++ * is_container() - check if @level is &LEVEL_CONTAINER ++ * @level: level value ++ * ++ * return: ++ * 1 if level is equal to &LEVEL_CONTAINER, 0 otherwise. ++ */ ++static inline int is_container(const int level) ++{ ++ if (level == LEVEL_CONTAINER) ++ return 1; ++ return 0; ++} +diff --git a/super-ddf.c b/super-ddf.c +index 949e7d15..9d1e3b94 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -3325,7 +3325,7 @@ validate_geometry_ddf_container(struct supertype *st, + int fd; + unsigned long long ldsize; + +- if (level != LEVEL_CONTAINER) ++ if (!is_container(level)) + return 0; + if (!dev) + return 1; +@@ -3371,7 +3371,7 @@ static int validate_geometry_ddf(struct supertype *st, + + if (level == LEVEL_NONE) + level = LEVEL_CONTAINER; +- if (level == LEVEL_CONTAINER) { ++ if (is_container(level)) { + /* Must be a fresh device to add to a container */ + return validate_geometry_ddf_container(st, level, raiddisks, + data_offset, dev, +@@ -3488,7 +3488,7 @@ static int validate_geometry_ddf_bvd(struct supertype *st, + struct dl *dl; + unsigned long long maxsize; + /* ddf/bvd supports lots of things, but not containers */ +- if (level == LEVEL_CONTAINER) { ++ if (is_container(level)) { + if (verbose) + pr_err("DDF cannot create a container within an container\n"); + return 0; +diff --git a/super-intel.c b/super-intel.c +index 4d82af3d..b0565610 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -6727,7 +6727,7 @@ static int validate_geometry_imsm_container(struct supertype *st, int level, + struct intel_super *super = NULL; + int rv = 0; + +- if (level != LEVEL_CONTAINER) ++ if (!is_container(level)) + return 0; + if (!dev) + return 1; +@@ -7692,7 +7692,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + * if given unused devices create a container + * if given given devices in a container create a member volume + */ +- if (level == LEVEL_CONTAINER) ++ if (is_container(level)) + /* Must be a fresh device to add to a container */ + return validate_geometry_imsm_container(st, level, raiddisks, + data_offset, dev, +diff --git a/super0.c b/super0.c +index 37f595ed..93876e2e 100644 +--- a/super0.c ++++ b/super0.c +@@ -1273,7 +1273,7 @@ static int validate_geometry0(struct supertype *st, int level, + if (get_linux_version() < 3001000) + tbmax = 2; + +- if (level == LEVEL_CONTAINER) { ++ if (is_container(level)) { + if (verbose) + pr_err("0.90 metadata does not support containers\n"); + return 0; +diff --git a/super1.c b/super1.c +index 58345e68..0b505a7e 100644 +--- a/super1.c ++++ b/super1.c +@@ -2830,7 +2830,7 @@ static int validate_geometry1(struct supertype *st, int level, + unsigned long long overhead; + int fd; + +- if (level == LEVEL_CONTAINER) { ++ if (is_container(level)) { + if (verbose) + pr_err("1.x metadata does not support containers\n"); + return 0; +diff --git a/sysfs.c b/sysfs.c +index 0d98a65f..ca1d888f 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -763,7 +763,7 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume) + + rv = sysfs_set_num(sra, sd, "offset", sd->data_offset); + rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2); +- if (sra->array.level != LEVEL_CONTAINER) { ++ if (!is_container(sra->array.level)) { + if (sra->consistency_policy == CONSISTENCY_POLICY_PPL) { + rv |= sysfs_set_num(sra, sd, "ppl_sector", sd->ppl_sector); + rv |= sysfs_set_num(sra, sd, "ppl_size", sd->ppl_size); +-- +2.38.1 + diff --git a/0061-Mdmonitor-Omit-non-md-devices.patch b/0061-Mdmonitor-Omit-non-md-devices.patch new file mode 100644 index 0000000..062ecdf --- /dev/null +++ b/0061-Mdmonitor-Omit-non-md-devices.patch @@ -0,0 +1,58 @@ +From 8b668d4aa3305af5963162b7499b128bd71f8f29 Mon Sep 17 00:00:00 2001 +From: Lukasz Florczak +Date: Thu, 22 Sep 2022 08:29:50 +0200 +Subject: [PATCH 61/83] Mdmonitor: Omit non-md devices + +Fix segfault commit [1] introduced check whether given device is +mddevice, but it happend to terminate Mdmonitor if at least one of given +devices didn't fulfill that condition. In result Mdmonitor service was +no longer started on boot (with --scan option) when config contained some +non-existent array entry. + +This commit introduces ommiting non-md devices so scan option can still +be used when config is wrong and allow Mdmonitor service to run on boot. + +Giving a list of devices to monitor containing non-existing or +non-md devices will result in monitoring only confirmed mddevices. + +[1] https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git/commit/?id=e702f392959d1c2ad2089e595b52235ed97b4e18 + +Signed-off-by: Lukasz Florczak +Signed-off-by: Jes Sorensen +--- + Monitor.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index b4e954c6..7d7dc4d2 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -185,10 +185,8 @@ int Monitor(struct mddev_dev *devlist, + continue; + if (strcasecmp(mdlist->devname, "") == 0) + continue; +- if (!is_mddev(mdlist->devname)) { +- free_statelist(statelist); +- return 1; +- } ++ if (!is_mddev(mdlist->devname)) ++ continue; + + st = xcalloc(1, sizeof *st); + snprintf(st->devname, MD_NAME_MAX + sizeof("/dev/md/"), +@@ -208,10 +206,8 @@ int Monitor(struct mddev_dev *devlist, + for (dv = devlist; dv; dv = dv->next) { + struct state *st; + +- if (!is_mddev(dv->devname)) { +- free_statelist(statelist); +- return 1; +- } ++ if (!is_mddev(dv->devname)) ++ continue; + + st = xcalloc(1, sizeof *st); + mdlist = conf_get_ident(dv->devname); +-- +2.38.1 + diff --git a/0062-Mdmonitor-Split-alert-into-separate-functions.patch b/0062-Mdmonitor-Split-alert-into-separate-functions.patch new file mode 100644 index 0000000..c7562e7 --- /dev/null +++ b/0062-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 62/83] 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 7d7dc4d2..0036e8cd 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.38.1 + diff --git a/0063-Monitor-block-if-monitor-modes-are-combined.patch b/0063-Monitor-block-if-monitor-modes-are-combined.patch new file mode 100644 index 0000000..d993d9d --- /dev/null +++ b/0063-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 63/83] 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 0036e8cd..188cb8be 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.38.1 + diff --git a/0064-Update-mdadm-Monitor-manual.patch b/0064-Update-mdadm-Monitor-manual.patch new file mode 100644 index 0000000..15f52e1 --- /dev/null +++ b/0064-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 64/83] 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 70c79d1e..64f71ed1 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.38.1 + diff --git a/0065-Grow-fix-possible-memory-leak.patch b/0065-Grow-fix-possible-memory-leak.patch new file mode 100644 index 0000000..07d9fb6 --- /dev/null +++ b/0065-Grow-fix-possible-memory-leak.patch @@ -0,0 +1,38 @@ +From 434b3b9bb96a76dc12f693b64cf23b581781e20b Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Tue, 20 Dec 2022 12:07:51 +0100 +Subject: [PATCH 65/83] Grow: fix possible memory leak. + +Signed-off-by: Blazej Kucman +Signed-off-by: Jes Sorensen +--- + Grow.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index e362403a..b73ec2ae 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -432,6 +432,7 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) + if (((disk.state & (1 << MD_DISK_WRITEMOSTLY)) == 0) && + (strcmp(s->bitmap_file, "clustered") == 0)) { + pr_err("%s disks marked write-mostly are not supported with clustered bitmap\n",devname); ++ free(mdi); + return 1; + } + fd2 = dev_open(dv, O_RDWR); +@@ -453,8 +454,10 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) + pr_err("failed to load super-block.\n"); + } + close(fd2); +- if (rv) ++ if (rv) { ++ free(mdi); + return 1; ++ } + } + if (offset_setable) { + st->ss->getinfo_super(st, mdi, NULL); +-- +2.38.1 + diff --git a/0066-mdadm-create-ident_init.patch b/0066-mdadm-create-ident_init.patch new file mode 100644 index 0000000..32d374b --- /dev/null +++ b/0066-mdadm-create-ident_init.patch @@ -0,0 +1,148 @@ +From 7fcbfd7c620e2dcd3b539d18e93cb503ee3a8a62 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Wed, 21 Dec 2022 12:50:17 +0100 +Subject: [PATCH 66/83] 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(-) + +diff --git a/config.c b/config.c +index dc1620c1..eeedd0c6 100644 +--- a/config.c ++++ b/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) { +diff --git a/mdadm.c b/mdadm.c +index 972adb52..74fdec31 100644 +--- a/mdadm.c ++++ b/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) { +diff --git a/mdadm.h b/mdadm.h +index 3673494e..23ffe977 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -33,8 +33,10 @@ extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); + # endif + #endif + ++#include + #include + #include ++#include + #include + #include + #include +@@ -1552,6 +1554,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); + ++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); +@@ -1779,8 +1783,7 @@ static inline sighandler_t signal_s(int sig, sighandler_t handler) + #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; +-- +2.38.1 + 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..faa7113 --- /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 67/83] 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 50a5e36d..bd8d50d2 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 20fcf719..b586679a 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 74fdec31..f5f505fe 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 23ffe977..51f1db2d 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.38.1 + 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..7c1c4bc --- /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 68/83] 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 b1d0e630..5a9ea316 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 b0565610..5f93f3d3 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.38.1 + 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..57386f5 --- /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 69/83] 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 b586679a..c59036f1 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 51f1db2d..31db25f5 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.38.1 + 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..7a6d213 --- /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 70/83] 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 9d1e3b94..309812df 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.38.1 + 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..f01c534 --- /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 71/83] 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 93876e2e..d9f5bff4 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.38.1 + 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..bd164b8 --- /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 72/83] 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 0b505a7e..b0a97016 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.38.1 + 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..6756297 --- /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 73/83] 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 5f93f3d3..85fb7f17 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.38.1 + 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..c9e186e --- /dev/null +++ b/0074-Change-update-to-enum-in-update_super-and-update_sub.patch @@ -0,0 +1,424 @@ +From 03312b5240438ffc3b63114bdc87e911222f01e5 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:35:22 +0100 +Subject: [PATCH 74/83] 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 8b0af0c9..dba910cd 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 9574a3cc..c9605a60 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 b73ec2ae..82d5d2ea 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 5a9ea316..87b8aa0c 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 c59036f1..b586679a 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 31db25f5..5dc94390 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 85fb7f17..1f5f6eda 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 d9f5bff4..a7c5f813 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 b0a97016..f7020320 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.38.1 + 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..d4b20ff --- /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 75/83] 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 82d5d2ea..8f5cf07d 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 5a5f4c4c..ff3548c0 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 87b8aa0c..594e3d2c 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 f5f505fe..d06e2820 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 5dc94390..924f4b63 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.38.1 + 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..a18f8d1 --- /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 76/83] 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 dba910cd..49804941 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 d06e2820..57e8e6fa 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 924f4b63..13f8b4cb 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.38.1 + diff --git a/0077-mdmon-fix-segfault.patch b/0077-mdmon-fix-segfault.patch new file mode 100644 index 0000000..980ceda --- /dev/null +++ b/0077-mdmon-fix-segfault.patch @@ -0,0 +1,86 @@ +From 9b429fc0a4ffd7028b3b336589d38e32fb9045dc Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:46:21 +0100 +Subject: [PATCH 77/83] mdmon: fix segfault + +Mdmon crashes if stat2devnm returns null. +Use open_mddev to check if device is mddevice and get name using +fd2devnm. +Refactor container name handling. + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + Makefile | 2 +- + mdmon.c | 26 ++++++++++++-------------- + 2 files changed, 13 insertions(+), 15 deletions(-) + +diff --git a/Makefile b/Makefile +index ec1f99ed..5eac1a4e 100644 +--- a/Makefile ++++ b/Makefile +@@ -160,7 +160,7 @@ SRCS = $(patsubst %.o,%.c,$(OBJS)) + + INCL = mdadm.h part.h bitmap.h + +-MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o \ ++MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o config.o mapfile.o mdopen.o\ + policy.o lib.o \ + Kill.o sg_io.o dlink.o ReadMe.o super-intel.o \ + super-mbr.o super-gpt.o \ +diff --git a/mdmon.c b/mdmon.c +index e9d035eb..ecf52dc8 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -363,14 +363,14 @@ int main(int argc, char *argv[]) + } + + if (all == 0 && container_name == NULL) { +- if (argv[optind]) +- container_name = argv[optind]; ++ if (argv[optind]) { ++ container_name = get_md_name(argv[optind]); ++ if (!container_name) ++ container_name = argv[optind]; ++ } + } + +- if (container_name == NULL) +- usage(); +- +- if (argc - optind > 1) ++ if (container_name == NULL || argc - optind > 1) + usage(); + + if (strcmp(container_name, "/proc/mdstat") == 0) +@@ -402,21 +402,19 @@ int main(int argc, char *argv[]) + free_mdstat(mdstat); + + return status; +- } else if (strncmp(container_name, "md", 2) == 0) { +- int id = devnm2devid(container_name); +- if (id) +- devnm = container_name; + } else { +- struct stat st; ++ int mdfd = open_mddev(container_name, 1); + +- if (stat(container_name, &st) == 0) +- devnm = xstrdup(stat2devnm(&st)); ++ if (mdfd < 0) ++ return 1; ++ devnm = fd2devnm(mdfd); ++ close(mdfd); + } + + if (!devnm) { + pr_err("%s is not a valid md device name\n", + container_name); +- exit(1); ++ return 1; + } + return mdmon(devnm, dofork && do_fork(), takeover); + } +-- +2.38.1 + diff --git a/0078-util-remove-obsolete-code-from-get_md_name.patch b/0078-util-remove-obsolete-code-from-get_md_name.patch new file mode 100644 index 0000000..b371d39 --- /dev/null +++ b/0078-util-remove-obsolete-code-from-get_md_name.patch @@ -0,0 +1,116 @@ +From b938519e7719c992dae2d61c796c45fe49e6b71b Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Jan 2023 09:46:22 +0100 +Subject: [PATCH 78/83] util: remove obsolete code from get_md_name + +get_md_name() is used only with mdstat entries. +Remove dead code and simplyfy function. + +Remove redundadnt checks from mdmon.c + +Signed-off-by: Mateusz Kusiak +Signed-off-by: Jes Sorensen +--- + mdmon.c | 8 +++----- + util.c | 51 +++++++++++++++++---------------------------------- + 2 files changed, 20 insertions(+), 39 deletions(-) + +diff --git a/mdmon.c b/mdmon.c +index ecf52dc8..60ba3182 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -366,7 +366,7 @@ int main(int argc, char *argv[]) + if (argv[optind]) { + container_name = get_md_name(argv[optind]); + if (!container_name) +- container_name = argv[optind]; ++ return 1; + } + } + +@@ -403,11 +403,9 @@ int main(int argc, char *argv[]) + + return status; + } else { +- int mdfd = open_mddev(container_name, 1); +- +- if (mdfd < 0) +- return 1; ++ int mdfd = open_mddev(container_name, 0); + devnm = fd2devnm(mdfd); ++ + close(mdfd); + } + +diff --git a/util.c b/util.c +index 26ffdcea..9cd89fa4 100644 +--- a/util.c ++++ b/util.c +@@ -968,47 +968,30 @@ dev_t devnm2devid(char *devnm) + return 0; + } + ++/** ++ * get_md_name() - Get main dev node of the md device. ++ * @devnm: Md device name or path. ++ * ++ * Function checks if the full name was passed and returns md name ++ * if it is the MD device. ++ * ++ * Return: Main dev node of the md device or NULL if not found. ++ */ + char *get_md_name(char *devnm) + { +- /* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */ +- /* if dev < 0, want /dev/md/d%d or find mdp in /proc/devices ... */ +- +- static char devname[50]; ++ static char devname[NAME_MAX]; + struct stat stb; +- dev_t rdev = devnm2devid(devnm); +- char *dn; + +- if (rdev == 0) +- return 0; +- if (strncmp(devnm, "md_", 3) == 0) { +- snprintf(devname, sizeof(devname), "/dev/md/%s", +- devnm + 3); +- if (stat(devname, &stb) == 0 && +- (S_IFMT&stb.st_mode) == S_IFBLK && (stb.st_rdev == rdev)) +- return devname; +- } +- snprintf(devname, sizeof(devname), "/dev/%s", devnm); +- if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK && +- (stb.st_rdev == rdev)) +- return devname; ++ if (strncmp(devnm, "/dev/", 5) == 0) ++ snprintf(devname, sizeof(devname), "%s", devnm); ++ else ++ snprintf(devname, sizeof(devname), "/dev/%s", devnm); + +- snprintf(devname, sizeof(devname), "/dev/md/%s", devnm+2); +- if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK && +- (stb.st_rdev == rdev)) ++ if (!is_mddev(devname)) ++ return NULL; ++ if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK) + return devname; + +- dn = map_dev(major(rdev), minor(rdev), 0); +- if (dn) +- return dn; +- snprintf(devname, sizeof(devname), "/dev/.tmp.%s", devnm); +- if (mknod(devname, S_IFBLK | 0600, rdev) == -1) +- if (errno != EEXIST) +- return NULL; +- +- if (stat(devname, &stb) == 0 && (S_IFMT&stb.st_mode) == S_IFBLK && +- (stb.st_rdev == rdev)) +- return devname; +- unlink(devname); + return NULL; + } + +-- +2.38.1 + diff --git a/0079-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch b/0079-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch new file mode 100644 index 0000000..f888a09 --- /dev/null +++ b/0079-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 79/83] 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 39b4344b..d4a7f0a5 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.38.1 + diff --git a/0080-Manage-do-not-check-array-state-when-drive-is-remove.patch b/0080-Manage-do-not-check-array-state-when-drive-is-remove.patch new file mode 100644 index 0000000..e2c1179 --- /dev/null +++ b/0080-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 80/83] 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 594e3d2c..4d6e54b1 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.38.1 + diff --git a/0081-incremental-manage-do-not-verify-if-remove-is-safe.patch b/0081-incremental-manage-do-not-verify-if-remove-is-safe.patch new file mode 100644 index 0000000..4e0169c --- /dev/null +++ b/0081-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 81/83] 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 ff3548c0..09b94b9f 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 4d6e54b1..6184d3f7 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.38.1 + diff --git a/0082-super-intel-make-freesize-not-required-for-chunk-siz.patch b/0082-super-intel-make-freesize-not-required-for-chunk-siz.patch new file mode 100644 index 0000000..0035c89 --- /dev/null +++ b/0082-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 82/83] 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 1f5f6eda..89fac626 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.38.1 + diff --git a/0083-manage-move-comment-with-function-description.patch b/0083-manage-move-comment-with-function-description.patch new file mode 100644 index 0000000..091854f --- /dev/null +++ b/0083-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 83/83] 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 6184d3f7..fde6aba3 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.38.1 + diff --git a/mdadm-udev.patch b/mdadm-udev.patch new file mode 100644 index 0000000..a9d4d93 --- /dev/null +++ b/mdadm-udev.patch @@ -0,0 +1,26 @@ +--- mdadm/udev-md-raid-assembly.rules.orig 2023-01-06 16:37:03.780756100 +0800 ++++ mdadm/udev-md-raid-assembly.rules 2023-01-06 17:04:09.536159980 +0800 +@@ -5,6 +5,9 @@ + ENV{ANACONDA}=="?*", GOTO="md_inc_end" + # assemble md arrays + ++# Also don't process disks that are slated to be a multipath device ++ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_inc_end" ++ + SUBSYSTEM!="block", GOTO="md_inc_end" + + # skip non-initialized devices +@@ -33,6 +36,13 @@ + + LABEL="md_inc" + ++# Make sure we don't handle dm devices when some limits are set. ++# And linux_raid_member only be set when change/remove event happen. ++# So we don't need to consider add event here. ++KERNEL=="dm-*", ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="md_inc_end" ++KERNEL=="dm-*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="md_inc_end" ++KERNEL=="dm-*", ENV{DM_SUSPENDED}=="1", GOTO="md_inc_end" ++ + # Bare disks are ready when add event happens, the raid can be assembled. + ACTION=="change", KERNEL!="dm-*|md*", GOTO="md_inc_end" + diff --git a/mdadm.rules b/mdadm.rules deleted file mode 100644 index 682e9e8..0000000 --- a/mdadm.rules +++ /dev/null @@ -1,67 +0,0 @@ -# This file causes block devices with Linux RAID (mdadm) signatures to -# automatically cause mdadm to be run. -# See udev(8) for syntax - -# Don't process any events if anaconda is running as anaconda brings up -# raid devices manually -ENV{ANACONDA}=="?*", GOTO="md_end" - -# Also don't process disks that are slated to be a multipath device -ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_end" - -# We process add events on block devices (since they are ready as soon as -# they are added to the system), but we must process change events as well -# on any dm devices (like LUKS partitions or LVM logical volumes) and on -# md devices because both of these first get added, then get brought live -# and trigger a change event. The reason we don't process change events -# on bare hard disks is because if you stop all arrays on a disk, then -# run fdisk on the disk to change the partitions, when fdisk exits it -# triggers a change event, and we want to wait until all the fdisks on -# all member disks are done before we do anything. Unfortunately, we have -# no way of knowing that, so we just have to let those arrays be brought -# up manually after fdisk has been run on all of the disks. - -# First, process all add events (md and dm devices will not really do -# anything here, just regular disks, and this also won't get any imsm -# array members either) -SUBSYSTEM=="block", ACTION=="add", ENV{ID_FS_TYPE}=="linux_raid_member", \ - IMPORT{program}="/sbin/mdadm -I $env{DEVNAME} --export $devnode --offroot $${DEVLINKS}" -SUBSYSTEM=="block", ACTION=="add", ENV{ID_FS_TYPE}=="linux_raid_member", \ - ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer" -SUBSYSTEM=="block", ACTION=="remove", ENV{ID_PATH}=="?*", \ - ENV{ID_FS_TYPE}=="linux_raid_member", \ - RUN+="/sbin/mdadm -If $name --path $env{ID_PATH}" -SUBSYSTEM=="block", ACTION=="remove", ENV{ID_PATH}!="?*", \ - ENV{ID_FS_TYPE}=="linux_raid_member", \ - RUN+="/sbin/mdadm -If $name" - -# Next, check to make sure the BIOS raid stuff wasn't turned off via cmdline -IMPORT{cmdline}="noiswmd" -IMPORT{cmdline}="nodmraid" -ENV{noiswmd}=="?*", GOTO="md_imsm_inc_end" -ENV{nodmraid}=="?*", GOTO="md_imsm_inc_end" -SUBSYSTEM=="block", ACTION=="add", ENV{ID_FS_TYPE}=="isw_raid_member", \ - RUN+="/sbin/mdadm -I $env{DEVNAME}" -SUBSYSTEM=="block", ACTION=="remove", ENV{ID_PATH}=="?*", \ - ENV{ID_FS_TYPE}=="isw_raid_member", \ - RUN+="/sbin/mdadm -If $name --path $env{ID_PATH}" -SUBSYSTEM=="block", ACTION=="remove", ENV{ID_PATH}!="?*", \ - ENV{ID_FS_TYPE}=="isw_raid_member", \ - RUN+="/sbin/mdadm -If $name" -LABEL="md_imsm_inc_end" - -# Next make sure that this isn't a dm device we should skip for some reason -ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="dm_change_end" -ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="dm_change_end" -ENV{DM_SUSPENDED}=="1", GOTO="dm_change_end" -KERNEL=="dm-*", SUBSYSTEM=="block", ENV{ID_FS_TYPE}=="linux_raid_member", \ - ACTION=="change", RUN+="/sbin/mdadm -I $env{DEVNAME}" -LABEL="dm_change_end" - -# Finally catch any nested md raid arrays. If we brought up an md raid -# array that's part of another md raid array, it won't be ready to be used -# until the change event that occurs when it becomes live -KERNEL=="md*", SUBSYSTEM=="block", ENV{ID_FS_TYPE}=="linux_raid_member", \ - ACTION=="change", RUN+="/sbin/mdadm -I $env{DEVNAME}" - -LABEL="md_end" diff --git a/mdadm.spec b/mdadm.spec index 06886b6..e03694c 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,26 +1,108 @@ Name: mdadm Version: 4.2 -Release: 3%{?dist} +Release: 4%{?dist} Summary: The mdadm program controls Linux md devices (software RAID arrays) URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ License: GPLv2+ Source: http://www.kernel.org/pub/linux/utils/raid/mdadm/%{name}-%{version}%{?subversion:-%{subversion}}.tar.xz Source1: raid-check -Source2: mdadm.rules -Source3: mdadm-raid-check-sysconfig -Source4: mdmonitor.service -Source5: mdadm.conf -Source6: mdadm_event.conf -Source7: raid-check.timer -Source8: raid-check.service - -# Build without -Werror. -Patch00: disable-Werror.patch +Source2: mdadm-raid-check-sysconfig +Source3: mdmonitor.service +Source4: mdadm.conf +Source5: mdadm_event.conf +Source6: raid-check.timer +Source7: raid-check.service + +Patch000: 0001-Unify-error-message.patch +Patch001: 0002-mdadm-Fix-double-free.patch +Patch002: 0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch +Patch003: 0004-udev-adapt-rules-to-systemd-v247.patch +Patch004: 0005-Replace-error-prone-signal-with-sigaction.patch +Patch005: 0006-mdadm-Respect-config-file-location-in-man.patch +Patch006: 0007-mdadm-Update-ReadMe.patch +Patch007: 0008-mdadm-Update-config-man-regarding-default-files-and-.patch +Patch008: 0009-mdadm-Update-config-manual.patch +Patch009: 0010-Create-Build-use-default_layout.patch +Patch010: 0011-mdadm-add-map_num_s.patch +# patch0012 is deleted because of needing KillMode=none +Patch011: 0013-mdmon-Stop-parsing-duplicate-options.patch +Patch012: 0014-Grow-block-n-on-external-volumes.patch +Patch013: 0015-Incremental-Fix-possible-memory-and-resource-leaks.patch +Patch014: 0016-Mdmonitor-Fix-segfault.patch +Patch015: 0017-Mdmonitor-Improve-logging-method.patch +Patch016: 0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch +Patch017: 0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch +Patch018: 0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch +Patch019: 0021-util-replace-ioctl-use-with-function.patch +Patch020: 0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch +Patch021: 0023-imsm-introduce-get_disk_slot_in_dev.patch +Patch022: 0024-imsm-use-same-slot-across-container.patch +Patch023: 0025-imsm-block-changing-slots-during-creation.patch +Patch024: 0026-mdadm-block-update-ppl-for-non-raid456-levels.patch +Patch025: 0027-mdadm-Fix-array-size-mismatch-after-grow.patch +Patch026: 0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch +Patch027: 0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch +Patch028: 0030-Monitor-use-snprintf-to-fill-device-name.patch +Patch029: 0031-Makefile-Don-t-build-static-build-with-everything-an.patch +Patch030: 0032-DDF-Cleanup-validate_geometry_ddf_container.patch +Patch031: 0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch +Patch032: 0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch +Patch033: 0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch +Patch034: 0036-mdadm-Fix-mdadm-r-remove-option-regression.patch +Patch035: 0037-mdadm-Fix-optional-write-behind-parameter.patch +Patch036: 0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch +Patch037: 0039-tests-fix-raid0-tests-for-0.90-metadata.patch +Patch038: 0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch +Patch039: 0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch +Patch040: 0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch +Patch041: 0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch +Patch042: 0044-tests-Add-broken-files-for-all-broken-tests.patch +Patch043: 0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch +Patch044: 0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch +Patch045: 0047-tests-add-test-for-names.patch +Patch046: 0048-mdadm-remove-symlink-option.patch +Patch047: 0049-mdadm-move-data_offset-to-struct-shape.patch +Patch048: 0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch +Patch049: 0051-Grow-Split-Grow_reshape-into-helper-function.patch +Patch050: 0052-Assemble-check-if-device-is-container-before-schedul.patch +Patch051: 0053-super1-report-truncated-device.patch +Patch052: 0054-mdadm-Correct-typos-punctuation-and-grammar-in-man.patch +Patch053: 0055-Manage-Block-unsafe-member-failing.patch +Patch054: 0056-Monitor-Fix-statelist-memory-leaks.patch +Patch055: 0057-mdadm-added-support-for-Intel-Alderlake-RST-on-VMD-p.patch +Patch056: 0058-mdadm-Add-Documentation-entries-to-systemd-services.patch +Patch057: 0059-ReadMe-fix-command-line-help.patch +Patch058: 0060-mdadm-replace-container-level-checking-with-inline.patch +Patch059: 0061-Mdmonitor-Omit-non-md-devices.patch +Patch060: 0062-Mdmonitor-Split-alert-into-separate-functions.patch +Patch061: 0063-Monitor-block-if-monitor-modes-are-combined.patch +Patch062: 0064-Update-mdadm-Monitor-manual.patch +Patch063: 0065-Grow-fix-possible-memory-leak.patch +Patch064: 0066-mdadm-create-ident_init.patch +Patch065: 0067-mdadm-Add-option-validation-for-update-subarray.patch +Patch066: 0068-Fix-update-subarray-on-active-volume.patch +Patch067: 0069-Add-code-specific-update-options-to-enum.patch +Patch068: 0070-super-ddf-Remove-update_super_ddf.patch +Patch069: 0071-super0-refactor-the-code-for-enum.patch +Patch070: 0072-super1-refactor-the-code-for-enum.patch +Patch071: 0073-super-intel-refactor-the-code-for-enum.patch +Patch072: 0074-Change-update-to-enum-in-update_super-and-update_sub.patch +Patch073: 0075-Manage-Incremental-code-refactor-string-to-enum.patch +Patch074: 0076-Change-char-to-enum-in-context-update-refactor-code.patch +Patch075: 0077-mdmon-fix-segfault.patch +Patch076: 0078-util-remove-obsolete-code-from-get_md_name.patch +Patch077: 0079-mdadm-udev-Don-t-handle-change-event-on-raw-devices.patch +Patch078: 0080-Manage-do-not-check-array-state-when-drive-is-remove.patch +Patch079: 0081-incremental-manage-do-not-verify-if-remove-is-safe.patch +Patch080: 0082-super-intel-make-freesize-not-required-for-chunk-siz.patch +Patch081: 0083-manage-move-comment-with-function-description.patch # Fedora customization patches -Patch97: mdadm-3.3-udev.patch +Patch97: mdadm-udev.patch Patch98: mdadm-2.5.2-static.patch +# Build without -Werror. +Patch99: disable-Werror.patch BuildRequires: make BuildRequires: systemd-rpm-macros binutils-devel gcc systemd-devel @@ -45,25 +127,24 @@ make %{?_smp_mflags} CXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" SYSCONFDIR %install make DESTDIR=%{buildroot} MANDIR=%{_mandir} BINDIR=%{_sbindir} SYSTEMD_DIR=%{_unitdir} UDEVDIR=/usr/lib/udev/ install install-systemd install -Dp -m 755 %{SOURCE1} %{buildroot}%{_sbindir}/raid-check -install -Dp -m 644 %{SOURCE2} %{buildroot}%{_udevrulesdir}/65-md-incremental.rules -install -Dp -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/sysconfig/raid-check +install -Dp -m 644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/raid-check mkdir -p -m 710 %{buildroot}/run/mdadm # systemd mkdir -p %{buildroot}%{_unitdir} -install -m644 %{SOURCE4} %{buildroot}%{_unitdir} +install -m644 %{SOURCE3} %{buildroot}%{_unitdir} +install -m644 %{SOURCE6} %{buildroot}%{_unitdir} install -m644 %{SOURCE7} %{buildroot}%{_unitdir} -install -m644 %{SOURCE8} %{buildroot}%{_unitdir} # tmpfile mkdir -p %{buildroot}%{_tmpfilesdir} -install -m 0644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/%{name}.conf +install -m 0644 %{SOURCE4} %{buildroot}%{_tmpfilesdir}/%{name}.conf mkdir -p %{buildroot}%{_localstatedir}/run/ install -d -m 0710 %{buildroot}/run/%{name}/ # abrt mkdir -p %{buildroot}/etc/libreport/events.d -install -m644 %{SOURCE6} %{buildroot}/etc/libreport/events.d +install -m644 %{SOURCE5} %{buildroot}/etc/libreport/events.d %post %systemd_post mdmonitor.service raid-check.timer @@ -89,6 +170,10 @@ install -m644 %{SOURCE6} %{buildroot}/etc/libreport/events.d /etc/libreport/events.d/* %changelog +* Mon Jan 30 2023 Xiao Ni - 4.2-4 +- Update to latest upstream for f38 +- Resolves bz#2163711 + * Thu Jan 19 2023 Fedora Release Engineering - 4.2-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild