diff --git a/0067-mdadm-Change-main-repository-to-Github.patch b/0067-mdadm-Change-main-repository-to-Github.patch new file mode 100644 index 0000000..ae729f5 --- /dev/null +++ b/0067-mdadm-Change-main-repository-to-Github.patch @@ -0,0 +1,193 @@ +From 3f90be087fa62c0c7ed76c2ac26752f0ac3a89e7 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 7 May 2024 17:35:09 +0200 +Subject: [PATCH 067/201] mdadm: Change main repository to Github + +Now github will be used for tracking mdadm, adjust README.md. +Daily routines will be automated on Github, there is not need to +decribe them. + +Adjust release process, it must be published to both repositories. + +Signed-off-by: Mariusz Tkaczyk +--- + MAINTAINERS.md | 41 ++++++++---------------- + README.md | 86 ++++++++++++++++++++++++++++---------------------- + 2 files changed, 61 insertions(+), 66 deletions(-) + +diff --git a/MAINTAINERS.md b/MAINTAINERS.md +index 9c79ba87..e5b635f0 100644 +--- a/MAINTAINERS.md ++++ b/MAINTAINERS.md +@@ -1,44 +1,29 @@ + # Maintainer tools + +-Useful tools used in daily routines: ++Useful tools for mdadm maintenance: + - [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) + - [kup](https://korg.docs.kernel.org/kup.html) + - [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer) + - [b4](https://b4.docs.kernel.org/en/latest/) + +-# Checklist before applying patch +- +-We don't have CI testing yet, so all those steps must be performed manually: +-- Style check with [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html): +- +- This is the current code style follows. We are not strict to all rules. It must be run +- by **checkpatch --no-tree**, see README.md. +- +-- [Commit style](https://www.kernel.org/doc/html/v4.10/process/submitting-patches.html): +- +- It doesn't need to be followed as strictly as is in kernel but changes should be logically +- separated. Submitter should care at least to mention "It is used in next patches" if unused +- externs/files are added in patch. We love: *Reported-by:*, *Suggested-by:*, *Fixes:* tags. +- +-- Compilation, ideally on various gcc versions. +-- Mdadm test suite execution. +-- Consider requesting new tests from submitter, especially for new functionalities. +-- Ensure that maintainer *sign-off* is added, before pushing. +- + # Making a release + + Assuming that maintainer is certain that release is safe, following steps must be done: + +-- Update versions strings in release commit, please refer to previous releases for examples. ++- Make and push release commit: ++ - Update versions strings, refer to previous releases for examples. ++ - Update CHANGELOG.md. ++ ++- Create GPG signed tag and push it to both remotes. Use same format as was used previously, ++ prefixed by **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**. + +-- Create GPG signed tag and push it to repo. Use same format as was used previously, prefixed by +- **mdadm-**, e.g. **mdadm-3.1.2**, **mdadm-4.1**. ++- Run kernel.org ++ [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer): + +-- [Auto-publishing](https://korg.docs.kernel.org/kup.html#auto-publishing-with-git-archive-signer): ++ Adopt script to our release tag model. When ready, push signed note to kernel.org repository. If ++ it is done correctly, then *(sig)* is added to the package automatically generated by ++ kernel.org automation. There is no need to upload archive manually. + +- Adopt script to our release tag model. When ready, push signed note to repository. If it is done +- correctly, then *(sig)* is added to the package automatically generated by kernel.org automation. +- There is no need to upload archive manually. ++- Add release entry on Github. + +-- Update CHANGELOG.md. + - Write "ANNOUNCE" mail to linux-raid@kernel.org to notify community. +diff --git a/README.md b/README.md +index 64f2ecec..486c8929 100644 +--- a/README.md ++++ b/README.md +@@ -20,58 +20,68 @@ + **IMPORTANT:** DDF is in **maintenance only** mode. There is no active development around it. + Please do not use it in new solutions. + +-# How to Contribute +- +- **mdadm** is hosted on [kernel.org](https://kernel.org/). You can access repository +-[here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git). ++# Questions and Support ++ ++This Github site is **not** right place to ask if your are looking for: ++- support from Linux Raid Community; ++- support with kernel issues; ++ ++This is the place where development of mdadm application is done. Please, do not use for ++looking for support. You should always ask on [Mailing List](https://lore.kernel.org/linux-raid/). ++ ++Please use issues if you have confirmation that issue you are experiencing is related to mdadm ++components: ++- mdadm; ++- mdmon; ++- raid6check; ++- swap_super; ++- test_stripe; ++- systemd services ( see systemd/); ++- udev rules; ++- manual pages (including md.man) ++ ++For example: ++- mdadm issues (e.g segfaults, memory leaks, crashes, bad communication with MD driver); ++- feature requests for mdadm; ++- suggestions or minor fixes requested (e.g. better error messages); ++ ++Generally, if you are not sure it is better to ask on ++[Mailing List](https://lore.kernel.org/linux-raid/) first. + +-It is maintained similarly to kernel, using *mailing list*. Patches must be send through email. +-Please familiarize with general kernel +-[submitting patches](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html) +-documentation. Formatting, tags and commit message guidelines applies to **mdadm**. ++# How to Contribute + +-## Sending patches step-by-step ++Effective immediately [Github](https://github.com/md-raid-utilities/mdadm) is the primary ++location for **mdadm**. Use pull request to contribute. + +-To maximize change of patches being taken, follow this instruction when submitting: ++It was originally hosted on [kernel.org](https://kernel.org/). You can access the old repository ++[here](https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git). + +-1. Create possibly logically separated commits and generate patches: ++Patches sent through Mailing list are accepted but Github is preferred. Sent then to ML only ++if you cannot use Github. Please add "mdadm:" to the subject to allow automation to create Github ++Pull Request and run checks. + +- Use ``git format-patch --cover-letter --signoff -v `` to create patches: +- * ``--cover-letter`` can be skipped if it is only one patch; +- * ``--signoff`` adds sign-off tag; +- * ``-v `` indicates review revision number, sender should increment it before resending. ++**NOTE:** Maintainers may ask you to send RFC to mailing list if the proposed code requires ++consultation with kernel developers. + +-2. Check style of every patch with kernel +- [checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script: ++Kernel coding style is used. Please familiarize with general kernel ++[submitting patches](https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html) ++documentation. Formatting, tags and commit message guidelines applies to **mdadm**. + +- It is important to keep same coding style that is why in **mdadm** +- [kernel coding style](https://www.kernel.org/doc/html/v4.10/process/coding-style.html) +- is preferred. ``checkpath --no-tree `` can be used to verify patches. +- Following checkpatch issues can be ignored: +- - New typedefs. +- - comparing with *True/False*. +- - kernel *MAINTAINERS* file warning. +- - *extern* keyword in headers. ++[Checkpatch](https://docs.kernel.org/dev-tools/checkpatch.html) script is run on ++every patch in pull request so be sure that your commits are not generating ++issues. There are some excludes, so the best is to follow github checkpatch action result. + +-3. Send patches using ``git send-mail --to=linux-raid@vger.kernel.org (...)`` ++Pull Request are closed by `Rebase and Merge` option, so it requires to keep every commit ++meaningful. Kernel style requires that. The review changes must be pushed with **push --force** ++to the chosen branch, then Pull Request will be automatically updated. + +-# Maintainers ++# Maintainers of mdadm repository on kernel.org + +-It is good practice to add **mdadm maintainers** to recipients for patches: ++If there are differences between github and kernel.org, please contact kernel.org mdadm maintainers: + + - Jes Sorensen ; + - Mariusz Tkaczyk ; + +-Adding **MD maintainers** could be reasonable, especially if patches may affect MD driver: +- +-- Song Liu ; +-- Yu Kuai ; +- +-# Reviewers +- +-**mdadm** utility is not part of kernel tree, so there is no certificated *Reviewers* list. Everyone +-can comment on mailing list, last decision (and merging) belongs to maintainers. +- + # Minimal supported kernel version + + We do not support kernel versions below **v3.10**. Please be aware that maintainers may remove +-- +2.41.0 + diff --git a/0070-add-checking-of-return-status-on-fstat-calls.patch b/0070-add-checking-of-return-status-on-fstat-calls.patch new file mode 100644 index 0000000..78c98ef --- /dev/null +++ b/0070-add-checking-of-return-status-on-fstat-calls.patch @@ -0,0 +1,267 @@ +From 95673c7d83c8ac7f2aeb91a34ead2971ba30e96e Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Mon, 20 May 2024 09:36:50 -0400 +Subject: [PATCH 070/201] add checking of return status on fstat calls + +There are a few places we don't check the return status when +calling fstat for success. Clean up the calls by adding a +check before continuing. + +Signed-off-by: Nigel Croxon +--- + Assemble.c | 41 +++++++++++++++++++++++------------------ + Dump.c | 11 +++++++++-- + Grow.c | 12 ++++++++---- + config.c | 3 ++- + mdstat.c | 3 ++- + super-ddf.c | 8 ++++++-- + super-intel.c | 8 ++++++-- + 7 files changed, 56 insertions(+), 30 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 83dced19..58dc2c5e 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -652,7 +652,9 @@ static int load_devices(struct devs *devices, char *devmap, + /* prepare useful information in info structures */ + struct stat stb2; + int err; +- fstat(mdfd, &stb2); ++ ++ if (fstat(mdfd, &stb2) != 0) ++ goto error; + + if (c->update == UOPT_UUID && !ident->uuid_set) + random_uuid((__u8 *)ident->uuid); +@@ -675,13 +677,10 @@ static int load_devices(struct devs *devices, char *devmap, + devname); + if (dfd >= 0) + close(dfd); +- close(mdfd); +- free(devices); +- free(devmap); + tst->ss->free_super(tst); + free(tst); + *stp = st; +- return -1; ++ goto error; + } + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); + +@@ -715,12 +714,9 @@ static int load_devices(struct devs *devices, char *devmap, + map_num(update_options, c->update), tst->ss->name); + tst->ss->free_super(tst); + free(tst); +- close(mdfd); + close(dfd); +- free(devices); +- free(devmap); + *stp = st; +- return -1; ++ goto error; + } + if (c->update == UOPT_UUID && + !ident->uuid_set) { +@@ -751,18 +747,23 @@ static int load_devices(struct devs *devices, char *devmap, + devname); + if (dfd >= 0) + close(dfd); +- close(mdfd); +- free(devices); +- free(devmap); + tst->ss->free_super(tst); + free(tst); + *stp = st; +- return -1; ++ goto error; + } + tst->ss->getinfo_super(tst, content, devmap + devcnt * content->array.raid_disks); + } + +- fstat(dfd, &stb); ++ if (fstat(dfd, &stb) != 0) { ++ close(dfd); ++ free(devices); ++ free(devmap); ++ tst->ss->free_super(tst); ++ free(tst); ++ *stp = st; ++ return -1; ++ } + close(dfd); + + if (c->verbose > 0) +@@ -842,12 +843,9 @@ static int load_devices(struct devs *devices, char *devmap, + inargv ? "the list" : + "the\n DEVICE list in mdadm.conf" + ); +- close(mdfd); +- free(devices); +- free(devmap); + free(best); + *stp = st; +- return -1; ++ goto error; + } + if (best[i] == -1 || (devices[best[i]].i.events + < devices[devcnt].i.events)) +@@ -863,6 +861,13 @@ static int load_devices(struct devs *devices, char *devmap, + *bestp = best; + *stp = st; + return devcnt; ++ ++error: ++ close(mdfd); ++ free(devices); ++ free(devmap); ++ return -1; ++ + } + + static int force_array(struct mdinfo *content, +diff --git a/Dump.c b/Dump.c +index 736bcb60..81b94940 100644 +--- a/Dump.c ++++ b/Dump.c +@@ -37,6 +37,7 @@ int Dump_metadata(char *dev, char *dir, struct context *c, + unsigned long long size; + DIR *dirp; + struct dirent *de; ++ int ret = 0; + + if (stat(dir, &stb) != 0 || + (S_IFMT & stb.st_mode) != S_IFDIR) { +@@ -112,9 +113,15 @@ int Dump_metadata(char *dev, char *dir, struct context *c, + } + if (c->verbose >= 0) + printf("%s saved as %s.\n", dev, fname); +- fstat(fd, &dstb); +- close(fd); ++ + close(fl); ++ ret = fstat(fd, &dstb); ++ close(fd); ++ if (ret) { ++ unlink(fname); ++ free(fname); ++ return 1; ++ } + if ((dstb.st_mode & S_IFMT) != S_IFBLK) { + /* Not a block device, so cannot create links */ + free(fname); +diff --git a/Grow.c b/Grow.c +index 1923c27c..963792d0 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1223,13 +1223,14 @@ int reshape_open_backup_file(char *backup_file, + * way this will not notice, but it is better than + * nothing. + */ +- fstat(*fdlist, &stb); ++ if (fstat(*fdlist, &stb) != 0) ++ goto error; + dev = stb.st_dev; +- fstat(fd, &stb); ++ if (fstat(fd, &stb) != 0) ++ goto error; + if (stb.st_rdev == dev) { + pr_err("backup file must NOT be on the array being reshaped.\n"); +- close(*fdlist); +- return 0; ++ goto error; + } + + memset(buf, 0, 512); +@@ -1255,6 +1256,9 @@ int reshape_open_backup_file(char *backup_file, + } + + return 1; ++error: ++ close(*fdlist); ++ return 0; + } + + unsigned long compute_backup_blocks(int nchunk, int ochunk, +diff --git a/config.c b/config.c +index b46d71cb..612e700d 100644 +--- a/config.c ++++ b/config.c +@@ -949,7 +949,8 @@ void conf_file_or_dir(FILE *f) + struct dirent *dp; + struct fname *list = NULL; + +- fstat(fileno(f), &st); ++ if (fstat(fileno(f), &st) != 0) ++ return; + if (S_ISREG(st.st_mode)) + conf_file(f); + else if (!S_ISDIR(st.st_mode)) +diff --git a/mdstat.c b/mdstat.c +index 2fd792c5..e233f094 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -348,7 +348,8 @@ void mdstat_wait_fd(int fd, const sigset_t *sigmask) + + if (fd >= 0) { + struct stat stb; +- fstat(fd, &stb); ++ if (fstat(fd, &stb) != 0) ++ return; + if ((stb.st_mode & S_IFMT) == S_IFREG) + /* Must be a /proc or /sys fd, so expect + * POLLPRI +diff --git a/super-ddf.c b/super-ddf.c +index 21426c75..311001c1 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -1053,7 +1053,10 @@ static int load_ddf_local(int fd, struct ddf_super *super, + 0); + dl->devname = devname ? xstrdup(devname) : NULL; + +- fstat(fd, &stb); ++ if (fstat(fd, &stb) != 0) { ++ free(dl); ++ return 1; ++ } + dl->major = major(stb.st_rdev); + dl->minor = minor(stb.st_rdev); + dl->next = super->dlist; +@@ -2786,7 +2789,8 @@ static int add_to_super_ddf(struct supertype *st, + /* This is device numbered dk->number. We need to create + * a phys_disk entry and a more detailed disk_data entry. + */ +- fstat(fd, &stb); ++ if (fstat(fd, &stb) != 0) ++ return 1; + n = find_unused_pde(ddf); + if (n == DDF_NOTFOUND) { + pr_err("No free slot in array, cannot add disk\n"); +diff --git a/super-intel.c b/super-intel.c +index 2b8b6fda..4d257371 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -4239,7 +4239,10 @@ load_imsm_disk(int fd, struct intel_super *super, char *devname, int keep_fd) + + dl = xcalloc(1, sizeof(*dl)); + +- fstat(fd, &stb); ++ if (fstat(fd, &stb) != 0) { ++ free(dl); ++ return 1; ++ } + dl->major = major(stb.st_rdev); + dl->minor = minor(stb.st_rdev); + dl->next = super->disks; +@@ -5981,7 +5984,8 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + if (super->current_vol >= 0) + return add_to_super_imsm_volume(st, dk, fd, devname); + +- fstat(fd, &stb); ++ if (fstat(fd, &stb) != 0) ++ return 1; + dd = xcalloc(sizeof(*dd), 1); + dd->major = major(stb.st_rdev); + dd->minor = minor(stb.st_rdev); +-- +2.41.0 + diff --git a/0071-super-intel-fix-typo-in-error-msg.patch b/0071-super-intel-fix-typo-in-error-msg.patch new file mode 100644 index 0000000..beb7849 --- /dev/null +++ b/0071-super-intel-fix-typo-in-error-msg.patch @@ -0,0 +1,28 @@ +From c7790592bb7d050a990a9accb50de8f584879169 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Wed, 22 May 2024 11:13:17 +0200 +Subject: [PATCH 071/201] super-intel: fix typo in error msg + +Fix typo in encryption policy error msg. + +Signed-off-by: Blazej Kucman +--- + super-intel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/super-intel.c b/super-intel.c +index 4d257371..95856322 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -11328,7 +11328,7 @@ check_policy: + return MDADM_STATUS_SUCCESS; + + fd2devname(disk_fd, devname); +- pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected eariler.\n", ++ pr_vrb("Encryption status \"%s\" detected for disk %s, but \"%s\" status was detected earlier.\n", + encryption_state, devname, expected_policy->value); + pr_vrb("Disks with different encryption status cannot be used.\n"); + return MDADM_STATUS_ERROR; +-- +2.41.0 + diff --git a/0072-mdadm-super-intel-remove-dead-code.patch b/0072-mdadm-super-intel-remove-dead-code.patch new file mode 100644 index 0000000..48c916d --- /dev/null +++ b/0072-mdadm-super-intel-remove-dead-code.patch @@ -0,0 +1,45 @@ +From 49145d4f574b21a6c0612ce691f255732cb91832 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 22 May 2024 16:05:25 -0400 +Subject: [PATCH 072/201] mdadm: super-intel remove dead code + +Execution cannot reach this statement: "while (devlist) { dv = de...". +Local variable "err" is assigned only once, to a constant value, +making it effectively constant throughout its scope. +Remove dead code. + +Signed-off-by: Nigel Croxon +--- + super-intel.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 95856322..d1b737c7 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7046,7 +7046,6 @@ get_devices(const char *hba_path) + struct md_list *dv; + struct dirent *ent; + DIR *dir; +- int err = 0; + + #if DEBUG_LOOP + devlist = get_loop_devices(); +@@ -7088,14 +7087,6 @@ get_devices(const char *hba_path) + dv->next = devlist; + devlist = dv; + } +- if (err) { +- while(devlist) { +- dv = devlist; +- devlist = devlist->next; +- free(dv->devname); +- free(dv); +- } +- } + closedir(dir); + return devlist; + } +-- +2.41.0 + diff --git a/0073-mdadm-super-intel-fix-bad-shift.patch b/0073-mdadm-super-intel-fix-bad-shift.patch new file mode 100644 index 0000000..95689dc --- /dev/null +++ b/0073-mdadm-super-intel-fix-bad-shift.patch @@ -0,0 +1,55 @@ +From 5c30864146412fcdfdcfddcdd94c5c449d9ddbed Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 22 May 2024 16:53:22 -0400 +Subject: [PATCH 073/201] mdadm: super-intel fix bad shift + +In the expression "1 << i", left shifting by more than 31 bits has undefined behavior. +The shift amount, "i", is as much as 63. The operand has type "int" (32 bits) and will +be shifted as an "int". The fix is to change to a 64 bit int. + +Signed-off-by: Nigel Croxon +--- + super-intel.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index d1b737c7..0287a618 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2343,7 +2343,8 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type) + get_encryption_status_string(information.status)); + } + +-static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_base, int verbose) ++static int ahci_enumerate_ports(struct sys_dev *hba, unsigned long port_count, int host_base, ++ int verbose) + { + /* dump an unsorted list of devices attached to AHCI Intel storage + * controller, as well as non-connected ports +@@ -2357,7 +2358,7 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba + + if (port_count > (int)sizeof(port_mask) * 8) { + if (verbose > 0) +- pr_err("port_count %d out of range\n", port_count); ++ pr_err("port_count %ld out of range\n", port_count); + return 2; + } + +@@ -2499,11 +2500,11 @@ static int ahci_enumerate_ports(struct sys_dev *hba, int port_count, int host_ba + if (dir) + closedir(dir); + if (err == 0) { +- int i; ++ unsigned long i; + + for (i = 0; i < port_count; i++) +- if (port_mask & (1 << i)) +- printf(" Port%d : - no device attached -\n", i); ++ if (port_mask & (1L << i)) ++ printf(" Port%ld : - no device attached -\n", i); + } + + return err; +-- +2.41.0 + diff --git a/0074-mdadm-deprecate-bitmap-custom-file.patch b/0074-mdadm-deprecate-bitmap-custom-file.patch new file mode 100644 index 0000000..7f321ba --- /dev/null +++ b/0074-mdadm-deprecate-bitmap-custom-file.patch @@ -0,0 +1,438 @@ +From 50b100768a115526f5029113af957658ef76b383 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 29 Mar 2024 15:21:54 +0100 +Subject: [PATCH 074/201] mdadm: deprecate bitmap custom file + +This option has been deprecated in kernel by Christoph in commit +0ae1c9d38426 ("md: deprecate bitmap file support"). Do the same in +mdadm. + +With this change, user must acknowledge it, it is not +skippable. The implementation of custom bitmap file looks like it's +abandoned. It cannot be done by Incremental so it is not respected by +any udev based system and it seems to not be recorded by metadata. +User must assemble such volume manually. + +Tests for bitmap custom file are removed because now they will not +pass because interaction with user is mandatory. + +Signed-off-by: Mariusz Tkaczyk +--- + mdadm.8.in | 34 +++++++++---------- + mdadm.c | 70 +++++++++++++++++++++++++++------------- + tests/05r1-bitmapfile | 49 ---------------------------- + tests/05r1-grow-external | 33 ------------------- + tests/05r1-n3-bitmapfile | 53 ------------------------------ + tests/05r5-bitmapfile | 49 ---------------------------- + tests/05r6-bitmapfile | 49 ---------------------------- + 7 files changed, 62 insertions(+), 275 deletions(-) + delete mode 100644 tests/05r1-bitmapfile + delete mode 100644 tests/05r1-grow-external + delete mode 100644 tests/05r1-n3-bitmapfile + delete mode 100644 tests/05r5-bitmapfile + delete mode 100644 tests/05r6-bitmapfile + +diff --git a/mdadm.8.in b/mdadm.8.in +index 9ba66825..aa0c5403 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -727,29 +727,25 @@ same as + + .TP + .BR \-b ", " \-\-bitmap= +-Specify a file to store a write-intent bitmap in. The file should not +-exist unless +-.B \-\-force +-is also given. The same file should be provided +-when assembling the array. If the word +-.B "internal" +-is given, then the bitmap is stored with the metadata on the array, +-and so is replicated on all devices. If the word +-.B "none" +-is given with +-.B \-\-grow +-mode, then any bitmap that is present is removed. If the word +-.B "clustered" +-is given, the array is created for a clustered environment. One bitmap +-is created for each node as defined by the ++Specify how to store a write-intent bitmap. Following values are supported: ++ ++.B internal ++- the bitmap is stored with the metadata on the array and so is replicated on all devices. ++ ++.B clustered ++- the array is created for a clustered environment. One bitmap is created for each node as defined ++by the + .B \-\-nodes + parameter and are stored internally. + +-To help catch typing errors, the filename must contain at least one +-slash ('/') if it is a real file (not 'internal' or 'none'). ++.B none ++- create array with no bitmap or remove any present bitmap (grow mode). + +-Note: external bitmaps are only known to work on ext2 and ext3. +-Storing bitmap files on other filesystems may result in serious problems. ++Setting bitmap for file is deprecated and should not be used. The file should not exist unless ++.B \-\-force ++is also given. The same file should be provided when assembling the array. The file name must ++contain at least one slash ('/'). Bitmap files are only known to work on ext2 and ext3. Storing ++bitmap files on other filesystems may result in serious problems. + + When creating an array on devices which are 100G or larger, + .I mdadm +diff --git a/mdadm.c b/mdadm.c +index d18619db..0b99fad4 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -29,6 +29,51 @@ + #include "md_p.h" + #include + ++/** ++ * set_bitmap_value() - set bitmap value. ++ * @s: Shape. ++ * @c: Context. ++ * @val: value to set. ++ * ++ * Validate and set bitmap. Context is needed for setting nodes for clustered bitmap. ++ */ ++static mdadm_status_t set_bitmap_value(struct shape *s, struct context *c, char *val) ++{ ++ if (s->bitmap_file) { ++ pr_err("--bitmap cannot be set twice. Second value: \"%s\".\n", val); ++ return MDADM_STATUS_ERROR; ++ } ++ ++ if (strcmp(val, "internal") == 0 || strcmp(optarg, STR_COMMON_NONE) == 0) { ++ s->bitmap_file = val; ++ return MDADM_STATUS_SUCCESS; ++ } ++ ++ if (strcmp(val, "clustered") == 0) { ++ s->bitmap_file = val; ++ /* Set the default number of cluster nodes ++ * to 4 if not already set by user ++ */ ++ if (c->nodes < 1) ++ c->nodes = 4; ++ return MDADM_STATUS_SUCCESS; ++ } ++ ++ if (strchr(val, '/')) { ++ pr_info("Custom write-intent bitmap file option is deprecated.\n"); ++ if (ask("Do you want to continue? (y/n)")) { ++ s->bitmap_file = val; ++ return MDADM_STATUS_SUCCESS; ++ } ++ ++ return MDADM_STATUS_ERROR; ++ } ++ ++ pr_err("--bitmap value must contain a '/' or be 'internal', 'clustered' or 'none'\n"); ++ pr_err("Current value is \"%s\"", val); ++ return MDADM_STATUS_ERROR; ++} ++ + static int scan_assemble(struct supertype *ss, + struct context *c, + struct mddev_ident *ident); +@@ -1094,30 +1139,9 @@ int main(int argc, char *argv[]) + case O(CREATE,Bitmap): /* here we create the bitmap */ + case O(GROW,'b'): + case O(GROW,Bitmap): +- if (s.bitmap_file) { +- pr_err("bitmap cannot be set twice. Second value: %s.\n", optarg); ++ if (set_bitmap_value(&s, &c, optarg)) + exit(2); +- } +- if (strcmp(optarg, "internal") == 0 || +- strcmp(optarg, STR_COMMON_NONE) == 0 || +- strchr(optarg, '/') != NULL) { +- s.bitmap_file = optarg; +- continue; +- } +- if (strcmp(optarg, "clustered") == 0) { +- s.bitmap_file = optarg; +- /* Set the default number of cluster nodes +- * to 4 if not already set by user +- */ +- if (c.nodes < 1) +- c.nodes = 4; +- continue; +- } +- /* probable typo */ +- pr_err("bitmap file must contain a '/', or be 'internal', or be 'clustered', or 'none'\n" +- " not '%s'\n", optarg); +- exit(2); +- ++ continue; + case O(GROW,BitmapChunk): + case O(BUILD,BitmapChunk): + case O(CREATE,BitmapChunk): /* bitmap chunksize */ +diff --git a/tests/05r1-bitmapfile b/tests/05r1-bitmapfile +deleted file mode 100644 +index f384f0ea..00000000 +--- a/tests/05r1-bitmapfile ++++ /dev/null +@@ -1,49 +0,0 @@ +- +-# +-# create a raid1 with a bitmap file +-# +-bmf=$targetdir/bitmap +-rm -f $bmf +-mdadm --create --run $md0 --level=1 -n2 --delay=1 --bitmap $bmf $dev1 $dev2 +-check wait +-testdev $md0 1 $mdsize1a 64 +-mdadm -S $md0 +- +-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 +-testdev $md0 1 $mdsize1a 64 +-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-sleep 4 +-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" +- exit 1 +-fi +-mdadm $md0 -f $dev1 +-testdev $md0 1 $mdsize1a 64 +-sleep 4 +-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" +- exit 2 +-fi +- +-mdadm -S $md0 +- +-mdadm --assemble -R $md0 --bitmap=$bmf $dev2 +-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-mdadm --zero $dev1 # force --add, not --re-add +-mdadm $md0 --add $dev1 +-#it is too fast# check recovery +- +-check wait +-sleep 4 +-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" +- exit 1 +-fi +- +-mdadm -S $md0 +diff --git a/tests/05r1-grow-external b/tests/05r1-grow-external +deleted file mode 100644 +index 69da3e90..00000000 +--- a/tests/05r1-grow-external ++++ /dev/null +@@ -1,33 +0,0 @@ +- +-# +-# create a raid1 array, add an external bitmap +-# +-mdadm --create --run $md0 -l 1 -n 2 $dev1 $dev2 +-check wait +-testdev $md0 1 $mdsize1a 64 +- +-bmf=$targetdir/bm +-rm -f $bmf +-#mdadm -E $dev1 +-mdadm --grow $md0 --bitmap=$bmf --delay=1 || { mdadm -X $bmf ; exit 1; } +-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-sleep 4 +-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-testdev $md0 1 $mdsize1a 64 +-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-sleep 4 +-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-#echo $dirty1 $dirty2 $dirty3 $dirty4 +-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ] +-then +- echo bad dirty counts +- exit 1 +-fi +- +-# now to remove the bitmap +-check bitmap +-mdadm --grow $md0 --bitmap=none +-check nobitmap +-mdadm -S $md0 +diff --git a/tests/05r1-n3-bitmapfile b/tests/05r1-n3-bitmapfile +deleted file mode 100644 +index f1c3f1ee..00000000 +--- a/tests/05r1-n3-bitmapfile ++++ /dev/null +@@ -1,53 +0,0 @@ +- +-# +-# create a raid1 with 3 devices and a bitmap file +-# make sure resync does right thing. +-# +-# +-bmf=$targetdir/bitmap +-rm -f $bmf +-mdadm --create -e0.90 --run $md0 --level=1 -n3 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3 +-check wait +-testdev $md0 1 $mdsize0 64 +-mdadm -S $md0 +- +-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3 +-testdev $md0 1 $mdsize0 64 +-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-sleep 4 +-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" +- exit 1 +-fi +-mdadm $md0 -f $dev2 +-testdev $md0 1 $mdsize0 64 +-sleep 4 +-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" +- exit 2 +-fi +- +-mdadm -S $md0 +- +-mdadm --assemble -R $md0 --bitmap=$bmf $dev1 $dev3 +-check nosync +-mdadm --zero-superblock $dev2 +-mdadm $md0 --add $dev2 +-check recovery +- +-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-check wait +-sleep 4 +-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" +- exit 1 +-fi +- +-mdadm -S $md0 +-exit 0 +diff --git a/tests/05r5-bitmapfile b/tests/05r5-bitmapfile +deleted file mode 100644 +index 6d173d88..00000000 +--- a/tests/05r5-bitmapfile ++++ /dev/null +@@ -1,49 +0,0 @@ +- +-# +-# create a raid1 with a bitmap file +-# +-bmf=$targetdir/bitmap +-rm -f $bmf +-mdadm --create --run $md0 --level=5 -n3 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3 +-check wait +-testdev $md0 2 $mdsize1 512 +-mdadm -S $md0 +- +-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3 +-testdev $md0 2 $mdsize1 512 +-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-sleep 4 +-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" +- exit 1 +-fi +-mdadm $md0 -f $dev1 +-testdev $md0 2 $mdsize1 512 +-sleep 4 +-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" +- exit 2 +-fi +- +-mdadm -S $md0 +- +-mdadm --assemble -R $md0 --bitmap=$bmf $dev2 $dev3 +-mdadm --zero $dev1 # force add, not re-add +-mdadm $md0 --add $dev1 +-check recovery +- +-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-check wait +-sleep 4 +-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" +- exit 1 +-fi +- +-mdadm -S $md0 +diff --git a/tests/05r6-bitmapfile b/tests/05r6-bitmapfile +deleted file mode 100644 +index d11896db..00000000 +--- a/tests/05r6-bitmapfile ++++ /dev/null +@@ -1,49 +0,0 @@ +- +-# +-# create a raid1 with a bitmap file +-# +-bmf=$targetdir/bitmap +-rm -f $bmf +-mdadm --create --run $md0 --level=6 -n4 --delay=1 --bitmap $bmf $dev1 $dev2 $dev3 $dev4 +-check wait +-testdev $md0 2 $mdsize1 512 +-mdadm -S $md0 +- +-mdadm --assemble $md0 --bitmap=$bmf $dev1 $dev2 $dev3 $dev4 +-testdev $md0 2 $mdsize1 512 +-dirty1=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-sleep 4 +-dirty2=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" +- exit 1 +-fi +-mdadm $md0 -f $dev3 +-testdev $md0 2 $mdsize1 512 +-sleep 4 +-dirty3=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" +- exit 2 +-fi +- +-mdadm -S $md0 +- +-mdadm --assemble -R $md0 --bitmap=$bmf $dev1 $dev2 $dev4 +-mdadm --zero $dev3 # force --add, not --re-add +-mdadm $md0 --add $dev3 +-check recovery +- +-dirty4=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-check wait +-sleep 4 +-dirty5=`mdadm -X $bmf | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +- +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" +- exit 1 +-fi +- +-mdadm -S $md0 +-- +2.41.0 + diff --git a/0075-Makefile-fix-make-s-detection.patch b/0075-Makefile-fix-make-s-detection.patch new file mode 100644 index 0000000..bc54005 --- /dev/null +++ b/0075-Makefile-fix-make-s-detection.patch @@ -0,0 +1,31 @@ +From 906922ee321d64e2ce8458147e67d4892696fb58 Mon Sep 17 00:00:00 2001 +From: Valery Ushakov +Date: Wed, 22 May 2024 17:07:38 +0300 +Subject: [PATCH 075/201] Makefile: fix make -s detection + +Only check the first word of MAKEFLAGS for 's', that's where all the +single letter options are collected. + +MAKEFLAGS contains _all_ make flags, so if any command line argument +contains a letter 's', the silent test will be false positive. Think +e.g. make 'DESTDIR=.../aports/main/mdadm/pkg/mdadm' install +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index adac7905..446710bd 100644 +--- a/Makefile ++++ b/Makefile +@@ -157,7 +157,7 @@ ifndef UDEVDIR + UDEVDIR = /lib/udev + endif + +-ifeq (,$(findstring s,$(MAKEFLAGS))) ++ifeq (,$(findstring s,$(firstword -$(MAKEFLAGS)))) + ECHO=echo + else + ECHO=: +-- +2.41.0 + diff --git a/0076-Change-some-error-messages-to-info-level.patch b/0076-Change-some-error-messages-to-info-level.patch new file mode 100644 index 0000000..72f2508 --- /dev/null +++ b/0076-Change-some-error-messages-to-info-level.patch @@ -0,0 +1,81 @@ +From 13a0e92a3ed70c52246a0f0572dee61203994327 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:38 +0800 +Subject: [PATCH 076/201] Change some error messages to info level + +These logs are not error logs. Change them to info level. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Assemble.c | 16 ++++++---------- + Manage.c | 2 +- + util.c | 4 ++-- + 3 files changed, 9 insertions(+), 13 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 58dc2c5e..0e6da593 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -1214,23 +1214,19 @@ static int start_array(int mdfd, + if (rv == 0) { + sysfs_rules_apply(mddev, content); + if (c->verbose >= 0) { +- pr_err("%s has been started with %d drive%s", ++ pr_info("%s has been started with %d drive%s", + mddev, okcnt, okcnt==1?"":"s"); + if (okcnt < (unsigned)content->array.raid_disks) +- fprintf(stderr, " (out of %d)", +- content->array.raid_disks); ++ printf(" (out of %d)", content->array.raid_disks); + if (rebuilding_cnt) +- fprintf(stderr, "%s %d rebuilding", +- sparecnt?",":" and", ++ printf("%s %d rebuilding", sparecnt?",":" and", + rebuilding_cnt); + if (sparecnt) +- fprintf(stderr, " and %d spare%s", +- sparecnt, ++ printf(" and %d spare%s", sparecnt, + sparecnt == 1 ? "" : "s"); + if (content->journal_clean) +- fprintf(stderr, " and %d journal", +- journalcnt); +- fprintf(stderr, ".\n"); ++ printf(" and %d journal", journalcnt); ++ printf(".\n"); + } + if (content->reshape_active && + is_level456(content->array.level)) { +diff --git a/Manage.c b/Manage.c +index 96e5ee54..5db72b77 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -463,7 +463,7 @@ done: + } + + if (verbose >= 0) +- pr_err("stopped %s\n", devname); ++ pr_info("stopped %s\n", devname); + map_lock(&map); + map_remove(&map, devnm); + map_unlock(&map); +diff --git a/util.c b/util.c +index bf79742f..48c97545 100644 +--- a/util.c ++++ b/util.c +@@ -633,9 +633,9 @@ int check_ext2(int fd, char *name) + bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8; + size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8; + size <<= bsize; +- pr_err("%s appears to contain an ext2fs file system\n", ++ pr_info("%s appears to contain an ext2fs file system\n", + name); +- cont_err("size=%lluK mtime=%s", size, ctime(&mtime)); ++ pr_info("size=%lluK mtime=%s", size, ctime(&mtime)); + return 1; + } + +-- +2.41.0 + diff --git a/0077-mdadm-Start-update_opt-from-0.patch b/0077-mdadm-Start-update_opt-from-0.patch new file mode 100644 index 0000000..4fc0a65 --- /dev/null +++ b/0077-mdadm-Start-update_opt-from-0.patch @@ -0,0 +1,40 @@ +From 296398299391b10650bdd79d986b115588e60590 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:39 +0800 +Subject: [PATCH 077/201] mdadm: Start update_opt from 0 + +Before f2e8393bd722 ('Manage&Incremental: code refactor, string to enum'), it uses +NULL to represent it doesn't need to update. So init UOPT_UNDEFINED to 0. This +problem is found by test case 05r6tor0. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + mdadm.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/mdadm.h b/mdadm.h +index b71d7b32..40818941 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -535,7 +535,8 @@ enum special_options { + }; + + enum update_opt { +- UOPT_NAME = 1, ++ UOPT_UNDEFINED = 0, ++ UOPT_NAME, + UOPT_PPL, + UOPT_NO_PPL, + UOPT_BITMAP, +@@ -575,7 +576,6 @@ enum update_opt { + UOPT_SPEC_FAILFAST, + UOPT_SPEC_NOFAILFAST, + UOPT_SPEC_REVERT_RESHAPE_NOBACKUP, +- UOPT_UNDEFINED + }; + extern void fprint_update_options(FILE *outf, enum update_opt update_mode); + +-- +2.41.0 + diff --git a/0078-Don-t-control-reshape-speed-in-daemon.patch b/0078-Don-t-control-reshape-speed-in-daemon.patch new file mode 100644 index 0000000..31c69fb --- /dev/null +++ b/0078-Don-t-control-reshape-speed-in-daemon.patch @@ -0,0 +1,49 @@ +From f79f7189aa25b9da51736f2c578a51c2c4fe7706 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:40 +0800 +Subject: [PATCH 078/201] Don't control reshape speed in daemon + +It tries to set the max sync speed in reshape. This should be done by +administrators by control interfaces /proc/sys/dev/raid/speed_limit_max/min. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 963792d0..b135930d 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -4488,7 +4488,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape, + */ + char *buf; + int degraded = -1; +- unsigned long long speed; + unsigned long long suspend_point, array_size; + unsigned long long backup_point, wait_point; + unsigned long long reshape_completed; +@@ -4544,10 +4543,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape, + if (posix_memalign((void**)&buf, 4096, disks * chunk)) + /* Don't start the 'reshape' */ + return 0; +- if (reshape->before.data_disks == reshape->after.data_disks) { +- sysfs_get_ll(sra, NULL, "sync_speed_min", &speed); +- sysfs_set_num(sra, NULL, "sync_speed_min", 200000); +- } + + if (increasing) { + array_size = sra->component_size * reshape->after.data_disks; +@@ -4680,8 +4675,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape, + sysfs_set_num(sra, NULL, "suspend_lo", 0); + sysfs_set_num(sra, NULL, "sync_min", 0); + +- if (reshape->before.data_disks == reshape->after.data_disks) +- sysfs_set_num(sra, NULL, "sync_speed_min", speed); + free(buf); + return done; + } +-- +2.41.0 + diff --git a/0079-mdadm-tests-test-enhance.patch b/0079-mdadm-tests-test-enhance.patch new file mode 100644 index 0000000..7b3e027 --- /dev/null +++ b/0079-mdadm-tests-test-enhance.patch @@ -0,0 +1,119 @@ +From 6e8af9475cf0ac22f7ac167040dbf92fbfdd97ab Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:41 +0800 +Subject: [PATCH 079/201] mdadm/tests: test enhance + +There are two changes. +First, if md module is not loaded, it gives error when reading +speed_limit_max. So read the value after loading md module which +is done in do_setup + +Second, sometimes the test reports error sync action doesn't +happen. But dmesg shows sync action is done. So limit the sync +speed before test. It doesn't affect the test run time. Because +check wait sets the max speed before waiting sync action. And +recording speed_limit_max/min in do_setup. + +Fixes: 4c12714d1ca0 ('test: run tests on system level mdadm') +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 10 +++++----- + tests/func.sh | 26 +++++++++++++++++++++++--- + 2 files changed, 28 insertions(+), 8 deletions(-) + +diff --git a/test b/test +index 338c2db4..ff403293 100755 +--- a/test ++++ b/test +@@ -6,7 +6,10 @@ targetdir="/var/tmp" + logdir="$targetdir" + config=/tmp/mdadm.conf + testdir=$PWD/tests +-system_speed_limit=`cat /proc/sys/dev/raid/speed_limit_max` ++system_speed_limit_max=0 ++system_speed_limit_min=0 ++test_speed_limit_min=100 ++test_speed_limit_max=500 + devlist= + + savelogs=0 +@@ -39,10 +42,6 @@ ctrl_c() { + ctrl_c_error=1 + } + +-restore_system_speed_limit() { +- echo $system_speed_limit > /proc/sys/dev/raid/speed_limit_max +-} +- + mdadm() { + rm -f $targetdir/stderr + case $* in +@@ -103,6 +102,7 @@ do_test() { + do_clean + # source script in a subshell, so it has access to our + # namespace, but cannot change it. ++ control_system_speed_limit + echo -ne "$_script... " + if ( set -ex ; . $_script ) &> $targetdir/log + then +diff --git a/tests/func.sh b/tests/func.sh +index b474442b..221cff15 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -136,6 +136,23 @@ check_env() { + fi + } + ++record_system_speed_limit() { ++ system_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max` ++ system_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min` ++} ++ ++# To avoid sync action finishes before checking it, it needs to limit ++# the sync speed ++control_system_speed_limit() { ++ echo $test_speed_limit_min > /proc/sys/dev/raid/speed_limit_min ++ echo $test_speed_limit_max > /proc/sys/dev/raid/speed_limit_max ++} ++ ++restore_system_speed_limit() { ++ echo $system_speed_limit_min > /proc/sys/dev/raid/speed_limit_max ++ echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max ++} ++ + do_setup() { + trap cleanup 0 1 3 15 + trap ctrl_c 2 +@@ -214,6 +231,7 @@ do_setup() { + ulimit -c unlimited + [ -f /proc/mdstat ] || modprobe md_mod + echo 0 > /sys/module/md_mod/parameters/start_ro ++ record_system_speed_limit + } + + # check various things +@@ -265,15 +283,17 @@ check() { + fi + ;; + wait ) +- p=`cat /proc/sys/dev/raid/speed_limit_max` +- echo 2000000 > /proc/sys/dev/raid/speed_limit_max ++ min=`cat /proc/sys/dev/raid/speed_limit_min` ++ max=`cat /proc/sys/dev/raid/speed_limit_max` ++ echo 200000 > /proc/sys/dev/raid/speed_limit_max + sleep 0.1 + while grep -Eq '(resync|recovery|reshape|check|repair) *=' /proc/mdstat || + grep -v idle > /dev/null /sys/block/md*/md/sync_action + do + sleep 0.5 + done +- echo $p > /proc/sys/dev/raid/speed_limit_max ++ echo $min > /proc/sys/dev/raid/speed_limit_min ++ echo $max > /proc/sys/dev/raid/speed_limit_max + ;; + state ) + grep -sq "blocks.*\[$2\]\$" /proc/mdstat || +-- +2.41.0 + diff --git a/0080-mdadm-tests-test-don-t-fail-when-systemd-reports-err.patch b/0080-mdadm-tests-test-don-t-fail-when-systemd-reports-err.patch new file mode 100644 index 0000000..18b2cd4 --- /dev/null +++ b/0080-mdadm-tests-test-don-t-fail-when-systemd-reports-err.patch @@ -0,0 +1,31 @@ +From 73ba062ef93d0a57360a2d5200bc7a8f8781e7b6 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:42 +0800 +Subject: [PATCH 080/201] mdadm/tests: test don't fail when systemd reports + error + +Sometimes systemd reports error in dmesg and test fails. Add +a condition to avoid this failure. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test b/test +index ff403293..3da53f87 100755 +--- a/test ++++ b/test +@@ -109,7 +109,7 @@ do_test() { + if [ -f "${_script}.inject_error" ]; then + echo "dmesg checking is skipped because test inject error" + else +- dmesg | grep -iq "error\|call trace\|segfault" && ++ dmesg | grep -iq "error\|call trace\|segfault" | grep -v "systemd" && + die "dmesg prints errors when testing $_basename!" + fi + echo "succeeded" +-- +2.41.0 + diff --git a/0081-mdadm-tests-names_template-enhance.patch b/0081-mdadm-tests-names_template-enhance.patch new file mode 100644 index 0000000..245d944 --- /dev/null +++ b/0081-mdadm-tests-names_template-enhance.patch @@ -0,0 +1,109 @@ +From 41706a91568472d10153bf4ada3c3f0d93ef327a Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:43 +0800 +Subject: [PATCH 081/201] mdadm/tests: names_template enhance + +For super1, if the length of hostname is >= 32, it doesn't add hostname +in metadata name. Fix this problem by checking the length of hostname. +Because other cases may use need to check this, so do the check in +do_setup. + +And this patch adds a check if link /dev/md/name exists. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 5 +++++ + tests/func.sh | 13 +++++++++++++ + tests/templates/names_template | 14 ++++++++++++-- + 3 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/test b/test +index 3da53f87..814ce199 100755 +--- a/test ++++ b/test +@@ -11,6 +11,11 @@ system_speed_limit_min=0 + test_speed_limit_min=100 + test_speed_limit_max=500 + devlist= ++# If super1 metadata name doesn't have the same hostname with machine, ++# it's treated as foreign. ++# For example, /dev/md0 is created, stops it, then assemble it, the ++# device node will be /dev/md127 (127 is choosed by mdadm autumatically) ++is_foreign="no" + + savelogs=0 + exitonerror=1 +diff --git a/tests/func.sh b/tests/func.sh +index 221cff15..cfe83e55 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -153,6 +153,18 @@ restore_system_speed_limit() { + echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max + } + ++is_raid_foreign() { ++ ++ # If the length of hostname is >= 32, super1 doesn't use ++ # hostname in metadata ++ hostname=$(hostname) ++ if [ `expr length $(hostname)` -lt 32 ]; then ++ is_foreign="no" ++ else ++ is_foreign="yes" ++ fi ++} ++ + do_setup() { + trap cleanup 0 1 3 15 + trap ctrl_c 2 +@@ -232,6 +244,7 @@ do_setup() { + [ -f /proc/mdstat ] || modprobe md_mod + echo 0 > /sys/module/md_mod/parameters/start_ro + record_system_speed_limit ++ is_raid_foreign + } + + # check various things +diff --git a/tests/templates/names_template b/tests/templates/names_template +index 1b6cd14b..88ad5b8c 100644 +--- a/tests/templates/names_template ++++ b/tests/templates/names_template +@@ -30,6 +30,7 @@ function names_verify() { + local DEVNODE_NAME="$1" + local WANTED_LINK="$2" + local WANTED_NAME="$3" ++ local EXPECTED="" + + local RES="$(mdadm -D --export $DEVNODE_NAME | grep MD_DEVNAME)" + if [[ "$?" != "0" ]]; then +@@ -38,7 +39,12 @@ function names_verify() { + fi + + if [[ "$WANTED_LINK" != "empty" ]]; then +- local EXPECTED="MD_DEVNAME=$WANTED_LINK" ++ EXPECTED="MD_DEVNAME=$WANTED_LINK" ++ ++ if [ ! -b /dev/md/$WANTED_LINK ]; then ++ echo "/dev/md/$WANTED_LINK doesn't exit" ++ exit 1 ++ fi + fi + + if [[ "$RES" != "$EXPECTED" ]]; then +@@ -52,7 +58,11 @@ function names_verify() { + exit 1 + fi + +- local EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" ++ if [ $is_foreign == "no" ]; then ++ EXPECTED="MD_NAME=$(hostname):$WANTED_NAME" ++ else ++ EXPECTED="MD_NAME=$WANTED_NAME" ++ fi + if [[ "$RES" != "$EXPECTED" ]]; then + echo "$RES doesn't match $EXPECTED." + exit 1 +-- +2.41.0 + diff --git a/0082-mdadm-tests-03assem-incr-enhance.patch b/0082-mdadm-tests-03assem-incr-enhance.patch new file mode 100644 index 0000000..107fbf6 --- /dev/null +++ b/0082-mdadm-tests-03assem-incr-enhance.patch @@ -0,0 +1,67 @@ +From 23f45965a0abe3506885c8e8005ee79473a66422 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:44 +0800 +Subject: [PATCH 082/201] mdadm/tests: 03assem-incr enhance + +It fails when hostname lenght > 32. Because the super1 metadata name +doesn't include hostname when hostname length > 32. Then mdadm thinks +the array is a foreign array if no device link is specified when +assembling the array. It chooses a minor number from 127. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 3 +++ + tests/03assem-incr | 20 +++++++++++++------- + 2 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/test b/test +index 814ce199..1fce6be2 100755 +--- a/test ++++ b/test +@@ -33,6 +33,9 @@ LVM_VOLGROUP=mdtest + md0=/dev/md0 + md1=/dev/md1 + md2=/dev/md2 ++# if user doesn't specify minor number, mdadm chooses minor number ++# automatically from 127. ++md127=/dev/md127 + mdp0=/dev/md_d0 + mdp1=/dev/md_d1 + +diff --git a/tests/03assem-incr b/tests/03assem-incr +index 38880a7f..21215a34 100644 +--- a/tests/03assem-incr ++++ b/tests/03assem-incr +@@ -9,15 +9,21 @@ set -x -e + levels=(raid0 raid1 raid5) + + if [ "$LINEAR" == "yes" ]; then +- levels+=( linear ) ++ levels+=( linear ) + fi + + for l in ${levels[@]} + do +- mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean +- mdadm -S md0 +- mdadm -I $dev1 +- mdadm -I $dev3 +- mdadm -A /dev/md0 $dev0 $dev1 $dev2 $dev3 $dev4 +- mdadm -S /dev/md0 ++ mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean ++ mdadm -S $md0 ++ mdadm -I $dev1 ++ mdadm -I $dev3 ++ mdadm -A $md0 $dev0 $dev1 $dev2 $dev3 $dev4 ++ # If one array is foreign (metadata name doesn't have the machine's ++ # hostname), mdadm chooses a minor number automatically from 127 ++ if [ $is_foreign == "no" ]; then ++ mdadm -S $md0 ++ else ++ mdadm -S $md127 ++ fi + done +-- +2.41.0 + diff --git a/0083-mdadm-tests-03r0assem-enhance.patch b/0083-mdadm-tests-03r0assem-enhance.patch new file mode 100644 index 0000000..5d3e34d --- /dev/null +++ b/0083-mdadm-tests-03r0assem-enhance.patch @@ -0,0 +1,38 @@ +From f136d9a8b7d8fdfd7539b96707bc9a03528754aa Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:45 +0800 +Subject: [PATCH 083/201] mdadm/tests 03r0assem enhance + +dcc22ae74a864 ('super1: remove support for name= in config') already +removes name= support. So remove related test codes in 03r0assem. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/03r0assem | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/tests/03r0assem b/tests/03r0assem +index f7c29e8c..4bf8b9e8 100644 +--- a/tests/03r0assem ++++ b/tests/03r0assem +@@ -33,16 +33,6 @@ mdadm -As -c $conf $md2 + $tst + mdadm -S $md2 + +-{ +- echo DEVICE $devlist +- echo array $md2 name=2 +-} > $conf +- +-mdadm -As -c $conf $md2 +-$tst +-mdadm -S $md2 +- +- + { + echo DEVICE $devlist + echo array $md2 devices=$dev0,$dev1,$dev2 +-- +2.41.0 + diff --git a/0084-mdadm-tests-remove-03r5assem-failed.patch b/0084-mdadm-tests-remove-03r5assem-failed.patch new file mode 100644 index 0000000..4d3f4ae --- /dev/null +++ b/0084-mdadm-tests-remove-03r5assem-failed.patch @@ -0,0 +1,35 @@ +From 5c1133ba8d026d65362953f25178fbf974b78ce9 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:46 +0800 +Subject: [PATCH 084/201] mdadm/tests: remove 03r5assem-failed + +03r5assem can run successfully with kernel 6.9.0-rc4 + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/03r5assem-failed | 12 ------------ + 1 file changed, 12 deletions(-) + delete mode 100644 tests/03r5assem-failed + +diff --git a/tests/03r5assem-failed b/tests/03r5assem-failed +deleted file mode 100644 +index d38241df..00000000 +--- a/tests/03r5assem-failed ++++ /dev/null +@@ -1,12 +0,0 @@ +- +-# Create an array, fail one device while array is active, stop array, +-# then re-assemble listing the failed device first. +- +-mdadm -CR $md1 -l5 -n4 $dev0 $dev1 $dev2 $dev3 +-check wait +- +-echo 2000 > /sys/block/md1/md/safe_mode_delay +-mkfs $md1 +-mdadm $md1 -f $dev0 +-mdadm -S $md1 +-mdadm -A $md1 $dev0 $dev1 $dev2 $dev3 || exit 1 +-- +2.41.0 + diff --git a/0085-mdadm-tests-03r5assemV1.patch b/0085-mdadm-tests-03r5assemV1.patch new file mode 100644 index 0000000..6731421 --- /dev/null +++ b/0085-mdadm-tests-03r5assemV1.patch @@ -0,0 +1,52 @@ +From 6077e9248acda8c70df58fabc8de23195c19a0cf Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:47 +0800 +Subject: [PATCH 085/201] mdadm/tests: 03r5assemV1 + +dcc22ae74a864 ('super1: remove support for name= in config') already +removes name= support. So remove related test codes in 03r5assemV1. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/03r5assemV1 | 17 ----------------- + 1 file changed, 17 deletions(-) + +diff --git a/tests/03r5assemV1 b/tests/03r5assemV1 +index bca0c583..6026011e 100644 +--- a/tests/03r5assemV1 ++++ b/tests/03r5assemV1 +@@ -31,14 +31,6 @@ conf=$targetdir/mdadm.conf + mdadm -As -c $conf $md1 + eval $tst + +-{ +- echo DEVICE $devlist +- echo array $md1 name=one +-} > $conf +- +-mdadm -As -c $conf +-eval $tst +- + { + echo DEVICE $devlist + echo array $md1 devices=$dev0,$dev1,$dev2,$dev3,$dev4 +@@ -88,15 +80,6 @@ mdadm -As -c $conf $md1 + check state U_U + eval $tst + +-{ +- echo DEVICE $devlist +- echo array $md1 name=one +-} > $conf +- +-mdadm -As -c $conf +-check state U_U +-eval $tst +- + { + echo DEVICE $devlist + echo array $md1 devices=$dev0,$dev1,$dev2 +-- +2.41.0 + diff --git a/0086-mdadm-tests-remove-04r5swap.broken.patch b/0086-mdadm-tests-remove-04r5swap.broken.patch new file mode 100644 index 0000000..b4bc67d --- /dev/null +++ b/0086-mdadm-tests-remove-04r5swap.broken.patch @@ -0,0 +1,30 @@ +From b9b8eaef49e075ce68846abb7cf0ca47c1ba9f2f Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:48 +0800 +Subject: [PATCH 086/201] mdadm/tests: remove 04r5swap.broken + +04r5swap can run successfully with kernel 6.9.0-rc4 + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/04r5swap.broken | 7 ------- + 1 file changed, 7 deletions(-) + delete mode 100644 tests/04r5swap.broken + +diff --git a/tests/04r5swap.broken b/tests/04r5swap.broken +deleted file mode 100644 +index e38987db..00000000 +--- a/tests/04r5swap.broken ++++ /dev/null +@@ -1,7 +0,0 @@ +-always fails +- +-Fails with errors: +- +- mdadm: /dev/loop0 has no superblock - assembly aborted +- +- ERROR: no recovery happening +-- +2.41.0 + diff --git a/0087-tests-04update-metadata-skip-linear.patch b/0087-tests-04update-metadata-skip-linear.patch new file mode 100644 index 0000000..789bb41 --- /dev/null +++ b/0087-tests-04update-metadata-skip-linear.patch @@ -0,0 +1,116 @@ +From 9808f110c5aea5454e9f56b2b660612a57adb347 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:49 +0800 +Subject: [PATCH 087/201] tests/04update-metadata skip linear + +Add one check that if kernel doesn't support linear/multipath, it can +skip linear/multipath testing. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 3 +++ + tests/04update-metadata | 35 ++++++++++++++++++++--------------- + tests/func.sh | 2 ++ + 3 files changed, 25 insertions(+), 15 deletions(-) + +diff --git a/test b/test +index 1fce6be2..f09994e7 100755 +--- a/test ++++ b/test +@@ -17,6 +17,9 @@ devlist= + # device node will be /dev/md127 (127 is choosed by mdadm autumatically) + is_foreign="no" + ++skipping_linear="no" ++skipping_multipath="no" ++ + savelogs=0 + exitonerror=1 + ctrl_c_error=0 +diff --git a/tests/04update-metadata b/tests/04update-metadata +index 2b72a303..c748770c 100644 +--- a/tests/04update-metadata ++++ b/tests/04update-metadata +@@ -8,24 +8,29 @@ set -xe + + dlist="$dev0 $dev1 $dev2 $dev3" + +-for ls in linear/4 raid1/1 raid5/3 raid6/2 ++if [ $skipping_linear == "yes" ]; then ++ level_list="raid1/1 raid5/3 raid6/2" ++else ++ level_list="linear/4 raid1/1 raid5/3 raid6/2" ++fi ++for ls in $level_list + do +- s=${ls#*/} l=${ls%/*} +- if [[ $l == 'raid1' ]]; then +- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist +- else +- mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist +- fi +- testdev $md0 $s 19904 64 +- mdadm -S $md0 +- mdadm -A $md0 --update=metadata $dlist +- testdev $md0 $s 19904 64 check +- mdadm -S $md0 ++ s=${ls#*/} l=${ls%/*} ++ if [[ $l == 'raid1' ]]; then ++ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 $dlist ++ else ++ mdadm -CR --assume-clean -e 0.90 $md0 --level $l -n 4 -c 64 $dlist ++ fi ++ testdev $md0 $s 19904 64 ++ mdadm -S $md0 ++ mdadm -A $md0 --update=metadata $dlist ++ testdev $md0 $s 19904 64 check ++ mdadm -S $md0 + done + + if mdadm -A $md0 --update=metadata $dlist + then echo >&2 should fail with v1.0 metadata +- exit 1 ++ exit 1 + fi + + mdadm -CR -e 0.90 $md0 --level=6 -n4 -c32 $dlist +@@ -33,7 +38,7 @@ mdadm -S $md0 + + if mdadm -A $md0 --update=metadata $dlist + then echo >&2 should fail during resync +- exit 1 ++ exit 1 + fi + mdadm -A $md0 $dlist + mdadm --wait $md0 || true +@@ -48,5 +53,5 @@ mdadm -S $md0 + + if mdadm -A $md0 --update=metadata $dlist + then echo >&2 should fail when bitmap present +- exit 1 ++ exit 1 + fi +diff --git a/tests/func.sh b/tests/func.sh +index cfe83e55..db55542d 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -125,6 +125,7 @@ check_env() { + MULTIPATH="yes" + if [ "$MULTIPATH" != "yes" ]; then + echo "test: skipping tests for multipath, which is removed in upstream 6.8+ kernels" ++ skipping_multipath="yes" + fi + + # Check whether to run linear tests +@@ -133,6 +134,7 @@ check_env() { + LINEAR="yes" + if [ "$LINEAR" != "yes" ]; then + echo "test: skipping tests for linear, which is removed in upstream 6.8+ kernels" ++ skipping_linear="yes" + fi + } + +-- +2.41.0 + diff --git a/0088-mdadm-tests-05r5-internalbitmap.patch b/0088-mdadm-tests-05r5-internalbitmap.patch new file mode 100644 index 0000000..a57280b --- /dev/null +++ b/0088-mdadm-tests-05r5-internalbitmap.patch @@ -0,0 +1,68 @@ +From 7664a3851476cfcda931d35f495d03f51707bac9 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:50 +0800 +Subject: [PATCH 088/201] mdadm/tests: 05r5-internalbitmap + +It's not right to compare bitmap bits with a number after io comes. +Because maybe those bits are already flused. Remove the related +tests. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/05r5-internalbitmap | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/tests/05r5-internalbitmap b/tests/05r5-internalbitmap +index 13dc5921..1a64482f 100644 +--- a/tests/05r5-internalbitmap ++++ b/tests/05r5-internalbitmap +@@ -9,21 +9,20 @@ mdadm -S $md0 + + mdadm --assemble $md0 $dev1 $dev2 $dev3 + testdev $md0 2 $mdsize1 512 +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" ++if [ $dirty1 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty1" + exit 1 + fi + mdadm $md0 -f $dev1 + testdev $md0 2 $mdsize1 512 + sleep 4 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++if [ $dirty2 -lt 400 ] + then +- echo >&2 "ERROR dirty count $dirty3 is too small" ++ echo >&2 "ERROR dirty count $dirty2 is too small" + exit 2 + fi + +@@ -33,14 +32,12 @@ mdadm --assemble -R $md0 $dev2 $dev3 + mdadm --zero $dev1 # force --add, not --re-add + mdadm $md0 --add $dev1 + check recovery +- +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + check wait + sleep 4 +-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" ++if [ $dirty3 -ne 0 ] ++then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty3" + exit 1 + fi + +-- +2.41.0 + diff --git a/0089-mdadm-tests-06name-enhance.patch b/0089-mdadm-tests-06name-enhance.patch new file mode 100644 index 0000000..3b1583f --- /dev/null +++ b/0089-mdadm-tests-06name-enhance.patch @@ -0,0 +1,38 @@ +From 6e7d850a57d40e18d525d0739a4f4226f6057d91 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:52 +0800 +Subject: [PATCH 089/201] mdadm/tests: 06name enhance + +It needs to check hostname in metadata name if one array is +local. Add the check in this case. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/06name | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/tests/06name b/tests/06name +index 86eaab69..c3213f6c 100644 +--- a/tests/06name ++++ b/tests/06name +@@ -3,8 +3,14 @@ set -x + # create an array with a name + + mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1 +-mdadm -E $dev0 | grep 'Name : Fred' > /dev/null || exit 1 +-mdadm -D $md0 | grep 'Name : Fred' > /dev/null || exit 1 ++ ++if [ $is_foreign == "no" ]; then ++ mdadm -E $dev0 | grep "Name : $(hostname):Fred" > /dev/null || exit 1 ++ mdadm -D $md0 | grep "Name : $(hostname):Fred" > /dev/null || exit 1 ++else ++ mdadm -E $dev0 | grep "Name : Fred" > /dev/null || exit 1 ++ mdadm -D $md0 | grep "Name : Fred" > /dev/null || exit 1 ++fi + mdadm -S $md0 + + mdadm -A $md0 --name="Fred" $devlist +-- +2.41.0 + diff --git a/0090-mdadm-tests-07autoassemble.patch b/0090-mdadm-tests-07autoassemble.patch new file mode 100644 index 0000000..f5aea04 --- /dev/null +++ b/0090-mdadm-tests-07autoassemble.patch @@ -0,0 +1,108 @@ +From 63e99a49cc02cbe4d1777b477719078897fc8308 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:53 +0800 +Subject: [PATCH 090/201] mdadm/tests: 07autoassemble + +This test is used to test stacked array auto assemble. + +There are two different cases depends on if array is foreign or not. +If the array is foreign, the stacked array (md0 is on md1 and md2) +can't be assembled with name md0. Because udev rule will run when md1 +and md2 are assembled and mdadm -I doesn't specify homehost. So it +will treat stacked array (md0) as foreign array and choose md127 as +the device node name (/dev/md127) + +Add the case that stacked array is local. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 2 ++ + tests/07autoassemble | 37 +++++++++++++++++++++++++++++++++++-- + tests/07autoassemble.broken | 8 -------- + 3 files changed, 37 insertions(+), 10 deletions(-) + delete mode 100644 tests/07autoassemble.broken + +diff --git a/test b/test +index f09994e7..4a88de58 100755 +--- a/test ++++ b/test +@@ -39,6 +39,8 @@ md2=/dev/md2 + # if user doesn't specify minor number, mdadm chooses minor number + # automatically from 127. + md127=/dev/md127 ++md126=/dev/md126 ++md125=/dev/md125 + mdp0=/dev/md_d0 + mdp1=/dev/md_d1 + +diff --git a/tests/07autoassemble b/tests/07autoassemble +index e689be7c..9dc78149 100644 +--- a/tests/07autoassemble ++++ b/tests/07autoassemble +@@ -10,7 +10,14 @@ mdadm -Ss + mdadm -As -c /dev/null --homehost=testing -vvv + testdev $md1 1 $mdsize1a 64 + testdev $md2 1 $mdsize1a 64 +-testdev $md0 2 $mdsize11a 512 ++# md1 and md2 will be incremental assemble by udev rule. And ++# the testing machines' hostname is not testing. The md0 will ++# be considered as a foreign array. It can use 0 as metadata ++# name. md127 will be used ++testdev $md127 2 $mdsize11a 512 ++mdadm --stop $md127 ++mdadm --zero-superblock $md1 ++mdadm --zero-superblock $md2 + mdadm -Ss + + mdadm --zero-superblock $dev0 $dev1 $dev2 $dev3 +@@ -20,5 +27,31 @@ mdadm -CR $md0 -l0 -n2 $md1 $dev2 --homehost=testing + mdadm -Ss + mdadm -As -c /dev/null --homehost=testing -vvv + testdev $md1 1 $mdsize1a 64 +-testdev $md0 1 $[mdsize1a+mdsize11a] 512 ++testdev $md127 1 $[mdsize1a+mdsize11a] 512 ++mdadm --stop $md127 ++mdadm --zero-superblock $md1 ++mdadm -Ss ++ ++# Don't specify homehost when creating raid and use the test ++# machine's homehost. For super1.2, if homehost name's length ++# is > 32, it doesn't use homehost name in metadata name and ++# the array will be treated as foreign array ++mdadm --zero-superblock $dev0 $dev1 $dev2 $dev3 ++mdadm -CR $md1 -l1 -n2 $dev0 $dev1 ++mdadm -CR $md2 -l1 -n2 $dev2 $dev3 ++mdadm -CR $md0 -l0 -n2 $md1 $md2 ++mdadm -Ss ++mdadm -As -c /dev/null ++if [ $is_foreign == "yes" ]; then ++ # md127 is md1 ++ testdev $md127 1 $mdsize1a 64 ++ # md126 is md0, udev rule incremental assemble it ++ testdev $md126 2 $mdsize11a 512 ++ # md125 is md2 ++ testdev $md125 1 $mdsize1a 64 ++else ++ testdev $md1 1 $mdsize1a 64 ++ testdev $md2 1 $mdsize1a 64 ++ testdev $md0 2 $mdsize11a 512 ++fi + mdadm -Ss +diff --git a/tests/07autoassemble.broken b/tests/07autoassemble.broken +deleted file mode 100644 +index 8be09407..00000000 +--- a/tests/07autoassemble.broken ++++ /dev/null +@@ -1,8 +0,0 @@ +-always fails +- +-Prints lots of messages, but the array doesn't assemble. Error +-possibly related to: +- +- mdadm: /dev/md/1 is busy - skipping +- mdadm: no recogniseable superblock on /dev/md/testing:0 +- mdadm: /dev/md/2 is busy - skipping +-- +2.41.0 + diff --git a/0091-mdadm-tests-07autodetect.broken-can-be-removed.patch b/0091-mdadm-tests-07autodetect.broken-can-be-removed.patch new file mode 100644 index 0000000..3c2fd5b --- /dev/null +++ b/0091-mdadm-tests-07autodetect.broken-can-be-removed.patch @@ -0,0 +1,28 @@ +From 1d0c61f4baa49bc218687017ccb2e3a664351390 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:54 +0800 +Subject: [PATCH 091/201] mdadm/tests: 07autodetect.broken can be removed + +07autodetect can run successfully without error in kernel 6.9.0-rc5. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/07autodetect.broken | 5 ----- + 1 file changed, 5 deletions(-) + delete mode 100644 tests/07autodetect.broken + +diff --git a/tests/07autodetect.broken b/tests/07autodetect.broken +deleted file mode 100644 +index 294954a1..00000000 +--- a/tests/07autodetect.broken ++++ /dev/null +@@ -1,5 +0,0 @@ +-always fails +- +-Fails with error: +- +- ERROR: no resync happening +-- +2.41.0 + diff --git a/0092-mdadm-tests-07changelevelintr.patch b/0092-mdadm-tests-07changelevelintr.patch new file mode 100644 index 0000000..f52edba --- /dev/null +++ b/0092-mdadm-tests-07changelevelintr.patch @@ -0,0 +1,73 @@ +From cd3b2350bef136b20c81190371fb0b60d62a0365 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:55 +0800 +Subject: [PATCH 092/201] mdadm/tests: 07changelevelintr + +It needs to specify a 2 powered array size when updating array size. +If not, it can't change chunksize. + +And sometimes it reports error reshape doesn't happen. In fact the +reshape has finished. It doesn't need to wait before checking +reshape action. Because check function waits itself. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/07changelevelintr | 9 +++++---- + tests/07changelevelintr.broken | 9 --------- + 2 files changed, 5 insertions(+), 13 deletions(-) + delete mode 100644 tests/07changelevelintr.broken + +diff --git a/tests/07changelevelintr b/tests/07changelevelintr +index 18c63092..d921f2b2 100644 +--- a/tests/07changelevelintr ++++ b/tests/07changelevelintr +@@ -27,11 +27,9 @@ checkgeo() { + } + + restart() { +- sleep 0.5 + check reshape + mdadm -S $md0 + mdadm -A $md0 $devs --backup-file=$bu +- sleep 0.5 + check reshape + } + +@@ -49,13 +47,16 @@ mdadm -G $md0 --layout rs --backup-file=$bu + restart + checkgeo md0 raid5 5 $[128*1024] 3 + +-mdadm -G $md0 --array-size 58368 ++# It needs to shrink array size first. Choose a value that ++# is power of 2 for array size. If not, it can't change ++# chunk size. ++mdadm -G $md0 --array-size 51200 + mdadm -G $md0 --raid-disks 4 -c 64 --backup-file=$bu + restart + checkgeo md0 raid5 4 $[64*1024] 3 + + devs="$dev0 $dev1 $dev2 $dev3" +-mdadm -G $md0 --array-size 19456 ++mdadm -G $md0 --array-size 18432 + mdadm -G $md0 -n 2 -c 256 --backup-file=$bu + restart + checkgeo md0 raid5 2 $[256*1024] 3 +diff --git a/tests/07changelevelintr.broken b/tests/07changelevelintr.broken +deleted file mode 100644 +index 284b4906..00000000 +--- a/tests/07changelevelintr.broken ++++ /dev/null +@@ -1,9 +0,0 @@ +-always fails +- +-Fails with errors: +- +- mdadm: this change will reduce the size of the array. +- use --grow --array-size first to truncate array. +- e.g. mdadm --grow /dev/md0 --array-size 56832 +- +- ERROR: no reshape happening +-- +2.41.0 + diff --git a/0093-mdadm-tests-disable-selinux.patch b/0093-mdadm-tests-disable-selinux.patch new file mode 100644 index 0000000..d7082ba --- /dev/null +++ b/0093-mdadm-tests-disable-selinux.patch @@ -0,0 +1,68 @@ +From b914aa25ee1fe3e0bd97f58bdf2bfdd185992a79 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 22 May 2024 16:50:56 +0800 +Subject: [PATCH 093/201] mdadm/tests: disable selinux + +Sometimes systemd service fails because selinux. Disable selinux +during testing now. We can enable it in future when having a better +method. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + test | 3 +++ + tests/func.sh | 10 ++++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/test b/test +index 4a88de58..47f53ad7 100755 +--- a/test ++++ b/test +@@ -16,6 +16,8 @@ devlist= + # For example, /dev/md0 is created, stops it, then assemble it, the + # device node will be /dev/md127 (127 is choosed by mdadm autumatically) + is_foreign="no" ++#disable selinux ++sys_selinux="Permissive" + + skipping_linear="no" + skipping_multipath="no" +@@ -351,6 +353,7 @@ main() { + fi + done + ++ restore_selinux + exit 0 + } + +diff --git a/tests/func.sh b/tests/func.sh +index db55542d..b2e4d122 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -167,6 +167,15 @@ is_raid_foreign() { + fi + } + ++record_selinux() { ++ sys_selinux=`getenforce` ++ setenforce Permissive ++} ++ ++restore_selinux() { ++ setenforce $sys_selinux ++} ++ + do_setup() { + trap cleanup 0 1 3 15 + trap ctrl_c 2 +@@ -247,6 +256,7 @@ do_setup() { + echo 0 > /sys/module/md_mod/parameters/start_ro + record_system_speed_limit + is_raid_foreign ++ record_selinux + } + + # check various things +-- +2.41.0 + diff --git a/0094-mdadm-platform-intel-buffer-overflow-detected.patch b/0094-mdadm-platform-intel-buffer-overflow-detected.patch new file mode 100644 index 0000000..a913674 --- /dev/null +++ b/0094-mdadm-platform-intel-buffer-overflow-detected.patch @@ -0,0 +1,44 @@ +From 827e1870f320545796d907f50af594e901399417 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 28 May 2024 16:44:39 +0800 +Subject: [PATCH 094/201] mdadm/platform-intel: buffer overflow detected + +mdadm -CR /dev/md0 -l1 -n2 /dev/nvme0n1 /dev/nvme2n1 +*** buffer overflow detected ***: terminated +Aborted (core dumped) + +It doesn't happen 100% and it depends on the building environment. +It can be fixed by replacing sprintf with snprintf. + +Fixes: d835518b6b53 ('imsm: nvme multipath support') +Reported-by: Guang Wu +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + platform-intel.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 15a9fa5a..d6a53533 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -907,14 +907,14 @@ char *get_nvme_multipath_dev_hw_path(const char *dev_path) + return NULL; + + for (ent = readdir(dir); ent; ent = readdir(dir)) { +- char buf[strlen(dev_path) + strlen(ent->d_name) + 1]; ++ char buf[PATH_MAX]; + + /* Check if dir is a controller, ignore namespaces*/ + if (!(strncmp(ent->d_name, "nvme", 4) == 0) || + (strrchr(ent->d_name, 'n') != &ent->d_name[0])) + continue; + +- sprintf(buf, "%s/%s", dev_path, ent->d_name); ++ snprintf(buf, PATH_MAX, "%s/%s", dev_path, ent->d_name); + rp = realpath(buf, NULL); + break; + } +-- +2.41.0 + diff --git a/0095-mdadm-tests-bitmap-cases-enhance.patch b/0095-mdadm-tests-bitmap-cases-enhance.patch new file mode 100644 index 0000000..5b6ad30 --- /dev/null +++ b/0095-mdadm-tests-bitmap-cases-enhance.patch @@ -0,0 +1,279 @@ +From c006602b313e2f6062b51aad37d93dccd29649de Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 28 May 2024 21:51:47 +0800 +Subject: [PATCH 095/201] mdadm/tests: bitmap cases enhance + +It fails because bitmap dirty number is smaller than 400 sometimes. It's not +good to compare bitmap dirty bits with a number. It depends on the test +machine, it can flush soon before checking the number. So remove related codes. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/05r1-grow-internal | 11 ++++------- + tests/05r1-grow-internal-1 | 12 ++++-------- + tests/05r1-internalbitmap | 22 ++++++++++------------ + tests/05r1-internalbitmap-v1a | 22 ++++++++++------------ + tests/05r1-internalbitmap-v1b | 23 ++++++++++------------- + tests/05r1-internalbitmap-v1c | 22 ++++++++++------------ + 6 files changed, 48 insertions(+), 64 deletions(-) + +diff --git a/tests/05r1-grow-internal b/tests/05r1-grow-internal +index 24b3aece..f7fff989 100644 +--- a/tests/05r1-grow-internal ++++ b/tests/05r1-grow-internal +@@ -8,18 +8,15 @@ testdev $md0 1 $mdsize1a 64 + + #mdadm -E $dev1 + mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1 || { mdadm -X $dev2 ; exit 1; } +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + + testdev $md0 1 $mdsize1a 64 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-#echo $dirty1 $dirty2 $dirty3 $dirty4 +-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ] +-then ++if [ $dirty1 -ne 0 -o $dirty2 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: dirty1 $dirty1, dirty2 $dirty2" + echo bad dirty counts + exit 1 + fi +diff --git a/tests/05r1-grow-internal-1 b/tests/05r1-grow-internal-1 +index 2f0d8237..f0f8349f 100644 +--- a/tests/05r1-grow-internal-1 ++++ b/tests/05r1-grow-internal-1 +@@ -8,19 +8,15 @@ testdev $md0 1 $mdsize1b 64 + + #mdadm -E $dev1 + mdadm --grow $md0 --bitmap=internal --bitmap-chunk=4 --delay=1 +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + + testdev $md0 1 $mdsize1b 64 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-#echo $dirty1 $dirty2 $dirty3 $dirty4 +-if [ $dirty2 -ne 0 -o $dirty4 -ne 0 -o $dirty3 -lt 400 ] +-then +- echo bad dirty counts ++if [ $dirty1 -ne 0 -o $dirty2 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: dirty1 $dirty1, dirty2 $dirty2" + exit 1 + fi + +diff --git a/tests/05r1-internalbitmap b/tests/05r1-internalbitmap +index dd7232a7..f1a2843e 100644 +--- a/tests/05r1-internalbitmap ++++ b/tests/05r1-internalbitmap +@@ -9,21 +9,20 @@ mdadm -S $md0 + + mdadm --assemble $md0 $dev1 $dev2 + testdev $md0 1 $mdsize0 64 +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" ++if [ $dirty1 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty1" + exit 1 + fi + mdadm $md0 -f $dev1 + testdev $md0 1 $mdsize0 64 + sleep 4 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" ++total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'` ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++if [ $dirty2 -ne $total ] ++then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2" + exit 2 + fi + +@@ -34,13 +33,12 @@ mdadm --zero-superblock $dev1 + mdadm $md0 --add $dev1 + check recovery + +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + check wait + sleep 4 +-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" ++if [ $dirty3 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty3" + exit 1 + fi + +diff --git a/tests/05r1-internalbitmap-v1a b/tests/05r1-internalbitmap-v1a +index 3ddc082f..cf3f3972 100644 +--- a/tests/05r1-internalbitmap-v1a ++++ b/tests/05r1-internalbitmap-v1a +@@ -10,21 +10,20 @@ mdadm -S $md0 + + mdadm --assemble $md0 $dev1 $dev2 + testdev $md0 1 $mdsize1b 64 +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" ++if [ $dirty1 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty1" + exit 1 + fi + mdadm $md0 -f $dev1 + testdev $md0 1 $mdsize1b 64 + sleep 4 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" ++total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'` ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++if [ $dirty2 -ne $total ] ++then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2" + exit 2 + fi + +@@ -35,13 +34,12 @@ mdadm --assemble -R $md0 $dev2 + mdadm $md0 --add $dev1 + check recovery + +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + check wait + sleep 4 +-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" ++if [ $dirty3 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty3" + exit 1 + fi + +diff --git a/tests/05r1-internalbitmap-v1b b/tests/05r1-internalbitmap-v1b +index 40f7abea..4952887e 100644 +--- a/tests/05r1-internalbitmap-v1b ++++ b/tests/05r1-internalbitmap-v1b +@@ -11,21 +11,20 @@ mdadm -S $md0 + mdadm --assemble $md0 $dev1 $dev2 + check bitmap + testdev $md0 1 $mdsize11 64 +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" ++if [ $dirty1 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty1" + exit 1 + fi + mdadm $md0 -f $dev1 + testdev $md0 1 $mdsize11 64 + sleep 4 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" ++total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'` ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++if [ $dirty2 -ne $total ] ++then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2" + exit 2 + fi + +@@ -35,14 +34,12 @@ mdadm --zero-superblock $dev1 + mdadm --assemble -R $md0 $dev2 + mdadm $md0 --add $dev1 + check recovery +- +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + check wait + sleep 4 +-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" ++if [ $dirty3 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty3" + exit 1 + fi + +diff --git a/tests/05r1-internalbitmap-v1c b/tests/05r1-internalbitmap-v1c +index 2eaea59b..e1e4472f 100644 +--- a/tests/05r1-internalbitmap-v1c ++++ b/tests/05r1-internalbitmap-v1c +@@ -10,21 +10,20 @@ mdadm -S $md0 + + mdadm --assemble $md0 $dev1 $dev2 + testdev $md0 1 $mdsize12 64 +-dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + sleep 4 +-dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty1=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty1 -lt 400 -o $dirty2 -ne 0 ] +-then echo >&2 "ERROR bad 'dirty' counts: $dirty1 and $dirty2" ++if [ $dirty1 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty1" + exit 1 + fi + mdadm $md0 -f $dev1 + testdev $md0 1 $mdsize12 64 + sleep 4 +-dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` +-if [ $dirty3 -lt 400 ] +-then +- echo >&2 "ERROR dirty count $dirty3 is too small" ++total=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) bits.*/\1/p'` ++dirty2=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++if [ $dirty2 -ne $total ] ++then echo >&2 "ERROR bad 'dirty' counts: total $total, dirty2 $dirty2" + exit 2 + fi + +@@ -35,13 +34,12 @@ mdadm --assemble -R $md0 $dev2 + mdadm $md0 --add $dev1 + check recovery + +-dirty4=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + check wait + sleep 4 +-dirty5=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` ++dirty3=`mdadm -X $dev2 | sed -n -e 's/.*Bitmap.* \([0-9]*\) dirty.*/\1/p'` + +-if [ $dirty4 -lt 400 -o $dirty5 -ne 0 ] +-then echo echo >&2 "ERROR bad 'dirty' counts at end: $dirty4 $dirty5" ++if [ $dirty3 -ne 0 ] ++then echo >&2 "ERROR bad 'dirty' counts: $dirty3" + exit 1 + fi + +-- +2.41.0 + diff --git a/0096-mdadm-tests-04update-uuid.patch b/0096-mdadm-tests-04update-uuid.patch new file mode 100644 index 0000000..1ee708c --- /dev/null +++ b/0096-mdadm-tests-04update-uuid.patch @@ -0,0 +1,39 @@ +From 19cde79fda386329f69ead15ca6ae26527fab707 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 28 May 2024 21:51:48 +0800 +Subject: [PATCH 096/201] mdadm/tests: 04update-uuid + +Patch 50b100768a11('mdadm: deprecate bitmap custom file') needs to confirm when +creating raid device with bitmap file. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/04update-uuid | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/04update-uuid b/tests/04update-uuid +index a4409e78..25314ab5 100644 +--- a/tests/04update-uuid ++++ b/tests/04update-uuid +@@ -25,7 +25,7 @@ mdadm -S /dev/md0 + + # now if we have a bitmap, that needs updating too. + rm -f $targetdir/bitmap +-mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2 ++yes | mdadm -CR --assume-clean -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2 + mdadm -S /dev/md0 + mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2 + no_errors +@@ -41,7 +41,7 @@ mdadm -S /dev/md0 + + # and bitmap for version1 + rm -f $targetdir/bitmap +-mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2 ++yes | mdadm -CR --assume-clean -e1.1 -b $targetdir/bitmap $md0 -l5 -n3 $dev0 $dev1 $dev2 + mdadm -S /dev/md0 + mdadm -A /dev/md0 -b $targetdir/bitmap --update=uuid --uuid=0123456789abcdef:fedcba9876543210 $dev0 $dev1 $dev2 + no_errors +-- +2.41.0 + diff --git a/0097-mdadm-tests-05r1-re-add-nosuper.patch b/0097-mdadm-tests-05r1-re-add-nosuper.patch new file mode 100644 index 0000000..deccca2 --- /dev/null +++ b/0097-mdadm-tests-05r1-re-add-nosuper.patch @@ -0,0 +1,30 @@ +From c36477fac2e485fd294e5cb48d411b548c654f30 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 28 May 2024 21:51:49 +0800 +Subject: [PATCH 097/201] mdadm/tests: 05r1-re-add-nosuper + +Patch 50b100768a11('mdadm: deprecate bitmap custom file') needs to confirm when +creating raid device with bitmap file. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/05r1-re-add-nosuper | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/05r1-re-add-nosuper b/tests/05r1-re-add-nosuper +index 058d602d..7d41fd7b 100644 +--- a/tests/05r1-re-add-nosuper ++++ b/tests/05r1-re-add-nosuper +@@ -6,7 +6,7 @@ + # + bmf=$targetdir/bitmap2 + rm -f $bmf +-mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2 ++yes | mdadm -B $md0 -l1 -n2 -b$bmf -d1 $dev1 $dev2 + check resync + check wait + testdev $md0 1 $size 1 +-- +2.41.0 + diff --git a/0098-mdadm-tests-remove-strace-test.patch b/0098-mdadm-tests-remove-strace-test.patch new file mode 100644 index 0000000..d6ce870 --- /dev/null +++ b/0098-mdadm-tests-remove-strace-test.patch @@ -0,0 +1,44 @@ +From c5a4fe7874f94b3f172027043f9a94b037f4d4dd Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Tue, 28 May 2024 21:51:50 +0800 +Subject: [PATCH 098/201] mdadm/tests: remove strace test + +Some tests will fail if the test env doesn't have strace +commands. So remove the dependency. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/07revert-grow | 2 +- + tests/07revert-inplace | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/07revert-grow b/tests/07revert-grow +index c8c4e855..333483dc 100644 +--- a/tests/07revert-grow ++++ b/tests/07revert-grow +@@ -43,7 +43,7 @@ testdev $md0 2 $mdsize1 512 + mdadm -G $md0 -n 5 + sleep 3 + mdadm -S $md0 +-strace -o /tmp/str ./mdadm -A $md0 --update=revert-reshape $devlist4 ++mdadm -A $md0 --update=revert-reshape $devlist4 + check wait + check raid10 + testdev $md0 2 $mdsize1 512 +diff --git a/tests/07revert-inplace b/tests/07revert-inplace +index a73eb977..776324ac 100644 +--- a/tests/07revert-inplace ++++ b/tests/07revert-inplace +@@ -37,7 +37,7 @@ testdev $md0 3 $mdsize1 64 + mdadm -G $md0 -c 32 + sleep 2 + mdadm -S $md0 +-strace -o /tmp/str ./mdadm -A $md0 --update=revert-reshape $devlist5 ++mdadm -A $md0 --update=revert-reshape $devlist5 + check wait + check raid10 + testdev $md0 3 $mdsize1 64 +-- +2.41.0 + diff --git a/0099-mdadm.h-provide-basename-if-GLIBC-is-not-avialable.patch b/0099-mdadm.h-provide-basename-if-GLIBC-is-not-avialable.patch new file mode 100644 index 0000000..54890d1 --- /dev/null +++ b/0099-mdadm.h-provide-basename-if-GLIBC-is-not-avialable.patch @@ -0,0 +1,37 @@ +From 9dbd11e091f84eb0bf9d717283774816c4c4453d Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 21 May 2024 16:26:33 +0200 +Subject: [PATCH 099/201] mdadm.h: provide basename if GLIBC is not avialable + +If GNU basename is not avilable, define it. It is safer to use that +rather than include libgen.h with XPG basename() definition. + +Fixes:#12 + +Signed-off-by: Mariusz Tkaczyk +--- + mdadm.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/mdadm.h b/mdadm.h +index 40818941..e9f764a2 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -223,6 +223,14 @@ struct dlm_lksb { + struct __una_u16 { __u16 x; } __attribute__ ((packed)); + struct __una_u32 { __u32 x; } __attribute__ ((packed)); + ++/* ++ * Ensure GNU basename behavior on GLIBC less systems. ++ */ ++#ifndef __GLIBC__ ++#define basename(path) \ ++ (strrchr((path), '/') ? strrchr((path),'/') + 1 : (path)) ++#endif ++ + static inline __u16 __get_unaligned16(const void *p) + { + const struct __una_u16 *ptr = (const struct __una_u16 *)p; +-- +2.41.0 + diff --git a/0100-imsm-fix-first-volume-autolayout-with-IMSM_NO_PLATFO.patch b/0100-imsm-fix-first-volume-autolayout-with-IMSM_NO_PLATFO.patch new file mode 100644 index 0000000..6d2831b --- /dev/null +++ b/0100-imsm-fix-first-volume-autolayout-with-IMSM_NO_PLATFO.patch @@ -0,0 +1,79 @@ +From 46f19270265fe54cda1c728cb156b755273b4ab6 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 23 May 2024 12:06:36 +0200 +Subject: [PATCH 100/201] imsm: fix first volume autolayout with + IMSM_NO_PLATFORM + +Autolayout_imsm() is not executed if IMSM_NO_PLATFORM=1 is set. +This causes that first volume cannot be created. Disk for new volume are +never configured. + +Fix it by making autolayout_imsm() independent from super->orom because +NULL there means that IMSM_NO_PLATFORM=1 is set. There are not platform +restrictions to create volume, we just analyze drives. It is safe. + +Fixes: 6d4d9ab295de ("imsm: use same slot across container") +Signed-off-by: Mariusz Tkaczyk +--- + super-intel.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 0287a618..29652196 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7706,9 +7706,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + char *dev, unsigned long long *freesize, + int consistency_policy, int verbose) + { +- int fd, cfd; ++ struct intel_super *super = st->sb; + struct mdinfo *sra; + int is_member = 0; ++ imsm_status_t rv; ++ int fd, cfd; + + /* load capability + * if given unused devices create a container +@@ -7733,11 +7735,10 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + } + + if (!dev) { +- struct intel_super *super = st->sb; +- + /* + * Autolayout mode, st->sb must be set. + */ ++ + if (!super) { + pr_vrb("superblock must be set for autolayout, aborting\n"); + return 0; +@@ -7749,20 +7750,19 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + return 0; + + if (super->orom && freesize) { +- imsm_status_t rv; +- int count = count_volumes(super->hba, super->orom->dpa, +- verbose); ++ int count = count_volumes(super->hba, super->orom->dpa, verbose); ++ + if (super->orom->vphba <= count) { + pr_vrb("platform does not support more than %d raid volumes.\n", + super->orom->vphba); + return 0; + } ++ } + +- rv = autolayout_imsm(super, raiddisks, size, *chunk, +- freesize); ++ rv = autolayout_imsm(super, raiddisks, size, *chunk, freesize); + if (rv != IMSM_STATUS_OK) + return 0; +- } ++ + return 1; + } + if (st->sb) { +-- +2.41.0 + diff --git a/0101-imsm-make-freesize-required-to-volume-autolayout.patch b/0101-imsm-make-freesize-required-to-volume-autolayout.patch new file mode 100644 index 0000000..5fb8b4a --- /dev/null +++ b/0101-imsm-make-freesize-required-to-volume-autolayout.patch @@ -0,0 +1,50 @@ +From 4f3efc34644d06f55fc650e4aa6b5a6ec22cea5f Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Tue, 11 Jun 2024 07:58:49 +0200 +Subject: [PATCH 101/201] imsm: make freesize required to volume autolayout + +Autolayout_imsm() shall be executed when IMSM_NO_PLATFORM=1 is set. +It was fixed by listed commit, checking super->orom was removed, but +also checking freesize. Freesize is not set for operations on RAID +volume with no size update, that's why it is not required to have +this value and always run autolayout_imsm(). +Fix it by making autolayout_imsm() dependent on freesize. + +Fixes: 46f192 ("imsm: fix first volume autolayout with IMSM_NO_PLATFORM") + +Signed-off-by: Kinga Stefaniuk +--- + super-intel.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 29652196..ef3f5da1 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -7749,7 +7749,7 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + verbose)) + return 0; + +- if (super->orom && freesize) { ++ if (super->orom) { + int count = count_volumes(super->hba, super->orom->dpa, verbose); + + if (super->orom->vphba <= count) { +@@ -7759,9 +7759,11 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, + } + } + +- rv = autolayout_imsm(super, raiddisks, size, *chunk, freesize); +- if (rv != IMSM_STATUS_OK) +- return 0; ++ if (freesize) { ++ rv = autolayout_imsm(super, raiddisks, size, *chunk, freesize); ++ if (rv != IMSM_STATUS_OK) ++ return 0; ++ } + + return 1; + } +-- +2.41.0 + diff --git a/0102-mdadm-Fix-hang-race-condition-in-wait_for_zero_forks.patch b/0102-mdadm-Fix-hang-race-condition-in-wait_for_zero_forks.patch new file mode 100644 index 0000000..675e248 --- /dev/null +++ b/0102-mdadm-Fix-hang-race-condition-in-wait_for_zero_forks.patch @@ -0,0 +1,86 @@ +From 1a5c0e60308651a20d25ff52511230a20d830330 Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Tue, 4 Jun 2024 10:38:36 -0600 +Subject: [PATCH 102/201] mdadm: Fix hang race condition in + wait_for_zero_forks() + +Running a create operation with --write-zeros can randomly hang +forever waiting for child processes. This happens roughly on in +ten runs with when running with small (20MB) loop devices. + +The bug is caused by the fact that signals can be coallesced into +one if they are not read by signalfd quick enough. So if two children +finish at exactly the same time, only one SIGCHLD will be received +by the parent. + +To fix this, wait on all processes with WNOHANG every time a SIGCHLD +is received and exit when all processes have been waited on. + +Reported-by: Xiao Ni +Signed-off-by: Logan Gunthorpe +Signed-off-by: Mariusz Tkaczyk +--- + Create.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/Create.c b/Create.c +index d033eb68..4f992a22 100644 +--- a/Create.c ++++ b/Create.c +@@ -178,6 +178,7 @@ static int wait_for_zero_forks(int *zero_pids, int count) + bool interrupted = false; + sigset_t sigset; + ssize_t s; ++ pid_t pid; + + for (i = 0; i < count; i++) + if (zero_pids[i]) +@@ -196,7 +197,7 @@ static int wait_for_zero_forks(int *zero_pids, int count) + return 1; + } + +- while (1) { ++ while (wait_count) { + s = read(sfd, &fdsi, sizeof(fdsi)); + if (s != sizeof(fdsi)) { + pr_err("Invalid signalfd read: %s\n", strerror(errno)); +@@ -209,23 +210,24 @@ static int wait_for_zero_forks(int *zero_pids, int count) + pr_info("Interrupting zeroing processes, please wait...\n"); + interrupted = true; + } else if (fdsi.ssi_signo == SIGCHLD) { +- if (!--wait_count) +- break; ++ for (i = 0; i < count; i++) { ++ if (!zero_pids[i]) ++ continue; ++ ++ pid = waitpid(zero_pids[i], &wstatus, WNOHANG); ++ if (pid <= 0) ++ continue; ++ ++ zero_pids[i] = 0; ++ if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) ++ ret = 1; ++ wait_count--; ++ } + } + } + + close(sfd); + +- for (i = 0; i < count; i++) { +- if (!zero_pids[i]) +- continue; +- +- waitpid(zero_pids[i], &wstatus, 0); +- zero_pids[i] = 0; +- if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) +- ret = 1; +- } +- + if (interrupted) { + pr_err("zeroing interrupted!\n"); + return 1; +-- +2.41.0 + diff --git a/0103-mdadm-Block-SIGCHLD-processes-before-starting-childr.patch b/0103-mdadm-Block-SIGCHLD-processes-before-starting-childr.patch new file mode 100644 index 0000000..d011eb4 --- /dev/null +++ b/0103-mdadm-Block-SIGCHLD-processes-before-starting-childr.patch @@ -0,0 +1,37 @@ +From 539ad6e6f9a067646a018d77582af0babf8e125e Mon Sep 17 00:00:00 2001 +From: Logan Gunthorpe +Date: Tue, 4 Jun 2024 10:38:37 -0600 +Subject: [PATCH 103/201] mdadm: Block SIGCHLD processes before starting + children + +There is a small race condition noticed during code review, but +never actully hit in practice, with the write_zero feature. + +If a write zeros fork finishes quickly before wait_for_zero_forks() +gets called, then the SIGCHLD will be delivered before the signalfd +is setup. + +While this is only theoretical, fix this by blocking the SIGCHLD +signal before forking any children. + +Signed-off-by: Logan Gunthorpe +Signed-off-by: Mariusz Tkaczyk +--- + Create.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Create.c b/Create.c +index 4f992a22..bd4875e4 100644 +--- a/Create.c ++++ b/Create.c +@@ -401,6 +401,7 @@ static int add_disks(int mdfd, struct mdinfo *info, struct shape *s, + */ + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); ++ sigaddset(&sigset, SIGCHLD); + sigprocmask(SIG_BLOCK, &sigset, &orig_sigset); + memset(zero_pids, 0, sizeof(zero_pids)); + +-- +2.41.0 + diff --git a/0104-test-pass-flags-to-services.patch b/0104-test-pass-flags-to-services.patch new file mode 100644 index 0000000..75c1901 --- /dev/null +++ b/0104-test-pass-flags-to-services.patch @@ -0,0 +1,137 @@ +From 29aa21d94bc7ff10f3f7ef0b7f490f3903f5c6fd Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Fri, 15 Mar 2024 16:03:09 -0400 +Subject: [PATCH 104/201] test: pass flags to services + +Commit 4c12714d1ca0 ("test: run tests on system level mdadm") removed +MDADM_NO_SYSTEMCTL flag from test suite. This causes imsm tests to fail +as mdadm no longer triggers mdmon and flags exists only within session. + +Use systemd set/unset-environment to pass necessary flags. + +Introduce colors to grab users attention to warnings and key messages. + +Make test suite setup systemd environment. +Add setup/clean_systemd_env() functions. +Warn user about altering systemd environment. + +Add colors to success/fail messages and warnings. + +Signed-off-by: Mateusz Kusiak +--- + test | 8 +++----- + tests/func.sh | 46 +++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 48 insertions(+), 6 deletions(-) + +diff --git a/test b/test +index 47f53ad7..3a05bc9b 100755 +--- a/test ++++ b/test +@@ -127,7 +127,7 @@ do_test() { + dmesg | grep -iq "error\|call trace\|segfault" | grep -v "systemd" && + die "dmesg prints errors when testing $_basename!" + fi +- echo "succeeded" ++ succeed "succeeded\n" + _fail=0 + else + save_log fail +@@ -315,10 +315,8 @@ parse_args() { + } + + print_warning() { +- cat <<-EOF +- Warning! Tests are performed on system level mdadm! +- If you want to test local build, you need to install it first! +- EOF ++ warn "Warning! Tests are performed on system level mdadm!\n" ++ echo "If you want to test local build, you need to install it first!" + } + + main() { +diff --git a/tests/func.sh b/tests/func.sh +index b2e4d122..8c142c76 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -23,6 +23,28 @@ mdsize12=19988 + # ddf needs bigger devices as 32Meg is reserved! + ddfsize=65536 + ++# Systemd flags ++devname_as_serial_flag="IMSM_DEVNAME_AS_SERIAL=1" ++no_platform_flag="IMSM_NO_PLATFORM=1" ++ ++# Common colors ++COLOR_FAIL='\033[0;31m' #RED ++COLOR_WARN='\033[1;33m' #YELLOW ++COLOR_SUCCESS='\033[0;32m' #GREEN ++COLOR_NONE='\033[0m' ++ ++fail() { ++ printf "${COLOR_FAIL}$1${COLOR_NONE}" ++} ++ ++warn() { ++ printf "${COLOR_WARN}$1${COLOR_NONE}" ++} ++ ++succeed() { ++ printf "${COLOR_SUCCESS}$1${COLOR_NONE}" ++} ++ + # $1 is optional parameter, it shows why to save log + save_log() { + status=$1 +@@ -36,7 +58,8 @@ save_log() { + cat /proc/mdstat >> $logdir/$logfile + array=($(mdadm -Ds | cut -d' ' -f2)) + [ "$1" == "fail" ] && +- echo "FAILED - see $logdir/$_basename.log and $logdir/$logfile for details" ++ fail "FAILED" ++ echo " - see $logdir/$_basename.log and $logdir/$logfile for details\n" + if [ $DEVTYPE == 'lvm' ] + then + # not supported lvm type yet +@@ -86,6 +109,7 @@ cleanup() { + $mdadm --zero ${disks[@]} &> /dev/null + ;; + esac ++ clean_systemd_env + } + + do_clean() +@@ -176,11 +200,31 @@ restore_selinux() { + setenforce $sys_selinux + } + ++setup_systemd_env() { ++ warn "Warning! Test suite will set up systemd environment!\n" ++ echo "Use \"systemctl show-environment\" to show systemd environment variables" ++ for env_var in $devname_as_serial_flag $no_platform_flag ++ do ++ systemctl set-environment $env_var ++ echo "Added $env_var" to systemd environment, use \ ++ \"systemctl unset-environment $env_var\" to remove it. ++ done ++} ++ ++clean_systemd_env() { ++ for env_var in $devname_as_serial_flag $no_platform_flag ++ do ++ systemctl unset-environment $env_var ++ echo "Removed $env_var from systemd environment." ++ done ++} ++ + do_setup() { + trap cleanup 0 1 3 15 + trap ctrl_c 2 + + check_env ++ setup_systemd_env + [ -d $logdir ] || mkdir -p $logdir + + devlist= +-- +2.41.0 + diff --git a/0105-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch b/0105-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch new file mode 100644 index 0000000..d38dc2b --- /dev/null +++ b/0105-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch @@ -0,0 +1,68 @@ +From 66a54b266f6c579e5f37b6253820903a55c3346c Mon Sep 17 00:00:00 2001 +From: Shminderjit Singh +Date: Tue, 4 Jun 2024 07:46:03 +0000 +Subject: [PATCH 105/201] mdadm: Fix socket connection failure when mdmon runs + in foreground mode. + +While creating an IMSM RAID, mdadm will wait for the mdmon main process +to finish if mdmon runs in forking mode. This is because with +"Type=forking" in the mdmon service unit file, "systemctl start service" +will block until the main process of mdmon exits. At that moment, mdmon +has already created the socket, so the subsequent socket connect from +mdadm will succeed. + +However, when mdmon runs in foreground mode (without "Type=forking" in +the service unit file), "systemctl start service" will return once the +mdmon process starts. This causes mdadm and mdmon to run in parallel, +which may lead to a socket connection failure since mdmon has not yet +initialized the socket when mdadm tries to connect. If the next +instruction/command is to access this device and try to write to it, a +permission error will occur since mdmon has not yet set the array to RW +mode. + +Signed-off-by: Shminderjit Singh +--- + msg.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/msg.c b/msg.c +index ba0e25be..d17f679d 100644 +--- a/msg.c ++++ b/msg.c +@@ -151,6 +151,7 @@ int connect_monitor(char *devname) + struct sockaddr_un addr; + int pos; + char *c; ++ int rv, retry_count = 0; + + pos = sprintf(path, "%s/", MDMON_DIR); + if (is_subarray(devname)) { +@@ -170,7 +171,24 @@ int connect_monitor(char *devname) + + addr.sun_family = PF_LOCAL; + strcpy(addr.sun_path, path); +- if (connect(sfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { ++ ++ /* In foreground mode, when mdadm is trying to connect to control ++ * socket it is possible that the mdmon has not created it yet. ++ * Give some time to mdmon to create socket. ++ */ ++ for (retry_count = 0; retry_count < 10; retry_count++) { ++ rv = connect(sfd, (struct sockaddr*)&addr, sizeof(addr)); ++ ++ if (rv < 0) { ++ sleep_for(0, MSEC_TO_NSEC(200), true); ++ continue; ++ } ++ break; ++ } ++ ++ if (rv < 0) { ++ pr_err("Failed to connect to control socket. (%s!!)\n", ++ strerror(errno)); + close(sfd); + return -1; + } +-- +2.41.0 + diff --git a/0106-Makefile-Do-not-call-gcc-directly.patch b/0106-Makefile-Do-not-call-gcc-directly.patch new file mode 100644 index 0000000..bda7a5d --- /dev/null +++ b/0106-Makefile-Do-not-call-gcc-directly.patch @@ -0,0 +1,50 @@ +From 027b2d37a8cd56973d117107acc25a64cfe0a92f Mon Sep 17 00:00:00 2001 +From: Gwendal Grignou +Date: Wed, 15 May 2024 14:30:59 -0700 +Subject: [PATCH 106/201] Makefile: Do not call gcc directly + +When mdadm is compiled with clang, direct gcc will fail. +Make sure to use $(CC) variable instead. + +Note that Clang does not support --help=warnings, +--print-diagnostic-options should be used instead. +So with Clang, the compilation will go through, but the +extra warning flags will never be added. + +Signed-off-by: Gwendal Grignou +--- + Makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Makefile b/Makefile +index 446710bd..3fe0a053 100644 +--- a/Makefile ++++ b/Makefile +@@ -56,21 +56,21 @@ CWFLAGS += -Wp -O3 + endif + + ifeq ($(origin FALLTHROUGH), undefined) +- FALLTHROUGH := $(shell gcc -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l) ++ FALLTHROUGH := $(shell $(CC) -Q --help=warnings 2>&1 | grep "implicit-fallthrough" | wc -l) + ifneq "$(FALLTHROUGH)" "0" + CWFLAGS += -Wimplicit-fallthrough=0 + endif + endif + + ifeq ($(origin FORMATOVERFLOW), undefined) +- FORMATOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l) ++ FORMATOVERFLOW := $(shell $(CC) -Q --help=warnings 2>&1 | grep "format-overflow" | wc -l) + ifneq "$(FORMATOVERFLOW)" "0" + CWFLAGS += -Wformat-overflow + endif + endif + + ifeq ($(origin STRINGOPOVERFLOW), undefined) +- STRINGOPOVERFLOW := $(shell gcc -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l) ++ STRINGOPOVERFLOW := $(shell $(CC) -Q --help=warnings 2>&1 | grep "stringop-overflow" | wc -l) + ifneq "$(STRINGOPOVERFLOW)" "0" + CWFLAGS += -Wstringop-overflow + endif +-- +2.41.0 + diff --git a/0107-mdadm-tests-judge-foreign-array-in-test-cases.patch b/0107-mdadm-tests-judge-foreign-array-in-test-cases.patch new file mode 100644 index 0000000..74155a1 --- /dev/null +++ b/0107-mdadm-tests-judge-foreign-array-in-test-cases.patch @@ -0,0 +1,103 @@ +From 23aef35113553cb97ef2e7b01c760d5449592e14 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 14 Jun 2024 10:45:01 +0800 +Subject: [PATCH 107/201] mdadm/tests: judge foreign array in test cases + +It needs to use array name when judging if one array is foreign or not. +So calling is_raid_foreign in test cases which need it. + +Fixes: 41706a915684 ('mdadm/tests: names_template enhance') +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/03assem-incr | 2 ++ + tests/06name | 2 ++ + tests/07autoassemble | 3 +++ + tests/func.sh | 9 +++++---- + tests/templates/names_template | 2 ++ + 5 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/tests/03assem-incr b/tests/03assem-incr +index 21215a34..56afbf2c 100644 +--- a/tests/03assem-incr ++++ b/tests/03assem-incr +@@ -12,6 +12,8 @@ if [ "$LINEAR" == "yes" ]; then + levels+=( linear ) + fi + ++is_raid_foreign $md0 ++ + for l in ${levels[@]} + do + mdadm -CR $md0 -l $l -n5 $dev0 $dev1 $dev2 $dev3 $dev4 --assume-clean +diff --git a/tests/06name b/tests/06name +index c3213f6c..9ec3437b 100644 +--- a/tests/06name ++++ b/tests/06name +@@ -2,6 +2,8 @@ set -x + + # create an array with a name + ++is_raid_foreign $md0 ++ + mdadm -CR $md0 -l0 -n2 --metadata=1 --name="Fred" $dev0 $dev1 + + if [ $is_foreign == "no" ]; then +diff --git a/tests/07autoassemble b/tests/07autoassemble +index 9dc78149..b6630e17 100644 +--- a/tests/07autoassemble ++++ b/tests/07autoassemble +@@ -2,6 +2,9 @@ + # create two raid1s, build a raid0 on top, then + # tear it down and get auto-assemble to rebuild it. + ++#the length of md0/md1/md2 is same. So use md0 here. ++is_raid_foreign $md0 ++ + mdadm -CR $md1 -l1 -n2 $dev0 $dev1 --homehost=testing + mdadm -CR $md2 -l1 -n2 $dev2 $dev3 --homehost=testing + mdadm -CR $md0 -l0 -n2 $md1 $md2 --homehost=testing +diff --git a/tests/func.sh b/tests/func.sh +index 8c142c76..e7ccc4fc 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -181,10 +181,12 @@ restore_system_speed_limit() { + + is_raid_foreign() { + +- # If the length of hostname is >= 32, super1 doesn't use +- # hostname in metadata ++ name=$1 ++ # super1 uses this formula strlen(homehost)+1+strlen(name) < 32 ++ # to decide if an array is foreign or local. It adds homehost if ++ # one array is local + hostname=$(hostname) +- if [ `expr length $(hostname)` -lt 32 ]; then ++ if [ `expr length "$(hostname)$name"` -lt 31 ]; then + is_foreign="no" + else + is_foreign="yes" +@@ -299,7 +301,6 @@ do_setup() { + [ -f /proc/mdstat ] || modprobe md_mod + echo 0 > /sys/module/md_mod/parameters/start_ro + record_system_speed_limit +- is_raid_foreign + record_selinux + } + +diff --git a/tests/templates/names_template b/tests/templates/names_template +index 88ad5b8c..c94245ea 100644 +--- a/tests/templates/names_template ++++ b/tests/templates/names_template +@@ -4,6 +4,8 @@ function names_create() { + local NAME=$2 + local NEG_TEST=$3 + ++ is_raid_foreign $DEVNAME ++ + if [[ -z "$NAME" ]]; then + mdadm -CR "$DEVNAME" -l0 -n 1 $dev0 --force + else +-- +2.41.0 + diff --git a/0108-Revert-mdadm-Fix-socket-connection-failure-when-mdmo.patch b/0108-Revert-mdadm-Fix-socket-connection-failure-when-mdmo.patch new file mode 100644 index 0000000..1c9e873 --- /dev/null +++ b/0108-Revert-mdadm-Fix-socket-connection-failure-when-mdmo.patch @@ -0,0 +1,58 @@ +From f98340f1b830d950978abba752b2b9b004528faf Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 20 Jun 2024 15:22:50 +0200 +Subject: [PATCH 108/201] Revert "mdadm: Fix socket connection failure when + mdmon runs in foreground mode." + +This reverts commit 66a54b266f6c579e5f37b6253820903a55c3346c. + +connect_monitor() is called from ping_monitor() but this function is often +used as advice, without verification that mdmon is really working. This +produces hangs in many scenarios. + +Signed-off-by: Mariusz Tkaczyk +--- + msg.c | 20 +------------------- + 1 file changed, 1 insertion(+), 19 deletions(-) + +diff --git a/msg.c b/msg.c +index d17f679d..f0772b3f 100644 +--- a/msg.c ++++ b/msg.c +@@ -151,7 +151,6 @@ int connect_monitor(char *devname) + struct sockaddr_un addr; + int pos; + char *c; +- int rv, retry_count = 0; + + pos = sprintf(path, "%s/", MDMON_DIR); + if (is_subarray(devname)) { +@@ -171,24 +170,7 @@ int connect_monitor(char *devname) + + addr.sun_family = PF_LOCAL; + strcpy(addr.sun_path, path); +- +- /* In foreground mode, when mdadm is trying to connect to control +- * socket it is possible that the mdmon has not created it yet. +- * Give some time to mdmon to create socket. +- */ +- for (retry_count = 0; retry_count < 10; retry_count++) { +- rv = connect(sfd, (struct sockaddr*)&addr, sizeof(addr)); +- +- if (rv < 0) { +- sleep_for(0, MSEC_TO_NSEC(200), true); +- continue; +- } +- break; +- } +- +- if (rv < 0) { +- pr_err("Failed to connect to control socket. (%s!!)\n", +- strerror(errno)); ++ if (connect(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + close(sfd); + return -1; + } +-- +2.41.0 + diff --git a/0109-mdadm-Assemble.c-fix-coverity-issues.patch b/0109-mdadm-Assemble.c-fix-coverity-issues.patch new file mode 100644 index 0000000..8810889 --- /dev/null +++ b/0109-mdadm-Assemble.c-fix-coverity-issues.patch @@ -0,0 +1,149 @@ +From 3e6358e9aa0618f6a7de3a58e545caaada03739f Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 25 Jun 2024 07:57:28 -0400 +Subject: [PATCH 109/201] mdadm: Assemble.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event dereference: Dereferencing "pre_exist", which is known to be "NULL". +* Event parameter_hidden: Declaration hides parameter "c". +* Event leaked_storage: Variable "pre_exist" going out of scope leaks the + storage it points to. +* Event leaked_storage: Variable "avail" going out of scope leaks the + storage it points to. + +Signed-off-by: Nigel Croxon +--- + Assemble.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 0e6da593..77f2b50e 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -567,6 +567,9 @@ static int select_devices(struct mddev_dev *devlist, + tmpdev->used = 1; + content = *contentp; + ++ if (!st) ++ return -1; ++ + if (!st->sb) { + /* we need sb from one of the spares */ + int dfd = dev_open(tmpdev->devname, O_RDONLY); +@@ -815,12 +818,12 @@ static int load_devices(struct devs *devices, char *devmap, + if (i >= bestcnt) { + int newbestcnt = i+10; + int *newbest = xmalloc(sizeof(int)*newbestcnt); +- int c; +- for (c=0; c < newbestcnt; c++) +- if (c < bestcnt) +- newbest[c] = best[c]; ++ int cc; ++ for (cc = 0; cc < newbestcnt; cc++) ++ if (cc < bestcnt) ++ newbest[cc] = best[cc]; + else +- newbest[c] = -1; ++ newbest[cc] = -1; + if (best)free(best); + best = newbest; + bestcnt = newbestcnt; +@@ -1493,8 +1496,11 @@ try_again: + mp = map_by_uuid(&map, content->uuid); + if (mp) { + struct mdinfo *dv; +- /* array already exists. */ + pre_exist = sysfs_read(-1, mp->devnm, GET_LEVEL|GET_DEVS); ++ if (!pre_exist) ++ goto out; ++ ++ /* array already exists. */ + if (pre_exist->array.level != UnSet) { + pr_err("Found some drive for an array that is already active: %s\n", + mp->path); +@@ -1606,6 +1612,7 @@ try_again: + err = assemble_container_content(st, mdfd, content, c, + chosen_name, NULL); + close(mdfd); ++ sysfs_free(pre_exist); + return err; + } + +@@ -1745,23 +1752,27 @@ try_again: + : (O_RDONLY|O_EXCL)))< 0) { + pr_err("Cannot open %s: %s\n", + devices[j].devname, strerror(errno)); ++ free(avail); + goto out; + } + if (st->ss->load_super(st,fd, NULL)) { + close(fd); + pr_err("RAID superblock has disappeared from %s\n", + devices[j].devname); ++ free(avail); + goto out; + } + close(fd); + } + if (st->sb == NULL) { + pr_err("No suitable drives found for %s\n", mddev); ++ free(avail); + goto out; + } + st->ss->getinfo_super(st, content, NULL); + if (sysfs_init(content, mdfd, NULL)) { + pr_err("Unable to initialize sysfs\n"); ++ free(avail); + goto out; + } + +@@ -1824,12 +1835,14 @@ try_again: + if (fd < 0) { + pr_err("Could not open %s for write - cannot Assemble array.\n", + devices[chosen_drive].devname); ++ free(avail); + goto out; + } + if (st->ss->store_super(st, fd)) { + close(fd); + pr_err("Could not re-write superblock on %s\n", + devices[chosen_drive].devname); ++ free(avail); + goto out; + } + if (c->verbose >= 0) +@@ -1888,6 +1901,7 @@ try_again: + pr_err("Failed to restore critical section for reshape, sorry.\n"); + if (c->backup_file == NULL) + cont_err("Possibly you needed to specify the --backup-file\n"); ++ free(avail); + goto out; + } + } +@@ -1916,6 +1930,7 @@ try_again: + if (rv == 1 && !pre_exist) + ioctl(mdfd, STOP_ARRAY, NULL); + free(devices); ++ free(avail); + out: + map_unlock(&map); + if (rv == 0) { +@@ -1951,11 +1966,14 @@ out: + close(mdfd); + + free(best); ++ sysfs_free(pre_exist); ++ + /* '2' means 'OK, but not started yet' */ + if (rv == -1) { + free(devices); + return 1; + } ++ close(mdfd); + return rv == 2 ? 0 : rv; + } + +-- +2.41.0 + diff --git a/0111-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch b/0111-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch new file mode 100644 index 0000000..c5ebc40 --- /dev/null +++ b/0111-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch @@ -0,0 +1,118 @@ +From 3cbe13403ec0c78374343dcd889609aefe791f9b Mon Sep 17 00:00:00 2001 +From: Shminderjit Singh +Date: Mon, 24 Jun 2024 08:58:51 +0000 +Subject: [PATCH 111/201] mdadm: Fix socket connection failure when mdmon runs + in foreground mode. + +While creating an IMSM RAID, mdadm will wait for the mdmon main process +to finish if mdmon runs in forking mode. This is because with +"Type=forking" in the mdmon service unit file, "systemctl start service" +will block until the main process of mdmon exits. At that moment, mdmon +has already created the socket, so the subsequent socket connect from +mdadm will succeed. + +However, when mdmon runs in foreground mode (without "Type=forking" in +the service unit file), "systemctl start service" will return once the +mdmon process starts. This causes mdadm and mdmon to run in parallel, +which may lead to a socket connection failure since mdmon has not yet +initialized the socket when mdadm tries to connect. If the next +instruction/command is to access this device and try to write to it, a +permission error will occur since mdmon has not yet set the array to RW +mode. + +Signed-off-by: Shminderjit Singh +--- + Create.c | 6 ++++-- + mdadm.h | 1 + + util.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 50 insertions(+), 2 deletions(-) + +diff --git a/Create.c b/Create.c +index bd4875e4..479c2715 100644 +--- a/Create.c ++++ b/Create.c +@@ -1344,9 +1344,11 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, + if (c->verbose >= 0) + pr_info("array %s started.\n", chosen_name); + if (st->ss->external && st->container_devnm[0]) { +- if (need_mdmon) ++ if (need_mdmon) { + start_mdmon(st->container_devnm); +- ++ if (wait_for_mdmon_control_socket(st->container_devnm) != MDADM_STATUS_SUCCESS) ++ goto abort; ++ } + ping_monitor(st->container_devnm); + close(container_fd); + } +diff --git a/mdadm.h b/mdadm.h +index e9f764a2..27009154 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1776,6 +1776,7 @@ extern int is_subarray_active(char *subarray, char *devname); + extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet); + extern struct superswitch *version_to_superswitch(char *vers); + ++extern mdadm_status_t wait_for_mdmon_control_socket(const char *container_devnm); + extern int mdmon_running(const char *devnm); + extern int mdmon_pid(const char *devnm); + extern mdadm_status_t wait_for_mdmon(const char *devnm); +diff --git a/util.c b/util.c +index 48c97545..908f8430 100644 +--- a/util.c ++++ b/util.c +@@ -1932,6 +1932,51 @@ int mdmon_running(const char *devnm) + return 0; + } + ++/* ++ * wait_for_mdmon_control_socket() - Waits for mdmon control socket ++ * to be created within specified time. ++ * @container_devnm: Device for which mdmon control socket should start. ++ * ++ * In foreground mode, when mdadm is trying to connect to control ++ * socket it is possible that the mdmon has not created it yet. ++ * Give some time to mdmon to create socket. Timeout set to 2 sec. ++ * ++ * Return: MDADM_STATUS_SUCCESS if connect succeed, otherwise return ++ * error code. ++ */ ++mdadm_status_t wait_for_mdmon_control_socket(const char *container_devnm) ++{ ++ enum mdadm_status status = MDADM_STATUS_SUCCESS; ++ int sfd, rv, retry_count = 0; ++ struct sockaddr_un addr; ++ char path[PATH_MAX]; ++ ++ snprintf(path, PATH_MAX, "%s/%s.sock", MDMON_DIR, container_devnm); ++ sfd = socket(PF_LOCAL, SOCK_STREAM, 0); ++ if (!is_fd_valid(sfd)) ++ return MDADM_STATUS_ERROR; ++ ++ addr.sun_family = PF_LOCAL; ++ strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1); ++ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; ++ ++ for (retry_count = 0; retry_count < 10; retry_count++) { ++ rv = connect(sfd, (struct sockaddr*)&addr, sizeof(addr)); ++ if (rv < 0) { ++ sleep_for(0, MSEC_TO_NSEC(200), true); ++ continue; ++ } ++ break; ++ } ++ ++ if (rv < 0) { ++ pr_err("Failed to connect to control socket.\n"); ++ status = MDADM_STATUS_ERROR; ++ } ++ close(sfd); ++ return status; ++} ++ + /* + * wait_for_mdmon() - Waits for mdmon within specified time. + * @devnm: Device for which mdmon should start. +-- +2.41.0 + diff --git a/0113-config.c-Fix-memory-leak-in-load_containers.patch b/0113-config.c-Fix-memory-leak-in-load_containers.patch new file mode 100644 index 0000000..6074241 --- /dev/null +++ b/0113-config.c-Fix-memory-leak-in-load_containers.patch @@ -0,0 +1,28 @@ +From 44457789fd67168c37932060f9a991f0c611e5a2 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Fri, 28 Jun 2024 12:32:16 +0200 +Subject: [PATCH 113/201] config.c: Fix memory leak in load_containers() + +Fix memory leak in load_containers() in config.c reported by SAST +analysis. + +Signed-off-by: Anna Sztukowska +--- + config.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/config.c b/config.c +index 612e700d..cd2379bd 100644 +--- a/config.c ++++ b/config.c +@@ -379,6 +379,7 @@ struct mddev_dev *load_containers(void) + map = NULL; + } + free_mdstat(mdstat); ++ map_free(map); + + return rv; + } +-- +2.41.0 + diff --git a/0114-mdadm-Build.c-fix-coverity-issues.patch b/0114-mdadm-Build.c-fix-coverity-issues.patch new file mode 100644 index 0000000..74dcf9a --- /dev/null +++ b/0114-mdadm-Build.c-fix-coverity-issues.patch @@ -0,0 +1,40 @@ +From 0244bac0a828e69aef36404437cac4ff148eaea0 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 2 Jul 2024 09:49:13 -0400 +Subject: [PATCH 114/201] mdadm: Build.c fix coverity issues + +Event leaked_handle: Handle variable "bitmap_fd" going out of +scope leaks the handle. + +Signed-off-by: Nigel Croxon +--- + Build.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/Build.c b/Build.c +index 1be90e41..052b1bc2 100644 +--- a/Build.c ++++ b/Build.c +@@ -168,13 +168,13 @@ int Build(struct mddev_ident *ident, struct mddev_dev *devlist, struct shape *s, + goto abort; + } + } +- if (bitmap_fd >= 0) { +- if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { +- pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, +- strerror(errno)); +- goto abort; +- } ++ if (ioctl(mdfd, SET_BITMAP_FILE, bitmap_fd) < 0) { ++ pr_err("Cannot set bitmap file for %s: %s\n", chosen_name, ++ strerror(errno)); ++ close(bitmap_fd); ++ goto abort; + } ++ close(bitmap_fd); + } + if (ioctl(mdfd, RUN_ARRAY, ¶m)) { + pr_err("RUN_ARRAY failed: %s\n", strerror(errno)); +-- +2.41.0 + diff --git a/0115-mdadm-Create.c-fix-coverity-issues.patch b/0115-mdadm-Create.c-fix-coverity-issues.patch new file mode 100644 index 0000000..08c5651 --- /dev/null +++ b/0115-mdadm-Create.c-fix-coverity-issues.patch @@ -0,0 +1,45 @@ +From 7c524aa83c4463c15a13f6f47a27a18ab4de9eef Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Fri, 5 Jul 2024 08:45:32 -0400 +Subject: [PATCH 115/201] mdadm: Create.c fix coverity issues + +* Event negative_returns: "fd" is passed to a parameter that cannot be negative. Which +is set to -1 to start. + +* Event open_fn: Returning handle opened by "open_dev_excl". +* Event var_assign: Assigning: "container_fd" = handle returned from +"open_dev_excl(st->container_devnm)" +* Event leaked_handle: Handle variable "container_fd" going out of scope leaks the handle + +Signed-off-by: Nigel Croxon +--- + Create.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Create.c b/Create.c +index 479c2715..7fde1c16 100644 +--- a/Create.c ++++ b/Create.c +@@ -297,7 +297,7 @@ static int add_disk_to_super(int mdfd, struct shape *s, struct context *c, + if (st->ss->add_to_super(st, &info->disk, fd, dv->devname, + dv->data_offset)) { + ioctl(mdfd, STOP_ARRAY, NULL); +- close(fd); ++ close_fd(&fd); + return 1; + } + st->ss->getinfo_super(st, info, NULL); +@@ -1370,8 +1370,8 @@ int Create(struct supertype *st, struct mddev_ident *ident, int subdevs, + map_remove(&map, fd2devnm(mdfd)); + map_unlock(&map); + +- if (mdfd >= 0) +- close(mdfd); ++ close_fd(&mdfd); ++ close_fd(&container_fd); + + dev_policy_free(custom_pols); + return 1; +-- +2.41.0 + diff --git a/0116-mdadm-super-ddf.c-fix-coverity-issues.patch b/0116-mdadm-super-ddf.c-fix-coverity-issues.patch new file mode 100644 index 0000000..5e223d1 --- /dev/null +++ b/0116-mdadm-super-ddf.c-fix-coverity-issues.patch @@ -0,0 +1,473 @@ +From 96b8035a09b6449ea99f2eb91f9ba4f6912e5bd6 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 2 Jul 2024 10:11:26 -0400 +Subject: [PATCH 116/201] mdadm: super-ddf.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Calling "lseek64" without checking return value. This library function may +fail and return an error code. +* Overrunning array "anchor->pad2" of 3 bytes by passing it to a function +which accesses it at byte offset 398 using argument "399UL". +* Event leaked_storage: Variable "sra" going out of scope leaks the storage +it points to. +* Event leaked_storage: Variable "super" going out of scope leaks the storage +it points to. +* Event leaked_handle: Handle variable "dfd" going out of scope leaks the +handle. +* Event leaked_storage: Variable "dl1" going out of scope leaks the storage +it points to +* Event leaked_handle: Handle variable "cfd" going out of scope leaks the +handle. +* Variable "avail" going out of scope leaks the storage it points to. +* Passing unterminated string "super->anchor.revision" to "fprintf", which +expects a null-terminated string. +* You might overrun the 32-character fixed-size string "st->container_devnm" +by copying the return value of "fd2devnm" without checking the length. +* Event fixed_size_dest: You might overrun the 33-character fixed-size string +"dev->name" by copying "(*d).devname" without checking the length. +* Event uninit_use_in_call: Using uninitialized value "info.array.raid_disks" +when calling "getinfo_super_ddf" + +V2: clean up validate_geometry_ddf() routine with Mariusz Tkaczyk recommendations. +V3: clean up spaces with Blazej Kucman recommendations. +V4: clean up recommended by Mariusz Tkaczyk. +V5: clean up recommended by Mariusz Tkaczyk. + +Signed-off-by: Nigel Croxon +--- + super-ddf.c | 172 +++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 115 insertions(+), 57 deletions(-) + +diff --git a/super-ddf.c b/super-ddf.c +index 311001c1..d870102d 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -809,7 +809,7 @@ static int load_ddf_header(int fd, unsigned long long lba, + if (lba >= size-1) + return 0; + +- if (lseek64(fd, lba<<9, 0) < 0) ++ if (lseek64(fd, lba << 9, 0) == -1L) + return 0; + + if (read(fd, hdr, 512) != 512) +@@ -828,8 +828,7 @@ static int load_ddf_header(int fd, unsigned long long lba, + !be64_eq(anchor->primary_lba, hdr->primary_lba) || + !be64_eq(anchor->secondary_lba, hdr->secondary_lba) || + hdr->type != type || +- memcmp(anchor->pad2, hdr->pad2, 512 - +- offsetof(struct ddf_header, pad2)) != 0) { ++ memcmp(anchor->pad2, hdr->pad2, sizeof(anchor->pad2)) != 0) { + pr_err("header mismatch\n"); + return 0; + } +@@ -863,7 +862,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)lseek64(fd, offset << 9, 0) != (offset << 9)) { + if (dofree) + free(buf); + return NULL; +@@ -882,7 +881,7 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname) + + get_dev_size(fd, NULL, &dsize); + +- if (lseek64(fd, dsize-512, 0) < 0) { ++ if (lseek64(fd, dsize - 512, 0) == -1L) { + if (devname) + pr_err("Cannot seek to anchor block on %s: %s\n", + devname, strerror(errno)); +@@ -909,8 +908,7 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname) + if (memcmp(super->anchor.revision, DDF_REVISION_0, 8) != 0 && + memcmp(super->anchor.revision, DDF_REVISION_2, 8) != 0) { + if (devname) +- pr_err("can only support super revision %.8s and earlier, not %.8s on %s\n", +- DDF_REVISION_2, super->anchor.revision,devname); ++ pr_err("The DDF revision on %s\n is not supported", devname); + return 2; + } + super->active = NULL; +@@ -1610,6 +1608,7 @@ static unsigned int get_vd_num_of_subarray(struct supertype *st) + return DDF_NOTFOUND; + } + ++ sysfs_free(sra); + return vcnum; + } + +@@ -1617,11 +1616,11 @@ static void brief_examine_super_ddf(struct supertype *st, int verbose) + { + /* We just write a generic DDF ARRAY entry + */ +- struct mdinfo info; ++ struct mdinfo info = {0}; + char nbuf[64]; ++ + getinfo_super_ddf(st, &info, NULL); + fname_from_uuid(&info, nbuf); +- + printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5); + } + +@@ -1631,9 +1630,10 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose) + * by uuid and member by unit number and uuid. + */ + struct ddf_super *ddf = st->sb; +- struct mdinfo info; ++ struct mdinfo info = {0}; + unsigned int i; + char nbuf[64]; ++ + getinfo_super_ddf(st, &info, NULL); + fname_from_uuid(&info, nbuf); + +@@ -1658,8 +1658,9 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose) + + static void export_examine_super_ddf(struct supertype *st) + { +- struct mdinfo info; ++ struct mdinfo info = {0}; + char nbuf[64]; ++ + getinfo_super_ddf(st, &info, NULL); + fname_from_uuid(&info, nbuf); + printf("MD_METADATA=ddf\n"); +@@ -1692,10 +1693,12 @@ 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) < 0) ++ if (lseek64(from, dsize - 512, 0) == -1L) + goto err; ++ + if (read(from, buf, 512) != 512) + goto err; ++ + ddf = buf; + if (!be32_eq(ddf->magic, DDF_HEADER_MAGIC) || + !be32_eq(calc_crc(ddf, 512), ddf->crc) || +@@ -1711,9 +1714,9 @@ static int copy_metadata_ddf(struct supertype *st, int from, int to) + + bytes = dsize - offset; + +- if (lseek64(from, offset, 0) < 0 || +- lseek64(to, offset, 0) < 0) ++ if (lseek64(from, offset, 0) == -1L || lseek64(to, offset, 0) == -1L) + goto err; ++ + while (written < bytes) { + int n = bytes - written; + if (n > 4096) +@@ -1795,6 +1798,7 @@ static void brief_detail_super_ddf(struct supertype *st, char *subarray) + char nbuf[64]; + struct ddf_super *ddf = st->sb; + unsigned int vcnum = get_vd_num_of_subarray(st); ++ + if (vcnum == DDF_CONTAINER) + uuid_from_super_ddf(st, info.uuid); + else if (vcnum == DDF_NOTFOUND) +@@ -2971,7 +2975,9 @@ static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type) + header->openflag = 1; + header->crc = calc_crc(header, 512); + +- lseek64(fd, sector<<9, 0); ++ if (lseek64(fd, sector << 9, 0) == -1L) ++ goto out; ++ + if (write(fd, header, 512) < 0) + goto out; + +@@ -2982,6 +2988,7 @@ static int __write_ddf_structure(struct dl *d, struct ddf_super *ddf, __u8 type) + ddf->phys->crc = calc_crc(ddf->phys, ddf->pdsize); + if (write(fd, ddf->phys, ddf->pdsize) < 0) + goto out; ++ + ddf->virt->crc = calc_crc(ddf->virt, ddf->vdsize); + if (write(fd, ddf->virt, ddf->vdsize) < 0) + goto out; +@@ -3035,7 +3042,9 @@ out: + header->openflag = 0; + header->crc = calc_crc(header, 512); + +- lseek64(fd, sector<<9, 0); ++ if (lseek64(fd, sector << 9, 0) == -1L) ++ return 0; ++ + if (write(fd, header, 512) < 0) + ret = 0; + +@@ -3088,7 +3097,9 @@ static int _write_super_to_disk(struct ddf_super *ddf, struct dl *d) + if (!__write_ddf_structure(d, ddf, DDF_HEADER_SECONDARY)) + return 0; + +- lseek64(fd, (size-1)*512, SEEK_SET); ++ if (lseek64(fd, (size - 1) * 512, SEEK_SET) == -1L) ++ return 0; ++ + if (write(fd, &ddf->anchor, 512) < 0) + return 0; + +@@ -3299,9 +3310,10 @@ static int validate_geometry_ddf(struct supertype *st, + char *dev, unsigned long long *freesize, + int consistency_policy, int verbose) + { +- int fd; +- struct mdinfo *sra; ++ struct mdinfo *sra = NULL; ++ int ret = 1; + int cfd; ++ int fd; + + /* ddf potentially supports lots of things, but it depends on + * what devices are offered (and maybe kernel version?) +@@ -3369,7 +3381,7 @@ static int validate_geometry_ddf(struct supertype *st, + * Later we should check for a BVD and make an SVD. + */ + fd = open(dev, O_RDONLY|O_EXCL, 0); +- if (fd >= 0) { ++ if (is_fd_valid(fd)) { + close(fd); + /* Just a bare device, no good to us */ + if (verbose) +@@ -3377,44 +3389,58 @@ static int validate_geometry_ddf(struct supertype *st, + dev); + return 0; + } ++ + if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) { + if (verbose) + pr_err("ddf: Cannot open %s: %s\n", + dev, strerror(errno)); + return 0; + } ++ + /* Well, it is in use by someone, maybe a 'ddf' container. */ + cfd = open_container(fd); +- if (cfd < 0) { +- close(fd); ++ close(fd); ++ ++ if (!is_fd_valid(cfd)) { + if (verbose) +- pr_err("ddf: Cannot use %s: %s\n", +- dev, strerror(EBUSY)); ++ pr_err("ddf: Cannot use %s\n", dev); + return 0; + } ++ + sra = sysfs_read(cfd, NULL, GET_VERSION); +- close(fd); +- if (sra && sra->array.major_version == -1 && +- strcmp(sra->text_version, "ddf") == 0) { ++ if (!sra) { ++ pr_err("Cannot read sysfs for /dev/%s\n", fd2kname(cfd)); ++ goto error; ++ } ++ ++ if (sra->array.major_version == -1 && strcmp(sra->text_version, "ddf") == 0) { + /* This is a member of a ddf container. Load the container + * and try to create a bvd + */ +- struct ddf_super *ddf; ++ struct ddf_super *ddf = NULL; ++ + if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL) == 0) { + st->sb = ddf; +- strcpy(st->container_devnm, fd2devnm(cfd)); ++ snprintf(st->container_devnm, sizeof(st->container_devnm), ++ "%s", fd2kname(cfd)); + close(cfd); +- return validate_geometry_ddf_bvd(st, level, layout, +- raiddisks, chunk, size, +- data_offset, +- dev, freesize, +- verbose); ++ free(sra); ++ ++ return validate_geometry_ddf_bvd(st, level, layout, raiddisks, ++ chunk, size, data_offset, dev, ++ freesize, verbose); + } +- close(cfd); +- } else /* device may belong to a different container */ +- return 0; ++ free(ddf); ++ } + +- return 1; ++ /* device may belong to a different container */ ++ ret = 0; ++ ++error: ++ free(sra); ++ close(cfd); ++ ++ return ret; + } + + static int validate_geometry_ddf_bvd(struct supertype *st, +@@ -3483,35 +3509,42 @@ static int validate_geometry_ddf_bvd(struct supertype *st, + static int load_super_ddf_all(struct supertype *st, int fd, + void **sbp, char *devname) + { +- struct mdinfo *sra; +- struct ddf_super *super; + struct mdinfo *sd, *best = NULL; ++ struct ddf_super *super = NULL; ++ struct mdinfo *sra; + int bestseq = 0; +- int seq; ++ int ret = 1; + char nm[20]; ++ int seq; + int dfd; + + sra = sysfs_read(fd, NULL, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); + if (!sra) + return 1; +- if (sra->array.major_version != -1 || +- sra->array.minor_version != -2 || ++ if (sra->array.major_version != -1 || sra->array.minor_version != -2 || + strcmp(sra->text_version, "ddf") != 0) +- return 1; ++ goto out; + + if (posix_memalign((void**)&super, 512, sizeof(*super)) != 0) +- return 1; ++ goto out; ++ + memset(super, 0, sizeof(*super)); + + /* first, try each device, and choose the best ddf */ + for (sd = sra->devs ; sd ; sd = sd->next) { + int rv; ++ + sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor); ++ + dfd = dev_open(nm, O_RDONLY); +- if (dfd < 0) +- return 2; ++ if (!is_fd_valid(dfd)) { ++ ret = 2; ++ goto out; ++ } ++ + rv = load_ddf_headers(dfd, super, NULL); + close(dfd); ++ + if (rv == 0) { + seq = be32_to_cpu(super->active->seq); + if (super->active->openflag) +@@ -3523,28 +3556,39 @@ static int load_super_ddf_all(struct supertype *st, int fd, + } + } + if (!best) +- return 1; ++ goto out; ++ + /* OK, load this ddf */ + sprintf(nm, "%d:%d", best->disk.major, best->disk.minor); ++ + dfd = dev_open(nm, O_RDONLY); + if (dfd < 0) +- return 1; ++ goto out; ++ + load_ddf_headers(dfd, super, NULL); + load_ddf_global(dfd, super, NULL); + close(dfd); ++ + /* Now we need the device-local bits */ + for (sd = sra->devs ; sd ; sd = sd->next) { + int rv; + + sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor); ++ + dfd = dev_open(nm, O_RDWR); +- if (dfd < 0) +- return 2; ++ if (dfd < 0) { ++ ret = 2; ++ goto out; ++ } ++ + rv = load_ddf_headers(dfd, super, NULL); + if (rv == 0) + rv = load_ddf_local(dfd, super, NULL, 1); +- if (rv) +- return 1; ++ ++ if (rv) { ++ close(dfd); ++ goto out; ++ } + } + + *sbp = super; +@@ -3553,8 +3597,16 @@ static int load_super_ddf_all(struct supertype *st, int fd, + st->minor_version = 0; + st->max_devs = 512; + } +- strcpy(st->container_devnm, fd2devnm(fd)); +- return 0; ++ ++ snprintf(st->container_devnm, sizeof(st->container_devnm), "%s", fd2devnm(fd)); ++ ret = 0; ++ ++out: ++ if (sra) ++ free(sra); ++ if (super && ret != 0) ++ free(super); ++ return ret; + } + + static int load_container_ddf(struct supertype *st, int fd, +@@ -3791,7 +3843,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray + be64_to_cpu(LBA_OFFSET(ddf, bvd)[iphys]); + dev->component_size = be64_to_cpu(bvd->blocks); + if (d->devname) +- strcpy(dev->name, d->devname); ++ snprintf(dev->name, sizeof(dev->name), "%s", d->devname); + } + } + return rest; +@@ -3840,11 +3892,15 @@ static int store_super_ddf(struct supertype *st, int fd) + return 1; + memset(buf, 0, 512); + +- lseek64(fd, dsize-512, 0); ++ if (lseek64(fd, dsize - 512, 0) == -1L) { ++ free(buf); ++ return 1; ++ } + rc = write(fd, buf, 512); + free(buf); + if (rc < 0) + return 1; ++ + return 0; + } + +@@ -3959,6 +4015,7 @@ static int compare_super_ddf(struct supertype *st, struct supertype *tst, + if (posix_memalign((void **)&dl1->spare, 512, + first->conf_rec_len*512) != 0) { + pr_err("could not allocate spare info buf\n"); ++ free(dl1); + return 3; + } + memcpy(dl1->spare, dl2->spare, first->conf_rec_len*512); +@@ -4180,6 +4237,7 @@ static int get_bvd_state(const struct ddf_super *ddf, + state = DDF_state_part_optimal; + break; + } ++ free(avail); + return state; + } + +-- +2.41.0 + diff --git a/0117-mdadm-clustermd_tests-add-some-APIs-in-func.sh-to-su.patch b/0117-mdadm-clustermd_tests-add-some-APIs-in-func.sh-to-su.patch new file mode 100644 index 0000000..c699102 --- /dev/null +++ b/0117-mdadm-clustermd_tests-add-some-APIs-in-func.sh-to-su.patch @@ -0,0 +1,102 @@ +From cdce3219a52938fc35f93b5f17561f2ca7175e37 Mon Sep 17 00:00:00 2001 +From: Heming Zhao +Date: Tue, 9 Jul 2024 20:04:51 +0800 +Subject: [PATCH 117/201] mdadm/clustermd_tests: add some APIs in func.sh to + support running the tests without errors + +clustermd_tests/func.sh lacks some APIs to run, this patch makes +clustermd_tests runnable from the test suite. + +Signed-off-by: Heming Zhao +Signed-off-by: Mariusz Tkaczyk +--- + clustermd_tests/func.sh | 60 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +diff --git a/clustermd_tests/func.sh b/clustermd_tests/func.sh +index 801d6043..e659c0ba 100644 +--- a/clustermd_tests/func.sh ++++ b/clustermd_tests/func.sh +@@ -1,5 +1,22 @@ + #!/bin/bash + ++COLOR_FAIL='\033[0;31m' #RED ++COLOR_WARN='\033[1;33m' #YELLOW ++COLOR_SUCCESS='\033[0;32m' #GREEN ++COLOR_NONE='\033[0m' ++ ++fail() { ++ printf "${COLOR_FAIL}$1${COLOR_NONE}" ++} ++ ++warn() { ++ printf "${COLOR_WARN}$1${COLOR_NONE}" ++} ++ ++succeed() { ++ printf "${COLOR_SUCCESS}$1${COLOR_NONE}" ++} ++ + check_ssh() + { + NODE1="$(grep '^NODE1' $CLUSTER_CONF | cut -d'=' -f2)" +@@ -151,6 +168,33 @@ stop_md() + fi + } + ++record_system_speed_limit() { ++ system_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max` ++ system_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min` ++} ++ ++# To avoid sync action finishes before checking it, it needs to limit ++# the sync speed ++control_system_speed_limit() { ++ echo $test_speed_limit_min > /proc/sys/dev/raid/speed_limit_min ++ echo $test_speed_limit_max > /proc/sys/dev/raid/speed_limit_max ++} ++ ++restore_system_speed_limit() { ++ echo $system_speed_limit_min > /proc/sys/dev/raid/speed_limit_max ++ echo $system_speed_limit_max > /proc/sys/dev/raid/speed_limit_max ++} ++ ++record_selinux() { ++ # empty ++ return 0 ++} ++ ++restore_selinux() { ++ # empty ++ return 0 ++} ++ + # $1/optional, it shows why to save log + save_log() + { +@@ -240,6 +284,22 @@ check() + die "$ip: check '$2' failed." + done + ;; ++ recovery-remote ) ++ cnt=5 ++ for ip in ${NODES[@]} ++ do ++ while ! ssh $ip "grep -sqE 'recovery|REMOTE' /proc/mdstat" ++ do ++ if [ "$cnt" -gt '0' ] ++ then ++ sleep 0.2 ++ cnt=$[cnt-1] ++ else ++ die "$ip: no '$2' happening!" ++ fi ++ done ++ done ++ ;; + PENDING | recovery | resync | reshape ) + cnt=5 + for ip in ${NODES[@]} +-- +2.41.0 + diff --git a/0118-mdadm-clustermd_tests-adjust-test-cases-to-support-m.patch b/0118-mdadm-clustermd_tests-adjust-test-cases-to-support-m.patch new file mode 100644 index 0000000..0e55e3c --- /dev/null +++ b/0118-mdadm-clustermd_tests-adjust-test-cases-to-support-m.patch @@ -0,0 +1,81 @@ +From bde21cc929d4864bd4b9f459f46ce63dd8c793ca Mon Sep 17 00:00:00 2001 +From: Heming Zhao +Date: Tue, 9 Jul 2024 20:04:52 +0800 +Subject: [PATCH 118/201] mdadm/clustermd_tests: adjust test cases to support + md module changes + +Since kernel commit db5e653d7c9f ("md: delay choosing sync action to +md_start_sync()") delays the start of the sync action, clustermd +array sync/resync jobs can happen on any leg of the array. This +commit adjusts the test cases to follow the new kernel layer behavior. + +Signed-off-by: Heming Zhao +Signed-off-by: Mariusz Tkaczyk +--- + clustermd_tests/02r10_Manage_re-add | 3 ++- + clustermd_tests/02r1_Manage_re-add | 1 + + clustermd_tests/03r10_switch-recovery | 4 ++-- + clustermd_tests/03r1_switch-recovery | 4 ++-- + 4 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/clustermd_tests/02r10_Manage_re-add b/clustermd_tests/02r10_Manage_re-add +index 2288a008..d8764667 100644 +--- a/clustermd_tests/02r10_Manage_re-add ++++ b/clustermd_tests/02r10_Manage_re-add +@@ -9,7 +9,8 @@ check all state UU + check all dmesg + mdadm --manage $md0 --fail $dev0 --remove $dev0 + mdadm --manage $md0 --re-add $dev0 +-check $NODE1 recovery ++#non-clustered array also doesn't do sync job ++#check $NODE1 recovery + check all wait + check all state UU + check all dmesg +diff --git a/clustermd_tests/02r1_Manage_re-add b/clustermd_tests/02r1_Manage_re-add +index d0d13e53..811df87b 100644 +--- a/clustermd_tests/02r1_Manage_re-add ++++ b/clustermd_tests/02r1_Manage_re-add +@@ -9,6 +9,7 @@ check all state UU + check all dmesg + mdadm --manage $md0 --fail $dev0 --remove $dev0 + mdadm --manage $md0 --re-add $dev0 ++check all wait + check all state UU + check all dmesg + stop_md all $md0 +diff --git a/clustermd_tests/03r10_switch-recovery b/clustermd_tests/03r10_switch-recovery +index 867388d0..7d0b8812 100644 +--- a/clustermd_tests/03r10_switch-recovery ++++ b/clustermd_tests/03r10_switch-recovery +@@ -10,9 +10,9 @@ check all state UU + check all dmesg + mdadm --manage $md0 --fail $dev0 + sleep 0.2 +-check $NODE1 recovery ++check $NODE1 recovery-remote + stop_md $NODE1 $md0 +-check $NODE2 recovery ++check $NODE2 recovery-remote + check $NODE2 wait + check $NODE2 state UU + check all dmesg +diff --git a/clustermd_tests/03r1_switch-recovery b/clustermd_tests/03r1_switch-recovery +index a1a7cbe7..d8483c45 100644 +--- a/clustermd_tests/03r1_switch-recovery ++++ b/clustermd_tests/03r1_switch-recovery +@@ -10,9 +10,9 @@ check all state UU + check all dmesg + mdadm --manage $md0 --fail $dev0 + sleep 0.3 +-check $NODE1 recovery ++check $NODE1 recovery-remote + stop_md $NODE1 $md0 +-check $NODE2 recovery ++check $NODE2 recovery-remote + check $NODE2 wait + check $NODE2 state UU + check all dmesg +-- +2.41.0 + diff --git a/0119-mapfile.c-Fix-STRING_OVERFLOW-issue.patch b/0119-mapfile.c-Fix-STRING_OVERFLOW-issue.patch new file mode 100644 index 0000000..2abcdb3 --- /dev/null +++ b/0119-mapfile.c-Fix-STRING_OVERFLOW-issue.patch @@ -0,0 +1,40 @@ +From 48c365376ce7763fd9a9e7735b1e9ec5d0ff1631 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Wed, 3 Jul 2024 14:11:58 +0200 +Subject: [PATCH 119/201] mapfile.c: Fix STRING_OVERFLOW issue + +Fix STRING_OVERFLOW issue found by SAST analysis in map_add() and +map_update() in mapfile.c. + +Signed-off-by: Anna Sztukowska +--- + mapfile.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/mapfile.c b/mapfile.c +index f1f3ee2c..ea9837ac 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -165,8 +165,8 @@ void map_add(struct map_ent **melp, + { + struct map_ent *me = xmalloc(sizeof(*me)); + +- strcpy(me->devnm, devnm); +- strcpy(me->metadata, metadata); ++ snprintf(me->devnm, sizeof(me->devnm), "%s", devnm); ++ snprintf(me->metadata, sizeof(me->metadata), "%s", metadata); + memcpy(me->uuid, uuid, 16); + me->path = path ? xstrdup(path) : NULL; + me->next = *melp; +@@ -227,7 +227,7 @@ int map_update(struct map_ent **mpp, char *devnm, char *metadata, + + for (mp = map ; mp ; mp=mp->next) + if (strcmp(mp->devnm, devnm) == 0) { +- strcpy(mp->metadata, metadata); ++ snprintf(mp->metadata, sizeof(mp->metadata), "%s", metadata); + memcpy(mp->uuid, uuid, 16); + free(mp->path); + mp->path = path ? xstrdup(path) : NULL; +-- +2.41.0 + diff --git a/0120-mdadm-Manage.c-fix-coverity-issues.patch b/0120-mdadm-Manage.c-fix-coverity-issues.patch new file mode 100644 index 0000000..75ba7c6 --- /dev/null +++ b/0120-mdadm-Manage.c-fix-coverity-issues.patch @@ -0,0 +1,484 @@ +From 1b4b73fd535a6487075e98f620454ff2e13b5240 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 10 Jul 2024 08:55:08 -0400 +Subject: [PATCH 120/201] mdadm: Manage.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event parameter_hidden: declaration hides parameter "dv". +* Event leaked_storage: Variable "mdi" going out of scope leaks the storage +it points to. +* Event overwrite_var: Overwriting "mdi" in "mdi = mdi->devs" leaks the +storage that "mdi" points to. +* Event leaked_handle: Handle variable "lfd" going out of scope leaks +the handle. +* Event leaked_handle: Returning without closing handle "fd" leaks it. +* Event fixed_size_dest: You might overrun the 32-character fixed-sizei +string "devnm" by copying the return value of "fd2devnm" without +checking the length. +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "nm" by copying "nmp" without checking the length. +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "devnm" by copying the return value of "fd2devnm" without +checking the length. +* Event assigned_value: Assigning value "-1" to "tfd" here, but that +stored value is overwritten before it can be used. + +Signed-off-by: Nigel Croxon +--- + Manage.c | 149 ++++++++++++++++++++++++++----------------------------- + 1 file changed, 71 insertions(+), 78 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 5db72b77..aa5e80b2 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -56,7 +56,7 @@ int Manage_ro(char *devname, int fd, int readonly) + vers[9] = '-'; + sysfs_set_str(mdi, NULL, "metadata_version", vers); + +- close(fd); ++ close_fd(&fd); + rv = sysfs_set_str(mdi, NULL, "array_state", "readonly"); + + if (rv < 0) { +@@ -165,7 +165,7 @@ int Manage_run(char *devname, int fd, struct context *c) + pr_err("Cannot find %s in sysfs!!\n", devname); + return 1; + } +- strcpy(nm, nmp); ++ snprintf(nm, sizeof(nm), "%s", nmp); + return IncrementalScan(c, nm); + } + +@@ -187,7 +187,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + if (will_retry && verbose == 0) + verbose = -1; + +- strcpy(devnm, fd2devnm(fd)); ++ snprintf(devnm, sizeof(devnm), "%s", fd2devnm(fd)); + /* Get EXCL access first. If this fails, then attempting + * to stop is probably a bad idea. + */ +@@ -195,7 +195,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + if (mdi && is_subarray(mdi->text_version)) + sysfs_get_container_devnm(mdi, container); + +- close(fd); ++ close_fd(&fd); + count = 5; + while (((fd = ((devname[0] == '/') + ?open(devname, O_RDONLY|O_EXCL) +@@ -206,14 +206,12 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + * is a container, so we might be racing with mdmon, so + * retry for a bit. + */ +- if (fd >= 0) +- close(fd); ++ close_fd(&fd); + flush_mdmon(container); + count--; + } + if (fd < 0 || strcmp(fd2devnm(fd), devnm) != 0) { +- if (fd >= 0) +- close(fd); ++ close_fd(&fd); + if (verbose >= 0) + pr_err("Cannot get exclusive access to %s:Perhaps a running process, mounted filesystem or active volume group?\n", + devname); +@@ -228,7 +226,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + is_subarray(mdi->text_version)) { + int err; + /* This is mdmon managed. */ +- close(fd); ++ close_fd(&fd); + + /* As we had an O_EXCL open, any use of the device + * which blocks STOP_ARRAY is probably a transient use, +@@ -430,8 +428,7 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + break; + sysfs_wait(scfd, &delay); + } +- if (scfd >= 0) +- close(scfd); ++ close_fd(&scfd); + + } + done: +@@ -469,6 +466,7 @@ done: + map_unlock(&map); + out: + sysfs_free(mdi); ++ close_fd(&fd); + + return rv; + } +@@ -664,7 +662,7 @@ int attempt_re_add(int fd, int tfd, struct mddev_dev *dv, + devname, verbose, 0, NULL); + if (rv == 0) + rv = dev_st->ss->store_super(dev_st, tfd); +- close(tfd); ++ close_fd(&tfd); + if (rv != 0) { + pr_err("failed to update superblock during re-add\n"); + return -1; +@@ -766,15 +764,15 @@ mdadm_status_t manage_add_external(struct supertype *st, int fd, char *disk_name + rv = MDADM_STATUS_SUCCESS; + + out: +- close(container_fd); ++ close_fd(&container_fd); + dev_policy_free(pols); + + if (sra) + sysfs_free(sra); + +- if (rv != MDADM_STATUS_SUCCESS && is_fd_valid(disk_fd)) ++ if (rv != MDADM_STATUS_SUCCESS) + /* Metadata handler records this descriptor, so release it only on failure. */ +- close(disk_fd); ++ close_fd(&disk_fd); + + if (st->sb) + st->ss->free_super(st); +@@ -845,10 +843,10 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + continue; + if (tst->ss->load_super(tst, dfd, + NULL)) { +- close(dfd); ++ close_fd(&dfd); + continue; + } +- close(dfd); ++ close_fd(&dfd); + break; + } + /* FIXME this is a bad test to be using */ +@@ -1100,7 +1098,8 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, + */ + int ret; + char devnm[32]; +- strcpy(devnm, fd2devnm(fd)); ++ ++ snprintf(devnm, sizeof(devnm), "%s", fd2devnm(fd)); + lfd = open_dev_excl(devnm); + if (lfd < 0) { + pr_err("Cannot get exclusive access to container - odd\n"); +@@ -1134,13 +1133,13 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, + if (ret == 0) { + pr_err("%s is not a member, cannot remove.\n", + dv->devname); +- close(lfd); ++ close_fd(&lfd); + return -1; + } + if (ret >= 2) { + pr_err("%s is still in use, cannot remove.\n", + dv->devname); +- close(lfd); ++ close_fd(&lfd); + return -1; + } + } +@@ -1157,26 +1156,27 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, + /* Old kernels rejected this if no personality + * is registered */ + struct mdinfo *sra = sysfs_read(fd, NULL, GET_DEVS); +- struct mdinfo *dv = NULL; +- if (sra) +- dv = sra->devs; +- for ( ; dv ; dv=dv->next) +- if (dv->disk.major == (int)major(rdev) && +- dv->disk.minor == (int)minor(rdev)) +- break; +- if (dv) +- err = sysfs_set_str(sra, dv, +- "state", "remove"); +- else ++ struct mdinfo *dev = NULL; ++ ++ if (!sra) { + err = -1; +- sysfs_free(sra); ++ } else { ++ for (dev = sra->devs; dev ; dev = dev->next) ++ if (dev->disk.major == (int)major(rdev) && ++ dev->disk.minor == (int)minor(rdev)) ++ break; ++ ++ if (dev) ++ err = sysfs_set_str(sra, dev, ++ "state", "remove"); ++ sysfs_free(sra); ++ } + } + } + if (err) { + pr_err("hot remove failed for %s: %s\n", dv->devname, + strerror(errno)); +- if (lfd >= 0) +- close(lfd); ++ close_fd(&lfd); + return -1; + } + if (tst->ss->external) { +@@ -1190,13 +1190,13 @@ int Manage_remove(struct supertype *tst, int fd, struct mddev_dev *dv, + + if (!devnm) { + pr_err("unable to get container name\n"); ++ close_fd(&lfd); + return -1; + } + + ping_manager(devnm); + } +- if (lfd >= 0) +- close(lfd); ++ close_fd(&lfd); + if (verbose >= 0) + pr_err("hot removed %s from %s\n", + dv->devname, devname); +@@ -1218,7 +1218,7 @@ int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv, + if (!mdi || !mdi->devs) { + pr_err("Cannot find status of %s to enable replacement - strange\n", + devname); +- return -1; ++ goto abort; + } + for (di = mdi->devs; di; di = di->next) + if (di->disk.major == (int)major(rdev) && +@@ -1229,16 +1229,14 @@ int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv, + if (di->disk.raid_disk < 0) { + pr_err("%s is not active and so cannot be replaced.\n", + dv->devname); +- sysfs_free(mdi); +- return -1; ++ goto abort; + } + rv = sysfs_set_str(mdi, di, + "state", "want_replacement"); + if (rv) { +- sysfs_free(mdi); + pr_err("Failed to request replacement for %s\n", + dv->devname); +- return -1; ++ goto abort; + } + if (verbose >= 0) + pr_err("Marked %s (device %d in %s) for replacement\n", +@@ -1252,11 +1250,13 @@ int Manage_replace(struct supertype *tst, int fd, struct mddev_dev *dv, + dv->disposition = 'w'; + dv->used = di->disk.raid_disk; + } ++ sysfs_free(mdi); + return 1; + } +- sysfs_free(mdi); + pr_err("%s not found in %s so cannot --replace it\n", + dv->devname, devname); ++abort: ++ sysfs_free(mdi); + return -1; + } + +@@ -1269,7 +1269,7 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv, + if (!mdi || !mdi->devs) { + pr_err("Cannot find status of %s to enable replacement - strange\n", + devname); +- return -1; ++ goto abort; + } + for (di = mdi->devs; di; di = di->next) + if (di->disk.major == (int)major(rdev) && +@@ -1280,31 +1280,30 @@ int Manage_with(struct supertype *tst, int fd, struct mddev_dev *dv, + if (di->disk.state & (1<devname); +- sysfs_free(mdi); +- return -1; ++ goto abort; + } + if (di->disk.raid_disk >= 0) { + pr_err("%s is active and cannot be a replacement\n", + dv->devname); +- sysfs_free(mdi); +- return -1; ++ goto abort; + } + rv = sysfs_set_num(mdi, di, + "slot", dv->used); + if (rv) { +- sysfs_free(mdi); + pr_err("Failed to set %s as preferred replacement.\n", + dv->devname); +- return -1; ++ goto abort; + } + if (verbose >= 0) + pr_err("Marked %s in %s as replacement for device %d\n", + dv->devname, devname, dv->used); ++ sysfs_free(mdi); + return 1; + } +- sysfs_free(mdi); + pr_err("%s not found in %s so cannot make it preferred replacement\n", + dv->devname, devname); ++abort: ++ sysfs_free(mdi); + return -1; + } + +@@ -1324,6 +1323,7 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const + { + dev_t devid = devnm2devid(devname + 5); + struct mdinfo *mdi = sysfs_read(fd, NULL, GET_DEVS | GET_DISKS | GET_STATE); ++ struct mdinfo *disk; + + if (!mdi) { + if (verbose) +@@ -1333,14 +1333,14 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const + + char *avail = xcalloc(array->raid_disks, sizeof(char)); + +- for (mdi = mdi->devs; mdi; mdi = mdi->next) { +- if (mdi->disk.raid_disk < 0) ++ for (disk = mdi->devs; disk; disk = mdi->next) { ++ if (disk->disk.raid_disk < 0) + continue; +- if (!(mdi->disk.state & (1 << MD_DISK_SYNC))) ++ if (!(disk->disk.state & (1 << MD_DISK_SYNC))) + continue; +- if (makedev(mdi->disk.major, mdi->disk.minor) == devid) ++ if (makedev(disk->disk.major, disk->disk.minor) == devid) + continue; +- avail[mdi->disk.raid_disk] = 1; ++ avail[disk->disk.raid_disk] = 1; + } + sysfs_free(mdi); + +@@ -1550,7 +1550,7 @@ int Manage_subdevs(char *devname, int fd, + rdev = makedev(mj,mn); + found = 1; + } +- close(sysfd); ++ close_fd(&sysfd); + sysfd = -1; + } + if (!found) { +@@ -1572,7 +1572,7 @@ int Manage_subdevs(char *devname, int fd, + tfd = dev_open(dv->devname, O_RDONLY); + if (tfd >= 0) { + fstat_is_blkdev(tfd, dv->devname, &rdev); +- close(tfd); ++ close_fd(&tfd); + } else { + int open_err = errno; + if (!stat_is_blkdev(dv->devname, &rdev)) { +@@ -1635,7 +1635,7 @@ int Manage_subdevs(char *devname, int fd, + * need non-exclusive access to add it, so + * do that now. + */ +- close(tfd); ++ close_fd(&tfd); + tfd = dev_open(dv->devname, O_RDONLY); + } + if (tfd < 0) { +@@ -1654,8 +1654,7 @@ int Manage_subdevs(char *devname, int fd, + rv = Manage_add(fd, tfd, dv, tst, &array, + force, verbose, devname, update, + rdev, array_size, raid_slot); +- close(tfd); +- tfd = -1; ++ close_fd(&tfd); + if (rv < 0) + goto abort; + if (rv > 0) +@@ -1672,7 +1671,7 @@ int Manage_subdevs(char *devname, int fd, + rdev, verbose, force, + devname); + if (sysfd >= 0) +- close(sysfd); ++ close_fd(&sysfd); + sysfd = -1; + if (rv < 0) + goto abort; +@@ -1684,8 +1683,7 @@ int Manage_subdevs(char *devname, int fd, + if (!is_remove_safe(&array, fd, dv->devname, verbose)) { + pr_err("Cannot remove %s from %s, array will be failed.\n", + dv->devname, devname); +- if (sysfd >= 0) +- close(sysfd); ++ close_fd(&sysfd); + goto abort; + } + case 'I': /* incremental fail */ +@@ -1696,13 +1694,10 @@ int Manage_subdevs(char *devname, int fd, + busy = 1; + pr_err("set device faulty failed for %s: %s\n", + dv->devname, strerror(errno)); +- if (sysfd >= 0) +- close(sysfd); ++ close_fd(&sysfd); + goto abort; + } +- if (sysfd >= 0) +- close(sysfd); +- sysfd = -1; ++ close_fd(&sysfd); + count++; + if (verbose >= 0) + pr_err("set %s faulty in %s\n", +@@ -1762,7 +1757,7 @@ int autodetect(void) + if (fd >= 0) { + if (ioctl(fd, RAID_AUTORUN, 0) == 0) + rv = 0; +- close(fd); ++ close_fd(&fd); + } + return rv; + } +@@ -1825,7 +1820,7 @@ free_super: + if (info) + free(info); + st->ss->free_super(st); +- close(fd); ++ close_fd(&fd); + + return rv; + } +@@ -1843,10 +1838,8 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + int fd2 = open(from_devname, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) { +- if (fd1 >= 0) +- close(fd1); +- if (fd2 >= 0) +- close(fd2); ++ close_fd(&fd1); ++ close_fd(&fd2); + return 0; + } + +@@ -1865,15 +1858,15 @@ int move_spare(char *from_devname, char *to_devname, dev_t devid) + /* make sure manager is aware of changes */ + ping_manager(to_devname); + ping_manager(from_devname); +- close(fd1); +- close(fd2); ++ close_fd(&fd1); ++ close_fd(&fd2); + return 1; + } + else + Manage_subdevs(from_devname, fd2, &devlist, + -1, 0, UOPT_UNDEFINED, 0); + } +- close(fd1); +- close(fd2); ++ close_fd(&fd1); ++ close_fd(&fd2); + return 0; + } +-- +2.41.0 + diff --git a/0121-Manage-fix-is_remove_safe.patch b/0121-Manage-fix-is_remove_safe.patch new file mode 100644 index 0000000..02006cc --- /dev/null +++ b/0121-Manage-fix-is_remove_safe.patch @@ -0,0 +1,29 @@ +From ec72668a9768ad01b409b68f31f3ca7ffeeaab4e Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 16 Jul 2024 15:37:34 +0200 +Subject: [PATCH 121/201] Manage: fix is_remove_safe() + +Fix for to make --set-faulty working. + +Fixes: 1b4b73fd535a ("mdadm: Manage.c fix coverity issues") +Signed-off-by: Mariusz Tkaczyk +--- + Manage.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Manage.c b/Manage.c +index aa5e80b2..f0304e1e 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1333,7 +1333,7 @@ bool is_remove_safe(mdu_array_info_t *array, const int fd, char *devname, const + + char *avail = xcalloc(array->raid_disks, sizeof(char)); + +- for (disk = mdi->devs; disk; disk = mdi->next) { ++ for (disk = mdi->devs; disk; disk = disk->next) { + if (disk->disk.raid_disk < 0) + continue; + if (!(disk->disk.state & (1 << MD_DISK_SYNC))) +-- +2.41.0 + diff --git a/0122-imsm-add-indent-for-encryption-details.patch b/0122-imsm-add-indent-for-encryption-details.patch new file mode 100644 index 0000000..c9dded4 --- /dev/null +++ b/0122-imsm-add-indent-for-encryption-details.patch @@ -0,0 +1,28 @@ +From f8274feea5c63300e893109840943513df924da2 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 15 Jul 2024 12:21:19 +0200 +Subject: [PATCH 122/201] imsm: add indent for encryption details + +Improve readability of the output. + +Signed-off-by: Mariusz Tkaczyk +--- + super-intel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/super-intel.c b/super-intel.c +index ef3f5da1..713bfccf 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2318,7 +2318,7 @@ void print_encryption_information(int disk_fd, enum sys_dev_type hba_type) + { + struct encryption_information information = {0}; + mdadm_status_t status = MDADM_STATUS_SUCCESS; +- const char *indent = " "; ++ const char *indent = " "; + + switch (hba_type) { + case SYS_DEV_VMD: +-- +2.41.0 + diff --git a/0123-mdadm-Monitor.c-fix-coverity-issues.patch b/0123-mdadm-Monitor.c-fix-coverity-issues.patch new file mode 100644 index 0000000..c4edc19 --- /dev/null +++ b/0123-mdadm-Monitor.c-fix-coverity-issues.patch @@ -0,0 +1,67 @@ +From 5cb6df3f190feccc8b3e82da2b01a0e01e612a25 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Mon, 15 Jul 2024 10:13:46 -0400 +Subject: [PATCH 123/201] mdadm: Monitor.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event check_return: Calling "fcntl(fd, 2, 1)" without checking +return value. This library function may fail and return an error code. + +* Dereferencing "sl", which is known to be "NULL". + +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "devnm" by copying "tmp" without checking the length. + +Signed-off-by: Nigel Croxon +--- + Monitor.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index 9b016bc3..26c53e13 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -782,7 +782,9 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, + if (!is_container && !md_array_active(fd)) + goto disappeared; + +- fcntl(fd, F_SETFD, FD_CLOEXEC); ++ if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) ++ goto out; ++ + if (md_get_array_info(fd, &array) < 0) + goto disappeared; + +@@ -997,7 +999,8 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist) + snprintf(st->parent_devnm, MD_NAME_MAX, + "%s", mse->metadata_version + 10); + sl = strchr(st->parent_devnm, '/'); +- *sl = 0; ++ if (sl) ++ *sl = 0; + } else + st->parent_devnm[0] = 0; + *statelist = st; +@@ -1261,7 +1264,7 @@ int Wait(char *dev) + return 2; + } + +- strcpy(devnm, tmp); ++ snprintf(devnm, sizeof(devnm), "%s", tmp); + + while(1) { + struct mdstat_ent *ms = mdstat_read(1, 0); +@@ -1332,7 +1335,8 @@ int WaitClean(char *dev, int verbose) + return 1; + } + +- strcpy(devnm, fd2devnm(fd)); ++ snprintf(devnm, sizeof(devnm), "%s", fd2devnm(fd)); ++ + mdi = sysfs_read(fd, devnm, GET_VERSION|GET_LEVEL|GET_SAFEMODE); + if (!mdi) { + if (verbose) +-- +2.41.0 + diff --git a/0124-mdadm-Query.c-fix-coverity-issues.patch b/0124-mdadm-Query.c-fix-coverity-issues.patch new file mode 100644 index 0000000..4da409f --- /dev/null +++ b/0124-mdadm-Query.c-fix-coverity-issues.patch @@ -0,0 +1,42 @@ +From bcc3ab1728da61e5519e1f01597c8da0c5bc769b Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 16 Jul 2024 07:19:34 -0400 +Subject: [PATCH 124/201] mdadm: Query.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event leaked_storage: Variable "sra" going out of scope leaks the +storage it points to. + +* Event uninit_use_in_call: Using uninitialized value "larray_size" when +calling "human_size_brief". + +Signed-off-by: Nigel Croxon +--- + Query.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Query.c b/Query.c +index adcd231e..aedb4ce7 100644 +--- a/Query.c ++++ b/Query.c +@@ -39,7 +39,7 @@ int Query(char *dev) + struct mdinfo info; + struct mdinfo *sra; + struct supertype *st = NULL; +- unsigned long long larray_size; ++ unsigned long long larray_size = 0; + struct stat stb; + char *mddev; + mdu_disk_info_t disc; +@@ -136,5 +136,7 @@ int Query(char *dev) + if (st->ss == &super0) + put_md_name(mddev); + } ++ free(sra); ++ + return 0; + } +-- +2.41.0 + diff --git a/0125-mdadm-lib.c-fix-coverity-issues.patch b/0125-mdadm-lib.c-fix-coverity-issues.patch new file mode 100644 index 0000000..21455c3 --- /dev/null +++ b/0125-mdadm-lib.c-fix-coverity-issues.patch @@ -0,0 +1,43 @@ +From da7aecdf25371e1476da4ec56e9ec5ddf13af5da Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Tue, 16 Jul 2024 07:20:10 -0400 +Subject: [PATCH 125/201] mdadm: lib.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "devnm" by copying "cp + 1" without checking the length. + +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "devnm" by copying "cp" without checking the length. + +Signed-off-by: Nigel Croxon +--- + lib.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib.c b/lib.c +index 2b09293c..13d4e4f1 100644 +--- a/lib.c ++++ b/lib.c +@@ -109,7 +109,7 @@ char *devid2kname(dev_t devid) + link[n] = 0; + cp = strrchr(link, '/'); + if (cp) { +- strcpy(devnm, cp + 1); ++ snprintf(devnm, sizeof(devnm), "%s", cp + 1); + return devnm; + } + } +@@ -159,7 +159,7 @@ char *devid2devnm(dev_t devid) + ep = strchr(cp, '/'); + if (ep) + *ep = 0; +- strcpy(devnm, cp); ++ snprintf(devnm, sizeof(devnm), "%s", cp); + return devnm; + } + } +-- +2.41.0 + diff --git a/0126-mdadm-do-not-allow-leading-dot-in-MD-device-name.patch b/0126-mdadm-do-not-allow-leading-dot-in-MD-device-name.patch new file mode 100644 index 0000000..a068948 --- /dev/null +++ b/0126-mdadm-do-not-allow-leading-dot-in-MD-device-name.patch @@ -0,0 +1,158 @@ +From 998544c198c156db027a6e4f1b201910b138041e Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 15 Jul 2024 12:29:24 +0200 +Subject: [PATCH 126/201] mdadm: do not allow leading dot in MD device name + +Do not allow to use '.' on first place for named MD device. +Having leading dot might be confusing, MD device cannot be hidden. +It also removes possibility to create md device with name '.'. + +Additionally, code optimalizations are done. + +Signed-off-by: Mariusz Tkaczyk +--- + config.c | 75 +++++++++++++++++++++++++++++++------------------------- + 1 file changed, 41 insertions(+), 34 deletions(-) + +diff --git a/config.c b/config.c +index cd2379bd..6ea905f3 100644 +--- a/config.c ++++ b/config.c +@@ -188,8 +188,36 @@ 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_set_devname() - verify devname and set it in &mddev_ident. + * @ident: pointer to &mddev_ident. + * @devname: devname to be set. + * @cmdline: context dependent actions. If set, ignore keyword is not allowed. +@@ -202,8 +230,7 @@ inline void ident_init(struct mddev_ident *ident) + * /dev/md/{name} + * {name} + * +- * {name} must follow name's criteria and be POSIX compatible. +- * If criteria passed, duplicate memory and set devname in @ident. ++ * If verification passed, duplicate memory and set devname in @ident. + * + * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR. + */ +@@ -216,6 +243,7 @@ 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) { +@@ -242,53 +270,40 @@ mdadm_status_t _ident_set_devname(struct mddev_ident *ident, const char *devname + else + name = devname; + +- if (is_name_posix_compatible(name) == false) { +- ident_log(prop_name, name, "Not POSIX compatible", cmdline); +- return MDADM_STATUS_ERROR; +- } +- +- if (is_string_lq(name, MD_NAME_MAX + 1) == false) { +- ident_log(prop_name, devname, "Invalid length", cmdline); +- return MDADM_STATUS_ERROR; +- } ++ ret = ident_check_name(name, prop_name, cmdline); ++ if (ret) ++ return ret; + pass: + ident->devname = xstrdup(devname); + return MDADM_STATUS_SUCCESS; + } + + /** +- * _ident_set_name()- set name in &mddev_ident. ++ * _ident_set_name() - set name in &mddev_ident. + * @ident: pointer to &mddev_ident. + * @name: name to be set. +- * @cmdline: context dependent actions. + * + * If criteria passed, set name in @ident. + * Note: name is not used by config file, it for cmdline only. + * + * Return: %MDADM_STATUS_SUCCESS or %MDADM_STATUS_ERROR. + */ +-static mdadm_status_t _ident_set_name(struct mddev_ident *ident, const char *name, +- const bool cmdline) ++mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name) + { + assert(name); + assert(ident); + + const char *prop_name = "name"; ++ mdadm_status_t ret; + + if (ident->name[0]) { +- ident_log(prop_name, name, "Already defined", cmdline); ++ ident_log(prop_name, name, "Already defined", true); + return MDADM_STATUS_ERROR; + } + +- if (is_string_lq(name, MD_NAME_MAX + 1) == false) { +- ident_log(prop_name, name, "Too long or empty", cmdline); +- return MDADM_STATUS_ERROR; +- } +- +- if (is_name_posix_compatible(name) == false) { +- ident_log(prop_name, name, "Not POSIX compatible", cmdline); +- return MDADM_STATUS_ERROR; +- } ++ ret = ident_check_name(name, prop_name, true); ++ if (ret) ++ return ret; + + snprintf(ident->name, MD_NAME_MAX + 1, "%s", name); + return MDADM_STATUS_SUCCESS; +@@ -302,14 +317,6 @@ mdadm_status_t ident_set_devname(struct mddev_ident *ident, const char *name) + return _ident_set_devname(ident, name, true); + } + +-/** +- * ident_set_name()- exported, for cmdline. +- */ +-mdadm_status_t ident_set_name(struct mddev_ident *ident, const char *name) +-{ +- return _ident_set_name(ident, name, true); +-} +- + struct conf_dev { + struct conf_dev *next; + char *name; +-- +2.41.0 + diff --git a/0070-Detail-fix-detail-export-for-uuid_zero.patch b/0128-Detail-fix-detail-export-for-uuid_zero.patch similarity index 94% rename from 0070-Detail-fix-detail-export-for-uuid_zero.patch rename to 0128-Detail-fix-detail-export-for-uuid_zero.patch index f9499cd..f06f937 100644 --- a/0070-Detail-fix-detail-export-for-uuid_zero.patch +++ b/0128-Detail-fix-detail-export-for-uuid_zero.patch @@ -1,7 +1,7 @@ From 5be749ce416852e7acbb2415be380be358859612 Mon Sep 17 00:00:00 2001 From: Kinga Stefaniuk Date: Tue, 23 Jul 2024 15:38:41 +0200 -Subject: [PATCH 1/1] Detail: fix --detail --export for uuid_zero +Subject: [PATCH 128/201] Detail: fix --detail --export for uuid_zero Mentioned commit (see Fixes) causes that devices with UUID equal to uuid_zero was not recognized properly. For few devices diff --git a/0129-drive_encryption-Fix-ata-passthrough12-verify.patch b/0129-drive_encryption-Fix-ata-passthrough12-verify.patch new file mode 100644 index 0000000..1d43190 --- /dev/null +++ b/0129-drive_encryption-Fix-ata-passthrough12-verify.patch @@ -0,0 +1,84 @@ +From 2bb4efb504d0991eaba755242d3e70facb5d994b Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Tue, 23 Jul 2024 12:45:10 +0200 +Subject: [PATCH 129/201] drive_encryption: Fix ata passthrough12 verify + +Based on documentation SCSI Primary Commands - 4 (SPC-4) only first 7 bits +of first byte in sense data are used to store response code. The current +verification uses all 8 bits for comparison of response code. + +Incorrect verification may make impossible to use SATA disks with IMSM, +because IMSM requires verification of the encryption state before use. + +There was issue in kernel libata [1]. This issue hides bug in mdadm because +last bit was not set. + +Example output with affected mdadm: + + Port3 : /dev/sde (BTPR212503EK120LGN) +mdadm: Failed ata passthrough12 ioctl. Device: /dev/sde. +mdadm: Failed to get drive encryption information + +The fix is use the first 7 bits of Byte 0, to compare with the expected +values. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/libata/linux.git/commit/?id=38dab832c3f4 + +Fixes: df38df3052c3 ("Add reading SATA encryption information") +Signed-off-by: Blazej Kucman +--- + drive_encryption.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drive_encryption.c b/drive_encryption.c +index a4ad799f..63bdab1a 100644 +--- a/drive_encryption.c ++++ b/drive_encryption.c +@@ -65,6 +65,7 @@ + #define SENSE_DATA_CURRENT_FIXED (0x70) + #define SENSE_DATA_CURRENT_DESC (0x72) + #define SENSE_CURRENT_RES_DESC_POS (8) ++#define SENSE_RESPONSE_CODE_MASK (0x7f) + #define SG_DRIVER_SENSE (0x08) + + typedef enum drive_feature_support_status { +@@ -473,6 +474,7 @@ ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u1 + { + __u8 cdb[ATA_INQUIRY_LENGTH] = {0}; + __u8 sense[SG_SENSE_SIZE] = {0}; ++ __u8 sense_response_code; + __u8 *sense_desc = NULL; + sg_io_hdr_t sg = {0}; + +@@ -517,15 +519,17 @@ ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u1 + return MDADM_STATUS_ERROR; + } + ++ sense_response_code = sense[0] & SENSE_RESPONSE_CODE_MASK; + /* verify expected sense response code */ +- if (!(sense[0] == SENSE_DATA_CURRENT_DESC || sense[0] == SENSE_DATA_CURRENT_FIXED)) { ++ if (!(sense_response_code == SENSE_DATA_CURRENT_DESC || ++ sense_response_code == SENSE_DATA_CURRENT_FIXED)) { + pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s.\n", fd2kname(disk_fd)); + return MDADM_STATUS_ERROR; + } + + sense_desc = sense + SENSE_CURRENT_RES_DESC_POS; + /* verify sense data current response with descriptor format */ +- if (sense[0] == SENSE_DATA_CURRENT_DESC && ++ if (sense_response_code == SENSE_DATA_CURRENT_DESC && + !(sense_desc[0] == ATA_STATUS_RETURN_DESCRIPTOR && + sense_desc[1] == ATA_INQUIRY_LENGTH)) { + pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n", +@@ -534,7 +538,7 @@ ata_pass_through12_ioctl(int disk_fd, __u8 ata_command, __u8 sec_protocol, __u1 + } + + /* verify sense data current response with fixed format */ +- if (sense[0] == SENSE_DATA_CURRENT_FIXED && ++ if (sense_response_code == SENSE_DATA_CURRENT_FIXED && + !(sense[12] == ATA_PT_INFORMATION_AVAILABLE_ASC && + sense[13] == ATA_PT_INFORMATION_AVAILABLE_ASCQ)) { + pr_vrb("Failed ata passthrough12 ioctl. Device: /dev/%s. Sense data ASC: %d, ASCQ: %d.\n", +-- +2.41.0 + diff --git a/0130-super0-use-define-for-char-array-in-examine_super0.patch b/0130-super0-use-define-for-char-array-in-examine_super0.patch new file mode 100644 index 0000000..f774066 --- /dev/null +++ b/0130-super0-use-define-for-char-array-in-examine_super0.patch @@ -0,0 +1,46 @@ +From 0af8c9ebf50b68ad5f80efad7e94688235544a3d Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Thu, 4 Jul 2024 14:53:35 +0200 +Subject: [PATCH 130/201] super0: use define for char array in examine_super0 + +Using nb with 11 length may cause format-truncation errors, +because it was possible to use snprintf with 12 length input +and write it to 11 length output. Added new define and use it +to avoid this error. + +Signed-off-by: Kinga Stefaniuk +--- + mdadm.h | 3 +++ + super0.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/mdadm.h b/mdadm.h +index 27009154..22d5e8f4 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -2021,6 +2021,9 @@ enum r0layout { + #define PATH_MAX 4096 + #endif + ++/* The max string length necessary for decimal conversion, cannot be longer than count of bits */ ++#define INT_2_DEC_STR_MAX (sizeof(int) * 8) ++ + #define RESYNC_NONE -1 + #define RESYNC_DELAYED -2 + #define RESYNC_PENDING -3 +diff --git a/super0.c b/super0.c +index 9b8a1bd6..9b4e187e 100644 +--- a/super0.c ++++ b/super0.c +@@ -229,7 +229,7 @@ static void examine_super0(struct supertype *st, char *homehost) + d++) { + mdp_disk_t *dp; + char *dv; +- char nb[11]; ++ char nb[INT_2_DEC_STR_MAX]; + int wonly, failfast; + if (d>=0) dp = &sb->disks[d]; + else dp = &sb->this_disk; +-- +2.41.0 + diff --git a/0131-Makefile-add-more-compiler-flags.patch b/0131-Makefile-add-more-compiler-flags.patch new file mode 100644 index 0000000..0fda9b7 --- /dev/null +++ b/0131-Makefile-add-more-compiler-flags.patch @@ -0,0 +1,61 @@ +From 93c5215677a71e9772f68a449533cb3c97d2b869 Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Thu, 4 Jul 2024 15:01:06 +0200 +Subject: [PATCH 131/201] Makefile: add more compiler flags + +It is essential to avoid vulnerabilities in code as much +as possible using safe compilation flags. It is easier if +they are added to the Makefile and applied during compilation. +Add new gcc flags and make them configurable, because they +may not be supported for some compilers. +Set FORTIFY_SOURCE with the highest supported value for platform. + +Signed-off-by: Kinga Stefaniuk +--- + Makefile | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 3fe0a053..a914b178 100644 +--- a/Makefile ++++ b/Makefile +@@ -30,7 +30,7 @@ + + # define "CXFLAGS" to give extra flags to CC. + # e.g. make CXFLAGS=-O to optimise +-CXFLAGS ?=-O2 -D_FORTIFY_SOURCE=2 ++CXFLAGS ?=-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE + TCC = tcc + UCLIBC_GCC = $(shell for nm in i386-uclibc-linux-gcc i386-uclibc-gcc; do which $$nm > /dev/null && { echo $$nm ; exit; } ; done; echo false No uclibc found ) + #DIET_GCC = diet gcc +@@ -76,6 +76,27 @@ ifeq ($(origin STRINGOPOVERFLOW), undefined) + endif + endif + ++ifeq ($(origin NOSTRICTOVERFLOW), undefined) ++ NOSTRICTOVERFLOW := $(shell $(CC) -Q --help=warning 2>&1 | grep "strict-overflow" | wc -l) ++ ifneq "$(NOSTRICTOVERFLOW)" "0" ++ CWFLAGS += -fno-strict-overflow ++ endif ++endif ++ ++ifeq ($(origin NODELETENULLPOINTER), undefined) ++ NODELETENULLPOINTER := $(shell $(CC) -Q --help=optimizers 2>&1 | grep "delete-null-pointer-checks" | wc -l) ++ ifneq "$(NODELETENULLPOINTER)" "0" ++ CWFLAGS += -fno-delete-null-pointer-checks ++ endif ++endif ++ ++ifeq ($(origin WRAPV), undefined) ++ WRAPV := $(shell $(CC) -Q --help=optimizers 2>&1 | grep "wrapv" | wc -l) ++ ifneq "$(WRAPV)" "0" ++ CWFLAGS += -fwrapv ++ endif ++endif ++ + ifdef DEBIAN + CPPFLAGS += -DDEBIAN + endif +-- +2.41.0 + diff --git a/0133-mdstat-Rework-mdstat-external-arrays-handling.patch b/0133-mdstat-Rework-mdstat-external-arrays-handling.patch new file mode 100644 index 0000000..00d5d4c --- /dev/null +++ b/0133-mdstat-Rework-mdstat-external-arrays-handling.patch @@ -0,0 +1,575 @@ +From 4b3644ab4ce6df8c7f64c189c12b66627ff3e027 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 5 Jul 2024 10:49:27 +0200 +Subject: [PATCH 133/201] mdstat: Rework mdstat external arrays handling + +To avoid repeating mdstat_read() in IncrementalRemove(), new function +mdstat_find_by_member_name() has been proposed. With that, +IncrementalRemove() handles own copy of mdstat content and there is no +need to repeat reading for external stop. + +Additionally, It proposed few helper to avoid repeating +mdstat_ent->metadata_version checks across code. + +Signed-off-by: Mariusz Tkaczyk +--- + Assemble.c | 9 ++-- + Incremental.c | 37 +++++++++------ + Manage.c | 6 +-- + Monitor.c | 18 +++---- + config.c | 49 ++++++++++--------- + mapfile.c | 12 ++--- + mdadm.h | 6 ++- + mdmon.c | 4 +- + mdmon.h | 2 +- + mdstat.c | 129 ++++++++++++++++++++++++++++++++++++-------------- + super-intel.c | 9 ++-- + util.c | 10 ---- + 12 files changed, 167 insertions(+), 124 deletions(-) + +diff --git a/Assemble.c b/Assemble.c +index 77f2b50e..a2bb7b64 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -114,14 +114,11 @@ static int is_member_busy(char *metadata_version) + int busy = 0; + + for (ent = mdstat; ent; ent = ent->next) { +- if (ent->metadata_version == NULL) +- continue; +- if (strncmp(ent->metadata_version, "external:", 9) != 0) +- continue; +- if (!is_subarray(&ent->metadata_version[9])) ++ if (!is_mdstat_ent_subarray(ent)) + continue; ++ + /* Skip first char - it can be '/' or '-' */ +- if (strcmp(&ent->metadata_version[10], metadata_version+1) == 0) { ++ if (strcmp(&ent->metadata_version[10], metadata_version + 1) == 0) { + busy = 1; + break; + } +diff --git a/Incremental.c b/Incremental.c +index 83db0712..abc7721b 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1686,12 +1686,13 @@ static void remove_from_member_array(struct mdstat_ent *memb, + */ + int IncrementalRemove(char *devname, char *id_path, int verbose) + { +- int mdfd; +- int rv = 0; +- struct mdstat_ent *ent; ++ struct mdstat_ent *ent = NULL; ++ char buf[SYSFS_MAX_BUF_SIZE]; ++ struct mdstat_ent *mdstat; + struct mddev_dev devlist; + struct mdinfo mdi; +- char buf[SYSFS_MAX_BUF_SIZE]; ++ int rv = 1; ++ int mdfd; + + if (!id_path) + dprintf("incremental removal without --path lacks the possibility to re-add new device in this port\n"); +@@ -1700,16 +1701,25 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + pr_err("incremental removal requires a kernel device name, not a file: %s\n", devname); + return 1; + } +- ent = mdstat_by_component(devname); ++ ++ mdstat = mdstat_read(0, 0); ++ if (!mdstat) { ++ pr_err("Cannot read /proc/mdstat file, aborting\n"); ++ return 1; ++ } ++ ++ ent = mdstat_find_by_member_name(mdstat, devname); + if (!ent) { + if (verbose >= 0) + pr_err("%s does not appear to be a component of any array\n", devname); +- return 1; ++ goto out; + } ++ + if (sysfs_init(&mdi, -1, ent->devnm)) { + pr_err("unable to initialize sysfs for: %s\n", devname); +- return 1; ++ goto out; + } ++ + mdfd = open_dev_excl(ent->devnm); + if (is_fd_valid(mdfd)) { + close_fd(&mdfd); +@@ -1725,8 +1735,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + if (mdfd < 0) { + if (verbose >= 0) + pr_err("Cannot open array %s!!\n", ent->devnm); +- free_mdstat(ent); +- return 1; ++ goto out; + } + + if (id_path) { +@@ -1741,16 +1750,13 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + devlist.devname = devname; + devlist.disposition = 'I'; + /* for a container, we must fail each member array */ +- if (ent->metadata_version && +- strncmp(ent->metadata_version, "external:", 9) == 0) { +- struct mdstat_ent *mdstat = mdstat_read(0, 0); ++ if (is_mdstat_ent_external(ent)) { + struct mdstat_ent *memb; + for (memb = mdstat ; memb ; memb = memb->next) { + if (is_container_member(memb, ent->devnm)) + remove_from_member_array(memb, + &devlist, verbose); + } +- free_mdstat(mdstat); + } else { + /* + * This 'I' incremental remove is a try-best effort, +@@ -1765,7 +1771,8 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + rv = Manage_subdevs(ent->devnm, mdfd, &devlist, + verbose, 0, UOPT_UNDEFINED, 0); + +- close(mdfd); +- free_mdstat(ent); ++ close_fd(&mdfd); ++out: ++ free_mdstat(mdstat); + return rv; + } +diff --git a/Manage.c b/Manage.c +index f0304e1e..241de055 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -276,10 +276,8 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + */ + mds = mdstat_read(0, 0); + for (m = mds; m; m = m->next) +- if (m->metadata_version && +- strncmp(m->metadata_version, "external:", 9)==0 && +- metadata_container_matches(m->metadata_version+9, +- devnm)) { ++ if (is_mdstat_ent_external(m) && ++ metadata_container_matches(m->metadata_version + 9, devnm)) { + if (verbose >= 0) + pr_err("Cannot stop container %s: member %s still active\n", + devname, m->devnm); +diff --git a/Monitor.c b/Monitor.c +index 26c53e13..cf14fbb3 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -879,9 +879,7 @@ static int check_array(struct state *st, struct mdstat_ent *mdstat, + } + last_disk = i; + +- if (mse->metadata_version && +- strncmp(mse->metadata_version, "external:", 9) == 0 && +- is_subarray(mse->metadata_version+9)) { ++ if (is_mdstat_ent_subarray(mse)) { + char *sl; + snprintf(st->parent_devnm, MD_NAME_MAX, "%s", mse->metadata_version + 10); + sl = strchr(st->parent_devnm, '/'); +@@ -991,13 +989,12 @@ static int add_new_arrays(struct mdstat_ent *mdstat, struct state **statelist) + snprintf(st->devnm, MD_NAME_MAX, "%s", mse->devnm); + st->percent = RESYNC_UNKNOWN; + st->expected_spares = -1; +- if (mse->metadata_version && +- strncmp(mse->metadata_version, +- "external:", 9) == 0 && +- is_subarray(mse->metadata_version+9)) { ++ ++ if (is_mdstat_ent_subarray(mse)) { + char *sl; +- snprintf(st->parent_devnm, MD_NAME_MAX, +- "%s", mse->metadata_version + 10); ++ ++ snprintf(st->parent_devnm, MD_NAME_MAX, "%s", ++ mse->metadata_version + 10); + sl = strchr(st->parent_devnm, '/'); + if (sl) + *sl = 0; +@@ -1297,8 +1294,7 @@ int Wait(char *dev) + } + } + if (!e || e->percent == RESYNC_NONE) { +- if (e && e->metadata_version && +- strncmp(e->metadata_version, "external:", 9) == 0) { ++ if (e && is_mdstat_ent_external(e)) { + if (is_subarray(&e->metadata_version[9])) + ping_monitor(&e->metadata_version[9]); + else +diff --git a/config.c b/config.c +index 6ea905f3..5411a480 100644 +--- a/config.c ++++ b/config.c +@@ -360,35 +360,38 @@ struct mddev_dev *load_partitions(void) + struct mddev_dev *load_containers(void) + { + struct mdstat_ent *mdstat = mdstat_read(0, 0); ++ struct mddev_dev *dev_list = NULL; ++ struct map_ent *map_list = NULL; + struct mdstat_ent *ent; +- struct mddev_dev *d; +- struct mddev_dev *rv = NULL; +- struct map_ent *map = NULL, *me; + +- if (!mdstat) +- return NULL; ++ for (ent = mdstat; ent; ent = ent->next) { ++ struct mddev_dev *d; ++ struct map_ent *map; + +- for (ent = mdstat; ent; ent = ent->next) +- if (ent->metadata_version && +- strncmp(ent->metadata_version, "external:", 9) == 0 && +- !is_subarray(&ent->metadata_version[9])) { +- d = xcalloc(1, sizeof(*d)); +- me = map_by_devnm(&map, ent->devnm); +- if (me) +- d->devname = xstrdup(me->path); +- else if (asprintf(&d->devname, "/dev/%s", ent->devnm) < 0) { +- free(d); +- continue; +- } +- d->next = rv; +- rv = d; +- map_free(map); +- map = NULL; ++ if (!is_mdstat_ent_external(ent)) ++ continue; ++ ++ if (is_mdstat_ent_subarray(ent)) ++ continue; ++ ++ d = xcalloc(1, sizeof(*d)); ++ ++ map = map_by_devnm(&map_list, ent->devnm); ++ if (map) { ++ d->devname = xstrdup(map->path); ++ } else if (asprintf(&d->devname, "/dev/%s", ent->devnm) < 0) { ++ free(d); ++ continue; + } ++ ++ d->next = dev_list; ++ dev_list = d; ++ } ++ + free_mdstat(mdstat); +- map_free(map); ++ map_free(map_list); + +- return rv; ++ return dev_list; + } + + struct createinfo createinfo = { +diff --git a/mapfile.c b/mapfile.c +index ea9837ac..632cf5e8 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -339,18 +339,14 @@ struct map_ent *map_by_name(struct map_ent **map, char *name) + */ + static char *get_member_info(struct mdstat_ent *ent) + { ++ char *subarray; + +- if (ent->metadata_version == NULL || +- strncmp(ent->metadata_version, "external:", 9) != 0) ++ if (!is_mdstat_ent_subarray(ent)) + return NULL; + +- if (is_subarray(&ent->metadata_version[9])) { +- char *subarray; ++ subarray = strrchr(ent->metadata_version, '/'); + +- subarray = strrchr(ent->metadata_version, '/'); +- return subarray + 1; +- } +- return NULL; ++ return subarray + 1; + } + + void RebuildMap(void) +diff --git a/mdadm.h b/mdadm.h +index 22d5e8f4..5c3a9836 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -743,8 +743,12 @@ extern int mdstat_wait(int seconds); + extern void mdstat_wait_fd(int fd, const sigset_t *sigmask); + extern int mddev_busy(char *devnm); + extern struct mdstat_ent *mdstat_by_component(char *name); ++extern struct mdstat_ent *mdstat_find_by_member_name(struct mdstat_ent *mdstat, char *member_devnm); + extern struct mdstat_ent *mdstat_by_subdev(char *subdev, char *container); + ++extern bool is_mdstat_ent_external(struct mdstat_ent *ent); ++extern bool is_mdstat_ent_subarray(struct mdstat_ent *ent); ++ + struct map_ent { + struct map_ent *next; + char devnm[32]; +@@ -1771,7 +1775,7 @@ extern int is_mddev(char *dev); + extern int open_container(int fd); + extern int metadata_container_matches(char *metadata, char *devnm); + extern int metadata_subdev_matches(char *metadata, char *devnm); +-extern int is_container_member(struct mdstat_ent *ent, char *devname); ++extern bool is_container_member(struct mdstat_ent *ent, char *devname); + extern int is_subarray_active(char *subarray, char *devname); + extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet); + extern struct superswitch *version_to_superswitch(char *vers); +diff --git a/mdmon.c b/mdmon.c +index 5fdb5cdb..95e350f4 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -394,9 +394,7 @@ int main(int argc, char *argv[]) + /* launch an mdmon instance for each container found */ + mdstat = mdstat_read(0, 0); + for (e = mdstat; e; e = e->next) { +- if (e->metadata_version && +- strncmp(e->metadata_version, "external:", 9) == 0 && +- !is_subarray(&e->metadata_version[9])) { ++ if (is_mdstat_ent_external(e) && !is_mdstat_ent_subarray(e)) { + /* update cmdline so this mdmon instance can be + * distinguished from others in a call to ps(1) + */ +diff --git a/mdmon.h b/mdmon.h +index b3d72ac3..110cbef2 100644 +--- a/mdmon.h ++++ b/mdmon.h +@@ -78,7 +78,7 @@ void do_manager(struct supertype *container); + extern int sigterm; + + int read_dev_state(int fd); +-int is_container_member(struct mdstat_ent *mdstat, char *container); ++bool is_container_member(struct mdstat_ent *mdstat, char *container); + + struct mdstat_ent *mdstat_read(int hold, int start); + +diff --git a/mdstat.c b/mdstat.c +index e233f094..cbbace3d 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -110,6 +110,28 @@ static int add_member_devname(struct dev_member **m, char *name) + return 1; + } + ++/* Detach element from the list, it may modify list_head */ ++static void mdstat_ent_list_detach_element(struct mdstat_ent **list_head, struct mdstat_ent *el) ++{ ++ struct mdstat_ent *ent = *list_head; ++ ++ if (ent == el) { ++ *list_head = ent->next; ++ } else { ++ while (ent) { ++ if (ent->next == el) { ++ ent->next = el->next; ++ break; ++ } ++ } ++ ++ ent = ent->next; ++ } ++ ++ assert(ent); ++ ent->next = NULL; ++} ++ + void free_mdstat(struct mdstat_ent *ms) + { + while (ms) { +@@ -124,6 +146,32 @@ void free_mdstat(struct mdstat_ent *ms) + } + } + ++bool is_mdstat_ent_external(struct mdstat_ent *ent) ++{ ++ if (!ent->metadata_version) ++ return false; ++ ++ if (strncmp(ent->metadata_version, "external:", 9) == 0) ++ return true; ++ return false; ++} ++ ++bool is_mdstat_ent_subarray(struct mdstat_ent *ent) ++{ ++ if (is_mdstat_ent_external(ent) && is_subarray(ent->metadata_version + 9)) ++ return true; ++ return false; ++} ++ ++bool is_container_member(struct mdstat_ent *mdstat, char *container) ++{ ++ if (is_mdstat_ent_external(mdstat) && ++ metadata_container_matches(mdstat->metadata_version + 9, container)) ++ return true; ++ ++ return false; ++} ++ + static int mdstat_fd = -1; + struct mdstat_ent *mdstat_read(int hold, int start) + { +@@ -382,61 +430,70 @@ int mddev_busy(char *devnm) + return me != NULL; + } + +-struct mdstat_ent *mdstat_by_component(char *name) ++/** ++ * mdstat_find_by_member_devnm()- Return first array or external container with member device. ++ * @mdstat: Preloaded mdstat to iterate over. ++ * @member_devnm: devnm of the device to find. ++ * ++ * External subarrays are skipped. ++ */ ++struct mdstat_ent *mdstat_find_by_member_name(struct mdstat_ent *mdstat, char *member_devnm) + { +- struct mdstat_ent *mdstat = mdstat_read(0, 0); ++ struct mdstat_ent *ent; + +- while (mdstat) { +- struct dev_member *m; +- struct mdstat_ent *ent; +- if (mdstat->metadata_version && +- strncmp(mdstat->metadata_version, "external:", 9) == 0 && +- is_subarray(mdstat->metadata_version+9)) +- /* don't return subarrays, only containers */ +- ; +- else for (m = mdstat->members; m; m = m->next) { +- if (strcmp(m->name, name) == 0) { +- free_mdstat(mdstat->next); +- mdstat->next = NULL; +- return mdstat; +- } +- } +- ent = mdstat; +- mdstat = mdstat->next; +- ent->next = NULL; +- free_mdstat(ent); ++ for (ent = mdstat; ent; ent = ent->next) { ++ struct dev_member *member; ++ ++ if (is_mdstat_ent_subarray(ent)) ++ continue; ++ ++ for (member = ent->members; member; member = member->next) ++ if (strcmp(member->name, member_devnm) == 0) ++ return ent; + } ++ + return NULL; + } + ++ ++struct mdstat_ent *mdstat_by_component(char *name) ++{ ++ struct mdstat_ent *mdstat = mdstat_read(0, 0); ++ struct mdstat_ent *ent = mdstat_find_by_member_name(mdstat, name); ++ ++ if (ent) ++ mdstat_ent_list_detach_element(&mdstat, ent); ++ ++ free_mdstat(mdstat); ++ ++ return ent; ++} ++ + struct mdstat_ent *mdstat_by_subdev(char *subdev, char *container) + { + struct mdstat_ent *mdstat = mdstat_read(0, 0); + struct mdstat_ent *ent = NULL; + +- while (mdstat) { ++ for (ent = mdstat; ent; ent = ent->next) { + /* metadata version must match: + * external:[/-]%s/%s + * where first %s is 'container' and second %s is 'subdev' + */ +- if (ent) +- free_mdstat(ent); +- ent = mdstat; +- mdstat = mdstat->next; +- ent->next = NULL; + +- if (ent->metadata_version == NULL || +- strncmp(ent->metadata_version, "external:", 9) != 0) ++ if (!is_mdstat_ent_external(ent)) + continue; + +- if (!metadata_container_matches(ent->metadata_version+9, +- container) || +- !metadata_subdev_matches(ent->metadata_version+9, +- subdev)) ++ if (!metadata_container_matches(ent->metadata_version + 9, container)) ++ continue; ++ if (!metadata_subdev_matches(ent->metadata_version + 9, subdev)) + continue; + +- free_mdstat(mdstat); +- return ent; ++ break; + } +- return NULL; ++ ++ if (ent) ++ mdstat_ent_list_detach_element(&mdstat, ent); ++ ++ free_mdstat(mdstat); ++ return ent; + } +diff --git a/super-intel.c b/super-intel.c +index 713bfccf..c215b910 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -6974,13 +6974,11 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist, + int found; + + for (memb = mdstat ; memb ; memb = memb->next) { +- if (memb->metadata_version && +- (strncmp(memb->metadata_version, "external:", 9) == 0) && +- (strcmp(&memb->metadata_version[9], name) == 0) && +- !is_subarray(memb->metadata_version+9) && +- memb->members) { ++ if (is_mdstat_ent_external(memb) && !is_subarray(memb->metadata_version + 9) && ++ strcmp(&memb->metadata_version[9], name) == 0 && memb->members) { + struct dev_member *dev = memb->members; + int fd = -1; ++ + while (dev && !is_fd_valid(fd)) { + char *path = xmalloc(strlen(dev->name) + strlen("/dev/") + 1); + num = snprintf(path, PATH_MAX, "%s%s", "/dev/", dev->name); +@@ -6998,7 +6996,6 @@ active_arrays_by_format(char *name, char* hba, struct md_list **devlist, + struct mdstat_ent *vol; + for (vol = mdstat ; vol ; vol = vol->next) { + if (vol->active > 0 && +- vol->metadata_version && + is_container_member(vol, memb->devnm)) { + found++; + count++; +diff --git a/util.c b/util.c +index 908f8430..83d42833 100644 +--- a/util.c ++++ b/util.c +@@ -1671,16 +1671,6 @@ int metadata_subdev_matches(char *metadata, char *devnm) + return 0; + } + +-int is_container_member(struct mdstat_ent *mdstat, char *container) +-{ +- if (mdstat->metadata_version == NULL || +- strncmp(mdstat->metadata_version, "external:", 9) != 0 || +- !metadata_container_matches(mdstat->metadata_version+9, container)) +- return 0; +- +- return 1; +-} +- + int is_subarray_active(char *subarray, char *container) + { + struct mdstat_ent *mdstat = mdstat_read(0, 0); +-- +2.41.0 + diff --git a/0134-mdadm-managemon.c-fix-coverity-issues.patch b/0134-mdadm-managemon.c-fix-coverity-issues.patch new file mode 100644 index 0000000..525e9d4 --- /dev/null +++ b/0134-mdadm-managemon.c-fix-coverity-issues.patch @@ -0,0 +1,56 @@ +From 2a4c40766d654dcbf5911d1b7b63bbbe8b2c0128 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 24 Jul 2024 09:04:08 -0400 +Subject: [PATCH 134/201] mdadm: managemon.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event check_return: Calling "fcntl(fd, 4, fl)" without checking +return value. This library function may fail and return an error code. + +* Event check_after_deref: Null-checking "new" suggests that it may +be null, but it has already been dereferenced on all paths leading +to the check. + +Signed-off-by: Nigel Croxon +--- + managemon.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/managemon.c b/managemon.c +index 358459e7..add6a79e 100644 +--- a/managemon.c ++++ b/managemon.c +@@ -776,10 +776,8 @@ static void manage_new(struct mdstat_ent *mdstat, + + error: + pr_err("failed to monitor %s\n", mdstat->metadata_version); +- if (new) { +- new->container = NULL; +- free_aa(new); +- } ++ new->container = NULL; ++ free_aa(new); + if (mdi) + sysfs_free(mdi); + } +@@ -870,8 +868,15 @@ void read_sock(struct supertype *container) + return; + + fl = fcntl(fd, F_GETFL, 0); ++ if (fl < 0) { ++ close_fd(&fd); ++ return; ++ } + fl |= O_NONBLOCK; +- fcntl(fd, F_SETFL, fl); ++ if (fcntl(fd, F_SETFL, fl) < 0) { ++ close_fd(&fd); ++ return; ++ } + + do { + msg.buf = NULL; +-- +2.41.0 + diff --git a/0135-mdadm-msg.c-fix-coverity-issues.patch b/0135-mdadm-msg.c-fix-coverity-issues.patch new file mode 100644 index 0000000..6cd0339 --- /dev/null +++ b/0135-mdadm-msg.c-fix-coverity-issues.patch @@ -0,0 +1,40 @@ +From 87f96c870399cd029933a9742ba72e85e3251c3e Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 24 Jul 2024 09:20:28 -0400 +Subject: [PATCH 135/201] mdadm: msg.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event check_return: Calling "fcntl(sfd, 4, fl)" without +checking return value. This library function may fail and +return an error code. + +Signed-off-by: Nigel Croxon +--- + msg.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/msg.c b/msg.c +index f0772b3f..b6da91d3 100644 +--- a/msg.c ++++ b/msg.c +@@ -176,8 +176,15 @@ int connect_monitor(char *devname) + } + + fl = fcntl(sfd, F_GETFL, 0); ++ if (fl < 0) { ++ close(sfd); ++ return -1; ++ } + fl |= O_NONBLOCK; +- fcntl(sfd, F_SETFL, fl); ++ if (fcntl(sfd, F_SETFL, fl) < 0) { ++ close(sfd); ++ return -1; ++ } + + return sfd; + } +-- +2.41.0 + diff --git a/0136-imsm-refactor-chunk-size-print.patch b/0136-imsm-refactor-chunk-size-print.patch new file mode 100644 index 0000000..86a2266 --- /dev/null +++ b/0136-imsm-refactor-chunk-size-print.patch @@ -0,0 +1,150 @@ +From a944180a7e6a7d6d4cd08f6afcb83e58986c35f9 Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Wed, 24 Jul 2024 22:17:42 +0200 +Subject: [PATCH 136/201] imsm: refactor chunk size print + +- add imsm_chunk_ops struct for better code readability, +- move chunk size mapping to string into array, +- add function to print supported chunk sizes by IMSM controller. + +Signed-off-by: Blazej Kucman +--- + super-intel.c | 92 +++++++++++++++++++++++++++------------------------ + 1 file changed, 49 insertions(+), 43 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index c215b910..ab9b5d3f 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -647,6 +647,31 @@ static const char *_sys_dev_type[] = { + [SYS_DEV_SATA_VMD] = "SATA VMD" + }; + ++struct imsm_chunk_ops { ++ uint chunk; ++ char *chunk_str; ++}; ++ ++static const struct imsm_chunk_ops imsm_chunk_ops[] = { ++ {IMSM_OROM_SSS_2kB, "2k"}, ++ {IMSM_OROM_SSS_4kB, "4k"}, ++ {IMSM_OROM_SSS_8kB, "8k"}, ++ {IMSM_OROM_SSS_16kB, "16k"}, ++ {IMSM_OROM_SSS_32kB, "32k"}, ++ {IMSM_OROM_SSS_64kB, "64k"}, ++ {IMSM_OROM_SSS_128kB, "128k"}, ++ {IMSM_OROM_SSS_256kB, "256k"}, ++ {IMSM_OROM_SSS_512kB, "512k"}, ++ {IMSM_OROM_SSS_1MB, "1M"}, ++ {IMSM_OROM_SSS_2MB, "2M"}, ++ {IMSM_OROM_SSS_4MB, "4M"}, ++ {IMSM_OROM_SSS_8MB, "8M"}, ++ {IMSM_OROM_SSS_16MB, "16M"}, ++ {IMSM_OROM_SSS_32MB, "32M"}, ++ {IMSM_OROM_SSS_64MB, "64M"}, ++ {0, NULL} ++}; ++ + static int no_platform = -1; + + static int check_no_platform(void) +@@ -2626,6 +2651,16 @@ static void print_imsm_level_capability(const struct imsm_orom *orom) + printf("%s ", imsm_level_ops[idx].name); + } + ++static void print_imsm_chunk_size_capability(const struct imsm_orom *orom) ++{ ++ int idx; ++ ++ for (idx = 0; imsm_chunk_ops[idx].chunk_str; idx++) ++ if (imsm_chunk_ops[idx].chunk & orom->sss) ++ printf("%s ", imsm_chunk_ops[idx].chunk_str); ++} ++ ++ + static void print_imsm_capability(const struct imsm_orom *orom) + { + printf(" Platform : Intel(R) "); +@@ -2638,41 +2673,25 @@ static void print_imsm_capability(const struct imsm_orom *orom) + imsm_orom_is_enterprise(orom) ? " enterprise" : ""); + if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) { + if (imsm_orom_is_vmd_without_efi(orom)) +- printf(" Version : %d.%d\n", orom->major_ver, +- orom->minor_ver); ++ printf(" Version : %d.%d\n", orom->major_ver, orom->minor_ver); + else +- printf(" Version : %d.%d.%d.%d\n", orom->major_ver, +- orom->minor_ver, orom->hotfix_ver, orom->build); ++ printf(" Version : %d.%d.%d.%d\n", orom->major_ver, orom->minor_ver, ++ orom->hotfix_ver, orom->build); + } + + printf(" RAID Levels : "); + print_imsm_level_capability(orom); + printf("\n"); + +- printf(" Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", +- imsm_orom_has_chunk(orom, 2) ? " 2k" : "", +- imsm_orom_has_chunk(orom, 4) ? " 4k" : "", +- imsm_orom_has_chunk(orom, 8) ? " 8k" : "", +- imsm_orom_has_chunk(orom, 16) ? " 16k" : "", +- imsm_orom_has_chunk(orom, 32) ? " 32k" : "", +- imsm_orom_has_chunk(orom, 64) ? " 64k" : "", +- imsm_orom_has_chunk(orom, 128) ? " 128k" : "", +- imsm_orom_has_chunk(orom, 256) ? " 256k" : "", +- imsm_orom_has_chunk(orom, 512) ? " 512k" : "", +- imsm_orom_has_chunk(orom, 1024*1) ? " 1M" : "", +- imsm_orom_has_chunk(orom, 1024*2) ? " 2M" : "", +- imsm_orom_has_chunk(orom, 1024*4) ? " 4M" : "", +- imsm_orom_has_chunk(orom, 1024*8) ? " 8M" : "", +- imsm_orom_has_chunk(orom, 1024*16) ? " 16M" : "", +- imsm_orom_has_chunk(orom, 1024*32) ? " 32M" : "", +- imsm_orom_has_chunk(orom, 1024*64) ? " 64M" : ""); +- printf(" 2TB volumes :%s supported\n", +- (orom->attr & IMSM_OROM_ATTR_2TB)?"":" not"); ++ printf(" Chunk Sizes : "); ++ print_imsm_chunk_size_capability(orom); ++ printf("\n"); ++ ++ printf(" 2TB volumes :%s supported\n", (orom->attr & IMSM_OROM_ATTR_2TB) ? "" : " not"); + printf(" 2TB disks :%s supported\n", +- (orom->attr & IMSM_OROM_ATTR_2TB_DISK)?"":" not"); ++ (orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "" : " not"); + printf(" Max Disks : %d\n", orom->tds); +- printf(" Max Volumes : %d per array, %d per %s\n", +- orom->vpa, orom->vphba, ++ printf(" Max Volumes : %d per array, %d per %s\n", orom->vpa, orom->vphba, + imsm_orom_is_nvme(orom) ? "platform" : "controller"); + return; + } +@@ -2688,23 +2707,10 @@ static void print_imsm_capability_export(const struct imsm_orom *orom) + print_imsm_level_capability(orom); + printf("\n"); + +- printf("IMSM_SUPPORTED_CHUNK_SIZES=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", +- imsm_orom_has_chunk(orom, 2) ? "2k " : "", +- imsm_orom_has_chunk(orom, 4) ? "4k " : "", +- imsm_orom_has_chunk(orom, 8) ? "8k " : "", +- imsm_orom_has_chunk(orom, 16) ? "16k " : "", +- imsm_orom_has_chunk(orom, 32) ? "32k " : "", +- imsm_orom_has_chunk(orom, 64) ? "64k " : "", +- imsm_orom_has_chunk(orom, 128) ? "128k " : "", +- imsm_orom_has_chunk(orom, 256) ? "256k " : "", +- imsm_orom_has_chunk(orom, 512) ? "512k " : "", +- imsm_orom_has_chunk(orom, 1024*1) ? "1M " : "", +- imsm_orom_has_chunk(orom, 1024*2) ? "2M " : "", +- imsm_orom_has_chunk(orom, 1024*4) ? "4M " : "", +- imsm_orom_has_chunk(orom, 1024*8) ? "8M " : "", +- imsm_orom_has_chunk(orom, 1024*16) ? "16M " : "", +- imsm_orom_has_chunk(orom, 1024*32) ? "32M " : "", +- imsm_orom_has_chunk(orom, 1024*64) ? "64M " : ""); ++ printf("IMSM_SUPPORTED_CHUNK_SIZES="); ++ print_imsm_chunk_size_capability(orom); ++ printf("\n"); ++ + printf("IMSM_2TB_VOLUMES=%s\n",(orom->attr & IMSM_OROM_ATTR_2TB) ? "yes" : "no"); + printf("IMSM_2TB_DISKS=%s\n",(orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "yes" : "no"); + printf("IMSM_MAX_DISKS=%d\n",orom->tds); +-- +2.41.0 + diff --git a/0137-mdadm-Grow-fix-coverity-issue-CHECKED_RETURN.patch b/0137-mdadm-Grow-fix-coverity-issue-CHECKED_RETURN.patch new file mode 100644 index 0000000..4567c0c --- /dev/null +++ b/0137-mdadm-Grow-fix-coverity-issue-CHECKED_RETURN.patch @@ -0,0 +1,109 @@ +From e0373b734db511cdfec248ff6d769270ec8fd492 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:03 +0800 +Subject: [PATCH 137/201] mdadm/Grow: fix coverity issue CHECKED_RETURN + +It needs to check return value when functions have return value. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 43 ++++++++++++++++++++++++++++++++++++------- + 1 file changed, 36 insertions(+), 7 deletions(-) + +diff --git a/Grow.c b/Grow.c +index b135930d..7ae967bd 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -3261,7 +3261,12 @@ static int reshape_array(char *container, int fd, char *devname, + /* This is a spare that wants to + * be part of the array. + */ +- add_disk(fd, st, info2, d); ++ if (add_disk(fd, st, info2, d) < 0) { ++ pr_err("Can not add disk %s\n", ++ d->sys_name); ++ free(info2); ++ goto release; ++ } + } + } + sysfs_free(info2); +@@ -4413,7 +4418,10 @@ static void validate(int afd, int bfd, unsigned long long offset) + */ + if (afd < 0) + return; +- lseek64(bfd, offset - 4096, 0); ++ if (lseek64(bfd, offset - 4096, 0) < 0) { ++ pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ return; ++ } + if (read(bfd, &bsb2, 512) != 512) + fail("cannot read bsb"); + if (bsb2.sb_csum != bsb_csum((char*)&bsb2, +@@ -4444,12 +4452,19 @@ static void validate(int afd, int bfd, unsigned long long offset) + } + } + +- lseek64(bfd, offset, 0); ++ if (lseek64(bfd, offset, 0) < 0) { ++ pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ goto out; ++ } + if ((unsigned long long)read(bfd, bbuf, len) != len) { + //printf("len %llu\n", len); + fail("read first backup failed"); + } +- lseek64(afd, __le64_to_cpu(bsb2.arraystart)*512, 0); ++ ++ if (lseek64(afd, __le64_to_cpu(bsb2.arraystart)*512, 0) < 0) { ++ pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ goto out; ++ } + if ((unsigned long long)read(afd, abuf, len) != len) + fail("read first from array failed"); + if (memcmp(bbuf, abuf, len) != 0) +@@ -4466,15 +4481,25 @@ static void validate(int afd, int bfd, unsigned long long offset) + bbuf = xmalloc(abuflen); + } + +- lseek64(bfd, offset+__le64_to_cpu(bsb2.devstart2)*512, 0); ++ if (lseek64(bfd, offset+__le64_to_cpu(bsb2.devstart2)*512, 0) < 0) { ++ pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ goto out; ++ } + if ((unsigned long long)read(bfd, bbuf, len) != len) + fail("read second backup failed"); +- lseek64(afd, __le64_to_cpu(bsb2.arraystart2)*512, 0); ++ if (lseek64(afd, __le64_to_cpu(bsb2.arraystart2)*512, 0) < 0) { ++ pr_err("lseek64 fails %d:%s\n", errno, strerror(errno)); ++ goto out; ++ } + if ((unsigned long long)read(afd, abuf, len) != len) + fail("read second from array failed"); + if (memcmp(bbuf, abuf, len) != 0) + fail("data2 compare failed"); + } ++out: ++ free(abuf); ++ free(bbuf); ++ return; + } + + int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape, +@@ -5033,7 +5058,11 @@ int Grow_continue_command(char *devname, int fd, struct context *c) + goto Grow_continue_command_exit; + } + content = &array; +- sysfs_init(content, fd, NULL); ++ if (sysfs_init(content, fd, NULL) < 0) { ++ pr_err("sysfs_init fails\n"); ++ ret_val = 1; ++ goto Grow_continue_command_exit; ++ } + /* Need to load a superblock. + * FIXME we should really get what we need from + * sysfs +-- +2.41.0 + diff --git a/0138-mdadm-Grow-fix-coverity-issue-RESOURCE_LEAK.patch b/0138-mdadm-Grow-fix-coverity-issue-RESOURCE_LEAK.patch new file mode 100644 index 0000000..0c4d797 --- /dev/null +++ b/0138-mdadm-Grow-fix-coverity-issue-RESOURCE_LEAK.patch @@ -0,0 +1,166 @@ +From 54c09eaa8bc057dfd88ae20d259f88457f67fd1c Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:04 +0800 +Subject: [PATCH 138/201] mdadm/Grow: fix coverity issue RESOURCE_LEAK + +Fix some resource leak problems. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 42 +++++++++++++++++++++++++++++++----------- + 1 file changed, 31 insertions(+), 11 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 7ae967bd..907a6e1b 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -530,8 +530,10 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) + pr_err("Cannot add bitmap while array is resyncing or reshaping etc.\n"); + pr_err("Cannot set bitmap file for %s: %s\n", + devname, strerror(err)); ++ close_fd(&bitmap_fd); + return 1; + } ++ close_fd(&bitmap_fd); + } + + return 0; +@@ -3083,6 +3085,7 @@ static int reshape_array(char *container, int fd, char *devname, + int done; + struct mdinfo *sra = NULL; + char buf[SYSFS_MAX_BUF_SIZE]; ++ bool located_backup = false; + + /* when reshaping a RAID0, the component_size might be zero. + * So try to fix that up. +@@ -3165,8 +3168,10 @@ static int reshape_array(char *container, int fd, char *devname, + goto release; + } + +- if (!backup_file) ++ if (!backup_file) { + backup_file = locate_backup(sra->sys_name); ++ located_backup = true; ++ } + + goto started; + } +@@ -3612,15 +3617,13 @@ started: + mdstat_wait(30 - (delayed-1) * 25); + } while (delayed); + mdstat_close(); +- if (check_env("MDADM_GROW_VERIFY")) +- fd = open(devname, O_RDONLY | O_DIRECT); +- else +- fd = -1; + mlockall(MCL_FUTURE); + + if (signal_s(SIGTERM, catch_term) == SIG_ERR) + goto release; + ++ if (check_env("MDADM_GROW_VERIFY")) ++ fd = open(devname, O_RDONLY | O_DIRECT); + if (st->ss->external) { + /* metadata handler takes it from here */ + done = st->ss->manage_reshape( +@@ -3632,6 +3635,7 @@ started: + fd, sra, &reshape, st, blocks, fdlist, offsets, + d - odisks, fdlist + odisks, offsets + odisks); + ++ close_fd(&fd); + free(fdlist); + free(offsets); + +@@ -3701,6 +3705,8 @@ out: + exit(0); + + release: ++ if (located_backup) ++ free(backup_file); + free(fdlist); + free(offsets); + if (orig_level != UnSet && sra) { +@@ -3839,6 +3845,7 @@ int reshape_container(char *container, char *devname, + pr_err("Unable to initialize sysfs for %s\n", + mdstat->devnm); + rv = 1; ++ close_fd(&fd); + break; + } + +@@ -4717,6 +4724,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, + unsigned long long *offsets; + unsigned long long nstripe, ostripe; + int ndata, odata; ++ int fd, backup_fd = -1; + + odata = info->array.raid_disks - info->delta_disks - 1; + if (info->array.level == 6) +@@ -4732,9 +4740,18 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, + * been used + */ + old_disks = cnt; ++ ++ if (backup_file) { ++ backup_fd = open(backup_file, O_RDONLY); ++ if (!is_fd_valid(backup_fd)) { ++ pr_err("Can't open backup file %s : %s\n", ++ backup_file, strerror(errno)); ++ return -EINVAL; ++ } ++ } ++ + for (i=old_disks-(backup_file?1:0); iss->store_super(st, fdlist[j]); + st->ss->free_super(st); + } ++ close_fd(&backup_fd); + return 0; + } ++ ++ close_fd(&backup_fd); ++ + /* Didn't find any backup data, try to see if any + * was needed. + */ +-- +2.41.0 + diff --git a/0139-mdadm-Grow-fix-coverity-issue-STRING_OVERFLOW.patch b/0139-mdadm-Grow-fix-coverity-issue-STRING_OVERFLOW.patch new file mode 100644 index 0000000..8365c7c --- /dev/null +++ b/0139-mdadm-Grow-fix-coverity-issue-STRING_OVERFLOW.patch @@ -0,0 +1,29 @@ +From 13c1f4a56b3bedbf802d66e86afd787e318e25fb Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:05 +0800 +Subject: [PATCH 139/201] mdadm/Grow: fix coverity issue STRING_OVERFLOW + +Fix string overflow problems in Grow.c + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index 907a6e1b..a5f9027d 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -1694,7 +1694,7 @@ char *analyse_change(char *devname, struct mdinfo *info, struct reshape *re) + /* Current RAID6 layout has a RAID5 + * equivalent - good + */ +- strcat(strcpy(layout, ls), "-6"); ++ snprintf(layout, 40, "%s-6", ls); + l = map_name(r6layout, layout); + if (l == UnSet) + return "Cannot find RAID6 layout to convert to"; +-- +2.41.0 + diff --git a/0140-mdadm-Incremental-fix-coverity-issues.patch b/0140-mdadm-Incremental-fix-coverity-issues.patch new file mode 100644 index 0000000..d03c3b8 --- /dev/null +++ b/0140-mdadm-Incremental-fix-coverity-issues.patch @@ -0,0 +1,87 @@ +From 17c99bab3e2e3606961d7ecec62c29921b5d6660 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:06 +0800 +Subject: [PATCH 140/201] mdadm/Incremental: fix coverity issues. + +There are two issues PW.PARAMETER_HIDDEN (declaration hides +parameter 'devname') and INTEGER_OVERFLOW. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Incremental.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index abc7721b..fc4e68ff 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -770,7 +770,7 @@ static int count_active(struct supertype *st, struct mdinfo *sra, + replcnt++; + st->ss->free_super(st); + } +- if (max_journal_events >= max_events - 1) ++ if (max_events > 0 && max_journal_events >= max_events - 1) + bestinfo->journal_clean = 1; + + if (!avail) +@@ -1113,7 +1113,7 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + int fd = -1; + struct mdinfo info; + struct supertype *st2 = NULL; +- char *devname = NULL; ++ char *dev_path_name = NULL; + unsigned long long devsectors; + char *pathlist[2]; + +@@ -1142,14 +1142,14 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + domain_free(domlist); + domlist = NULL; + +- if (asprintf(&devname, "/dev/disk/by-path/%s", de->d_name) != 1) { +- devname = NULL; ++ if (asprintf(&dev_path_name, "/dev/disk/by-path/%s", de->d_name) != 1) { ++ dev_path_name = NULL; + goto next; + } +- fd = open(devname, O_RDONLY); ++ fd = open(dev_path_name, O_RDONLY); + if (fd < 0) + goto next; +- if (get_dev_size(fd, devname, &devsectors) == 0) ++ if (get_dev_size(fd, dev_path_name, &devsectors) == 0) + goto next; + devsectors >>= 9; + +@@ -1188,8 +1188,8 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + if (chosen == NULL || chosen_size < info.component_size) { + chosen_size = info.component_size; + free(chosen); +- chosen = devname; +- devname = NULL; ++ chosen = dev_path_name; ++ dev_path_name = NULL; + if (chosen_st) { + chosen_st->ss->free_super(chosen_st); + free(chosen_st); +@@ -1199,7 +1199,7 @@ static int partition_try_spare(char *devname, int *dfdp, struct dev_policy *pol, + } + + next: +- free(devname); ++ free(dev_path_name); + domain_free(domlist); + dev_policy_free(pol2); + if (st2) +@@ -1246,7 +1246,7 @@ static int is_bare(int dfd) + + /* OK, first 4K appear blank, try the end. */ + get_dev_size(dfd, NULL, &size); +- if (lseek(dfd, size-4096, SEEK_SET) < 0 || ++ if ((size >= 4096 && lseek(dfd, size-4096, SEEK_SET) < 0) || + read(dfd, buf, 4096) != 4096) + return 0; + +-- +2.41.0 + diff --git a/0141-mdadm-mdmon-fix-coverity-issue-CHECKED_RETURN.patch b/0141-mdadm-mdmon-fix-coverity-issue-CHECKED_RETURN.patch new file mode 100644 index 0000000..847ee5b --- /dev/null +++ b/0141-mdadm-mdmon-fix-coverity-issue-CHECKED_RETURN.patch @@ -0,0 +1,46 @@ +From f9949a04355f0fca29c6bc02ead8425e76daa573 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:07 +0800 +Subject: [PATCH 141/201] mdadm/mdmon: fix coverity issue CHECKED_RETURN + +It needs to check return values when functions have return value. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + mdmon.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/mdmon.c b/mdmon.c +index 95e350f4..cae63841 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -198,8 +198,12 @@ static void try_kill_monitor(pid_t pid, char *devname, int sock) + /* Wait for monitor to exit by reading from the socket, after + * clearing the non-blocking flag */ + fl = fcntl(sock, F_GETFL, 0); ++ if (fl < 0) ++ return; ++ + fl &= ~O_NONBLOCK; +- fcntl(sock, F_SETFL, fl); ++ if (fcntl(sock, F_SETFL, fl) < 0) ++ return; + n = read(sock, buf, 100); + + /* If there is I/O going on it might took some time to get to +@@ -249,7 +253,10 @@ static int make_control_sock(char *devname) + listen(sfd, 10); + fl = fcntl(sfd, F_GETFL, 0); + fl |= O_NONBLOCK; +- fcntl(sfd, F_SETFL, fl); ++ if (fcntl(sfd, F_SETFL, fl) < 0) { ++ close_fd(&sfd); ++ return -1; ++ } + return sfd; + } + +-- +2.41.0 + diff --git a/0142-mdadm-mdmon-fix-coverity-issue-RESOURCE_LEAK.patch b/0142-mdadm-mdmon-fix-coverity-issue-RESOURCE_LEAK.patch new file mode 100644 index 0000000..4575a56 --- /dev/null +++ b/0142-mdadm-mdmon-fix-coverity-issue-RESOURCE_LEAK.patch @@ -0,0 +1,49 @@ +From e7623d5ae4724c72e873e8af17f2ed6bfdc54427 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:08 +0800 +Subject: [PATCH 142/201] mdadm/mdmon: fix coverity issue RESOURCE_LEAK + +Fix resource leak problem in mdmon.c + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + mdmon.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/mdmon.c b/mdmon.c +index cae63841..6e28b56e 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -456,22 +456,25 @@ static int mdmon(char *devnm, int must_fork, int takeover) + if (must_fork) { + if (pipe(pfd) != 0) { + pr_err("failed to create pipe\n"); ++ close_fd(&mdfd); + return 1; + } + switch(fork()) { + case -1: + pr_err("failed to fork: %s\n", strerror(errno)); ++ close_fd(&mdfd); + return 1; + case 0: /* child */ +- close(pfd[0]); ++ close_fd(&pfd[0]); + break; + default: /* parent */ +- close(pfd[1]); ++ close_fd(&pfd[1]); + if (read(pfd[0], &status, sizeof(status)) != sizeof(status)) { + wait(&status); + status = WEXITSTATUS(status); + } +- close(pfd[0]); ++ close_fd(&pfd[0]); ++ close_fd(&mdfd); + return status; + } + } else +-- +2.41.0 + diff --git a/0143-mdadm-mdopen-fix-coverity-issue-CHECKED_RETURN.patch b/0143-mdadm-mdopen-fix-coverity-issue-CHECKED_RETURN.patch new file mode 100644 index 0000000..6cc6c8c --- /dev/null +++ b/0143-mdadm-mdopen-fix-coverity-issue-CHECKED_RETURN.patch @@ -0,0 +1,33 @@ +From f34040081c36ff92180674b89c39ddc7bdd47288 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:09 +0800 +Subject: [PATCH 143/201] mdadm/mdopen: fix coverity issue CHECKED_RETURN + +It needs to check return values when functions return value. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + mdopen.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/mdopen.c b/mdopen.c +index eaa59b59..c9fda131 100644 +--- a/mdopen.c ++++ b/mdopen.c +@@ -406,7 +406,11 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, + perror("chown"); + if (chmod(devname, ci->mode)) + perror("chmod"); +- stat(devname, &stb); ++ if (stat(devname, &stb) < 0) { ++ pr_err("failed to stat %s\n", ++ devname); ++ return -1; ++ } + add_dev(devname, &stb, 0, NULL); + } + if (use_mdp == 1) +-- +2.41.0 + diff --git a/0144-mdadm-mdopen-fix-coverity-issue-STRING_OVERFLOW.patch b/0144-mdadm-mdopen-fix-coverity-issue-STRING_OVERFLOW.patch new file mode 100644 index 0000000..0f883e1 --- /dev/null +++ b/0144-mdadm-mdopen-fix-coverity-issue-STRING_OVERFLOW.patch @@ -0,0 +1,29 @@ +From debf421db02c85f176b5eda2e8dcc9d17d89623c Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:10 +0800 +Subject: [PATCH 144/201] mdadm/mdopen: fix coverity issue STRING_OVERFLOW + +Fix string overflow problems in mdopen.c + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + mdopen.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mdopen.c b/mdopen.c +index c9fda131..e49defb6 100644 +--- a/mdopen.c ++++ b/mdopen.c +@@ -376,7 +376,7 @@ int create_mddev(char *dev, char *name, int autof, int trustworthy, + + sprintf(devname, "/dev/%s", devnm); + +- if (dev && dev[0] == '/') ++ if (dev && dev[0] == '/' && strlen(dev) < 400) + strcpy(chosen, dev); + else if (cname[0] == 0) + strcpy(chosen, devname); +-- +2.41.0 + diff --git a/0145-mdadm-mdstat-fix-coverity-issue-CHECKED_RETURN.patch b/0145-mdadm-mdstat-fix-coverity-issue-CHECKED_RETURN.patch new file mode 100644 index 0000000..63fbbaf --- /dev/null +++ b/0145-mdadm-mdstat-fix-coverity-issue-CHECKED_RETURN.patch @@ -0,0 +1,46 @@ +From 6984814b6fd879efae178acb057c1025aa4c64e8 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:11 +0800 +Subject: [PATCH 145/201] mdadm/mdstat: fix coverity issue CHECKED_RETURN + +It needs to check return values when functions return value. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + mdstat.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/mdstat.c b/mdstat.c +index cbbace3d..a971a957 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -194,8 +194,11 @@ struct mdstat_ent *mdstat_read(int hold, int start) + f = fopen("/proc/mdstat", "r"); + if (f == NULL) + return NULL; +- else +- fcntl(fileno(f), F_SETFD, FD_CLOEXEC); ++ ++ if (fcntl(fileno(f), F_SETFD, FD_CLOEXEC) < 0) { ++ fclose(f); ++ return NULL; ++ } + + all = NULL; + end = &all; +@@ -329,7 +332,10 @@ struct mdstat_ent *mdstat_read(int hold, int start) + } + if (hold && mdstat_fd == -1) { + mdstat_fd = dup(fileno(f)); +- fcntl(mdstat_fd, F_SETFD, FD_CLOEXEC); ++ if (fcntl(mdstat_fd, F_SETFD, FD_CLOEXEC) < 0) { ++ fclose(f); ++ return NULL; ++ } + } + fclose(f); + +-- +2.41.0 + diff --git a/0146-mdadm-super0-fix-coverity-issue-CHECKED_RETURN-and-E.patch b/0146-mdadm-super0-fix-coverity-issue-CHECKED_RETURN-and-E.patch new file mode 100644 index 0000000..c01f550 --- /dev/null +++ b/0146-mdadm-super0-fix-coverity-issue-CHECKED_RETURN-and-E.patch @@ -0,0 +1,56 @@ +From e055d9236a7d0dca2a311e8bb8013018dc571d6a Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:12 +0800 +Subject: [PATCH 146/201] mdadm/super0: fix coverity issue CHECKED_RETURN and + EVALUATION_ORDER + +Fix coverity problems in super0. It needs to check return value when +functions return value. And fix EVALUATION_ORDER problems in super0.c + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + super0.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/super0.c b/super0.c +index 9b4e187e..c428e2a6 100644 +--- a/super0.c ++++ b/super0.c +@@ -83,6 +83,9 @@ static void examine_super0(struct supertype *st, char *homehost) + int d; + int delta_extra = 0; + char *c; ++ unsigned long expected_csum = 0; ++ ++ expected_csum = calc_sb0_csum(sb); + + printf(" Magic : %08x\n", sb->md_magic); + printf(" Version : %d.%02d.%02d\n", +@@ -187,11 +190,11 @@ static void examine_super0(struct supertype *st, char *homehost) + printf("Working Devices : %d\n", sb->working_disks); + printf(" Failed Devices : %d\n", sb->failed_disks); + printf(" Spare Devices : %d\n", sb->spare_disks); +- if (calc_sb0_csum(sb) == sb->sb_csum) ++ if (expected_csum == sb->sb_csum) + printf(" Checksum : %x - correct\n", sb->sb_csum); + else + printf(" Checksum : %x - expected %lx\n", +- sb->sb_csum, calc_sb0_csum(sb)); ++ sb->sb_csum, expected_csum); + printf(" Events : %llu\n", + ((unsigned long long)sb->events_hi << 32) + sb->events_lo); + printf("\n"); +@@ -1212,7 +1215,8 @@ static int locate_bitmap0(struct supertype *st, int fd, int node_num) + + offset += MD_SB_BYTES; + +- lseek64(fd, offset, 0); ++ if (lseek64(fd, offset, 0) < 0) ++ return -1; + return 0; + } + +-- +2.41.0 + diff --git a/0147-mdadm-super1-fix-coverity-issue-CHECKED_RETURN.patch b/0147-mdadm-super1-fix-coverity-issue-CHECKED_RETURN.patch new file mode 100644 index 0000000..5679a53 --- /dev/null +++ b/0147-mdadm-super1-fix-coverity-issue-CHECKED_RETURN.patch @@ -0,0 +1,67 @@ +From eb9834599c8c9764bb3e711b6f291b10797eff27 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:13 +0800 +Subject: [PATCH 147/201] mdadm/super1: fix coverity issue CHECKED_RETURN + +It needs to check return value when functions return value. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + super1.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/super1.c b/super1.c +index 81d29a65..4e4c7bfd 100644 +--- a/super1.c ++++ b/super1.c +@@ -260,7 +260,10 @@ static int aread(struct align_fd *afd, void *buf, int len) + n = read(afd->fd, b, iosize); + if (n <= 0) + return n; +- lseek(afd->fd, len - n, 1); ++ if (lseek(afd->fd, len - n, 1) < 0) { ++ pr_err("lseek fails\n"); ++ return -1; ++ } + if (n > len) + n = len; + memcpy(buf, b, n); +@@ -294,14 +297,20 @@ static int awrite(struct align_fd *afd, void *buf, int len) + n = read(afd->fd, b, iosize); + if (n <= 0) + return n; +- lseek(afd->fd, -n, 1); ++ if (lseek(afd->fd, -n, 1) < 0) { ++ pr_err("lseek fails\n"); ++ return -1; ++ } + } + + memcpy(b, buf, len); + n = write(afd->fd, b, iosize); + if (n <= 0) + return n; +- lseek(afd->fd, len - n, 1); ++ if (lseek(afd->fd, len - n, 1) < 0) { ++ pr_err("lseek fails\n"); ++ return -1; ++ } + return len; + } + +@@ -2667,7 +2676,10 @@ static int locate_bitmap1(struct supertype *st, int fd, int node_num) + } + if (mustfree) + free(sb); +- lseek64(fd, offset<<9, 0); ++ if (lseek64(fd, offset<<9, 0) < 0) { ++ pr_err("lseek fails\n"); ++ ret = -1; ++ } + return ret; + } + +-- +2.41.0 + diff --git a/0148-mdadm-super1-fix-coverity-issue-DEADCODE.patch b/0148-mdadm-super1-fix-coverity-issue-DEADCODE.patch new file mode 100644 index 0000000..5565095 --- /dev/null +++ b/0148-mdadm-super1-fix-coverity-issue-DEADCODE.patch @@ -0,0 +1,29 @@ +From 7904dc1c576a742c601c40dab4d0a6e562c4d00c Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:14 +0800 +Subject: [PATCH 148/201] mdadm/super1: fix coverity issue DEADCODE + +optimal_space is at most 2046. So space can't be larger than UINT16_MAX. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + super1.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/super1.c b/super1.c +index 4e4c7bfd..24bc1026 100644 +--- a/super1.c ++++ b/super1.c +@@ -1466,8 +1466,6 @@ static int update_super1(struct supertype *st, struct mdinfo *info, + __le32_to_cpu(sb->chunksize)); + if (space > optimal_space) + space = optimal_space; +- if (space > UINT16_MAX) +- space = UINT16_MAX; + } + + sb->ppl.offset = __cpu_to_le16(offset); +-- +2.41.0 + diff --git a/0149-mdadm-super1-fix-coverity-issue-EVALUATION_ORDER.patch b/0149-mdadm-super1-fix-coverity-issue-EVALUATION_ORDER.patch new file mode 100644 index 0000000..3733e2b --- /dev/null +++ b/0149-mdadm-super1-fix-coverity-issue-EVALUATION_ORDER.patch @@ -0,0 +1,46 @@ +From 38f712dba339bb9bd6a73cc7219d217871e7f27a Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:15 +0800 +Subject: [PATCH 149/201] mdadm/super1: fix coverity issue EVALUATION_ORDER + +Fix evaluation order problems in super1.c + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + super1.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/super1.c b/super1.c +index 24bc1026..243eeb1a 100644 +--- a/super1.c ++++ b/super1.c +@@ -340,6 +340,9 @@ static void examine_super1(struct supertype *st, char *homehost) + unsigned long long sb_offset; + struct mdinfo info; + int inconsistent = 0; ++ unsigned int expected_csum = 0; ++ ++ expected_csum = calc_sb_1_csum(sb); + + printf(" Magic : %08x\n", __le32_to_cpu(sb->magic)); + printf(" Version : 1"); +@@ -507,13 +510,13 @@ static void examine_super1(struct supertype *st, char *homehost) + printf("\n"); + } + +- if (calc_sb_1_csum(sb) == sb->sb_csum) ++ if (expected_csum == sb->sb_csum) + printf(" Checksum : %x - correct\n", + __le32_to_cpu(sb->sb_csum)); + else + printf(" Checksum : %x - expected %x\n", + __le32_to_cpu(sb->sb_csum), +- __le32_to_cpu(calc_sb_1_csum(sb))); ++ __le32_to_cpu(expected_csum)); + printf(" Events : %llu\n", + (unsigned long long)__le64_to_cpu(sb->events)); + printf("\n"); +-- +2.41.0 + diff --git a/0150-mdadm-super1-fix-coverity-issue-RESOURCE_LEAK.patch b/0150-mdadm-super1-fix-coverity-issue-RESOURCE_LEAK.patch new file mode 100644 index 0000000..c4291cd --- /dev/null +++ b/0150-mdadm-super1-fix-coverity-issue-RESOURCE_LEAK.patch @@ -0,0 +1,41 @@ +From ae2308ddf38b8f24a2b5e8e14e31153dfe608239 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 26 Jul 2024 15:14:16 +0800 +Subject: [PATCH 150/201] mdadm/super1: fix coverity issue RESOURCE_LEAK + +Fix resource leak problems in super1.c + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + super1.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/super1.c b/super1.c +index 243eeb1a..9c9c7dd1 100644 +--- a/super1.c ++++ b/super1.c +@@ -923,10 +923,12 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname) + offset <<= 9; + if (lseek64(fd, offset, 0) < 0) { + pr_err("Cannot seek to bad-blocks list\n"); ++ free(bbl); + return 1; + } + if (read(fd, bbl, size) != size) { + pr_err("Cannot read bad-blocks list\n"); ++ free(bbl); + return 1; + } + /* 64bits per entry. 10 bits is block-count, 54 bits is block +@@ -947,6 +949,7 @@ static int examine_badblocks_super1(struct supertype *st, int fd, char *devname) + + printf("%20llu for %d sectors\n", sector, count); + } ++ free(bbl); + return 0; + } + +-- +2.41.0 + diff --git a/0151-policy.c-Fix-check_return-issue-in-Write_rules.patch b/0151-policy.c-Fix-check_return-issue-in-Write_rules.patch new file mode 100644 index 0000000..07c8893 --- /dev/null +++ b/0151-policy.c-Fix-check_return-issue-in-Write_rules.patch @@ -0,0 +1,66 @@ +From 44c2a293260952fbb14db23d1ad07e6066641e0a Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Thu, 11 Jul 2024 14:31:57 +0200 +Subject: [PATCH 151/201] policy.c: Fix check_return issue in Write_rules() + +Refactor Write_rules() in policy.c to eliminate check_return issue found +by SAST analysis. Create udev rules file directly using rule_name +instead of creating temporary file and renaming it. + +Signed-off-by: Anna Sztukowska +--- + policy.c | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) + +diff --git a/policy.c b/policy.c +index dfaafdc0..4d4b248d 100644 +--- a/policy.c ++++ b/policy.c +@@ -969,19 +969,13 @@ int generate_entries(int fd) + */ + int Write_rules(char *rule_name) + { +- int fd; +- char udev_rule_file[PATH_MAX]; ++ int fd = fileno(stdout); + +- if (rule_name) { +- strncpy(udev_rule_file, rule_name, sizeof(udev_rule_file) - 6); +- udev_rule_file[sizeof(udev_rule_file) - 6] = '\0'; +- strcat(udev_rule_file, ".temp"); +- fd = creat(udev_rule_file, +- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +- if (fd == -1) +- return 1; +- } else +- fd = 1; ++ if (rule_name) ++ fd = creat(rule_name, 0644); ++ ++ if (!is_fd_valid(fd)) ++ return 1; + + /* write static invocation */ + if (write(fd, udev_template_start, sizeof(udev_template_start) - 1) != +@@ -993,15 +987,14 @@ int Write_rules(char *rule_name) + goto abort; + + fsync(fd); +- if (rule_name) { ++ if (rule_name) + close(fd); +- rename(udev_rule_file, rule_name); +- } ++ + return 0; + abort: + if (rule_name) { + close(fd); +- unlink(udev_rule_file); ++ unlink(rule_name); + } + return 1; + } +-- +2.41.0 + diff --git a/0152-super-gpt.c-Fix-check_return-issue-in-load_gpt.patch b/0152-super-gpt.c-Fix-check_return-issue-in-load_gpt.patch new file mode 100644 index 0000000..97bdbac --- /dev/null +++ b/0152-super-gpt.c-Fix-check_return-issue-in-load_gpt.patch @@ -0,0 +1,40 @@ +From 483ff037f1036f5f604e085cf76097a87e2be348 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Wed, 24 Jul 2024 11:46:57 +0200 +Subject: [PATCH 152/201] super-gpt.c: Fix check_return issue in load_gpt() + +Fix check_return issue in load_gpt() reported by SAST analysis in +super-gpt.c. + +Signed-off-by: Anna Sztukowska +--- + super-gpt.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/super-gpt.c b/super-gpt.c +index a1e9aa9d..ec3cf53f 100644 +--- a/super-gpt.c ++++ b/super-gpt.c +@@ -105,7 +105,8 @@ static int load_gpt(struct supertype *st, int fd, char *devname) + return 1; + } + /* Set offset to second block (GPT header) */ +- lseek(fd, sector_size, SEEK_SET); ++ if (lseek(fd, sector_size, SEEK_SET) == -1L) ++ goto no_read; + /* Seem to have GPT, load the header */ + gpt_head = (struct GPT*)(super+1); + if (read(fd, gpt_head, sizeof(*gpt_head)) != sizeof(*gpt_head)) +@@ -118,7 +119,8 @@ static int load_gpt(struct supertype *st, int fd, char *devname) + to_read = __le32_to_cpu(gpt_head->part_cnt) * sizeof(struct GPT_part_entry); + to_read = ((to_read+511)/512) * 512; + /* Set offset to third block (GPT entries) */ +- lseek(fd, sector_size*2, SEEK_SET); ++ if (lseek(fd, sector_size * 2, SEEK_SET) == -1L) ++ goto no_read; + if (read(fd, gpt_head+1, to_read) != to_read) + goto no_read; + +-- +2.41.0 + diff --git a/0153-super-intel-fix-compilation-error.patch b/0153-super-intel-fix-compilation-error.patch new file mode 100644 index 0000000..85e2c77 --- /dev/null +++ b/0153-super-intel-fix-compilation-error.patch @@ -0,0 +1,46 @@ +From 734de8b02022bf3b7a5f2111f5314a87ddebcc83 Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Tue, 6 Aug 2024 11:14:02 +0200 +Subject: [PATCH 153/201] super-intel: fix compilation error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix compilation error: + +super-intel.c: In function ‘end_migration’: +super-intel.c:4360:29: error: writing 2 bytes into a region + of size 0 [-Werror=stringop-overflow=] + 4360 | dev->vol.migr_state = 0; + | ~~~~~~~~~~~~~~~~~~~~^~~ +cc1: note: destination object is likely at address zero +cc1: all warnings being treated as errors +make: *** [Makefile:232: super-intel.o] Error 1 + +reported, when GCC 14 is used. Return when dev is NULL, to avoid it. + +Signed-off-by: Kinga Stefaniuk +--- + super-intel.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/super-intel.c b/super-intel.c +index ab9b5d3f..f6745e10 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -4330,6 +4330,12 @@ static void migrate(struct imsm_dev *dev, struct intel_super *super, + static void end_migration(struct imsm_dev *dev, struct intel_super *super, + __u8 map_state) + { ++ /* To avoid compilation error, saying dev can't be NULL when ++ * migr_state is assigned. ++ */ ++ if (dev == NULL) ++ return; ++ + struct imsm_map *map = get_imsm_map(dev, MAP_0); + struct imsm_map *prev = get_imsm_map(dev, dev->vol.migr_state == 0 ? + MAP_0 : MAP_1); +-- +2.41.0 + diff --git a/0154-super-intel-add-define-for-migr_state.patch b/0154-super-intel-add-define-for-migr_state.patch new file mode 100644 index 0000000..624593b --- /dev/null +++ b/0154-super-intel-add-define-for-migr_state.patch @@ -0,0 +1,92 @@ +From 125217e0903ab0eb574d20c698c49b04e3b1a99c Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Wed, 31 Jul 2024 15:06:42 +0200 +Subject: [PATCH 154/201] super-intel: add define for migr_state + +Represent migr_state with the define, which helps in code readability. +Add new values for Normal and Migration states. + +Signed-off-by: Kinga Stefaniuk +--- + super-intel.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index f6745e10..354c292a 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -194,6 +194,8 @@ ASSERT_SIZE(imsm_map, 52) + struct imsm_vol { + __u32 curr_migr_unit_lo; + __u32 checkpoint_id; /* id to access curr_migr_unit */ ++#define MIGR_STATE_NORMAL 0 ++#define MIGR_STATE_MIGRATING 1 + __u8 migr_state; /* Normal or Migrating */ + #define MIGR_INIT 0 + #define MIGR_REBUILD 1 +@@ -4303,7 +4305,7 @@ static void migrate(struct imsm_dev *dev, struct intel_super *super, + struct imsm_map *dest; + struct imsm_map *src = get_imsm_map(dev, MAP_0); + +- dev->vol.migr_state = 1; ++ dev->vol.migr_state = MIGR_STATE_MIGRATING; + set_migr_type(dev, migr_type); + set_vol_curr_migr_unit(dev, 0); + dest = get_imsm_map(dev, MAP_1); +@@ -4337,7 +4339,7 @@ static void end_migration(struct imsm_dev *dev, struct intel_super *super, + return; + + struct imsm_map *map = get_imsm_map(dev, MAP_0); +- struct imsm_map *prev = get_imsm_map(dev, dev->vol.migr_state == 0 ? ++ struct imsm_map *prev = get_imsm_map(dev, dev->vol.migr_state == MIGR_STATE_NORMAL ? + MAP_0 : MAP_1); + int i, j; + +@@ -4369,7 +4371,7 @@ static void end_migration(struct imsm_dev *dev, struct intel_super *super, + map_state = imsm_check_degraded(super, dev, failed, MAP_0); + } + +- dev->vol.migr_state = 0; ++ dev->vol.migr_state = MIGR_STATE_NORMAL; + set_migr_type(dev, 0); + set_vol_curr_migr_unit(dev, 0); + map->map_state = map_state; +@@ -4449,7 +4451,7 @@ int check_mpb_migr_compatibility(struct intel_super *super) + for (i = 0; i < super->anchor->num_raid_devs; i++) { + struct imsm_dev *dev_iter = __get_imsm_dev(super->anchor, i); + +- if (dev_iter->vol.migr_state == 1 && ++ if (dev_iter->vol.migr_state == MIGR_STATE_MIGRATING && + dev_iter->vol.migr_type == MIGR_GEN_MIGR) { + /* This device is migrating */ + map0 = get_imsm_map(dev_iter, MAP_0); +@@ -5654,7 +5656,7 @@ static int init_super_imsm_volume(struct supertype *st, mdu_array_info_t *info, + set_imsm_dev_size(dev, array_blocks); + dev->status = (DEV_READ_COALESCING | DEV_WRITE_COALESCING); + vol = &dev->vol; +- vol->migr_state = 0; ++ vol->migr_state = MIGR_STATE_NORMAL; + set_migr_type(dev, MIGR_INIT); + vol->dirty = !info->state; + set_vol_curr_migr_unit(dev, 0); +@@ -8631,7 +8633,7 @@ static void imsm_progress_container_reshape(struct intel_super *super) + copy_map_size = sizeof_imsm_map(map); + prev_num_members = map->num_members; + map->num_members = prev_disks; +- dev->vol.migr_state = 1; ++ dev->vol.migr_state = MIGR_STATE_MIGRATING; + set_vol_curr_migr_unit(dev, 0); + set_migr_type(dev, MIGR_GEN_MIGR); + for (i = prev_num_members; +@@ -9863,7 +9865,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u, + dprintf("imsm: modifying subdev: %i\n", + id->index); + devices_to_reshape--; +- newdev->vol.migr_state = 1; ++ newdev->vol.migr_state = MIGR_STATE_MIGRATING; + set_vol_curr_migr_unit(newdev, 0); + set_migr_type(newdev, MIGR_GEN_MIGR); + newmap->num_members = u->new_raid_disks; +-- +2.41.0 + diff --git a/0156-Grow_reshape-set-only-component_size-for-size-grow.patch b/0156-Grow_reshape-set-only-component_size-for-size-grow.patch new file mode 100644 index 0000000..846f4b3 --- /dev/null +++ b/0156-Grow_reshape-set-only-component_size-for-size-grow.patch @@ -0,0 +1,52 @@ +From c653054b322a03e8912ac05accc87b6a1ba8daab Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Fri, 26 Apr 2024 08:33:00 +0200 +Subject: [PATCH 156/201] Grow_reshape: set only component_size for size grow + +Component_size couldn't be set using ioctl when new drive size is big +(e.g. 5TB). Command value is bigger than 32 bits and error is reported +- it is known ioctl limitation. Remove updating array properties using +ioctl, use sysfs instead. Sysfs was introduced in 3.10, so now it is old +enough to be safely used. Array_size in sysfs should be set for every +size change for external metadata, when grow is performed without +errors. + +Signed-off-by: Kinga Stefaniuk +--- + Grow.c | 19 +++++++------------ + 1 file changed, 7 insertions(+), 12 deletions(-) + +diff --git a/Grow.c b/Grow.c +index a5f9027d..5810b128 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -2149,19 +2149,14 @@ int Grow_reshape(char *devname, int fd, + if (s->size == MAX_SIZE) + s->size = 0; + array.size = s->size; +- if (s->size & ~INT32_MAX) { +- /* got truncated to 32bit, write to +- * component_size instead +- */ +- rv = sysfs_set_num(sra, NULL, "component_size", s->size); +- } else { +- rv = md_set_array_info(fd, &array); ++ rv = sysfs_set_num(sra, NULL, "component_size", s->size); + +- /* manage array size when it is managed externally +- */ +- if ((rv == 0) && st->ss->external) +- rv = set_array_size(st, sra, sra->text_version); +- } ++ /* ++ * For native metadata, md/array_size is updated by kernel, ++ * for external management update it here. ++ */ ++ if (st->ss->external && rv == MDADM_STATUS_SUCCESS) ++ rv = set_array_size(st, sra, sra->text_version); + + if (raid0_takeover) { + /* do not recync non-existing parity, +-- +2.41.0 + diff --git a/0157-mdstat-fix-list-detach-issues.patch b/0157-mdstat-fix-list-detach-issues.patch new file mode 100644 index 0000000..018771f --- /dev/null +++ b/0157-mdstat-fix-list-detach-issues.patch @@ -0,0 +1,43 @@ +From 4b041873ff5556882bc6f17ac3de00c72eebcc4f Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 6 Aug 2024 16:11:18 +0200 +Subject: [PATCH 157/201] mdstat: fix list detach issues + +Move ent = ent->next; to while. It was outside the loop so if there +are more than 2 elements and we are looking for 3rd element it causes +infinite loop.. + +Fix el->next zeroing. It causes segfault in mdstat_free(). Theses +issues were not visible in my testing because I had only 2 MD devices. + +Fixes: 4b3644ab4ce6 ("mdstat: Rework mdstat external arrays handling") +Signed-off-by: Mariusz Tkaczyk +--- + mdstat.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/mdstat.c b/mdstat.c +index a971a957..29e78362 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -123,13 +123,15 @@ static void mdstat_ent_list_detach_element(struct mdstat_ent **list_head, struct + ent->next = el->next; + break; + } ++ ++ ent = ent->next; + } + +- ent = ent->next; + } + ++ /* Guard if not found or list is empty - not allowed */ + assert(ent); +- ent->next = NULL; ++ el->next = NULL; + } + + void free_mdstat(struct mdstat_ent *ms) +-- +2.41.0 + diff --git a/0158-md.4-replace-wrong-word.patch b/0158-md.4-replace-wrong-word.patch new file mode 100644 index 0000000..c510a3f --- /dev/null +++ b/0158-md.4-replace-wrong-word.patch @@ -0,0 +1,28 @@ +From 1f49ecbf3d2ab8003d37eb1c0454c5cfbe335ee5 Mon Sep 17 00:00:00 2001 +From: Nicolas Roeser +Date: Sun, 4 Aug 2024 14:34:44 +0200 +Subject: [PATCH 158/201] md.4: replace wrong word + +There is a wrong word in the md(4) man page, this commit corrects it. + +Signed-off-by: Nicolas Roeser +--- + md.4 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/md.4 b/md.4 +index 7a0bc7e6..7aef1577 100644 +--- a/md.4 ++++ b/md.4 +@@ -224,7 +224,7 @@ option. If you use this option to + while running a newer kernel, the array will NOT assemble, but the + metadata will be update so that it can be assembled on an older kernel. + +-No that setting the layout to "unspecified" removes protections against ++Note that setting the layout to "unspecified" removes protections against + this bug, and you must be sure that the kernel you use matches the + layout of the array. + +-- +2.41.0 + diff --git a/0159-mdadm-util.c-fix-coverity-issues.patch b/0159-mdadm-util.c-fix-coverity-issues.patch new file mode 100644 index 0000000..b2bc66a --- /dev/null +++ b/0159-mdadm-util.c-fix-coverity-issues.patch @@ -0,0 +1,134 @@ +From ea076e7c4bc8b3122ad9d7131098c4b85902a299 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Wed, 7 Aug 2024 11:33:23 -0400 +Subject: [PATCH 159/201] mdadm: util.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event check_return: Calling "open" without checking return value +* Event check_return: Calling "lseek(fd, sector_size, 0)" without +checking return value. +* Event leaked_handle: Handle variable "fd" going out of scope leaks +the handle. +* Event leaked_storage: Variable "dir" going out of scope leaks the +storage it points to. +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "st->devnm" by copying "_devnm" without checking the length. +* Event fixed_size_dest: You might overrun the 32-character fixed-size +string "container" by copying "dev" without checking the length. + +Signed-off-by: Nigel Croxon +--- + util.c | 41 +++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 16 deletions(-) + +diff --git a/util.c b/util.c +index 83d42833..1cee0feb 100644 +--- a/util.c ++++ b/util.c +@@ -1253,7 +1253,7 @@ struct supertype *super_by_fd(int fd, char **subarrayp) + *subarray++ = '\0'; + subarray = xstrdup(subarray); + } +- strcpy(container, dev); ++ snprintf(container, sizeof(container), "%s", dev); + sysfs_free(sra); + sra = sysfs_read(-1, container, GET_VERSION); + if (sra && sra->text_version[0]) +@@ -1430,7 +1430,8 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart) + /* skip protective MBR */ + if (!get_dev_sector_size(fd, NULL, §or_size)) + return 0; +- lseek(fd, sector_size, SEEK_SET); ++ if (lseek(fd, sector_size, SEEK_SET) == -1L) ++ return 0; + /* read GPT header */ + if (read(fd, &gpt, 512) != 512) + return 0; +@@ -1451,7 +1452,8 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart) + part = (struct GPT_part_entry *)buf; + + /* set offset to third block (GPT entries) */ +- lseek(fd, sector_size*2, SEEK_SET); ++ if (lseek(fd, sector_size*2, SEEK_SET) == -1L) ++ return 0; + for (part_nr = 0; part_nr < all_partitions; part_nr++) { + /* read partition entry */ + if (read(fd, buf, entry_size) != (ssize_t)entry_size) +@@ -1486,7 +1488,8 @@ static int get_last_partition_end(int fd, unsigned long long *endofpart) + + BUILD_BUG_ON(sizeof(boot_sect) != 512); + /* read MBR */ +- lseek(fd, 0, 0); ++ if (lseek(fd, 0, 0) == -1L) ++ goto abort; + if (read(fd, &boot_sect, 512) != 512) + goto abort; + +@@ -1715,7 +1718,7 @@ int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet) + dev); + goto close_fd; + } +- strcpy(st->devnm, _devnm); ++ snprintf(st->devnm, sizeof(st->devnm), "%s", _devnm); + + mdi = sysfs_read(fd, st->devnm, GET_VERSION|GET_LEVEL); + if (!mdi) { +@@ -2293,14 +2296,16 @@ void manage_fork_fds(int close_all) + { + DIR *dir; + struct dirent *dirent; ++ int fd = open("/dev/null", O_RDWR); + +- close(0); +- open("/dev/null", O_RDWR); +- ++ if (is_fd_valid(fd)) { ++ dup2(fd, 0); + #ifndef DEBUG + dup2(0, 1); + dup2(0, 2); ++ close_fd(&fd); + #endif ++ } + + if (close_all == 0) + return; +@@ -2319,8 +2324,10 @@ void manage_fork_fds(int close_all) + + fd = strtol(dirent->d_name, NULL, 10); + if (fd > 2) +- close(fd); ++ close_fd(&fd); + } ++ closedir(dir); ++ return; + } + + /* In a systemd/udev world, it is best to get systemd to +@@ -2367,13 +2374,15 @@ void reopen_mddev(int mdfd) + /* Re-open without any O_EXCL, but keep + * the same fd + */ +- char *devnm; +- int fd; +- devnm = fd2devnm(mdfd); +- close(mdfd); +- fd = open_dev(devnm); +- if (fd >= 0 && fd != mdfd) +- dup2(fd, mdfd); ++ char *devnm = fd2devnm(mdfd); ++ int fd = open_dev(devnm); ++ ++ if (!is_fd_valid(fd)) ++ return; ++ ++ dup2(fd, mdfd); ++ ++ close_fd(&fd); + } + + static struct cmap_hooks *cmap_hooks = NULL; +-- +2.41.0 + diff --git a/0160-mdadm-sysfs.c-fix-coverity-issues.patch b/0160-mdadm-sysfs.c-fix-coverity-issues.patch new file mode 100644 index 0000000..03f3d39 --- /dev/null +++ b/0160-mdadm-sysfs.c-fix-coverity-issues.patch @@ -0,0 +1,56 @@ +From 18eaf6c5206a37ad059c930d1ee2dbc9b7297513 Mon Sep 17 00:00:00 2001 +From: Nigel Croxon +Date: Thu, 18 Jul 2024 13:05:57 -0400 +Subject: [PATCH 160/201] mdadm: sysfs.c fix coverity issues + +Fixing the following coding errors the coverity tools found: + +* Event fixed_size_dest: You might overrun the 32-character +fixed-size string "mdi->sys_name" by copying "devnm" without +checking the length + +* Event fixed_size_dest: You might overrun the 50-character +fixed-size string "sra->text_version" by copying "buf + 9" +without checking the length. + +* Event string_overflow: You might overrun the 32-character +destination string "dev->sys_name" by writing 256 characters +from "de->d_name". + +Signed-off-by: Nigel Croxon +--- + sysfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sysfs.c b/sysfs.c +index 20fe1e9e..b3c8b10d 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -139,7 +139,7 @@ int sysfs_init(struct mdinfo *mdi, int fd, char *devnm) + goto out; + if (!S_ISDIR(stb.st_mode)) + goto out; +- strcpy(mdi->sys_name, devnm); ++ strncpy(mdi->sys_name, devnm, sizeof(mdi->sys_name) - 1); + + retval = 0; + out: +@@ -179,6 +179,7 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) + sra->array.major_version = -1; + sra->array.minor_version = -2; + strcpy(sra->text_version, buf+9); ++ sra->text_version[sizeof(sra->text_version) - 1] = '\0'; + } else { + sscanf(buf, "%d.%d", + &sra->array.major_version, +@@ -340,6 +341,7 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) + + } + strcpy(dev->sys_name, de->d_name); ++ dev->sys_name[sizeof(dev->sys_name) - 1] = '\0'; + dev->disk.raid_disk = strtoul(buf, &ep, 10); + if (*ep) dev->disk.raid_disk = -1; + +-- +2.41.0 + diff --git a/0161-imsm-add-read-OROM-form-ACPI-UEFI-tables.patch b/0161-imsm-add-read-OROM-form-ACPI-UEFI-tables.patch new file mode 100644 index 0000000..586fa4c --- /dev/null +++ b/0161-imsm-add-read-OROM-form-ACPI-UEFI-tables.patch @@ -0,0 +1,405 @@ +From 91845dab52c3f9ab56710338c0c38e9c1473df1d Mon Sep 17 00:00:00 2001 +From: Blazej Kucman +Date: Thu, 11 Jul 2024 18:45:41 +0200 +Subject: [PATCH 161/201] imsm: add read OROM form ACPI UEFI tables + +OROM - IMSM hardware capabilities + +EFI vars depends on userspace, they need to be mounted to be accessible. +Sporadic problems have been observed with availability at an early +assemble stage. It is not possible to fully synchronize EFI vars mounts +with udev rules processing. + +For the reason above, read of IMSM OROM from ACPI tables as secondary +option is added. This method will be used for SATA and VMD family +controllers. + +ACPI tables are generated by sysfs, earlier in the boot process, before +the stage of RAID assembly. The way of loading OROM via EFI vars is +retained, ACPI tables will be a backup way. + +Two paths will be maintained, because IMSM hardware capabilities are +necessary for RAID assembly during booting, so access to them must be +provided. + +Signed-off-by: Blazej Kucman +--- + platform-intel.c | 324 +++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 299 insertions(+), 25 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index d6a53533..9705c925 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -577,6 +577,9 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + + #define SYS_EFI_VAR_PATH "/sys/firmware/efi/vars" + #define SYS_EFIVARS_PATH "/sys/firmware/efi/efivars" ++#define ACPI_TABLES_PATH "/sys/firmware/acpi/tables/" ++#define ACPI_UEFI_TABLE_BASE_NAME "UEFI" ++#define ACPI_UEFI_DATA_OFFSET 52 + #define SCU_PROP "RstScuV" + #define AHCI_PROP "RstSataV" + #define AHCI_SSATA_PROP "RstsSatV" +@@ -584,10 +587,73 @@ static const struct imsm_orom *find_imsm_hba_orom(struct sys_dev *hba) + #define VROC_VMD_PROP "RstUefiV" + #define RST_VMD_PROP "RstVmdV" + +-#define VENDOR_GUID \ ++#define PCI_CLASS_RAID_CNTRL 0x010400 ++ ++/* GUID length in Bytes */ ++#define GUID_LENGTH 16 ++ ++/* GUID entry in 'UEFI' for Sata controller. */ ++#define RST_SATA_V_GUID \ ++ EFI_GUID(0xe4dd92e0, 0xac7d, 0x11df, 0x94, 0xe2, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66) ++ ++/* GUID entry in 'UEFI' for sSata controller. */ ++#define RST_SSATA_V_GUID \ ++ EFI_GUID(0xb002be42, 0x901d, 0x4018, 0xb4, 0x1e, 0xd7, 0x04, 0xab, 0x3a, 0x0f, 0x15) ++ ++/* GUID entry in 'UEFI' for tSata controller. */ ++#define RST_TSATA_V_GUID \ ++ EFI_GUID(0x101ce8f1, 0xb873, 0x4362, 0xa9, 0x76, 0xb5, 0x54, 0x31, 0x74, 0x52, 0x7e) ++ ++/* GUID entry in 'UEFI' for Intel(R) VROC VMD. */ ++#define RST_UEFI_V_GUID \ ++ EFI_GUID(0x4bf2da96, 0xde6e, 0x4d8a, 0xa8, 0x8b, 0xb3, 0xd, 0x33, 0xf6, 0xf, 0x3e) ++ ++/** ++ * GUID entry in 'UEFI' for Intel(R) RST VMD. ++ * Currently is the same like in 'UEFI' for Sata controller. ++ */ ++#define RST_VMD_V_GUID RST_SATA_V_GUID ++ ++/* GUID of intel RST vendor EFI var. */ ++#define INTEL_RST_VENDOR_GUID \ + EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, 0x1a, 0x04, 0xc6) + +-#define PCI_CLASS_RAID_CNTRL 0x010400 ++/* ++ * Unified Extensible Firmware Interface (UEFI) Specification Release 2.10 ++ * UEFI ACPI DATA TABLE, Table O.1 ++ */ ++typedef struct uefi_acpi_table { ++ char signature[4]; ++ __u32 length; ++ __u8 revision; ++ __u8 checksum; ++ char oemid[6]; ++ /* controller name */ ++ char oem_table_id[8]; ++ __u32 oem_revision; ++ __u32 creator_id; ++ __u32 creator_revision; ++ /* controller GUID */ ++ struct efi_guid identifier; ++ /* OROM data offeset */ ++ __u16 dataOffset; ++} uefi_acpi_table_t; ++ ++typedef struct uefi_acpi_table_with_orom { ++ struct uefi_acpi_table table; ++ struct imsm_orom orom; ++} uefi_acpi_table_with_orom_t; ++ ++/* imsm_orom_id - Identifier used to match imsm efi var or acpi table ++ * @name: name of the UEFI property, it is part of efivar name or ACPI table oem_table_id ++ * @guid: acpi table guid identifier ++ * ++ * vendor guid (second part of evifar name) is not added here because it is cost. ++ */ ++typedef struct imsm_orom_id { ++ char *name; ++ struct efi_guid guid; ++} imsm_orom_id_t; + + static int read_efi_var(void *buffer, ssize_t buf_size, + const char *variable_name, struct efi_guid guid) +@@ -669,14 +735,238 @@ static int read_efi_variable(void *buffer, ssize_t buf_size, + return 0; + } + ++/** ++ * is_efi_guid_equal() - check if EFI guids are equal. ++ * @guid: EFI guid. ++ * @guid1: EFI guid to compare. ++ * ++ * Return: %true if guid are equal, %false otherwise. ++ */ ++static inline bool is_efi_guid_equal(struct efi_guid guid, struct efi_guid guid1) ++{ ++ if (memcmp(guid.b, guid1.b, GUID_LENGTH) == 0) ++ return true; ++ return false; ++} ++ ++/** ++ * acpi_any_imsm_orom_id_matching() - match ACPI table with any of given imsm_orom_id. ++ * @imsm_orom_ids: array of IMSM OROM Identifiers. ++ * @imsm_orom_ids_number: number of IMSM OROM Identifiers. ++ * @table: struct with read ACPI UEFI table. ++ * ++ * Check if read UEFI table contains requested OROM id. ++ * EFI GUID and controller name are compared with expected. ++ * ++ * Return: %true if length is proper table, %false otherwise. ++ */ ++bool acpi_any_imsm_orom_id_matching(imsm_orom_id_t *imsm_orom_ids, int imsm_orom_ids_number, ++ struct uefi_acpi_table table) ++{ ++ int index; ++ ++ for (index = 0; index < imsm_orom_ids_number; index++) ++ if (strncmp(table.oem_table_id, imsm_orom_ids[index].name, ++ strlen(imsm_orom_ids[index].name)) == 0 && ++ is_efi_guid_equal(table.identifier, ++ imsm_orom_ids[index].guid) == true) ++ return true; ++ return false; ++} ++ ++/** ++ * read_uefi_acpi_orom_data() - read OROM data from UEFI ACPI table. ++ * @fd: file descriptor. ++ * @uefi_table: struct to fill out. ++ * ++ * Read OROM from ACPI UEFI table under given file descriptor. ++ * Table must have the appropriate OROM data, which should be confirmed before call this function. ++ * In case of success, &orom in structure in &uefi_table will be filled.. ++ * ++ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise. ++ */ ++mdadm_status_t ++read_uefi_acpi_orom_data(int fd, uefi_acpi_table_with_orom_t *uefi_table) ++{ ++ assert(is_fd_valid(fd)); ++ ++ if (lseek(fd, uefi_table->table.dataOffset, 0) == -1L) ++ return MDADM_STATUS_ERROR; ++ ++ if (read(fd, &uefi_table->orom, sizeof(uefi_table->orom)) == -1) ++ return MDADM_STATUS_ERROR; ++ ++ return MDADM_STATUS_SUCCESS; ++} ++ ++/** ++ * verify_uefi_acpi_table_length() - verify if ACPI UEFI table have correct length with focus at ++ * OROM. ++ * @table: struct with UEFI table. ++ * ++ * Verify if ACPI UEFI table have correct length with focus at OROM. Make sure that the file is ++ * correct and contains the appropriate length data based on the length of the OROM. ++ * ++ * Return: %true if length is correct, %false otherwise. ++ */ ++bool verify_uefi_acpi_table_length(struct uefi_acpi_table table) ++{ ++ if (table.length < ACPI_UEFI_DATA_OFFSET) ++ return false; ++ ++ if (table.length - table.dataOffset != sizeof(struct imsm_orom)) ++ return false; ++ return true; ++} ++ ++/** ++ * find_orom_in_acpi_uefi_tables() - find OROM in UEFI ACPI tables based on requested OROM ids. ++ * @imsm_orom_ids: array of IMSM OROM Identifiers. ++ * @imsm_orom_ids_number: number of IMSM OROM Identifiers. ++ * @orom: OROM struct buffer to fill out. ++ * ++ * Find OROM in UEFI ACPI tables provided by Intel, based on requested controllers. ++ * The first one to be matched, will be used. ++ * If found, the buffer with the OROM structure will be filled. ++ * ++ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise. ++ */ ++mdadm_status_t ++find_orom_in_acpi_uefi_tables(imsm_orom_id_t *imsm_orom_ids, int imsm_orom_ids_number, ++ struct imsm_orom *orom) ++{ ++ mdadm_status_t status = MDADM_STATUS_ERROR; ++ uefi_acpi_table_with_orom_t uefi_table; ++ char path[PATH_MAX]; ++ struct dirent *ent; ++ int fd = -1; ++ DIR *dir; ++ ++ dir = opendir(ACPI_TABLES_PATH); ++ if (!dir) ++ return MDADM_STATUS_ERROR; ++ ++ for (ent = readdir(dir); ent; ent = readdir(dir)) { ++ close_fd(&fd); ++ ++ /* Check if file is a UEFI table */ ++ if (strncmp(ent->d_name, ACPI_UEFI_TABLE_BASE_NAME, ++ strlen(ACPI_UEFI_TABLE_BASE_NAME)) != 0) ++ continue; ++ ++ snprintf(path, PATH_MAX, "%s/%s", ACPI_TABLES_PATH, ent->d_name); ++ ++ fd = open(path, O_RDONLY); ++ if (!is_fd_valid(fd)) { ++ pr_err("Fail to open ACPI UEFI table file. File: %s, Error: %s\n", ++ ent->d_name, strerror(errno)); ++ continue; ++ } ++ ++ if (read(fd, &uefi_table.table, sizeof(struct uefi_acpi_table)) == -1) { ++ pr_err("Fail to read IMSM OROM from ACPI UEFI table file. File: %s\n", ++ ent->d_name); ++ continue; ++ } ++ ++ if (!acpi_any_imsm_orom_id_matching(imsm_orom_ids, imsm_orom_ids_number, ++ uefi_table.table)) ++ continue; ++ ++ if (!verify_uefi_acpi_table_length(uefi_table.table)) ++ continue; ++ ++ if (read_uefi_acpi_orom_data(fd, &uefi_table)) { ++ pr_err("Fail to read IMSM OROM from ACPI UEFI table file. File: %s\n", ++ ent->d_name); ++ continue; ++ } ++ ++ memcpy(orom, &uefi_table.orom, sizeof(uefi_table.orom)); ++ status = MDADM_STATUS_SUCCESS; ++ break; ++ } ++ ++ close_fd(&fd); ++ closedir(dir); ++ return status; ++} ++ ++/** ++ * find_orom_in_efi_variables() - find first IMSM OROM in EFI vars that matches any imsm_orom_id. ++ * @imsm_orom_ids: array of IMSM OROM Identifiers. ++ * @imsm_orom_ids_number: number of IMSM OROM Identifiers. ++ * @orom: OROM struct buffer to fill out. ++ * ++ * Find IMSM OROM that matches on of imsm_orom_id in EFI variables. The first match is used. ++ * If found, the buffer with the OROM structure is filled. ++ * ++ * Return: %MDADM_STATUS_SUCCESS on success, %MDADM_STATUS_ERROR otherwise. ++ */ ++mdadm_status_t ++find_orom_in_efi_variables(imsm_orom_id_t *imsm_orom_ids, int imsm_orom_ids_number, ++ struct imsm_orom *orom) ++{ ++ int index; ++ ++ for (index = 0; index < imsm_orom_ids_number; index++) ++ if (!read_efi_variable(orom, sizeof(struct imsm_orom), imsm_orom_ids[index].name, ++ INTEL_RST_VENDOR_GUID)) ++ return MDADM_STATUS_SUCCESS; ++ return MDADM_STATUS_ERROR; ++} ++ ++/** ++ * find_imsm_efi_orom() - find OROM for requested controller. ++ * @orom: buffer for OROM. ++ * @controller_type: requested controller type. ++ * ++ * Based on controller type, function first search in EFI vars then in ACPI UEFI tables. ++ * For each controller there is defined an array of OROM ids from which we can read OROM, ++ * the first one to be matched, will be used. ++ * In case of success, the structure &orom will be filed out. ++ * ++ * Return: %MDADM_STATUS_SUCCESS on success. ++ */ ++static mdadm_status_t ++find_imsm_efi_orom(struct imsm_orom *orom, enum sys_dev_type controller_type) ++{ ++ static imsm_orom_id_t sata_imsm_orrom_ids[] = { ++ {AHCI_PROP, RST_SATA_V_GUID}, ++ {AHCI_SSATA_PROP, RST_SSATA_V_GUID}, ++ {AHCI_TSATA_PROP, RST_TSATA_V_GUID}, ++ }; ++ static imsm_orom_id_t vmd_imsm_orom_ids[] = { ++ {VROC_VMD_PROP, RST_UEFI_V_GUID}, ++ {RST_VMD_PROP, RST_VMD_V_GUID}, ++ }; ++ static imsm_orom_id_t *imsm_orom_ids; ++ int imsm_orom_ids_number; ++ ++ switch (controller_type) { ++ case SYS_DEV_SATA: ++ imsm_orom_ids = sata_imsm_orrom_ids; ++ imsm_orom_ids_number = ARRAY_SIZE(sata_imsm_orrom_ids); ++ break; ++ case SYS_DEV_VMD: ++ case SYS_DEV_SATA_VMD: ++ imsm_orom_ids = vmd_imsm_orom_ids; ++ imsm_orom_ids_number = ARRAY_SIZE(vmd_imsm_orom_ids); ++ break; ++ default: ++ return MDADM_STATUS_UNDEF; ++ } ++ ++ if (!find_orom_in_efi_variables(imsm_orom_ids, imsm_orom_ids_number, orom)) ++ return MDADM_STATUS_SUCCESS; ++ ++ return find_orom_in_acpi_uefi_tables(imsm_orom_ids, imsm_orom_ids_number, orom); ++} ++ + const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + { + struct imsm_orom orom; + struct orom_entry *ret; +- static const char * const sata_efivars[] = {AHCI_PROP, AHCI_SSATA_PROP, +- AHCI_TSATA_PROP}; +- static const char * const vmd_efivars[] = {VROC_VMD_PROP, RST_VMD_PROP}; +- unsigned long i; + + if (check_env("IMSM_TEST_AHCI_EFI") || check_env("IMSM_TEST_SCU_EFI")) + return imsm_platform_test(hba); +@@ -687,36 +977,20 @@ const struct imsm_orom *find_imsm_efi(struct sys_dev *hba) + + switch (hba->type) { + case SYS_DEV_SAS: +- if (!read_efi_variable(&orom, sizeof(orom), SCU_PROP, +- VENDOR_GUID)) ++ if (!read_efi_variable(&orom, sizeof(orom), SCU_PROP, INTEL_RST_VENDOR_GUID)) + break; +- + return NULL; + case SYS_DEV_SATA: + if (hba->class != PCI_CLASS_RAID_CNTRL) + return NULL; + +- for (i = 0; i < ARRAY_SIZE(sata_efivars); i++) { +- if (!read_efi_variable(&orom, sizeof(orom), +- sata_efivars[i], VENDOR_GUID)) +- break; +- +- } +- if (i == ARRAY_SIZE(sata_efivars)) ++ if (find_imsm_efi_orom(&orom, hba->type)) + return NULL; +- + break; + case SYS_DEV_VMD: + case SYS_DEV_SATA_VMD: +- for (i = 0; i < ARRAY_SIZE(vmd_efivars); i++) { +- if (!read_efi_variable(&orom, sizeof(orom), +- vmd_efivars[i], VENDOR_GUID)) +- break; +- } +- +- if (i == ARRAY_SIZE(vmd_efivars)) ++ if (find_imsm_efi_orom(&orom, hba->type)) + return NULL; +- + break; + default: + return NULL; +-- +2.41.0 + diff --git a/0162-imsm-get-bus-from-VMD-driver-directory.patch b/0162-imsm-get-bus-from-VMD-driver-directory.patch new file mode 100644 index 0000000..3f34550 --- /dev/null +++ b/0162-imsm-get-bus-from-VMD-driver-directory.patch @@ -0,0 +1,146 @@ +From 6e793aeace463d7687656f7ac6968300ba106228 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 8 Aug 2024 13:07:50 +0200 +Subject: [PATCH 162/201] imsm: get bus from VMD driver directory + +Enumeration of VMD child devices is started early, kernel is not waiting +for VMD enumeration to finish. It causes that: +/sys/bus/pci/drivers/vmd/{dev}/domain/device link might be not yet ready. + +With PCI gen5 devices we can observe that mdadm is failing to start IMSM +raid arrays because of that. In that case, it needs to find bus path +manually. + +Look for bus device in VMD driver directory if realpath() failed with +ENOENT. + +Signed-off-by: Mariusz Tkaczyk +--- + platform-intel.c | 88 ++++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 77 insertions(+), 11 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 9705c925..d0ef9111 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -105,12 +105,75 @@ static void free_sys_dev(struct sys_dev **list) + } + } + ++/** ++ * vmd_find_pci_bus() - look for PCI bus created by VMD. ++ * @vmd_path: path to vmd driver. ++ * @buf: return buffer, must be PATH_MAX. ++ * ++ * Each VMD device represents one domain and each VMD device adds separate PCI bus. ++ * IMSM must know VMD domains, therefore it needs to determine and follow buses. ++ * ++ */ ++mdadm_status_t vmd_find_pci_bus(char *vmd_path, char *buf) ++{ ++ char tmp[PATH_MAX]; ++ struct dirent *ent; ++ DIR *vmd_dir; ++ char *rp_ret; ++ ++ snprintf(tmp, PATH_MAX, "%s/domain/device", vmd_path); ++ ++ rp_ret = realpath(tmp, buf); ++ ++ if (rp_ret) ++ return MDADM_STATUS_SUCCESS; ++ ++ if (errno != ENOENT) ++ return MDADM_STATUS_ERROR; ++ ++ /* ++ * If it is done early, there is a chance that kernel is still enumerating VMD device but ++ * kernel did enough to start enumerating child devices, {vmd_path}/domain/device link may ++ * not exist yet. We have to look into @vmd_path directory and find it ourselves. ++ */ ++ ++ vmd_dir = opendir(vmd_path); ++ ++ if (!vmd_dir) ++ return MDADM_STATUS_ERROR; ++ ++ for (ent = readdir(vmd_dir); ent; ent = readdir(vmd_dir)) { ++ static const char pci[] = "pci"; ++ ++ /** ++ * Pci bus must have form pciXXXXX:XX, where X is a digit i.e pci10000:00. ++ * We do not check digits here, it is sysfs so it should be safe to check ++ * length and ':' position only. ++ */ ++ if (strncmp(ent->d_name, pci, strlen(pci)) != 0) ++ continue; ++ ++ if (ent->d_name[8] != ':' || ent->d_name[11] != 0) ++ continue; ++ break; ++ } ++ ++ if (!ent) { ++ closedir(vmd_dir); ++ return MDADM_STATUS_ERROR; ++ } ++ ++ snprintf(buf, PATH_MAX, "%s/%s", vmd_path, ent->d_name); ++ closedir(vmd_dir); ++ return MDADM_STATUS_SUCCESS; ++} ++ + struct sys_dev *find_driver_devices(const char *bus, const char *driver) + { + /* search sysfs for devices driven by 'driver' */ + char path[PATH_MAX]; + char link[PATH_MAX]; +- char *c, *p; ++ char *c; + DIR *driver_dir; + struct dirent *de; + struct sys_dev *head = NULL; +@@ -142,8 +205,9 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + return NULL; + } + for (de = readdir(driver_dir); de; de = readdir(driver_dir)) { +- int n; + int skip = 0; ++ char *p; ++ int n; + + /* is 'de' a device? check that the 'subsystem' link exists and + * that its target matches 'bus' +@@ -195,18 +259,20 @@ struct sys_dev *find_driver_devices(const char *bus, const char *driver) + if (devpath_to_ll(path, "class", &class) != 0) + continue; + +- /* +- * Each VMD device (domain) adds separate PCI bus, it is better +- * to store path as a path to that bus (easier further +- * determination which NVMe dev is connected to this particular +- * VMD domain). +- */ + if (type == SYS_DEV_VMD) { +- sprintf(path, "/sys/bus/%s/drivers/%s/%s/domain/device", +- bus, driver, de->d_name); ++ char vmd_path[PATH_MAX]; ++ ++ sprintf(vmd_path, "/sys/bus/%s/drivers/%s/%s", bus, driver, de->d_name); ++ ++ if (vmd_find_pci_bus(vmd_path, path)) { ++ pr_err("Cannot determine VMD bus for %s\n", vmd_path); ++ continue; ++ } + } ++ + p = realpath(path, NULL); +- if (p == NULL) { ++ ++ if (!p) { + pr_err("Unable to get real path for '%s'\n", path); + continue; + } +-- +2.41.0 + diff --git a/0163-platform-intel-refactor-path_attached_to_hba.patch b/0163-platform-intel-refactor-path_attached_to_hba.patch new file mode 100644 index 0000000..038c16c --- /dev/null +++ b/0163-platform-intel-refactor-path_attached_to_hba.patch @@ -0,0 +1,129 @@ +From a6392b419f38a0144a03df90371d6890540a55cf Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Tue, 7 May 2024 12:05:43 -0400 +Subject: [PATCH 163/201] platform-intel: refactor path_attached_to_hba() + +dprintf() call in path_attached_to_hba() is too noisy. Remove the call +and refactor the function. Remove obsolete env variables check. + +Signed-off-by: Mateusz Kusiak +--- + platform-intel.c | 31 ++++++++++++++----------------- + platform-intel.h | 2 +- + super-intel.c | 8 ++++---- + 3 files changed, 19 insertions(+), 22 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index d0ef9111..3a86f785 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -1331,31 +1331,28 @@ char *diskfd_to_devpath(int fd, int dev_level, char *buf) + + return devt_to_devpath(st.st_rdev, dev_level, buf); + } +- +-int path_attached_to_hba(const char *disk_path, const char *hba_path) ++/** ++ * is_path_attached_to_hba() - Check if disk is attached to hba ++ * ++ * @disk_path: Path to disk. ++ * @hba_path: Path to hba. ++ * ++ * Returns: true if disk is attached to hba, false otherwise. ++ */ ++bool is_path_attached_to_hba(const char *disk_path, const char *hba_path) + { +- int rc; +- +- if (check_env("IMSM_TEST_AHCI_DEV") || +- check_env("IMSM_TEST_SCU_DEV")) { +- return 1; +- } +- + if (!disk_path || !hba_path) +- return 0; +- dprintf("hba: %s - disk: %s\n", hba_path, disk_path); ++ return false; + if (strncmp(disk_path, hba_path, strlen(hba_path)) == 0) +- rc = 1; +- else +- rc = 0; ++ return true; + +- return rc; ++ return false; + } + + int devt_attached_to_hba(dev_t dev, const char *hba_path) + { + char *disk_path = devt_to_devpath(dev, 1, NULL); +- int rc = path_attached_to_hba(disk_path, hba_path); ++ int rc = is_path_attached_to_hba(disk_path, hba_path); + + if (disk_path) + free(disk_path); +@@ -1366,7 +1363,7 @@ int devt_attached_to_hba(dev_t dev, const char *hba_path) + int disk_attached_to_hba(int fd, const char *hba_path) + { + char *disk_path = diskfd_to_devpath(fd, 1, NULL); +- int rc = path_attached_to_hba(disk_path, hba_path); ++ int rc = is_path_attached_to_hba(disk_path, hba_path); + + if (disk_path) + free(disk_path); +diff --git a/platform-intel.h b/platform-intel.h +index dcc5aaa7..344624d7 100644 +--- a/platform-intel.h ++++ b/platform-intel.h +@@ -257,7 +257,7 @@ const struct imsm_orom *find_imsm_orom(void); + int disk_attached_to_hba(int fd, const char *hba_path); + int devt_attached_to_hba(dev_t dev, const char *hba_path); + char *devt_to_devpath(dev_t dev, int dev_level, char *buf); +-int path_attached_to_hba(const char *disk_path, const char *hba_path); ++bool is_path_attached_to_hba(const char *disk_path, const char *hba_path); + const struct orom_entry *get_orom_entry_by_device_id(__u16 dev_id); + const struct imsm_orom *get_orom_by_device_id(__u16 device_id); + struct sys_dev *device_by_id(__u16 device_id); +diff --git a/super-intel.c b/super-intel.c +index 354c292a..75d7c060 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -800,7 +800,7 @@ static struct sys_dev* find_disk_attached_hba(int fd, const char *devname) + return 0; + + for (elem = list; elem; elem = elem->next) +- if (path_attached_to_hba(disk_path, elem->path)) ++ if (is_path_attached_to_hba(disk_path, elem->path)) + break; + + if (disk_path != devname) +@@ -2412,7 +2412,7 @@ static int ahci_enumerate_ports(struct sys_dev *hba, unsigned long port_count, i + path = devt_to_devpath(makedev(major, minor), 1, NULL); + if (!path) + continue; +- if (!path_attached_to_hba(path, hba->path)) { ++ if (!is_path_attached_to_hba(path, hba->path)) { + free(path); + path = NULL; + continue; +@@ -2563,7 +2563,7 @@ static int print_nvme_info(struct sys_dev *hba) + !diskfd_to_devpath(fd, 1, cntrl_path)) + goto skip; + +- if (!path_attached_to_hba(cntrl_path, hba->path)) ++ if (!is_path_attached_to_hba(cntrl_path, hba->path)) + goto skip; + + if (!imsm_is_nvme_namespace_supported(fd, 0)) +@@ -7077,7 +7077,7 @@ get_devices(const char *hba_path) + path = devt_to_devpath(makedev(major, minor), 1, NULL); + if (!path) + continue; +- if (!path_attached_to_hba(path, hba_path)) { ++ if (!is_path_attached_to_hba(path, hba_path)) { + free(path); + path = NULL; + continue; +-- +2.41.0 + diff --git a/0164-mdadm-Change-displaying-of-devices-in-detail.patch b/0164-mdadm-Change-displaying-of-devices-in-detail.patch new file mode 100644 index 0000000..02ba8d3 --- /dev/null +++ b/0164-mdadm-Change-displaying-of-devices-in-detail.patch @@ -0,0 +1,44 @@ +From bd5511c792ecc73de8897fbd8713e8c6eaf3e835 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Wed, 28 Aug 2024 12:04:35 +0200 +Subject: [PATCH 164/201] mdadm: Change displaying of devices in --detail + +The counts of active, working, failed and spare devices were not +printed when the number was zero. + +Refactor the code to always display the counts of all device types, +regardless of their number. This way, it is more reliable for users. + +Signed-off-by: Anna Sztukowska +--- + Detail.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/Detail.c b/Detail.c +index f8b9e847..331e1da3 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -549,16 +549,10 @@ int Detail(char *dev, struct context *c) + } else if (inactive && !is_container) { + printf(" State : inactive\n"); + } +- if (array.raid_disks) +- printf(" Active Devices : %d\n", array.active_disks); +- if (array.working_disks > 0) +- printf(" Working Devices : %d\n", +- array.working_disks); +- if (array.raid_disks) { +- printf(" Failed Devices : %d\n", array.failed_disks); +- if (!external) +- printf(" Spare Devices : %d\n", array.spare_disks); +- } ++ printf(" Active Devices : %d\n", array.active_disks); ++ printf(" Working Devices : %d\n", array.working_disks); ++ printf(" Failed Devices : %d\n", array.failed_disks); ++ printf(" Spare Devices : %d\n", array.spare_disks); + printf("\n"); + if (array.level == 5) { + str = map_num(r5layout, array.layout); +-- +2.41.0 + diff --git a/0165-imsm-Remove-warning-and-refactor-add_to_super_imsm-c.patch b/0165-imsm-Remove-warning-and-refactor-add_to_super_imsm-c.patch new file mode 100644 index 0000000..6501c61 --- /dev/null +++ b/0165-imsm-Remove-warning-and-refactor-add_to_super_imsm-c.patch @@ -0,0 +1,196 @@ +From 734e7db4dfc502044d2a3dacfab67aeab0081cf9 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 22 Aug 2024 11:55:15 +0200 +Subject: [PATCH 165/201] imsm: Remove warning and refactor add_to_super_imsm + code + +Intel x8 drives are not supported, remove unnecessary warning and +refactor add_to_super_imsm code. + +Signed-off-by: Mariusz Tkaczyk +--- + super-intel.c | 102 +++++++++++++++++++------------------------------- + 1 file changed, 39 insertions(+), 63 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 75d7c060..50fd56d0 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -5976,12 +5976,12 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + unsigned long long data_offset) + { + struct intel_super *super = st->sb; +- struct dl *dd; +- unsigned long long size; + unsigned int member_sector_size; ++ unsigned long long size; ++ struct stat stb; ++ struct dl *dd; + __u32 id; + int rv; +- struct stat stb; + + /* If we are on an RAID enabled platform check that the disk is + * attached to the raid controller. +@@ -5991,114 +5991,86 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + rv = find_intel_hba_capability(fd, super, devname); + /* no orom/efi or non-intel hba of the disk */ + if (rv != 0) { +- dprintf("capability: %p fd: %d ret: %d\n", +- super->orom, fd, rv); +- return 1; ++ dprintf("capability: %p fd: %d ret: %d\n", super->orom, fd, rv); ++ return MDADM_STATUS_ERROR; + } + + if (super->current_vol >= 0) + return add_to_super_imsm_volume(st, dk, fd, devname); + + if (fstat(fd, &stb) != 0) +- return 1; ++ return MDADM_STATUS_ERROR; ++ + dd = xcalloc(sizeof(*dd), 1); ++ ++ if (devname) ++ dd->devname = xstrdup(devname); ++ ++ if (sysfs_disk_to_scsi_id(fd, &id) == 0) ++ dd->disk.scsi_id = __cpu_to_le32(id); ++ + dd->major = major(stb.st_rdev); + dd->minor = minor(stb.st_rdev); +- dd->devname = devname ? xstrdup(devname) : NULL; +- dd->fd = fd; +- dd->e = NULL; + dd->action = DISK_ADD; ++ dd->fd = fd; ++ + rv = imsm_read_serial(fd, devname, dd->serial, MAX_RAID_SERIAL_LEN); + if (rv) { + pr_err("failed to retrieve scsi serial, aborting\n"); +- __free_imsm_disk(dd, 0); +- abort(); ++ goto error; + } + + if (super->hba && ((super->hba->type == SYS_DEV_NVME) || + (super->hba->type == SYS_DEV_VMD))) { +- int i; +- char cntrl_path[PATH_MAX]; +- char *cntrl_name; + char pci_dev_path[PATH_MAX]; ++ char cntrl_path[PATH_MAX]; + + if (!diskfd_to_devpath(fd, 2, pci_dev_path) || + !diskfd_to_devpath(fd, 1, cntrl_path)) { + pr_err("failed to get dev paths, aborting\n"); +- __free_imsm_disk(dd, 0); +- return 1; ++ goto error; + } + +- cntrl_name = basename(cntrl_path); + if (is_multipath_nvme(fd)) + pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", +- cntrl_name); ++ basename(cntrl_path)); + +- if (devpath_to_vendor(pci_dev_path) == 0x8086) { +- /* +- * If Intel's NVMe drive has serial ended with +- * "-A","-B","-1" or "-2" it means that this is "x8" +- * device (double drive on single PCIe card). +- * User should be warned about potential data loss. +- */ +- for (i = MAX_RAID_SERIAL_LEN-1; i > 0; i--) { +- /* Skip empty character at the end */ +- if (dd->serial[i] == 0) +- continue; +- +- if (((dd->serial[i] == 'A') || +- (dd->serial[i] == 'B') || +- (dd->serial[i] == '1') || +- (dd->serial[i] == '2')) && +- (dd->serial[i-1] == '-')) +- pr_err("\tThe action you are about to take may put your data at risk.\n" +- "\tPlease note that x8 devices may consist of two separate x4 devices " +- "located on a single PCIe port.\n" +- "\tRAID 0 is the only supported configuration for this type of x8 device.\n"); +- break; +- } +- } else if (super->hba->type == SYS_DEV_VMD && super->orom && ++ if (super->hba->type == SYS_DEV_VMD && super->orom && + !imsm_orom_has_tpv_support(super->orom)) { + pr_err("\tPlatform configuration does not support non-Intel NVMe drives.\n" + "\tPlease refer to Intel(R) RSTe/VROC user guide.\n"); +- __free_imsm_disk(dd, 0); +- return 1; ++ goto error; + } + } + +- get_dev_size(fd, NULL, &size); +- if (!get_dev_sector_size(fd, NULL, &member_sector_size)) { +- __free_imsm_disk(dd, 0); +- return 1; +- } ++ if (!get_dev_size(fd, NULL, &size) || !get_dev_sector_size(fd, NULL, &member_sector_size)) ++ goto error; + +- if (super->sector_size == 0) { ++ if (super->sector_size == 0) + /* this a first device, so sector_size is not set yet */ + super->sector_size = member_sector_size; +- } + + /* 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 ((unsigned int)write(fd, super->migr_rec_buf, +- MIGR_REC_BUF_SECTORS*member_sector_size) != +- MIGR_REC_BUF_SECTORS*member_sector_size) ++ 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) { ++ unsigned int nbytes = MIGR_REC_BUF_SECTORS * member_sector_size; ++ ++ if ((unsigned int)write(fd, super->migr_rec_buf, nbytes) != nbytes) + perror("Write migr_rec failed"); + } + + size /= 512; + serialcpy(dd->disk.serial, dd->serial); + set_total_blocks(&dd->disk, size); ++ + if (__le32_to_cpu(dd->disk.total_blocks_hi) > 0) { + struct imsm_super *mpb = super->anchor; ++ + mpb->attributes |= MPB_ATTRIB_2TB_DISK; + } ++ + mark_spare(dd); +- if (sysfs_disk_to_scsi_id(fd, &id) == 0) +- dd->disk.scsi_id = __cpu_to_le32(id); +- else +- dd->disk.scsi_id = __cpu_to_le32(0); + + if (st->update_tail) { + dd->next = super->disk_mgmt_list; +@@ -6113,7 +6085,11 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + write_super_imsm_spare(super, dd); + } + +- return 0; ++ return MDADM_STATUS_SUCCESS; ++ ++error: ++ __free_imsm_disk(dd, 0); ++ return MDADM_STATUS_ERROR; + } + + static int remove_from_super_imsm(struct supertype *st, mdu_disk_info_t *dk) +-- +2.41.0 + diff --git a/0166-imsm-add-IMSM_OROM_CAPABILITIES_TPV-to-nvme-orom.patch b/0166-imsm-add-IMSM_OROM_CAPABILITIES_TPV-to-nvme-orom.patch new file mode 100644 index 0000000..3545f0b --- /dev/null +++ b/0166-imsm-add-IMSM_OROM_CAPABILITIES_TPV-to-nvme-orom.patch @@ -0,0 +1,192 @@ +From b1d38b512aa3162b5089fbf6b02357ed5fdf5760 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 22 Aug 2024 12:18:06 +0200 +Subject: [PATCH 166/201] imsm: add IMSM_OROM_CAPABILITIES_TPV to nvme orom + +Add it to avoid excluding. It has some value for users even if it is +always true for nvme virtual orom. + +Rework detail-platform printing code, move printing 3rd party nvmes +to print_imsm_capability (as it should be), but keep it meaningful +only for nvme controllers (NVME and VMD hba types). Pass whole +orom_entry instead of orom there. + +Squash code responsible for printing NVME and VMD hbas. + +Signed-off-by: Mariusz Tkaczyk +--- + platform-intel.c | 3 +- + super-intel.c | 76 +++++++++++++++++++++++------------------------- + 2 files changed, 39 insertions(+), 40 deletions(-) + +diff --git a/platform-intel.c b/platform-intel.c +index 3a86f785..21591317 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -1089,7 +1089,8 @@ const struct imsm_orom *find_imsm_nvme(struct sys_dev *hba) + .vpa = IMSM_OROM_VOLUMES_PER_ARRAY, + .vphba = IMSM_OROM_TOTAL_DISKS_NVME / 2 * IMSM_OROM_VOLUMES_PER_ARRAY, + .attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK, +- .driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem ++ .driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem | ++ IMSM_OROM_CAPABILITIES_TPV + }; + nvme_orom = add_orom(&nvme_orom_compat); + } +diff --git a/super-intel.c b/super-intel.c +index 50fd56d0..744715d5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -2663,9 +2663,12 @@ static void print_imsm_chunk_size_capability(const struct imsm_orom *orom) + } + + +-static void print_imsm_capability(const struct imsm_orom *orom) ++static void print_imsm_capability(const struct orom_entry *entry) + { ++ const struct imsm_orom *orom = &entry->orom; ++ + printf(" Platform : Intel(R) "); ++ + if (orom->capabilities == 0 && orom->driver_features == 0) + printf("Matrix Storage Manager\n"); + else if (imsm_orom_is_enterprise(orom) && orom->major_ver >= 6) +@@ -2673,6 +2676,7 @@ static void print_imsm_capability(const struct imsm_orom *orom) + else + printf("Rapid Storage Technology%s\n", + imsm_orom_is_enterprise(orom) ? " enterprise" : ""); ++ + if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) { + if (imsm_orom_is_vmd_without_efi(orom)) + printf(" Version : %d.%d\n", orom->major_ver, orom->minor_ver); +@@ -2690,11 +2694,19 @@ static void print_imsm_capability(const struct imsm_orom *orom) + printf("\n"); + + printf(" 2TB volumes :%s supported\n", (orom->attr & IMSM_OROM_ATTR_2TB) ? "" : " not"); ++ + printf(" 2TB disks :%s supported\n", + (orom->attr & IMSM_OROM_ATTR_2TB_DISK) ? "" : " not"); ++ + printf(" Max Disks : %d\n", orom->tds); ++ + printf(" Max Volumes : %d per array, %d per %s\n", orom->vpa, orom->vphba, + imsm_orom_is_nvme(orom) ? "platform" : "controller"); ++ ++ if (entry->type == SYS_DEV_VMD || entry->type == SYS_DEV_NVME) ++ /* This is only meaningful for controllers with nvme support */ ++ printf(" 3rd party NVMe :%s supported\n", ++ imsm_orom_has_tpv_support(&entry->orom) ? "" : " not"); + return; + } + +@@ -2733,26 +2745,25 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + * platform capabilities. If raid support is disabled in the BIOS the + * option-rom capability structure will not be available. + */ ++ const struct orom_entry *entry; + struct sys_dev *list, *hba; +- int host_base = 0; ++ struct devid_list *devid; + int port_count = 0; +- int result=1; ++ int host_base = 0; ++ int result = 1; + + if (enumerate_only) { + if (check_no_platform()) + return 0; ++ + list = find_intel_devices(); + if (!list) + return 2; +- for (hba = list; hba; hba = hba->next) { +- if (find_imsm_capability(hba)) { +- result = 0; +- break; +- } +- else +- result = 2; +- } +- return result; ++ ++ for (hba = list; hba; hba = hba->next) ++ if (find_imsm_capability(hba)) ++ return 0; ++ return 2; + } + + list = find_intel_devices(); +@@ -2768,6 +2779,7 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + continue; + if (!find_imsm_capability(hba)) { + char buf[PATH_MAX]; ++ + pr_err("imsm capabilities not found for controller: %s (type %s)\n", + hba->type == SYS_DEV_VMD || hba->type == SYS_DEV_SATA_VMD ? + vmd_domain_to_controller(hba, buf) : +@@ -2783,40 +2795,27 @@ static int detail_platform_imsm(int verbose, int enumerate_only, char *controlle + return result; + } + +- const struct orom_entry *entry; +- + for (entry = orom_entries; entry; entry = entry->next) { +- if (entry->type == SYS_DEV_VMD) { +- print_imsm_capability(&entry->orom); +- printf(" 3rd party NVMe :%s supported\n", +- imsm_orom_has_tpv_support(&entry->orom)?"":" not"); ++ print_imsm_capability(entry); ++ ++ if (entry->type == SYS_DEV_VMD || entry->type == SYS_DEV_NVME) { + for (hba = list; hba; hba = hba->next) { +- if (hba->type == SYS_DEV_VMD) { +- char buf[PATH_MAX]; ++ char buf[PATH_MAX]; ++ ++ if (hba->type != entry->type) ++ continue; ++ ++ if (hba->type == SYS_DEV_VMD) + printf(" I/O Controller : %s (%s)\n", +- vmd_domain_to_controller(hba, buf), get_sys_dev_type(hba->type)); +- if (print_nvme_info(hba)) { +- if (verbose > 0) +- pr_err("failed to get devices attached to VMD domain.\n"); +- result |= 2; +- } +- } +- } +- printf("\n"); +- continue; +- } ++ vmd_domain_to_controller(hba, buf), ++ get_sys_dev_type(hba->type)); + +- print_imsm_capability(&entry->orom); +- if (entry->type == SYS_DEV_NVME) { +- for (hba = list; hba; hba = hba->next) { +- if (hba->type == SYS_DEV_NVME) +- print_nvme_info(hba); ++ print_nvme_info(hba); + } + printf("\n"); + continue; + } + +- struct devid_list *devid; + for (devid = entry->devid_list; devid; devid = devid->next) { + hba = device_by_id(devid->devid); + if (!hba) +@@ -6035,8 +6034,7 @@ static int add_to_super_imsm(struct supertype *st, mdu_disk_info_t *dk, + pr_err("%s controller supports Multi-Path I/O, Intel (R) VROC does not support multipathing\n", + basename(cntrl_path)); + +- if (super->hba->type == SYS_DEV_VMD && super->orom && +- !imsm_orom_has_tpv_support(super->orom)) { ++ if (super->orom && !imsm_orom_has_tpv_support(super->orom)) { + pr_err("\tPlatform configuration does not support non-Intel NVMe drives.\n" + "\tPlease refer to Intel(R) RSTe/VROC user guide.\n"); + goto error; +-- +2.41.0 + diff --git a/0167-mdadm-Increase-number-limit-in-md-device-name-to-102.patch b/0167-mdadm-Increase-number-limit-in-md-device-name-to-102.patch new file mode 100644 index 0000000..9be51ba --- /dev/null +++ b/0167-mdadm-Increase-number-limit-in-md-device-name-to-102.patch @@ -0,0 +1,33 @@ +From f786072a3e2928766a9b4f1b7d3372a601c259ea Mon Sep 17 00:00:00 2001 +From: Shminderjit Singh +Date: Mon, 26 Aug 2024 10:06:50 +0000 +Subject: [PATCH 167/201] mdadm: Increase number limit in md device name to + 1024. + +Updated the maximum device number in md device names from 127 to 1024. +The previous limit was causing issues in the automation framework. +This change ensures backward compatibility and allows for future +scalability. + +Fixes: 25aa7329141c ("mdadm: numbered names verification") +Signed-off-by: Shminderjit Singh +--- + util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util.c b/util.c +index 1cee0feb..2fc0e9f8 100644 +--- a/util.c ++++ b/util.c +@@ -1003,7 +1003,7 @@ 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 > 127) ++ if (val > 1024) + return false; + + return true; +-- +2.41.0 + diff --git a/0168-imsm-save-checkpoint-prior-to-exit.patch b/0168-imsm-save-checkpoint-prior-to-exit.patch new file mode 100644 index 0000000..01791e4 --- /dev/null +++ b/0168-imsm-save-checkpoint-prior-to-exit.patch @@ -0,0 +1,44 @@ +From dd0d193ad8722140e240c95a4fd1e214077dd719 Mon Sep 17 00:00:00 2001 +From: Mateusz Kusiak +Date: Mon, 2 Sep 2024 12:27:56 -0400 +Subject: [PATCH 168/201] imsm: save checkpoint prior to exit + +If reshape (eg. chunksize migration) is gracefully stopped via SIGTERM +the checkpoint is not saved and reshape cannot be resumed due to "data +being present in copy area". This is because UNIT_SRC_NORMAL isn't set +if SIGTERM occurred. + +Move SIGTERM handling at the end of the loop to allow saving checkpoint +(and state) so reshapes can be properly resumed. + +Signed-off-by: Mateusz Kusiak +--- + super-intel.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/super-intel.c b/super-intel.c +index 744715d5..30c2939a 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -12631,8 +12631,6 @@ static int imsm_manage_reshape( + dprintf("wait_for_reshape_imsm returned error!\n"); + goto abort; + } +- if (sigterm) +- goto abort; + + if (save_checkpoint_imsm(st, sra, UNIT_SRC_NORMAL) == 1) { + /* ignore error == 2, this can mean end of reshape here +@@ -12641,6 +12639,9 @@ static int imsm_manage_reshape( + goto abort; + } + ++ if (sigterm) ++ goto abort; ++ + } + + /* clear migr_rec on disks after successful migration */ +-- +2.41.0 + diff --git a/0169-Examine.c-Fix-memory-leaks-in-Examine.patch b/0169-Examine.c-Fix-memory-leaks-in-Examine.patch new file mode 100644 index 0000000..826f343 --- /dev/null +++ b/0169-Examine.c-Fix-memory-leaks-in-Examine.patch @@ -0,0 +1,116 @@ +From da26064bfe4457d5037f3a1f1bb83a54225c6375 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Thu, 8 Aug 2024 17:02:38 +0200 +Subject: [PATCH 169/201] Examine.c: Fix memory leaks in Examine() + +Fix memory leaks in Examine() reported by SAST analysis. Implement a +method to traverse and free all the nodes of the doubly linked list. +Replace for loop with while loop in order to improve redability of the +code and free allocated memory correctly. + +Signed-off-by: Anna Sztukowska +--- + Examine.c | 22 +++++++++++++++++----- + dlink.c | 15 +++++++++++++++ + dlink.h | 1 + + 3 files changed, 33 insertions(+), 5 deletions(-) + +diff --git a/Examine.c b/Examine.c +index c9605a60..fe162167 100644 +--- a/Examine.c ++++ b/Examine.c +@@ -111,8 +111,10 @@ int Examine(struct mddev_dev *devlist, + close(fd); + + if (err) { +- if (st) ++ if (st) { + st->ss->free_super(st); ++ free(st); ++ } + continue; + } + +@@ -152,19 +154,24 @@ int Examine(struct mddev_dev *devlist, + if (st->ss->export_examine_super) + st->ss->export_examine_super(st); + st->ss->free_super(st); ++ free(st); + } else { + printf("%s:\n",devlist->devname); + st->ss->examine_super(st, c->homehost); + st->ss->free_super(st); ++ free(st); + } + } + if (c->brief) { +- struct array *ap; +- for (ap = arrays; ap; ap = ap->next) { ++ struct array *ap = arrays, *next; ++ ++ while (ap) { + char sep='='; + char *d; + int newline = 0; + ++ next = ap->next; ++ + ap->st->ss->brief_examine_super(ap->st, c->verbose > 0); + if (ap->spares && !ap->st->ss->external) + newline += printf(" spares=%d", ap->spares); +@@ -182,10 +189,15 @@ int Examine(struct mddev_dev *devlist, + printf("\n"); + ap->st->ss->brief_examine_subarrays(ap->st, c->verbose); + } +- ap->st->ss->free_super(ap->st); +- /* FIXME free ap */ + if (ap->spares || c->verbose > 0) + printf("\n"); ++ ++ ap->st->ss->free_super(ap->st); ++ free(ap->st); ++ dl_free_all(ap->devs); ++ free(ap); ++ ++ ap = next; + } + } + return rv; +diff --git a/dlink.c b/dlink.c +index 69aa7aa3..34633672 100644 +--- a/dlink.c ++++ b/dlink.c +@@ -26,6 +26,21 @@ void dl_free(void *v) + free(vv-1); + } + ++void dl_free_all(void *head) ++{ ++ /* The list head is linked with the list tail so in order to free ++ * all the elements properly there is a need to keep starting point. ++ */ ++ void *d = dl_next(head), *next; ++ ++ while (d != head) { ++ next = dl_next(d); ++ dl_free(d); ++ d = next; ++ } ++ dl_free(head); ++} ++ + void dl_init(void *v) + { + dl_next(v) = v; +diff --git a/dlink.h b/dlink.h +index ab2a9459..ce667839 100644 +--- a/dlink.h ++++ b/dlink.h +@@ -23,3 +23,4 @@ void dl_add(void*, void*); + void dl_del(void*); + void dl_free(void*); + void dl_init(void*); ++void dl_free_all(void *head); +-- +2.41.0 + diff --git a/0170-dlink.h-Fix-checkpatch-warnings-for-function-args.patch b/0170-dlink.h-Fix-checkpatch-warnings-for-function-args.patch new file mode 100644 index 0000000..13038b1 --- /dev/null +++ b/0170-dlink.h-Fix-checkpatch-warnings-for-function-args.patch @@ -0,0 +1,39 @@ +From be1b4ff0957b287b2d8494967a7f0a1e3401dd8a Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Mon, 9 Sep 2024 09:36:47 +0200 +Subject: [PATCH 170/201] dlink.h: Fix checkpatch warnings for function args + +Checkpatch issued a warning due to missing function argument names. +Add the names to resolve the warnings. + +Signed-off-by: Anna Sztukowska +--- + dlink.h | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/dlink.h b/dlink.h +index ce667839..18cc294a 100644 +--- a/dlink.h ++++ b/dlink.h +@@ -16,11 +16,11 @@ struct __dl_head + #define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev)) + + void *dl_head(void); +-char *dl_strdup(char *); +-char *dl_strndup(char *, int); +-void dl_insert(void*, void*); +-void dl_add(void*, void*); +-void dl_del(void*); +-void dl_free(void*); +-void dl_init(void*); ++char *dl_strdup(char *s); ++char *dl_strndup(char *s, int l); ++void dl_insert(void *head, void *val); ++void dl_add(void *head, void *val); ++void dl_del(void *val); ++void dl_free(void *v); ++void dl_init(void *v); + void dl_free_all(void *head); +-- +2.41.0 + diff --git a/0171-Incremental-support-devnode-in-IncrementalRemove.patch b/0171-Incremental-support-devnode-in-IncrementalRemove.patch new file mode 100644 index 0000000..c31cfb8 --- /dev/null +++ b/0171-Incremental-support-devnode-in-IncrementalRemove.patch @@ -0,0 +1,151 @@ +From 9b8933bb6dbfcae1bd5a2f933c87684de99412de Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 25 Jun 2024 12:53:46 +0200 +Subject: [PATCH 171/201] Incremental: support devnode in IncrementalRemove. + +There are no reasons to keep this interface different than others. +Allow to use devnode but keep old way for backward compatibility. +Method is added to verify that only devnode or kernel name is used. + +Signed-off-by: Mariusz Tkaczyk +--- + Incremental.c | 60 ++++++++++++++++++++++++------------- + mdadm.h | 5 ++++ + udev-md-raid-assembly.rules | 4 +-- + 3 files changed, 46 insertions(+), 23 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index fc4e68ff..c1389a15 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1674,33 +1674,52 @@ static void remove_from_member_array(struct mdstat_ent *memb, + } + } + +-/* +- * IncrementalRemove - Attempt to see if the passed in device belongs to any +- * raid arrays, and if so first fail (if needed) and then remove the device. ++/** ++ * is_devnode_path() - check if the devname passed might be devnode path. ++ * @devnode: the path to check. + * +- * @devname - The device we want to remove +- * @id_path - name as found in /dev/disk/by-path for this device ++ * Devnode must be located directly in /dev directory. It is not checking existence of the file ++ * because the device might no longer exist during removal from raid array. ++ */ ++static bool is_devnode_path(char *devnode) ++{ ++ char *devnm = strrchr(devnode, '/'); ++ ++ if (!devnm || *(devnm + 1) == 0) ++ return false; ++ ++ if (strncmp(devnode, DEV_DIR, DEV_DIR_LEN) == 0 && devnode + DEV_DIR_LEN - 1 == devnm) ++ return true; ++ ++ return false; ++} ++ ++/** ++ * IncrementalRemove() - Remove the device from all raid arrays. ++ * @devname: the device we want to remove, it could be kernel device name or devnode. ++ * @id_path: optional, /dev/disk/by-path path to save for bare scenarios support. ++ * @verbose: verbose flag. + * +- * Note: the device name must be a kernel name like "sda", so +- * that we can find it in /proc/mdstat ++ * First, fail the device (if needed) and then remove the device from native raid array or external ++ * container. If it is external container, the device is removed from each subarray first. + */ + int IncrementalRemove(char *devname, char *id_path, int verbose) + { +- struct mdstat_ent *ent = NULL; ++ char *devnm = basename(devname); ++ struct mddev_dev devlist = {0}; + char buf[SYSFS_MAX_BUF_SIZE]; + struct mdstat_ent *mdstat; +- struct mddev_dev devlist; ++ struct mdstat_ent *ent; + struct mdinfo mdi; + int rv = 1; + int mdfd; + +- if (!id_path) +- dprintf("incremental removal without --path lacks the possibility to re-add new device in this port\n"); +- +- if (strchr(devname, '/')) { +- pr_err("incremental removal requires a kernel device name, not a file: %s\n", devname); +- return 1; +- } ++ if (strcmp(devnm, devname) != 0) ++ if (!is_devnode_path(devname)) { ++ pr_err("Cannot remove \"%s\", devnode path or kernel device name is allowed.\n", ++ devname); ++ return 1; ++ } + + mdstat = mdstat_read(0, 0); + if (!mdstat) { +@@ -1708,15 +1727,15 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + return 1; + } + +- ent = mdstat_find_by_member_name(mdstat, devname); ++ ent = mdstat_find_by_member_name(mdstat, devnm); + if (!ent) { + if (verbose >= 0) +- pr_err("%s does not appear to be a component of any array\n", devname); ++ pr_vrb("%s does not appear to be a component of any array\n", devnm); + goto out; + } + + if (sysfs_init(&mdi, -1, ent->devnm)) { +- pr_err("unable to initialize sysfs for: %s\n", devname); ++ pr_err("unable to initialize sysfs for: %s\n", devnm); + goto out; + } + +@@ -1746,8 +1765,7 @@ int IncrementalRemove(char *devname, char *id_path, int verbose) + map_free(map); + } + +- memset(&devlist, 0, sizeof(devlist)); +- devlist.devname = devname; ++ devlist.devname = devnm; + devlist.disposition = 'I'; + /* for a container, we must fail each member array */ + if (is_mdstat_ent_external(ent)) { +diff --git a/mdadm.h b/mdadm.h +index 5c3a9836..f3b9f54c 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -100,6 +100,11 @@ struct dlm_lksb { + #define DEFAULT_BITMAP_DELAY 5 + #define DEFAULT_MAX_WRITE_BEHIND 256 + ++#ifndef DEV_DIR ++#define DEV_DIR "/dev/" ++#define DEV_DIR_LEN (sizeof(DEV_DIR) - 1) ++#endif /* DEV_DIR */ ++ + /* DEV_NUM_PREF is a subpath to numbered MD devices, e.g. /dev/md1 or directory name. + * DEV_NUM_PREF_LEN is a length with Null byte excluded. + */ +diff --git a/udev-md-raid-assembly.rules b/udev-md-raid-assembly.rules +index d4a7f0a5..4cd2c6f4 100644 +--- a/udev-md-raid-assembly.rules ++++ b/udev-md-raid-assembly.rules +@@ -41,7 +41,7 @@ ACTION=="change", KERNEL!="dm-*|md*", GOTO="md_inc_end" + ACTION!="remove", IMPORT{program}="BINDIR/mdadm --incremental --export $devnode --offroot $env{DEVLINKS}" + ACTION!="remove", ENV{MD_STARTED}=="*unsafe*", ENV{MD_FOREIGN}=="no", ENV{SYSTEMD_WANTS}+="mdadm-last-resort@$env{MD_DEVICE}.timer" + +-ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="BINDIR/mdadm -If $name --path $env{ID_PATH}" +-ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="BINDIR/mdadm -If $name" ++ACTION=="remove", ENV{ID_PATH}=="?*", RUN+="BINDIR/mdadm -If $devnode --path $env{ID_PATH}" ++ACTION=="remove", ENV{ID_PATH}!="?*", RUN+="BINDIR/mdadm -If $devnode" + + LABEL="md_inc_end" +-- +2.41.0 + diff --git a/0172-Detail.c-Fix-divide_by_zero-issue.patch b/0172-Detail.c-Fix-divide_by_zero-issue.patch new file mode 100644 index 0000000..59d92d8 --- /dev/null +++ b/0172-Detail.c-Fix-divide_by_zero-issue.patch @@ -0,0 +1,75 @@ +From 7b65dd6d71dfff35847440e19d309990dfcb29d3 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Mon, 29 Jul 2024 07:47:39 +0200 +Subject: [PATCH 172/201] Detail.c: Fix divide_by_zero issue + +Fix divide_by_zero issue reported by SAST analysis in Detail.c when +calling enough() from util.c. Also add missing spaces for better code +readability. + +Signed-off-by: Anna Sztukowska +--- + util.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/util.c b/util.c +index 2fc0e9f8..cc162278 100644 +--- a/util.c ++++ b/util.c +@@ -513,6 +513,9 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail) + int i; + int avail_disks = 0; + ++ if (raid_disks <= 0) ++ return 0; ++ + for (i = 0; i < raid_disks; i++) + avail_disks += !!avail[i]; + +@@ -521,7 +524,7 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail) + /* This is the tricky one - we need to check + * which actual disks are present. + */ +- copies = (layout&255)* ((layout>>8) & 255); ++ copies = (layout & 255) * ((layout >> 8) & 255); + first = 0; + do { + /* there must be one of the 'copies' form 'first' */ +@@ -531,16 +534,16 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail) + while (n--) { + if (avail[this]) + cnt++; +- this = (this+1) % raid_disks; ++ this = (this + 1) % raid_disks; + } + if (cnt == 0) + return 0; +- first = (first+(layout&255)) % raid_disks; ++ first = (first + (layout & 255)) % raid_disks; + } while (first != 0); + return 1; + + case LEVEL_MULTIPATH: +- return avail_disks>= 1; ++ return avail_disks >= 1; + case LEVEL_LINEAR: + case 0: + return avail_disks == raid_disks; +@@ -556,12 +559,12 @@ int enough(int level, int raid_disks, int layout, int clean, char *avail) + /* FALL THROUGH */ + case 5: + if (clean) +- return avail_disks >= raid_disks-1; ++ return avail_disks >= raid_disks - 1; + else + return avail_disks >= raid_disks; + case 6: + if (clean) +- return avail_disks >= raid_disks-2; ++ return avail_disks >= raid_disks - 2; + else + return avail_disks >= raid_disks; + default: +-- +2.41.0 + diff --git a/0173-mdadm-Add-compilation-process-to-README.md.patch b/0173-mdadm-Add-compilation-process-to-README.md.patch new file mode 100644 index 0000000..cfb5064 --- /dev/null +++ b/0173-mdadm-Add-compilation-process-to-README.md.patch @@ -0,0 +1,81 @@ +From 983e9226fb02a91692c2c55a19b5cd06d8ddd005 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Tue, 6 Aug 2024 10:44:01 +0200 +Subject: [PATCH 173/201] mdadm: Add compilation process to README.md + +Add compilation process and dependencies to README.md. + +Signed-off-by: Anna Sztukowska +--- + README.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/README.md b/README.md +index 486c8929..870ecb7e 100644 +--- a/README.md ++++ b/README.md +@@ -87,6 +87,61 @@ If there are differences between github and kernel.org, please contact kernel.or + We do not support kernel versions below **v3.10**. Please be aware that maintainers may remove + workarounds and fixes for legacy issues. + ++# Dependencies ++ ++The following packages are required for compilation: ++ ++| RHEL | SLES | Debian/Ubuntu | ++| :---: | :---: | :---: | ++| `pkgconf` | `pkg-config` | `pkg-config` | ++| `gcc` | `gcc` | `gcc` | ++| `make` | `make` | `make` | ++| `libudev-devel` | `libudev-devel` | `libudev-dev` | ++ ++# Compiling mdadm ++ ++Run `make` command to compile mdadm. ++ ++Specifying more jobs e.g. `make -j4` can decrease compilation time significantly. ++ ++Various values can be specified for the `CXFLAGS` variable to customize the build process: ++- Run `make CXFLAGS=-ggdb` to include gdb debugging information. ++- Run `make CXFLAGS=-DDEBUG` to enable additional debug information through dprintf statements ++and call traces. ++- Run `make CXFLAGS=-DNO_LIBUDEV` to compile without `libudev`. ++ ++To build with more than one option specified in `CXFLAGS`, separate each option with a space, e.g. ++`make CXFLAGS="-ggdb -DDEBUG"`. ++ ++Additionally, the `EXTRAVERSION` variable can be set to build with user-friendly version label, ++useful when customizing mdadm builds or labeling some instance in between major releases, ++e.g. `make EXTRAVERSION="custom-label"`. ++ ++# Installing mdadm ++ ++Before installing mdadm, it is advised to uninstall vendor-provided packages (mdadm.deb, mdadm.rpm ++etc.) in order to avoid configuration issues. ++ ++Run `make install` command to install mdadm. This command invokes the following targets: ++- `install-bin` ++- `install-man` ++- `install-udev` ++ ++After installing mdadm, consider rebuilding initramfs to ensure the changes take effect. ++ ++List of installation targets: ++- Run `make install-bin` to install the mdadm and mdmon binary files. ++- Run `make install-systemd` to install the systemd services. ++- Run `make install-udev` to install the udev rules. ++- Run `make install-man` to install the manual pages (`mdadm.8`, `md.4`, `mdadm.conf.5`, ++`mdmon.8`). ++ ++The following targets are deprecated and should not be used: ++- `install-static` ++- `install-tcc` ++- `install-uclibc` ++- `install-klibc` ++ + # License + + It is released under the terms of the **GNU General Public License version 2** as published +-- +2.41.0 + diff --git a/0174-mdadm-Grow-Update-new-level-when-starting-reshape.patch b/0174-mdadm-Grow-Update-new-level-when-starting-reshape.patch new file mode 100644 index 0000000..0541434 --- /dev/null +++ b/0174-mdadm-Grow-Update-new-level-when-starting-reshape.patch @@ -0,0 +1,53 @@ +From 21212f6ad7c634f5f114f342ca84fe8c42a13f40 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:23 +0800 +Subject: [PATCH 174/201] mdadm/Grow: Update new level when starting reshape + +Reshape needs to specify a backup file when it can't update data offset +of member disks. For this situation, first, it starts reshape and then +it kicks off mdadm-grow-continue service which does backup job and +monitors the reshape process. The service is a new process, so it needs +to read superblock from member disks to get information. + +But in the first step, it doesn't update new level in superblock. So +it can't change level after reshape finishes, because the new level is +not right. So records the new level in the first step. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/Grow.c b/Grow.c +index 5810b128..533f3014 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -2941,15 +2941,24 @@ static int impose_reshape(struct mdinfo *sra, + * persists from some earlier problem. + */ + int err = 0; ++ + if (sysfs_set_num(sra, NULL, "chunk_size", info->new_chunk) < 0) + err = errno; ++ + if (!err && sysfs_set_num(sra, NULL, "layout", + reshape->after.layout) < 0) + err = errno; ++ ++ /* new_level is introduced in kernel 6.12 */ ++ if (!err && get_linux_version() >= 6012000 && ++ sysfs_set_num(sra, NULL, "new_level", info->new_level) < 0) ++ err = errno; ++ + if (!err && subarray_set_num(container, sra, "raid_disks", + reshape->after.data_disks + + reshape->parity) < 0) + err = errno; ++ + if (err) { + pr_err("Cannot set device shape for %s\n", devname); + +-- +2.41.0 + diff --git a/0175-mdadm-Grow-Update-reshape_progress-to-need_back-afte.patch b/0175-mdadm-Grow-Update-reshape_progress-to-need_back-afte.patch new file mode 100644 index 0000000..dc5a889 --- /dev/null +++ b/0175-mdadm-Grow-Update-reshape_progress-to-need_back-afte.patch @@ -0,0 +1,57 @@ +From 568259859cafeefbf54354c19405cf2292da4b4a Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:24 +0800 +Subject: [PATCH 175/201] mdadm/Grow: Update reshape_progress to need_back + after reshape finishes + +It tries to update data offset when kicking off reshape. If it can't +change data offset, it needs to use child_monitor to monitor reshape +progress and do back up job. And it needs to update reshape_progress +to need_back when reshape finishes. If not, it will be in a infinite +loop. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 533f3014..3b9f9942 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -4148,8 +4148,8 @@ int progress_reshape(struct mdinfo *info, struct reshape *reshape, + * waiting forever on a dead array + */ + char action[SYSFS_MAX_BUF_SIZE]; +- if (sysfs_get_str(info, NULL, "sync_action", action, sizeof(action)) <= 0 || +- strncmp(action, "reshape", 7) != 0) ++ ++ if (sysfs_get_str(info, NULL, "sync_action", action, sizeof(action)) <= 0) + break; + /* Some kernels reset 'sync_completed' to zero + * before setting 'sync_action' to 'idle'. +@@ -4157,12 +4157,18 @@ int progress_reshape(struct mdinfo *info, struct reshape *reshape, + */ + if (completed == 0 && advancing && + strncmp(action, "idle", 4) == 0 && +- info->reshape_progress > 0) ++ info->reshape_progress > 0) { ++ info->reshape_progress = need_backup; + break; ++ } + if (completed == 0 && !advancing && + strncmp(action, "idle", 4) == 0 && + info->reshape_progress < +- (info->component_size * reshape->after.data_disks)) ++ (info->component_size * reshape->after.data_disks)) { ++ info->reshape_progress = need_backup; ++ break; ++ } ++ if (strncmp(action, "reshape", 7) != 0) + break; + sysfs_wait(fd, NULL); + if (sysfs_fd_get_ll(fd, &completed) < 0) +-- +2.41.0 + diff --git a/0176-mdadm-Grow-Can-t-open-raid-when-running-grow-continu.patch b/0176-mdadm-Grow-Can-t-open-raid-when-running-grow-continu.patch new file mode 100644 index 0000000..ebe0d4a --- /dev/null +++ b/0176-mdadm-Grow-Can-t-open-raid-when-running-grow-continu.patch @@ -0,0 +1,38 @@ +From cd94b9adf7d53457d86cdc39b983b18713f24032 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:25 +0800 +Subject: [PATCH 176/201] mdadm/Grow: Can't open raid when running --grow + --continue + +It passes 'array' as devname in Grow_continue. So it fails to +open raid device. Use mdinfo to open raid device. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/Grow.c b/Grow.c +index 3b9f9942..ebb53a0d 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -3694,9 +3694,12 @@ started: + set_array_size(st, info, info->text_version); + + if (info->new_level != reshape.level) { +- if (fd < 0) +- fd = open(devname, O_RDONLY); +- impose_level(fd, info->new_level, devname, verbose); ++ fd = open_dev(sra->sys_name); ++ if (fd < 0) { ++ pr_err("Can't open %s\n", sra->sys_name); ++ goto out; ++ } ++ impose_level(fd, info->new_level, sra->sys_name, verbose); + close(fd); + if (info->new_level == 0) + st->update_tail = NULL; +-- +2.41.0 + diff --git a/0177-mdadm-Grow-sleep-a-while-after-removing-disk-in-impo.patch b/0177-mdadm-Grow-sleep-a-while-after-removing-disk-in-impo.patch new file mode 100644 index 0000000..7e60aca --- /dev/null +++ b/0177-mdadm-Grow-sleep-a-while-after-removing-disk-in-impo.patch @@ -0,0 +1,39 @@ +From 166e5e2fc4b634df100ccc0010035f925bb2ad63 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:26 +0800 +Subject: [PATCH 177/201] mdadm/Grow: sleep a while after removing disk in + impose_level + +It needs to remove disks when reshaping from raid456 to raid0. In +kernel space it sets MD_RECOVERY_RUNNING. And it will fail to change +level. So wait sometime to let md thread to clear this flag. + +This is found by test case 05r6tor0. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/Grow.c b/Grow.c +index ebb53a0d..60076f56 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -3034,6 +3034,13 @@ static int impose_level(int fd, int level, char *devname, int verbose) + makedev(disk.major, disk.minor)); + hot_remove_disk(fd, makedev(disk.major, disk.minor), 1); + } ++ /* ++ * hot_remove_disk lets kernel set MD_RECOVERY_RUNNING ++ * and it can't set level. It needs to wait sometime ++ * to let md thread to clear the flag. ++ */ ++ pr_info("wait 5 seconds to give kernel space to finish job\n"); ++ sleep_for(5, 0, true); + } + c = map_num(pers, level); + if (c) { +-- +2.41.0 + diff --git a/0178-mdadm-tests-wait-until-level-changes.patch b/0178-mdadm-tests-wait-until-level-changes.patch new file mode 100644 index 0000000..3437de6 --- /dev/null +++ b/0178-mdadm-tests-wait-until-level-changes.patch @@ -0,0 +1,33 @@ +From 098337f31de3f0683cd99727104c81db81fda9cd Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:27 +0800 +Subject: [PATCH 178/201] mdadm/tests: wait until level changes + +check wait waits reshape finishes, but it doesn't wait level changes. +The level change happens in a forked child progress. So we need to +search the child progress and monitor it. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/05r6tor0 | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tests/05r6tor0 b/tests/05r6tor0 +index 2fd51f2e..b2685b72 100644 +--- a/tests/05r6tor0 ++++ b/tests/05r6tor0 +@@ -13,6 +13,10 @@ check raid5 + testdev $md0 3 19456 512 + mdadm -G $md0 -l0 + check wait; sleep 1 ++while ps auxf | grep "mdadm -G" | grep -v grep ++do ++ sleep 1 ++done + check raid0 + testdev $md0 3 19456 512 + mdadm -G $md0 -l5 --add $dev3 $dev4 +-- +2.41.0 + diff --git a/0179-mdadm-tests-07changelevels-fix.patch b/0179-mdadm-tests-07changelevels-fix.patch new file mode 100644 index 0000000..68805a4 --- /dev/null +++ b/0179-mdadm-tests-07changelevels-fix.patch @@ -0,0 +1,179 @@ +From f5b2dddd258084836634e169c84400e82825996c Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:28 +0800 +Subject: [PATCH 179/201] mdadm/tests: 07changelevels fix + +There are five changes to this case. + +1. remove testdev check. It can't work anymore and check if it's a +block device directly. + +2. It can't change level and chunk size at the same time + +3. Sleep more than 10s before check wait. +The test devices are small. Sometimes it can finish so quickly once +the reshape just starts. mdadm will be stuck before it waits reshape +to start. So the sync speed is limited. And it restores the sync speed +when it waits reshape to finish. It's good for case without backup +file. + +It uses systemd service mdadm-grow-continue to monitor reshape +progress when specifying backup file. If reshape finishes so quickly +before it starts monitoring reshape progress, the daemon will be stuck +too. Because reshape_progress is 0 which means the reshape hasn't been +started. So give more time to let service can get right information +from kernel space. + +But before getting these information. It needs to suspend array. At +the same time the reshape is running. The kernel reshape daemon will +update metadata 10s. So it needs to limit the sync speed more than 10s +before restoring sync speed. Then systemd service can suspend array +and start monitoring reshape progress. + +4. Wait until mdadm-grow-continue service exits +mdadm --wait doesn't wait systemd service. For the case that needs +backup file, systemd service deletes the backup file after reshape +finishes. In this test case, it runs next case when reshape finishes. +And it fails because it can't create backup file because the backup +file exits. + +5. Don't reshape from raid5 to raid1. It can't work now. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + dev/null | 0 + tests/07changelevels | 27 ++++++++++++--------------- + tests/07changelevels.broken | 9 --------- + tests/func.sh | 4 ++++ + 4 files changed, 16 insertions(+), 24 deletions(-) + create mode 100644 dev/null + delete mode 100644 tests/07changelevels.broken + +diff --git a/dev/null b/dev/null +new file mode 100644 +index 00000000..e69de29b +diff --git a/tests/07changelevels b/tests/07changelevels +index a328874a..3df8660e 100644 +--- a/tests/07changelevels ++++ b/tests/07changelevels +@@ -10,7 +10,6 @@ export MDADM_GROW_VERIFY=1 + dotest() { + sleep 2 + check wait +- testdev $md0 $1 19968 64 nd + blockdev --flushbufs $md0 + cmp -s -n $[textK*1024] $md0 /tmp/RandFile || { echo cmp failed; exit 2; } + # write something new - shift chars 4 space +@@ -24,7 +23,7 @@ checkgeo() { + # level raid_disks chunk_size layout + dev=$1 + shift +- sleep 0.5 ++ sleep 15 + check wait + sleep 1 + for attr in level raid_disks chunk_size layout +@@ -43,22 +42,25 @@ checkgeo() { + + bu=/tmp/md-test-backup + rm -f $bu +-mdadm -CR $md0 -l1 -n2 -x1 $dev0 $dev1 $dev2 -z 19968 +-testdev $md0 1 $mdsize1a 64 ++mdadm -CR $md0 -l1 -n2 -x1 $dev0 $dev1 $dev2 ++[ -b $md0 ] || die "$1 isn't a block device." + dd if=/tmp/RandFile of=$md0 + dotest 1 + +-mdadm --grow $md0 -l5 -n3 --chunk 64 ++mdadm --grow $md0 -l5 -n3 ++checkgeo md0 raid5 3 + dotest 2 + + mdadm $md0 --add $dev3 $dev4 + mdadm --grow $md0 -n4 --chunk 32 ++checkgeo md0 raid5 4 $[32*1024] + dotest 3 + + mdadm -G $md0 -l6 --backup-file $bu ++checkgeo md0 raid6 5 $[32*1024] + dotest 3 + +-mdadm -G /dev/md0 --array-size 39936 ++mdadm -G /dev/md0 --array-size 37888 + mdadm -G $md0 -n4 --backup-file $bu + checkgeo md0 raid6 4 $[32*1024] + dotest 2 +@@ -67,14 +69,11 @@ mdadm -G $md0 -l5 --backup-file $bu + checkgeo md0 raid5 3 $[32*1024] + dotest 2 + +-mdadm -G /dev/md0 --array-size 19968 ++mdadm -G /dev/md0 --array-size 18944 + mdadm -G $md0 -n2 --backup-file $bu + checkgeo md0 raid5 2 $[32*1024] + dotest 1 + +-mdadm -G --level=1 $md0 +-dotest 1 +- + # now repeat that last few steps only with a degraded array. + mdadm -S $md0 + mdadm -CR $md0 -l6 -n5 $dev0 $dev1 $dev2 $dev3 $dev4 +@@ -83,7 +82,7 @@ dotest 3 + + mdadm $md0 --fail $dev0 + +-mdadm -G /dev/md0 --array-size 37888 ++mdadm -G /dev/md0 --array-size 35840 + mdadm -G $md0 -n4 --backup-file $bu + dotest 2 + checkgeo md0 raid6 4 $[512*1024] +@@ -103,12 +102,10 @@ dotest 2 + mdadm -G $md0 -l5 --backup-file $bu + dotest 2 + +-mdadm -G /dev/md0 --array-size 18944 ++mdadm -G /dev/md0 --array-size 17920 + mdadm -G $md0 -n2 --backup-file $bu + dotest 1 + checkgeo md0 raid5 2 $[512*1024] + mdadm $md0 --fail $dev2 + +-mdadm -G --level=1 $md0 +-dotest 1 +-checkgeo md0 raid1 2 ++mdadm -S $md0 +diff --git a/tests/07changelevels.broken b/tests/07changelevels.broken +deleted file mode 100644 +index 9b930d93..00000000 +--- a/tests/07changelevels.broken ++++ /dev/null +@@ -1,9 +0,0 @@ +-always fails +- +-Fails with errors: +- +- mdadm: /dev/loop0 is smaller than given size. 18976K < 19968K + metadata +- mdadm: /dev/loop1 is smaller than given size. 18976K < 19968K + metadata +- mdadm: /dev/loop2 is smaller than given size. 18976K < 19968K + metadata +- +- ERROR: /dev/md0 isn't a block device. +diff --git a/tests/func.sh b/tests/func.sh +index e7ccc4fc..567d91d9 100644 +--- a/tests/func.sh ++++ b/tests/func.sh +@@ -362,6 +362,10 @@ check() { + do + sleep 0.5 + done ++ while ps auxf | grep "mdadm --grow --continue" | grep -v grep ++ do ++ sleep 1 ++ done + echo $min > /proc/sys/dev/raid/speed_limit_min + echo $max > /proc/sys/dev/raid/speed_limit_max + ;; +-- +2.41.0 + diff --git a/0180-mdadm-tests-Remove-07reshape5intr.broken.patch b/0180-mdadm-tests-Remove-07reshape5intr.broken.patch new file mode 100644 index 0000000..901ac9f --- /dev/null +++ b/0180-mdadm-tests-Remove-07reshape5intr.broken.patch @@ -0,0 +1,68 @@ +From 01f5aefd830d6ad5357de4d6f5ce139b415a62b9 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:29 +0800 +Subject: [PATCH 180/201] mdadm/tests: Remove 07reshape5intr.broken + +07reshape5intr can run successfully now. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/07reshape5intr.broken | 45 ------------------------------------- + 1 file changed, 45 deletions(-) + delete mode 100644 tests/07reshape5intr.broken + +diff --git a/tests/07reshape5intr.broken b/tests/07reshape5intr.broken +deleted file mode 100644 +index efe52a66..00000000 +--- a/tests/07reshape5intr.broken ++++ /dev/null +@@ -1,45 +0,0 @@ +-always fails +- +-This patch, recently added to md-next causes the test to always fail: +- +-7e6ba434cc60 ("md: don't unregister sync_thread with reconfig_mutex +-held") +- +-The new error is simply: +- +- ERROR: no reshape happening +- +-Before the patch, the error seen is below. +- +--- +- +-fails infrequently +- +-Fails roughly 1 in 4 runs with errors: +- +- mdadm: Merging with already-assembled /dev/md/0 +- mdadm: cannot re-read metadata from /dev/loop6 - aborting +- +- ERROR: no reshape happening +- +-Also have seen a random deadlock: +- +- INFO: task mdadm:109702 blocked for more than 30 seconds. +- Not tainted 5.18.0-rc3-eid-vmlocalyes-dbg-00095-g3c2b5427979d #2040 +- "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +- task:mdadm state:D stack: 0 pid:109702 ppid: 1 flags:0x00004000 +- Call Trace: +- +- __schedule+0x67e/0x13b0 +- schedule+0x82/0x110 +- mddev_suspend+0x2e1/0x330 +- suspend_lo_store+0xbd/0x140 +- md_attr_store+0xcb/0x130 +- sysfs_kf_write+0x89/0xb0 +- kernfs_fop_write_iter+0x202/0x2c0 +- new_sync_write+0x222/0x330 +- vfs_write+0x3bc/0x4d0 +- ksys_write+0xd9/0x180 +- __x64_sys_write+0x43/0x50 +- do_syscall_64+0x3b/0x90 +- entry_SYSCALL_64_after_hwframe+0x44/0xae +-- +2.41.0 + diff --git a/0181-mdadm-tests-07testreshape5-fix.patch b/0181-mdadm-tests-07testreshape5-fix.patch new file mode 100644 index 0000000..fb4e2c4 --- /dev/null +++ b/0181-mdadm-tests-07testreshape5-fix.patch @@ -0,0 +1,48 @@ +From fe3e4809476ab4e2e0e905e36f6bb1a45c16a2c3 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:30 +0800 +Subject: [PATCH 181/201] mdadm/tests: 07testreshape5 fix + +Init dir to avoid test failure. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/07testreshape5 | 1 + + tests/07testreshape5.broken | 12 ------------ + 2 files changed, 1 insertion(+), 12 deletions(-) + delete mode 100644 tests/07testreshape5.broken + +diff --git a/tests/07testreshape5 b/tests/07testreshape5 +index 0e1f25f9..d90fd15e 100644 +--- a/tests/07testreshape5 ++++ b/tests/07testreshape5 +@@ -4,6 +4,7 @@ + # kernel md code to move data into and out of variously + # shaped md arrays. + set -x ++dir="." + layouts=(la ra ls rs) + for level in 5 6 + do +diff --git a/tests/07testreshape5.broken b/tests/07testreshape5.broken +deleted file mode 100644 +index a8ce03e4..00000000 +--- a/tests/07testreshape5.broken ++++ /dev/null +@@ -1,12 +0,0 @@ +-always fails +- +-Test seems to run 'test_stripe' at $dir directory, but $dir is never +-set. If $dir is adjusted to $PWD, the test still fails with: +- +- mdadm: /dev/loop2 is not suitable for this array. +- mdadm: create aborted +- ++ return 1 +- ++ cmp -s -n 8192 /dev/md0 /tmp/RandFile +- ++ echo cmp failed +- cmp failed +- ++ exit 2 +-- +2.41.0 + diff --git a/0182-mdadm-tests-remove-09imsm-assemble.broken.patch b/0182-mdadm-tests-remove-09imsm-assemble.broken.patch new file mode 100644 index 0000000..1ded516 --- /dev/null +++ b/0182-mdadm-tests-remove-09imsm-assemble.broken.patch @@ -0,0 +1,29 @@ +From 5cafbc8b3a7f352be80c5dc22d59d26b06f57680 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:31 +0800 +Subject: [PATCH 182/201] mdadm/tests: remove 09imsm-assemble.broken + +09imsm-assemble can run successfully. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + tests/09imsm-assemble.broken | 6 ------ + 1 file changed, 6 deletions(-) + delete mode 100644 tests/09imsm-assemble.broken + +diff --git a/tests/09imsm-assemble.broken b/tests/09imsm-assemble.broken +deleted file mode 100644 +index a6d4d5cf..00000000 +--- a/tests/09imsm-assemble.broken ++++ /dev/null +@@ -1,6 +0,0 @@ +-fails infrequently +- +-Fails roughly 1 in 10 runs with errors: +- +- mdadm: /dev/loop2 is still in use, cannot remove. +- /dev/loop2 removal from /dev/md/container should have succeeded +-- +2.41.0 + diff --git a/0183-mdadm-Manage-record-errno.patch b/0183-mdadm-Manage-record-errno.patch new file mode 100644 index 0000000..f37f629 --- /dev/null +++ b/0183-mdadm-Manage-record-errno.patch @@ -0,0 +1,56 @@ +From e3c3cfb64b8ec8b616e2eefbc69fbc3de29b64b6 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Wed, 11 Sep 2024 16:54:32 +0800 +Subject: [PATCH 183/201] mdadm/Manage: record errno + +Sometimes it reports: +mdadm: failed to stop array /dev/md0: Success +It's the reason the errno is reset. So record errno during the loop. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Manage.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/Manage.c b/Manage.c +index 241de055..aba97df8 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -238,13 +238,14 @@ int Manage_stop(char *devname, int fd, int verbose, int will_retry) + "array_state", + "inactive")) < 0 && + errno == EBUSY) { ++ err = errno; + sleep_for(0, MSEC_TO_NSEC(200), true); + count--; + } + if (err) { + if (verbose >= 0) + pr_err("failed to stop array %s: %s\n", +- devname, strerror(errno)); ++ devname, strerror(err)); + rv = 1; + goto out; + } +@@ -438,14 +439,15 @@ done: + count = 25; err = 0; + while (count && fd >= 0 && + (err = ioctl(fd, STOP_ARRAY, NULL)) < 0 && errno == EBUSY) { ++ err = errno; + sleep_for(0, MSEC_TO_NSEC(200), true); + count --; + } + if (fd >= 0 && err) { + if (verbose >= 0) { + pr_err("failed to stop array %s: %s\n", +- devname, strerror(errno)); +- if (errno == EBUSY) ++ devname, strerror(err)); ++ if (err == EBUSY) + cont_err("Perhaps a running process, mounted filesystem or active volume group?\n"); + } + rv = 1; +-- +2.41.0 + diff --git a/0184-Remove-INSTALL-and-dev-null.patch b/0184-Remove-INSTALL-and-dev-null.patch new file mode 100644 index 0000000..551bd64 --- /dev/null +++ b/0184-Remove-INSTALL-and-dev-null.patch @@ -0,0 +1,43 @@ +From 2c2a9d63d07102e54608ad7691072ebbed0f8be8 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 23 Sep 2024 11:12:53 +0200 +Subject: [PATCH 184/201] Remove INSTALL and dev/null + +INSTALL is not needed because it added to README.md +dev/null was created accidentally. + +Remove them. + +Signed-off-by: Mariusz Tkaczyk +--- + INSTALL | 13 ------------- + dev/null | 0 + 2 files changed, 13 deletions(-) + delete mode 100644 INSTALL + delete mode 100644 dev/null + +diff --git a/INSTALL b/INSTALL +deleted file mode 100644 +index f7bcc3e6..00000000 +--- a/INSTALL ++++ /dev/null +@@ -1,13 +0,0 @@ +- +-To build mdadm, simply run: +- +- make +- +-to install, run +- +- make install +- +-as root. +- +- +-No configuration is necessary. +diff --git a/dev/null b/dev/null +deleted file mode 100644 +index e69de29b..00000000 +-- +2.41.0 + diff --git a/0186-Incremental-Rename-IncrementalRemove.patch b/0186-Incremental-Rename-IncrementalRemove.patch new file mode 100644 index 0000000..0aa8bef --- /dev/null +++ b/0186-Incremental-Rename-IncrementalRemove.patch @@ -0,0 +1,67 @@ +From 60923d5cae78447902e9ec10c44504e0588cf447 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Mon, 23 Sep 2024 14:15:31 +0200 +Subject: [PATCH 186/201] Incremental: Rename IncrementalRemove + +Rename it to Incremental_remove for better readability. +No functional changes. + +Signed-off-by: Mariusz Tkaczyk +--- + Incremental.c | 4 ++-- + mdadm.c | 3 +-- + mdadm.h | 2 +- + 3 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/Incremental.c b/Incremental.c +index c1389a15..e7987d1d 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -1695,7 +1695,7 @@ static bool is_devnode_path(char *devnode) + } + + /** +- * IncrementalRemove() - Remove the device from all raid arrays. ++ * Incremental_remove() - Remove the device from all raid arrays. + * @devname: the device we want to remove, it could be kernel device name or devnode. + * @id_path: optional, /dev/disk/by-path path to save for bare scenarios support. + * @verbose: verbose flag. +@@ -1703,7 +1703,7 @@ static bool is_devnode_path(char *devnode) + * First, fail the device (if needed) and then remove the device from native raid array or external + * container. If it is external container, the device is removed from each subarray first. + */ +-int IncrementalRemove(char *devname, char *id_path, int verbose) ++int Incremental_remove(char *devname, char *id_path, int verbose) + { + char *devnm = basename(devname); + struct mddev_dev devlist = {0}; +diff --git a/mdadm.c b/mdadm.c +index 0b99fad4..90fd1575 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -1703,8 +1703,7 @@ int main(int argc, char *argv[]) + rv = 1; + break; + } +- rv = IncrementalRemove(devlist->devname, remove_path, +- c.verbose); ++ rv = Incremental_remove(devlist->devname, remove_path, c.verbose); + } else + rv = Incremental(devlist, &c, ss); + break; +diff --git a/mdadm.h b/mdadm.h +index f3b9f54c..d4f5702c 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1606,7 +1606,7 @@ extern int Incremental(struct mddev_dev *devlist, struct context *c, + struct supertype *st); + extern void RebuildMap(void); + extern int IncrementalScan(struct context *c, char *devnm); +-extern int IncrementalRemove(char *devname, char *path, int verbose); ++extern int Incremental_remove(char *devname, char *path, int verbose); + extern int CreateBitmap(char *filename, int force, char uuid[16], + unsigned long chunksize, unsigned long daemon_sleep, + unsigned long write_behind, +-- +2.41.0 + diff --git a/0187-sysfs-add-function-for-writing-to-sysfs-fd.patch b/0187-sysfs-add-function-for-writing-to-sysfs-fd.patch new file mode 100644 index 0000000..7740007 --- /dev/null +++ b/0187-sysfs-add-function-for-writing-to-sysfs-fd.patch @@ -0,0 +1,315 @@ +From d95edceb362a6b647ec454c2a83add11c4ed4e64 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 24 Sep 2024 15:53:18 +0200 +Subject: [PATCH 187/201] sysfs: add function for writing to sysfs fd + +Proposed function sysfs_wrte_descriptor() unifies error handling for +write() done to sysfs files. Main purpose is to use it with MD sysfs +file but it can be used elsewhere. + +No functional changes. + +Signed-off-by: Mariusz Tkaczyk +--- + Manage.c | 45 +++++++++++++++++++++---------------- + managemon.c | 13 +++-------- + mdadm.h | 3 +++ + monitor.c | 12 ++-------- + sysfs.c | 65 +++++++++++++++++++++++++++++++++++++++++++---------- + util.c | 19 +++++++++++----- + 6 files changed, 101 insertions(+), 56 deletions(-) + +diff --git a/Manage.c b/Manage.c +index aba97df8..0f232a57 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -1439,7 +1439,7 @@ int Manage_subdevs(char *devname, int fd, + + for (dv = devlist; dv; dv = dv->next) { + dev_t rdev = 0; /* device to add/remove etc */ +- int rv; ++ int rv, err = 0; + int mj,mn; + + raid_slot = -1; +@@ -1670,9 +1670,8 @@ int Manage_subdevs(char *devname, int fd, + rv = Manage_remove(tst, fd, dv, sysfd, + rdev, verbose, force, + devname); +- if (sysfd >= 0) +- close_fd(&sysfd); +- sysfd = -1; ++ close_fd(&sysfd); ++ + if (rv < 0) + goto abort; + if (rv > 0) +@@ -1686,23 +1685,31 @@ int Manage_subdevs(char *devname, int fd, + close_fd(&sysfd); + goto abort; + } +- case 'I': /* incremental fail */ +- if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) || +- (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY, +- rdev))) { +- if (errno == EBUSY) +- busy = 1; +- pr_err("set device faulty failed for %s: %s\n", +- dv->devname, strerror(errno)); +- close_fd(&sysfd); +- goto abort; ++ case 'I': ++ if (is_fd_valid(sysfd)) { ++ static const char val[] = "faulty"; ++ ++ rv = sysfs_write_descriptor(sysfd, val, strlen(val), &err); ++ } else { ++ rv = ioctl(fd, SET_DISK_FAULTY, rdev); ++ if (rv) ++ err = errno; + } ++ + close_fd(&sysfd); +- count++; +- if (verbose >= 0) +- pr_err("set %s faulty in %s\n", +- dv->devname, devname); +- break; ++ ++ if (rv == MDADM_STATUS_SUCCESS) { ++ count++; ++ ++ pr_vrb("set %s faulty in %s\n", dv->devname, devname); ++ break; ++ } ++ ++ if (err == EBUSY) ++ busy = 1; ++ ++ pr_err("set device faulty failed for %s: %s\n", dv->devname, strerror(err)); ++ goto abort; + case 'R': /* Mark as replaceable */ + if (subarray) { + pr_err("Cannot replace disks in a \'member\' array, perform this operation on the parent container\n"); +diff --git a/managemon.c b/managemon.c +index add6a79e..877e8605 100644 +--- a/managemon.c ++++ b/managemon.c +@@ -512,16 +512,9 @@ static void manage_member(struct mdstat_ent *mdstat, + if (a->container == NULL) + return; + +- if (sigterm && a->info.safe_mode_delay != 1 && +- a->safe_mode_delay_fd >= 0) { +- long int new_delay = 1; +- char delay[10]; +- ssize_t len; +- +- len = snprintf(delay, sizeof(delay), "0.%03ld\n", new_delay); +- if (write(a->safe_mode_delay_fd, delay, len) == len) +- a->info.safe_mode_delay = new_delay; +- } ++ if (sigterm && a->info.safe_mode_delay != 1 && a->safe_mode_delay_fd >= 0) ++ if (write_attr("0.001", a->safe_mode_delay_fd) == MDADM_STATUS_SUCCESS) ++ a->info.safe_mode_delay = 1; + + /* We don't check the array while any update is pending, as it + * might container a change (such as a spare assignment) which +diff --git a/mdadm.h b/mdadm.h +index d4f5702c..ce8155b5 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -803,6 +803,9 @@ enum sysfs_read_flags { + + #define SYSFS_MAX_BUF_SIZE 64 + ++extern mdadm_status_t sysfs_write_descriptor(const int fd, const char *value, ++ const ssize_t len, int *errno_p); ++extern mdadm_status_t write_attr(const char *value, const int fd); + extern void sysfs_get_container_devnm(struct mdinfo *mdi, char *buf); + + /* If fd >= 0, get the array it is open on, +diff --git a/monitor.c b/monitor.c +index be0bec78..a4f707cc 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -35,11 +35,6 @@ enum bb_action { + COMPARE_BB, + }; + +-static int write_attr(char *attr, int fd) +-{ +- return write(fd, attr, strlen(attr)); +-} +- + static void add_fd(fd_set *fds, int *maxfd, int fd) + { + struct stat st; +@@ -173,7 +168,7 @@ int process_ubb(struct active_array *a, struct mdinfo *mdi, const unsigned long + * via sysfs file + */ + if ((ss->record_bad_block(a, mdi->disk.raid_disk, sector, length)) && +- (write(mdi->bb_fd, buf, buf_len) == buf_len)) ++ (sysfs_write_descriptor(mdi->bb_fd, buf, buf_len, NULL) == MDADM_STATUS_SUCCESS)) + return 1; + + /* +@@ -622,14 +617,11 @@ static int read_and_act(struct active_array *a, fd_set *fds) + } + + if ((mdi->next_state & DS_REMOVE) && mdi->state_fd >= 0) { +- int remove_result; +- + /* The kernel may not be able to immediately remove the + * disk. In that case we wait a little while and + * try again. + */ +- remove_result = write_attr("remove", mdi->state_fd); +- if (remove_result > 0) { ++ if (write_attr("remove", mdi->state_fd) == MDADM_STATUS_SUCCESS) { + dprintf_cont(" %d:removed", mdi->disk.raid_disk); + close(mdi->state_fd); + close(mdi->recovery_fd); +diff --git a/sysfs.c b/sysfs.c +index b3c8b10d..7a81cc5b 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -73,6 +73,47 @@ void sysfs_free(struct mdinfo *sra) + sra = sra2; + } + } ++/** ++ * write_attr() - write value to fd, don't check errno. ++ * @attr: value to write. ++ * @fd: file descriptor write to. ++ * ++ * Size to write is calculated by strlen(). ++ */ ++mdadm_status_t write_attr(const char *value, const int fd) ++{ ++ return sysfs_write_descriptor(fd, value, strlen(value), NULL); ++} ++ ++/** ++ * sysfs_write_descriptor()- wrapper for write(), projected to be used with sysfs. ++ * @fd: file descriptor. ++ * @value: value to set. ++ * @len: length of the value. ++ * @errno_p: On write() failure, buffer to copy errno value, might be NULL. ++ * ++ * Errors are differentiated, because (at least theoretically) kernel may not process whole string ++ * and it may or may not be a problem (it depends on implementation in kernel). Decision belongs to ++ * caller then. ++ * Generally, it should be safe to check if @errno_p changed to determine if error occurred. ++ */ ++mdadm_status_t sysfs_write_descriptor(const int fd, const char *value, const ssize_t len, ++ int *errno_p) ++{ ++ ssize_t ret; ++ ++ ret = write(fd, value, len); ++ if (ret == -1) { ++ if (errno_p) ++ *errno_p = errno; ++ return MDADM_STATUS_ERROR; ++ } ++ ++ if (ret != len) ++ return MDADM_STATUS_UNDEF; ++ ++ return MDADM_STATUS_SUCCESS; ++} + + /** + * sysfs_get_container_devnm() - extract container device name. +@@ -486,7 +527,6 @@ int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev, + char *name, char *val) + { + char fname[MAX_SYSFS_PATH_LEN]; +- unsigned int n; + int fd; + + snprintf(fname, MAX_SYSFS_PATH_LEN, "/sys/block/%s/md/%s/%s", +@@ -494,13 +534,14 @@ int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev, + fd = open(fname, O_WRONLY); + if (fd < 0) + return -1; +- n = write(fd, val, strlen(val)); +- close(fd); +- if (n != strlen(val)) { +- dprintf("failed to write '%s' to '%s' (%s)\n", +- val, fname, strerror(errno)); ++ ++ if (write_attr(val, fd)) { ++ pr_err("failed to write '%s' to '%s' (%s)\n", val, fname, strerror(errno)); ++ close(fd); + return -1; + } ++ ++ close(fd); + return 0; + } + +@@ -523,7 +564,6 @@ int sysfs_set_num_signed(struct mdinfo *sra, struct mdinfo *dev, + int sysfs_uevent(struct mdinfo *sra, char *event) + { + char fname[MAX_SYSFS_PATH_LEN]; +- int n; + int fd; + + snprintf(fname, MAX_SYSFS_PATH_LEN, "/sys/block/%s/uevent", +@@ -531,13 +571,14 @@ int sysfs_uevent(struct mdinfo *sra, char *event) + fd = open(fname, O_WRONLY); + if (fd < 0) + return -1; +- n = write(fd, event, strlen(event)); +- close(fd); +- if (n != (int)strlen(event)) { +- dprintf("failed to write '%s' to '%s' (%s)\n", +- event, fname, strerror(errno)); ++ ++ if (write_attr(event, fd)) { ++ pr_err("failed to write '%s' to '%s' (%s)\n", event, fname, strerror(errno)); ++ close(fd); + return -1; + } ++ ++ close(fd); + return 0; + } + +diff --git a/util.c b/util.c +index cc162278..2b660725 100644 +--- a/util.c ++++ b/util.c +@@ -1854,13 +1854,22 @@ int hot_remove_disk(int mdfd, unsigned long dev, int force) + int sys_hot_remove_disk(int statefd, int force) + { + int cnt = force ? 500 : 5; +- int ret; ++ static const char val[] = "faulty"; ++ ++ while (cnt--) { ++ int err = 0; ++ int ret = sysfs_write_descriptor(statefd, val, strlen(val), &err); ++ ++ if (ret == MDADM_STATUS_SUCCESS) ++ return 0; ++ ++ if (err != EBUSY) ++ break; + +- while ((ret = write(statefd, "remove", 6)) == -1 && +- errno == EBUSY && +- cnt-- > 0) + sleep_for(0, MSEC_TO_NSEC(10), true); +- return ret == 6 ? 0 : -1; ++ } ++ ++ return -1; + } + + int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info) +-- +2.41.0 + diff --git a/0188-Mdmonitor-Fix-startup-with-missing-directory.patch b/0188-Mdmonitor-Fix-startup-with-missing-directory.patch new file mode 100644 index 0000000..4cc9e5e --- /dev/null +++ b/0188-Mdmonitor-Fix-startup-with-missing-directory.patch @@ -0,0 +1,61 @@ +From 344690313ae4e66f760b14afafda663ec750dfe0 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Tue, 3 Sep 2024 13:01:04 +0200 +Subject: [PATCH 188/201] Mdmonitor: Fix startup with missing directory + +Commit 0a07dea8d3b78 ("Mdmonitor: Refactor check_one_sharer() for +better error handling") introduced an issue, if directory /run/mdadm +is missing, monitor fails to start. Move the directory creation +earlier to ensure it is always created. + +Signed-off-by: Anna Sztukowska +--- + Monitor.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/Monitor.c b/Monitor.c +index cf14fbb3..d260b0f1 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -225,6 +225,11 @@ int Monitor(struct mddev_dev *devlist, + return 1; + } + ++ if (mkdir(MDMON_DIR, 0700) < 0 && errno != EEXIST) { ++ pr_err("Failed to create directory " MDMON_DIR ": %s\n", strerror(errno)); ++ return 1; ++ } ++ + if (share){ + if (check_one_sharer(c->scan) == 2) + return 1; +@@ -432,12 +437,12 @@ static int make_daemon(char *pidfile) + } + + /* +- * check_one_sharer() - Checks for other mdmon processes running. ++ * check_one_sharer() - Checks for other mdmonitor processes running. + * + * Return: + * 0 - no other processes running, + * 1 - warning, +- * 2 - error, or when scan mode is enabled, and one mdmon process already exists ++ * 2 - error, or when scan mode is enabled, and one mdmonitor process already exists + */ + static int check_one_sharer(int scan) + { +@@ -513,11 +518,6 @@ static int write_autorebuild_pid(void) + FILE *fp; + int fd; + +- if (mkdir(MDMON_DIR, 0700) < 0 && errno != EEXIST) { +- pr_err("%s: %s\n", strerror(errno), MDMON_DIR); +- return 1; +- } +- + if (!is_directory(MDMON_DIR)) { + pr_err("%s is not a regular directory.\n", MDMON_DIR); + return 1; +-- +2.41.0 + diff --git a/0189-mdadm-add-xmalloc.h.patch b/0189-mdadm-add-xmalloc.h.patch new file mode 100644 index 0000000..c0b8ca1 --- /dev/null +++ b/0189-mdadm-add-xmalloc.h.patch @@ -0,0 +1,590 @@ +From ee3a6cab09c8acaf6706b3710f5652e9be43b57e Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Wed, 25 Sep 2024 13:16:10 +0200 +Subject: [PATCH 189/201] mdadm: add xmalloc.h + +Move memory declaration helpers outside mdadm.h. They seems to be +useful so keep them but include separatelly. Rework them to not reffer +to Name[] declared internally in mdadm/mdmon. + +This is first step to start decomplexing mdadm.h. + +Signed-off-by: Mariusz Tkaczyk +--- + Assemble.c | 2 ++ + Create.c | 4 +++- + Detail.c | 2 ++ + Examine.c | 8 ++++--- + Grow.c | 2 ++ + Incremental.c | 2 ++ + Manage.c | 2 ++ + Monitor.c | 4 +++- + bitmap.c | 1 + + config.c | 2 ++ + lib.c | 2 ++ + managemon.c | 2 ++ + mapfile.c | 2 ++ + mdadm.c | 2 ++ + mdadm.h | 5 ---- + mdmon.c | 1 + + mdopen.c | 2 ++ + mdstat.c | 2 ++ + msg.c | 1 + + platform-intel.c | 2 ++ + policy.c | 2 ++ + restripe.c | 2 ++ + super-ddf.c | 2 ++ + super-gpt.c | 1 + + super-intel.c | 2 ++ + super-mbr.c | 1 + + super0.c | 2 ++ + super1.c | 2 ++ + sysfs.c | 4 +++- + udev.c | 2 ++ + util.c | 2 ++ + xmalloc.c | 59 +++++++++++++++++++++--------------------------- + xmalloc.h | 13 +++++++++++ + 33 files changed, 100 insertions(+), 44 deletions(-) + create mode 100644 xmalloc.h + +diff --git a/Assemble.c b/Assemble.c +index a2bb7b64..d3dbfbc6 100644 +--- a/Assemble.c ++++ b/Assemble.c +@@ -23,6 +23,8 @@ + */ + + #include "mdadm.h" ++#include "xmalloc.h" ++ + #include + + mapping_t assemble_statuses[] = { +diff --git a/Create.c b/Create.c +index 7fde1c16..1640f21e 100644 +--- a/Create.c ++++ b/Create.c +@@ -23,9 +23,11 @@ + */ + + #include "mdadm.h" +-#include "udev.h" + #include "md_u.h" + #include "md_p.h" ++#include "udev.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/Detail.c b/Detail.c +index 331e1da3..5819ced9 100644 +--- a/Detail.c ++++ b/Detail.c +@@ -25,6 +25,8 @@ + #include "mdadm.h" + #include "md_p.h" + #include "md_u.h" ++#include "xmalloc.h" ++ + #include + #include + +diff --git a/Examine.c b/Examine.c +index fe162167..036b7a56 100644 +--- a/Examine.c ++++ b/Examine.c +@@ -22,14 +22,16 @@ + * Email: + */ + +-#include "mdadm.h" + #include "dlink.h" ++#include "mdadm.h" ++#include "md_u.h" ++#include "md_p.h" ++#include "xmalloc.h" + + #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN) + #error no endian defined + #endif +-#include "md_u.h" +-#include "md_p.h" ++ + int Examine(struct mddev_dev *devlist, + struct context *c, + struct supertype *forcest) +diff --git a/Grow.c b/Grow.c +index 60076f56..ef1285ec 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -23,6 +23,8 @@ + */ + #include "mdadm.h" + #include "dlink.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/Incremental.c b/Incremental.c +index e7987d1d..8c915783 100644 +--- a/Incremental.c ++++ b/Incremental.c +@@ -29,6 +29,8 @@ + */ + + #include "mdadm.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/Manage.c b/Manage.c +index 0f232a57..246ef319 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -26,6 +26,8 @@ + #include "md_u.h" + #include "md_p.h" + #include "udev.h" ++#include "xmalloc.h" ++ + #include + + int Manage_ro(char *devname, int fd, int readonly) +diff --git a/Monitor.c b/Monitor.c +index d260b0f1..d1cfbf94 100644 +--- a/Monitor.c ++++ b/Monitor.c +@@ -23,9 +23,11 @@ + */ + + #include "mdadm.h" +-#include "udev.h" + #include "md_p.h" + #include "md_u.h" ++#include "udev.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/bitmap.c b/bitmap.c +index 9a7ffe3b..5110ae2f 100644 +--- a/bitmap.c ++++ b/bitmap.c +@@ -19,6 +19,7 @@ + */ + + #include "mdadm.h" ++#include "xmalloc.h" + + static inline void sb_le_to_cpu(bitmap_super_t *sb) + { +diff --git a/config.c b/config.c +index 5411a480..022fb2a0 100644 +--- a/config.c ++++ b/config.c +@@ -24,6 +24,8 @@ + + #include "mdadm.h" + #include "dlink.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/lib.c b/lib.c +index 13d4e4f1..f36ae03a 100644 +--- a/lib.c ++++ b/lib.c +@@ -24,6 +24,8 @@ + + #include "mdadm.h" + #include "dlink.h" ++#include "xmalloc.h" ++ + #include + #include + +diff --git a/managemon.c b/managemon.c +index 877e8605..6ca592b1 100644 +--- a/managemon.c ++++ b/managemon.c +@@ -104,6 +104,8 @@ + #endif + #include "mdadm.h" + #include "mdmon.h" ++#include "xmalloc.h" ++ + #include + #include + +diff --git a/mapfile.c b/mapfile.c +index 632cf5e8..33d40d9e 100644 +--- a/mapfile.c ++++ b/mapfile.c +@@ -43,6 +43,8 @@ + * at compile time via MAP_DIR and MAP_FILE. + */ + #include "mdadm.h" ++#include "xmalloc.h" ++ + #include + #include + +diff --git a/mdadm.c b/mdadm.c +index 90fd1575..de7cde07 100644 +--- a/mdadm.c ++++ b/mdadm.c +@@ -27,6 +27,8 @@ + + #include "mdadm.h" + #include "md_p.h" ++#include "xmalloc.h" ++ + #include + + /** +diff --git a/mdadm.h b/mdadm.h +index ce8155b5..bbc1b97f 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -1937,11 +1937,6 @@ static inline int xasprintf(char **strp, const char *fmt, ...) { + + #define pr_vrb(fmt, arg...) ((void)(verbose && pr_err(fmt, ##arg))) + +-void *xmalloc(size_t len); +-void *xrealloc(void *ptr, size_t len); +-void *xcalloc(size_t num, size_t size); +-char *xstrdup(const char *str); +- + #define LEVEL_MULTIPATH (-4) + #define LEVEL_LINEAR (-1) + #define LEVEL_FAULTY (-5) +diff --git a/mdmon.c b/mdmon.c +index 6e28b56e..a16647c6 100644 +--- a/mdmon.c ++++ b/mdmon.c +@@ -65,6 +65,7 @@ + + #include "mdadm.h" + #include "mdmon.h" ++#include "xmalloc.h" + + char const Name[] = "mdmon"; + +diff --git a/mdopen.c b/mdopen.c +index e49defb6..8587524b 100644 +--- a/mdopen.c ++++ b/mdopen.c +@@ -25,6 +25,8 @@ + #include "mdadm.h" + #include "udev.h" + #include "md_p.h" ++#include "xmalloc.h" ++ + #include + + void make_parts(char *dev, int cnt) +diff --git a/mdstat.c b/mdstat.c +index 29e78362..8d97a2fc 100644 +--- a/mdstat.c ++++ b/mdstat.c +@@ -80,6 +80,8 @@ + + #include "mdadm.h" + #include "dlink.h" ++#include "xmalloc.h" ++ + #include + #include + +diff --git a/msg.c b/msg.c +index b6da91d3..0cc7fc5d 100644 +--- a/msg.c ++++ b/msg.c +@@ -30,6 +30,7 @@ + #include + #include "mdadm.h" + #include "mdmon.h" ++#include "xmalloc.h" + + static const __u32 start_magic = 0x5a5aa5a5; + static const __u32 end_magic = 0xa5a55a5a; +diff --git a/platform-intel.c b/platform-intel.c +index 21591317..95bc4929 100644 +--- a/platform-intel.c ++++ b/platform-intel.c +@@ -19,6 +19,8 @@ + #include "mdadm.h" + #include "platform-intel.h" + #include "probe_roms.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/policy.c b/policy.c +index 4d4b248d..f417a9af 100644 +--- a/policy.c ++++ b/policy.c +@@ -23,6 +23,8 @@ + */ + + #include "mdadm.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/restripe.c b/restripe.c +index a7a7229f..5e126eb7 100644 +--- a/restripe.c ++++ b/restripe.c +@@ -23,6 +23,8 @@ + */ + + #include "mdadm.h" ++#include "xmalloc.h" ++ + #include + + /* To restripe, we read from old geometry to a buffer, and +diff --git a/super-ddf.c b/super-ddf.c +index d870102d..6cd099ab 100644 +--- a/super-ddf.c ++++ b/super-ddf.c +@@ -29,6 +29,8 @@ + #include "mdadm.h" + #include "mdmon.h" + #include "sha1.h" ++#include "xmalloc.h" ++ + #include + #include + +diff --git a/super-gpt.c b/super-gpt.c +index ec3cf53f..50c267f6 100644 +--- a/super-gpt.c ++++ b/super-gpt.c +@@ -40,6 +40,7 @@ + + #include "mdadm.h" + #include "part.h" ++#include "xmalloc.h" + + static void free_gpt(struct supertype *st) + { +diff --git a/super-intel.c b/super-intel.c +index 30c2939a..7c5119c5 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -23,6 +23,8 @@ + #include "dlink.h" + #include "sha1.h" + #include "platform-intel.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/super-mbr.c b/super-mbr.c +index 839f0003..98810170 100644 +--- a/super-mbr.c ++++ b/super-mbr.c +@@ -41,6 +41,7 @@ + + #include "mdadm.h" + #include "part.h" ++#include "xmalloc.h" + + static void free_mbr(struct supertype *st) + { +diff --git a/super0.c b/super0.c +index c428e2a6..ff4905b9 100644 +--- a/super0.c ++++ b/super0.c +@@ -25,6 +25,8 @@ + #define HAVE_STDINT_H 1 + #include "mdadm.h" + #include "sha1.h" ++#include "xmalloc.h" ++ + /* + * All handling for the 0.90.0 version superblock is in + * this file. +diff --git a/super1.c b/super1.c +index 9c9c7dd1..fe3c4c64 100644 +--- a/super1.c ++++ b/super1.c +@@ -24,6 +24,8 @@ + + #include + #include "mdadm.h" ++#include "xmalloc.h" ++ + /* + * The version-1 superblock : + * All numeric fields are little-endian. +diff --git a/sysfs.c b/sysfs.c +index 7a81cc5b..0f0506ca 100644 +--- a/sysfs.c ++++ b/sysfs.c +@@ -24,9 +24,11 @@ + */ + + #include "mdadm.h" ++#include "dlink.h" ++#include "xmalloc.h" ++ + #include + #include +-#include "dlink.h" + + #define MAX_SYSFS_PATH_LEN 120 + +diff --git a/udev.c b/udev.c +index 066e6ab1..88a99781 100644 +--- a/udev.c ++++ b/udev.c +@@ -22,6 +22,8 @@ + #include "udev.h" + #include "md_p.h" + #include "md_u.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/util.c b/util.c +index 2b660725..4dfe757d 100644 +--- a/util.c ++++ b/util.c +@@ -24,6 +24,8 @@ + + #include "mdadm.h" + #include "md_p.h" ++#include "xmalloc.h" ++ + #include + #include + #include +diff --git a/xmalloc.c b/xmalloc.c +index 8b3f78a6..dac30eb6 100644 +--- a/xmalloc.c ++++ b/xmalloc.c +@@ -21,64 +21,57 @@ + * Email: + */ + +-#include "mdadm.h" +-/*#include +-#include +-#include +-#include +-#include +-#include +-#include +-*/ ++#include "xmalloc.h" ++ ++#include ++#include ++#include ++#include ++ ++static void *exit_memory_alloc_failure(void) ++{ ++ fprintf(stderr, "Memory allocation failure - aborting\n"); ++ ++ /* TODO: replace with MDADM_STATUS_MEM_FAIL */ ++ exit(1); ++} + + void *xmalloc(size_t len) + { + void *rv = malloc(len); +- char *msg; +- int n; ++ + if (rv) + return rv; +- msg = ": memory allocation failure - aborting\n"; +- n = write(2, Name, strlen(Name)); +- n += write(2, msg, strlen(msg)); +- exit(4+!!n); ++ ++ return exit_memory_alloc_failure(); + } + + void *xrealloc(void *ptr, size_t len) + { + void *rv = realloc(ptr, len); +- char *msg; +- int n; ++ + if (rv) + return rv; +- msg = ": memory allocation failure - aborting\n"; +- n = write(2, Name, strlen(Name)); +- n += write(2, msg, strlen(msg)); +- exit(4+!!n); ++ ++ return exit_memory_alloc_failure(); + } + + void *xcalloc(size_t num, size_t size) + { + void *rv = calloc(num, size); +- char *msg; +- int n; ++ + if (rv) + return rv; +- msg = ": memory allocation failure - aborting\n"; +- n = write(2, Name, strlen(Name)); +- n += write(2, msg, strlen(msg)); +- exit(4+!!n); ++ ++ return exit_memory_alloc_failure(); + } + + char *xstrdup(const char *str) + { + char *rv = strdup(str); +- char *msg; +- int n; ++ + if (rv) + return rv; +- msg = ": memory allocation failure - aborting\n"; +- n = write(2, Name, strlen(Name)); +- n += write(2, msg, strlen(msg)); +- exit(4+!!n); ++ ++ return exit_memory_alloc_failure(); + } +diff --git a/xmalloc.h b/xmalloc.h +new file mode 100644 +index 00000000..0904b0ab +--- /dev/null ++++ b/xmalloc.h +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#ifndef XMALLOC_H ++#define XMALLOC_H ++ ++#include ++ ++void *xmalloc(size_t len); ++void *xrealloc(void *ptr, size_t len); ++void *xcalloc(size_t num, size_t size); ++char *xstrdup(const char *str); ++ ++#endif +-- +2.41.0 + diff --git a/0190-md.man-update-refference-to-raid5-ppl.rst.patch b/0190-md.man-update-refference-to-raid5-ppl.rst.patch new file mode 100644 index 0000000..613570a --- /dev/null +++ b/0190-md.man-update-refference-to-raid5-ppl.rst.patch @@ -0,0 +1,43 @@ +From 4157e8da40ce976883c5b6e51e2352732e709b52 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 10 Sep 2024 14:17:58 +0200 +Subject: [PATCH 190/201] md.man: update refference to raid5-ppl.rst + +Documentation/md has moved to Documentation/driver-api/md. +Update and and rework sentence. + +Remove refference to not supported kernel close to updated text. + +Signed-off-by: Mariusz Tkaczyk +--- + md.4 | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/md.4 b/md.4 +index 7aef1577..9d5e55bf 100644 +--- a/md.4 ++++ b/md.4 +@@ -937,18 +937,12 @@ Partial parity for a write operation is the XOR of stripe data chunks not + modified by the write. PPL is stored in the metadata region of RAID member drives, + no additional journal drive is needed. + After crashes, if one of the not modified data disks of +-the stripe is missing, this updated parity can be used to recover its +-data. ++the stripe is missing, this updated parity can be used to recover its data. + +-This mechanism is documented more fully in the file +-Documentation/md/raid5-ppl.rst ++See Documentation/driver-api/md/raid5-ppl.rst for implementation details. + + .SS WRITE-BEHIND + +-From Linux 2.6.14, +-.I md +-supports WRITE-BEHIND on RAID1 arrays. +- + This allows certain devices in the array to be flagged as + .IR write-mostly . + MD will only read from such devices if there is no +-- +2.41.0 + diff --git a/0191-util-fix-sys_hot_remove_disk.patch b/0191-util-fix-sys_hot_remove_disk.patch new file mode 100644 index 0000000..70c389e --- /dev/null +++ b/0191-util-fix-sys_hot_remove_disk.patch @@ -0,0 +1,30 @@ +From 6f227de0a17369d3d6667591241c49140d5239b2 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Fri, 4 Oct 2024 13:57:48 +0200 +Subject: [PATCH 191/201] util: fix sys_hot_remove_disk() + +Instead of "remove", "faulty" was called. + +Fixes: d95edceb362a ("sysfs: add function for writing to sysfs fd") +Signed-off-by: Mariusz Tkaczyk +--- + util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/util.c b/util.c +index 4dfe757d..7c5c5c8f 100644 +--- a/util.c ++++ b/util.c +@@ -1855,8 +1855,8 @@ int hot_remove_disk(int mdfd, unsigned long dev, int force) + + int sys_hot_remove_disk(int statefd, int force) + { ++ static const char val[] = "remove"; + int cnt = force ? 500 : 5; +- static const char val[] = "faulty"; + + while (cnt--) { + int err = 0; +-- +2.41.0 + diff --git a/0192-Rename-Monitor.c-to-mdmonitor.c.patch b/0192-Rename-Monitor.c-to-mdmonitor.c.patch new file mode 100644 index 0000000..1d4a5fd --- /dev/null +++ b/0192-Rename-Monitor.c-to-mdmonitor.c.patch @@ -0,0 +1,35 @@ +From da826501c708b49a6e03394cf56f070160ea59d9 Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Mon, 30 Sep 2024 15:48:11 +0200 +Subject: [PATCH 192/201] Rename Monitor.c to mdmonitor.c + +Rename Monitor.c to mdmonitor.c to avoid errors during compilation on +case-insensitive filesystems. + +Signed-off-by: Kinga Stefaniuk +--- + Makefile | 2 +- + Monitor.c => mdmonitor.c | 0 + 2 files changed, 1 insertion(+), 1 deletion(-) + rename Monitor.c => mdmonitor.c (100%) + +diff --git a/Makefile b/Makefile +index a914b178..32f579de 100644 +--- a/Makefile ++++ b/Makefile +@@ -186,7 +186,7 @@ endif + + OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o uuid.o util.o maps.o lib.o udev.o \ + Manage.o Assemble.o Build.o \ +- Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o \ ++ Create.o Detail.o Examine.o Grow.o mdmonitor.o dlink.o Kill.o Query.o \ + Incremental.o Dump.o \ + mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \ + super-mbr.o super-gpt.o \ +diff --git a/Monitor.c b/mdmonitor.c +similarity index 100% +rename from Monitor.c +rename to mdmonitor.c +-- +2.41.0 + diff --git a/0193-super-intel-move-scsi_get_serial-from-sg_io.patch b/0193-super-intel-move-scsi_get_serial-from-sg_io.patch new file mode 100644 index 0000000..5adf215 --- /dev/null +++ b/0193-super-intel-move-scsi_get_serial-from-sg_io.patch @@ -0,0 +1,178 @@ +From bafa5ccfa56d776d431f766c765178eda0a4900d Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Fri, 4 Oct 2024 10:23:57 +0200 +Subject: [PATCH 193/201] super-intel: move scsi_get_serial from sg_io + +scsi_get_serial() function is used only by super-intel.c. Move function +to this file and remove sg_io.c file. + +Signed-off-by: Kinga Stefaniuk +--- + Makefile | 4 ++-- + sg_io.c | 60 --------------------------------------------------- + super-intel.c | 47 ++++++++++++++++++++++++++++++++++++---- + 3 files changed, 45 insertions(+), 66 deletions(-) + delete mode 100644 sg_io.c + +diff --git a/Makefile b/Makefile +index 32f579de..24367b0f 100644 +--- a/Makefile ++++ b/Makefile +@@ -190,7 +190,7 @@ OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o uuid.o util.o maps.o lib.o u + Incremental.o Dump.o \ + mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \ + super-mbr.o super-gpt.o \ +- restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o xmalloc.o \ ++ restripe.o sysfs.o sha1.o mapfile.o crc32.o msg.o xmalloc.o \ + platform-intel.o probe_roms.o crc32c.o drive_encryption.o + + CHECK_OBJS = restripe.o uuid.o sysfs.o maps.o lib.o xmalloc.o dlink.o +@@ -201,7 +201,7 @@ INCL = mdadm.h part.h bitmap.h + + MON_OBJS = mdmon.o monitor.o managemon.o uuid.o util.o maps.o mdstat.o sysfs.o config.o mapfile.o mdopen.o\ + policy.o lib.o udev.o \ +- Kill.o sg_io.o dlink.o ReadMe.o super-intel.o \ ++ Kill.o dlink.o ReadMe.o super-intel.o \ + super-mbr.o super-gpt.o \ + super-ddf.o sha1.o crc32.o msg.o bitmap.o xmalloc.o \ + platform-intel.o probe_roms.o crc32c.o drive_encryption.o +diff --git a/sg_io.c b/sg_io.c +deleted file mode 100644 +index 7889a95e..00000000 +--- a/sg_io.c ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* +- * Copyright (C) 2007-2008 Intel Corporation +- * +- * Retrieve drive serial numbers for scsi disks +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms and conditions of the GNU General Public License, +- * version 2, as published by the Free Software Foundation. +- * +- * This program is distributed in the hope it will be useful, but WITHOUT +- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +- * more details. +- * +- * You should have received a copy of the GNU General Public License along with +- * this program; if not, write to the Free Software Foundation, Inc., +- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +- */ +-#include +-#include +-#include +-#include +- +-int scsi_get_serial(int fd, void *buf, size_t buf_len) +-{ +- unsigned char rsp_buf[255]; +- unsigned char inq_cmd[] = {INQUIRY, 1, 0x80, 0, sizeof(rsp_buf), 0}; +- unsigned char sense[32]; +- struct sg_io_hdr io_hdr; +- int rv; +- unsigned int rsp_len; +- +- memset(&io_hdr, 0, sizeof(io_hdr)); +- io_hdr.interface_id = 'S'; +- io_hdr.cmdp = inq_cmd; +- io_hdr.cmd_len = sizeof(inq_cmd); +- io_hdr.dxferp = rsp_buf; +- io_hdr.dxfer_len = sizeof(rsp_buf); +- io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; +- io_hdr.sbp = sense; +- io_hdr.mx_sb_len = sizeof(sense); +- io_hdr.timeout = 5000; +- +- rv = ioctl(fd, SG_IO, &io_hdr); +- +- if (rv) +- return rv; +- +- if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) +- return -1; +- +- rsp_len = rsp_buf[3]; +- +- if (!rsp_len || buf_len < rsp_len) +- return -1; +- +- memcpy(buf, &rsp_buf[4], rsp_len); +- +- return 0; +-} +diff --git a/super-intel.c b/super-intel.c +index 7c5119c5..3b856ad0 100644 +--- a/super-intel.c ++++ b/super-intel.c +@@ -21,15 +21,18 @@ + #include "mdadm.h" + #include "mdmon.h" + #include "dlink.h" ++#include "drive_encryption.h" + #include "sha1.h" + #include "platform-intel.h" + #include "xmalloc.h" + +-#include +-#include + #include + #include +-#include "drive_encryption.h" ++#include ++#include ++#include ++#include ++#include + + /* MPB == Metadata Parameter Block */ + #define MPB_SIGNATURE "Intel Raid ISM Cfg Sig. " +@@ -4131,7 +4134,43 @@ static int nvme_get_serial(int fd, void *buf, size_t buf_len) + return devpath_to_char(path, "serial", buf, buf_len, 0); + } + +-extern int scsi_get_serial(int fd, void *buf, size_t buf_len); ++mdadm_status_t scsi_get_serial(int fd, void *buf, size_t buf_len) ++{ ++ struct sg_io_hdr io_hdr = {0}; ++ unsigned char rsp_buf[255]; ++ unsigned char inq_cmd[] = {INQUIRY, 1, 0x80, 0, sizeof(rsp_buf), 0}; ++ unsigned char sense[32]; ++ unsigned int rsp_len; ++ int rv; ++ ++ io_hdr.interface_id = 'S'; ++ io_hdr.cmdp = inq_cmd; ++ io_hdr.cmd_len = sizeof(inq_cmd); ++ io_hdr.dxferp = rsp_buf; ++ io_hdr.dxfer_len = sizeof(rsp_buf); ++ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; ++ io_hdr.sbp = sense; ++ io_hdr.mx_sb_len = sizeof(sense); ++ io_hdr.timeout = 5000; ++ ++ rv = ioctl(fd, SG_IO, &io_hdr); ++ ++ if (rv) ++ return MDADM_STATUS_ERROR; ++ ++ if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) ++ return MDADM_STATUS_ERROR; ++ ++ rsp_len = rsp_buf[3]; ++ ++ if (!rsp_len || buf_len < rsp_len) ++ return MDADM_STATUS_ERROR; ++ ++ memcpy(buf, &rsp_buf[4], rsp_len); ++ ++ return MDADM_STATUS_SUCCESS; ++} ++ + + static int imsm_read_serial(int fd, char *devname, + __u8 *serial, size_t serial_buf_len) +-- +2.41.0 + diff --git a/0194-mdmonitor-Abandon-custom-configuration-files.patch b/0194-mdmonitor-Abandon-custom-configuration-files.patch new file mode 100644 index 0000000..4b598fb --- /dev/null +++ b/0194-mdmonitor-Abandon-custom-configuration-files.patch @@ -0,0 +1,120 @@ +From a7a5e676a7eb2ac97acd31b13f75515e9573f891 Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Thu, 26 Sep 2024 09:01:55 +0200 +Subject: [PATCH 194/201] mdmonitor: Abandon custom configuration files + +Operating system vendors are customizing mdmonitor service beacause +the default form is not satifying for them (expect SUSE). As a result, +support is complicated (maintainers have to check the system) and man page +is not detailed. + +I propose to abandon custom configuration files via sysconfig and keep +it inside mdadm.conf only. + +Detailed comment in service for OSV maintainers is added to help with +transition. + +Signed-off-by: Mariusz Tkaczyk +--- + Makefile | 1 - + systemd/SUSE-mdadm_env.sh | 48 --------------------------------------- + systemd/mdmonitor.service | 19 ++++++++++++---- + 3 files changed, 15 insertions(+), 53 deletions(-) + delete mode 100644 systemd/SUSE-mdadm_env.sh + +diff --git a/Makefile b/Makefile +index 24367b0f..bcd092de 100644 +--- a/Makefile ++++ b/Makefile +@@ -341,7 +341,6 @@ install-systemd: systemd/mdmon@.service + $(INSTALL) -D -m 755 .install.tmp.3 $(DESTDIR)$(SYSTEMD_DIR)-shutdown/$$file ; \ + rm -f .install.tmp.3; \ + done +- if [ -f /etc/SuSE-release -o -n "$(SUSE)" ] ;then $(INSTALL) -D -m 755 systemd/SUSE-mdadm_env.sh $(DESTDIR)$(LIB_DIR)/mdadm_env.sh ;fi + + install-bin: mdadm mdmon + $(INSTALL) -D $(STRIP) -m 755 mdadm $(DESTDIR)$(BINDIR)/mdadm +diff --git a/systemd/SUSE-mdadm_env.sh b/systemd/SUSE-mdadm_env.sh +deleted file mode 100644 +index c13b48ab..00000000 +--- a/systemd/SUSE-mdadm_env.sh ++++ /dev/null +@@ -1,48 +0,0 @@ +-#!/bin/sh +- +-# extract configuration from /etc/sysconfig/mdadm and write +-# environment to /run/sysconfig/mdadm to be used by +-# systemd unit files. +- +-MDADM_SCAN="yes" +- +-# Following adapted from /etc/init.d/mdadmd on openSUSE +- +-mdadmd_CONFIG=/etc/sysconfig/mdadm +-if test -r $mdadmd_CONFIG; then +- . $mdadmd_CONFIG +-fi +- +-if [ x$MDADM_DELAY != x"" ]; then +- MDADM_DELAY="-d "$MDADM_DELAY; +-fi +- +-if [ x$MDADM_MAIL != x"" ]; then +- MDADM_MAIL="-m \"$MDADM_MAIL\"" +-fi +- +-if [ x$MDADM_PROGRAM != x"" ]; then +- MDADM_PROGRAM="-p \"$MDADM_PROGRAM\"" +-fi +- +-if [ x$MDADM_SCAN = x"yes" ]; then +- MDADM_SCAN="--scan" +-else +- MDADM_SCAN="" +-fi +- +-if [ x$MDADM_SEND_MAIL_ON_START = x"yes" ]; then +- MDADM_SEND_MAIL="-t" +-else +- MDADM_SEND_MAIL="" +-fi +- +-if [ x$MDADM_CONFIG != x"" ]; then +- MDADM_CONFIG="-c \"$MDADM_CONFIG\"" +-fi +- +-mkdir -p /run/sysconfig +-echo "MDADM_MONITOR_ARGS=$MDADM_RAIDDEVICES $MDADM_DELAY $MDADM_MAIL $MDADM_PROGRAM $MDADM_SCAN $MDADM_SEND_MAIL $MDADM_CONFIG" > /run/sysconfig/mdadm +-if [ -n "$MDADM_CHECK_DURATION" ]; then +- echo "MDADM_CHECK_DURATION=$MDADM_CHECK_DURATION" >> /run/sysconfig/mdadm +-fi +diff --git a/systemd/mdmonitor.service b/systemd/mdmonitor.service +index 9c364785..6d0c0039 100644 +--- a/systemd/mdmonitor.service ++++ b/systemd/mdmonitor.service +@@ -11,7 +11,18 @@ DefaultDependencies=no + Documentation=man:mdadm(8) + + [Service] +-Environment= MDADM_MONITOR_ARGS=--scan +-EnvironmentFile=-/run/sysconfig/mdadm +-ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh +-ExecStart=BINDIR/mdadm --monitor $MDADM_MONITOR_ARGS ++# For Maintainers: ++# We need to provide consistent mdmonitor configuration man page to the users. We don't want to get ++# asked continuously how it can be configured. ++# /etc/sysconfig/mdadm or /etc/sysconfig/mdmonitor or whatever else, should be abandoned. ++# Following parameters should be customized via mdadm.conf only: ++# - MONITORDELAY (do not set --delay in service) ++# - MAILADDR (do not set --mail in service) ++# - MAILFROM (not settable from cmdline) ++# - PROGRAM (do not set --program or --alert in service) ++# ++# Following parameters can be customized in service: ++# - --syslog (configure syslog logging) ++# - --fork (Type=forking must be added, not recommended and not needed with systemd) ++# - --pid-file (allowed only when --fork selected) ++ExecStart=BINDIR/mdadm --monitor --scan +-- +2.41.0 + diff --git a/0195-mdadm.man-elaborate-more-about-mdmonitor.service.patch b/0195-mdadm.man-elaborate-more-about-mdmonitor.service.patch new file mode 100644 index 0000000..157cff4 --- /dev/null +++ b/0195-mdadm.man-elaborate-more-about-mdmonitor.service.patch @@ -0,0 +1,131 @@ +From 70f3a1bcb0ff3b740f986b5819931b93c8bed24d Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 10 Sep 2024 15:35:03 +0200 +Subject: [PATCH 195/201] mdadm.man: elaborate more about mdmonitor.service + +Describe how it behaves and how it can be configured to work. + +Signed-off-by: Mariusz Tkaczyk +--- + mdadm.8.in | 52 ++++++++++++++++++++------------------- + systemd/mdmonitor.service | 11 ++++++--- + 2 files changed, 34 insertions(+), 29 deletions(-) + +diff --git a/mdadm.8.in b/mdadm.8.in +index aa0c5403..ee5b9bd4 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -1878,11 +1878,15 @@ script. + .SH For Monitor mode: + .TP + .BR \-m ", " \-\-mail +-Give a mail address to send alerts to. ++Give an mail address to send alerts to. Can be configured in ++.B mdadm.conf ++as MAILADDR. + + .TP + .BR \-p ", " \-\-program ", " \-\-alert +-Give a program to be run whenever an event is detected. ++Give a program to be run whenever an event is detected. Can be configured in ++.B mdadm.conf ++as PROGRAM. + + .TP + .BR \-y ", " \-\-syslog +@@ -1891,13 +1895,12 @@ facility of 'daemon' and varying priorities. + + .TP + .BR \-d ", " \-\-delay +-Give a delay in seconds. +-.I mdadm +-polls the md arrays and then waits this many seconds before polling +-again. The default is 60 seconds. Since 2.6.16, there is no need to +-reduce this as the kernel alerts ++Give a delay in seconds. The default is 60 seconds. + .I mdadm +-immediately when there is any change. ++polls the md arrays and then waits this many seconds before polling again if no event happened. ++Can be configured in ++.B mdadm.conf ++as MONITORDELAY. + + .TP + .BR \-r ", " \-\-increment +@@ -2595,30 +2598,29 @@ is given, then a + .B program + or an + .B e-mail +-address must be specified on the +-command line or in the config file. If neither are available, then ++address must be specified on the command line or in the config file. If neither are available, then + .I mdadm +-will not monitor anything. +-For devices given directly in command line, without ++will not monitor anything. For devices given directly in command line, without + .B program + or + .B email + specified, each event is reported to + .BR stdout. + +-Note: For systems where +-.If mdadm monitor +-is configured via systemd, +-.B mdmonitor(mdmonitor.service) +-should be configured. The service is designed to be primary solution for array monitoring, +-it is configured to work in system wide mode. +-It is automatically started and stopped according to current state and types of MD arrays in system. +-The service may require additional configuration, like +-.B e-mail +-or +-.B delay. +-That should be done in +-.B mdadm.conf. ++Note: On systems where mdadm monitoring is managed through systemd, the mdmonitor.service ++should be present. This service is designed to be the primary solution for array monitoring. ++It is configured to operate in system-wide mode. It is initiated by udev when start criteria are ++met, e.g. ++.B mdadm.conf ++exists and necessary configuration parameters are set. ++It is kept alive as long as a redundant RAID array is active; it stops otherwise. User should ++customize MAILADDR in ++.B mdadm.conf ++to receive mail notifications. MONITORDELAY, MAILFROM and PROGRAM are optional. See ++.BR mdadm.conf (5) ++for detailed description of these options. ++Use systemctl status mdmonitor.service to verify status or determine if additional configuration ++is needed. + + The different events are: + +diff --git a/systemd/mdmonitor.service b/systemd/mdmonitor.service +index 6d0c0039..95046bc5 100644 +--- a/systemd/mdmonitor.service ++++ b/systemd/mdmonitor.service +@@ -12,10 +12,12 @@ Documentation=man:mdadm(8) + + [Service] + # For Maintainers: +-# We need to provide consistent mdmonitor configuration man page to the users. We don't want to get +-# asked continuously how it can be configured. +-# /etc/sysconfig/mdadm or /etc/sysconfig/mdmonitor or whatever else, should be abandoned. +-# Following parameters should be customized via mdadm.conf only: ++# We need to ensure that the mdmonitor configuration aligns with the guidelines provided ++# in the man page for users. ++# /etc/sysconfig/mdadm, /etc/sysconfig/mdmonitor, or any other similar configuration file should ++# not be supported because non upstream components are not described in man pages. ++ ++# Parameters designed to be customized by user, should be settable via mdadm.conf: + # - MONITORDELAY (do not set --delay in service) + # - MAILADDR (do not set --mail in service) + # - MAILFROM (not settable from cmdline) +@@ -25,4 +27,5 @@ Documentation=man:mdadm(8) + # - --syslog (configure syslog logging) + # - --fork (Type=forking must be added, not recommended and not needed with systemd) + # - --pid-file (allowed only when --fork selected) ++ + ExecStart=BINDIR/mdadm --monitor --scan +-- +2.41.0 + diff --git a/0196-mdadm-Add-mdadm_status.h.patch b/0196-mdadm-Add-mdadm_status.h.patch new file mode 100644 index 0000000..6b5c0e2 --- /dev/null +++ b/0196-mdadm-Add-mdadm_status.h.patch @@ -0,0 +1,85 @@ +From f2f938b0b2755bb2c558eef87f5767beb2ff2ca1 Mon Sep 17 00:00:00 2001 +From: Anna Sztukowska +Date: Wed, 9 Oct 2024 08:14:05 +0200 +Subject: [PATCH 196/201] mdadm: Add mdadm_status.h + +Move mdadm_status_t to mdadm_status.h file. Add status for memory +allocation failure. + +Signed-off-by: Anna Sztukowska +--- + mdadm.h | 7 +------ + mdadm_status.h | 13 +++++++++++++ + xmalloc.c | 4 ++-- + 3 files changed, 16 insertions(+), 8 deletions(-) + create mode 100644 mdadm_status.h + +diff --git a/mdadm.h b/mdadm.h +index bbc1b97f..5781948e 100644 +--- a/mdadm.h ++++ b/mdadm.h +@@ -166,6 +166,7 @@ struct dlm_lksb { + #include "md_p.h" + #include "bitmap.h" + #include "msg.h" ++#include "mdadm_status.h" + + #include + /* Redhat don't like to #include , and +@@ -449,12 +450,6 @@ struct spare_criteria { + struct dev_policy *pols; + }; + +-typedef enum mdadm_status { +- MDADM_STATUS_SUCCESS = 0, +- MDADM_STATUS_ERROR, +- MDADM_STATUS_UNDEF, +-} mdadm_status_t; +- + enum mode { + ASSEMBLE=1, + BUILD, +diff --git a/mdadm_status.h b/mdadm_status.h +new file mode 100644 +index 00000000..905105e2 +--- /dev/null ++++ b/mdadm_status.h +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#ifndef MDADM_STATUS_H ++#define MDADM_STATUS_H ++ ++typedef enum mdadm_status { ++ MDADM_STATUS_SUCCESS = 0, ++ MDADM_STATUS_ERROR, ++ MDADM_STATUS_UNDEF, ++ MDADM_STATUS_MEM_FAIL ++} mdadm_status_t; ++ ++#endif +diff --git a/xmalloc.c b/xmalloc.c +index dac30eb6..e28d3bd6 100644 +--- a/xmalloc.c ++++ b/xmalloc.c +@@ -22,6 +22,7 @@ + */ + + #include "xmalloc.h" ++#include "mdadm_status.h" + + #include + #include +@@ -32,8 +33,7 @@ static void *exit_memory_alloc_failure(void) + { + fprintf(stderr, "Memory allocation failure - aborting\n"); + +- /* TODO: replace with MDADM_STATUS_MEM_FAIL */ +- exit(1); ++ exit(MDADM_STATUS_MEM_FAIL); + } + + void *xmalloc(size_t len) +-- +2.41.0 + diff --git a/0197-mdadm.conf.man-Explain-udev-rule.patch b/0197-mdadm.conf.man-Explain-udev-rule.patch new file mode 100644 index 0000000..2fd711e --- /dev/null +++ b/0197-mdadm.conf.man-Explain-udev-rule.patch @@ -0,0 +1,67 @@ +From 13378ba880c251aa65dac12a5d366230cb7ea039 Mon Sep 17 00:00:00 2001 +From: Andre Paiusco +Date: Sat, 12 Oct 2024 16:28:29 +0200 +Subject: [PATCH 197/201] mdadm.conf.man: Explain udev rule + +Clarify a filename is accepted and the need of reloading the +udev rules. + +Small correction on example order. + +Signed-off-by: Andre Paiusco +--- + mdadm.conf.5.in | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/mdadm.conf.5.in b/mdadm.conf.5.in +index 14302a91..97862fdb 100644 +--- a/mdadm.conf.5.in ++++ b/mdadm.conf.5.in +@@ -506,8 +506,12 @@ of the new disk or if both arrays have the same + .IR spare-group . + + To update hot plug configuration it is necessary to execute +-.B mdadm \-\-udev\-rules +-command after changing the config file ++.B mdadm \-\-udev\-rules\= ++e.g. ++.B /etc/udev/rules.d/65-md-bare.rules ++command after changing the config file. And also run ++.B udevadm control \-\-reload ++otherwise, a reboot is needed. + + Keywords used in the + .I POLICY +@@ -724,14 +728,6 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b + .br + auto=part + .br +-POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-* +-.br +- action=spare +-.br +-POLICY domain=domain1 metadata=imsm path=pci-0000:04:00.0-scsi-[01]* +-.br +- action=include +-.br + # One domain comprising of devices attached to specified paths is defined. + .br + # Bare device matching first path will be made an imsm spare on hot plug. +@@ -742,6 +738,14 @@ POLICY domain=domain1 metadata=imsm path=pci-0000:04:00.0-scsi-[01]* + .br + # given domain name can be migrated. + .br ++POLICY domain=domain1 metadata=imsm path=pci-0000:00:1f.2-scsi-* ++.br ++ action=spare ++.br ++POLICY domain=domain1 metadata=imsm path=pci-0000:04:00.0-scsi-[01]* ++.br ++ action=include ++.br + MAILADDR root@mydomain.tld + .br + PROGRAM /usr/sbin/handle\-mdadm\-events +-- +2.41.0 + diff --git a/0198-mdadm.man-Add-udev-rules-flag.patch b/0198-mdadm.man-Add-udev-rules-flag.patch new file mode 100644 index 0000000..a4ba75e --- /dev/null +++ b/0198-mdadm.man-Add-udev-rules-flag.patch @@ -0,0 +1,37 @@ +From cb4acfa372a8d66703706ef54f985bd588d8bb99 Mon Sep 17 00:00:00 2001 +From: Andre Paiusco +Date: Sat, 12 Oct 2024 16:29:01 +0200 +Subject: [PATCH 198/201] mdadm.man: Add udev-rules flag + +--udev-rules flag is added and point to mdadm.conf man page +for further explanations about POLICY. + +Signed-off-by: Andre Paiusco +--- + mdadm.8.in | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/mdadm.8.in b/mdadm.8.in +index ee5b9bd4..43d6fe05 100644 +--- a/mdadm.8.in ++++ b/mdadm.8.in +@@ -1830,6 +1830,16 @@ can be found it + under + .BR "SCRUBBING AND MISMATCHES" . + ++.TP ++.B \-\-udev\-rules= ++it generates the udev rules to the file that handles hot-plug bare devices. ++Given the POLICYs defined under ++.IR {CONFFILE}\ (or {CONFFILE2}) ++ ++See ++.BR mdadm.conf (5) ++for more details and usage examples about POLICY. ++ + .SH For Incremental Assembly mode: + .TP + .BR \-\-rebuild\-map ", " \-r +-- +2.41.0 + diff --git a/0199-util-use-only-dev-directory-in-open_dev.patch b/0199-util-use-only-dev-directory-in-open_dev.patch new file mode 100644 index 0000000..e2c3d53 --- /dev/null +++ b/0199-util-use-only-dev-directory-in-open_dev.patch @@ -0,0 +1,40 @@ +From 0d29e12553cd9f51c1d4428ea373cdb8c62fbcf2 Mon Sep 17 00:00:00 2001 +From: Kinga Stefaniuk +Date: Wed, 9 Oct 2024 08:48:20 +0200 +Subject: [PATCH 199/201] util: use only /dev directory in open_dev() + +Previously, open_dev() tried to open device in two ways - using /dev and +/tmp directory. This method could be used by users which have no access +to /tmp directory (e.g. udev) and dev_open() fails which may affect many +processes. Remove try to open in /tmp directory. + +Signed-off-by: Kinga Stefaniuk +--- + util.c | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/util.c b/util.c +index 7c5c5c8f..f05392a2 100644 +--- a/util.c ++++ b/util.c +@@ -1111,17 +1111,6 @@ int dev_open(char *dev, int flags) + fd = open(devname, flags); + unlink(devname); + } +- if (fd < 0) { +- /* Try /tmp as /dev appear to be read-only */ +- snprintf(devname, sizeof(devname), +- "/tmp/.tmp.md.%d:%d:%d", +- (int)getpid(), major, minor); +- if (mknod(devname, S_IFBLK|0600, +- makedev(major, minor)) == 0) { +- fd = open(devname, flags); +- unlink(devname); +- } +- } + } else + fd = open(dev, flags); + return fd; +-- +2.41.0 + diff --git a/0200-mdadm-Manage-Clear-superblock-if-adding-new-device-f.patch b/0200-mdadm-Manage-Clear-superblock-if-adding-new-device-f.patch new file mode 100644 index 0000000..033987b --- /dev/null +++ b/0200-mdadm-Manage-Clear-superblock-if-adding-new-device-f.patch @@ -0,0 +1,47 @@ +From c6ca5b31e18f92490e639de0e5eae88985628633 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 18 Oct 2024 16:48:16 +0800 +Subject: [PATCH 200/201] mdadm/Manage: Clear superblock if adding new device + fails + +The superblock is kept if adding new device fails. It should clear the +superblock if it fails to add a new disk. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Manage.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/Manage.c b/Manage.c +index 246ef319..8c58683b 100644 +--- a/Manage.c ++++ b/Manage.c +@@ -793,6 +793,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + int j; + mdu_disk_info_t disc; + struct map_ent *map = NULL; ++ bool add_new_super = false; + + if (!get_dev_size(tfd, dv->devname, &ldsize)) { + if (dv->disposition == 'M') +@@ -1011,6 +1012,7 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + goto unlock; + if (tst->ss->write_init_super(tst)) + goto unlock; ++ add_new_super = true; + } else if (dv->disposition == 'A') { + /* this had better be raid1. + * As we are "--re-add"ing we must find a spare slot +@@ -1078,6 +1080,8 @@ int Manage_add(int fd, int tfd, struct mddev_dev *dv, + map_unlock(&map); + return 1; + unlock: ++ if (add_new_super) ++ Kill(dv->devname, tst, 0, -1, 0); + map_unlock(&map); + return -1; + } +-- +2.41.0 + diff --git a/0201-mdadm-Grow-Check-new_level-interface-rather-than-ker.patch b/0201-mdadm-Grow-Check-new_level-interface-rather-than-ker.patch new file mode 100644 index 0000000..f0a9152 --- /dev/null +++ b/0201-mdadm-Grow-Check-new_level-interface-rather-than-ker.patch @@ -0,0 +1,31 @@ +From b278b2fc172bb8d50f607adef4d515af1f52d913 Mon Sep 17 00:00:00 2001 +From: Xiao Ni +Date: Fri, 18 Oct 2024 16:48:17 +0800 +Subject: [PATCH 201/201] mdadm/Grow: Check new_level interface rather than + kernel version + +Different os distributions have different kernel version themselves. +Check new_level sysfs interface rather than kernel version. + +Signed-off-by: Xiao Ni +Signed-off-by: Mariusz Tkaczyk +--- + Grow.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Grow.c b/Grow.c +index ef1285ec..9032c3e9 100644 +--- a/Grow.c ++++ b/Grow.c +@@ -2952,7 +2952,7 @@ static int impose_reshape(struct mdinfo *sra, + err = errno; + + /* new_level is introduced in kernel 6.12 */ +- if (!err && get_linux_version() >= 6012000 && ++ if (!err && sysfs_attribute_available(sra, NULL, "new_level") && + sysfs_set_num(sra, NULL, "new_level", info->new_level) < 0) + err = errno; + +-- +2.41.0 + diff --git a/mdadm.spec b/mdadm.spec index 6425f2f..0021d7d 100644 --- a/mdadm.spec +++ b/mdadm.spec @@ -1,7 +1,7 @@ Name: mdadm Version: 4.3 # extraversion is used to define rhel internal version -%define extraversion 3 +%define extraversion 4 Release: %{extraversion}%{?dist} Summary: The mdadm program controls Linux md devices (software RAID arrays) URL: http://www.kernel.org/pub/linux/utils/raid/mdadm/ @@ -85,8 +85,134 @@ Patch062: 0063-Makefile-Move-pie-to-LDFLAGS.patch Patch063: 0064-tests-23rdev-lifetime-fix-a-typo.patch Patch064: 0065-util.c-change-devnm-to-const-in-mdmon-functions.patch Patch065: 0066-Wait-for-mdmon-when-it-is-stared-via-systemd.patch -Patch066: 0069-mdadm-Fix-compilation-for-32-bit-arch.patch -Patch067: 0070-Detail-fix-detail-export-for-uuid_zero.patch +Patch066: 0067-mdadm-Change-main-repository-to-Github.patch +Patch067: 0069-mdadm-Fix-compilation-for-32-bit-arch.patch +Patch068: 0070-add-checking-of-return-status-on-fstat-calls.patch +Patch069: 0071-super-intel-fix-typo-in-error-msg.patch +Patch070: 0072-mdadm-super-intel-remove-dead-code.patch +Patch071: 0073-mdadm-super-intel-fix-bad-shift.patch +Patch072: 0074-mdadm-deprecate-bitmap-custom-file.patch +Patch073: 0075-Makefile-fix-make-s-detection.patch +Patch074: 0076-Change-some-error-messages-to-info-level.patch +Patch075: 0077-mdadm-Start-update_opt-from-0.patch +Patch076: 0078-Don-t-control-reshape-speed-in-daemon.patch +Patch077: 0079-mdadm-tests-test-enhance.patch +Patch078: 0080-mdadm-tests-test-don-t-fail-when-systemd-reports-err.patch +Patch079: 0081-mdadm-tests-names_template-enhance.patch +Patch080: 0082-mdadm-tests-03assem-incr-enhance.patch +Patch081: 0083-mdadm-tests-03r0assem-enhance.patch +Patch082: 0084-mdadm-tests-remove-03r5assem-failed.patch +Patch083: 0085-mdadm-tests-03r5assemV1.patch +Patch084: 0086-mdadm-tests-remove-04r5swap.broken.patch +Patch085: 0087-tests-04update-metadata-skip-linear.patch +Patch086: 0088-mdadm-tests-05r5-internalbitmap.patch +Patch087: 0089-mdadm-tests-06name-enhance.patch +Patch088: 0090-mdadm-tests-07autoassemble.patch +Patch089: 0091-mdadm-tests-07autodetect.broken-can-be-removed.patch +Patch090: 0092-mdadm-tests-07changelevelintr.patch +Patch091: 0093-mdadm-tests-disable-selinux.patch +Patch092: 0094-mdadm-platform-intel-buffer-overflow-detected.patch +Patch093: 0095-mdadm-tests-bitmap-cases-enhance.patch +Patch094: 0096-mdadm-tests-04update-uuid.patch +Patch095: 0097-mdadm-tests-05r1-re-add-nosuper.patch +Patch096: 0098-mdadm-tests-remove-strace-test.patch +Patch097: 0099-mdadm.h-provide-basename-if-GLIBC-is-not-avialable.patch +Patch098: 0100-imsm-fix-first-volume-autolayout-with-IMSM_NO_PLATFO.patch +Patch099: 0101-imsm-make-freesize-required-to-volume-autolayout.patch +Patch100: 0102-mdadm-Fix-hang-race-condition-in-wait_for_zero_forks.patch +Patch101: 0103-mdadm-Block-SIGCHLD-processes-before-starting-childr.patch +Patch102: 0104-test-pass-flags-to-services.patch +Patch103: 0105-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch +Patch104: 0106-Makefile-Do-not-call-gcc-directly.patch +Patch105: 0107-mdadm-tests-judge-foreign-array-in-test-cases.patch +Patch106: 0108-Revert-mdadm-Fix-socket-connection-failure-when-mdmo.patch +Patch107: 0109-mdadm-Assemble.c-fix-coverity-issues.patch +Patch108: 0111-mdadm-Fix-socket-connection-failure-when-mdmon-runs-.patch +Patch109: 0113-config.c-Fix-memory-leak-in-load_containers.patch +Patch110: 0114-mdadm-Build.c-fix-coverity-issues.patch +Patch111: 0115-mdadm-Create.c-fix-coverity-issues.patch +Patch112: 0116-mdadm-super-ddf.c-fix-coverity-issues.patch +Patch113: 0117-mdadm-clustermd_tests-add-some-APIs-in-func.sh-to-su.patch +Patch114: 0118-mdadm-clustermd_tests-adjust-test-cases-to-support-m.patch +Patch115: 0119-mapfile.c-Fix-STRING_OVERFLOW-issue.patch +Patch116: 0120-mdadm-Manage.c-fix-coverity-issues.patch +Patch117: 0121-Manage-fix-is_remove_safe.patch +Patch118: 0122-imsm-add-indent-for-encryption-details.patch +Patch119: 0123-mdadm-Monitor.c-fix-coverity-issues.patch +Patch120: 0124-mdadm-Query.c-fix-coverity-issues.patch +Patch121: 0125-mdadm-lib.c-fix-coverity-issues.patch +Patch122: 0126-mdadm-do-not-allow-leading-dot-in-MD-device-name.patch +Patch123: 0128-Detail-fix-detail-export-for-uuid_zero.patch +Patch124: 0129-drive_encryption-Fix-ata-passthrough12-verify.patch +Patch125: 0130-super0-use-define-for-char-array-in-examine_super0.patch +Patch126: 0131-Makefile-add-more-compiler-flags.patch +Patch127: 0133-mdstat-Rework-mdstat-external-arrays-handling.patch +Patch128: 0134-mdadm-managemon.c-fix-coverity-issues.patch +Patch129: 0135-mdadm-msg.c-fix-coverity-issues.patch +Patch130: 0136-imsm-refactor-chunk-size-print.patch +Patch131: 0137-mdadm-Grow-fix-coverity-issue-CHECKED_RETURN.patch +Patch132: 0138-mdadm-Grow-fix-coverity-issue-RESOURCE_LEAK.patch +Patch133: 0139-mdadm-Grow-fix-coverity-issue-STRING_OVERFLOW.patch +Patch134: 0140-mdadm-Incremental-fix-coverity-issues.patch +Patch135: 0141-mdadm-mdmon-fix-coverity-issue-CHECKED_RETURN.patch +Patch136: 0142-mdadm-mdmon-fix-coverity-issue-RESOURCE_LEAK.patch +Patch137: 0143-mdadm-mdopen-fix-coverity-issue-CHECKED_RETURN.patch +Patch138: 0144-mdadm-mdopen-fix-coverity-issue-STRING_OVERFLOW.patch +Patch139: 0145-mdadm-mdstat-fix-coverity-issue-CHECKED_RETURN.patch +Patch140: 0146-mdadm-super0-fix-coverity-issue-CHECKED_RETURN-and-E.patch +Patch141: 0147-mdadm-super1-fix-coverity-issue-CHECKED_RETURN.patch +Patch142: 0148-mdadm-super1-fix-coverity-issue-DEADCODE.patch +Patch143: 0149-mdadm-super1-fix-coverity-issue-EVALUATION_ORDER.patch +Patch144: 0150-mdadm-super1-fix-coverity-issue-RESOURCE_LEAK.patch +Patch145: 0151-policy.c-Fix-check_return-issue-in-Write_rules.patch +Patch146: 0152-super-gpt.c-Fix-check_return-issue-in-load_gpt.patch +Patch147: 0153-super-intel-fix-compilation-error.patch +Patch148: 0154-super-intel-add-define-for-migr_state.patch +Patch149: 0156-Grow_reshape-set-only-component_size-for-size-grow.patch +Patch150: 0157-mdstat-fix-list-detach-issues.patch +Patch151: 0158-md.4-replace-wrong-word.patch +Patch152: 0159-mdadm-util.c-fix-coverity-issues.patch +Patch153: 0160-mdadm-sysfs.c-fix-coverity-issues.patch +Patch154: 0161-imsm-add-read-OROM-form-ACPI-UEFI-tables.patch +Patch155: 0162-imsm-get-bus-from-VMD-driver-directory.patch +Patch156: 0163-platform-intel-refactor-path_attached_to_hba.patch +Patch157: 0164-mdadm-Change-displaying-of-devices-in-detail.patch +Patch158: 0165-imsm-Remove-warning-and-refactor-add_to_super_imsm-c.patch +Patch159: 0166-imsm-add-IMSM_OROM_CAPABILITIES_TPV-to-nvme-orom.patch +Patch160: 0167-mdadm-Increase-number-limit-in-md-device-name-to-102.patch +Patch161: 0168-imsm-save-checkpoint-prior-to-exit.patch +Patch162: 0169-Examine.c-Fix-memory-leaks-in-Examine.patch +Patch163: 0170-dlink.h-Fix-checkpatch-warnings-for-function-args.patch +Patch164: 0171-Incremental-support-devnode-in-IncrementalRemove.patch +Patch165: 0172-Detail.c-Fix-divide_by_zero-issue.patch +Patch166: 0173-mdadm-Add-compilation-process-to-README.md.patch +Patch167: 0174-mdadm-Grow-Update-new-level-when-starting-reshape.patch +Patch168: 0175-mdadm-Grow-Update-reshape_progress-to-need_back-afte.patch +Patch169: 0176-mdadm-Grow-Can-t-open-raid-when-running-grow-continu.patch +Patch170: 0177-mdadm-Grow-sleep-a-while-after-removing-disk-in-impo.patch +Patch171: 0178-mdadm-tests-wait-until-level-changes.patch +Patch172: 0179-mdadm-tests-07changelevels-fix.patch +Patch173: 0180-mdadm-tests-Remove-07reshape5intr.broken.patch +Patch174: 0181-mdadm-tests-07testreshape5-fix.patch +Patch175: 0182-mdadm-tests-remove-09imsm-assemble.broken.patch +Patch176: 0183-mdadm-Manage-record-errno.patch +Patch177: 0184-Remove-INSTALL-and-dev-null.patch +Patch178: 0186-Incremental-Rename-IncrementalRemove.patch +Patch179: 0187-sysfs-add-function-for-writing-to-sysfs-fd.patch +Patch180: 0188-Mdmonitor-Fix-startup-with-missing-directory.patch +Patch181: 0189-mdadm-add-xmalloc.h.patch +Patch182: 0190-md.man-update-refference-to-raid5-ppl.rst.patch +Patch183: 0191-util-fix-sys_hot_remove_disk.patch +Patch184: 0192-Rename-Monitor.c-to-mdmonitor.c.patch +Patch185: 0193-super-intel-move-scsi_get_serial-from-sg_io.patch +Patch186: 0194-mdmonitor-Abandon-custom-configuration-files.patch +Patch187: 0195-mdadm.man-elaborate-more-about-mdmonitor.service.patch +Patch188: 0196-mdadm-Add-mdadm_status.h.patch +Patch189: 0197-mdadm.conf.man-Explain-udev-rule.patch +Patch190: 0198-mdadm.man-Add-udev-rules-flag.patch +Patch191: 0199-util-use-only-dev-directory-in-open_dev.patch +Patch192: 0200-mdadm-Manage-Clear-superblock-if-adding-new-device-f.patch +Patch193: 0201-mdadm-Grow-Check-new_level-interface-rather-than-ker.patch # Fedora customization patches @@ -165,6 +291,10 @@ install -m644 %{SOURCE5} %{buildroot}/etc/libreport/events.d /usr/share/mdadm/mdcheck %changelog +* Sat Oct 19 2024 Xiao Ni 4.3-4 +- Update to latest upstream +- Resolves RHEL-52059 RHEL-40729 RHEL-31448 + * Sun Aug 11 2024 Xiao Ni 4.3-3 - /dev/md symlink not created for second RAID container - Resolves RHEL-50456