diff --git a/0103-libmultipath-fix-NULL-dereference-in-find_path_by_de.patch b/0103-libmultipath-fix-NULL-dereference-in-find_path_by_de.patch new file mode 100644 index 0000000..4dd4051 --- /dev/null +++ b/0103-libmultipath-fix-NULL-dereference-in-find_path_by_de.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: lixiaokeng +Date: Sat, 23 Jan 2021 16:19:28 +0800 +Subject: [PATCH] libmultipath: fix NULL dereference in find_path_by_dev + +When I test the 0.8.5 code with iscsi login/out, multipathd command +and multipath command concurrently, there is a multipathd coredump. +The stack is shown: + +uxlsnrloop + ->cli_list_devices + ->show_devices + ->snprint_devices + ->find_path_by_dev + +The reason is that devname is NULL in snprint_devices, then it will +be dereference. Here we check dev in find_path_by_dev. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index 464596fc..a3f27fd6 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -453,12 +453,12 @@ find_mp_by_str (const struct _vector *mpvec, const char * str) + } + + struct path * +-find_path_by_dev (const struct _vector *pathvec, const char * dev) ++find_path_by_dev (const struct _vector *pathvec, const char *dev) + { + int i; + struct path * pp; + +- if (!pathvec) ++ if (!pathvec || !dev) + return NULL; + + vector_foreach_slot (pathvec, pp, i) +-- +2.17.2 + diff --git a/0104-libmultipath-snprint_devices-avoid-NULL-dereference.patch b/0104-libmultipath-snprint_devices-avoid-NULL-dereference.patch new file mode 100644 index 0000000..04ff739 --- /dev/null +++ b/0104-libmultipath-snprint_devices-avoid-NULL-dereference.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 25 Jan 2021 16:12:10 +0100 +Subject: [PATCH] libmultipath: snprint_devices(): avoid NULL dereference + +All libudev functions may return NULL. Watch out for it. + +Fixes: d041258 ("libmultipath: snprint_devices(): use udev_enumerate" +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/print.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/libmultipath/print.c b/libmultipath/print.c +index 19de2c7c..8151e11e 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -2055,8 +2055,16 @@ int snprint_devices(struct config *conf, char *buff, size_t len, + struct udev_device *u_dev; + + path = udev_list_entry_get_name(item); ++ if (!path) ++ continue; + u_dev = udev_device_new_from_syspath(udev, path); ++ if (!u_dev) ++ continue; + devname = udev_device_get_sysname(u_dev); ++ if (!devname) { ++ udev_device_unref(u_dev); ++ continue; ++ } + + fwd += snprintf(buff + fwd, len - fwd, " %s", devname); + if (fwd >= len) +-- +2.17.2 + diff --git a/0105-libmpathpersist-fix-thread-safety-of-default-functio.patch b/0105-libmpathpersist-fix-thread-safety-of-default-functio.patch new file mode 100644 index 0000000..dad9963 --- /dev/null +++ b/0105-libmpathpersist-fix-thread-safety-of-default-functio.patch @@ -0,0 +1,274 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 25 Jan 2021 23:31:04 -0600 +Subject: [PATCH] libmpathpersist: fix thread safety of default functions + +commit a839e39e ("libmpathpersist: factor out initialization and +teardown") made mpath_presistent_reserve_{in,out} use share variables +for curmp and pathvec. There are users of this library that call these +functions in a multi-threaded process, and this change causes their +application to crash. config and udev are also shared variables, but +libmpathpersist doesn't write to the config in +mpath_presistent_reserve_{in,out}, and looking into the libudev code, I +don't see any place where libmpathpersist uses the udev object in a way +that isn't thread-safe. + +This patch makes mpath_presistent_reserve_{in,out} go back to using +local variables for curmp and pathvec, so that multiple threads won't +be operating on these variables at the same time. + +Fixes: a839e39e ("libmpathpersist: factor out initialization and teardown") +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + libmpathpersist/mpath_persist.c | 116 +++++++++++++++++++++----------- + libmpathpersist/mpath_persist.h | 24 +++++-- + 2 files changed, 94 insertions(+), 46 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 08077936..5c95af20 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -133,69 +133,57 @@ mpath_prin_activepath (struct multipath *mpp, int rq_servact, + return ret; + } + +-int mpath_persistent_reserve_in (int fd, int rq_servact, +- struct prin_resp *resp, int noisy, int verbose) +-{ +- int ret = mpath_persistent_reserve_init_vecs(verbose); +- +- if (ret != MPATH_PR_SUCCESS) +- return ret; +- ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy); +- mpath_persistent_reserve_free_vecs(); +- return ret; +-} +- +-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, +- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose) +-{ +- int ret = mpath_persistent_reserve_init_vecs(verbose); +- +- if (ret != MPATH_PR_SUCCESS) +- return ret; +- ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type, +- paramp, noisy); +- mpath_persistent_reserve_free_vecs(); +- return ret; +-} +- + static vector curmp; + static vector pathvec; + +-void mpath_persistent_reserve_free_vecs(void) ++static void __mpath_persistent_reserve_free_vecs(vector curmp, vector pathvec) + { + free_multipathvec(curmp, KEEP_PATHS); + free_pathvec(pathvec, FREE_PATHS); ++} ++ ++void mpath_persistent_reserve_free_vecs(void) ++{ ++ __mpath_persistent_reserve_free_vecs(curmp, pathvec); + curmp = pathvec = NULL; + } + +-int mpath_persistent_reserve_init_vecs(int verbose) ++static int __mpath_persistent_reserve_init_vecs(vector *curmp_p, ++ vector *pathvec_p, int verbose) + { + libmp_verbosity = verbose; + +- if (curmp) ++ if (*curmp_p) + return MPATH_PR_SUCCESS; + /* + * allocate core vectors to store paths and multipaths + */ +- curmp = vector_alloc (); +- pathvec = vector_alloc (); ++ *curmp_p = vector_alloc (); ++ *pathvec_p = vector_alloc (); + +- if (!curmp || !pathvec){ ++ if (!*curmp_p || !*pathvec_p){ + condlog (0, "vector allocation failed."); + goto err; + } + +- if (dm_get_maps(curmp)) ++ if (dm_get_maps(*curmp_p)) + goto err; + + return MPATH_PR_SUCCESS; + + err: +- mpath_persistent_reserve_free_vecs(); ++ __mpath_persistent_reserve_free_vecs(*curmp_p, *pathvec_p); ++ *curmp_p = *pathvec_p = NULL; + return MPATH_PR_DMMP_ERROR; + } + +-static int mpath_get_map(int fd, char **palias, struct multipath **pmpp) ++int mpath_persistent_reserve_init_vecs(int verbose) ++{ ++ return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose); ++} ++ ++static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias, ++ struct multipath **pmpp) + { + int ret = MPATH_PR_DMMP_ERROR; + struct stat info; +@@ -255,13 +243,13 @@ out: + return ret; + } + +-int __mpath_persistent_reserve_in (int fd, int rq_servact, +- struct prin_resp *resp, int noisy) ++static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec, ++ int fd, int rq_servact, struct prin_resp *resp, int noisy) + { + struct multipath *mpp; + int ret; + +- ret = mpath_get_map(fd, NULL, &mpp); ++ ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp); + if (ret != MPATH_PR_SUCCESS) + return ret; + +@@ -270,8 +258,17 @@ int __mpath_persistent_reserve_in (int fd, int rq_servact, + return ret; + } + +-int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, +- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy) ++ ++int __mpath_persistent_reserve_in (int fd, int rq_servact, ++ struct prin_resp *resp, int noisy) ++{ ++ return do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact, ++ resp, noisy); ++} ++ ++static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd, ++ int rq_servact, int rq_scope, unsigned int rq_type, ++ struct prout_param_descriptor *paramp, int noisy) + { + struct multipath *mpp; + char *alias; +@@ -279,7 +276,7 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + uint64_t prkey; + struct config *conf; + +- ret = mpath_get_map(fd, &alias, &mpp); ++ ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp); + if (ret != MPATH_PR_SUCCESS) + return ret; + +@@ -349,6 +346,45 @@ out1: + return ret; + } + ++ ++int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, ++ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy) ++{ ++ return do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact, ++ rq_scope, rq_type, paramp, ++ noisy); ++} ++ ++int mpath_persistent_reserve_in (int fd, int rq_servact, ++ struct prin_resp *resp, int noisy, int verbose) ++{ ++ vector curmp = NULL, pathvec; ++ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, ++ verbose); ++ ++ if (ret != MPATH_PR_SUCCESS) ++ return ret; ++ ret = do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact, ++ resp, noisy); ++ __mpath_persistent_reserve_free_vecs(curmp, pathvec); ++ return ret; ++} ++ ++int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, ++ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose) ++{ ++ vector curmp = NULL, pathvec; ++ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, ++ verbose); ++ ++ if (ret != MPATH_PR_SUCCESS) ++ return ret; ++ ret = do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact, ++ rq_scope, rq_type, paramp, noisy); ++ __mpath_persistent_reserve_free_vecs(curmp, pathvec); ++ return ret; ++} ++ + int + get_mpvec (vector curmp, vector pathvec, char * refwwid) + { +diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h +index 5435eae4..9e9c0a82 100644 +--- a/libmpathpersist/mpath_persist.h ++++ b/libmpathpersist/mpath_persist.h +@@ -246,9 +246,13 @@ extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp + + /* + * DESCRIPTION : +- * This function is like mpath_persistent_reserve_in(), except that it doesn't call +- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs() +- * before and after the actual PR call. ++ * This function is like mpath_persistent_reserve_in(), except that it ++ * requires mpath_persistent_reserve_init_vecs() to be called before the ++ * PR call to set up internal variables. These must later be cleanup up ++ * by calling mpath_persistent_reserve_free_vecs(). ++ * ++ * RESTRICTIONS: ++ * This function uses static internal variables, and is not thread-safe. + */ + extern int __mpath_persistent_reserve_in(int fd, int rq_servact, + struct prin_resp *resp, int noisy); +@@ -280,9 +284,13 @@ extern int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + int verbose); + /* + * DESCRIPTION : +- * This function is like mpath_persistent_reserve_out(), except that it doesn't call +- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs() +- * before and after the actual PR call. ++ * This function is like mpath_persistent_reserve_out(), except that it ++ * requires mpath_persistent_reserve_init_vecs() to be called before the ++ * PR call to set up internal variables. These must later be cleanup up ++ * by calling mpath_persistent_reserve_free_vecs(). ++ * ++ * RESTRICTIONS: ++ * This function uses static internal variables, and is not thread-safe. + */ + extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope, + unsigned int rq_type, struct prout_param_descriptor *paramp, +@@ -296,6 +304,7 @@ extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope, + * @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose + * + * RESTRICTIONS: ++ * This function uses static internal variables, and is not thread-safe. + * + * RETURNS: MPATH_PR_SUCCESS if successful else returns any of the status specified + * above in RETURN_STATUS. +@@ -306,6 +315,9 @@ int mpath_persistent_reserve_init_vecs(int verbose); + * DESCRIPTION : + * This function frees data structures allocated by + * mpath_persistent_reserve_init_vecs(). ++ * ++ * RESTRICTIONS: ++ * This function uses static internal variables, and is not thread-safe. + */ + void mpath_persistent_reserve_free_vecs(void); + +-- +2.17.2 + diff --git a/0106-Added-github-action-for-building.patch b/0106-Added-github-action-for-building.patch new file mode 100644 index 0000000..8a8a7d0 --- /dev/null +++ b/0106-Added-github-action-for-building.patch @@ -0,0 +1,37 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 18 Dec 2020 21:38:43 +0100 +Subject: [PATCH] Added github action for building + +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + create mode 100644 .github/workflows/build-and-unittest.yaml + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +new file mode 100644 +index 00000000..2b13c65c +--- /dev/null ++++ b/.github/workflows/build-and-unittest.yaml +@@ -0,0 +1,17 @@ ++name: basic-build-and-ci ++on: [push] ++jobs: ++ build: ++ runs-on: ubuntu-latest ++ steps: ++ - uses: actions/checkout@v2 ++ - name: dependencies ++ run: > ++ sudo apt-get install --yes gcc ++ make perl-base pkg-config ++ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev ++ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev ++ - name: build ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) ++ - name: test ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) test +-- +2.17.2 + diff --git a/0107-github-workflow-use-zram-device-as-test-block-device.patch b/0107-github-workflow-use-zram-device-as-test-block-device.patch new file mode 100644 index 0000000..5b25c29 --- /dev/null +++ b/0107-github-workflow-use-zram-device-as-test-block-device.patch @@ -0,0 +1,40 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 18 Dec 2020 22:18:20 +0100 +Subject: [PATCH] github workflow: use zram device as test block device + +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +index 2b13c65c..ef55b8c1 100644 +--- a/.github/workflows/build-and-unittest.yaml ++++ b/.github/workflows/build-and-unittest.yaml +@@ -5,6 +5,14 @@ jobs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 ++ - name: mpath ++ run: sudo modprobe dm_multipath ++ - name: zram ++ run: sudo modprobe zram num_devices=0 ++ - name: zram-device ++ run: echo ZRAM=$(sudo cat /sys/class/zram-control/hot_add) >> $GITHUB_ENV ++ - name: set-zram-size ++ run: echo 1G | sudo tee /sys/block/zram$ZRAM/disksize + - name: dependencies + run: > + sudo apt-get install --yes gcc +@@ -15,3 +23,7 @@ jobs: + run: make -O -j$(grep -c ^processor /proc/cpuinfo) + - name: test + run: make -O -j$(grep -c ^processor /proc/cpuinfo) test ++ - name: clean-nonroot-artifacts ++ run: rm -f tests/dmevents.out tests/directio.out ++ - name: root-test ++ run: sudo make DIO_TEST_DEV=/dev/zram$ZRAM test +-- +2.17.2 + diff --git a/0108-github-workflow-use-explicit-Ubuntu-version.patch b/0108-github-workflow-use-explicit-Ubuntu-version.patch new file mode 100644 index 0000000..ff565d6 --- /dev/null +++ b/0108-github-workflow-use-explicit-Ubuntu-version.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 18 Dec 2020 22:54:24 +0100 +Subject: [PATCH] github workflow: use explicit Ubuntu version + +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +index ef55b8c1..577a14ac 100644 +--- a/.github/workflows/build-and-unittest.yaml ++++ b/.github/workflows/build-and-unittest.yaml +@@ -2,7 +2,7 @@ name: basic-build-and-ci + on: [push] + jobs: + build: +- runs-on: ubuntu-latest ++ runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - name: mpath +-- +2.17.2 + diff --git a/0109-github-workflow-add-valgrind-tests.patch b/0109-github-workflow-add-valgrind-tests.patch new file mode 100644 index 0000000..5c4e366 --- /dev/null +++ b/0109-github-workflow-add-valgrind-tests.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 18 Dec 2020 23:21:16 +0100 +Subject: [PATCH] github workflow: add valgrind tests + +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +index 577a14ac..929f63a6 100644 +--- a/.github/workflows/build-and-unittest.yaml ++++ b/.github/workflows/build-and-unittest.yaml +@@ -16,13 +16,17 @@ jobs: + - name: dependencies + run: > + sudo apt-get install --yes gcc +- make perl-base pkg-config ++ make perl-base pkg-config valgrind + libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev + libudev-dev libjson-c-dev liburcu-dev libcmocka-dev + - name: build + run: make -O -j$(grep -c ^processor /proc/cpuinfo) + - name: test + run: make -O -j$(grep -c ^processor /proc/cpuinfo) test ++ - name: valgrind-test ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) valgrind-test ++ - name: valgrind-results ++ run: cat tests/*.vgr + - name: clean-nonroot-artifacts + run: rm -f tests/dmevents.out tests/directio.out + - name: root-test +-- +2.17.2 + diff --git a/0110-github-workflow-run-apt-get-update.patch b/0110-github-workflow-run-apt-get-update.patch new file mode 100644 index 0000000..d27f1ca --- /dev/null +++ b/0110-github-workflow-run-apt-get-update.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 18 Dec 2020 23:26:16 +0100 +Subject: [PATCH] github workflow: run apt-get update + +E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/main/g/glibc/libc6-dbg_2.27-3ubuntu1.3_amd64.deb 404 Not Found [IP: 52.252.75.106 80] +E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing? +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +index 929f63a6..389578be 100644 +--- a/.github/workflows/build-and-unittest.yaml ++++ b/.github/workflows/build-and-unittest.yaml +@@ -13,6 +13,8 @@ jobs: + run: echo ZRAM=$(sudo cat /sys/class/zram-control/hot_add) >> $GITHUB_ENV + - name: set-zram-size + run: echo 1G | sudo tee /sys/block/zram$ZRAM/disksize ++ - name: update ++ run: sudo apt-get update + - name: dependencies + run: > + sudo apt-get install --yes gcc +-- +2.17.2 + diff --git a/0111-github-workflow-add-tests-with-gcc-10-and-clang.patch b/0111-github-workflow-add-tests-with-gcc-10-and-clang.patch new file mode 100644 index 0000000..e95b3f8 --- /dev/null +++ b/0111-github-workflow-add-tests-with-gcc-10-and-clang.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 18 Dec 2020 23:44:11 +0100 +Subject: [PATCH] github workflow: add tests with gcc 10 and clang + +Signed-off-by: Benjamin Marzinski +--- + .github/workflows/build-and-unittest.yaml | 62 ++++++++++++++++++++++- + 1 file changed, 61 insertions(+), 1 deletion(-) + +diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml +index 389578be..4173576f 100644 +--- a/.github/workflows/build-and-unittest.yaml ++++ b/.github/workflows/build-and-unittest.yaml +@@ -1,7 +1,7 @@ + name: basic-build-and-ci + on: [push] + jobs: +- build: ++ bionic: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 +@@ -33,3 +33,63 @@ jobs: + run: rm -f tests/dmevents.out tests/directio.out + - name: root-test + run: sudo make DIO_TEST_DEV=/dev/zram$ZRAM test ++ focal-gcc10: ++ runs-on: ubuntu-20.04 ++ steps: ++ - uses: actions/checkout@v2 ++ - name: mpath ++ run: sudo modprobe dm_multipath ++ - name: brd ++ run: sudo modprobe brd rd_nr=1 rd_size=65536 ++ - name: update ++ run: sudo apt-get update ++ - name: dependencies ++ run: > ++ sudo apt-get install --yes gcc-10 ++ make perl-base pkg-config valgrind ++ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev ++ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev ++ - name: set CC ++ run: echo CC=gcc-10 >> $GITHUB_ENV ++ - name: build ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) ++ - name: test ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) test ++ - name: valgrind-test ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) valgrind-test ++ - name: valgrind-results ++ run: cat tests/*.vgr ++ - name: clean-nonroot-artifacts ++ run: rm -f tests/dmevents.out tests/directio.out ++ - name: root-test ++ run: sudo make DIO_TEST_DEV=/dev/ram0 test ++ focal-clang10: ++ runs-on: ubuntu-20.04 ++ steps: ++ - uses: actions/checkout@v2 ++ - name: mpath ++ run: sudo modprobe dm_multipath ++ - name: brd ++ run: sudo modprobe brd rd_nr=1 rd_size=65536 ++ - name: update ++ run: sudo apt-get update ++ - name: dependencies ++ run: > ++ sudo apt-get install --yes clang ++ make perl-base pkg-config valgrind ++ libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev ++ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev ++ - name: set CC ++ run: echo CC=clang >> $GITHUB_ENV ++ - name: build ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) ++ - name: test ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) test ++ - name: valgrind-test ++ run: make -O -j$(grep -c ^processor /proc/cpuinfo) valgrind-test ++ - name: valgrind-results ++ run: cat tests/*.vgr ++ - name: clean-nonroot-artifacts ++ run: rm -f tests/dmevents.out tests/directio.out ++ - name: root-test ++ run: sudo make DIO_TEST_DEV=/dev/ram0 test +-- +2.17.2 + diff --git a/0112-multipathd-Fix-multipathd-stopping-on-shutdown.patch b/0112-multipathd-Fix-multipathd-stopping-on-shutdown.patch new file mode 100644 index 0000000..49ea563 --- /dev/null +++ b/0112-multipathd-Fix-multipathd-stopping-on-shutdown.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 18 Dec 2020 17:06:41 -0600 +Subject: [PATCH] multipathd: Fix multipathd stopping on shutdown + +According to man "systemd.special" + +"shutdown.target: ... Services that shall be terminated on system +shutdown shall add Conflicts= and Before= dependencies to this unit for +their service unit, which is implicitly done when +DefaultDependencies=yes is set (the default)." + +multipathd.service sets DefaultDependencies=no and includes the +Conflits= dependency, but not the Before= one. This can cause multipathd +to continue running past when it is supposed to during shutdown. + +Signed-off-by: Benjamin Marzinski +Reviewed-by: Martin Wilck +--- + multipathd/multipathd.service | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service +index ba24983e..7d547fa7 100644 +--- a/multipathd/multipathd.service ++++ b/multipathd/multipathd.service +@@ -2,7 +2,7 @@ + Description=Device-Mapper Multipath Device Controller + Wants=systemd-udev-trigger.service systemd-udev-settle.service + Before=iscsi.service iscsid.service lvm2-activation-early.service +-Before=local-fs-pre.target blk-availability.service ++Before=local-fs-pre.target blk-availability.service shutdown.target + After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service + DefaultDependencies=no + Conflicts=shutdown.target +-- +2.17.2 + diff --git a/0113-libmultipath-use-3rd-digit-as-transport_id-for-expan.patch b/0113-libmultipath-use-3rd-digit-as-transport_id-for-expan.patch new file mode 100644 index 0000000..17d53ce --- /dev/null +++ b/0113-libmultipath-use-3rd-digit-as-transport_id-for-expan.patch @@ -0,0 +1,45 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Nov 2020 22:34:41 +0100 +Subject: [PATCH] libmultipath: use 3rd digit as transport_id for expanders + +On SAS expanders, node id's have 3 digits. sysfs paths look like this: + +/sys/devices/pci0000:80/0000:80:02.0/0000:8b:00.0/0000:8c:09.0/0000:8f:00.0/host9/port-9:0/expander-9:0/port-9:0:13/expander-9:1/port-9:1:12/expander-9:2/port-9:2:4/end_device-9:2:4/target9:0:29/9:0:29:0/block/sdac + +In that case, we should use the last digit as transport id. + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index e818585a..6d74cc07 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -358,10 +358,17 @@ sysfs_get_tgt_nodename(struct path *pp, char *node) + if (value) { + tgtdev = udev_device_get_parent(parent); + while (tgtdev) { ++ char c; ++ + tgtname = udev_device_get_sysname(tgtdev); +- if (tgtname && sscanf(tgtname, "end_device-%d:%d", +- &host, &tgtid) == 2) +- break; ++ if (tgtname) { ++ if (sscanf(tgtname, "end_device-%d:%d:%d%c", ++ &host, &channel, &tgtid, &c) == 3) ++ break; ++ if (sscanf(tgtname, "end_device-%d:%d%c", ++ &host, &tgtid, &c) == 2) ++ break; ++ } + tgtdev = udev_device_get_parent(tgtdev); + tgtid = -1; + } +-- +2.17.2 + diff --git a/0114-libmultipath-sysfs_set_nexus_loss_tmo-support-SAS-ex.patch b/0114-libmultipath-sysfs_set_nexus_loss_tmo-support-SAS-ex.patch new file mode 100644 index 0000000..3207d2d --- /dev/null +++ b/0114-libmultipath-sysfs_set_nexus_loss_tmo-support-SAS-ex.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Fri, 13 Nov 2020 22:38:21 +0100 +Subject: [PATCH] libmultipath: sysfs_set_nexus_loss_tmo(): support SAS + expanders + +With SAS expanders, SAS node names have 3 digits. libmultipath +would fail to discover the sas_end_device matching a given SCSI +target in this case. Fix it. + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 24 +++++++++++++++++++----- + 1 file changed, 19 insertions(+), 5 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 6d74cc07..921025d4 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -789,14 +789,28 @@ sysfs_set_session_tmo(struct multipath *mpp, struct path *pp) + static void + sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp) + { +- struct udev_device *sas_dev = NULL; +- char end_dev_id[64]; ++ struct udev_device *parent, *sas_dev = NULL; ++ const char *end_dev_id = NULL; + char value[11]; ++ static const char ed_str[] = "end_device-"; + +- if (mpp->dev_loss == DEV_LOSS_TMO_UNSET) ++ if (!pp->udev || mpp->dev_loss == DEV_LOSS_TMO_UNSET) + return; +- sprintf(end_dev_id, "end_device-%d:%d", +- pp->sg_id.host_no, pp->sg_id.transport_id); ++ ++ for (parent = udev_device_get_parent(pp->udev); ++ parent; ++ parent = udev_device_get_parent(parent)) { ++ const char *ed = udev_device_get_sysname(parent); ++ ++ if (!strncmp(ed, ed_str, sizeof(ed_str) - 1)) { ++ end_dev_id = ed; ++ break; ++ } ++ } ++ if (!end_dev_id) { ++ condlog(1, "%s: No SAS end device", pp->dev); ++ return; ++ } + sas_dev = udev_device_new_from_subsystem_sysname(udev, + "sas_end_device", end_dev_id); + if (!sas_dev) { +-- +2.17.2 + diff --git a/0115-multipathd-add-code-to-initalize-unwinder.patch b/0115-multipathd-add-code-to-initalize-unwinder.patch new file mode 100644 index 0000000..e231733 --- /dev/null +++ b/0115-multipathd-add-code-to-initalize-unwinder.patch @@ -0,0 +1,134 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 17 Dec 2020 16:50:06 +0100 +Subject: [PATCH] multipathd: add code to initalize unwinder + +glibc's implementation of pthread_cancel() loads symbols from +libgcc_s.so using dlopen() when pthread_cancel() is called +for the first time. This happens even with LD_BIND_NOW=1. +This may imply the need for file system access when a thread is +cancelled, which in the case of multipath-tools might be in a +dangerous situation where multipathd must avoid blocking. + +Call load_unwinder() during startup to make sure the dynamic +linker has all necessary symbols resolved early on. + +This implementation simply creates a dummy thread and cancels +it. This way all necessary symbols for thread cancellation +will be loaded, no matter what the C library needs to implement +cancellation. + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipathd/Makefile | 2 +- + multipathd/init_unwinder.c | 34 ++++++++++++++++++++++++++++++++++ + multipathd/init_unwinder.h | 21 +++++++++++++++++++++ + multipathd/main.c | 2 ++ + 4 files changed, 58 insertions(+), 1 deletion(-) + create mode 100644 multipathd/init_unwinder.c + create mode 100644 multipathd/init_unwinder.h + +diff --git a/multipathd/Makefile b/multipathd/Makefile +index 632b82b1..d053c1ed 100644 +--- a/multipathd/Makefile ++++ b/multipathd/Makefile +@@ -30,7 +30,7 @@ ifeq ($(ENABLE_DMEVENTS_POLL),0) + endif + + OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o \ +- dmevents.o ++ dmevents.o init_unwinder.o + + EXEC = multipathd + +diff --git a/multipathd/init_unwinder.c b/multipathd/init_unwinder.c +new file mode 100644 +index 00000000..14467f3d +--- /dev/null ++++ b/multipathd/init_unwinder.c +@@ -0,0 +1,34 @@ ++#include ++#include ++#include "init_unwinder.h" ++ ++static pthread_mutex_t dummy_mtx = PTHREAD_MUTEX_INITIALIZER; ++static pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER; ++ ++static void *dummy_thread(void *arg __attribute__((unused))) ++{ ++ pthread_mutex_lock(&dummy_mtx); ++ pthread_cond_broadcast(&dummy_cond); ++ pthread_mutex_unlock(&dummy_mtx); ++ pause(); ++ return NULL; ++} ++ ++int init_unwinder(void) ++{ ++ pthread_t dummy; ++ int rc; ++ ++ pthread_mutex_lock(&dummy_mtx); ++ ++ rc = pthread_create(&dummy, NULL, dummy_thread, NULL); ++ if (rc != 0) { ++ pthread_mutex_unlock(&dummy_mtx); ++ return rc; ++ } ++ ++ pthread_cond_wait(&dummy_cond, &dummy_mtx); ++ pthread_mutex_unlock(&dummy_mtx); ++ ++ return pthread_cancel(dummy); ++} +diff --git a/multipathd/init_unwinder.h b/multipathd/init_unwinder.h +new file mode 100644 +index 00000000..ada09f82 +--- /dev/null ++++ b/multipathd/init_unwinder.h +@@ -0,0 +1,21 @@ ++#ifndef _INIT_UNWINDER_H ++#define _INIT_UNWINDER_H 1 ++ ++/* ++ * init_unwinder(): make sure unwinder symbols are loaded ++ * ++ * libc's implementation of pthread_cancel() loads symbols from ++ * libgcc_s.so using dlopen() when pthread_cancel() is called ++ * for the first time. This happens even with LD_BIND_NOW=1. ++ * This may imply the need for file system access when a thread is ++ * cancelled, which in the case of multipath-tools might be in a ++ * dangerous situation where multipathd must avoid blocking. ++ * ++ * Call load_unwinder() during startup to make sure the dynamic ++ * linker has all necessary symbols resolved early on. ++ * ++ * Return: 0 if successful, an error number otherwise. ++ */ ++int init_unwinder(void); ++ ++#endif +diff --git a/multipathd/main.c b/multipathd/main.c +index 99a89a69..6f851ae8 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -83,6 +83,7 @@ + #include "wwids.h" + #include "foreign.h" + #include "../third-party/valgrind/drd.h" ++#include "init_unwinder.h" + + #define FILE_NAME_SIZE 256 + #define CMDSIZE 160 +@@ -3041,6 +3042,7 @@ child (__attribute__((unused)) void *param) + enum daemon_status state; + int exit_code = 1; + ++ init_unwinder(); + mlockall(MCL_CURRENT | MCL_FUTURE); + signal_init(); + mp_rcu_data = setup_rcu(); +-- +2.17.2 + diff --git a/0116-libmultipath-check-if-adopt_path-really-added-curren.patch b/0116-libmultipath-check-if-adopt_path-really-added-curren.patch new file mode 100644 index 0000000..b656c08 --- /dev/null +++ b/0116-libmultipath-check-if-adopt_path-really-added-curren.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 2 Feb 2021 11:12:21 +0100 +Subject: [PATCH] libmultipath: check if adopt_path() really added current path + +The description of 2d32d6f ("libmultipath: adopt_paths(): don't bail out on +single path failure") said "we need to check after successful call to +adopt_paths() if that specific path had been actually added, and fail in the +caller otherwise". But the commit failed to actually implement this check. +Instead, it just checked if the path was member of the pathvec, which will +almost always be the case. + +Fix it by checking what actually needs to be checked, membership of the +path to be added in mpp->paths. + +Fixes: 2d32d6f ("libmultipath: adopt_paths(): don't bail out on single path failure") + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs_vec.c | 4 ++-- + multipathd/main.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index f7f45f11..47b1d03e 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -707,8 +707,8 @@ struct multipath *add_map_with_path(struct vectors *vecs, struct path *pp, + goto out; + mpp->size = pp->size; + +- if (adopt_paths(vecs->pathvec, mpp) || +- find_slot(vecs->pathvec, pp) == -1) ++ if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp || ++ find_slot(mpp->paths, pp) == -1) + goto out; + + if (add_vec) { +diff --git a/multipathd/main.c b/multipathd/main.c +index 6f851ae8..43d77688 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1008,8 +1008,8 @@ rescan: + if (mpp) { + condlog(4,"%s: adopting all paths for path %s", + mpp->alias, pp->dev); +- if (adopt_paths(vecs->pathvec, mpp) || +- find_slot(vecs->pathvec, pp) == -1) ++ if (adopt_paths(vecs->pathvec, mpp) || pp->mpp != mpp || ++ find_slot(mpp->paths, pp) == -1) + goto fail; /* leave path added to pathvec */ + + verify_paths(mpp); +-- +2.17.2 + diff --git a/0117-multipathd-ev_add_path-fail-if-add_map_with_path-fai.patch b/0117-multipathd-ev_add_path-fail-if-add_map_with_path-fai.patch new file mode 100644 index 0000000..f223728 --- /dev/null +++ b/0117-multipathd-ev_add_path-fail-if-add_map_with_path-fai.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 1 Feb 2021 13:10:46 +0100 +Subject: [PATCH] multipathd: ev_add_path: fail if add_map_with_path() fails + +If start_waiter was set before and the "rescan" label was used, +we may try to set up an empty/invalid map. +Always fail if add_map_with_path() isn't successful. + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 43d77688..425492a9 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1028,7 +1028,7 @@ rescan: + */ + start_waiter = 1; + } +- if (!start_waiter) ++ else + goto fail; /* leave path added to pathvec */ + } + +-- +2.17.2 + diff --git a/0118-libmultipath-check-return-value-of-udev_device_get_d.patch b/0118-libmultipath-check-return-value-of-udev_device_get_d.patch new file mode 100644 index 0000000..fe69708 --- /dev/null +++ b/0118-libmultipath-check-return-value-of-udev_device_get_d.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 2 Feb 2021 15:18:33 +0100 +Subject: [PATCH] libmultipath: check return value of udev_device_get_devnum() + +udev_device_get_devnum() may fail, in which case it returns +makedev(0, 0). + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 921025d4..15cf6413 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1659,6 +1659,9 @@ common_sysfs_pathinfo (struct path * pp) + return PATHINFO_FAILED; + } + devt = udev_device_get_devnum(pp->udev); ++ if (major(devt) == 0 && minor(devt) == 0) ++ return PATHINFO_FAILED; ++ + snprintf(pp->dev_t, BLK_DEV_SIZE, "%d:%d", major(devt), minor(devt)); + + condlog(4, "%s: dev_t = %s", pp->dev, pp->dev_t); +-- +2.17.2 + diff --git a/0119-pathinfo-call-filter_property-after-sysfs_pathinfo.patch b/0119-pathinfo-call-filter_property-after-sysfs_pathinfo.patch new file mode 100644 index 0000000..cf106c2 --- /dev/null +++ b/0119-pathinfo-call-filter_property-after-sysfs_pathinfo.patch @@ -0,0 +1,281 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 2 Feb 2021 17:07:37 +0100 +Subject: [PATCH] pathinfo: call filter_property() after sysfs_pathinfo() + +The of filter_property() depends on the value of pp->uid_attribute. +This may in turn depend on pp->hwe, which is initialized in +sysfs_pathinfo(). To obtain consistent results from pathinfo(), +make sure uid_attribute is correctly set before calling filter_property(). + +filter_property() is now called from pathinfo() with properly set +uid_attribute, thus we don't need to call it from is_path_valid() any more. + +Thes changes require modifications to the unit tests. The is_path_valid() +test now wouldn't need to test filter_property() any more, because +is_path_valid() calls filter_property() no more. But that doesn't feel +right. Instead, test_filter_property() is modified to test the behavior +with the filter_property() test called indirectly from pathinfo(). + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 21 +++++++++- + libmultipath/valid.c | 4 -- + tests/Makefile | 2 +- + tests/test-lib.c | 5 ++- + tests/valid.c | 91 ++++++++++++++++++++++++++++++++++++---- + 5 files changed, 105 insertions(+), 18 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 15cf6413..febcd0ae 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -2247,9 +2247,17 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + condlog(4, "%s: hidden", pp->dev); + return PATHINFO_SKIPPED; + } +- if (is_claimed_by_foreign(pp->udev) || +- filter_property(conf, pp->udev, 4, pp->uid_attribute) > 0) ++ ++ if (is_claimed_by_foreign(pp->udev)) + return PATHINFO_SKIPPED; ++ ++ /* ++ * uid_attribute is required for filter_property below, ++ * and needs access to pp->hwe. ++ */ ++ if (!(mask & DI_SYSFS) && !pp->uid_attribute && ++ VECTOR_SIZE(pp->hwe) == 0) ++ mask |= DI_SYSFS; + } + + if (strlen(pp->dev) != 0 && filter_devnode(conf->blist_devnode, +@@ -2287,6 +2295,15 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + } + } + ++ if (pp->udev) { ++ /* uid_attribute is required for filter_property() */ ++ if (!pp->uid_attribute) ++ select_getuid(conf, pp); ++ ++ if (filter_property(conf, pp->udev, 4, pp->uid_attribute) > 0) ++ return PATHINFO_SKIPPED; ++ } ++ + if (mask & DI_BLACKLIST && mask & DI_SYSFS) { + if (filter_device(conf->blist_device, conf->elist_device, + pp->vendor_id, pp->product_id, pp->dev) > 0 || +diff --git a/libmultipath/valid.c b/libmultipath/valid.c +index 456b1f6e..a6aa9215 100644 +--- a/libmultipath/valid.c ++++ b/libmultipath/valid.c +@@ -89,10 +89,6 @@ is_path_valid(const char *name, struct config *conf, struct path *pp, + if (pp->wwid[0] == '\0') + return PATH_IS_NOT_VALID; + +- if (pp->udev && pp->uid_attribute && +- filter_property(conf, pp->udev, 3, pp->uid_attribute) > 0) +- return PATH_IS_NOT_VALID; +- + r = is_failed_wwid(pp->wwid); + if (r != WWID_IS_NOT_FAILED) { + if (r == WWID_IS_FAILED) +diff --git a/tests/Makefile b/tests/Makefile +index 50673fae..11ca1be5 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -54,7 +54,7 @@ vpd-test_OBJDEPS := ../libmultipath/discovery.o + vpd-test_LIBDEPS := -ludev -lpthread -ldl + alias-test_TESTDEPS := test-log.o + alias-test_LIBDEPS := -lpthread -ldl +-valid-test_OBJDEPS := ../libmultipath/valid.o ++valid-test_OBJDEPS := ../libmultipath/valid.o ../libmultipath/discovery.o + valid-test_LIBDEPS := -ludev -lpthread -ldl + devt-test_LIBDEPS := -ludev + mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl +diff --git a/tests/test-lib.c b/tests/test-lib.c +index e7663f9a..960a7665 100644 +--- a/tests/test-lib.c ++++ b/tests/test-lib.c +@@ -257,6 +257,9 @@ void mock_pathinfo(int mask, const struct mocked_path *mp) + } else + will_return(__wrap_udev_device_get_sysattr_value, "0"); + ++ if (mask & DI_SYSFS) ++ mock_sysfs_pathinfo(mp); ++ + /* filter_property */ + will_return(__wrap_udev_device_get_sysname, mp->devnode); + if (mp->flags & BL_BY_PROPERTY) { +@@ -265,8 +268,6 @@ void mock_pathinfo(int mask, const struct mocked_path *mp) + } else + will_return(__wrap_udev_list_entry_get_name, + "SCSI_IDENT_LUN_NAA_EXT"); +- if (mask & DI_SYSFS) +- mock_sysfs_pathinfo(mp); + + if (mp->flags & BL_BY_DEVICE && + (mask & DI_BLACKLIST && mask & DI_SYSFS)) +diff --git a/tests/valid.c b/tests/valid.c +index 693c72c5..8ec803e8 100644 +--- a/tests/valid.c ++++ b/tests/valid.c +@@ -25,13 +25,18 @@ + #include + #include + #include ++#include ++ + #include "globals.c" + #include "util.h" + #include "discovery.h" + #include "wwids.h" + #include "blacklist.h" ++#include "foreign.h" + #include "valid.h" + ++#define PATHINFO_REAL 9999 ++ + int test_fd; + struct udev_device { + int unused; +@@ -78,12 +83,66 @@ struct udev_device *__wrap_udev_device_new_from_subsystem_sysname(struct udev *u + return NULL; + } + ++/* For the "hidden" check in pathinfo() */ ++const char *__wrap_udev_device_get_sysattr_value(struct udev_device *udev_device, ++ const char *sysattr) ++{ ++ check_expected(sysattr); ++ return mock_ptr_type(char *); ++} ++ ++/* For pathinfo() -> is_claimed_by_foreign() */ ++int __wrap_add_foreign(struct udev_device *udev_device) ++{ ++ return mock_type(int); ++} ++ ++/* called from pathinfo() */ ++int __wrap_filter_devnode(struct config *conf, const struct _vector *elist, ++ const char *vendor, const char * product, const char *dev) ++{ ++ return mock_type(int); ++} ++ ++/* called from pathinfo() */ ++int __wrap_filter_device(const struct _vector *blist, const struct _vector *elist, ++ const char *vendor, const char * product, const char *dev) ++{ ++ return mock_type(int); ++} ++ ++/* for common_sysfs_pathinfo() */ ++dev_t __wrap_udev_device_get_devnum(struct udev_device *ud) ++{ ++ return mock_type(dev_t); ++} ++ ++/* for common_sysfs_pathinfo() */ ++int __wrap_sysfs_get_size(struct path *pp, unsigned long long * size) ++{ ++ return mock_type(int); ++} ++ ++/* called in pathinfo() before filter_property() */ ++int __wrap_select_getuid(struct config *conf, struct path *pp) ++{ ++ pp->uid_attribute = mock_ptr_type(char *); ++ return 0; ++} ++ ++int __real_pathinfo(struct path *pp, struct config *conf, int mask); ++ + int __wrap_pathinfo(struct path *pp, struct config *conf, int mask) + { + int ret = mock_type(int); ++ + assert_string_equal(pp->dev, mock_ptr_type(char *)); + assert_int_equal(mask, DI_SYSFS | DI_WWID | DI_BLACKLIST); +- if (ret == PATHINFO_OK) { ++ if (ret == PATHINFO_REAL) { ++ /* for test_filter_property() */ ++ ret = __real_pathinfo(pp, conf, mask); ++ return ret; ++ } else if (ret == PATHINFO_OK) { + pp->uid_attribute = "ID_TEST"; + strlcpy(pp->wwid, mock_ptr_type(char *), WWID_SIZE); + } else +@@ -128,6 +187,7 @@ enum { + STAGE_IS_MULTIPATHED, + STAGE_CHECK_MULTIPATHD, + STAGE_GET_UDEV_DEVICE, ++ STAGE_PATHINFO_REAL, + STAGE_PATHINFO, + STAGE_FILTER_PROPERTY, + STAGE_IS_FAILED, +@@ -167,12 +227,25 @@ static void setup_passing(char *name, char *wwid, unsigned int check_multipathd, + name); + if (stage == STAGE_GET_UDEV_DEVICE) + return; ++ if (stage == STAGE_PATHINFO_REAL) { ++ /* special case for test_filter_property() */ ++ will_return(__wrap_pathinfo, PATHINFO_REAL); ++ will_return(__wrap_pathinfo, name); ++ expect_string(__wrap_udev_device_get_sysattr_value, ++ sysattr, "hidden"); ++ will_return(__wrap_udev_device_get_sysattr_value, NULL); ++ will_return(__wrap_add_foreign, FOREIGN_IGNORED); ++ will_return(__wrap_filter_devnode, MATCH_NOTHING); ++ will_return(__wrap_udev_device_get_devnum, makedev(259, 0)); ++ will_return(__wrap_sysfs_get_size, 0); ++ will_return(__wrap_select_getuid, "ID_TEST"); ++ return; ++ } + will_return(__wrap_pathinfo, PATHINFO_OK); + will_return(__wrap_pathinfo, name); + will_return(__wrap_pathinfo, wwid); + if (stage == STAGE_PATHINFO) + return; +- will_return(__wrap_filter_property, MATCH_PROPERTY_BLIST_EXCEPT); + if (stage == STAGE_FILTER_PROPERTY) + return; + will_return(__wrap_is_failed_wwid, WWID_IS_NOT_FAILED); +@@ -317,24 +390,24 @@ static void test_filter_property(void **state) + /* test blacklist property */ + memset(&pp, 0, sizeof(pp)); + conf.find_multipaths = FIND_MULTIPATHS_STRICT; +- setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO); ++ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO_REAL); + will_return(__wrap_filter_property, MATCH_PROPERTY_BLIST); + assert_int_equal(is_path_valid(name, &conf, &pp, false), + PATH_IS_NOT_VALID); + assert_ptr_equal(pp.udev, &test_udev); +- assert_string_equal(pp.wwid, wwid); ++ + /* test missing property */ + memset(&pp, 0, sizeof(pp)); +- setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO); ++ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO_REAL); + will_return(__wrap_filter_property, MATCH_PROPERTY_BLIST_MISSING); + assert_int_equal(is_path_valid(name, &conf, &pp, false), + PATH_IS_NOT_VALID); +- /* test MATCH_NOTHING fail on is_failed_wwid */ ++ ++ /* test MATCH_NOTHING fail on filter_device */ + memset(&pp, 0, sizeof(pp)); +- setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO); ++ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO_REAL); + will_return(__wrap_filter_property, MATCH_NOTHING); +- will_return(__wrap_is_failed_wwid, WWID_IS_FAILED); +- will_return(__wrap_is_failed_wwid, wwid); ++ will_return(__wrap_filter_device, MATCH_DEVICE_BLIST); + assert_int_equal(is_path_valid(name, &conf, &pp, false), + PATH_IS_NOT_VALID); + } +-- +2.17.2 + diff --git a/0120-libmultipath-pathinfo-call-filter_property-only-with.patch b/0120-libmultipath-pathinfo-call-filter_property-only-with.patch new file mode 100644 index 0000000..c4c8efc --- /dev/null +++ b/0120-libmultipath-pathinfo-call-filter_property-only-with.patch @@ -0,0 +1,88 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 2 Feb 2021 19:55:28 +0100 +Subject: [PATCH] libmultipath: pathinfo: call filter_property only with + DI_BLACKLIST + +With the previous change to call filter_property() after sysfs_pathinfo(), +it can't happen any more that filter_property() is called from pathinfo +with uid_attribute not set. This may cause pathinfo() to return failure +in some cases where it should actually proceed (e.g. when called from +"multipath -m" -> get_refwwid(). Therefore, don't call filter_property() +any more unless DI_BLACKLIST is set. + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 16 ++++++---------- + tests/test-lib.c | 17 +++++++++-------- + 2 files changed, 15 insertions(+), 18 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index febcd0ae..9be94cd1 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -2255,8 +2255,8 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + * uid_attribute is required for filter_property below, + * and needs access to pp->hwe. + */ +- if (!(mask & DI_SYSFS) && !pp->uid_attribute && +- VECTOR_SIZE(pp->hwe) == 0) ++ if (!(mask & DI_SYSFS) && (mask & DI_BLACKLIST) && ++ !pp->uid_attribute && VECTOR_SIZE(pp->hwe) == 0) + mask |= DI_SYSFS; + } + +@@ -2295,17 +2295,13 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + } + } + +- if (pp->udev) { ++ if (mask & DI_BLACKLIST && mask & DI_SYSFS) { + /* uid_attribute is required for filter_property() */ +- if (!pp->uid_attribute) ++ if (pp->udev && !pp->uid_attribute) + select_getuid(conf, pp); + +- if (filter_property(conf, pp->udev, 4, pp->uid_attribute) > 0) +- return PATHINFO_SKIPPED; +- } +- +- if (mask & DI_BLACKLIST && mask & DI_SYSFS) { +- if (filter_device(conf->blist_device, conf->elist_device, ++ if (filter_property(conf, pp->udev, 4, pp->uid_attribute) > 0 || ++ filter_device(conf->blist_device, conf->elist_device, + pp->vendor_id, pp->product_id, pp->dev) > 0 || + filter_protocol(conf->blist_protocol, conf->elist_protocol, + pp) > 0) +diff --git a/tests/test-lib.c b/tests/test-lib.c +index 960a7665..f5542ed0 100644 +--- a/tests/test-lib.c ++++ b/tests/test-lib.c +@@ -260,14 +260,15 @@ void mock_pathinfo(int mask, const struct mocked_path *mp) + if (mask & DI_SYSFS) + mock_sysfs_pathinfo(mp); + +- /* filter_property */ +- will_return(__wrap_udev_device_get_sysname, mp->devnode); +- if (mp->flags & BL_BY_PROPERTY) { +- will_return(__wrap_udev_list_entry_get_name, "BAZ"); +- return; +- } else +- will_return(__wrap_udev_list_entry_get_name, +- "SCSI_IDENT_LUN_NAA_EXT"); ++ if (mask & DI_BLACKLIST) { ++ will_return(__wrap_udev_device_get_sysname, mp->devnode); ++ if (mp->flags & BL_BY_PROPERTY) { ++ will_return(__wrap_udev_list_entry_get_name, "BAZ"); ++ return; ++ } else ++ will_return(__wrap_udev_list_entry_get_name, ++ "SCSI_IDENT_LUN_NAA_EXT"); ++ } + + if (mp->flags & BL_BY_DEVICE && + (mask & DI_BLACKLIST && mask & DI_SYSFS)) +-- +2.17.2 + diff --git a/0121-multipath-w-allow-removing-blacklisted-paths.patch b/0121-multipath-w-allow-removing-blacklisted-paths.patch new file mode 100644 index 0000000..db6fe52 --- /dev/null +++ b/0121-multipath-w-allow-removing-blacklisted-paths.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 2 Feb 2021 21:54:37 +0100 +Subject: [PATCH] multipath -w: allow removing blacklisted paths + +multipath should allow removing WWIDs of paths even if they +are blacklisted. + +Reviewed-by: Benjamin Marzinski +Signed-off-by: Benjamin Marzinski +--- + libmultipath/configure.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 3263bb01..598efe05 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1441,7 +1441,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev, + return ret; + } + } +- if (pp->udev && pp->uid_attribute && ++ if (flags & DI_BLACKLIST && + filter_property(conf, pp->udev, 3, pp->uid_attribute) > 0) + return PATHINFO_SKIPPED; + refwwid = pp->wwid; +@@ -1466,7 +1466,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev, + refwwid = dev; + } + +- if (refwwid && strlen(refwwid) && ++ if (flags & DI_BLACKLIST && refwwid && strlen(refwwid) && + filter_wwid(conf->blist_wwid, conf->elist_wwid, refwwid, + NULL) > 0) + return PATHINFO_SKIPPED; +-- +2.17.2 + diff --git a/0122-libmultipath-fix-use-after-free-in-uev_add_path.patch b/0122-libmultipath-fix-use-after-free-in-uev_add_path.patch new file mode 100644 index 0000000..6a5fcad --- /dev/null +++ b/0122-libmultipath-fix-use-after-free-in-uev_add_path.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 1 Feb 2021 19:47:11 -0600 +Subject: [PATCH] libmultipath: fix use-after-free in uev_add_path + +if ev_remove_path() returns success the path has very likely been +deleted. However, if pathinfo() returned something besides PATHINFO_OK, +but ev_remove_path() succeeded, uev_add_path() was still accessing the +the path afterwards, which would likely cause a use-after-free error. +Insted, uev_add_path() should only continue to access the path if +ev_remove_path() didn't succeed. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 425492a9..19679848 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -890,13 +890,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map) + */ + pp->mpp = prev_mpp; + ret = ev_remove_path(pp, vecs, true); +- if (r == PATHINFO_OK && !ret) +- /* +- * Path successfully freed, move on to +- * "new path" code path below +- */ +- pp = NULL; +- else { ++ if (ret != 0) { + /* + * Failure in ev_remove_path will keep + * path in pathvec in INIT_REMOVED state +@@ -907,7 +901,12 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map) + dm_fail_path(pp->mpp->alias, pp->dev_t); + condlog(1, "%s: failed to re-add path still mapped in %s", + pp->dev, pp->mpp->alias); +- } ++ } else if (r == PATHINFO_OK) ++ /* ++ * Path successfully freed, move on to ++ * "new path" code path below ++ */ ++ pp = NULL; + } else if (r == PATHINFO_SKIPPED) { + condlog(3, "%s: remove blacklisted path", + uev->kernel); +-- +2.17.2 + diff --git a/0123-kpartx-free-loop-device-after-listing-partitions.patch b/0123-kpartx-free-loop-device-after-listing-partitions.patch new file mode 100644 index 0000000..4db7cfd --- /dev/null +++ b/0123-kpartx-free-loop-device-after-listing-partitions.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Feb 2021 17:16:04 -0600 +Subject: [PATCH] kpartx: free loop device after listing partitions + +If "kpartx -l" is run on a file that doesn't already have a loop device +associated with it, it will create a loop device to run the command. +Starting with da59d15c6 ("Fix loopback file with kpartx -av"), it will +not free the loop device when exitting. This is because it checks if the +the file it stat()ed is a regular file, before freeing the loop device. +However, after da59d15c6, stat() is rerun on the loop device itself, so +the check fails. There is no need to check this, if loopcreated is +true, then the file will be a kpartx created loop device, and should be +freed. + +Also, keep kpartx from printing that the loop device has been removed +at normal verbosity. + +Fixes: da59d15c6 ("Fix loopback file with kpartx -av") +Signed-off-by: Benjamin Marzinski +--- + kpartx/kpartx.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c +index 6a7933fa..8ff116b8 100644 +--- a/kpartx/kpartx.c ++++ b/kpartx/kpartx.c +@@ -424,7 +424,7 @@ main(int argc, char **argv){ + fprintf(stderr, "can't del loop : %s\n", + loopdev); + r = 1; +- } else ++ } else if (verbose) + fprintf(stderr, "loop deleted : %s\n", loopdev); + } + goto end; +@@ -668,16 +668,17 @@ main(int argc, char **argv){ + if (n > 0) + break; + } +- if (what == LIST && loopcreated && S_ISREG (buf.st_mode)) { ++ if (what == LIST && loopcreated) { + if (fd != -1) + close(fd); + if (del_loop(device)) { + if (verbose) +- printf("can't del loop : %s\n", ++ fprintf(stderr, "can't del loop : %s\n", + device); + exit(1); + } +- printf("loop deleted : %s\n", device); ++ if (verbose) ++ fprintf(stderr, "loop deleted : %s\n", device); + } + + end: +-- +2.17.2 + diff --git a/0103-RH-fixup-udev-rules-for-redhat.patch b/0124-RH-fixup-udev-rules-for-redhat.patch similarity index 100% rename from 0103-RH-fixup-udev-rules-for-redhat.patch rename to 0124-RH-fixup-udev-rules-for-redhat.patch diff --git a/0104-RH-Remove-the-property-blacklist-exception-builtin.patch b/0125-RH-Remove-the-property-blacklist-exception-builtin.patch similarity index 100% rename from 0104-RH-Remove-the-property-blacklist-exception-builtin.patch rename to 0125-RH-Remove-the-property-blacklist-exception-builtin.patch diff --git a/0105-RH-don-t-start-without-a-config-file.patch b/0126-RH-don-t-start-without-a-config-file.patch similarity index 97% rename from 0105-RH-don-t-start-without-a-config-file.patch rename to 0126-RH-don-t-start-without-a-config-file.patch index 2f8d791..2931726 100644 --- a/0105-RH-don-t-start-without-a-config-file.patch +++ b/0126-RH-don-t-start-without-a-config-file.patch @@ -81,12 +81,12 @@ index 048a838d..8bd47a80 100644 . .\" ---------------------------------------------------------------------------- diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index ba24983e..17434cef 100644 +index 7d547fa7..af592057 100644 --- a/multipathd/multipathd.service +++ b/multipathd/multipathd.service @@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service Before=iscsi.service iscsid.service lvm2-activation-early.service - Before=local-fs-pre.target blk-availability.service + Before=local-fs-pre.target blk-availability.service shutdown.target After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service +ConditionPathExists=/etc/multipath.conf DefaultDependencies=no diff --git a/0106-RH-Fix-nvme-function-missing-argument.patch b/0127-RH-Fix-nvme-function-missing-argument.patch similarity index 100% rename from 0106-RH-Fix-nvme-function-missing-argument.patch rename to 0127-RH-Fix-nvme-function-missing-argument.patch diff --git a/0107-RH-use-rpm-optflags-if-present.patch b/0128-RH-use-rpm-optflags-if-present.patch similarity index 100% rename from 0107-RH-use-rpm-optflags-if-present.patch rename to 0128-RH-use-rpm-optflags-if-present.patch diff --git a/0108-RH-add-mpathconf.patch b/0129-RH-add-mpathconf.patch similarity index 93% rename from 0108-RH-add-mpathconf.patch rename to 0129-RH-add-mpathconf.patch index 503fef2..346251a 100644 --- a/0108-RH-add-mpathconf.patch +++ b/0129-RH-add-mpathconf.patch @@ -69,7 +69,7 @@ index b9bbb3cf..e720c7f6 100644 $(RM) core *.o $(EXEC) *.gz diff --git a/multipath/mpathconf b/multipath/mpathconf new file mode 100644 -index 00000000..f34003c9 +index 00000000..2f4f3eaf --- /dev/null +++ b/multipath/mpathconf @@ -0,0 +1,555 @@ @@ -129,7 +129,7 @@ index 00000000..f34003c9 + echo "Disable: --disable" + echo "Only allow certain wwids (instead of enable): --allow " + echo "Set user_friendly_names (Default y): --user_friendly_names " -+ echo "Set find_multipaths (Default y): --find_multipaths " ++ echo "Set find_multipaths (Default y): --find_multipaths " + echo "Set default property blacklist (Default y): --property_blacklist " + echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign " + echo "Load the dm-multipath modules on enable (Default y): --with_module " @@ -299,8 +299,12 @@ index 00000000..f34003c9 + echo "--user_friendly_names must be either 'y' or 'n'" + exit 1 + fi -+ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then -+ echo "--find_multipaths must be either 'y' or 'n'" ++ if [ "$FIND" = "y" ]; then ++ FIND="yes" ++ elif [ "$FIND" = "n" ]; then ++ FIND="no" ++ elif [ -n "$FIND" ] && [ "$FIND" != "yes" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then ++ echo "--find_multipaths must be one of 'yes' 'no' 'strict' 'greedy' or 'smart'" + exit 1 + fi + if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then @@ -402,10 +406,11 @@ index 00000000..f34003c9 +fi + +if [ "$HAVE_DEFAULTS" = "1" ]; then -+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then -+ HAVE_FIND=1 -+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then -+ HAVE_FIND=0 ++ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p` ++ if [ "$HAVE_FIND" = "1" ]; then ++ HAVE_FIND="yes" ++ elif [ "$HAVE_FIND" = "0" ]; then ++ HAVE_FIND="no" + fi + if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then + HAVE_FRIENDLY=1 @@ -435,10 +440,10 @@ index 00000000..f34003c9 + else + echo "multipath is disabled" + fi -+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then -+ echo "find_multipaths is disabled" ++ if [ -z "$HAVE_FIND" ]; then ++ echo "find_multipaths is no" + else -+ echo "find_multipaths is enabled" ++ echo "find_multipaths is $HAVE_FIND" + fi + if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then + echo "user_friendly_names is disabled" @@ -530,19 +535,14 @@ index 00000000..f34003c9 + fi +fi + -+if [ "$FIND" = "n" ]; then -+ if [ "$HAVE_FIND" = 1 ]; then -+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE -+ CHANGED_CONFIG=1 -+ fi -+elif [ "$FIND" = "y" ]; then ++if [ -n "$FIND" ]; then + if [ -z "$HAVE_FIND" ]; then + sed -i '/^defaults[[:space:]]*{/ a\ -+ find_multipaths yes ++ find_multipaths '"$FIND"' +' $TMPFILE + CHANGED_CONFIG=1 -+ elif [ "$HAVE_FIND" = 0 ]; then -+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE ++ elif [ "$FIND" != "$HAVE_FIND" ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE + CHANGED_CONFIG=1 + fi +fi @@ -630,7 +630,7 @@ index 00000000..f34003c9 +fi diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8 new file mode 100644 -index 00000000..b82961d6 +index 00000000..83515eb4 --- /dev/null +++ b/multipath/mpathconf.8 @@ -0,0 +1,135 @@ @@ -674,9 +674,9 @@ index 00000000..b82961d6 +already exists, mpathconf will edit it. If it does not exist, mpathconf will +create a default file with +.B user_friendly_names -+and ++set and +.B find_multipaths -+set. To disable these, use the ++set to \fByes\fP. To disable these, use the +.B --user_friendly_names n +and +.B --find_multipaths n @@ -713,13 +713,13 @@ index 00000000..b82961d6 +defaults section. If set to \fBn\fP, this removes the line, if present. This +command can be used along with any other command. +.TP -+.B --find_multipaths\fP { \fBy\fP | \fBn\fP } -+If set to \fBy\fP, this adds the line -+.B find_multipaths yes ++.B --find_multipaths\fP { \fByes\fP | \fBno\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP } ++If set to \fB\fP, this adds the line ++.B find_multipaths +to the +.B /etc/multipath.conf -+defaults section. If set to \fBn\fP, this removes the line, if present. This -+command can be used along with any other command. ++defaults section. This command can be used along with any other command. ++\fBy\fP and \fBn\fP can be used instead of \fByes\fP and \fBno\fP. +.TP +.B --property_blacklist \fP { \fBy\fP | \fBn\fP } +If set to \fBy\fP, this adds the line diff --git a/0109-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/0130-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch similarity index 99% rename from 0109-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch rename to 0130-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch index cdce408..3f0a9ad 100644 --- a/0109-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ b/0130-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -138,7 +138,7 @@ index 5b29a5d9..0478f4e7 100644 Remove the WWID for the specified device from the WWIDs file. . diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index 17434cef..0fbcc46b 100644 +index af592057..bc8fa07a 100644 --- a/multipathd/multipathd.service +++ b/multipathd/multipathd.service @@ -15,6 +15,7 @@ Type=notify diff --git a/0110-RH-reset-default-find_mutipaths-value-to-off.patch b/0131-RH-reset-default-find_mutipaths-value-to-off.patch similarity index 100% rename from 0110-RH-reset-default-find_mutipaths-value-to-off.patch rename to 0131-RH-reset-default-find_mutipaths-value-to-off.patch diff --git a/0111-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/0132-RH-attempt-to-get-ANA-info-via-sysfs-first.patch similarity index 100% rename from 0111-RH-attempt-to-get-ANA-info-via-sysfs-first.patch rename to 0132-RH-attempt-to-get-ANA-info-via-sysfs-first.patch diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec index 3969445..a304363 100644 --- a/device-mapper-multipath.spec +++ b/device-mapper-multipath.spec @@ -1,6 +1,6 @@ Name: device-mapper-multipath Version: 0.8.5 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Tools to manage multipath devices using device-mapper License: GPLv2 URL: http://christophe.varoqui.free.fr/ @@ -112,15 +112,36 @@ Patch0099: 0099-multipathd-avoid-io_err_stat-ABBA-deadlock.patch Patch0100: 0100-multipathd-use-get_monotonic_time-in-io_err_stat-cod.patch Patch0101: 0101-multipathd-combine-free_io_err_stat_path-and-destroy.patch Patch0102: 0102-multipathd-cleanup-logging-for-marginal-paths.patch -Patch0103: 0103-RH-fixup-udev-rules-for-redhat.patch -Patch0104: 0104-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0105: 0105-RH-don-t-start-without-a-config-file.patch -Patch0106: 0106-RH-Fix-nvme-function-missing-argument.patch -Patch0107: 0107-RH-use-rpm-optflags-if-present.patch -Patch0108: 0108-RH-add-mpathconf.patch -Patch0109: 0109-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0110: 0110-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0111: 0111-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0103: 0103-libmultipath-fix-NULL-dereference-in-find_path_by_de.patch +Patch0104: 0104-libmultipath-snprint_devices-avoid-NULL-dereference.patch +Patch0105: 0105-libmpathpersist-fix-thread-safety-of-default-functio.patch +Patch0106: 0106-Added-github-action-for-building.patch +Patch0107: 0107-github-workflow-use-zram-device-as-test-block-device.patch +Patch0108: 0108-github-workflow-use-explicit-Ubuntu-version.patch +Patch0109: 0109-github-workflow-add-valgrind-tests.patch +Patch0110: 0110-github-workflow-run-apt-get-update.patch +Patch0111: 0111-github-workflow-add-tests-with-gcc-10-and-clang.patch +Patch0112: 0112-multipathd-Fix-multipathd-stopping-on-shutdown.patch +Patch0113: 0113-libmultipath-use-3rd-digit-as-transport_id-for-expan.patch +Patch0114: 0114-libmultipath-sysfs_set_nexus_loss_tmo-support-SAS-ex.patch +Patch0115: 0115-multipathd-add-code-to-initalize-unwinder.patch +Patch0116: 0116-libmultipath-check-if-adopt_path-really-added-curren.patch +Patch0117: 0117-multipathd-ev_add_path-fail-if-add_map_with_path-fai.patch +Patch0118: 0118-libmultipath-check-return-value-of-udev_device_get_d.patch +Patch0119: 0119-pathinfo-call-filter_property-after-sysfs_pathinfo.patch +Patch0120: 0120-libmultipath-pathinfo-call-filter_property-only-with.patch +Patch0121: 0121-multipath-w-allow-removing-blacklisted-paths.patch +Patch0122: 0122-libmultipath-fix-use-after-free-in-uev_add_path.patch +Patch0123: 0123-kpartx-free-loop-device-after-listing-partitions.patch +Patch0124: 0124-RH-fixup-udev-rules-for-redhat.patch +Patch0125: 0125-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0126: 0126-RH-don-t-start-without-a-config-file.patch +Patch0127: 0127-RH-Fix-nvme-function-missing-argument.patch +Patch0128: 0128-RH-use-rpm-optflags-if-present.patch +Patch0129: 0129-RH-add-mpathconf.patch +Patch0130: 0130-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0131: 0131-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0132: 0132-RH-attempt-to-get-ANA-info-via-sysfs-first.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -318,6 +339,15 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog +* Thu Feb 11 2021 Benjamin Marzinski - 0.8.5-4 +- Update Source to upstream version 0.8.5 plus post tag commits + * Patches 0001-0121 are from + https://github.com/openSUSE/multipath-tools/tree/queue and are + already queued for upstream + * Patches 0122&0123 have been posted for upstream inclusion +- Rename files + * Previous patches 0103-0111 are now patches 0124-0132 + * Tue Jan 26 2021 Fedora Release Engineering - 0.8.5-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild