From bc91465ba5673cfe67eb7dab111ca422f769121c Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Mon, 16 Feb 2026 12:25:37 +0100 Subject: [PATCH 01/40] multipath-tools: add missing colon to the multipath output Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Martin Wilck (cherry picked from commit baffc26c8f07856e14a64390b7e7564e5b4bac4f) --- libmultipath/propsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index 56895c4bb..0c10ebc1c 100644 --- a/libmultipath/propsel.c +++ b/libmultipath/propsel.c @@ -640,7 +640,7 @@ int select_checker_timeout(struct config *conf, struct path *pp) } pp_set_default(checker_timeout, DEF_TIMEOUT); out: - condlog(3, "%s checker timeout = %u s %s", pp->dev, pp->checker_timeout, + condlog(3, "%s: checker timeout = %u s %s", pp->dev, pp->checker_timeout, origin); return 0; } From abc05fe59c7b1746a9d4bf866042171df82c07ce Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 13 Apr 2026 18:38:35 -0400 Subject: [PATCH 02/40] libmultipath: Handle SCSI-2 style vpd page 0x83 descriptors Some older SCSI devices return a SCSI-2 style vpd page 0x83, instead of a SPC-2/3 format one. The SCSI-2 page 83 format returns an IEEE WWN in binary encoded hexi-decimal in the 16 bytes following the initial 4-byte page 83 reply header. Check the 7th byte of the vpd page 83 buffer to determine whether this is a SCSI-2 or SPC-2/3 confomant one. Byte 7 is the 3rd byte of first Identification descriptor in a SPC-2/3 confromant vpd page 83. This is a reserved field, and is guaranteed to be 0. If it is not zero, then it is likely the 3rd byte of a SCSI-2 Identifier (The first 3 bytes of the ID are the Organizationally Unique Identifier). Both the sg_inq and scsi_id commands handle vpd page 83 this way. To make sure that the WWID which multipath reads directly from the device matches, it should handle this format as well. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit ed6f6aef4fd7f763beb2cb43d509c4d191d973f2) --- libmultipath/discovery.c | 13 +++++++++ tests/vpd.c | 58 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index 0efb8213d..f59fa6d4a 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -1208,6 +1208,18 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, if (out_len <= 1) return 0; + /* + * Not a valid SPC-2/3 vpd page 83. Assume it's a SCSI-2 style + * descriptor. + */ + if (in_len >= 20 && in[6] != 0) { + len = 0; + vpd_type = 0x3; + vpd_len = in_len - 4; + vpd = in + 4; + goto decode; + } + d = in + 4; while (d <= in + in_len - 4) { bool invalid = false; @@ -1323,6 +1335,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, vpd_type = vpd[1] & 0xf; vpd_len = vpd[3]; vpd += 4; +decode: /* untaint vpd_len for coverity */ if (vpd_len > WWID_SIZE) { condlog(1, "%s: suspicious designator length %zu truncated to %u", diff --git a/tests/vpd.c b/tests/vpd.c index f9e22cd87..b02179483 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -331,6 +331,28 @@ static int create_vpd83(unsigned char *buf, size_t bufsiz, const char *id, return n + 4; } +/** + * create_pre_spc3_vpd83() - create pre-SPC3 "device identification" VPD page + * + * @buf, @bufsiz: see above. + * @id: input ID (third byte must be non-zero) + * + * Create a pre-SPC3 "device identification" VPD page. See comments in + * sg3_utils/src/sg_inq.c for details + * + * Return: VPD page length. + */ +static int create_pre_spc3_vpd83(unsigned char *buf, size_t bufsize, + const char *id) +{ + memset(buf, 0, bufsize); + buf[1] = 0x83; + + hex2bin(buf + 4, id, 16, 32); + put_unaligned_be16(16, buf + 2); + return 20; +} + /** * assert_correct_wwid() - test that a retrieved WWID matches expectations * @test: test name @@ -479,6 +501,30 @@ static void test_vpd_str_ ## typ ## _ ## len ## _ ## wlen(void **state) \ test_id, vt->wwid); \ } +/** + * test_vpd_prespc3_WLEN() - test code for pre-SPC3 VPD 83 + * @WLEN: WWID buffer size + */ +#define make_test_vpd_prespc3(wlen) \ +static void test_vpd_prespc3_ ## wlen(void **state) \ +{ \ + struct vpdtest *vt = *state; \ + int n, ret; \ + int exp_len; \ + \ + /* returned size is always uneven */ \ + exp_len = wlen > 33 ? 33 : \ + wlen % 2 == 0 ? wlen - 1 : wlen - 2; \ + \ + n = create_pre_spc3_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), \ + test_id); \ + wrap_will_return(WRAP_IOCTL, n); \ + wrap_will_return(WRAP_IOCTL, vt->vpdbuf); \ + ret = get_vpd_sgio(10, 0x83, 0, vt->wwid, wlen); \ + assert_correct_wwid("test_vpd_prespc3_" #wlen, exp_len, ret, \ + '3', 0, true, test_id, vt->wwid); \ +} + /** * test_vpd_naa_NAA_WLEN() - test code for VPD 83 NAA designation * @NAA: Network Name Authority (2, 3, 5, or 6) @@ -814,6 +860,13 @@ make_test_vpd_str(18, 20, 17) make_test_vpd_str(18, 20, 16) make_test_vpd_str(18, 20, 15) +/* PRE-SPC3, WWID size: 34 */ +make_test_vpd_prespc3(40) +make_test_vpd_prespc3(34) +make_test_vpd_prespc3(33) +make_test_vpd_prespc3(32) +make_test_vpd_prespc3(20) + static int test_vpd(void) { const struct CMUnitTest tests[] = { @@ -945,6 +998,11 @@ static int test_vpd(void) cmocka_unit_test(test_vpd_str_18_20_17), cmocka_unit_test(test_vpd_str_18_20_16), cmocka_unit_test(test_vpd_str_18_20_15), + cmocka_unit_test(test_vpd_prespc3_40), + cmocka_unit_test(test_vpd_prespc3_34), + cmocka_unit_test(test_vpd_prespc3_33), + cmocka_unit_test(test_vpd_prespc3_32), + cmocka_unit_test(test_vpd_prespc3_20), }; return cmocka_run_group_tests(tests, setup, teardown); } From b603d3cc43d439ec760434d51f9a032a6f2981d2 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 19 Mar 2026 16:29:52 +0100 Subject: [PATCH 03/40] multipathd: get_new_state: map PATH_TIMEOUT to PATH_DOWN We map PATH_TIMEOUT to PATH_DOWN in pathinfo(), but not in get_new_state(). Do it there, too, to treat the states consistently. This avoids logging "checker timed out" twice in update_path_state(), even if log_checker_err is set to "once". Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 8933b22b82c49f2a240193c4dd20105f7f1df26e) --- multipathd/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/multipathd/main.c b/multipathd/main.c index d87c7b127..9bce4d6be 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -2503,8 +2503,10 @@ get_new_state(struct path *pp) * Wait for uevent for removed paths; * some LLDDs like zfcp keep paths unavailable * without sending uevents. + * Also, map PATH_TIMEOUT to PATH_DOWN here, like we do in + * pathinfo(). */ - if (newstate == PATH_REMOVED) + if (newstate == PATH_REMOVED || newstate == PATH_TIMEOUT) newstate = PATH_DOWN; /* From bc180b6eb39e03500b5d4aa65cc1b63bf0d3f0e3 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 11 Jun 2026 09:25:18 +0200 Subject: [PATCH 04/40] kpartx: Fix integer overflow in GPT size calculation A crafted GPT table with num_partition_entries >= 0x02000000 can trigger an integer overflow in kpartx. Fix it by casting one operand of the multiplication to size_t. Same as kernel commit c5082b70adfe ("partitions/efi: Fix integer overflow in GPT size calculation"). Signed-off-by: Martin Wilck Reported-by: Tristan Reviewed-by: Benjamin Marzinski (cherry picked from commit 15310a33712447fa740d396fddc1e5ddac466c0a) --- kpartx/gpt.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/kpartx/gpt.c b/kpartx/gpt.c index 69ddce99a..df5c42eaa 100644 --- a/kpartx/gpt.c +++ b/kpartx/gpt.c @@ -52,6 +52,12 @@ #define BLKGETSIZE64 _IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */ #endif +/* + * The max size of a partition table that we will read for calculating the CRC. + * Note that this is much larger than MAX_SLICES. It's 0x02000000 on most systems. + */ +#define MAX_PT_SIZE ((SIZE_MAX <= UINT32_MAX ? SIZE_MAX : UINT32_MAX) / sizeof(gpt_entry)) + struct blkdev_ioctl_param { unsigned int block; size_t content_length; @@ -70,8 +76,7 @@ struct blkdev_ioctl_param { * Note, the EFI Specification, v1.02, has a reference to * Dr. Dobbs Journal, May 1994 (actually it's in May 1992). */ -static inline uint32_t -efi_crc32(const void *buf, unsigned long len) +static inline uint32_t efi_crc32(const void *buf, size_t len) { return (crc32(~0L, buf, len) ^ ~0L); } @@ -226,10 +231,15 @@ static gpt_entry * alloc_read_gpt_entries(int fd, gpt_header * gpt) { gpt_entry *pte; - size_t count = __le32_to_cpu(gpt->num_partition_entries) * - __le32_to_cpu(gpt->sizeof_partition_entry); + size_t num_entries = __le32_to_cpu(gpt->num_partition_entries); + uint32_t sizeof_pe = __le32_to_cpu(gpt->sizeof_partition_entry); + size_t count; - if (!count) return NULL; + if (!sizeof_pe || num_entries > MAX_PT_SIZE) + return NULL; + count = num_entries * sizeof_pe; + if (!count) + return NULL; if (aligned_malloc((void **)&pte, get_sector_size(fd), &count)) return NULL; @@ -284,6 +294,8 @@ is_gpt_valid(int fd, uint64_t lba, { int rc = 0; /* default to not valid */ uint32_t crc, origcrc; + size_t num_pe; + uint32_t sizeof_pe; if (!gpt || !ptes) return 0; @@ -341,20 +353,25 @@ is_gpt_valid(int fd, uint64_t lba, } /* Check the GUID Partition Entry Array CRC */ - crc = efi_crc32(*ptes, - __le32_to_cpu((*gpt)->num_partition_entries) * - __le32_to_cpu((*gpt)->sizeof_partition_entry)); - if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) { - // printf("GUID Partition Entry Array CRC check failed.\n"); - free(*gpt); - *gpt = NULL; - free(*ptes); - *ptes = NULL; - return 0; - } + num_pe = __le32_to_cpu((*gpt)->num_partition_entries); + sizeof_pe = __le32_to_cpu((*gpt)->sizeof_partition_entry); + + if (num_pe > MAX_PT_SIZE) + goto bad_crc; + crc = efi_crc32(*ptes, num_pe * sizeof_pe); + if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) + goto bad_crc; /* We're done, all's well */ return 1; + +bad_crc: + // printf("GUID Partition Entry Array CRC check failed.\n"); + free(*gpt); + *gpt = NULL; + free(*ptes); + *ptes = NULL; + return 0; } /** * compare_gpts() - Search disk for valid GPT headers and PTEs From 5eeff68e0ca1b34410d9009b5698b3c47dfb8bb0 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 11 Jun 2026 16:36:34 +0200 Subject: [PATCH 05/40] kpartx: use mmap() to implement alloc_read_gpt_entries() A maliciously crafted partition table could cause an unnecessarily large memory allocation. By using mmap(), we can calculate the checksum without needing to allocate space for more than the supported number of partitions. Tested with odd values of MAX_SLICES like 1, 2, 4, 7, 8, 19. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 8697ea7e35b85dba8a79c9977a0f86f2d28786e6) --- kpartx/gpt.c | 100 +++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/kpartx/gpt.c b/kpartx/gpt.c index df5c42eaa..1068da2e3 100644 --- a/kpartx/gpt.c +++ b/kpartx/gpt.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "crc32.h" #include "kpartx.h" @@ -227,29 +228,48 @@ read_lba(int fd, uint64_t lba, void *buffer, size_t bytes) * Allocates space for PTEs based on information found in @gpt. * Notes: remember to free pte when you're done! */ -static gpt_entry * -alloc_read_gpt_entries(int fd, gpt_header * gpt) +static gpt_entry *alloc_read_gpt_entries(int fd, gpt_header *gpt, unsigned int ns) { - gpt_entry *pte; + gpt_entry *pte = NULL; size_t num_entries = __le32_to_cpu(gpt->num_partition_entries); - uint32_t sizeof_pe = __le32_to_cpu(gpt->sizeof_partition_entry); - size_t count; - - if (!sizeof_pe || num_entries > MAX_PT_SIZE) - return NULL; - count = num_entries * sizeof_pe; - if (!count) + size_t n_alloc = num_entries <= ns ? num_entries : ns; + long pagesz = sysconf(_SC_PAGESIZE); + off_t ofs = __le64_to_cpu(gpt->partition_entry_lba) * get_sector_size(fd); + off_t ofs_aligned = ofs & ~(pagesz - 1); + uint32_t crc; + size_t arr_len, count; + unsigned char *pe_map; + + if (!num_entries || num_entries > MAX_PT_SIZE) return NULL; - if (aligned_malloc((void **)&pte, get_sector_size(fd), &count)) - return NULL; - memset(pte, 0, count); + arr_len = num_entries * sizeof(gpt_entry); + ofs -= ofs_aligned; + pe_map = mmap(NULL, arr_len + ofs, PROT_READ, MAP_SHARED, fd, ofs_aligned); - if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte, - count)) { - free(pte); + if (pe_map == MAP_FAILED) { + fprintf(stderr, "%s: mmap failed: %s\n", __func__, strerror(errno)); return NULL; } + + crc = efi_crc32(pe_map + ofs, arr_len); + if (crc != __le32_to_cpu(gpt->partition_entry_array_crc32)) { + fprintf(stderr, "%s: CRC32 checksum mismatch", __func__); + goto out; + } + + count = n_alloc * sizeof(gpt_entry); + pte = malloc(count); + if (pte == NULL) + goto out; + + memcpy(pte, pe_map + ofs, count); + if (n_alloc < num_entries) + fprintf(stderr, + "%s: partition table size (%zu) is larger than supported (%zu)\n", + __func__, num_entries, n_alloc); +out: + munmap(pe_map, arr_len + ofs); return pte; } @@ -288,14 +308,11 @@ alloc_read_gpt_header(int fd, uint64_t lba) * Description: returns 1 if valid, 0 on error. * If valid, returns pointers to newly allocated GPT header and PTEs. */ -static int -is_gpt_valid(int fd, uint64_t lba, - gpt_header ** gpt, gpt_entry ** ptes) +static int is_gpt_valid(int fd, uint64_t lba, gpt_header **gpt, + gpt_entry **ptes, unsigned int ns) { int rc = 0; /* default to not valid */ uint32_t crc, origcrc; - size_t num_pe; - uint32_t sizeof_pe; if (!gpt || !ptes) return 0; @@ -346,33 +363,16 @@ is_gpt_valid(int fd, uint64_t lba, return 0; } - if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) { + if (!(*ptes = alloc_read_gpt_entries(fd, *gpt, ns))) { free(*gpt); *gpt = NULL; return 0; } - /* Check the GUID Partition Entry Array CRC */ - num_pe = __le32_to_cpu((*gpt)->num_partition_entries); - sizeof_pe = __le32_to_cpu((*gpt)->sizeof_partition_entry); - - if (num_pe > MAX_PT_SIZE) - goto bad_crc; - crc = efi_crc32(*ptes, num_pe * sizeof_pe); - if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) - goto bad_crc; - /* We're done, all's well */ return 1; - -bad_crc: - // printf("GUID Partition Entry Array CRC check failed.\n"); - free(*gpt); - *gpt = NULL; - free(*ptes); - *ptes = NULL; - return 0; } + /** * compare_gpts() - Search disk for valid GPT headers and PTEs * @pgpt is the primary GPT header @@ -494,8 +494,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba) * Validity depends on finding either the Primary GPT header and PTEs valid, * or the Alternate GPT header and PTEs valid, and the PMBR valid. */ -static int -find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes) +static int find_valid_gpt(int fd, gpt_header **gpt, gpt_entry **ptes, unsigned int ns) { int good_pgpt = 0, good_agpt = 0, good_pmbr = 0; gpt_header *pgpt = NULL, *agpt = NULL; @@ -508,20 +507,17 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes) if (!(lastlba = last_lba(fd))) return 0; - good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA, - &pgpt, &pptes); + good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, + &pptes, ns); if (good_pgpt) { - good_agpt = is_gpt_valid(fd, - __le64_to_cpu(pgpt->alternate_lba), - &agpt, &aptes); + good_agpt = is_gpt_valid(fd, __le64_to_cpu(pgpt->alternate_lba), + &agpt, &aptes, ns); if (!good_agpt) { - good_agpt = is_gpt_valid(fd, lastlba, - &agpt, &aptes); + good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes, ns); } } else { - good_agpt = is_gpt_valid(fd, lastlba, - &agpt, &aptes); + good_agpt = is_gpt_valid(fd, lastlba, &agpt, &aptes, ns); } /* The obviously unsuccessful case */ @@ -614,7 +610,7 @@ read_gpt_pt (int fd, __attribute__((unused)) struct slice all, int last_used_index = -1; int sector_size_mul = get_sector_size(fd)/512; - if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) { + if (!find_valid_gpt(fd, &gpt, &ptes, ns) || !gpt || !ptes) { if (gpt) free (gpt); if (ptes) From 264b85809e240e949511188f821a44f1aecd3ddb Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 11 Jun 2026 17:23:20 +0200 Subject: [PATCH 06/40] kpartx: dasd: avoid out-of-bounds write in read_dasd_pt() Make sure not to write to the struct slice array sp beyond the upper bound (ns). Signed-off-by: Martin Wilck Reported-by: Tristan Reviewed-by: Benjamin Marzinski (cherry picked from commit d08eefd5150470547d6cc38db597dfa5ede80b01) --- kpartx/dasd.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kpartx/dasd.c b/kpartx/dasd.c index 337d5f45c..a044ec638 100644 --- a/kpartx/dasd.c +++ b/kpartx/dasd.c @@ -53,9 +53,8 @@ typedef unsigned int __attribute__((__may_alias__)) label_ints_t; /* */ -int -read_dasd_pt(int fd, __attribute__((unused)) struct slice all, - struct slice *sp, __attribute__((unused)) unsigned int ns) +int read_dasd_pt(int fd, __attribute__((unused)) struct slice all, + struct slice *sp, unsigned int ns) { int retval = -1; int blocksize; @@ -243,6 +242,8 @@ read_dasd_pt(int fd, __attribute__((unused)) struct slice all, sp[counter].start = sectors512(offset, blocksize); sp[counter].size = sectors512(size, blocksize); counter++; + if ((unsigned int)counter >= ns) + break; blk++; } retval = counter; From fde0ad34e4628331abd2274417660b0b9e6657df Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 11 Jun 2026 17:27:09 +0200 Subject: [PATCH 07/40] kpartx: dasd: avoid infinite loop in read_dasd_pt Make sure that the loop terminates if read() encounters EOF and returns 0. Found with the help of Claude Sonnet 4.6. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit cd77a2be8967c2dfa24a2b8d0142d71008d1ef1b) --- kpartx/dasd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kpartx/dasd.c b/kpartx/dasd.c index a044ec638..7d8a14ccd 100644 --- a/kpartx/dasd.c +++ b/kpartx/dasd.c @@ -216,7 +216,7 @@ int read_dasd_pt(int fd, __attribute__((unused)) struct slice all, if (lseek(fd_dasd, blk * blocksize, SEEK_SET) == -1) goto out; - while (read(fd_dasd, data, blocksize) != -1) { + while (read(fd_dasd, data, blocksize) > 0) { format1_label_t f1; memcpy(&f1, data, sizeof(format1_label_t)); From e2039568fd66414269abe24930d3a9e3c01e1065 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 11 Jun 2026 17:30:13 +0200 Subject: [PATCH 08/40] kpartx: dasd: double check blocksize bounds after reading it from disk Avoid a crash when a maliciously crafted disk image reports an invalid block size. Allowed blocksizes are between 512 and 4096 bytes [1]. Found withe the help of Claude Sonnet 4.6. [1] https://www.ibm.com/docs/en/zvm/7.4.0?topic=commands-format Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 6179c2dfb750a269766ab0c211247c3ec82cb7bf) --- kpartx/dasd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kpartx/dasd.c b/kpartx/dasd.c index 7d8a14ccd..108e2303f 100644 --- a/kpartx/dasd.c +++ b/kpartx/dasd.c @@ -192,6 +192,8 @@ int read_dasd_pt(int fd, __attribute__((unused)) struct slice all, label_ints_t *label = (label_ints_t *) &vlabel; blocksize = label[4]; + if (blocksize < 512 || blocksize > 4096) + goto out; if (label[14] != 0) { /* disk is reserved minidisk */ offset = label[14]; From 50dda54423c07d4b83acdc64d97d97b833822f8a Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 11 Jun 2026 17:33:09 +0200 Subject: [PATCH 09/40] kpartx: dasd: avoid negative partition size Make sure that size - sp[0].start does not result in a negative value. Found withe the help of Claude Sonnet 4.6. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit c616a95e00d145ae6f97ad03cd00918991c2c997) --- kpartx/dasd.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/kpartx/dasd.c b/kpartx/dasd.c index 108e2303f..9062e9041 100644 --- a/kpartx/dasd.c +++ b/kpartx/dasd.c @@ -59,7 +59,7 @@ int read_dasd_pt(int fd, __attribute__((unused)) struct slice all, int retval = -1; int blocksize; uint64_t disksize; - uint64_t offset, size, fmt_size; + uint64_t offset, size, fmt_size, start; dasd_information_t info; struct hd_geometry geo; char type[5] = {0,}; @@ -202,8 +202,11 @@ int read_dasd_pt(int fd, __attribute__((unused)) struct slice all, offset = info.label_block + 1; size = sectors512(label[8], blocksize); } - sp[0].start = sectors512(offset, blocksize); - sp[0].size = size - sp[0].start; + start = sectors512(offset, blocksize); + if (start >= size) + goto out; + sp[0].start = start; + sp[0].size = size - start; retval = 1; } else if ((strncmp(type, "VOL1", 4) == 0) && (!info.FBA_layout) && (!memcmp(info.type, "ECKD",4))) { @@ -276,8 +279,11 @@ int read_dasd_pt(int fd, __attribute__((unused)) struct slice all, } else size = disksize; - sp[0].start = sectors512(info.label_block + 1, blocksize); - sp[0].size = size - sp[0].start; + start = sectors512(info.label_block + 1, blocksize); + if (start >= size) + goto out; + sp[0].start = start; + sp[0].size = size - start; retval = 1; } From 8347f8f39a326941b965a0b9f6d8ff928b5ab89a Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 15 Jun 2026 19:36:11 -0400 Subject: [PATCH 10/40] libmultipath: don't set hwhander for bio based devices The kernel prints an error message when a bio-based multipath device sets a hardware handler, since bio-based devices only support using the already attached hardware handler as-is. Change select_hwhandler() to not set a hardware handler for bio-based devices. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit b6c7aab40ea83eafd634907794c21b5ba6f68e4d) --- libmultipath/propsel.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index 0c10ebc1c..2c3733896 100644 --- a/libmultipath/propsel.c +++ b/libmultipath/propsel.c @@ -582,6 +582,11 @@ int select_hwhandler(struct config *conf, struct multipath *mp) dh_state = &handler[2]; + if (mp->queue_mode == QUEUE_MODE_BIO) { + mp->hwhandler = DEFAULT_HWHANDLER; + origin = "(setting: disabled due to \"queue_mode bio\")"; + goto set; + } /* * TPGS_UNDEF means that ALUA support couldn't determined either way * yet, probably because the path was always down. @@ -622,6 +627,7 @@ int select_hwhandler(struct config *conf, struct multipath *mp) mp->hwhandler = DEFAULT_HWHANDLER; origin = tpgs_origin; } +set: mp->hwhandler = strdup(mp->hwhandler); condlog(3, "%s: hardware_handler = \"%s\" %s", mp->alias, mp->hwhandler, origin); From 9ea11367a626932d365a63601a53f67f7648ae3a Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 31 May 2026 12:38:27 +0200 Subject: [PATCH 11/40] multipath-tools: align ALUA state strings with kernel scsi_sysfs Update ALUA asymmetric access state descriptions in the prioritizer to match the shorter names defined in the SCSI kernel subsystem: $ grep "{ SCSI_ACCESS_STATE_" linux/drivers/scsi/scsi_sysfs.c { SCSI_ACCESS_STATE_OPTIMAL, "active/optimized" }, { SCSI_ACCESS_STATE_ACTIVE, "active/non-optimized" }, { SCSI_ACCESS_STATE_STANDBY, "standby" }, { SCSI_ACCESS_STATE_UNAVAILABLE, "unavailable" }, { SCSI_ACCESS_STATE_LBA, "lba-dependent" }, { SCSI_ACCESS_STATE_OFFLINE, "offline" }, { SCSI_ACCESS_STATE_TRANSITIONING, "transitioning" }, This unifies diagnostic strings across the stack and replaces the misleading "ARRAY BUG: invalid TPGs state!" message with the standard SPC "reserved" designation. These codes are explicitly reserved for future standard definitions rather than being treated as malformed states. Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Martin Wilck (cherry picked from commit fa2eb1268bf66332b859259051308030f78001fc) --- libmultipath/prioritizers/alua.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libmultipath/prioritizers/alua.c b/libmultipath/prioritizers/alua.c index ec68f3702..3aedbda15 100644 --- a/libmultipath/prioritizers/alua.c +++ b/libmultipath/prioritizers/alua.c @@ -26,16 +26,18 @@ #define ALUA_PRIO_TPGS_FAILED 4 #define ALUA_PRIO_NO_INFORMATION 5 +// clang-format off static const char * aas_string[] = { [AAS_OPTIMIZED] = "active/optimized", [AAS_NON_OPTIMIZED] = "active/non-optimized", [AAS_STANDBY] = "standby", [AAS_UNAVAILABLE] = "unavailable", - [AAS_LBA_DEPENDENT] = "logical block dependent", - [AAS_RESERVED] = "ARRAY BUG: invalid TPGs state!", + [AAS_LBA_DEPENDENT] = "lba-dependent", + [AAS_RESERVED] = "reserved", [AAS_OFFLINE] = "offline", - [AAS_TRANSITIONING] = "transitioning between states", + [AAS_TRANSITIONING] = "transitioning", }; +// clang-format on static const char *aas_print_string(int rc) { From 123abdbc3d6be8a30ed7069019fa577a24bbd5e0 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Tue, 16 Jun 2026 14:28:58 +0200 Subject: [PATCH 12/40] multipath-tools: remove explicit width from .TP macros in multipath.conf.5 This allows man/groff to calculate the width automatically, preventing excessive whitespace and improving readability on various terminal sizes. Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- multipath/multipath.conf.5.in | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in index 84cd1a0ab..fb93661d4 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -103,7 +103,7 @@ matches, standard regular expression syntax using the special characters "^" and .LP . The following \fIsection\fP keywords are recognized: -.TP 17 +.TP .B defaults This section defines default values for attributes which are used whenever no values are given in the appropriate device or multipath @@ -142,7 +142,7 @@ device-specific settings for all devices. The \fIdefaults\fR section recognizes the following keywords: . . -.TP 17 +.TP .B verbosity Default verbosity. Higher values increase the verbosity level. Valid levels are between 0 and 6. @@ -195,7 +195,7 @@ The default is: \fBno\fR The default path selector algorithm to use; they are offered by the kernel multipath target: .RS -.TP 12 +.TP .I "round-robin 0" Choose the path for the next bunch of I/O by looping through every path in the path group, sending \fBthe same number of I/O requests\fR to each path. Some @@ -224,7 +224,7 @@ The default is: \fBservice-time 0\fR (Hardware-dependent) The default path grouping policy to apply to unspecified multipaths. Possible values are: .RS -.TP 12 +.TP .I failover One path per priority group. .TP @@ -334,7 +334,7 @@ of this path. Higher number have a higher priority. \fI"none"\fR is a valid value. Currently the following path priority routines are implemented: .RS -.TP 12 +.TP .I const Return a constant priority of \fI1\fR. .TP @@ -409,12 +409,12 @@ NetAPP E/EF Series, where it is \fBalua\fR). If \fBdetect_prio\fR is Arguments to pass to to the prio function. This only applies to certain prioritizers: .RS -.TP 12 +.TP .I weighted Needs a value of the form \fI" ..."\fR .RS -.TP 8 +.TP .I hbtl Regex can be of SCSI H:B:T:L format. For example: 1:0:.:. , *:0:0:. .TP @@ -431,11 +431,11 @@ Regex can be of the form \fI"host_wwnn:host_wwpn:target_wwnn:target_wwpn"\fR these values can be looked up through sysfs or by running \fImultipathd show paths format "%N:%R:%n:%r"\fR. For example: 0x200100e08ba0aea0:0x210100e08ba0aea0:.*:.* , .*:.*:iqn.2009-10.com.redhat.msp.lab.ask-06:.* .RE -.TP 12 +.TP .I path_latency Needs a value of the form "io_num=\fI<20>\fR base_num=\fI<10>\fR" .RS -.TP 8 +.TP .I io_num The number of read IOs sent to the current path continuously, used to calculate the average path latency. Valid Values: Integer, [20, 200]. @@ -446,7 +446,7 @@ Double-precision floating-point, [1.1, 10]. And Max average latency value is 100 For example: If base_num=10, the paths will be grouped in priority groups with path latency <=1us, (1us, 10us], (10us, 100us], (100us, 1ms], (1ms, 10ms], (10ms, 100ms], (100ms, 1s], (1s, 10s], (10s, 100s], >100s. .RE -.TP 12 +.TP .I alua If \fIexclusive_pref_bit\fR is set, paths with the \fIpreferred path\fR bit set will always be in their own path group. @@ -457,17 +457,17 @@ set will always be in their own path group. .TP .I datacore .RS -.TP 8 +.TP .I preferredsds (Mandatory) The preferred "SDS name". .TP .I timeout (Optional) The timeout for the INQUIRY, in ms. .RE -.TP 12 +.TP .I iet .RS -.TP 8 +.TP .I preferredip=... (Mandatory) Th preferred IP address, in dotted decimal notation, for iSCSI targets. .RE @@ -482,7 +482,7 @@ Specify any device-mapper features to be used. Syntax is \fInum list\fR where \fInum\fR is the number, between 0 and 8, of features in \fIlist\fR. Possible values for the feature list are: .RS -.TP 12 +.TP .I queue_if_no_path (Deprecated, superseded by \fIno_path_retry\fR) Queue I/O if no path is active. Identical to the \fIno_path_retry\fR with \fIqueue\fR value. If both this @@ -521,7 +521,7 @@ to respond. The asynchronous checkers (\fItur\fR and \fIdirectio\fR) will not pause multipathd. Instead, multipathd will check for a response once per second, until \fIchecker_timeout\fR seconds have elapsed. Possible values are: .RS -.TP 12 +.TP .I readsector0 (Deprecated) Read the first sector of the device. This checker is being deprecated, please use \fItur\fR or \fIdirectio\fR instead. @@ -575,7 +575,7 @@ Tell multipathd how to manage path group failback. To select \fIimmediate\fR or a \fIvalue\fR, it's mandatory that the device has support for a working prioritizer. .RS -.TP 12 +.TP .I immediate Immediately failback to the highest priority pathgroup that contains active paths. @@ -650,7 +650,7 @@ The default is: \fBuniform\fR .B no_path_retry Specify what to do when all paths are down. Possible values are: .RS -.TP 12 +.TP .I value > 0 Number of retries until disable I/O queueing. .TP @@ -1192,7 +1192,7 @@ blocked from further processing by higher layers - such as LVM - if and only if it\'s considered a valid multipath device path), and b) when multipathd detects a new device. The following values are possible: .RS -.TP 10 +.TP .I strict Both multipath and multipathd treat only such devices as multipath devices which have been part of a multipath map previously, and which are therefore @@ -1460,7 +1460,7 @@ by multipath-tools. . The following keywords are recognized in both sections. The defaults are empty unless explicitly stated. -.TP 17 +.TP .B devnode Regular expression matching the device nodes to be excluded/included. .RS @@ -1550,7 +1550,7 @@ from later entries take precedence. . . The \fImultipath\fR subsection recognizes the following attributes: -.TP 17 +.TP .B wwid (Mandatory) World Wide Identifier. Detected multipath maps are matched against this attribute. Note that, unlike the \fIwwid\fR attribute in the \fIblacklist\fR section, @@ -1569,7 +1569,7 @@ section: .sp 1 .PD .1v .RS -.TP 18 +.TP .B path_grouping_policy .TP .B path_selector @@ -1632,7 +1632,7 @@ section: .SH "devices section" .\" ---------------------------------------------------------------------------- . -.TP 4 +.TP .B Important: The built-in hardware device table of .I multipath-tools @@ -1668,7 +1668,7 @@ for all devices in the system. .LP . The \fIdevice\fR subsection recognizes the following attributes: -.TP 17 +.TP .B vendor (Mandatory) Regular expression to match the vendor name. .RS @@ -1711,7 +1711,7 @@ and \fImultipathd show paths format\fR commands. Currently only the The hardware handler to use for this device type. The following hardware handler are implemented: .RS -.TP 12 +.TP .I 1 emc (Hardware-dependent) Hardware handler for DGC class arrays as CLARiiON CX/AX and EMC VNX families @@ -1752,7 +1752,7 @@ section: .sp 1 .PD .1v .RS -.TP 18 +.TP .B path_grouping_policy .TP .B uid_attribute @@ -1836,7 +1836,7 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections: .sp 1 .PD .1v .RS -.TP 18 +.TP .B path_grouping_policy .TP .B uid_attribute @@ -1956,7 +1956,7 @@ which paths belong to the same device. Each path presenting the same WWID is assumed to point to the same device. .LP The WWID is generated by four methods (in the order of preference): -.TP 17 +.TP .B uid_attrs The WWID is derived from udev attributes by matching the device node name; cf \fIuid_attrs\fR above. @@ -1996,7 +1996,7 @@ pathgroups will not be used until all other pathgroups have been tried. At the time when the path would normally be reinstated, it will be returned to its normal pathgroup. The logic of determining \(dqshaky\(dq condition, as well as the logic when to reinstate, differs between the three methods. -.TP 8 +.TP .B \(dqdelay_checks\(dq failure tracking (Deprecated) This method is \fBdeprecated\fR and mapped to the \(dqsan_path_err\(dq method. See the \fIdelay_watch_checks\fR and \fIdelay_wait_checks\fR options above From 3ccc0d300e01ec7c14d8e648a18d52016c9f78d0 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Tue, 16 Jun 2026 14:28:59 +0200 Subject: [PATCH 13/40] multipath-tools: remove explicit widths from macros in the remaining man pages This allows man/groff to calculate the width automatically, preventing excessive whitespace and improving readability on various terminal sizes. Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- libmpathpersist/mpath_persistent_reserve_in.3 | 4 ++-- libmpathpersist/mpath_persistent_reserve_out.3 | 4 ++-- mpathpersist/mpathpersist.8.in | 2 +- multipath/multipath.8.in | 6 +++--- multipath/multipath.conf.5.in | 10 +++++----- multipathd/multipathd.8.in | 9 ++++----- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/libmpathpersist/mpath_persistent_reserve_in.3 b/libmpathpersist/mpath_persistent_reserve_in.3 index 4ac43fa37..871242d56 100644 --- a/libmpathpersist/mpath_persistent_reserve_in.3 +++ b/libmpathpersist/mpath_persistent_reserve_in.3 @@ -35,7 +35,7 @@ the DM device and gets the response. .TP .B Parameters: .RS -.TP 12 +.TP .I fd The file descriptor of a multipath device. Input argument. .TP @@ -57,7 +57,7 @@ Set verbosity level. Input argument. value:[0-3]. 0->Errors, 1->Warnings, 2->Inf .SH RETURNS .\" ---------------------------------------------------------------------------- . -.TP 12 +.TP .B MPATH_PR_SUCCESS If PR command successful. .TP diff --git a/libmpathpersist/mpath_persistent_reserve_out.3 b/libmpathpersist/mpath_persistent_reserve_out.3 index ab1f923e1..bf44777c3 100644 --- a/libmpathpersist/mpath_persistent_reserve_out.3 +++ b/libmpathpersist/mpath_persistent_reserve_out.3 @@ -35,7 +35,7 @@ the DM device and gets the response. .TP .B Parameters: .RS -.TP 12 +.TP .I fd The file descriptor of a multipath device. Input argument. .TP @@ -74,7 +74,7 @@ Set verbosity level. Input argument. value: 0 to 3. 0->Errors, 1->Warnings, 2->I .SH RETURNS .\" ---------------------------------------------------------------------------- . -.TP 12 +.TP .B MPATH_PR_SUCCESS If PR command successful else returns any one of the status mentioned below. .TP diff --git a/mpathpersist/mpathpersist.8.in b/mpathpersist/mpathpersist.8.in index fecef0d63..9a5a716bd 100644 --- a/mpathpersist/mpathpersist.8.in +++ b/mpathpersist/mpathpersist.8.in @@ -50,7 +50,7 @@ various options. .BI \-verbose|\-v " level" Verbosity: .RS -.TP 5 +.TP .I 0 Critical messages. .TP diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in index b88e9a4ca..0b170101b 100644 --- a/multipath/multipath.8.in +++ b/multipath/multipath.8.in @@ -100,7 +100,7 @@ The \fBdevice\fR argument restricts \fBmultipath\fR's operation to devices match expression. The argument may refer either to a multipath map or to its components ("paths"). The expression may be in one of the following formats: . -.TP 1.4i +.TP .B device node file name of a device node, e.g. \fI/dev/dm-10\fR or \fI/dev/sda\fR. If the node refers to an existing device mapper device representing a multipath map, this selects @@ -195,8 +195,8 @@ creating \fI@CONFIGFILE@\fR. .BI \-v " level" Verbosity of information printed to stdout in default and "list" operation modes. The default level is \fI-v 2\fR. -.RS 1.2i -.TP 1.2i +.RS +.TP .I 0 Nothing is printed. .TP diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in index fb93661d4..c2fff75ba 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -1566,7 +1566,7 @@ the same WWID in the \fIbindings_file\fR. The following attributes are optional; if not set the default values are taken from the \fIoverrides\fR, \fIdevices\fR, or \fIdefaults\fR section: -.sp 1 +.sp .PD .1v .RS .TP @@ -1749,7 +1749,7 @@ has no effect. The following attributes are optional; if not set the default values are taken from the \fIdefaults\fR section: -.sp 1 +.sp .PD .1v .RS .TP @@ -1833,7 +1833,7 @@ section: . The overrides section recognizes the following optional attributes; if not set the values are taken from the \fIdevices\fR or \fIdefaults\fR sections: -.sp 1 +.sp .PD .1v .RS .TP @@ -1935,7 +1935,7 @@ exactly. The protocol that a path is using can be viewed by running .LP The following attributes are optional; if not set, the default values are taken from the \fIoverrides\fR, \fIdevices\fR, or \fIdefaults\fR section: -.sp 1 +.sp .PD .1v .RS .TP @@ -2026,7 +2026,7 @@ increase and the threshold is never reached. Ticks are the time between path checks by multipathd, which is variable and controlled by the \fIpolling_interval\fR and \fImax_polling_interval\fR parameters. . -.RS 8 +.RS .LP This algorithm is superseded by the \(dqmarginal_path\(dq failure tracking, but remains supported for backward compatibility. diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in index 38a243e3e..d766dc65b 100644 --- a/multipathd/multipathd.8.in +++ b/multipathd/multipathd.8.in @@ -416,7 +416,7 @@ appropriate device information. The following wildcards are supported. .TP .B Multipath format wildcards .RS -.TP 12 +.TP .B %n The device name. .TP @@ -521,7 +521,7 @@ the configured one). .TP .B Path format wildcards .RS -.TP 12 +.TP .B %w The device WWID (uuid). .TP @@ -548,7 +548,7 @@ sysfs states, it shows "running". .B %T The multipathd path checker state of the device. The possible states are: .RS -.TP 12 +.TP .I ready The device is ready to handle IO. .TP @@ -693,8 +693,7 @@ Overrides the \fImax_fds\fR configuration setting. . .BR multipathc (8), .BR multipath (8), -.BR kpartx (8) -.RE +.BR kpartx (8), .BR sd_notify (3), .BR systemd.service (5). . From c203553dca9f6d4d92ff1477d654a34f1bb78338 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Tue, 16 Jun 2026 14:29:00 +0200 Subject: [PATCH 14/40] multipath-tools: remove syntax check comments from man pages Remove the embedded groff/man command lines from the header comments of all man pages. Suggested-by: Martin Wilck Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- kpartx/kpartx.8 | 4 ---- libmpathpersist/mpath_persistent_reserve_in.3 | 4 ---- libmpathpersist/mpath_persistent_reserve_out.3 | 4 ---- mpathpersist/mpathpersist.8.in | 4 ---- multipath/multipath.8.in | 4 ---- multipath/multipath.conf.5.in | 4 ---- multipathd/multipathc.8 | 4 ---- multipathd/multipathd.8.in | 4 ---- 8 files changed, 32 deletions(-) diff --git a/kpartx/kpartx.8 b/kpartx/kpartx.8 index ef8051a50..fbc8f726b 100644 --- a/kpartx/kpartx.8 +++ b/kpartx/kpartx.8 @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t kpartx/kpartx.8 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z kpartx/kpartx.8 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/libmpathpersist/mpath_persistent_reserve_in.3 b/libmpathpersist/mpath_persistent_reserve_in.3 index 871242d56..5109fb033 100644 --- a/libmpathpersist/mpath_persistent_reserve_in.3 +++ b/libmpathpersist/mpath_persistent_reserve_in.3 @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t libmpathpersist/mpath_persistent_reserve_in.3 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z libmpathpersist/mpath_persistent_reserve_in.3 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/libmpathpersist/mpath_persistent_reserve_out.3 b/libmpathpersist/mpath_persistent_reserve_out.3 index bf44777c3..09708b93d 100644 --- a/libmpathpersist/mpath_persistent_reserve_out.3 +++ b/libmpathpersist/mpath_persistent_reserve_out.3 @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t libmpathpersist/mpath_persistent_reserve_out.3 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z libmpathpersist/mpath_persistent_reserve_out.3 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/mpathpersist/mpathpersist.8.in b/mpathpersist/mpathpersist.8.in index 9a5a716bd..d5f5a4526 100644 --- a/mpathpersist/mpathpersist.8.in +++ b/mpathpersist/mpathpersist.8.in @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t mpathpersist/mpathpersist.8 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z mpathpersist/mpathpersist.8 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in index 0b170101b..da5effb07 100644 --- a/multipath/multipath.8.in +++ b/multipath/multipath.8.in @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t multipath/multipath.8 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z multipath/multipath.8 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in index c2fff75ba..7884f951a 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t multipath/multipath.conf.5 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z multipath/multipath.conf.5 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/multipathd/multipathc.8 b/multipathd/multipathc.8 index cf7ae5be1..5e97fb81a 100644 --- a/multipathd/multipathc.8 +++ b/multipathd/multipathc.8 @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t multipathd/multipathc.8 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z multipathd/multipathc.8 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in index d766dc65b..93625a908 100644 --- a/multipathd/multipathd.8.in +++ b/multipathd/multipathd.8.in @@ -1,8 +1,4 @@ .\" ---------------------------------------------------------------------------- -.\" Make sure there are no errors with: -.\" groff -z -wall -b -e -t multipathd/multipathd.8 -.\" man --warnings -E UTF-8 -l -Tutf8 -Z multipathd/multipathd.8 > /dev/null -.\" .\" Update the date below if you make any significant change. .\" ---------------------------------------------------------------------------- . From f68e22cca85c2ee8dc238a27e898a76b14dba807 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Tue, 16 Jun 2026 14:29:02 +0200 Subject: [PATCH 15/40] multipath-tools: specify file paths using variables and add FILES section in multipath.conf.5 Replace hardcoded file name references with their dynamic build variables. Also, add a dedicated FILES section at the end of the man page to clearly document configuration files/dirs. Suggested-by: Benjamin Marzinski Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- multipath/multipath.conf.5.in | 55 ++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in index 7884f951a..de8f8eb07 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -27,7 +27,7 @@ or \fBmultipathd show config\fR command. . .PP Additional configuration can be made in drop-in files under -.B @CONFIGDIR@. +.BR @CONFIGDIR@/ . Files ending in \fI.conf\fR in this directory are read in alphabetical order, after reading \fI@CONFIGFILE@\fR. They use the same syntax as \fI@CONFIGFILE@\fR itself, @@ -867,11 +867,11 @@ to the end of the reservation key. .RS .PP Alternatively, this can be set to \fBfile\fR, which will store the RESERVATION -KEY registered by mpathpersist in the \fIprkeys_file\fR. multipathd will then -use this key to register additional paths as they appear. When the +KEY registered by mpathpersist in the \fI@STATE_DIR@/prkeys\fR file. multipathd +will then use this key to register additional paths as they appear. When the registration is removed, the RESERVATION KEY is removed from the -\fIprkeys_file\fR. The prkeys file will automatically keep track of whether -the key was registered with \fI--param-aptpl\fR. +\fI@STATE_DIR@/prkeys\fR file. The prkeys file will automatically keep track of +whether the key was registered with \fI--param-aptpl\fR. .TP The default is: \fB\fR .RE @@ -1192,9 +1192,9 @@ detects a new device. The following values are possible: .I strict Both multipath and multipathd treat only such devices as multipath devices which have been part of a multipath map previously, and which are therefore -listed in the \fBwwids_file\fR. Users can manually set up multipath maps using the -\fBmultipathd add map\fR command. Once set up manually, the map is -remembered in the wwids file and will be set up automatically in the future. +listed in the \fI@STATE_DIR@/wwids\fR file. Users can manually set up multipath +maps using the \fBmultipathd add map\fR command. Once set up manually, the map is +remembered in the WWIDs file and will be set up automatically in the future. .TP .I off Multipath behaves like \fBstrict\fR. Multipathd behaves like \fBgreedy\fR. @@ -1554,8 +1554,8 @@ this is \fBnot\fR a regular expression or a substring; WWIDs must match exactly inside the multipaths section. .TP .B alias -Symbolic name for the multipath map. This takes precedence over a an entry for -the same WWID in the \fIbindings_file\fR. +Symbolic name for the multipath map. This takes precedence over an entry for +the same WWID in the \fI@STATE_DIR@/bindings\fR file. .LP . . @@ -1645,9 +1645,9 @@ for more than 100 known multipath-capable storage devices. The devices section can be used to override these settings. If there are multiple matches for a given device, the attributes of all matching entries are applied to it. If an attribute is specified in several matching device subsections, -later entries take precedence. Thus, entries in files under \fIconfig_dir\fR (in -reverse alphabetical order) have the highest precedence, followed by entries -in \fI@CONFIGFILE@\fR; the built-in hardware table has the lowest +later entries take precedence. Thus, entries in files under the \fI@CONFIGDIR@/\fR +directory (in reverse alphabetical order) have the highest precedence, followed +by entries in \fI@CONFIGFILE@\fR; the built-in hardware table has the lowest precedence. Inside a configuration file, later entries have higher precedence than earlier ones. .LP @@ -2087,6 +2087,35 @@ specified the order of precedence is \fIno_path_retry, queue_if_no_path, dev_los . . .\" ---------------------------------------------------------------------------- +.SH "FILES" +.\" ---------------------------------------------------------------------------- +. +Default paths for configuration files and directories: +.TP +.I @CONFIGFILE@ +Main configuration file. +.TP +.I @CONFIGDIR@/ +Directory for configuration drop-in files. +.TP +.I @STATE_DIR@/bindings +Bindings file, used when the \fBuser_friendly_names\fR option is set to +\fByes\fR to assign a persistent and unique alias to each multipath device. +.TP +.I @STATE_DIR@/prkeys +Persistent reservation keys file, used by multipathd to keep track of the +reservation key used for a specific WWID when \fBreservation_key\fR is set +to \fBfile\fR. +.TP +.I @STATE_DIR@/wwids +WWIDs file, used by multipath to keep track of the WWIDs of LUNs for which +multipath devices have been created in the past. +.TP +.I @RUNTIME_DIR@/multipathd.pid +PID file. +. +. +.\" ---------------------------------------------------------------------------- .SH "SEE ALSO" .\" ---------------------------------------------------------------------------- . From 17c469ea31dee63da8e2e94d7ae1a62cd7609292 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Tue, 16 Jun 2026 14:29:03 +0200 Subject: [PATCH 16/40] multipath-tools: clarify user_friendly_names prefix behavior in multipath.conf.5 Clarify that the alias prefix depends on the alias_prefix setting. Cc: Martin Wilck Cc: Benjamin Marzinski Cc: Christophe Varoqui Cc: DM_DEVEL-ML Signed-off-by: Xose Vazquez Perez Reviewed-by: Benjamin Marzinski Reviewed-by: Martin Wilck --- multipath/multipath.conf.5.in | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in index de8f8eb07..e2519d4a1 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -728,11 +728,13 @@ The default is: \fBunused\fR .B user_friendly_names If set to .I yes -, using the bindings file \fI@STATE_DIR@/bindings\fR to assign a persistent -and unique alias to the multipath, in the form of mpath. If set to +, the bindings file \fI@STATE_DIR@/bindings\fR is used to assign a persistent +and unique alias to the multipath, in the form of \fIprefix\fR (where +\fIprefix\fR is defined by \fIalias_prefix\fR; by default \fImpath\fR). +If set to .I no -use the WWID as the alias. In either case this be will -be overridden by any specific aliases in the \fImultipaths\fR section. +, the WWID is used as the alias. In either case, this will be overridden +by any specific aliases defined in the \fImultipaths\fR section. .RS .TP The default is: \fBno\fR From 888e338891f6bcb6fd45c90fee6c1240d2bbc112 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 18 Jun 2026 21:31:45 +0200 Subject: [PATCH 17/40] .clang-format: set Cpp11BracedListStyle: false This avoids reformatting the subsequent patch "libmultipath: deprecate rr_min_io_rq, and make it do nothing". Signed-off-by: Martin Wilck Reviewed-by: Martin Wilck (cherry picked from commit 4e440522868abeabeb70004f7b2c5cdb15e4c9e0) --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index 5c762eba5..214adf1b0 100644 --- a/.clang-format +++ b/.clang-format @@ -29,4 +29,5 @@ ForEachMacros: - vector_foreach_slot - vector_foreach_slot_backwards - vector_foreach_slot_after +Cpp11BracedListStyle: false --- From d6b3e276b8cc2642398a07167b430cd220f17b4d Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 19 Mar 2026 17:01:48 +0100 Subject: [PATCH 18/40] .clang-format: Add AllignArrayOfStructures Signed-off-by: Martin Wilck (cherry picked from commit 0e07fbc9c650e3d8bd12c89f8cd8d522bd2634de) --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index 214adf1b0..e68fd4d5c 100644 --- a/.clang-format +++ b/.clang-format @@ -9,6 +9,7 @@ BreakBeforeBraces: Linux BreakStringLiterals: false AllowShortFunctionsOnASingleLine: Empty AlignAfterOpenBracket: Align +AlignArrayOfStructures: Left PointerAlignment: Right ColumnLimit: 79 PenaltyBreakAssignment: 50 From 60183a1773ce72dc1774747bdfaf7c634c1b141e Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 10 Jul 2026 11:25:57 +0200 Subject: [PATCH 19/40] Add github workflows (pre-0.15) on new orphan branch We will use this branch to maintain the workflows separately from the actual code. That makes maintenance of the workflows easier for the stable branches. Signed-off-by: Martin Wilck --- .github/workflows/abi-stable.yaml | 122 +++++++++++ .github/workflows/abi.yaml | 76 +++++++ .github/workflows/build-and-unittest.yaml | 114 +++++++++++ .github/workflows/codingstyle.yml | 43 ++++ .github/workflows/coverity.yaml | 52 +++++ .github/workflows/foreign.yaml | 183 +++++++++++++++++ .github/workflows/multiarch-stable.yaml | 98 +++++++++ .github/workflows/multiarch.yaml | 113 ++++++++++ .github/workflows/native.yaml | 239 ++++++++++++++++++++++ .github/workflows/rolling.yaml | 96 +++++++++ 10 files changed, 1136 insertions(+) create mode 100644 .github/workflows/abi-stable.yaml create mode 100644 .github/workflows/abi.yaml create mode 100644 .github/workflows/build-and-unittest.yaml create mode 100644 .github/workflows/codingstyle.yml create mode 100644 .github/workflows/coverity.yaml create mode 100644 .github/workflows/foreign.yaml create mode 100644 .github/workflows/multiarch-stable.yaml create mode 100644 .github/workflows/multiarch.yaml create mode 100644 .github/workflows/native.yaml create mode 100644 .github/workflows/rolling.yaml diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml new file mode 100644 index 000000000..de8050ab0 --- /dev/null +++ b/.github/workflows/abi-stable.yaml @@ -0,0 +1,122 @@ +name: check-abi for stable branch +on: + push: + branches: + - 'stable-*' + paths: + - '.github/workflows/abi-stable.yaml' + - '**.h' + - '**.c' + - '**.version' + pull_request: + branches: + - 'stable-*' + workflow_dispatch: + +jobs: + reference-abi: + runs-on: ubuntu-24.04 + steps: + - name: get parent tag (push) + run: > + echo ${{ github.ref }} | + sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV + if: github.event_name == 'push' + - name: get parent tag (PR) + run: > + echo ${{ github.base_ref }} | + sed -E 's,stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV + if: github.event_name == 'pull_request' + - name: assert parent tag + run: /bin/false + if: env.PARENT_TAG == '' + - name: try to download ABI for ${{ env.PARENT_TAG }} + id: download_abi + continue-on-error: true + uses: dawidd6/action-download-artifact@v6 + with: + workflow: abi-stable.yaml + workflow_conclusion: '' + branch: ${{ github.ref_name }} + name: multipath-abi-${{ env.PARENT_TAG }} + search_artifacts: true + path: __unused__ + - name: update + if: steps.download_abi.outcome != 'success' + run: sudo apt-get update + - name: dependencies + if: steps.download_abi.outcome != 'success' + run: > + sudo apt-get install --yes gcc + gcc make pkg-config abigail-tools + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev + libmount-dev + - name: checkout ${{ env.PARENT_TAG }} + if: steps.download_abi.outcome != 'success' + uses: actions/checkout@v4 + with: + ref: ${{ env.PARENT_TAG }} + - name: build ABI for ${{ env.PARENT_TAG }} + if: steps.download_abi.outcome != 'success' + run: make -j$(nproc) -Orecurse abi + - name: save ABI + if: steps.download_abi.outcome != 'success' + uses: actions/upload-artifact@v4 + with: + name: multipath-abi-${{ env.PARENT_TAG }} + path: abi + + check-abi: + runs-on: ubuntu-24.04 + needs: reference-abi + steps: + - name: get parent tag (push) + run: > + echo ${{ github.ref }} | + sed -E 's,refs/heads/stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV + if: github.event_name == 'push' + - name: get parent tag (PR) + run: > + echo ${{ github.base_ref }} | + sed -E 's,stable-([0-9]\.[0-9]*)\.y,PARENT_TAG=\1.0,' >> $GITHUB_ENV + if: github.event_name == 'pull_request' + - name: assert parent tag + run: /bin/false + if: env.PARENT_TAG == '' + - name: checkout ${{ github.ref }} + uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + - name: download ABI for ${{ env.PARENT_TAG }} + id: download_abi + uses: dawidd6/action-download-artifact@v6 + with: + workflow: abi-stable.yaml + workflow_conclusion: '' + branch: ${{ github.ref_name }} + name: multipath-abi-${{ env.PARENT_TAG }} + search_artifacts: true + path: reference-abi + - name: update + run: sudo apt-get update + - name: dependencies + run: > + sudo apt-get install --yes gcc + gcc make pkg-config abigail-tools + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev + libmount-dev + - name: check ABI of ${{ github.ref }} against ${{ env.PARENT_TAG }} + id: check_abi + run: make -j$(nproc) -Orecurse abi-test + continue-on-error: true + - name: save differences + if: steps.check_abi.outcome != 'success' + uses: actions/upload-artifact@v4 + with: + name: abi-test + path: abi-test + - name: fail + run: /bin/false + if: steps.check_abi.outcome != 'success' diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml new file mode 100644 index 000000000..1a7d3e5dd --- /dev/null +++ b/.github/workflows/abi.yaml @@ -0,0 +1,76 @@ +name: check-abi +on: + push: + branches: + - master + - queue + - abi + paths: + - '.github/workflows/abi.yaml' + - '**.h' + - '**.c' + pull_request: + branches: + - master + - queue + workflow_dispatch: +env: + ABI_BRANCH: ${{ secrets.ABI_BRANCH }} + +jobs: + save-and-test-ABI: + runs-on: ubuntu-24.04 + steps: + - name: set ABI branch + if: env.ABI_BRANCH == '' + run: echo "ABI_BRANCH=master" >> $GITHUB_ENV + - name: checkout + uses: actions/checkout@v4 + - name: get reference ABI + id: reference + continue-on-error: true + uses: dawidd6/action-download-artifact@v6 + with: + workflow: abi.yaml + branch: ${{ env.ABI_BRANCH }} + name: abi + path: reference-abi + - name: update + run: sudo apt-get update + - name: dependencies + run: > + sudo apt-get install --yes gcc + gcc make pkg-config abigail-tools + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev + libmount-dev + - name: create ABI + run: make -Orecurse -j$(nproc) abi.tar.gz + - name: save ABI + uses: actions/upload-artifact@v4 + with: + name: abi + path: abi + overwrite: true + - name: compare ABI against reference + id: compare + continue-on-error: true + if: steps.reference.outcome == 'success' + run: make abi-test + - name: save differences + if: steps.compare.outcome == 'failure' + uses: actions/upload-artifact@v4 + with: + name: abi-test + path: abi-test + overwrite: true + + - name: fail + # MUST use >- here, otherwise the condition always evaluates to true + if: >- + ${{ + env.ABI_BRANCH != github.ref_name && + (steps.reference.outcome == 'failure' || + steps.compare.outcome == 'failure') + }} + run: false diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml new file mode 100644 index 000000000..616a4de1f --- /dev/null +++ b/.github/workflows/build-and-unittest.yaml @@ -0,0 +1,114 @@ +name: basic-build-and-ci +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + pull_request: + branches: + - master + - queue + - 'stable-*' +jobs: + jammy: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + rl: ['', 'libreadline', 'libedit'] + cc: [ gcc, clang ] + steps: + - uses: actions/checkout@v4 + - name: update + run: sudo apt-get update + - name: dependencies + run: > + sudo apt-get install --yes gcc + make pkg-config valgrind + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev + libmount-dev linux-modules-extra-$(uname -r) + - name: mpath + run: sudo modprobe dm_multipath + - name: zram + run: sudo modprobe zram num_devices=0 + - name: zram-device + run: echo ZRAM=$(sudo cat /sys/class/zram-control/hot_add) >> $GITHUB_ENV + - name: set-zram-size + run: echo 1G | sudo tee /sys/block/zram$ZRAM/disksize + - name: set CC + run: echo CC=${{ matrix.cc }} >> $GITHUB_ENV + - name: set optflags + # valgrind doesn't support the dwarf-5 format of clang 14 + run: echo OPT='-O2 -gdwarf-4 -fstack-protector-strong' >> $GITHUB_ENV + if: matrix.cc == 'clang' + - name: build + run: > + make -Orecurse -j$(nproc) + READLINE=${{ matrix.rl }} OPTFLAGS="$OPT" + - name: test + run: > + make -Orecurse -j$(nproc) + OPTFLAGS="$OPT" test + - name: valgrind-test + id: valgrind + run: > + make -Orecurse -j$(nproc) + OPTFLAGS="$OPT" valgrind-test + continue-on-error: true + - name: valgrind-results + run: cat tests/*.vgr + - name: fail if valgrind failed + run: /bin/false + if: steps.valgrind.outcome != 'success' + - name: clean-nonroot-artifacts + run: rm -f tests/dmevents.out tests/directio.out + - name: root-test + run: sudo make DIO_TEST_DEV=/dev/zram$ZRAM test + - name: kpartx-test + run: sudo make -C kpartx test + noble: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + rl: ['', 'libreadline', 'libedit'] + cc: [ gcc, clang ] + steps: + - uses: actions/checkout@v4 + - name: mpath + run: sudo modprobe dm_multipath + - name: brd + run: sudo modprobe brd rd_nr=1 rd_size=65536 + - name: update + run: sudo apt-get update + - name: dependencies + run: > + sudo apt-get install --yes gcc-10 + make pkg-config valgrind + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev + libmount-dev linux-modules-extra-$(uname -r) + - name: set CC + run: echo CC=${{ matrix.cc }} >> $GITHUB_ENV + - name: build + run: make -Orecurse -j$(nproc) READLINE=${{ matrix.rl }} + - name: test + run: make -Orecurse -j$(nproc) test + - name: valgrind-test + id: valgrind + run: make -Orecurse -j$(nproc) valgrind-test + continue-on-error: true + - name: valgrind-results + run: cat tests/*.vgr + - name: fail if valgrind failed + run: /bin/false + if: steps.valgrind.outcome != 'success' + - name: clean-nonroot-artifacts + run: rm -f tests/dmevents.out tests/directio.out + - name: root-test + run: sudo make DIO_TEST_DEV=/dev/ram0 test + - name: kpartx-test + run: sudo make -C kpartx test diff --git a/.github/workflows/codingstyle.yml b/.github/workflows/codingstyle.yml new file mode 100644 index 000000000..a36b3874e --- /dev/null +++ b/.github/workflows/codingstyle.yml @@ -0,0 +1,43 @@ +name: Check coding style + +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + paths: + - '.clang-format' + - '.github/workflows/codingstyle.yaml' + - '**.h' + - '**.c' + pull_request: + branches: + - master + - queue + - 'stable-*' + paths: + - '.clang-format' + - '.github/workflows/codingstyle.yaml' + - '**.h' + - '**.c' + +permissions: + contents: read + +jobs: + stylecheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: >- + echo "BASEREF=${{ github.event.pull_request.base.sha }}" >>$GITHUB_ENV + if: github.event_name == 'pull_request' + - run: >- + echo "BASEREF=${{ github.event.before }}" >>$GITHUB_ENV + if: github.event_name == 'push' + - run: git fetch --depth=1 origin ${{ env.BASEREF }} + - uses: yshui/git-clang-format-lint@master + with: + base: ${{ env.BASEREF }} diff --git a/.github/workflows/coverity.yaml b/.github/workflows/coverity.yaml new file mode 100644 index 000000000..30e5471d3 --- /dev/null +++ b/.github/workflows/coverity.yaml @@ -0,0 +1,52 @@ +name: coverity +on: + push: + branches: + - coverity + +jobs: + upload-coverity-scan: + runs-on: ubuntu-24.04 + steps: + - name: checkout + uses: actions/checkout@v4 + - name: dependencies + run: > + sudo apt-get install --yes + gcc make pkg-config + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev + libmount-dev + - name: download coverity + run: > + curl -o cov-analysis-linux64.tar.gz + --form token="$COV_TOKEN" + --form project="$COV_PROJECT" + https://scan.coverity.com/download/cxx/linux64 + env: + COV_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + COV_PROJECT: ${{ secrets.COVERITY_SCAN_PROJECT }} + - name: unpack coverity + run: | + mkdir -p coverity + tar xfz cov-analysis-linux64.tar.gz --strip 1 -C coverity + - name: build with cov-build + run: > + PATH="$PWD/coverity/bin:$PATH" + cov-build --dir cov-int make -Orecurse -j"$(nproc)" + - name: pack results + run: tar cfz multipath-tools.tgz cov-int + - name: submit results + run: > + curl + --form token="$COV_TOKEN" + --form email="$COV_EMAIL" + --form file="@multipath-tools.tgz" + --form version="${{ github.ref_name }}" + --form description="$(git describe --tags --match "0.*")" + --form project="$COV_PROJECT" + https://scan.coverity.com/builds + env: + COV_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + COV_PROJECT: ${{ secrets.COVERITY_SCAN_PROJECT }} + COV_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }} diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml new file mode 100644 index 000000000..42e21f580 --- /dev/null +++ b/.github/workflows/foreign.yaml @@ -0,0 +1,183 @@ +name: compile and unit test on foreign arch +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + paths: + - '.github/workflows/foreign.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + pull_request: + branches: + - master + - queue + - 'stable-*' + paths: + - '.github/workflows/foreign.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + +jobs: + + cross-build: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + os: [bullseye, bookworm, trixie, sid] + arch: [ppc64le, arm64, s390x] + exclude: + - os: bullseye + arch: ppc64le + - os: bullseye + arch: s390x + container: ghcr.io/mwilck/multipath-cross-debian_cross-${{ matrix.os }}-${{ matrix.arch }} + steps: + - name: checkout + uses: actions/checkout@v4 + - name: build + run: make -j$(nproc) -Orecurse test-progs.tar + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: cross-${{ matrix.os }}-${{ matrix.arch }} + path: test-progs.tar + overwrite: true + + test: + runs-on: ubuntu-24.04 + needs: cross-build + strategy: + fail-fast: false + matrix: + os: [bullseye, bookworm, trixie, sid] + arch: [ppc64le, arm64, s390x] + exclude: + - os: bullseye + arch: ppc64le + - os: bullseye + arch: s390x + steps: + - name: set container arch + run: echo CONTAINER_ARCH="${{ matrix.arch }}" >> $GITHUB_ENV + if: matrix.arch != 'armhf' + - name: set container arch + run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV + if: matrix.arch == 'armhf' + - name: download binary archive + uses: actions/download-artifact@v4 + with: + name: cross-${{ matrix.os }}-${{ matrix.arch }} + - name: unpack binary archive + run: tar xfv test-progs.tar + - name: enable foreign arch + uses: docker/setup-qemu-action@v2 + with: + image: tonistiigi/binfmt:latest + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + - name: run tests + id: test + run: | + docker run \ + --pids-limit 4096 \ + --workdir /__w/multipath-tools/multipath-tools \ + --platform linux/${{ env.CONTAINER_ARCH }} \ + -w /__w/multipath-tools/multipath-tools \ + -v${{ github.workspace }}:/__w/multipath-tools/multipath-tools \ + ghcr.io/mwilck/multipath-run-debian-${{ matrix.os }} -C tests + continue-on-error: true + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+x + if: steps.test.outcome != 'success' + - name: save test outputs + run: make test-outputs.tar + if: steps.test.outcome != 'success' + - name: upload test outputs + uses: actions/upload-artifact@v4 + with: + name: test-${{ matrix.os }}-${{ matrix.arch }} + path: test-outputs.tar + overwrite: true + if: steps.test.outcome != 'success' + - name: fail if test failed + run: /bin/false + if: steps.test.outcome != 'success' + + root-test: + runs-on: ubuntu-24.04 + needs: cross-build + strategy: + fail-fast: false + matrix: + os: [bullseye, bookworm, trixie, sid] + arch: [ppc64le, arm64, s390x] + exclude: + - os: bullseye + arch: ppc64le + - os: bullseye + arch: s390x + steps: + - name: mpath + run: sudo modprobe dm_multipath + - name: brd + run: sudo modprobe brd rd_nr=1 rd_size=65536 + - name: set container arch + run: echo CONTAINER_ARCH="${{ matrix.arch }}" >> $GITHUB_ENV + if: matrix.arch != 'armhf' + - name: set container arch + run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV + if: matrix.arch == 'armhf' + - name: download binary archive + uses: actions/download-artifact@v4 + with: + name: cross-${{ matrix.os }}-${{ matrix.arch }} + - name: unpack binary archive + run: tar xfv test-progs.tar + - name: enable foreign arch + uses: docker/setup-qemu-action@v2 + with: + image: tonistiigi/binfmt:latest + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + - name: run tests + id: root-test + run: | + docker run \ + --workdir /__w/multipath-tools/multipath-tools \ + --pids-limit 4096 \ + --platform linux/${{ env.CONTAINER_ARCH }} \ + --privileged \ + -v /dev/ram0:/dev/ram0 -e DIO_TEST_DEV=/dev/ram0 \ + -w /__w/multipath-tools/multipath-tools \ + -v${{ github.workspace }}:/__w/multipath-tools/multipath-tools \ + ghcr.io/mwilck/multipath-run-debian-${{ matrix.os }} \ + -C tests dmevents.out + continue-on-error: true + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+x + if: steps.root-test.outcome != 'success' + - name: save test outputs + run: make test-outputs.tar + if: steps.root-test.outcome != 'success' + - name: upload test outputs + uses: actions/upload-artifact@v4 + with: + name: root-test-${{ matrix.os }}-${{ matrix.arch }} + path: test-outputs.tar + overwrite: true + if: steps.root-test.outcome != 'success' + - name: fail if root test failed + run: /bin/false + if: steps.root-test.outcome != 'success' diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml new file mode 100644 index 000000000..7dbcc8f6d --- /dev/null +++ b/.github/workflows/multiarch-stable.yaml @@ -0,0 +1,98 @@ +name: multiarch test for stable distros +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + paths: + - '.github/workflows/multiarch-stable.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + pull_request: + branches: + - master + - queue + - 'stable-*' + paths: + - '.github/workflows/multiarch-stable.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' +jobs: + + build-old: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + os: + - debian-trixie + - debian-bookworm + - debian-buster + - ubuntu-trusty + arch: [386, arm/v7] + include: + - os: debian-trixie + arch: s390x + - os: debian-trixie + arch: ppc64le + - os: debian-bookworm + arch: s390x + - os: debian-bookworm + arch: ppc64le + steps: + - name: checkout + uses: actions/checkout@v4 + - name: enable foreign arch + uses: docker/setup-qemu-action@v2 + with: + image: tonistiigi/binfmt:latest + - name: set architecture name + run: | + __arch="${{ matrix.arch }}" + echo "ARCH_NAME=${__arch//\//-}" >>"$GITHUB_ENV" + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + - name: compile and run unit tests + id: test + run: | + docker run --pids-limit 4096 --platform linux/${{ matrix.arch }} \ + -w /build -v${{ github.workspace }}:/build \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} test + continue-on-error: true + - name: create binary archive + run: | + docker run --platform linux/${{ matrix.arch }} \ + -w /build -v${{ github.workspace }}:/build \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} test-progs.tar + if: steps.test.outcome != 'success' + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: binaries-${{ matrix.os }}-${{ env.ARCH_NAME }} + path: test-progs.tar + overwrite: true + if: steps.test.outcome != 'success' + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+r + if: steps.test.outcome != 'success' + - name: save test outputs + run: make test-outputs.tar + if: steps.test.outcome != 'success' + - name: upload test outputs + uses: actions/upload-artifact@v4 + with: + name: test-${{ matrix.os }}-${{ env.ARCH_NAME }} + path: test-outputs.tar + overwrite: true + if: steps.test.outcome != 'success' + - name: fail if test failed + run: /bin/false + if: steps.test.outcome != 'success' diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml new file mode 100644 index 000000000..3aee3b028 --- /dev/null +++ b/.github/workflows/multiarch.yaml @@ -0,0 +1,113 @@ +name: multiarch test for rolling distros +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + - musl + paths: + - '.github/workflows/multiarch.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + pull_request: + branches: + - master + - queue + - 'stable-*' + paths: + - '.github/workflows/multiarch.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + # run monthly to catch rolling distro changes + schedule: + - cron: '45 02 1 * *' + +jobs: + + build-current: + strategy: + fail-fast: false + matrix: + os: + - alpine + - debian-sid + - fedora-rawhide + - opensuse-tumbleweed + arch: [ppc64le, s390x, 386, arm/v7] + variant: + - arch: ppc64le + runner: ubuntu-24.04 + - arch: s390x + runner: ubuntu-24.04 + - arch: 386 + runner: ubuntu-24.04 + - arch: arm/v7 + runner: ubuntu-24.04-arm + exclude: + - os: fedora-rawhide + variant: + arch: 386 + runner: ubuntu-24.04 + - os: fedora-rawhide + variant: + arch: arm/v7 + runner: ubuntu-24.04-arm + include: + - os: alpine + variant: + arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.variant.runner }} + steps: + - name: checkout + uses: actions/checkout@v4 + - name: enable foreign arch + uses: docker/setup-qemu-action@v2 + with: + image: tonistiigi/binfmt:latest + - name: set architecture name + run: | + __arch="${{ matrix.variant.arch }}" + echo "ARCH_NAME=${__arch//\//-}" >>"$GITHUB_ENV" + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + - name: compile and run unit tests + id: test + run: | + docker run --pids-limit 4096 --platform linux/${{ matrix.variant.arch }} \ + -w /build -v${{ github.workspace }}:/build \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} test + continue-on-error: true + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+x + if: steps.test.outcome != 'success' + - name: create archives + run: | + docker run --platform linux/${{ matrix.variant.arch }} \ + -w /build -v${{ github.workspace }}:/build \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} test-progs.tar test-outputs.tar + if: steps.test.outcome != 'success' + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: binaries-${{ matrix.os }}w-${{ env.ARCH_NAME }} + path: test-progs.tar + if: steps.test.outcome != 'success' + - name: upload test outputs + uses: actions/upload-artifact@v4 + with: + name: test-${{ matrix.os }}-${{ env.ARCH_NAME }} + path: test-outputs.tar + overwrite: true + if: steps.test.outcome != 'success' + - name: fail if test failed + run: /bin/false + if: steps.test.outcome != 'success' diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml new file mode 100644 index 000000000..9c4fa2e82 --- /dev/null +++ b/.github/workflows/native.yaml @@ -0,0 +1,239 @@ +name: compile and unit test on native arch +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + paths: + - '.github/workflows/native.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + pull_request: + branches: + - master + - queue + - 'stable-*' + paths: + - '.github/workflows/native.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + +jobs: + stable: + strategy: + fail-fast: false + matrix: + os: + - debian-jessie + - debian-buster + - debian-bullseye + - debian-bookworm + - debian-trixie + - fedora-43 + - opensuse-leap-15.6 + - opensuse-leap-16.0 + variant: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.variant.runner }} + steps: + - name: checkout + uses: actions/checkout@v4 + + # On jessie, we use libreadline 5 (no licensing issue) + - name: set readline make option (Jessie) + run: echo READLINE=libreadline >> $GITHUB_ENV + if: matrix.os == 'debian-jessie' + + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + + - name: build and test + id: test + run: | + docker run -w ${{ github.workspace }} -v${{ github.workspace }}:${{ github.workspace }} \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} \ + -j$(nproc) -Orecurse V=1 READLINE=$READLINE test + continue-on-error: true + + - name: create test-progs.tar + run: | + docker run -w ${{ github.workspace }} -v${{ github.workspace }}:${{ github.workspace }} \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} test-progs.tar + + - name: upload test-progs.tar + uses: actions/upload-artifact@v4 + with: + name: native-${{ matrix.os }}-${{ matrix.variant.arch }} + path: test-progs.tar + overwrite: true + + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+r + if: steps.test.outcome != 'success' + + - name: create test-outputs.tar + run: make test-outputs.tar + if: steps.test.outcome != 'success' + + - name: upload test-outputs.tar + uses: actions/upload-artifact@v4 + with: + name: gcc-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} + path: test-outputs.tar + overwrite: true + if: steps.test.outcome != 'success' + + - name: fail if test failed + run: /bin/false + if: steps.test.outcome != 'success' + + clang: + strategy: + fail-fast: false + matrix: + os: + - debian-buster + - debian-bullseye + - debian-bookworm + - debian-trixie + - fedora-43 + - opensuse-leap-15.6 + - opensuse-leap-16.0 + variant: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + include: + - os: debian-jessie + variant: + arch: x86_64 + runner: ubuntu-24.04 + runs-on: ${{ matrix.variant.runner }} + steps: + - name: checkout + uses: actions/checkout@v4 + + # On jessie, we use libreadline 5 (no licensing issue) + - name: set readline make option (Jessie) + run: echo READLINE=libreadline >> $GITHUB_ENV + if: matrix.os == 'debian-jessie' + + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + + - name: build and test with clang + id: test + run: | + docker run --pids-limit 4096 -e CC=clang \ + -w ${{ github.workspace }} -v${{ github.workspace }}:${{ github.workspace }} \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} \ + -j$(nproc) -Orecurse V=1 READLINE=$READLINE test + continue-on-error: true + + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+r + if: steps.test.outcome != 'success' + + - name: create test-outputs.tar + run: make test-outputs.tar + if: steps.test.outcome != 'success' + + - name: upload test-outputs.tar + uses: actions/upload-artifact@v4 + with: + name: clang-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} + path: test-outputs.tar + overwrite: true + if: steps.test.outcome != 'success' + + - name: fail if test failed + run: /bin/false + if: steps.test.outcome != 'success' + + root-test: + needs: stable + strategy: + fail-fast: false + matrix: + os: + - debian-jessie + - debian-buster + - debian-bullseye + - debian-bookworm + - debian-trixie + - fedora-43 + - opensuse-leap-15.6 + - opensuse-leap-16.0 + variant: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.variant.runner }} + steps: + - name: mpath + run: sudo modprobe dm_multipath + - name: brd + run: sudo modprobe brd rd_nr=1 rd_size=65536 + + - name: checkout + uses: actions/checkout@v4 + + - name: download binary archive + uses: actions/download-artifact@v4 + with: + name: native-${{ matrix.os }}-${{ matrix.variant.arch }} + + - name: unpack binary archive + run: tar xfmv test-progs.tar + + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + + - name: run root tests + id: test + run: | + docker run \ + --workdir /__w/multipath-tools/multipath-tools --privileged \ + -v /dev/ram0:/dev/ram0 -e DIO_TEST_DEV=/dev/ram0 \ + -w /__w/multipath-tools/multipath-tools \ + -v${{ github.workspace }}:/__w/multipath-tools/multipath-tools \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} \ + -C tests V=1 directio.out dmevents.out + continue-on-error: true + + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+r + if: steps.test.outcome != 'success' + + - name: create test-outputs.tar + run: make test-outputs.tar + if: steps.test.outcome != 'success' + + - name: upload test-outputs.tar + uses: actions/upload-artifact@v4 + with: + name: clang-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} + path: test-outputs.tar + overwrite: true + if: steps.test.outcome != 'success' + + - name: fail if test failed + run: /bin/false + if: steps.test.outcome != 'success' diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml new file mode 100644 index 000000000..9f178f776 --- /dev/null +++ b/.github/workflows/rolling.yaml @@ -0,0 +1,96 @@ +name: compile and unit test on rolling distros +on: + push: + branches: + - master + - queue + - tip + - 'stable-*' + paths: + - '.github/workflows/rolling.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + pull_request: + branches: + - master + - queue + - 'stable-*' + paths: + - '.github/workflows/rolling.yaml' + - '**.h' + - '**.c' + - '**Makefile*' + - '**.mk' + # run weekly to catch rolling distro changes + schedule: + - cron: '30 06 * * 1' + +jobs: + rolling: + strategy: + fail-fast: false + matrix: + os: + - debian-sid + - opensuse-tumbleweed + - fedora-rawhide + variant: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + compiler: + - gcc + - clang + include: + - os: alpine + variant: + arch: x86_64 + runner: ubuntu-24.04 + compiler: gcc + - os: alpine + variant: + arch: x86_64 + runner: ubuntu-24.04 + compiler: clang + runs-on: ${{ matrix.variant.runner }} + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern + - name: build and test + id: test + run: | + docker run -w /build -v${{ github.workspace }}:/build \ + ghcr.io/mwilck/multipath-build-${{ matrix.os }} \ + CC=${{ matrix.compiler }} READLINE=libreadline -j$(nproc) -Orecurse test + continue-on-error: true + - name: create binary archive + run: make test-progs.tar + if: steps.test.outcome != 'success' + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: binaries-${{ matrix.os }}-${{ matrix.variant.arch }}-${{ matrix.compiler }} + path: test-progs.tar + if: steps.test.outcome != 'success' + - name: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+r + if: steps.test.outcome != 'success' + - name: create test-outputs.tar + run: make test-outputs.tar + if: steps.test.outcome != 'success' + - name: upload test-outputs.tar + uses: actions/upload-artifact@v4 + with: + name: outputs-${{ matrix.os }}-${{ matrix.variant.arch }}-${{ matrix.compiler }} + path: test-outputs.tar + if: steps.test.outcome != 'success' + - name: fail + run: /bin/false + if: steps.test.outcome != 'success' From 32ad33ef553f43a359268013a66b4af80e572f81 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 7 May 2026 22:00:51 +0200 Subject: [PATCH 20/40] fixup "GitHub workflows: upload log files in case of failure" actions/upload-artifact@v4 doesn't support slashes in file names. Signed-off-by: Martin Wilck Reviewed-by: Martin Wilck (cherry picked from commit c70991550113d3a0ea97f5f1fa479842087492c9) --- .github/workflows/multiarch-stable.yaml | 6 +++++- .github/workflows/multiarch.yaml | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index b8c770e40..69ea272c8 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -52,6 +52,10 @@ jobs: uses: docker/setup-qemu-action@v2 with: image: tonistiigi/binfmt:latest + - name: set architecture name + run: | + __arch="${{ matrix.arch }}" + echo "ARCH_NAME=${__arch//\//-}" >>"$GITHUB_ENV" - name: compile and run unit tests id: test uses: mosteo-actions/docker-run@v1 @@ -76,7 +80,7 @@ jobs: - name: upload binary archive uses: actions/upload-artifact@v4 with: - name: binaries-${{ matrix.os }}-${{ matrix.arch }} + name: binaries-${{ matrix.os }}-${{ env.ARCH_NAME }} path: test-progs.tar if: steps.test.outcome != 'success' - name: fail diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index 806275a13..9302fb52d 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -55,6 +55,10 @@ jobs: uses: docker/setup-qemu-action@v2 with: image: tonistiigi/binfmt:latest + - name: set architecture name + run: | + __arch="${{ matrix.arch }}" + echo "ARCH_NAME=${__arch//\//-}" >>"$GITHUB_ENV" - name: compile and run unit tests id: test uses: mosteo-actions/docker-run@v1 @@ -79,7 +83,7 @@ jobs: - name: upload binary archive uses: actions/upload-artifact@v4 with: - name: binaries-${{ matrix.os }}-${{ matrix.arch }} + name: binaries-${{ matrix.os }}w-${{ env.ARCH_NAME }} path: test-progs.tar if: steps.test.outcome != 'success' - name: fail From 20c88a762a5c455264f63c50a93633f1c8cd741b Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 6 Jul 2026 16:12:14 +0200 Subject: [PATCH 21/40] Update NEWS.md --- NEWS.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/NEWS.md b/NEWS.md index 1fd4766ab..138652adb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,40 @@ release. These bug fixes will be tracked in stable branches. See [README.md](README.md) for additional information. +## multipath-tools 0.14.4, 2026/07 + +### User-visible changes + +* Fix ALUA asymmetric access state descriptions in multipathd logs, so that + the same terms are used as by the kernel ("lba-dependent", "transitioning"). +* Don't set a hardware handler for bio-based multipath devices. The kernel + rejects this anyway. + +### Bug fixes + +* Fix WWID detection for legacy devices that use the older SCSI-2 VPD page + 0x83 format for their device identifier. +* kpartx: Fix an integer overflow in the GPT partition table size calculation. + A crafted partition table with an extremely large number of partition entries + could trigger the overflow. +* kpartx: Fix several issues in the DASD partition table reader that could be + triggered by a maliciously crafted disk image. +* Fix duplicate "checker timed out" log messages when `log_checker_err` is + set to `once`. + +### Other changes + +* Man page improvements + +### CI + +* Removed the `check_spelling` GitHub Action after a + [security incident](https://github.com/jsoref/2026-06-16-credential-leak) + reported against the action's source repository. +* Added coredump collection in the CI. +* GitHub action updates related to node 20 depreciation on GitHub. +* Fixes for various errors in the CI. + ## multipath-tools 0.14.3, 2026/02 * Fix boot failures with multipath introduced in 0.14.1. Commit 01cc89c. From 9c83980b87a30c4ee81f1adb5d505dfbb9ddd946 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 6 Jul 2026 20:48:16 -0400 Subject: [PATCH 22/40] libmultipath: make sure sscanf sets a max field width for strings In the iet and datacore prioritizers, multipath was using sscanf to get a string for a 255 byte buffer, without limiting the size of the string. This could result in a buffer overflow, if there was a bad value in multipath.conf. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit 4611f971c514f0f6a1fdaa1146d8ecd006cc98a7) --- libmultipath/prioritizers/datacore.c | 6 +++--- libmultipath/prioritizers/iet.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libmultipath/prioritizers/datacore.c b/libmultipath/prioritizers/datacore.c index ab813a0ea..a7c2ae3e8 100644 --- a/libmultipath/prioritizers/datacore.c +++ b/libmultipath/prioritizers/datacore.c @@ -49,11 +49,11 @@ int datacore_prio (const char *dev, int sg_fd, char * args, return 0; } - if (sscanf(args, "timeout=%i preferredsds=%s", + if (sscanf(args, "timeout=%i preferredsds=%254s", (int *)&timeout_ms, preferredsds) == 2) {} - else if (sscanf(args, "preferredsds=%s timeout=%i", + else if (sscanf(args, "preferredsds=%254s timeout=%i", preferredsds, (int *)&timeout_ms) == 2) {} - else if (sscanf(args, "preferredsds=%s", + else if (sscanf(args, "preferredsds=%254s", preferredsds) == 1) {} else { dc_log(0, "unexpected prio_args format"); diff --git a/libmultipath/prioritizers/iet.c b/libmultipath/prioritizers/iet.c index f5fdd42aa..3aefaa32c 100644 --- a/libmultipath/prioritizers/iet.c +++ b/libmultipath/prioritizers/iet.c @@ -84,7 +84,7 @@ int iet_prio(const char *dev, char * args) return 0; } // check if args format is OK - if (sscanf(args, "preferredip=%s", preferredip) ==1) {} + if (sscanf(args, "preferredip=%254s", preferredip) == 1) {} else { dc_log(0, "unexpected prio_args format"); return 0; From 32fa1010042da3fd999548c37ebeaa7410891117 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 9 Jul 2026 17:07:32 +0200 Subject: [PATCH 23/40] .clang-format: avoid reformatting comments Signed-off-by: Martin Wilck --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index e68fd4d5c..927b8e0dd 100644 --- a/.clang-format +++ b/.clang-format @@ -31,4 +31,5 @@ ForEachMacros: - vector_foreach_slot_backwards - vector_foreach_slot_after Cpp11BracedListStyle: false +ReflowComments: Never --- From abdba3fcc6d05e396242ace93fa4abdd4856a9b3 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 9 Jul 2026 16:26:54 +0200 Subject: [PATCH 24/40] multipath-tools tests: fix code formatting in vpd.c Avoid that "git clang-format" wrongly indents the invocations of the macros make_test_vpd_str() and make_test_vpd_prespc3 in tests/vpd.c, by appending semicolons to the macro invocation as we did for other macros in the same file. Note: The indentation issue could also be fixed by adding these macros to the "StatementMacros:" directive in .clang-format. Signed-off-by: Martin Wilck --- tests/vpd.c | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/vpd.c b/tests/vpd.c index b02179483..ba4b21d96 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -825,47 +825,47 @@ make_test_vpd_naa(2, 17); make_test_vpd_naa(2, 16); /* SCSI Name string: EUI64, WWID size: 17 */ -make_test_vpd_str(0, 20, 18) -make_test_vpd_str(0, 20, 17) -make_test_vpd_str(0, 20, 16) -make_test_vpd_str(0, 20, 15) +make_test_vpd_str(0, 20, 18); +make_test_vpd_str(0, 20, 17); +make_test_vpd_str(0, 20, 16); +make_test_vpd_str(0, 20, 15); /* SCSI Name string: EUI64, zero padded, WWID size: 16 */ -make_test_vpd_str(16, 20, 18) -make_test_vpd_str(16, 20, 17) -make_test_vpd_str(16, 20, 16) -make_test_vpd_str(16, 20, 15) +make_test_vpd_str(16, 20, 18); +make_test_vpd_str(16, 20, 17); +make_test_vpd_str(16, 20, 16); +make_test_vpd_str(16, 20, 15); /* SCSI Name string: NAA, WWID size: 17 */ -make_test_vpd_str(1, 20, 18) -make_test_vpd_str(1, 20, 17) -make_test_vpd_str(1, 20, 16) -make_test_vpd_str(1, 20, 15) +make_test_vpd_str(1, 20, 18); +make_test_vpd_str(1, 20, 17); +make_test_vpd_str(1, 20, 16); +make_test_vpd_str(1, 20, 15); /* SCSI Name string: NAA, zero padded, WWID size: 16 */ -make_test_vpd_str(17, 20, 18) -make_test_vpd_str(17, 20, 17) -make_test_vpd_str(17, 20, 16) -make_test_vpd_str(17, 20, 15) +make_test_vpd_str(17, 20, 18); +make_test_vpd_str(17, 20, 17); +make_test_vpd_str(17, 20, 16); +make_test_vpd_str(17, 20, 15); /* SCSI Name string: IQN, WWID size: 17 */ -make_test_vpd_str(2, 20, 18) -make_test_vpd_str(2, 20, 17) -make_test_vpd_str(2, 20, 16) -make_test_vpd_str(2, 20, 15) +make_test_vpd_str(2, 20, 18); +make_test_vpd_str(2, 20, 17); +make_test_vpd_str(2, 20, 16); +make_test_vpd_str(2, 20, 15); /* SCSI Name string: IQN, zero padded, WWID size: 16 */ -make_test_vpd_str(18, 20, 18) -make_test_vpd_str(18, 20, 17) -make_test_vpd_str(18, 20, 16) -make_test_vpd_str(18, 20, 15) +make_test_vpd_str(18, 20, 18); +make_test_vpd_str(18, 20, 17); +make_test_vpd_str(18, 20, 16); +make_test_vpd_str(18, 20, 15); /* PRE-SPC3, WWID size: 34 */ -make_test_vpd_prespc3(40) -make_test_vpd_prespc3(34) -make_test_vpd_prespc3(33) -make_test_vpd_prespc3(32) -make_test_vpd_prespc3(20) +make_test_vpd_prespc3(40); +make_test_vpd_prespc3(34); +make_test_vpd_prespc3(33); +make_test_vpd_prespc3(32); +make_test_vpd_prespc3(20); static int test_vpd(void) { From 8661344cd794809f4f9f5f7186e5e6567c146805 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 9 Jul 2026 16:33:28 +0200 Subject: [PATCH 25/40] Fix minor code formatting issues in latest commits With these changes, "git clang-format --commit 0.14.0" doesn't change any code. Signed-off-by: Martin Wilck --- libmultipath/prioritizers/datacore.c | 13 ++++++------- libmultipath/prioritizers/iet.c | 4 ++-- libmultipath/propsel.c | 4 ++-- tests/vpd.c | 3 +-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/libmultipath/prioritizers/datacore.c b/libmultipath/prioritizers/datacore.c index a7c2ae3e8..b03d14731 100644 --- a/libmultipath/prioritizers/datacore.c +++ b/libmultipath/prioritizers/datacore.c @@ -49,13 +49,12 @@ int datacore_prio (const char *dev, int sg_fd, char * args, return 0; } - if (sscanf(args, "timeout=%i preferredsds=%254s", - (int *)&timeout_ms, preferredsds) == 2) {} - else if (sscanf(args, "preferredsds=%254s timeout=%i", - preferredsds, (int *)&timeout_ms) == 2) {} - else if (sscanf(args, "preferredsds=%254s", - preferredsds) == 1) {} - else { + if (sscanf(args, "timeout=%i preferredsds=%254s", (int *)&timeout_ms, + preferredsds) == 2) { + } else if (sscanf(args, "preferredsds=%254s timeout=%i", preferredsds, + (int *)&timeout_ms) == 2) { + } else if (sscanf(args, "preferredsds=%254s", preferredsds) == 1) { + } else { dc_log(0, "unexpected prio_args format"); return 0; } diff --git a/libmultipath/prioritizers/iet.c b/libmultipath/prioritizers/iet.c index 3aefaa32c..1e7f1e895 100644 --- a/libmultipath/prioritizers/iet.c +++ b/libmultipath/prioritizers/iet.c @@ -84,8 +84,8 @@ int iet_prio(const char *dev, char * args) return 0; } // check if args format is OK - if (sscanf(args, "preferredip=%254s", preferredip) == 1) {} - else { + if (sscanf(args, "preferredip=%254s", preferredip) == 1) { + } else { dc_log(0, "unexpected prio_args format"); return 0; } diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index 2c3733896..c1045daa9 100644 --- a/libmultipath/propsel.c +++ b/libmultipath/propsel.c @@ -646,8 +646,8 @@ int select_checker_timeout(struct config *conf, struct path *pp) } pp_set_default(checker_timeout, DEF_TIMEOUT); out: - condlog(3, "%s: checker timeout = %u s %s", pp->dev, pp->checker_timeout, - origin); + condlog(3, "%s: checker timeout = %u s %s", pp->dev, + pp->checker_timeout, origin); return 0; } diff --git a/tests/vpd.c b/tests/vpd.c index ba4b21d96..0f408db4c 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -342,8 +342,7 @@ static int create_vpd83(unsigned char *buf, size_t bufsiz, const char *id, * * Return: VPD page length. */ -static int create_pre_spc3_vpd83(unsigned char *buf, size_t bufsize, - const char *id) +static int create_pre_spc3_vpd83(unsigned char *buf, size_t bufsize, const char *id) { memset(buf, 0, bufsize); buf[1] = 0x83; From c3de59ddffb0c79a4e98426ec5b8ed2ba589444b Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 9 Jul 2026 17:17:42 +0200 Subject: [PATCH 26/40] Update NEWS.md Signed-off-by: Martin Wilck --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 138652adb..58dae2e5a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -29,6 +29,8 @@ See [README.md](README.md) for additional information. triggered by a maliciously crafted disk image. * Fix duplicate "checker timed out" log messages when `log_checker_err` is set to `once`. +* Avoid potential buffer overflows in the iet and datacore prioritizers. + Commit 4611f97. ### Other changes From c4f2145063806cf034452619d0f6a0526c2faa71 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 20 Mar 2026 12:23:46 +0100 Subject: [PATCH 27/40] Makefile: add 'test-outputs.tar' target For saving test outputs in GitHub actions. Also add "test-outputs.cpio", although it'll be hardly used. Signed-off-by: Martin Wilck --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f06f7faa9..8e46ee732 100644 --- a/Makefile +++ b/Makefile @@ -113,6 +113,7 @@ clean: @touch config.mk $(Q)$(MAKE) $(BUILDDIRS:=.clean) tests.clean || true $(Q)$(RM) -r abi abi.tar.gz abi-test config.mk + $(Q)$(RM) test-progs.* test-outputs.* install: $(BUILDDIRS:=.install) uninstall: $(BUILDDIRS:=.uninstall) @@ -131,10 +132,16 @@ TEST-ARTIFACTS := config.mk Makefile.inc \ tests/Makefile tests/*.so* tests/lib/* tests/*-test test-progs.cpio: test-progs - @printf "%s\\n" $(TEST-ARTIFACTS) | cpio -o -H crc >$@ + $(Q)printf "%s\\n" $(TEST-ARTIFACTS) | cpio -o -H crc >$@ test-progs.tar: test-progs - @tar cf $@ $(TEST-ARTIFACTS) + $(Q)tar cf $@ $(TEST-ARTIFACTS) + +test-outputs.cpio: $(wildcard tests/*.out) $(wildcard tests/*.vgr) + $(Q)printf "%s\\n" $^ | cpio -o -H crc >$@ + +test-outputs.tar: $(wildcard tests/*.out) $(wildcard tests/*.vgr) + $(Q)tar cf "$@" $^ || touch $@ .PHONY: TAGS TAGS: From f49ed0ffcd194d11931dcee3f77dbfaebe5bcc72 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 24 Jun 2026 10:17:50 +0200 Subject: [PATCH 28/40] multipath-tools Makefile: collect core dumps in test-outputs.tar Signed-off-by: Martin Wilck --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8e46ee732..a5f30ce24 100644 --- a/Makefile +++ b/Makefile @@ -137,10 +137,10 @@ test-progs.cpio: test-progs test-progs.tar: test-progs $(Q)tar cf $@ $(TEST-ARTIFACTS) -test-outputs.cpio: $(wildcard tests/*.out) $(wildcard tests/*.vgr) +test-outputs.cpio: $(wildcard tests/*.out) $(wildcard tests/*.vgr) $(wildcard tests/core*) $(Q)printf "%s\\n" $^ | cpio -o -H crc >$@ -test-outputs.tar: $(wildcard tests/*.out) $(wildcard tests/*.vgr) +test-outputs.tar: $(wildcard tests/*.out) $(wildcard tests/*.vgr) $(wildcard tests/core*) $(Q)tar cf "$@" $^ || touch $@ .PHONY: TAGS From 9f322216bf00524de5dbfd7ed5b24958cfc82ff0 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 20 Mar 2026 16:08:21 +0100 Subject: [PATCH 29/40] Makefile: include top-level Makefile in test-progs.tar Signed-off-by: Martin Wilck --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a5f30ce24..b1dac5b70 100644 --- a/Makefile +++ b/Makefile @@ -127,9 +127,9 @@ test: all valgrind-test: all @$(MAKE) -C tests valgrind -TEST-ARTIFACTS := config.mk Makefile.inc \ +TEST-ARTIFACTS := config.mk Makefile Makefile.inc \ $(LIB_BUILDDIRS:%=%/*.so*) $(PLUGIN_BUILDDIRS:%=%/*.so) \ - tests/Makefile tests/*.so* tests/lib/* tests/*-test + tests/Makefile tests/*.so* tests/lib/* tests/*-test test-progs.cpio: test-progs $(Q)printf "%s\\n" $(TEST-ARTIFACTS) | cpio -o -H crc >$@ From b420ed1fd1092c801ba53e98546aa04337528164 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 10 Jul 2026 11:44:42 +0200 Subject: [PATCH 30/40] GitHub workflows: replace actions/checkout@v4 with @v7 actions/checkout@v4 uses the deprecated node 20. Signed-off-by: Martin Wilck --- .github/workflows/abi-stable.yaml | 4 ++-- .github/workflows/abi.yaml | 2 +- .github/workflows/build-and-unittest.yaml | 4 ++-- .github/workflows/coverity.yaml | 2 +- .github/workflows/foreign.yaml | 2 +- .github/workflows/multiarch-stable.yaml | 2 +- .github/workflows/multiarch.yaml | 2 +- .github/workflows/native.yaml | 6 +++--- .github/workflows/rolling.yaml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml index de8050ab0..b41a00dca 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -54,7 +54,7 @@ jobs: libmount-dev - name: checkout ${{ env.PARENT_TAG }} if: steps.download_abi.outcome != 'success' - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: ref: ${{ env.PARENT_TAG }} - name: build ABI for ${{ env.PARENT_TAG }} @@ -85,7 +85,7 @@ jobs: run: /bin/false if: env.PARENT_TAG == '' - name: checkout ${{ github.ref }} - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: ref: ${{ github.ref }} - name: download ABI for ${{ env.PARENT_TAG }} diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml index 1a7d3e5dd..4810737a5 100644 --- a/.github/workflows/abi.yaml +++ b/.github/workflows/abi.yaml @@ -25,7 +25,7 @@ jobs: if: env.ABI_BRANCH == '' run: echo "ABI_BRANCH=master" >> $GITHUB_ENV - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: get reference ABI id: reference continue-on-error: true diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml index 616a4de1f..386b01db8 100644 --- a/.github/workflows/build-and-unittest.yaml +++ b/.github/workflows/build-and-unittest.yaml @@ -20,7 +20,7 @@ jobs: rl: ['', 'libreadline', 'libedit'] cc: [ gcc, clang ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: update run: sudo apt-get update - name: dependencies @@ -77,7 +77,7 @@ jobs: rl: ['', 'libreadline', 'libedit'] cc: [ gcc, clang ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: mpath run: sudo modprobe dm_multipath - name: brd diff --git a/.github/workflows/coverity.yaml b/.github/workflows/coverity.yaml index 30e5471d3..2e981f8ae 100644 --- a/.github/workflows/coverity.yaml +++ b/.github/workflows/coverity.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: dependencies run: > sudo apt-get install --yes diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml index 42e21f580..9d0c99de9 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -41,7 +41,7 @@ jobs: container: ghcr.io/mwilck/multipath-cross-debian_cross-${{ matrix.os }}-${{ matrix.arch }} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: build run: make -j$(nproc) -Orecurse test-progs.tar - name: upload binary archive diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index 7dbcc8f6d..cf1b016a4 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -47,7 +47,7 @@ jobs: arch: ppc64le steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: enable foreign arch uses: docker/setup-qemu-action@v2 with: diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index 3aee3b028..c187e9cda 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -66,7 +66,7 @@ jobs: runs-on: ${{ matrix.variant.runner }} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: enable foreign arch uses: docker/setup-qemu-action@v2 with: diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 9c4fa2e82..218be91cf 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -46,7 +46,7 @@ jobs: runs-on: ${{ matrix.variant.runner }} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 # On jessie, we use libreadline 5 (no licensing issue) - name: set readline make option (Jessie) @@ -123,7 +123,7 @@ jobs: runs-on: ${{ matrix.variant.runner }} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 # On jessie, we use libreadline 5 (no licensing issue) - name: set readline make option (Jessie) @@ -191,7 +191,7 @@ jobs: run: sudo modprobe brd rd_nr=1 rd_size=65536 - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: download binary archive uses: actions/download-artifact@v4 diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index 9f178f776..5f650e7a5 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -58,7 +58,7 @@ jobs: runs-on: ${{ matrix.variant.runner }} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Set coredump pattern run: | echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern From 0c76a5485adeefc0d375823e9b72e6b109657207 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 10 Jul 2026 11:48:05 +0200 Subject: [PATCH 31/40] GitHub workflows: replace setup-qemu-action@v2 with @v4 setup-qemu-action@v2 uses node 20. Signed-off-by: Martin Wilck --- .github/workflows/foreign.yaml | 4 ++-- .github/workflows/multiarch-stable.yaml | 2 +- .github/workflows/multiarch.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml index 9d0c99de9..4f187403b 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -78,7 +78,7 @@ jobs: - name: unpack binary archive run: tar xfv test-progs.tar - name: enable foreign arch - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v4 with: image: tonistiigi/binfmt:latest - name: Set coredump pattern @@ -144,7 +144,7 @@ jobs: - name: unpack binary archive run: tar xfv test-progs.tar - name: enable foreign arch - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v4 with: image: tonistiigi/binfmt:latest - name: Set coredump pattern diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index cf1b016a4..947ea0cab 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -49,7 +49,7 @@ jobs: - name: checkout uses: actions/checkout@v7 - name: enable foreign arch - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v4 with: image: tonistiigi/binfmt:latest - name: set architecture name diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index c187e9cda..4f9e68cdb 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -68,7 +68,7 @@ jobs: - name: checkout uses: actions/checkout@v7 - name: enable foreign arch - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v4 with: image: tonistiigi/binfmt:latest - name: set architecture name From 2a92d133d906f95f7baf4488794d6a44e471aa8f Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 10 Jul 2026 12:34:55 +0200 Subject: [PATCH 32/40] Add dependabot.yml for tracking github action updates Use the special branch "workflows" for this purpose. It contains only files related to GitHub workflows. Signed-off-by: Martin Wilck --- dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 dependabot.yml diff --git a/dependabot.yml b/dependabot.yml new file mode 100644 index 000000000..57dff7fa7 --- /dev/null +++ b/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + # Enable version updates for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + target-branch: "workflows" + commit-message: + prefix: "GitHub workflows [dependabot]: " From 9dfa719f0f91e2c6ef335b0447a3bd8dbdadf7ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:59:40 +0000 Subject: [PATCH 33/40] GitHub workflows [dependabot]: Bump actions/upload-artifact from 4 to 7 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/abi-stable.yaml | 4 ++-- .github/workflows/abi.yaml | 4 ++-- .github/workflows/foreign.yaml | 6 +++--- .github/workflows/multiarch-stable.yaml | 4 ++-- .github/workflows/multiarch.yaml | 4 ++-- .github/workflows/native.yaml | 8 ++++---- .github/workflows/rolling.yaml | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml index b41a00dca..61e60d8b6 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -62,7 +62,7 @@ jobs: run: make -j$(nproc) -Orecurse abi - name: save ABI if: steps.download_abi.outcome != 'success' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: multipath-abi-${{ env.PARENT_TAG }} path: abi @@ -113,7 +113,7 @@ jobs: continue-on-error: true - name: save differences if: steps.check_abi.outcome != 'success' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: abi-test path: abi-test diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml index 4810737a5..0d679bb4f 100644 --- a/.github/workflows/abi.yaml +++ b/.github/workflows/abi.yaml @@ -47,7 +47,7 @@ jobs: - name: create ABI run: make -Orecurse -j$(nproc) abi.tar.gz - name: save ABI - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: abi path: abi @@ -59,7 +59,7 @@ jobs: run: make abi-test - name: save differences if: steps.compare.outcome == 'failure' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: abi-test path: abi-test diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml index 4f187403b..310fbb650 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -45,7 +45,7 @@ jobs: - name: build run: make -j$(nproc) -Orecurse test-progs.tar - name: upload binary archive - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: cross-${{ matrix.os }}-${{ matrix.arch }} path: test-progs.tar @@ -103,7 +103,7 @@ jobs: run: make test-outputs.tar if: steps.test.outcome != 'success' - name: upload test outputs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: test-${{ matrix.os }}-${{ matrix.arch }} path: test-outputs.tar @@ -172,7 +172,7 @@ jobs: run: make test-outputs.tar if: steps.root-test.outcome != 'success' - name: upload test outputs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: root-test-${{ matrix.os }}-${{ matrix.arch }} path: test-outputs.tar diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index 947ea0cab..e69e371c8 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -73,7 +73,7 @@ jobs: ghcr.io/mwilck/multipath-build-${{ matrix.os }} test-progs.tar if: steps.test.outcome != 'success' - name: upload binary archive - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: binaries-${{ matrix.os }}-${{ env.ARCH_NAME }} path: test-progs.tar @@ -87,7 +87,7 @@ jobs: run: make test-outputs.tar if: steps.test.outcome != 'success' - name: upload test outputs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: test-${{ matrix.os }}-${{ env.ARCH_NAME }} path: test-outputs.tar diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index 4f9e68cdb..f0fb4b6a4 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -96,13 +96,13 @@ jobs: ghcr.io/mwilck/multipath-build-${{ matrix.os }} test-progs.tar test-outputs.tar if: steps.test.outcome != 'success' - name: upload binary archive - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: binaries-${{ matrix.os }}w-${{ env.ARCH_NAME }} path: test-progs.tar if: steps.test.outcome != 'success' - name: upload test outputs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: test-${{ matrix.os }}-${{ env.ARCH_NAME }} path: test-outputs.tar diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 218be91cf..06f830fad 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -71,7 +71,7 @@ jobs: ghcr.io/mwilck/multipath-build-${{ matrix.os }} test-progs.tar - name: upload test-progs.tar - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: native-${{ matrix.os }}-${{ matrix.variant.arch }} path: test-progs.tar @@ -87,7 +87,7 @@ jobs: if: steps.test.outcome != 'success' - name: upload test-outputs.tar - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: gcc-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} path: test-outputs.tar @@ -153,7 +153,7 @@ jobs: if: steps.test.outcome != 'success' - name: upload test-outputs.tar - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: clang-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} path: test-outputs.tar @@ -227,7 +227,7 @@ jobs: if: steps.test.outcome != 'success' - name: upload test-outputs.tar - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: clang-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} path: test-outputs.tar diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index 5f650e7a5..43f5c4c72 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -73,7 +73,7 @@ jobs: run: make test-progs.tar if: steps.test.outcome != 'success' - name: upload binary archive - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: binaries-${{ matrix.os }}-${{ matrix.variant.arch }}-${{ matrix.compiler }} path: test-progs.tar @@ -86,7 +86,7 @@ jobs: run: make test-outputs.tar if: steps.test.outcome != 'success' - name: upload test-outputs.tar - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: outputs-${{ matrix.os }}-${{ matrix.variant.arch }}-${{ matrix.compiler }} path: test-outputs.tar From 73be7841798da3c06a93d41776b332dc9f5978b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:59:59 +0000 Subject: [PATCH 34/40] GitHub workflows [dependabot]: Bump actions/checkout from 4 to 7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codingstyle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codingstyle.yml b/.github/workflows/codingstyle.yml index a36b3874e..75d9a8a2f 100644 --- a/.github/workflows/codingstyle.yml +++ b/.github/workflows/codingstyle.yml @@ -30,7 +30,7 @@ jobs: stylecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - run: >- echo "BASEREF=${{ github.event.pull_request.base.sha }}" >>$GITHUB_ENV if: github.event_name == 'pull_request' From 5ad8ce72986ff438822e6f728c152185779d04c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:00:08 +0000 Subject: [PATCH 35/40] GitHub workflows [dependabot]: Bump actions/download-artifact Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/foreign.yaml | 4 ++-- .github/workflows/native.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml index 310fbb650..5e6cf0bfd 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -72,7 +72,7 @@ jobs: run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV if: matrix.arch == 'armhf' - name: download binary archive - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: cross-${{ matrix.os }}-${{ matrix.arch }} - name: unpack binary archive @@ -138,7 +138,7 @@ jobs: run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV if: matrix.arch == 'armhf' - name: download binary archive - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: cross-${{ matrix.os }}-${{ matrix.arch }} - name: unpack binary archive diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 06f830fad..e9a16664a 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -194,7 +194,7 @@ jobs: uses: actions/checkout@v7 - name: download binary archive - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: native-${{ matrix.os }}-${{ matrix.variant.arch }} From 7177fa065b7610128981aa27b9ef3d4a7df41653 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jul 2026 10:59:48 +0000 Subject: [PATCH 36/40] GitHub workflows [dependabot]: Bump dawidd6/action-download-artifact Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 6 to 21. - [Release notes](https://github.com/dawidd6/action-download-artifact/releases) - [Commits](https://github.com/dawidd6/action-download-artifact/compare/v6...v21) --- updated-dependencies: - dependency-name: dawidd6/action-download-artifact dependency-version: '21' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/abi-stable.yaml | 4 ++-- .github/workflows/abi.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml index 61e60d8b6..7d197f49d 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -33,7 +33,7 @@ jobs: - name: try to download ABI for ${{ env.PARENT_TAG }} id: download_abi continue-on-error: true - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v21 with: workflow: abi-stable.yaml workflow_conclusion: '' @@ -90,7 +90,7 @@ jobs: ref: ${{ github.ref }} - name: download ABI for ${{ env.PARENT_TAG }} id: download_abi - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v21 with: workflow: abi-stable.yaml workflow_conclusion: '' diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml index 0d679bb4f..82af1e498 100644 --- a/.github/workflows/abi.yaml +++ b/.github/workflows/abi.yaml @@ -29,7 +29,7 @@ jobs: - name: get reference ABI id: reference continue-on-error: true - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v21 with: workflow: abi.yaml branch: ${{ env.ABI_BRANCH }} From 1e193a620773abd91f2707b273d57202ce81f38f Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 18 Jun 2026 21:54:45 +0200 Subject: [PATCH 37/40] GitHub workflows: remove spelling action The check_spelling action seems to have been compromised. Disabling it. https://github.com/jsoref/2026-06-16-credential-leak/blob/main/README.md Signed-off-by: Martin Wilck --- .github/actions/spelling/expect.txt | 278 -------------------------- .github/actions/spelling/only.txt | 18 -- .github/actions/spelling/patterns.txt | 119 ----------- .github/workflows/spelling.yml | 197 ------------------ 4 files changed, 612 deletions(-) delete mode 100644 .github/actions/spelling/expect.txt delete mode 100644 .github/actions/spelling/only.txt delete mode 100644 .github/actions/spelling/patterns.txt delete mode 100644 .github/workflows/spelling.yml diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt deleted file mode 100644 index dd39ed672..000000000 --- a/.github/actions/spelling/expect.txt +++ /dev/null @@ -1,278 +0,0 @@ -abi -adt -aio -Alletra -alloc -alltgpt -alua -aptpl -ASAN -ascq -ata -autoconfig -autodetected -autoresize -barbie -BINDIR -bitfield -blkid -bmarzins -Bsymbolic -cciss -CFLAGS -cgroups -christophe -clangd -clariion -cmdline -cmocka -coldplug -commandline -COMPAQ -configdir -configfile -configurator -coverity -cplusplus -CPPFLAGS -ctx -dasd -datacore -ddf -Debian -DESTDIR -devmaps -devname -devnode -devpath -DEVTYPE -DGC -DIO -directio -disablequeueing -dmevent -dmi -dmmp -dmraid -dmsetup -dracut -EAGAIN -ECKD -emc -Engenio -EVPD -Exos -failback -failover -fds -fexceptions -FFFFFFFF -fge -fno -followover -forcequeueing -fpin -fulldescr -gcc -getprkey -getprstatus -getrlimit -getuid -github -gitlab -google -GPT -hbtl -hds -HITACHI -hotplug -HPE -HSG -HSV -Huawei -hwhandler -hwtable -iet -ifdef -ifndef -igroup -img -Infini -Infinidat -inotify -inttypes -ioctls -iscsi -isw -kpartx -LDFLAGS -len -libaio -libc -LIBDEPS -libdevmapper -libdmmp -libedit -libjson -libmpathcmd -libmpathpersist -libmpathutil -libmpathvalid -libmultipath -libreadline -libsystemd -libudev -libudevdir -liburcu -linux -LIO -lld -lpthread -Lun -lvm -lvmteam -Lyve -Marzinski -misdetection -mpath -mpathb -mpathpersist -mpathvalid -msecs -multipathc -multipathd -multipathed -multipathing -multipaths -multiqueue -mwilck -NFINIDAT -NOLOG -nompath -NOSCAN -Nosync -nvme -Nytro -OBJDEPS -oneshot -ontap -OOM -opensvc -OPTFLAGS -paramp -partx -pathgroup -pathlist -petabytes -pgpolicy -pgvec -plugindir -PNR -ppc -preferredip -preferredsds -prefixdir -prgeneration -Primera -prioritizer -prkeys -PROUT -pthreads -QSAN -rdac -rdma -readcap -readdescr -readfd -readkeys -readline -readsector -rebranded -reconfig -redhat -restorequeueing -retrigger -retryable -rhabarber -rootprefix -rootprefixdir -rpmbuild -rport -rtpi -rtprio -sanitizers -sas -sbp -scsi -SCST -sda -Seagate -setmarginal -setprkey -setprstatus -shm -shu -SIGHUP -softdep -spi -srp -ssa -standalone -statedir -stdarg -stdint -STRERR -strerror -suse -svg -switchgroup -sys -SYSDIR -sysfs -sysinit -tcp -terabytes -TESTDEPS -testname -tgill -TGTDIR -TIDS -tmo -tpg -transitioning -transportid -trnptid -udev -udevadm -udevd -uevent -uid -unitdir -unsetmarginal -unsetprkey -unsetprstatus -unspec -usb -userdata -userspace -usr -uuid -valgrind -varoqui -versioning -Vess -vgr -VNX -vpd -VSN -wakka -weightedpath -wholedisk -Wilck -wildcards -workflows -wrt -wwid -wwn -wwnn -wwpn diff --git a/.github/actions/spelling/only.txt b/.github/actions/spelling/only.txt deleted file mode 100644 index a1750d935..000000000 --- a/.github/actions/spelling/only.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Files to check - see on.push.paths in spelling.yml -# public header files -libdmmp\.h -mpath_valid\.h -mpath_cmd\.h -mpath_persist\.h -# udev rules -\.rules -\.rules\.in -# systemd unit files -\.service -\.service\.in -\.socket -# man pages -\.[358] -\.[358]\.in -README\.md -NEWS\.md diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt deleted file mode 100644 index b6a7aaeb7..000000000 --- a/.github/actions/spelling/patterns.txt +++ /dev/null @@ -1,119 +0,0 @@ -# https://www.gnu.org/software/groff/manual/groff.html -# man troff content -\\f[BCIPR] -# '/" -\\\([ad]q - -# uuid: -\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b - -#commit -\b[0-9a-f]{7}\b - -# Generic Hex numbers -\b0x[0-9a-f]{4}\b -\b0x[0-9a-f]{8}\b -\b0x[0-9a-f]{16}\b - -# Commit SHAs -\b[0-9a-f]{7}\b - -# WWNN/WWPN (NAA identifiers) -\b(?:0x)?10[0-9a-f]{14}\b -\b(?:0x|3)?[25][0-9a-f]{15}\b -\b(?:0x|3)?6[0-9a-f]{31}\b - -# iSCSI iqn (approximate regex) -\biqn\.[0-9]{4}-[0-9]{2}(?:[\.-][a-z][a-z0-9]*)*\b - -# identifiers -\bCODESET_UTF8\b -\bdev_loss_tmo\b -\bdmmp_mps\b -\bdmmp_pgs\b -\bdmmp_mpath_kdev_name_get\b -\bfast_io_fail_tmo\b -\blibmp_mapinfo\b -\bLimitRTPRIO=?\b -\bmax_fds\b -\bmissing_uev_wait_timeout\b -\bMPATH_MAX_PARAM_LEN\b -\bMPATH_MX_TIDS\b -\bMPATH_MX_TID_LEN\b -\bMPATH_PRIN_RKEY_SA\b -\bMPATH_PRIN_RRES_SA\b -\bMPATH_PRIN_RCAP_SA\b -\bMPATH_PRIN_RFSTAT_SA\b -\bMPATH_PROUT_REG_SA\b -\bMPATH_PROUT_RES_SA\b -\bMPATH_PROUT_REL_SA\b -\bMPATH_PROUT_CLEAR_SA\b -\bMPATH_PROUT_PREE_SA\b -\bMPATH_PROUT_PREE_AB_SA\b -\bMPATH_PROUT_REG_IGN_SA\b -\bMPATH_PROUT_REG_MOV_SA\b -\bMPATH_LU_SCOPE\b -\bMPATH_PRTPE_WE\b -\bMPATH_PRTPE_EA\b -\bMPATH_PRTPE_WE_RO\b -\bMPATH_PRTPE_EA_RO\b -\bMPATH_PRTPE_WE_AR\b -\bMPATH_PRTPE_EA_AR\b -\bMPATH_PR_SKIP\b -\bMPATH_PR_SUCCESS\b -\bMPATH_PR_SYNTAX_ERROR\b -\bMPATH_PR_SENSE_NOT_READY\b -\bMPATH_PR_SENSE_MEDIUM_ERROR\b -\bMPATH_PR_SENSE_HARDWARE_ERROR\b -\bMPATH_PR_ILLEGAL_REQ\b -\bMPATH_PR_SENSE_UNIT_ATTENTION\b -\bMPATH_PR_SENSE_INVALID_OP\b -\bMPATH_PR_SENSE_ABORTED_COMMAND\b -\bMPATH_PR_NO_SENSE\b -\bMPATH_PR_SENSE_MALFORMED\b -\bMPATH_PR_RESERV_CONFLICT\b -\bMPATH_PR_FILE_ERROR\b -\bMPATH_PR_DMMP_ERROR\b -\bMPATH_PR_THREAD_ERROR\b -\bMPATH_PR_OTHER\b -\bMPATH_F_APTPL_MASK\b -\bMPATH_F_ALL_TG_PT_MASK\b -\bMPATH_F_SPEC_I_PT_MASK\b -\bMPATH_PR_TYPE_MASK\b -\bMPATH_PR_SCOPE_MASK\b -\bMPATH_PROTOCOL_ID_FC\b -\bMPATH_PROTOCOL_ID_ISCSI\b -\bMPATH_PROTOCOL_ID_SAS\b -\bMPATH_WWUI_DEVICE_NAME\b -\bMPATH_WWUI_PORT_IDENTIFIER\b -\bmpath_persistent_reserve_init_vecs\b -\bmpath_persistent_reserve_free_vecs\b -\bmpath_recv_reply\b -\bmpath_recv_reply_len\b -\bmpath_recv_reply_data\b -\bMPATHTEST_VERBOSITY\b -\bprkeys_file\b -\bprout-type\b -\bprin_capdescr\b -\bprin_readresv\b -\bprin_resvdescr\b -\bprout_param_descriptor\b -\brq_servact\b -\bRLIMIT_RTPRIO\b -\bSCHED_RT_PRIO\b -\bssize_t\b -\btrnptid_list\b -\buxsock_timeout\b - -# Other -\bTutf8\b -\bUTF-8\b -\bCLARiiON\b -\bGPLv2\b -\bHBAs\b -\bSANtricity\b -\bVTrak\b -\bXSG1\b - - - diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml deleted file mode 100644 index bfce4e662..000000000 --- a/.github/workflows/spelling.yml +++ /dev/null @@ -1,197 +0,0 @@ -name: Check Spelling - -# Comment management is handled through a secondary job, for details see: -# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions -# -# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment -# (in odd cases, it might actually run just to collapse a comment, but that's fairly rare) -# it needs `contents: write` in order to add a comment. -# -# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment -# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment) -# it needs `pull-requests: write` in order to manipulate those comments. - -# Updating pull request branches is managed via comment handling. -# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list -# -# These elements work together to make it happen: -# -# `on.issue_comment` -# This event listens to comments by users asking to update the metadata. -# -# `jobs.update` -# This job runs in response to an issue_comment and will push a new commit -# to update the spelling metadata. -# -# `with.experimental_apply_changes_via_bot` -# Tells the action to support and generate messages that enable it -# to make a commit to update the spelling metadata. -# -# `with.ssh_key` -# In order to trigger workflows when the commit is made, you can provide a -# secret (typically, a write-enabled github deploy key). -# -# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key - -# Sarif reporting -# -# Access to Sarif reports is generally restricted (by GitHub) to members of the repository. -# -# Requires enabling `security-events: write` -# and configuring the action with `use_sarif: 1` -# -# For information on the feature, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Sarif-output - -# Minimal workflow structure: -# -# on: -# push: -# ... -# pull_request_target: -# ... -# jobs: -# # you only want the spelling job, all others should be omitted -# spelling: -# # remove `security-events: write` and `use_sarif: 1` -# # remove `experimental_apply_changes_via_bot: 1` -# ... otherwise adjust the `with:` as you wish - -on: - push: - branches: - - "**" - tags-ignore: - - "**" - paths: - - '.github/workflows/spelling.yml' - - 'README*' - - 'NEWS.md' - - '**.3' - - '**.5' - - '**.8' - - '**.8' - - '**.in' - - '**.service' - - '**.socket' - - '**.rules' - - '**/libdmmp.h' - - '**/mpath_valid.h' - - '**/mpath_cmd.h' - - '**/mpath_persist.h' - - '.github/actions/spelling/*' - pull_request_target: - branches: - - "**" - types: - - 'opened' - - 'reopened' - - 'synchronize' - paths: - - '.github/workflows/spelling.yml' - - 'README*' - - 'NEWS.md' - - '**.3' - - '**.5' - - '**.8' - - '**.8' - - '**.in' - - '**.service' - - '**.socket' - - '**.rules' - - '**/libdmmp.h' - - '**/mpath_valid.h' - - '**/mpath_cmd.h' - - '**/mpath_persist.h' - - '.github/actions/spelling/*' - -jobs: - spelling: - name: Check Spelling - permissions: - contents: read - pull-requests: read - actions: read - security-events: write - outputs: - followup: ${{ steps.spelling.outputs.followup }} - runs-on: ubuntu-latest - if: ${{ contains(github.event_name, 'pull_request') || github.event_name == 'push' }} - concurrency: - group: spelling-${{ github.event.pull_request.number || github.ref }} - # note: If you use only_check_changed_files, you do not want cancel-in-progress - cancel-in-progress: true - steps: - - name: check-spelling - id: spelling - uses: check-spelling/check-spelling@main - with: - suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }} - checkout: true - spell_check_this: opensvc/multipath-tools@master - post_comment: 0 - use_magic_file: 1 - report-timing: 0 - warnings: bad-regex,binary-file,deprecated-feature,large-file,limited-references,no-newline-at-eof,noisy-file,non-alpha-in-dictionary,token-is-substring,unexpected-line-ending,whitespace-in-dictionary,minified-file,unsupported-configuration,no-files-to-check - experimental_apply_changes_via_bot: 1 - use_sarif: ${{ (!github.event.pull_request || (github.event.pull_request.head.repo.full_name == github.repository)) && 1 }} - extra_dictionary_limit: 20 - extra_dictionaries: - cspell:software-terms/dict/softwareTerms.txt - cspell:cpp/src/stdlib-c.txt - - comment-push: - name: Report (Push) - # If your workflow isn't running on push, you can remove this job - runs-on: ubuntu-latest - needs: spelling - permissions: - contents: write - if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push' - steps: - - name: comment - uses: check-spelling/check-spelling@main - with: - checkout: true - spell_check_this: opensvc/multipath-tools@master - task: ${{ needs.spelling.outputs.followup }} - - comment-pr: - name: Report (PR) - # If you workflow isn't running on pull_request*, you can remove this job - runs-on: ubuntu-latest - needs: spelling - permissions: - contents: read - pull-requests: write - if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request') - steps: - - name: comment - uses: check-spelling/check-spelling@main - with: - checkout: true - spell_check_this: opensvc/multipath-tools@master - task: ${{ needs.spelling.outputs.followup }} - experimental_apply_changes_via_bot: 1 - - update: - name: Update PR - permissions: - contents: write - pull-requests: write - actions: read - runs-on: ubuntu-latest - if: ${{ - github.event_name == 'issue_comment' && - github.event.issue.pull_request && - contains(github.event.comment.body, '@check-spelling-bot apply') - }} - concurrency: - group: spelling-update-${{ github.event.issue.number }} - cancel-in-progress: false - steps: - - name: apply spelling updates - uses: check-spelling/check-spelling@main - with: - experimental_apply_changes_via_bot: 1 - checkout: true - ssh_key: "${{ secrets.CHECK_SPELLING }}" From 6b70d3bc4791963c2ca82c6e8a00f177f9326fb7 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 10 Jul 2026 22:51:08 +0200 Subject: [PATCH 38/40] libmultipath: bump version to 0.14.4 Signed-off-by: Martin Wilck --- libmultipath/version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libmultipath/version.h b/libmultipath/version.h index 8d25955ce..fba155c60 100644 --- a/libmultipath/version.h +++ b/libmultipath/version.h @@ -11,9 +11,9 @@ #ifndef VERSION_H_INCLUDED #define VERSION_H_INCLUDED -#define VERSION_CODE 0x000E03 +#define VERSION_CODE 0x000E04 /* MMDDYY, in hex */ -#define DATE_CODE 0x02051A +#define DATE_CODE 0x070A1A #define PROG "multipath-tools" From 0dd289769ecc8adf90cbc22fed4beb939bbb1eb0 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 6 Jul 2026 17:44:54 +0200 Subject: [PATCH 39/40] libmultipath: iet prioritizer: obtain PATH_ID from udev Instead of reading /dev/disk/by-id, use the udev PATH_ID property to derive the device path. Signed-off-by: Martin Wilck Tested-by: Arnaldo Viegas de Lima (cherry picked from commit 5cbd51e418b6ab0dc69b3fff4a583863e6055996) --- libmultipath/prioritizers/Makefile | 2 +- libmultipath/prioritizers/iet.c | 97 ++++++++++++++---------------- 2 files changed, 45 insertions(+), 54 deletions(-) diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile index ff2524c26..78f69ff76 100644 --- a/libmultipath/prioritizers/Makefile +++ b/libmultipath/prioritizers/Makefile @@ -8,7 +8,7 @@ include ../../Makefile.inc CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) CFLAGS += $(LIB_CFLAGS) LDFLAGS += -L$(multipathdir) -L$(mpathutildir) -LIBDEPS = -lmultipath -lmpathutil -lm -lpthread -lrt +LIBDEPS = -lmultipath -lmpathutil -ludev -lm -lpthread -lrt # If you add or remove a prioritizer also update multipath/multipath.conf.5 LIBS = \ diff --git a/libmultipath/prioritizers/iet.c b/libmultipath/prioritizers/iet.c index 1e7f1e895..8581bcf19 100644 --- a/libmultipath/prioritizers/iet.c +++ b/libmultipath/prioritizers/iet.c @@ -1,10 +1,11 @@ -#include #include +#include #include #include #include #include #include +#include #include "prio.h" #include "debug.h" #include @@ -26,13 +27,14 @@ // by Olivier Lambert // -#define dc_log(prio, msg) condlog(prio, "%s: iet prio: " msg, dev) +#define dc_log(prio, msg) condlog(prio, "%s: iet prio: " msg, sysname) + // // name: find_regex // @param string: string you want to search into // @param regex: the pattern used // @return result: string found in string with regex, "none" if none -char *find_regex(char * string, char * regex) +char *find_regex(const char *string, const char *regex) { int err; regex_t preg; @@ -73,75 +75,64 @@ char *find_regex(char * string, char * regex) // name: inet_prio // @param // @return prio -int iet_prio(const char *dev, char * args) +int iet_prio(struct udev_device *udev, char *args) { char preferredip_buff[255] = ""; char *preferredip = &preferredip_buff[0]; + const char *by_path; + char *ip; + static bool arg_logged = false; + int prio = 10; + const char *sysname; + + if (!udev) + return 0; + sysname = udev_device_get_sysname(udev); + if (!sysname) + sysname = "UNKNOWN"; + // Phase 1 : checks. If anyone fails, return prio 0. // check if args exists if (!args) { - dc_log(0, "need prio_args with preferredip set"); + if (!arg_logged) { + dc_log(2, "need prio_args with preferredip set"); + arg_logged = true; + } return 0; } // check if args format is OK - if (sscanf(args, "preferredip=%254s", preferredip) == 1) { - } else { - dc_log(0, "unexpected prio_args format"); + if (sscanf(args, "preferredip=%254s", preferredip) != 1) { + if (!arg_logged) { + dc_log(2, "unexpected prio_args format"); + arg_logged = true; + } return 0; } // check if ip is not too short if (strlen(preferredip) <= 7) { - dc_log(0, "prio args: preferredip too short"); + if (!arg_logged) { + dc_log(2, "prio args: preferredip too short"); + arg_logged = true; + } return 0; } - // Phase 2 : find device in /dev/disk/by-path to match device/ip - DIR *dir_p; - struct dirent *dir_entry_p; - enum { BUFFERSIZE = 1024 }; - char buffer[BUFFERSIZE]; - char fullpath[BUFFERSIZE] = "/dev/disk/by-path/"; - dir_p = opendir(fullpath); - if (!dir_p) - goto out; - // loop to find device in /dev/disk/by-path - while( NULL != (dir_entry_p = readdir(dir_p))) { - if (dir_entry_p->d_name[0] != '.') { - char path[BUFFERSIZE] = "/dev/disk/by-path/"; - strcat(path,dir_entry_p->d_name); - ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1); - if (nchars != -1) { - char *device; - buffer[nchars] = '\0'; - device = find_regex(buffer,"(sd[a-z]+)"); - // if device parsed is the right one - if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) { - char *ip; - ip = find_regex(dir_entry_p->d_name,"([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); - // if prefferedip and ip fetched matches - if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) { - // high prio - free(ip); - free(device); - closedir(dir_p); - return 20; - } - free(ip); - } - free(device); - } - else { - printf("error\n"); - } - } + by_path = udev_device_get_property_value(udev, "ID_PATH"); + if (by_path == NULL) { + dc_log(2, "failed to get BY_PATH property"); + return 0; } - // nothing found, low prio - closedir(dir_p); -out: - return 10; + condlog(3, "%s: iet prio: by_path=%s", sysname, by_path); + ip = find_regex(by_path, + "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); + if (ip != NULL && strncmp(ip, preferredip, strlen(ip)) == 0) + prio = 20; + + free(ip); + return prio; } int getprio(struct path * pp, char * args) { - return iet_prio(pp->dev, args); + return iet_prio(pp->udev, args); } From 35166e75a458bb00b6798297eda54a40300b0396 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 13 Jul 2026 15:55:57 +0000 Subject: [PATCH 40/40] Update NEWS.md Signed-off-by: Martin Wilck --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 58dae2e5a..c45301ed6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -31,6 +31,9 @@ See [README.md](README.md) for additional information. set to `once`. * Avoid potential buffer overflows in the iet and datacore prioritizers. Commit 4611f97. +* iet prioritizer: avoid misleading error message with systemd 256 and + newer, and properly use udev to derive path parameters. + Fixes [#145](https://github.com/opensvc/multipath-tools/issues/145). ### Other changes