From 83162b2d38ab37d351acece118c8861815c0727b Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Tue, 11 Nov 2025 15:52:53 -0500 Subject: [PATCH 01/34] mpathpersist: Fix REPORT CAPABILITIES output mpathpersist was incorrectly parsing the REPORT CAPABILITES service action output. In reality, the type mask is two bytes where the type information is stored in bits 7, 6, 5, 3, & 1 (0xea) of the first byte and bit 0 (0x01) of the second byte. libmpathpersist was treating these two bytes as a big endian 16 bit number, but mpathpersist was looking for bits in that number as if it was little endian number. Ideally, libmpathpersist would treat prin_capdescr.pr_type_mask as two bytes, like it does for the flags. But we already expose this as a 16 bit number, where we treated the input bytes as a big endian number. There's no great reason to mess with the libmpathpersist API, when we can just make mpathpersist treat this data like libmpathpersist provides it. So, fix mpathpersist to print the data out correctly. Additionally, instead of printing a 1 or a 0 to indicate if a type was supported or not, it was printing the value of the type flag. Also, Persist Through Power Loss Capable (PTPL_C) was being reported if any bit in flags[0] was set. Fix these as well. Reformat all of the capability printing lines, since it is less confusing than only reformatting some of them. Fixes: ae4e8a6 ("mpathpersist: Add new utility for managing persistent reservation on dm multipath device") Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit c8ed5e6eea98244745904adaaa4aef83a8722fb0) --- libmpathpersist/mpath_persist.h | 4 ++- mpathpersist/main.c | 43 +++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h index d94205f08..3a924dc22 100644 --- a/libmpathpersist/mpath_persist.h +++ b/libmpathpersist/mpath_persist.h @@ -107,7 +107,9 @@ struct prin_capdescr { uint16_t length; uint8_t flags[2]; - uint16_t pr_type_mask; + uint16_t pr_type_mask; /* The two bytes of the type mask are treated + as a single big-endian number. So the valid + type bits are 0xea01 */ uint16_t _reserved; }; diff --git a/mpathpersist/main.c b/mpathpersist/main.c index efb46b95e..62cba5dcc 100644 --- a/mpathpersist/main.c +++ b/mpathpersist/main.c @@ -750,25 +750,42 @@ void mpath_print_buf_readcap( struct prin_resp *pr_buff) printf("Report capabilities response:\n"); - printf(" Compatible Reservation Handling(CRH): %d\n", !!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x10)); - printf(" Specify Initiator Ports Capable(SIP_C): %d\n",!!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x8)); - printf(" All Target Ports Capable(ATP_C): %d\n",!!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x4 )); - printf(" Persist Through Power Loss Capable(PTPL_C): %d\n",!!(pr_buff->prin_descriptor.prin_readcap.flags[0])); - printf(" Type Mask Valid(TMV): %d\n", !!(pr_buff->prin_descriptor.prin_readcap.flags[1] & 0x80)); - printf(" Allow Commands: %d\n", !!(( pr_buff->prin_descriptor.prin_readcap.flags[1] >> 4) & 0x7)); + printf(" Compatible Reservation Handling(CRH): %d\n", + !!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x10)); + printf(" Specify Initiator Ports Capable(SIP_C): %d\n", + !!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x8)); + printf(" All Target Ports Capable(ATP_C): %d\n", + !!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x4)); + printf(" Persist Through Power Loss Capable(PTPL_C): %d\n", + !!(pr_buff->prin_descriptor.prin_readcap.flags[0] & 0x1)); + printf(" Type Mask Valid(TMV): %d\n", + !!(pr_buff->prin_descriptor.prin_readcap.flags[1] & 0x80)); + printf(" Allow Commands: %d\n", + !!((pr_buff->prin_descriptor.prin_readcap.flags[1] >> 4) & 0x7)); printf(" Persist Through Power Loss Active(PTPL_A): %d\n", - !!(pr_buff->prin_descriptor.prin_readcap.flags[1] & 0x1)); + !!(pr_buff->prin_descriptor.prin_readcap.flags[1] & 0x1)); if(pr_buff->prin_descriptor.prin_readcap.flags[1] & 0x80) { printf(" Support indicated in Type mask:\n"); - printf(" %s: %d\n", pr_type_strs[7], pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x80); - printf(" %s: %d\n", pr_type_strs[6], pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x40); - printf(" %s: %d\n", pr_type_strs[5], pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x20); - printf(" %s: %d\n", pr_type_strs[3], pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x8); - printf(" %s: %d\n", pr_type_strs[1], pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x2); - printf(" %s: %d\n", pr_type_strs[8], pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x100); + printf(" %s: %d\n", pr_type_strs[7], + !!(pr_buff->prin_descriptor.prin_readcap.pr_type_mask & + 0x8000)); + printf(" %s: %d\n", pr_type_strs[6], + !!(pr_buff->prin_descriptor.prin_readcap.pr_type_mask & + 0x4000)); + printf(" %s: %d\n", pr_type_strs[5], + !!(pr_buff->prin_descriptor.prin_readcap.pr_type_mask & + 0x2000)); + printf(" %s: %d\n", pr_type_strs[3], + !!(pr_buff->prin_descriptor.prin_readcap.pr_type_mask & + 0x800)); + printf(" %s: %d\n", pr_type_strs[1], + !!(pr_buff->prin_descriptor.prin_readcap.pr_type_mask & + 0x200)); + printf(" %s: %d\n", pr_type_strs[8], + !!(pr_buff->prin_descriptor.prin_readcap.pr_type_mask & 0x1)); } } From ae08e5649825d051bbcbd4105e931cc523ef624e Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 14 Nov 2025 12:12:46 +0100 Subject: [PATCH 02/34] GitHub workflows: Update runners to ubuntu-24.04 Signed-off-by: Martin Wilck (cherry picked from commit 541e36e5e5f9394e9aa4a5af3d70ffbaaff8eeff) --- .github/workflows/abi-stable.yaml | 4 ++-- .github/workflows/abi.yaml | 3 ++- .github/workflows/build-and-unittest.yaml | 2 +- .github/workflows/coverity.yaml | 2 +- .github/workflows/foreign.yaml | 6 +++--- .github/workflows/multiarch-stable.yaml | 2 +- .github/workflows/multiarch.yaml | 2 +- .github/workflows/native.yaml | 6 +++--- .github/workflows/rolling.yaml | 2 +- 9 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml index 238a06bf3..8b2c83a85 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -15,7 +15,7 @@ on: jobs: reference-abi: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: get parent tag (push) run: > @@ -51,7 +51,7 @@ jobs: path: abi check-abi: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: reference-abi steps: - name: get parent tag (push) diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml index b1282493f..70ceb89df 100644 --- a/.github/workflows/abi.yaml +++ b/.github/workflows/abi.yaml @@ -18,7 +18,7 @@ env: jobs: save-and-test-ABI: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: set ABI branch if: ${{ env.ABI_BRANCH == '' }} @@ -42,6 +42,7 @@ jobs: 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$(grep -c ^processor /proc/cpuinfo) abi.tar.gz - name: save ABI diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml index 4f568131c..a3ee7d8e7 100644 --- a/.github/workflows/build-and-unittest.yaml +++ b/.github/workflows/build-and-unittest.yaml @@ -13,7 +13,7 @@ on: - 'stable-*' jobs: jammy: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: diff --git a/.github/workflows/coverity.yaml b/.github/workflows/coverity.yaml index 678d0d2a3..3ade6771b 100644 --- a/.github/workflows/coverity.yaml +++ b/.github/workflows/coverity.yaml @@ -6,7 +6,7 @@ on: jobs: upload-coverity-scan: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: checkout uses: actions/checkout@v4 diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml index 4cdc784a1..a0d9d988b 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -27,7 +27,7 @@ on: jobs: cross-build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -52,7 +52,7 @@ jobs: overwrite: true test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: cross-build strategy: fail-fast: false @@ -92,7 +92,7 @@ jobs: pull-params: "--platform linux/${{ env.CONTAINER_ARCH }}" root-test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: cross-build strategy: fail-fast: false diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index 2a30a8605..4c4bf95c0 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -26,7 +26,7 @@ on: jobs: build-old: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index c453446a6..c94f19ee6 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -30,7 +30,7 @@ on: jobs: build-current: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 6b38fa712..7b7e8c64a 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -26,7 +26,7 @@ on: jobs: stable: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -85,7 +85,7 @@ jobs: overwrite: true clang: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -117,7 +117,7 @@ jobs: command: -j -Orecurse READLINE=libreadline test root-test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: stable strategy: fail-fast: false diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index 503625e04..b5ff4f516 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -29,7 +29,7 @@ on: jobs: rolling: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: From 30c94649972cd3d26b740f188c6c2eb86da66b3d Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 14 Nov 2025 13:02:50 +0100 Subject: [PATCH 03/34] GitHub workflows: native.yaml: add fedora-43 Signed-off-by: Martin Wilck (cherry picked from commit 1dbc6ff522fdb188d750abb97b7fc714ded54c95) --- .github/workflows/native.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 7b7e8c64a..dbe701f0f 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -36,7 +36,7 @@ jobs: - debian-bullseye - debian-bookworm - debian-trixie - - fedora-42 + - fedora-43 - opensuse-leap steps: - name: checkout @@ -95,7 +95,7 @@ jobs: - debian-bullseye - debian-bookworm - debian-trixie - - fedora-42 + - fedora-43 - opensuse-leap steps: - name: checkout @@ -128,7 +128,7 @@ jobs: - debian-bullseye - debian-bookworm - debian-trixie - - fedora-42 + - fedora-43 - opensuse-leap steps: - name: mpath From e29ac85cef729be1b16dfd4ed6667a26c9759909 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 14 Nov 2025 13:03:15 +0100 Subject: [PATCH 04/34] GitHub workflows: native.yaml: add openSUSE Leap 16.0 and 15.6 "opensuse-leap" would use 15.6 already, but make this explicit. Signed-off-by: Martin Wilck (cherry picked from commit 6e09ca12218621589e2dfe7c59ef62d55bc4279d) --- .github/workflows/native.yaml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index dbe701f0f..f6ee8699f 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -37,7 +37,8 @@ jobs: - debian-bookworm - debian-trixie - fedora-43 - - opensuse-leap + - opensuse-leap-15.6 + - opensuse-leap-16.0 steps: - name: checkout uses: actions/checkout@v4 @@ -45,10 +46,10 @@ jobs: - name: set archive name # Leap containers have cpio but not tar run: echo ARCHIVE_TGT=test-progs.cpio >> $GITHUB_ENV - if: ${{ matrix.os == 'opensuse-leap' }} + if: ${{ startswith(matrix.os, 'opensuse-leap-15') }} - name: set archive name run: echo ARCHIVE_TGT=test-progs.tar >> $GITHUB_ENV - if: ${{ matrix.os != 'opensuse-leap' }} + if: ${{ !startswith(matrix.os, 'opensuse-leap-15') }} - name: build and test if: ${{ matrix.os != 'debian-jessie' }} @@ -96,7 +97,8 @@ jobs: - debian-bookworm - debian-trixie - fedora-43 - - opensuse-leap + - opensuse-leap-15.6 + - opensuse-leap-16.0 steps: - name: checkout uses: actions/checkout@v4 @@ -129,7 +131,8 @@ jobs: - debian-bookworm - debian-trixie - fedora-43 - - opensuse-leap + - opensuse-leap-15.6 + - opensuse-leap-16.0 steps: - name: mpath run: sudo modprobe dm_multipath @@ -145,10 +148,10 @@ jobs: name: native-${{ matrix.os }} - name: unpack binary archive run: cpio -idv < test-progs.cpio - if: ${{ matrix.os == 'opensuse-leap' }} + if: ${{ startswith(matrix.os, 'opensuse-leap-15') }} - name: unpack binary archive run: tar xfmv test-progs.tar - if: ${{ matrix.os != 'opensuse-leap' }} + if: ${{ !startswith(matrix.os, 'opensuse-leap-15') }} - name: run root tests uses: mosteo-actions/docker-run@v1 From 4f5d3828a537baeb14dc025191a7e3b95c70765c Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 14 Nov 2025 14:38:52 +0100 Subject: [PATCH 05/34] GitHub workflows: run arm64 tests on native runner GitHub provides arm64 runners now [1]. Use them. The workflows don't seem to run faster than before, but the tests should be more realistic. [1] https://github.blog/changelog/2025-01-16-linux-arm64-hosted-runners-now-available-for-free-in-public-repositories-public-preview/ Signed-off-by: Martin Wilck (cherry picked from commit 00cdcbc43e149aa41c1d81022350a74c9d2b4d69) --- .github/workflows/multiarch-stable.yaml | 4 ---- .github/workflows/multiarch.yaml | 5 +++- .github/workflows/native.yaml | 31 ++++++++++++++++++++----- .github/workflows/rolling.yaml | 13 +++++++++-- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index 4c4bf95c0..76ff1026d 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -37,14 +37,10 @@ jobs: - ubuntu-trusty arch: [386, arm/v7] include: - - os: debian-trixie - arch: aarch64 - os: debian-trixie arch: s390x - os: debian-trixie arch: ppc64le - - os: debian-bookworm - arch: aarch64 - os: debian-bookworm arch: s390x - os: debian-bookworm diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index c94f19ee6..b11ba06d5 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -39,12 +39,15 @@ jobs: - debian-sid - fedora-rawhide - opensuse-tumbleweed - arch: [amd64, ppc64le, aarch64, s390x, 386, arm/v7] + arch: [ppc64le, s390x, 386, arm/v7] exclude: - os: fedora-rawhide arch: 386 - os: fedora-rawhide arch: arm/v7 + include: + - os: alpine + arch: aarch64 steps: - name: checkout uses: actions/checkout@v4 diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index f6ee8699f..93eed5ff6 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -26,7 +26,6 @@ on: jobs: stable: - runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -39,6 +38,12 @@ jobs: - 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 @@ -81,17 +86,15 @@ jobs: - name: upload binary archive uses: actions/upload-artifact@v4 with: - name: native-${{ matrix.os }} + name: native-${{ matrix.os }}-${{ matrix.variant.arch }} path: ${{ env.ARCHIVE_TGT }} overwrite: true clang: - runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: os: - - debian-jessie - debian-buster - debian-bullseye - debian-bookworm @@ -99,6 +102,17 @@ jobs: - 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 @@ -119,7 +133,6 @@ jobs: command: -j -Orecurse READLINE=libreadline test root-test: - runs-on: ubuntu-24.04 needs: stable strategy: fail-fast: false @@ -133,6 +146,12 @@ jobs: - 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 @@ -145,7 +164,7 @@ jobs: - name: download binary archive uses: actions/download-artifact@v4 with: - name: native-${{ matrix.os }} + name: native-${{ matrix.os }}-${{ matrix.variant.arch }} - name: unpack binary archive run: cpio -idv < test-progs.cpio if: ${{ startswith(matrix.os, 'opensuse-leap-15') }} diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index b5ff4f516..a4b67a0ef 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -29,15 +29,24 @@ on: jobs: rolling: - runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: os: - debian-sid - - alpine - opensuse-tumbleweed - fedora-rawhide + variant: + - arch: x86_64 + runner: ubuntu-24.04 + - arch: aarch64 + runner: ubuntu-24.04-arm + include: + - os: alpine + variant: + arch: x86_64 + runner: ubuntu-24.04 + runs-on: ${{ matrix.variant.runner }} container: ghcr.io/mwilck/multipath-build-${{ matrix.os }} steps: - name: checkout From 110943a0c1411f071fc4c756df04d9766d12efe2 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 17 Nov 2025 13:07:57 +0100 Subject: [PATCH 06/34] GitHub workflows: rolling: upload binaries on error This will allow debugging CI failures (to some extent, as we compile with optimization by default). Signed-off-by: Martin Wilck (cherry picked from commit aee2310bb6e8671e8311ea098df581bbf1acfdcb) --- .github/workflows/rolling.yaml | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index a4b67a0ef..34efcff68 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -41,21 +41,38 @@ jobs: 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 }} container: ghcr.io/mwilck/multipath-build-${{ matrix.os }} steps: - name: checkout uses: actions/checkout@v4 - name: build and test - run: make READLINE=libreadline -j -Orecurse test - - name: clean - run: make -j -Orecurse clean - - name: clang - env: - CC: clang - run: make READLINE=libedit -j -Orecurse test + id: test + run: make CC=${{ matrix.compiler }} READLINE=libreadline -j -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: fail + run: /bin/false + if: steps.test.outcome != 'success' From fe4cad18c97ddef724f1080150b3986e33d3b469 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 17 Nov 2025 13:31:25 +0100 Subject: [PATCH 07/34] GitHub workflows: multiarch-stable: upload binaries on error Signed-off-by: Martin Wilck (cherry picked from commit 34746cd08af6fa4969b0bc062d62d92750bef6f8) --- .github/workflows/multiarch-stable.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index 76ff1026d..b8c770e40 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -53,6 +53,7 @@ jobs: with: image: tonistiigi/binfmt:latest - name: compile and run unit tests + id: test uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} @@ -61,3 +62,23 @@ jobs: command: test params: "--platform linux/${{ matrix.arch }}" pull-params: "--platform linux/${{ matrix.arch }}" + continue-on-error: true + - name: create binary archive + uses: mosteo-actions/docker-run@v1 + with: + image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} + guest-dir: /build + host-dir: ${{ github.workspace }} + command: test-progs.tar + params: "--platform linux/${{ matrix.arch }}" + pull-params: "--platform linux/${{ matrix.arch }}" + if: steps.test.outcome != 'success' + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: binaries-${{ matrix.os }}-${{ matrix.arch }} + path: test-progs.tar + if: steps.test.outcome != 'success' + - name: fail + run: /bin/false + if: steps.test.outcome != 'success' From cec1303a5f3be42fa4316eec8eaecfc8b4e090e7 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 17 Nov 2025 13:31:47 +0100 Subject: [PATCH 08/34] GitHub workflows: native: upload binaries on error Signed-off-by: Martin Wilck (cherry picked from commit f3bdfef8f63b9647de0cf9d65fbbe2c9b31751cd) --- .github/workflows/native.yaml | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 93eed5ff6..94e5ef22d 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -57,18 +57,23 @@ jobs: if: ${{ !startswith(matrix.os, 'opensuse-leap-15') }} - name: build and test + id: test if: ${{ matrix.os != 'debian-jessie' }} uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} command: -j -Orecurse test + continue-on-error: true + - name: build and test (jessie) + id: test_jessie # On jessie, we use libreadline 5 (no licensing issue) if: ${{ matrix.os == 'debian-jessie' }} uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} command: -j -Orecurse READLINE=libreadline test + continue-on-error: true - name: create ${{ env.ARCHIVE_TGT }} if: ${{ matrix.os != 'debian-jessie' }} @@ -90,6 +95,13 @@ jobs: path: ${{ env.ARCHIVE_TGT }} overwrite: true + - name: fail + run: /bin/false + if: >- + ${{ ( matrix.os == 'debian-jessie' && + steps.test_jessie.outcome != 'success' ) || + ( matrix.os != 'debian-jessie' && + steps.test.outcome != 'success' ) }} clang: strategy: fail-fast: false @@ -117,20 +129,75 @@ jobs: - name: checkout uses: actions/checkout@v4 + - name: set archive name + # Leap containers have cpio but not tar + run: echo ARCHIVE_TGT=test-progs.cpio >> $GITHUB_ENV + if: ${{ startswith(matrix.os, 'opensuse-leap-15') }} + - name: set archive name + run: echo ARCHIVE_TGT=test-progs.tar >> $GITHUB_ENV + if: ${{ !startswith(matrix.os, 'opensuse-leap-15') }} + - name: clang + id: test if: ${{ matrix.os != 'debian-jessie' }} uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} params: -e CC=clang command: -j -Orecurse test + continue-on-error: true - name: clang (jessie) + id: test_jessie if: ${{ matrix.os == 'debian-jessie' }} uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} params: -e CC=clang command: -j -Orecurse READLINE=libreadline test + continue-on-error: true + + - name: create ${{ env.ARCHIVE_TGT }} + if: ${{ matrix.os != 'debian-jessie' }} + uses: mosteo-actions/docker-run@v1 + with: + image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} + command: ${{ env.ARCHIVE_TGT }} + if: >- + ${{ ( matrix.os == 'debian-jessie' && + steps.test_jessie.outcome != 'success' ) || + ( matrix.os != 'debian-jessie' && + steps.test.outcome != 'success' ) }} + - name: create ${{ env.ARCHIVE_TGT }} (jessie) + if: ${{ matrix.os == 'debian-jessie' }} + uses: mosteo-actions/docker-run@v1 + with: + image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} + command: READLINE=libreadline ${{ env.ARCHIVE_TGT }} + if: >- + ${{ ( matrix.os == 'debian-jessie' && + steps.test_jessie.outcome != 'success' ) || + ( matrix.os != 'debian-jessie' && + steps.test.outcome != 'success' ) }} + + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: clang-${{ matrix.os }}-${{ matrix.variant.arch }} + path: ${{ env.ARCHIVE_TGT }} + overwrite: true + if: >- + ${{ ( matrix.os == 'debian-jessie' && + steps.test_jessie.outcome != 'success' ) || + ( matrix.os != 'debian-jessie' && + steps.test.outcome != 'success' ) }} + + - name: fail + run: /bin/false + if: >- + ${{ ( matrix.os == 'debian-jessie' && + steps.test_jessie.outcome != 'success' ) || + ( matrix.os != 'debian-jessie' && + steps.test.outcome != 'success' ) }} root-test: needs: stable From 08eaf7969766811ac867b19506723baa7e60eb03 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 17 Nov 2025 13:35:08 +0100 Subject: [PATCH 09/34] GitHub workflows: multiarch: upload binaries on error Signed-off-by: Martin Wilck (cherry picked from commit b854c7b9208d3fffff7cfb5fabb18d5e8db4770f) --- .github/workflows/multiarch.yaml | 22 +++++++++++++++++++++- .github/workflows/native.yaml | 2 -- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/multiarch.yaml b/.github/workflows/multiarch.yaml index b11ba06d5..806275a13 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -56,6 +56,7 @@ jobs: with: image: tonistiigi/binfmt:latest - name: compile and run unit tests + id: test uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} @@ -64,4 +65,23 @@ jobs: command: test params: "--platform linux/${{ matrix.arch }}" pull-params: "--platform linux/${{ matrix.arch }}" - + continue-on-error: true + - name: create binary archive + uses: mosteo-actions/docker-run@v1 + with: + image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} + guest-dir: /build + host-dir: ${{ github.workspace }} + command: test-progs.tar + params: "--platform linux/${{ matrix.arch }}" + pull-params: "--platform linux/${{ matrix.arch }}" + if: steps.test.outcome != 'success' + - name: upload binary archive + uses: actions/upload-artifact@v4 + with: + name: binaries-${{ matrix.os }}-${{ matrix.arch }} + path: test-progs.tar + if: steps.test.outcome != 'success' + - name: fail + run: /bin/false + if: steps.test.outcome != 'success' diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 94e5ef22d..7baded415 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -157,7 +157,6 @@ jobs: continue-on-error: true - name: create ${{ env.ARCHIVE_TGT }} - if: ${{ matrix.os != 'debian-jessie' }} uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} @@ -168,7 +167,6 @@ jobs: ( matrix.os != 'debian-jessie' && steps.test.outcome != 'success' ) }} - name: create ${{ env.ARCHIVE_TGT }} (jessie) - if: ${{ matrix.os == 'debian-jessie' }} uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} From a1138a8fa3858906a82dfa9041b4de9448aa57fa Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 17 Nov 2025 15:05:47 +0100 Subject: [PATCH 10/34] GitHub workflows: use -j$(nproc) consistently The workflow files were using make's -j flag inconsistently. Fix it. Signed-off-by: Martin Wilck (cherry picked from commit f24aca35628371c25d92d14f8067b71972d16a00) --- .github/workflows/abi-stable.yaml | 4 ++-- .github/workflows/abi.yaml | 2 +- .github/workflows/build-and-unittest.yaml | 12 ++++++------ .github/workflows/coverity.yaml | 2 +- .github/workflows/foreign.yaml | 2 +- .github/workflows/native.yaml | 8 ++++---- .github/workflows/rolling.yaml | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml index 8b2c83a85..1ba9e7fa6 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -43,7 +43,7 @@ jobs: with: ref: ${{ env.PARENT_TAG }} - name: build ABI for ${{ env.PARENT_TAG }} - run: make -j$(grep -c ^processor /proc/cpuinfo) -Orecurse abi + run: make -j$(nproc) -Orecurse abi - name: save ABI uses: actions/upload-artifact@v4 with: @@ -88,7 +88,7 @@ jobs: libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev - name: check ABI of ${{ github.ref }} against ${{ env.PARENT_TAG }} id: check_abi - run: make -j$(grep -c ^processor /proc/cpuinfo) -Orecurse abi-test + run: make -j$(nproc) -Orecurse abi-test continue-on-error: true - name: save differences if: ${{ steps.check_abi.outcome != 'success' }} diff --git a/.github/workflows/abi.yaml b/.github/workflows/abi.yaml index 70ceb89df..adc2081f1 100644 --- a/.github/workflows/abi.yaml +++ b/.github/workflows/abi.yaml @@ -44,7 +44,7 @@ jobs: libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev libmount-dev - name: create ABI - run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) abi.tar.gz + run: make -Orecurse -j$(nproc) abi.tar.gz - name: save ABI uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml index a3ee7d8e7..2fb5327d4 100644 --- a/.github/workflows/build-and-unittest.yaml +++ b/.github/workflows/build-and-unittest.yaml @@ -46,16 +46,16 @@ jobs: if: ${{ matrix.cc == 'clang' }} - name: build run: > - make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) + make -Orecurse -j$(nproc) READLINE=${{ matrix.rl }} OPTFLAGS="$OPT" - name: test run: > - make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) + make -Orecurse -j$(nproc) OPTFLAGS="$OPT" test - name: valgrind-test id: valgrind run: > - make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) + make -Orecurse -j$(nproc) OPTFLAGS="$OPT" valgrind-test continue-on-error: true - name: valgrind-results @@ -92,12 +92,12 @@ jobs: - name: set CC run: echo CC=${{ matrix.cc }} >> $GITHUB_ENV - name: build - run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) READLINE=${{ matrix.rl }} + run: make -Orecurse -j$(nproc) READLINE=${{ matrix.rl }} - name: test - run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) test + run: make -Orecurse -j$(nproc) test - name: valgrind-test id: valgrind - run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) valgrind-test + run: make -Orecurse -j$(nproc) valgrind-test continue-on-error: true - name: valgrind-results run: cat tests/*.vgr diff --git a/.github/workflows/coverity.yaml b/.github/workflows/coverity.yaml index 3ade6771b..3c04c2124 100644 --- a/.github/workflows/coverity.yaml +++ b/.github/workflows/coverity.yaml @@ -32,7 +32,7 @@ jobs: - name: build with cov-build run: > PATH="$PWD/coverity/bin:$PATH" - cov-build --dir cov-int make -Orecurse -j"$(grep -c ^processor /proc/cpuinfo)" + cov-build --dir cov-int make -Orecurse -j"$(nproc)" - name: pack results run: tar cfz multipath-tools.tgz cov-int - name: submit results diff --git a/.github/workflows/foreign.yaml b/.github/workflows/foreign.yaml index a0d9d988b..fdcfaac69 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -43,7 +43,7 @@ jobs: - name: checkout uses: actions/checkout@v4 - name: build - run: make -j -Orecurse test-progs.tar + run: make -j$(nproc) -Orecurse test-progs.tar - name: upload binary archive uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/native.yaml b/.github/workflows/native.yaml index 7baded415..9e89780b1 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -62,7 +62,7 @@ jobs: uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - command: -j -Orecurse test + command: -j$(nproc) -Orecurse test continue-on-error: true - name: build and test (jessie) @@ -72,7 +72,7 @@ jobs: uses: mosteo-actions/docker-run@v1 with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - command: -j -Orecurse READLINE=libreadline test + command: -j$(nproc) -Orecurse READLINE=libreadline test continue-on-error: true - name: create ${{ env.ARCHIVE_TGT }} @@ -144,7 +144,7 @@ jobs: with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} params: -e CC=clang - command: -j -Orecurse test + command: -j$(nproc) -Orecurse test continue-on-error: true - name: clang (jessie) id: test_jessie @@ -153,7 +153,7 @@ jobs: with: image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} params: -e CC=clang - command: -j -Orecurse READLINE=libreadline test + command: -j$(nproc) -Orecurse READLINE=libreadline test continue-on-error: true - name: create ${{ env.ARCHIVE_TGT }} diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index 34efcff68..a4706e52e 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -62,7 +62,7 @@ jobs: uses: actions/checkout@v4 - name: build and test id: test - run: make CC=${{ matrix.compiler }} READLINE=libreadline -j -Orecurse test + run: make CC=${{ matrix.compiler }} READLINE=libreadline -j$(nproc) -Orecurse test continue-on-error: true - name: create binary archive run: make test-progs.tar From 34c597f0f3d82ec520d37e693dac5a09907a7133 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 17 Nov 2025 16:37:07 +0100 Subject: [PATCH 11/34] GitHub workflows: install libmount-dev on Ubuntu Without it, the workflows will fail. Signed-off-by: Martin Wilck --- .github/workflows/abi-stable.yaml | 2 ++ .github/workflows/coverity.yaml | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/workflows/abi-stable.yaml b/.github/workflows/abi-stable.yaml index 1ba9e7fa6..8f9a9dbf3 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -38,6 +38,7 @@ jobs: 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 }} uses: actions/checkout@v4 with: @@ -86,6 +87,7 @@ jobs: 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 diff --git a/.github/workflows/coverity.yaml b/.github/workflows/coverity.yaml index 3c04c2124..30e5471d3 100644 --- a/.github/workflows/coverity.yaml +++ b/.github/workflows/coverity.yaml @@ -16,6 +16,7 @@ jobs: 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 From 31be694aff2b14c687c5bfff94914d4a6dc3387b Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 21 Nov 2025 13:09:57 +0100 Subject: [PATCH 12/34] GitHub actions: spelling: ignore generic hex number patterns Fix the spelling CI complaints about "0xea01". Signed-off-by: Martin Wilck (cherry picked from commit 7ef482e8c0e89a69de729cff60d4981ca261d7e3) --- .github/actions/spelling/patterns.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt index f2ef14240..55d4742eb 100644 --- a/.github/actions/spelling/patterns.txt +++ b/.github/actions/spelling/patterns.txt @@ -10,6 +10,11 @@ #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 + # WWNN/WWPN (NAA identifiers) \b(?:0x)?10[0-9a-f]{14}\b \b(?:0x|3)?[25][0-9a-f]{15}\b From 3dcdf002976ba64a47c9812a0ff1d179b62f3661 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Wed, 7 Jan 2026 12:09:51 +0000 Subject: [PATCH 13/34] libmultipath: Remove the undefined symbol from the linker script dm_get_multipath() is a static function, not a symbol that can be exported. Clang is strict about not allowing undefined symbols in linker scripts and therefore its presence prevents clang from building libmultipath. It looks like it's a linker error and it's thrown only by lld. lld enabled --no-undefined-version as a default option [0]. Choice of a compiler (gcc, clang) shouldn't matter. One can reproduce the error on any system by specifying lld explicitly: $ make LDFLAGS="-fuse-ld=lld" Or by passing --no-undefined-version (and making the warning fatal), which throws an error wyth any linker: $ make LDFLAGS="-fuse-ld=mold -Wl,--no-undefined-version -Wl,--fatal-warnings". [0] https://reviews.llvm.org/D135402 Fixes: https://github.com/opensvc/multipath-tools/issues/132 Fixes: bf3a4ad ("libmultipath: simplify dm_get_maps()") Signed-off-by: Michal Rostecki Reviewed-by: Martin Wilck (cherry picked from commit a2986033c13de3b51002c6592dcfd59a6a8240dd) --- libmultipath/libmultipath.version | 1 - 1 file changed, 1 deletion(-) diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version index a0c8bacab..359565a89 100644 --- a/libmultipath/libmultipath.version +++ b/libmultipath/libmultipath.version @@ -82,7 +82,6 @@ global: dm_geteventnr; dm_get_major_minor; dm_get_maps; - dm_get_multipath; dm_is_mpath; dm_mapname; dm_prereq; From 21a54863b2e6765bc3b9661f0af63929162fab93 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 8 Dec 2025 15:18:01 +0100 Subject: [PATCH 14/34] multipath-tools: Fix ISO C23 errors with strchr() In ISO C23, memchr, strchr, strpbrk, strrchr and strstr become const-preserving macros [1], meaning that the return value inherits the const qualifier from the function argument. This has turned up a few glitches in our code. [1] https://gustedt.gitlabpages.inria.fr/c23-library/#memchr Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 9f611e2f10a4456477b6447641eea041ecee1019) --- libmpathutil/parser.c | 2 +- libmpathutil/util.c | 2 +- libmultipath/prkey.c | 2 +- libmultipath/prkey.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libmpathutil/parser.c b/libmpathutil/parser.c index b1db433f4..05784f9fd 100644 --- a/libmpathutil/parser.c +++ b/libmpathutil/parser.c @@ -153,7 +153,7 @@ snprint_keyword(struct strbuf *buff, const char *fmt, struct keyword *kw, const void *data) { int r = 0; - char *f; + const char *f; struct config *conf; STRBUF_ON_STACK(sbuf); diff --git a/libmpathutil/util.c b/libmpathutil/util.c index 125597427..32c76f4c1 100644 --- a/libmpathutil/util.c +++ b/libmpathutil/util.c @@ -38,7 +38,7 @@ strchop(char *str) */ const char *libmp_basename(const char *filename) { - char *p = strrchr(filename, '/'); + const char *p = strrchr(filename, '/'); return p ? p + 1 : filename; } diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c index c66d293b9..af4a28267 100644 --- a/libmultipath/prkey.c +++ b/libmultipath/prkey.c @@ -50,7 +50,7 @@ static int parse_prkey(const char *ptr, uint64_t *prkey) return 0; } -int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags) +int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags) { char *flagstr; diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h index a89a617bd..806795ed3 100644 --- a/libmultipath/prkey.h +++ b/libmultipath/prkey.h @@ -15,7 +15,7 @@ int print_reservation_key(struct strbuf *buff, struct be64 key, uint8_t flags, int source); -int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags); +int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags); int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey, uint8_t sa_flags); int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags); From 06ed46040530c0adb35fac3f050d87d18ddabb18 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Tue, 16 Dec 2025 21:58:42 +0100 Subject: [PATCH 15/34] Makefile: fix CI build errors with cmocka 2.0 cmocka 2.0.0 introduces a couple of changes that require version-dependent code to be used. Add macros to determine the cmocka version. If the version can't be determined, assume 1.1.0. Use a different approach here than in the stable branch, because the fix there is rather large. Instead of replacing all deprecated macros, just treat the respective warnings as non-fatal by adding the compiler flag -Wno-error=deprecated-declarations for the CI code. cmocka 2.0.1 added a macro to suppress these warnings altogether, but we should also be able to build against 2.0.0. Fixes: https://github.com/opensvc/multipath-tools/issues/129 Signed-off-by: Martin Wilck (cherry picked from commit 41807aa065d8ce87c5910beb2b1fdf14effe0b37) --- Makefile.inc | 2 +- create-config.mk | 5 +++++ tests/Makefile | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile.inc b/Makefile.inc index 65f6efc8c..71f352bd3 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -109,7 +109,7 @@ WARNFLAGS := $(WERROR) -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)imp -W$(ERROR)implicit-function-declaration -W$(ERROR)format-security \ $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \ +CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) $(D_CMOCKA_VERSION) \ -D_FILE_OFFSET_BITS=64 \ -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \ -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \ diff --git a/create-config.mk b/create-config.mk index e8fa391cc..14ab9ba00 100644 --- a/create-config.mk +++ b/create-config.mk @@ -77,6 +77,10 @@ URCU_VERSION = $(shell \ $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') +CMOCKA_VERSION = $(shell \ + ($(PKG_CONFIG) --modversion cmocka 2>/dev/null || echo "1.1.0" ) | \ + awk -F. '{ printf("%d", 256 * ( 256 * $$1 + $$2) + $$3); }') + DEFINES := ifneq ($(call check_func,dm_task_no_flush,$(devmapper_incdir)/libdevmapper.h),0) @@ -185,6 +189,7 @@ $(TOPDIR)/config.mk: $(multipathdir)/autoconfig.h @echo "FPIN_SUPPORT := $(FPIN_SUPPORT)" >$@ @echo "FORTIFY_OPT := $(FORTIFY_OPT)" >>$@ @echo "D_URCU_VERSION := $(call URCU_VERSION)" >>$@ + @echo "CMOCKA_VERSION := $(call CMOCKA_VERSION)" >>$@ @echo "SYSTEMD := $(SYSTEMD)" >>$@ @echo "ANA_SUPPORT := $(ANA_SUPPORT)" >>$@ @echo "STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)" >>$@ diff --git a/tests/Makefile b/tests/Makefile index 28c00ad2d..0ec036ebd 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,7 +5,8 @@ TESTDIR := $(CURDIR) CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathcmddir) -I$(daemondir) \ -DTESTCONFDIR=\"$(TESTDIR)/conf.d\" -CFLAGS += $(BIN_CFLAGS) -Wno-unused-parameter $(W_MISSING_INITIALIZERS) +CFLAGS += $(BIN_CFLAGS) -Wno-unused-parameter $(W_MISSING_INITIALIZERS) \ + $(if $(shell [ $(CMOCKA_VERSION) -ge 131072 ] && echo yes),-Wno-error=deprecated-declarations) LIBDEPS += -L. -L $(mpathutildir) -L$(mpathcmddir) -lmultipath -lmpathutil -lmpathcmd -lcmocka TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \ From 4d8827bc4b38ae822947cc843bf94db47a923835 Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Mon, 1 Dec 2025 22:02:11 -0500 Subject: [PATCH 16/34] multipath-tools man pages: fix multipathd commands keyword ordering multipathd now has a fixed ordering of the keywords. Specifically, verbs must come first. Fix the man page to reflect the ordering. Fixes: f812466f6 ("multipathd: more robust command parsing") Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit f3ba2e719567d5f21076e90aea9ba10b04004abd) --- multipathd/multipathd.8.in | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in index 7bc8806eb..cd0d4dda1 100644 --- a/multipathd/multipathd.8.in +++ b/multipathd/multipathd.8.in @@ -313,48 +313,48 @@ will not be disabled when the daemon stops. Restores configured queue_without_daemon mode. . .TP -.B map|multipath $map setprstatus +.B setprstatus map|multipath $map Enable persistent reservation management on $map. . .TP -.B map|multipath $map unsetprstatus +.B unsetprstatus map|multipath $map Disable persistent reservation management on $map. . .TP -.B map|multipath $map getprstatus +.B getprstatus map|multipath $map Get the current persistent reservation management status of $map. . .TP -.B map|multipath $map getprkey +.B getprkey map|multipath $map Get the current persistent reservation key associated with $map. . .TP -.B map|multipath $map setprkey key $key +.B setprkey map|multipath $map key $key Set the persistent reservation key associated with $map to $key in the \fIprkeys_file\fR. This key will only be used by multipathd if \fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR. . .TP -.B map|multipath $map unsetprkey +.B unsetprkey map|multipath $map Remove the persistent reservation key associated with $map from the \fIprkeys_file\fR. This will only unset the key used by multipathd if \fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR. . .TP -.B path $path setmarginal +.B setmarginal path $path move $path to a marginal pathgroup. The path will remain in the marginal path group until \fIunsetmarginal\fR is called. This command will only work if \fImarginal_pathgroups\fR is enabled and there is no Shaky paths detection method configured (see the multipath.conf man page for details). . .TP -.B path $path unsetmarginal +.B unsetmarginal path $path return marginal path $path to its normal pathgroup. This command will only work if \fImarginal_pathgroups\fR is enabled and there is no Shaky paths detection method configured (see the multipath.conf man page for details). . .TP -.B map $map unsetmarginal +.B unsetmarginal map $map return all marginal paths in $map to their normal pathgroups. This command will only work if \fImarginal_pathgroups\fR is enabled and there is no Shaky paths detection method configured (see the multipath.conf man page for details). From 81ffbb2468c5e0b3ac616c112be77ddf4f6600d5 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sat, 15 Nov 2025 15:50:10 +0100 Subject: [PATCH 17/34] multipath-tools: add Seagate Exos and Nytro series to hwtable Config from, #102: https://www.seagate.com/content/dam/seagate/migrated-assets/www-content/support-content/raid-storage-systems/corvault/_shared/files/205042000-01-B_CORVAULT_SMG.pdf 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 9889faee3ad2453a3976caaec50646aea1f4a798) --- libmultipath/hwtable.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c index 925230422..2734b78ea 100644 --- a/libmultipath/hwtable.c +++ b/libmultipath/hwtable.c @@ -1326,6 +1326,15 @@ static struct hwentry default_hw[] = { .prio_name = PRIO_ALUA, .no_path_retry = 30, }, + { + // Exos / Nytro series + .vendor = "SEAGATE", + .product = "^[456]", + .pgpolicy = GROUP_BY_PRIO, + .pgfailback = -FAILBACK_IMMEDIATE, + .prio_name = PRIO_ALUA, + .no_path_retry = 30, + }, /* * AccelStor */ From 48f5ccc328ef3d72136ea7f4d6eb40af2a0a1999 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Sun, 16 Nov 2025 15:20:19 +0100 Subject: [PATCH 18/34] multipath-tools: identify more Storwize models multipath is also supported by V3500 and V3700 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 5bdafa5f299a34fa418b24bb9c4f24f3c495b564) --- libmultipath/hwtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c index 2734b78ea..23c549335 100644 --- a/libmultipath/hwtable.c +++ b/libmultipath/hwtable.c @@ -682,7 +682,7 @@ static struct hwentry default_hw[] = { .pgfailback = -FAILBACK_IMMEDIATE, }, { - // Storwize V5000/V7000 lines / SAN Volume Controller (SVC) + // Storwize V3x00/V5000/V7000 lines / SAN Volume Controller (SVC) // Flex System V7000 / FlashSystem V840/V9000 and 5x00/7x00/9x00/Cx00 .vendor = "IBM", .product = "^2145", From e499cfe44c82d5bd492f8dcf7f7f601c64870fe5 Mon Sep 17 00:00:00 2001 From: Itxaka Date: Fri, 5 Dec 2025 09:28:06 +0100 Subject: [PATCH 19/34] multipathd: Dont pthread_join twice Currently it seems that urcu would already call pthread_join when calling call_rcu_data_free since a couple of years ago (since version v0.14.0)[0] so calling pthread_join on the just released one is problematic under musl systems. It seems like under glibc this has several checks in place before trying to dereference the thread but under musl it has nothing in place to validate so this causes a coredump on program shutdown. This is currently present in all version when compiled under musl, running multipathd -d and sending a SIGTERM to it, you can see the coredump happening at this point in the code. The patch runs only the old behaviour in urcu older than 0.14.0 to maintain the same bahaviour. In higher versions its not neccesary so we skip it. [0] https://github.com/urcu/userspace-rcu/commit/1cf55ba47342156cdf25335264b9774a16e0bb2d Signed-off-by: Itxaka Reviewed-by: Martin Wilck (cherry picked from commit 5835dca56c7fe0b06aad99183de4e8e179e3c56b) --- multipathd/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/multipathd/main.c b/multipathd/main.c index 21f55891c..ededff115 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -3654,18 +3654,21 @@ static struct call_rcu_data *mp_rcu_data; static void cleanup_rcu(void) { - pthread_t rcu_thread; - /* Wait for any pending RCU calls */ rcu_barrier(); if (mp_rcu_data != NULL) { +#if (URCU_VERSION < 0x000E00) + pthread_t rcu_thread; rcu_thread = get_call_rcu_thread(mp_rcu_data); +#endif /* detach this thread from the RCU thread */ set_thread_call_rcu_data(NULL); synchronize_rcu(); /* tell RCU thread to exit */ call_rcu_data_free(mp_rcu_data); +#if (URCU_VERSION < 0x000E00) pthread_join(rcu_thread, NULL); +#endif } rcu_unregister_thread(); } From 03e0d5d296b1fe55aafd5edc7b44726815457c5a Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 10 Dec 2025 20:00:33 +0100 Subject: [PATCH 20/34] multipathd: join the init_unwinder dummy thread This closes a minor memory leak (thread-local storage of the dummy thread is never freed). Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 29f262b7c7ee4ba1b384eac76be956b3efbfe99f) --- multipathd/init_unwinder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/multipathd/init_unwinder.c b/multipathd/init_unwinder.c index b1cd283d5..d39e4282f 100644 --- a/multipathd/init_unwinder.c +++ b/multipathd/init_unwinder.c @@ -34,5 +34,7 @@ int init_unwinder(void) pthread_mutex_unlock(&dummy_mtx); - return pthread_cancel(dummy); + rc = pthread_cancel(dummy); + pthread_join(dummy, NULL); + return rc; } From 7834a038def2d345f7ac037e364a406aa2ac3720 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 10 Dec 2025 23:39:02 +0100 Subject: [PATCH 21/34] kpartx: fix some memory leaks These leaks were reported by LeakSanitizer. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 8c39e60cba6c6ce6f9153f3d219574fbdb8e6ea0) --- kpartx/kpartx.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c index a1495e55e..7ec89b479 100644 --- a/kpartx/kpartx.c +++ b/kpartx/kpartx.c @@ -227,6 +227,11 @@ xmalloc (size_t size) { return t; } +static void cleanup_charp(char **p) +{ + free(*p); +} + int main(int argc, char **argv){ int i, j, m, n, op, off, arg, c, d, ro=0; @@ -237,10 +242,10 @@ main(int argc, char **argv){ char *type, *diskdevice, *device, *progname; int verbose = 0; char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16]; - char * loopdev = NULL; - char * delim = NULL; - char *uuid = NULL; - char *mapname = NULL; + char *loopdev __attribute__((cleanup(cleanup_charp))) = NULL; + char *delim __attribute__((cleanup(cleanup_charp))) = NULL; + char *uuid __attribute__((cleanup(cleanup_charp))) = NULL; + char *mapname __attribute__((cleanup(cleanup_charp))) = NULL; int hotplug = 0; int loopcreated = 0; struct stat buf; @@ -292,7 +297,9 @@ main(int argc, char **argv){ verbose = 1; break; case 'p': - delim = optarg; + delim = strdup(optarg); + if (!delim) + exit(1); break; case 'l': what = LIST; @@ -674,7 +681,6 @@ main(int argc, char **argv){ if (verbose) fprintf(stderr, "loop deleted : %s\n", device); } - end: dm_lib_exit(); From dc9ad51a3495c287c01126688a8a7c54d175b211 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 15 Jan 2026 23:08:39 +0100 Subject: [PATCH 22/34] kpartx: avoid double-free of mapname The variable mapname is sometimes allocated and sometimes not. To avoid double-free and still free allocated memory cleanly, introduce a helper pointer for storing possibly allocated memory. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 02e0933b1ea022c24d4d4aa2233082324b2771a1) --- kpartx/kpartx.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c index 7ec89b479..6f2ec4ea0 100644 --- a/kpartx/kpartx.c +++ b/kpartx/kpartx.c @@ -245,7 +245,8 @@ main(int argc, char **argv){ char *loopdev __attribute__((cleanup(cleanup_charp))) = NULL; char *delim __attribute__((cleanup(cleanup_charp))) = NULL; char *uuid __attribute__((cleanup(cleanup_charp))) = NULL; - char *mapname __attribute__((cleanup(cleanup_charp))) = NULL; + char *_mapname __attribute__((cleanup(cleanup_charp))) = NULL; + char *mapname; int hotplug = 0; int loopcreated = 0; struct stat buf; @@ -388,11 +389,15 @@ main(int argc, char **argv){ off = find_devname_offset(device); if (!loopdev) { - mapname = dm_mapname(major(buf.st_rdev), minor(buf.st_rdev)); - if (mapname) - uuid = dm_mapuuid(mapname); + _mapname = dm_mapname(major(buf.st_rdev), minor(buf.st_rdev)); + if (_mapname) + uuid = dm_mapuuid(_mapname); } + mapname = _mapname; + if (!mapname) + mapname = device + off; + /* * We are called for a non-DM device. * Make up a fake UUID for the device, unless "-d -f" is given. @@ -402,9 +407,6 @@ main(int argc, char **argv){ if (!uuid && !(what == DELETE && force_devmap)) uuid = nondm_create_uuid(buf.st_rdev); - if (!mapname) - mapname = device + off; - if (delim == NULL) { delim = xmalloc(DELIM_SIZE); memset(delim, 0, DELIM_SIZE); From f4b19b7d54e78dbb309edc7f0f6139578bddaa48 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 9 Jan 2026 15:26:48 +0100 Subject: [PATCH 23/34] libmultipath: warn only once in scsi_tmo_error_msg() The intention of this code was to warn only once for each unsupported protocol. But the condition statement is missing. Fixes: 6ad77db ("libmultipath: Set the scsi timeout parameters by path") Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 958c826862d04779a7405349b7c75db8fd0ddad1) --- libmultipath/discovery.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c index b58515615..abf84486e 100644 --- a/libmultipath/discovery.c +++ b/libmultipath/discovery.c @@ -879,6 +879,8 @@ scsi_tmo_error_msg(struct path *pp) STRBUF_ON_STACK(proto_buf); unsigned int proto_id = bus_protocol_id(pp); + if (is_bit_set_in_bitfield(proto_id, bf)) + return; snprint_path_protocol(&proto_buf, pp); condlog(2, "%s: setting scsi timeouts is unsupported for protocol %s", pp->dev, get_strbuf_str(&proto_buf)); From bc6fbc909a8618c1eb794d373cd8cc47ea87597c Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 9 Jan 2026 18:23:52 +0100 Subject: [PATCH 24/34] multipath-tools: compile with -fno-strict-aliasing multipath-tools uses container_of() and similar macros, which imply casts between different types, which isn't stricly compliant with strict aliasing rules. The issue that lead to the previous commit "libmpathutil: use union for bitfield" was one example where this can fail. While that one could be fixed relatively easily, it shows that surprises can happen any time when we compile our code with strict aliasing enabled. This can be seen clearly when we compile with "-fstrict-aliasing -Wstrict-aliasing=1" (note that the bitfield problem is only reported by gcc with "-Wstrict-aliasing=1", other levels of aliasing detection miss it with gcc 15). Use -fno-strict-aliasing to disable it. The kernel does the same. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 1ef540a323ab37993efba517ca150715e3ef42d7) --- Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index 71f352bd3..ddc58c065 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -116,7 +116,7 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) $(D_CMOCKA_VERSION) \ -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ - -fexceptions + -fexceptions -fno-strict-aliasing BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared From 3f2e09ea695ab24061955db9264d32675b599d59 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 16 Jan 2026 11:44:55 +0100 Subject: [PATCH 25/34] multipathd: fix an uninitialized variable warning This isn't necessary in practice, but it fixes a compile warning. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit c032ba1e013283f1171817e8524b92d5f9814113) (cherry picked from commit cd8116755679f105c8c9eeb1e32ebc51fdf9f436) (cherry picked from commit 6c4608c779b4741f836a3b0fe05030d0dbda2aec) --- multipathd/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multipathd/main.c b/multipathd/main.c index ededff115..d11d8e01d 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -3708,7 +3708,7 @@ child (__attribute__((unused)) void *param) int rc; struct config *conf; char *envp; - enum daemon_status state; + enum daemon_status state = DAEMON_INIT; int exit_code = 1; int fpin_marginal_paths = 0; From bc9cee8fd936b180d8d70bc1f617a949f90c3249 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 16 Jan 2026 11:37:41 +0100 Subject: [PATCH 26/34] Makefiles: add "ASAN=1" make parameter for AddressSanitizer It's now possible to enable AddressSanitizer by passing the parameter `ASAN=1` on the "make" command line. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit 5e5d2102f7a409d2cc9165605d0117457bc9fe41) (cherry picked from commit 56a2bba6851d2ccd7bbac023bd4c4a47345d6864) (cherry picked from commit a6be30eade82dc0c451b84e11b40759f469025e0) --- .github/actions/spelling/expect.txt | 4 ++++ Makefile.inc | 7 +++++-- README.md | 3 +++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 51c8a1307..22915348a 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -6,6 +6,7 @@ alloc alltgpt alua aptpl +ASAN ascq ata autoconfig @@ -77,6 +78,7 @@ getrlimit getuid github gitlab +google GPT hbtl hds @@ -192,6 +194,8 @@ rpmbuild rport rtpi rtprio +sanitizer +sanitizers sas sbp scsi diff --git a/Makefile.inc b/Makefile.inc index ddc58c065..729f8f55b 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -9,6 +9,9 @@ # Uncomment to disable dmevents polling support # ENABLE_DMEVENTS_POLL = 0 # +# Use ASAN=1 on make command line to enable address sanitizer +ASAN := +# # Readline library to use, libedit, libreadline, or empty # Caution: Using libreadline may make the multipathd binary undistributable, # see https://github.com/opensvc/multipath-tools/issues/36 @@ -116,11 +119,11 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) $(D_CMOCKA_VERSION) \ -DDEFAULT_CONFIGFILE=\"$(TGTDIR)$(configfile)\" -DSTATE_DIR=\"$(TGTDIR)$(statedir)\" \ -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \ - -fexceptions -fno-strict-aliasing + -fexceptions -fno-strict-aliasing $(if $(ASAN),-fsanitize=address) BIN_CFLAGS := -fPIE -DPIE LIB_CFLAGS := -fPIC SHARED_FLAGS := -shared -LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs +LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs $(if $(ASAN),-lasan) BIN_LDFLAGS := -pie # Source code directories. Don't modify. diff --git a/README.md b/README.md index 530caed7d..8ff139c7a 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,9 @@ See "Passing standard compiler flags" below for an exception. The following variables can be passed to the `make` command line: * `V=1`: enable verbose build. + * `ASAN=1`: Enable + [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer) + during build for debugging memory allocation. This is off by default. * `plugindir="/some/path"`: directory where libmultipath plugins (path checkers, prioritizers, and foreign multipath support) will be looked up. This used to be the run-time option `multipath_dir` in earlier versions. From 5f2052a6b2c3461107091ce3df0eebae4a6549a8 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Fri, 16 Jan 2026 11:39:22 +0100 Subject: [PATCH 27/34] Makefiles: add "OPT=" make parameter Our OPTFLAGS variable contains stack protection options which are intended to be overridable by distribution build scripts. When developers just want to experiment with optimization levels, they often just want to modify the `-O` level. Introduce a variable `OPT` that allows to do just that by passing e.g. `OPT=-O0` to the `make` command line. Signed-off-by: Martin Wilck Reviewed-by: Benjamin Marzinski (cherry picked from commit c94c65cc7357ca609e46438bff84a1a4bd82268e) (cherry picked from commit 47bee74edb37fa10a301d90c900fd4a064b70afa) (cherry picked from commit 7d4522078b3260d30ded3edbb57745aa9734ccf2) --- Makefile.inc | 5 ++++- README.md | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile.inc b/Makefile.inc index 729f8f55b..05564f4ad 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -12,6 +12,9 @@ # Use ASAN=1 on make command line to enable address sanitizer ASAN := # +# Override on make command line if desired +OPT := -O2 + # Readline library to use, libedit, libreadline, or empty # Caution: Using libreadline may make the multipathd binary undistributable, # see https://github.com/opensvc/multipath-tools/issues/36 @@ -102,7 +105,7 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \ echo "modprobe@dm_multipath.service") -OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 +OPTFLAGS := $(OPT) -g $(STACKPROT) --param=ssp-buffer-size=4 # Set WARN_ONLY=1 to avoid compilation erroring out due to warnings. Useful during development. WARN_ONLY := diff --git a/README.md b/README.md index 8ff139c7a..888998b7e 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,12 @@ See "Passing standard compiler flags" below for an exception. The following variables can be passed to the `make` command line: * `V=1`: enable verbose build. + * `OPT=`: set optimization flags. You may want to set `OPT="-O0"` for + debugging, for example. The default is `-O2`. Note that it is also + possible to set `OPTFLAGS`, which takes precedence over `OPT`. `OPTFLAGS` + sets additional options by default, which are intended for distribution + build environments to override. For quick customization of the optimization + level, use `OPT`. * `ASAN=1`: Enable [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer) during build for debugging memory allocation. This is off by default. From 76995418b28a95a4f01f1881000d1dfc3369f8f2 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 19 Jan 2026 11:45:40 +0100 Subject: [PATCH 28/34] multipath-tools tests: suppress a compiler warning for vpd.c The following warning has been observed with gcc 15.2.1 on Fedora Rawhide: vpd.c: In function 'create_vpd83.constprop': vpd.c:265:55: error: '%s' directive output truncated writing 64 bytes into a region of size 40 [-Werror=format-truncation=] 265 | len = snprintf((char *)(desc + 4), maxlen, "%s%s", | ^~ In file included from /usr/include/stdio.h:974, from vpd.c:8: In function 'snprintf', inlined from 'create_scsi_string_desc' at vpd.c:265:8, inlined from 'create_vpd83.constprop' at vpd.c:313:7: /usr/include/bits/stdio2.h:68:10: note: '__builtin___snprintf_chk' output 65 or more bytes into a destination of size 40 68 | return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 | __glibc_objsize (__s), __fmt, | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | __va_arg_pack ()); | ~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Fix it. Signed-off-by: Martin Wilck (cherry picked from commit 888187ed1336cf6e938d625c59593661bb359882) (cherry picked from commit 283b1c2a165432eecfd4fb67142d7a2304cf8626) (cherry picked from commit e76073ea9dd2ddd590e9ba1843e66db16bb5c21f) --- tests/vpd.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/vpd.c b/tests/vpd.c index e3212e614..a72865337 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -262,8 +262,20 @@ static int create_scsi_string_desc(unsigned char *desc, assert_in_range(type, STR_EUI, STR_IQN); assert_true(maxlen % 4 == 0); +#if defined(__GNUC__) && __GNUC__ >= 15 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-truncation=" + /* + * This is called from test_vpd_str_XYZ() functions, where + * we deliberately use the overlong input string test_id. + * So format truncation is expected here. + */ +#endif len = snprintf((char *)(desc + 4), maxlen, "%s%s", str_prefix[type], id); +#if defined(__GNUC__) && __GNUC__ >= 15 +#pragma GCC diagnostic pop +#endif if (len > maxlen) len = maxlen; /* zero-pad */ @@ -451,7 +463,6 @@ static void test_vpd_str_ ## typ ## _ ## len ## _ ## wlen(void **state) \ int n, ret; \ int exp_len; \ int type = typ & STR_MASK; \ - \ n = create_vpd83(vt->vpdbuf, sizeof(vt->vpdbuf), test_id, \ 8, typ, len); \ exp_len = len - strlen(str_prefix[type]); \ From 5459019b96afaed54b2a2bc27917c59aa9902402 Mon Sep 17 00:00:00 2001 From: Xose Vazquez Perez Date: Fri, 9 May 2025 23:45:02 +0200 Subject: [PATCH 29/34] multipath-tools: update Path Selector descriptions on the man page v2: at Martin's suggestion: - change round-robin description - replace "I/Os" with "I/O requests" - fix "dinamyc" typo - remove all path selectors parameters 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 e9e3ee19f5944b86b75ec3293890d7fa5309a999) --- multipath/multipath.conf.5.in | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in index 126875c31..64d1eb56e 100644 --- a/multipath/multipath.conf.5.in +++ b/multipath/multipath.conf.5.in @@ -197,22 +197,23 @@ kernel multipath target: .RS .TP 12 .I "round-robin 0" -Loop through every path in the path group, sending the same amount of I/O to -each. Some aspects of behavior can be controlled with the attributes: -\fIrr_min_io\fR, \fIrr_min_io_rq\fR and \fIrr_weight\fR. +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 +aspects of behavior can be controlled with the attributes: \fIrr_min_io\fR, +\fIrr_min_io_rq\fR and \fIrr_weight\fR. .TP .I "queue-length 0" -(Since 2.6.31 kernel) Choose the path for the next bunch of I/O based on the amount -of outstanding I/O to the path. +(Since 2.6.31 kernel) Choose the path for the next bunch of I/O based on \fBthe lowest +number of outstanding in-flight I/O requests\fR to the path. .TP .I "service-time 0" -(Since 2.6.31 kernel) Choose the path for the next bunch of I/O based on the amount -of outstanding I/O to the path and its relative throughput. +(Since 2.6.31 kernel) Choose the path for the next bunch of I/O based on \fBthe +lowest total size (in bytes) of outstanding in-flight I/O requests\fR to the path. .TP .I "historical-service-time 0" -(Since 5.8 kernel) Choose the path for the next bunch of I/O based on the -estimation of future service time based on the history of previous I/O submitted -to each path. +(Since 5.8 kernel) Choose the path for the next bunch of I/O with \fBa dynamic +algorithm based on the historical service time and the number of outstanding +in-flight I/O requests\fR to the path. .TP The default is: \fBservice-time 0\fR .RE From 077cf9817cebd9ddb2e5d31d815463cb49276935 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Tue, 20 Jan 2026 16:18:24 +0100 Subject: [PATCH 30/34] Spelling: pull in changes from master branch Signed-off-by: Martin Wilck --- .github/actions/spelling/expect.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 22915348a..6abf55c81 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -15,6 +15,7 @@ autoresize backported barbie BINDIR +bitfield blkid bmarzins Bsymbolic @@ -61,12 +62,14 @@ ECKD emc Engenio EVPD +Exos failback failover fds fexceptions FFFFFFFF fge +fno followover forcequeueing fpin @@ -124,6 +127,7 @@ libudevdir liburcu linux LIO +lld lpthread Lun lvm @@ -143,12 +147,13 @@ multipathing multipaths multiqueue mwilck +NFINIDAT NOLOG nompath NOSCAN Nosync nvme -NFINIDAT +Nytro OBJDEPS oneshot ontap @@ -158,8 +163,10 @@ OPTFLAGS paramp partx pathgroup +pathlist petabytes pgpolicy +pgvec plugindir PNR ppc @@ -194,14 +201,12 @@ rpmbuild rport rtpi rtprio -sanitizer sanitizers sas sbp scsi SCST sda -sdc Seagate setmarginal setprkey @@ -223,12 +228,11 @@ suse svg switchgroup sys +SYSDIR sysfs sysinit -systemd tcp terabytes -SYSDIR TESTDEPS testname tgill @@ -263,11 +267,11 @@ VNX vpd VSN wakka -watchdogsec weightedpath wholedisk Wilck wildcards +Wno workflows wrt wwid From c974b2241b8578da99b284a3c022e2e43ff25f90 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Tue, 20 Jan 2026 13:54:39 +0100 Subject: [PATCH 31/34] Update NEWS.md for 0.11.4 Signed-off-by: Martin Wilck --- NEWS.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/NEWS.md b/NEWS.md index 56c24f0a9..bacf85362 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,36 @@ release. These bug fixes will be tracked in stable branches. See [README.md](README.md) for additional information. +## multipath-tools 0.11.4, 2026/01 + +### Bug fixes + +* Fix `mpathpersist --report-capabilities` output. Fixes 0.5.0. +* Fix command descriptions in the multipathd man page. Fixes 0.9.2. +* Fix an undefined symbol error with the LLVM lld linker. + Fixes [#132](https://github.com/opensvc/multipath-tools/issues/132), 0.10.0. +* Fix ISO C23 compatibility issue causing errors with new compilers. +* Fix memory leak caused by not joining the "init unwinder" thread. + Fixes 0.8.6. +* Fix memory leaks in kpartx. Fixes any version. +* Print the warning "setting scsi timeouts is unsupported for protocol" only + once per protocol. Fixes 0.9.0. +* Make sure multipath-tools is compiled with the compiler flag + `-fno-strict-aliasing`. This turns out to be necessary because our code + uses techniques like `container_of()` which don't work well with + strict aliasing rules. + Fixes [#130](https://github.com/opensvc/multipath-tools/issues/130). + +### Other changes + +* Hardware table: add Seagate Exos and Nytro series. +* Avoid joining threads twice with liburcu 0.14.0 and newer. +* CI updates (GitHub workflows). +* Fix CI for cmocka 2.0 by adding the `-Wno-error=deprecated-declarations` + compiler flag. + Fixes [#129](https://github.com/opensvc/multipath-tools/issues/129) +* Add the ASAN=1 and OPT= make variables (see README.md). + ## multipath-tools 0.11.3, 2025/10 ### Other changes From 03f2d5f9b812759dc41573eab22b166245940d25 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Tue, 20 Jan 2026 13:55:29 +0100 Subject: [PATCH 32/34] libmultipath: bump version to 0.11.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 1f1a41642..03d838fc1 100644 --- a/libmultipath/version.h +++ b/libmultipath/version.h @@ -20,9 +20,9 @@ #ifndef VERSION_H_INCLUDED #define VERSION_H_INCLUDED -#define VERSION_CODE 0x000B03 +#define VERSION_CODE 0x000B04 /* MMDDYY, in hex */ -#define DATE_CODE 0x0A1B19 +#define DATE_CODE 0x01141A #define PROG "multipath-tools" From b987f126e608d3d1832475e1392485cb21bf116d Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 21 Jan 2026 16:03:11 -0500 Subject: [PATCH 33/34] multipathd: finish initalization of paths added while offline If a path in a mulitpath device is offline while multipathd is reconfigured, it will get added to the updated multipath device, just like it was in the old multipath device. However the device will still be in the INIT_NEW state because it can't get initilized while offline. This is different than the INIT_PARTIAL state because the path was discovered in path_discovery(). INIT_PARTIAL is for paths that multipathd did not discover in path_discovery() or receive a uevent for, but are part of a multipath device that was added, and which should receive a uevent shortly. There is no reason to expect a uevent for these offline paths. When the path comes back online, multipathd will run the checker and prioritizer on it. The only pathinfo check that won't happen is DI_WWID. Make sure that when one of these offline paths becomes usable, its WWID is rechecked. With those changes, all the DI_ALL checks will be accounted for, and the path can be marked INIT_OK. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit 1942fb136a388c9bdd964741116ed0a89cf9e198) [mwilck: retrying DI_IOCTL is not implemented in 0.11.y, removed that part from the patch]. --- multipathd/main.c | 53 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/multipathd/main.c b/multipathd/main.c index d11d8e01d..96838477c 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -2488,6 +2488,26 @@ sync_mpp(struct vectors * vecs, struct multipath *mpp, unsigned int ticks) do_sync_mpp(vecs, mpp); } +/* + * pp->wwid should never be empty when this function is called, but if it + * is, this function can set it. + */ +static bool new_path_wwid_changed(struct path *pp, int state) +{ + char wwid[WWID_SIZE]; + + strlcpy(wwid, pp->wwid, WWID_SIZE); + if (get_uid(pp, state, pp->udev, 1) != 0) { + strlcpy(pp->wwid, wwid, WWID_SIZE); + return false; + } + if (strlen(wwid) && strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { + strlcpy(pp->wwid, wwid, WWID_SIZE); + return true; + } + return false; +} + static int update_path_state (struct vectors * vecs, struct path * pp) { @@ -2516,14 +2536,33 @@ update_path_state (struct vectors * vecs, struct path * pp) pp->tick = 1; return CHECK_PATH_SKIPPED; } - if (pp->recheck_wwid == RECHECK_WWID_ON && - (newstate == PATH_UP || newstate == PATH_GHOST) && + + if ((newstate == PATH_UP || newstate == PATH_GHOST) && ((pp->state != PATH_UP && pp->state != PATH_GHOST) || - pp->dmstate == PSTATE_FAILED) && - check_path_wwid_change(pp)) { - condlog(0, "%s: path wwid change detected. Removing", pp->dev); - return handle_path_wwid_change(pp, vecs)? CHECK_PATH_REMOVED : - CHECK_PATH_SKIPPED; + pp->dmstate == PSTATE_FAILED)) { + bool wwid_changed = false; + + if (pp->initialized == INIT_NEW) { + /* + * Path was added to map while offline, mark it as + * initialized. + * DI_SYSFS was checked when the path was added + * DI_CHECKER just got checked + * DI_WWID is about to be checked + * DI_PRIO will get checked at the end of this checker + * loop + */ + pp->initialized = INIT_OK; + wwid_changed = new_path_wwid_changed(pp, newstate); + } else if (pp->recheck_wwid == RECHECK_WWID_ON) + wwid_changed = check_path_wwid_change(pp); + if (wwid_changed) { + condlog(0, "%s: path wwid change detected. Removing", + pp->dev); + return handle_path_wwid_change(pp, vecs) + ? CHECK_PATH_REMOVED + : CHECK_PATH_SKIPPED; + } } if (pp->mpp->synced_count == 0) { do_sync_mpp(vecs, pp->mpp); From 1bab2045813b52d9b797cec2b4a62272b28c39dd Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Wed, 21 Jan 2026 16:03:13 -0500 Subject: [PATCH 34/34] multipathd: print path offline message even without a checker If a path has a checker selected and is offline, multipathd will print a "path offline" message. However if the checker isn't selected, for instance because multipathd was started or reconfigured while the path was offline, multipathd was not printing the "path offline" message. Fix that. Signed-off-by: Benjamin Marzinski Reviewed-by: Martin Wilck (cherry picked from commit 1a364a1699baec8cb886c0e82a5e4699142ac153) --- multipathd/main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/multipathd/main.c b/multipathd/main.c index 96838477c..c8f004c95 100644 --- a/multipathd/main.c +++ b/multipathd/main.c @@ -94,12 +94,11 @@ void * mpath_pr_event_handler_fn (void * ); #define LOG_MSG(lvl, pp) \ do { \ - if (pp->mpp && checker_selected(&pp->checker) && \ - lvl <= libmp_verbosity) { \ - if (pp->sysfs_state == PATH_DOWN) \ + if (pp->mpp && lvl <= libmp_verbosity) { \ + if (pp->sysfs_state != PATH_UP) \ condlog(lvl, "%s: %s - path offline", \ pp->mpp->alias, pp->dev); \ - else { \ + else if (checker_selected(&pp->checker)) { \ const char *__m = \ checker_message(&pp->checker); \ \