From a89d4425fda735c585fea349ea18df01c38d6f4f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 15 Nov 2022 01:54:39 -0500 Subject: [PATCH] import mdadm-4.2-6.el9 --- ...dadm-fix-coredump-of-mdadm-monitor-r.patch | 38 - SOURCES/0001-Unify-error-message.patch | 47 + SOURCES/0002-mdadm-Fix-double-free.patch | 33 + ...-r0-grow-size-error-message-and-upda.patch | 83 + ...004-udev-adapt-rules-to-systemd-v247.patch | 67 + ...ce-error-prone-signal-with-sigaction.patch | 252 +++ ...-Respect-config-file-location-in-man.patch | 1533 +++++++++++++++++ SOURCES/0007-mdadm-Update-ReadMe.patch | 48 + ...fig-man-regarding-default-files-and-.patch | 203 +++ SOURCES/0009-mdadm-Update-config-manual.patch | 45 + ...0010-Create-Build-use-default_layout.patch | 153 ++ SOURCES/0011-mdadm-add-map_num_s.patch | 382 ++++ ...mdmon-Stop-parsing-duplicate-options.patch | 122 ++ ...014-Grow-block-n-on-external-volumes.patch | 41 + ...x-possible-memory-and-resource-leaks.patch | 90 + SOURCES/0016-Mdmonitor-Fix-segfault.patch | 98 ++ ...017-Mdmonitor-Improve-logging-method.patch | 61 + ...LL-ptr-dereferences-and-memory-leaks.patch | 73 + ...ibility-for-get_imsm_dev-to-return-N.patch | 301 ++++ ...dadm-fix-coredump-of-mdadm-monitor-r.patch | 85 + ...util-replace-ioctl-use-with-function.patch | 31 + ...tore-commit-45a87c2f31335-to-fix-clu.patch | 110 ++ ...-imsm-introduce-get_disk_slot_in_dev.patch | 122 ++ ...-imsm-use-same-slot-across-container.patch | 252 +++ ...block-changing-slots-during-creation.patch | 122 ++ ...ck-update-ppl-for-non-raid456-levels.patch | 177 ++ ...m-Fix-array-size-mismatch-after-grow.patch | 30 + ...-dead-code-in-imsm_fix_size_mismatch.patch | 34 + ...ame-as-char-array-instead-of-pointer.patch | 40 + ...tor-use-snprintf-to-fill-device-name.patch | 133 ++ ...uild-static-build-with-everything-an.patch | 42 + ...anup-validate_geometry_ddf_container.patch | 141 ++ ...nter-dereference-in-validate_geometr.patch | 49 + ...se-after-close-bug-by-closing-after-.patch | 85 + ...gfault-when-calling-NULL-get_bad_blo.patch | 36 + ...Fix-mdadm-r-remove-option-regression.patch | 78 + ...-Fix-optional-write-behind-parameter.patch | 42 + ...d-a-test-that-validates-raid0-with-l.patch | 38 + ...ts-fix-raid0-tests-for-0.90-metadata.patch | 99 ++ ...etadata-avoid-passing-chunk-size-to-.patch | 39 + ...ow-clear-the-superblock-at-every-ite.patch | 31 + ...Add-a-mode-to-repeat-specified-tests.patch | 88 + ...Mark-and-ignore-broken-test-failures.patch | 120 ++ ...dd-broken-files-for-all-broken-tests.patch | 447 +++++ ...place-obsolete-usleep-with-nanosleep.patch | 316 ++++ ...-Run-udevadm-settle-before-setting-r.patch | 36 + SOURCES/0047-tests-add-test-for-names.patch | 119 ++ .../0048-mdadm-remove-symlink-option.patch | 176 ++ ...adm-move-data_offset-to-struct-shape.patch | 232 +++ ...en-md-device-for-CREATE-and-ASSEMBLE.patch | 162 ++ ...it-Grow_reshape-into-helper-function.patch | 231 +++ ...f-device-is-container-before-schedul.patch | 36 + SOURCES/mdadm.rules | 2 + SPECS/mdadm.spec | 70 +- 54 files changed, 7481 insertions(+), 40 deletions(-) delete mode 100644 SOURCES/0001-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch create mode 100644 SOURCES/0001-Unify-error-message.patch create mode 100644 SOURCES/0002-mdadm-Fix-double-free.patch create mode 100644 SOURCES/0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch create mode 100644 SOURCES/0004-udev-adapt-rules-to-systemd-v247.patch create mode 100644 SOURCES/0005-Replace-error-prone-signal-with-sigaction.patch create mode 100644 SOURCES/0006-mdadm-Respect-config-file-location-in-man.patch create mode 100644 SOURCES/0007-mdadm-Update-ReadMe.patch create mode 100644 SOURCES/0008-mdadm-Update-config-man-regarding-default-files-and-.patch create mode 100644 SOURCES/0009-mdadm-Update-config-manual.patch create mode 100644 SOURCES/0010-Create-Build-use-default_layout.patch create mode 100644 SOURCES/0011-mdadm-add-map_num_s.patch create mode 100644 SOURCES/0013-mdmon-Stop-parsing-duplicate-options.patch create mode 100644 SOURCES/0014-Grow-block-n-on-external-volumes.patch create mode 100644 SOURCES/0015-Incremental-Fix-possible-memory-and-resource-leaks.patch create mode 100644 SOURCES/0016-Mdmonitor-Fix-segfault.patch create mode 100644 SOURCES/0017-Mdmonitor-Improve-logging-method.patch create mode 100644 SOURCES/0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch create mode 100644 SOURCES/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch create mode 100644 SOURCES/0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch create mode 100644 SOURCES/0021-util-replace-ioctl-use-with-function.patch create mode 100644 SOURCES/0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch create mode 100644 SOURCES/0023-imsm-introduce-get_disk_slot_in_dev.patch create mode 100644 SOURCES/0024-imsm-use-same-slot-across-container.patch create mode 100644 SOURCES/0025-imsm-block-changing-slots-during-creation.patch create mode 100644 SOURCES/0026-mdadm-block-update-ppl-for-non-raid456-levels.patch create mode 100644 SOURCES/0027-mdadm-Fix-array-size-mismatch-after-grow.patch create mode 100644 SOURCES/0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch create mode 100644 SOURCES/0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch create mode 100644 SOURCES/0030-Monitor-use-snprintf-to-fill-device-name.patch create mode 100644 SOURCES/0031-Makefile-Don-t-build-static-build-with-everything-an.patch create mode 100644 SOURCES/0032-DDF-Cleanup-validate_geometry_ddf_container.patch create mode 100644 SOURCES/0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch create mode 100644 SOURCES/0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch create mode 100644 SOURCES/0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch create mode 100644 SOURCES/0036-mdadm-Fix-mdadm-r-remove-option-regression.patch create mode 100644 SOURCES/0037-mdadm-Fix-optional-write-behind-parameter.patch create mode 100644 SOURCES/0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch create mode 100644 SOURCES/0039-tests-fix-raid0-tests-for-0.90-metadata.patch create mode 100644 SOURCES/0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch create mode 100644 SOURCES/0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch create mode 100644 SOURCES/0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch create mode 100644 SOURCES/0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch create mode 100644 SOURCES/0044-tests-Add-broken-files-for-all-broken-tests.patch create mode 100644 SOURCES/0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch create mode 100644 SOURCES/0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch create mode 100644 SOURCES/0047-tests-add-test-for-names.patch create mode 100644 SOURCES/0048-mdadm-remove-symlink-option.patch create mode 100644 SOURCES/0049-mdadm-move-data_offset-to-struct-shape.patch create mode 100644 SOURCES/0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch create mode 100644 SOURCES/0051-Grow-Split-Grow_reshape-into-helper-function.patch create mode 100644 SOURCES/0052-Assemble-check-if-device-is-container-before-schedul.patch diff --git a/SOURCES/0001-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch b/SOURCES/0001-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch deleted file mode 100644 index 08b6900..0000000 --- a/SOURCES/0001-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 7e92ef334af165a5e50b33ddff98e18f1c8a18d0 Mon Sep 17 00:00:00 2001 -From: Xiao Ni -Date: Thu, 24 Feb 2022 11:37:34 +0800 -Subject: [PATCH 1/1] Revert "mdadm: fix coredump of mdadm --monitor -r" - -This reverts commit 546047688e1c64638f462147c755b58119cabdc8. - -This is a rhel ony patch. We have sent patch to upstream. But -it hasn't been merged. We will remove this patch once upstream -merges our patch. - -Signed-off-by: Xiao Ni ---- - ReadMe.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/ReadMe.c b/ReadMe.c -index 81399765..ee457a54 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.31.1 - diff --git a/SOURCES/0001-Unify-error-message.patch b/SOURCES/0001-Unify-error-message.patch new file mode 100644 index 0000000..b4ceb95 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0002-mdadm-Fix-double-free.patch b/SOURCES/0002-mdadm-Fix-double-free.patch new file mode 100644 index 0000000..d3e1db1 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch b/SOURCES/0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch new file mode 100644 index 0000000..a36866b --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0004-udev-adapt-rules-to-systemd-v247.patch b/SOURCES/0004-udev-adapt-rules-to-systemd-v247.patch new file mode 100644 index 0000000..c1bcb29 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0005-Replace-error-prone-signal-with-sigaction.patch b/SOURCES/0005-Replace-error-prone-signal-with-sigaction.patch new file mode 100644 index 0000000..34552bb --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0006-mdadm-Respect-config-file-location-in-man.patch b/SOURCES/0006-mdadm-Respect-config-file-location-in-man.patch new file mode 100644 index 0000000..c5885b6 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0007-mdadm-Update-ReadMe.patch b/SOURCES/0007-mdadm-Update-ReadMe.patch new file mode 100644 index 0000000..90ce556 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0008-mdadm-Update-config-man-regarding-default-files-and-.patch b/SOURCES/0008-mdadm-Update-config-man-regarding-default-files-and-.patch new file mode 100644 index 0000000..8375fd9 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0009-mdadm-Update-config-manual.patch b/SOURCES/0009-mdadm-Update-config-manual.patch new file mode 100644 index 0000000..313b2c9 --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0010-Create-Build-use-default_layout.patch b/SOURCES/0010-Create-Build-use-default_layout.patch new file mode 100644 index 0000000..a15ae3e --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0011-mdadm-add-map_num_s.patch b/SOURCES/0011-mdadm-add-map_num_s.patch new file mode 100644 index 0000000..196d47d --- /dev/null +++ b/SOURCES/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/12] 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.31.1 + diff --git a/SOURCES/0013-mdmon-Stop-parsing-duplicate-options.patch b/SOURCES/0013-mdmon-Stop-parsing-duplicate-options.patch new file mode 100644 index 0000000..fed1740 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0014-Grow-block-n-on-external-volumes.patch b/SOURCES/0014-Grow-block-n-on-external-volumes.patch new file mode 100644 index 0000000..25ffac1 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0015-Incremental-Fix-possible-memory-and-resource-leaks.patch b/SOURCES/0015-Incremental-Fix-possible-memory-and-resource-leaks.patch new file mode 100644 index 0000000..42fa773 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0016-Mdmonitor-Fix-segfault.patch b/SOURCES/0016-Mdmonitor-Fix-segfault.patch new file mode 100644 index 0000000..05c7fb4 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0017-Mdmonitor-Improve-logging-method.patch b/SOURCES/0017-Mdmonitor-Improve-logging-method.patch new file mode 100644 index 0000000..f00b8b3 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch b/SOURCES/0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch new file mode 100644 index 0000000..a5e9351 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch b/SOURCES/0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch new file mode 100644 index 0000000..87b6db6 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch b/SOURCES/0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch new file mode 100644 index 0000000..107ac28 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0021-util-replace-ioctl-use-with-function.patch b/SOURCES/0021-util-replace-ioctl-use-with-function.patch new file mode 100644 index 0000000..3833674 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch b/SOURCES/0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch new file mode 100644 index 0000000..360ec6e --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0023-imsm-introduce-get_disk_slot_in_dev.patch b/SOURCES/0023-imsm-introduce-get_disk_slot_in_dev.patch new file mode 100644 index 0000000..d979cc5 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0024-imsm-use-same-slot-across-container.patch b/SOURCES/0024-imsm-use-same-slot-across-container.patch new file mode 100644 index 0000000..31348e4 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0025-imsm-block-changing-slots-during-creation.patch b/SOURCES/0025-imsm-block-changing-slots-during-creation.patch new file mode 100644 index 0000000..6de11e1 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0026-mdadm-block-update-ppl-for-non-raid456-levels.patch b/SOURCES/0026-mdadm-block-update-ppl-for-non-raid456-levels.patch new file mode 100644 index 0000000..5e9e87f --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0027-mdadm-Fix-array-size-mismatch-after-grow.patch b/SOURCES/0027-mdadm-Fix-array-size-mismatch-after-grow.patch new file mode 100644 index 0000000..cd3e93a --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch b/SOURCES/0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch new file mode 100644 index 0000000..4fde0c9 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch b/SOURCES/0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch new file mode 100644 index 0000000..c7d871d --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0030-Monitor-use-snprintf-to-fill-device-name.patch b/SOURCES/0030-Monitor-use-snprintf-to-fill-device-name.patch new file mode 100644 index 0000000..83543cb --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0031-Makefile-Don-t-build-static-build-with-everything-an.patch b/SOURCES/0031-Makefile-Don-t-build-static-build-with-everything-an.patch new file mode 100644 index 0000000..8922281 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0032-DDF-Cleanup-validate_geometry_ddf_container.patch b/SOURCES/0032-DDF-Cleanup-validate_geometry_ddf_container.patch new file mode 100644 index 0000000..99e2e6b --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch b/SOURCES/0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch new file mode 100644 index 0000000..3be71e7 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch b/SOURCES/0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch new file mode 100644 index 0000000..849a475 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch b/SOURCES/0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch new file mode 100644 index 0000000..c19c1e4 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0036-mdadm-Fix-mdadm-r-remove-option-regression.patch b/SOURCES/0036-mdadm-Fix-mdadm-r-remove-option-regression.patch new file mode 100644 index 0000000..8bcf0c9 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0037-mdadm-Fix-optional-write-behind-parameter.patch b/SOURCES/0037-mdadm-Fix-optional-write-behind-parameter.patch new file mode 100644 index 0000000..c10712a --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch b/SOURCES/0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch new file mode 100644 index 0000000..e934bed --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0039-tests-fix-raid0-tests-for-0.90-metadata.patch b/SOURCES/0039-tests-fix-raid0-tests-for-0.90-metadata.patch new file mode 100644 index 0000000..ace5fbe --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch b/SOURCES/0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch new file mode 100644 index 0000000..76a7586 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch b/SOURCES/0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch new file mode 100644 index 0000000..00c9367 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch b/SOURCES/0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch new file mode 100644 index 0000000..288ca2c --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch b/SOURCES/0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch new file mode 100644 index 0000000..5585173 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0044-tests-Add-broken-files-for-all-broken-tests.patch b/SOURCES/0044-tests-Add-broken-files-for-all-broken-tests.patch new file mode 100644 index 0000000..643bf3f --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch b/SOURCES/0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch new file mode 100644 index 0000000..44b6d7c --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch b/SOURCES/0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch new file mode 100644 index 0000000..34f81dd --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0047-tests-add-test-for-names.patch b/SOURCES/0047-tests-add-test-for-names.patch new file mode 100644 index 0000000..b1dee23 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0048-mdadm-remove-symlink-option.patch b/SOURCES/0048-mdadm-remove-symlink-option.patch new file mode 100644 index 0000000..13f67ad --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0049-mdadm-move-data_offset-to-struct-shape.patch b/SOURCES/0049-mdadm-move-data_offset-to-struct-shape.patch new file mode 100644 index 0000000..9613654 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch b/SOURCES/0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch new file mode 100644 index 0000000..a28efa4 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0051-Grow-Split-Grow_reshape-into-helper-function.patch b/SOURCES/0051-Grow-Split-Grow_reshape-into-helper-function.patch new file mode 100644 index 0000000..2b5aaaf --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/0052-Assemble-check-if-device-is-container-before-schedul.patch b/SOURCES/0052-Assemble-check-if-device-is-container-before-schedul.patch new file mode 100644 index 0000000..4c4c323 --- /dev/null +++ b/SOURCES/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/52] 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.31.1 + diff --git a/SOURCES/mdadm.rules b/SOURCES/mdadm.rules index 682e9e8..74646b3 100644 --- a/SOURCES/mdadm.rules +++ b/SOURCES/mdadm.rules @@ -42,6 +42,8 @@ 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=="add", ENV{ID_FS_TYPE}=="ddf_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}" diff --git a/SPECS/mdadm.spec b/SPECS/mdadm.spec index 14f63f6..53140f9 100644 --- a/SPECS/mdadm.spec +++ b/SPECS/mdadm.spec @@ -1,7 +1,7 @@ Name: mdadm Version: 4.2 # extraversion is used to define rhel internal version -%define extraversion 2 +%define extraversion 6 Release: %{extraversion}%{?dist} Summary: The mdadm program controls Linux md devices (software RAID arrays) URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ @@ -19,7 +19,57 @@ Source8: raid-check.service # Build without -Werror. Patch00: disable-Werror.patch -Patch01: 0001-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch +Patch01: 0001-Unify-error-message.patch +Patch02: 0002-mdadm-Fix-double-free.patch +Patch03: 0003-Grow_reshape-Add-r0-grow-size-error-message-and-upda.patch +Patch04: 0004-udev-adapt-rules-to-systemd-v247.patch +Patch05: 0005-Replace-error-prone-signal-with-sigaction.patch +Patch06: 0006-mdadm-Respect-config-file-location-in-man.patch +Patch07: 0007-mdadm-Update-ReadMe.patch +Patch08: 0008-mdadm-Update-config-man-regarding-default-files-and-.patch +Patch09: 0009-mdadm-Update-config-manual.patch +Patch10: 0010-Create-Build-use-default_layout.patch +Patch11: 0011-mdadm-add-map_num_s.patch +Patch12: 0013-mdmon-Stop-parsing-duplicate-options.patch +Patch13: 0014-Grow-block-n-on-external-volumes.patch +Patch14: 0015-Incremental-Fix-possible-memory-and-resource-leaks.patch +Patch15: 0016-Mdmonitor-Fix-segfault.patch +Patch16: 0017-Mdmonitor-Improve-logging-method.patch +Patch17: 0018-Fix-possible-NULL-ptr-dereferences-and-memory-leaks.patch +Patch18: 0019-imsm-Remove-possibility-for-get_imsm_dev-to-return-N.patch +Patch19: 0020-Revert-mdadm-fix-coredump-of-mdadm-monitor-r.patch +Patch20: 0021-util-replace-ioctl-use-with-function.patch +Patch21: 0022-mdadm-super1-restore-commit-45a87c2f31335-to-fix-clu.patch +Patch22: 0023-imsm-introduce-get_disk_slot_in_dev.patch +Patch23: 0024-imsm-use-same-slot-across-container.patch +Patch24: 0025-imsm-block-changing-slots-during-creation.patch +Patch25: 0026-mdadm-block-update-ppl-for-non-raid456-levels.patch +Patch26: 0027-mdadm-Fix-array-size-mismatch-after-grow.patch +Patch27: 0028-mdadm-Remove-dead-code-in-imsm_fix_size_mismatch.patch +Patch28: 0029-Monitor-use-devname-as-char-array-instead-of-pointer.patch +Patch29: 0030-Monitor-use-snprintf-to-fill-device-name.patch +Patch30: 0031-Makefile-Don-t-build-static-build-with-everything-an.patch +Patch31: 0032-DDF-Cleanup-validate_geometry_ddf_container.patch +Patch32: 0033-DDF-Fix-NULL-pointer-dereference-in-validate_geometr.patch +Patch33: 0034-mdadm-Grow-Fix-use-after-close-bug-by-closing-after-.patch +Patch34: 0035-monitor-Avoid-segfault-when-calling-NULL-get_bad_blo.patch +Patch35: 0036-mdadm-Fix-mdadm-r-remove-option-regression.patch +Patch36: 0037-mdadm-Fix-optional-write-behind-parameter.patch +Patch37: 0038-tests-00raid0-add-a-test-that-validates-raid0-with-l.patch +Patch38: 0039-tests-fix-raid0-tests-for-0.90-metadata.patch +Patch39: 0040-tests-04update-metadata-avoid-passing-chunk-size-to-.patch +Patch40: 0041-tests-02lineargrow-clear-the-superblock-at-every-ite.patch +Patch41: 0042-mdadm-test-Add-a-mode-to-repeat-specified-tests.patch +Patch42: 0043-mdadm-test-Mark-and-ignore-broken-test-failures.patch +Patch43: 0044-tests-Add-broken-files-for-all-broken-tests.patch +Patch44: 0045-mdadm-Replace-obsolete-usleep-with-nanosleep.patch +Patch45: 0046-tests-00readonly-Run-udevadm-settle-before-setting-r.patch +Patch46: 0047-tests-add-test-for-names.patch +Patch47: 0048-mdadm-remove-symlink-option.patch +Patch48: 0049-mdadm-move-data_offset-to-struct-shape.patch +Patch49: 0050-mdadm-Don-t-open-md-device-for-CREATE-and-ASSEMBLE.patch +Patch50: 0051-Grow-Split-Grow_reshape-into-helper-function.patch +Patch51: 0052-Assemble-check-if-device-is-container-before-schedul.patch # Fedora customization patches Patch97: mdadm-3.3-udev.patch @@ -93,6 +143,22 @@ install -m644 %{SOURCE6} %{buildroot}/etc/libreport/events.d /etc/libreport/events.d/* %changelog +* Mon Sep 5 2022 Xiao Ni - 4.2-6 +- Add ddf auto-assemble in mdadm udev rule +- Resolves rhbz#2120690 + +* Thu Aug 25 2022 Xiao Ni - 4.2-5 +- Update to latest upstream +- Resolves rhbz#2092330 + +* Wed Aug 10 2022 Xiao Ni - 4.2-4 +- Add Killmode=none for mdmon systemd service again +- Resolves rhbz#2109042 + +* Mon May 30 2022 Xiao Ni - 4.2-3 +- Update mdadm to latest upstream +- Resolves rhbz#2052029, rhbz#1974184 + * Thu Feb 24 2022 Xiao Ni - 4.2-2 - mdadm re-add fault/removed disk failed - Resolves rhbz#2047567