* [PATCH v2 00/49] multipath-tools: devmapper API refactored
@ 2024-07-12 17:14 Martin Wilck
2024-07-12 17:14 ` [PATCH v2 01/49] multipath-tools CI: more fixes for arm/v7 Martin Wilck
` (48 more replies)
0 siblings, 49 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Patch 1-9 are generic cleanups, partly targeting the previously reported
issues with multipath-tools installation on NixOS by removing hard-coded
paths as much as possible.
Patch 10-18 are basic cleanups for the devmapper code.
Patch 19 is the heart of this patch set, introducing the function
libmp_mapinfo(), which is supposed to serve as general API for fetching
information about maps from libdevmapper. It can work with arbitrary
input for identifying a map, and produce any combination of desired
outputs, with the most lightweight (combination of) ioctls possible.
This part of the set removes some code that had been changed
in patch 10-16. This is sort of suboptimal, but IMO it improves
the readability of the set as a whole.
Patch 20 adds unit tests for this function.
Patch 21-45 change the libmultipath code to use the new API everywhere,
and add some additional minor improvements and fixes.
Patch 46-49 have been added in v2.
* 46: fix a long-standing bug I accidentally discovered during testing
* 47: simplify and fix the logic for determining whether a map is in use
* 48: implement Ben's idea from the comment of #31 in the old series.
* 49: unrelated, fixes for the directio test
The code is pushed to https://github.com/openSUSE/multipath-tools/tree/tip.
Comments and reviews welcome.
I'm posting the entire series, because some of those patches that Ben had
already reviewed are changed.
# Changes v1->v2:
* 1: add fix for libaio
* 6: make sure kpartx.rules is built (Ben)
* 16: split this large patch between the changes that are just related
to cleanup_dm_task(), and the other code modifications
* 17: new, used to be part of #16
* 18: new, used to be part of #17. Changed the treatment of DMP_ERR /
DM_IS_MPATH_ERR (Ben)
(From here on, patch number n maps to (n-2) in the v1 set).
* 19 (was 17):
- Allow passing a dev_t in mapid_t (Ben).
- Remove the tgt_type field in mapinfo_t. Instead, introduce
flags MAPINFO_MPATH_ONLY and MAPINFO_PART_ONLY to make
libmp_mapinfo__() filter either multipath or partition devices,
inspired by Ben's comment on patch #31 of the v1 series.
See also #48.
These changes require changes in users of the API in patch 30ff.
I have not removed the Reviewed-by: tags in the followup patches.
* 20 (18): Adapt tests to #19.
* 25 (23):
- dm_get_wwid() won't touch the output unless it returns DMP_OK
- adjusted callers to make sure the uuid is not accessed unless
DMP_OK was returned
- distinguish between "multipath map is present" and "other map
is present" in domap() (Ben)
- Change handling of DMP_ERR in alias_already_taken() (Ben)
* 28 (26): Fixed bug in the return code handling in dm_dev_t()
* 30 (28):
- Change return code handling in dm_type_match(), to distinguish
between "not multipath" and "generic error" (Ben)
- adapt to #19
* 31 (29): adapt to #19
* 32 (30): adapt to #19
* 33 (31): adapt to #18. is_mpath_uuid() will be unexported in #48
* 36 (34):
- don't check the UUID in do_foreach_partmaps(). This would break
the partmap_in_use detection (but see #47 below).
- adapt to #19
* 37 (35): fetch mpp->size (Ben). Print a warning if the size has changed.
* 41 (39):
- fetch mpp->size (Ben).
- adapt to #19
* 42 (40): - remove redundant sync_map_state() call (Ben)
- fetch mpp->size (Ben)
- check return code of dm_get_wwid()
- fix segfault caused by passing NULL to update_map()
* n/a (42): dropped (Ben)
(From here on, n maps to (n - 1) in the v1 set).
* 44 (43): adapt to #19
Patch 46-49 are new.
Martin Wilck (49):
multipath-tools CI: more fixes for arm/v7
multipath-tools CI: fix dmevents test for Debian Sid, arm/v7
create-config.mk: use printf instead of /bin/echo
multipathd.service.in: use @BINDIR@ instead of /sbin
Makefile.inc: replace @BINDIR@ with $(TGTDIR)/$(bindir)
kpartx.rules: use @BINDIR@ to locate kpartx
multipath-tools: Remove hard-coded paths to executables
multipath-tools: compile_commands.json fixes
multipath-tools: .gitignore: ignore o.wrap files for CI helpers
libmultipath: remove unused includes in devmapper.h
libmultipath: use DM_DEVICE_INFO in dm_mapname()
multipath-tools: don't call dm_task_no_open_count()
libmpathutil: export cleanup_udev_device()
libmpathutil: add cleanup_vector()
libmultipath: add cleanup helpers for struct multipath
libmultipath: add cleanup_dm_task(), and use it in devmapper.c
libmultipath: rename dm_type()->dm_type_match() and use symbolic
values
libmultipath: Use symbolic return values for dm_is_mpath()
libmultipath: add libmp_mapinfo()
libmultipath tests: add tests for libmp_mapinfo()
libmultipath: implement dm_get_info() and dm_map_present() with new
API
libmultipath: remove dm_get_prefixed_uuid()
libmultipath: is_mpath_part(): improve parsing
libmultipath: rename dm_get_uuid() -> dm_get_wwid()
libmultipath: improve dm_get_wwid() return value logic
libmultipath: reimplement dm_map_name() with new API
libmultipath: reimplement dm_map_present_by_uuid()
libmultipath: reimplement dm_get_opencount() with new API
libmpathpersist: skip redundant dm_map_present() call
libmultipath: implement dm_is_mpath() with new API
libmultipath: implement dm_get_multipath() with new API
libmultipath: use libmp_mapinfo() in _dm_flush_map()
libmultipath: add is_mpath_uuid() helper
libmultipath: add is_mpath_part_uuid() helper
libmultipath: add dmp_errstr() helper
libmultipath: use libmp_mapinfo() in do_foreach_partmaps()
libmultipath: use libmp_pathinfo() in update_multipath_table()
libmultipath: update mpp->dmi in update_multipath_table()
libmultipath: drop extra call to dm_map_present() in domap()
libmultipath: split off update_multipath_table__()
multipath: implement check_usable_paths() with libmp_pathinfo()
multipathd: implement add_map_without_path() with libmp_mapinfo()
libmultipath: simplify dm_get_maps()
libmpathpersist: use libmp_mapinfo() in mpath_get_map()
libmpathpersist: use mpp->alias in do_mpath_persistent_reserve_out()
libmultipath: fix deferred_remove logic in remove_partmap()
libmultipath: don't call do_foreach_partmaps() recursively
libmultipath: Move UUID check into libmp_pathinfo__()
multipath-tools tests: fix directio test with real device
.gitignore | 4 +
Makefile | 4 +-
Makefile.inc | 29 +-
create-config.mk | 4 +-
kpartx/Makefile | 6 +-
kpartx/devmapper.c | 15 -
kpartx/{kpartx.rules => kpartx.rules.in} | 2 +-
kpartx/kpartx_id | 8 +-
libmpathpersist/mpath_persist_int.c | 81 +-
libmpathutil/libmpathutil.version | 5 +
libmpathutil/util.c | 6 +
libmpathutil/util.h | 3 +
libmpathutil/vector.c | 6 +
libmpathutil/vector.h | 1 +
libmultipath/alias.c | 11 +-
libmultipath/configure.c | 31 +-
libmultipath/devmapper.c | 1052 +++++++---------
libmultipath/devmapper.h | 109 +-
libmultipath/libmultipath.version | 11 +-
libmultipath/print.c | 6 -
libmultipath/structs.c | 12 +
libmultipath/structs.h | 2 +
libmultipath/structs_vec.c | 52 +-
libmultipath/structs_vec.h | 2 +
libmultipath/valid.c | 2 +-
libmultipath/wwids.c | 2 +-
multipath/11-dm-mpath.rules.in | 4 +-
multipath/main.c | 57 +-
multipath/multipath.rules.in | 6 +-
multipathd/dmevents.c | 21 +-
multipathd/main.c | 77 +-
multipathd/multipathd.service.in | 4 +-
multipathd/waiter.c | 2 -
tests/Makefile | 13 +-
tests/README.md | 29 +-
tests/alias.c | 32 +-
tests/directio.c | 182 +--
tests/dmevents.c | 34 +-
tests/mapinfo.c | 1401 ++++++++++++++++++++++
tests/valid.c | 10 +-
tests/wrap64.h | 11 +-
41 files changed, 2370 insertions(+), 979 deletions(-)
rename kpartx/{kpartx.rules => kpartx.rules.in} (96%)
create mode 100644 tests/mapinfo.c
--
2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH v2 01/49] multipath-tools CI: more fixes for arm/v7
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 02/49] multipath-tools CI: fix dmevents test for Debian Sid, arm/v7 Martin Wilck
` (47 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The previous fix for the CI under arm/v7 was incomplete, and actually broke
the tests under openSUSE Tumbleweed. Closer examination showed that the issues
were caused by Debian's move to 64bit time_t on some 32 bit architectures [1][2].
This effort causes _TIME_BITS=64 to be set by gcc internally, and introduces
symbol redirections for libaio [3], on Debian with gcc 13 and newer only.
Fix the conditions for symbol remappings in wrap64.h.
[1] https://wiki.debian.org/ReleaseGoals/64bit-time
[2] https://salsa.debian.org/toolchain-team/gcc/-/commit/d82fb8a8ab7b84f61fb8290a2c3aa2e3f54e7b8a
[3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1062218
Fixes: 6a7524a ("multipath-tools tests: fix CI failures on arm/v7 with glibc 2.37")
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/wrap64.h | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/tests/wrap64.h b/tests/wrap64.h
index 7e43420..af6cc2b 100644
--- a/tests/wrap64.h
+++ b/tests/wrap64.h
@@ -2,6 +2,8 @@
#define _WRAP64_H 1
#include <syscall.h>
#include <linux/types.h>
+/* The following include is required for LIBAIO_REDIRECT */
+#include <libaio.h>
#include "util.h"
/*
@@ -47,7 +49,8 @@
* fcntl() needs special treatment; fcntl64() has been introduced in 2.28.
* https://savannah.gnu.org/forum/forum.php?forum_id=9205
*/
-#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 37) && defined(__arm__) && __ARM_ARCH == 7
+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 34) && __BITS_PER_LONG == 32 \
+ && defined(_TIME_BITS) && _TIME_BITS == 64
#define WRAP_FCNTL_NAME __fcntl_time64
#elif defined(__GLIBC__) && __GLIBC_PREREQ(2, 28)
#define WRAP_FCNTL_NAME WRAP_NAME(fcntl)
@@ -60,7 +63,8 @@
/*
* glibc 2.37 uses __ioctl_time64 for ioctl
*/
-#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 37) && defined(__arm__) && __ARM_ARCH == 7
+#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 34) && __BITS_PER_LONG == 32 \
+ && defined(_TIME_BITS) && _TIME_BITS == 64
#define WRAP_IOCTL_NAME __ioctl_time64
#else
#define WRAP_IOCTL_NAME ioctl
@@ -68,7 +72,8 @@
#define WRAP_IOCTL CONCAT2(__wrap_, WRAP_IOCTL_NAME)
#define REAL_IOCTL CONCAT2(__real_, WRAP_IOCTL_NAME)
-#if defined(__NR_io_pgetevents) && __BITS_PER_LONG == 32 && defined(_TIME_BITS) && _TIME_BITS == 64
+#if defined(__GLIBC__) && defined(LIBAIO_REDIRECT) && __BITS_PER_LONG == 32 \
+ && defined(_TIME_BITS) && _TIME_BITS == 64
#define WRAP_IO_GETEVENTS_NAME io_getevents_time64
#else
#define WRAP_IO_GETEVENTS_NAME io_getevents
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 02/49] multipath-tools CI: fix dmevents test for Debian Sid, arm/v7
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
2024-07-12 17:14 ` [PATCH v2 01/49] multipath-tools CI: more fixes for arm/v7 Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 03/49] create-config.mk: use printf instead of /bin/echo Martin Wilck
` (46 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Same fix as in 6a7524a ("multipath-tools tests: fix CI failures on arm/v7 with
glibc 2.37").
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
tests/dmevents.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/tests/dmevents.c b/tests/dmevents.c
index 395b16d..668e6d2 100644
--- a/tests/dmevents.c
+++ b/tests/dmevents.c
@@ -253,8 +253,9 @@ int __wrap_dm_geteventnr(const char *name)
return -1;
}
-int __wrap_ioctl(int fd, unsigned long request, void *argp)
+int WRAP_IOCTL(int fd, unsigned long request, void *argp)
{
+ condlog(1, "%s %ld", __func__, request);
assert_int_equal(fd, waiter->fd);
assert_int_equal(request, DM_DEV_ARM_POLL);
return mock_type(int);
@@ -675,7 +676,7 @@ static void test_dmevent_loop_bad1(void **state)
skip();
will_return(__wrap_poll, 1);
- will_return(__wrap_ioctl, -1);
+ wrap_will_return(WRAP_IOCTL, -1);
assert_int_equal(dmevent_loop(), 1);
dev_evt = find_dmevents("foo");
assert_ptr_not_equal(dev_evt, NULL);
@@ -697,7 +698,7 @@ static void test_dmevent_loop_bad2(void **state)
skip();
will_return(__wrap_poll, 1);
- will_return(__wrap_ioctl, 0);
+ wrap_will_return(WRAP_IOCTL, 0);
will_return(__wrap_libmp_dm_task_create, NULL);
assert_int_equal(dmevent_loop(), 1);
dev_evt = find_dmevents("foo");
@@ -721,9 +722,8 @@ static void test_dmevent_loop_good0(void **state)
remove_all_dm_device_events();
unwatch_all_dmevents();
will_return(__wrap_poll, 1);
- will_return(__wrap_ioctl, 0);
+ wrap_will_return(WRAP_IOCTL, 0);
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 1);
assert_int_equal(dmevent_loop(), 1);
@@ -757,9 +757,8 @@ static void test_dmevent_loop_good1(void **state)
assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
assert_int_equal(remove_dm_device_event("xyzzy"), 0);
will_return(__wrap_poll, 1);
- will_return(__wrap_ioctl, 0);
+ wrap_will_return(WRAP_IOCTL, 0);
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 1);
expect_string(__wrap_update_multipath, mapname, "foo");
@@ -805,9 +804,8 @@ static void test_dmevent_loop_good2(void **state)
assert_int_equal(watch_dmevents("baz"), 0);
assert_int_equal(add_dm_device_event("baz", 1, 14), 0);
will_return(__wrap_poll, 1);
- will_return(__wrap_ioctl, 0);
+ wrap_will_return(WRAP_IOCTL, 0);
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 1);
expect_string(__wrap_update_multipath, mapname, "bar");
@@ -849,9 +847,8 @@ static void test_dmevent_loop_good3(void **state)
assert_int_equal(remove_dm_device_event("foo"), 0);
unwatch_dmevents("bar");
will_return(__wrap_poll, 1);
- will_return(__wrap_ioctl, 0);
+ wrap_will_return(WRAP_IOCTL, 0);
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 1);
expect_string(__wrap_remove_map_by_alias, alias, "foo");
@@ -874,7 +871,7 @@ static void test_arm_poll(void **state)
struct test_data *datap = (struct test_data *)(*state);
if (datap == NULL)
skip();
- will_return(__wrap_ioctl, 0);
+ wrap_will_return(WRAP_IOCTL, 0);
assert_int_equal(arm_dm_event_poll(waiter->fd), 0);
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 03/49] create-config.mk: use printf instead of /bin/echo
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
2024-07-12 17:14 ` [PATCH v2 01/49] multipath-tools CI: more fixes for arm/v7 Martin Wilck
2024-07-12 17:14 ` [PATCH v2 02/49] multipath-tools CI: fix dmevents test for Debian Sid, arm/v7 Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 04/49] multipathd.service.in: use @BINDIR@ instead of /sbin Martin Wilck
` (45 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The behavior of "echo -e" is not part of the POSIY standard and
different shells handle it differently. OTOH, /bin/echo isn't necessarily
available, either. Use printf instead, which is part of POSIX.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
create-config.mk | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/create-config.mk b/create-config.mk
index 4d318b9..0abbb3a 100644
--- a/create-config.mk
+++ b/create-config.mk
@@ -147,11 +147,11 @@ TEST_CC_OPTION = $(shell \
# On some distros (e.g. Debian Buster) it will be falsely reported as supported
# but it doesn't seem to make a difference wrt the compilation result.
FORTIFY_OPT := $(shell \
- if /bin/echo -e '$(__HASH__)include <string.h>\nint main(void) { return 0; }' | \
+ if printf '$(__HASH__)include <string.h>\nint main(void) { return 0; }\n' | \
$(CC) -o /dev/null $(OPTFLAGS) -c -Werror -D_FORTIFY_SOURCE=3 -xc - 2>/dev/null; \
then \
echo "-D_FORTIFY_SOURCE=3"; \
- elif /bin/echo -e '$(__HASH__)include <string.h>\nint main(void) { return 0; }' | \
+ elif printf '$(__HASH__)include <string.h>\nint main(void) { return 0; }\n' | \
$(CC) -o /dev/null $(OPTFLAGS) -c -Werror -D_FORTIFY_SOURCE=2 -xc - 2>/dev/null; \
then \
echo "-D_FORTIFY_SOURCE=2"; \
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 04/49] multipathd.service.in: use @BINDIR@ instead of /sbin
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (2 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 03/49] create-config.mk: use printf instead of /bin/echo Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 05/49] Makefile.inc: replace @BINDIR@ with $(TGTDIR)/$(bindir) Martin Wilck
` (44 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The path in the unit file should match the actual installation path.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/multipathd.service.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
index a63ddd9..646001e 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -16,8 +16,8 @@ ConditionVirtualization=!container
[Service]
Type=notify
NotifyAccess=main
-ExecStart=/sbin/multipathd -d -s
-ExecReload=/sbin/multipathd reconfigure
+ExecStart=@BINDIR@/multipathd -d -s
+ExecReload=@BINDIR@/multipathd reconfigure
TasksMax=infinity
LimitRTPRIO=10
CPUWeight=1000
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 05/49] Makefile.inc: replace @BINDIR@ with $(TGTDIR)/$(bindir)
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (3 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 04/49] multipathd.service.in: use @BINDIR@ instead of /sbin Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 06/49] kpartx.rules: use @BINDIR@ to locate kpartx Martin Wilck
` (43 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The unit files and udev rules that use @BINDIR@ for substitutions
have the installation target's point of view, they must include
$(TGTDIR) (which is empty by default).
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index ed4a423..28b6032 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -150,4 +150,4 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version)
%: %.in
@echo creating $@
- $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(bindir)':g' $< >$@
+ $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(TGTDIR)$(bindir)':g' $< >$@
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 06/49] kpartx.rules: use @BINDIR@ to locate kpartx
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (4 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 05/49] Makefile.inc: replace @BINDIR@ with $(TGTDIR)/$(bindir) Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:08 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 07/49] multipath-tools: Remove hard-coded paths to executables Martin Wilck
` (42 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The path for kpartx should match the installed binary.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
.gitignore | 1 +
kpartx/Makefile | 6 +++---
kpartx/{kpartx.rules => kpartx.rules.in} | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
rename kpartx/{kpartx.rules => kpartx.rules.in} (96%)
diff --git a/.gitignore b/.gitignore
index 049ffe8..355ddbb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ config.mk
cscope.files
cscope.out
kpartx/kpartx
+kpartx/kpartx.rules
multipath/multipath
multipath/multipath.8
multipath/multipath.conf.5
diff --git a/kpartx/Makefile b/kpartx/Makefile
index 7720a74..849fd36 100644
--- a/kpartx/Makefile
+++ b/kpartx/Makefile
@@ -13,13 +13,13 @@ LIBDEPS += -ldevmapper
OBJS := bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \
gpt.o mac.o ps3.o crc32.o lopart.o xstrncpy.o devmapper.o
-all: $(EXEC)
+all: $(EXEC) kpartx.rules
$(EXEC): $(OBJS)
@echo building $@ because of $?
$(Q)$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
-install: $(EXEC) $(EXEC).8
+install: $(EXEC) $(EXEC).8 kpartx.rules
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir)
@@ -41,7 +41,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/68-del-part-nodes.rules
clean: dep_clean
- $(Q)$(RM) core *.o $(EXEC)
+ $(Q)$(RM) core *.o $(EXEC) kpartx.rules
include $(wildcard $(OBJS:.o=.d))
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules.in
similarity index 96%
rename from kpartx/kpartx.rules
rename to kpartx/kpartx.rules.in
index 8dd3369..9d87960 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules.in
@@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
+RUN+="@BINDIR@/kpartx -un -p -part /dev/$name"
LABEL="kpartx_end"
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 07/49] multipath-tools: Remove hard-coded paths to executables
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (5 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 06/49] kpartx.rules: use @BINDIR@ to locate kpartx Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 08/49] multipath-tools: compile_commands.json fixes Martin Wilck
` (41 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 17 ++++++++++++++---
kpartx/kpartx_id | 8 ++++----
multipath/11-dm-mpath.rules.in | 4 ++--
multipath/multipath.rules.in | 6 +++---
4 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 28b6032..fe9f1bf 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -42,9 +42,11 @@ etc_prefix := $(prefix)
# Where to install systemd-related files. systemd is usually installed under /usr
# Note: systemd installations with "split-usr=true" use separate "prefixdir" and
# "rootprefixdir". Our systemd_prefix corresponds to "prefixdir".
-# In this case, override only unitdir and libudevdir below to use
-# systemd's "rootprefixdir" instead of $(systemd_prefix)
+# In this case, override only unitdir, libudevdir and sys_execprefix below
+# to use systemd's "rootprefixdir" instead of $(systemd_prefix)
systemd_prefix := /usr
+# Prefix for binaries that are owned by other packages (including systemd)
+sys_execprefix := /usr
# Make sure all prefix variables end in "/"
append-slash = $(1)$(if $(filter %/,$(1)),,/)
@@ -53,6 +55,7 @@ override exec_prefix := $(call append-slash,$(exec_prefix))
override usr_prefix := $(call append-slash,$(usr_prefix))
override etc_prefix := $(call append-slash,$(etc_prefix))
override systemd_prefix := $(call append-slash,$(systemd_prefix))
+override sys_execprefix := $(call append-slash,$(sys_execprefix))
unitdir := $(systemd_prefix)lib/systemd/system
tmpfilesdir := $(systemd_prefix)lib/tmpfiles.d
@@ -74,6 +77,7 @@ runtimedir := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/ru
devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include)
libudev_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include)
kernel_incdir := /usr/include
+sysdir_bin := $(sys_execprefix)bin
ifeq ($(V),)
Q := @
@@ -150,4 +154,11 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version)
%: %.in
@echo creating $@
- $(Q)sed 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g;s:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g;s:@STATE_DIR@:'$(TGTDIR)$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g;s/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g;s:@BINDIR@:'$(TGTDIR)$(bindir)':g' $< >$@
+ $(Q)sed -e 's:@CONFIGFILE@:'$(TGTDIR)$(configfile)':g' \
+ -e 's:@CONFIGDIR@:'$(TGTDIR)$(configdir)':g' \
+ -e 's:@STATE_DIR@:'$(TGTDIR)$(statedir)':g' \
+ -e 's:@BINDIR@:'$(TGTDIR)$(bindir)':g' \
+ -e 's:@SYSDIR_BIN@:'$(sysdir_bin)': g' \
+ -e 's:@RUNTIME_DIR@:'$(runtimedir)':g' \
+ -e 's/@MODPROBE_UNIT@/'$(MODPROBE_UNIT)'/g' \
+ $< >$@
diff --git a/kpartx/kpartx_id b/kpartx/kpartx_id
index 4672927..f9211d2 100755
--- a/kpartx/kpartx_id
+++ b/kpartx/kpartx_id
@@ -21,8 +21,6 @@
# sent upstream but has not been accepted yet.
#
-DMSETUP=/sbin/dmsetup
-
MAJOR=$1
MINOR=$2
UUID=$3
@@ -32,12 +30,14 @@ if [ -z "$MAJOR" -o -z "$MINOR" ]; then
exit 1;
fi
+DMSETUP=$(command -v dmsetup) || DMSETUP=/sbin/dmsetup
+
# Device-mapper not installed; not an error
-if [ ! -x $DMSETUP ] ; then
+if [ ! -x "$DMSETUP" ] ; then
+ echo "$0: dmsetup not found" >&2
exit 0
fi
-
# Table UUIDs are always '<type>-<uuid>'.
dmuuid=${UUID#*-}
dmtbl=${UUID%%-*}
diff --git a/multipath/11-dm-mpath.rules.in b/multipath/11-dm-mpath.rules.in
index 0562edd..30647b9 100644
--- a/multipath/11-dm-mpath.rules.in
+++ b/multipath/11-dm-mpath.rules.in
@@ -9,7 +9,7 @@ ENV{.DM_SUSPENDED}!="?*", ENV{.DM_SUSPENDED}="$env{DM_SUSPENDED}"
# Coldplug event while device is suspended (e.g. during a reload)
ACTION=="add", ENV{DM_ACTIVATION}=="1", ENV{.DM_SUSPENDED}=="1", \
- PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.warning \"Coldplug event for suspended device\"", \
+ PROGRAM="@SYSDIR_BIN@/logger -t 11-dm-mpath.rules -p daemon.warning \"Coldplug event for suspended device\"", \
ENV{DM_COLDPLUG_SUSPENDED}="1", GOTO="scan_import"
# Coldplug event. Import previously set properties.
@@ -70,7 +70,7 @@ LABEL="check_mpath_unchanged"
IMPORT{db}="DM_COLDPLUG_SUSPENDED"
ENV{DM_COLDPLUG_SUSPENDED}=="1", ENV{.DM_SUSPENDED}!="1", \
ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0", \
- PROGRAM="/bin/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \
+ PROGRAM="@SYSDIR_BIN@/logger -t 11-dm-mpath.rules -p daemon.notice \"Forcing activation of previously suspended device\"", \
GOTO="check_mpath_ready"
# DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem.
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 780bf85..2ac1972 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -2,7 +2,7 @@
SUBSYSTEM!="block", GOTO="end_mpath"
KERNEL!="sd*|dasd*|nvme*", GOTO="end_mpath"
ACTION=="remove", TEST=="@RUNTIME_DIR@/multipath/find_multipaths/$major:$minor", \
- RUN+="/usr/bin/rm -f @RUNTIME_DIR@/multipath/find_multipaths/$major:$minor"
+ RUN+="@SYSDIR_BIN@/rm -f @RUNTIME_DIR@/multipath/find_multipaths/$major:$minor"
ACTION!="add|change", GOTO="end_mpath"
IMPORT{cmdline}="nompath"
@@ -69,7 +69,7 @@ ENV{.SAVED_FM_WAIT_UNTIL}=="?*", GOTO="pretend_mpath"
#
# We must trigger an "add" event because LVM2 will only act on those.
-RUN+="/usr/bin/systemd-run --unit=cancel-multipath-wait-$kernel --description 'cancel waiting for multipath siblings of $kernel' --no-block --timer-property DefaultDependencies=no --timer-property Conflicts=shutdown.target --timer-property Before=shutdown.target --timer-property Conflicts=initrd-cleanup.service --timer-property Before=initrd-cleanup.service --timer-property AccuracySec=500ms --property DefaultDependencies=no --property Conflicts=shutdown.target --property Before=shutdown.target --property Conflicts=initrd-cleanup.service --property Before=initrd-cleanup.service --on-active=$env{FIND_MULTIPATHS_WAIT_UNTIL} /usr/bin/udevadm trigger --action=add $sys$devpath"
+RUN+="@SYSDIR_BIN@/systemd-run --unit=cancel-multipath-wait-$kernel --description 'cancel waiting for multipath siblings of $kernel' --no-block --timer-property DefaultDependencies=no --timer-property Conflicts=shutdown.target --timer-property Before=shutdown.target --timer-property Conflicts=initrd-cleanup.service --timer-property Before=initrd-cleanup.service --timer-property AccuracySec=500ms --property DefaultDependencies=no --property Conflicts=shutdown.target --property Before=shutdown.target --property Conflicts=initrd-cleanup.service --property Before=initrd-cleanup.service --on-active=$env{FIND_MULTIPATHS_WAIT_UNTIL} @SYSDIR_BIN@/udevadm trigger --action=add $sys$devpath"
LABEL="pretend_mpath"
ENV{DM_MULTIPATH_DEVICE_PATH}="1"
@@ -85,7 +85,7 @@ ENV{FIND_MULTIPATHS_WAIT_UNTIL}!="?*", GOTO="end_mpath"
ENV{FIND_MULTIPATHS_WAIT_UNTIL}=="0", GOTO="end_mpath"
ENV{FIND_MULTIPATHS_WAIT_CANCELLED}="1"
-RUN+="/usr/bin/systemctl stop cancel-multipath-wait-$kernel.timer"
+RUN+="@SYSDIR_BIN@/systemctl stop cancel-multipath-wait-$kernel.timer"
# If "multipath -u" failed, no values are imported from the program,
# and we are still using the values for DM_MULTIPATH_DEVICE_PATH and
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 08/49] multipath-tools: compile_commands.json fixes
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (6 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 07/49] multipath-tools: Remove hard-coded paths to executables Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 09/49] multipath-tools: .gitignore: ignore o.wrap files for CI helpers Martin Wilck
` (40 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
compile_commands.json serves as input for clangd, while working with
lsp under emacs. It's normal for functions and parameters to be unused while
writing code. Therefore suppress -Werror for this use case. clangd will
display the warnings.
Use "make testprogs" to generate compile_commands.json, in order to be
able to use clangd for the CI code, too.
Finally, don't remove compile_commands.json with "make clean". Normally the
compile commands remain the same, even if a clean rebuild of the binaries
is necessary. Put the file into .gitignore instead.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.gitignore | 1 +
Makefile | 4 ++--
Makefile.inc | 12 +++++++++---
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/.gitignore b/.gitignore
index 355ddbb..efdbd8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@
*.gz
*.d
\#*
+compile_commands.json
config.mk
cscope.files
cscope.out
diff --git a/Makefile b/Makefile
index 4df5f16..14bbac2 100644
--- a/Makefile
+++ b/Makefile
@@ -83,7 +83,7 @@ abi-test: abi reference-abi $(wildcard abi/*.abi)
# Requires bear (https://github.com/rizsotto/Bear)
compile_commands.json: Makefile Makefile.inc $(BUILDDIRS:=/Makefile)
$(Q)$(MAKE) clean
- $(Q)bear -- $(MAKE)
+ $(Q)bear -- $(MAKE) WARN_ONLY=1 test-progs || rm $@
libmpathutil libdmmp: libmpathcmd
libmultipath: libmpathutil
@@ -109,7 +109,7 @@ $(BUILDDIRS:=.uninstall):
clean:
@touch config.mk
$(Q)$(MAKE) $(BUILDDIRS:=.clean) tests.clean || true
- $(Q)$(RM) -r abi abi.tar.gz abi-test compile_commands.json config.mk
+ $(Q)$(RM) -r abi abi.tar.gz abi-test config.mk
install: $(BUILDDIRS:=.install)
uninstall: $(BUILDDIRS:=.uninstall)
diff --git a/Makefile.inc b/Makefile.inc
index fe9f1bf..729618b 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -100,9 +100,15 @@ MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \
echo "modprobe@dm_multipath.service")
OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
-WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
- -Werror=implicit-function-declaration -Werror=format-security \
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
+
+# Set WARN_ONLY=1 to avoid compilation erroring out due to warnings. Useful during development.
+WARN_ONLY :=
+ERROR := $(if $(WARN_ONLY),,error=)
+WERROR := $(if $(WARN_ONLY),,-Werror)
+WARNFLAGS := $(WERROR) -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \
+ -W$(ERROR)implicit-function-declaration -W$(ERROR)format-security \
+ $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
+
CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
-D_FILE_OFFSET_BITS=64 \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 09/49] multipath-tools: .gitignore: ignore o.wrap files for CI helpers
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (7 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 08/49] multipath-tools: compile_commands.json fixes Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 10/49] libmultipath: remove unused includes in devmapper.h Martin Wilck
` (39 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Unlike the .o.wrap files for the CI tests themselves, these are
not automatically deleted by "make" as intermediate files. Ignore them.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.gitignore | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.gitignore b/.gitignore
index efdbd8a..4548cfb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,8 @@ libdmmp/test/libdmmp_speed_test
tests/*-test
tests/*.out
tests/*.vgr
+tests/test-lib.o.wrap
+tests/test-log.o.wrap
libmultipath/nvme-ioctl.c
libmultipath/nvme-ioctl.h
libmultipath/autoconfig.h
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 10/49] libmultipath: remove unused includes in devmapper.h
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (8 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 09/49] multipath-tools: .gitignore: ignore o.wrap files for CI helpers Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 11/49] libmultipath: use DM_DEVICE_INFO in dm_mapname() Martin Wilck
` (38 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 08bb3c5..3ee8555 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -17,13 +17,11 @@
#include <linux/dm-ioctl.h>
#include "util.h"
-#include "checkers.h"
#include "vector.h"
#include "structs.h"
#include "debug.h"
#include "devmapper.h"
#include "sysfs.h"
-#include "config.h"
#include "wwids.h"
#include "version.h"
#include "time-util.h"
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 11/49] libmultipath: use DM_DEVICE_INFO in dm_mapname()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (9 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 10/49] libmultipath: remove unused includes in devmapper.h Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 12/49] multipath-tools: don't call dm_task_no_open_count() Martin Wilck
` (37 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
DM_DEVICE_INFO aka the kernel's DM_DEV_STATUS ioctl, is sufficient to
fetch the map name, and more lightweight than DM_DEVICE_STATUS, which maps to
the kernel's DM_TABLE_STATUS ioctl.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 3ee8555..baa1ead 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1412,7 +1412,7 @@ dm_mapname(int major, int minor)
struct dm_task *dmt;
int r;
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
+ if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
return NULL;
if (!dm_task_set_major(dmt, major) ||
@@ -1422,7 +1422,7 @@ dm_mapname(int major, int minor)
dm_task_no_open_count(dmt);
r = libmp_dm_task_run(dmt);
if (!r) {
- dm_log_error(2, DM_DEVICE_STATUS, dmt);
+ dm_log_error(2, DM_DEVICE_INFO, dmt);
goto bad;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 12/49] multipath-tools: don't call dm_task_no_open_count()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (10 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 11/49] libmultipath: use DM_DEVICE_INFO in dm_mapname() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 13/49] libmpathutil: export cleanup_udev_device() Martin Wilck
` (36 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
dm_task_no_open_count() only sets DM_SKIP_BDGET_FLAG in the dm task,
which has been ignored by the kernel since 5c6bd75d06db ("[PATCH] dm: prevent
removal if open") (v2.6.18 / 2006). Even for older kernels, not setting
this flag has only a minor, performance-related effect (skipping one call
to bdget_disk()). Don't use this dead API any more.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
kpartx/devmapper.c | 15 ---------------
libmultipath/devmapper.c | 36 ------------------------------------
multipathd/dmevents.c | 2 --
multipathd/waiter.c | 2 --
tests/dmevents.c | 13 -------------
5 files changed, 68 deletions(-)
diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c
index f12762c..bf07838 100644
--- a/kpartx/devmapper.c
+++ b/kpartx/devmapper.c
@@ -35,8 +35,6 @@ int dm_prereq(char * str, uint32_t x, uint32_t y, uint32_t z)
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return 1;
- dm_task_no_open_count(dmt);
-
if (!dm_task_run(dmt))
goto out;
@@ -78,7 +76,6 @@ int dm_simplecmd(int task, const char *name, int no_flush, __DM_API_COOKIE_UNUSE
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
dm_task_skip_lockfs(dmt);
if (no_flush)
@@ -175,8 +172,6 @@ int dm_addmap(int task, const char *name, const char *target,
if (!dm_task_set_gid(dmt, gid))
goto addout;
- dm_task_no_open_count(dmt);
-
#ifdef LIBDM_API_COOKIE
if (!udev_sync)
udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
@@ -212,8 +207,6 @@ static int dm_map_present(char *str, char **uuid)
if (!dm_task_set_name(dmt, str))
goto out;
- dm_task_no_open_count(dmt);
-
if (!dm_task_run(dmt))
goto out;
@@ -247,7 +240,6 @@ static int dm_rename (const char *old, const char *new)
if (!dm_task_set_name(dmt, old) ||
!dm_task_set_newname(dmt, new) ||
- !dm_task_no_open_count(dmt) ||
!dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
@@ -291,7 +283,6 @@ dm_mapname(int major, int minor)
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
return NULL;
- dm_task_no_open_count(dmt);
dm_task_set_major(dmt, major);
dm_task_set_minor(dmt, minor);
@@ -352,7 +343,6 @@ dm_mapuuid(const char *mapname)
if (!dm_task_set_name(dmt, mapname))
goto out;
- dm_task_no_open_count(dmt);
if (!dm_task_run(dmt))
goto out;
@@ -407,7 +397,6 @@ dm_get_map(const char *mapname, char * outparams)
if (!dm_task_set_name(dmt, mapname))
goto out;
- dm_task_no_open_count(dmt);
if (!dm_task_run(dmt))
goto out;
@@ -474,8 +463,6 @@ dm_type(const char * name, char * type)
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
-
if (!dm_task_run(dmt))
goto out;
@@ -545,8 +532,6 @@ do_foreach_partmaps (const char * mapname, const char *uuid,
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 1;
- dm_task_no_open_count(dmt);
-
if (!dm_task_run(dmt))
goto out;
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index baa1ead..8996c1d 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -217,8 +217,6 @@ static int dm_tgt_version (unsigned int *version, char *str)
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return 1;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(2, DM_DEVICE_LIST_VERSIONS, dmt);
condlog(0, "Cannot communicate with kernel DM");
@@ -398,7 +396,6 @@ dm_simplecmd (int task, const char *name, int flags, uint16_t udev_flags) {
if (!dm_task_set_name (dmt, name))
goto out;
- dm_task_no_open_count(dmt);
dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */
#ifdef LIBDM_API_FLUSH
if (flags & DMFL_NO_FLUSH)
@@ -495,8 +492,6 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size,
target, params);
- dm_task_no_open_count(dmt);
-
if (task == DM_DEVICE_CREATE &&
!dm_task_set_cookie(dmt, &cookie, udev_flags))
goto freeout;
@@ -627,8 +622,6 @@ dm_get_info(const char *name, struct dm_info *info)
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_INFO, dmt);
goto out;
@@ -667,8 +660,6 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
-
errno = 0;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
@@ -787,8 +778,6 @@ int dm_get_status(const char *name, char **outstatus)
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
-
errno = 0;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_STATUS, dmt);
@@ -845,8 +834,6 @@ int dm_type(const char *name, char *type)
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
goto out;
@@ -889,8 +876,6 @@ int dm_is_mpath(const char *name)
if (!dm_task_set_name(dmt, name))
goto out_task;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
goto out_task;
@@ -950,8 +935,6 @@ dm_map_present_by_uuid(const char *uuid)
if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
goto out;
- dm_task_no_open_count(dmt);
-
if (!dm_task_set_uuid(dmt, prefixed_uuid))
goto out_task;
@@ -1158,8 +1141,6 @@ int dm_flush_maps (int retries)
if (!(dmt = libmp_dm_task_create (DM_DEVICE_LIST)))
return r;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run (dmt)) {
dm_log_error(3, DM_DEVICE_LIST, dmt);
goto out;
@@ -1205,8 +1186,6 @@ dm_message(const char * mapname, char * message)
if (!dm_task_set_message(dmt, message))
goto out;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(2, DM_DEVICE_TARGET_MSG, dmt);
goto out;
@@ -1341,8 +1320,6 @@ dm_get_maps (vector mp)
if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
return 1;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_LIST, dmt);
goto out;
@@ -1419,7 +1396,6 @@ dm_mapname(int major, int minor)
!dm_task_set_minor(dmt, minor))
goto bad;
- dm_task_no_open_count(dmt);
r = libmp_dm_task_run(dmt);
if (!r) {
dm_log_error(2, DM_DEVICE_INFO, dmt);
@@ -1455,8 +1431,6 @@ do_foreach_partmaps (const char * mapname,
if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
return 1;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_LIST, dmt);
goto out;
@@ -1665,8 +1639,6 @@ dm_rename (const char * old, char * new, char *delim, int skip_kpartx)
if (!dm_task_set_newname(dmt, new))
goto out;
- dm_task_no_open_count(dmt);
-
if (!dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
r = libmp_dm_task_run(dmt);
@@ -1713,8 +1685,6 @@ int dm_reassign_table(const char *name, char *old, char *new)
if (!dm_task_set_name(dmt, name))
goto out;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
goto out;
@@ -1756,8 +1726,6 @@ int dm_reassign_table(const char *name, char *old, char *new)
} while (next);
if (modified) {
- dm_task_no_open_count(reload_dmt);
-
if (!libmp_dm_task_run(reload_dmt)) {
dm_log_error(3, DM_DEVICE_RELOAD, reload_dmt);
condlog(3, "%s: failed to reassign targets", name);
@@ -1803,8 +1771,6 @@ int dm_reassign(const char *mapname)
if (!dm_task_set_name(dmt, mapname))
goto out;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_DEPS, dmt);
goto out;
@@ -1861,8 +1827,6 @@ int dm_setgeometry(struct multipath *mpp)
if (!dm_task_set_name(dmt, mpp->alias))
goto out;
- dm_task_no_open_count(dmt);
-
/* What a sick interface ... */
snprintf(heads, 4, "%u", pp->geom.heads);
snprintf(sectors, 4, "%u", pp->geom.sectors);
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
index 5657000..3fbdc55 100644
--- a/multipathd/dmevents.c
+++ b/multipathd/dmevents.c
@@ -154,8 +154,6 @@ static int dm_get_events(void)
if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
return -1;
- dm_task_no_open_count(dmt);
-
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_LIST, dmt);
goto fail;
diff --git a/multipathd/waiter.c b/multipathd/waiter.c
index d1f344b..1dd93c5 100644
--- a/multipathd/waiter.c
+++ b/multipathd/waiter.c
@@ -108,8 +108,6 @@ static int waiteventloop (struct event_thread *waiter)
return 1;
}
- dm_task_no_open_count(waiter->dmt);
-
/* wait */
sigemptyset(&set);
sigaddset(&set, SIGUSR2);
diff --git a/tests/dmevents.c b/tests/dmevents.c
index 668e6d2..2f98173 100644
--- a/tests/dmevents.c
+++ b/tests/dmevents.c
@@ -267,15 +267,6 @@ struct dm_task *__wrap_libmp_dm_task_create(int task)
return mock_type(struct dm_task *);
}
-int __real_dm_task_no_open_count(struct dm_task *dmt);
-int __wrap_dm_task_no_open_count(struct dm_task *dmt)
-{
- if (!setup_done)
- return __real_dm_task_no_open_count(dmt);
- assert_ptr_equal((struct test_data *)dmt, &data);
- return mock_type(int);
-}
-
int __real_dm_task_run(struct dm_task *dmt);
int __wrap_dm_task_run(struct dm_task *dmt)
{
@@ -554,7 +545,6 @@ static void test_get_events_bad1(void **state)
skip();
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 0);
assert_int_equal(dm_get_events(), -1);
}
@@ -567,7 +557,6 @@ static void test_get_events_bad2(void **state)
skip();
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 0);
assert_int_equal(dm_get_events(), -1);
@@ -582,7 +571,6 @@ static void test_get_events_good0(void **state)
assert_int_equal(add_dm_device_event("foo", 1, 5), 0);
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 1);
assert_int_equal(dm_get_events(), 0);
@@ -617,7 +605,6 @@ static void test_get_events_good1(void **state)
assert_int_equal(add_dm_device_event("foo", 1, 6), 0);
assert_int_equal(remove_dm_device_event("xyzzy"), 0);
will_return(__wrap_libmp_dm_task_create, &data);
- will_return(__wrap_dm_task_no_open_count, 1);
will_return(__wrap_dm_task_run, 1);
will_return(__wrap_dm_task_get_names, 1);
assert_int_equal(dm_get_events(), 0);
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 13/49] libmpathutil: export cleanup_udev_device()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (11 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 12/49] multipath-tools: don't call dm_task_no_open_count() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 14/49] libmpathutil: add cleanup_vector() Martin Wilck
` (35 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
This function is useful in multiple callers.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathutil/libmpathutil.version | 4 ++++
libmpathutil/util.c | 6 ++++++
libmpathutil/util.h | 3 +++
libmultipath/print.c | 6 ------
tests/Makefile | 2 +-
5 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/libmpathutil/libmpathutil.version b/libmpathutil/libmpathutil.version
index fee74a3..86450f4 100644
--- a/libmpathutil/libmpathutil.version
+++ b/libmpathutil/libmpathutil.version
@@ -133,3 +133,7 @@ LIBMPATHUTIL_2.0 {
LIBMPATHUTIL_2.1 {
libmp_basename;
};
+
+LIBMPATHUTIL_2.2 {
+ cleanup_udev_device;
+};
diff --git a/libmpathutil/util.c b/libmpathutil/util.c
index 23d303f..67db3c8 100644
--- a/libmpathutil/util.c
+++ b/libmpathutil/util.c
@@ -373,3 +373,9 @@ void cleanup_ucharp(unsigned char **p)
{
free(*p);
}
+
+void cleanup_udev_device(struct udev_device **udd)
+{
+ if (*udd)
+ udev_device_unref(*udd);
+}
diff --git a/libmpathutil/util.h b/libmpathutil/util.h
index 4997fed..c19f749 100644
--- a/libmpathutil/util.h
+++ b/libmpathutil/util.h
@@ -10,6 +10,7 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
+#include <libudev.h>
size_t strchop(char *);
@@ -139,4 +140,6 @@ static inline void clear_bit_in_bitfield(unsigned int bit, struct bitfield *bf)
void cleanup_charp(char **p);
void cleanup_ucharp(unsigned char **p);
+void cleanup_udev_device(struct udev_device **udd);
+
#endif /* _UTIL_H */
diff --git a/libmultipath/print.c b/libmultipath/print.c
index d592001..b7af913 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -436,12 +436,6 @@ snprint_multipath_vpd_data(struct strbuf *buff,
return append_strbuf_str(buff, "[undef]");
}
-static void cleanup_udev_device(struct udev_device **udd)
-{
- if (*udd)
- udev_device_unref(*udd);
-}
-
static int
snprint_multipath_max_sectors_kb(struct strbuf *buff, const struct multipath *mpp)
{
diff --git a/tests/Makefile b/tests/Makefile
index 4005204..8afa8c6 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -53,7 +53,7 @@ vpd-test_OBJDEPS := $(multipathdir)/discovery.o
vpd-test_LIBDEPS := -ludev -lpthread -ldl
alias-test_TESTDEPS := test-log.o
alias-test_OBJDEPS := $(mpathutildir)/util.o
-alias-test_LIBDEPS := -lpthread -ldl
+alias-test_LIBDEPS := -ludev -lpthread -ldl
valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o
valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl
devt-test_LIBDEPS := -ludev
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 14/49] libmpathutil: add cleanup_vector()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (12 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 13/49] libmpathutil: export cleanup_udev_device() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 15/49] libmultipath: add cleanup helpers for struct multipath Martin Wilck
` (34 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathutil/libmpathutil.version | 1 +
libmpathutil/vector.c | 6 ++++++
libmpathutil/vector.h | 1 +
3 files changed, 8 insertions(+)
diff --git a/libmpathutil/libmpathutil.version b/libmpathutil/libmpathutil.version
index 86450f4..cb05231 100644
--- a/libmpathutil/libmpathutil.version
+++ b/libmpathutil/libmpathutil.version
@@ -136,4 +136,5 @@ LIBMPATHUTIL_2.1 {
LIBMPATHUTIL_2.2 {
cleanup_udev_device;
+ cleanup_vector;
};
diff --git a/libmpathutil/vector.c b/libmpathutil/vector.c
index df59db5..7c3ce43 100644
--- a/libmpathutil/vector.c
+++ b/libmpathutil/vector.c
@@ -169,6 +169,12 @@ vector_free(vector v)
free(v);
}
+void cleanup_vector(vector *pv)
+{
+ if (*pv)
+ vector_free(*pv);
+}
+
void
free_strvec(vector strvec)
{
diff --git a/libmpathutil/vector.h b/libmpathutil/vector.h
index c0b09cb..a41f157 100644
--- a/libmpathutil/vector.h
+++ b/libmpathutil/vector.h
@@ -78,6 +78,7 @@ extern vector vector_alloc(void);
extern bool vector_alloc_slot(vector v);
vector vector_reset(vector v);
extern void vector_free(vector v);
+void cleanup_vector(vector *pv);
#define vector_free_const(x) vector_free((vector)(long)(x))
extern void free_strvec(vector strvec);
extern void vector_set_slot(vector v, void *value);
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 15/49] libmultipath: add cleanup helpers for struct multipath
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (13 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 14/49] libmpathutil: add cleanup_vector() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 16/49] libmultipath: add cleanup_dm_task(), and use it in devmapper.c Martin Wilck
` (33 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Export cleanup_multipath_and_paths(), which will be used by multipath.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/libmultipath.version | 1 +
libmultipath/structs.c | 12 ++++++++++++
libmultipath/structs.h | 2 ++
3 files changed, 15 insertions(+)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index eb51174..f58cb1d 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -66,6 +66,7 @@ global:
check_foreign;
cleanup_bindings;
cleanup_lock;
+ cleanup_multipath_and_paths;
coalesce_paths;
count_active_paths;
delete_all_foreign;
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index be3125e..1583e00 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -329,6 +329,18 @@ free_multipath (struct multipath * mpp, enum free_path_mode free_paths)
free(mpp);
}
+void cleanup_multipath(struct multipath **pmpp)
+{
+ if (*pmpp)
+ free_multipath(*pmpp, KEEP_PATHS);
+}
+
+void cleanup_multipath_and_paths(struct multipath **pmpp)
+{
+ if (*pmpp)
+ free_multipath(*pmpp, FREE_PATHS);
+}
+
void
drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths)
{
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index dbaf4d4..3b91e39 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -544,6 +544,8 @@ void free_pathvec (vector vec, enum free_path_mode free_paths);
void free_pathgroup (struct pathgroup * pgp, enum free_path_mode free_paths);
void free_pgvec (vector pgvec, enum free_path_mode free_paths);
void free_multipath (struct multipath *, enum free_path_mode free_paths);
+void cleanup_multipath(struct multipath **pmpp);
+void cleanup_multipath_and_paths(struct multipath **pmpp);
void free_multipath_attributes (struct multipath *);
void drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths);
void free_multipathvec (vector mpvec, enum free_path_mode free_paths);
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 16/49] libmultipath: add cleanup_dm_task(), and use it in devmapper.c
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (14 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 15/49] libmultipath: add cleanup helpers for struct multipath Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:13 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 17/49] libmultipath: rename dm_type()->dm_type_match() and use symbolic values Martin Wilck
` (32 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
This allows us to get rid of a lot of goto statements, and generally
obtain cleaner code.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 258 ++++++++++++++++-----------------------
1 file changed, 107 insertions(+), 151 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 8996c1d..4bff62d 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -91,6 +91,12 @@ int libmp_dm_task_run(struct dm_task *dmt)
return r;
}
+static void cleanup_dm_task(struct dm_task **pdmt)
+{
+ if (*pdmt)
+ dm_task_destroy(*pdmt);
+}
+
__attribute__((format(printf, 4, 5))) static void
dm_write_log (int level, const char *file, int line, const char *f, ...)
{
@@ -203,8 +209,8 @@ static void init_dm_drv_version(void)
static int dm_tgt_version (unsigned int *version, char *str)
{
- int r = 2;
- struct dm_task *dmt;
+ bool found = false;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_versions *target;
struct dm_versions *last_target;
unsigned int *v;
@@ -220,31 +226,28 @@ static int dm_tgt_version (unsigned int *version, char *str)
if (!libmp_dm_task_run(dmt)) {
dm_log_error(2, DM_DEVICE_LIST_VERSIONS, dmt);
condlog(0, "Cannot communicate with kernel DM");
- goto out;
+ return 1;
}
target = dm_task_get_versions(dmt);
do {
last_target = target;
if (!strncmp(str, target->name, strlen(str))) {
- r = 1;
+ found = true;
break;
}
target = (void *) target + target->next;
} while (last_target != target);
- if (r == 2) {
+ if (!found) {
condlog(0, "DM %s kernel driver not loaded", str);
- goto out;
+ return 1;
}
v = target->version;
version[0] = v[0];
version[1] = v[1];
version[2] = v[2];
- r = 0;
-out:
- dm_task_destroy(dmt);
- return r;
+ return 0;
}
static void init_dm_mpath_version(void)
@@ -383,18 +386,18 @@ libmp_dm_task_create(int task)
static int
dm_simplecmd (int task, const char *name, int flags, uint16_t udev_flags) {
- int r = 0;
+ int r;
int udev_wait_flag = (((flags & DMFL_NEED_SYNC) || udev_flags) &&
(task == DM_DEVICE_RESUME ||
task == DM_DEVICE_REMOVE));
uint32_t cookie = 0;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
if (!(dmt = libmp_dm_task_create (task)))
return 0;
if (!dm_task_set_name (dmt, name))
- goto out;
+ return 0;
dm_task_skip_lockfs(dmt); /* for DM_DEVICE_RESUME */
#ifdef LIBDM_API_FLUSH
@@ -408,7 +411,7 @@ dm_simplecmd (int task, const char *name, int flags, uint16_t udev_flags) {
if (udev_wait_flag &&
!dm_task_set_cookie(dmt, &cookie,
DM_UDEV_DISABLE_LIBRARY_FALLBACK | udev_flags))
- goto out;
+ return 0;
r = libmp_dm_task_run (dmt);
if (!r)
@@ -416,8 +419,6 @@ dm_simplecmd (int task, const char *name, int flags, uint16_t udev_flags) {
if (udev_wait_flag)
libmp_udev_wait(cookie);
-out:
- dm_task_destroy (dmt);
return r;
}
@@ -440,8 +441,9 @@ static int
dm_addmap (int task, const char *target, struct multipath *mpp,
char * params, int ro, uint16_t udev_flags) {
int r = 0;
- struct dm_task *dmt;
- char *prefixed_uuid = NULL;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *prefixed_uuid = NULL;
+
uint32_t cookie = 0;
if (task == DM_DEVICE_CREATE && strlen(mpp->wwid) == 0) {
@@ -457,10 +459,10 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
return 0;
if (!dm_task_set_name (dmt, mpp->alias))
- goto addout;
+ return 0;
if (!dm_task_add_target (dmt, 0, mpp->size, target, params))
- goto addout;
+ return 0;
if (ro)
dm_task_set_ro(dmt);
@@ -469,10 +471,10 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
if (asprintf(&prefixed_uuid, UUID_PREFIX "%s", mpp->wwid) < 0) {
condlog(0, "cannot create prefixed uuid : %s",
strerror(errno));
- goto addout;
+ return 0;
}
if (!dm_task_set_uuid(dmt, prefixed_uuid))
- goto freeout;
+ return 0;
dm_task_skip_lockfs(dmt);
#ifdef LIBDM_API_FLUSH
dm_task_no_flush(dmt);
@@ -481,33 +483,28 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
if (mpp->attribute_flags & (1 << ATTR_MODE) &&
!dm_task_set_mode(dmt, mpp->mode))
- goto freeout;
+ return 0;
if (mpp->attribute_flags & (1 << ATTR_UID) &&
!dm_task_set_uid(dmt, mpp->uid))
- goto freeout;
+ return 0;
if (mpp->attribute_flags & (1 << ATTR_GID) &&
!dm_task_set_gid(dmt, mpp->gid))
- goto freeout;
+ return 0;
+
condlog(2, "%s: %s [0 %llu %s %s]", mpp->alias,
task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size,
target, params);
if (task == DM_DEVICE_CREATE &&
!dm_task_set_cookie(dmt, &cookie, udev_flags))
- goto freeout;
+ return 0;
r = libmp_dm_task_run (dmt);
if (!r)
dm_log_error(2, task, dmt);
if (task == DM_DEVICE_CREATE)
- libmp_udev_wait(cookie);
-freeout:
- if (prefixed_uuid)
- free(prefixed_uuid);
-
-addout:
- dm_task_destroy (dmt);
+ libmp_udev_wait(cookie);
if (r)
mpp->need_reload = false;
@@ -648,46 +645,41 @@ int dm_map_present(const char * str)
int dm_get_map(const char *name, unsigned long long *size, char **outparams)
{
- int r = DMP_ERR;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params = NULL;
if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
- return r;
+ return DMP_ERR;
if (!dm_task_set_name(dmt, name))
- goto out;
+ return DMP_ERR;
errno = 0;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
if (dm_task_get_errno(dmt) == ENXIO)
- r = DMP_NOT_FOUND;
- goto out;
+ return DMP_NOT_FOUND;
+ else
+ return DMP_ERR;
}
- r = DMP_NOT_FOUND;
/* Fetch 1st target */
if (dm_get_next_target(dmt, NULL, &start, &length,
&target_type, ¶ms) != NULL || !params)
/* more than one target or not found target */
- goto out;
+ return DMP_NOT_FOUND;
if (size)
*size = length;
if (!outparams)
- r = DMP_OK;
+ return DMP_OK;
else {
*outparams = strdup(params);
- r = *outparams ? DMP_OK : DMP_ERR;
+ return *outparams ? DMP_OK : DMP_ERR;
}
-
-out:
- dm_task_destroy(dmt);
- return r;
}
static int
@@ -767,7 +759,7 @@ is_mpath_part(const char *part_name, const char *map_name)
int dm_get_status(const char *name, char **outstatus)
{
int r = DMP_ERR;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
uint64_t start, length;
char *target_type = NULL;
char *status = NULL;
@@ -796,7 +788,7 @@ int dm_get_status(const char *name, char **outstatus)
goto out;
if (!status) {
- condlog(2, "get null status.");
+ condlog(2, "got null status.");
goto out;
}
@@ -808,9 +800,9 @@ int dm_get_status(const char *name, char **outstatus)
}
out:
if (r != DMP_OK)
- condlog(0, "%s: error getting map status string", name);
+ condlog(0, "%s: %s: error getting map status string: %d",
+ __func__, name, r);
- dm_task_destroy(dmt);
return r;
}
@@ -823,7 +815,7 @@ out:
int dm_type(const char *name, char *type)
{
int r = 0;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
@@ -850,7 +842,6 @@ int dm_type(const char *name, char *type)
r = 1;
out:
- dm_task_destroy(dmt);
return r;
}
@@ -863,7 +854,7 @@ out:
int dm_is_mpath(const char *name)
{
int r = -1;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_info info;
uint64_t start, length;
char *target_type = NULL;
@@ -874,38 +865,36 @@ int dm_is_mpath(const char *name)
goto out;
if (!dm_task_set_name(dmt, name))
- goto out_task;
+ goto out;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
- goto out_task;
+ goto out;
}
if (!dm_task_get_info(dmt, &info))
- goto out_task;
+ goto out;
r = 0;
if (!info.exists)
- goto out_task;
+ goto out;
uuid = dm_task_get_uuid(dmt);
if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
- goto out_task;
+ goto out;
/* Fetch 1st target */
if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
¶ms) != NULL)
/* multiple targets */
- goto out_task;
+ goto out;
if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
- goto out_task;
+ goto out;
r = 1;
-out_task:
- dm_task_destroy(dmt);
out:
if (r < 0)
condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno));
@@ -1131,10 +1120,10 @@ dm_flush_map_nopaths(const char *mapname, int deferred_remove __DR_UNUSED__)
return _dm_flush_map(mapname, flags, 0);
}
-int dm_flush_maps (int retries)
+int dm_flush_maps(int retries)
{
int r = DM_FLUSH_FAIL;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_names *names;
unsigned next = 0;
@@ -1143,15 +1132,15 @@ int dm_flush_maps (int retries)
if (!libmp_dm_task_run (dmt)) {
dm_log_error(3, DM_DEVICE_LIST, dmt);
- goto out;
+ return r;
}
if (!(names = dm_task_get_names (dmt)))
- goto out;
+ return r;
r = DM_FLUSH_OK;
if (!names->dev)
- goto out;
+ return r;
do {
int ret;
@@ -1163,16 +1152,13 @@ int dm_flush_maps (int retries)
names = (void *) names + next;
} while (next);
-out:
- dm_task_destroy (dmt);
return r;
}
int
dm_message(const char * mapname, char * message)
{
- int r = 1;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
if (!(dmt = libmp_dm_task_create(DM_DEVICE_TARGET_MSG)))
return 1;
@@ -1191,13 +1177,10 @@ dm_message(const char * mapname, char * message)
goto out;
}
- r = 0;
+ return 0;
out:
- if (r)
- condlog(0, "DM message failed [%s]", message);
-
- dm_task_destroy(dmt);
- return r;
+ condlog(0, "DM message failed [%s]", message);
+ return 1;
}
int
@@ -1305,12 +1288,10 @@ out:
return NULL;
}
-int
-dm_get_maps (vector mp)
+int dm_get_maps(vector mp)
{
struct multipath * mpp;
- int r = 1;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_names *names;
unsigned next = 0;
@@ -1322,15 +1303,15 @@ dm_get_maps (vector mp)
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_LIST, dmt);
- goto out;
+ return 1;
}
if (!(names = dm_task_get_names(dmt)))
- goto out;
+ return 1;
if (!names->dev) {
- r = 0; /* this is perfectly valid */
- goto out;
+ /* this is perfectly valid */
+ return 0;
}
do {
@@ -1339,11 +1320,11 @@ dm_get_maps (vector mp)
mpp = dm_get_multipath(names->name);
if (!mpp)
- goto out;
+ return 1;
if (!vector_alloc_slot(mp)) {
free_multipath(mpp, KEEP_PATHS);
- goto out;
+ return 1;
}
vector_set_slot(mp, mpp);
@@ -1352,11 +1333,7 @@ next:
names = (void *) names + next;
} while (next);
- r = 0;
- goto out;
-out:
- dm_task_destroy (dmt);
- return r;
+ return 0;
}
int
@@ -1419,10 +1396,10 @@ do_foreach_partmaps (const char * mapname,
int (*partmap_func)(const char *, void *),
void *data)
{
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *params = NULL;
struct dm_names *names;
unsigned next = 0;
- char *params = NULL;
unsigned long long size;
char dev_t[32];
int r = 1;
@@ -1431,21 +1408,18 @@ do_foreach_partmaps (const char * mapname,
if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
return 1;
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_LIST, dmt);
- goto out;
- }
+ if (!libmp_dm_task_run(dmt))
+ return 1;
if (!(names = dm_task_get_names(dmt)))
- goto out;
+ return 1;
- if (!names->dev) {
- r = 0; /* this is perfectly valid */
- goto out;
- }
+ if (!names->dev)
+ /* this is perfectly valid */
+ return 0;
if (dm_dev_t(mapname, &dev_t[0], 32))
- goto out;
+ return 1;
do {
if (
@@ -1472,7 +1446,7 @@ do_foreach_partmaps (const char * mapname,
!isdigit(*(p + strlen(dev_t)))
) {
if ((r = partmap_func(names->name, data)) != 0)
- goto out;
+ return 1;
}
free(params);
@@ -1481,11 +1455,7 @@ do_foreach_partmaps (const char * mapname,
names = (void *) names + next;
} while (next);
- r = 0;
-out:
- free(params);
- dm_task_destroy (dmt);
- return r;
+ return 0;
}
struct remove_data {
@@ -1623,7 +1593,7 @@ int
dm_rename (const char * old, char * new, char *delim, int skip_kpartx)
{
int r = 0;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
uint32_t cookie = 0;
uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
@@ -1634,22 +1604,19 @@ dm_rename (const char * old, char * new, char *delim, int skip_kpartx)
return r;
if (!dm_task_set_name(dmt, old))
- goto out;
+ return r;
if (!dm_task_set_newname(dmt, new))
- goto out;
+ return r;
if (!dm_task_set_cookie(dmt, &cookie, udev_flags))
- goto out;
+ return r;
+
r = libmp_dm_task_run(dmt);
if (!r)
dm_log_error(2, DM_DEVICE_RENAME, dmt);
libmp_udev_wait(cookie);
-
-out:
- dm_task_destroy(dmt);
-
return r;
}
@@ -1672,9 +1639,10 @@ void dm_reassign_deps(char *table, const char *dep, const char *newdep)
int dm_reassign_table(const char *name, char *old, char *new)
{
- int r = 0, modified = 0;
+ int modified = 0;
uint64_t start, length;
- struct dm_task *dmt, *reload_dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *reload_dmt = NULL;
char *target, *params = NULL;
char *buff;
void *next = NULL;
@@ -1683,16 +1651,16 @@ int dm_reassign_table(const char *name, char *old, char *new)
return 0;
if (!dm_task_set_name(dmt, name))
- goto out;
+ return 0;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
- goto out;
+ return 0;
}
if (!(reload_dmt = libmp_dm_task_create(DM_DEVICE_RELOAD)))
- goto out;
+ return 0;
if (!dm_task_set_name(reload_dmt, name))
- goto out_reload;
+ return 0;
do {
next = dm_get_next_target(dmt, next, &start, &length,
@@ -1705,13 +1673,13 @@ int dm_reassign_table(const char *name, char *old, char *new)
*/
condlog(1, "%s: invalid target found in map %s",
__func__, name);
- goto out_reload;
+ return 0;
}
buff = strdup(params);
if (!buff) {
condlog(3, "%s: failed to replace target %s, "
"out of memory", name, target);
- goto out_reload;
+ return 0;
}
if (strcmp(target, TGT_MPATH) && strstr(params, old)) {
condlog(3, "%s: replace target %s %s",
@@ -1729,18 +1697,12 @@ int dm_reassign_table(const char *name, char *old, char *new)
if (!libmp_dm_task_run(reload_dmt)) {
dm_log_error(3, DM_DEVICE_RELOAD, reload_dmt);
condlog(3, "%s: failed to reassign targets", name);
- goto out_reload;
+ return 0;
}
dm_simplecmd_noflush(DM_DEVICE_RESUME, name,
MPATH_UDEV_RELOAD_FLAG);
}
- r = 1;
-
-out_reload:
- dm_task_destroy(reload_dmt);
-out:
- dm_task_destroy(dmt);
- return r;
+ return 1;
}
@@ -1752,10 +1714,9 @@ out:
int dm_reassign(const char *mapname)
{
struct dm_deps *deps;
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_info info;
char dev_t[32], dm_dep[32];
- int r = 0;
unsigned int i;
if (dm_dev_t(mapname, &dev_t[0], 32)) {
@@ -1769,21 +1730,21 @@ int dm_reassign(const char *mapname)
}
if (!dm_task_set_name(dmt, mapname))
- goto out;
+ return 0;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_DEPS, dmt);
- goto out;
+ return 0;
}
if (!dm_task_get_info(dmt, &info))
- goto out;
+ return 0;
if (!(deps = dm_task_get_deps(dmt)))
- goto out;
+ return 0;
if (!info.exists)
- goto out;
+ return 0;
for (i = 0; i < deps->count; i++) {
sprintf(dm_dep, "%d:%d",
@@ -1792,15 +1753,12 @@ int dm_reassign(const char *mapname)
sysfs_check_holders(dm_dep, dev_t);
}
- r = 1;
-out:
- dm_task_destroy (dmt);
- return r;
+ return 1;
}
int dm_setgeometry(struct multipath *mpp)
{
- struct dm_task *dmt;
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct path *pp;
char heads[4], sectors[4];
char cylinders[10], start[32];
@@ -1825,7 +1783,7 @@ int dm_setgeometry(struct multipath *mpp)
return 0;
if (!dm_task_set_name(dmt, mpp->alias))
- goto out;
+ return 0;
/* What a sick interface ... */
snprintf(heads, 4, "%u", pp->geom.heads);
@@ -1834,14 +1792,12 @@ int dm_setgeometry(struct multipath *mpp)
snprintf(start, 32, "%lu", pp->geom.start);
if (!dm_task_set_geometry(dmt, cylinders, heads, sectors, start)) {
condlog(3, "%s: Failed to set geometry", mpp->alias);
- goto out;
+ return 0;
}
r = libmp_dm_task_run(dmt);
if (!r)
dm_log_error(3, DM_DEVICE_SET_GEOMETRY, dmt);
-out:
- dm_task_destroy(dmt);
return r;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 17/49] libmultipath: rename dm_type()->dm_type_match() and use symbolic values
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (15 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 16/49] libmultipath: add cleanup_dm_task(), and use it in devmapper.c Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:14 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 18/49] libmultipath: Use symbolic return values for dm_is_mpath() Martin Wilck
` (31 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Also, make the function static.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 37 +++++++++++++++++++------------------
libmultipath/devmapper.h | 1 -
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 4bff62d..a63154f 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -806,43 +806,44 @@ out:
return r;
}
-/*
- * returns:
- * 1 : match
- * 0 : no match
- * -1 : empty map, or more than 1 target
- */
-int dm_type(const char *name, char *type)
+enum {
+ DM_TYPE_NOMATCH = 0,
+ DM_TYPE_MATCH,
+ /* more than 1 target */
+ DM_TYPE_MULTI,
+ /* empty map */
+ DM_TYPE_EMPTY,
+ DM_TYPE_ERR,
+};
+static int dm_type_match(const char *name, char *type)
{
- int r = 0;
struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
- return 0;
+ return DM_TYPE_ERR;
if (!dm_task_set_name(dmt, name))
- goto out;
+ return DM_TYPE_ERR;
if (!libmp_dm_task_run(dmt)) {
dm_log_error(3, DM_DEVICE_TABLE, dmt);
- goto out;
+ return DM_TYPE_ERR;
}
/* Fetch 1st target */
if (dm_get_next_target(dmt, NULL, &start, &length,
&target_type, ¶ms) != NULL)
/* multiple targets */
- r = -1;
+ return DM_TYPE_MULTI;
else if (!target_type)
- r = -1;
+ return DM_TYPE_EMPTY;
else if (!strcmp(target_type, type))
- r = 1;
-
-out:
- return r;
+ return DM_TYPE_MATCH;
+ else
+ return DM_TYPE_NOMATCH;
}
/*
@@ -1426,7 +1427,7 @@ do_foreach_partmaps (const char * mapname,
/*
* if there is only a single "linear" target
*/
- (dm_type(names->name, TGT_PART) == 1) &&
+ (dm_type_match(names->name, TGT_PART) == DM_TYPE_MATCH) &&
/*
* and the uuid of the target is a partition of the
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 19b79c5..ff28575 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -46,7 +46,6 @@ int dm_map_present (const char *name);
int dm_map_present_by_uuid(const char *uuid);
int dm_get_map(const char *name, unsigned long long *size, char **outparams);
int dm_get_status(const char *name, char **outstatus);
-int dm_type(const char *name, char *type);
int dm_is_mpath(const char *name);
enum {
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 18/49] libmultipath: Use symbolic return values for dm_is_mpath()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (16 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 17/49] libmultipath: rename dm_type()->dm_type_match() and use symbolic values Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:14 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 19/49] libmultipath: add libmp_mapinfo() Martin Wilck
` (30 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist_int.c | 2 +-
libmultipath/devmapper.c | 22 ++++++++--------------
libmultipath/devmapper.h | 6 ++++++
multipath/main.c | 4 ++--
multipathd/dmevents.c | 19 +++++++++++++------
multipathd/main.c | 2 +-
6 files changed, 31 insertions(+), 24 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index 178c2f5..6da0401 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -185,7 +185,7 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
condlog(3, "alias = %s", alias);
- if (dm_map_present(alias) && dm_is_mpath(alias) != 1){
+ if (dm_map_present(alias) && dm_is_mpath(alias) != DM_IS_MPATH_YES) {
condlog(3, "%s: not a multipath device.", alias);
goto out;
}
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index a63154f..3abdc26 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -846,15 +846,9 @@ static int dm_type_match(const char *name, char *type)
return DM_TYPE_NOMATCH;
}
-/*
- * returns:
- * 1 : is multipath device
- * 0 : is not multipath device
- * -1 : error
- */
int dm_is_mpath(const char *name)
{
- int r = -1;
+ int r = DM_IS_MPATH_ERR;
struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_info info;
uint64_t start, length;
@@ -876,7 +870,7 @@ int dm_is_mpath(const char *name)
if (!dm_task_get_info(dmt, &info))
goto out;
- r = 0;
+ r = DM_IS_MPATH_NO;
if (!info.exists)
goto out;
@@ -895,10 +889,10 @@ int dm_is_mpath(const char *name)
if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
goto out;
- r = 1;
+ r = DM_IS_MPATH_YES;
out:
- if (r < 0)
- condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno));
+ if (r == DM_IS_MPATH_ERR)
+ condlog(3, "%s: dm command failed in %s: %s", name, __func__, strerror(errno));
return r;
}
@@ -1039,7 +1033,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
unsigned long long mapsize;
char *params = NULL;
- if (dm_is_mpath(mapname) != 1)
+ if (dm_is_mpath(mapname) != DM_IS_MPATH_YES)
return DM_FLUSH_OK; /* nothing to do */
/* if the device currently has no partitions, do not
@@ -1086,7 +1080,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
}
condlog(4, "multipath map %s removed", mapname);
return DM_FLUSH_OK;
- } else if (dm_is_mpath(mapname) != 1) {
+ } else if (dm_is_mpath(mapname) != DM_IS_MPATH_YES) {
condlog(4, "multipath map %s removed externally",
mapname);
return DM_FLUSH_OK; /* raced. someone else removed it */
@@ -1316,7 +1310,7 @@ int dm_get_maps(vector mp)
}
do {
- if (dm_is_mpath(names->name) != 1)
+ if (dm_is_mpath(names->name) != DM_IS_MPATH_YES)
goto next;
mpp = dm_get_multipath(names->name);
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index ff28575..9438c2d 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -46,6 +46,12 @@ int dm_map_present (const char *name);
int dm_map_present_by_uuid(const char *uuid);
int dm_get_map(const char *name, unsigned long long *size, char **outparams);
int dm_get_status(const char *name, char **outstatus);
+
+enum {
+ DM_IS_MPATH_NO,
+ DM_IS_MPATH_YES,
+ DM_IS_MPATH_ERR,
+};
int dm_is_mpath(const char *name);
enum {
diff --git a/multipath/main.c b/multipath/main.c
index ce702e7..c82bc86 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -247,7 +247,7 @@ static int check_usable_paths(struct config *conf,
goto out;
}
- if (dm_is_mpath(mapname) != 1) {
+ if (dm_is_mpath(mapname) != DM_IS_MPATH_YES) {
condlog(1, "%s is not a multipath map", devpath);
goto free;
}
@@ -1080,7 +1080,7 @@ main (int argc, char *argv[])
goto out;
}
if (cmd == CMD_FLUSH_ONE) {
- if (dm_is_mpath(dev) != 1) {
+ if (dm_is_mpath(dev) != DM_IS_MPATH_YES) {
condlog(0, "%s is not a multipath device", dev);
r = RTVL_FAIL;
goto out;
diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
index 3fbdc55..af1e12e 100644
--- a/multipathd/dmevents.c
+++ b/multipathd/dmevents.c
@@ -168,9 +168,13 @@ static int dm_get_events(void)
while (names->dev) {
uint32_t event_nr;
- /* Don't delete device if dm_is_mpath() fails without
- * checking the device type */
- if (dm_is_mpath(names->name) == 0)
+ /*
+ * Don't delete device if dm_is_mpath() fails without
+ * checking the device type.
+ * IOW, only delete devices from the event list for which
+ * we positively know that they aren't multipath devices.
+ */
+ if (dm_is_mpath(names->name) == DM_IS_MPATH_NO)
goto next;
event_nr = dm_event_nr(names);
@@ -206,9 +210,12 @@ int watch_dmevents(char *name)
struct dev_event *dev_evt, *old_dev_evt;
int i;
- /* We know that this is a multipath device, so only fail if
- * device-mapper tells us that we're wrong */
- if (dm_is_mpath(name) == 0) {
+ /*
+ * We know that this is a multipath device, so only fail if
+ * device-mapper tells us that we're wrong
+ * IOW, don't fail for DM generic errors.
+ */
+ if (dm_is_mpath(name) == DM_IS_MPATH_NO) {
condlog(0, "%s: not a multipath device. can't watch events",
name);
return -1;
diff --git a/multipathd/main.c b/multipathd/main.c
index 58afe14..132bb2e 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -865,7 +865,7 @@ ev_add_map (char * dev, const char * alias, struct vectors * vecs)
int reassign_maps;
struct config *conf;
- if (dm_is_mpath(alias) != 1) {
+ if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
condlog(4, "%s: not a multipath map", alias);
return 0;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 19/49] libmultipath: add libmp_mapinfo()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (17 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 18/49] libmultipath: Use symbolic return values for dm_is_mpath() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:41 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 20/49] libmultipath tests: add tests for libmp_mapinfo() Martin Wilck
` (29 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
libmp_mapinfo() is intended as a generic abstraction for retrieving information from
the kernel device-mapper driver. It retrieves the information that the caller
needs, with a minimal set of DM ioctls, and never more then 2 ioctl calls.
libdm's DM_DEVICE_TABLE and DM_DEVICE_STATUS calls map to the kernel's
DM_TABLE_STATUS ioctl, with or without the DM_STATUS_TABLE_FLAG set,
respectively. DM_TABLE_STATUS always retrieves the basic map status (struct
dm_info) and the map UUID and name, too.
Note: I'd prefer to use an unnamed struct instead of _u in
union libmp_map_identifer. But doing using an unnamed struct and and
initializing the union like this in a function argument:
func((mapid_t) { .major = major, .minor = minor })
is not part of C99, and not supported in gcc 4.8, which we still support.
Likewise, the following syntax for initializing an empty struct:
(mapinfo_t) { 0 }
is not supported on all architectures we support (notably clang 3.5 under
Debian Jessie).
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 192 +++++++++++++++++++++++++++++-
libmultipath/devmapper.h | 70 +++++++++++
libmultipath/libmultipath.version | 3 +-
3 files changed, 263 insertions(+), 2 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 3abdc26..4e6b5b2 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -14,7 +14,6 @@
#include <errno.h>
#include <syslog.h>
#include <sys/sysmacros.h>
-#include <linux/dm-ioctl.h>
#include "util.h"
#include "vector.h"
@@ -604,6 +603,197 @@ has_dm_info(const struct multipath *mpp)
return (mpp && mpp->dmi.exists != 0);
}
+static int libmp_set_map_identifier(int flags, mapid_t id, struct dm_task *dmt)
+{
+ switch (flags & __DM_MAP_BY_MASK) {
+ case DM_MAP_BY_UUID:
+ if (!id.str || !(*id.str))
+ return 0;
+ return dm_task_set_uuid(dmt, id.str);
+ case DM_MAP_BY_NAME:
+ if (!id.str || !(*id.str))
+ return 0;
+ return dm_task_set_name(dmt, id.str);
+ case DM_MAP_BY_DEV:
+ if (!dm_task_set_major(dmt, id._u.major))
+ return 0;
+ return dm_task_set_minor(dmt, id._u.minor);
+ case DM_MAP_BY_DEVT:
+ if (!dm_task_set_major(dmt, major(id.devt)))
+ return 0;
+ return dm_task_set_minor(dmt, minor(id.devt));
+ default:
+ condlog(0, "%s: invalid by_id", __func__);
+ return 0;
+ }
+}
+
+static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info, const char *map_id)
+{
+ struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
+ struct dm_info dmi;
+ int rc, ioctl_nr;
+ uint64_t start, length = 0;
+ char *target_type = NULL, *params = NULL;
+ const char *name = NULL, *uuid = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *tmp_target = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *tmp_status = NULL;
+ bool tgt_set = false;
+
+ /*
+ * If both info.target and info.status are set, we need two
+ * ioctls. Call this function recursively.
+ * If successful, tmp_target will be non-NULL.
+ */
+ if (info.target && info.status) {
+ rc = libmp_mapinfo__(flags, id,
+ (mapinfo_t) { .target = &tmp_target },
+ map_id);
+ if (rc != DMP_OK)
+ return rc;
+ tgt_set = true;
+ }
+
+ /*
+ * The DM_DEVICE_TABLE and DM_DEVICE_STATUS ioctls both fetch the basic
+ * information from DM_DEVICE_INFO, too.
+ * Choose the most lightweight ioctl to fetch all requested info.
+ */
+ if (info.target && !info.status)
+ ioctl_nr = DM_DEVICE_TABLE;
+ else if (info.status || info.size || flags & __MAPINFO_TGT_TYPE)
+ ioctl_nr = DM_DEVICE_STATUS;
+ else
+ ioctl_nr = DM_DEVICE_INFO;
+
+ if (!(dmt = libmp_dm_task_create(ioctl_nr)))
+ return DMP_ERR;
+
+ if (!libmp_set_map_identifier(flags, id, dmt)) {
+ condlog(2, "%s: failed to set map identifier to %s", __func__, map_id);
+ return DMP_ERR;
+ }
+
+ if (!libmp_dm_task_run(dmt)) {
+ dm_log_error(3, ioctl_nr, dmt);
+ if (dm_task_get_errno(dmt) == ENXIO) {
+ condlog(2, "%s: map %s not found", __func__, map_id);
+ return DMP_NOT_FOUND;
+ } else
+ return DMP_ERR;
+ }
+
+ condlog(4, "%s: DM ioctl %d succeeded for %s",
+ __func__, ioctl_nr, map_id);
+
+ if (!dm_task_get_info(dmt, &dmi)) {
+ condlog(2, "%s: dm_task_get_info() failed for %s ", __func__, map_id);
+ return DMP_ERR;
+ } else if(!dmi.exists) {
+ condlog(2, "%s: map %s doesn't exist", __func__, map_id);
+ return DMP_NOT_FOUND;
+ }
+
+ if (info.target || info.status || info.size || flags & __MAPINFO_TGT_TYPE) {
+ if (dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, ¶ms) != NULL) {
+ condlog(2, "%s: map %s has multiple targets", __func__, map_id);
+ return DMP_NOT_FOUND;
+ }
+ if (!params) {
+ condlog(2, "%s: map %s has no targets", __func__, map_id);
+ return DMP_NOT_FOUND;
+ }
+ if (flags & __MAPINFO_TGT_TYPE) {
+ const char *tgt_type = flags & MAPINFO_MPATH_ONLY ? TGT_MPATH : TGT_PART;
+
+ if (strcmp(target_type, tgt_type)) {
+ condlog(3, "%s: target type mismatch: \"%s\" != \"%s\"",
+ __func__, tgt_type, target_type);
+ return DMP_NO_MATCH;
+ }
+ }
+ }
+
+ /*
+ * Check possible error conditions.
+ * If error is returned, don't touch any output parameters.
+ */
+ if ((info.name && !(name = dm_task_get_name(dmt)))
+ || (info.uuid && !(uuid = dm_task_get_uuid(dmt)))
+ || (info.status && !(tmp_status = strdup(params)))
+ || (info.target && !tmp_target && !(tmp_target = strdup(params))))
+ return DMP_ERR;
+
+ if (info.name) {
+ strlcpy(info.name, name, WWID_SIZE);
+ condlog(4, "%s: %s: name: \"%s\"", __func__, map_id, info.name);
+ }
+ if (info.uuid) {
+ strlcpy(info.uuid, uuid, DM_UUID_LEN);
+ condlog(4, "%s: %s: uuid: \"%s\"", __func__, map_id, info.uuid);
+ }
+
+ if (info.size) {
+ *info.size = length;
+ condlog(4, "%s: %s: size: %lld", __func__, map_id, *info.size);
+ }
+
+ if (info.dmi) {
+ memcpy(info.dmi, &dmi, sizeof(*info.dmi));
+ condlog(4, "%s: %s %d:%d, %d targets, %s table, %s, %s, %d opened, %u events",
+ __func__, map_id,
+ info.dmi->major, info.dmi->minor,
+ info.dmi->target_count,
+ info.dmi->live_table ? "live" :
+ info.dmi->inactive_table ? "inactive" : "no",
+ info.dmi->suspended ? "suspended" : "active",
+ info.dmi->read_only ? "ro" : "rw",
+ info.dmi->open_count,
+ info.dmi->event_nr);
+ }
+
+ if (info.target) {
+ *info.target = steal_ptr(tmp_target);
+ if (!tgt_set)
+ condlog(4, "%s: %s: target: \"%s\"", __func__, map_id, *info.target);
+ }
+
+ if (info.status) {
+ *info.status = steal_ptr(tmp_status);
+ condlog(4, "%s: %s: status: \"%s\"", __func__, map_id, *info.status);
+ }
+
+ return DMP_OK;
+}
+
+/* Helper: format a string describing the map for log messages */
+static const char* libmp_map_identifier(int flags, mapid_t id, char buf[BLK_DEV_SIZE])
+{
+ switch (flags & __DM_MAP_BY_MASK) {
+ case DM_MAP_BY_NAME:
+ case DM_MAP_BY_UUID:
+ return id.str;
+ case DM_MAP_BY_DEV:
+ safe_snprintf(buf, BLK_DEV_SIZE, "%d:%d", id._u.major, id._u.minor);
+ return buf;
+ case DM_MAP_BY_DEVT:
+ safe_snprintf(buf, BLK_DEV_SIZE, "%d:%d", major(id.devt), minor(id.devt));
+ return buf;
+ default:
+ safe_snprintf(buf, BLK_DEV_SIZE, "*invalid*");
+ return buf;
+ }
+}
+
+int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
+{
+ char idbuf[BLK_DEV_SIZE];
+
+ return libmp_mapinfo__(flags, id, info,
+ libmp_map_identifier(flags, id, idbuf));
+}
+
int
dm_get_info(const char *name, struct dm_info *info)
{
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 9438c2d..725889b 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -1,5 +1,6 @@
#ifndef _DEVMAPPER_H
#define _DEVMAPPER_H
+#include <linux/dm-ioctl.h>
#include "autoconfig.h"
#include "structs.h"
@@ -31,8 +32,77 @@ enum {
DMP_ERR,
DMP_OK,
DMP_NOT_FOUND,
+ DMP_NO_MATCH,
};
+/**
+ * enum mapinfo_flags: input flags for libmp_mapinfo()
+ */
+enum __mapinfo_flags {
+ /** DM_MAP_BY_NAME: identify map by device-mapper name from @name */
+ DM_MAP_BY_NAME = 0,
+ /** DM_MAP_BY_UUID: identify map by device-mapper UUID from @uuid */
+ DM_MAP_BY_UUID,
+ /** DM_MAP_BY_DEV: identify map by major/minor number from @dmi */
+ DM_MAP_BY_DEV,
+ /** DM_MAP_BY_DEVT: identify map by a dev_t */
+ DM_MAP_BY_DEVT,
+ __DM_MAP_BY_MASK = (1 << 3) - 1,
+ /* Fail if target type is not multipath */
+ MAPINFO_MPATH_ONLY = (1 << 3),
+ /* Fail if target type is not "partition" (linear) */
+ MAPINFO_PART_ONLY = (1 << 4),
+ __MAPINFO_TGT_TYPE = (MAPINFO_MPATH_ONLY | MAPINFO_PART_ONLY),
+};
+
+typedef union libmp_map_identifier {
+ const char *str;
+ struct {
+ int major;
+ int minor;
+ } _u;
+ dev_t devt;
+} mapid_t;
+
+typedef struct libmp_map_info {
+ /** @name: name of the map.
+ * If non-NULL, it must point to an array of WWID_SIZE bytes
+ */
+ char *name;
+ /** @uuid: UUID of the map.
+ * If non-NULL it must point to an array of DM_UUID_LEN bytes
+ */
+ char *uuid;
+ /** @dmi: Basic info, must point to a valid dm_info buffer if non-NULL */
+ struct dm_info *dmi;
+ /** @target: target params, *@target will be allocated if @target is non-NULL*/
+ char **target;
+ /** @size: target size. Will be ignored if @target is NULL */
+ unsigned long long *size;
+ /** @status: target status, *@status will be allocated if @status is non-NULL */
+ char **status;
+} mapinfo_t;
+
+/**
+ * libmp_mapinfo(): obtain information about a map from the kernel
+ * @param flags: see __mapinfo_flags above.
+ * Exactly one of DM_MAP_BY_NAME, DM_MAP_BY_UUID, and DM_MAP_BY_DEV must be set.
+ * @param id: string or major/minor to identify the map to query
+ * @param info: output parameters, see above. Non-NULL elements will be filled in.
+ * @returns:
+ * DMP_OK if successful.
+ * DMP_NOT_FOUND if the map wasn't found, or has no or multiple targets.
+ * DMP_NO_MATCH if the map didn't match @tgt_type (see above).
+ * DMP_ERR if some other error occurred.
+ *
+ * This function obtains the requested information for the device-mapper map
+ * identified by the input parameters.
+ * Output parameters are only filled in if the return value is DMP_OK.
+ * For target / status / size information, the map's table should contain
+ * only one target (usually multipath or linear).
+ */
+int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info);
+
int dm_prereq(unsigned int *v);
void skip_libmp_dm_init(void);
void libmp_dm_exit(void);
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index f58cb1d..48c2b67 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 {
put_multipath_config;
};
-LIBMULTIPATH_24.0.0 {
+LIBMULTIPATH_25.0.0 {
global:
/* symbols referenced by multipath and multipathd */
add_foreign;
@@ -134,6 +134,7 @@ global:
libmp_get_version;
libmp_get_multipath_config;
libmp_dm_task_run;
+ libmp_mapinfo;
libmp_put_multipath_config;
libmp_udev_set_sync_support;
libmultipath_exit;
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 20/49] libmultipath tests: add tests for libmp_mapinfo()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (18 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 19/49] libmultipath: add libmp_mapinfo() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 21/49] libmultipath: implement dm_get_info() and dm_map_present() with new API Martin Wilck
` (28 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Unfortunately, we need several ugly compatibility macros again
in order to make these tests work with the entire set of compilers
and libraries supported by multipath-tools. Details are found in
comments in the code.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.h | 1 +
tests/Makefile | 3 +-
tests/mapinfo.c | 1175 ++++++++++++++++++++++++++++++++++++++
3 files changed, 1178 insertions(+), 1 deletion(-)
create mode 100644 tests/mapinfo.c
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 725889b..62f50de 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -1,5 +1,6 @@
#ifndef _DEVMAPPER_H
#define _DEVMAPPER_H
+#include <sys/sysmacros.h>
#include <linux/dm-ioctl.h>
#include "autoconfig.h"
#include "structs.h"
diff --git a/tests/Makefile b/tests/Makefile
index 8afa8c6..55fbf0f 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -9,7 +9,7 @@ CFLAGS += $(BIN_CFLAGS) -Wno-unused-parameter $(W_MISSING_INITIALIZERS)
LIBDEPS += -L. -L $(mpathutildir) -L$(mpathcmddir) -lmultipath -lmpathutil -lmpathcmd -lcmocka
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
- alias directio valid devt mpathvalid strbuf sysfs features cli
+ alias directio valid devt mpathvalid strbuf sysfs features cli mapinfo
HELPERS := test-lib.o test-log.o
.PRECIOUS: $(TESTS:%=%-test)
@@ -68,6 +68,7 @@ sysfs-test_OBJDEPS := $(multipathdir)/sysfs.o $(mpathutildir)/util.o
sysfs-test_LIBDEPS := -ludev -lpthread -ldl
features-test_LIBDEPS := -ludev -lpthread
cli-test_OBJDEPS := $(daemondir)/cli.o
+mapinfo-test_LIBDEPS = -lpthread -ldevmapper
%.o: %.c
@echo building $@ because of $?
diff --git a/tests/mapinfo.c b/tests/mapinfo.c
new file mode 100644
index 0000000..f3a8440
--- /dev/null
+++ b/tests/mapinfo.c
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (c) 2024 Martin Wilck, SUSE
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+/*
+ * glibc <= 2.19 (Ubuntu Trusty, Debian Jessie) uses macros to inline strdup(),
+ * which makes our strdup wrapper fail.
+ */
+#define _GNU_SOURCE 1
+#include <features.h>
+#include <linux/types.h>
+#ifndef __GLIBC_PREREQ
+#define __GLIBC_PREREQ(x, y) 0
+#endif
+#if defined(__GLIBC__) && !(__GLIBC_PREREQ(2, 20))
+#define __NO_STRING_INLINES 1
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <cmocka.h>
+#include "util.h"
+#include "devmapper.h"
+#include "globals.c"
+/*
+ * We can't just use mapinfo-test_OBJDEPS because
+ */
+#include "../libmultipath/devmapper.c"
+
+static const struct dm_info __attribute__((unused)) MPATH_DMI_01 = {
+ .exists = 1,
+ .live_table = 1,
+ .open_count = 1,
+ .target_count = 1,
+ .major = 254,
+ .minor = 123,
+};
+
+static const char MPATH_NAME_01[] = "mpathx";
+static const char MPATH_UUID_01[] = "mpath-3600a098038302d414b2b4d4453474f62";
+static const char MPATH_TARGET_01[] =
+ "2 pg_init_retries 50 1 alua 2 1 "
+ "service-time 0 3 2 65:32 1 1 67:64 1 1 69:96 1 1 "
+ "service-time 0 3 2 8:16 1 1 66:48 1 1 68:80 1 1 ";
+static const char MPATH_STATUS_01[] =
+ "2 0 1 0 2 1 "
+ "A 0 3 2 65:32 A 0 0 1 67:64 A 0 0 1 69:96 A 0 0 1 "
+ "E 0 3 2 8:16 A 0 0 1 66:48 A 0 0 1 68:80 A 0 0 1 ";
+
+char *__real_strdup(const char *str);
+char *__wrap_strdup(const char *str)
+{
+ if (mock_type(int))
+ return __real_strdup(str);
+ return NULL;
+}
+
+void __wrap_dm_task_destroy(struct dm_task *t)
+{
+}
+
+struct dm_task *__wrap_dm_task_create(int task)
+{
+ check_expected(task);
+ return mock_ptr_type(void *);
+}
+
+int __wrap_dm_task_run(struct dm_task *t)
+{
+ return mock_type(int);
+}
+
+/*
+ * Hack for older versions of libdevmapper, where dm_task_get_errno()
+ * is not available.
+ */
+#ifndef LIBDM_API_GET_ERRNO
+#define WILL_RETURN_GET_ERRNO(y) do { errno = y; } while (0)
+#else
+int __wrap_dm_task_get_errno(struct dm_task *t)
+{
+ return mock_type(int);
+}
+#define WILL_RETURN_GET_ERRNO(y) will_return(__wrap_dm_task_get_errno, y)
+#endif
+
+int __wrap_dm_task_set_name(struct dm_task *t, const char *name)
+{
+ check_expected(name);
+ return mock_type(int);
+}
+
+int __wrap_dm_task_set_uuid(struct dm_task *t, const char *uuid)
+{
+ check_expected(uuid);
+ return mock_type(int);
+}
+
+int __wrap_dm_task_set_major(struct dm_task *t, int val)
+{
+ check_expected(val);
+ return mock_type(int);
+}
+
+int __wrap_dm_task_set_minor(struct dm_task *t, int val)
+{
+ check_expected(val);
+ return mock_type(int);
+}
+
+/* between LVM2 2.02.110 and 2.02.112, dm_task_get_info was a macro */
+#ifdef dm_task_get_info
+#define WRAP_DM_TASK_GET_INFO(x) \
+ will_return(__wrap_dm_task_get_info_with_deferred_remove, x)
+int __wrap_dm_task_get_info_with_deferred_remove(struct dm_task *t, struct dm_info *dmi)
+#else
+#define WRAP_DM_TASK_GET_INFO(x) \
+ will_return(__wrap_dm_task_get_info, x)
+int __wrap_dm_task_get_info(struct dm_task *t, struct dm_info *dmi)
+#endif
+{
+ int rc = mock_type(int);
+
+ assert_non_null(dmi);
+ if (rc) {
+ struct dm_info *info = mock_ptr_type(struct dm_info *);
+
+ memcpy(dmi, info, sizeof(*dmi));
+ }
+ return rc;
+}
+
+void * __wrap_dm_get_next_target(struct dm_task *dmt, void *next,
+ uint64_t *start, uint64_t *length,
+ char **target_type, char **params)
+{
+ *start = 0;
+ *length = mock_type(uint64_t);
+ *target_type = mock_ptr_type(char *);
+ *params = mock_ptr_type(char *);
+ return mock_ptr_type(void *);
+}
+
+static void mock_dm_get_next_target(uint64_t len, const char *target_type,
+ const char *params, void *next)
+{
+ will_return(__wrap_dm_get_next_target, len);
+ will_return(__wrap_dm_get_next_target, target_type);
+ will_return(__wrap_dm_get_next_target, params);
+ will_return(__wrap_dm_get_next_target, next);
+}
+
+const char *__wrap_dm_task_get_name(struct dm_task *t)
+{
+ return mock_ptr_type(const char *);
+}
+
+const char *__wrap_dm_task_get_uuid(struct dm_task *t)
+{
+ return mock_ptr_type(const char *);
+}
+
+static void mock_mapinfo_name_1(int ioctl_nr, int create_rc, const char *name,
+ int name_rc, int run_rc, int err)
+{
+ expect_value(__wrap_dm_task_create, task, ioctl_nr);
+ will_return(__wrap_dm_task_create, create_rc);
+ if (create_rc == 0)
+ return;
+ expect_value(__wrap_dm_task_set_name, name, name);
+ will_return(__wrap_dm_task_set_name, name_rc);
+ if (name_rc == 0)
+ return;
+ will_return(__wrap_dm_task_run, run_rc);
+ if (run_rc == 0) {
+ WILL_RETURN_GET_ERRNO(err);
+ /* for dm_log_error() */
+ WILL_RETURN_GET_ERRNO(err);
+ }
+}
+
+static void test_mapinfo_bad_task_create_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 0, NULL, 0, 0, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_mapid(void **state)
+{
+ int rc;
+
+ /* can't use mock_mapinfo_name() here because of invalid id type */
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME + 100,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_set_name(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 0, 0, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_task_run_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 0, EINVAL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_task_run_02(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 0, ENXIO);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+}
+
+/* libmp_mapinfo must choose DM_DEVICE_STATUS */
+static void test_mapinfo_bad_task_run_03(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 0, EINVAL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_task_run_04(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 0, ENXIO);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+}
+
+/* If target is set, libmp_mapinfo must choose DM_DEVICE_TABLE */
+static void test_mapinfo_bad_task_run_05(void **state)
+{
+ int rc;
+ char *params = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 0, EINVAL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = ¶ms });
+ assert_int_equal(rc, DMP_ERR);
+ assert_ptr_equal(params, NULL);
+}
+
+static void test_mapinfo_bad_task_run_06(void **state)
+{
+ int rc;
+ char *params = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 0, ENXIO);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = ¶ms });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+ assert_ptr_equal(params, NULL);
+}
+
+/* If status is set, libmp_mapinfo must choose DM_DEVICE_STATUS */
+static void test_mapinfo_bad_task_run_07(void **state)
+{
+ int rc;
+ char *params = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 0, EINVAL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = ¶ms });
+ assert_int_equal(rc, DMP_ERR);
+ assert_ptr_equal(params, NULL);
+}
+
+static void test_mapinfo_bad_task_run_08(void **state)
+{
+ int rc;
+ char *params = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 0, ENXIO);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = ¶ms });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+ assert_ptr_equal(params, NULL);
+}
+
+static void test_mapinfo_bad_task_run_09(void **state)
+{
+ int rc;
+ char *params = NULL, *status = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 0, EINVAL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = ¶ms, .status = &status });
+ assert_int_equal(rc, DMP_ERR);
+ assert_ptr_equal(params, NULL);
+ assert_ptr_equal(status, NULL);
+}
+
+static void test_mapinfo_bad_task_run_10(void **state)
+{
+ int rc;
+ char *params = NULL, *status = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 0, ENXIO);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = ¶ms, .status = &status });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+ assert_ptr_equal(params, NULL);
+ assert_ptr_equal(status, NULL);
+}
+
+static void test_mapinfo_bad_get_info_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(0);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_get_info_02(void **state)
+{
+ int rc;
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&dmi);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+}
+
+static void test_mapinfo_bad_get_info_03(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(0);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_get_info_04(void **state)
+{
+ int rc;
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&dmi);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+}
+
+static void test_mapinfo_good_exists(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_bad_set_uuid(void **state)
+{
+ int rc;
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_uuid, uuid, "foo");
+ will_return(__wrap_dm_task_set_uuid, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_set_dev_01(void **state)
+{
+ int rc;
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_major, val, 254);
+ will_return(__wrap_dm_task_set_major, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_DEV,
+ (mapid_t) { ._u = { 254, 123 } },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_set_dev_02(void **state)
+{
+ int rc;
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_major, val, 254);
+ will_return(__wrap_dm_task_set_major, 1);
+ expect_value(__wrap_dm_task_set_minor, val, 123);
+ will_return(__wrap_dm_task_set_minor, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_DEV,
+ (mapid_t) { ._u = { 254, 123 } },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_set_dev_03(void **state)
+{
+ int rc;
+ dev_t devt = makedev(254, 123);
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_major, val, 254);
+ will_return(__wrap_dm_task_set_major, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_DEVT,
+ (mapid_t) { .devt = devt },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_set_dev_04(void **state)
+{
+ int rc;
+ dev_t devt = makedev(254, 123);
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_major, val, 254);
+ will_return(__wrap_dm_task_set_major, 1);
+ expect_value(__wrap_dm_task_set_minor, val, 123);
+ will_return(__wrap_dm_task_set_minor, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_DEVT,
+ (mapid_t) { .devt = devt },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_good_info(void **state)
+{
+ int rc;
+ struct dm_info dmi;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .dmi = &dmi });
+ assert_int_equal(rc, DMP_OK);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+}
+
+static void test_mapinfo_good_by_uuid_info(void **state)
+{
+ int rc;
+ struct dm_info dmi;
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_uuid, uuid, "foo");
+ will_return(__wrap_dm_task_set_uuid, 1);
+ will_return(__wrap_dm_task_run, 1);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ rc = libmp_mapinfo(DM_MAP_BY_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .dmi = &dmi });
+ assert_int_equal(rc, DMP_OK);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+}
+
+static void test_mapinfo_good_by_dev_info(void **state)
+{
+ int rc;
+ struct dm_info dmi;
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_major, val, 254);
+ will_return(__wrap_dm_task_set_major, 1);
+ expect_value(__wrap_dm_task_set_minor, val, 123);
+ will_return(__wrap_dm_task_set_minor, 1);
+ will_return(__wrap_dm_task_run, 1);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ rc = libmp_mapinfo(DM_MAP_BY_DEV,
+ (mapid_t) { ._u = { 254, 123 } },
+ (mapinfo_t) { .dmi = &dmi });
+ assert_int_equal(rc, DMP_OK);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+}
+
+static void test_mapinfo_good_by_devt_info(void **state)
+{
+ dev_t devt = makedev(254, 123);
+ int rc;
+ struct dm_info dmi;
+
+ expect_value(__wrap_dm_task_create, task, DM_DEVICE_INFO);
+ will_return(__wrap_dm_task_create, 1);
+ expect_value(__wrap_dm_task_set_major, val, 254);
+ will_return(__wrap_dm_task_set_major, 1);
+ expect_value(__wrap_dm_task_set_minor, val, 123);
+ will_return(__wrap_dm_task_set_minor, 1);
+ will_return(__wrap_dm_task_run, 1);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ rc = libmp_mapinfo(DM_MAP_BY_DEVT,
+ (mapid_t) { .devt = devt },
+ (mapinfo_t) { .dmi = &dmi });
+ assert_int_equal(rc, DMP_OK);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+}
+
+static void test_mapinfo_bad_name(void **state)
+{
+ int rc;
+ char name[WWID_SIZE] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_name, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = name });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_good_name(void **state)
+{
+ int rc;
+ char name[WWID_SIZE] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = name });
+ assert_int_equal(rc, DMP_OK);
+ assert_true(!strcmp(name, MPATH_NAME_01));
+}
+
+static void test_mapinfo_bad_uuid(void **state)
+{
+ int rc;
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .uuid = uuid });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_good_uuid(void **state)
+{
+ int rc;
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .uuid = uuid });
+ assert_int_equal(rc, DMP_OK);
+ assert_true(!strcmp(uuid, MPATH_UUID_01));
+}
+
+/* If size is set, libmp_mapinfo needs to do a DM_DEVICE_STATUS ioctl */
+static void test_mapinfo_good_size(void **state)
+{
+ int rc;
+ unsigned long long size;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, NULL, MPATH_TARGET_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .size = &size });
+ assert_int_equal(rc, DMP_OK);
+ assert_int_equal(size, 12345);
+}
+
+static void test_mapinfo_bad_next_target_01(void **state)
+{
+ int rc;
+ unsigned long long size;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ /* multiple targets */
+ mock_dm_get_next_target(12345, NULL, MPATH_STATUS_01, (void *)1);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .size = &size });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+}
+
+static void test_mapinfo_bad_next_target_02(void **state)
+{
+ int rc;
+ unsigned long long size;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ /* no targets */
+ mock_dm_get_next_target(12345, NULL, NULL, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .size = &size });
+ assert_int_equal(rc, DMP_NOT_FOUND);
+}
+
+/* libmp_mapinfo needs to do a DM_DEVICE_STATUS ioctl */
+static void test_mapinfo_bad_target_type_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, "linear", MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_target_type_02(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_target_type_03(void **state)
+{
+ int rc;
+ struct dm_info dmi = { .suspended = 0 };
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_PART, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .dmi = &dmi, .name = name, .uuid = uuid });
+ assert_int_equal(rc, DMP_NO_MATCH);
+ /* make sure memory content is not changed */
+ assert_memory_equal(&dmi, &((struct dm_info) { .exists = 0 }), sizeof(dmi));
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+}
+
+static void test_mapinfo_bad_target_type_04(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = &status });
+ assert_int_equal(rc, DMP_NO_MATCH);
+ assert_null(status);
+}
+
+static void test_mapinfo_bad_target_type_05(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *target = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = &target });
+ assert_int_equal(rc, DMP_NO_MATCH);
+ assert_null(target);
+}
+
+static void test_mapinfo_good_target_type_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_good_target_type_02(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_PART, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_good_target_type_03(void **state)
+{
+ int rc;
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .dmi = &dmi });
+ assert_int_equal(rc, DMP_OK);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+}
+
+/* test for returning multiple parameters */
+static void test_mapinfo_good_target_type_04(void **state)
+{
+ int rc;
+ struct dm_info dmi = { .suspended = 0 };
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .dmi = &dmi, .name = name, .uuid = uuid });
+ assert_int_equal(rc, DMP_OK);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+ assert_true(!strcmp(name, MPATH_NAME_01));
+ assert_true(!strcmp(uuid, MPATH_UUID_01));
+}
+
+static void test_mapinfo_good_status_01(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_strdup, 1);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = &status });
+ assert_int_equal(rc, DMP_OK);
+ assert_non_null(status);
+ assert_true(!strcmp(status, MPATH_STATUS_01));
+}
+
+static void test_mapinfo_bad_strdup_01(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ will_return(__wrap_strdup, 0);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = &status, .uuid = uuid, .name = name });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+
+}
+
+static void test_mapinfo_bad_get_name_01(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = &status, .uuid = uuid, .name = name });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+
+}
+
+static void test_mapinfo_bad_get_uuid_01(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ will_return(__wrap_dm_task_get_uuid, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .status = &status, .uuid = uuid, .name = name });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+
+}
+
+static void test_mapinfo_bad_task_run_11(void **state)
+{
+ int rc;
+ char *params = NULL, *status = NULL;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, NULL, MPATH_TARGET_01, NULL);
+ will_return(__wrap_strdup, 1);
+ /* error in 2nd dm_task_run */
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 0, EINVAL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = ¶ms, .status = &status });
+ assert_int_equal(rc, DMP_ERR);
+ assert_ptr_equal(params, NULL);
+ assert_ptr_equal(status, NULL);
+}
+
+static void test_mapinfo_bad_get_name_02(void **state)
+{
+ int rc;
+ char *target = NULL, *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_TARGET_01, NULL);
+ will_return(__wrap_strdup, 1);
+ /* 2nd ioctl */
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, NULL);
+
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) {
+ .target = &target, .status = &status,
+ .uuid = uuid, .name = name, .dmi = &dmi });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_null(target);
+ assert_memory_equal(&dmi, &((struct dm_info) { .suspended = 0 }), sizeof(dmi));
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+}
+
+static void test_mapinfo_bad_get_uuid_02(void **state)
+{
+ int rc;
+ char *target = NULL, *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_TARGET_01, NULL);
+ will_return(__wrap_strdup, 1);
+ /* 2nd ioctl */
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ will_return(__wrap_dm_task_get_uuid, NULL);
+
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) {
+ .target = &target, .status = &status,
+ .uuid = uuid, .name = name, .dmi = &dmi });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_null(target);
+ assert_memory_equal(&dmi, &((struct dm_info) { .suspended = 0 }), sizeof(dmi));
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+}
+
+static void test_mapinfo_bad_strdup_02(void **state)
+{
+ int rc;
+ char *target = NULL, *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_TARGET_01, NULL);
+ will_return(__wrap_strdup, 1);
+ /* 2nd ioctl */
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ will_return(__wrap_strdup, 0);
+
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) {
+ .target = &target, .status = &status,
+ .uuid = uuid, .name = name, .dmi = &dmi });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_null(target);
+ assert_memory_equal(&dmi, &((struct dm_info) { .suspended = 0 }), sizeof(dmi));
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+}
+
+static void test_mapinfo_bad_strdup_03(void **state)
+{
+ int rc;
+ char *target = NULL, *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+ struct dm_info dmi = { .suspended = 0 };
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_TARGET_01, NULL);
+ will_return(__wrap_strdup, 0);
+ /* No 2nd ioctl, as there was an error in the 1st */
+
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) {
+ .target = &target, .status = &status,
+ .uuid = uuid, .name = name, .dmi = &dmi });
+ assert_int_equal(rc, DMP_ERR);
+ assert_null(status);
+ assert_null(target);
+ assert_memory_equal(&dmi, &((struct dm_info) { .suspended = 0 }), sizeof(dmi));
+ assert_memory_equal(&name, &((char[WWID_SIZE]) { 0 }), WWID_SIZE);
+ assert_memory_equal(&uuid, &((char[DM_UUID_LEN]) { 0 }), DM_UUID_LEN);
+}
+
+static void test_mapinfo_good_all_01(void **state)
+{
+ int rc;
+ char __attribute__((cleanup(cleanup_charp))) *target = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+ char name[WWID_SIZE] = { 0 };
+ char uuid[DM_UUID_LEN] = { 0 };
+ struct dm_info dmi = { .suspended = 0 };
+ unsigned long long size;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_TARGET_01, NULL);
+ will_return(__wrap_strdup, 1);
+ /* 2nd ioctl */
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_name, MPATH_NAME_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ will_return(__wrap_strdup, 1);
+
+ rc = libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) {
+ .target = &target, .status = &status,
+ .uuid = uuid, .name = name,
+ .dmi = &dmi, .size = &size });
+ assert_int_equal(rc, DMP_OK);
+ assert_non_null(status);
+ assert_non_null(target);
+ assert_int_equal(size, 12345);
+ assert_memory_equal(&dmi, &MPATH_DMI_01, sizeof(dmi));
+ assert_true(!strcmp(target, MPATH_TARGET_01));
+ assert_true(!strcmp(status, MPATH_STATUS_01));
+ assert_true(!strcmp(name, MPATH_NAME_01));
+ assert_true(!strcmp(uuid, MPATH_UUID_01));
+}
+
+static int test_mapinfo(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_mapinfo_bad_task_create_01),
+ cmocka_unit_test(test_mapinfo_bad_mapid),
+ cmocka_unit_test(test_mapinfo_bad_set_name),
+ cmocka_unit_test(test_mapinfo_bad_task_run_01),
+ cmocka_unit_test(test_mapinfo_bad_task_run_02),
+ cmocka_unit_test(test_mapinfo_bad_task_run_03),
+ cmocka_unit_test(test_mapinfo_bad_task_run_04),
+ cmocka_unit_test(test_mapinfo_bad_task_run_05),
+ cmocka_unit_test(test_mapinfo_bad_task_run_06),
+ cmocka_unit_test(test_mapinfo_bad_task_run_07),
+ cmocka_unit_test(test_mapinfo_bad_task_run_08),
+ cmocka_unit_test(test_mapinfo_bad_task_run_09),
+ cmocka_unit_test(test_mapinfo_bad_task_run_10),
+ cmocka_unit_test(test_mapinfo_bad_task_run_11),
+ cmocka_unit_test(test_mapinfo_bad_get_info_01),
+ cmocka_unit_test(test_mapinfo_bad_get_info_02),
+ cmocka_unit_test(test_mapinfo_bad_get_info_03),
+ cmocka_unit_test(test_mapinfo_bad_get_info_04),
+ cmocka_unit_test(test_mapinfo_good_exists),
+ cmocka_unit_test(test_mapinfo_bad_set_uuid),
+ cmocka_unit_test(test_mapinfo_bad_set_dev_01),
+ cmocka_unit_test(test_mapinfo_bad_set_dev_02),
+ cmocka_unit_test(test_mapinfo_bad_set_dev_03),
+ cmocka_unit_test(test_mapinfo_bad_set_dev_04),
+ cmocka_unit_test(test_mapinfo_good_info),
+ cmocka_unit_test(test_mapinfo_good_by_uuid_info),
+ cmocka_unit_test(test_mapinfo_good_by_dev_info),
+ cmocka_unit_test(test_mapinfo_good_by_devt_info),
+ cmocka_unit_test(test_mapinfo_bad_name),
+ cmocka_unit_test(test_mapinfo_good_name),
+ cmocka_unit_test(test_mapinfo_bad_uuid),
+ cmocka_unit_test(test_mapinfo_good_uuid),
+ cmocka_unit_test(test_mapinfo_good_size),
+ cmocka_unit_test(test_mapinfo_bad_next_target_01),
+ cmocka_unit_test(test_mapinfo_bad_next_target_02),
+ cmocka_unit_test(test_mapinfo_bad_target_type_01),
+ cmocka_unit_test(test_mapinfo_bad_target_type_02),
+ cmocka_unit_test(test_mapinfo_bad_target_type_03),
+ cmocka_unit_test(test_mapinfo_bad_target_type_04),
+ cmocka_unit_test(test_mapinfo_bad_target_type_05),
+ cmocka_unit_test(test_mapinfo_good_target_type_01),
+ cmocka_unit_test(test_mapinfo_good_target_type_02),
+ cmocka_unit_test(test_mapinfo_good_target_type_03),
+ cmocka_unit_test(test_mapinfo_good_target_type_04),
+ cmocka_unit_test(test_mapinfo_good_status_01),
+ cmocka_unit_test(test_mapinfo_bad_get_name_01),
+ cmocka_unit_test(test_mapinfo_bad_get_uuid_01),
+ cmocka_unit_test(test_mapinfo_bad_strdup_01),
+ cmocka_unit_test(test_mapinfo_bad_get_name_02),
+ cmocka_unit_test(test_mapinfo_bad_get_uuid_02),
+ cmocka_unit_test(test_mapinfo_bad_strdup_02),
+ cmocka_unit_test(test_mapinfo_bad_strdup_03),
+ cmocka_unit_test(test_mapinfo_good_all_01),
+ };
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+
+int main(void)
+{
+ int ret = 0;
+
+ init_test_verbosity(4);
+ skip_libmp_dm_init();
+ ret += test_mapinfo();
+ return ret;
+}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 21/49] libmultipath: implement dm_get_info() and dm_map_present() with new API
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (19 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 20/49] libmultipath tests: add tests for libmp_mapinfo() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 22/49] libmultipath: remove dm_get_prefixed_uuid() Martin Wilck
` (27 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 54 ++++---------------------------
libmultipath/devmapper.h | 16 +++++++--
libmultipath/libmultipath.version | 2 --
multipathd/main.c | 4 +--
4 files changed, 23 insertions(+), 53 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 4e6b5b2..754f45e 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -794,45 +794,6 @@ int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
libmp_map_identifier(flags, id, idbuf));
}
-int
-dm_get_info(const char *name, struct dm_info *info)
-{
- int r = -1;
- struct dm_task *dmt;
-
- if (!name || !info)
- return r;
-
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
- return r;
-
- if (!dm_task_set_name(dmt, name))
- goto out;
-
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_INFO, dmt);
- goto out;
- }
-
- if (!dm_task_get_info(dmt, info))
- goto out;
-
- if (!info->exists)
- goto out;
-
- r = 0;
-out:
- dm_task_destroy(dmt);
- return r;
-}
-
-int dm_map_present(const char * str)
-{
- struct dm_info info;
-
- return (dm_get_info(str, &info) == 0);
-}
-
int dm_get_map(const char *name, unsigned long long *size, char **outparams)
{
struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
@@ -1131,15 +1092,14 @@ out:
return r;
}
-static int
-dm_dev_t (const char * mapname, char * dev_t, int len)
+static int dm_dev_t (const char *mapname, char *dev_t, int len)
{
struct dm_info info;
- if (dm_get_info(mapname, &info) != 0)
+ if (dm_get_info(mapname, &info) != DMP_OK)
return 1;
- if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
+ if (safe_snprintf(dev_t, len, "%i:%i", info.major, info.minor))
return 1;
return 0;
@@ -1180,7 +1140,7 @@ dm_get_major_minor(const char *name, int *major, int *minor)
{
struct dm_info info;
- if (dm_get_info(name, &info) != 0)
+ if (dm_get_info(name, &info) != DMP_OK)
return -1;
*major = info.major;
@@ -1526,7 +1486,7 @@ dm_geteventnr (const char *name)
{
struct dm_info info;
- if (dm_get_info(name, &info) != 0)
+ if (dm_get_info(name, &info) != DMP_OK)
return -1;
return info.event_nr;
@@ -1537,7 +1497,7 @@ dm_is_suspended(const char *name)
{
struct dm_info info;
- if (dm_get_info(name, &info) != 0)
+ if (dm_get_info(name, &info) != DMP_OK)
return -1;
return info.suspended;
@@ -1689,7 +1649,7 @@ dm_get_deferred_remove (const char * mapname)
{
struct dm_info info;
- if (dm_get_info(mapname, &info) != 0)
+ if (dm_get_info(mapname, &info) != DMP_OK)
return -1;
return info.deferred_remove;
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 62f50de..6fa99be 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -104,6 +104,20 @@ typedef struct libmp_map_info {
*/
int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info);
+static inline int dm_get_info(const char *mapname, struct dm_info *info)
+{
+ return libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = mapname },
+ (mapinfo_t) { .dmi = info });
+}
+
+static inline int dm_map_present(const char *mapname)
+{
+ return libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = mapname },
+ (mapinfo_t) { .name = NULL }) == DMP_OK;
+}
+
int dm_prereq(unsigned int *v);
void skip_libmp_dm_init(void);
void libmp_dm_exit(void);
@@ -113,7 +127,6 @@ int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags);
int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags);
int dm_addmap_create (struct multipath *mpp, char *params);
int dm_addmap_reload (struct multipath *mpp, char *params, int flush);
-int dm_map_present (const char *name);
int dm_map_present_by_uuid(const char *uuid);
int dm_get_map(const char *name, unsigned long long *size, char **outparams);
int dm_get_status(const char *name, char **outstatus);
@@ -164,7 +177,6 @@ int dm_get_major_minor (const char *name, int *major, int *minor);
char * dm_mapname(int major, int minor);
int dm_get_uuid(const char *name, char *uuid, int uuid_len);
bool has_dm_info(const struct multipath *mpp);
-int dm_get_info (const char * mapname, struct dm_info *dmi);
int dm_rename (const char * old, char * new, char * delim, int skip_kpartx);
int dm_reassign(const char * mapname);
int dm_reassign_table(const char *name, char *old, char *new);
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 48c2b67..7a50349 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -78,14 +78,12 @@ global:
dm_flush_map_nopaths;
dm_flush_maps;
dm_geteventnr;
- dm_get_info;
dm_get_major_minor;
dm_get_maps;
dm_get_multipath;
dm_get_uuid;
dm_is_mpath;
dm_mapname;
- dm_map_present;
dm_prereq;
dm_queue_if_no_path;
dm_reassign;
diff --git a/multipathd/main.c b/multipathd/main.c
index 132bb2e..394ca7d 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -502,7 +502,7 @@ remove_maps_and_stop_waiters(struct vectors *vecs)
int refresh_multipath(struct vectors *vecs, struct multipath *mpp)
{
- if (dm_get_info(mpp->alias, &mpp->dmi)) {
+ if (dm_get_info(mpp->alias, &mpp->dmi) != DMP_OK) {
/* Error accessing table */
condlog(2, "%s: cannot access table", mpp->alias);
goto out;
@@ -722,7 +722,7 @@ add_map_without_path (struct vectors *vecs, const char *alias)
mpp->alias = strdup(alias);
- if (dm_get_info(mpp->alias, &mpp->dmi)) {
+ if (dm_get_info(mpp->alias, &mpp->dmi) != DMP_OK) {
condlog(3, "%s: cannot access table", mpp->alias);
goto out;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 22/49] libmultipath: remove dm_get_prefixed_uuid()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (20 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 21/49] libmultipath: implement dm_get_info() and dm_map_present() with new API Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 23/49] libmultipath: is_mpath_part(): improve parsing Martin Wilck
` (26 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
... and replace it by calls to the new API.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 53 +++++++++-------------------------------
1 file changed, 11 insertions(+), 42 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 754f45e..0bc5e34 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -794,6 +794,13 @@ int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
libmp_map_identifier(flags, id, idbuf));
}
+static int dm_get_dm_uuid(const char *mapname, char uuid[DM_UUID_LEN])
+{
+ return libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = mapname },
+ (mapinfo_t) { .uuid = uuid });
+}
+
int dm_get_map(const char *name, unsigned long long *size, char **outparams)
{
struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
@@ -833,48 +840,11 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
}
}
-static int
-dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len)
-{
- struct dm_task *dmt;
- const char *uuidtmp;
- struct dm_info info;
- int r = 1;
-
- dmt = libmp_dm_task_create(DM_DEVICE_INFO);
- if (!dmt)
- return 1;
-
- if (uuid_len > 0)
- uuid[0] = '\0';
-
- if (!dm_task_set_name (dmt, name))
- goto uuidout;
-
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_INFO, dmt);
- goto uuidout;
- }
-
- if (!dm_task_get_info(dmt, &info) ||
- !info.exists)
- goto uuidout;
-
- uuidtmp = dm_task_get_uuid(dmt);
- if (uuidtmp)
- strlcpy(uuid, uuidtmp, uuid_len);
-
- r = 0;
-uuidout:
- dm_task_destroy(dmt);
- return r;
-}
-
int dm_get_uuid(const char *name, char *uuid, int uuid_len)
{
char tmp[DM_UUID_LEN];
- if (dm_get_prefixed_uuid(name, tmp, sizeof(tmp)))
+ if (dm_get_dm_uuid(name, tmp) != DMP_OK)
return 1;
if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
@@ -885,16 +855,15 @@ int dm_get_uuid(const char *name, char *uuid, int uuid_len)
return 0;
}
-static int
-is_mpath_part(const char *part_name, const char *map_name)
+static int is_mpath_part(const char *part_name, const char *map_name)
{
char *p;
char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN];
- if (dm_get_prefixed_uuid(part_name, part_uuid, sizeof(part_uuid)))
+ if (dm_get_dm_uuid(part_name, part_uuid) != DMP_OK)
return 0;
- if (dm_get_prefixed_uuid(map_name, map_uuid, sizeof(map_uuid)))
+ if (dm_get_dm_uuid(map_name, map_uuid) != DMP_OK)
return 0;
if (strncmp(part_uuid, "part", 4) != 0)
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 23/49] libmultipath: is_mpath_part(): improve parsing
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (21 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 22/49] libmultipath: remove dm_get_prefixed_uuid() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 24/49] libmultipath: rename dm_get_uuid() -> dm_get_wwid() Martin Wilck
` (25 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Use sscanf to make the parsing of the UUID more robust.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 0bc5e34..f80fbdf 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -857,23 +857,20 @@ int dm_get_uuid(const char *name, char *uuid, int uuid_len)
static int is_mpath_part(const char *part_name, const char *map_name)
{
- char *p;
- char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN];
+ char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN], c;
+ int np, nc;
if (dm_get_dm_uuid(part_name, part_uuid) != DMP_OK)
return 0;
+ if (2 != sscanf(part_uuid, "part%d-%n" UUID_PREFIX "%c", &np, &nc, &c)
+ || np <= 0)
+ return 0;
+
if (dm_get_dm_uuid(map_name, map_uuid) != DMP_OK)
return 0;
- if (strncmp(part_uuid, "part", 4) != 0)
- return 0;
-
- p = strstr(part_uuid, UUID_PREFIX);
- if (p && !strcmp(p, map_uuid))
- return 1;
-
- return 0;
+ return !strcmp(part_uuid + nc, map_uuid);
}
int dm_get_status(const char *name, char **outstatus)
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 24/49] libmultipath: rename dm_get_uuid() -> dm_get_wwid()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (22 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 23/49] libmultipath: is_mpath_part(): improve parsing Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 25/49] libmultipath: improve dm_get_wwid() return value logic Martin Wilck
` (24 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
... to make the distinction between WWID (multipath) and
UUID (device mapper) a little more obvious.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/alias.c | 2 +-
libmultipath/configure.c | 4 ++--
libmultipath/devmapper.c | 4 ++--
libmultipath/devmapper.h | 2 +-
libmultipath/libmultipath.version | 2 +-
libmultipath/wwids.c | 2 +-
multipathd/main.c | 2 +-
tests/alias.c | 30 +++++++++++++++---------------
8 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index a54616c..10e58a7 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -410,7 +410,7 @@ static bool alias_already_taken(const char *alias, const char *map_wwid)
char wwid[WWID_SIZE];
/* If the map doesn't exist, it's fine */
- if (dm_get_uuid(alias, wwid, sizeof(wwid)) != 0)
+ if (dm_get_wwid(alias, wwid, sizeof(wwid)) != 0)
return false;
/* If both the name and the wwid match, it's fine.*/
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index b5c701f..666d4e8 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -846,7 +846,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
if (mpp->action == ACT_CREATE && dm_map_present(mpp->alias)) {
char wwid[WWID_SIZE];
- if (dm_get_uuid(mpp->alias, wwid, sizeof(wwid)) == 0) {
+ if (dm_get_wwid(mpp->alias, wwid, sizeof(wwid)) == 0) {
if (!strncmp(mpp->wwid, wwid, sizeof(wwid))) {
condlog(3, "%s: map already present",
mpp->alias);
@@ -1320,7 +1320,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev,
break;
case DEV_DEVMAP:
- if (((dm_get_uuid(dev, tmpwwid, WWID_SIZE)) == 0)
+ if (((dm_get_wwid(dev, tmpwwid, WWID_SIZE)) == 0)
&& (strlen(tmpwwid)))
refwwid = tmpwwid;
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index f80fbdf..3fca08c 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -840,7 +840,7 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
}
}
-int dm_get_uuid(const char *name, char *uuid, int uuid_len)
+int dm_get_wwid(const char *name, char *uuid, int uuid_len)
{
char tmp[DM_UUID_LEN];
@@ -1388,7 +1388,7 @@ struct multipath *dm_get_multipath(const char *name)
if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
goto out;
- if (dm_get_uuid(name, mpp->wwid, WWID_SIZE) != 0)
+ if (dm_get_wwid(name, mpp->wwid, WWID_SIZE) != 0)
condlog(2, "%s: failed to get uuid for %s", __func__, name);
if (dm_get_info(name, &mpp->dmi) != 0)
condlog(2, "%s: failed to get info for %s", __func__, name);
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 6fa99be..25e0504 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -175,7 +175,7 @@ int dm_geteventnr (const char *name);
int dm_is_suspended(const char *name);
int dm_get_major_minor (const char *name, int *major, int *minor);
char * dm_mapname(int major, int minor);
-int dm_get_uuid(const char *name, char *uuid, int uuid_len);
+int dm_get_wwid(const char *name, char *uuid, int uuid_len);
bool has_dm_info(const struct multipath *mpp);
int dm_rename (const char * old, char * new, char * delim, int skip_kpartx);
int dm_reassign(const char * mapname);
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 7a50349..7d3ff63 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -81,7 +81,7 @@ global:
dm_get_major_minor;
dm_get_maps;
dm_get_multipath;
- dm_get_uuid;
+ dm_get_wwid;
dm_is_mpath;
dm_mapname;
dm_prereq;
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 591cd09..7a4cb74 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -295,7 +295,7 @@ should_multipath(struct path *pp1, vector pathvec, vector mpvec)
struct multipath *mp = find_mp_by_wwid(mpvec, pp1->wwid);
if (mp != NULL &&
- dm_get_uuid(mp->alias, tmp_wwid, WWID_SIZE) == 0 &&
+ dm_get_wwid(mp->alias, tmp_wwid, WWID_SIZE) == 0 &&
!strncmp(tmp_wwid, pp1->wwid, WWID_SIZE)) {
condlog(3, "wwid %s is already multipathed, keeping it",
pp1->wwid);
diff --git a/multipathd/main.c b/multipathd/main.c
index 394ca7d..442a154 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -727,7 +727,7 @@ add_map_without_path (struct vectors *vecs, const char *alias)
goto out;
}
if (!strlen(mpp->wwid))
- dm_get_uuid(mpp->alias, mpp->wwid, WWID_SIZE);
+ dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE);
if (!strlen(mpp->wwid))
condlog(1, "%s: adding map with empty WWID", mpp->alias);
conf = get_multipath_config();
diff --git a/tests/alias.c b/tests/alias.c
index 95ce994..1f78656 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -76,7 +76,7 @@ int WRAP_FUNC(mkstemp)(char *template)
return 10;
}
-int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
+int __wrap_dm_get_wwid(const char *name, char *uuid, int uuid_len)
{
int ret;
@@ -436,17 +436,17 @@ static int test_scan_devname(void)
static void mock_unused_alias(const char *alias)
{
- expect_string(__wrap_dm_get_uuid, name, alias);
- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE);
- will_return(__wrap_dm_get_uuid, 1);
+ expect_string(__wrap_dm_get_wwid, name, alias);
+ expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE);
+ will_return(__wrap_dm_get_wwid, 1);
}
static void mock_self_alias(const char *alias, const char *wwid)
{
- expect_string(__wrap_dm_get_uuid, name, alias);
- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE);
- will_return(__wrap_dm_get_uuid, 0);
- will_return(__wrap_dm_get_uuid, wwid);
+ expect_string(__wrap_dm_get_wwid, name, alias);
+ expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE);
+ will_return(__wrap_dm_get_wwid, 0);
+ will_return(__wrap_dm_get_wwid, wwid);
}
#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n"
@@ -469,17 +469,17 @@ static void mock_self_alias(const char *alias, const char *wwid)
#define mock_failed_alias(alias, wwid) \
do { \
- expect_string(__wrap_dm_get_uuid, name, alias); \
- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \
- will_return(__wrap_dm_get_uuid, 1); \
+ expect_string(__wrap_dm_get_wwid, name, alias); \
+ expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE); \
+ will_return(__wrap_dm_get_wwid, 1); \
} while (0)
#define mock_used_alias(alias, wwid) \
do { \
- expect_string(__wrap_dm_get_uuid, name, alias); \
- expect_value(__wrap_dm_get_uuid, uuid_len, WWID_SIZE); \
- will_return(__wrap_dm_get_uuid, 0); \
- will_return(__wrap_dm_get_uuid, "WWID_USED"); \
+ expect_string(__wrap_dm_get_wwid, name, alias); \
+ expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE); \
+ will_return(__wrap_dm_get_wwid, 0); \
+ will_return(__wrap_dm_get_wwid, "WWID_USED"); \
expect_condlog(3, USED_STR(alias, wwid)); \
} while(0)
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 25/49] libmultipath: improve dm_get_wwid() return value logic
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (23 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 24/49] libmultipath: rename dm_get_uuid() -> dm_get_wwid() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:42 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 26/49] libmultipath: reimplement dm_map_name() with new API Martin Wilck
` (23 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Make dm_get_wwid() return different status codes for non-existing maps,
maps that exists but are not multipath maps, and generic error case,
and handle these return codes appropriately in callers.
The error handling is als changed; dm_get_wwid() doesn't take
care of making the ouput 0-terminated if anything fails. The
caller is responsible for that. Change callers accordingly.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/alias.c | 11 ++++++++---
libmultipath/configure.c | 27 +++++++++++++++------------
libmultipath/devmapper.c | 22 +++++++++++++++++-----
libmultipath/wwids.c | 2 +-
multipathd/main.c | 7 +++++--
tests/alias.c | 10 +++++-----
6 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 10e58a7..c4eb5d8 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -408,13 +408,18 @@ static bool alias_already_taken(const char *alias, const char *map_wwid)
{
char wwid[WWID_SIZE];
+ int rc = dm_get_wwid(alias, wwid, sizeof(wwid));
- /* If the map doesn't exist, it's fine */
- if (dm_get_wwid(alias, wwid, sizeof(wwid)) != 0)
+ /*
+ * If the map doesn't exist, it's fine.
+ * In the generic error case, assume that the device is not
+ * taken, and try to proceed.
+ */
+ if (rc == DMP_NOT_FOUND || rc == DMP_ERR)
return false;
/* If both the name and the wwid match, it's fine.*/
- if (strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
+ if (rc == DMP_OK && strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
return false;
condlog(3, "%s: alias '%s' already taken, reselecting alias",
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 666d4e8..2fdaca8 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -845,18 +845,21 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
if (mpp->action == ACT_CREATE && dm_map_present(mpp->alias)) {
char wwid[WWID_SIZE];
+ int rc = dm_get_wwid(mpp->alias, wwid, sizeof(wwid));
- if (dm_get_wwid(mpp->alias, wwid, sizeof(wwid)) == 0) {
- if (!strncmp(mpp->wwid, wwid, sizeof(wwid))) {
- condlog(3, "%s: map already present",
- mpp->alias);
- mpp->action = ACT_RELOAD;
- } else {
- condlog(0, "%s: map \"%s\" already present with WWID %s, skipping",
- mpp->wwid, mpp->alias, wwid);
- condlog(0, "please check alias settings in config and bindings file");
- mpp->action = ACT_REJECT;
- }
+ if (rc == DMP_OK && !strncmp(mpp->wwid, wwid, sizeof(wwid))) {
+ condlog(3, "%s: map already present",
+ mpp->alias);
+ mpp->action = ACT_RELOAD;
+ } else if (rc == DMP_OK) {
+ condlog(1, "%s: map \"%s\" already present with WWID \"%s\", skipping\n"
+ "please check alias settings in config and bindings file",
+ mpp->wwid, mpp->alias, wwid);
+ mpp->action = ACT_REJECT;
+ } else if (rc == DMP_NO_MATCH) {
+ condlog(1, "%s: alias \"%s\" already taken by a non-multipath map",
+ mpp->wwid, mpp->alias);
+ mpp->action = ACT_REJECT;
}
}
@@ -1320,7 +1323,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev,
break;
case DEV_DEVMAP:
- if (((dm_get_wwid(dev, tmpwwid, WWID_SIZE)) == 0)
+ if (((dm_get_wwid(dev, tmpwwid, WWID_SIZE)) == DMP_OK)
&& (strlen(tmpwwid)))
refwwid = tmpwwid;
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 3fca08c..003d834 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -840,19 +840,29 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
}
}
+/**
+ * dm_get_wwid(): return WWID for a multipath map
+ * @returns:
+ * DMP_OK if successful
+ * DMP_NOT_FOUND if the map doesn't exist
+ * DMP_NO_MATCH if the map exists but is not a multipath map
+ * DMP_ERR for other errors
+ * Caller may access uuid if and only if DMP_OK is returned.
+ */
int dm_get_wwid(const char *name, char *uuid, int uuid_len)
{
char tmp[DM_UUID_LEN];
+ int rc = dm_get_dm_uuid(name, tmp);
- if (dm_get_dm_uuid(name, tmp) != DMP_OK)
- return 1;
+ if (rc != DMP_OK)
+ return rc;
if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
else
- uuid[0] = '\0';
+ return DMP_NO_MATCH;
- return 0;
+ return DMP_OK;
}
static int is_mpath_part(const char *part_name, const char *map_name)
@@ -1388,8 +1398,10 @@ struct multipath *dm_get_multipath(const char *name)
if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
goto out;
- if (dm_get_wwid(name, mpp->wwid, WWID_SIZE) != 0)
+ if (dm_get_wwid(name, mpp->wwid, WWID_SIZE) != DMP_OK) {
condlog(2, "%s: failed to get uuid for %s", __func__, name);
+ mpp->wwid[0] = '\0';
+ }
if (dm_get_info(name, &mpp->dmi) != 0)
condlog(2, "%s: failed to get info for %s", __func__, name);
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 7a4cb74..aac18c0 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -295,7 +295,7 @@ should_multipath(struct path *pp1, vector pathvec, vector mpvec)
struct multipath *mp = find_mp_by_wwid(mpvec, pp1->wwid);
if (mp != NULL &&
- dm_get_wwid(mp->alias, tmp_wwid, WWID_SIZE) == 0 &&
+ dm_get_wwid(mp->alias, tmp_wwid, WWID_SIZE) == DMP_OK &&
!strncmp(tmp_wwid, pp1->wwid, WWID_SIZE)) {
condlog(3, "wwid %s is already multipathed, keeping it",
pp1->wwid);
diff --git a/multipathd/main.c b/multipathd/main.c
index 442a154..1e7a6ac 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -726,8 +726,11 @@ add_map_without_path (struct vectors *vecs, const char *alias)
condlog(3, "%s: cannot access table", mpp->alias);
goto out;
}
- if (!strlen(mpp->wwid))
- dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE);
+ if (!strlen(mpp->wwid) &&
+ dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE) != DMP_OK) {
+ condlog(3, "%s: cannot obtain WWID", mpp->alias);
+ goto out;
+ }
if (!strlen(mpp->wwid))
condlog(1, "%s: adding map with empty WWID", mpp->alias);
conf = get_multipath_config();
diff --git a/tests/alias.c b/tests/alias.c
index 1f78656..a95b308 100644
--- a/tests/alias.c
+++ b/tests/alias.c
@@ -84,7 +84,7 @@ int __wrap_dm_get_wwid(const char *name, char *uuid, int uuid_len)
check_expected(uuid_len);
assert_non_null(uuid);
ret = mock_type(int);
- if (ret == 0)
+ if (ret == DMP_OK)
strcpy(uuid, mock_ptr_type(char *));
return ret;
}
@@ -438,14 +438,14 @@ static void mock_unused_alias(const char *alias)
{
expect_string(__wrap_dm_get_wwid, name, alias);
expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE);
- will_return(__wrap_dm_get_wwid, 1);
+ will_return(__wrap_dm_get_wwid, DMP_NOT_FOUND);
}
static void mock_self_alias(const char *alias, const char *wwid)
{
expect_string(__wrap_dm_get_wwid, name, alias);
expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE);
- will_return(__wrap_dm_get_wwid, 0);
+ will_return(__wrap_dm_get_wwid, DMP_OK);
will_return(__wrap_dm_get_wwid, wwid);
}
@@ -471,14 +471,14 @@ static void mock_self_alias(const char *alias, const char *wwid)
do { \
expect_string(__wrap_dm_get_wwid, name, alias); \
expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE); \
- will_return(__wrap_dm_get_wwid, 1); \
+ will_return(__wrap_dm_get_wwid, DMP_NOT_FOUND); \
} while (0)
#define mock_used_alias(alias, wwid) \
do { \
expect_string(__wrap_dm_get_wwid, name, alias); \
expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE); \
- will_return(__wrap_dm_get_wwid, 0); \
+ will_return(__wrap_dm_get_wwid, DMP_OK); \
will_return(__wrap_dm_get_wwid, "WWID_USED"); \
expect_condlog(3, USED_STR(alias, wwid)); \
} while(0)
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 26/49] libmultipath: reimplement dm_map_name() with new API
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (24 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 25/49] libmultipath: improve dm_get_wwid() return value logic Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:42 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 27/49] libmultipath: reimplement dm_map_present_by_uuid() Martin Wilck
` (22 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 34 ++++++----------------------------
1 file changed, 6 insertions(+), 28 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 003d834..8af4167 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1481,37 +1481,15 @@ dm_is_suspended(const char *name)
return info.suspended;
}
-char *
-dm_mapname(int major, int minor)
+char *dm_mapname(int major, int minor)
{
- char * response = NULL;
- const char *map;
- struct dm_task *dmt;
- int r;
+ char name[WWID_SIZE];
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
+ if (libmp_mapinfo(DM_MAP_BY_DEV,
+ (mapid_t) { ._u = { major, minor } },
+ (mapinfo_t) { .name = name }) != DMP_OK)
return NULL;
-
- if (!dm_task_set_major(dmt, major) ||
- !dm_task_set_minor(dmt, minor))
- goto bad;
-
- r = libmp_dm_task_run(dmt);
- if (!r) {
- dm_log_error(2, DM_DEVICE_INFO, dmt);
- goto bad;
- }
-
- map = dm_task_get_name(dmt);
- if (map && strlen(map))
- response = strdup((const char *)map);
-
- dm_task_destroy(dmt);
- return response;
-bad:
- dm_task_destroy(dmt);
- condlog(0, "%i:%i: error fetching map name", major, minor);
- return NULL;
+ return strdup(name);
}
static int
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 27/49] libmultipath: reimplement dm_map_present_by_uuid()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (25 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 26/49] libmultipath: reimplement dm_map_name() with new API Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 28/49] libmultipath: reimplement dm_get_opencount() with new API Martin Wilck
` (21 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
... and rename it to dm_map_present_by_wwid().
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 47 ++++++----------------------------------
libmultipath/devmapper.h | 2 +-
libmultipath/valid.c | 2 +-
tests/valid.c | 10 ++++-----
4 files changed, 14 insertions(+), 47 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 8af4167..5cada4c 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1023,49 +1023,16 @@ out:
return r;
}
-/*
- * Return
- * 1 : map with uuid exists
- * 0 : map with uuid doesn't exist
- * -1 : error
- */
-int
-dm_map_present_by_uuid(const char *uuid)
+int dm_map_present_by_wwid(const char *wwid)
{
- struct dm_task *dmt;
- struct dm_info info;
- char prefixed_uuid[WWID_SIZE + UUID_PREFIX_LEN];
- int r = -1;
+ char tmp[DM_UUID_LEN];
- if (!uuid || uuid[0] == '\0')
- return 0;
+ if (safe_sprintf(tmp, UUID_PREFIX "%s", wwid))
+ return DMP_ERR;
- if (safe_sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid))
- goto out;
-
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
- goto out;
-
- if (!dm_task_set_uuid(dmt, prefixed_uuid))
- goto out_task;
-
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_INFO, dmt);
- goto out_task;
- }
-
- if (!dm_task_get_info(dmt, &info))
- goto out_task;
-
- r = !!info.exists;
-
-out_task:
- dm_task_destroy(dmt);
-out:
- if (r < 0)
- condlog(3, "%s: dm command failed in %s: %s", uuid,
- __FUNCTION__, strerror(errno));
- return r;
+ return libmp_mapinfo(DM_MAP_BY_UUID,
+ (mapid_t) { .str = tmp },
+ (mapinfo_t) { .name = NULL });
}
static int dm_dev_t (const char *mapname, char *dev_t, int len)
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 25e0504..4c8f345 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -127,7 +127,7 @@ int dm_simplecmd_flush (int task, const char *name, uint16_t udev_flags);
int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags);
int dm_addmap_create (struct multipath *mpp, char *params);
int dm_addmap_reload (struct multipath *mpp, char *params, int flush);
-int dm_map_present_by_uuid(const char *uuid);
+int dm_map_present_by_wwid(const char *uuid);
int dm_get_map(const char *name, unsigned long long *size, char **outparams);
int dm_get_status(const char *name, char **outstatus);
diff --git a/libmultipath/valid.c b/libmultipath/valid.c
index f223778..9267cef 100644
--- a/libmultipath/valid.c
+++ b/libmultipath/valid.c
@@ -360,7 +360,7 @@ is_path_valid(const char *name, struct config *conf, struct path *pp,
if (check_wwids_file(pp->wwid, 0) == 0)
return PATH_IS_VALID_NO_CHECK;
- if (dm_map_present_by_uuid(pp->wwid) == 1)
+ if (dm_map_present_by_wwid(pp->wwid) == DMP_OK)
return PATH_IS_VALID;
/* all these act like FIND_MULTIPATHS_STRICT for finding if a
diff --git a/tests/valid.c b/tests/valid.c
index 18a5a7b..a93bbe5 100644
--- a/tests/valid.c
+++ b/tests/valid.c
@@ -189,7 +189,7 @@ int __wrap_check_wwids_file(char *wwid, int write_wwid)
return -1;
}
-int __wrap_dm_map_present_by_uuid(const char *uuid)
+int __wrap_dm_map_present_by_wwid(const char *uuid)
{
int ret = mock_type(int);
assert_string_equal(uuid, mock_ptr_type(char *));
@@ -271,8 +271,8 @@ static void setup_passing(char *name, char *wwid, unsigned int check_multipathd,
will_return(__wrap_check_wwids_file, wwid);
if (stage == STAGE_CHECK_WWIDS)
return;
- will_return(__wrap_dm_map_present_by_uuid, 0);
- will_return(__wrap_dm_map_present_by_uuid, wwid);
+ will_return(__wrap_dm_map_present_by_wwid, 0);
+ will_return(__wrap_dm_map_present_by_wwid, wwid);
}
static void test_bad_arguments(void **state)
@@ -516,8 +516,8 @@ static void test_check_uuid_present(void **state)
memset(&pp, 0, sizeof(pp));
conf.find_multipaths = FIND_MULTIPATHS_STRICT;
setup_passing(name, wwid, CHECK_MPATHD_RUNNING, STAGE_CHECK_WWIDS);
- will_return(__wrap_dm_map_present_by_uuid, 1);
- will_return(__wrap_dm_map_present_by_uuid, wwid);
+ will_return(__wrap_dm_map_present_by_wwid, 1);
+ will_return(__wrap_dm_map_present_by_wwid, wwid);
assert_int_equal(is_path_valid(name, &conf, &pp, true),
PATH_IS_VALID);
assert_string_equal(pp.dev, name);
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 28/49] libmultipath: reimplement dm_get_opencount() with new API
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (26 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 27/49] libmultipath: reimplement dm_map_present_by_uuid() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 29/49] libmpathpersist: skip redundant dm_map_present() call Martin Wilck
` (20 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 28 ++++------------------------
1 file changed, 4 insertions(+), 24 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 5cada4c..47ff827 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1048,34 +1048,14 @@ static int dm_dev_t (const char *mapname, char *dev_t, int len)
return 0;
}
-int
-dm_get_opencount (const char * mapname)
+int dm_get_opencount (const char *mapname)
{
- int r = -1;
- struct dm_task *dmt;
struct dm_info info;
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
- return 0;
+ if (dm_get_info(mapname, &info) != DMP_OK)
+ return -1;
- if (!dm_task_set_name(dmt, mapname))
- goto out;
-
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_INFO, dmt);
- goto out;
- }
-
- if (!dm_task_get_info(dmt, &info))
- goto out;
-
- if (!info.exists)
- goto out;
-
- r = info.open_count;
-out:
- dm_task_destroy(dmt);
- return r;
+ return info.open_count;
}
int
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 29/49] libmpathpersist: skip redundant dm_map_present() call
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (27 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 28/49] libmultipath: reimplement dm_get_opencount() with new API Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 30/49] libmultipath: implement dm_is_mpath() with new API Martin Wilck
` (19 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
dm_is_mpath() returns 0 if the map does not exist, the additional
dm_map_present() call is not necessary.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_persist_int.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index 6da0401..5a5ac3b 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -185,7 +185,7 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
condlog(3, "alias = %s", alias);
- if (dm_map_present(alias) && dm_is_mpath(alias) != DM_IS_MPATH_YES) {
+ if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
condlog(3, "%s: not a multipath device.", alias);
goto out;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 30/49] libmultipath: implement dm_is_mpath() with new API
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (28 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 29/49] libmpathpersist: skip redundant dm_map_present() call Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:43 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 31/49] libmultipath: implement dm_get_multipath() " Martin Wilck
` (18 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 59 ++++++++++------------------------------
1 file changed, 15 insertions(+), 44 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 47ff827..11bccb1 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -975,52 +975,23 @@ static int dm_type_match(const char *name, char *type)
int dm_is_mpath(const char *name)
{
- int r = DM_IS_MPATH_ERR;
- struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
- struct dm_info info;
- uint64_t start, length;
- char *target_type = NULL;
- char *params;
- const char *uuid;
+ char uuid[DM_UUID_LEN];
+ int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = name },
+ (mapinfo_t) { .uuid = uuid });
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
- goto out;
-
- if (!dm_task_set_name(dmt, name))
- goto out;
-
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_TABLE, dmt);
- goto out;
+ switch (rc) {
+ case DMP_OK:
+ if (!strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
+ return DM_IS_MPATH_YES;
+ /* fallthrough */
+ case DMP_NOT_FOUND:
+ case DMP_NO_MATCH:
+ return DM_IS_MPATH_NO;
+ case DMP_ERR:
+ default:
+ return DM_IS_MPATH_ERR;
}
-
- if (!dm_task_get_info(dmt, &info))
- goto out;
-
- r = DM_IS_MPATH_NO;
-
- if (!info.exists)
- goto out;
-
- uuid = dm_task_get_uuid(dmt);
-
- if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
- goto out;
-
- /* Fetch 1st target */
- if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
- ¶ms) != NULL)
- /* multiple targets */
- goto out;
-
- if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
- goto out;
-
- r = DM_IS_MPATH_YES;
-out:
- if (r == DM_IS_MPATH_ERR)
- condlog(3, "%s: dm command failed in %s: %s", name, __func__, strerror(errno));
- return r;
}
int dm_map_present_by_wwid(const char *wwid)
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 31/49] libmultipath: implement dm_get_multipath() with new API
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (29 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 30/49] libmultipath: implement dm_is_mpath() with new API Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 32/49] libmultipath: use libmp_mapinfo() in _dm_flush_map() Martin Wilck
` (17 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 11bccb1..2f547ab 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1302,7 +1302,8 @@ dm_disablegroup(const char * mapname, int index)
struct multipath *dm_get_multipath(const char *name)
{
- struct multipath *mpp = NULL;
+ struct multipath __attribute((cleanup(cleanup_multipath))) *mpp = NULL;
+ char uuid[DM_UUID_LEN];
mpp = alloc_multipath();
if (!mpp)
@@ -1311,22 +1312,22 @@ struct multipath *dm_get_multipath(const char *name)
mpp->alias = strdup(name);
if (!mpp->alias)
- goto out;
+ return NULL;
- if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
- goto out;
+ if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = name },
+ (mapinfo_t) {
+ .size = &mpp->size,
+ .uuid = uuid,
+ .dmi = &mpp->dmi,
+ }) != DMP_OK)
+ return NULL;
- if (dm_get_wwid(name, mpp->wwid, WWID_SIZE) != DMP_OK) {
- condlog(2, "%s: failed to get uuid for %s", __func__, name);
- mpp->wwid[0] = '\0';
- }
- if (dm_get_info(name, &mpp->dmi) != 0)
- condlog(2, "%s: failed to get info for %s", __func__, name);
+ if (strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
+ return NULL;
- return mpp;
-out:
- free_multipath(mpp, KEEP_PATHS);
- return NULL;
+ strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
+ return steal_ptr(mpp);
}
int dm_get_maps(vector mp)
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 32/49] libmultipath: use libmp_mapinfo() in _dm_flush_map()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (30 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 31/49] libmultipath: implement dm_get_multipath() " Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 33/49] libmultipath: add is_mpath_uuid() helper Martin Wilck
` (16 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
We can spare one dm ioctl here.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 2f547ab..9483f02 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1074,10 +1074,15 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
int r;
int queue_if_no_path = 0;
int udev_flags = 0;
- unsigned long long mapsize;
- char *params = NULL;
+ char *params __attribute__((cleanup(cleanup_charp))) = NULL;
+ char uuid[DM_UUID_LEN];
- if (dm_is_mpath(mapname) != DM_IS_MPATH_YES)
+ if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = mapname },
+ (mapinfo_t) {
+ .uuid = uuid,
+ .target = ¶ms }) != DMP_OK
+ || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
return DM_FLUSH_OK; /* nothing to do */
/* if the device currently has no partitions, do not
@@ -1091,7 +1096,6 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
return DM_FLUSH_BUSY;
if ((flags & DMFL_SUSPEND) &&
- dm_get_map(mapname, &mapsize, ¶ms) == DMP_OK &&
strstr(params, "queue_if_no_path")) {
if (!_dm_queue_if_no_path(mapname, 0))
queue_if_no_path = 1;
@@ -1099,8 +1103,6 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
/* Leave queue_if_no_path alone if unset failed */
queue_if_no_path = -1;
}
- free(params);
- params = NULL;
if ((r = dm_remove_partmaps(mapname, flags)))
return r;
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 33/49] libmultipath: add is_mpath_uuid() helper
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (31 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 32/49] libmultipath: use libmp_mapinfo() in _dm_flush_map() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:43 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 34/49] libmultipath: add is_mpath_part_uuid() helper Martin Wilck
` (15 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Export it, as it will be used by multipathd and libmpathpersist.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 13 +++++++++----
libmultipath/devmapper.h | 2 ++
libmultipath/libmultipath.version | 1 +
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 9483f02..6f17d32 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -840,6 +840,11 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
}
}
+bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
+{
+ return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
+}
+
/**
* dm_get_wwid(): return WWID for a multipath map
* @returns:
@@ -857,7 +862,7 @@ int dm_get_wwid(const char *name, char *uuid, int uuid_len)
if (rc != DMP_OK)
return rc;
- if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
+ if (is_mpath_uuid(tmp))
strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
else
return DMP_NO_MATCH;
@@ -982,7 +987,7 @@ int dm_is_mpath(const char *name)
switch (rc) {
case DMP_OK:
- if (!strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
+ if (is_mpath_uuid(uuid))
return DM_IS_MPATH_YES;
/* fallthrough */
case DMP_NOT_FOUND:
@@ -1082,7 +1087,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
(mapinfo_t) {
.uuid = uuid,
.target = ¶ms }) != DMP_OK
- || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
+ || !is_mpath_uuid(uuid))
return DM_FLUSH_OK; /* nothing to do */
/* if the device currently has no partitions, do not
@@ -1325,7 +1330,7 @@ struct multipath *dm_get_multipath(const char *name)
}) != DMP_OK)
return NULL;
- if (strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
+ if (!is_mpath_uuid(uuid))
return NULL;
strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 4c8f345..a10821f 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -136,6 +136,8 @@ enum {
DM_IS_MPATH_YES,
DM_IS_MPATH_ERR,
};
+
+bool is_mpath_uuid(const char uuid[DM_UUID_LEN]);
int dm_is_mpath(const char *name);
enum {
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 7d3ff63..5b8f9e0 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -127,6 +127,7 @@ global:
init_foreign;
init_prio;
io_err_stat_handle_pathfail;
+ is_mpath_uuid;
is_path_valid;
libmp_dm_task_create;
libmp_get_version;
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 34/49] libmultipath: add is_mpath_part_uuid() helper
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (32 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 33/49] libmultipath: add is_mpath_uuid() helper Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 35/49] libmultipath: add dmp_errstr() helper Martin Wilck
` (14 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 6f17d32..4ad84dd 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -870,21 +870,15 @@ int dm_get_wwid(const char *name, char *uuid, int uuid_len)
return DMP_OK;
}
-static int is_mpath_part(const char *part_name, const char *map_name)
+static bool is_mpath_part_uuid(const char part_uuid[DM_UUID_LEN],
+ const char map_uuid[DM_UUID_LEN])
{
- char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN], c;
+ char c;
int np, nc;
- if (dm_get_dm_uuid(part_name, part_uuid) != DMP_OK)
- return 0;
-
if (2 != sscanf(part_uuid, "part%d-%n" UUID_PREFIX "%c", &np, &nc, &c)
|| np <= 0)
- return 0;
-
- if (dm_get_dm_uuid(map_name, map_uuid) != DMP_OK)
- return 0;
-
+ return false;
return !strcmp(part_uuid + nc, map_uuid);
}
@@ -978,6 +972,20 @@ static int dm_type_match(const char *name, char *type)
return DM_TYPE_NOMATCH;
}
+static bool is_mpath_part(const char *part_name, const char *map_name)
+{
+ char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN];
+
+ if (dm_get_dm_uuid(map_name, map_uuid) != DMP_OK
+ || !is_mpath_uuid(map_uuid))
+ return false;
+
+ if (dm_get_dm_uuid(part_name, part_uuid) != DMP_OK)
+ return false;
+
+ return is_mpath_part_uuid(part_uuid, map_uuid);
+}
+
int dm_is_mpath(const char *name)
{
char uuid[DM_UUID_LEN];
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 35/49] libmultipath: add dmp_errstr() helper
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (33 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 34/49] libmultipath: add is_mpath_part_uuid() helper Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 36/49] libmultipath: use libmp_mapinfo() in do_foreach_partmaps() Martin Wilck
` (13 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 14 ++++++++++++++
libmultipath/devmapper.h | 3 +++
2 files changed, 17 insertions(+)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 4ad84dd..e51c2f0 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -79,6 +79,20 @@ static void libmp_udev_wait(unsigned int c)
}
#endif
+const char *dmp_errstr(int rc)
+{
+ static const char *str[] = {
+ [DMP_ERR] = "generic error",
+ [DMP_OK] = "success",
+ [DMP_NOT_FOUND] = "not found",
+ [DMP_NO_MATCH] = "target type mismatch",
+ [__DMP_LAST__] = "**invalid**",
+ };
+ if (rc < 0 || rc > __DMP_LAST__)
+ rc = __DMP_LAST__;
+ return str[rc];
+}
+
int libmp_dm_task_run(struct dm_task *dmt)
{
int r;
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index a10821f..7231a98 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -34,8 +34,11 @@ enum {
DMP_OK,
DMP_NOT_FOUND,
DMP_NO_MATCH,
+ __DMP_LAST__,
};
+const char* dmp_errstr(int rc);
+
/**
* enum mapinfo_flags: input flags for libmp_mapinfo()
*/
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 36/49] libmultipath: use libmp_mapinfo() in do_foreach_partmaps()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (34 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 35/49] libmultipath: add dmp_errstr() helper Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 37/49] libmultipath: use libmp_pathinfo() in update_multipath_table() Martin Wilck
` (12 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Also, simplify the if statement a bit.
drop is_mpath_part() and dm_type_match, because do_foreach_partmaps() was the
last user of these functions.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 100 ++++++++++-----------------------------
1 file changed, 26 insertions(+), 74 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index e51c2f0..587fc17 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -946,60 +946,6 @@ out:
return r;
}
-enum {
- DM_TYPE_NOMATCH = 0,
- DM_TYPE_MATCH,
- /* more than 1 target */
- DM_TYPE_MULTI,
- /* empty map */
- DM_TYPE_EMPTY,
- DM_TYPE_ERR,
-};
-static int dm_type_match(const char *name, char *type)
-{
- struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
- uint64_t start, length;
- char *target_type = NULL;
- char *params;
-
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
- return DM_TYPE_ERR;
-
- if (!dm_task_set_name(dmt, name))
- return DM_TYPE_ERR;
-
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_TABLE, dmt);
- return DM_TYPE_ERR;
- }
-
- /* Fetch 1st target */
- if (dm_get_next_target(dmt, NULL, &start, &length,
- &target_type, ¶ms) != NULL)
- /* multiple targets */
- return DM_TYPE_MULTI;
- else if (!target_type)
- return DM_TYPE_EMPTY;
- else if (!strcmp(target_type, type))
- return DM_TYPE_MATCH;
- else
- return DM_TYPE_NOMATCH;
-}
-
-static bool is_mpath_part(const char *part_name, const char *map_name)
-{
- char part_uuid[DM_UUID_LEN], map_uuid[DM_UUID_LEN];
-
- if (dm_get_dm_uuid(map_name, map_uuid) != DMP_OK
- || !is_mpath_uuid(map_uuid))
- return false;
-
- if (dm_get_dm_uuid(part_name, part_uuid) != DMP_OK)
- return false;
-
- return is_mpath_part_uuid(part_uuid, map_uuid);
-}
-
int dm_is_mpath(const char *name)
{
char uuid[DM_UUID_LEN];
@@ -1441,7 +1387,7 @@ char *dm_mapname(int major, int minor)
}
static int
-do_foreach_partmaps (const char * mapname,
+do_foreach_partmaps (const char *mapname,
int (*partmap_func)(const char *, void *),
void *data)
{
@@ -1449,10 +1395,19 @@ do_foreach_partmaps (const char * mapname,
char __attribute__((cleanup(cleanup_charp))) *params = NULL;
struct dm_names *names;
unsigned next = 0;
- unsigned long long size;
- char dev_t[32];
+ char dev_t[BLK_DEV_SIZE];
int r = 1;
char *p;
+ char map_uuid[DM_UUID_LEN];
+ struct dm_info info;
+
+ if (libmp_mapinfo(DM_MAP_BY_NAME,
+ (mapid_t) { .str = mapname },
+ (mapinfo_t) { .uuid = map_uuid, .dmi = &info }) != DMP_OK)
+ return 1;
+
+ if (safe_sprintf(dev_t, "%i:%i", info.major, info.minor))
+ return 1;
if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
return 1;
@@ -1467,41 +1422,38 @@ do_foreach_partmaps (const char * mapname,
/* this is perfectly valid */
return 0;
- if (dm_dev_t(mapname, &dev_t[0], 32))
- return 1;
-
do {
+ char part_uuid[DM_UUID_LEN];
+
if (
/*
* if there is only a single "linear" target
*/
- (dm_type_match(names->name, TGT_PART) == DM_TYPE_MATCH) &&
-
+ libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_PART_ONLY,
+ (mapid_t) { .str = names->name },
+ (mapinfo_t) {
+ .uuid = part_uuid,
+ .target = ¶ms,
+ }) == DMP_OK &&
/*
* and the uuid of the target is a partition of the
* uuid of the multipath device
*/
- is_mpath_part(names->name, mapname) &&
-
- /*
- * and we can fetch the map table from the kernel
- */
- dm_get_map(names->name, &size, ¶ms) == DMP_OK &&
+ is_mpath_part_uuid(part_uuid, map_uuid) &&
/*
* and the table maps over the multipath map
*/
(p = strstr(params, dev_t)) &&
- !isdigit(*(p + strlen(dev_t)))
- ) {
- if ((r = partmap_func(names->name, data)) != 0)
- return 1;
- }
+ !isdigit(*(p + strlen(dev_t))) &&
+
+ (r = partmap_func(names->name, data)) != 0)
+ return 1;
free(params);
params = NULL;
next = names->next;
- names = (void *) names + next;
+ names = (void*) names + next;
} while (next);
return 0;
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 37/49] libmultipath: use libmp_pathinfo() in update_multipath_table()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (35 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 36/49] libmultipath: use libmp_mapinfo() in do_foreach_partmaps() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:44 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 38/49] libmultipath: update mpp->dmi " Martin Wilck
` (11 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
This allows us to remove dm_get_status(), and dm_get_map(), of which
update_multipath_table() was the last caller.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 89 --------------------------------------
libmultipath/devmapper.h | 2 -
libmultipath/structs_vec.c | 26 ++++++-----
3 files changed, 15 insertions(+), 102 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 587fc17..86ac01b 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -815,45 +815,6 @@ static int dm_get_dm_uuid(const char *mapname, char uuid[DM_UUID_LEN])
(mapinfo_t) { .uuid = uuid });
}
-int dm_get_map(const char *name, unsigned long long *size, char **outparams)
-{
- struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
- uint64_t start, length;
- char *target_type = NULL;
- char *params = NULL;
-
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
- return DMP_ERR;
-
- if (!dm_task_set_name(dmt, name))
- return DMP_ERR;
-
- errno = 0;
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_TABLE, dmt);
- if (dm_task_get_errno(dmt) == ENXIO)
- return DMP_NOT_FOUND;
- else
- return DMP_ERR;
- }
-
- /* Fetch 1st target */
- if (dm_get_next_target(dmt, NULL, &start, &length,
- &target_type, ¶ms) != NULL || !params)
- /* more than one target or not found target */
- return DMP_NOT_FOUND;
-
- if (size)
- *size = length;
-
- if (!outparams)
- return DMP_OK;
- else {
- *outparams = strdup(params);
- return *outparams ? DMP_OK : DMP_ERR;
- }
-}
-
bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
{
return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
@@ -896,56 +857,6 @@ static bool is_mpath_part_uuid(const char part_uuid[DM_UUID_LEN],
return !strcmp(part_uuid + nc, map_uuid);
}
-int dm_get_status(const char *name, char **outstatus)
-{
- int r = DMP_ERR;
- struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
- uint64_t start, length;
- char *target_type = NULL;
- char *status = NULL;
-
- if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
- return r;
-
- if (!dm_task_set_name(dmt, name))
- goto out;
-
- errno = 0;
- if (!libmp_dm_task_run(dmt)) {
- dm_log_error(3, DM_DEVICE_STATUS, dmt);
- if (dm_task_get_errno(dmt) == ENXIO)
- r = DMP_NOT_FOUND;
- goto out;
- }
-
- r = DMP_NOT_FOUND;
- /* Fetch 1st target */
- if (dm_get_next_target(dmt, NULL, &start, &length,
- &target_type, &status) != NULL)
- goto out;
-
- if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
- goto out;
-
- if (!status) {
- condlog(2, "got null status.");
- goto out;
- }
-
- if (!outstatus)
- r = DMP_OK;
- else {
- *outstatus = strdup(status);
- r = *outstatus ? DMP_OK : DMP_ERR;
- }
-out:
- if (r != DMP_OK)
- condlog(0, "%s: %s: error getting map status string: %d",
- __func__, name, r);
-
- return r;
-}
-
int dm_is_mpath(const char *name)
{
char uuid[DM_UUID_LEN];
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 7231a98..3daaa4c 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -131,8 +131,6 @@ int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags);
int dm_addmap_create (struct multipath *mpp, char *params);
int dm_addmap_reload (struct multipath *mpp, char *params, int flush);
int dm_map_present_by_wwid(const char *uuid);
-int dm_get_map(const char *name, unsigned long long *size, char **outparams);
-int dm_get_status(const char *name, char **outstatus);
enum {
DM_IS_MPATH_NO,
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index ccc4efc..f2cfe31 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -484,30 +484,34 @@ int
update_multipath_table (struct multipath *mpp, vector pathvec, int flags)
{
int r = DMP_ERR;
- char *params = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *params = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+ unsigned long long size = mpp->size;
if (!mpp)
return r;
- r = dm_get_map(mpp->alias, &mpp->size, ¶ms);
+ r = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = mpp->alias },
+ (mapinfo_t) {
+ .target = ¶ms,
+ .status = &status,
+ .size = &mpp->size,
+ });
+
if (r != DMP_OK) {
- condlog(2, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting table" : "map not present");
+ condlog(2, "%s: %s", mpp->alias, dmp_errstr(r));
return r;
- }
+ } else if (size != mpp->size)
+ condlog(0, "%s: size changed from %llu to %llu", mpp->alias, size, mpp->size);
if (disassemble_map(pathvec, params, mpp)) {
condlog(2, "%s: cannot disassemble map", mpp->alias);
- free(params);
return DMP_ERR;
}
- free(params);
- params = NULL;
- if (dm_get_status(mpp->alias, ¶ms) != DMP_OK)
- condlog(2, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting status" : "map not present");
- else if (disassemble_status(params, mpp))
+ if (disassemble_status(status, mpp))
condlog(2, "%s: cannot disassemble status", mpp->alias);
- free(params);
/* FIXME: we should deal with the return value here */
update_pathvec_from_dm(pathvec, mpp, flags);
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 38/49] libmultipath: update mpp->dmi in update_multipath_table()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (36 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 37/49] libmultipath: use libmp_pathinfo() in update_multipath_table() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 39/49] libmultipath: drop extra call to dm_map_present() in domap() Martin Wilck
` (10 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
This comes almost for free now.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs_vec.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index f2cfe31..295dac8 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -497,6 +497,7 @@ update_multipath_table (struct multipath *mpp, vector pathvec, int flags)
.target = ¶ms,
.status = &status,
.size = &mpp->size,
+ .dmi = &mpp->dmi,
});
if (r != DMP_OK) {
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 39/49] libmultipath: drop extra call to dm_map_present() in domap()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (37 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 38/49] libmultipath: update mpp->dmi " Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 40/49] libmultipath: split off update_multipath_table__() Martin Wilck
` (9 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
dm_get_wwid() will return DMP_NOT_FOUND if the map doesn't exist.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 2fdaca8..b4de863 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -834,6 +834,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
{
int r = DOMAP_FAIL;
struct config *conf;
+ char wwid[WWID_SIZE];
/*
* last chance to quit before touching the devmaps
@@ -843,8 +844,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
return DOMAP_DRY;
}
- if (mpp->action == ACT_CREATE && dm_map_present(mpp->alias)) {
- char wwid[WWID_SIZE];
+ if (mpp->action == ACT_CREATE) {
int rc = dm_get_wwid(mpp->alias, wwid, sizeof(wwid));
if (rc == DMP_OK && !strncmp(mpp->wwid, wwid, sizeof(wwid))) {
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 40/49] libmultipath: split off update_multipath_table__()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (38 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 39/49] libmultipath: drop extra call to dm_map_present() in domap() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 41/49] multipath: implement check_usable_paths() with libmp_pathinfo() Martin Wilck
` (8 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Split off the part of the function that does the disassembly
from the part calling libmp_mapinfo(). This makes it possible
to call the function from a context where the map info is already
available.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/libmultipath.version | 1 +
libmultipath/structs_vec.c | 31 +++++++++++++++++++------------
libmultipath/structs_vec.h | 2 ++
3 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 5b8f9e0..54b5a23 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -206,6 +206,7 @@ global:
uninit_config;
update_mpp_paths;
update_multipath_strings;
+ update_multipath_table__;
update_multipath_table;
update_queue_mode_add_path;
update_queue_mode_del_path;
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 295dac8..731b1bc 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -480,6 +480,24 @@ done:
condlog(2, "%s: no hwe found", mpp->alias);
}
+int
+update_multipath_table__ (struct multipath *mpp, vector pathvec, int flags,
+ const char *params, const char *status)
+{
+ if (disassemble_map(pathvec, params, mpp)) {
+ condlog(2, "%s: cannot disassemble map", mpp->alias);
+ return DMP_ERR;
+ }
+
+ if (disassemble_status(status, mpp))
+ condlog(2, "%s: cannot disassemble status", mpp->alias);
+
+ /* FIXME: we should deal with the return value here */
+ update_pathvec_from_dm(pathvec, mpp, flags);
+
+ return DMP_OK;
+}
+
int
update_multipath_table (struct multipath *mpp, vector pathvec, int flags)
{
@@ -506,18 +524,7 @@ update_multipath_table (struct multipath *mpp, vector pathvec, int flags)
} else if (size != mpp->size)
condlog(0, "%s: size changed from %llu to %llu", mpp->alias, size, mpp->size);
- if (disassemble_map(pathvec, params, mpp)) {
- condlog(2, "%s: cannot disassemble map", mpp->alias);
- return DMP_ERR;
- }
-
- if (disassemble_status(status, mpp))
- condlog(2, "%s: cannot disassemble status", mpp->alias);
-
- /* FIXME: we should deal with the return value here */
- update_pathvec_from_dm(pathvec, mpp, flags);
-
- return DMP_OK;
+ return update_multipath_table__(mpp, pathvec, flags, params, status);
}
static struct path *find_devt_in_pathgroups(const struct multipath *mpp,
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index dbc4305..01f5dc4 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -33,6 +33,8 @@ struct multipath * add_map_with_path (struct vectors * vecs,
const struct multipath *current_mpp);
void update_queue_mode_del_path(struct multipath *mpp);
void update_queue_mode_add_path(struct multipath *mpp);
+int update_multipath_table__ (struct multipath *mpp, vector pathvec, int flags,
+ const char *params, const char *status);
int update_multipath_table (struct multipath *mpp, vector pathvec, int flags);
int update_multipath_status (struct multipath *mpp);
vector get_used_hwes(const struct _vector *pathvec);
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 41/49] multipath: implement check_usable_paths() with libmp_pathinfo()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (39 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 40/49] libmultipath: split off update_multipath_table__() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:45 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 42/49] multipathd: implement add_map_without_path() with libmp_mapinfo() Martin Wilck
` (7 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
... and use cleanup attributes. We need to call the disassemble...()
functions from multipath directly now, but we fetch exactly the data
we need from the kernel.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
multipath/main.c | 58 ++++++++++++++++++++++++++----------------------
1 file changed, 31 insertions(+), 27 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index c82bc86..0d989dc 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -222,12 +222,14 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
static int check_usable_paths(struct config *conf,
const char *devpath, enum devtypes dev_type)
{
- struct udev_device *ud = NULL;
- struct multipath *mpp = NULL;
+ struct udev_device __attribute__((cleanup(cleanup_udev_device))) *ud = NULL;
+ struct multipath __attribute__((cleanup(cleanup_multipath_and_paths))) *mpp = NULL;
struct pathgroup *pg;
struct path *pp;
- char *mapname;
- vector pathvec = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *params = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
+ vector __attribute((cleanup(cleanup_vector))) pathvec = NULL;
+ char uuid[DM_UUID_LEN];
dev_t devt;
int r = 1, i, j;
@@ -238,31 +240,39 @@ static int check_usable_paths(struct config *conf,
devt = udev_device_get_devnum(ud);
if (!dm_is_dm_major(major(devt))) {
condlog(1, "%s is not a dm device", devpath);
- goto out;
+ return r;
}
- mapname = dm_mapname(major(devt), minor(devt));
- if (mapname == NULL) {
- condlog(1, "dm device not found: %s", devpath);
- goto out;
- }
-
- if (dm_is_mpath(mapname) != DM_IS_MPATH_YES) {
- condlog(1, "%s is not a multipath map", devpath);
- goto free;
- }
+ mpp = alloc_multipath();
+ if (!mpp)
+ return r;
+ if (!(mpp->alias = malloc(WWID_SIZE)))
+ return r;
/* pathvec is needed for disassemble_map */
pathvec = vector_alloc();
if (pathvec == NULL)
- goto free;
+ return r;
- mpp = dm_get_multipath(mapname);
- if (mpp == NULL)
- goto free;
+ if (libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .devt = devt },
+ (mapinfo_t) {
+ .name = mpp->alias,
+ .uuid = uuid,
+ .dmi = &mpp->dmi,
+ .size = &mpp->size,
+ .target = ¶ms,
+ .status = &status,
+ }) != DMP_OK)
+ return r;
- if (update_multipath_table(mpp, pathvec, 0) != DMP_OK)
- goto free;
+ if (!is_mpath_uuid(uuid))
+ return r;
+
+ strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
+
+ if (update_multipath_table__(mpp, pathvec, 0, params, status) != DMP_OK)
+ return r;
vector_foreach_slot (mpp->pg, pg, i) {
vector_foreach_slot (pg->paths, pp, j) {
@@ -284,12 +294,6 @@ static int check_usable_paths(struct config *conf,
found:
condlog(r == 0 ? 3 : 2, "%s:%s usable paths found",
devpath, r == 0 ? "" : " no");
-free:
- free(mapname);
- free_multipath(mpp, FREE_PATHS);
- vector_free(pathvec);
-out:
- udev_device_unref(ud);
return r;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 42/49] multipathd: implement add_map_without_path() with libmp_mapinfo()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (40 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 41/49] multipath: implement check_usable_paths() with libmp_pathinfo() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:47 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 43/49] libmultipath: simplify dm_get_maps() Martin Wilck
` (6 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Also, change the return value to int, as this is more expressive and
the returned struct multipath isn't used by the caller.
Also remove the call to sync_map_state() in ev_add_map(), which is
redundant because add_map_without_path() would have called update_map()
and thus sync_map_state() already.
Note: this removes the call to remove_map() at the end of the function,
which doesn't make sense anyway, because update_multipath_table()
would not return error unless the table disassembly failed, in which
case nothing would have been added the the mpvec or pathvec yet.
It should be sufficient to just cleanup the local data structures when
add_map_without_path() fails.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
multipathd/main.c | 79 ++++++++++++++++++++++++-----------------------
1 file changed, 41 insertions(+), 38 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 1e7a6ac..536974c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -707,51 +707,57 @@ fail:
return 0;
}
-static struct multipath *
-add_map_without_path (struct vectors *vecs, const char *alias)
+static int add_map_without_path (struct vectors *vecs, const char *alias)
{
- struct multipath * mpp = alloc_multipath();
+ struct multipath __attribute__((cleanup(cleanup_multipath_and_paths)))
+ *mpp = alloc_multipath();
+ char __attribute__((cleanup(cleanup_charp))) *params = NULL;
+ char __attribute__((cleanup(cleanup_charp))) *status = NULL;
struct config *conf;
+ char uuid[DM_UUID_LEN];
+ int rc = DMP_ERR;
- if (!mpp)
- return NULL;
- if (!alias) {
- free(mpp);
- return NULL;
- }
+ if (!mpp || !(mpp->alias = strdup(alias)))
+ return DMP_ERR;
- mpp->alias = strdup(alias);
+ if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .str = mpp->alias },
+ (mapinfo_t) {
+ .uuid = uuid,
+ .dmi = &mpp->dmi,
+ .size = &mpp->size,
+ .target = ¶ms,
+ .status = &status,
+ })) != DMP_OK)
+ return rc;
+
+ if (!is_mpath_uuid(uuid))
+ return DMP_NO_MATCH;
+ else
+ strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
- if (dm_get_info(mpp->alias, &mpp->dmi) != DMP_OK) {
- condlog(3, "%s: cannot access table", mpp->alias);
- goto out;
- }
- if (!strlen(mpp->wwid) &&
- dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE) != DMP_OK) {
- condlog(3, "%s: cannot obtain WWID", mpp->alias);
- goto out;
- }
if (!strlen(mpp->wwid))
condlog(1, "%s: adding map with empty WWID", mpp->alias);
+
conf = get_multipath_config();
mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
put_multipath_config(conf);
- if (update_multipath_table(mpp, vecs->pathvec, 0) != DMP_OK)
- goto out;
+ if ((rc = update_multipath_table__(mpp, vecs->pathvec, 0, params, status)) != DMP_OK)
+ return DMP_ERR;
if (!vector_alloc_slot(vecs->mpvec))
- goto out;
+ return DMP_ERR;
+ vector_set_slot(vecs->mpvec, steal_ptr(mpp));
- vector_set_slot(vecs->mpvec, mpp);
+ /*
+ * We can pass mpp here, steal_ptr() has just nullified it.
+ * vector_set_slot() just set the last slot, use that.
+ */
+ if (update_map(VECTOR_LAST_SLOT(vecs->mpvec), vecs, 1) != 0) /* map removed */
+ return DMP_ERR;
- if (update_map(mpp, vecs, 1) != 0) /* map removed */
- return NULL;
-
- return mpp;
-out:
- remove_map(mpp, vecs->pathvec, vecs->mpvec);
- return NULL;
+ return DMP_OK;
}
static int
@@ -865,14 +871,9 @@ int
ev_add_map (char * dev, const char * alias, struct vectors * vecs)
{
struct multipath * mpp;
- int reassign_maps;
+ int reassign_maps, rc;
struct config *conf;
- if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
- condlog(4, "%s: not a multipath map", alias);
- return 0;
- }
-
mpp = find_mp_by_alias(vecs->mpvec, alias);
if (mpp) {
@@ -910,10 +911,12 @@ ev_add_map (char * dev, const char * alias, struct vectors * vecs)
/*
* now we can register the map
*/
- if ((mpp = add_map_without_path(vecs, alias))) {
- sync_map_state(mpp);
+ if ((rc = add_map_without_path(vecs, alias)) == DMP_OK) {
condlog(2, "%s: devmap %s registered", alias, dev);
return 0;
+ } else if (rc == DMP_NO_MATCH) {
+ condlog(4, "%s: not a multipath map", alias);
+ return 0;
} else {
condlog(2, "%s: ev_add_map failed", dev);
return 1;
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 43/49] libmultipath: simplify dm_get_maps()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (41 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 42/49] multipathd: implement add_map_without_path() with libmp_mapinfo() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 44/49] libmpathpersist: use libmp_mapinfo() in mpath_get_map() Martin Wilck
` (5 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Make dm_get_multipath() return a distinct error code for non-multipath
targets. This way the extra call to dm_is_mpath() is not necessary any
more. As dm_get_maps() is the only caller of dm_get_multipath(), transform
it into a static function.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/devmapper.c | 44 +++++++++++++++++++++-------------------
libmultipath/devmapper.h | 1 -
2 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 86ac01b..b52b10e 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1186,39 +1186,42 @@ dm_disablegroup(const char * mapname, int index)
return dm_groupmsg("disable", mapname, index);
}
-struct multipath *dm_get_multipath(const char *name)
+static int dm_get_multipath(const char *name, struct multipath **pmpp)
{
struct multipath __attribute((cleanup(cleanup_multipath))) *mpp = NULL;
char uuid[DM_UUID_LEN];
+ int rc;
mpp = alloc_multipath();
if (!mpp)
- return NULL;
+ return DMP_ERR;
mpp->alias = strdup(name);
if (!mpp->alias)
- return NULL;
+ return DMP_ERR;
- if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
(mapid_t) { .str = name },
(mapinfo_t) {
.size = &mpp->size,
.uuid = uuid,
.dmi = &mpp->dmi,
- }) != DMP_OK)
- return NULL;
+ })) != DMP_OK)
+ return rc;
if (!is_mpath_uuid(uuid))
- return NULL;
+ return DMP_NO_MATCH;
strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
- return steal_ptr(mpp);
+ *pmpp = steal_ptr(mpp);
+
+ return DMP_OK;
}
int dm_get_maps(vector mp)
{
- struct multipath * mpp;
+ struct multipath *mpp = NULL;
struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
struct dm_names *names;
unsigned next = 0;
@@ -1243,20 +1246,19 @@ int dm_get_maps(vector mp)
}
do {
- if (dm_is_mpath(names->name) != DM_IS_MPATH_YES)
- goto next;
-
- mpp = dm_get_multipath(names->name);
- if (!mpp)
- return 1;
-
- if (!vector_alloc_slot(mp)) {
- free_multipath(mpp, KEEP_PATHS);
+ switch (dm_get_multipath(names->name, &mpp)) {
+ case DMP_OK:
+ if (!vector_alloc_slot(mp)) {
+ free_multipath(mpp, KEEP_PATHS);
+ return 1;
+ }
+ vector_set_slot(mp, mpp);
+ break;
+ case DMP_NO_MATCH:
+ break;
+ default:
return 1;
}
-
- vector_set_slot(mp, mpp);
-next:
next = names->next;
names = (void *) names + next;
} while (next);
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 3daaa4c..d01f9f2 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -184,7 +184,6 @@ int dm_rename (const char * old, char * new, char * delim, int skip_kpartx);
int dm_reassign(const char * mapname);
int dm_reassign_table(const char *name, char *old, char *new);
int dm_setgeometry(struct multipath *mpp);
-struct multipath *dm_get_multipath(const char *name);
#define VERSION_GE(v, minv) ( \
(v[0] > minv[0]) || \
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 44/49] libmpathpersist: use libmp_mapinfo() in mpath_get_map()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (42 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 43/49] libmultipath: simplify dm_get_maps() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:48 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 45/49] libmpathpersist: use mpp->alias in do_mpath_persistent_reserve_out() Martin Wilck
` (4 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
When obtaining the map name, make sure right away that the map is a multipath
device. This saves an ioctl and slightly simplifies the function.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist_int.c | 50 +++++++++++++----------------
1 file changed, 23 insertions(+), 27 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index 5a5ac3b..a3eb80a 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -157,10 +157,9 @@ static int get_mpvec(vector curmp, vector pathvec, char *refwwid)
static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
struct multipath **pmpp)
{
- int ret = MPATH_PR_DMMP_ERROR;
+ int rc;
struct stat info;
- int major, minor;
- char *alias;
+ char alias[WWID_SIZE], uuid[DM_UUID_LEN];
struct multipath *mpp;
if (fstat(fd, &info) != 0){
@@ -172,47 +171,44 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
return MPATH_PR_FILE_ERROR;
}
- major = major(info.st_rdev);
- minor = minor(info.st_rdev);
- condlog(4, "Device %d:%d", major, minor);
-
/* get alias from major:minor*/
- alias = dm_mapname(major, minor);
- if (!alias){
- condlog(0, "%d:%d failed to get device alias.", major, minor);
+ rc = libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
+ (mapid_t) { .devt = info.st_rdev },
+ (mapinfo_t) {
+ .name = alias,
+ .uuid = uuid,
+ });
+
+ if (rc == DMP_NO_MATCH || !is_mpath_uuid(uuid)) {
+ condlog(3, "%s: not a multipath device.", alias);
+ return MPATH_PR_DMMP_ERROR;
+ } else if (rc != DMP_OK) {
+ condlog(1, "%d:%d failed to get device alias.",
+ major(info.st_rdev), minor(info.st_rdev));
return MPATH_PR_DMMP_ERROR;
}
- condlog(3, "alias = %s", alias);
-
- if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
- condlog(3, "%s: not a multipath device.", alias);
- goto out;
- }
+ condlog(4, "alias = %s", alias);
/* get info of all paths from the dm device */
- if (get_mpvec(curmp, pathvec, alias)){
+ if (get_mpvec(curmp, pathvec, alias)) {
condlog(0, "%s: failed to get device info.", alias);
- goto out;
+ return MPATH_PR_DMMP_ERROR;
}
mpp = find_mp_by_alias(curmp, alias);
if (!mpp) {
condlog(0, "%s: devmap not registered.", alias);
- goto out;
+ return MPATH_PR_DMMP_ERROR;
}
- ret = MPATH_PR_SUCCESS;
if (pmpp)
*pmpp = mpp;
- if (palias) {
- *palias = alias;
- alias = NULL;
- }
-out:
- free(alias);
- return ret;
+ if (palias && (*palias = strdup(alias)) == NULL)
+ return MPATH_PR_DMMP_ERROR;
+
+ return MPATH_PR_SUCCESS;
}
int do_mpath_persistent_reserve_in(vector curmp, vector pathvec,
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 45/49] libmpathpersist: use mpp->alias in do_mpath_persistent_reserve_out()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (43 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 44/49] libmpathpersist: use libmp_mapinfo() in mpath_get_map() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-12 17:14 ` [PATCH v2 46/49] libmultipath: fix deferred_remove logic in remove_partmap() Martin Wilck
` (3 subsequent siblings)
48 siblings, 0 replies; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The extra pointer "alias" isn't necessary. The mp vector is initialized
by dm_get_maps(), which will allocate mpp->alias for every map, thus we
can use it in do_mpath_persistent_reserve_out(). This allows us to simplify
both this function itself and mpath_get_map().
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_persist_int.c | 38 ++++++++++++-----------------
1 file changed, 15 insertions(+), 23 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index a3eb80a..807415f 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -154,8 +154,7 @@ static int get_mpvec(vector curmp, vector pathvec, char *refwwid)
return MPATH_PR_SUCCESS ;
}
-static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
- struct multipath **pmpp)
+static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath **pmpp)
{
int rc;
struct stat info;
@@ -205,8 +204,6 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
if (pmpp)
*pmpp = mpp;
- if (palias && (*palias = strdup(alias)) == NULL)
- return MPATH_PR_DMMP_ERROR;
return MPATH_PR_SUCCESS;
}
@@ -218,7 +215,7 @@ int do_mpath_persistent_reserve_in(vector curmp, vector pathvec,
struct multipath *mpp;
int ret;
- ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
+ ret = mpath_get_map(curmp, pathvec, fd, &mpp);
if (ret != MPATH_PR_SUCCESS)
return ret;
@@ -649,12 +646,11 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
struct prout_param_descriptor *paramp, int noisy)
{
struct multipath *mpp;
- char *alias;
int ret;
uint64_t prkey;
struct config *conf;
- ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
+ ret = mpath_get_map(curmp, pathvec, fd, &mpp);
if (ret != MPATH_PR_SUCCESS)
return ret;
@@ -670,21 +666,20 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
(!get_be64(mpp->reservation_key) ||
memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
memcpy(&mpp->reservation_key, paramp->sa_key, 8);
- if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
+ if (update_prkey_flags(mpp->alias, get_be64(mpp->reservation_key),
paramp->sa_flags)) {
condlog(0, "%s: failed to set prkey for multipathd.",
- alias);
- ret = MPATH_PR_DMMP_ERROR;
- goto out1;
+ mpp->alias);
+ return MPATH_PR_DMMP_ERROR;
}
}
if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
(prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
- condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
- ret = MPATH_PR_SYNTAX_ERROR;
- goto out1;
+ condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64,
+ mpp->alias, get_be64(mpp->reservation_key));
+ return MPATH_PR_SYNTAX_ERROR;
}
switch(rq_servact)
@@ -703,24 +698,21 @@ int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
ret = mpath_prout_rel(mpp, rq_servact, rq_scope, rq_type, paramp, noisy);
break;
default:
- ret = MPATH_PR_OTHER;
- goto out1;
+ return MPATH_PR_OTHER;
}
if ((ret == MPATH_PR_SUCCESS) && ((rq_servact == MPATH_PROUT_REG_SA) ||
(rq_servact == MPATH_PROUT_REG_IGN_SA)))
{
if (prkey == 0) {
- update_prflag(alias, 0);
- update_prkey(alias, 0);
+ update_prflag(mpp->alias, 0);
+ update_prkey(mpp->alias, 0);
} else
- update_prflag(alias, 1);
+ update_prflag(mpp->alias, 1);
} else if ((ret == MPATH_PR_SUCCESS) && (rq_servact == MPATH_PROUT_CLEAR_SA)) {
- update_prflag(alias, 0);
- update_prkey(alias, 0);
+ update_prflag(mpp->alias, 0);
+ update_prkey(mpp->alias, 0);
}
-out1:
- free(alias);
return ret;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 46/49] libmultipath: fix deferred_remove logic in remove_partmap()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (44 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 45/49] libmpathpersist: use mpp->alias in do_mpath_persistent_reserve_out() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:49 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 47/49] libmultipath: don't call do_foreach_partmaps() recursively Martin Wilck
` (2 subsequent siblings)
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
The logic for returning DM_FLUSH_BUSY in remove_partmap() got
accidentally reverted in commit 20aeeb6. Fix it.
Fixes: 20aeeb6 ("libmultipath: fix deferred_remove function arguments")
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index b52b10e..5749d63 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1383,7 +1383,7 @@ remove_partmap(const char *name, void *data)
if (dm_get_opencount(name)) {
dm_remove_partmaps(name, rd->flags);
- if ((rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
+ if (!(rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
condlog(2, "%s: map in use", name);
return DM_FLUSH_BUSY;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 47/49] libmultipath: don't call do_foreach_partmaps() recursively
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (45 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 46/49] libmultipath: fix deferred_remove logic in remove_partmap() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 22:51 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 48/49] libmultipath: Move UUID check into libmp_pathinfo__() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 49/49] multipath-tools tests: fix directio test with real device Martin Wilck
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
We've removed partition mappings recursively since 83fb936 ("Correctly remove
logical partition maps"). This was wrong, because kpartx doesn't create
logical partitions as mappings onto the extended partition. Rather, logical
partitions are created by kpartx as mappings to the multipath device, and
afaics, this has always been the case. Therefore, the loop in
do_foreach_partmaps() will detect all partition mappings (primary, extended,
and logical) without recursion. At least since 4059e42 ("libmultipath: fix
partition detection"), the recursion has actually been pointless, because
is_mpath_part() would never have returned "true" for a pair of two partition
mappings (one representing an extended partition and one a logical partition).
Avoiding the recursion has the additional benefit that the complexity of
removing maps scales with N, where N is the number of dm devices, rather than
with N^2. Also, it simplifies the code.
Split partmap_in_use() into two separate functions, mpath_in_use() (to be called
for multipath maps) and count_partitions(), which is called from
do_foreach_partmaps().
Because do_foreach_partmaps() is now only legitimately called for multipath
maps, quit early if called for another map type.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/devmapper.c | 48 +++++++++++++++++++------------
libmultipath/devmapper.h | 2 +-
libmultipath/libmultipath.version | 2 +-
multipathd/main.c | 2 +-
4 files changed, 33 insertions(+), 21 deletions(-)
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 5749d63..d9d96be 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -933,22 +933,37 @@ has_partmap(const char *name __attribute__((unused)),
return 1;
}
-int
-partmap_in_use(const char *name, void *data)
+/*
+ * This will be called from mpath_in_use, for each partition.
+ * If the partition itself in use, returns 1 immediately, causing
+ * do_foreach_partmaps() to stop iterating and return 1.
+ * Otherwise, increases the partition count.
+ */
+static int count_partitions(const char *name, void *data)
+{
+ int *ret_count = (int *)data;
+ int open_count = dm_get_opencount(name);
+
+ if (open_count)
+ return 1;
+ (*ret_count)++;
+ return 0;
+}
+
+int mpath_in_use(const char *name)
{
- int part_count, *ret_count = (int *)data;
int open_count = dm_get_opencount(name);
- if (ret_count)
- (*ret_count)++;
- part_count = 0;
if (open_count) {
- if (do_foreach_partmaps(name, partmap_in_use, &part_count))
- return 1;
- if (open_count != part_count) {
- condlog(2, "%s: map in use", name);
+ int part_count = 0;
+
+ if (do_foreach_partmaps(name, count_partitions, &part_count)) {
+ condlog(4, "%s: %s has open partitions", __func__, name);
return 1;
}
+ condlog(4, "%s: %s: %d openers, %d partitions", __func__, name,
+ open_count, part_count);
+ return open_count > part_count;
}
return 0;
}
@@ -976,7 +991,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
/* If you aren't doing a deferred remove, make sure that no
* devices are in use */
- if (!(flags & DMFL_DEFERRED) && partmap_in_use(mapname, NULL))
+ if (!(flags & DMFL_DEFERRED) && mpath_in_use(mapname))
return DM_FLUSH_BUSY;
if ((flags & DMFL_SUSPEND) &&
@@ -1314,7 +1329,7 @@ do_foreach_partmaps (const char *mapname,
char map_uuid[DM_UUID_LEN];
struct dm_info info;
- if (libmp_mapinfo(DM_MAP_BY_NAME,
+ if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
(mapid_t) { .str = mapname },
(mapinfo_t) { .uuid = map_uuid, .dmi = &info }) != DMP_OK)
return 1;
@@ -1381,12 +1396,9 @@ remove_partmap(const char *name, void *data)
{
struct remove_data *rd = (struct remove_data *)data;
- if (dm_get_opencount(name)) {
- dm_remove_partmaps(name, rd->flags);
- if (!(rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
- condlog(2, "%s: map in use", name);
- return DM_FLUSH_BUSY;
- }
+ if (!(rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
+ condlog(2, "%s: map in use", name);
+ return DM_FLUSH_BUSY;
}
condlog(4, "partition map %s removed", name);
dm_device_remove(name, rd->flags);
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index d01f9f2..6eb5ab9 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -149,7 +149,7 @@ enum {
DM_FLUSH_BUSY,
};
-int partmap_in_use(const char *name, void *data);
+int mpath_in_use(const char *name);
enum {
DMFL_NONE = 0,
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 54b5a23..649c1cb 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -139,10 +139,10 @@ global:
libmultipath_exit;
libmultipath_init;
load_config;
+ mpath_in_use;
need_io_err_check;
orphan_path;
parse_prkey_flags;
- partmap_in_use;
pathcount;
path_discovery;
path_get_tpgs;
diff --git a/multipathd/main.c b/multipathd/main.c
index 536974c..13af94e 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -597,7 +597,7 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
return false;
}
if (mpp->flush_on_last_del == FLUSH_UNUSED &&
- partmap_in_use(mpp->alias, NULL) && is_queueing) {
+ mpath_in_use(mpp->alias) && is_queueing) {
condlog(2, "%s: map in use and queueing, can't remove",
mpp->alias);
return false;
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 48/49] libmultipath: Move UUID check into libmp_pathinfo__()
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (46 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 47/49] libmultipath: don't call do_foreach_partmaps() recursively Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 23:24 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 49/49] multipath-tools tests: fix directio test with real device Martin Wilck
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
We have a couple of callers that check whether the map UUID conforms
to the multipath convention ("mpath-xyz"). Move this check into
libmp_mapinfo__(). Add another flag MAPINFO_CHECK_UUID for this
purpose. This allows to simplify some callers, which only fetched
the UUID in order to check it.
Note that the UUID check is orthogonal to MAPINFO_MPATH_ONLY, which
tests the target type. We shold make sure that both tests are in
agreement, but this is postponed to a later patch set.
is_mpath_uuid() can now be converted to a static function.
Also add some unit tests for the WWID check.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist_int.c | 11 +-
libmultipath/devmapper.c | 52 +++----
libmultipath/devmapper.h | 3 +-
libmultipath/libmultipath.version | 1 -
multipath/main.c | 5 +-
multipathd/main.c | 7 +-
tests/mapinfo.c | 226 ++++++++++++++++++++++++++++
7 files changed, 256 insertions(+), 49 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index 807415f..f4d9e7c 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -158,7 +158,7 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath
{
int rc;
struct stat info;
- char alias[WWID_SIZE], uuid[DM_UUID_LEN];
+ char alias[WWID_SIZE];
struct multipath *mpp;
if (fstat(fd, &info) != 0){
@@ -171,14 +171,11 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath
}
/* get alias from major:minor*/
- rc = libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
+ rc = libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
(mapid_t) { .devt = info.st_rdev },
- (mapinfo_t) {
- .name = alias,
- .uuid = uuid,
- });
+ (mapinfo_t) { .name = alias });
- if (rc == DMP_NO_MATCH || !is_mpath_uuid(uuid)) {
+ if (rc == DMP_NO_MATCH) {
condlog(3, "%s: not a multipath device.", alias);
return MPATH_PR_DMMP_ERROR;
} else if (rc != DMP_OK) {
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index d9d96be..bbbadee 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -611,6 +611,11 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush)
return 0;
}
+static bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
+{
+ return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
+}
+
bool
has_dm_info(const struct multipath *mpp)
{
@@ -734,11 +739,17 @@ static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info, const char *ma
* If error is returned, don't touch any output parameters.
*/
if ((info.name && !(name = dm_task_get_name(dmt)))
- || (info.uuid && !(uuid = dm_task_get_uuid(dmt)))
+ || ((info.uuid || flags & MAPINFO_CHECK_UUID)
+ && !(uuid = dm_task_get_uuid(dmt)))
|| (info.status && !(tmp_status = strdup(params)))
|| (info.target && !tmp_target && !(tmp_target = strdup(params))))
return DMP_ERR;
+ if (flags & MAPINFO_CHECK_UUID && !is_mpath_uuid(uuid)) {
+ condlog(3, "%s: UUID mismatch: %s", __func__, uuid);
+ return DMP_NO_MATCH;
+ }
+
if (info.name) {
strlcpy(info.name, name, WWID_SIZE);
condlog(4, "%s: %s: name: \"%s\"", __func__, map_id, info.name);
@@ -808,18 +819,6 @@ int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
libmp_map_identifier(flags, id, idbuf));
}
-static int dm_get_dm_uuid(const char *mapname, char uuid[DM_UUID_LEN])
-{
- return libmp_mapinfo(DM_MAP_BY_NAME,
- (mapid_t) { .str = mapname },
- (mapinfo_t) { .uuid = uuid });
-}
-
-bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
-{
- return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
-}
-
/**
* dm_get_wwid(): return WWID for a multipath map
* @returns:
@@ -832,16 +831,14 @@ bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
int dm_get_wwid(const char *name, char *uuid, int uuid_len)
{
char tmp[DM_UUID_LEN];
- int rc = dm_get_dm_uuid(name, tmp);
+ int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = name },
+ (mapinfo_t) { .uuid = tmp });
if (rc != DMP_OK)
return rc;
- if (is_mpath_uuid(tmp))
- strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
- else
- return DMP_NO_MATCH;
-
+ strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
return DMP_OK;
}
@@ -859,16 +856,13 @@ static bool is_mpath_part_uuid(const char part_uuid[DM_UUID_LEN],
int dm_is_mpath(const char *name)
{
- char uuid[DM_UUID_LEN];
- int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
(mapid_t) { .str = name },
- (mapinfo_t) { .uuid = uuid });
+ (mapinfo_t) { .uuid = NULL });
switch (rc) {
case DMP_OK:
- if (is_mpath_uuid(uuid))
- return DM_IS_MPATH_YES;
- /* fallthrough */
+ return DM_IS_MPATH_YES;
case DMP_NOT_FOUND:
case DMP_NO_MATCH:
return DM_IS_MPATH_NO;
@@ -974,14 +968,10 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
int queue_if_no_path = 0;
int udev_flags = 0;
char *params __attribute__((cleanup(cleanup_charp))) = NULL;
- char uuid[DM_UUID_LEN];
- if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
(mapid_t) { .str = mapname },
- (mapinfo_t) {
- .uuid = uuid,
- .target = ¶ms }) != DMP_OK
- || !is_mpath_uuid(uuid))
+ (mapinfo_t) { .target = ¶ms }) != DMP_OK)
return DM_FLUSH_OK; /* nothing to do */
/* if the device currently has no partitions, do not
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index 6eb5ab9..c28991f 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -57,6 +57,8 @@ enum __mapinfo_flags {
/* Fail if target type is not "partition" (linear) */
MAPINFO_PART_ONLY = (1 << 4),
__MAPINFO_TGT_TYPE = (MAPINFO_MPATH_ONLY | MAPINFO_PART_ONLY),
+ /* Fail if the UUID doesn't match the multipath UUID format */
+ MAPINFO_CHECK_UUID = (1 << 8),
};
typedef union libmp_map_identifier {
@@ -138,7 +140,6 @@ enum {
DM_IS_MPATH_ERR,
};
-bool is_mpath_uuid(const char uuid[DM_UUID_LEN]);
int dm_is_mpath(const char *name);
enum {
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 649c1cb..959f675 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -127,7 +127,6 @@ global:
init_foreign;
init_prio;
io_err_stat_handle_pathfail;
- is_mpath_uuid;
is_path_valid;
libmp_dm_task_create;
libmp_get_version;
diff --git a/multipath/main.c b/multipath/main.c
index 0d989dc..4b19d2e 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -254,7 +254,7 @@ static int check_usable_paths(struct config *conf,
if (pathvec == NULL)
return r;
- if (libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
+ if (libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
(mapid_t) { .devt = devt },
(mapinfo_t) {
.name = mpp->alias,
@@ -266,9 +266,6 @@ static int check_usable_paths(struct config *conf,
}) != DMP_OK)
return r;
- if (!is_mpath_uuid(uuid))
- return r;
-
strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
if (update_multipath_table__(mpp, pathvec, 0, params, status) != DMP_OK)
diff --git a/multipathd/main.c b/multipathd/main.c
index 13af94e..386cd07 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -720,7 +720,7 @@ static int add_map_without_path (struct vectors *vecs, const char *alias)
if (!mpp || !(mpp->alias = strdup(alias)))
return DMP_ERR;
- if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
+ if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
(mapid_t) { .str = mpp->alias },
(mapinfo_t) {
.uuid = uuid,
@@ -731,10 +731,7 @@ static int add_map_without_path (struct vectors *vecs, const char *alias)
})) != DMP_OK)
return rc;
- if (!is_mpath_uuid(uuid))
- return DMP_NO_MATCH;
- else
- strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
+ strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
if (!strlen(mpp->wwid))
condlog(1, "%s: adding map with empty WWID", mpp->alias);
diff --git a/tests/mapinfo.c b/tests/mapinfo.c
index f3a8440..f7ad868 100644
--- a/tests/mapinfo.c
+++ b/tests/mapinfo.c
@@ -54,6 +54,16 @@ static const char MPATH_STATUS_01[] =
"A 0 3 2 65:32 A 0 0 1 67:64 A 0 0 1 69:96 A 0 0 1 "
"E 0 3 2 8:16 A 0 0 1 66:48 A 0 0 1 68:80 A 0 0 1 ";
+static const char BAD_UUID_01[] = "";
+static const char BAD_UUID_02[] = "mpath3600a098038302d414b2b4d4453474f62";
+static const char BAD_UUID_03[] = " mpath-3600a098038302d414b2b4d4453474f62";
+static const char BAD_UUID_04[] = "-mpath-3600a098038302d414b2b4d4453474f62";
+static const char BAD_UUID_05[] = "mpth-3600a098038302d414b2b4d4453474f62";
+static const char BAD_UUID_06[] = "part1-mpath-3600a098038302d414b2b4d4453474f62";
+static const char BAD_UUID_07[] = "mpath 3600a098038302d414b2b4d4453474f62";
+static const char BAD_UUID_08[] = "mpath";
+static const char BAD_UUID_09[] = "mpath-";
+
char *__real_strdup(const char *str);
char *__wrap_strdup(const char *str)
{
@@ -413,6 +423,208 @@ static void test_mapinfo_good_exists(void **state)
assert_int_equal(rc, DMP_OK);
}
+static void test_mapinfo_bad_check_uuid_00(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, NULL);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_ERR);
+}
+
+static void test_mapinfo_bad_check_uuid_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_02(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_02);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_03(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_03);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_04(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_04);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_05(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_05);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_06(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_06);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_07(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_07);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_08(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_08);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_NO_MATCH);
+}
+
+static void test_mapinfo_bad_check_uuid_09(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, BAD_UUID_09);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_good_check_uuid_01(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_good_check_uuid_02(void **state)
+{
+ int rc;
+ char uuid[DM_UUID_LEN];
+
+ mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .uuid = uuid });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_good_check_uuid_03(void **state)
+{
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .name = NULL });
+ assert_int_equal(rc, DMP_OK);
+}
+
+static void test_mapinfo_good_check_uuid_04(void **state)
+{
+ char __attribute__((cleanup(cleanup_charp))) *target = NULL;
+ int rc;
+
+ mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
+ WRAP_DM_TASK_GET_INFO(1);
+ WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
+ mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
+ will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
+ will_return(__wrap_strdup, 1);
+
+ rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
+ (mapid_t) { .str = "foo", },
+ (mapinfo_t) { .target = &target });
+ assert_int_equal(rc, DMP_OK);
+}
+
static void test_mapinfo_bad_set_uuid(void **state)
{
int rc;
@@ -1126,6 +1338,20 @@ static int test_mapinfo(void)
cmocka_unit_test(test_mapinfo_bad_get_info_03),
cmocka_unit_test(test_mapinfo_bad_get_info_04),
cmocka_unit_test(test_mapinfo_good_exists),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_00),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_01),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_02),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_03),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_04),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_05),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_06),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_07),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_08),
+ cmocka_unit_test(test_mapinfo_bad_check_uuid_09),
+ cmocka_unit_test(test_mapinfo_good_check_uuid_01),
+ cmocka_unit_test(test_mapinfo_good_check_uuid_02),
+ cmocka_unit_test(test_mapinfo_good_check_uuid_03),
+ cmocka_unit_test(test_mapinfo_good_check_uuid_04),
cmocka_unit_test(test_mapinfo_bad_set_uuid),
cmocka_unit_test(test_mapinfo_bad_set_dev_01),
cmocka_unit_test(test_mapinfo_bad_set_dev_02),
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH v2 49/49] multipath-tools tests: fix directio test with real device
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
` (47 preceding siblings ...)
2024-07-12 17:14 ` [PATCH v2 48/49] libmultipath: Move UUID check into libmp_pathinfo__() Martin Wilck
@ 2024-07-12 17:14 ` Martin Wilck
2024-07-15 23:25 ` Benjamin Marzinski
48 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-12 17:14 UTC (permalink / raw)
To: Christophe Varoqui, Benjamin Marzinski; +Cc: dm-devel, Martin Wilck
Allow setting DIO_TEST_DEV during runtime, by reading the environment
variable. The test was fragile despite the delay, because the real
io_getevents() call isn't guaranteed to return the number of events
requested. Fix that. Moreover, allow reading DIO_TEST_DELAY (in us)
from the environment. With the io_getevents fix, for me the test
succeeded even with 0 us delay.
Change the README accordingly.
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
tests/Makefile | 8 ---
tests/README.md | 29 ++++++--
tests/directio.c | 182 ++++++++++++++++++++++++++---------------------
3 files changed, 122 insertions(+), 97 deletions(-)
diff --git a/tests/Makefile b/tests/Makefile
index 55fbf0f..02580e7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -21,12 +21,6 @@ valgrind: $(TESTS:%=%.vgr)
# test-specific compiler flags
# XYZ-test_FLAGS: Additional compiler flags for this test
-ifneq ($(wildcard directio_test_dev),)
-DIO_TEST_DEV = $(shell sed -n -e 's/^[[:space:]]*DIO_TEST_DEV[[:space:]]*=[[:space:]]*\([^[:space:]\#]\+\).*/\1/p' < directio_test_dev)
-endif
-ifneq ($(DIO_TEST_DEV),)
-directio-test_FLAGS := -DDIO_TEST_DEV=\"$(DIO_TEST_DEV)\"
-endif
mpathvalid-test_FLAGS := -I$(mpathvaliddir)
features-test_FLAGS := -I$(multipathdir)/nvme
@@ -59,9 +53,7 @@ valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl
devt-test_LIBDEPS := -ludev
mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl
mpathvalid-test_OBJDEPS := $(mpathvaliddir)/mpath_valid.o
-ifneq ($(DIO_TEST_DEV),)
directio-test_LIBDEPS := -laio
-endif
strbuf-test_OBJDEPS := $(mpathutildir)/strbuf.o
sysfs-test_TESTDEPS := test-log.o
sysfs-test_OBJDEPS := $(multipathdir)/sysfs.o $(mpathutildir)/util.o
diff --git a/tests/README.md b/tests/README.md
index fd36fc1..0cae057 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -13,6 +13,17 @@ If valgrind detects a bad memory access or leak, the test will fail. The
output of the test run, including valgrind output, is stored as
`<testname>.vgr`.
+## Running tests manually
+
+`make test` or `make -C test "$TEST.out"` will only run the test program if
+the output files `$TEST.out` don't exist yet. To re-run the test, delete the
+output file first. In order to run a test outside `make`, set the library
+search path:
+
+ cd tests
+ export LD_LIBRARY_PATH=.:../libmpathutil:../libmpathcmd
+ ./dmevents-test # or whatever other test you want to run
+
## Controlling verbosity for unit tests
Some test programs use the environment variable `MPATHTEST_VERBOSITY` to
@@ -37,15 +48,21 @@ This test includes test items that require a access to a block device. The
device will be opened in read-only mode; you don't need to worry about data
loss. However, the user needs to specify a device to be used. Set the
environment variable `DIO_TEST_DEV` to the path of the device.
-Alternatively, create a file `directio_test_dev` under
-the `tests` directory containing a single line that sets this environment
-variable in Bourne Shell syntax, like this:
-
- DIO_TEST_DEV=/dev/sdc3
-
After that, run `make directio.out` as root in the `tests` directory to
perform the test.
+With a real test device, the test results may note be 100% reproducible,
+and sporadic test failures may occur under certain circumstances.
+It may be necessary to introduce a certain delay between test
+operations. To do so, set the environment variable `DIO_TEST_DELAY` to a
+positive integer that determines the delay (in microseconds) after each
+`io_submit()` operation. The default delay is 10 microseconds.
+
+*Note:* `DIO_TEST_DEV` doesn't have to be set during compilation of
+`directio-test`. This used to be the case in previous versions of
+multipath-tools. Previously, it was possible to set `DIO_TEST_DEV` in a file
+`tests/directio_test_dev`. This is not supported any more.
+
## Adding tests
The unit tests are based on the [cmocka test framework](https://cmocka.org/),
diff --git a/tests/directio.c b/tests/directio.c
index d5f84f1..763929e 100644
--- a/tests/directio.c
+++ b/tests/directio.c
@@ -34,6 +34,8 @@ struct io_event mock_events[AIO_GROUP_SIZE]; /* same as the checker max */
int ev_off = 0;
struct timespec zero_timeout = { .tv_sec = 0 };
struct timespec full_timeout = { .tv_sec = -1 };
+const char *test_dev = NULL;
+unsigned int test_delay = 10000;
#ifdef __GLIBC__
#define ioctl_request_t unsigned long
@@ -45,12 +47,13 @@ int REAL_IOCTL(int fd, ioctl_request_t request, void *argp);
int WRAP_IOCTL(int fd, ioctl_request_t request, void *argp)
{
-#ifdef DIO_TEST_DEV
- mock_type(int);
- return REAL_IOCTL(fd, request, argp);
-#else
int *blocksize = (int *)argp;
+ if (test_dev) {
+ mock_type(int);
+ return REAL_IOCTL(fd, request, argp);
+ }
+
assert_int_equal(fd, test_fd);
/*
* On MUSL libc, the "request" arg is an int (glibc: unsigned long).
@@ -64,88 +67,80 @@ int WRAP_IOCTL(int fd, ioctl_request_t request, void *argp)
assert_non_null(blocksize);
*blocksize = mock_type(int);
return 0;
-#endif
}
int REAL_FCNTL (int fd, int cmd, long arg);
int WRAP_FCNTL (int fd, int cmd, long arg)
{
-#ifdef DIO_TEST_DEV
- return REAL_FCNTL(fd, cmd, arg);
-#else
+ if (test_dev)
+ return REAL_FCNTL(fd, cmd, arg);
assert_int_equal(fd, test_fd);
assert_int_equal(cmd, F_GETFL);
return O_DIRECT;
-#endif
}
int __real___fxstat(int ver, int fd, struct stat *statbuf);
int __wrap___fxstat(int ver, int fd, struct stat *statbuf)
{
-#ifdef DIO_TEST_DEV
- return __real___fxstat(ver, fd, statbuf);
-#else
+ if (test_dev)
+ return __real___fxstat(ver, fd, statbuf);
+
assert_int_equal(fd, test_fd);
assert_non_null(statbuf);
memset(statbuf, 0, sizeof(struct stat));
return 0;
-#endif
+
}
int __real_io_setup(int maxevents, io_context_t *ctxp);
int __wrap_io_setup(int maxevents, io_context_t *ctxp)
{
- ioctx_count++;
-#ifdef DIO_TEST_DEV
int ret = mock_type(int);
- assert_int_equal(ret, __real_io_setup(maxevents, ctxp));
+
+ if (test_dev)
+ assert_int_equal(ret, __real_io_setup(maxevents, ctxp));
+ ioctx_count++;
return ret;
-#else
- return mock_type(int);
-#endif
}
int __real_io_destroy(io_context_t ctx);
int __wrap_io_destroy(io_context_t ctx)
{
- ioctx_count--;
-#ifdef DIO_TEST_DEV
int ret = mock_type(int);
- assert_int_equal(ret, __real_io_destroy(ctx));
+
+ ioctx_count--;
+ if (test_dev)
+ assert_int_equal(ret, __real_io_destroy(ctx));
+
return ret;
-#else
- return mock_type(int);
-#endif
}
int __real_io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
int __wrap_io_submit(io_context_t ctx, long nr, struct iocb *ios[])
{
-#ifdef DIO_TEST_DEV
- struct timespec dev_delay = { .tv_nsec = 100000 };
int ret = mock_type(int);
- assert_int_equal(ret, __real_io_submit(ctx, nr, ios));
- nanosleep(&dev_delay, NULL);
+
+ if (test_dev) {
+ struct timespec dev_delay = { .tv_nsec = test_delay };
+ assert_int_equal(ret, __real_io_submit(ctx, nr, ios));
+ nanosleep(&dev_delay, NULL);
+ }
return ret;
-#else
- return mock_type(int);
-#endif
}
int __real_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
int __wrap_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt)
{
-#ifdef DIO_TEST_DEV
- return __real_io_cancel(ctx, iocb, evt);
-#else
- return 0;
-#endif
+ if (test_dev)
+ return __real_io_cancel(ctx, iocb, evt);
+ else
+ return 0;
}
int REAL_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr,
@@ -155,38 +150,43 @@ int WRAP_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr,
struct io_event *events, struct timespec *timeout)
{
int nr_evs;
-#ifndef DIO_TEST_DEV
struct timespec *sleep_tmo;
int i;
struct io_event *evs;
-#endif
assert_non_null(timeout);
nr_evs = mock_type(int);
assert_true(nr_evs <= nr);
if (!nr_evs)
return 0;
-#ifdef DIO_TEST_DEV
- mock_ptr_type(struct timespec *);
- mock_ptr_type(struct io_event *);
- assert_int_equal(nr_evs, REAL_IO_GETEVENTS(ctx, min_nr, nr_evs,
- events, timeout));
-#else
- sleep_tmo = mock_ptr_type(struct timespec *);
- if (sleep_tmo) {
- if (sleep_tmo->tv_sec < 0)
- nanosleep(timeout, NULL);
- else
- nanosleep(sleep_tmo, NULL);
+ if (test_dev) {
+ int n = 0;
+ mock_ptr_type(struct timespec *);
+ mock_ptr_type(struct io_event *);
+
+ condlog(2, "min_nr = %ld nr_evs = %d", min_nr, nr_evs);
+ while (n < nr_evs) {
+ min_nr = min_nr <= nr_evs - n ? min_nr : nr_evs - n;
+ n += REAL_IO_GETEVENTS(ctx, min_nr, nr_evs - n,
+ events + n, timeout);
+ }
+ assert_int_equal(nr_evs, n);
+ } else {
+ sleep_tmo = mock_ptr_type(struct timespec *);
+ if (sleep_tmo) {
+ if (sleep_tmo->tv_sec < 0)
+ nanosleep(timeout, NULL);
+ else
+ nanosleep(sleep_tmo, NULL);
+ }
+ if (nr_evs < 0) {
+ errno = -nr_evs;
+ return -1;
+ }
+ evs = mock_ptr_type(struct io_event *);
+ for (i = 0; i < nr_evs; i++)
+ events[i] = evs[i];
}
- if (nr_evs < 0) {
- errno = -nr_evs;
- return -1;
- }
- evs = mock_ptr_type(struct io_event *);
- for (i = 0; i < nr_evs; i++)
- events[i] = evs[i];
-#endif
ev_off -= nr_evs;
return nr_evs;
}
@@ -259,10 +259,9 @@ static void do_libcheck_init(struct checker *c, int blocksize,
assert_non_null(ct->req);
if (req)
*req = ct->req;
-#ifndef DIO_TEST_DEV
- /* don't check fake blocksize on real devices */
- assert_int_equal(ct->req->blksize, blocksize);
-#endif
+ if (!test_dev)
+ /* don't check fake blocksize on real devices */
+ assert_int_equal(ct->req->blksize, blocksize);
}
static int is_checker_running(struct checker *c)
@@ -583,11 +582,11 @@ static void test_async_timeout_cancel_failed(void **state)
do_check_state(&c[1], 0, 2, PATH_PENDING);
return_io_getevents_none();
do_check_state(&c[0], 0, 2, PATH_DOWN);
-#ifndef DIO_TEST_DEV
- /* can't pick which even gets returned on real devices */
- return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
- do_check_state(&c[1], 0, 2, PATH_UP);
-#endif
+ if (!test_dev) {
+ /* can't pick which even gets returned on real devices */
+ return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
+ do_check_state(&c[1], 0, 2, PATH_UP);
+ }
return_io_getevents_none();
do_check_state(&c[0], 0, 2, PATH_DOWN);
assert_true(is_checker_running(&c[0]));
@@ -663,12 +662,11 @@ static void test_check_state_blksize(void **state)
int blksize[] = {4096, 1024, 512};
struct async_req *reqs[3];
int res[] = {0,1,0};
-#ifdef DIO_TEST_DEV
- /* can't pick event return state on real devices */
int chk_state[] = {PATH_UP, PATH_UP, PATH_UP};
-#else
- int chk_state[] = {PATH_UP, PATH_DOWN, PATH_UP};
-#endif
+
+ /* can't pick event return state on real devices */
+ if (!test_dev)
+ chk_state[1] = PATH_DOWN;
assert_true(list_empty(&aio_grp_list));
will_return(__wrap_io_setup, 0);
@@ -718,20 +716,38 @@ static void test_check_state_async(void **state)
static int setup(void **state)
{
-#ifdef DIO_TEST_DEV
- test_fd = open(DIO_TEST_DEV, O_RDONLY);
- if (test_fd < 0)
- fail_msg("cannot open %s: %m", DIO_TEST_DEV);
-#endif
+ char *dl = getenv("DIO_TEST_DELAY");
+ test_dev = getenv("DIO_TEST_DEV");
+
+ if (test_dev) {
+ condlog(2, "%s: opening %s", __func__, test_dev);
+ test_fd = open(test_dev, O_RDONLY);
+ if (dl) {
+ char *e;
+ long int d = strtol(dl, &e, 10);
+
+ if (*e == '\0' && d >= 0 && (d * 1000) < (long)UINT_MAX)
+ test_delay = d * 1000;
+ else {
+ condlog(1, "DIO_TEST_DELAY=%s is invalid", dl);
+ return 1;
+ }
+ }
+ condlog(2, "%s: delay = %u us", __func__, test_delay / 1000);
+ }
+ if (test_fd < 0) {
+ fail_msg("cannot open %s: %m", test_dev);
+ return 1;
+ }
return 0;
}
static int teardown(void **state)
{
-#ifdef DIO_TEST_DEV
- assert_true(test_fd > 0);
- assert_int_equal(close(test_fd), 0);
-#endif
+ if (test_dev) {
+ assert_true(test_fd > 0);
+ assert_int_equal(close(test_fd), 0);
+ }
return 0;
}
@@ -762,7 +778,7 @@ int main(void)
{
int ret = 0;
- init_test_verbosity(5);
+ init_test_verbosity(2);
ret += test_directio();
return ret;
}
--
2.45.2
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH v2 06/49] kpartx.rules: use @BINDIR@ to locate kpartx
2024-07-12 17:14 ` [PATCH v2 06/49] kpartx.rules: use @BINDIR@ to locate kpartx Martin Wilck
@ 2024-07-15 22:08 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:08 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:14PM +0200, Martin Wilck wrote:
> The path for kpartx should match the installed binary.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> .gitignore | 1 +
> kpartx/Makefile | 6 +++---
> kpartx/{kpartx.rules => kpartx.rules.in} | 2 +-
> 3 files changed, 5 insertions(+), 4 deletions(-)
> rename kpartx/{kpartx.rules => kpartx.rules.in} (96%)
>
> diff --git a/.gitignore b/.gitignore
> index 049ffe8..355ddbb 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -12,6 +12,7 @@ config.mk
> cscope.files
> cscope.out
> kpartx/kpartx
> +kpartx/kpartx.rules
> multipath/multipath
> multipath/multipath.8
> multipath/multipath.conf.5
> diff --git a/kpartx/Makefile b/kpartx/Makefile
> index 7720a74..849fd36 100644
> --- a/kpartx/Makefile
> +++ b/kpartx/Makefile
> @@ -13,13 +13,13 @@ LIBDEPS += -ldevmapper
> OBJS := bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \
> gpt.o mac.o ps3.o crc32.o lopart.o xstrncpy.o devmapper.o
>
> -all: $(EXEC)
> +all: $(EXEC) kpartx.rules
>
> $(EXEC): $(OBJS)
> @echo building $@ because of $?
> $(Q)$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
>
> -install: $(EXEC) $(EXEC).8
> +install: $(EXEC) $(EXEC).8 kpartx.rules
> $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
> $(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
> $(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir)
> @@ -41,7 +41,7 @@ uninstall:
> $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/68-del-part-nodes.rules
>
> clean: dep_clean
> - $(Q)$(RM) core *.o $(EXEC)
> + $(Q)$(RM) core *.o $(EXEC) kpartx.rules
>
> include $(wildcard $(OBJS:.o=.d))
>
> diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules.in
> similarity index 96%
> rename from kpartx/kpartx.rules
> rename to kpartx/kpartx.rules.in
> index 8dd3369..9d87960 100644
> --- a/kpartx/kpartx.rules
> +++ b/kpartx/kpartx.rules.in
> @@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end"
> GOTO="kpartx_end"
>
> LABEL="run_kpartx"
> -RUN+="/sbin/kpartx -un -p -part /dev/$name"
> +RUN+="@BINDIR@/kpartx -un -p -part /dev/$name"
>
> LABEL="kpartx_end"
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 16/49] libmultipath: add cleanup_dm_task(), and use it in devmapper.c
2024-07-12 17:14 ` [PATCH v2 16/49] libmultipath: add cleanup_dm_task(), and use it in devmapper.c Martin Wilck
@ 2024-07-15 22:13 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:13 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:24PM +0200, Martin Wilck wrote:
> This allows us to get rid of a lot of goto statements, and generally
> obtain cleaner code.
>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 258 ++++++++++++++++-----------------------
> 1 file changed, 107 insertions(+), 151 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 8996c1d..4bff62d 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -1419,10 +1396,10 @@ do_foreach_partmaps (const char * mapname,
> int (*partmap_func)(const char *, void *),
> void *data)
> {
> - struct dm_task *dmt;
> + struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *params = NULL;
> struct dm_names *names;
> unsigned next = 0;
> - char *params = NULL;
> unsigned long long size;
> char dev_t[32];
> int r = 1;
Nitpick: You can remove 'r' now.
-Ben
> @@ -1431,21 +1408,18 @@ do_foreach_partmaps (const char * mapname,
> if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
> return 1;
>
> - if (!libmp_dm_task_run(dmt)) {
> - dm_log_error(3, DM_DEVICE_LIST, dmt);
> - goto out;
> - }
> + if (!libmp_dm_task_run(dmt))
> + return 1;
>
> if (!(names = dm_task_get_names(dmt)))
> - goto out;
> + return 1;
>
> - if (!names->dev) {
> - r = 0; /* this is perfectly valid */
> - goto out;
> - }
> + if (!names->dev)
> + /* this is perfectly valid */
> + return 0;
>
> if (dm_dev_t(mapname, &dev_t[0], 32))
> - goto out;
> + return 1;
>
> do {
> if (
> @@ -1472,7 +1446,7 @@ do_foreach_partmaps (const char * mapname,
> !isdigit(*(p + strlen(dev_t)))
> ) {
> if ((r = partmap_func(names->name, data)) != 0)
> - goto out;
> + return 1;
> }
>
> free(params);
> @@ -1481,11 +1455,7 @@ do_foreach_partmaps (const char * mapname,
> names = (void *) names + next;
> } while (next);
>
> - r = 0;
> -out:
> - free(params);
> - dm_task_destroy (dmt);
> - return r;
> + return 0;
> }
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 17/49] libmultipath: rename dm_type()->dm_type_match() and use symbolic values
2024-07-12 17:14 ` [PATCH v2 17/49] libmultipath: rename dm_type()->dm_type_match() and use symbolic values Martin Wilck
@ 2024-07-15 22:14 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:14 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:25PM +0200, Martin Wilck wrote:
> Also, make the function static.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 37 +++++++++++++++++++------------------
> libmultipath/devmapper.h | 1 -
> 2 files changed, 19 insertions(+), 19 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 4bff62d..a63154f 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -806,43 +806,44 @@ out:
> return r;
> }
>
> -/*
> - * returns:
> - * 1 : match
> - * 0 : no match
> - * -1 : empty map, or more than 1 target
> - */
> -int dm_type(const char *name, char *type)
> +enum {
> + DM_TYPE_NOMATCH = 0,
> + DM_TYPE_MATCH,
> + /* more than 1 target */
> + DM_TYPE_MULTI,
> + /* empty map */
> + DM_TYPE_EMPTY,
> + DM_TYPE_ERR,
> +};
> +static int dm_type_match(const char *name, char *type)
> {
> - int r = 0;
> struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> uint64_t start, length;
> char *target_type = NULL;
> char *params;
>
> if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
> - return 0;
> + return DM_TYPE_ERR;
>
> if (!dm_task_set_name(dmt, name))
> - goto out;
> + return DM_TYPE_ERR;
>
> if (!libmp_dm_task_run(dmt)) {
> dm_log_error(3, DM_DEVICE_TABLE, dmt);
> - goto out;
> + return DM_TYPE_ERR;
> }
>
> /* Fetch 1st target */
> if (dm_get_next_target(dmt, NULL, &start, &length,
> &target_type, ¶ms) != NULL)
> /* multiple targets */
> - r = -1;
> + return DM_TYPE_MULTI;
> else if (!target_type)
> - r = -1;
> + return DM_TYPE_EMPTY;
> else if (!strcmp(target_type, type))
> - r = 1;
> -
> -out:
> - return r;
> + return DM_TYPE_MATCH;
> + else
> + return DM_TYPE_NOMATCH;
> }
>
> /*
> @@ -1426,7 +1427,7 @@ do_foreach_partmaps (const char * mapname,
> /*
> * if there is only a single "linear" target
> */
> - (dm_type(names->name, TGT_PART) == 1) &&
> + (dm_type_match(names->name, TGT_PART) == DM_TYPE_MATCH) &&
>
> /*
> * and the uuid of the target is a partition of the
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index 19b79c5..ff28575 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -46,7 +46,6 @@ int dm_map_present (const char *name);
> int dm_map_present_by_uuid(const char *uuid);
> int dm_get_map(const char *name, unsigned long long *size, char **outparams);
> int dm_get_status(const char *name, char **outstatus);
> -int dm_type(const char *name, char *type);
> int dm_is_mpath(const char *name);
>
> enum {
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 18/49] libmultipath: Use symbolic return values for dm_is_mpath()
2024-07-12 17:14 ` [PATCH v2 18/49] libmultipath: Use symbolic return values for dm_is_mpath() Martin Wilck
@ 2024-07-15 22:14 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:14 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:26PM +0200, Martin Wilck wrote:
> Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
> libmpathpersist/mpath_persist_int.c | 2 +-
> libmultipath/devmapper.c | 22 ++++++++--------------
> libmultipath/devmapper.h | 6 ++++++
> multipath/main.c | 4 ++--
> multipathd/dmevents.c | 19 +++++++++++++------
> multipathd/main.c | 2 +-
> 6 files changed, 31 insertions(+), 24 deletions(-)
>
> diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
> index 178c2f5..6da0401 100644
> --- a/libmpathpersist/mpath_persist_int.c
> +++ b/libmpathpersist/mpath_persist_int.c
> @@ -185,7 +185,7 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
>
> condlog(3, "alias = %s", alias);
>
> - if (dm_map_present(alias) && dm_is_mpath(alias) != 1){
> + if (dm_map_present(alias) && dm_is_mpath(alias) != DM_IS_MPATH_YES) {
> condlog(3, "%s: not a multipath device.", alias);
> goto out;
> }
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index a63154f..3abdc26 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -846,15 +846,9 @@ static int dm_type_match(const char *name, char *type)
> return DM_TYPE_NOMATCH;
> }
>
> -/*
> - * returns:
> - * 1 : is multipath device
> - * 0 : is not multipath device
> - * -1 : error
> - */
> int dm_is_mpath(const char *name)
> {
> - int r = -1;
> + int r = DM_IS_MPATH_ERR;
> struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> struct dm_info info;
> uint64_t start, length;
> @@ -876,7 +870,7 @@ int dm_is_mpath(const char *name)
> if (!dm_task_get_info(dmt, &info))
> goto out;
>
> - r = 0;
> + r = DM_IS_MPATH_NO;
>
> if (!info.exists)
> goto out;
> @@ -895,10 +889,10 @@ int dm_is_mpath(const char *name)
> if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
> goto out;
>
> - r = 1;
> + r = DM_IS_MPATH_YES;
> out:
> - if (r < 0)
> - condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno));
> + if (r == DM_IS_MPATH_ERR)
> + condlog(3, "%s: dm command failed in %s: %s", name, __func__, strerror(errno));
> return r;
> }
>
> @@ -1039,7 +1033,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
> unsigned long long mapsize;
> char *params = NULL;
>
> - if (dm_is_mpath(mapname) != 1)
> + if (dm_is_mpath(mapname) != DM_IS_MPATH_YES)
> return DM_FLUSH_OK; /* nothing to do */
>
> /* if the device currently has no partitions, do not
> @@ -1086,7 +1080,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
> }
> condlog(4, "multipath map %s removed", mapname);
> return DM_FLUSH_OK;
> - } else if (dm_is_mpath(mapname) != 1) {
> + } else if (dm_is_mpath(mapname) != DM_IS_MPATH_YES) {
> condlog(4, "multipath map %s removed externally",
> mapname);
> return DM_FLUSH_OK; /* raced. someone else removed it */
> @@ -1316,7 +1310,7 @@ int dm_get_maps(vector mp)
> }
>
> do {
> - if (dm_is_mpath(names->name) != 1)
> + if (dm_is_mpath(names->name) != DM_IS_MPATH_YES)
> goto next;
>
> mpp = dm_get_multipath(names->name);
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index ff28575..9438c2d 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -46,6 +46,12 @@ int dm_map_present (const char *name);
> int dm_map_present_by_uuid(const char *uuid);
> int dm_get_map(const char *name, unsigned long long *size, char **outparams);
> int dm_get_status(const char *name, char **outstatus);
> +
> +enum {
> + DM_IS_MPATH_NO,
> + DM_IS_MPATH_YES,
> + DM_IS_MPATH_ERR,
> +};
> int dm_is_mpath(const char *name);
>
> enum {
> diff --git a/multipath/main.c b/multipath/main.c
> index ce702e7..c82bc86 100644
> --- a/multipath/main.c
> +++ b/multipath/main.c
> @@ -247,7 +247,7 @@ static int check_usable_paths(struct config *conf,
> goto out;
> }
>
> - if (dm_is_mpath(mapname) != 1) {
> + if (dm_is_mpath(mapname) != DM_IS_MPATH_YES) {
> condlog(1, "%s is not a multipath map", devpath);
> goto free;
> }
> @@ -1080,7 +1080,7 @@ main (int argc, char *argv[])
> goto out;
> }
> if (cmd == CMD_FLUSH_ONE) {
> - if (dm_is_mpath(dev) != 1) {
> + if (dm_is_mpath(dev) != DM_IS_MPATH_YES) {
> condlog(0, "%s is not a multipath device", dev);
> r = RTVL_FAIL;
> goto out;
> diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c
> index 3fbdc55..af1e12e 100644
> --- a/multipathd/dmevents.c
> +++ b/multipathd/dmevents.c
> @@ -168,9 +168,13 @@ static int dm_get_events(void)
> while (names->dev) {
> uint32_t event_nr;
>
> - /* Don't delete device if dm_is_mpath() fails without
> - * checking the device type */
> - if (dm_is_mpath(names->name) == 0)
> + /*
> + * Don't delete device if dm_is_mpath() fails without
> + * checking the device type.
> + * IOW, only delete devices from the event list for which
> + * we positively know that they aren't multipath devices.
> + */
> + if (dm_is_mpath(names->name) == DM_IS_MPATH_NO)
> goto next;
>
> event_nr = dm_event_nr(names);
> @@ -206,9 +210,12 @@ int watch_dmevents(char *name)
> struct dev_event *dev_evt, *old_dev_evt;
> int i;
>
> - /* We know that this is a multipath device, so only fail if
> - * device-mapper tells us that we're wrong */
> - if (dm_is_mpath(name) == 0) {
> + /*
> + * We know that this is a multipath device, so only fail if
> + * device-mapper tells us that we're wrong
> + * IOW, don't fail for DM generic errors.
> + */
> + if (dm_is_mpath(name) == DM_IS_MPATH_NO) {
> condlog(0, "%s: not a multipath device. can't watch events",
> name);
> return -1;
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 58afe14..132bb2e 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -865,7 +865,7 @@ ev_add_map (char * dev, const char * alias, struct vectors * vecs)
> int reassign_maps;
> struct config *conf;
>
> - if (dm_is_mpath(alias) != 1) {
> + if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
> condlog(4, "%s: not a multipath map", alias);
> return 0;
> }
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 19/49] libmultipath: add libmp_mapinfo()
2024-07-12 17:14 ` [PATCH v2 19/49] libmultipath: add libmp_mapinfo() Martin Wilck
@ 2024-07-15 22:41 ` Benjamin Marzinski
2024-07-16 15:51 ` Martin Wilck
0 siblings, 1 reply; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:41 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:27PM +0200, Martin Wilck wrote:
> libmp_mapinfo() is intended as a generic abstraction for retrieving information from
> the kernel device-mapper driver. It retrieves the information that the caller
> needs, with a minimal set of DM ioctls, and never more then 2 ioctl calls.
>
> libdm's DM_DEVICE_TABLE and DM_DEVICE_STATUS calls map to the kernel's
> DM_TABLE_STATUS ioctl, with or without the DM_STATUS_TABLE_FLAG set,
> respectively. DM_TABLE_STATUS always retrieves the basic map status (struct
> dm_info) and the map UUID and name, too.
>
> Note: I'd prefer to use an unnamed struct instead of _u in
> union libmp_map_identifer. But doing using an unnamed struct and and
> initializing the union like this in a function argument:
>
> func((mapid_t) { .major = major, .minor = minor })
>
> is not part of C99, and not supported in gcc 4.8, which we still support.
>
> Likewise, the following syntax for initializing an empty struct:
>
> (mapinfo_t) { 0 }
>
> is not supported on all architectures we support (notably clang 3.5 under
> Debian Jessie).
>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 192 +++++++++++++++++++++++++++++-
> libmultipath/devmapper.h | 70 +++++++++++
> libmultipath/libmultipath.version | 3 +-
> 3 files changed, 263 insertions(+), 2 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 3abdc26..4e6b5b2 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -14,7 +14,6 @@
> #include <errno.h>
> #include <syslog.h>
> #include <sys/sysmacros.h>
> -#include <linux/dm-ioctl.h>
>
> #include "util.h"
> #include "vector.h"
> @@ -604,6 +603,197 @@ has_dm_info(const struct multipath *mpp)
> return (mpp && mpp->dmi.exists != 0);
> }
>
> +static int libmp_set_map_identifier(int flags, mapid_t id, struct dm_task *dmt)
> +{
> + switch (flags & __DM_MAP_BY_MASK) {
> + case DM_MAP_BY_UUID:
> + if (!id.str || !(*id.str))
> + return 0;
> + return dm_task_set_uuid(dmt, id.str);
> + case DM_MAP_BY_NAME:
> + if (!id.str || !(*id.str))
> + return 0;
> + return dm_task_set_name(dmt, id.str);
> + case DM_MAP_BY_DEV:
> + if (!dm_task_set_major(dmt, id._u.major))
> + return 0;
> + return dm_task_set_minor(dmt, id._u.minor);
> + case DM_MAP_BY_DEVT:
> + if (!dm_task_set_major(dmt, major(id.devt)))
> + return 0;
> + return dm_task_set_minor(dmt, minor(id.devt));
> + default:
> + condlog(0, "%s: invalid by_id", __func__);
> + return 0;
> + }
> +}
> +
> +static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info, const char *map_id)
> +{
> + struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> + struct dm_info dmi;
> + int rc, ioctl_nr;
> + uint64_t start, length = 0;
> + char *target_type = NULL, *params = NULL;
> + const char *name = NULL, *uuid = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *tmp_target = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *tmp_status = NULL;
> + bool tgt_set = false;
> +
> + /*
> + * If both info.target and info.status are set, we need two
> + * ioctls. Call this function recursively.
> + * If successful, tmp_target will be non-NULL.
> + */
> + if (info.target && info.status) {
> + rc = libmp_mapinfo__(flags, id,
> + (mapinfo_t) { .target = &tmp_target },
> + map_id);
> + if (rc != DMP_OK)
> + return rc;
> + tgt_set = true;
> + }
> +
> + /*
> + * The DM_DEVICE_TABLE and DM_DEVICE_STATUS ioctls both fetch the basic
> + * information from DM_DEVICE_INFO, too.
> + * Choose the most lightweight ioctl to fetch all requested info.
> + */
> + if (info.target && !info.status)
> + ioctl_nr = DM_DEVICE_TABLE;
> + else if (info.status || info.size || flags & __MAPINFO_TGT_TYPE)
> + ioctl_nr = DM_DEVICE_STATUS;
> + else
> + ioctl_nr = DM_DEVICE_INFO;
> +
> + if (!(dmt = libmp_dm_task_create(ioctl_nr)))
> + return DMP_ERR;
> +
> + if (!libmp_set_map_identifier(flags, id, dmt)) {
> + condlog(2, "%s: failed to set map identifier to %s", __func__, map_id);
> + return DMP_ERR;
> + }
> +
> + if (!libmp_dm_task_run(dmt)) {
> + dm_log_error(3, ioctl_nr, dmt);
> + if (dm_task_get_errno(dmt) == ENXIO) {
I wonder if we should wrap ibmp_mapinfo in a macro that grabs the
function name of the calling function and passes it down to
libmp_mapinfo__() otherwise there will be a lot of messages like this or
condlog(2, "%s: map %s doesn't exist", __func__, map_id);
that use "libmp_mapinfo__" as the function, which isn't super useful.
> + condlog(2, "%s: map %s not found", __func__, map_id);
> + return DMP_NOT_FOUND;
> + } else
> + return DMP_ERR;
> + }
> +
> + condlog(4, "%s: DM ioctl %d succeeded for %s",
> + __func__, ioctl_nr, map_id);
> +
> + if (!dm_task_get_info(dmt, &dmi)) {
> + condlog(2, "%s: dm_task_get_info() failed for %s ", __func__, map_id);
> + return DMP_ERR;
> + } else if(!dmi.exists) {
> + condlog(2, "%s: map %s doesn't exist", __func__, map_id);
> + return DMP_NOT_FOUND;
> + }
> +
> + if (info.target || info.status || info.size || flags & __MAPINFO_TGT_TYPE) {
> + if (dm_get_next_target(dmt, NULL, &start, &length,
> + &target_type, ¶ms) != NULL) {
> + condlog(2, "%s: map %s has multiple targets", __func__, map_id);
> + return DMP_NOT_FOUND;
> + }
> + if (!params) {
> + condlog(2, "%s: map %s has no targets", __func__, map_id);
> + return DMP_NOT_FOUND;
> + }
> + if (flags & __MAPINFO_TGT_TYPE) {
> + const char *tgt_type = flags & MAPINFO_MPATH_ONLY ? TGT_MPATH : TGT_PART;
> +
> + if (strcmp(target_type, tgt_type)) {
> + condlog(3, "%s: target type mismatch: \"%s\" != \"%s\"",
> + __func__, tgt_type, target_type);
> + return DMP_NO_MATCH;
> + }
> + }
> + }
> +
> + /*
> + * Check possible error conditions.
> + * If error is returned, don't touch any output parameters.
> + */
> + if ((info.name && !(name = dm_task_get_name(dmt)))
> + || (info.uuid && !(uuid = dm_task_get_uuid(dmt)))
> + || (info.status && !(tmp_status = strdup(params)))
> + || (info.target && !tmp_target && !(tmp_target = strdup(params))))
> + return DMP_ERR;
> +
> + if (info.name) {
> + strlcpy(info.name, name, WWID_SIZE);
> + condlog(4, "%s: %s: name: \"%s\"", __func__, map_id, info.name);
> + }
> + if (info.uuid) {
> + strlcpy(info.uuid, uuid, DM_UUID_LEN);
> + condlog(4, "%s: %s: uuid: \"%s\"", __func__, map_id, info.uuid);
> + }
> +
> + if (info.size) {
> + *info.size = length;
> + condlog(4, "%s: %s: size: %lld", __func__, map_id, *info.size);
> + }
> +
> + if (info.dmi) {
> + memcpy(info.dmi, &dmi, sizeof(*info.dmi));
> + condlog(4, "%s: %s %d:%d, %d targets, %s table, %s, %s, %d opened, %u events",
> + __func__, map_id,
> + info.dmi->major, info.dmi->minor,
> + info.dmi->target_count,
> + info.dmi->live_table ? "live" :
> + info.dmi->inactive_table ? "inactive" : "no",
> + info.dmi->suspended ? "suspended" : "active",
> + info.dmi->read_only ? "ro" : "rw",
> + info.dmi->open_count,
> + info.dmi->event_nr);
> + }
> +
> + if (info.target) {
> + *info.target = steal_ptr(tmp_target);
> + if (!tgt_set)
> + condlog(4, "%s: %s: target: \"%s\"", __func__, map_id, *info.target);
> + }
> +
> + if (info.status) {
> + *info.status = steal_ptr(tmp_status);
> + condlog(4, "%s: %s: status: \"%s\"", __func__, map_id, *info.status);
> + }
> +
> + return DMP_OK;
> +}
> +
> +/* Helper: format a string describing the map for log messages */
> +static const char* libmp_map_identifier(int flags, mapid_t id, char buf[BLK_DEV_SIZE])
> +{
> + switch (flags & __DM_MAP_BY_MASK) {
> + case DM_MAP_BY_NAME:
> + case DM_MAP_BY_UUID:
> + return id.str;
> + case DM_MAP_BY_DEV:
> + safe_snprintf(buf, BLK_DEV_SIZE, "%d:%d", id._u.major, id._u.minor);
> + return buf;
> + case DM_MAP_BY_DEVT:
> + safe_snprintf(buf, BLK_DEV_SIZE, "%d:%d", major(id.devt), minor(id.devt));
> + return buf;
> + default:
> + safe_snprintf(buf, BLK_DEV_SIZE, "*invalid*");
> + return buf;
> + }
> +}
> +
> +int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
> +{
> + char idbuf[BLK_DEV_SIZE];
> +
> + return libmp_mapinfo__(flags, id, info,
> + libmp_map_identifier(flags, id, idbuf));
> +}
> +
> int
> dm_get_info(const char *name, struct dm_info *info)
> {
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index 9438c2d..725889b 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -1,5 +1,6 @@
> #ifndef _DEVMAPPER_H
> #define _DEVMAPPER_H
> +#include <linux/dm-ioctl.h>
> #include "autoconfig.h"
> #include "structs.h"
>
> @@ -31,8 +32,77 @@ enum {
> DMP_ERR,
> DMP_OK,
> DMP_NOT_FOUND,
> + DMP_NO_MATCH,
> };
>
> +/**
> + * enum mapinfo_flags: input flags for libmp_mapinfo()
> + */
> +enum __mapinfo_flags {
> + /** DM_MAP_BY_NAME: identify map by device-mapper name from @name */
> + DM_MAP_BY_NAME = 0,
> + /** DM_MAP_BY_UUID: identify map by device-mapper UUID from @uuid */
> + DM_MAP_BY_UUID,
> + /** DM_MAP_BY_DEV: identify map by major/minor number from @dmi */
> + DM_MAP_BY_DEV,
> + /** DM_MAP_BY_DEVT: identify map by a dev_t */
> + DM_MAP_BY_DEVT,
I mentioned tihs before, but the DM_MAP_BY_* identifiers only take up 3
bytes so __DM_MAP_BY_MASK can just be 3 or (1 << 2) - 1, unless you are
reserving space for more identifiers which is fine but probably
unnecessary, since libmultipath isn't a stable API. Or is there some
other reason I'm missing.
> + __DM_MAP_BY_MASK = (1 << 3) - 1,
> + /* Fail if target type is not multipath */
> + MAPINFO_MPATH_ONLY = (1 << 3),
> + /* Fail if target type is not "partition" (linear) */
> + MAPINFO_PART_ONLY = (1 << 4),
> + __MAPINFO_TGT_TYPE = (MAPINFO_MPATH_ONLY | MAPINFO_PART_ONLY),
> +};
> +
> +typedef union libmp_map_identifier {
> + const char *str;
> + struct {
> + int major;
> + int minor;
> + } _u;
> + dev_t devt;
> +} mapid_t;
> +
> +typedef struct libmp_map_info {
> + /** @name: name of the map.
> + * If non-NULL, it must point to an array of WWID_SIZE bytes
> + */
> + char *name;
> + /** @uuid: UUID of the map.
> + * If non-NULL it must point to an array of DM_UUID_LEN bytes
> + */
> + char *uuid;
> + /** @dmi: Basic info, must point to a valid dm_info buffer if non-NULL */
> + struct dm_info *dmi;
> + /** @target: target params, *@target will be allocated if @target is non-NULL*/
> + char **target;
> + /** @size: target size. Will be ignored if @target is NULL */
AFAICT this isn't true. You can just request the device size, and
libmp_mapinfo() will give you the size.
-Ben
> + unsigned long long *size;
> + /** @status: target status, *@status will be allocated if @status is non-NULL */
> + char **status;
> +} mapinfo_t;
> +
> +/**
> + * libmp_mapinfo(): obtain information about a map from the kernel
> + * @param flags: see __mapinfo_flags above.
> + * Exactly one of DM_MAP_BY_NAME, DM_MAP_BY_UUID, and DM_MAP_BY_DEV must be set.
> + * @param id: string or major/minor to identify the map to query
> + * @param info: output parameters, see above. Non-NULL elements will be filled in.
> + * @returns:
> + * DMP_OK if successful.
> + * DMP_NOT_FOUND if the map wasn't found, or has no or multiple targets.
> + * DMP_NO_MATCH if the map didn't match @tgt_type (see above).
> + * DMP_ERR if some other error occurred.
> + *
> + * This function obtains the requested information for the device-mapper map
> + * identified by the input parameters.
> + * Output parameters are only filled in if the return value is DMP_OK.
> + * For target / status / size information, the map's table should contain
> + * only one target (usually multipath or linear).
> + */
> +int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info);
> +
> int dm_prereq(unsigned int *v);
> void skip_libmp_dm_init(void);
> void libmp_dm_exit(void);
> diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
> index f58cb1d..48c2b67 100644
> --- a/libmultipath/libmultipath.version
> +++ b/libmultipath/libmultipath.version
> @@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 {
> put_multipath_config;
> };
>
> -LIBMULTIPATH_24.0.0 {
> +LIBMULTIPATH_25.0.0 {
> global:
> /* symbols referenced by multipath and multipathd */
> add_foreign;
> @@ -134,6 +134,7 @@ global:
> libmp_get_version;
> libmp_get_multipath_config;
> libmp_dm_task_run;
> + libmp_mapinfo;
> libmp_put_multipath_config;
> libmp_udev_set_sync_support;
> libmultipath_exit;
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 25/49] libmultipath: improve dm_get_wwid() return value logic
2024-07-12 17:14 ` [PATCH v2 25/49] libmultipath: improve dm_get_wwid() return value logic Martin Wilck
@ 2024-07-15 22:42 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:42 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:33PM +0200, Martin Wilck wrote:
> Make dm_get_wwid() return different status codes for non-existing maps,
> maps that exists but are not multipath maps, and generic error case,
> and handle these return codes appropriately in callers.
>
> The error handling is als changed; dm_get_wwid() doesn't take
> care of making the ouput 0-terminated if anything fails. The
> caller is responsible for that. Change callers accordingly.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/alias.c | 11 ++++++++---
> libmultipath/configure.c | 27 +++++++++++++++------------
> libmultipath/devmapper.c | 22 +++++++++++++++++-----
> libmultipath/wwids.c | 2 +-
> multipathd/main.c | 7 +++++--
> tests/alias.c | 10 +++++-----
> 6 files changed, 51 insertions(+), 28 deletions(-)
>
> diff --git a/libmultipath/alias.c b/libmultipath/alias.c
> index 10e58a7..c4eb5d8 100644
> --- a/libmultipath/alias.c
> +++ b/libmultipath/alias.c
> @@ -408,13 +408,18 @@ static bool alias_already_taken(const char *alias, const char *map_wwid)
> {
>
> char wwid[WWID_SIZE];
> + int rc = dm_get_wwid(alias, wwid, sizeof(wwid));
>
> - /* If the map doesn't exist, it's fine */
> - if (dm_get_wwid(alias, wwid, sizeof(wwid)) != 0)
> + /*
> + * If the map doesn't exist, it's fine.
> + * In the generic error case, assume that the device is not
> + * taken, and try to proceed.
> + */
> + if (rc == DMP_NOT_FOUND || rc == DMP_ERR)
> return false;
>
> /* If both the name and the wwid match, it's fine.*/
> - if (strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
> + if (rc == DMP_OK && strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
> return false;
>
> condlog(3, "%s: alias '%s' already taken, reselecting alias",
> diff --git a/libmultipath/configure.c b/libmultipath/configure.c
> index 666d4e8..2fdaca8 100644
> --- a/libmultipath/configure.c
> +++ b/libmultipath/configure.c
> @@ -845,18 +845,21 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
>
> if (mpp->action == ACT_CREATE && dm_map_present(mpp->alias)) {
> char wwid[WWID_SIZE];
> + int rc = dm_get_wwid(mpp->alias, wwid, sizeof(wwid));
>
> - if (dm_get_wwid(mpp->alias, wwid, sizeof(wwid)) == 0) {
> - if (!strncmp(mpp->wwid, wwid, sizeof(wwid))) {
> - condlog(3, "%s: map already present",
> - mpp->alias);
> - mpp->action = ACT_RELOAD;
> - } else {
> - condlog(0, "%s: map \"%s\" already present with WWID %s, skipping",
> - mpp->wwid, mpp->alias, wwid);
> - condlog(0, "please check alias settings in config and bindings file");
> - mpp->action = ACT_REJECT;
> - }
> + if (rc == DMP_OK && !strncmp(mpp->wwid, wwid, sizeof(wwid))) {
> + condlog(3, "%s: map already present",
> + mpp->alias);
> + mpp->action = ACT_RELOAD;
> + } else if (rc == DMP_OK) {
> + condlog(1, "%s: map \"%s\" already present with WWID \"%s\", skipping\n"
> + "please check alias settings in config and bindings file",
> + mpp->wwid, mpp->alias, wwid);
> + mpp->action = ACT_REJECT;
> + } else if (rc == DMP_NO_MATCH) {
> + condlog(1, "%s: alias \"%s\" already taken by a non-multipath map",
> + mpp->wwid, mpp->alias);
> + mpp->action = ACT_REJECT;
> }
> }
>
> @@ -1320,7 +1323,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev,
> break;
>
> case DEV_DEVMAP:
> - if (((dm_get_wwid(dev, tmpwwid, WWID_SIZE)) == 0)
> + if (((dm_get_wwid(dev, tmpwwid, WWID_SIZE)) == DMP_OK)
> && (strlen(tmpwwid)))
> refwwid = tmpwwid;
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 3fca08c..003d834 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -840,19 +840,29 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
> }
> }
>
> +/**
> + * dm_get_wwid(): return WWID for a multipath map
> + * @returns:
> + * DMP_OK if successful
> + * DMP_NOT_FOUND if the map doesn't exist
> + * DMP_NO_MATCH if the map exists but is not a multipath map
> + * DMP_ERR for other errors
> + * Caller may access uuid if and only if DMP_OK is returned.
> + */
> int dm_get_wwid(const char *name, char *uuid, int uuid_len)
> {
> char tmp[DM_UUID_LEN];
> + int rc = dm_get_dm_uuid(name, tmp);
>
> - if (dm_get_dm_uuid(name, tmp) != DMP_OK)
> - return 1;
> + if (rc != DMP_OK)
> + return rc;
>
> if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
> strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
> else
> - uuid[0] = '\0';
> + return DMP_NO_MATCH;
>
> - return 0;
> + return DMP_OK;
> }
>
> static int is_mpath_part(const char *part_name, const char *map_name)
> @@ -1388,8 +1398,10 @@ struct multipath *dm_get_multipath(const char *name)
> if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
> goto out;
>
> - if (dm_get_wwid(name, mpp->wwid, WWID_SIZE) != 0)
> + if (dm_get_wwid(name, mpp->wwid, WWID_SIZE) != DMP_OK) {
> condlog(2, "%s: failed to get uuid for %s", __func__, name);
> + mpp->wwid[0] = '\0';
> + }
> if (dm_get_info(name, &mpp->dmi) != 0)
> condlog(2, "%s: failed to get info for %s", __func__, name);
>
> diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
> index 7a4cb74..aac18c0 100644
> --- a/libmultipath/wwids.c
> +++ b/libmultipath/wwids.c
> @@ -295,7 +295,7 @@ should_multipath(struct path *pp1, vector pathvec, vector mpvec)
> struct multipath *mp = find_mp_by_wwid(mpvec, pp1->wwid);
>
> if (mp != NULL &&
> - dm_get_wwid(mp->alias, tmp_wwid, WWID_SIZE) == 0 &&
> + dm_get_wwid(mp->alias, tmp_wwid, WWID_SIZE) == DMP_OK &&
> !strncmp(tmp_wwid, pp1->wwid, WWID_SIZE)) {
> condlog(3, "wwid %s is already multipathed, keeping it",
> pp1->wwid);
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 442a154..1e7a6ac 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -726,8 +726,11 @@ add_map_without_path (struct vectors *vecs, const char *alias)
> condlog(3, "%s: cannot access table", mpp->alias);
> goto out;
> }
> - if (!strlen(mpp->wwid))
> - dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE);
> + if (!strlen(mpp->wwid) &&
> + dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE) != DMP_OK) {
> + condlog(3, "%s: cannot obtain WWID", mpp->alias);
> + goto out;
> + }
> if (!strlen(mpp->wwid))
> condlog(1, "%s: adding map with empty WWID", mpp->alias);
> conf = get_multipath_config();
> diff --git a/tests/alias.c b/tests/alias.c
> index 1f78656..a95b308 100644
> --- a/tests/alias.c
> +++ b/tests/alias.c
> @@ -84,7 +84,7 @@ int __wrap_dm_get_wwid(const char *name, char *uuid, int uuid_len)
> check_expected(uuid_len);
> assert_non_null(uuid);
> ret = mock_type(int);
> - if (ret == 0)
> + if (ret == DMP_OK)
> strcpy(uuid, mock_ptr_type(char *));
> return ret;
> }
> @@ -438,14 +438,14 @@ static void mock_unused_alias(const char *alias)
> {
> expect_string(__wrap_dm_get_wwid, name, alias);
> expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE);
> - will_return(__wrap_dm_get_wwid, 1);
> + will_return(__wrap_dm_get_wwid, DMP_NOT_FOUND);
> }
>
> static void mock_self_alias(const char *alias, const char *wwid)
> {
> expect_string(__wrap_dm_get_wwid, name, alias);
> expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE);
> - will_return(__wrap_dm_get_wwid, 0);
> + will_return(__wrap_dm_get_wwid, DMP_OK);
> will_return(__wrap_dm_get_wwid, wwid);
> }
>
> @@ -471,14 +471,14 @@ static void mock_self_alias(const char *alias, const char *wwid)
> do { \
> expect_string(__wrap_dm_get_wwid, name, alias); \
> expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE); \
> - will_return(__wrap_dm_get_wwid, 1); \
> + will_return(__wrap_dm_get_wwid, DMP_NOT_FOUND); \
> } while (0)
>
> #define mock_used_alias(alias, wwid) \
> do { \
> expect_string(__wrap_dm_get_wwid, name, alias); \
> expect_value(__wrap_dm_get_wwid, uuid_len, WWID_SIZE); \
> - will_return(__wrap_dm_get_wwid, 0); \
> + will_return(__wrap_dm_get_wwid, DMP_OK); \
> will_return(__wrap_dm_get_wwid, "WWID_USED"); \
> expect_condlog(3, USED_STR(alias, wwid)); \
> } while(0)
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 26/49] libmultipath: reimplement dm_map_name() with new API
2024-07-12 17:14 ` [PATCH v2 26/49] libmultipath: reimplement dm_map_name() with new API Martin Wilck
@ 2024-07-15 22:42 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:42 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:34PM +0200, Martin Wilck wrote:
> Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
> libmultipath/devmapper.c | 34 ++++++----------------------------
> 1 file changed, 6 insertions(+), 28 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 003d834..8af4167 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -1481,37 +1481,15 @@ dm_is_suspended(const char *name)
> return info.suspended;
> }
>
> -char *
> -dm_mapname(int major, int minor)
> +char *dm_mapname(int major, int minor)
> {
> - char * response = NULL;
> - const char *map;
> - struct dm_task *dmt;
> - int r;
> + char name[WWID_SIZE];
>
> - if (!(dmt = libmp_dm_task_create(DM_DEVICE_INFO)))
> + if (libmp_mapinfo(DM_MAP_BY_DEV,
> + (mapid_t) { ._u = { major, minor } },
> + (mapinfo_t) { .name = name }) != DMP_OK)
> return NULL;
> -
> - if (!dm_task_set_major(dmt, major) ||
> - !dm_task_set_minor(dmt, minor))
> - goto bad;
> -
> - r = libmp_dm_task_run(dmt);
> - if (!r) {
> - dm_log_error(2, DM_DEVICE_INFO, dmt);
> - goto bad;
> - }
> -
> - map = dm_task_get_name(dmt);
> - if (map && strlen(map))
> - response = strdup((const char *)map);
> -
> - dm_task_destroy(dmt);
> - return response;
> -bad:
> - dm_task_destroy(dmt);
> - condlog(0, "%i:%i: error fetching map name", major, minor);
> - return NULL;
> + return strdup(name);
> }
>
> static int
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 30/49] libmultipath: implement dm_is_mpath() with new API
2024-07-12 17:14 ` [PATCH v2 30/49] libmultipath: implement dm_is_mpath() with new API Martin Wilck
@ 2024-07-15 22:43 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:43 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:38PM +0200, Martin Wilck wrote:
> Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
> libmultipath/devmapper.c | 59 ++++++++++------------------------------
> 1 file changed, 15 insertions(+), 44 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 47ff827..11bccb1 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -975,52 +975,23 @@ static int dm_type_match(const char *name, char *type)
>
> int dm_is_mpath(const char *name)
> {
> - int r = DM_IS_MPATH_ERR;
> - struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> - struct dm_info info;
> - uint64_t start, length;
> - char *target_type = NULL;
> - char *params;
> - const char *uuid;
> + char uuid[DM_UUID_LEN];
> + int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
> + (mapid_t) { .str = name },
> + (mapinfo_t) { .uuid = uuid });
>
> - if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
> - goto out;
> -
> - if (!dm_task_set_name(dmt, name))
> - goto out;
> -
> - if (!libmp_dm_task_run(dmt)) {
> - dm_log_error(3, DM_DEVICE_TABLE, dmt);
> - goto out;
> + switch (rc) {
> + case DMP_OK:
> + if (!strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
> + return DM_IS_MPATH_YES;
> + /* fallthrough */
> + case DMP_NOT_FOUND:
> + case DMP_NO_MATCH:
> + return DM_IS_MPATH_NO;
> + case DMP_ERR:
> + default:
> + return DM_IS_MPATH_ERR;
> }
> -
> - if (!dm_task_get_info(dmt, &info))
> - goto out;
> -
> - r = DM_IS_MPATH_NO;
> -
> - if (!info.exists)
> - goto out;
> -
> - uuid = dm_task_get_uuid(dmt);
> -
> - if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0)
> - goto out;
> -
> - /* Fetch 1st target */
> - if (dm_get_next_target(dmt, NULL, &start, &length, &target_type,
> - ¶ms) != NULL)
> - /* multiple targets */
> - goto out;
> -
> - if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
> - goto out;
> -
> - r = DM_IS_MPATH_YES;
> -out:
> - if (r == DM_IS_MPATH_ERR)
> - condlog(3, "%s: dm command failed in %s: %s", name, __func__, strerror(errno));
> - return r;
> }
>
> int dm_map_present_by_wwid(const char *wwid)
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 33/49] libmultipath: add is_mpath_uuid() helper
2024-07-12 17:14 ` [PATCH v2 33/49] libmultipath: add is_mpath_uuid() helper Martin Wilck
@ 2024-07-15 22:43 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:43 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:41PM +0200, Martin Wilck wrote:
> Export it, as it will be used by multipathd and libmpathpersist.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 13 +++++++++----
> libmultipath/devmapper.h | 2 ++
> libmultipath/libmultipath.version | 1 +
> 3 files changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 9483f02..6f17d32 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -840,6 +840,11 @@ int dm_get_map(const char *name, unsigned long long *size, char **outparams)
> }
> }
>
> +bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
> +{
> + return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
> +}
> +
> /**
> * dm_get_wwid(): return WWID for a multipath map
> * @returns:
> @@ -857,7 +862,7 @@ int dm_get_wwid(const char *name, char *uuid, int uuid_len)
> if (rc != DMP_OK)
> return rc;
>
> - if (!strncmp(tmp, UUID_PREFIX, UUID_PREFIX_LEN))
> + if (is_mpath_uuid(tmp))
> strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
> else
> return DMP_NO_MATCH;
> @@ -982,7 +987,7 @@ int dm_is_mpath(const char *name)
>
> switch (rc) {
> case DMP_OK:
> - if (!strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
> + if (is_mpath_uuid(uuid))
> return DM_IS_MPATH_YES;
> /* fallthrough */
> case DMP_NOT_FOUND:
> @@ -1082,7 +1087,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
> (mapinfo_t) {
> .uuid = uuid,
> .target = ¶ms }) != DMP_OK
> - || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
> + || !is_mpath_uuid(uuid))
> return DM_FLUSH_OK; /* nothing to do */
>
> /* if the device currently has no partitions, do not
> @@ -1325,7 +1330,7 @@ struct multipath *dm_get_multipath(const char *name)
> }) != DMP_OK)
> return NULL;
>
> - if (strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
> + if (!is_mpath_uuid(uuid))
> return NULL;
>
> strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index 4c8f345..a10821f 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -136,6 +136,8 @@ enum {
> DM_IS_MPATH_YES,
> DM_IS_MPATH_ERR,
> };
> +
> +bool is_mpath_uuid(const char uuid[DM_UUID_LEN]);
> int dm_is_mpath(const char *name);
>
> enum {
> diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
> index 7d3ff63..5b8f9e0 100644
> --- a/libmultipath/libmultipath.version
> +++ b/libmultipath/libmultipath.version
> @@ -127,6 +127,7 @@ global:
> init_foreign;
> init_prio;
> io_err_stat_handle_pathfail;
> + is_mpath_uuid;
> is_path_valid;
> libmp_dm_task_create;
> libmp_get_version;
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 37/49] libmultipath: use libmp_pathinfo() in update_multipath_table()
2024-07-12 17:14 ` [PATCH v2 37/49] libmultipath: use libmp_pathinfo() in update_multipath_table() Martin Wilck
@ 2024-07-15 22:44 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:44 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:45PM +0200, Martin Wilck wrote:
> This allows us to remove dm_get_status(), and dm_get_map(), of which
> update_multipath_table() was the last caller.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 89 --------------------------------------
> libmultipath/devmapper.h | 2 -
> libmultipath/structs_vec.c | 26 ++++++-----
> 3 files changed, 15 insertions(+), 102 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 587fc17..86ac01b 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -815,45 +815,6 @@ static int dm_get_dm_uuid(const char *mapname, char uuid[DM_UUID_LEN])
> (mapinfo_t) { .uuid = uuid });
> }
>
> -int dm_get_map(const char *name, unsigned long long *size, char **outparams)
> -{
> - struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> - uint64_t start, length;
> - char *target_type = NULL;
> - char *params = NULL;
> -
> - if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
> - return DMP_ERR;
> -
> - if (!dm_task_set_name(dmt, name))
> - return DMP_ERR;
> -
> - errno = 0;
> - if (!libmp_dm_task_run(dmt)) {
> - dm_log_error(3, DM_DEVICE_TABLE, dmt);
> - if (dm_task_get_errno(dmt) == ENXIO)
> - return DMP_NOT_FOUND;
> - else
> - return DMP_ERR;
> - }
> -
> - /* Fetch 1st target */
> - if (dm_get_next_target(dmt, NULL, &start, &length,
> - &target_type, ¶ms) != NULL || !params)
> - /* more than one target or not found target */
> - return DMP_NOT_FOUND;
> -
> - if (size)
> - *size = length;
> -
> - if (!outparams)
> - return DMP_OK;
> - else {
> - *outparams = strdup(params);
> - return *outparams ? DMP_OK : DMP_ERR;
> - }
> -}
> -
> bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
> {
> return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
> @@ -896,56 +857,6 @@ static bool is_mpath_part_uuid(const char part_uuid[DM_UUID_LEN],
> return !strcmp(part_uuid + nc, map_uuid);
> }
>
> -int dm_get_status(const char *name, char **outstatus)
> -{
> - int r = DMP_ERR;
> - struct dm_task __attribute__((cleanup(cleanup_dm_task))) *dmt = NULL;
> - uint64_t start, length;
> - char *target_type = NULL;
> - char *status = NULL;
> -
> - if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
> - return r;
> -
> - if (!dm_task_set_name(dmt, name))
> - goto out;
> -
> - errno = 0;
> - if (!libmp_dm_task_run(dmt)) {
> - dm_log_error(3, DM_DEVICE_STATUS, dmt);
> - if (dm_task_get_errno(dmt) == ENXIO)
> - r = DMP_NOT_FOUND;
> - goto out;
> - }
> -
> - r = DMP_NOT_FOUND;
> - /* Fetch 1st target */
> - if (dm_get_next_target(dmt, NULL, &start, &length,
> - &target_type, &status) != NULL)
> - goto out;
> -
> - if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
> - goto out;
> -
> - if (!status) {
> - condlog(2, "got null status.");
> - goto out;
> - }
> -
> - if (!outstatus)
> - r = DMP_OK;
> - else {
> - *outstatus = strdup(status);
> - r = *outstatus ? DMP_OK : DMP_ERR;
> - }
> -out:
> - if (r != DMP_OK)
> - condlog(0, "%s: %s: error getting map status string: %d",
> - __func__, name, r);
> -
> - return r;
> -}
> -
> int dm_is_mpath(const char *name)
> {
> char uuid[DM_UUID_LEN];
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index 7231a98..3daaa4c 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -131,8 +131,6 @@ int dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags);
> int dm_addmap_create (struct multipath *mpp, char *params);
> int dm_addmap_reload (struct multipath *mpp, char *params, int flush);
> int dm_map_present_by_wwid(const char *uuid);
> -int dm_get_map(const char *name, unsigned long long *size, char **outparams);
> -int dm_get_status(const char *name, char **outstatus);
>
> enum {
> DM_IS_MPATH_NO,
> diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
> index ccc4efc..f2cfe31 100644
> --- a/libmultipath/structs_vec.c
> +++ b/libmultipath/structs_vec.c
> @@ -484,30 +484,34 @@ int
> update_multipath_table (struct multipath *mpp, vector pathvec, int flags)
> {
> int r = DMP_ERR;
> - char *params = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *params = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *status = NULL;
> + unsigned long long size = mpp->size;
>
> if (!mpp)
> return r;
>
> - r = dm_get_map(mpp->alias, &mpp->size, ¶ms);
> + r = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
> + (mapid_t) { .str = mpp->alias },
> + (mapinfo_t) {
> + .target = ¶ms,
> + .status = &status,
> + .size = &mpp->size,
> + });
> +
> if (r != DMP_OK) {
> - condlog(2, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting table" : "map not present");
> + condlog(2, "%s: %s", mpp->alias, dmp_errstr(r));
> return r;
> - }
> + } else if (size != mpp->size)
> + condlog(0, "%s: size changed from %llu to %llu", mpp->alias, size, mpp->size);
>
> if (disassemble_map(pathvec, params, mpp)) {
> condlog(2, "%s: cannot disassemble map", mpp->alias);
> - free(params);
> return DMP_ERR;
> }
>
> - free(params);
> - params = NULL;
> - if (dm_get_status(mpp->alias, ¶ms) != DMP_OK)
> - condlog(2, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting status" : "map not present");
> - else if (disassemble_status(params, mpp))
> + if (disassemble_status(status, mpp))
> condlog(2, "%s: cannot disassemble status", mpp->alias);
> - free(params);
>
> /* FIXME: we should deal with the return value here */
> update_pathvec_from_dm(pathvec, mpp, flags);
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 41/49] multipath: implement check_usable_paths() with libmp_pathinfo()
2024-07-12 17:14 ` [PATCH v2 41/49] multipath: implement check_usable_paths() with libmp_pathinfo() Martin Wilck
@ 2024-07-15 22:45 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:45 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:49PM +0200, Martin Wilck wrote:
> ... and use cleanup attributes. We need to call the disassemble...()
> functions from multipath directly now, but we fetch exactly the data
> we need from the kernel.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> multipath/main.c | 58 ++++++++++++++++++++++++++----------------------
> 1 file changed, 31 insertions(+), 27 deletions(-)
>
> diff --git a/multipath/main.c b/multipath/main.c
> index c82bc86..0d989dc 100644
> --- a/multipath/main.c
> +++ b/multipath/main.c
> @@ -222,12 +222,14 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
> static int check_usable_paths(struct config *conf,
> const char *devpath, enum devtypes dev_type)
> {
> - struct udev_device *ud = NULL;
> - struct multipath *mpp = NULL;
> + struct udev_device __attribute__((cleanup(cleanup_udev_device))) *ud = NULL;
> + struct multipath __attribute__((cleanup(cleanup_multipath_and_paths))) *mpp = NULL;
> struct pathgroup *pg;
> struct path *pp;
> - char *mapname;
> - vector pathvec = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *params = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *status = NULL;
> + vector __attribute((cleanup(cleanup_vector))) pathvec = NULL;
> + char uuid[DM_UUID_LEN];
> dev_t devt;
> int r = 1, i, j;
>
> @@ -238,31 +240,39 @@ static int check_usable_paths(struct config *conf,
> devt = udev_device_get_devnum(ud);
> if (!dm_is_dm_major(major(devt))) {
> condlog(1, "%s is not a dm device", devpath);
> - goto out;
> + return r;
> }
>
> - mapname = dm_mapname(major(devt), minor(devt));
> - if (mapname == NULL) {
> - condlog(1, "dm device not found: %s", devpath);
> - goto out;
> - }
> -
> - if (dm_is_mpath(mapname) != DM_IS_MPATH_YES) {
> - condlog(1, "%s is not a multipath map", devpath);
> - goto free;
> - }
> + mpp = alloc_multipath();
> + if (!mpp)
> + return r;
> + if (!(mpp->alias = malloc(WWID_SIZE)))
> + return r;
>
> /* pathvec is needed for disassemble_map */
> pathvec = vector_alloc();
> if (pathvec == NULL)
> - goto free;
> + return r;
>
> - mpp = dm_get_multipath(mapname);
> - if (mpp == NULL)
> - goto free;
> + if (libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
> + (mapid_t) { .devt = devt },
> + (mapinfo_t) {
> + .name = mpp->alias,
> + .uuid = uuid,
> + .dmi = &mpp->dmi,
> + .size = &mpp->size,
> + .target = ¶ms,
> + .status = &status,
> + }) != DMP_OK)
> + return r;
>
> - if (update_multipath_table(mpp, pathvec, 0) != DMP_OK)
> - goto free;
> + if (!is_mpath_uuid(uuid))
> + return r;
> +
> + strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
> +
> + if (update_multipath_table__(mpp, pathvec, 0, params, status) != DMP_OK)
> + return r;
>
> vector_foreach_slot (mpp->pg, pg, i) {
> vector_foreach_slot (pg->paths, pp, j) {
> @@ -284,12 +294,6 @@ static int check_usable_paths(struct config *conf,
> found:
> condlog(r == 0 ? 3 : 2, "%s:%s usable paths found",
> devpath, r == 0 ? "" : " no");
> -free:
> - free(mapname);
> - free_multipath(mpp, FREE_PATHS);
> - vector_free(pathvec);
> -out:
> - udev_device_unref(ud);
> return r;
> }
>
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 42/49] multipathd: implement add_map_without_path() with libmp_mapinfo()
2024-07-12 17:14 ` [PATCH v2 42/49] multipathd: implement add_map_without_path() with libmp_mapinfo() Martin Wilck
@ 2024-07-15 22:47 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:47 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:50PM +0200, Martin Wilck wrote:
> Also, change the return value to int, as this is more expressive and
> the returned struct multipath isn't used by the caller.
>
> Also remove the call to sync_map_state() in ev_add_map(), which is
> redundant because add_map_without_path() would have called update_map()
> and thus sync_map_state() already.
>
> Note: this removes the call to remove_map() at the end of the function,
> which doesn't make sense anyway, because update_multipath_table()
> would not return error unless the table disassembly failed, in which
> case nothing would have been added the the mpvec or pathvec yet.
> It should be sufficient to just cleanup the local data structures when
> add_map_without_path() fails.
>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> multipathd/main.c | 79 ++++++++++++++++++++++++-----------------------
> 1 file changed, 41 insertions(+), 38 deletions(-)
>
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 1e7a6ac..536974c 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -707,51 +707,57 @@ fail:
> return 0;
> }
>
> -static struct multipath *
> -add_map_without_path (struct vectors *vecs, const char *alias)
> +static int add_map_without_path (struct vectors *vecs, const char *alias)
> {
> - struct multipath * mpp = alloc_multipath();
> + struct multipath __attribute__((cleanup(cleanup_multipath_and_paths)))
> + *mpp = alloc_multipath();
> + char __attribute__((cleanup(cleanup_charp))) *params = NULL;
> + char __attribute__((cleanup(cleanup_charp))) *status = NULL;
> struct config *conf;
> + char uuid[DM_UUID_LEN];
> + int rc = DMP_ERR;
>
> - if (!mpp)
> - return NULL;
> - if (!alias) {
> - free(mpp);
> - return NULL;
> - }
> + if (!mpp || !(mpp->alias = strdup(alias)))
> + return DMP_ERR;
>
> - mpp->alias = strdup(alias);
> + if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
> + (mapid_t) { .str = mpp->alias },
> + (mapinfo_t) {
> + .uuid = uuid,
> + .dmi = &mpp->dmi,
> + .size = &mpp->size,
> + .target = ¶ms,
> + .status = &status,
> + })) != DMP_OK)
> + return rc;
> +
> + if (!is_mpath_uuid(uuid))
> + return DMP_NO_MATCH;
> + else
> + strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
>
> - if (dm_get_info(mpp->alias, &mpp->dmi) != DMP_OK) {
> - condlog(3, "%s: cannot access table", mpp->alias);
> - goto out;
> - }
> - if (!strlen(mpp->wwid) &&
> - dm_get_wwid(mpp->alias, mpp->wwid, WWID_SIZE) != DMP_OK) {
> - condlog(3, "%s: cannot obtain WWID", mpp->alias);
> - goto out;
> - }
> if (!strlen(mpp->wwid))
> condlog(1, "%s: adding map with empty WWID", mpp->alias);
> +
> conf = get_multipath_config();
> mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
> put_multipath_config(conf);
>
> - if (update_multipath_table(mpp, vecs->pathvec, 0) != DMP_OK)
> - goto out;
> + if ((rc = update_multipath_table__(mpp, vecs->pathvec, 0, params, status)) != DMP_OK)
> + return DMP_ERR;
>
> if (!vector_alloc_slot(vecs->mpvec))
> - goto out;
> + return DMP_ERR;
> + vector_set_slot(vecs->mpvec, steal_ptr(mpp));
>
> - vector_set_slot(vecs->mpvec, mpp);
> + /*
> + * We can pass mpp here, steal_ptr() has just nullified it.
Nitpick: "We *can't* pass mpp here, ..."
-Ben
> + * vector_set_slot() just set the last slot, use that.
> + */
> + if (update_map(VECTOR_LAST_SLOT(vecs->mpvec), vecs, 1) != 0) /* map removed */
> + return DMP_ERR;
>
> - if (update_map(mpp, vecs, 1) != 0) /* map removed */
> - return NULL;
> -
> - return mpp;
> -out:
> - remove_map(mpp, vecs->pathvec, vecs->mpvec);
> - return NULL;
> + return DMP_OK;
> }
>
> static int
> @@ -865,14 +871,9 @@ int
> ev_add_map (char * dev, const char * alias, struct vectors * vecs)
> {
> struct multipath * mpp;
> - int reassign_maps;
> + int reassign_maps, rc;
> struct config *conf;
>
> - if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
> - condlog(4, "%s: not a multipath map", alias);
> - return 0;
> - }
> -
> mpp = find_mp_by_alias(vecs->mpvec, alias);
>
> if (mpp) {
> @@ -910,10 +911,12 @@ ev_add_map (char * dev, const char * alias, struct vectors * vecs)
> /*
> * now we can register the map
> */
> - if ((mpp = add_map_without_path(vecs, alias))) {
> - sync_map_state(mpp);
> + if ((rc = add_map_without_path(vecs, alias)) == DMP_OK) {
> condlog(2, "%s: devmap %s registered", alias, dev);
> return 0;
> + } else if (rc == DMP_NO_MATCH) {
> + condlog(4, "%s: not a multipath map", alias);
> + return 0;
> } else {
> condlog(2, "%s: ev_add_map failed", dev);
> return 1;
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 44/49] libmpathpersist: use libmp_mapinfo() in mpath_get_map()
2024-07-12 17:14 ` [PATCH v2 44/49] libmpathpersist: use libmp_mapinfo() in mpath_get_map() Martin Wilck
@ 2024-07-15 22:48 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:48 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:52PM +0200, Martin Wilck wrote:
> When obtaining the map name, make sure right away that the map is a multipath
> device. This saves an ioctl and slightly simplifies the function.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmpathpersist/mpath_persist_int.c | 50 +++++++++++++----------------
> 1 file changed, 23 insertions(+), 27 deletions(-)
>
> diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
> index 5a5ac3b..a3eb80a 100644
> --- a/libmpathpersist/mpath_persist_int.c
> +++ b/libmpathpersist/mpath_persist_int.c
> @@ -157,10 +157,9 @@ static int get_mpvec(vector curmp, vector pathvec, char *refwwid)
> static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
> struct multipath **pmpp)
> {
> - int ret = MPATH_PR_DMMP_ERROR;
> + int rc;
> struct stat info;
> - int major, minor;
> - char *alias;
> + char alias[WWID_SIZE], uuid[DM_UUID_LEN];
> struct multipath *mpp;
>
> if (fstat(fd, &info) != 0){
> @@ -172,47 +171,44 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
> return MPATH_PR_FILE_ERROR;
> }
>
> - major = major(info.st_rdev);
> - minor = minor(info.st_rdev);
> - condlog(4, "Device %d:%d", major, minor);
> -
> /* get alias from major:minor*/
> - alias = dm_mapname(major, minor);
> - if (!alias){
> - condlog(0, "%d:%d failed to get device alias.", major, minor);
> + rc = libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
> + (mapid_t) { .devt = info.st_rdev },
> + (mapinfo_t) {
> + .name = alias,
> + .uuid = uuid,
> + });
> +
> + if (rc == DMP_NO_MATCH || !is_mpath_uuid(uuid)) {
> + condlog(3, "%s: not a multipath device.", alias);
> + return MPATH_PR_DMMP_ERROR;
> + } else if (rc != DMP_OK) {
> + condlog(1, "%d:%d failed to get device alias.",
> + major(info.st_rdev), minor(info.st_rdev));
> return MPATH_PR_DMMP_ERROR;
> }
>
> - condlog(3, "alias = %s", alias);
> -
> - if (dm_is_mpath(alias) != DM_IS_MPATH_YES) {
> - condlog(3, "%s: not a multipath device.", alias);
> - goto out;
> - }
> + condlog(4, "alias = %s", alias);
>
> /* get info of all paths from the dm device */
> - if (get_mpvec(curmp, pathvec, alias)){
> + if (get_mpvec(curmp, pathvec, alias)) {
> condlog(0, "%s: failed to get device info.", alias);
> - goto out;
> + return MPATH_PR_DMMP_ERROR;
> }
>
> mpp = find_mp_by_alias(curmp, alias);
>
> if (!mpp) {
> condlog(0, "%s: devmap not registered.", alias);
> - goto out;
> + return MPATH_PR_DMMP_ERROR;
> }
>
> - ret = MPATH_PR_SUCCESS;
> if (pmpp)
> *pmpp = mpp;
> - if (palias) {
> - *palias = alias;
> - alias = NULL;
> - }
> -out:
> - free(alias);
> - return ret;
> + if (palias && (*palias = strdup(alias)) == NULL)
> + return MPATH_PR_DMMP_ERROR;
> +
> + return MPATH_PR_SUCCESS;
> }
>
> int do_mpath_persistent_reserve_in(vector curmp, vector pathvec,
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 46/49] libmultipath: fix deferred_remove logic in remove_partmap()
2024-07-12 17:14 ` [PATCH v2 46/49] libmultipath: fix deferred_remove logic in remove_partmap() Martin Wilck
@ 2024-07-15 22:49 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:49 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:54PM +0200, Martin Wilck wrote:
> The logic for returning DM_FLUSH_BUSY in remove_partmap() got
> accidentally reverted in commit 20aeeb6. Fix it.
>
> Fixes: 20aeeb6 ("libmultipath: fix deferred_remove function arguments")
Oops.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index b52b10e..5749d63 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -1383,7 +1383,7 @@ remove_partmap(const char *name, void *data)
>
> if (dm_get_opencount(name)) {
> dm_remove_partmaps(name, rd->flags);
> - if ((rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
> + if (!(rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
> condlog(2, "%s: map in use", name);
> return DM_FLUSH_BUSY;
> }
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 47/49] libmultipath: don't call do_foreach_partmaps() recursively
2024-07-12 17:14 ` [PATCH v2 47/49] libmultipath: don't call do_foreach_partmaps() recursively Martin Wilck
@ 2024-07-15 22:51 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 22:51 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:55PM +0200, Martin Wilck wrote:
> We've removed partition mappings recursively since 83fb936 ("Correctly remove
> logical partition maps"). This was wrong, because kpartx doesn't create
> logical partitions as mappings onto the extended partition. Rather, logical
> partitions are created by kpartx as mappings to the multipath device, and
> afaics, this has always been the case. Therefore, the loop in
> do_foreach_partmaps() will detect all partition mappings (primary, extended,
> and logical) without recursion. At least since 4059e42 ("libmultipath: fix
> partition detection"), the recursion has actually been pointless, because
> is_mpath_part() would never have returned "true" for a pair of two partition
> mappings (one representing an extended partition and one a logical partition).
>
> Avoiding the recursion has the additional benefit that the complexity of
> removing maps scales with N, where N is the number of dm devices, rather than
> with N^2. Also, it simplifies the code.
>
> Split partmap_in_use() into two separate functions, mpath_in_use() (to be called
> for multipath maps) and count_partitions(), which is called from
> do_foreach_partmaps().
>
> Because do_foreach_partmaps() is now only legitimately called for multipath
> maps, quit early if called for another map type.
>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmultipath/devmapper.c | 48 +++++++++++++++++++------------
> libmultipath/devmapper.h | 2 +-
> libmultipath/libmultipath.version | 2 +-
> multipathd/main.c | 2 +-
> 4 files changed, 33 insertions(+), 21 deletions(-)
>
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 5749d63..d9d96be 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -933,22 +933,37 @@ has_partmap(const char *name __attribute__((unused)),
> return 1;
> }
>
> -int
> -partmap_in_use(const char *name, void *data)
> +/*
> + * This will be called from mpath_in_use, for each partition.
> + * If the partition itself in use, returns 1 immediately, causing
> + * do_foreach_partmaps() to stop iterating and return 1.
> + * Otherwise, increases the partition count.
> + */
> +static int count_partitions(const char *name, void *data)
> +{
> + int *ret_count = (int *)data;
> + int open_count = dm_get_opencount(name);
> +
> + if (open_count)
> + return 1;
> + (*ret_count)++;
> + return 0;
> +}
> +
> +int mpath_in_use(const char *name)
> {
> - int part_count, *ret_count = (int *)data;
> int open_count = dm_get_opencount(name);
>
> - if (ret_count)
> - (*ret_count)++;
> - part_count = 0;
> if (open_count) {
> - if (do_foreach_partmaps(name, partmap_in_use, &part_count))
> - return 1;
> - if (open_count != part_count) {
> - condlog(2, "%s: map in use", name);
> + int part_count = 0;
> +
> + if (do_foreach_partmaps(name, count_partitions, &part_count)) {
> + condlog(4, "%s: %s has open partitions", __func__, name);
> return 1;
> }
> + condlog(4, "%s: %s: %d openers, %d partitions", __func__, name,
> + open_count, part_count);
> + return open_count > part_count;
> }
> return 0;
> }
> @@ -976,7 +991,7 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
>
> /* If you aren't doing a deferred remove, make sure that no
> * devices are in use */
> - if (!(flags & DMFL_DEFERRED) && partmap_in_use(mapname, NULL))
> + if (!(flags & DMFL_DEFERRED) && mpath_in_use(mapname))
> return DM_FLUSH_BUSY;
>
> if ((flags & DMFL_SUSPEND) &&
> @@ -1314,7 +1329,7 @@ do_foreach_partmaps (const char *mapname,
> char map_uuid[DM_UUID_LEN];
> struct dm_info info;
>
> - if (libmp_mapinfo(DM_MAP_BY_NAME,
> + if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
This patch is out of order. You add MAPINFO_CHECK_UUID in the next one.
Otherwise
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
-Ben
> (mapid_t) { .str = mapname },
> (mapinfo_t) { .uuid = map_uuid, .dmi = &info }) != DMP_OK)
> return 1;
> @@ -1381,12 +1396,9 @@ remove_partmap(const char *name, void *data)
> {
> struct remove_data *rd = (struct remove_data *)data;
>
> - if (dm_get_opencount(name)) {
> - dm_remove_partmaps(name, rd->flags);
> - if (!(rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
> - condlog(2, "%s: map in use", name);
> - return DM_FLUSH_BUSY;
> - }
> + if (!(rd->flags & DMFL_DEFERRED) && dm_get_opencount(name)) {
> + condlog(2, "%s: map in use", name);
> + return DM_FLUSH_BUSY;
> }
> condlog(4, "partition map %s removed", name);
> dm_device_remove(name, rd->flags);
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index d01f9f2..6eb5ab9 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -149,7 +149,7 @@ enum {
> DM_FLUSH_BUSY,
> };
>
> -int partmap_in_use(const char *name, void *data);
> +int mpath_in_use(const char *name);
>
> enum {
> DMFL_NONE = 0,
> diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
> index 54b5a23..649c1cb 100644
> --- a/libmultipath/libmultipath.version
> +++ b/libmultipath/libmultipath.version
> @@ -139,10 +139,10 @@ global:
> libmultipath_exit;
> libmultipath_init;
> load_config;
> + mpath_in_use;
> need_io_err_check;
> orphan_path;
> parse_prkey_flags;
> - partmap_in_use;
> pathcount;
> path_discovery;
> path_get_tpgs;
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 536974c..13af94e 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -597,7 +597,7 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
> return false;
> }
> if (mpp->flush_on_last_del == FLUSH_UNUSED &&
> - partmap_in_use(mpp->alias, NULL) && is_queueing) {
> + mpath_in_use(mpp->alias) && is_queueing) {
> condlog(2, "%s: map in use and queueing, can't remove",
> mpp->alias);
> return false;
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 48/49] libmultipath: Move UUID check into libmp_pathinfo__()
2024-07-12 17:14 ` [PATCH v2 48/49] libmultipath: Move UUID check into libmp_pathinfo__() Martin Wilck
@ 2024-07-15 23:24 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 23:24 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:56PM +0200, Martin Wilck wrote:
> We have a couple of callers that check whether the map UUID conforms
> to the multipath convention ("mpath-xyz"). Move this check into
> libmp_mapinfo__(). Add another flag MAPINFO_CHECK_UUID for this
> purpose. This allows to simplify some callers, which only fetched
> the UUID in order to check it.
>
> Note that the UUID check is orthogonal to MAPINFO_MPATH_ONLY, which
> tests the target type. We shold make sure that both tests are in
> agreement, but this is postponed to a later patch set.
>
> is_mpath_uuid() can now be converted to a static function.
>
> Also add some unit tests for the WWID check.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> libmpathpersist/mpath_persist_int.c | 11 +-
> libmultipath/devmapper.c | 52 +++----
> libmultipath/devmapper.h | 3 +-
> libmultipath/libmultipath.version | 1 -
> multipath/main.c | 5 +-
> multipathd/main.c | 7 +-
> tests/mapinfo.c | 226 ++++++++++++++++++++++++++++
> 7 files changed, 256 insertions(+), 49 deletions(-)
>
> diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
> index 807415f..f4d9e7c 100644
> --- a/libmpathpersist/mpath_persist_int.c
> +++ b/libmpathpersist/mpath_persist_int.c
> @@ -158,7 +158,7 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath
> {
> int rc;
> struct stat info;
> - char alias[WWID_SIZE], uuid[DM_UUID_LEN];
> + char alias[WWID_SIZE];
> struct multipath *mpp;
>
> if (fstat(fd, &info) != 0){
> @@ -171,14 +171,11 @@ static int mpath_get_map(vector curmp, vector pathvec, int fd, struct multipath
> }
>
> /* get alias from major:minor*/
> - rc = libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
> + rc = libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> (mapid_t) { .devt = info.st_rdev },
> - (mapinfo_t) {
> - .name = alias,
> - .uuid = uuid,
> - });
> + (mapinfo_t) { .name = alias });
>
> - if (rc == DMP_NO_MATCH || !is_mpath_uuid(uuid)) {
> + if (rc == DMP_NO_MATCH) {
> condlog(3, "%s: not a multipath device.", alias);
> return MPATH_PR_DMMP_ERROR;
> } else if (rc != DMP_OK) {
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index d9d96be..bbbadee 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -611,6 +611,11 @@ int dm_addmap_reload(struct multipath *mpp, char *params, int flush)
> return 0;
> }
>
> +static bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
> +{
> + return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
> +}
> +
> bool
> has_dm_info(const struct multipath *mpp)
> {
> @@ -734,11 +739,17 @@ static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info, const char *ma
> * If error is returned, don't touch any output parameters.
> */
> if ((info.name && !(name = dm_task_get_name(dmt)))
> - || (info.uuid && !(uuid = dm_task_get_uuid(dmt)))
> + || ((info.uuid || flags & MAPINFO_CHECK_UUID)
> + && !(uuid = dm_task_get_uuid(dmt)))
> || (info.status && !(tmp_status = strdup(params)))
> || (info.target && !tmp_target && !(tmp_target = strdup(params))))
> return DMP_ERR;
>
> + if (flags & MAPINFO_CHECK_UUID && !is_mpath_uuid(uuid)) {
> + condlog(3, "%s: UUID mismatch: %s", __func__, uuid);
> + return DMP_NO_MATCH;
> + }
> +
> if (info.name) {
> strlcpy(info.name, name, WWID_SIZE);
> condlog(4, "%s: %s: name: \"%s\"", __func__, map_id, info.name);
> @@ -808,18 +819,6 @@ int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
> libmp_map_identifier(flags, id, idbuf));
> }
>
> -static int dm_get_dm_uuid(const char *mapname, char uuid[DM_UUID_LEN])
> -{
> - return libmp_mapinfo(DM_MAP_BY_NAME,
> - (mapid_t) { .str = mapname },
> - (mapinfo_t) { .uuid = uuid });
> -}
> -
> -bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
> -{
> - return !strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN);
> -}
> -
> /**
> * dm_get_wwid(): return WWID for a multipath map
> * @returns:
> @@ -832,16 +831,14 @@ bool is_mpath_uuid(const char uuid[DM_UUID_LEN])
> int dm_get_wwid(const char *name, char *uuid, int uuid_len)
> {
> char tmp[DM_UUID_LEN];
> - int rc = dm_get_dm_uuid(name, tmp);
> + int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = name },
> + (mapinfo_t) { .uuid = tmp });
>
> if (rc != DMP_OK)
> return rc;
>
> - if (is_mpath_uuid(tmp))
> - strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
> - else
> - return DMP_NO_MATCH;
> -
> + strlcpy(uuid, tmp + UUID_PREFIX_LEN, uuid_len);
> return DMP_OK;
> }
>
> @@ -859,16 +856,13 @@ static bool is_mpath_part_uuid(const char part_uuid[DM_UUID_LEN],
>
> int dm_is_mpath(const char *name)
> {
> - char uuid[DM_UUID_LEN];
> - int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
> + int rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> (mapid_t) { .str = name },
> - (mapinfo_t) { .uuid = uuid });
> + (mapinfo_t) { .uuid = NULL });
>
> switch (rc) {
> case DMP_OK:
> - if (is_mpath_uuid(uuid))
> - return DM_IS_MPATH_YES;
> - /* fallthrough */
> + return DM_IS_MPATH_YES;
> case DMP_NOT_FOUND:
> case DMP_NO_MATCH:
> return DM_IS_MPATH_NO;
> @@ -974,14 +968,10 @@ int _dm_flush_map (const char *mapname, int flags, int retries)
> int queue_if_no_path = 0;
> int udev_flags = 0;
> char *params __attribute__((cleanup(cleanup_charp))) = NULL;
> - char uuid[DM_UUID_LEN];
>
> - if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
> + if (libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> (mapid_t) { .str = mapname },
> - (mapinfo_t) {
> - .uuid = uuid,
> - .target = ¶ms }) != DMP_OK
> - || !is_mpath_uuid(uuid))
> + (mapinfo_t) { .target = ¶ms }) != DMP_OK)
> return DM_FLUSH_OK; /* nothing to do */
>
> /* if the device currently has no partitions, do not
> diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> index 6eb5ab9..c28991f 100644
> --- a/libmultipath/devmapper.h
> +++ b/libmultipath/devmapper.h
> @@ -57,6 +57,8 @@ enum __mapinfo_flags {
> /* Fail if target type is not "partition" (linear) */
> MAPINFO_PART_ONLY = (1 << 4),
> __MAPINFO_TGT_TYPE = (MAPINFO_MPATH_ONLY | MAPINFO_PART_ONLY),
> + /* Fail if the UUID doesn't match the multipath UUID format */
> + MAPINFO_CHECK_UUID = (1 << 8),
> };
>
> typedef union libmp_map_identifier {
> @@ -138,7 +140,6 @@ enum {
> DM_IS_MPATH_ERR,
> };
>
> -bool is_mpath_uuid(const char uuid[DM_UUID_LEN]);
> int dm_is_mpath(const char *name);
>
> enum {
> diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
> index 649c1cb..959f675 100644
> --- a/libmultipath/libmultipath.version
> +++ b/libmultipath/libmultipath.version
> @@ -127,7 +127,6 @@ global:
> init_foreign;
> init_prio;
> io_err_stat_handle_pathfail;
> - is_mpath_uuid;
> is_path_valid;
> libmp_dm_task_create;
> libmp_get_version;
> diff --git a/multipath/main.c b/multipath/main.c
> index 0d989dc..4b19d2e 100644
> --- a/multipath/main.c
> +++ b/multipath/main.c
> @@ -254,7 +254,7 @@ static int check_usable_paths(struct config *conf,
> if (pathvec == NULL)
> return r;
>
> - if (libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY,
> + if (libmp_mapinfo(DM_MAP_BY_DEVT | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> (mapid_t) { .devt = devt },
> (mapinfo_t) {
> .name = mpp->alias,
> @@ -266,9 +266,6 @@ static int check_usable_paths(struct config *conf,
> }) != DMP_OK)
> return r;
>
> - if (!is_mpath_uuid(uuid))
> - return r;
> -
> strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
>
> if (update_multipath_table__(mpp, pathvec, 0, params, status) != DMP_OK)
> diff --git a/multipathd/main.c b/multipathd/main.c
> index 13af94e..386cd07 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -720,7 +720,7 @@ static int add_map_without_path (struct vectors *vecs, const char *alias)
> if (!mpp || !(mpp->alias = strdup(alias)))
> return DMP_ERR;
>
> - if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY,
> + if ((rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> (mapid_t) { .str = mpp->alias },
> (mapinfo_t) {
> .uuid = uuid,
> @@ -731,10 +731,7 @@ static int add_map_without_path (struct vectors *vecs, const char *alias)
> })) != DMP_OK)
> return rc;
>
> - if (!is_mpath_uuid(uuid))
> - return DMP_NO_MATCH;
> - else
> - strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
> + strlcpy(mpp->wwid, uuid + UUID_PREFIX_LEN, sizeof(mpp->wwid));
>
> if (!strlen(mpp->wwid))
> condlog(1, "%s: adding map with empty WWID", mpp->alias);
> diff --git a/tests/mapinfo.c b/tests/mapinfo.c
> index f3a8440..f7ad868 100644
> --- a/tests/mapinfo.c
> +++ b/tests/mapinfo.c
> @@ -54,6 +54,16 @@ static const char MPATH_STATUS_01[] =
> "A 0 3 2 65:32 A 0 0 1 67:64 A 0 0 1 69:96 A 0 0 1 "
> "E 0 3 2 8:16 A 0 0 1 66:48 A 0 0 1 68:80 A 0 0 1 ";
>
> +static const char BAD_UUID_01[] = "";
> +static const char BAD_UUID_02[] = "mpath3600a098038302d414b2b4d4453474f62";
> +static const char BAD_UUID_03[] = " mpath-3600a098038302d414b2b4d4453474f62";
> +static const char BAD_UUID_04[] = "-mpath-3600a098038302d414b2b4d4453474f62";
> +static const char BAD_UUID_05[] = "mpth-3600a098038302d414b2b4d4453474f62";
> +static const char BAD_UUID_06[] = "part1-mpath-3600a098038302d414b2b4d4453474f62";
> +static const char BAD_UUID_07[] = "mpath 3600a098038302d414b2b4d4453474f62";
> +static const char BAD_UUID_08[] = "mpath";
> +static const char BAD_UUID_09[] = "mpath-";
> +
> char *__real_strdup(const char *str);
> char *__wrap_strdup(const char *str)
> {
> @@ -413,6 +423,208 @@ static void test_mapinfo_good_exists(void **state)
> assert_int_equal(rc, DMP_OK);
> }
>
> +static void test_mapinfo_bad_check_uuid_00(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, NULL);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_ERR);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_01(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_01);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_02(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_02);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_03(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_03);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_04(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_04);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_05(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_05);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_06(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_06);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_07(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_07);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_08(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_08);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_NO_MATCH);
> +}
> +
> +static void test_mapinfo_bad_check_uuid_09(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, BAD_UUID_09);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_OK);
> +}
> +
> +static void test_mapinfo_good_check_uuid_01(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_OK);
> +}
> +
> +static void test_mapinfo_good_check_uuid_02(void **state)
> +{
> + int rc;
> + char uuid[DM_UUID_LEN];
> +
> + mock_mapinfo_name_1(DM_DEVICE_INFO, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .uuid = uuid });
> + assert_int_equal(rc, DMP_OK);
> +}
> +
> +static void test_mapinfo_good_check_uuid_03(void **state)
> +{
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_STATUS, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
> + will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .name = NULL });
> + assert_int_equal(rc, DMP_OK);
> +}
> +
> +static void test_mapinfo_good_check_uuid_04(void **state)
> +{
> + char __attribute__((cleanup(cleanup_charp))) *target = NULL;
> + int rc;
> +
> + mock_mapinfo_name_1(DM_DEVICE_TABLE, 1, "foo", 1, 1, 0);
> + WRAP_DM_TASK_GET_INFO(1);
> + WRAP_DM_TASK_GET_INFO(&MPATH_DMI_01);
> + mock_dm_get_next_target(12345, TGT_MPATH, MPATH_STATUS_01, NULL);
> + will_return(__wrap_dm_task_get_uuid, MPATH_UUID_01);
> + will_return(__wrap_strdup, 1);
> +
> + rc = libmp_mapinfo(DM_MAP_BY_NAME | MAPINFO_MPATH_ONLY | MAPINFO_CHECK_UUID,
> + (mapid_t) { .str = "foo", },
> + (mapinfo_t) { .target = &target });
> + assert_int_equal(rc, DMP_OK);
> +}
> +
> static void test_mapinfo_bad_set_uuid(void **state)
> {
> int rc;
> @@ -1126,6 +1338,20 @@ static int test_mapinfo(void)
> cmocka_unit_test(test_mapinfo_bad_get_info_03),
> cmocka_unit_test(test_mapinfo_bad_get_info_04),
> cmocka_unit_test(test_mapinfo_good_exists),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_00),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_01),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_02),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_03),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_04),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_05),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_06),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_07),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_08),
> + cmocka_unit_test(test_mapinfo_bad_check_uuid_09),
> + cmocka_unit_test(test_mapinfo_good_check_uuid_01),
> + cmocka_unit_test(test_mapinfo_good_check_uuid_02),
> + cmocka_unit_test(test_mapinfo_good_check_uuid_03),
> + cmocka_unit_test(test_mapinfo_good_check_uuid_04),
> cmocka_unit_test(test_mapinfo_bad_set_uuid),
> cmocka_unit_test(test_mapinfo_bad_set_dev_01),
> cmocka_unit_test(test_mapinfo_bad_set_dev_02),
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 49/49] multipath-tools tests: fix directio test with real device
2024-07-12 17:14 ` [PATCH v2 49/49] multipath-tools tests: fix directio test with real device Martin Wilck
@ 2024-07-15 23:25 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-15 23:25 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel, Martin Wilck
On Fri, Jul 12, 2024 at 07:14:57PM +0200, Martin Wilck wrote:
> Allow setting DIO_TEST_DEV during runtime, by reading the environment
> variable. The test was fragile despite the delay, because the real
> io_getevents() call isn't guaranteed to return the number of events
> requested. Fix that. Moreover, allow reading DIO_TEST_DELAY (in us)
> from the environment. With the io_getevents fix, for me the test
> succeeded even with 0 us delay.
>
> Change the README accordingly.
>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
> Signed-off-by: Martin Wilck <mwilck@suse.com>
> ---
> tests/Makefile | 8 ---
> tests/README.md | 29 ++++++--
> tests/directio.c | 182 ++++++++++++++++++++++++++---------------------
> 3 files changed, 122 insertions(+), 97 deletions(-)
>
> diff --git a/tests/Makefile b/tests/Makefile
> index 55fbf0f..02580e7 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -21,12 +21,6 @@ valgrind: $(TESTS:%=%.vgr)
> # test-specific compiler flags
> # XYZ-test_FLAGS: Additional compiler flags for this test
>
> -ifneq ($(wildcard directio_test_dev),)
> -DIO_TEST_DEV = $(shell sed -n -e 's/^[[:space:]]*DIO_TEST_DEV[[:space:]]*=[[:space:]]*\([^[:space:]\#]\+\).*/\1/p' < directio_test_dev)
> -endif
> -ifneq ($(DIO_TEST_DEV),)
> -directio-test_FLAGS := -DDIO_TEST_DEV=\"$(DIO_TEST_DEV)\"
> -endif
> mpathvalid-test_FLAGS := -I$(mpathvaliddir)
> features-test_FLAGS := -I$(multipathdir)/nvme
>
> @@ -59,9 +53,7 @@ valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl
> devt-test_LIBDEPS := -ludev
> mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl
> mpathvalid-test_OBJDEPS := $(mpathvaliddir)/mpath_valid.o
> -ifneq ($(DIO_TEST_DEV),)
> directio-test_LIBDEPS := -laio
> -endif
> strbuf-test_OBJDEPS := $(mpathutildir)/strbuf.o
> sysfs-test_TESTDEPS := test-log.o
> sysfs-test_OBJDEPS := $(multipathdir)/sysfs.o $(mpathutildir)/util.o
> diff --git a/tests/README.md b/tests/README.md
> index fd36fc1..0cae057 100644
> --- a/tests/README.md
> +++ b/tests/README.md
> @@ -13,6 +13,17 @@ If valgrind detects a bad memory access or leak, the test will fail. The
> output of the test run, including valgrind output, is stored as
> `<testname>.vgr`.
>
> +## Running tests manually
> +
> +`make test` or `make -C test "$TEST.out"` will only run the test program if
> +the output files `$TEST.out` don't exist yet. To re-run the test, delete the
> +output file first. In order to run a test outside `make`, set the library
> +search path:
> +
> + cd tests
> + export LD_LIBRARY_PATH=.:../libmpathutil:../libmpathcmd
> + ./dmevents-test # or whatever other test you want to run
> +
> ## Controlling verbosity for unit tests
>
> Some test programs use the environment variable `MPATHTEST_VERBOSITY` to
> @@ -37,15 +48,21 @@ This test includes test items that require a access to a block device. The
> device will be opened in read-only mode; you don't need to worry about data
> loss. However, the user needs to specify a device to be used. Set the
> environment variable `DIO_TEST_DEV` to the path of the device.
> -Alternatively, create a file `directio_test_dev` under
> -the `tests` directory containing a single line that sets this environment
> -variable in Bourne Shell syntax, like this:
> -
> - DIO_TEST_DEV=/dev/sdc3
> -
> After that, run `make directio.out` as root in the `tests` directory to
> perform the test.
>
> +With a real test device, the test results may note be 100% reproducible,
> +and sporadic test failures may occur under certain circumstances.
> +It may be necessary to introduce a certain delay between test
> +operations. To do so, set the environment variable `DIO_TEST_DELAY` to a
> +positive integer that determines the delay (in microseconds) after each
> +`io_submit()` operation. The default delay is 10 microseconds.
> +
> +*Note:* `DIO_TEST_DEV` doesn't have to be set during compilation of
> +`directio-test`. This used to be the case in previous versions of
> +multipath-tools. Previously, it was possible to set `DIO_TEST_DEV` in a file
> +`tests/directio_test_dev`. This is not supported any more.
> +
> ## Adding tests
>
> The unit tests are based on the [cmocka test framework](https://cmocka.org/),
> diff --git a/tests/directio.c b/tests/directio.c
> index d5f84f1..763929e 100644
> --- a/tests/directio.c
> +++ b/tests/directio.c
> @@ -34,6 +34,8 @@ struct io_event mock_events[AIO_GROUP_SIZE]; /* same as the checker max */
> int ev_off = 0;
> struct timespec zero_timeout = { .tv_sec = 0 };
> struct timespec full_timeout = { .tv_sec = -1 };
> +const char *test_dev = NULL;
> +unsigned int test_delay = 10000;
>
> #ifdef __GLIBC__
> #define ioctl_request_t unsigned long
> @@ -45,12 +47,13 @@ int REAL_IOCTL(int fd, ioctl_request_t request, void *argp);
>
> int WRAP_IOCTL(int fd, ioctl_request_t request, void *argp)
> {
> -#ifdef DIO_TEST_DEV
> - mock_type(int);
> - return REAL_IOCTL(fd, request, argp);
> -#else
> int *blocksize = (int *)argp;
>
> + if (test_dev) {
> + mock_type(int);
> + return REAL_IOCTL(fd, request, argp);
> + }
> +
> assert_int_equal(fd, test_fd);
> /*
> * On MUSL libc, the "request" arg is an int (glibc: unsigned long).
> @@ -64,88 +67,80 @@ int WRAP_IOCTL(int fd, ioctl_request_t request, void *argp)
> assert_non_null(blocksize);
> *blocksize = mock_type(int);
> return 0;
> -#endif
> }
>
> int REAL_FCNTL (int fd, int cmd, long arg);
>
> int WRAP_FCNTL (int fd, int cmd, long arg)
> {
> -#ifdef DIO_TEST_DEV
> - return REAL_FCNTL(fd, cmd, arg);
> -#else
> + if (test_dev)
> + return REAL_FCNTL(fd, cmd, arg);
> assert_int_equal(fd, test_fd);
> assert_int_equal(cmd, F_GETFL);
> return O_DIRECT;
> -#endif
> }
>
> int __real___fxstat(int ver, int fd, struct stat *statbuf);
>
> int __wrap___fxstat(int ver, int fd, struct stat *statbuf)
> {
> -#ifdef DIO_TEST_DEV
> - return __real___fxstat(ver, fd, statbuf);
> -#else
> + if (test_dev)
> + return __real___fxstat(ver, fd, statbuf);
> +
> assert_int_equal(fd, test_fd);
> assert_non_null(statbuf);
> memset(statbuf, 0, sizeof(struct stat));
> return 0;
> -#endif
> +
> }
>
> int __real_io_setup(int maxevents, io_context_t *ctxp);
>
> int __wrap_io_setup(int maxevents, io_context_t *ctxp)
> {
> - ioctx_count++;
> -#ifdef DIO_TEST_DEV
> int ret = mock_type(int);
> - assert_int_equal(ret, __real_io_setup(maxevents, ctxp));
> +
> + if (test_dev)
> + assert_int_equal(ret, __real_io_setup(maxevents, ctxp));
> + ioctx_count++;
> return ret;
> -#else
> - return mock_type(int);
> -#endif
> }
>
> int __real_io_destroy(io_context_t ctx);
>
> int __wrap_io_destroy(io_context_t ctx)
> {
> - ioctx_count--;
> -#ifdef DIO_TEST_DEV
> int ret = mock_type(int);
> - assert_int_equal(ret, __real_io_destroy(ctx));
> +
> + ioctx_count--;
> + if (test_dev)
> + assert_int_equal(ret, __real_io_destroy(ctx));
> +
> return ret;
> -#else
> - return mock_type(int);
> -#endif
> }
>
> int __real_io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
>
> int __wrap_io_submit(io_context_t ctx, long nr, struct iocb *ios[])
> {
> -#ifdef DIO_TEST_DEV
> - struct timespec dev_delay = { .tv_nsec = 100000 };
> int ret = mock_type(int);
> - assert_int_equal(ret, __real_io_submit(ctx, nr, ios));
> - nanosleep(&dev_delay, NULL);
> +
> + if (test_dev) {
> + struct timespec dev_delay = { .tv_nsec = test_delay };
> + assert_int_equal(ret, __real_io_submit(ctx, nr, ios));
> + nanosleep(&dev_delay, NULL);
> + }
> return ret;
> -#else
> - return mock_type(int);
> -#endif
> }
>
> int __real_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
>
> int __wrap_io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt)
> {
> -#ifdef DIO_TEST_DEV
> - return __real_io_cancel(ctx, iocb, evt);
> -#else
> - return 0;
> -#endif
> + if (test_dev)
> + return __real_io_cancel(ctx, iocb, evt);
> + else
> + return 0;
> }
>
> int REAL_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr,
> @@ -155,38 +150,43 @@ int WRAP_IO_GETEVENTS(io_context_t ctx, long min_nr, long nr,
> struct io_event *events, struct timespec *timeout)
> {
> int nr_evs;
> -#ifndef DIO_TEST_DEV
> struct timespec *sleep_tmo;
> int i;
> struct io_event *evs;
> -#endif
>
> assert_non_null(timeout);
> nr_evs = mock_type(int);
> assert_true(nr_evs <= nr);
> if (!nr_evs)
> return 0;
> -#ifdef DIO_TEST_DEV
> - mock_ptr_type(struct timespec *);
> - mock_ptr_type(struct io_event *);
> - assert_int_equal(nr_evs, REAL_IO_GETEVENTS(ctx, min_nr, nr_evs,
> - events, timeout));
> -#else
> - sleep_tmo = mock_ptr_type(struct timespec *);
> - if (sleep_tmo) {
> - if (sleep_tmo->tv_sec < 0)
> - nanosleep(timeout, NULL);
> - else
> - nanosleep(sleep_tmo, NULL);
> + if (test_dev) {
> + int n = 0;
> + mock_ptr_type(struct timespec *);
> + mock_ptr_type(struct io_event *);
> +
> + condlog(2, "min_nr = %ld nr_evs = %d", min_nr, nr_evs);
> + while (n < nr_evs) {
> + min_nr = min_nr <= nr_evs - n ? min_nr : nr_evs - n;
> + n += REAL_IO_GETEVENTS(ctx, min_nr, nr_evs - n,
> + events + n, timeout);
> + }
> + assert_int_equal(nr_evs, n);
> + } else {
> + sleep_tmo = mock_ptr_type(struct timespec *);
> + if (sleep_tmo) {
> + if (sleep_tmo->tv_sec < 0)
> + nanosleep(timeout, NULL);
> + else
> + nanosleep(sleep_tmo, NULL);
> + }
> + if (nr_evs < 0) {
> + errno = -nr_evs;
> + return -1;
> + }
> + evs = mock_ptr_type(struct io_event *);
> + for (i = 0; i < nr_evs; i++)
> + events[i] = evs[i];
> }
> - if (nr_evs < 0) {
> - errno = -nr_evs;
> - return -1;
> - }
> - evs = mock_ptr_type(struct io_event *);
> - for (i = 0; i < nr_evs; i++)
> - events[i] = evs[i];
> -#endif
> ev_off -= nr_evs;
> return nr_evs;
> }
> @@ -259,10 +259,9 @@ static void do_libcheck_init(struct checker *c, int blocksize,
> assert_non_null(ct->req);
> if (req)
> *req = ct->req;
> -#ifndef DIO_TEST_DEV
> - /* don't check fake blocksize on real devices */
> - assert_int_equal(ct->req->blksize, blocksize);
> -#endif
> + if (!test_dev)
> + /* don't check fake blocksize on real devices */
> + assert_int_equal(ct->req->blksize, blocksize);
> }
>
> static int is_checker_running(struct checker *c)
> @@ -583,11 +582,11 @@ static void test_async_timeout_cancel_failed(void **state)
> do_check_state(&c[1], 0, 2, PATH_PENDING);
> return_io_getevents_none();
> do_check_state(&c[0], 0, 2, PATH_DOWN);
> -#ifndef DIO_TEST_DEV
> - /* can't pick which even gets returned on real devices */
> - return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
> - do_check_state(&c[1], 0, 2, PATH_UP);
> -#endif
> + if (!test_dev) {
> + /* can't pick which even gets returned on real devices */
> + return_io_getevents_nr(NULL, 1, &reqs[1], &res[1]);
> + do_check_state(&c[1], 0, 2, PATH_UP);
> + }
> return_io_getevents_none();
> do_check_state(&c[0], 0, 2, PATH_DOWN);
> assert_true(is_checker_running(&c[0]));
> @@ -663,12 +662,11 @@ static void test_check_state_blksize(void **state)
> int blksize[] = {4096, 1024, 512};
> struct async_req *reqs[3];
> int res[] = {0,1,0};
> -#ifdef DIO_TEST_DEV
> - /* can't pick event return state on real devices */
> int chk_state[] = {PATH_UP, PATH_UP, PATH_UP};
> -#else
> - int chk_state[] = {PATH_UP, PATH_DOWN, PATH_UP};
> -#endif
> +
> + /* can't pick event return state on real devices */
> + if (!test_dev)
> + chk_state[1] = PATH_DOWN;
>
> assert_true(list_empty(&aio_grp_list));
> will_return(__wrap_io_setup, 0);
> @@ -718,20 +716,38 @@ static void test_check_state_async(void **state)
>
> static int setup(void **state)
> {
> -#ifdef DIO_TEST_DEV
> - test_fd = open(DIO_TEST_DEV, O_RDONLY);
> - if (test_fd < 0)
> - fail_msg("cannot open %s: %m", DIO_TEST_DEV);
> -#endif
> + char *dl = getenv("DIO_TEST_DELAY");
> + test_dev = getenv("DIO_TEST_DEV");
> +
> + if (test_dev) {
> + condlog(2, "%s: opening %s", __func__, test_dev);
> + test_fd = open(test_dev, O_RDONLY);
> + if (dl) {
> + char *e;
> + long int d = strtol(dl, &e, 10);
> +
> + if (*e == '\0' && d >= 0 && (d * 1000) < (long)UINT_MAX)
> + test_delay = d * 1000;
> + else {
> + condlog(1, "DIO_TEST_DELAY=%s is invalid", dl);
> + return 1;
> + }
> + }
> + condlog(2, "%s: delay = %u us", __func__, test_delay / 1000);
> + }
> + if (test_fd < 0) {
> + fail_msg("cannot open %s: %m", test_dev);
> + return 1;
> + }
> return 0;
> }
>
> static int teardown(void **state)
> {
> -#ifdef DIO_TEST_DEV
> - assert_true(test_fd > 0);
> - assert_int_equal(close(test_fd), 0);
> -#endif
> + if (test_dev) {
> + assert_true(test_fd > 0);
> + assert_int_equal(close(test_fd), 0);
> + }
> return 0;
> }
>
> @@ -762,7 +778,7 @@ int main(void)
> {
> int ret = 0;
>
> - init_test_verbosity(5);
> + init_test_verbosity(2);
> ret += test_directio();
> return ret;
> }
> --
> 2.45.2
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 19/49] libmultipath: add libmp_mapinfo()
2024-07-15 22:41 ` Benjamin Marzinski
@ 2024-07-16 15:51 ` Martin Wilck
2024-07-16 20:19 ` Benjamin Marzinski
0 siblings, 1 reply; 69+ messages in thread
From: Martin Wilck @ 2024-07-16 15:51 UTC (permalink / raw)
To: Benjamin Marzinski; +Cc: Christophe Varoqui, dm-devel
On Mon, 2024-07-15 at 18:41 -0400, Benjamin Marzinski wrote:
> On Fri, Jul 12, 2024 at 07:14:27PM +0200, Martin Wilck wrote:
> > libmp_mapinfo() is intended as a generic abstraction for retrieving
> > information from
> > the kernel device-mapper driver. It retrieves the information that
> > the caller
> > needs, with a minimal set of DM ioctls, and never more then 2 ioctl
> > calls.
> >
> > libdm's DM_DEVICE_TABLE and DM_DEVICE_STATUS calls map to the
> > kernel's
> > DM_TABLE_STATUS ioctl, with or without the DM_STATUS_TABLE_FLAG
> > set,
> > respectively. DM_TABLE_STATUS always retrieves the basic map status
> > (struct
> > dm_info) and the map UUID and name, too.
> >
> > Note: I'd prefer to use an unnamed struct instead of _u in
> > union libmp_map_identifer. But doing using an unnamed struct and
> > and
> > initializing the union like this in a function argument:
> >
> > func((mapid_t) { .major = major, .minor = minor })
> >
> > is not part of C99, and not supported in gcc 4.8, which we still
> > support.
> >
> > Likewise, the following syntax for initializing an empty struct:
> >
> > (mapinfo_t) { 0 }
> >
> > is not supported on all architectures we support (notably clang 3.5
> > under
> > Debian Jessie).
> >
> > Signed-off-by: Martin Wilck <mwilck@suse.com>
> > ---
> > libmultipath/devmapper.c | 192
> > +++++++++++++++++++++++++++++-
> > libmultipath/devmapper.h | 70 +++++++++++
> > libmultipath/libmultipath.version | 3 +-
> > 3 files changed, 263 insertions(+), 2 deletions(-)
> >
> > diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> > index 3abdc26..4e6b5b2 100644
> > --- a/libmultipath/devmapper.c
> > +++ b/libmultipath/devmapper.c
> > @@ -14,7 +14,6 @@
> > #include <errno.h>
> > #include <syslog.h>
> > #include <sys/sysmacros.h>
> > -#include <linux/dm-ioctl.h>
> >
> > #include "util.h"
> > #include "vector.h"
> > @@ -604,6 +603,197 @@ has_dm_info(const struct multipath *mpp)
> > return (mpp && mpp->dmi.exists != 0);
> > }
> >
> > +static int libmp_set_map_identifier(int flags, mapid_t id, struct
> > dm_task *dmt)
> > +{
> > + switch (flags & __DM_MAP_BY_MASK) {
> > + case DM_MAP_BY_UUID:
> > + if (!id.str || !(*id.str))
> > + return 0;
> > + return dm_task_set_uuid(dmt, id.str);
> > + case DM_MAP_BY_NAME:
> > + if (!id.str || !(*id.str))
> > + return 0;
> > + return dm_task_set_name(dmt, id.str);
> > + case DM_MAP_BY_DEV:
> > + if (!dm_task_set_major(dmt, id._u.major))
> > + return 0;
> > + return dm_task_set_minor(dmt, id._u.minor);
> > + case DM_MAP_BY_DEVT:
> > + if (!dm_task_set_major(dmt, major(id.devt)))
> > + return 0;
> > + return dm_task_set_minor(dmt, minor(id.devt));
> > + default:
> > + condlog(0, "%s: invalid by_id", __func__);
> > + return 0;
> > + }
> > +}
> > +
> > +static int libmp_mapinfo__(int flags, mapid_t id, mapinfo_t info,
> > const char *map_id)
> > +{
> > + struct dm_task __attribute__((cleanup(cleanup_dm_task)))
> > *dmt = NULL;
> > + struct dm_info dmi;
> > + int rc, ioctl_nr;
> > + uint64_t start, length = 0;
> > + char *target_type = NULL, *params = NULL;
> > + const char *name = NULL, *uuid = NULL;
> > + char __attribute__((cleanup(cleanup_charp))) *tmp_target =
> > NULL;
> > + char __attribute__((cleanup(cleanup_charp))) *tmp_status =
> > NULL;
> > + bool tgt_set = false;
> > +
> > + /*
> > + * If both info.target and info.status are set, we need
> > two
> > + * ioctls. Call this function recursively.
> > + * If successful, tmp_target will be non-NULL.
> > + */
> > + if (info.target && info.status) {
> > + rc = libmp_mapinfo__(flags, id,
> > + (mapinfo_t) { .target =
> > &tmp_target },
> > + map_id);
> > + if (rc != DMP_OK)
> > + return rc;
> > + tgt_set = true;
> > + }
> > +
> > + /*
> > + * The DM_DEVICE_TABLE and DM_DEVICE_STATUS ioctls both
> > fetch the basic
> > + * information from DM_DEVICE_INFO, too.
> > + * Choose the most lightweight ioctl to fetch all
> > requested info.
> > + */
> > + if (info.target && !info.status)
> > + ioctl_nr = DM_DEVICE_TABLE;
> > + else if (info.status || info.size || flags &
> > __MAPINFO_TGT_TYPE)
> > + ioctl_nr = DM_DEVICE_STATUS;
> > + else
> > + ioctl_nr = DM_DEVICE_INFO;
> > +
> > + if (!(dmt = libmp_dm_task_create(ioctl_nr)))
> > + return DMP_ERR;
> > +
> > + if (!libmp_set_map_identifier(flags, id, dmt)) {
> > + condlog(2, "%s: failed to set map identifier to
> > %s", __func__, map_id);
> > + return DMP_ERR;
> > + }
> > +
> > + if (!libmp_dm_task_run(dmt)) {
> > + dm_log_error(3, ioctl_nr, dmt);
> > + if (dm_task_get_errno(dmt) == ENXIO) {
>
> I wonder if we should wrap ibmp_mapinfo in a macro that grabs the
> function name of the calling function and passes it down to
> libmp_mapinfo__() otherwise there will be a lot of messages like this
> or
>
> condlog(2, "%s: map %s doesn't exist", __func__, map_id);
>
> that use "libmp_mapinfo__" as the function, which isn't super useful.
Right. I think what I'll do is just hardcode "libmp_mapinfo" in these
messages instead of using __func__.
>
> > + condlog(2, "%s: map %s not found",
> > __func__, map_id);
> > + return DMP_NOT_FOUND;
> > + } else
> > + return DMP_ERR;
> > + }
> > +
> > + condlog(4, "%s: DM ioctl %d succeeded for %s",
> > + __func__, ioctl_nr, map_id);
> > +
> > + if (!dm_task_get_info(dmt, &dmi)) {
> > + condlog(2, "%s: dm_task_get_info() failed for %s
> > ", __func__, map_id);
> > + return DMP_ERR;
> > + } else if(!dmi.exists) {
> > + condlog(2, "%s: map %s doesn't exist", __func__,
> > map_id);
> > + return DMP_NOT_FOUND;
> > + }
> > +
> > + if (info.target || info.status || info.size || flags &
> > __MAPINFO_TGT_TYPE) {
> > + if (dm_get_next_target(dmt, NULL, &start, &length,
> > + &target_type, ¶ms) !=
> > NULL) {
> > + condlog(2, "%s: map %s has multiple
> > targets", __func__, map_id);
> > + return DMP_NOT_FOUND;
> > + }
> > + if (!params) {
> > + condlog(2, "%s: map %s has no targets",
> > __func__, map_id);
> > + return DMP_NOT_FOUND;
> > + }
> > + if (flags & __MAPINFO_TGT_TYPE) {
> > + const char *tgt_type = flags &
> > MAPINFO_MPATH_ONLY ? TGT_MPATH : TGT_PART;
> > +
> > + if (strcmp(target_type, tgt_type)) {
> > + condlog(3, "%s: target type
> > mismatch: \"%s\" != \"%s\"",
> > + __func__, tgt_type,
> > target_type);
> > + return DMP_NO_MATCH;
> > + }
> > + }
> > + }
> > +
> > + /*
> > + * Check possible error conditions.
> > + * If error is returned, don't touch any output
> > parameters.
> > + */
> > + if ((info.name && !(name = dm_task_get_name(dmt)))
> > + || (info.uuid && !(uuid = dm_task_get_uuid(dmt)))
> > + || (info.status && !(tmp_status = strdup(params)))
> > + || (info.target && !tmp_target && !(tmp_target =
> > strdup(params))))
> > + return DMP_ERR;
> > +
> > + if (info.name) {
> > + strlcpy(info.name, name, WWID_SIZE);
> > + condlog(4, "%s: %s: name: \"%s\"", __func__,
> > map_id, info.name);
> > + }
> > + if (info.uuid) {
> > + strlcpy(info.uuid, uuid, DM_UUID_LEN);
> > + condlog(4, "%s: %s: uuid: \"%s\"", __func__,
> > map_id, info.uuid);
> > + }
> > +
> > + if (info.size) {
> > + *info.size = length;
> > + condlog(4, "%s: %s: size: %lld", __func__, map_id,
> > *info.size);
> > + }
> > +
> > + if (info.dmi) {
> > + memcpy(info.dmi, &dmi, sizeof(*info.dmi));
> > + condlog(4, "%s: %s %d:%d, %d targets, %s table,
> > %s, %s, %d opened, %u events",
> > + __func__, map_id,
> > + info.dmi->major, info.dmi->minor,
> > + info.dmi->target_count,
> > + info.dmi->live_table ? "live" :
> > + info.dmi->inactive_table ?
> > "inactive" : "no",
> > + info.dmi->suspended ? "suspended" :
> > "active",
> > + info.dmi->read_only ? "ro" : "rw",
> > + info.dmi->open_count,
> > + info.dmi->event_nr);
> > + }
> > +
> > + if (info.target) {
> > + *info.target = steal_ptr(tmp_target);
> > + if (!tgt_set)
> > + condlog(4, "%s: %s: target: \"%s\"",
> > __func__, map_id, *info.target);
> > + }
> > +
> > + if (info.status) {
> > + *info.status = steal_ptr(tmp_status);
> > + condlog(4, "%s: %s: status: \"%s\"", __func__,
> > map_id, *info.status);
> > + }
> > +
> > + return DMP_OK;
> > +}
> > +
> > +/* Helper: format a string describing the map for log messages */
> > +static const char* libmp_map_identifier(int flags, mapid_t id,
> > char buf[BLK_DEV_SIZE])
> > +{
> > + switch (flags & __DM_MAP_BY_MASK) {
> > + case DM_MAP_BY_NAME:
> > + case DM_MAP_BY_UUID:
> > + return id.str;
> > + case DM_MAP_BY_DEV:
> > + safe_snprintf(buf, BLK_DEV_SIZE, "%d:%d",
> > id._u.major, id._u.minor);
> > + return buf;
> > + case DM_MAP_BY_DEVT:
> > + safe_snprintf(buf, BLK_DEV_SIZE, "%d:%d",
> > major(id.devt), minor(id.devt));
> > + return buf;
> > + default:
> > + safe_snprintf(buf, BLK_DEV_SIZE, "*invalid*");
> > + return buf;
> > + }
> > +}
> > +
> > +int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info)
> > +{
> > + char idbuf[BLK_DEV_SIZE];
> > +
> > + return libmp_mapinfo__(flags, id, info,
> > + libmp_map_identifier(flags, id,
> > idbuf));
> > +}
> > +
> > int
> > dm_get_info(const char *name, struct dm_info *info)
> > {
> > diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
> > index 9438c2d..725889b 100644
> > --- a/libmultipath/devmapper.h
> > +++ b/libmultipath/devmapper.h
> > @@ -1,5 +1,6 @@
> > #ifndef _DEVMAPPER_H
> > #define _DEVMAPPER_H
> > +#include <linux/dm-ioctl.h>
> > #include "autoconfig.h"
> > #include "structs.h"
> >
> > @@ -31,8 +32,77 @@ enum {
> > DMP_ERR,
> > DMP_OK,
> > DMP_NOT_FOUND,
> > + DMP_NO_MATCH,
> > };
> >
> > +/**
> > + * enum mapinfo_flags: input flags for libmp_mapinfo()
> > + */
> > +enum __mapinfo_flags {
> > + /** DM_MAP_BY_NAME: identify map by device-mapper name
> > from @name */
> > + DM_MAP_BY_NAME = 0,
> > + /** DM_MAP_BY_UUID: identify map by device-mapper UUID
> > from @uuid */
> > + DM_MAP_BY_UUID,
> > + /** DM_MAP_BY_DEV: identify map by major/minor number from
> > @dmi */
> > + DM_MAP_BY_DEV,
> > + /** DM_MAP_BY_DEVT: identify map by a dev_t */
> > + DM_MAP_BY_DEVT,
>
> I mentioned tihs before, but the DM_MAP_BY_* identifiers only take up
> 3
> bytes so __DM_MAP_BY_MASK can just be 3 or (1 << 2) - 1, unless you
> are
> reserving space for more identifiers which is fine but probably
> unnecessary, since libmultipath isn't a stable API. Or is there some
> other reason I'm missing.
Is it important that this bit field is "dense"? Indeed I wanted to
leave some space, even though your're right that it most probably won't
be necessary. I thought it might be helpful during debugging, for
example.
Perhaps I should have used the entire low byte for the map_by part.
That might even provide optimization opportunities for the compiler.
Unless you object, this is what I'll do.
>
> > + __DM_MAP_BY_MASK = (1 << 3) - 1,
> > + /* Fail if target type is not multipath */
> > + MAPINFO_MPATH_ONLY = (1 << 3),
> > + /* Fail if target type is not "partition" (linear) */
> > + MAPINFO_PART_ONLY = (1 << 4),
> > + __MAPINFO_TGT_TYPE = (MAPINFO_MPATH_ONLY |
> > MAPINFO_PART_ONLY),
> > +};
> > +
> > +typedef union libmp_map_identifier {
> > + const char *str;
> > + struct {
> > + int major;
> > + int minor;
> > + } _u;
> > + dev_t devt;
> > +} mapid_t;
> > +
> > +typedef struct libmp_map_info {
> > + /** @name: name of the map.
> > + * If non-NULL, it must point to an array of WWID_SIZE
> > bytes
> > + */
> > + char *name;
> > + /** @uuid: UUID of the map.
> > + * If non-NULL it must point to an array of DM_UUID_LEN
> > bytes
> > + */
> > + char *uuid;
> > + /** @dmi: Basic info, must point to a valid dm_info buffer
> > if non-NULL */
> > + struct dm_info *dmi;
> > + /** @target: target params, *@target will be allocated if
> > @target is non-NULL*/
> > + char **target;
> > + /** @size: target size. Will be ignored if @target is NULL
> > */
>
> AFAICT this isn't true. You can just request the device size, and
> libmp_mapinfo() will give you the size.
Right.
Thanks
Martin
>
> -Ben
>
> > + unsigned long long *size;
> > + /** @status: target status, *@status will be allocated if
> > @status is non-NULL */
> > + char **status;
> > +} mapinfo_t;
> > +
> > +/**
> > + * libmp_mapinfo(): obtain information about a map from the kernel
> > + * @param flags: see __mapinfo_flags above.
> > + * Exactly one of DM_MAP_BY_NAME, DM_MAP_BY_UUID, and
> > DM_MAP_BY_DEV must be set.
> > + * @param id: string or major/minor to identify the map to query
> > + * @param info: output parameters, see above. Non-NULL elements
> > will be filled in.
> > + * @returns:
> > + * DMP_OK if successful.
> > + * DMP_NOT_FOUND if the map wasn't found, or has no or
> > multiple targets.
> > + * DMP_NO_MATCH if the map didn't match @tgt_type (see above).
> > + * DMP_ERR if some other error occurred.
> > + *
> > + * This function obtains the requested information for the device-
> > mapper map
> > + * identified by the input parameters.
> > + * Output parameters are only filled in if the return value is
> > DMP_OK.
> > + * For target / status / size information, the map's table should
> > contain
> > + * only one target (usually multipath or linear).
> > + */
> > +int libmp_mapinfo(int flags, mapid_t id, mapinfo_t info);
> > +
> > int dm_prereq(unsigned int *v);
> > void skip_libmp_dm_init(void);
> > void libmp_dm_exit(void);
> > diff --git a/libmultipath/libmultipath.version
> > b/libmultipath/libmultipath.version
> > index f58cb1d..48c2b67 100644
> > --- a/libmultipath/libmultipath.version
> > +++ b/libmultipath/libmultipath.version
> > @@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 {
> > put_multipath_config;
> > };
> >
> > -LIBMULTIPATH_24.0.0 {
> > +LIBMULTIPATH_25.0.0 {
> > global:
> > /* symbols referenced by multipath and multipathd */
> > add_foreign;
> > @@ -134,6 +134,7 @@ global:
> > libmp_get_version;
> > libmp_get_multipath_config;
> > libmp_dm_task_run;
> > + libmp_mapinfo;
> > libmp_put_multipath_config;
> > libmp_udev_set_sync_support;
> > libmultipath_exit;
> > --
> > 2.45.2
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH v2 19/49] libmultipath: add libmp_mapinfo()
2024-07-16 15:51 ` Martin Wilck
@ 2024-07-16 20:19 ` Benjamin Marzinski
0 siblings, 0 replies; 69+ messages in thread
From: Benjamin Marzinski @ 2024-07-16 20:19 UTC (permalink / raw)
To: Martin Wilck; +Cc: Christophe Varoqui, dm-devel
On Tue, Jul 16, 2024 at 05:51:21PM +0200, Martin Wilck wrote:
> On Mon, 2024-07-15 at 18:41 -0400, Benjamin Marzinski wrote:
> > On Fri, Jul 12, 2024 at 07:14:27PM +0200, Martin Wilck wrote:
> > I wonder if we should wrap ibmp_mapinfo in a macro that grabs the
> > function name of the calling function and passes it down to
> > libmp_mapinfo__() otherwise there will be a lot of messages like this
> > or
> >
> > condlog(2, "%s: map %s doesn't exist", __func__, map_id);
> >
> > that use "libmp_mapinfo__" as the function, which isn't super useful.
>
> Right. I think what I'll do is just hardcode "libmp_mapinfo" in these
> messages instead of using __func__.
Actually, I was thinking more of something like:
int do_libmp_mapinfo(int flags, mapid_t id, mapinfo_t info,
const char *func)
{
char idbuf[BLK_DEV_SIZE];
return libmp_mapinfo__(flags, id, info,
libmp_map_identifier(flags, id, idbuf));
}
#define libmp_mapinfo(flags, id, info) \
do_libmp_mapinfo(flags, id, info, __func__)
So we would retain the caller info, but I don't feel that strongly about
it.
>
> >
> > > + condlog(2, "%s: map %s not found",
> > > __func__, map_id);
> > > + return DMP_NOT_FOUND;
> > > + } else
> > > + return DMP_ERR;
> > > + }
> > > +
> >
> > I mentioned tihs before, but the DM_MAP_BY_* identifiers only take up
> > 3
> > bytes so __DM_MAP_BY_MASK can just be 3 or (1 << 2) - 1, unless you
> > are
> > reserving space for more identifiers which is fine but probably
> > unnecessary, since libmultipath isn't a stable API. Or is there some
> > other reason I'm missing.
>
> Is it important that this bit field is "dense"? Indeed I wanted to
> leave some space, even though your're right that it most probably won't
> be necessary. I thought it might be helpful during debugging, for
> example.
>
> Perhaps I should have used the entire low byte for the map_by part.
> That might even provide optimization opportunities for the compiler.
> Unless you object, this is what I'll do.
That's fine. Like I said, it's not a stable API. If it turns out we
don't like it later, we can always change it then.
-Ben
^ permalink raw reply [flat|nested] 69+ messages in thread
end of thread, other threads:[~2024-07-16 20:19 UTC | newest]
Thread overview: 69+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-12 17:14 [PATCH v2 00/49] multipath-tools: devmapper API refactored Martin Wilck
2024-07-12 17:14 ` [PATCH v2 01/49] multipath-tools CI: more fixes for arm/v7 Martin Wilck
2024-07-12 17:14 ` [PATCH v2 02/49] multipath-tools CI: fix dmevents test for Debian Sid, arm/v7 Martin Wilck
2024-07-12 17:14 ` [PATCH v2 03/49] create-config.mk: use printf instead of /bin/echo Martin Wilck
2024-07-12 17:14 ` [PATCH v2 04/49] multipathd.service.in: use @BINDIR@ instead of /sbin Martin Wilck
2024-07-12 17:14 ` [PATCH v2 05/49] Makefile.inc: replace @BINDIR@ with $(TGTDIR)/$(bindir) Martin Wilck
2024-07-12 17:14 ` [PATCH v2 06/49] kpartx.rules: use @BINDIR@ to locate kpartx Martin Wilck
2024-07-15 22:08 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 07/49] multipath-tools: Remove hard-coded paths to executables Martin Wilck
2024-07-12 17:14 ` [PATCH v2 08/49] multipath-tools: compile_commands.json fixes Martin Wilck
2024-07-12 17:14 ` [PATCH v2 09/49] multipath-tools: .gitignore: ignore o.wrap files for CI helpers Martin Wilck
2024-07-12 17:14 ` [PATCH v2 10/49] libmultipath: remove unused includes in devmapper.h Martin Wilck
2024-07-12 17:14 ` [PATCH v2 11/49] libmultipath: use DM_DEVICE_INFO in dm_mapname() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 12/49] multipath-tools: don't call dm_task_no_open_count() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 13/49] libmpathutil: export cleanup_udev_device() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 14/49] libmpathutil: add cleanup_vector() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 15/49] libmultipath: add cleanup helpers for struct multipath Martin Wilck
2024-07-12 17:14 ` [PATCH v2 16/49] libmultipath: add cleanup_dm_task(), and use it in devmapper.c Martin Wilck
2024-07-15 22:13 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 17/49] libmultipath: rename dm_type()->dm_type_match() and use symbolic values Martin Wilck
2024-07-15 22:14 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 18/49] libmultipath: Use symbolic return values for dm_is_mpath() Martin Wilck
2024-07-15 22:14 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 19/49] libmultipath: add libmp_mapinfo() Martin Wilck
2024-07-15 22:41 ` Benjamin Marzinski
2024-07-16 15:51 ` Martin Wilck
2024-07-16 20:19 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 20/49] libmultipath tests: add tests for libmp_mapinfo() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 21/49] libmultipath: implement dm_get_info() and dm_map_present() with new API Martin Wilck
2024-07-12 17:14 ` [PATCH v2 22/49] libmultipath: remove dm_get_prefixed_uuid() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 23/49] libmultipath: is_mpath_part(): improve parsing Martin Wilck
2024-07-12 17:14 ` [PATCH v2 24/49] libmultipath: rename dm_get_uuid() -> dm_get_wwid() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 25/49] libmultipath: improve dm_get_wwid() return value logic Martin Wilck
2024-07-15 22:42 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 26/49] libmultipath: reimplement dm_map_name() with new API Martin Wilck
2024-07-15 22:42 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 27/49] libmultipath: reimplement dm_map_present_by_uuid() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 28/49] libmultipath: reimplement dm_get_opencount() with new API Martin Wilck
2024-07-12 17:14 ` [PATCH v2 29/49] libmpathpersist: skip redundant dm_map_present() call Martin Wilck
2024-07-12 17:14 ` [PATCH v2 30/49] libmultipath: implement dm_is_mpath() with new API Martin Wilck
2024-07-15 22:43 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 31/49] libmultipath: implement dm_get_multipath() " Martin Wilck
2024-07-12 17:14 ` [PATCH v2 32/49] libmultipath: use libmp_mapinfo() in _dm_flush_map() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 33/49] libmultipath: add is_mpath_uuid() helper Martin Wilck
2024-07-15 22:43 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 34/49] libmultipath: add is_mpath_part_uuid() helper Martin Wilck
2024-07-12 17:14 ` [PATCH v2 35/49] libmultipath: add dmp_errstr() helper Martin Wilck
2024-07-12 17:14 ` [PATCH v2 36/49] libmultipath: use libmp_mapinfo() in do_foreach_partmaps() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 37/49] libmultipath: use libmp_pathinfo() in update_multipath_table() Martin Wilck
2024-07-15 22:44 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 38/49] libmultipath: update mpp->dmi " Martin Wilck
2024-07-12 17:14 ` [PATCH v2 39/49] libmultipath: drop extra call to dm_map_present() in domap() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 40/49] libmultipath: split off update_multipath_table__() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 41/49] multipath: implement check_usable_paths() with libmp_pathinfo() Martin Wilck
2024-07-15 22:45 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 42/49] multipathd: implement add_map_without_path() with libmp_mapinfo() Martin Wilck
2024-07-15 22:47 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 43/49] libmultipath: simplify dm_get_maps() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 44/49] libmpathpersist: use libmp_mapinfo() in mpath_get_map() Martin Wilck
2024-07-15 22:48 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 45/49] libmpathpersist: use mpp->alias in do_mpath_persistent_reserve_out() Martin Wilck
2024-07-12 17:14 ` [PATCH v2 46/49] libmultipath: fix deferred_remove logic in remove_partmap() Martin Wilck
2024-07-15 22:49 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 47/49] libmultipath: don't call do_foreach_partmaps() recursively Martin Wilck
2024-07-15 22:51 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 48/49] libmultipath: Move UUID check into libmp_pathinfo__() Martin Wilck
2024-07-15 23:24 ` Benjamin Marzinski
2024-07-12 17:14 ` [PATCH v2 49/49] multipath-tools tests: fix directio test with real device Martin Wilck
2024-07-15 23:25 ` Benjamin Marzinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.