From aa7b8fe9764b1bb67cb3223e32a4194020ee7b4f Mon Sep 17 00:00:00 2001 From: Xiao Ni Date: Tue, 28 Oct 2025 14:06:20 +0800 Subject: [PATCH] Update to latest upstream Resolves: RHEL-100004, RHEL-107084 Signed-off-by: Xiao Ni --- 0038-Update-tests.yml.patch | 30 + 0039-Update-tests.yml.patch | 28 + 0040-Update-run_mdadm_tests.sh.patch | 33 + 0041-tests-support-second-runner.patch | 65 ++ ...valid-minor-number-in-md-device-name.patch | 41 + 0043-mdadm-use-standard-libc-nftw.patch | 58 ++ ...ch => 0044-mdadm-fix-building-errors.patch | 29 +- ...dd-attribute-nonstring-for-signature.patch | 34 + ...ore-time-to-wait-sync-thread-to-reap.patch | 39 + ...ts-mark-10ddf-fail-two-spares-broken.patch | 38 + ...dm-tests-mark-09imsm-assemble-broken.patch | 52 ++ ...ark-10ddf-fail-readd-readonly-broken.patch | 44 + ...tim-al-ize-write-indent-write-intent.patch | 31 + ...dadm-enable-sync-file-for-udev-rules.patch | 210 +++++ 0052-mdadm-remove-POSIX-check.patch | 219 +++++ ...e-Don-t-stop-array-after-creating-it.patch | 30 + ...ILFROM-to-set-sendmail-envelope-send.patch | 47 ++ 0055-mdadm-use-lseek-consistently.patch | 749 ++++++++++++++++++ ...ps-bump-actions-checkout-from-4-to-5.patch | 68 ++ ...use-Type-simple-for-mdcheck-services.patch | 48 ++ ...set-sync_action-to-idle-when-stopped.patch | 95 +++ ...re-signals-are-processed-immediately.patch | 30 + ...check_continue.timer-before-mdcheck_.patch | 50 ++ ...or-scan-with-relative-ARRAY-devnames.patch | 39 + ...e-enable-mdadm-monitor-.-for-dev-mdX.patch | 108 +++ ...ix-meaing-typo-in-mdadm.conf-example.patch | 28 + 0064-Update-raid6check-man-page.patch | 121 +++ 0065-udev-Fix-memleak.patch | 41 + ...-order-of-free_super_xxx-to-avoid-me.patch | 60 ++ ...-Fix-memory-leak-issue-in-check_raid.patch | 28 + ...Fix-memory-leak-issue-in-Manage_stop.patch | 29 + ...-memory-leak-issue-in-load_ddf_local.patch | 29 + ...l-wait-a-while-before-removing-a-mem.patch | 67 ++ 0071-mdadm-sysfs-close-fd-before-return.patch | 39 + 0072-Update-README.md.patch | 28 + ...ate-array-with-sync-del-gendisk-mode.patch | 120 +++ ...ssemble-alloc-superblock-in-Assemble.patch | 210 +++++ mdadm-use-standard-libc-nftw.patch | 53 -- mdadm.spec | 45 +- 39 files changed, 3044 insertions(+), 69 deletions(-) create mode 100644 0038-Update-tests.yml.patch create mode 100644 0039-Update-tests.yml.patch create mode 100644 0040-Update-run_mdadm_tests.sh.patch create mode 100644 0041-tests-support-second-runner.patch create mode 100644 0042-mdadm-allow-any-valid-minor-number-in-md-device-name.patch create mode 100644 0043-mdadm-use-standard-libc-nftw.patch rename mdadm-fix-building-errors.patch => 0044-mdadm-fix-building-errors.patch (69%) create mode 100644 0045-mdadm-add-attribute-nonstring-for-signature.patch create mode 100644 0046-mdadm-give-more-time-to-wait-sync-thread-to-reap.patch create mode 100644 0047-mdadm-tests-mark-10ddf-fail-two-spares-broken.patch create mode 100644 0048-mdadm-tests-mark-09imsm-assemble-broken.patch create mode 100644 0049-mdadm-tests-mark-10ddf-fail-readd-readonly-broken.patch create mode 100644 0050-optim-al-ize-write-indent-write-intent.patch create mode 100644 0051-mdadm-enable-sync-file-for-udev-rules.patch create mode 100644 0052-mdadm-remove-POSIX-check.patch create mode 100644 0053-mdadm-assemble-Don-t-stop-array-after-creating-it.patch create mode 100644 0054-mdmonitor-use-MAILFROM-to-set-sendmail-envelope-send.patch create mode 100644 0055-mdadm-use-lseek-consistently.patch create mode 100644 0056-build-deps-bump-actions-checkout-from-4-to-5.patch create mode 100644 0057-systemd-use-Type-simple-for-mdcheck-services.patch create mode 100644 0058-mdcheck-reset-sync_action-to-idle-when-stopped.patch create mode 100644 0059-mdcheck-make-sure-signals-are-processed-immediately.patch create mode 100644 0060-systemd-start-mdcheck_continue.timer-before-mdcheck_.patch create mode 100644 0061-Fix-monitor-scan-with-relative-ARRAY-devnames.patch create mode 100644 0062-Re-enable-mdadm-monitor-.-for-dev-mdX.patch create mode 100644 0063-Fix-meaing-typo-in-mdadm.conf-example.patch create mode 100644 0064-Update-raid6check-man-page.patch create mode 100644 0065-udev-Fix-memleak.patch create mode 100644 0066-mdadm-modify-the-order-of-free_super_xxx-to-avoid-me.patch create mode 100644 0067-mdadm-Fix-memory-leak-issue-in-check_raid.patch create mode 100644 0068-mdadm-Fix-memory-leak-issue-in-Manage_stop.patch create mode 100644 0069-mdadm-Fix-memory-leak-issue-in-load_ddf_local.patch create mode 100644 0070-mdadm-Incremental-wait-a-while-before-removing-a-mem.patch create mode 100644 0071-mdadm-sysfs-close-fd-before-return.patch create mode 100644 0072-Update-README.md.patch create mode 100644 0073-mdadm-Create-array-with-sync-del-gendisk-mode.patch create mode 100644 0074-mdadm-Assemble-alloc-superblock-in-Assemble.patch delete mode 100644 mdadm-use-standard-libc-nftw.patch diff --git a/0038-Update-tests.yml.patch b/0038-Update-tests.yml.patch new file mode 100644 index 0000000..a461db9 --- /dev/null +++ b/0038-Update-tests.yml.patch @@ -0,0 +1,30 @@ +From 32ab389711c718e1690e6f63c21adbd8b84b010a Mon Sep 17 00:00:00 2001 +From: Paul Luse +Date: Wed, 30 Apr 2025 14:04:14 -0700 +Subject: [PATCH 38/74] Update tests.yml + +Signed-off-by: Paul Luse +--- + .github/workflows/tests.yml | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml +index 2556fccfb99b..73082fd2ef15 100644 +--- a/.github/workflows/tests.yml ++++ b/.github/workflows/tests.yml +@@ -37,9 +37,9 @@ jobs: + vagrant status + vagrant up + sleep 2 +- vagrant ssh -c "uname -r" +- echo "FYI vagrant uname command finished with exit code: $?" +- ++ vagrant ssh -c "sudo timedatectl set-timezone UTC && \ ++ sudo systemctl restart chronyd && sudo chronyc -a makestep && sleep 1 && uname -r" ++ echo "FYI vagrant time command finished with exit code: $?" + - name: 'Run tests' + id: testing + continue-on-error: true +-- +2.50.1 + diff --git a/0039-Update-tests.yml.patch b/0039-Update-tests.yml.patch new file mode 100644 index 0000000..b6c1653 --- /dev/null +++ b/0039-Update-tests.yml.patch @@ -0,0 +1,28 @@ +From 02b7cacefe080c7c0f55b942b26bfcae9297587b Mon Sep 17 00:00:00 2001 +From: Paul Luse +Date: Wed, 30 Apr 2025 17:45:32 -0700 +Subject: [PATCH 39/74] Update tests.yml + +Signed-off-by: Paul Luse +--- + .github/workflows/tests.yml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml +index 73082fd2ef15..ddba632dc13c 100644 +--- a/.github/workflows/tests.yml ++++ b/.github/workflows/tests.yml +@@ -31,7 +31,9 @@ jobs: + - name: 'Prepare machine' + run: | + cd .. +- vagrant snapshot restore clean_vm_v42 ++ # to upgrade the VMs to Fed42, comment the next line out and uncomment the one below that. ++ vagrant snapshot restore clean_vm_v1 ++ # vagrant snapshot restore clean_vm_v42 + echo "FYI vagrant restore command finished with exit code: $?" + sleep 2 + vagrant status +-- +2.50.1 + diff --git a/0040-Update-run_mdadm_tests.sh.patch b/0040-Update-run_mdadm_tests.sh.patch new file mode 100644 index 0000000..c478f2d --- /dev/null +++ b/0040-Update-run_mdadm_tests.sh.patch @@ -0,0 +1,33 @@ +From e05b13f97db18dfa98814fcebd9d1b58b9fcb8cd Mon Sep 17 00:00:00 2001 +From: Paul Luse +Date: Thu, 1 May 2025 12:18:17 -0700 +Subject: [PATCH 40/74] Update run_mdadm_tests.sh + +Signed-off-by: Paul Luse +--- + .github/tools/run_mdadm_tests.sh | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/.github/tools/run_mdadm_tests.sh b/.github/tools/run_mdadm_tests.sh +index 22d89a8c371a..8c287bde860e 100755 +--- a/.github/tools/run_mdadm_tests.sh ++++ b/.github/tools/run_mdadm_tests.sh +@@ -2,7 +2,15 @@ + + sudo make clean + sudo make -j$(nproc) ++if [ $? -ne 0 ]; then ++ echo "Error: make command failed." ++ exit 1 ++fi + sudo make install ++if [ $? -ne 0 ]; then ++ echo "Error: make install command failed." ++ exit 1 ++fi + sudo mdadm -Ss + sudo ./test setup + +-- +2.50.1 + diff --git a/0041-tests-support-second-runner.patch b/0041-tests-support-second-runner.patch new file mode 100644 index 0000000..91f9a0e --- /dev/null +++ b/0041-tests-support-second-runner.patch @@ -0,0 +1,65 @@ +From 4aa30f1beafc1fed844a0f335e196400adeb1840 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 11 Apr 2025 14:36:12 +0200 +Subject: [PATCH 41/74] tests: support second runner + +Second runner has different VM name. Honor that when coping +and removing logs. + +Signed-off-by: Mariusz Tkaczyk +--- + .github/workflows/tests.yml | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml +index ddba632dc13c..a07e320b03c4 100644 +--- a/.github/workflows/tests.yml ++++ b/.github/workflows/tests.yml +@@ -42,6 +42,10 @@ jobs: + vagrant ssh -c "sudo timedatectl set-timezone UTC && \ + sudo systemctl restart chronyd && sudo chronyc -a makestep && sleep 1 && uname -r" + echo "FYI vagrant time command finished with exit code: $?" ++ ++ - name: Export RUNNER_NAME ++ run: echo "RUNNER_NAME=$RUNNER_NAME" >> $GITHUB_ENV ++ + - name: 'Run tests' + id: testing + continue-on-error: true +@@ -55,18 +59,30 @@ jobs: + cd .. + vagrant ssh -c "sudo mkdir -p /home/vagrant/host/logs && sudo mv /var/tmp/*.log /home/vagrant/host/logs" + +- - name: "Save artifacts" +- if: ${{ steps.testing.outcome == 'failure' }} ++ - name: "Save artifacts inspur5" ++ if: ${{ steps.testing.outcome == 'failure' && env.RUNNER_NAME == 'inspur5' }} + uses: actions/upload-artifact@v4 + with: + name: "Logs from failed tests" + path: /home/ci/actions-runner/_work/mdadm/logs/*.log + ++ - name: "Save artifacts inspur5-2" ++ if: ${{ steps.testing.outcome == 'failure' && env.RUNNER_NAME == 'inspur5-2'}} ++ uses: actions/upload-artifact@v4 ++ with: ++ name: "Logs from failed tests" ++ path: /home/ci/actions-runner-2/_work/mdadm/logs/*.log ++ + - name: "Clean logs" + if: ${{ steps.testing.outcome == 'failure' }} + run: | + cd .. +- sudo rm -rf /home/ci/actions-runner/_work/mdadm/logs/*.log ++ ++ if [ "$RUNNER_NAME" == "inspur5" ]; then ++ sudo rm /home/ci/actions-runner/_work/mdadm/logs/*.log ++ else ++ sudo rm /home/ci/actions-runner-2/_work/mdadm/logs/*.log ++ fi + + - name: "Set failed" + if: ${{ steps.testing.outcome == 'failure' }} +-- +2.50.1 + diff --git a/0042-mdadm-allow-any-valid-minor-number-in-md-device-name.patch b/0042-mdadm-allow-any-valid-minor-number-in-md-device-name.patch new file mode 100644 index 0000000..60ba6a0 --- /dev/null +++ b/0042-mdadm-allow-any-valid-minor-number-in-md-device-name.patch @@ -0,0 +1,41 @@ +From e270c8f99e90cf89e0c1a0534547e7b4bf285041 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 30 Apr 2025 21:18:36 +0200 +Subject: [PATCH 42/74] mdadm: allow any valid minor number in md device name + +Since 25aa732 ("mdadm: numbered names verification"), it is not possible +any more to create arrays /dev/md${N} with N >= 127. The limit has later +been increased to 1024, which is also artificial. The error message printed +by mdadm is misleading, as the problem is not POSIX compatibility here. + + # mdadm -C -v /dev/md9999 --name=foo -l1 -n2 /dev/loop0 /dev/loop1 + mdadm: Value "/dev/md9999" cannot be set as devname. Reason: Not POSIX compatible. + +Given that mdadm creates an array with minor number ${N} if the argument is +/dev/md${N}, the natural limit for the number is the highest minor number +available, which is (1 << MINORBITS) with MINORBITS=20 on Linux. + +Fixes: 25aa732 ("mdadm: numbered names verification") +Fixes: f786072 ("mdadm: Increase number limit in md device name to 1024.") +Signed-off-by: Martin Wilck +--- + util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/util.c b/util.c +index 9fe2d2276712..0f77521149f8 100644 +--- a/util.c ++++ b/util.c +@@ -972,7 +972,8 @@ static bool is_devname_numbered(const char *devname, const char *pref, const int + if (parse_num(&val, devname + pref_len) != 0) + return false; + +- if (val > 1024) ++ /* Allow any number that represents a valid minor number */ ++ if (val >= (1 << 20)) + return false; + + return true; +-- +2.50.1 + diff --git a/0043-mdadm-use-standard-libc-nftw.patch b/0043-mdadm-use-standard-libc-nftw.patch new file mode 100644 index 0000000..94a9758 --- /dev/null +++ b/0043-mdadm-use-standard-libc-nftw.patch @@ -0,0 +1,58 @@ +From e549ac6ab2ce5e7ec182310f8f5f2e41c6ac9233 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 7 May 2025 18:06:59 +0800 +Subject: [PATCH 43/74] mdadm: use standard libc nftw + +commit bd648e3bec3d ("mdadm: Remove klibc and uclibc support") removes +macro HAVE_NFTW/HAVE_FTW and uses libc header ftw.h. But it leaves the +codes in lib.c which let mdadm command call nftw defined in lib.c. It +needs to remove these codes. + +The bug can be reproduced by: +mdadm -CR /dev/md0 --level raid5 --metadata=1.1 --chunk=32 --raid-disks 3 +--size 10000 /dev/loop1 /dev/loop2 /dev/loop3 +mdadm /dev/md0 --grow --chunk=64 +mdadm: /dev/md0: cannot open component -unknown- + +Fixes: bd648e3bec3d ("mdadm: Remove klibc and uclibc support") +Signed-off-by: Xiao Ni +--- + lib.c | 22 ---------------------- + 1 file changed, 22 deletions(-) + +diff --git a/lib.c b/lib.c +index f36ae03a3fa0..eb6cc1194cab 100644 +--- a/lib.c ++++ b/lib.c +@@ -245,28 +245,6 @@ int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s) + return 0; + } + +-#ifndef HAVE_NFTW +-#ifdef HAVE_FTW +-int add_dev_1(const char *name, const struct stat *stb, int flag) +-{ +- return add_dev(name, stb, flag, NULL); +-} +-int nftw(const char *path, +- int (*han)(const char *name, const struct stat *stb, +- int flag, struct FTW *s), int nopenfd, int flags) +-{ +- return ftw(path, add_dev_1, nopenfd); +-} +-#else +-int nftw(const char *path, +- int (*han)(const char *name, const struct stat *stb, +- int flag, struct FTW *s), int nopenfd, int flags) +-{ +- return 0; +-} +-#endif /* HAVE_FTW */ +-#endif /* HAVE_NFTW */ +- + /* + * Find a block device with the right major/minor number. + * If we find multiple names, choose the shortest. +-- +2.50.1 + diff --git a/mdadm-fix-building-errors.patch b/0044-mdadm-fix-building-errors.patch similarity index 69% rename from mdadm-fix-building-errors.patch rename to 0044-mdadm-fix-building-errors.patch index 03025ad..8184685 100644 --- a/mdadm-fix-building-errors.patch +++ b/0044-mdadm-fix-building-errors.patch @@ -1,18 +1,20 @@ -From 46940fbca6df3ddffa71541e459a277d79584fc0 Mon Sep 17 00:00:00 2001 +From f815615ebf74a71064ba480ba773ef4bf98b53b0 Mon Sep 17 00:00:00 2001 From: Xiao Ni -Date: Wed, 30 Apr 2025 06:47:08 -0400 -Subject: [PATCH 1/1] mdadm: fix building errors +Date: Wed, 7 May 2025 18:26:08 +0800 +Subject: [PATCH 44/74] mdadm: fix building errors -This is a rhel-only patch and this patch will be sent to upstream. +Some building errors are found in ppc64le platform: +format '%llu' expects argument of type 'long long unsigned int', but +argument 3 has type 'long unsigned int' [-Werror=format=] Signed-off-by: Xiao Ni --- super-ddf.c | 9 +++++---- - super-intel.c | 2 +- - 2 files changed, 6 insertions(+), 5 deletions(-) + super-intel.c | 3 ++- + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/super-ddf.c b/super-ddf.c -index 6e7db924..285d3b8b 100644 +index 6e7db924d2b1..dda8b7fedd64 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -1606,9 +1606,9 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid) @@ -32,7 +34,7 @@ index 6e7db924..285d3b8b 100644 be32_to_cpu(pd->refnum)); printf("%8lluK ", - be64_to_cpu(pd->config_size)>>1); -+ (unsigned long long)be64_to_cpu(pd->config_size)>>1); ++ (unsigned long long)be64_to_cpu(pd->config_size)>>1); for (dl = sb->dlist; dl ; dl = dl->next) { if (be32_eq(dl->disk.refnum, pd->refnum)) { char *dv = map_dev(dl->major, dl->minor, 0); @@ -42,23 +44,24 @@ index 6e7db924..285d3b8b 100644 __u64 cfs, t; - cfs = min(dl->size - 32*1024*2ULL, be64_to_cpu(dl->primary_lba)); + cfs = min((unsigned long long)dl->size - 32*1024*2ULL, -+ (unsigned long long)be64_to_cpu(dl->primary_lba)); ++ (unsigned long long)(be64_to_cpu(dl->primary_lba))); t = be64_to_cpu(dl->secondary_lba); if (t != ~(__u64)0) cfs = min(cfs, t); diff --git a/super-intel.c b/super-intel.c -index b7b030a2..caa583d8 100644 +index b7b030a20432..4fbbc98d915c 100644 --- a/super-intel.c +++ b/super-intel.c -@@ -2325,7 +2325,7 @@ static void export_examine_super_imsm(struct supertype *st) +@@ -2325,7 +2325,8 @@ static void export_examine_super_imsm(struct supertype *st) printf("MD_LEVEL=container\n"); printf("MD_UUID=%s\n", nbuf+5); printf("MD_DEVICES=%u\n", mpb->num_disks); - printf("MD_CREATION_TIME=%llu\n", __le64_to_cpu(mpb->creation_time)); -+ printf("MD_CREATION_TIME=%llu\n", (unsigned long long)__le64_to_cpu(mpb->creation_time)); ++ printf("MD_CREATION_TIME=%llu\n", ++ (unsigned long long)__le64_to_cpu(mpb->creation_time)); } static void detail_super_imsm(struct supertype *st, char *homehost, -- -2.41.0 +2.50.1 diff --git a/0045-mdadm-add-attribute-nonstring-for-signature.patch b/0045-mdadm-add-attribute-nonstring-for-signature.patch new file mode 100644 index 0000000..ad63dc8 --- /dev/null +++ b/0045-mdadm-add-attribute-nonstring-for-signature.patch @@ -0,0 +1,34 @@ +From a83ecaf17c75734aead366c6de71b6dd42a4a63d Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 7 May 2025 18:34:20 +0800 +Subject: [PATCH 45/74] mdadm: add attribute nonstring for signature +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It reports building error in f42: +error: initializer-string for array of ‘unsigned char’ truncates NULL +terminator but destination lacks ‘nonstring’ attribute (5 chars into 4 +available) [-Werror=unterminated-string-initialization] + +Signed-off-by: Xiao Ni +--- + platform-intel.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/platform-intel.h b/platform-intel.h +index 63d416826118..f92a9a11c3a0 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -24,7 +24,7 @@ + + /* The IMSM Capability (IMSM AHCI and ISCU OROM/EFI variable) Version Table definition */ + struct imsm_orom { +- __u8 signature[4]; ++ __u8 signature[4] __attribute__((nonstring)); + #define IMSM_OROM_SIGNATURE "$VER" + #define IMSM_NVME_OROM_COMPAT_SIGNATURE "$NVM" + #define IMSM_VMD_OROM_COMPAT_SIGNATURE "$VMD" +-- +2.50.1 + diff --git a/0046-mdadm-give-more-time-to-wait-sync-thread-to-reap.patch b/0046-mdadm-give-more-time-to-wait-sync-thread-to-reap.patch new file mode 100644 index 0000000..3b1f964 --- /dev/null +++ b/0046-mdadm-give-more-time-to-wait-sync-thread-to-reap.patch @@ -0,0 +1,39 @@ +From 1640b5c37bb870a9ae36d6e72e09dd8a47aeac43 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Thu, 8 May 2025 11:45:50 +0800 +Subject: [PATCH 46/74] mdadm: give more time to wait sync thread to reap + +01r5fail case reports error sometimes: +++ '[' -n '2248 / 35840' ']' +++ die 'resync or recovery is happening!' +++ echo -e '\n\tERROR: resync or recovery is happening! \n' + + ERROR: resync or recovery is happening! + +sync thread is reapped in md_thread. So we need to give more time to +wait sync thread to reap. + +Signed-off-by: Xiao Ni +--- + tests/func.sh | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tests/func.sh b/tests/func.sh +index e42c7d56d9a2..19ad8b3211e3 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -357,7 +357,10 @@ check() { + done + ;; + nosync ) +- sleep 0.5 ++ # sync thread is reapped in md_thread, give it more time to wait sync thread ++ # to reap. Before this change, it gives 0.5s which is too small. Sometimes ++ # the sync thread can't be reapped and error happens ++ sleep 3 + # Since 4.2 we delay the close of recovery until there has been a chance for + # spares to be activated. That means that a recovery that finds nothing + # to do can still take a little longer than expected. +-- +2.50.1 + diff --git a/0047-mdadm-tests-mark-10ddf-fail-two-spares-broken.patch b/0047-mdadm-tests-mark-10ddf-fail-two-spares-broken.patch new file mode 100644 index 0000000..9694ea6 --- /dev/null +++ b/0047-mdadm-tests-mark-10ddf-fail-two-spares-broken.patch @@ -0,0 +1,38 @@ +From 882c8fda76772573acf2000a850106a09413d2e9 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Thu, 8 May 2025 12:45:32 +0800 +Subject: [PATCH 47/74] mdadm/tests: mark 10ddf-fail-two-spares broken + +Sometimes 10ddf-fail-two-spares fail because: +++ grep -q 'state\[1\] : Optimal, Consistent' /tmp/mdtest-5k3MzO +++ echo ERROR: /dev/md/vol1 should be optimal in meta data +ERROR: /dev/md/vol1 should be optimal in meta data + +Mark this as broken. + +Signed-off-by: Xiao Ni +--- + tests/10ddf-fail-two-spares.broken | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 tests/10ddf-fail-two-spares.broken + +diff --git a/tests/10ddf-fail-two-spares.broken b/tests/10ddf-fail-two-spares.broken +new file mode 100644 +index 000000000000..d0158c042f22 +--- /dev/null ++++ b/tests/10ddf-fail-two-spares.broken +@@ -0,0 +1,11 @@ ++Sometimes ++ ++++ grep -q 'state\[0\] : Optimal, Consistent' /tmp/mdtest-5k3MzO ++++ grep -q 'state\[1\] : Optimal, Consistent' /tmp/mdtest-5k3MzO ++++ echo ERROR: /dev/md/vol1 should be optimal in meta data ++ERROR: /dev/md/vol1 should be optimal in meta data ++ ++if ! grep -q 'state\[1\] : Optimal, Consistent' $tmp; then ++ echo ERROR: $member1 should be optimal in meta data ++ ret=1 ++fi +-- +2.50.1 + diff --git a/0048-mdadm-tests-mark-09imsm-assemble-broken.patch b/0048-mdadm-tests-mark-09imsm-assemble-broken.patch new file mode 100644 index 0000000..c44602f --- /dev/null +++ b/0048-mdadm-tests-mark-09imsm-assemble-broken.patch @@ -0,0 +1,52 @@ +From 5d4c31e8c1ed273636aa9d9f36d8b6f0ebc9713e Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Thu, 8 May 2025 17:02:13 +0800 +Subject: [PATCH 48/74] mdadm/tests: mark 09imsm-assemble broken + +09imsm-assemble fails sometimes. So mark it as broken. + +Signed-off-by: Xiao Ni +--- + tests/09imsm-assemble.broken | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + create mode 100644 tests/09imsm-assemble.broken + +diff --git a/tests/09imsm-assemble.broken b/tests/09imsm-assemble.broken +new file mode 100644 +index 000000000000..a139042c99a0 +--- /dev/null ++++ b/tests/09imsm-assemble.broken +@@ -0,0 +1,30 @@ ++Sometimes ++ ++Sometimes it fails: ++++ /usr/sbin/mdadm --remove /dev/md/container /dev/loop2 ++++ rv=1 ++++ case $* in ++++ cat /var/tmp/stderr ++mdadm: /dev/loop2 is still in use, cannot remove. ++++ return 1 ++++ sleep 2 ++++ (( i++ )) ++++ (( i<=ret )) ++++ '[' 0 -ne 1 ']' ++++ echo '/dev/loop2 removal from /dev/md/container should have succeeded' ++/dev/loop2 removal from /dev/md/container should have succeeded ++ ++Sometimes it fails: ++++ imsm_check_hold /dev/md/container /dev/loop1 ++++ mdadm --remove /dev/md/container /dev/loop1 ++++ rm -f /var/tmp/stderr ++++ case $* in ++++ case $* in ++++ /usr/sbin/mdadm --remove /dev/md/container /dev/loop1 ++++ rv=0 ++++ case $* in ++++ cat /var/tmp/stderr ++mdadm: hot removed /dev/loop1 from /dev/md/container ++++ return 0 ++++ echo '/dev/loop1 removal from /dev/md/container should have been blocked' ++/dev/loop1 removal from /dev/md/container should have been blocked +-- +2.50.1 + diff --git a/0049-mdadm-tests-mark-10ddf-fail-readd-readonly-broken.patch b/0049-mdadm-tests-mark-10ddf-fail-readd-readonly-broken.patch new file mode 100644 index 0000000..eda39f8 --- /dev/null +++ b/0049-mdadm-tests-mark-10ddf-fail-readd-readonly-broken.patch @@ -0,0 +1,44 @@ +From 7ecd1fe2d709ad84fbed29b1594f02fad52592cc Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Thu, 8 May 2025 17:56:08 +0800 +Subject: [PATCH 49/74] mdadm/tests: mark 10ddf-fail-readd-readonly broken + +10ddf-fail-readd-readonly fails sometimes. Mark this case broken. + +Signed-off-by: Xiao Ni +--- + tests/10ddf-fail-readd-readonly.broken | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + create mode 100644 tests/10ddf-fail-readd-readonly.broken + +diff --git a/tests/10ddf-fail-readd-readonly.broken b/tests/10ddf-fail-readd-readonly.broken +new file mode 100644 +index 000000000000..500343cd9814 +--- /dev/null ++++ b/tests/10ddf-fail-readd-readonly.broken +@@ -0,0 +1,22 @@ ++Sometimes ++ ++This case fails sometimes like: ++mdadm: cannot open MISSING: No such file or directory ++++ return 1 ++++ grep -q 'state\[0\] : Optimal, Consistent' /tmp/mdtest-bDoaoB ++++ echo ERROR: member 0 should be optimal in meta data on MISSING ++ERROR: member 0 should be optimal in meta data on MISSING ++++ ret=1 ++++ for x in $@ ++++ mdadm -E /dev/loop9 ++++ rm -f /var/tmp/stderr ++++ case $* in ++++ case $* in ++++ /usr/sbin/mdadm -E /dev/loop9 ++++ rv=0 ++++ case $* in ++++ cat /var/tmp/stderr ++++ return 0 ++++ grep -q 'state\[0\] : Optimal, Consistent' /tmp/mdtest-bDoaoB ++++ echo ERROR: member 0 should be optimal in meta data on /dev/loop9 ++ERROR: member 0 should be optimal in meta data on /dev/loop9 +-- +2.50.1 + diff --git a/0050-optim-al-ize-write-indent-write-intent.patch b/0050-optim-al-ize-write-indent-write-intent.patch new file mode 100644 index 0000000..6fd238d --- /dev/null +++ b/0050-optim-al-ize-write-indent-write-intent.patch @@ -0,0 +1,31 @@ +From f0667a39f889395f40d8b6c41730e89ac5434c21 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= +Date: Tue, 6 May 2025 20:59:29 +0200 +Subject: [PATCH 50/74] optim[al]ize; write-indent -> write-intent +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Former is highly non-standard, latter is wrong + +Signed-off-by: наб +--- + mdadm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mdadm.c b/mdadm.c +index 6200cd0e7f9b..14649a40c236 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1522,7 +1522,7 @@ int main(int argc, char *argv[]) + + if (s.btype == BitmapUnknown) { + if (c.runstop != 1 && s.level >= 1 && +- ask("To optimalize recovery speed, it is recommended to enable write-indent bitmap, do you want to enable it now?")) ++ ask("To optimize recovery speed, it is recommended to enable write-intent bitmap, do you want to enable it now?")) + s.btype = BitmapInternal; + else + s.btype = BitmapNone; +-- +2.50.1 + diff --git a/0051-mdadm-enable-sync-file-for-udev-rules.patch b/0051-mdadm-enable-sync-file-for-udev-rules.patch new file mode 100644 index 0000000..00ed983 --- /dev/null +++ b/0051-mdadm-enable-sync-file-for-udev-rules.patch @@ -0,0 +1,210 @@ +From 8da27191aa62b08075d8e7ec36c14083f528eb89 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Fri, 4 Apr 2025 08:44:47 -0400 +Subject: [PATCH 51/74] mdadm: enable sync file for udev rules + +Mounting an md device may fail during boot from mdadm's claim +on the device not being released before systemd attempts to mount. + +In this case it was found that essentially there is a race condition +occurring in which the mount cannot happen without some kind of delay +being added BEFORE the mount itself triggers, or manual intervention +after a timeout. + +The findings: +the inode was for a tmp block node made by mdadm for md0. + +crash> detailedsearch ff1b0c398ff28380 +ff1b0c398f079720: ff1b0c398ff28380 slab:filp state:alloc + obj:ff1b0c398f079700 size:256 +ff1b0c398ff284f8: ff1b0c398ff28380 slab:shmem_inode_cache + state:alloc obj:ff1b0c398ff28308 size:768 + +crash> struct file.f_inode,f_path ff1b0c398f079700 +f_inode = 0xff1b0c398ff28380, +f_path = { +mnt = 0xff1b0c594aecc7a0, +dentry = 0xff1b0c3a8c614f00 +}, +crash> struct dentry.d_name 0xff1b0c3a8c614f00 +d_name = { +{ +{ hash = 3714992780, len = 16 }, +hash_len = 72434469516 +}, +name = 0xff1b0c3a8c614f38 ".tmp.md.1454:9:0" +}, + +For the race condition, mdadm and udev have some infrastructure for making +the device be ignored while under construction. e.g. + +$ cat lib/udev/rules.d/01-md-raid-creating.rules + +do not edit this file, it will be overwritten on update +While mdadm is creating an array, it creates a file +/run/mdadm/creating-mdXXX. If that file exists, then +the array is not "ready" and we should make sure the +content is ignored. +KERNEL=="md*", TEST=="/run/mdadm/creating-$kernel", ENV{SYSTEMD_READY}="0" + +However, this feature currently is only used by the mdadm create command. +See calls to udev_block/udev_unblock in the mdadm code as to where and when +this behavior is used. Any md array being started by incremental or +normal assemble commands does not use this udev integration. So assembly +of an existing array does not look to have any explicit protection from +systemd/udev seeing an array as in a usable state before an mdadm instance +with O_EXCL closes its file handle. +This is for the sake of showing the use case for such an option and why +it would be helpful to delay the mount itself. + +While mdadm is still constructing the array mdadm --incremental +that is called from within /usr/lib/udev/rules.d/64-md-raid-assembly.rules, +there is an attempt to mount the md device, but there is not a creation +of "/run/mdadm/creating-xxx" file when in incremental mode that +the rule is looking for. Therefore the device is not marked +as SYSTEMD_READY=0 in +"/usr/lib/udev/rules.d/01-md-raid-creating.rules" and missing +synchronization using the "/run/mdadm/creating-xxx" file. + +As to this change affecting containers or IMSM... +(container's array state is inactive all the time) + +Even if the "array_state" reports "inactive" when previous components +are added, the mdadm call for the very last array component that makes +it usable/ready, still needs to be synced properly - mdadm needs to drop +the claim first calling "close", then delete the "/run/mdadm/creating-xxx". +Then lets the udev know it is clear to act now (the "udev_unblock" in +mdadm code that generates a synthetic udev event so the rules are +reevalutated). It's this processing of the very last array component +that is the issue here (which is not IO error, but it is that trying to +open the dev returns -EBUSY because of the exclusive claim that mdadm +still holds while the mdadm device is being processed already by udev in +parallel, and that is what the +/run/mdadm/creating-xxx should prevent exactly). + +The patch to Incremental.c is to enable creating the +"/run/mdadm/creating-xxx" file during incremental mode. + +For the change to Create.c, the unlink is called right before dropping +the exculusive claim for the device. This should be the other way round +to avoid the race 100%. That is, if there's a "close" call and +"udev_unblock" call, the "close" should go first, then followed +"udev_unblock". + +Signed-off-by: Nigel Croxon +--- + Create.c | 2 +- + Incremental.c | 20 +++++++++++++++----- + 2 files changed, 16 insertions(+), 6 deletions(-) + +diff --git a/Create.c b/Create.c +index de90b0b8e781..420b9136c2c2 100644 +--- a/Create.c ++++ b/Create.c +@@ -1316,8 +1316,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, + } else { + pr_err("not starting array - not enough devices.\n"); + } +- udev_unblock(); + close(mdfd); ++ udev_unblock(); + sysfs_uevent(&info, "change"); + dev_policy_free(custom_pols); + +diff --git a/Incremental.c b/Incremental.c +index 228d2bdd5de2..ba3810e6157f 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -30,6 +30,7 @@ + + #include "mdadm.h" + #include "xmalloc.h" ++#include "udev.h" + + #include + #include +@@ -286,7 +287,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + + /* Couldn't find an existing array, maybe make a new one */ + mdfd = create_mddev(match ? match->devname : NULL, name_to_use, trustworthy, +- chosen_name, 0); ++ chosen_name, 1); + + if (mdfd < 0) + goto out_unlock; +@@ -447,7 +448,6 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + info.array.working_disks = 0; + for (d = sra->devs; d; d=d->next) + info.array.working_disks ++; +- + } + if (strncmp(chosen_name, DEV_MD_DIR, DEV_MD_DIR_LEN) == 0) + md_devname = chosen_name + DEV_MD_DIR_LEN; +@@ -464,7 +464,6 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + if (is_container(info.array.level)) { + char devnm[32]; + /* Try to assemble within the container */ +- sysfs_uevent(sra, "change"); + if (!c->export && c->verbose >= 0) + pr_err("container %s now has %d device%s\n", + chosen_name, info.array.working_disks, +@@ -476,6 +475,8 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + if (st->ss->load_container) + rv = st->ss->load_container(st, mdfd, NULL); + close(mdfd); ++ udev_unblock(); ++ sysfs_uevent(sra, "change"); + sysfs_free(sra); + if (!rv) + rv = Incremental_container(st, chosen_name, c, NULL); +@@ -484,6 +485,7 @@ int Incremental(struct mddev_dev *devlist, struct context *c, + * so that it can eg. try to rebuild degraded array */ + if (st->ss->external) + ping_monitor(devnm); ++ udev_unblock(); + return rv; + } + +@@ -606,7 +608,11 @@ out: + close(mdfd); + if (policy) + dev_policy_free(policy); +- sysfs_free(sra); ++ udev_unblock(); ++ if (sra) { ++ sysfs_uevent(sra, "change"); ++ sysfs_free(sra); ++ } + return rv; + out_unlock: + map_unlock(&map); +@@ -1561,7 +1567,7 @@ static int Incremental_container(struct supertype *st, char *devname, + trustworthy = LOCAL; + + mdfd = create_mddev(match ? match->devname : NULL, ra->name, trustworthy, +- chosen_name, 0); ++ chosen_name, 1); + + if (!is_fd_valid(mdfd)) { + pr_err("create_mddev failed with chosen name %s: %s.\n", +@@ -1581,6 +1587,8 @@ static int Incremental_container(struct supertype *st, char *devname, + map_free(map); + map = NULL; + close_fd(&mdfd); ++ udev_unblock(); ++ sysfs_uevent(&info, "change"); + } + if (c->export && result) { + char sep = '='; +@@ -1607,6 +1615,8 @@ static int Incremental_container(struct supertype *st, char *devname, + release: + map_free(map); + sysfs_free(list); ++ udev_unblock(); ++ sysfs_uevent(&info, "change"); + return rv; + } + +-- +2.50.1 + diff --git a/0052-mdadm-remove-POSIX-check.patch b/0052-mdadm-remove-POSIX-check.patch new file mode 100644 index 0000000..57f6c48 --- /dev/null +++ b/0052-mdadm-remove-POSIX-check.patch @@ -0,0 +1,219 @@ +From 0550fb37839866bb11ec139780d75f97d0765cfb Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Sat, 5 Apr 2025 19:47:18 +0200 +Subject: [PATCH 52/74] mdadm: remove POSIX check + +Neil Brown in #159 pointed that mdadm should been keep in base utility +style, allowing much more with no strict limitations until absolutely +necessary to prevent crashes. + +This view, supported with regression #160 caused by POSIX portable +character set requirement leads me to revert it. + +Revert the POSIX portable character set verification of name and +devname. Make it IMSM only. + +Fixes: e2eb503bd797 ("mdadm: Follow POSIX Portable Character Set") +Signed-off-by: Mariusz Tkaczyk +--- + config.c | 45 +++++++++------------------------------------ + mdadm.8.in | 24 ++++++++---------------- + super-intel.c | 11 +++++++++++ + tests/00confnames | 13 +++++-------- + 4 files changed, 33 insertions(+), 60 deletions(-) + +diff --git a/config.c b/config.c +index 8a8ae5e48c41..e6ede3bbe45d 100644 +--- a/config.c ++++ b/config.c +@@ -188,34 +188,6 @@ inline void ident_init(struct mddev_ident *ident) + ident->uuid_set = 0; + } + +-/** ident_check_name() - helper function to verify name. +- * @name: name to check. +- * @prop_name: the name of the property it is validated against, used for logging. +- * @cmdline: context dependent actions. +- * +- * @name must follow name's criteria, be POSIX compatible and does not have leading dot. +- */ +-static mdadm_status_t ident_check_name(const char *name, const char *prop_name, const bool cmdline) +-{ +- if (!is_string_lq(name, MD_NAME_MAX + 1)) { +- ident_log(prop_name, name, "Too long or empty", cmdline); +- return MDADM_STATUS_ERROR; +- } +- +- if (*name == '.') { +- /* MD device should not be considered as hidden. */ +- ident_log(prop_name, name, "Leading dot forbidden", cmdline); +- return MDADM_STATUS_ERROR; +- } +- +- if (!is_name_posix_compatible(name)) { +- ident_log(prop_name, name, "Not POSIX compatible", cmdline); +- return MDADM_STATUS_ERROR; +- } +- +- return MDADM_STATUS_SUCCESS; +-} +- + /** + * _ident_set_devname() - verify devname and set it in &mddev_ident. + * @ident: pointer to &mddev_ident. +@@ -243,7 +215,6 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname + static const char named_dev_pref[] = DEV_NUM_PREF "_"; + static const int named_dev_pref_size = sizeof(named_dev_pref) - 1; + const char *prop_name = "devname"; +- mdadm_status_t ret; + const char *name; + + if (ident->devname) { +@@ -270,9 +241,11 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname + else + name = devname; + +- ret = ident_check_name(name, prop_name, cmdline); +- if (ret) +- return ret; ++ if (!is_string_lq(name, MD_NAME_MAX + 1)) { ++ ident_log(prop_name, name, "Too long or empty", cmdline); ++ return MDADM_STATUS_ERROR; ++ } ++ + pass: + ident->devname = xstrdup(devname); + return MDADM_STATUS_SUCCESS; +@@ -294,16 +267,16 @@ mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name) + assert(ident); + + const char *prop_name = "name"; +- mdadm_status_t ret; + + if (ident->name[0]) { + ident_log(prop_name, name, "Already defined", true); + return MDADM_STATUS_ERROR; + } + +- ret = ident_check_name(name, prop_name, true); +- if (ret) +- return ret; ++ if (!is_string_lq(name, MD_NAME_MAX + 1)) { ++ ident_log(prop_name, name, "Too long or empty", true); ++ return MDADM_STATUS_ERROR; ++ } + + snprintf(ident->name, MD_NAME_MAX + 1, "%s", name); + return MDADM_STATUS_SUCCESS; +diff --git a/mdadm.8.in b/mdadm.8.in +index 452555216644..2a71e32237d4 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -884,10 +884,8 @@ are used to add different devices). + .BR \-N ", " \-\-name= + Set a + .B name +-for the array. It must be +-.BR "POSIX PORTABLE NAME" +-compatible and cannot be longer than 32 chars. This is effective when creating an array +-with a v1 metadata, or an external array. ++for the array. It cannot be longer than 32 chars. This is effective when ++creating an array with a v1 metadata, or an external array. + + If name is needed but not specified, it is taken from the basename of the device + that is being created. See +@@ -1024,11 +1022,9 @@ is much safer. + + .TP + .BR \-N ", " \-\-name= +-Specify the name of the array to assemble. It must be +-.BR "POSIX PORTABLE NAME" +-compatible and cannot be longer than 32 chars. This must be the name +-that was specified when creating the array. It must either match +-the name stored in the superblock exactly, or it must match ++Specify the name of the array to assemble. It cannot be longer than 32 chars. ++This must be the name that was specified when creating the array. It must ++either match the name stored in the superblock exactly, or it must match + with the current + .I homehost + prefixed to the start of the given name. +@@ -2236,10 +2232,8 @@ and + + The + .B name +-option updates the subarray name in the metadata. It must be +-.BR "POSIX PORTABLE NAME" +-compatible and cannot be longer than 32 chars. If successes, new value will be respected after +-next assembly. ++option updates the subarray name in the metadata. It cannot be longer than ++32 chars. If successes, new value will be respected after next assembly. + + The + .B ppl +@@ -3214,9 +3208,7 @@ can be given, or just the suffix of the second sort of name, such as + .I home + can be given. + +-In every style, raw name must be compatible with +-.BR "POSIX PORTABLE NAME" +-and has to be no longer than 32 chars. ++In every style, raw name has to be no longer than 32 chars. + + When + .I mdadm +diff --git a/super-intel.c b/super-intel.c +index 4fbbc98d915c..40519f8fce2a 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5630,6 +5630,17 @@ static bool imsm_is_name_allowed(struct intel_super *super, const char * const n + return false; + } + ++ if (name[0] == '.') { ++ pr_vrb("imsm: Name \"%s\" has forbidden leading dot", name); ++ return false; ++ } ++ ++ if (is_name_posix_compatible(name) == false) { ++ pr_vrb("imsm: Name \"%s\" doesn't follow POSIX portable file name character set", ++ name); ++ return false; ++ } ++ + for (i = 0; i < mpb->num_raid_devs; i++) { + struct imsm_dev *dev = get_imsm_dev(super, i); + +diff --git a/tests/00confnames b/tests/00confnames +index 191a905f3379..db22fa1a5035 100644 +--- a/tests/00confnames ++++ b/tests/00confnames +@@ -4,6 +4,10 @@ set -x -e + # Test how is handled during Incremental assemblation with + # config file and ARRAYLINE specified. + ++# for native, mdadm is not limiting or checking the set of ASCI symbols that ++# can be used. It is up to user to use symbols that are not conflicting with ++# system utilities. Any problem is this area is not mdadm issue. ++ + names_create "/dev/md/name" + local _UUID="$(mdadm -D --export /dev/md127 | grep MD_UUID | cut -d'=' -f2)" + [[ "$_UUID" == "" ]] && echo "Cannot obtain UUID for $DEVNODE_NAME" && exit 1 +@@ -41,14 +45,7 @@ mdadm -I $dev0 --config=$config + names_verify "/dev/md4" "empty" "name" + mdadm -S "/dev/md4" + +-# 6. with some special symbols and locales. +-# should be ignored. +-names_make_conf $_UUID "tźż-\.,<>st+-" $config +-mdadm -I $dev0 --config=$config +-names_verify "/dev/md127" "name" "name" +-mdadm -S "/dev/md127" +- +-# 7. No set. ++# 6. No set. + # Metadata name and default node used. + names_make_conf $_UUID "empty" $config + mdadm -I $dev0 --config=$config +-- +2.50.1 + diff --git a/0053-mdadm-assemble-Don-t-stop-array-after-creating-it.patch b/0053-mdadm-assemble-Don-t-stop-array-after-creating-it.patch new file mode 100644 index 0000000..026661b --- /dev/null +++ b/0053-mdadm-assemble-Don-t-stop-array-after-creating-it.patch @@ -0,0 +1,30 @@ +From ea4cdaea1a553685444a3fb39aae6b2cfee387ef Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 3 Jun 2025 08:49:29 +0800 +Subject: [PATCH 53/74] mdadm/assemble: Don't stop array after creating it + +It stops the array which is just created. From the comment it wants to +stop the array if it has no content. But it hasn't added member disks, +so it's a clean array. It's meaningless to do it. + +Signed-off-by: Xiao Ni +--- + Assemble.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index f8099cd32aa3..1949bf96c478 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1570,8 +1570,6 @@ try_again: + goto try_again; + goto out; + } +- /* just incase it was started but has no content */ +- ioctl(mdfd, STOP_ARRAY, NULL); + } + + if (content != &info) { +-- +2.50.1 + diff --git a/0054-mdmonitor-use-MAILFROM-to-set-sendmail-envelope-send.patch b/0054-mdmonitor-use-MAILFROM-to-set-sendmail-envelope-send.patch new file mode 100644 index 0000000..cdc9caf --- /dev/null +++ b/0054-mdmonitor-use-MAILFROM-to-set-sendmail-envelope-send.patch @@ -0,0 +1,47 @@ +From 34f21b7acea8afbea9348d0f421beeeedca7a136 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 7 May 2025 17:49:05 +0200 +Subject: [PATCH 54/74] mdmonitor: use MAILFROM to set sendmail envelope sender + address + +Modern mail relays may reject emails with unknown envelope sender +address. + +Use the MAILFROM address also as envelope sender address to work +around this issue. + +Signed-off-by: Martin Wilck +--- + mdmonitor.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/mdmonitor.c b/mdmonitor.c +index d51617cd0981..ea35d98ede30 100644 +--- a/mdmonitor.c ++++ b/mdmonitor.c +@@ -639,11 +639,20 @@ static void execute_alert_cmd(const struct event_data *data) + */ + static void send_event_email(const struct event_data *data) + { +- FILE *mp, *mdstat; ++ FILE *mp = NULL, *mdstat; + char buf[BUFSIZ]; + int n; + +- mp = popen(Sendmail, "w"); ++ if (info.mailfrom) { ++ char cmd[1024]; ++ int rc = snprintf(cmd, sizeof(cmd), "%s -f%s", ++ Sendmail, info.mailfrom); ++ ++ if (rc >= 0 && (unsigned int)rc < sizeof(cmd)) ++ mp = popen(cmd, "w"); ++ } ++ if (mp == NULL) ++ mp = popen(Sendmail, "w"); + if (!mp) { + pr_err("Cannot open pipe stream for sendmail.\n"); + return; +-- +2.50.1 + diff --git a/0055-mdadm-use-lseek-consistently.patch b/0055-mdadm-use-lseek-consistently.patch new file mode 100644 index 0000000..71ac50b --- /dev/null +++ b/0055-mdadm-use-lseek-consistently.patch @@ -0,0 +1,749 @@ +From 787cc1b60130b8031be59e49d54463c58cd8cf74 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 26 Jun 2025 06:29:37 +0100 +Subject: [PATCH 55/74] mdadm: use lseek consistently + +mdadm used both lseek and lseek64 for legacy reasons. These days, we just +need to configure __USE_LARGEFILE64 macro. Fixing this issue enables +musl compilation. + +Add macro, and change all lseek64 to lseek. Fix style issues in these +lines. + +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 52 +++++++++++++++++++++++++-------------------------- + mdadm.h | 10 ++-------- + raid6check.c | 15 ++++++++------- + restripe.c | 10 ++++------ + super-ddf.c | 24 ++++++++++++------------ + super-intel.c | 32 +++++++++++++++---------------- + super0.c | 14 +++++++------- + super1.c | 24 ++++++++++++------------ + swap_super.c | 12 +++++------- + util.c | 2 +- + 10 files changed, 93 insertions(+), 102 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 30eaa3c6a654..fbf56156a7c4 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -4280,10 +4280,10 @@ static int grow_backup(struct mdinfo *sra, + bsb.magic[15] = '2'; + for (i = 0; i < dests; i++) + if (part) +- lseek64(destfd[i], destoffsets[i] + +- __le64_to_cpu(bsb.devstart2)*512, 0); ++ lseek(destfd[i], destoffsets[i] + ++ __le64_to_cpu(bsb.devstart2) * 512, 0); + else +- lseek64(destfd[i], destoffsets[i], 0); ++ lseek(destfd[i], destoffsets[i], 0); + + rv = save_stripes(sources, offsets, disks, chunk, level, layout, + dests, destfd, offset * 512 * odata, +@@ -4293,24 +4293,24 @@ static int grow_backup(struct mdinfo *sra, + return rv; + bsb.mtime = __cpu_to_le64(time(0)); + for (i = 0; i < dests; i++) { +- bsb.devstart = __cpu_to_le64(destoffsets[i]/512); ++ unsigned long long seek = destoffsets[i] + stripes * chunk * odata; + +- bsb.sb_csum = bsb_csum((char*)&bsb, +- ((char*)&bsb.sb_csum)-((char*)&bsb)); ++ bsb.devstart = __cpu_to_le64(destoffsets[i] / 512); ++ ++ bsb.sb_csum = bsb_csum((char *)&bsb, ((char *)&bsb.sb_csum) - ((char *)&bsb)); + if (memcmp(bsb.magic, "md_backup_data-2", 16) == 0) +- bsb.sb_csum2 = bsb_csum((char*)&bsb, +- ((char*)&bsb.sb_csum2)-((char*)&bsb)); ++ bsb.sb_csum2 = bsb_csum((char *)&bsb, ++ ((char *)&bsb.sb_csum2) - ((char *)&bsb)); + + rv = -1; +- if ((unsigned long long)lseek64(destfd[i], +- destoffsets[i] - 4096, 0) != ++ ++ if ((unsigned long long)lseek(destfd[i], destoffsets[i] - 4096, 0) != + destoffsets[i] - 4096) + break; + if (write(destfd[i], &bsb, 512) != 512) + break; + if (destoffsets[i] > 4096) { +- if ((unsigned long long)lseek64(destfd[i], destoffsets[i]+stripes*chunk*odata, 0) != +- destoffsets[i]+stripes*chunk*odata) ++ if ((unsigned long long)lseek(destfd[i], seek, 0) != seek) + break; + if (write(destfd[i], &bsb, 512) != 512) + break; +@@ -4359,7 +4359,7 @@ static int forget_backup(int dests, int *destfd, + if (memcmp(bsb.magic, "md_backup_data-2", 16) == 0) + bsb.sb_csum2 = bsb_csum((char*)&bsb, + ((char*)&bsb.sb_csum2)-((char*)&bsb)); +- if ((unsigned long long)lseek64(destfd[i], destoffsets[i]-4096, 0) != ++ if ((unsigned long long)lseek(destfd[i], destoffsets[i]-4096, 0) != + destoffsets[i]-4096) + rv = -1; + if (rv == 0 && write(destfd[i], &bsb, 512) != 512) +@@ -4387,8 +4387,8 @@ static void validate(int afd, int bfd, unsigned long long offset) + */ + if (afd < 0) + return; +- if (lseek64(bfd, offset - 4096, 0) < 0) { +- pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ if (lseek(bfd, offset - 4096, 0) < 0) { ++ pr_err("lseek fails %d:%s\n", errno, strerror(errno)); + return; + } + if (read(bfd, &bsb2, 512) != 512) +@@ -4421,8 +4421,8 @@ static void validate(int afd, int bfd, unsigned long long offset) + } + } + +- if (lseek64(bfd, offset, 0) < 0) { +- pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ if (lseek(bfd, offset, 0) < 0) { ++ pr_err("lseek fails %d:%s\n", errno, strerror(errno)); + goto out; + } + if ((unsigned long long)read(bfd, bbuf, len) != len) { +@@ -4430,8 +4430,8 @@ static void validate(int afd, int bfd, unsigned long long offset) + fail("read first backup failed"); + } + +- if (lseek64(afd, __le64_to_cpu(bsb2.arraystart)*512, 0) < 0) { +- pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ if (lseek(afd, __le64_to_cpu(bsb2.arraystart)*512, 0) < 0) { ++ pr_err("lseek fails %d:%s\n", errno, strerror(errno)); + goto out; + } + if ((unsigned long long)read(afd, abuf, len) != len) +@@ -4450,14 +4450,14 @@ static void validate(int afd, int bfd, unsigned long long offset) + bbuf = xmalloc(abuflen); + } + +- if (lseek64(bfd, offset+__le64_to_cpu(bsb2.devstart2)*512, 0) < 0) { +- pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ if (lseek(bfd, offset+__le64_to_cpu(bsb2.devstart2)*512, 0) < 0) { ++ pr_err("lseek fails %d:%s\n", errno, strerror(errno)); + goto out; + } + if ((unsigned long long)read(bfd, bbuf, len) != len) + fail("read second backup failed"); +- if (lseek64(afd, __le64_to_cpu(bsb2.arraystart2)*512, 0) < 0) { +- pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ if (lseek(afd, __le64_to_cpu(bsb2.arraystart2)*512, 0) < 0) { ++ pr_err("lseek fails %d:%s\n", errno, strerror(errno)); + goto out; + } + if ((unsigned long long)read(afd, abuf, len) != len) +@@ -4740,7 +4740,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, + st->ss->getinfo_super(st, &dinfo, NULL); + st->ss->free_super(st); + +- if (lseek64(fd, ++ if (lseek(fd, + (dinfo.data_offset + dinfo.component_size - 8) <<9, + 0) < 0) { + pr_err("Cannot seek on device %d\n", i); +@@ -4840,7 +4840,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, + goto nonew; /* No new data here */ + } + } +- if (lseek64(fd, __le64_to_cpu(bsb.devstart)*512, 0)< 0) { ++ if (lseek(fd, __le64_to_cpu(bsb.devstart) * 512, 0) < 0) { + second_fail: + if (verbose) + pr_err("Failed to verify secondary backup-metadata block on %s\n", +@@ -4848,7 +4848,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, + continue; /* Cannot seek */ + } + /* There should be a duplicate backup superblock 4k before here */ +- if (lseek64(fd, -4096, 1) < 0 || ++ if (lseek(fd, -4096, 1) < 0 || + read(fd, &bsb2, sizeof(bsb2)) != sizeof(bsb2)) + goto second_fail; /* Cannot find leading superblock */ + if (bsb.magic[15] == '1') +diff --git a/mdadm.h b/mdadm.h +index ce9c216bf74d..84bd2c915fc2 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -24,15 +24,9 @@ + + #define _GNU_SOURCE + #define _FILE_OFFSET_BITS 64 +-#include +-#ifdef __GLIBC__ +-extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence)); +-#elif !defined(lseek64) +-# if defined(__NO_STAT64) || __WORDSIZE != 32 +-# define lseek64 lseek +-# endif +-#endif ++#define __USE_LARGEFILE64 1 + ++#include + #include + #include + #include +diff --git a/raid6check.c b/raid6check.c +index 95533f7d0836..4469dc8fac5a 100644 +--- a/raid6check.c ++++ b/raid6check.c +@@ -212,9 +212,12 @@ int autorepair(int *disk, unsigned long long start, int chunk_size, + for(j = 0; j < (chunk_size >> CHECK_PAGE_BITS); j++) { + if(page_to_write[j] == 1) { + int slot = block_index_for_slot[disk[j]]; +- lseek64(source[slot], offsets[slot] + start * chunk_size + j * CHECK_PAGE_SIZE, SEEK_SET); ++ lseek(source[slot], ++ offsets[slot] + start * chunk_size + ++ j * CHECK_PAGE_SIZE, SEEK_SET); + write_res += write(source[slot], +- blocks[disk[j]] + j * CHECK_PAGE_SIZE, ++ blocks[disk[j]] + ++ j * CHECK_PAGE_SIZE, + CHECK_PAGE_SIZE); + } + } +@@ -287,16 +290,14 @@ int manual_repair(int chunk_size, int syndrome_disks, + int write_res1, write_res2; + off64_t seek_res; + +- seek_res = lseek64(source[fd1], +- offsets[fd1] + start * chunk_size, SEEK_SET); ++ seek_res = lseek(source[fd1], offsets[fd1] + start * chunk_size, SEEK_SET); + if (seek_res < 0) { + fprintf(stderr, "lseek failed for failed_disk1\n"); + return -1; + } + write_res1 = write(source[fd1], blocks[failed_slot1], chunk_size); + +- seek_res = lseek64(source[fd2], +- offsets[fd2] + start * chunk_size, SEEK_SET); ++ seek_res = lseek(source[fd2], offsets[fd2] + start * chunk_size, SEEK_SET); + if (seek_res < 0) { + fprintf(stderr, "lseek failed for failed_disk2\n"); + return -1; +@@ -380,7 +381,7 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets, + goto exitCheck; + } + for (i = 0 ; i < raid_disks ; i++) { +- off64_t seek_res = lseek64(source[i], offsets[i] + start * chunk_size, ++ off64_t seek_res = lseek(source[i], offsets[i] + start * chunk_size, + SEEK_SET); + if (seek_res < 0) { + fprintf(stderr, "lseek to source %d failed\n", i); +diff --git a/restripe.c b/restripe.c +index 5e126eb7bfa5..ec8d6275c407 100644 +--- a/restripe.c ++++ b/restripe.c +@@ -583,8 +583,7 @@ int save_stripes(int *source, unsigned long long *offsets, + raid_disks, level, layout); + if (dnum < 0) abort(); + if (source[dnum] < 0 || +- lseek64(source[dnum], +- offsets[dnum] + offset, 0) < 0 || ++ lseek(source[dnum], offsets[dnum] + offset, 0) < 0 || + read(source[dnum], buf+disk * chunk_size, + chunk_size) != chunk_size) { + if (failed <= 2) { +@@ -756,7 +755,7 @@ int restore_stripes(int *dest, unsigned long long *offsets, + raid_disks, level, layout); + if (src_buf == NULL) { + /* read from file */ +- if (lseek64(source, read_offset, 0) != ++ if (lseek(source, read_offset, 0) != + (off64_t)read_offset) { + rv = -1; + goto abort; +@@ -818,8 +817,7 @@ int restore_stripes(int *dest, unsigned long long *offsets, + } + for (i=0; i < raid_disks ; i++) + if (dest[i] >= 0) { +- if (lseek64(dest[i], +- offsets[i]+offset, 0) < 0) { ++ if (lseek(dest[i], offsets[i]+offset, 0) < 0) { + rv = -1; + goto abort; + } +@@ -868,7 +866,7 @@ int test_stripes(int *source, unsigned long long *offsets, + int disk; + + for (i = 0 ; i < raid_disks ; i++) { +- if ((lseek64(source[i], offsets[i]+start, 0) < 0) || ++ if ((lseek(source[i], offsets[i]+start, 0) < 0) || + (read(source[i], stripes[i], chunk_size) != + chunk_size)) { + free(q); +diff --git a/super-ddf.c b/super-ddf.c +index dda8b7fedd64..f46217206437 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -815,7 +815,7 @@ static int load_ddf_header(int fd, unsigned long long lba, + if (lba >= size-1) + return 0; + +- if (lseek64(fd, lba << 9, 0) == -1L) ++ if (lseek(fd, lba << 9, 0) == -1L) + return 0; + + if (read(fd, hdr, 512) != 512) +@@ -868,7 +868,7 @@ static void *load_section(int fd, struct ddf_super *super, void *buf, + else + offset += be64_to_cpu(super->active->secondary_lba); + +- if ((unsigned long long)lseek64(fd, offset << 9, 0) != (offset << 9)) { ++ if ((unsigned long long)lseek(fd, offset << 9, 0) != (offset << 9)) { + if (dofree) + free(buf); + return NULL; +@@ -932,8 +932,8 @@ static int search_for_ddf_headers(int fd, char *devname, + if (search_end - pos < SEARCH_BLOCK_SIZE) + bytes_block_to_read = search_end - pos; + +- if (lseek64(fd, pos, SEEK_SET) < 0) { +- pr_err("lseek64 for %s failed %d:%s\n", ++ if (lseek(fd, pos, SEEK_SET) < 0) { ++ pr_err("lseek for %s failed %d:%s\n", + fd2devnm(fd), errno, strerror(errno)); + result = 2; + goto cleanup; +@@ -984,7 +984,7 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname) + get_dev_size(fd, NULL, &dsize); + + /* Check the last 512 bytes for the DDF header. */ +- if (lseek64(fd, dsize - 512, SEEK_SET) == -1L) { ++ if (lseek(fd, dsize - 512, SEEK_SET) == -1L) { + if (devname) { + pr_err("Cannot seek to last 512 bytes on %s: %s\n", + devname, strerror(errno)); +@@ -1019,7 +1019,7 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname) + } + + /* Seek to the found position */ +- if (lseek64(fd, ddfpos, SEEK_SET) == -1L) { ++ if (lseek(fd, ddfpos, SEEK_SET) == -1L) { + if (devname) { + pr_err("Cannot seek to anchor block on %s\n", + devname); +@@ -1849,7 +1849,7 @@ static int copy_metadata_ddf(struct supertype *st, int from, int to) + if (!get_dev_size(from, NULL, &dsize)) + goto err; + +- if (lseek64(from, dsize - 512, 0) == -1L) ++ if (lseek(from, dsize - 512, 0) == -1L) + goto err; + + if (read(from, buf, 512) != 512) +@@ -1870,7 +1870,7 @@ static int copy_metadata_ddf(struct supertype *st, int from, int to) + + bytes = dsize - offset; + +- if (lseek64(from, offset, 0) == -1L || lseek64(to, offset, 0) == -1L) ++ if (lseek(from, offset, 0) == -1L || lseek(to, offset, 0) == -1L) + goto err; + + while (written < bytes) { +@@ -3132,7 +3132,7 @@ static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type) + header->openflag = 1; + header->crc = calc_crc(header, 512); + +- if (lseek64(fd, sector << 9, 0) == -1L) ++ if (lseek(fd, sector << 9, 0) == -1L) + goto out; + + if (write(fd, header, 512) < 0) +@@ -3199,7 +3199,7 @@ out: + header->openflag = 0; + header->crc = calc_crc(header, 512); + +- if (lseek64(fd, sector << 9, 0) == -1L) ++ if (lseek(fd, sector << 9, 0) == -1L) + return 0; + + if (write(fd, header, 512) < 0) +@@ -3254,7 +3254,7 @@ static int _write_super_to_disk(struct ddf_super *ddf, struct dl *d) + if (!__write_ddf_structure(d, ddf, DDF_HEADER_SECONDARY)) + return 0; + +- if (lseek64(fd, (size - 1) * 512, SEEK_SET) == -1L) ++ if (lseek(fd, (size - 1) * 512, SEEK_SET) == -1L) + return 0; + + if (write(fd, &ddf->anchor, 512) < 0) +@@ -4050,7 +4050,7 @@ static int store_super_ddf(struct supertype *st, int fd) + + buf = xmemalign(SEARCH_BLOCK_SIZE, SEARCH_REGION_SIZE); + memset(buf, 0, SEARCH_REGION_SIZE); +- if (lseek64(fd, dsize - SEARCH_REGION_SIZE, 0) == -1L) { ++ if (lseek(fd, dsize - SEARCH_REGION_SIZE, 0) == -1L) { + free(buf); + return 1; + } +diff --git a/super-intel.c b/super-intel.c +index 40519f8fce2a..7162327ecdf2 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -3230,7 +3230,7 @@ static int read_imsm_migr_rec(int fd, struct intel_super *super) + unsigned long long dsize; + + get_dev_size(fd, NULL, &dsize); +- if (lseek64(fd, dsize - (sector_size*MIGR_REC_SECTOR_POSITION), ++ if (lseek(fd, dsize - (sector_size*MIGR_REC_SECTOR_POSITION), + SEEK_SET) < 0) { + pr_err("Cannot seek to anchor block: %s\n", + strerror(errno)); +@@ -3421,7 +3421,7 @@ static int write_imsm_migr_rec(struct supertype *st) + continue; + + get_dev_size(sd->fd, NULL, &dsize); +- if (lseek64(sd->fd, dsize - (MIGR_REC_SECTOR_POSITION * ++ if (lseek(sd->fd, dsize - (MIGR_REC_SECTOR_POSITION * + sector_size), + SEEK_SET) < 0) { + pr_err("Cannot seek to anchor block: %s\n", +@@ -4591,7 +4591,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname) + return 1; + } + +- if (lseek64(fd, dsize - (sector_size * 2), SEEK_SET) < 0) { ++ if (lseek(fd, dsize - (sector_size * 2), SEEK_SET) < 0) { + if (devname) + pr_err("Cannot seek to anchor block on %s: %s\n", + devname, strerror(errno)); +@@ -4660,7 +4660,7 @@ static int load_imsm_mpb(int fd, struct intel_super *super, char *devname) + } + + /* read the extended mpb */ +- if (lseek64(fd, dsize - (sector_size * (2 + sectors)), SEEK_SET) < 0) { ++ if (lseek(fd, dsize - (sector_size * (2 + sectors)), SEEK_SET) < 0) { + if (devname) + pr_err("Cannot seek to extended mpb on %s: %s\n", + devname, strerror(errno)); +@@ -6164,7 +6164,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + /* clear migr_rec when adding disk to container */ + memset(super->migr_rec_buf, 0, MIGR_REC_BUF_SECTORS * MAX_SECTOR_SIZE); + +- if (lseek64(fd, (size - MIGR_REC_SECTOR_POSITION * member_sector_size), SEEK_SET) >= 0) { ++ if (lseek(fd, (size - MIGR_REC_SECTOR_POSITION * member_sector_size), SEEK_SET) >= 0) { + unsigned int nbytes = MIGR_REC_BUF_SECTORS * member_sector_size; + + if ((unsigned int)write(fd, super->migr_rec_buf, nbytes) != nbytes) +@@ -6387,7 +6387,7 @@ static int write_super_imsm(struct supertype *st, int doclose) + unsigned long long dsize; + + get_dev_size(d->fd, NULL, &dsize); +- if (lseek64(d->fd, dsize - sector_size, ++ if (lseek(d->fd, dsize - sector_size, + SEEK_SET) >= 0) { + if ((unsigned int)write(d->fd, + super->migr_rec_buf, +@@ -6470,7 +6470,7 @@ static int write_ppl_header(unsigned long long ppl_sector, int fd, void *buf) + + ppl_hdr->checksum = __cpu_to_le32(~crc32c_le(~0, buf, PPL_HEADER_SIZE)); + +- if (lseek64(fd, ppl_sector * 512, SEEK_SET) < 0) { ++ if (lseek(fd, ppl_sector * 512, SEEK_SET) < 0) { + ret = -errno; + perror("Failed to seek to PPL header location"); + return ret; +@@ -6564,7 +6564,7 @@ static int validate_ppl_imsm(struct supertype *st, struct mdinfo *info, + + dprintf("Checking potential PPL at offset: %llu\n", ppl_offset); + +- if (lseek64(d->fd, info->ppl_sector * 512 + ppl_offset, ++ if (lseek(d->fd, info->ppl_sector * 512 + ppl_offset, + SEEK_SET) < 0) { + perror("Failed to seek to PPL header location"); + ret = -1; +@@ -9089,7 +9089,7 @@ static int store_imsm_mpb(int fd, struct imsm_super *mpb) + sectors = mpb_sectors(mpb, sector_size) - 1; + + /* write the extended mpb to the sectors preceeding the anchor */ +- if (lseek64(fd, dsize - (sector_size * (2 + sectors)), ++ if (lseek(fd, dsize - (sector_size * (2 + sectors)), + SEEK_SET) < 0) + return 1; + +@@ -9099,7 +9099,7 @@ static int store_imsm_mpb(int fd, struct imsm_super *mpb) + } + + /* first block is stored on second to last sector of the disk */ +- if (lseek64(fd, dsize - (sector_size * 2), SEEK_SET) < 0) ++ if (lseek(fd, dsize - (sector_size * 2), SEEK_SET) < 0) + return 1; + + if ((unsigned int)write(fd, buf, sector_size) != sector_size) +@@ -11282,7 +11282,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info) + skipped_disks++; + continue; + } +- if (lseek64(dl_disk->fd, read_offset, SEEK_SET) < 0) { ++ if (lseek(dl_disk->fd, read_offset, SEEK_SET) < 0) { + pr_err("Cannot seek to block: %s\n", + strerror(errno)); + skipped_disks++; +@@ -11294,7 +11294,7 @@ int recover_backup_imsm(struct supertype *st, struct mdinfo *info) + skipped_disks++; + continue; + } +- if (lseek64(dl_disk->fd, write_offset, SEEK_SET) < 0) { ++ if (lseek(dl_disk->fd, write_offset, SEEK_SET) < 0) { + pr_err("Cannot seek to block: %s\n", + strerror(errno)); + skipped_disks++; +@@ -12776,7 +12776,7 @@ static int imsm_manage_reshape( + unsigned long long dsize; + + get_dev_size(d->fd, NULL, &dsize); +- if (lseek64(d->fd, dsize - MIGR_REC_SECTOR_POSITION*sector_size, ++ if (lseek(d->fd, dsize - MIGR_REC_SECTOR_POSITION*sector_size, + SEEK_SET) >= 0) { + if ((unsigned int)write(d->fd, super->migr_rec_buf, + MIGR_REC_BUF_SECTORS*sector_size) != +@@ -12932,7 +12932,7 @@ static int validate_internal_bitmap_for_drive(struct supertype *st, + } + } + +- if (lseek64(fd, offset * super->sector_size, SEEK_SET) < 0) ++ if (lseek(fd, offset * super->sector_size, SEEK_SET) < 0) + goto abort; + if (read(fd, read_buf, IMSM_BITMAP_HEADER_SIZE) != + IMSM_BITMAP_HEADER_SIZE) +@@ -13050,7 +13050,7 @@ static int locate_bitmap_imsm(struct supertype *st, int fd, int node_num) + offset = get_bitmap_header_sector(super, super->current_vol); + dprintf("bitmap header offset is %llu\n", offset); + +- lseek64(fd, offset << 9, 0); ++ lseek(fd, offset << 9, 0); + + return 0; + } +@@ -13104,7 +13104,7 @@ static int write_init_bitmap_imsm(struct supertype *st, int fd, + return -1; + memset(buf, 0xFF, MAX_SECTOR_SIZE); + offset = get_bitmap_sector(super, vol_idx); +- lseek64(fd, offset << 9, 0); ++ lseek(fd, offset << 9, 0); + while (written < IMSM_BITMAP_AREA_SIZE) { + to_write = IMSM_BITMAP_AREA_SIZE - written; + if (to_write > MAX_SECTOR_SIZE) +diff --git a/super0.c b/super0.c +index 4a462bdca9c8..def553c63c80 100644 +--- a/super0.c ++++ b/super0.c +@@ -332,12 +332,12 @@ static int copy_metadata0(struct supertype *st, int from, int to) + + offset *= 512; + +- if (lseek64(from, offset, 0) < 0LL) ++ if (lseek(from, offset, 0) < 0LL) + goto err; + if (read(from, buf, bufsize) != bufsize) + goto err; + +- if (lseek64(to, offset, 0) < 0LL) ++ if (lseek(to, offset, 0) < 0LL) + goto err; + super = buf; + if (super->md_magic != MD_SB_MAGIC || +@@ -895,7 +895,7 @@ static int store_super0(struct supertype *st, int fd) + offset = dsize/512 - 8*2; + offset &= ~(4*2-1); + offset *= 512; +- if (lseek64(fd, offset, 0)< 0LL) ++ if (lseek(fd, offset, 0) < 0LL) + ret = 3; + else if (write(fd, st->other, 1024) != 1024) + ret = 4; +@@ -910,7 +910,7 @@ static int store_super0(struct supertype *st, int fd) + + offset *= 512; + +- if (lseek64(fd, offset, 0)< 0LL) ++ if (lseek(fd, offset, 0) < 0LL) + return 3; + + if (write(fd, super, sizeof(*super)) != sizeof(*super)) +@@ -1064,7 +1064,7 @@ static int load_super0(struct supertype *st, int fd, char *devname) + + offset *= 512; + +- if (lseek64(fd, offset, 0)< 0LL) { ++ if (lseek(fd, offset, 0) < 0LL) { + if (devname) + pr_err("Cannot seek to superblock on %s: %s\n", + devname, strerror(errno)); +@@ -1249,7 +1249,7 @@ static int locate_bitmap0(struct supertype *st, int fd, int node_num) + + offset += MD_SB_BYTES; + +- if (lseek64(fd, offset, 0) < 0) ++ if (lseek(fd, offset, 0) < 0) + return -1; + return 0; + } +@@ -1275,7 +1275,7 @@ static int write_bitmap0(struct supertype *st, int fd, enum bitmap_update update + + offset *= 512; + +- if (lseek64(fd, offset + 4096, 0)< 0LL) ++ if (lseek(fd, offset + 4096, 0) < 0LL) + return 3; + + if (posix_memalign(&buf, 4096, 4096)) +diff --git a/super1.c b/super1.c +index 84d735738401..a8081a441009 100644 +--- a/super1.c ++++ b/super1.c +@@ -628,7 +628,7 @@ static int copy_metadata1(struct supertype *st, int from, int to) + goto err; + } + +- if (lseek64(from, sb_offset << 9, 0) < 0LL) ++ if (lseek(from, sb_offset << 9, 0) < 0LL) + goto err; + if (read(from, buf, bufsize) != bufsize) + goto err; +@@ -642,7 +642,7 @@ static int copy_metadata1(struct supertype *st, int from, int to) + calc_sb_1_csum(sb) != super.sb_csum) + goto err; + +- if (lseek64(to, sb_offset << 9, 0) < 0LL) ++ if (lseek(to, sb_offset << 9, 0) < 0LL) + goto err; + if (write(to, buf, bufsize) != bufsize) + goto err; +@@ -658,9 +658,9 @@ static int copy_metadata1(struct supertype *st, int from, int to) + + bitmap_offset += (int32_t)__le32_to_cpu(super.bitmap_offset); + +- if (lseek64(from, bitmap_offset<<9, 0) < 0) ++ if (lseek(from, bitmap_offset<<9, 0) < 0) + goto err; +- if (lseek64(to, bitmap_offset<<9, 0) < 0) ++ if (lseek(to, bitmap_offset<<9, 0) < 0) + goto err; + + for (written = 0; written < bytes ; ) { +@@ -699,9 +699,9 @@ static int copy_metadata1(struct supertype *st, int from, int to) + + bb_offset += (int32_t)__le32_to_cpu(super.bblog_offset); + +- if (lseek64(from, bb_offset<<9, 0) < 0) ++ if (lseek(from, bb_offset<<9, 0) < 0) + goto err; +- if (lseek64(to, bb_offset<<9, 0) < 0) ++ if (lseek(to, bb_offset<<9, 0) < 0) + goto err; + + for (written = 0; written < bytes ; ) { +@@ -803,7 +803,7 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname) + offset = __le64_to_cpu(sb->super_offset) + + (int)__le32_to_cpu(sb->bblog_offset); + offset <<= 9; +- if (lseek64(fd, offset, 0) < 0) { ++ if (lseek(fd, offset, 0) < 0) { + pr_err("Cannot seek to bad-blocks list\n"); + free(bbl); + return 1; +@@ -1701,7 +1701,7 @@ static int store_super1(struct supertype *st, int fd) + abort(); + } + +- if (lseek64(fd, sb_offset << 9, 0)< 0LL) ++ if (lseek(fd, sb_offset << 9, 0) < 0LL) + return 3; + + sbsize = ROUND_UP(sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev), 512); +@@ -1770,7 +1770,7 @@ static int write_init_ppl1(struct supertype *st, struct mdinfo *info, int fd) + sizeof(sb->set_uuid))); + ppl_hdr->checksum = __cpu_to_le32(~crc32c_le(~0, buf, PPL_HEADER_SIZE)); + +- if (lseek64(fd, info->ppl_sector * 512, SEEK_SET) < 0) { ++ if (lseek(fd, info->ppl_sector * 512, SEEK_SET) < 0) { + ret = errno; + perror("Failed to seek to PPL header location"); + } +@@ -1815,7 +1815,7 @@ static int write_empty_r5l_meta_block(struct supertype *st, int fd) + crc = crc32c_le(crc, (void *)mb, META_BLOCK_SIZE); + mb->checksum = crc; + +- if (lseek64(fd, __le64_to_cpu(sb->data_offset) * 512, 0) < 0LL) { ++ if (lseek(fd, __le64_to_cpu(sb->data_offset) * 512, 0) < 0LL) { + pr_err("cannot seek to offset of the meta block\n"); + goto fail_to_write; + } +@@ -2184,7 +2184,7 @@ static int load_super1(struct supertype *st, int fd, char *devname) + return -EINVAL; + } + +- if (lseek64(fd, sb_offset << 9, 0)< 0LL) { ++ if (lseek(fd, sb_offset << 9, 0) < 0LL) { + if (devname) + pr_err("Cannot seek to superblock on %s: %s\n", + devname, strerror(errno)); +@@ -2569,7 +2569,7 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num) + } + if (mustfree) + free(sb); +- if (lseek64(fd, offset<<9, 0) < 0) { ++ if (lseek(fd, offset<<9, 0) < 0) { + pr_err("lseek fails\n"); + ret = -1; + } +diff --git a/swap_super.c b/swap_super.c +index b6db5743d572..15021bd18083 100644 +--- a/swap_super.c ++++ b/swap_super.c +@@ -16,7 +16,7 @@ + + #define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS) + +-extern long long lseek64(int, long long, int); ++#define __USE_LARGEFILE64 1 + + int main(int argc, char *argv[]) + { +@@ -38,10 +38,9 @@ int main(int argc, char *argv[]) + exit(1); + } + offset = MD_NEW_SIZE_SECTORS(size) * 512LL; +- if (lseek64(fd, offset, 0) < 0LL) { +- perror("lseek64"); ++ if (lseek(fd, offset, 0) < 0LL) + exit(1); +- } ++ + if (read(fd, super, 4096) != 4096) { + perror("read"); + exit(1); +@@ -68,10 +67,9 @@ int main(int argc, char *argv[]) + super[32*4+10*4 +i] = t; + } + +- if (lseek64(fd, offset, 0) < 0LL) { +- perror("lseek64"); ++ if (lseek(fd, offset, 0) < 0LL) + exit(1); +- } ++ + if (write(fd, super, 4096) != 4096) { + perror("write"); + exit(1); +diff --git a/util.c b/util.c +index 0f77521149f8..43d1c119d013 100644 +--- a/util.c ++++ b/util.c +@@ -2456,7 +2456,7 @@ int zero_disk_range(int fd, unsigned long long sector, size_t count) + return -1; + } + +- if (lseek64(fd, sector * 512, SEEK_SET) < 0) { ++ if (lseek(fd, sector * 512, SEEK_SET) < 0) { + ret = -errno; + pr_err("Failed to seek offset for zeroing\n"); + goto out; +-- +2.50.1 + diff --git a/0056-build-deps-bump-actions-checkout-from-4-to-5.patch b/0056-build-deps-bump-actions-checkout-from-4-to-5.patch new file mode 100644 index 0000000..e902c58 --- /dev/null +++ b/0056-build-deps-bump-actions-checkout-from-4-to-5.patch @@ -0,0 +1,68 @@ +From d764c4829947923142a83251296d04edaee7d2f7 Mon Sep 17 00:00:00 2001 +From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> +Date: Tue, 12 Aug 2025 21:18:44 +0000 +Subject: [PATCH 56/74] build(deps): bump actions/checkout from 4 to 5 + +Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. +- [Release notes](https://github.com/actions/checkout/releases) +- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) +- [Commits](https://github.com/actions/checkout/compare/v4...v5) + +--- +updated-dependencies: +- dependency-name: actions/checkout + dependency-version: '5' + dependency-type: direct:production + update-type: version-update:semver-major +... + +Signed-off-by: dependabot[bot] +--- + .github/workflows/review.yml | 4 ++-- + .github/workflows/tests.yml | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml +index e5fbf4eef4c5..098798b1b4e8 100644 +--- a/.github/workflows/review.yml ++++ b/.github/workflows/review.yml +@@ -12,7 +12,7 @@ jobs: + # gcc-versions are used to test up to 5 years old + gcc-version: [9, 10, 11, 12, 13, 14] + steps: +- - uses: actions/checkout@v4 ++ - uses: actions/checkout@v5 + - name: 'Add ubuntu repository and install dependencies' + run: .github/tools/install_ubuntu_packages.sh ${{ matrix.gcc-version }} + - name: 'Check if gcc was installed correctly' +@@ -35,7 +35,7 @@ jobs: + runs-on: ubuntu-latest + name: checkpatch review + steps: +- - uses: actions/checkout@v4 ++ - uses: actions/checkout@v5 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 +diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml +index a07e320b03c4..3892e56d4127 100644 +--- a/.github/workflows/tests.yml ++++ b/.github/workflows/tests.yml +@@ -18,12 +18,12 @@ jobs: + timeout-minutes: 150 + name: upstream tests + steps: +- - uses: actions/checkout@v4 ++ - uses: actions/checkout@v5 + if: ${{ github.event_name == 'pull_request' }} + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 +- - uses: actions/checkout@v4 ++ - uses: actions/checkout@v5 + if: ${{ github.event_name == 'schedule' }} + with: + ref: main +-- +2.50.1 + diff --git a/0057-systemd-use-Type-simple-for-mdcheck-services.patch b/0057-systemd-use-Type-simple-for-mdcheck-services.patch new file mode 100644 index 0000000..c33e57f --- /dev/null +++ b/0057-systemd-use-Type-simple-for-mdcheck-services.patch @@ -0,0 +1,48 @@ +From 191957c3e4f8bcc3fdc251067e523732749f75cd Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 13 Aug 2025 19:28:08 +0200 +Subject: [PATCH 57/74] systemd: use "Type=simple" for mdcheck services + +"Type=oneshot" means that systemd considers the unit as started when the +started process exits. But the "mdcheck" script may run for several +hours. Thus systemd will regard the unit as "activating" all the +time. This can be easily tested by running "systemctl start +mdcheck_start.service" manually. The systemctl command will not finish +until the mdcheck utility has finished or Ctrl-C is typed, which is +broken. + +Use "Type=simple" instead. + +Signed-off-by: Martin Wilck +--- + systemd/mdcheck_continue.service | 2 +- + systemd/mdcheck_start.service | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/systemd/mdcheck_continue.service b/systemd/mdcheck_continue.service +index 70892a1f6018..cd12db850e42 100644 +--- a/systemd/mdcheck_continue.service ++++ b/systemd/mdcheck_continue.service +@@ -11,6 +11,6 @@ ConditionPathExistsGlob=/var/lib/mdcheck/MD_UUID_* + Documentation=man:mdadm(8) + + [Service] +-Type=oneshot ++Type=simple + Environment="MDADM_CHECK_DURATION=6 hours" + ExecStart=/usr/share/mdadm/mdcheck --continue --duration ${MDADM_CHECK_DURATION} +diff --git a/systemd/mdcheck_start.service b/systemd/mdcheck_start.service +index fc4fc4388c6c..16ba6b67a1ce 100644 +--- a/systemd/mdcheck_start.service ++++ b/systemd/mdcheck_start.service +@@ -11,6 +11,6 @@ Wants=mdcheck_continue.timer + Documentation=man:mdadm(8) + + [Service] +-Type=oneshot ++Type=simple + Environment="MDADM_CHECK_DURATION=6 hours" + ExecStart=/usr/share/mdadm/mdcheck --duration ${MDADM_CHECK_DURATION} +-- +2.50.1 + diff --git a/0058-mdcheck-reset-sync_action-to-idle-when-stopped.patch b/0058-mdcheck-reset-sync_action-to-idle-when-stopped.patch new file mode 100644 index 0000000..0412c18 --- /dev/null +++ b/0058-mdcheck-reset-sync_action-to-idle-when-stopped.patch @@ -0,0 +1,95 @@ +From 303362bee868049959a0a3421080e685ff7cc4b2 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 13 Aug 2025 21:01:30 +0200 +Subject: [PATCH 58/74] mdcheck: reset sync_action to "idle" when stopped + +When the mdcheck script stops because the pre-set duration is exceeded, it +will also set the sync action in the kernel to "idle". But when it is +stopped by a signal (e.g. when the systemd service running it is stopped), +it doesn't. This is inconsistent behavior. + +Move the code that switches the sync_action to "idle" into a cleanup +function that is always executed on exit. This requires separate "trap" +statements for EXIT(0) and signals, because otherwise a race condition may +arise between the cleanup code and the script body. + +Signed-off-by: Martin Wilck +--- + misc/mdcheck | 50 +++++++++++++++++++++++++++----------------------- + 1 file changed, 27 insertions(+), 23 deletions(-) + +diff --git a/misc/mdcheck b/misc/mdcheck +index 5f068121b924..aa2096612e56 100644 +--- a/misc/mdcheck ++++ b/misc/mdcheck +@@ -66,15 +66,40 @@ shift + + # We need a temp file occasionally... + tmp=/var/lib/mdcheck/.md-check-$$ +-trap 'rm -f "$tmp"' 0 2 3 15 ++cnt=0 ++ ++cleanup() { ++ # We've waited, and there are still checks running. ++ # Time to stop them. ++ for i in `eval echo {1..$cnt}` ++ do ++ eval fl=\$MD_${i}_fl ++ eval sys=\$MD_${i}_sys ++ eval dev=\$MD_${i}_dev ++ ++ if [ -z "$fl" ]; then continue; fi ++ ++ if [ "`cat $sys/md/sync_action`" != 'check' ] ++ then ++ eval MD_${i}_fl= ++ rm -f $fl ++ continue; ++ fi ++ echo idle > $sys/md/sync_action ++ cat $sys/md/sync_min > $fl ++ logger -p daemon.info pause checking $dev at `cat $fl` ++ done ++ rm -f "$tmp" ++} + ++trap 'exit 129' 2 3 15 ++trap 'cleanup' 0 + + # firstly, clean out really old state files + mkdir -p /var/lib/mdcheck + find /var/lib/mdcheck -name "MD_UUID*" -type f -mtime +180 -exec rm {} \; + + # Now look at each md device. +-cnt=0 + for dev in /dev/md?* + do + [ -e "$dev" ] || continue +@@ -149,24 +174,3 @@ do + fi + sleep 220 + done +- +-# We've waited, and there are still checks running. +-# Time to stop them. +-for i in `eval echo {1..$cnt}` +-do +- eval fl=\$MD_${i}_fl +- eval sys=\$MD_${i}_sys +- eval dev=\$MD_${i}_dev +- +- if [ -z "$fl" ]; then continue; fi +- +- if [ "`cat $sys/md/sync_action`" != 'check' ] +- then +- eval MD_${i}_fl= +- rm -f $fl +- continue; +- fi +- echo idle > $sys/md/sync_action +- cat $sys/md/sync_min > $fl +- logger -p daemon.info pause checking $dev at `cat $fl` +-done +-- +2.50.1 + diff --git a/0059-mdcheck-make-sure-signals-are-processed-immediately.patch b/0059-mdcheck-make-sure-signals-are-processed-immediately.patch new file mode 100644 index 0000000..01442b1 --- /dev/null +++ b/0059-mdcheck-make-sure-signals-are-processed-immediately.patch @@ -0,0 +1,30 @@ +From a40a6a7e57095ad3ed20f827c2ad992cf7658699 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 13 Aug 2025 21:07:36 +0200 +Subject: [PATCH 59/74] mdcheck: make sure signals are processed immediately + +"systemctl stop mdcheck_start.service" may hang for a long time, +because the shell doesn't handle signals until the sleep process in +the foreground returns. Fix this by starting sleep in the background +and waiting for it (the built-in "wait" receives the signal). + +Signed-off-by: Martin Wilck +--- + misc/mdcheck | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/misc/mdcheck b/misc/mdcheck +index aa2096612e56..398a1ea607ca 100644 +--- a/misc/mdcheck ++++ b/misc/mdcheck +@@ -172,5 +172,6 @@ do + systemctl stop mdcheck_continue.timer + exit 0; + fi +- sleep 220 ++ sleep 220 & ++ wait $! + done +-- +2.50.1 + diff --git a/0060-systemd-start-mdcheck_continue.timer-before-mdcheck_.patch b/0060-systemd-start-mdcheck_continue.timer-before-mdcheck_.patch new file mode 100644 index 0000000..1b08602 --- /dev/null +++ b/0060-systemd-start-mdcheck_continue.timer-before-mdcheck_.patch @@ -0,0 +1,50 @@ +From 8aa4ea95db3525c2d381ddf65da69ab549c814d4 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 13 Aug 2025 22:12:53 +0200 +Subject: [PATCH 60/74] systemd: start mdcheck_continue.timer before + mdcheck_start.timer + +In the (unlikely but possible) case that a previously started md check +hasn't finished on the first Sunday of the following month, +mdcheck_start.service will start the scan from position 0, which is +probably not desired. + +Have mdcheck_continue.service start first, so that it will pick up the +check where it left off, and that the subsequent mdcheck_start.service will +do nothing. + +Signed-off-by: Martin Wilck +--- + systemd/mdcheck_continue.timer | 2 +- + systemd/mdcheck_start.timer | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/systemd/mdcheck_continue.timer b/systemd/mdcheck_continue.timer +index dba1074c1f44..0ab5d2ebecb5 100644 +--- a/systemd/mdcheck_continue.timer ++++ b/systemd/mdcheck_continue.timer +@@ -9,7 +9,7 @@ + Description=MD array scrubbing - continuation + + [Timer] +-OnCalendar= 1:05:00 ++OnCalendar= 1:00:00 + + [Install] + WantedBy= mdmonitor.service +diff --git a/systemd/mdcheck_start.timer b/systemd/mdcheck_start.timer +index 9e7e02ab7333..1b8f3f20878b 100644 +--- a/systemd/mdcheck_start.timer ++++ b/systemd/mdcheck_start.timer +@@ -9,7 +9,7 @@ + Description=MD array scrubbing + + [Timer] +-OnCalendar=Sun *-*-1..7 1:00:00 ++OnCalendar=Sun *-*-1..7 1:05:00 + + [Install] + WantedBy= mdmonitor.service +-- +2.50.1 + diff --git a/0061-Fix-monitor-scan-with-relative-ARRAY-devnames.patch b/0061-Fix-monitor-scan-with-relative-ARRAY-devnames.patch new file mode 100644 index 0000000..b0acbfb --- /dev/null +++ b/0061-Fix-monitor-scan-with-relative-ARRAY-devnames.patch @@ -0,0 +1,39 @@ +From 574b11602fb210c5b3e5f6fe460ab21e7c7d998c Mon Sep 17 00:00:00 2001 +From: QRPp +Date: Mon, 1 Sep 2025 21:33:57 +0100 +Subject: [PATCH 61/74] Fix --monitor --scan with relative ARRAY devnames + +Since commit e702f392959d ("Mdmonitor: Fix segfault"), when configuration +files used non-absolute ARRAY device names, commands like `mdadm --monitor +--scan` failed with `mdadm: error opening devname: No such file or +directory` unless run from the `/dev/md` directory. + +Signed-off-by: QRPp +--- + mdmonitor.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/mdmonitor.c b/mdmonitor.c +index ea35d98ede30..22b0a818f9bd 100644 +--- a/mdmonitor.c ++++ b/mdmonitor.c +@@ -254,12 +254,14 @@ int Monitor(struct mddev_dev *devlist, + continue; + if (is_devname_ignore(mdlist->devname) == true) + continue; +- if (!is_mddev(mdlist->devname)) +- continue; + + st = xcalloc(1, sizeof *st); + snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), DEV_MD_DIR "%s", + basename(mdlist->devname)); ++ if (!is_mddev(st->devname)) { ++ free(st); ++ continue; ++ } + st->next = statelist; + st->devnm[0] = 0; + st->percent = RESYNC_UNKNOWN; +-- +2.50.1 + diff --git a/0062-Re-enable-mdadm-monitor-.-for-dev-mdX.patch b/0062-Re-enable-mdadm-monitor-.-for-dev-mdX.patch new file mode 100644 index 0000000..f6bdc1a --- /dev/null +++ b/0062-Re-enable-mdadm-monitor-.-for-dev-mdX.patch @@ -0,0 +1,108 @@ +From 456c6bed0b9e0866c75f0f7c8579d5f4f3f3e966 Mon Sep 17 00:00:00 2001 +From: "Dr. Joachim Schneider" +Date: Sat, 6 Sep 2025 20:28:07 +0200 +Subject: [PATCH 62/74] Re-enable mdadm --monitor ... for /dev/mdX + +This fixes a regression introduced with +commit 84d969be8f6d ("Monitor: use snprintf to fill device name"): + +With this fix + + mdadm --monitor --scan -1 -p + +is possible again for /dev/mdX without symlink in /dev/md/. + +The bug can be reproduced by these steps: + +(a) Create block devices for testing: + + $ dd if=/dev/zero of=/tmp/d0.bin bs=1M count=16 + $ dd if=/dev/zero of=/tmp/d1.bin bs=1M count=16 + + $ losetup -f /tmp/d0.bin + $ losetup -f /tmp/d1.bin + $ losetup + NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO LOG-SEC + /dev/loop1 0 0 0 0 /tmp/d1.bin 0 512 + /dev/loop0 0 0 0 0 /tmp/d0.bin 0 512 + +(b) Create RAID-1 array '/dev/md0': + + $ mdadm --create /dev/md0 --level=1 --raid-devices=2 \ + /dev/loop0 /dev/loop1 + ... + mdadm: array /dev/md0 started. + +(c) Check: + + $ cat /proc/mdstat + Personalities : [raid1] + md0 : active raid1 loop1[1] loop0[0] + 15360 blocks super 1.2 [2/2] [UU] + + unused devices: + +(d) Create 'mdadm.conf': + + $ mdadm --detail --scan > /tmp/mdadm.conf + $ cat /tmp/mdadm.conf + ARRAY /dev/md0 metadata=1.2 UUID=c0280f55:9c32e4ff:34f85ea3:08d1331b + +(e) Use this bash script ('/tmp/report') for 'mdadm --monitor': + + [[ $# -lt 2 ]] && exit 0 + + problem="$1" + shift + array="$1" + shift + args="$*" + + echo "MD REPORT: ${problem} with ${array}: ${args}" + +(f) Call mdamd in monitor mode: + + $ mdadm --monitor -c /tmp/mdadm.conf --scan -1 -p /tmp/report + + Without the fix one gets this output: + + mdadm: DeviceDisappeared event detected on md device /dev/md/md0 + MD REPORT: DeviceDisappeared with /dev/md/md0: + mdadm: NewArray event detected on md device /dev/md0 + MD REPORT: NewArray with /dev/md0: + + Only the output of the 'report'-script: + + $ mdadm --monitor -c /tmp/mdadm.conf --scan -1 \ + -p /tmp/report 2>/dev/null + MD REPORT: DeviceDisappeared with /dev/md/md0: + MD REPORT: NewArray with /dev/md0: + + With the fix no (warning) output is produced: + + $ /tmp/mdadm-FIXED --monitor -c /tmp/mdadm.conf --scan -1 \ + -p /tmp/report + +Signed-off-by: Dr. Joachim Schneider +--- + mdmonitor.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/mdmonitor.c b/mdmonitor.c +index 22b0a818f9bd..314dafb4588b 100644 +--- a/mdmonitor.c ++++ b/mdmonitor.c +@@ -256,8 +256,8 @@ int Monitor(struct mddev_dev *devlist, + continue; + + st = xcalloc(1, sizeof *st); +- snprintf(st->devname, MD_NAME_MAX + sizeof(DEV_MD_DIR), DEV_MD_DIR "%s", +- basename(mdlist->devname)); ++ snprintf(st->devname, sizeof(st->devname), "%s%s", ++ '/' == *mdlist->devname ? "" : DEV_MD_DIR, mdlist->devname); + if (!is_mddev(st->devname)) { + free(st); + continue; +-- +2.50.1 + diff --git a/0063-Fix-meaing-typo-in-mdadm.conf-example.patch b/0063-Fix-meaing-typo-in-mdadm.conf-example.patch new file mode 100644 index 0000000..74fb550 --- /dev/null +++ b/0063-Fix-meaing-typo-in-mdadm.conf-example.patch @@ -0,0 +1,28 @@ +From 388ef731dccff3b8da369c1968af7daf9b32fe1d Mon Sep 17 00:00:00 2001 +From: Amon Bune +Date: Mon, 29 Sep 2025 19:16:00 +0200 +Subject: [PATCH 63/74] Fix 'meaing' typo in mdadm.conf-example + +Fix typo in mdadm.conf example file + +Signed-off-by: Amon Bune +--- + documentation/mdadm.conf-example | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/documentation/mdadm.conf-example b/documentation/mdadm.conf-example +index 35a75d128a69..29dd55ab3148 100644 +--- a/documentation/mdadm.conf-example ++++ b/documentation/mdadm.conf-example +@@ -28,7 +28,7 @@ + # + # + # The AUTO line can control which arrays get assembled by auto-assembly, +-# meaing either "mdadm -As" when there are no 'ARRAY' lines in this file, ++# meaning either "mdadm -As" when there are no 'ARRAY' lines in this file, + # or "mdadm --incremental" when the array found is not listed in this file. + # By default, all arrays that are found are assembled. + # If you want to ignore all DDF arrays (maybe they are managed by dmraid), +-- +2.50.1 + diff --git a/0064-Update-raid6check-man-page.patch b/0064-Update-raid6check-man-page.patch new file mode 100644 index 0000000..bbe93d3 --- /dev/null +++ b/0064-Update-raid6check-man-page.patch @@ -0,0 +1,121 @@ +From 2a63857e9506324ec3ef69746344de08f55e6d77 Mon Sep 17 00:00:00 2001 +From: Mingye Wang +Date: Sat, 20 Sep 2025 14:21:40 +0800 +Subject: [PATCH 64/74] Update raid6check man page + +This adds autorepair and manual repair modes, which have been here for about 12 years. The description of the manual repair mode can probably use more work. + + +Signed-off-by: Mingye Wang +--- + raid6check.8 | 61 +++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 17 deletions(-) + +diff --git a/raid6check.8 b/raid6check.8 +index 8999ca89e951..f6acb288834b 100644 +--- a/raid6check.8 ++++ b/raid6check.8 +@@ -13,48 +13,72 @@ Linux Software RAID + + .SH SYNOPSIS + +-.BI raid6check " " ++.BI raid6check " " ++.RB [ autorepair ] ++ ++.BI raid6check " " repair " " ++.I "" + + .SH DESCRIPTION + RAID6 devices in which one single component drive has errors can use + the double parity in order to find out which component drive. +-The "raid6check" tool checks, for each stripe, the double parity +-consistency, reports mismatches and, if possible, which ++The "raid6check" tool has two modes: check mode and repair mode. ++ ++"raid6check" requires a non-degraded RAID6 MD device as first ++parameter. If the given MD device is not a RAID6, "raid6check" will, ++of course, not continue. ++ ++If the RAID6 MD device is degraded, "raid6check" will report ++an error and it will not proceed further. ++ ++.SS Check mode ++In the check mode, the "raid6check" tool checks, for each stripe, the ++double parity consistency, reports mismatches and, if possible, which + component drive has the mismatch. + Since it works at stripe level, it can report different drives with + mismatches at different stripes. + +-"raid6check" requires a non-degraded RAID6 MD device as first +-parameter, a starting stripe (usually 0) and the number of stripes +-to be checked. ++In addition to the MD device, "raid6check" requries a starting stripe ++(usually 0) and the number of stripes to be checked. + If this third parameter is also 0, it will check the array up to + the end. ++If the fourth parameter is "autorepair", it will overwrite single-slot ++errors. + + "raid6check" will start printing information about the RAID6, then + for each stripe, it will report the parity rotation status. + In case of parity mismatches, "raid6check" reports, if possible, +-which component drive could be responsible. Otherwise it reports +-that it is not possible to find the component drive. +- +-If the given MD device is not a RAID6, "raid6check" will, of +-course, not continue. ++which component drive could be responsible. ++Otherwise it reports that it is not possible to find the component drive. + +-If the RAID6 MD device is degraded, "raid6check" will report +-an error and it will not proceed further. +- +-No write operations are performed on the array or the components. ++No write operations are performed on the array or the components, ++unless "autorepair" is specified. + Furthermore, the checked array can be online and in use during + the operation of "raid6check". + ++.SS Repair mode ++In the repair mode, the "raid6check" tool checks the given stripe. ++If inconsistencies are found, it attempts to repair the strip assuming ++that the two given slots are incorrect. ++ ++-1 may be used to specify parity P and -2 parity Q. ++ + .SH EXAMPLES + + .B " raid6check /dev/md0 0 0" + .br + This will check /dev/md0 from start to end. + +-.B " raid6check /dev/md3 0 1" ++.B " raid6check /dev/md3 0 1 autorepair" ++.br ++This will check the first stripe of /dev/md3. ++Any error will be reported, and if single-slot, repaired. ++ ++.B " raid6check /dev/md3 0 repair 1 -1 -2" + .br + This will check the first stripe of /dev/md3. ++If any inconsistencies are found, repair is performed assuming ++the two parities are incorrect. + + .B " raid6check /dev/md1 1000 0" + .br +@@ -76,7 +100,10 @@ Furthermore, the sysfs interface is needed in order to find out + the RAID6 parameters. + + .SH BUGS +-Negative parameters can lead to unexpected results. ++Negative stripe parameters can lead to unexpected results due to ++strtoull. ++(Negative slot numbers should work for Q [-1] and P [-2] but ++currently involve compiler-defined behavior.) + + It is not clear what will happen if the RAID6 MD device gets + degraded during the check. +-- +2.50.1 + diff --git a/0065-udev-Fix-memleak.patch b/0065-udev-Fix-memleak.patch new file mode 100644 index 0000000..780ed4e --- /dev/null +++ b/0065-udev-Fix-memleak.patch @@ -0,0 +1,41 @@ +From d478aff31f466d126eaa5b018c93654b58047b40 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 23 Sep 2025 08:06:12 +0200 +Subject: [PATCH 65/74] udev: Fix memleak + +According to manual: +On success, udev_monitor_receive_device() returns a pointer to a newly +referenced device that was received via the monitor. The caller is +responsible to drop this reference when done. + +Signed-off-by: Mariusz Tkaczyk +--- + udev.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/udev.c b/udev.c +index 961ca970d460..f857c723e4a1 100644 +--- a/udev.c ++++ b/udev.c +@@ -147,9 +147,16 @@ enum udev_status udev_wait_for_events(int seconds) + tv.tv_sec = seconds; + tv.tv_usec = 0; + +- if (select(fd + 1, &readfds, NULL, NULL, &tv) > 0 && FD_ISSET(fd, &readfds)) +- if (udev_monitor_receive_device(udev_monitor)) ++ if (select(fd + 1, &readfds, NULL, NULL, &tv) > 0 && FD_ISSET(fd, &readfds)) { ++ struct udev_device *dev = udev_monitor_receive_device(udev_monitor); ++ ++ if (dev) { ++ udev_device_unref(dev); + return UDEV_STATUS_SUCCESS; /* event detected */ ++ } else { ++ return UDEV_STATUS_ERROR; ++ } ++ } + return UDEV_STATUS_TIMEOUT; + } + #endif +-- +2.50.1 + diff --git a/0066-mdadm-modify-the-order-of-free_super_xxx-to-avoid-me.patch b/0066-mdadm-modify-the-order-of-free_super_xxx-to-avoid-me.patch new file mode 100644 index 0000000..a43f935 --- /dev/null +++ b/0066-mdadm-modify-the-order-of-free_super_xxx-to-avoid-me.patch @@ -0,0 +1,60 @@ +From c425cdc9297a1f27f664b19a9d9386b43d92f7b3 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Tue, 14 Oct 2025 10:23:46 +0800 +Subject: [PATCH 66/74] mdadm: modify the order of free_super_xxx() to avoid + memory leak + +free_super_xx() should be executed at the load_super_xx() entry. +When there are additional checks, it may lead to supertype not being +released, resulting in a memory leak. + +Signed-off-by: Wu Guanghao +--- + super-ddf.c | 4 ++-- + super-intel.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index f46217206437..7b38f9125134 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -1324,6 +1324,8 @@ static int load_super_ddf(struct supertype *st, int fd, + struct ddf_super *super; + int rv; + ++ free_super_ddf(st); ++ + if (get_dev_size(fd, devname, &dsize) == 0) + return 1; + +@@ -1345,8 +1347,6 @@ static int load_super_ddf(struct supertype *st, int fd, + return 1; + } + +- free_super_ddf(st); +- + if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) { + pr_err("malloc of %zu failed.\n", + sizeof(*super)); +diff --git a/super-intel.c b/super-intel.c +index 7162327ecdf2..5a4a2eb1c949 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5471,12 +5471,12 @@ static int load_super_imsm(struct supertype *st, int fd, char *devname) + int rv; + int retry; + ++ free_super_imsm(st); ++ + if (test_partition(fd)) + /* IMSM not allowed on partitions */ + return 1; + +- free_super_imsm(st); +- + super = alloc_super(); + if (!super) + return 1; +-- +2.50.1 + diff --git a/0067-mdadm-Fix-memory-leak-issue-in-check_raid.patch b/0067-mdadm-Fix-memory-leak-issue-in-check_raid.patch new file mode 100644 index 0000000..9dfc5ca --- /dev/null +++ b/0067-mdadm-Fix-memory-leak-issue-in-check_raid.patch @@ -0,0 +1,28 @@ +From 7cb225b4949ca63f9e8298a7feb00e04c71c7e9e Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Tue, 14 Oct 2025 10:50:18 +0800 +Subject: [PATCH 67/74] mdadm: Fix memory leak issue in check_raid() + +check_raid() alloc for st, but did not release it when exiting. + +Signed-off-by: Wu Guanghao +--- + util.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util.c b/util.c +index 43d1c119d013..5d6fe800d666 100644 +--- a/util.c ++++ b/util.c +@@ -693,6 +693,8 @@ int check_raid(int fd, char *name) + /* Looks like GPT or MBR */ + pr_err("partition table exists on %s\n", name); + } ++ ++ free(st); + return 1; + } + +-- +2.50.1 + diff --git a/0068-mdadm-Fix-memory-leak-issue-in-Manage_stop.patch b/0068-mdadm-Fix-memory-leak-issue-in-Manage_stop.patch new file mode 100644 index 0000000..41e1a67 --- /dev/null +++ b/0068-mdadm-Fix-memory-leak-issue-in-Manage_stop.patch @@ -0,0 +1,29 @@ +From b67f6f01c8c1638bca5c2c9327720b2b8197768f Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Tue, 14 Oct 2025 11:29:37 +0800 +Subject: [PATCH 68/74] mdadm: Fix memory leak issue in Manage_stop() + +The local variable 'mds' allocated in Manage_stop() is only released +under specific conditions in the for loop. This can lead to memory leak +when under othe conditions. + +Signed-off-by: Wu Guanghao +--- + Manage.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Manage.c b/Manage.c +index 22b1f52b7dc7..b53e65e9cea2 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -286,6 +286,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + rv = 1; + goto out; + } ++ free_mdstat(mds); + } + + /* If the array is undergoing a reshape which changes the number +-- +2.50.1 + diff --git a/0069-mdadm-Fix-memory-leak-issue-in-load_ddf_local.patch b/0069-mdadm-Fix-memory-leak-issue-in-load_ddf_local.patch new file mode 100644 index 0000000..649249c --- /dev/null +++ b/0069-mdadm-Fix-memory-leak-issue-in-load_ddf_local.patch @@ -0,0 +1,29 @@ +From ca10248139610ffb53fe90224333513dcc3ca155 Mon Sep 17 00:00:00 2001 +From: Wu Guanghao +Date: Tue, 14 Oct 2025 11:49:11 +0800 +Subject: [PATCH 69/74] mdadm: Fix memory leak issue in load_ddf_local() + +dl->devname might be allocated space through xstrdup(). Before an +abnormal exit, it needs to be checked and released. + +Signed-off-by: Wu Guanghao +--- + super-ddf.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/super-ddf.c b/super-ddf.c +index 7b38f9125134..657c53abe729 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -1208,6 +1208,8 @@ static int load_ddf_local(int fd, struct ddf_super *super, + dl->devname = devname ? xstrdup(devname) : NULL; + + if (fstat(fd, &stb) != 0) { ++ if (dl->devname) ++ free(dl->devname); + free(dl); + return 1; + } +-- +2.50.1 + diff --git a/0070-mdadm-Incremental-wait-a-while-before-removing-a-mem.patch b/0070-mdadm-Incremental-wait-a-while-before-removing-a-mem.patch new file mode 100644 index 0000000..9db2e68 --- /dev/null +++ b/0070-mdadm-Incremental-wait-a-while-before-removing-a-mem.patch @@ -0,0 +1,67 @@ +From 804a6a6b5747eed8794a6b007279dc8e09432270 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 17 Oct 2025 17:04:25 +0800 +Subject: [PATCH 70/74] mdadm/Incremental: wait a while before removing a + member + +We encountered a regression that member disk can't be removed in +incremental remove mode: +mdadm -If /dev/loop0 +mdadm: Cannot remove member device loop0 from md127 + +It doesn't allow to remove a member if sync thread is running. mdadm -If +sets member disk faulty first, then it removes the disk. If sync thread +is running, it will be interrupted by setting a member faulty. But the sync +thread hasn't been reapped. So it needs to wait a while to let kernel to +reap sync thread. + +Signed-off-by: Xiao Ni +--- + Incremental.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index ba3810e6157f..f30697fa684f 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1715,6 +1715,7 @@ int Incremental_remove(char *devname, char *id_path, int verbose) + struct mdstat_ent *ent; + struct mdinfo mdi; + int mdfd = -1; ++ int retry = 25; + + if (strcmp(devnm, devname) != 0) + if (!is_devnode_path(devname)) { +@@ -1790,11 +1791,26 @@ int Incremental_remove(char *devname, char *id_path, int verbose) + + /* Native arrays are handled separatelly to provide more detailed error handling */ + rv = sysfs_set_memb_state(ent->devnm, devnm, MEMB_STATE_FAULTY); +- if (rv && verbose >= 0) +- pr_err("Cannot fail member device %s in array %s.\n", devnm, ent->devnm); ++ if (rv) { ++ if (verbose >= 0) ++ pr_err("Cannot fail member device %s in array %s.\n", devnm, ent->devnm); ++ goto out; ++ } + +- if (rv == MDADM_STATUS_SUCCESS) ++ /* ++ * If resync/recovery is running, sync thread is interrupted by setting member faulty. ++ * And it needs to wait some time to let kernel to reap sync thread. If not, it will ++ * fail to remove it. ++ */ ++ while (retry) { + rv = sysfs_set_memb_state(ent->devnm, devnm, MEMB_STATE_REMOVE); ++ if (rv) { ++ sleep_for(0, MSEC_TO_NSEC(200), true); ++ retry--; ++ continue; ++ } ++ break; ++ } + + if (rv && verbose >= 0) + pr_err("Cannot remove member device %s from %s.\n", devnm, ent->devnm); +-- +2.50.1 + diff --git a/0071-mdadm-sysfs-close-fd-before-return.patch b/0071-mdadm-sysfs-close-fd-before-return.patch new file mode 100644 index 0000000..6f02512 --- /dev/null +++ b/0071-mdadm-sysfs-close-fd-before-return.patch @@ -0,0 +1,39 @@ +From abb9a2b097c940251673eba5f074638b10ceb26e Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 17 Oct 2025 17:06:13 +0800 +Subject: [PATCH 71/74] mdadm/sysfs: close fd before return + +It needs to close fd before returning the function. + +Signed-off-by: Xiao Ni +--- + sysfs.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sysfs.c b/sysfs.c +index c030d634b155..e60adc9f549f 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -160,6 +160,7 @@ mdadm_status_t sysfs_set_memb_state_fd(int fd, memb_state_t state, int *err) + mdadm_status_t sysfs_set_memb_state(char *array_devnm, char *memb_devnm, memb_state_t state) + { + int state_fd = sysfs_open_memb_attr(array_devnm, memb_devnm, "state", O_RDWR); ++ mdadm_status_t status; + + if (!is_fd_valid(state_fd)) { + pr_err("Cannot open file descriptor to %s in array %s, aborting.\n", +@@ -167,9 +168,9 @@ mdadm_status_t sysfs_set_memb_state(char *array_devnm, char *memb_devnm, memb_st + return MDADM_STATUS_ERROR; + } + +- return sysfs_set_memb_state_fd(state_fd, state, NULL); +- ++ status = sysfs_set_memb_state_fd(state_fd, state, NULL); + close_fd(&state_fd); ++ return status; + } + + /** +-- +2.50.1 + diff --git a/0072-Update-README.md.patch b/0072-Update-README.md.patch new file mode 100644 index 0000000..e2aebb1 --- /dev/null +++ b/0072-Update-README.md.patch @@ -0,0 +1,28 @@ +From 868376e030349417bc6c858dec565ae0d9808b60 Mon Sep 17 00:00:00 2001 +From: Guilherme Ferreira <16529503+piradata@users.noreply.github.com> +Date: Sat, 25 Oct 2025 20:15:53 -0300 +Subject: [PATCH 72/74] Update README.md + +just updated the link to the new one, the old pointed to an archive page + +Signed-off-by: Guilherme Ferreira <16529503+piradata@users.noreply.github.com> +--- + README.md | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/README.md b/README.md +index ba611ec5fb7b..9289f50ac776 100644 +--- a/README.md ++++ b/README.md +@@ -1,7 +1,7 @@ + **mdadm** is a utility used to create and manage **software RAID** devices implemented through + **Multiple devices driver (MD)** in kernel. It supports following RAID metadata formats: + +-* [Linux native RAID](https://raid.wiki.kernel.org/index.php/RAID_superblock_formats): ++* [Linux native RAID](https://docs.kernel.org/admin-guide/md.html#superblock-formats): + + Known as **native** or **native RAID**. First and default metadata format. Metadata management + is implemented in **MD driver**. +-- +2.50.1 + diff --git a/0073-mdadm-Create-array-with-sync-del-gendisk-mode.patch b/0073-mdadm-Create-array-with-sync-del-gendisk-mode.patch new file mode 100644 index 0000000..778494e --- /dev/null +++ b/0073-mdadm-Create-array-with-sync-del-gendisk-mode.patch @@ -0,0 +1,120 @@ +From d354d314db86379f18a4ccd35af9f6e56635b61d Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 24 Oct 2025 15:17:29 +0800 +Subject: [PATCH 73/74] mdadm: Create array with sync del gendisk mode + +kernel patch 9e59d609763f ('md: call del_gendisk in control path') calls +del_gendisk in sync way. After the patch mentioned just now, device node +(/dev/md0 .e.g) will disappear after mdadm --stop command. It resolves the +problem raid can be created again because raid can be created when opening +device node. Then regression tests will be interrupted. + +But it causes an error when assembling array which has been fixed by pr182. +So people can't assemble array if they use new kernel and old mdadm. So +in kernel space, 25db5f284fb8 ('md: add legacy_async_del_gendisk mod') is +used to fix this problem. The default is async mode. + +async del mode will be removed in future. We'll start use sync del mode in +new mdadm version. So people will not see failure when upgrading to the +new mdadm version with sync del mode. + +Signed-off-by: Xiao Ni +--- + mdadm.h | 3 +++ + mdopen.c | 5 +++++ + util.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 53 insertions(+) + +diff --git a/mdadm.h b/mdadm.h +index 84bd2c915fc2..7dcb20ed1f34 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -141,6 +141,8 @@ struct dlm_lksb { + #define MDMON_DIR "/run/mdadm" + #endif /* MDMON_DIR */ + ++#define MD_MOD_ASYNC_DEL_GENDISK "legacy_async_del_gendisk" ++ + /* FAILED_SLOTS is where to save files storing recent removal of array + * member in order to allow future reuse of disk inserted in the same + * slot for array recovery +@@ -855,6 +857,7 @@ extern int restore_stripes(int *dest, unsigned long long *offsets, + unsigned long long start, unsigned long long length, + char *src_buf); + extern bool sysfs_is_libata_allow_tpm_enabled(const int verbose); ++extern bool init_md_mod_param(void); + + #ifndef Sendmail + #define Sendmail "/usr/lib/sendmail -t" +diff --git a/mdopen.c b/mdopen.c +index 57252b646137..b685603d6de5 100644 +--- a/mdopen.c ++++ b/mdopen.c +@@ -148,6 +148,11 @@ int create_mddev(char *dev, char *name, int trustworthy, + char devnm[32]; + char cbuf[400]; + ++ if (!init_md_mod_param()) { ++ pr_err("init md module parameters fail\n"); ++ return -1; ++ } ++ + if (!udev_is_available()) + block_udev = 0; + +diff --git a/util.c b/util.c +index 5d6fe800d666..146f38fddd82 100644 +--- a/util.c ++++ b/util.c +@@ -2559,3 +2559,48 @@ bool is_file(const char *path) + + return true; + } ++ ++bool set_md_mod_parameter(const char *name, const char *value) ++{ ++ char path[256]; ++ int fd; ++ bool ret = true; ++ ++ snprintf(path, sizeof(path), "/sys/module/md_mod/parameters/%s", name); ++ ++ fd = open(path, O_WRONLY); ++ if (fd < 0) { ++ pr_err("Can't open %s\n", path); ++ return false; ++ } ++ ++ if (write(fd, value, strlen(value)) != (ssize_t)strlen(value)) { ++ pr_err("Failed to write to %s\n", path); ++ ret = false; ++ } ++ ++ close(fd); ++ return ret; ++} ++ ++/* Init kernel md_mod parameters here if needed */ ++bool init_md_mod_param(void) ++{ ++ bool ret = true; ++ ++ /* ++ * In kernel 9e59d609763f calls del_gendisk in sync way. So device ++ * node can be removed after stop command. But it can introduce a ++ * regression which can be fixed by github pr182. New mdadm version ++ * with pr182 can work well with new kernel. But users who don't ++ * update mdadm and update to new kernel, they can't assemble array ++ * anymore. So kernel adds a kernel parameter legacy_async_del_gendisk ++ * and uses async as default. ++ * We'll use sync mode since 6.18 rather than async mode. So in future ++ * the kernel parameter will be removed. ++ */ ++ if (get_linux_version() >= 6018000) ++ ret = set_md_mod_parameter(MD_MOD_ASYNC_DEL_GENDISK, "N"); ++ ++ return ret; ++} +-- +2.50.1 + diff --git a/0074-mdadm-Assemble-alloc-superblock-in-Assemble.patch b/0074-mdadm-Assemble-alloc-superblock-in-Assemble.patch new file mode 100644 index 0000000..77aedfc --- /dev/null +++ b/0074-mdadm-Assemble-alloc-superblock-in-Assemble.patch @@ -0,0 +1,210 @@ +From 6fa6c4b915f6bc024cf481d137569a255001a84a Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Mon, 27 Oct 2025 08:15:38 +0800 +Subject: [PATCH 74/74] mdadm/Assemble: alloc superblock in Assemble + +Now it allocs superblock outside Assemble and frees the memory outside +Assemble. But the memory can be freed and realloc in Assemble. So freed +memory will be dereferenced outside Assemble. This patch moves the memory +management into Assemble. So it's more safe and the input arguments is +less. + +This can be reproduced by: +mdadm -CR /dev/md0 -l1 -n2 /dev/loop0 /dev/loop1 --assume-clean +mdadm -Ss +mdadm -A -e 1.2 /dev/md0 /dev/loop0 /dev/loop1 + +Signed-off-by: Xiao Ni +--- + Assemble.c | 47 ++++++++++++++++++++++++++++++++++------------- + mdadm.c | 12 +++++++----- + mdadm.h | 7 +++---- + 3 files changed, 44 insertions(+), 22 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 1949bf96c478..cfe01ee237bb 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1308,10 +1308,8 @@ static int start_array(int mdfd, + return 1; + } + +-int Assemble(struct supertype *st, char *mddev, +- struct mddev_ident *ident, +- struct mddev_dev *devlist, +- struct context *c) ++int Assemble(char *mddev, struct mddev_ident *ident, ++ struct mddev_dev *devlist, struct context *c) + { + /* + * The task of Assemble is to find a collection of +@@ -1398,6 +1396,7 @@ int Assemble(struct supertype *st, char *mddev, + char chosen_name[1024]; + struct map_ent *map = NULL; + struct map_ent *mp; ++ struct supertype *st = NULL; + + /* + * If any subdevs are listed, then any that don't +@@ -1418,6 +1417,15 @@ int Assemble(struct supertype *st, char *mddev, + return 1; + } + ++ if (c->metadata) { ++ for (i = 0; !st && superlist[i]; i++) ++ st = superlist[i]->match_metadata_desc(c->metadata); ++ if (!st) { ++ pr_err("unrecognised metadata identifier: %s\n", c->metadata); ++ return -EINVAL; ++ } ++ } ++ + if (devlist == NULL) + devlist = conf_get_devs(); + else if (mddev) +@@ -1439,11 +1447,15 @@ try_again: + st->ignore_hw_compat = 1; + num_devs = select_devices(devlist, ident, &st, &content, c, + inargv, auto_assem); +- if (num_devs < 0) +- return 1; ++ if (num_devs < 0) { ++ rv = 1; ++ goto free_st; ++ } + +- if (!st || !st->sb || !content) +- return 2; ++ if (!st || !st->sb || !content) { ++ rv = 2; ++ goto free_st; ++ } + + /* We have a full set of devices - we now need to find the + * array device. +@@ -1574,12 +1586,11 @@ try_again: + + if (content != &info) { + /* This is a member of a container. Try starting the array. */ +- int err; +- err = assemble_container_content(st, mdfd, content, c, ++ rv = assemble_container_content(st, mdfd, content, c, + chosen_name, NULL); + close(mdfd); + sysfs_free(pre_exist); +- return err; ++ goto free_st; + } + + /* Ok, no bad inconsistancy, we can try updating etc */ +@@ -1937,10 +1948,20 @@ out: + /* '2' means 'OK, but not started yet' */ + if (rv == -1) { + free(devices); +- return 1; ++ rv = 1; ++ goto free_st; + } + close(mdfd); +- return rv == 2 ? 0 : rv; ++ ++ if (rv == 2) ++ rv = 0; ++free_st: ++ if (st) { ++ st->ss->free_super(st); ++ free(st); ++ } ++ ++ return rv; + } + + int assemble_container_content(struct supertype *st, int mdfd, +diff --git a/mdadm.c b/mdadm.c +index 14649a40c236..18ded25ee79d 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -107,6 +107,7 @@ int main(int argc, char *argv[]) + int grow_continue = 0; + struct context c = { + .require_homehost = 1, ++ .metadata = NULL, + }; + struct shape s = { + .journaldisks = 0, +@@ -445,6 +446,7 @@ int main(int argc, char *argv[]) + pr_err("unrecognised metadata identifier: %s\n", optarg); + exit(2); + } ++ c.metadata = optarg; + continue; + + case O(MANAGE,'W'): +@@ -1424,10 +1426,10 @@ int main(int argc, char *argv[]) + if (mdfd >= 0) + close(mdfd); + } else { +- rv |= Assemble(ss, ident.devname, array_ident, NULL, &c); ++ rv |= Assemble(ident.devname, array_ident, NULL, &c); + } + } else if (!c.scan) +- rv = Assemble(ss, ident.devname, &ident, devlist->next, &c); ++ rv = Assemble(ident.devname, &ident, devlist->next, &c); + else if (devs_found > 0) { + if (c.update && devs_found > 1) { + pr_err("can only update a single array at a time\n"); +@@ -1445,7 +1447,7 @@ int main(int argc, char *argv[]) + rv |= 1; + continue; + } +- rv |= Assemble(ss, dv->devname, array_ident, NULL, &c); ++ rv |= Assemble(dv->devname, array_ident, NULL, &c); + } + } else { + if (c.update) { +@@ -1737,7 +1739,7 @@ static int scan_assemble(struct supertype *ss, + if (a->devname && is_devname_ignore(a->devname) == true) + continue; + +- r = Assemble(ss, a->devname, ++ r = Assemble(a->devname, + a, NULL, c); + if (r == 0) { + a->assembled = 1; +@@ -1760,7 +1762,7 @@ static int scan_assemble(struct supertype *ss, + struct mddev_dev *devlist = conf_get_devs(); + acnt = 0; + do { +- rv2 = Assemble(ss, NULL, ++ rv2 = Assemble(NULL, + ident, + devlist, c); + if (rv2 == 0) { +diff --git a/mdadm.h b/mdadm.h +index 7dcb20ed1f34..56925cf863f1 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -638,6 +638,7 @@ struct context { + char *action; + int nodes; + char *homecluster; ++ char *metadata; + }; + + struct shape { +@@ -1516,10 +1517,8 @@ extern int restore_backup(struct supertype *st, + int verbose); + extern int Grow_continue_command(char *devname, int fd, struct context *c); + +-extern int Assemble(struct supertype *st, char *mddev, +- struct mddev_ident *ident, +- struct mddev_dev *devlist, +- struct context *c); ++extern int Assemble(char *mddev, struct mddev_ident *ident, ++ struct mddev_dev *devlist, struct context *c); + + extern int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, + struct context *c); +-- +2.50.1 + diff --git a/mdadm-use-standard-libc-nftw.patch b/mdadm-use-standard-libc-nftw.patch deleted file mode 100644 index c92cea8..0000000 --- a/mdadm-use-standard-libc-nftw.patch +++ /dev/null @@ -1,53 +0,0 @@ -commit e549ac6ab2ce5e7ec182310f8f5f2e41c6ac9233 -Author: Xiao Ni -Date: Wed May 7 18:06:59 2025 +0800 - - mdadm: use standard libc nftw - - commit bd648e3bec3d ("mdadm: Remove klibc and uclibc support") removes - macro HAVE_NFTW/HAVE_FTW and uses libc header ftw.h. But it leaves the - codes in lib.c which let mdadm command call nftw defined in lib.c. It - needs to remove these codes. - - The bug can be reproduced by: - mdadm -CR /dev/md0 --level raid5 --metadata=1.1 --chunk=32 --raid-disks 3 - --size 10000 /dev/loop1 /dev/loop2 /dev/loop3 - mdadm /dev/md0 --grow --chunk=64 - mdadm: /dev/md0: cannot open component -unknown- - - Fixes: bd648e3bec3d ("mdadm: Remove klibc and uclibc support") - Signed-off-by: Xiao Ni - -diff --git a/lib.c b/lib.c -index f36ae03a..eb6cc119 100644 ---- a/lib.c -+++ b/lib.c -@@ -245,28 +245,6 @@ int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s) - return 0; - } - --#ifndef HAVE_NFTW --#ifdef HAVE_FTW --int add_dev_1(const char *name, const struct stat *stb, int flag) --{ -- return add_dev(name, stb, flag, NULL); --} --int nftw(const char *path, -- int (*han)(const char *name, const struct stat *stb, -- int flag, struct FTW *s), int nopenfd, int flags) --{ -- return ftw(path, add_dev_1, nopenfd); --} --#else --int nftw(const char *path, -- int (*han)(const char *name, const struct stat *stb, -- int flag, struct FTW *s), int nopenfd, int flags) --{ -- return 0; --} --#endif /* HAVE_FTW */ --#endif /* HAVE_NFTW */ -- - /* - * Find a block device with the right major/minor number. - * If we find multiple names, choose the shortest. diff --git a/mdadm.spec b/mdadm.spec index e876039..1fc8073 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -3,7 +3,7 @@ Name: mdadm Version: 4.4 # extraversion is used to define rhel internal version -%define extraversion 2 +%define extraversion 3 Release: %{extraversion}%{?dist} Summary: The mdadm program controls Linux md devices (software RAID arrays) URL: https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git @@ -58,10 +58,45 @@ Patch033: 0034-Update-README.md.patch Patch034: 0035-mdadm-Remove-klibc-and-uclibc-support.patch Patch035: 0036-mdadm-include-asm-byteorder.h.patch Patch036: 0037-mdadm-use-kernel-raid-headers.patch -Patch037: mdadm-use-standard-libc-nftw.patch +Patch037: 0038-Update-tests.yml.patch +Patch038: 0039-Update-tests.yml.patch +Patch039: 0040-Update-run_mdadm_tests.sh.patch +Patch040: 0041-tests-support-second-runner.patch +Patch041: 0042-mdadm-allow-any-valid-minor-number-in-md-device-name.patch +Patch042: 0043-mdadm-use-standard-libc-nftw.patch +Patch043: 0044-mdadm-fix-building-errors.patch +Patch044: 0045-mdadm-add-attribute-nonstring-for-signature.patch +Patch045: 0046-mdadm-give-more-time-to-wait-sync-thread-to-reap.patch +Patch046: 0047-mdadm-tests-mark-10ddf-fail-two-spares-broken.patch +Patch047: 0048-mdadm-tests-mark-09imsm-assemble-broken.patch +Patch048: 0049-mdadm-tests-mark-10ddf-fail-readd-readonly-broken.patch +Patch049: 0050-optim-al-ize-write-indent-write-intent.patch +Patch050: 0051-mdadm-enable-sync-file-for-udev-rules.patch +Patch051: 0052-mdadm-remove-POSIX-check.patch +Patch052: 0053-mdadm-assemble-Don-t-stop-array-after-creating-it.patch +Patch053: 0054-mdmonitor-use-MAILFROM-to-set-sendmail-envelope-send.patch +Patch054: 0055-mdadm-use-lseek-consistently.patch +Patch055: 0056-build-deps-bump-actions-checkout-from-4-to-5.patch +Patch056: 0057-systemd-use-Type-simple-for-mdcheck-services.patch +Patch057: 0058-mdcheck-reset-sync_action-to-idle-when-stopped.patch +Patch058: 0059-mdcheck-make-sure-signals-are-processed-immediately.patch +Patch059: 0060-systemd-start-mdcheck_continue.timer-before-mdcheck_.patch +Patch060: 0061-Fix-monitor-scan-with-relative-ARRAY-devnames.patch +Patch061: 0062-Re-enable-mdadm-monitor-.-for-dev-mdX.patch +Patch062: 0063-Fix-meaing-typo-in-mdadm.conf-example.patch +Patch063: 0064-Update-raid6check-man-page.patch +Patch064: 0065-udev-Fix-memleak.patch +Patch065: 0066-mdadm-modify-the-order-of-free_super_xxx-to-avoid-me.patch +Patch066: 0067-mdadm-Fix-memory-leak-issue-in-check_raid.patch +Patch067: 0068-mdadm-Fix-memory-leak-issue-in-Manage_stop.patch +Patch068: 0069-mdadm-Fix-memory-leak-issue-in-load_ddf_local.patch +Patch069: 0070-mdadm-Incremental-wait-a-while-before-removing-a-mem.patch +Patch070: 0071-mdadm-sysfs-close-fd-before-return.patch +Patch071: 0072-Update-README.md.patch +Patch072: 0073-mdadm-Create-array-with-sync-del-gendisk-mode.patch +Patch073: 0074-mdadm-Assemble-alloc-superblock-in-Assemble.patch # Fedora customization patches -Patch196: mdadm-fix-building-errors.patch Patch197: mdadm-udev.patch Patch198: mdadm-2.5.2-static.patch @@ -143,6 +178,10 @@ install -m644 %{SOURCE5} %{buildroot}/etc/libreport/events.d /usr/share/mdadm/mdcheck %changelog +* Tue Oct 28 2025 Xiao Ni - 4.4-3 +- Update mdadm to latest upstream +- Resolves: RHEL-100004, RHEL-107084 + * Mon May 19 2025 Xiao Ni - 4.4-2 - grow command can't update chunksize - Resolves: RHEL-92288