diff --git a/.clang-format b/.clang-format index 5c762eba5..927b8e0dd 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 @@ -29,4 +30,6 @@ ForEachMacros: - vector_foreach_slot - vector_foreach_slot_backwards - vector_foreach_slot_after +Cpp11BracedListStyle: false +ReflowComments: Never --- 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/abi-stable.yaml b/.github/workflows/abi-stable.yaml index d0ee4543f..7d197f49d 100644 --- a/.github/workflows/abi-stable.yaml +++ b/.github/workflows/abi-stable.yaml @@ -21,19 +21,19 @@ jobs: 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' }} + 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' }} + if: github.event_name == 'pull_request' - name: assert parent tag run: /bin/false - if: ${{ env.PARENT_TAG == '' }} + 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 + uses: dawidd6/action-download-artifact@v21 with: workflow: abi-stable.yaml workflow_conclusion: '' @@ -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 }} @@ -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 @@ -75,22 +75,22 @@ jobs: 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' }} + 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' }} + if: github.event_name == 'pull_request' - name: assert parent tag run: /bin/false - if: ${{ env.PARENT_TAG == '' }} + 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 }} id: download_abi - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v21 with: workflow: abi-stable.yaml workflow_conclusion: '' @@ -112,8 +112,8 @@ jobs: 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 + if: steps.check_abi.outcome != 'success' + 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 3b5f1c1e4..82af1e498 100644 --- a/.github/workflows/abi.yaml +++ b/.github/workflows/abi.yaml @@ -22,14 +22,14 @@ jobs: runs-on: ubuntu-24.04 steps: - name: set ABI branch - if: ${{ env.ABI_BRANCH == '' }} + 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 - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v21 with: workflow: abi.yaml branch: ${{ env.ABI_BRANCH }} @@ -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 @@ -55,11 +55,11 @@ jobs: - name: compare ABI against reference id: compare continue-on-error: true - if: ${{ steps.reference.outcome == 'success' }} + if: steps.reference.outcome == 'success' run: make abi-test - name: save differences - if: ${{ steps.compare.outcome == 'failure' }} - uses: actions/upload-artifact@v4 + if: steps.compare.outcome == 'failure' + uses: actions/upload-artifact@v7 with: name: abi-test path: abi-test diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml index fdcc59b73..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 @@ -43,7 +43,7 @@ jobs: - 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' }} + if: matrix.cc == 'clang' - name: build run: > make -Orecurse -j$(nproc) @@ -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/codingstyle.yml b/.github/workflows/codingstyle.yml index 067f32666..75d9a8a2f 100644 --- a/.github/workflows/codingstyle.yml +++ b/.github/workflows/codingstyle.yml @@ -30,13 +30,13 @@ 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' }} + if: github.event_name == 'pull_request' - run: >- echo "BASEREF=${{ github.event.before }}" >>$GITHUB_ENV - if: ${{ github.event_name == 'push' }} + if: github.event_name == 'push' - run: git fetch --depth=1 origin ${{ env.BASEREF }} - uses: yshui/git-clang-format-lint@master with: 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 b232b60c1..5e6cf0bfd 100644 --- a/.github/workflows/foreign.yaml +++ b/.github/workflows/foreign.yaml @@ -41,11 +41,11 @@ 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 - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: cross-${{ matrix.os }}-${{ matrix.arch }} path: test-progs.tar @@ -67,31 +67,51 @@ jobs: steps: - name: set container arch run: echo CONTAINER_ARCH="${{ matrix.arch }}" >> $GITHUB_ENV - if: ${{ matrix.arch != 'armhf' }} + if: matrix.arch != 'armhf' - name: set container arch run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV - if: ${{ matrix.arch == 'armhf' }} + 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 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 + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern - name: run tests - uses: mosteo-actions/docker-run@v1 + 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@v7 with: - image: ghcr.io/mwilck/multipath-run-debian-${{ matrix.os }} - guest-dir: /__w/multipath-tools/multipath-tools - host-dir: ${{ github.workspace }} - command: -C tests - params: > - --workdir /__w/multipath-tools/multipath-tools - --platform linux/${{ env.CONTAINER_ARCH }} - pull-params: "--platform linux/${{ env.CONTAINER_ARCH }}" + 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 @@ -113,37 +133,51 @@ jobs: 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' }} + if: matrix.arch != 'armhf' - name: set container arch run: echo CONTAINER_ARCH="arm/v7" >> $GITHUB_ENV - if: ${{ matrix.arch == 'armhf' }} + 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 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 + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern - name: run tests - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-run-debian-${{ matrix.os }} - guest-dir: /__w/multipath-tools/multipath-tools - host-dir: ${{ github.workspace }} - command: -C tests dmevents.out - params: > - --workdir /__w/multipath-tools/multipath-tools - --platform linux/${{ env.CONTAINER_ARCH }} - --privileged - -v /dev/ram0:/dev/ram0 -e DIO_TEST_DEV=/dev/ram0 - pull-params: "--platform linux/${{ env.CONTAINER_ARCH }}" 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: show root test output - run: for o in tests/*.out; do echo "===== $o ====="; cat "$o"; done - - name: fail + - 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@v7 + 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 == 'failure' }} + if: steps.root-test.outcome != 'success' diff --git a/.github/workflows/multiarch-stable.yaml b/.github/workflows/multiarch-stable.yaml index b8c770e40..e69e371c8 100644 --- a/.github/workflows/multiarch-stable.yaml +++ b/.github/workflows/multiarch-stable.yaml @@ -47,38 +47,52 @@ jobs: arch: ppc64le steps: - name: checkout - uses: actions/checkout@v4 + 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 + 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 - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - guest-dir: /build - host-dir: ${{ github.workspace }} - command: test - params: "--platform linux/${{ matrix.arch }}" - pull-params: "--platform linux/${{ matrix.arch }}" + 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 - 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 }}" + 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 + uses: actions/upload-artifact@v7 with: - name: binaries-${{ matrix.os }}-${{ matrix.arch }} + 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@v7 + with: + name: test-${{ matrix.os }}-${{ env.ARCH_NAME }} + path: test-outputs.tar + overwrite: true if: steps.test.outcome != 'success' - - name: fail + - 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 index 806275a13..f0fb4b6a4 100644 --- a/.github/workflows/multiarch.yaml +++ b/.github/workflows/multiarch.yaml @@ -6,6 +6,7 @@ on: - queue - tip - 'stable-*' + - musl paths: - '.github/workflows/multiarch.yaml' - '**.h' @@ -30,7 +31,6 @@ on: jobs: build-current: - runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -40,48 +40,74 @@ jobs: - 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 - arch: 386 + variant: + arch: 386 + runner: ubuntu-24.04 - os: fedora-rawhide - arch: arm/v7 + variant: + arch: arm/v7 + runner: ubuntu-24.04-arm include: - os: alpine - arch: aarch64 + variant: + arch: aarch64 + runner: ubuntu-24.04-arm + 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 + uses: docker/setup-qemu-action@v4 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 - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - guest-dir: /build - host-dir: ${{ github.workspace }} - command: test - params: "--platform linux/${{ matrix.arch }}" - pull-params: "--platform linux/${{ matrix.arch }}" + 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: 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 }}" + - 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 + uses: actions/upload-artifact@v7 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 + - name: upload test outputs + uses: actions/upload-artifact@v7 + 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 index 9e89780b1..e9a16664a 100644 --- a/.github/workflows/native.yaml +++ b/.github/workflows/native.yaml @@ -46,62 +46,58 @@ jobs: runs-on: ${{ matrix.variant.runner }} steps: - name: checkout - uses: actions/checkout@v4 + uses: actions/checkout@v7 - - 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') }} + # 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 - if: ${{ matrix.os != 'debian-jessie' }} - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - command: -j$(nproc) -Orecurse 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: 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$(nproc) -Orecurse READLINE=libreadline 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: create ${{ env.ARCHIVE_TGT }} - if: ${{ matrix.os != 'debian-jessie' }} - uses: mosteo-actions/docker-run@v1 + - name: upload test-progs.tar + uses: actions/upload-artifact@v7 with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - command: ${{ env.ARCHIVE_TGT }} - - 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 }} + 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: upload binary archive - uses: actions/upload-artifact@v4 + - name: create test-outputs.tar + run: make test-outputs.tar + if: steps.test.outcome != 'success' + + - name: upload test-outputs.tar + uses: actions/upload-artifact@v7 with: - name: native-${{ matrix.os }}-${{ matrix.variant.arch }} - path: ${{ env.ARCHIVE_TGT }} + name: gcc-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} + path: test-outputs.tar overwrite: true + if: steps.test.outcome != 'success' - - name: fail + - name: fail if test failed run: /bin/false - if: >- - ${{ ( matrix.os == 'debian-jessie' && - steps.test_jessie.outcome != 'success' ) || - ( matrix.os != 'debian-jessie' && - steps.test.outcome != 'success' ) }} + if: steps.test.outcome != 'success' + clang: strategy: fail-fast: false @@ -127,75 +123,46 @@ 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) + run: echo READLINE=libreadline >> $GITHUB_ENV + if: matrix.os == 'debian-jessie' - - 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: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern - - name: clang + - name: build and test with 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$(nproc) -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$(nproc) -Orecurse READLINE=libreadline 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: create ${{ env.ARCHIVE_TGT }} - 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) - 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: Make core dumps accessible + run: | + find . \( -name 'core*' \) -print0 | xargs -0 -r sudo chmod a+r + if: steps.test.outcome != 'success' - - name: upload binary archive - uses: actions/upload-artifact@v4 + - name: create test-outputs.tar + run: make test-outputs.tar + if: steps.test.outcome != 'success' + + - name: upload test-outputs.tar + uses: actions/upload-artifact@v7 with: - name: clang-${{ matrix.os }}-${{ matrix.variant.arch }} - path: ${{ env.ARCHIVE_TGT }} + name: clang-outputs-${{ matrix.os }}-${{ matrix.variant.arch }} + path: test-outputs.tar overwrite: true - if: >- - ${{ ( matrix.os == 'debian-jessie' && - steps.test_jessie.outcome != 'success' ) || - ( matrix.os != 'debian-jessie' && - steps.test.outcome != 'success' ) }} + if: steps.test.outcome != 'success' - - name: fail + - name: fail if test failed run: /bin/false - if: >- - ${{ ( matrix.os == 'debian-jessie' && - steps.test_jessie.outcome != 'success' ) || - ( matrix.os != 'debian-jessie' && - steps.test.outcome != 'success' ) }} + if: steps.test.outcome != 'success' root-test: needs: stable @@ -224,33 +191,49 @@ 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 + uses: actions/download-artifact@v8 with: name: native-${{ matrix.os }}-${{ matrix.variant.arch }} - - name: unpack binary archive - run: cpio -idv < test-progs.cpio - if: ${{ startswith(matrix.os, 'opensuse-leap-15') }} + - name: unpack binary archive run: tar xfmv test-progs.tar - if: ${{ !startswith(matrix.os, 'opensuse-leap-15') }} + + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern - name: run root tests - uses: mosteo-actions/docker-run@v1 - with: - image: ghcr.io/mwilck/multipath-build-${{ matrix.os }} - guest-dir: /__w/multipath-tools/multipath-tools - host-dir: ${{ github.workspace }} - params: > - --workdir /__w/multipath-tools/multipath-tools --privileged - -v /dev/ram0:/dev/ram0 -e DIO_TEST_DEV=/dev/ram0 - command: -C tests directio.out dmevents.out - id: root-test + 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: show root test output - run: for o in tests/*.out; do echo "===== $o ====="; cat "$o"; done - - name: fail + + - 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@v7 + 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.root-test.outcome == 'failure' }} + if: steps.test.outcome != 'success' diff --git a/.github/workflows/rolling.yaml b/.github/workflows/rolling.yaml index a4706e52e..43f5c4c72 100644 --- a/.github/workflows/rolling.yaml +++ b/.github/workflows/rolling.yaml @@ -56,23 +56,41 @@ jobs: 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 + uses: actions/checkout@v7 + - name: Set coredump pattern + run: | + echo 'core.%e.%p' | sudo tee /proc/sys/kernel/core_pattern - name: build and test id: test - run: make CC=${{ matrix.compiler }} READLINE=libreadline -j$(nproc) -Orecurse 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 + uses: actions/upload-artifact@v7 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@v7 + 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' 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 }}" diff --git a/Makefile b/Makefile index f06f7faa9..b1dac5b70 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) @@ -126,15 +127,21 @@ 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 - @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) $(wildcard tests/core*) + $(Q)printf "%s\\n" $^ | cpio -o -H crc >$@ + +test-outputs.tar: $(wildcard tests/*.out) $(wildcard tests/*.vgr) $(wildcard tests/core*) + $(Q)tar cf "$@" $^ || touch $@ .PHONY: TAGS TAGS: diff --git a/NEWS.md b/NEWS.md index 1fd4766ab..c45301ed6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,45 @@ 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`. +* 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 + +* 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. 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]: " diff --git a/kpartx/dasd.c b/kpartx/dasd.c index 337d5f45c..9062e9041 100644 --- a/kpartx/dasd.c +++ b/kpartx/dasd.c @@ -53,14 +53,13 @@ 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; 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,}; @@ -193,6 +192,8 @@ 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]; @@ -201,8 +202,11 @@ 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))) { @@ -217,7 +221,7 @@ 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)); @@ -243,6 +247,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; @@ -273,8 +279,11 @@ 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; } diff --git a/kpartx/gpt.c b/kpartx/gpt.c index 69ddce99a..1068da2e3 100644 --- a/kpartx/gpt.c +++ b/kpartx/gpt.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "crc32.h" #include "kpartx.h" @@ -52,6 +53,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 +77,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); } @@ -222,24 +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; - size_t count = __le32_to_cpu(gpt->num_partition_entries) * - __le32_to_cpu(gpt->sizeof_partition_entry); + gpt_entry *pte = NULL; + size_t num_entries = __le32_to_cpu(gpt->num_partition_entries); + 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 (!count) return NULL; + 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 (aligned_malloc((void **)&pte, get_sector_size(fd), &count)) + if (pe_map == MAP_FAILED) { + fprintf(stderr, "%s: mmap failed: %s\n", __func__, strerror(errno)); return NULL; - memset(pte, 0, count); + } - if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte, - count)) { - free(pte); - 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; } @@ -278,9 +308,8 @@ 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; @@ -334,28 +363,16 @@ is_gpt_valid(int fd, uint64_t lba, return 0; } - if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) { - free(*gpt); - *gpt = NULL; - return 0; - } - - /* 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"); + if (!(*ptes = alloc_read_gpt_entries(fd, *gpt, ns))) { free(*gpt); *gpt = NULL; - free(*ptes); - *ptes = NULL; return 0; } /* We're done, all's well */ return 1; } + /** * compare_gpts() - Search disk for valid GPT headers and PTEs * @pgpt is the primary GPT header @@ -477,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; @@ -491,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 */ @@ -597,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) 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 4ac43fa37..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. .\" ---------------------------------------------------------------------------- . @@ -35,7 +31,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 +53,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..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. .\" ---------------------------------------------------------------------------- . @@ -35,7 +31,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 +70,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/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/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/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) { diff --git a/libmultipath/prioritizers/datacore.c b/libmultipath/prioritizers/datacore.c index ab813a0ea..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=%s", - (int *)&timeout_ms, preferredsds) == 2) {} - else if (sscanf(args, "preferredsds=%s timeout=%i", - preferredsds, (int *)&timeout_ms) == 2) {} - else if (sscanf(args, "preferredsds=%s", - 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 f5fdd42aa..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=%s", 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); } diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c index 56895c4bb..c1045daa9 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); @@ -640,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/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" diff --git a/mpathpersist/mpathpersist.8.in b/mpathpersist/mpathpersist.8.in index fecef0d63..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. .\" ---------------------------------------------------------------------------- . @@ -50,7 +46,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..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. .\" ---------------------------------------------------------------------------- . @@ -100,7 +96,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 +191,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 84cd1a0ab..e2519d4a1 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. .\" ---------------------------------------------------------------------------- . @@ -31,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, @@ -103,7 +99,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 +138,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 +191,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 +220,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 +330,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 +405,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 +427,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 +442,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 +453,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 +478,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 +517,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 +571,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 +646,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 @@ -732,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 @@ -871,11 +869,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,13 +1190,13 @@ 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 -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. @@ -1460,7 +1458,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 +1548,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, @@ -1558,18 +1556,18 @@ 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 . . 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 18 +.TP .B path_grouping_policy .TP .B path_selector @@ -1632,7 +1630,7 @@ section: .SH "devices section" .\" ---------------------------------------------------------------------------- . -.TP 4 +.TP .B Important: The built-in hardware device table of .I multipath-tools @@ -1649,9 +1647,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 @@ -1668,7 +1666,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 +1709,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 @@ -1749,10 +1747,10 @@ 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 18 +.TP .B path_grouping_policy .TP .B uid_attribute @@ -1833,10 +1831,10 @@ 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 18 +.TP .B path_grouping_policy .TP .B uid_attribute @@ -1935,7 +1933,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 @@ -1956,7 +1954,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 +1994,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 @@ -2026,7 +2024,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. @@ -2091,6 +2089,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" .\" ---------------------------------------------------------------------------- . 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; /* 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 38a243e3e..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. .\" ---------------------------------------------------------------------------- . @@ -416,7 +412,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 +517,7 @@ the configured one). .TP .B Path format wildcards .RS -.TP 12 +.TP .B %w The device WWID (uuid). .TP @@ -548,7 +544,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 +689,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). . diff --git a/tests/vpd.c b/tests/vpd.c index f9e22cd87..0f408db4c 100644 --- a/tests/vpd.c +++ b/tests/vpd.c @@ -331,6 +331,27 @@ 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 +500,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) @@ -779,40 +824,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); static int test_vpd(void) { @@ -945,6 +997,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); }