device-mapper-mulitpath-0.9.7-1
Update source to upstream version 0.9.7 * Previous patches 0001-0040 are included in the source tarball Rename redhat patches * Previous patches 0041-0053 are now patches 0001-0013 Remove /usr/lib/modules-load.d/multipath.conf * has been replaced with modprobe@dm_multipath.service unit Wants.
This commit is contained in:
		
							parent
							
								
									e5eddaae1a
								
							
						
					
					
						commit
						748e0a08b6
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -29,3 +29,4 @@ multipath-tools-091027.tar.gz | |||||||
| /multipath-tools-0.9.4.tgz | /multipath-tools-0.9.4.tgz | ||||||
| /multipath-tools-0.9.5.tgz | /multipath-tools-0.9.5.tgz | ||||||
| /multipath-tools-0.9.6.tgz | /multipath-tools-0.9.6.tgz | ||||||
|  | /multipath-tools-0.9.7.tgz | ||||||
|  | |||||||
| @ -9,27 +9,24 @@ different naming scheme for partitions than SuSE. | |||||||
| 
 | 
 | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | ||||||
| ---
 | ---
 | ||||||
|  Makefile.inc        | 4 ++-- |  Makefile.inc        | 2 +- | ||||||
|  kpartx/kpartx.rules | 2 +- |  kpartx/kpartx.rules | 2 +- | ||||||
|  multipath/Makefile  | 4 ++-- |  multipath/Makefile  | 4 ++-- | ||||||
|  3 files changed, 5 insertions(+), 5 deletions(-) |  3 files changed, 4 insertions(+), 4 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 | diff --git a/Makefile.inc b/Makefile.inc
 | ||||||
| index 04bfa56e..62d3d5cc 100644
 | index 6b454303..0b0e3ad2 100644
 | ||||||
| --- a/Makefile.inc
 | --- a/Makefile.inc
 | ||||||
| +++ b/Makefile.inc
 | +++ b/Makefile.inc
 | ||||||
| @@ -34,9 +34,9 @@ endif
 | @@ -34,7 +34,7 @@ endif
 | ||||||
|  # Paths. All these can be overridden on the "make" command line. |  # Paths. All these can be overridden on the "make" command line. | ||||||
|  prefix		:= |  prefix		:= | ||||||
|  # Prefix for binaries |  # Prefix for binaries | ||||||
| -exec_prefix	:= $(prefix)
 | -exec_prefix	:= $(prefix)
 | ||||||
| +exec_prefix	:= $(prefix)/usr
 | +exec_prefix	:= $(prefix)/usr
 | ||||||
|  # Prefix for non-essential libraries (libdmmp) |  # Prefix for non-essential libraries (libdmmp) | ||||||
| -usr_prefix	:= $(prefix)
 |  usr_prefix	:= $(if $(prefix),$(prefix),/usr) | ||||||
| +usr_prefix	:= $(prefix)/usr
 |  | ||||||
|  # Prefix for configfuration files (multipath.conf) |  # Prefix for configfuration files (multipath.conf) | ||||||
|  etc_prefix	:= $(prefix) |  | ||||||
|  # Where to install systemd-related files. systemd is usually installed under /usr |  | ||||||
| diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
 | diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
 | ||||||
| index 1969dee0..d2b28233 100644
 | index 1969dee0..d2b28233 100644
 | ||||||
| --- a/kpartx/kpartx.rules
 | --- a/kpartx/kpartx.rules
 | ||||||
| @ -43,7 +40,7 @@ index 1969dee0..d2b28233 100644 | |||||||
|   |   | ||||||
|  LABEL="kpartx_end" |  LABEL="kpartx_end" | ||||||
| diff --git a/multipath/Makefile b/multipath/Makefile
 | diff --git a/multipath/Makefile b/multipath/Makefile
 | ||||||
| index 68cb5ce7..f70e64ec 100644
 | index 0efb9b26..504d6892 100644
 | ||||||
| --- a/multipath/Makefile
 | --- a/multipath/Makefile
 | ||||||
| +++ b/multipath/Makefile
 | +++ b/multipath/Makefile
 | ||||||
| @@ -26,7 +26,7 @@ install:
 | @@ -26,7 +26,7 @@ install:
 | ||||||
| @ -52,10 +49,10 @@ index 68cb5ce7..f70e64ec 100644 | |||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) |  	$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) | ||||||
| -	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules
 | -	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules
 | ||||||
| +	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
 | +	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
 | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir) |  | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 modules-load.conf $(DESTDIR)$(modulesloaddir)/multipath.conf |  | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir) |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir) | ||||||
| @@ -46,7 +46,7 @@ uninstall:
 |  	$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf | ||||||
|  |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 | ||||||
|  | @@ -48,7 +48,7 @@ uninstall:
 | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules |  	$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf |  	$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf |  	$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf | ||||||
| @ -1,51 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 16:21:43 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: sysfs_set_scsi_tmo: do nothing for ACT_DRY_RUN |  | ||||||
| 
 |  | ||||||
| "multipath -d" might change sysfs timeouts of SCSI devices. |  | ||||||
| Make sure it doesn't. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Cc: Jehan Singh <jehan.singh@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/configure.c | 4 ++-- |  | ||||||
|  libmultipath/discovery.c | 3 +++ |  | ||||||
|  2 files changed, 5 insertions(+), 2 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/configure.c b/libmultipath/configure.c
 |  | ||||||
| index 9513baae..029fbbd2 100644
 |  | ||||||
| --- a/libmultipath/configure.c
 |  | ||||||
| +++ b/libmultipath/configure.c
 |  | ||||||
| @@ -1193,13 +1193,13 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
 |  | ||||||
|   |  | ||||||
|  		if (cmpp) |  | ||||||
|  			mpp->queue_mode = cmpp->queue_mode; |  | ||||||
| +		if (cmd == CMD_DRY_RUN && mpp->action == ACT_UNDEF)
 |  | ||||||
| +			mpp->action = ACT_DRY_RUN;
 |  | ||||||
|  		if (setup_map(mpp, ¶ms, vecs)) { |  | ||||||
|  			remove_map(mpp, vecs->pathvec, NULL); |  | ||||||
|  			continue; |  | ||||||
|  		} |  | ||||||
|   |  | ||||||
| -		if (cmd == CMD_DRY_RUN)
 |  | ||||||
| -			mpp->action = ACT_DRY_RUN;
 |  | ||||||
|  		if (mpp->action == ACT_UNDEF) |  | ||||||
|  			select_action(mpp, curmp, |  | ||||||
|  				      force_reload == FORCE_RELOAD_YES ? 1 : 0); |  | ||||||
| diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
 |  | ||||||
| index e4de48e7..84ce5fe7 100644
 |  | ||||||
| --- a/libmultipath/discovery.c
 |  | ||||||
| +++ b/libmultipath/discovery.c
 |  | ||||||
| @@ -857,6 +857,9 @@ sysfs_set_scsi_tmo (struct config *conf, struct multipath *mpp)
 |  | ||||||
|  	bool warn_dev_loss = false; |  | ||||||
|  	bool warn_fast_io_fail = false; |  | ||||||
|   |  | ||||||
| +	if (mpp->action == ACT_DRY_RUN || mpp->action == ACT_REJECT)
 |  | ||||||
| +		return 0;
 |  | ||||||
| +
 |  | ||||||
|  	if (mpp->no_path_retry > 0) { |  | ||||||
|  		uint64_t no_path_retry_tmo = |  | ||||||
|  			(uint64_t)mpp->no_path_retry * conf->checkint; |  | ||||||
| @ -42,10 +42,10 @@ index 75100b20..0b212078 100644 | |||||||
|  				udev_device_get_properties_list_entry(udev)) { |  				udev_device_get_properties_list_entry(udev)) { | ||||||
|   |   | ||||||
| diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
 | diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
 | ||||||
| index 226d0019..bae4168f 100644
 | index 683bdb72..87b3b2a5 100644
 | ||||||
| --- a/multipath/multipath.conf.5.in
 | --- a/multipath/multipath.conf.5.in
 | ||||||
| +++ b/multipath/multipath.conf.5.in
 | +++ b/multipath/multipath.conf.5.in
 | ||||||
| @@ -1402,9 +1402,14 @@ keywords. Both are regular expressions. For a full description of these keywords
 | @@ -1431,9 +1431,14 @@ keywords. Both are regular expressions. For a full description of these keywords
 | ||||||
|  Regular expression for an udev property. All |  Regular expression for an udev property. All | ||||||
|  devices that have matching udev properties will be excluded/included. |  devices that have matching udev properties will be excluded/included. | ||||||
|  The handling of the \fIproperty\fR keyword is special, |  The handling of the \fIproperty\fR keyword is special, | ||||||
| @ -61,7 +61,7 @@ index 226d0019..bae4168f 100644 | |||||||
|  . |  . | ||||||
|  .RS |  .RS | ||||||
|  .PP |  .PP | ||||||
| @@ -1415,10 +1420,6 @@ Blacklisting by missing properties is only applied to devices which do have the
 | @@ -1444,10 +1449,6 @@ Blacklisting by missing properties is only applied to devices which do have the
 | ||||||
|  property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) |  property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR) | ||||||
|  set. Previously, it was applied to every device, possibly causing devices to be |  set. Previously, it was applied to every device, possibly causing devices to be | ||||||
|  blacklisted because of temporary I/O error conditions. |  blacklisted because of temporary I/O error conditions. | ||||||
| @ -1,75 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 21:36:11 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: add alias_already_taken() |  | ||||||
| 
 |  | ||||||
| Factor out a trivial helper function. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 32 +++++++++++++++++++------------- |  | ||||||
|  1 file changed, 19 insertions(+), 13 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index c0139a2e..83ded886 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -8,6 +8,7 @@
 |  | ||||||
|  #include <string.h> |  | ||||||
|  #include <limits.h> |  | ||||||
|  #include <stdio.h> |  | ||||||
| +#include <stdbool.h>
 |  | ||||||
|   |  | ||||||
|  #include "debug.h" |  | ||||||
|  #include "util.h" |  | ||||||
| @@ -109,30 +110,35 @@ scan_devname(const char *alias, const char *prefix)
 |  | ||||||
|  	return n; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int
 |  | ||||||
| -id_already_taken(int id, const char *prefix, const char *map_wwid)
 |  | ||||||
| +static bool alias_already_taken(const char *alias, const char *map_wwid)
 |  | ||||||
|  { |  | ||||||
| -	STRBUF_ON_STACK(buf);
 |  | ||||||
| -	const char *alias;
 |  | ||||||
| -
 |  | ||||||
| -	if (append_strbuf_str(&buf, prefix) < 0 ||
 |  | ||||||
| -	    format_devname(&buf, id) < 0)
 |  | ||||||
| -		return 0;
 |  | ||||||
|   |  | ||||||
| -	alias = get_strbuf_str(&buf);
 |  | ||||||
|  	if (dm_map_present(alias)) { |  | ||||||
|  		char wwid[WWID_SIZE]; |  | ||||||
|   |  | ||||||
|  		/* If both the name and the wwid match, then it's fine.*/ |  | ||||||
|  		if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && |  | ||||||
|  		    strncmp(map_wwid, wwid, sizeof(wwid)) == 0) |  | ||||||
| -			return 0;
 |  | ||||||
| -		condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias", map_wwid, alias);
 |  | ||||||
| -		return 1;
 |  | ||||||
| +			return false;
 |  | ||||||
| +		condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias",
 |  | ||||||
| +			map_wwid, alias);
 |  | ||||||
| +		return true;
 |  | ||||||
|  	} |  | ||||||
| -	return 0;
 |  | ||||||
| +	return false;
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static bool id_already_taken(int id, const char *prefix, const char *map_wwid)
 |  | ||||||
| +{
 |  | ||||||
| +	STRBUF_ON_STACK(buf);
 |  | ||||||
| +	const char *alias;
 |  | ||||||
| +
 |  | ||||||
| +	if (append_strbuf_str(&buf, prefix) < 0 ||
 |  | ||||||
| +	    format_devname(&buf, id) < 0)
 |  | ||||||
| +		return false;
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_strbuf_str(&buf);
 |  | ||||||
| +	return alias_already_taken(alias, map_wwid);
 |  | ||||||
| +}
 |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
|   * Returns: 0   if matching entry in WWIDs file found |  | ||||||
| @ -12,13 +12,13 @@ simple way to disable multipath.  Simply removing or renaming | |||||||
| 
 | 
 | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | ||||||
| ---
 | ---
 | ||||||
|  libmultipath/config.c         | 13 +++++++++++++ |  libmultipath/config.c            | 13 +++++++++++++ | ||||||
|  libmultipath/config.h         |  1 + |  libmultipath/config.h            |  1 + | ||||||
|  multipath/main.c              |  6 ++++++ |  multipath/main.c                 |  6 ++++++ | ||||||
|  multipath/multipath.rules.in  |  1 + |  multipath/multipath.rules.in     |  1 + | ||||||
|  multipathd/multipathd.8.in    |  2 ++ |  multipathd/multipathd.8.in       |  2 ++ | ||||||
|  multipathd/multipathd.service |  1 + |  multipathd/multipathd.service.in |  1 + | ||||||
|  multipathd/multipathd.socket  |  1 + |  multipathd/multipathd.socket     |  1 + | ||||||
|  7 files changed, 25 insertions(+) |  7 files changed, 25 insertions(+) | ||||||
| 
 | 
 | ||||||
| diff --git a/libmultipath/config.c b/libmultipath/config.c
 | diff --git a/libmultipath/config.c b/libmultipath/config.c
 | ||||||
| @ -46,7 +46,7 @@ index b7dbc6f5..3a374b3d 100644 | |||||||
|   |   | ||||||
|  	conf->processed_main_config = 1; |  	conf->processed_main_config = 1; | ||||||
| diff --git a/libmultipath/config.h b/libmultipath/config.h
 | diff --git a/libmultipath/config.h b/libmultipath/config.h
 | ||||||
| index 8c22ce75..92f3a0df 100644
 | index 384193ab..158cebf0 100644
 | ||||||
| --- a/libmultipath/config.h
 | --- a/libmultipath/config.h
 | ||||||
| +++ b/libmultipath/config.h
 | +++ b/libmultipath/config.h
 | ||||||
| @@ -10,6 +10,7 @@
 | @@ -10,6 +10,7 @@
 | ||||||
| @ -111,12 +111,12 @@ index e98c27fd..fd2061e5 100644 | |||||||
|  . |  . | ||||||
|  . |  . | ||||||
|  .\" ---------------------------------------------------------------------------- |  .\" ---------------------------------------------------------------------------- | ||||||
| diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
 | diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
 | ||||||
| index 5a9cde12..311f49c7 100644
 | index 6d03ff71..0965d6f9 100644
 | ||||||
| --- a/multipathd/multipathd.service
 | --- a/multipathd/multipathd.service.in
 | ||||||
| +++ b/multipathd/multipathd.service
 | +++ b/multipathd/multipathd.service.in
 | ||||||
| @@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket
 | @@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket @MODPROBE_UNIT@
 | ||||||
|  After=systemd-udevd-kernel.socket |  After=systemd-udevd-kernel.socket @MODPROBE_UNIT@ | ||||||
|  After=multipathd.socket systemd-remount-fs.service |  After=multipathd.socket systemd-remount-fs.service | ||||||
|  Before=initrd-cleanup.service |  Before=initrd-cleanup.service | ||||||
| +ConditionPathExists=/etc/multipath.conf
 | +ConditionPathExists=/etc/multipath.conf
 | ||||||
| @ -1,207 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 22:00:58 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: unify use_existing_alias() and |  | ||||||
|  get_user_friendly_alias() |  | ||||||
| 
 |  | ||||||
| These functions are only called from select_alias(). The logic |  | ||||||
| is more obvious when unified in a single function. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c   | 82 ++++++++++++------------------------------ |  | ||||||
|  libmultipath/alias.h   |  9 ++--- |  | ||||||
|  libmultipath/propsel.c | 19 +++++----- |  | ||||||
|  3 files changed, 34 insertions(+), 76 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 83ded886..68f5d848 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -329,13 +329,13 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix)
 |  | ||||||
|  	return alias; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -char *
 |  | ||||||
| -use_existing_alias (const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
| -		    const char *prefix, int bindings_read_only)
 |  | ||||||
| +char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
| +			      const char *prefix, bool bindings_read_only)
 |  | ||||||
|  { |  | ||||||
|  	char *alias = NULL; |  | ||||||
|  	int id = 0; |  | ||||||
|  	int fd, can_write; |  | ||||||
| +	bool new_binding = false;
 |  | ||||||
|  	char buff[WWID_SIZE]; |  | ||||||
|  	FILE *f; |  | ||||||
|   |  | ||||||
| @@ -349,6 +349,10 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
|  		close(fd); |  | ||||||
|  		return NULL; |  | ||||||
|  	} |  | ||||||
| +
 |  | ||||||
| +	if (!strlen(alias_old))
 |  | ||||||
| +		goto new_alias;
 |  | ||||||
| +
 |  | ||||||
|  	/* lookup the binding. if it exists, the wwid will be in buff |  | ||||||
|  	 * either way, id contains the id for the alias |  | ||||||
|  	 */ |  | ||||||
| @@ -358,14 +362,14 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
|  		/* if buff is our wwid, it's already |  | ||||||
|  		 * allocated correctly |  | ||||||
|  		 */ |  | ||||||
| -		if (strcmp(buff, wwid) == 0)
 |  | ||||||
| +		if (strcmp(buff, wwid) == 0) {
 |  | ||||||
|  			alias = strdup(alias_old); |  | ||||||
| -		else {
 |  | ||||||
| -			alias = NULL;
 |  | ||||||
| +			goto out;
 |  | ||||||
| +		} else {
 |  | ||||||
|  			condlog(0, "alias %s already bound to wwid %s, cannot reuse", |  | ||||||
|  				alias_old, buff); |  | ||||||
| +			goto new_alias;
 |  | ||||||
|  		} |  | ||||||
| -		goto out;
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	id = lookup_binding(f, wwid, &alias, NULL, 0); |  | ||||||
| @@ -377,8 +381,15 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
|   |  | ||||||
|  	/* allocate the existing alias in the bindings file */ |  | ||||||
|  	id = scan_devname(alias_old, prefix); |  | ||||||
| -	if (id <= 0)
 |  | ||||||
| -		goto out;
 |  | ||||||
| +
 |  | ||||||
| +new_alias:
 |  | ||||||
| +	if (id <= 0) {
 |  | ||||||
| +		id = lookup_binding(f, wwid, &alias, prefix, 1);
 |  | ||||||
| +		if (id <= 0)
 |  | ||||||
| +			goto out;
 |  | ||||||
| +		else
 |  | ||||||
| +			new_binding = true;
 |  | ||||||
| +	}
 |  | ||||||
|   |  | ||||||
|  	if (fflush(f) != 0) { |  | ||||||
|  		condlog(0, "cannot fflush bindings file stream : %s", |  | ||||||
| @@ -388,8 +399,9 @@ use_existing_alias (const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
|   |  | ||||||
|  	if (can_write && !bindings_read_only) { |  | ||||||
|  		alias = allocate_binding(fd, wwid, id, prefix); |  | ||||||
| -		condlog(0, "Allocated existing binding [%s] for WWID [%s]",
 |  | ||||||
| -			alias, wwid);
 |  | ||||||
| +		if (alias && !new_binding)
 |  | ||||||
| +			condlog(2, "Allocated existing binding [%s] for WWID [%s]",
 |  | ||||||
| +				alias, wwid);
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  out: |  | ||||||
| @@ -399,54 +411,6 @@ out:
 |  | ||||||
|  	return alias; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -char *
 |  | ||||||
| -get_user_friendly_alias(const char *wwid, const char *file, const char *prefix,
 |  | ||||||
| -			int bindings_read_only)
 |  | ||||||
| -{
 |  | ||||||
| -	char *alias;
 |  | ||||||
| -	int fd, id;
 |  | ||||||
| -	FILE *f;
 |  | ||||||
| -	int can_write;
 |  | ||||||
| -
 |  | ||||||
| -	if (!wwid || *wwid == '\0') {
 |  | ||||||
| -		condlog(3, "Cannot find binding for empty WWID");
 |  | ||||||
| -		return NULL;
 |  | ||||||
| -	}
 |  | ||||||
| -
 |  | ||||||
| -	fd = open_file(file, &can_write, bindings_file_header);
 |  | ||||||
| -	if (fd < 0)
 |  | ||||||
| -		return NULL;
 |  | ||||||
| -
 |  | ||||||
| -	f = fdopen(fd, "r");
 |  | ||||||
| -	if (!f) {
 |  | ||||||
| -		condlog(0, "cannot fdopen on bindings file descriptor : %s",
 |  | ||||||
| -			strerror(errno));
 |  | ||||||
| -		close(fd);
 |  | ||||||
| -		return NULL;
 |  | ||||||
| -	}
 |  | ||||||
| -
 |  | ||||||
| -	id = lookup_binding(f, wwid, &alias, prefix, 1);
 |  | ||||||
| -	if (id < 0) {
 |  | ||||||
| -		fclose(f);
 |  | ||||||
| -		return NULL;
 |  | ||||||
| -	}
 |  | ||||||
| -
 |  | ||||||
| -	pthread_cleanup_push(free, alias);
 |  | ||||||
| -
 |  | ||||||
| -	if (fflush(f) != 0) {
 |  | ||||||
| -		condlog(0, "cannot fflush bindings file stream : %s",
 |  | ||||||
| -			strerror(errno));
 |  | ||||||
| -		free(alias);
 |  | ||||||
| -		alias = NULL;
 |  | ||||||
| -	} else if (can_write && !bindings_read_only && !alias)
 |  | ||||||
| -		alias = allocate_binding(fd, wwid, id, prefix);
 |  | ||||||
| -
 |  | ||||||
| -	fclose(f);
 |  | ||||||
| -
 |  | ||||||
| -	pthread_cleanup_pop(0);
 |  | ||||||
| -	return alias;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
|  int |  | ||||||
|  get_user_friendly_wwid(const char *alias, char *buff, const char *file) |  | ||||||
|  { |  | ||||||
| diff --git a/libmultipath/alias.h b/libmultipath/alias.h
 |  | ||||||
| index dbc950c4..fa332233 100644
 |  | ||||||
| --- a/libmultipath/alias.h
 |  | ||||||
| +++ b/libmultipath/alias.h
 |  | ||||||
| @@ -2,13 +2,10 @@
 |  | ||||||
|  #define _ALIAS_H |  | ||||||
|   |  | ||||||
|  int valid_alias(const char *alias); |  | ||||||
| -char *get_user_friendly_alias(const char *wwid, const char *file,
 |  | ||||||
| -			      const char *prefix,
 |  | ||||||
| -			      int bindings_readonly);
 |  | ||||||
|  int get_user_friendly_wwid(const char *alias, char *buff, const char *file); |  | ||||||
| -char *use_existing_alias (const char *wwid, const char *file,
 |  | ||||||
| -			  const char *alias_old,
 |  | ||||||
| -			  const char *prefix, int bindings_read_only);
 |  | ||||||
| +char *get_user_friendly_alias(const char *wwid, const char *file,
 |  | ||||||
| +			      const char *alias_old,
 |  | ||||||
| +			      const char *prefix, bool bindings_read_only);
 |  | ||||||
|   |  | ||||||
|  struct config; |  | ||||||
|  int check_alias_settings(const struct config *); |  | ||||||
| diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
 |  | ||||||
| index d6bce129..354e883f 100644
 |  | ||||||
| --- a/libmultipath/propsel.c
 |  | ||||||
| +++ b/libmultipath/propsel.c
 |  | ||||||
| @@ -401,19 +401,16 @@ int select_alias(struct config *conf, struct multipath * mp)
 |  | ||||||
|   |  | ||||||
|  	select_alias_prefix(conf, mp); |  | ||||||
|   |  | ||||||
| -	if (strlen(mp->alias_old) > 0) {
 |  | ||||||
| -		mp->alias = use_existing_alias(mp->wwid, conf->bindings_file,
 |  | ||||||
| -				mp->alias_old, mp->alias_prefix,
 |  | ||||||
| -				conf->bindings_read_only);
 |  | ||||||
| -		memset (mp->alias_old, 0, WWID_SIZE);
 |  | ||||||
| -		origin = "(setting: using existing alias)";
 |  | ||||||
| -	}
 |  | ||||||
| +	mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file,
 |  | ||||||
| +					    mp->alias_old, mp->alias_prefix,
 |  | ||||||
| +					    conf->bindings_read_only);
 |  | ||||||
|   |  | ||||||
| -	if (mp->alias == NULL) {
 |  | ||||||
| -		mp->alias = get_user_friendly_alias(mp->wwid,
 |  | ||||||
| -				conf->bindings_file, mp->alias_prefix, conf->bindings_read_only);
 |  | ||||||
| +	if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE))
 |  | ||||||
| +		origin = "(setting: using existing alias)";
 |  | ||||||
| +	else if (mp->alias)
 |  | ||||||
|  		origin = "(setting: user_friendly_name)"; |  | ||||||
| -	}
 |  | ||||||
| +	memset (mp->alias_old, 0, WWID_SIZE);
 |  | ||||||
| +
 |  | ||||||
|  out: |  | ||||||
|  	if (mp->alias == NULL) { |  | ||||||
|  		mp->alias = strdup(mp->wwid); |  | ||||||
| @ -1,101 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 22:23:29 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: never allocate an alias that's already taken |  | ||||||
| 
 |  | ||||||
| If the bindings file is changed in a way that multipathd can't handle |  | ||||||
| (e.g. by swapping the aliases of two maps), multipathd must not try |  | ||||||
| to re-use an alias that is already used by another map. Creating |  | ||||||
| or renaming a map with such an alias will fail. We already avoid |  | ||||||
| this for some cases, but not for all. Fix it. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Cc: David Bond <dbond@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 31 +++++++++++++++++++++++-------- |  | ||||||
|  tests/alias.c        |  2 +- |  | ||||||
|  2 files changed, 24 insertions(+), 9 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 68f5d848..3e3dfe98 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -120,7 +120,7 @@ static bool alias_already_taken(const char *alias, const char *map_wwid)
 |  | ||||||
|  		if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 && |  | ||||||
|  		    strncmp(map_wwid, wwid, sizeof(wwid)) == 0) |  | ||||||
|  			return false; |  | ||||||
| -		condlog(3, "%s: alias '%s' already taken, but not in bindings file. reselecting alias",
 |  | ||||||
| +		condlog(3, "%s: alias '%s' already taken, reselecting alias",
 |  | ||||||
|  			map_wwid, alias); |  | ||||||
|  		return true; |  | ||||||
|  	} |  | ||||||
| @@ -359,12 +359,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al
 |  | ||||||
|  	rlookup_binding(f, buff, alias_old); |  | ||||||
|   |  | ||||||
|  	if (strlen(buff) > 0) { |  | ||||||
| -		/* if buff is our wwid, it's already
 |  | ||||||
| -		 * allocated correctly
 |  | ||||||
| -		 */
 |  | ||||||
| +		/* If buff is our wwid, it's already allocated correctly. */
 |  | ||||||
|  		if (strcmp(buff, wwid) == 0) { |  | ||||||
|  			alias = strdup(alias_old); |  | ||||||
|  			goto out; |  | ||||||
| +
 |  | ||||||
|  		} else { |  | ||||||
|  			condlog(0, "alias %s already bound to wwid %s, cannot reuse", |  | ||||||
|  				alias_old, buff); |  | ||||||
| @@ -372,19 +371,35 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al
 |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	id = lookup_binding(f, wwid, &alias, NULL, 0);
 |  | ||||||
| +	/*
 |  | ||||||
| +	 * Look for an existing alias in the bindings file.
 |  | ||||||
| +	 * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id.
 |  | ||||||
| +	 */
 |  | ||||||
| +	lookup_binding(f, wwid, &alias, NULL, 0);
 |  | ||||||
|  	if (alias) { |  | ||||||
| -		condlog(3, "Use existing binding [%s] for WWID [%s]",
 |  | ||||||
| -			alias, wwid);
 |  | ||||||
| +		if (alias_already_taken(alias, wwid)) {
 |  | ||||||
| +			free(alias);
 |  | ||||||
| +			alias = NULL;
 |  | ||||||
| +		} else
 |  | ||||||
| +			condlog(3, "Use existing binding [%s] for WWID [%s]",
 |  | ||||||
| +				alias, wwid);
 |  | ||||||
|  		goto out; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	/* allocate the existing alias in the bindings file */
 |  | ||||||
| +	/* alias_old is already taken by our WWID, update bindings file. */
 |  | ||||||
|  	id = scan_devname(alias_old, prefix); |  | ||||||
|   |  | ||||||
|  new_alias: |  | ||||||
|  	if (id <= 0) { |  | ||||||
| +		/*
 |  | ||||||
| +		 * no existing alias was provided, or allocating it
 |  | ||||||
| +		 * failed. Try a new one.
 |  | ||||||
| +		 */
 |  | ||||||
|  		id = lookup_binding(f, wwid, &alias, prefix, 1); |  | ||||||
| +		if (id == 0 && alias_already_taken(alias, wwid)) {
 |  | ||||||
| +			free(alias);
 |  | ||||||
| +			alias = NULL;
 |  | ||||||
| +		}
 |  | ||||||
|  		if (id <= 0) |  | ||||||
|  			goto out; |  | ||||||
|  		else |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 3ca6c28b..11f209e0 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -398,7 +398,7 @@ static void mock_self_alias(const char *alias, const char *wwid)
 |  | ||||||
|  	will_return(__wrap_dm_get_uuid, wwid); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, but not in bindings file. reselecting alias\n"
 |  | ||||||
| +#define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n"
 |  | ||||||
|   |  | ||||||
|  static void mock_failed_alias(const char *alias, char *msg) |  | ||||||
|  { |  | ||||||
| @ -13,12 +13,12 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | |||||||
|  1 file changed, 17 insertions(+), 5 deletions(-) |  1 file changed, 17 insertions(+), 5 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 | diff --git a/Makefile.inc b/Makefile.inc
 | ||||||
| index 62d3d5cc..72fd8d57 100644
 | index 0b0e3ad2..3d80d224 100644
 | ||||||
| --- a/Makefile.inc
 | --- a/Makefile.inc
 | ||||||
| +++ b/Makefile.inc
 | +++ b/Makefile.inc
 | ||||||
| @@ -91,11 +91,23 @@ ORIG_LDFLAGS     := $(LDFLAGS)
 | @@ -95,11 +95,23 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo
 | ||||||
|  SYSTEMD_CPPFLAGS := $(if $(SYSTEMD),-DUSE_SYSTEMD=$(SYSTEMD)) |  MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \ | ||||||
|  SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo 1),-lsystemd,-lsystemd-daemon)) |  			echo "modprobe@dm_multipath.service") | ||||||
|   |   | ||||||
| -OPTFLAGS	:= -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
 | -OPTFLAGS	:= -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
 | ||||||
| -WARNFLAGS	:= -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
 | -WARNFLAGS	:= -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
 | ||||||
| @ -44,7 +44,7 @@ index 62d3d5cc..72fd8d57 100644 | |||||||
|  		   -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ |  		   -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ | ||||||
|  		   -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ |  		   -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ | ||||||
|  		   -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ |  		   -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ | ||||||
| @@ -104,7 +116,7 @@ CFLAGS		:= --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
 | @@ -108,7 +120,7 @@ CFLAGS		:= --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
 | ||||||
|  BIN_CFLAGS	:= -fPIE -DPIE |  BIN_CFLAGS	:= -fPIE -DPIE | ||||||
|  LIB_CFLAGS	:= -fPIC |  LIB_CFLAGS	:= -fPIC | ||||||
|  SHARED_FLAGS	:= -shared |  SHARED_FLAGS	:= -shared | ||||||
| @ -1,61 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 22:30:16 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: lookup_binding: add comment about the algorithm |  | ||||||
| 
 |  | ||||||
| When I read this code, I always get confused. Adding comments to |  | ||||||
| explain the algorithm. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 35 +++++++++++++++++++++++++++++++++++ |  | ||||||
|  1 file changed, 35 insertions(+) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 3e3dfe98..9e9ac563 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -172,6 +172,41 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
 |  | ||||||
|  		alias = strtok_r(buf, " \t", &saveptr); |  | ||||||
|  		if (!alias) /* blank line */ |  | ||||||
|  			continue; |  | ||||||
| +
 |  | ||||||
| +		/*
 |  | ||||||
| +		 * Find an unused index - explanation of the algorithm
 |  | ||||||
| +		 *
 |  | ||||||
| +		 * ID: 1 = mpatha, 2 = mpathb, ...
 |  | ||||||
| +		 *
 |  | ||||||
| +		 * We assume the bindings are unsorted. The only constraint
 |  | ||||||
| +		 * is that no ID occurs more than once. IDs that occur in the
 |  | ||||||
| +		 * bindings are called "used".
 |  | ||||||
| +		 *
 |  | ||||||
| +		 * We call the list 1,2,3,..., exactly in this order, the list
 |  | ||||||
| +		 * of "expected" IDs. The variable "id" always holds the next
 |  | ||||||
| +		 * "expected" ID, IOW the last "expected" ID encountered plus 1.
 |  | ||||||
| +		 * Thus all IDs below "id" are known to be used. However, at the
 |  | ||||||
| +		 * end of the loop, the value of "id" isn't necessarily unused.
 |  | ||||||
| +		 *
 |  | ||||||
| +		 * "smallest_bigger_id" is the smallest used ID that was
 |  | ||||||
| +		 * encountered while it was larger than the next "expected" ID
 |  | ||||||
| +		 * at that iteration. Let X be some used ID. If all IDs below X
 |  | ||||||
| +		 * are used and encountered in the right sequence before X, "id"
 |  | ||||||
| +		 * will be > X when the loop ends. Otherwise, X was encountered
 |  | ||||||
| +		 * "out of order", the condition (X > id) holds when X is
 |  | ||||||
| +		 * encountered, and "smallest_bigger_id" will be set to X; i.e.
 |  | ||||||
| +		 * it will be less or equal than X when the loop ends.
 |  | ||||||
| +		 *
 |  | ||||||
| +		 * At the end of the loop, (id < smallest_bigger_id) means that
 |  | ||||||
| +		 * the value of "id" had been encountered neither in order nor
 |  | ||||||
| +		 * out of order, and is thus unused. (id >= smallest_bigger_id)
 |  | ||||||
| +		 * means that "id"'s value is in use. In this case, we play safe
 |  | ||||||
| +		 * and use "biggest_id + 1" as the next value to try.
 |  | ||||||
| +		 *
 |  | ||||||
| +		 * biggest_id is always > smallest_bigger_id, except in the
 |  | ||||||
| +		 * "perfectly ordered" case.
 |  | ||||||
| +		 */
 |  | ||||||
| +
 |  | ||||||
|  		curr_id = scan_devname(alias, prefix); |  | ||||||
|  		if (curr_id == id) { |  | ||||||
|  			if (id < INT_MAX) |  | ||||||
| @ -34,7 +34,7 @@ index 3a374b3d..4544f484 100644 | |||||||
|  			conf->blist_devnode = vector_alloc(); |  			conf->blist_devnode = vector_alloc(); | ||||||
|  			if (!conf->blist_devnode) { |  			if (!conf->blist_devnode) { | ||||||
| diff --git a/multipath/Makefile b/multipath/Makefile
 | diff --git a/multipath/Makefile b/multipath/Makefile
 | ||||||
| index f70e64ec..9942d1a9 100644
 | index 504d6892..9f14036c 100644
 | ||||||
| --- a/multipath/Makefile
 | --- a/multipath/Makefile
 | ||||||
| +++ b/multipath/Makefile
 | +++ b/multipath/Makefile
 | ||||||
| @@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
 | @@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
 | ||||||
| @ -45,15 +45,15 @@ index f70e64ec..9942d1a9 100644 | |||||||
|  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) |  	$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules |  	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules | ||||||
| @@ -33,6 +34,7 @@ install:
 | @@ -31,6 +32,7 @@ install:
 | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf |  	$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8 | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 |  	$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 | ||||||
| +	$(Q)$(INSTALL_PROGRAM) -m 644 mpathconf.8 $(DESTDIR)$(mandir)/man8
 | +	$(Q)$(INSTALL_PROGRAM) -m 644 mpathconf.8 $(DESTDIR)$(mandir)/man8
 | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5 |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5 | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5 |  	$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5 | ||||||
|  ifneq ($(SCSI_DH_MODULES_PRELOAD),) |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir) | ||||||
| @@ -43,11 +45,13 @@ endif
 | @@ -45,11 +47,13 @@ endif
 | ||||||
|   |   | ||||||
|  uninstall: |  uninstall: | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) |  	$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) | ||||||
| @ -1,35 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Wed, 23 Aug 2023 22:56:41 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools test: simplify debugging for condlog mismatch |  | ||||||
| 
 |  | ||||||
| If there's a mismatch between expected and actual log message, |  | ||||||
| print both messages. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/test-log.c | 4 +++- |  | ||||||
|  1 file changed, 3 insertions(+), 1 deletion(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/test-log.c b/tests/test-log.c
 |  | ||||||
| index c1745872..63516999 100644
 |  | ||||||
| --- a/tests/test-log.c
 |  | ||||||
| +++ b/tests/test-log.c
 |  | ||||||
| @@ -16,12 +16,14 @@ void __wrap_dlog (int prio, const char * fmt, ...)
 |  | ||||||
|  	va_list ap; |  | ||||||
|  	char *expected; |  | ||||||
|   |  | ||||||
| -	check_expected(prio);
 |  | ||||||
|  	va_start(ap, fmt); |  | ||||||
|  	vsnprintf(buff, MAX_MSG_SIZE, fmt, ap); |  | ||||||
|  	va_end(ap); |  | ||||||
|  	fprintf(stderr, "%s(%d): %s", __func__, prio, buff); |  | ||||||
|  	expected = mock_ptr_type(char *); |  | ||||||
| +	if (memcmp(expected, buff, strlen(expected)))
 |  | ||||||
| +		fprintf(stderr, "%s(expected): %s", __func__, expected);
 |  | ||||||
| +	check_expected(prio);
 |  | ||||||
|  	assert_memory_equal(buff, expected, strlen(expected)); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @ -14,9 +14,9 @@ multipathd.service | |||||||
| 
 | 
 | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | ||||||
| ---
 | ---
 | ||||||
|  multipath/main.c              | 54 +++++++++++++++++++++++++++++++++-- |  multipath/main.c                 | 54 ++++++++++++++++++++++++++++++-- | ||||||
|  multipath/multipath.8.in      |  7 ++++- |  multipath/multipath.8.in         |  7 ++++- | ||||||
|  multipathd/multipathd.service |  1 + |  multipathd/multipathd.service.in |  1 + | ||||||
|  3 files changed, 59 insertions(+), 3 deletions(-) |  3 files changed, 59 insertions(+), 3 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/multipath/main.c b/multipath/main.c
 | diff --git a/multipath/main.c b/multipath/main.c
 | ||||||
| @ -137,10 +137,10 @@ index 348eb220..82a7e68e 100644 | |||||||
|  .B \-w |  .B \-w | ||||||
|  Remove the WWID for the specified device from the WWIDs file. |  Remove the WWID for the specified device from the WWIDs file. | ||||||
|  . |  . | ||||||
| diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
 | diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
 | ||||||
| index 311f49c7..5324f4bc 100644
 | index 0965d6f9..c964eb1b 100644
 | ||||||
| --- a/multipathd/multipathd.service
 | --- a/multipathd/multipathd.service.in
 | ||||||
| +++ b/multipathd/multipathd.service
 | +++ b/multipathd/multipathd.service.in
 | ||||||
| @@ -17,6 +17,7 @@ ConditionVirtualization=!container
 | @@ -17,6 +17,7 @@ ConditionVirtualization=!container
 | ||||||
|  [Service] |  [Service] | ||||||
|  Type=notify |  Type=notify | ||||||
| @ -1,493 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Wed, 23 Aug 2023 22:57:29 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools tests: add tests for |  | ||||||
|  get_user_friendly_alias() |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 441 ++++++++++++++++++++++++++++++++++++++++++++++++++ |  | ||||||
|  1 file changed, 441 insertions(+) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 11f209e0..7e443b06 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -81,6 +81,35 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
 |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#define TEST_FDNO 1234
 |  | ||||||
| +#define TEST_FPTR ((FILE *) 0xaffe)
 |  | ||||||
| +
 |  | ||||||
| +int __wrap_open_file(const char *file, int *can_write, const char *header)
 |  | ||||||
| +{
 |  | ||||||
| +	int cw = mock_type(int);
 |  | ||||||
| +
 |  | ||||||
| +        *can_write = cw;
 |  | ||||||
| +	return TEST_FDNO;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +FILE *__wrap_fdopen(int fd, const char *mode)
 |  | ||||||
| +{
 |  | ||||||
| +	assert_int_equal(fd, TEST_FDNO);
 |  | ||||||
| +	return TEST_FPTR;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +int __wrap_fflush(FILE *f)
 |  | ||||||
| +{
 |  | ||||||
| +	assert_ptr_equal(f, TEST_FPTR);
 |  | ||||||
| +	return 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +int __wrap_fclose(FILE *f)
 |  | ||||||
| +{
 |  | ||||||
| +	assert_ptr_equal(f, TEST_FPTR);
 |  | ||||||
| +	return 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  /* strbuf wrapper for the old format_devname() */ |  | ||||||
|  static int __format_devname(char *name, int id, size_t len, const char *prefix) |  | ||||||
|  { |  | ||||||
| @@ -399,6 +428,22 @@ static void mock_self_alias(const char *alias, const char *wwid)
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  #define USED_STR(alias_str, wwid_str) wwid_str ": alias '" alias_str "' already taken, reselecting alias\n" |  | ||||||
| +#define NOMATCH_STR(alias_str) ("No matching alias [" alias_str "] in bindings file.\n")
 |  | ||||||
| +#define FOUND_STR(alias_str, wwid_str)				\
 |  | ||||||
| +	"Found matching wwid [" wwid_str "] in bindings file."	\
 |  | ||||||
| +	" Setting alias to " alias_str "\n"
 |  | ||||||
| +#define FOUND_ALIAS_STR(alias_str, wwid_str)				\
 |  | ||||||
| +	"Found matching alias [" alias_str "] in bindings file."	\
 |  | ||||||
| +	" Setting wwid to " wwid_str "\n"
 |  | ||||||
| +#define NOMATCH_WWID_STR(wwid_str) ("No matching wwid [" wwid_str "] in bindings file.\n")
 |  | ||||||
| +#define NEW_STR(alias_str, wwid_str) ("Created new binding [" alias_str "] for WWID [" wwid_str "]\n")
 |  | ||||||
| +#define EXISTING_STR(alias_str, wwid_str) ("Use existing binding [" alias_str "] for WWID [" wwid_str "]\n")
 |  | ||||||
| +#define ALLOC_STR(alias_str, wwid_str) ("Allocated existing binding [" alias_str "] for WWID [" wwid_str "]\n")
 |  | ||||||
| +#define BINDING_STR(alias_str, wwid_str) (alias_str " " wwid_str "\n")
 |  | ||||||
| +#define BOUND_STR(alias_str, wwid_str) ("alias "alias_str " already bound to wwid " wwid_str ", cannot reuse")
 |  | ||||||
| +#define ERR_STR(alias_str, wwid_str) ("ERROR: old alias [" alias_str "] for wwid [" wwid_str "] is used by other map\n")
 |  | ||||||
| +#define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n")
 |  | ||||||
| +#define NOMORE_STR "no more available user_friendly_names\n"
 |  | ||||||
|   |  | ||||||
|  static void mock_failed_alias(const char *alias, char *msg) |  | ||||||
|  { |  | ||||||
| @@ -421,6 +466,24 @@ static void mock_used_alias(const char *alias, char *msg)
 |  | ||||||
|  	expect_condlog(3, msg); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static void mock_bindings_file(const char *content, int match_line)
 |  | ||||||
| +{
 |  | ||||||
| +	static char cnt[1024];
 |  | ||||||
| +	char *token;
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1);
 |  | ||||||
| +
 |  | ||||||
| +	for (token = strtok(cnt, "\n"), i = 0;
 |  | ||||||
| +	     token && *token;
 |  | ||||||
| +	     token = strtok(NULL, "\n"), i++) {
 |  | ||||||
| +		will_return(__wrap_fgets, token);
 |  | ||||||
| +		if (match_line == i)
 |  | ||||||
| +			return;
 |  | ||||||
| +	}
 |  | ||||||
| +	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static void lb_empty(void **state) |  | ||||||
|  { |  | ||||||
|  	int rc; |  | ||||||
| @@ -1147,6 +1210,382 @@ static int test_allocate_binding(void)
 |  | ||||||
|  	return cmocka_run_group_tests(tests, NULL, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#define mock_allocate_binding(alias, wwid)				\
 |  | ||||||
| +	do {								\
 |  | ||||||
| +		static const char ln[] = BINDING_STR(alias, wwid);	\
 |  | ||||||
| +									\
 |  | ||||||
| +		will_return(__wrap_lseek, 0);				\
 |  | ||||||
| +		expect_value(__wrap_write, count, strlen(ln));		\
 |  | ||||||
| +		expect_string(__wrap_write, buf, ln);			\
 |  | ||||||
| +		will_return(__wrap_write, strlen(ln));			\
 |  | ||||||
| +		expect_condlog(3, NEW_STR(alias, wwid));		\
 |  | ||||||
| +	} while (0)
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_empty_new_rw(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHa", "WWID0");
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHa");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_empty_new_ro_1(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, false);
 |  | ||||||
| +	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_ptr_equal(alias, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_empty_new_ro_2(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	assert_ptr_equal(alias, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_match_a_unused(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHa");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_match_a_self(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_self_alias("MPATHa", "WWID0");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHa");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_match_a_used(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	assert_ptr_equal(alias, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_nomatch_a_c(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHc WWID2",
 |  | ||||||
| +			   -1);
 |  | ||||||
| +	mock_unused_alias("MPATHb");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHb", "WWID1");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHb");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_nomatch_c_a(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file("MPATHc WWID2\n"
 |  | ||||||
| +			   "MPATHa WWID0",
 |  | ||||||
| +			   -1);
 |  | ||||||
| +	mock_unused_alias("MPATHb");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHb", "WWID1");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHb");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_nomatch_c_b(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file("MPATHc WWID2\n"
 |  | ||||||
| +			   "MPATHb WWID1\n",
 |  | ||||||
| +			   -1);
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHa", "WWID0");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHa");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_nomatch_c_b_used(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file("MPATHc WWID2\n"
 |  | ||||||
| +			   "MPATHb WWID1",
 |  | ||||||
| +			   -1);
 |  | ||||||
| +	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4"));
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID4"));
 |  | ||||||
| +	mock_unused_alias("MPATHd");
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHd", "WWID4");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHd");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_nomatch_b_f_a(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATHf WWID6\n"
 |  | ||||||
| +			   "MPATHa WWID0\n",
 |  | ||||||
| +			   -1);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID7"));
 |  | ||||||
| +	mock_unused_alias("MPATHg");
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHg", "WWID7");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHg");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_empty(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	/* rlookup_binding for ALIAS */
 |  | ||||||
| +	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHz"));
 |  | ||||||
| +
 |  | ||||||
| +	/* lookup_binding */
 |  | ||||||
| +	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHz", "WWID0");
 |  | ||||||
| +	expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHz");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_match(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATHz WWID0",
 |  | ||||||
| +			   1);
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHz");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_match_other(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = "MPATHz WWID9";
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 0);
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
 |  | ||||||
| +	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, -1);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHa", "WWID0");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHa");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_match_other_used(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = "MPATHz WWID9";
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 0);
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
 |  | ||||||
| +	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, -1);
 |  | ||||||
| +	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +	mock_unused_alias("MPATHb");
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHb", "WWID0");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHb");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_match_other_wwidmatch(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = ("MPATHz WWID9\n"
 |  | ||||||
| +					"MPATHc WWID2");
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 0);
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
 |  | ||||||
| +	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 1);
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
 |  | ||||||
| +	mock_unused_alias("MPATHc");
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHc");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_match_other_wwidmatch_used(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = ("MPATHz WWID9\n"
 |  | ||||||
| +					"MPATHc WWID2");
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 0);
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
 |  | ||||||
| +	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 1);
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_ptr_equal(alias, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_nomatch_wwidmatch(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = "MPATHa WWID0";
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, -1);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHz"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 0);
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_unused_alias("MPATHa");
 |  | ||||||
| +	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHa");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_nomatch_wwidmatch_used(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = "MPATHa WWID0";
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, -1);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHz"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, 0);
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_ptr_equal(alias, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void gufa_old_nomatch_nowwidmatch(void **state) {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	static const char bindings[] = "MPATHb WWID1";
 |  | ||||||
| +
 |  | ||||||
| +	will_return(__wrap_open_file, true);
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, -1);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHz"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_bindings_file(bindings, -1);
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	mock_allocate_binding("MPATHz", "WWID0");
 |  | ||||||
| +	expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
 |  | ||||||
| +
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	assert_string_equal(alias, "MPATHz");
 |  | ||||||
| +	free(alias);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static int test_get_user_friendly_alias()
 |  | ||||||
| +{
 |  | ||||||
| +	const struct CMUnitTest tests[] = {
 |  | ||||||
| +		cmocka_unit_test(gufa_empty_new_rw),
 |  | ||||||
| +		cmocka_unit_test(gufa_empty_new_ro_1),
 |  | ||||||
| +		cmocka_unit_test(gufa_empty_new_ro_2),
 |  | ||||||
| +		cmocka_unit_test(gufa_match_a_unused),
 |  | ||||||
| +		cmocka_unit_test(gufa_match_a_self),
 |  | ||||||
| +		cmocka_unit_test(gufa_match_a_used),
 |  | ||||||
| +		cmocka_unit_test(gufa_nomatch_a_c),
 |  | ||||||
| +		cmocka_unit_test(gufa_nomatch_c_a),
 |  | ||||||
| +		cmocka_unit_test(gufa_nomatch_c_b),
 |  | ||||||
| +		cmocka_unit_test(gufa_nomatch_c_b_used),
 |  | ||||||
| +		cmocka_unit_test(gufa_nomatch_b_f_a),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_empty),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_match),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_match_other),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_match_other_used),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_match_other_wwidmatch),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_match_other_wwidmatch_used),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_nomatch_wwidmatch),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_nomatch_wwidmatch_used),
 |  | ||||||
| +		cmocka_unit_test(gufa_old_nomatch_nowwidmatch),
 |  | ||||||
| +	};
 |  | ||||||
| +
 |  | ||||||
| +	return cmocka_run_group_tests(tests, NULL, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  int main(void) |  | ||||||
|  { |  | ||||||
|  	int ret = 0; |  | ||||||
| @@ -1157,6 +1596,8 @@ int main(void)
 |  | ||||||
|  	ret += test_lookup_binding(); |  | ||||||
|  	ret += test_rlookup_binding(); |  | ||||||
|  	ret += test_allocate_binding(); |  | ||||||
| +	ret += test_allocate_binding();
 |  | ||||||
| +	ret += test_get_user_friendly_alias();
 |  | ||||||
|   |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| @ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | |||||||
|  1 file changed, 1 insertion(+), 1 deletion(-) |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
 | diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
 | ||||||
| index d01f9712..ee2e13a9 100644
 | index 64b633f2..5bda9f93 100644
 | ||||||
| --- a/libmultipath/defaults.h
 | --- a/libmultipath/defaults.h
 | ||||||
| +++ b/libmultipath/defaults.h
 | +++ b/libmultipath/defaults.h
 | ||||||
| @@ -23,7 +23,7 @@
 | @@ -23,7 +23,7 @@
 | ||||||
| @ -1,365 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 10:40:32 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools test: consistent use of macros in alias test |  | ||||||
| 
 |  | ||||||
| Use the macros introduced with the tests for get_user_friendly_alias() |  | ||||||
| also in the previously existing tests. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 80 ++++++++++++++++++++++++--------------------------- |  | ||||||
|  1 file changed, 38 insertions(+), 42 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 7e443b06..427b2814 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -490,7 +490,7 @@ static void lb_empty(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); |  | ||||||
|  	assert_int_equal(rc, 1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -503,7 +503,7 @@ static void lb_empty_unused(void **state)
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -518,7 +518,7 @@ static void lb_empty_failed(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -533,7 +533,7 @@ static void lb_empty_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -548,7 +548,7 @@ static void lb_empty_1_used_self(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_self_alias("MPATHb", "WWID0"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID0] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -561,8 +561,7 @@ static void lb_match_a(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
| -	expect_condlog(3, "Found matching wwid [WWID0] in bindings file."
 |  | ||||||
| -		       " Setting alias to MPATHa\n");
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
| @@ -577,7 +576,7 @@ static void lb_nomatch_a(void **state)
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -590,7 +589,7 @@ static void lb_nomatch_a_bad_check(void **state)
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(0, "no more available user_friendly_names\n");
 |  | ||||||
| +	expect_condlog(0, NOMORE_STR);
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -604,7 +603,7 @@ static void lb_nomatch_a_unused(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -622,7 +621,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
 |  | ||||||
|  	mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1")); |  | ||||||
|  	mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1")); |  | ||||||
|  	mock_self_alias("MPATHf", "WWID1"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID1] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 6); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -635,8 +634,7 @@ static void do_lb_match_c(void **state, int check_if_taken)
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHc WWID1\n"); |  | ||||||
| -	expect_condlog(3, "Found matching wwid [WWID1] in bindings file."
 |  | ||||||
| -		       " Setting alias to MPATHc\n");
 |  | ||||||
| +	expect_condlog(3, FOUND_STR("MPATHc", "WWID1"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
| @@ -662,7 +660,7 @@ static void lb_nomatch_a_c(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHc WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -677,7 +675,7 @@ static void lb_nomatch_a_d_unused(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHd WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -693,7 +691,7 @@ static void lb_nomatch_a_d_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); |  | ||||||
|  	mock_unused_alias("MPATHc"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 3); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -710,7 +708,7 @@ static void lb_nomatch_a_d_2_used(void **state)
 |  | ||||||
|  	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); |  | ||||||
|  	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); |  | ||||||
|  	mock_unused_alias("MPATHe"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 5); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -728,7 +726,7 @@ static void lb_nomatch_a_d_3_used(void **state)
 |  | ||||||
|  	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2")); |  | ||||||
|  	mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2")); |  | ||||||
|  	mock_unused_alias("MPATHf"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 6); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -742,7 +740,7 @@ static void lb_nomatch_c_a(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHc WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -758,7 +756,7 @@ static void lb_nomatch_d_a_unused(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHd WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -775,7 +773,7 @@ static void lb_nomatch_d_a_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2")); |  | ||||||
|  	mock_unused_alias("MPATHe"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 5); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -790,7 +788,7 @@ static void lb_nomatch_a_b(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHz WWID26\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHb WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 3); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -806,7 +804,7 @@ static void lb_nomatch_a_b_bad(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHb\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 3); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -823,7 +821,7 @@ static void lb_nomatch_a_b_bad_self(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); |  | ||||||
|  	mock_self_alias("MPATHc", "WWID2"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 3); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -838,7 +836,7 @@ static void lb_nomatch_b_a(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHz WWID26\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 27); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -857,7 +855,7 @@ static void lb_nomatch_b_a_3_used(void **state)
 |  | ||||||
|  	mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2")); |  | ||||||
|  	mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2")); |  | ||||||
|  	mock_unused_alias("MPATHad"); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, 30); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -873,7 +871,7 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(0, "no more available user_friendly_names\n");
 |  | ||||||
| +	expect_condlog(0, NOMORE_STR);
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -898,7 +896,7 @@ static void lb_nomatch_int_max_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); |  | ||||||
| -	expect_condlog(0, "no more available user_friendly_names\n");
 |  | ||||||
| +	expect_condlog(0, NOMORE_STR);
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -913,7 +911,7 @@ static void lb_nomatch_int_max_m1(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, INT_MAX); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -929,7 +927,7 @@ static void lb_nomatch_int_max_m1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); |  | ||||||
| -	expect_condlog(0, "no more available user_friendly_names\n");
 |  | ||||||
| +	expect_condlog(0, NOMORE_STR);
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -945,7 +943,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); |  | ||||||
|  	mock_unused_alias("MPATH" MPATH_ID_INT_MAX); |  | ||||||
| -	expect_condlog(3, "No matching wwid [WWID2] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, INT_MAX); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -961,7 +959,7 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2")); |  | ||||||
|  	mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2")); |  | ||||||
| -	expect_condlog(0, "no more available user_friendly_names\n");
 |  | ||||||
| +	expect_condlog(0, NOMORE_STR);
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -1017,7 +1015,7 @@ static void rl_empty(void **state)
 |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHa"));
 |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_string_equal(buf, ""); |  | ||||||
| @@ -1030,8 +1028,7 @@ static void rl_match_a(void **state)
 |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
| -	expect_condlog(3, "Found matching alias [MPATHa] in bindings file. "
 |  | ||||||
| -		       "Setting wwid to WWID0\n");
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0"));
 |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
|  	assert_string_equal(buf, "WWID0"); |  | ||||||
| @@ -1045,7 +1042,7 @@ static void rl_nomatch_a(void **state)
 |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	expect_condlog(3, "No matching alias [MPATHb] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHb"));
 |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHb"); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_string_equal(buf, ""); |  | ||||||
| @@ -1060,7 +1057,7 @@ static void rl_malformed_a(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa     \n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); |  | ||||||
| -	expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHa"));
 |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_string_equal(buf, ""); |  | ||||||
| @@ -1080,7 +1077,7 @@ static void rl_overlong_a(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, line); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
|  	expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); |  | ||||||
| -	expect_condlog(3, "No matching alias [MPATHa] in bindings file.\n");
 |  | ||||||
| +	expect_condlog(3, NOMATCH_STR("MPATHa"));
 |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
|  	assert_string_equal(buf, ""); |  | ||||||
| @@ -1095,8 +1092,7 @@ static void rl_match_b(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHz WWID26\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHb WWID2\n"); |  | ||||||
| -	expect_condlog(3, "Found matching alias [MPATHb] in bindings file. "
 |  | ||||||
| -		       "Setting wwid to WWID2\n");
 |  | ||||||
| +	expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2"));
 |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHb"); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
|  	assert_string_equal(buf, "WWID2"); |  | ||||||
| @@ -1125,7 +1121,7 @@ static void al_a(void **state)
 |  | ||||||
|  	expect_value(__wrap_write, count, strlen(ln)); |  | ||||||
|  	expect_string(__wrap_write, buf, ln); |  | ||||||
|  	will_return(__wrap_write, strlen(ln)); |  | ||||||
| -	expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n");
 |  | ||||||
| +	expect_condlog(3, NEW_STR("MPATHa", "WWIDa"));
 |  | ||||||
|   |  | ||||||
|  	alias = allocate_binding(0, "WWIDa", 1, "MPATH"); |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
| @@ -1142,7 +1138,7 @@ static void al_zz(void **state)
 |  | ||||||
|  	expect_value(__wrap_write, count, strlen(ln)); |  | ||||||
|  	expect_string(__wrap_write, buf, ln); |  | ||||||
|  	will_return(__wrap_write, strlen(ln)); |  | ||||||
| -	expect_condlog(3, "Created new binding [MPATHzz] for WWID [WWIDzz]\n");
 |  | ||||||
| +	expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz"));
 |  | ||||||
|   |  | ||||||
|  	alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH"); |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
| @ -1,246 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 10:49:32 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools tests: convert mock_{failed,used}_alias to |  | ||||||
|  macros |  | ||||||
| 
 |  | ||||||
| This way we can further improve readability of the individual test |  | ||||||
| cases. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 92 +++++++++++++++++++++++++-------------------------- |  | ||||||
|  1 file changed, 46 insertions(+), 46 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 427b2814..a32b43e8 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -445,26 +445,26 @@ static void mock_self_alias(const char *alias, const char *wwid)
 |  | ||||||
|  #define REUSE_STR(alias_str, wwid_str) ("alias " alias_str " already bound to wwid " wwid_str ", cannot reuse\n") |  | ||||||
|  #define NOMORE_STR "no more available user_friendly_names\n" |  | ||||||
|   |  | ||||||
| -static void mock_failed_alias(const char *alias, char *msg)
 |  | ||||||
| -{
 |  | ||||||
| -	expect_string(__wrap_dm_map_present, str, alias);
 |  | ||||||
| -	will_return(__wrap_dm_map_present, 1);
 |  | ||||||
| -	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_condlog(3, msg);
 |  | ||||||
| -}
 |  | ||||||
| +#define mock_failed_alias(alias, wwid)					\
 |  | ||||||
| +	do {								\
 |  | ||||||
| +		expect_string(__wrap_dm_map_present, str, alias);	\
 |  | ||||||
| +		will_return(__wrap_dm_map_present, 1);			\
 |  | ||||||
| +		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_condlog(3, USED_STR(alias, wwid));		\
 |  | ||||||
| +	} while (0)
 |  | ||||||
|   |  | ||||||
| -static void mock_used_alias(const char *alias, char *msg)
 |  | ||||||
| -{
 |  | ||||||
| -	expect_string(__wrap_dm_map_present, str, alias);
 |  | ||||||
| -	will_return(__wrap_dm_map_present, 1);
 |  | ||||||
| -	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_condlog(3, msg);
 |  | ||||||
| -}
 |  | ||||||
| +#define mock_used_alias(alias, wwid)					\
 |  | ||||||
| +	do {								\
 |  | ||||||
| +		expect_string(__wrap_dm_map_present, str, alias);	\
 |  | ||||||
| +		will_return(__wrap_dm_map_present, 1);			\
 |  | ||||||
| +		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_condlog(3, USED_STR(alias, wwid));		\
 |  | ||||||
| +	} while(0)
 |  | ||||||
|   |  | ||||||
|  static void mock_bindings_file(const char *content, int match_line) |  | ||||||
|  { |  | ||||||
| @@ -516,7 +516,7 @@ static void lb_empty_failed(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_failed_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_failed_alias("MPATHa", "WWID0");
 |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
| @@ -531,7 +531,7 @@ static void lb_empty_1_used(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID0");
 |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
| @@ -546,7 +546,7 @@ static void lb_empty_1_used_self(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID0");
 |  | ||||||
|  	mock_self_alias("MPATHb", "WWID0"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
| @@ -616,10 +616,10 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID1"));
 |  | ||||||
| -	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID1"));
 |  | ||||||
| -	mock_used_alias("MPATHd", USED_STR("MPATHd", "WWID1"));
 |  | ||||||
| -	mock_failed_alias("MPATHe", USED_STR("MPATHe", "WWID1"));
 |  | ||||||
| +	mock_used_alias("MPATHb", "WWID1");
 |  | ||||||
| +	mock_used_alias("MPATHc", "WWID1");
 |  | ||||||
| +	mock_used_alias("MPATHd", "WWID1");
 |  | ||||||
| +	mock_failed_alias("MPATHe", "WWID1");
 |  | ||||||
|  	mock_self_alias("MPATHf", "WWID1"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID1")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); |  | ||||||
| @@ -689,7 +689,7 @@ static void lb_nomatch_a_d_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHd WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHb", "WWID2");
 |  | ||||||
|  	mock_unused_alias("MPATHc"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -705,8 +705,8 @@ static void lb_nomatch_a_d_2_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHd WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
 |  | ||||||
| -	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHb", "WWID2");
 |  | ||||||
| +	mock_used_alias("MPATHc", "WWID2");
 |  | ||||||
|  	mock_unused_alias("MPATHe"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -722,9 +722,9 @@ static void lb_nomatch_a_d_3_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHd WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
 |  | ||||||
| -	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
 |  | ||||||
| -	mock_used_alias("MPATHe", USED_STR("MPATHe", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHb", "WWID2");
 |  | ||||||
| +	mock_used_alias("MPATHc", "WWID2");
 |  | ||||||
| +	mock_used_alias("MPATHe", "WWID2");
 |  | ||||||
|  	mock_unused_alias("MPATHf"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -771,7 +771,7 @@ static void lb_nomatch_d_a_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHd WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHb", USED_STR("MPATHb", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHb", "WWID2");
 |  | ||||||
|  	mock_unused_alias("MPATHe"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -851,9 +851,9 @@ static void lb_nomatch_b_a_3_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHz WWID26\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHaa", USED_STR("MPATHaa", "WWID2"));
 |  | ||||||
| -	mock_used_alias("MPATHab", USED_STR("MPATHab", "WWID2"));
 |  | ||||||
| -	mock_used_alias("MPATHac", USED_STR("MPATHac", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHaa", "WWID2");
 |  | ||||||
| +	mock_used_alias("MPATHab", "WWID2");
 |  | ||||||
| +	mock_used_alias("MPATHac", "WWID2");
 |  | ||||||
|  	mock_unused_alias("MPATHad"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -895,7 +895,7 @@ static void lb_nomatch_int_max_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHb WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID2");
 |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -926,7 +926,7 @@ static void lb_nomatch_int_max_m1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATHa WWID0\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
 |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -941,7 +941,7 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHb WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID2");
 |  | ||||||
|  	mock_unused_alias("MPATH" MPATH_ID_INT_MAX); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -957,8 +957,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
 |  | ||||||
|  	will_return(__wrap_fgets, "MPATHb WWID1\n"); |  | ||||||
|  	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"); |  | ||||||
|  	will_return(__wrap_fgets, NULL); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID2"));
 |  | ||||||
| -	mock_used_alias("MPATH" MPATH_ID_INT_MAX, USED_STR("MPATH" MPATH_ID_INT_MAX, "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID2");
 |  | ||||||
| +	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
 |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -1291,7 +1291,7 @@ static void gufa_match_a_used(void **state) {
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0")); |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID0");
 |  | ||||||
|   |  | ||||||
|  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -1355,7 +1355,7 @@ static void gufa_nomatch_c_b_used(void **state) {
 |  | ||||||
|  	mock_bindings_file("MPATHc WWID2\n" |  | ||||||
|  			   "MPATHb WWID1", |  | ||||||
|  			   -1); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID4"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID4");
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID4")); |  | ||||||
|  	mock_unused_alias("MPATHd"); |  | ||||||
|   |  | ||||||
| @@ -1450,7 +1450,7 @@ static void gufa_old_match_other_used(void **state) {
 |  | ||||||
|  	expect_condlog(0, REUSE_STR("MPATHz", "WWID9")); |  | ||||||
|   |  | ||||||
|  	mock_bindings_file(bindings, -1); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID0");
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|   |  | ||||||
| @@ -1493,7 +1493,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_bindings_file(bindings, 1); |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); |  | ||||||
| -	mock_used_alias("MPATHc", USED_STR("MPATHc", "WWID2"));
 |  | ||||||
| +	mock_used_alias("MPATHc", "WWID2");
 |  | ||||||
|   |  | ||||||
|  	alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @@ -1528,7 +1528,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_bindings_file(bindings, 0); |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
| -	mock_used_alias("MPATHa", USED_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_used_alias("MPATHa", "WWID0");
 |  | ||||||
|   |  | ||||||
|  	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false); |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
| @ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | |||||||
|  2 files changed, 8 insertions(+), 10 deletions(-) |  2 files changed, 8 insertions(+), 10 deletions(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
 | diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
 | ||||||
| index 84ce5fe7..104fdd5a 100644
 | index 6fd4dabb..19692b1e 100644
 | ||||||
| --- a/libmultipath/discovery.c
 | --- a/libmultipath/discovery.c
 | ||||||
| +++ b/libmultipath/discovery.c
 | +++ b/libmultipath/discovery.c
 | ||||||
| @@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
 | @@ -1216,13 +1216,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
 | ||||||
|  				good_len = 8; |  				good_len = 8; | ||||||
|  				break; |  				break; | ||||||
|  			case 2: |  			case 2: | ||||||
| @ -33,7 +33,7 @@ index 84ce5fe7..104fdd5a 100644 | |||||||
|  				good_len = 8; |  				good_len = 8; | ||||||
|  				break; |  				break; | ||||||
|  			default: |  			default: | ||||||
| @@ -1201,10 +1197,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
 | @@ -1240,10 +1236,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
 | ||||||
|  			break; |  			break; | ||||||
|  		case 0x8: |  		case 0x8: | ||||||
|  			/* SCSI Name: Prio 3 */ |  			/* SCSI Name: Prio 3 */ | ||||||
| @ -1,500 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 11:13:44 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools test: use mock_bindings_file() consistently |  | ||||||
| 
 |  | ||||||
| Further improve test readablity. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 178 +++++++++++++++++++++----------------------------- |  | ||||||
|  1 file changed, 76 insertions(+), 102 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index a32b43e8..f334f928 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -489,7 +489,7 @@ static void lb_empty(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0); |  | ||||||
|  	assert_int_equal(rc, 1); |  | ||||||
| @@ -501,7 +501,7 @@ static void lb_empty_unused(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
| @@ -515,7 +515,7 @@ static void lb_empty_failed(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_failed_alias("MPATHa", "WWID0"); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
| @@ -530,7 +530,7 @@ static void lb_empty_1_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_used_alias("MPATHa", "WWID0"); |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
| @@ -545,7 +545,7 @@ static void lb_empty_1_used_self(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_used_alias("MPATHa", "WWID0"); |  | ||||||
|  	mock_self_alias("MPATHb", "WWID0"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
| @@ -560,7 +560,7 @@ static void lb_match_a(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", 0);
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
| @@ -574,8 +574,7 @@ static void lb_nomatch_a(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID1")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
| @@ -587,8 +586,7 @@ static void lb_nomatch_a_bad_check(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -600,8 +598,7 @@ static void lb_nomatch_a_unused(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID1")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); |  | ||||||
| @@ -614,8 +611,7 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATHb", "WWID1"); |  | ||||||
|  	mock_used_alias("MPATHc", "WWID1"); |  | ||||||
|  	mock_used_alias("MPATHd", "WWID1"); |  | ||||||
| @@ -632,8 +628,8 @@ static void do_lb_match_c(void **state, int check_if_taken)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHc WWID1\n");
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHc WWID1", 1);
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHc", "WWID1")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
| @@ -657,9 +653,8 @@ static void lb_nomatch_a_c(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHc WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHc WWID1", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
| @@ -671,9 +666,8 @@ static void lb_nomatch_a_d_unused(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHd WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHd WWID1", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -686,9 +680,8 @@ static void lb_nomatch_a_d_1_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHd WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHd WWID1", -1);
 |  | ||||||
|  	mock_used_alias("MPATHb", "WWID2"); |  | ||||||
|  	mock_unused_alias("MPATHc"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
| @@ -702,9 +695,8 @@ static void lb_nomatch_a_d_2_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHd WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHd WWID1", -1);
 |  | ||||||
|  	mock_used_alias("MPATHb", "WWID2"); |  | ||||||
|  	mock_used_alias("MPATHc", "WWID2"); |  | ||||||
|  	mock_unused_alias("MPATHe"); |  | ||||||
| @@ -719,9 +711,8 @@ static void lb_nomatch_a_d_3_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHd WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHd WWID1", -1);
 |  | ||||||
|  	mock_used_alias("MPATHb", "WWID2"); |  | ||||||
|  	mock_used_alias("MPATHc", "WWID2"); |  | ||||||
|  	mock_used_alias("MPATHe", "WWID2"); |  | ||||||
| @@ -737,9 +728,8 @@ static void lb_nomatch_c_a(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHc WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHc WWID1\n"
 |  | ||||||
| +			   "MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 2); |  | ||||||
| @@ -751,10 +741,9 @@ static void lb_nomatch_d_a_unused(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHc WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHd WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHc WWID1\n"
 |  | ||||||
| +			   "MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHd WWID0\n", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -767,10 +756,9 @@ static void lb_nomatch_d_a_1_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHc WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHd WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHc WWID1\n"
 |  | ||||||
| +			   "MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHd WWID0\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATHb", "WWID2"); |  | ||||||
|  	mock_unused_alias("MPATHe"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
| @@ -784,10 +772,9 @@ static void lb_nomatch_a_b(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHz WWID26\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHz WWID26\n"
 |  | ||||||
| +			   "MPATHb WWID1\n", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 3); |  | ||||||
| @@ -799,10 +786,9 @@ static void lb_nomatch_a_b_bad(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHz WWID26\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHz WWID26\n"
 |  | ||||||
| +			   "MPATHb\n", -1);
 |  | ||||||
|  	expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
| @@ -815,10 +801,9 @@ static void lb_nomatch_a_b_bad_self(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHz WWID26\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHz WWID26\n"
 |  | ||||||
| +			   "MPATHb\n", -1);
 |  | ||||||
|  	expect_condlog(3, "Ignoring malformed line 3 in bindings file\n"); |  | ||||||
|  	mock_self_alias("MPATHc", "WWID2"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
| @@ -832,10 +817,9 @@ static void lb_nomatch_b_a(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHz WWID26\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATHz WWID26\n"
 |  | ||||||
| +			   "MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, 27); |  | ||||||
| @@ -847,10 +831,9 @@ static void lb_nomatch_b_a_3_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHz WWID26\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATHz WWID26\n"
 |  | ||||||
| +			   "MPATHa WWID0\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATHaa", "WWID2"); |  | ||||||
|  	mock_used_alias("MPATHab", "WWID2"); |  | ||||||
|  	mock_used_alias("MPATHac", "WWID2"); |  | ||||||
| @@ -867,10 +850,9 @@ static void do_lb_nomatch_int_max(void **state, int check_if_taken)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"
 |  | ||||||
| +			   "MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -892,9 +874,8 @@ static void lb_nomatch_int_max_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATHa", "WWID2"); |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -907,10 +888,9 @@ static void lb_nomatch_int_max_m1(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"
 |  | ||||||
| +			   "MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0); |  | ||||||
|  	assert_int_equal(rc, INT_MAX); |  | ||||||
| @@ -922,10 +902,9 @@ static void lb_nomatch_int_max_m1_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"
 |  | ||||||
| +			   "MPATHa WWID0\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
|  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1); |  | ||||||
| @@ -938,9 +917,8 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATHa", "WWID2"); |  | ||||||
|  	mock_unused_alias("MPATH" MPATH_ID_INT_MAX); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID2")); |  | ||||||
| @@ -954,9 +932,8 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID1\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHb WWID1\n"
 |  | ||||||
| +			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1);
 |  | ||||||
|  	mock_used_alias("MPATHa", "WWID2"); |  | ||||||
|  	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2"); |  | ||||||
|  	expect_condlog(0, NOMORE_STR); |  | ||||||
| @@ -1014,7 +991,7 @@ static void rl_empty(void **state)
 |  | ||||||
|  	char buf[WWID_SIZE]; |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_STR("MPATHa")); |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -1027,7 +1004,7 @@ static void rl_match_a(void **state)
 |  | ||||||
|  	char buf[WWID_SIZE]; |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", 0);
 |  | ||||||
|  	expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0")); |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
| @@ -1040,8 +1017,7 @@ static void rl_nomatch_a(void **state)
 |  | ||||||
|  	char buf[WWID_SIZE]; |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_STR("MPATHb")); |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHb"); |  | ||||||
|  	assert_int_equal(rc, -1); |  | ||||||
| @@ -1054,8 +1030,7 @@ static void rl_malformed_a(void **state)
 |  | ||||||
|  	char buf[WWID_SIZE]; |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa     \n");
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("MPATHa     \n", -1);
 |  | ||||||
|  	expect_condlog(3, "Ignoring malformed line 1 in bindings file\n"); |  | ||||||
|  	expect_condlog(3, NOMATCH_STR("MPATHa")); |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
| @@ -1074,8 +1049,7 @@ static void rl_overlong_a(void **state)
 |  | ||||||
|  	snprintf(line + sizeof(line) - 2, 2, "\n"); |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
| -	will_return(__wrap_fgets, line);
 |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file(line, -1);
 |  | ||||||
|  	expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n"); |  | ||||||
|  	expect_condlog(3, NOMATCH_STR("MPATHa")); |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHa"); |  | ||||||
| @@ -1089,9 +1063,9 @@ static void rl_match_b(void **state)
 |  | ||||||
|  	char buf[WWID_SIZE]; |  | ||||||
|   |  | ||||||
|  	buf[0] = '\0'; |  | ||||||
| -	will_return(__wrap_fgets, "MPATHa WWID0\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHz WWID26\n");
 |  | ||||||
| -	will_return(__wrap_fgets, "MPATHb WWID2\n");
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0\n"
 |  | ||||||
| +			   "MPATHz WWID26\n"
 |  | ||||||
| +			   "MPATHb WWID2\n", 2);
 |  | ||||||
|  	expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2")); |  | ||||||
|  	rc = rlookup_binding(NULL, buf, "MPATHb"); |  | ||||||
|  	assert_int_equal(rc, 0); |  | ||||||
| @@ -1222,7 +1196,7 @@ static void gufa_empty_new_rw(void **state) {
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_open_file, true); |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|   |  | ||||||
| @@ -1235,7 +1209,7 @@ static void gufa_empty_new_rw(void **state) {
 |  | ||||||
|  static void gufa_empty_new_ro_1(void **state) { |  | ||||||
|  	char *alias; |  | ||||||
|  	will_return(__wrap_open_file, false); |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|   |  | ||||||
| @@ -1248,7 +1222,7 @@ static void gufa_empty_new_ro_2(void **state) {
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_open_file, true); |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|   |  | ||||||
| @@ -1261,7 +1235,7 @@ static void gufa_match_a_unused(void **state) {
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_open_file, true); |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0", 0);
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|   |  | ||||||
| @@ -1275,7 +1249,7 @@ static void gufa_match_a_self(void **state) {
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_open_file, true); |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0", 0);
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_self_alias("MPATHa", "WWID0"); |  | ||||||
|   |  | ||||||
| @@ -1289,7 +1263,7 @@ static void gufa_match_a_used(void **state) {
 |  | ||||||
|   |  | ||||||
|  	will_return(__wrap_open_file, true); |  | ||||||
|   |  | ||||||
| -	will_return(__wrap_fgets, BINDING_STR("MPATHa", "WWID0"));
 |  | ||||||
| +	mock_bindings_file("MPATHa WWID0", 0);
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_used_alias("MPATHa", "WWID0"); |  | ||||||
|   |  | ||||||
| @@ -1389,11 +1363,11 @@ static void gufa_old_empty(void **state) {
 |  | ||||||
|  	will_return(__wrap_open_file, true); |  | ||||||
|   |  | ||||||
|  	/* rlookup_binding for ALIAS */ |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_STR("MPATHz")); |  | ||||||
|   |  | ||||||
|  	/* lookup_binding */ |  | ||||||
| -	will_return(__wrap_fgets, NULL);
 |  | ||||||
| +	mock_bindings_file("", -1);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding("MPATHz", "WWID0"); |  | ||||||
| @ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | |||||||
|  1 file changed, 1 insertion(+), 1 deletion(-) |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 | diff --git a/Makefile.inc b/Makefile.inc
 | ||||||
| index 72fd8d57..a49e9f5a 100644
 | index 3d80d224..15e3bd3a 100644
 | ||||||
| --- a/Makefile.inc
 | --- a/Makefile.inc
 | ||||||
| +++ b/Makefile.inc
 | +++ b/Makefile.inc
 | ||||||
| @@ -16,7 +16,7 @@ READLINE :=
 | @@ -16,7 +16,7 @@ READLINE :=
 | ||||||
| @ -1,109 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 15:32:17 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: add global variable for current bindings |  | ||||||
| 
 |  | ||||||
| Add a variable global_bindings that holds the currently active vector of |  | ||||||
| bindings. This variable is freed at program exit. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c              | 11 +++++++++-- |  | ||||||
|  libmultipath/alias.h              |  1 + |  | ||||||
|  libmultipath/libmultipath.version |  1 + |  | ||||||
|  multipath/main.c                  |  2 ++ |  | ||||||
|  multipathd/main.c                 |  1 + |  | ||||||
|  5 files changed, 14 insertions(+), 2 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 9e9ac563..dd363fd8 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -511,6 +511,7 @@ static void _free_binding(struct binding *bdg)
 |  | ||||||
|   * an abstract type. |  | ||||||
|   */ |  | ||||||
|  typedef struct _vector Bindings; |  | ||||||
| +static Bindings global_bindings = { .allocated = 0 };
 |  | ||||||
|   |  | ||||||
|  static void free_bindings(Bindings *bindings) |  | ||||||
|  { |  | ||||||
| @@ -522,6 +523,11 @@ static void free_bindings(Bindings *bindings)
 |  | ||||||
|  	vector_reset(bindings); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +void cleanup_bindings(void)
 |  | ||||||
| +{
 |  | ||||||
| +	free_bindings(&global_bindings);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  enum { |  | ||||||
|  	BINDING_EXISTS, |  | ||||||
|  	BINDING_CONFLICT, |  | ||||||
| @@ -751,7 +757,6 @@ int check_alias_settings(const struct config *conf)
 |  | ||||||
|  	pthread_cleanup_pop(1); |  | ||||||
|  	pthread_cleanup_pop(1); |  | ||||||
|   |  | ||||||
| -	pthread_cleanup_push_cast(free_bindings, &bindings);
 |  | ||||||
|  	fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER); |  | ||||||
|  	if (fd != -1) { |  | ||||||
|  		FILE *file = fdopen(fd, "r"); |  | ||||||
| @@ -771,6 +776,8 @@ int check_alias_settings(const struct config *conf)
 |  | ||||||
|  			close(fd); |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
| -	pthread_cleanup_pop(1);
 |  | ||||||
| +
 |  | ||||||
| +	cleanup_bindings();
 |  | ||||||
| +	global_bindings = bindings;
 |  | ||||||
|  	return rc; |  | ||||||
|  } |  | ||||||
| diff --git a/libmultipath/alias.h b/libmultipath/alias.h
 |  | ||||||
| index fa332233..37b49d9c 100644
 |  | ||||||
| --- a/libmultipath/alias.h
 |  | ||||||
| +++ b/libmultipath/alias.h
 |  | ||||||
| @@ -9,5 +9,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file,
 |  | ||||||
|   |  | ||||||
|  struct config; |  | ||||||
|  int check_alias_settings(const struct config *); |  | ||||||
| +void cleanup_bindings(void);
 |  | ||||||
|   |  | ||||||
|  #endif /* _ALIAS_H */ |  | ||||||
| diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
 |  | ||||||
| index a7b8c337..ddd302f5 100644
 |  | ||||||
| --- a/libmultipath/libmultipath.version
 |  | ||||||
| +++ b/libmultipath/libmultipath.version
 |  | ||||||
| @@ -64,6 +64,7 @@ global:
 |  | ||||||
|  	checker_name; |  | ||||||
|  	checker_state_name; |  | ||||||
|  	check_foreign; |  | ||||||
| +	cleanup_bindings;
 |  | ||||||
|  	cleanup_lock; |  | ||||||
|  	coalesce_paths; |  | ||||||
|  	count_active_paths; |  | ||||||
| diff --git a/multipath/main.c b/multipath/main.c
 |  | ||||||
| index b78f3162..45e9745f 100644
 |  | ||||||
| --- a/multipath/main.c
 |  | ||||||
| +++ b/multipath/main.c
 |  | ||||||
| @@ -843,6 +843,8 @@ main (int argc, char *argv[])
 |  | ||||||
|  	conf->force_sync = 1; |  | ||||||
|  	if (atexit(cleanup_vecs)) |  | ||||||
|  		condlog(1, "failed to register cleanup handler for vecs: %m"); |  | ||||||
| +	if (atexit(cleanup_bindings))
 |  | ||||||
| +		condlog(1, "failed to register cleanup handler for bindings: %m");
 |  | ||||||
|  	while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) { |  | ||||||
|  		switch(arg) { |  | ||||||
|  		case 'v': |  | ||||||
| diff --git a/multipathd/main.c b/multipathd/main.c
 |  | ||||||
| index 2e02a548..214ed4ae 100644
 |  | ||||||
| --- a/multipathd/main.c
 |  | ||||||
| +++ b/multipathd/main.c
 |  | ||||||
| @@ -3325,6 +3325,7 @@ static void cleanup_child(void)
 |  | ||||||
|  { |  | ||||||
|  	cleanup_threads(); |  | ||||||
|  	cleanup_vecs(); |  | ||||||
| +	cleanup_bindings();
 |  | ||||||
|  	if (poll_dmevents) |  | ||||||
|  		cleanup_dmevent_waiter(); |  | ||||||
|   |  | ||||||
| @ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | |||||||
|  1 file changed, 1 insertion(+), 1 deletion(-) |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
| 
 | 
 | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 | diff --git a/Makefile.inc b/Makefile.inc
 | ||||||
| index a49e9f5a..51b55196 100644
 | index 15e3bd3a..64384a72 100644
 | ||||||
| --- a/Makefile.inc
 | --- a/Makefile.inc
 | ||||||
| +++ b/Makefile.inc
 | +++ b/Makefile.inc
 | ||||||
| @@ -12,7 +12,7 @@
 | @@ -12,7 +12,7 @@
 | ||||||
| @ -1,40 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 15:37:15 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: rename fix_bindings_file() to |  | ||||||
|  update_bindings_file() |  | ||||||
| 
 |  | ||||||
| We will use this function in a more generic way, give it a more |  | ||||||
| generic name. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 6 +++--- |  | ||||||
|  1 file changed, 3 insertions(+), 3 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index dd363fd8..0aac2393 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -595,8 +595,8 @@ static int write_bindings_file(const Bindings *bindings, int fd)
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int fix_bindings_file(const struct config *conf,
 |  | ||||||
| -			     const Bindings *bindings)
 |  | ||||||
| +static int update_bindings_file(const struct config *conf,
 |  | ||||||
| +				const Bindings *bindings)
 |  | ||||||
|  { |  | ||||||
|  	int rc; |  | ||||||
|  	int fd = -1; |  | ||||||
| @@ -766,7 +766,7 @@ int check_alias_settings(const struct config *conf)
 |  | ||||||
|  			rc = _check_bindings_file(conf, file, &bindings); |  | ||||||
|  			pthread_cleanup_pop(1); |  | ||||||
|  			if (rc == -1 && can_write && !conf->bindings_read_only) |  | ||||||
| -				rc = fix_bindings_file(conf, &bindings);
 |  | ||||||
| +				rc = update_bindings_file(conf, &bindings);
 |  | ||||||
|  			else if (rc == -1) |  | ||||||
|  				condlog(0, "ERROR: bad settings in read-only bindings file %s", |  | ||||||
|  					conf->bindings_file); |  | ||||||
| @ -14,7 +14,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> | |||||||
|  create mode 100755 multipath/mpathcleanup |  create mode 100755 multipath/mpathcleanup | ||||||
| 
 | 
 | ||||||
| diff --git a/multipath/Makefile b/multipath/Makefile
 | diff --git a/multipath/Makefile b/multipath/Makefile
 | ||||||
| index 9942d1a9..d281b501 100644
 | index 9f14036c..99ad81b0 100644
 | ||||||
| --- a/multipath/Makefile
 | --- a/multipath/Makefile
 | ||||||
| +++ b/multipath/Makefile
 | +++ b/multipath/Makefile
 | ||||||
| @@ -25,6 +25,7 @@ install:
 | @@ -25,6 +25,7 @@ install:
 | ||||||
| @ -25,7 +25,7 @@ index 9942d1a9..d281b501 100644 | |||||||
|  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) |  	$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) |  	$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules |  	$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules | ||||||
| @@ -46,6 +47,7 @@ endif
 | @@ -48,6 +49,7 @@ endif
 | ||||||
|  uninstall: |  uninstall: | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) |  	$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC) | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf |  	$(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf | ||||||
| @ -1,285 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 16:54:54 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: alias.c: move bindings related code up |  | ||||||
| 
 |  | ||||||
| No code changes, just moving code. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 239 ++++++++++++++++++++++--------------------- |  | ||||||
|  1 file changed, 120 insertions(+), 119 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 0aac2393..7af403da 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -9,6 +9,7 @@
 |  | ||||||
|  #include <limits.h> |  | ||||||
|  #include <stdio.h> |  | ||||||
|  #include <stdbool.h> |  | ||||||
| +#include <assert.h>
 |  | ||||||
|   |  | ||||||
|  #include "debug.h" |  | ||||||
|  #include "util.h" |  | ||||||
| @@ -51,6 +52,125 @@
 |  | ||||||
|   |  | ||||||
|  static const char bindings_file_header[] = BINDINGS_FILE_HEADER; |  | ||||||
|   |  | ||||||
| +struct binding {
 |  | ||||||
| +	char *alias;
 |  | ||||||
| +	char *wwid;
 |  | ||||||
| +};
 |  | ||||||
| +
 |  | ||||||
| +/*
 |  | ||||||
| + * Perhaps one day we'll implement this more efficiently, thus use
 |  | ||||||
| + * an abstract type.
 |  | ||||||
| + */
 |  | ||||||
| +typedef struct _vector Bindings;
 |  | ||||||
| +static Bindings global_bindings = { .allocated = 0 };
 |  | ||||||
| +
 |  | ||||||
| +enum {
 |  | ||||||
| +	BINDING_EXISTS,
 |  | ||||||
| +	BINDING_CONFLICT,
 |  | ||||||
| +	BINDING_ADDED,
 |  | ||||||
| +	BINDING_DELETED,
 |  | ||||||
| +	BINDING_NOTFOUND,
 |  | ||||||
| +	BINDING_ERROR,
 |  | ||||||
| +};
 |  | ||||||
| +
 |  | ||||||
| +static void _free_binding(struct binding *bdg)
 |  | ||||||
| +{
 |  | ||||||
| +	free(bdg->wwid);
 |  | ||||||
| +	free(bdg->alias);
 |  | ||||||
| +	free(bdg);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
 |  | ||||||
| +{
 |  | ||||||
| +	struct binding *bdg;
 |  | ||||||
| +	int i, cmp = 0;
 |  | ||||||
| +
 |  | ||||||
| +	/*
 |  | ||||||
| +	 * Keep the bindings array sorted by alias.
 |  | ||||||
| +	 * Optimization: Search backwards, assuming that the bindings file is
 |  | ||||||
| +	 * sorted already.
 |  | ||||||
| +	 */
 |  | ||||||
| +	vector_foreach_slot_backwards(bindings, bdg, i) {
 |  | ||||||
| +		if ((cmp = strcmp(bdg->alias, alias)) <= 0)
 |  | ||||||
| +			break;
 |  | ||||||
| +	}
 |  | ||||||
| +
 |  | ||||||
| +	/* Check for exact match */
 |  | ||||||
| +	if (i >= 0 && cmp == 0)
 |  | ||||||
| +		return strcmp(bdg->wwid, wwid) ?
 |  | ||||||
| +			BINDING_CONFLICT : BINDING_EXISTS;
 |  | ||||||
| +
 |  | ||||||
| +	i++;
 |  | ||||||
| +	bdg = calloc(1, sizeof(*bdg));
 |  | ||||||
| +	if (bdg) {
 |  | ||||||
| +		bdg->wwid = strdup(wwid);
 |  | ||||||
| +		bdg->alias = strdup(alias);
 |  | ||||||
| +		if (bdg->wwid && bdg->alias &&
 |  | ||||||
| +		    vector_insert_slot(bindings, i, bdg))
 |  | ||||||
| +			return BINDING_ADDED;
 |  | ||||||
| +		else
 |  | ||||||
| +			_free_binding(bdg);
 |  | ||||||
| +	}
 |  | ||||||
| +
 |  | ||||||
| +	return BINDING_ERROR;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static int write_bindings_file(const Bindings *bindings, int fd)
 |  | ||||||
| +{
 |  | ||||||
| +	struct binding *bnd;
 |  | ||||||
| +	STRBUF_ON_STACK(line);
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1)
 |  | ||||||
| +	    != sizeof(BINDINGS_FILE_HEADER) - 1)
 |  | ||||||
| +		return -1;
 |  | ||||||
| +
 |  | ||||||
| +	vector_foreach_slot(bindings, bnd, i) {
 |  | ||||||
| +		int len;
 |  | ||||||
| +
 |  | ||||||
| +		if ((len = print_strbuf(&line, "%s %s\n",
 |  | ||||||
| +					bnd->alias, bnd->wwid)) < 0)
 |  | ||||||
| +			return -1;
 |  | ||||||
| +		if (write(fd, get_strbuf_str(&line), len) != len)
 |  | ||||||
| +			return -1;
 |  | ||||||
| +		truncate_strbuf(&line, 0);
 |  | ||||||
| +	}
 |  | ||||||
| +	return 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static int update_bindings_file(const struct config *conf,
 |  | ||||||
| +				const Bindings *bindings)
 |  | ||||||
| +{
 |  | ||||||
| +	int rc;
 |  | ||||||
| +	int fd = -1;
 |  | ||||||
| +	char tempname[PATH_MAX];
 |  | ||||||
| +	mode_t old_umask;
 |  | ||||||
| +
 |  | ||||||
| +	if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file))
 |  | ||||||
| +		return -1;
 |  | ||||||
| +	/* coverity: SECURE_TEMP */
 |  | ||||||
| +	old_umask = umask(0077);
 |  | ||||||
| +	if ((fd = mkstemp(tempname)) == -1) {
 |  | ||||||
| +		condlog(1, "%s: mkstemp: %m", __func__);
 |  | ||||||
| +		return -1;
 |  | ||||||
| +	}
 |  | ||||||
| +	umask(old_umask);
 |  | ||||||
| +	pthread_cleanup_push(cleanup_fd_ptr, &fd);
 |  | ||||||
| +	rc = write_bindings_file(bindings, fd);
 |  | ||||||
| +	pthread_cleanup_pop(1);
 |  | ||||||
| +	if (rc == -1) {
 |  | ||||||
| +		condlog(1, "failed to write new bindings file %s",
 |  | ||||||
| +			tempname);
 |  | ||||||
| +		unlink(tempname);
 |  | ||||||
| +		return rc;
 |  | ||||||
| +	}
 |  | ||||||
| +	if ((rc = rename(tempname, conf->bindings_file)) == -1)
 |  | ||||||
| +		condlog(0, "%s: rename: %m", __func__);
 |  | ||||||
| +	else
 |  | ||||||
| +		condlog(1, "updated bindings file %s", conf->bindings_file);
 |  | ||||||
| +	return rc;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  int |  | ||||||
|  valid_alias(const char *alias) |  | ||||||
|  { |  | ||||||
| @@ -494,25 +614,6 @@ get_user_friendly_wwid(const char *alias, char *buff, const char *file)
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -struct binding {
 |  | ||||||
| -	char *alias;
 |  | ||||||
| -	char *wwid;
 |  | ||||||
| -};
 |  | ||||||
| -
 |  | ||||||
| -static void _free_binding(struct binding *bdg)
 |  | ||||||
| -{
 |  | ||||||
| -	free(bdg->wwid);
 |  | ||||||
| -	free(bdg->alias);
 |  | ||||||
| -	free(bdg);
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
| -/*
 |  | ||||||
| - * Perhaps one day we'll implement this more efficiently, thus use
 |  | ||||||
| - * an abstract type.
 |  | ||||||
| - */
 |  | ||||||
| -typedef struct _vector Bindings;
 |  | ||||||
| -static Bindings global_bindings = { .allocated = 0 };
 |  | ||||||
| -
 |  | ||||||
|  static void free_bindings(Bindings *bindings) |  | ||||||
|  { |  | ||||||
|  	struct binding *bdg; |  | ||||||
| @@ -528,106 +629,6 @@ void cleanup_bindings(void)
 |  | ||||||
|  	free_bindings(&global_bindings); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -enum {
 |  | ||||||
| -	BINDING_EXISTS,
 |  | ||||||
| -	BINDING_CONFLICT,
 |  | ||||||
| -	BINDING_ADDED,
 |  | ||||||
| -	BINDING_DELETED,
 |  | ||||||
| -	BINDING_NOTFOUND,
 |  | ||||||
| -	BINDING_ERROR,
 |  | ||||||
| -};
 |  | ||||||
| -
 |  | ||||||
| -static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
 |  | ||||||
| -{
 |  | ||||||
| -	struct binding *bdg;
 |  | ||||||
| -	int i, cmp = 0;
 |  | ||||||
| -
 |  | ||||||
| -	/*
 |  | ||||||
| -	 * Keep the bindings array sorted by alias.
 |  | ||||||
| -	 * Optimization: Search backwards, assuming that the bindings file is
 |  | ||||||
| -	 * sorted already.
 |  | ||||||
| -	 */
 |  | ||||||
| -	vector_foreach_slot_backwards(bindings, bdg, i) {
 |  | ||||||
| -		if ((cmp = strcmp(bdg->alias, alias)) <= 0)
 |  | ||||||
| -			break;
 |  | ||||||
| -	}
 |  | ||||||
| -
 |  | ||||||
| -	/* Check for exact match */
 |  | ||||||
| -	if (i >= 0 && cmp == 0)
 |  | ||||||
| -		return strcmp(bdg->wwid, wwid) ?
 |  | ||||||
| -			BINDING_CONFLICT : BINDING_EXISTS;
 |  | ||||||
| -
 |  | ||||||
| -	i++;
 |  | ||||||
| -	bdg = calloc(1, sizeof(*bdg));
 |  | ||||||
| -	if (bdg) {
 |  | ||||||
| -		bdg->wwid = strdup(wwid);
 |  | ||||||
| -		bdg->alias = strdup(alias);
 |  | ||||||
| -		if (bdg->wwid && bdg->alias &&
 |  | ||||||
| -		    vector_insert_slot(bindings, i, bdg))
 |  | ||||||
| -			return BINDING_ADDED;
 |  | ||||||
| -		else
 |  | ||||||
| -			_free_binding(bdg);
 |  | ||||||
| -	}
 |  | ||||||
| -
 |  | ||||||
| -	return BINDING_ERROR;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
| -static int write_bindings_file(const Bindings *bindings, int fd)
 |  | ||||||
| -{
 |  | ||||||
| -	struct binding *bnd;
 |  | ||||||
| -	STRBUF_ON_STACK(line);
 |  | ||||||
| -	int i;
 |  | ||||||
| -
 |  | ||||||
| -	if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1)
 |  | ||||||
| -	    != sizeof(BINDINGS_FILE_HEADER) - 1)
 |  | ||||||
| -		return -1;
 |  | ||||||
| -
 |  | ||||||
| -	vector_foreach_slot(bindings, bnd, i) {
 |  | ||||||
| -		int len;
 |  | ||||||
| -
 |  | ||||||
| -		if ((len = print_strbuf(&line, "%s %s\n",
 |  | ||||||
| -					bnd->alias, bnd->wwid)) < 0)
 |  | ||||||
| -			return -1;
 |  | ||||||
| -		if (write(fd, get_strbuf_str(&line), len) != len)
 |  | ||||||
| -			return -1;
 |  | ||||||
| -		truncate_strbuf(&line, 0);
 |  | ||||||
| -	}
 |  | ||||||
| -	return 0;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
| -static int update_bindings_file(const struct config *conf,
 |  | ||||||
| -				const Bindings *bindings)
 |  | ||||||
| -{
 |  | ||||||
| -	int rc;
 |  | ||||||
| -	int fd = -1;
 |  | ||||||
| -	char tempname[PATH_MAX];
 |  | ||||||
| -	mode_t old_umask;
 |  | ||||||
| -
 |  | ||||||
| -	if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file))
 |  | ||||||
| -		return -1;
 |  | ||||||
| -	/* coverity: SECURE_TEMP */
 |  | ||||||
| -	old_umask = umask(0077);
 |  | ||||||
| -	if ((fd = mkstemp(tempname)) == -1) {
 |  | ||||||
| -		condlog(1, "%s: mkstemp: %m", __func__);
 |  | ||||||
| -		return -1;
 |  | ||||||
| -	}
 |  | ||||||
| -	umask(old_umask);
 |  | ||||||
| -	pthread_cleanup_push(cleanup_fd_ptr, &fd);
 |  | ||||||
| -	rc = write_bindings_file(bindings, fd);
 |  | ||||||
| -	pthread_cleanup_pop(1);
 |  | ||||||
| -	if (rc == -1) {
 |  | ||||||
| -		condlog(1, "failed to write new bindings file %s",
 |  | ||||||
| -			tempname);
 |  | ||||||
| -		unlink(tempname);
 |  | ||||||
| -		return rc;
 |  | ||||||
| -	}
 |  | ||||||
| -	if ((rc = rename(tempname, conf->bindings_file)) == -1)
 |  | ||||||
| -		condlog(0, "%s: rename: %m", __func__);
 |  | ||||||
| -	else
 |  | ||||||
| -		condlog(1, "updated bindings file %s", conf->bindings_file);
 |  | ||||||
| -	return rc;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
|  static int _check_bindings_file(const struct config *conf, FILE *file, |  | ||||||
|  				 Bindings *bindings) |  | ||||||
|  { |  | ||||||
| @ -1,61 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 15:53:49 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: update_bindings_file: take filename argument |  | ||||||
| 
 |  | ||||||
| This function just uses the file name, no other configuration |  | ||||||
| parameters. Also, pass the Bindings argument first to use the |  | ||||||
| same convention as the other functions in this file. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 12 ++++++------ |  | ||||||
|  1 file changed, 6 insertions(+), 6 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 7af403da..9bd3875e 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -138,15 +138,15 @@ static int write_bindings_file(const Bindings *bindings, int fd)
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int update_bindings_file(const struct config *conf,
 |  | ||||||
| -				const Bindings *bindings)
 |  | ||||||
| +static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
| +				const char *bindings_file)
 |  | ||||||
|  { |  | ||||||
|  	int rc; |  | ||||||
|  	int fd = -1; |  | ||||||
|  	char tempname[PATH_MAX]; |  | ||||||
|  	mode_t old_umask; |  | ||||||
|   |  | ||||||
| -	if (safe_sprintf(tempname, "%s.XXXXXX", conf->bindings_file))
 |  | ||||||
| +	if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file))
 |  | ||||||
|  		return -1; |  | ||||||
|  	/* coverity: SECURE_TEMP */ |  | ||||||
|  	old_umask = umask(0077); |  | ||||||
| @@ -164,10 +164,10 @@ static int update_bindings_file(const struct config *conf,
 |  | ||||||
|  		unlink(tempname); |  | ||||||
|  		return rc; |  | ||||||
|  	} |  | ||||||
| -	if ((rc = rename(tempname, conf->bindings_file)) == -1)
 |  | ||||||
| +	if ((rc = rename(tempname, bindings_file)) == -1)
 |  | ||||||
|  		condlog(0, "%s: rename: %m", __func__); |  | ||||||
|  	else |  | ||||||
| -		condlog(1, "updated bindings file %s", conf->bindings_file);
 |  | ||||||
| +		condlog(1, "updated bindings file %s", bindings_file);
 |  | ||||||
|  	return rc; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -767,7 +767,7 @@ int check_alias_settings(const struct config *conf)
 |  | ||||||
|  			rc = _check_bindings_file(conf, file, &bindings); |  | ||||||
|  			pthread_cleanup_pop(1); |  | ||||||
|  			if (rc == -1 && can_write && !conf->bindings_read_only) |  | ||||||
| -				rc = update_bindings_file(conf, &bindings);
 |  | ||||||
| +				rc = update_bindings_file(&bindings, conf->bindings_file);
 |  | ||||||
|  			else if (rc == -1) |  | ||||||
|  				condlog(0, "ERROR: bad settings in read-only bindings file %s", |  | ||||||
|  					conf->bindings_file); |  | ||||||
| @ -1,59 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 15:54:45 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: update_bindings_file: use a single write() |  | ||||||
| 
 |  | ||||||
| Save code and syscalls by assembling the content in memory first. |  | ||||||
| write() may return less bytes written than expected. Deal with it. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 26 +++++++++++++++++--------- |  | ||||||
|  1 file changed, 17 insertions(+), 9 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 9bd3875e..92f90f05 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -118,22 +118,30 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
 |  | ||||||
|  static int write_bindings_file(const Bindings *bindings, int fd) |  | ||||||
|  { |  | ||||||
|  	struct binding *bnd; |  | ||||||
| -	STRBUF_ON_STACK(line);
 |  | ||||||
| +	STRBUF_ON_STACK(content);
 |  | ||||||
|  	int i; |  | ||||||
| +	size_t len;
 |  | ||||||
|   |  | ||||||
| -	if (write(fd, BINDINGS_FILE_HEADER, sizeof(BINDINGS_FILE_HEADER) - 1)
 |  | ||||||
| -	    != sizeof(BINDINGS_FILE_HEADER) - 1)
 |  | ||||||
| +	if (__append_strbuf_str(&content, BINDINGS_FILE_HEADER,
 |  | ||||||
| +				sizeof(BINDINGS_FILE_HEADER) - 1) == -1)
 |  | ||||||
|  		return -1; |  | ||||||
|   |  | ||||||
|  	vector_foreach_slot(bindings, bnd, i) { |  | ||||||
| -		int len;
 |  | ||||||
| -
 |  | ||||||
| -		if ((len = print_strbuf(&line, "%s %s\n",
 |  | ||||||
| -					bnd->alias, bnd->wwid)) < 0)
 |  | ||||||
| +		if (print_strbuf(&content, "%s %s\n",
 |  | ||||||
| +					bnd->alias, bnd->wwid) < 0)
 |  | ||||||
|  			return -1; |  | ||||||
| -		if (write(fd, get_strbuf_str(&line), len) != len)
 |  | ||||||
| +	}
 |  | ||||||
| +	len = get_strbuf_len(&content);
 |  | ||||||
| +	while (len > 0) {
 |  | ||||||
| +		ssize_t n = write(fd, get_strbuf_str(&content), len);
 |  | ||||||
| +
 |  | ||||||
| +		if (n < 0)
 |  | ||||||
| +			return n;
 |  | ||||||
| +		else if (n == 0) {
 |  | ||||||
| +			condlog(2, "%s: short write", __func__);
 |  | ||||||
|  			return -1; |  | ||||||
| -		truncate_strbuf(&line, 0);
 |  | ||||||
| +		}
 |  | ||||||
| +		len -= n;
 |  | ||||||
|  	} |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
| @ -1,29 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 22:33:39 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: update_bindings_file: don't log temp file name |  | ||||||
| 
 |  | ||||||
| The name of the temp file is unlikely to be helpful for users, |  | ||||||
| and hard to predict in the unit test. Omit it. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 3 +-- |  | ||||||
|  1 file changed, 1 insertion(+), 2 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 92f90f05..afa5879e 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -167,8 +167,7 @@ static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
|  	rc = write_bindings_file(bindings, fd); |  | ||||||
|  	pthread_cleanup_pop(1); |  | ||||||
|  	if (rc == -1) { |  | ||||||
| -		condlog(1, "failed to write new bindings file %s",
 |  | ||||||
| -			tempname);
 |  | ||||||
| +		condlog(1, "failed to write new bindings file");
 |  | ||||||
|  		unlink(tempname); |  | ||||||
|  		return rc; |  | ||||||
|  	} |  | ||||||
| @ -1,94 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 24 Aug 2023 21:17:25 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: alias.c: factor out read_binding() |  | ||||||
| 
 |  | ||||||
| This way we can test the parsing of input lines from the bindings |  | ||||||
| file more easily. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 58 ++++++++++++++++++++++++++++++-------------- |  | ||||||
|  1 file changed, 40 insertions(+), 18 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index afa5879e..ecf4a2ac 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -636,6 +636,43 @@ void cleanup_bindings(void)
 |  | ||||||
|  	free_bindings(&global_bindings); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +enum {
 |  | ||||||
| +	READ_BINDING_OK,
 |  | ||||||
| +	READ_BINDING_SKIP,
 |  | ||||||
| +};
 |  | ||||||
| +
 |  | ||||||
| +static int read_binding(char *line, unsigned int linenr, char **alias,
 |  | ||||||
| +			char **wwid) {
 |  | ||||||
| +	char *c, *saveptr;
 |  | ||||||
| +
 |  | ||||||
| +	c = strpbrk(line, "#\n\r");
 |  | ||||||
| +	if (c)
 |  | ||||||
| +		*c = '\0';
 |  | ||||||
| +
 |  | ||||||
| +	*alias = strtok_r(line, " \t", &saveptr);
 |  | ||||||
| +	if (!*alias) /* blank line */
 |  | ||||||
| +		return READ_BINDING_SKIP;
 |  | ||||||
| +
 |  | ||||||
| +	*wwid = strtok_r(NULL, " \t", &saveptr);
 |  | ||||||
| +	if (!*wwid) {
 |  | ||||||
| +		condlog(1, "invalid line %u in bindings file, missing WWID",
 |  | ||||||
| +			linenr);
 |  | ||||||
| +		return READ_BINDING_SKIP;
 |  | ||||||
| +	}
 |  | ||||||
| +	if (strlen(*wwid) > WWID_SIZE - 1) {
 |  | ||||||
| +		condlog(3,
 |  | ||||||
| +			"Ignoring too large wwid at %u in bindings file",
 |  | ||||||
| +			linenr);
 |  | ||||||
| +		return READ_BINDING_SKIP;
 |  | ||||||
| +	}
 |  | ||||||
| +	c = strtok_r(NULL, " \t", &saveptr);
 |  | ||||||
| +	if (c)
 |  | ||||||
| +		/* This is non-fatal */
 |  | ||||||
| +		condlog(1, "invalid line %d in bindings file, extra args \"%s\"",
 |  | ||||||
| +			linenr, c);
 |  | ||||||
| +	return READ_BINDING_OK;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static int _check_bindings_file(const struct config *conf, FILE *file, |  | ||||||
|  				 Bindings *bindings) |  | ||||||
|  { |  | ||||||
| @@ -647,27 +684,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
 |  | ||||||
|   |  | ||||||
|  	pthread_cleanup_push(cleanup_free_ptr, &line); |  | ||||||
|  	while ((n = getline(&line, &line_len, file)) >= 0) { |  | ||||||
| -		char *c, *alias, *wwid, *saveptr;
 |  | ||||||
| +		char *alias, *wwid;
 |  | ||||||
|  		const char *mpe_wwid; |  | ||||||
|   |  | ||||||
| -		linenr++;
 |  | ||||||
| -		c = strpbrk(line, "#\n\r");
 |  | ||||||
| -		if (c)
 |  | ||||||
| -			*c = '\0';
 |  | ||||||
| -		alias = strtok_r(line, " \t", &saveptr);
 |  | ||||||
| -		if (!alias) /* blank line */
 |  | ||||||
| -			continue;
 |  | ||||||
| -		wwid = strtok_r(NULL, " \t", &saveptr);
 |  | ||||||
| -		if (!wwid) {
 |  | ||||||
| -			condlog(1, "invalid line %d in bindings file, missing WWID",
 |  | ||||||
| -				linenr);
 |  | ||||||
| +		if (read_binding(line, ++linenr, &alias, &wwid)
 |  | ||||||
| +		    == READ_BINDING_SKIP)
 |  | ||||||
|  			continue; |  | ||||||
| -		}
 |  | ||||||
| -		c = strtok_r(NULL, " \t", &saveptr);
 |  | ||||||
| -		if (c)
 |  | ||||||
| -			/* This is non-fatal */
 |  | ||||||
| -			condlog(1, "invalid line %d in bindings file, extra args \"%s\"",
 |  | ||||||
| -				linenr, c);
 |  | ||||||
|   |  | ||||||
|  		mpe_wwid = get_mpe_wwid(conf->mptable, alias); |  | ||||||
|  		if (mpe_wwid && strcmp(mpe_wwid, wwid)) { |  | ||||||
| @ -1,545 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 22 Aug 2023 21:14:51 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: keep bindings in memory |  | ||||||
| 
 |  | ||||||
| Rather than opening the bindings file every time we must retrieve |  | ||||||
| a binding, keep the contents in memory and write the file only |  | ||||||
| if additions have been made. This simplifies the code, and should speed up |  | ||||||
| alias lookups significantly. As a side effect, the aliases will be stored |  | ||||||
| sorted by alias, which changes the way aliases are allocated if there are |  | ||||||
| unused "holes" in the sequence of aliases. For example, if the bindings file |  | ||||||
| contains mpathb, mpathy, and mpatha, in this order, the next new alias used to |  | ||||||
| be mpathz and is now mpathc. |  | ||||||
| 
 |  | ||||||
| Another side effect is that multipathd will not automatically pick up changes |  | ||||||
| to the bindings file at runtime without a reconfigure operation. It is |  | ||||||
| questionable whether these on-the-fly changes were a good idea in the first |  | ||||||
| place, as inconsistent configurations may easily come to pass. It desired, |  | ||||||
| it would be feasible to implement automatic update of the bindings using the |  | ||||||
| existing inotify approach. |  | ||||||
| 
 |  | ||||||
| The new implementation of get_user_friendly_alias() is slightly different |  | ||||||
| than before. The logic is summarized in a comment in the code. Unit tests |  | ||||||
| will be provided that illustrate the changes. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c     | 351 ++++++++++++++++----------------------- |  | ||||||
|  libmultipath/alias.h     |   2 +- |  | ||||||
|  libmultipath/configure.c |   3 +- |  | ||||||
|  3 files changed, 144 insertions(+), 212 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index ecf4a2ac..d6563749 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -50,8 +50,6 @@
 |  | ||||||
|  "# alias wwid\n" \ |  | ||||||
|  "#\n" |  | ||||||
|   |  | ||||||
| -static const char bindings_file_header[] = BINDINGS_FILE_HEADER;
 |  | ||||||
| -
 |  | ||||||
|  struct binding { |  | ||||||
|  	char *alias; |  | ||||||
|  	char *wwid; |  | ||||||
| @@ -80,6 +78,45 @@ static void _free_binding(struct binding *bdg)
 |  | ||||||
|  	free(bdg); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static const struct binding *get_binding_for_alias(const Bindings *bindings,
 |  | ||||||
| +						   const char *alias)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct binding *bdg;
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	if (!alias)
 |  | ||||||
| +		return NULL;
 |  | ||||||
| +	vector_foreach_slot(bindings, bdg, i) {
 |  | ||||||
| +		if (!strncmp(bdg->alias, alias, WWID_SIZE)) {
 |  | ||||||
| +			condlog(3, "Found matching alias [%s] in bindings file."
 |  | ||||||
| +				" Setting wwid to %s", alias, bdg->wwid);
 |  | ||||||
| +			return bdg;
 |  | ||||||
| +		}
 |  | ||||||
| +	}
 |  | ||||||
| +
 |  | ||||||
| +	condlog(3, "No matching alias [%s] in bindings file.", alias);
 |  | ||||||
| +	return NULL;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static const struct binding *get_binding_for_wwid(const Bindings *bindings,
 |  | ||||||
| +						  const char *wwid)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct binding *bdg;
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	if (!wwid)
 |  | ||||||
| +		return NULL;
 |  | ||||||
| +	vector_foreach_slot(bindings, bdg, i) {
 |  | ||||||
| +		if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) {
 |  | ||||||
| +			condlog(3, "Found matching wwid [%s] in bindings file."
 |  | ||||||
| +				" Setting alias to %s", wwid, bdg->alias);
 |  | ||||||
| +			return bdg;
 |  | ||||||
| +		}
 |  | ||||||
| +	}
 |  | ||||||
| +	condlog(3, "No matching wwid [%s] in bindings file.", wwid);
 |  | ||||||
| +	return NULL;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static int add_binding(Bindings *bindings, const char *alias, const char *wwid) |  | ||||||
|  { |  | ||||||
|  	struct binding *bdg; |  | ||||||
| @@ -115,6 +152,24 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
 |  | ||||||
|  	return BINDING_ERROR; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static int delete_binding(Bindings *bindings, const char *wwid)
 |  | ||||||
| +{
 |  | ||||||
| +	struct binding *bdg;
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	vector_foreach_slot(bindings, bdg, i) {
 |  | ||||||
| +		if (!strncmp(bdg->wwid, wwid, WWID_SIZE)) {
 |  | ||||||
| +			_free_binding(bdg);
 |  | ||||||
| +			break;
 |  | ||||||
| +		}
 |  | ||||||
| +	}
 |  | ||||||
| +	if (i >= VECTOR_SIZE(bindings))
 |  | ||||||
| +		return BINDING_NOTFOUND;
 |  | ||||||
| +
 |  | ||||||
| +	vector_del_slot(bindings, i);
 |  | ||||||
| +	return BINDING_DELETED;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static int write_bindings_file(const Bindings *bindings, int fd) |  | ||||||
|  { |  | ||||||
|  	struct binding *bnd; |  | ||||||
| @@ -267,38 +322,15 @@ static bool id_already_taken(int id, const char *prefix, const char *map_wwid)
 |  | ||||||
|  	return alias_already_taken(alias, map_wwid); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -/*
 |  | ||||||
| - * Returns: 0   if matching entry in WWIDs file found
 |  | ||||||
| - *         -1   if an error occurs
 |  | ||||||
| - *         >0   a free ID that could be used for the WWID at hand
 |  | ||||||
| - * *map_alias is set to a freshly allocated string with the matching alias if
 |  | ||||||
| - * the function returns 0, or to NULL otherwise.
 |  | ||||||
| - */
 |  | ||||||
| -static int
 |  | ||||||
| -lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
 |  | ||||||
| -	       const char *prefix, int check_if_taken)
 |  | ||||||
| +int get_free_id(const Bindings *bindings, const char *prefix, const char *map_wwid)
 |  | ||||||
|  { |  | ||||||
| -	char buf[LINE_MAX];
 |  | ||||||
| -	unsigned int line_nr = 0;
 |  | ||||||
| -	int id = 1;
 |  | ||||||
| +	const struct binding *bdg;
 |  | ||||||
| +	int i, id = 1;
 |  | ||||||
|  	int biggest_id = 1; |  | ||||||
|  	int smallest_bigger_id = INT_MAX; |  | ||||||
|   |  | ||||||
| -	*map_alias = NULL;
 |  | ||||||
| -
 |  | ||||||
| -	rewind(f);
 |  | ||||||
| -	while (fgets(buf, LINE_MAX, f)) {
 |  | ||||||
| -		const char *alias, *wwid;
 |  | ||||||
| -		char *c, *saveptr;
 |  | ||||||
| -		int curr_id;
 |  | ||||||
| -
 |  | ||||||
| -		line_nr++;
 |  | ||||||
| -		c = strpbrk(buf, "#\n\r");
 |  | ||||||
| -		if (c)
 |  | ||||||
| -			*c = '\0';
 |  | ||||||
| -		alias = strtok_r(buf, " \t", &saveptr);
 |  | ||||||
| -		if (!alias) /* blank line */
 |  | ||||||
| -			continue;
 |  | ||||||
| +	vector_foreach_slot(bindings, bdg, i) {
 |  | ||||||
| +		int curr_id = scan_devname(bdg->alias, prefix);
 |  | ||||||
|   |  | ||||||
|  		/* |  | ||||||
|  		 * Find an unused index - explanation of the algorithm |  | ||||||
| @@ -333,8 +365,6 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
 |  | ||||||
|  		 * biggest_id is always > smallest_bigger_id, except in the |  | ||||||
|  		 * "perfectly ordered" case. |  | ||||||
|  		 */ |  | ||||||
| -
 |  | ||||||
| -		curr_id = scan_devname(alias, prefix);
 |  | ||||||
|  		if (curr_id == id) { |  | ||||||
|  			if (id < INT_MAX) |  | ||||||
|  				id++; |  | ||||||
| @@ -345,36 +375,15 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
 |  | ||||||
|  		} |  | ||||||
|  		if (curr_id > biggest_id) |  | ||||||
|  			biggest_id = curr_id; |  | ||||||
| +
 |  | ||||||
|  		if (curr_id > id && curr_id < smallest_bigger_id) |  | ||||||
|  			smallest_bigger_id = curr_id; |  | ||||||
| -		wwid = strtok_r(NULL, " \t", &saveptr);
 |  | ||||||
| -		if (!wwid){
 |  | ||||||
| -			condlog(3,
 |  | ||||||
| -				"Ignoring malformed line %u in bindings file",
 |  | ||||||
| -				line_nr);
 |  | ||||||
| -			continue;
 |  | ||||||
| -		}
 |  | ||||||
| -		if (strcmp(wwid, map_wwid) == 0){
 |  | ||||||
| -			condlog(3, "Found matching wwid [%s] in bindings file."
 |  | ||||||
| -				" Setting alias to %s", wwid, alias);
 |  | ||||||
| -			*map_alias = strdup(alias);
 |  | ||||||
| -			if (*map_alias == NULL) {
 |  | ||||||
| -				condlog(0, "Cannot copy alias from bindings "
 |  | ||||||
| -					"file: out of memory");
 |  | ||||||
| -				return -1;
 |  | ||||||
| -			}
 |  | ||||||
| -			return 0;
 |  | ||||||
| -		}
 |  | ||||||
| -	}
 |  | ||||||
| -	if (!prefix && check_if_taken)
 |  | ||||||
| -		id = -1;
 |  | ||||||
| -	if (id >= smallest_bigger_id) {
 |  | ||||||
| -		if (biggest_id < INT_MAX)
 |  | ||||||
| -			id = biggest_id + 1;
 |  | ||||||
| -		else
 |  | ||||||
| -			id = -1;
 |  | ||||||
|  	} |  | ||||||
| -	if (id > 0 && check_if_taken) {
 |  | ||||||
| +
 |  | ||||||
| +	if (id >= smallest_bigger_id)
 |  | ||||||
| +		id = biggest_id < INT_MAX ? biggest_id + 1 : -1;
 |  | ||||||
| +
 |  | ||||||
| +	if (id > 0) {
 |  | ||||||
|  		while(id_already_taken(id, prefix, map_wwid)) { |  | ||||||
|  			if (id == INT_MAX) { |  | ||||||
|  				id = -1; |  | ||||||
| @@ -391,64 +400,17 @@ lookup_binding(FILE *f, const char *map_wwid, char **map_alias,
 |  | ||||||
|  			} |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
| -	if (id < 0) {
 |  | ||||||
| +
 |  | ||||||
| +	if (id < 0)
 |  | ||||||
|  		condlog(0, "no more available user_friendly_names"); |  | ||||||
| -		return -1;
 |  | ||||||
| -	} else
 |  | ||||||
| -		condlog(3, "No matching wwid [%s] in bindings file.", map_wwid);
 |  | ||||||
|  	return id; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int
 |  | ||||||
| -rlookup_binding(FILE *f, char *buff, const char *map_alias)
 |  | ||||||
| -{
 |  | ||||||
| -	char line[LINE_MAX];
 |  | ||||||
| -	unsigned int line_nr = 0;
 |  | ||||||
| -
 |  | ||||||
| -	buff[0] = '\0';
 |  | ||||||
| -
 |  | ||||||
| -	while (fgets(line, LINE_MAX, f)) {
 |  | ||||||
| -		char *c, *saveptr;
 |  | ||||||
| -		const char *alias, *wwid;
 |  | ||||||
| -
 |  | ||||||
| -		line_nr++;
 |  | ||||||
| -		c = strpbrk(line, "#\n\r");
 |  | ||||||
| -		if (c)
 |  | ||||||
| -			*c = '\0';
 |  | ||||||
| -		alias = strtok_r(line, " \t", &saveptr);
 |  | ||||||
| -		if (!alias) /* blank line */
 |  | ||||||
| -			continue;
 |  | ||||||
| -		wwid = strtok_r(NULL, " \t", &saveptr);
 |  | ||||||
| -		if (!wwid){
 |  | ||||||
| -			condlog(3,
 |  | ||||||
| -				"Ignoring malformed line %u in bindings file",
 |  | ||||||
| -				line_nr);
 |  | ||||||
| -			continue;
 |  | ||||||
| -		}
 |  | ||||||
| -		if (strlen(wwid) > WWID_SIZE - 1) {
 |  | ||||||
| -			condlog(3,
 |  | ||||||
| -				"Ignoring too large wwid at %u in bindings file", line_nr);
 |  | ||||||
| -			continue;
 |  | ||||||
| -		}
 |  | ||||||
| -		if (strcmp(alias, map_alias) == 0){
 |  | ||||||
| -			condlog(3, "Found matching alias [%s] in bindings file."
 |  | ||||||
| -				" Setting wwid to %s", alias, wwid);
 |  | ||||||
| -			strlcpy(buff, wwid, WWID_SIZE);
 |  | ||||||
| -			return 0;
 |  | ||||||
| -		}
 |  | ||||||
| -	}
 |  | ||||||
| -	condlog(3, "No matching alias [%s] in bindings file.", map_alias);
 |  | ||||||
| -
 |  | ||||||
| -	return -1;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
|  static char * |  | ||||||
| -allocate_binding(int fd, const char *wwid, int id, const char *prefix)
 |  | ||||||
| +allocate_binding(const char *filename, const char *wwid, int id, const char *prefix)
 |  | ||||||
|  { |  | ||||||
|  	STRBUF_ON_STACK(buf); |  | ||||||
| -	off_t offset;
 |  | ||||||
| -	ssize_t len;
 |  | ||||||
| -	char *alias, *c;
 |  | ||||||
| +	char *alias;
 |  | ||||||
|   |  | ||||||
|  	if (id <= 0) { |  | ||||||
|  		condlog(0, "%s: cannot allocate new binding for id %d", |  | ||||||
| @@ -460,164 +422,135 @@ allocate_binding(int fd, const char *wwid, int id, const char *prefix)
 |  | ||||||
|  	    format_devname(&buf, id) == -1) |  | ||||||
|  		return NULL; |  | ||||||
|   |  | ||||||
| -	if (print_strbuf(&buf, " %s\n", wwid) < 0)
 |  | ||||||
| -		return NULL;
 |  | ||||||
| +	alias = steal_strbuf_str(&buf);
 |  | ||||||
|   |  | ||||||
| -	offset = lseek(fd, 0, SEEK_END);
 |  | ||||||
| -	if (offset < 0){
 |  | ||||||
| -		condlog(0, "Cannot seek to end of bindings file : %s",
 |  | ||||||
| -			strerror(errno));
 |  | ||||||
| +	if (add_binding(&global_bindings, alias, wwid) != BINDING_ADDED) {
 |  | ||||||
| +		condlog(0, "%s: cannot allocate new binding %s for %s",
 |  | ||||||
| +			__func__, alias, wwid);
 |  | ||||||
| +		free(alias);
 |  | ||||||
|  		return NULL; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	len = get_strbuf_len(&buf);
 |  | ||||||
| -	alias = steal_strbuf_str(&buf);
 |  | ||||||
| -
 |  | ||||||
| -	if (write(fd, alias, len) != len) {
 |  | ||||||
| -		condlog(0, "Cannot write binding to bindings file : %s",
 |  | ||||||
| -			strerror(errno));
 |  | ||||||
| -		/* clear partial write */
 |  | ||||||
| -		if (ftruncate(fd, offset))
 |  | ||||||
| -			condlog(0, "Cannot truncate the header : %s",
 |  | ||||||
| -				strerror(errno));
 |  | ||||||
| +	if (update_bindings_file(&global_bindings, filename) == -1) {
 |  | ||||||
| +		condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid);
 |  | ||||||
| +		delete_binding(&global_bindings, wwid);
 |  | ||||||
|  		free(alias); |  | ||||||
|  		return NULL; |  | ||||||
|  	} |  | ||||||
| -	c = strchr(alias, ' ');
 |  | ||||||
| -	if (c)
 |  | ||||||
| -		*c = '\0';
 |  | ||||||
|   |  | ||||||
|  	condlog(3, "Created new binding [%s] for WWID [%s]", alias, wwid); |  | ||||||
|  	return alias; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +/*
 |  | ||||||
| + * get_user_friendly_alias() action table
 |  | ||||||
| + *
 |  | ||||||
| + * The table shows the various cases, the actions taken, and the CI
 |  | ||||||
| + * functions from tests/alias.c that represent them.
 |  | ||||||
| + *
 |  | ||||||
| + *  - O: old alias given
 |  | ||||||
| + *  - A: old alias in table (y: yes, correct WWID; X: yes, wrong WWID)
 |  | ||||||
| + *  - W: wwid in table
 |  | ||||||
| + *
 |  | ||||||
| + *  | No | O | A | W | action                                     | function gufa_X              |
 |  | ||||||
| + *  |----+---+---+---+--------------------------------------------+------------------------------|
 |  | ||||||
| + *  |  1 | n | - | n | get new alias                              | nomatch_Y                    |
 |  | ||||||
| + *  |  2 | n | - | y | use alias from bindings                    | match_a_Y                    |
 |  | ||||||
| + *  |  3 | y | n | n | add binding for old alias                  | old_nomatch_nowwidmatch      |
 |  | ||||||
| + *  |  4 | y | n | y | use alias from bindings (avoid duplicates) | old_nomatch_wwidmatch        |
 |  | ||||||
| + *  |  5 | y | y | n | [ impossible ]                             | -                            |
 |  | ||||||
| + *  |  6 | y | y | y | use old alias == alias from bindings       | old_match                    |
 |  | ||||||
| + *  |  7 | y | X | n | get new alias                              | old_match_other              |
 |  | ||||||
| + *  |  8 | y | X | y | use alias from bindings                    | old_match_other_wwidmatch    |
 |  | ||||||
| + *
 |  | ||||||
| + * Notes:
 |  | ||||||
| + *  - "use alias from bindings" means that the alias from the bindings file will
 |  | ||||||
| + *    be tried; if it is in use, the alias selection will fail. No other
 |  | ||||||
| + *    bindings will be attempted.
 |  | ||||||
| + *  - "get new alias" fails if all aliases are used up, or if writing the
 |  | ||||||
| + *    bindings file fails.
 |  | ||||||
| + *  - if "alias_old" is set, it can't be bound to a different map. alias_old is
 |  | ||||||
| + *    initialized in find_existing_alias() by scanning the mpvec. We trust
 |  | ||||||
| + *    that the mpvec corrcectly represents kernel state.
 |  | ||||||
| + */
 |  | ||||||
| +
 |  | ||||||
|  char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old, |  | ||||||
|  			      const char *prefix, bool bindings_read_only) |  | ||||||
|  { |  | ||||||
|  	char *alias = NULL; |  | ||||||
|  	int id = 0; |  | ||||||
| -	int fd, can_write;
 |  | ||||||
|  	bool new_binding = false; |  | ||||||
| -	char buff[WWID_SIZE];
 |  | ||||||
| -	FILE *f;
 |  | ||||||
| -
 |  | ||||||
| -	fd = open_file(file, &can_write, bindings_file_header);
 |  | ||||||
| -	if (fd < 0)
 |  | ||||||
| -		return NULL;
 |  | ||||||
| -
 |  | ||||||
| -	f = fdopen(fd, "r");
 |  | ||||||
| -	if (!f) {
 |  | ||||||
| -		condlog(0, "cannot fdopen on bindings file descriptor");
 |  | ||||||
| -		close(fd);
 |  | ||||||
| -		return NULL;
 |  | ||||||
| -	}
 |  | ||||||
| +	const struct binding *bdg;
 |  | ||||||
|   |  | ||||||
| -	if (!strlen(alias_old))
 |  | ||||||
| +	if (!*alias_old)
 |  | ||||||
|  		goto new_alias; |  | ||||||
|   |  | ||||||
| -	/* lookup the binding. if it exists, the wwid will be in buff
 |  | ||||||
| -	 * either way, id contains the id for the alias
 |  | ||||||
| -	 */
 |  | ||||||
| -	rlookup_binding(f, buff, alias_old);
 |  | ||||||
| -
 |  | ||||||
| -	if (strlen(buff) > 0) {
 |  | ||||||
| -		/* If buff is our wwid, it's already allocated correctly. */
 |  | ||||||
| -		if (strcmp(buff, wwid) == 0) {
 |  | ||||||
| +	/* See if there's a binding matching both alias_old and wwid */
 |  | ||||||
| +	bdg = get_binding_for_alias(&global_bindings, alias_old);
 |  | ||||||
| +	if (bdg) {
 |  | ||||||
| +		if (!strcmp(bdg->wwid, wwid)) {
 |  | ||||||
|  			alias = strdup(alias_old); |  | ||||||
|  			goto out; |  | ||||||
| -
 |  | ||||||
|  		} else { |  | ||||||
|  			condlog(0, "alias %s already bound to wwid %s, cannot reuse", |  | ||||||
| -				alias_old, buff);
 |  | ||||||
| +				alias_old, bdg->wwid);
 |  | ||||||
|  			goto new_alias; |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	/*
 |  | ||||||
| -	 * Look for an existing alias in the bindings file.
 |  | ||||||
| -	 * Pass prefix = NULL, so lookup_binding() won't try to allocate a new id.
 |  | ||||||
| -	 */
 |  | ||||||
| -	lookup_binding(f, wwid, &alias, NULL, 0);
 |  | ||||||
| -	if (alias) {
 |  | ||||||
| -		if (alias_already_taken(alias, wwid)) {
 |  | ||||||
| -			free(alias);
 |  | ||||||
| -			alias = NULL;
 |  | ||||||
| -		} else
 |  | ||||||
| +	/* allocate the existing alias in the bindings file */
 |  | ||||||
| +	id = scan_devname(alias_old, prefix);
 |  | ||||||
| +
 |  | ||||||
| +new_alias:
 |  | ||||||
| +	/* Check for existing binding of WWID */
 |  | ||||||
| +	bdg = get_binding_for_wwid(&global_bindings, wwid);
 |  | ||||||
| +	if (bdg) {
 |  | ||||||
| +		if (!alias_already_taken(bdg->alias, wwid)) {
 |  | ||||||
|  			condlog(3, "Use existing binding [%s] for WWID [%s]", |  | ||||||
| -				alias, wwid);
 |  | ||||||
| +				bdg->alias, wwid);
 |  | ||||||
| +			alias = strdup(bdg->alias);
 |  | ||||||
| +		}
 |  | ||||||
|  		goto out; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	/* alias_old is already taken by our WWID, update bindings file. */
 |  | ||||||
| -	id = scan_devname(alias_old, prefix);
 |  | ||||||
| -
 |  | ||||||
| -new_alias:
 |  | ||||||
|  	if (id <= 0) { |  | ||||||
|  		/* |  | ||||||
|  		 * no existing alias was provided, or allocating it |  | ||||||
|  		 * failed. Try a new one. |  | ||||||
|  		 */ |  | ||||||
| -		id = lookup_binding(f, wwid, &alias, prefix, 1);
 |  | ||||||
| -		if (id == 0 && alias_already_taken(alias, wwid)) {
 |  | ||||||
| -			free(alias);
 |  | ||||||
| -			alias = NULL;
 |  | ||||||
| -		}
 |  | ||||||
| +		id = get_free_id(&global_bindings, prefix, wwid);
 |  | ||||||
|  		if (id <= 0) |  | ||||||
|  			goto out; |  | ||||||
|  		else |  | ||||||
|  			new_binding = true; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	if (fflush(f) != 0) {
 |  | ||||||
| -		condlog(0, "cannot fflush bindings file stream : %s",
 |  | ||||||
| -			strerror(errno));
 |  | ||||||
| -		goto out;
 |  | ||||||
| -	}
 |  | ||||||
| +	if (!bindings_read_only && id > 0)
 |  | ||||||
| +		alias = allocate_binding(file, wwid, id, prefix);
 |  | ||||||
|   |  | ||||||
| -	if (can_write && !bindings_read_only) {
 |  | ||||||
| -		alias = allocate_binding(fd, wwid, id, prefix);
 |  | ||||||
| -		if (alias && !new_binding)
 |  | ||||||
| -			condlog(2, "Allocated existing binding [%s] for WWID [%s]",
 |  | ||||||
| -				alias, wwid);
 |  | ||||||
| -	}
 |  | ||||||
| +	if (alias && !new_binding)
 |  | ||||||
| +		condlog(2, "Allocated existing binding [%s] for WWID [%s]",
 |  | ||||||
| +			alias, wwid);
 |  | ||||||
|   |  | ||||||
|  out: |  | ||||||
| -	pthread_cleanup_push(free, alias);
 |  | ||||||
| -	fclose(f);
 |  | ||||||
| -	pthread_cleanup_pop(0);
 |  | ||||||
|  	return alias; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -int
 |  | ||||||
| -get_user_friendly_wwid(const char *alias, char *buff, const char *file)
 |  | ||||||
| +int get_user_friendly_wwid(const char *alias, char *buff)
 |  | ||||||
|  { |  | ||||||
| -	int fd, unused;
 |  | ||||||
| -	FILE *f;
 |  | ||||||
| +	const struct binding *bdg;
 |  | ||||||
|   |  | ||||||
|  	if (!alias || *alias == '\0') { |  | ||||||
|  		condlog(3, "Cannot find binding for empty alias"); |  | ||||||
|  		return -1; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	fd = open_file(file, &unused, bindings_file_header);
 |  | ||||||
| -	if (fd < 0)
 |  | ||||||
| -		return -1;
 |  | ||||||
| -
 |  | ||||||
| -	f = fdopen(fd, "r");
 |  | ||||||
| -	if (!f) {
 |  | ||||||
| -		condlog(0, "cannot fdopen on bindings file descriptor : %s",
 |  | ||||||
| -			strerror(errno));
 |  | ||||||
| -		close(fd);
 |  | ||||||
| +	bdg = get_binding_for_alias(&global_bindings, alias);
 |  | ||||||
| +	if (!bdg) {
 |  | ||||||
| +		*buff = '\0';
 |  | ||||||
|  		return -1; |  | ||||||
|  	} |  | ||||||
| -
 |  | ||||||
| -	rlookup_binding(f, buff, alias);
 |  | ||||||
| -	if (!strlen(buff)) {
 |  | ||||||
| -		fclose(f);
 |  | ||||||
| -		return -1;
 |  | ||||||
| -	}
 |  | ||||||
| -
 |  | ||||||
| -	fclose(f);
 |  | ||||||
| +	strlcpy(buff, bdg->wwid, WWID_SIZE);
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| diff --git a/libmultipath/alias.h b/libmultipath/alias.h
 |  | ||||||
| index 37b49d9c..5ef6720b 100644
 |  | ||||||
| --- a/libmultipath/alias.h
 |  | ||||||
| +++ b/libmultipath/alias.h
 |  | ||||||
| @@ -2,7 +2,7 @@
 |  | ||||||
|  #define _ALIAS_H |  | ||||||
|   |  | ||||||
|  int valid_alias(const char *alias); |  | ||||||
| -int get_user_friendly_wwid(const char *alias, char *buff, const char *file);
 |  | ||||||
| +int get_user_friendly_wwid(const char *alias, char *buff);
 |  | ||||||
|  char *get_user_friendly_alias(const char *wwid, const char *file, |  | ||||||
|  			      const char *alias_old, |  | ||||||
|  			      const char *prefix, bool bindings_read_only); |  | ||||||
| diff --git a/libmultipath/configure.c b/libmultipath/configure.c
 |  | ||||||
| index 029fbbd2..d8094903 100644
 |  | ||||||
| --- a/libmultipath/configure.c
 |  | ||||||
| +++ b/libmultipath/configure.c
 |  | ||||||
| @@ -1378,8 +1378,7 @@ static int _get_refwwid(enum mpath_cmds cmd, const char *dev,
 |  | ||||||
|  			refwwid = tmpwwid; |  | ||||||
|   |  | ||||||
|  		/* or may be a binding */ |  | ||||||
| -		else if (get_user_friendly_wwid(dev, tmpwwid,
 |  | ||||||
| -						conf->bindings_file) == 0)
 |  | ||||||
| +		else if (get_user_friendly_wwid(dev, tmpwwid) == 0)
 |  | ||||||
|  			refwwid = tmpwwid; |  | ||||||
|   |  | ||||||
|  		/* or may be an alias */ |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,53 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 25 Aug 2023 20:35:19 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: dm_get_uuid(): return emtpy UUID for |  | ||||||
|  non-existing maps |  | ||||||
| 
 |  | ||||||
| libdevmapper will most probably not return a UUID for non-existing |  | ||||||
| maps anyway. But it's cheap to double-check here. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/devmapper.c | 10 ++++++++-- |  | ||||||
|  1 file changed, 8 insertions(+), 2 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
 |  | ||||||
| index 248c3734..9be82f4e 100644
 |  | ||||||
| --- a/libmultipath/devmapper.c
 |  | ||||||
| +++ b/libmultipath/devmapper.c
 |  | ||||||
| @@ -706,12 +706,16 @@ 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; |  | ||||||
|   |  | ||||||
| @@ -720,11 +724,13 @@ dm_get_prefixed_uuid(const char *name, char *uuid, int uuid_len)
 |  | ||||||
|  		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); |  | ||||||
| -	else
 |  | ||||||
| -		uuid[0] = '\0';
 |  | ||||||
|   |  | ||||||
|  	r = 0; |  | ||||||
|  uuidout: |  | ||||||
| @ -1,158 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 28 Aug 2023 12:26:37 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: adapt to new semantics of dm_get_uuid() |  | ||||||
| 
 |  | ||||||
| dm_get_uuid() will return 1 for non-existing maps. Thus we don't need |  | ||||||
| to call dm_map_present() any more in alias_already_taken(). This changes |  | ||||||
| our semantics: previously we'd avoid using an alias for which dm_get_uuid() |  | ||||||
| had failed. Now we treat failure in dm_get_uuid() as indication that the |  | ||||||
| map doesn't exist. This is not dangerous because dm_task_get_uuid() cannot |  | ||||||
| fail, and thus the modified dm_get_uuid() will fail if and only if |  | ||||||
| dm_map_present() would return false. |  | ||||||
| 
 |  | ||||||
| This makes the "failed alias" test mostly obsolete, as "failed" is now |  | ||||||
| treated as "unused". |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 25 +++++++++++++------------ |  | ||||||
|  tests/alias.c        | 32 +++++++------------------------- |  | ||||||
|  2 files changed, 20 insertions(+), 37 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index d6563749..58436ec0 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -295,18 +295,19 @@ scan_devname(const char *alias, const char *prefix)
 |  | ||||||
|  static bool alias_already_taken(const char *alias, const char *map_wwid) |  | ||||||
|  { |  | ||||||
|   |  | ||||||
| -	if (dm_map_present(alias)) {
 |  | ||||||
| -		char wwid[WWID_SIZE];
 |  | ||||||
| -
 |  | ||||||
| -		/* If both the name and the wwid match, then it's fine.*/
 |  | ||||||
| -		if (dm_get_uuid(alias, wwid, sizeof(wwid)) == 0 &&
 |  | ||||||
| -		    strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
 |  | ||||||
| -			return false;
 |  | ||||||
| -		condlog(3, "%s: alias '%s' already taken, reselecting alias",
 |  | ||||||
| -			map_wwid, alias);
 |  | ||||||
| -		return true;
 |  | ||||||
| -	}
 |  | ||||||
| -	return false;
 |  | ||||||
| +	char wwid[WWID_SIZE];
 |  | ||||||
| +
 |  | ||||||
| +	/* If the map doesn't exist, it's fine */
 |  | ||||||
| +	if (dm_get_uuid(alias, wwid, sizeof(wwid)) != 0)
 |  | ||||||
| +		return false;
 |  | ||||||
| +
 |  | ||||||
| +	/* If both the name and the wwid match, it's fine.*/
 |  | ||||||
| +	if (strncmp(map_wwid, wwid, sizeof(wwid)) == 0)
 |  | ||||||
| +		return false;
 |  | ||||||
| +
 |  | ||||||
| +	condlog(3, "%s: alias '%s' already taken, reselecting alias",
 |  | ||||||
| +		map_wwid, alias);
 |  | ||||||
| +	return true;
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static bool id_already_taken(int id, const char *prefix, const char *map_wwid) |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 50a21ecf..d1cc487b 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -73,12 +73,6 @@ int __wrap_mkstemp(char *template)
 |  | ||||||
|  	return 10; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -int __wrap_dm_map_present(const char * str)
 |  | ||||||
| -{
 |  | ||||||
| -	check_expected(str);
 |  | ||||||
| -	return mock_type(int);
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
|  int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len) |  | ||||||
|  { |  | ||||||
|  	int ret; |  | ||||||
| @@ -398,14 +392,13 @@ static int test_scan_devname(void)
 |  | ||||||
|   |  | ||||||
|  static void mock_unused_alias(const char *alias) |  | ||||||
|  { |  | ||||||
| -	expect_string(__wrap_dm_map_present, str, alias);
 |  | ||||||
| -	will_return(__wrap_dm_map_present, 0);
 |  | ||||||
| +	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);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static void mock_self_alias(const char *alias, const char *wwid) |  | ||||||
|  { |  | ||||||
| -	expect_string(__wrap_dm_map_present, str, alias);
 |  | ||||||
| -	will_return(__wrap_dm_map_present, 1);
 |  | ||||||
|  	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); |  | ||||||
| @@ -432,18 +425,13 @@ static void mock_self_alias(const char *alias, const char *wwid)
 |  | ||||||
|   |  | ||||||
|  #define mock_failed_alias(alias, wwid)					\ |  | ||||||
|  	do {								\ |  | ||||||
| -		expect_string(__wrap_dm_map_present, str, alias);	\
 |  | ||||||
| -		will_return(__wrap_dm_map_present, 1);			\
 |  | ||||||
|  		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_condlog(3, USED_STR(alias, wwid));		\
 |  | ||||||
|  	} while (0) |  | ||||||
|   |  | ||||||
|  #define mock_used_alias(alias, wwid)					\ |  | ||||||
|  	do {								\ |  | ||||||
| -		expect_string(__wrap_dm_map_present, str, alias);	\
 |  | ||||||
| -		will_return(__wrap_dm_map_present, 1);			\
 |  | ||||||
|  		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);			\ |  | ||||||
| @@ -566,9 +554,8 @@ static void lb_empty_failed(void **state)
 |  | ||||||
|  	mock_bindings_file(""); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	mock_failed_alias("MPATHa", "WWID0"); |  | ||||||
| -	mock_unused_alias("MPATHb");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, 2);
 |  | ||||||
| +	assert_int_equal(rc, 1);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -666,9 +653,8 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
 |  | ||||||
|  	mock_used_alias("MPATHc", "WWID1"); |  | ||||||
|  	mock_used_alias("MPATHd", "WWID1"); |  | ||||||
|  	mock_failed_alias("MPATHe", "WWID1"); |  | ||||||
| -	mock_self_alias("MPATHf", "WWID1");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, 6);
 |  | ||||||
| +	assert_int_equal(rc, 5);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -940,7 +926,7 @@ static void lb_nomatch_b_a_aa(void **state)
 |  | ||||||
|   |  | ||||||
|  static void lb_nomatch_b_a_aa_zz(void **state) |  | ||||||
|  { |  | ||||||
| -	int rc, i;
 |  | ||||||
| +	int rc;
 |  | ||||||
|  	char *alias; |  | ||||||
|  	STRBUF_ON_STACK(buf); |  | ||||||
|   |  | ||||||
| @@ -949,11 +935,7 @@ static void lb_nomatch_b_a_aa_zz(void **state)
 |  | ||||||
|  	 * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is |  | ||||||
|  	 * found before MPATHb, and MPATHzz was in the bindings, too. |  | ||||||
|  	 */ |  | ||||||
| -	for (i = 0; i <= 26; i++) {
 |  | ||||||
| -		print_strbuf(&buf,  "MPATH");
 |  | ||||||
| -		format_devname(&buf, i + 1);
 |  | ||||||
| -		print_strbuf(&buf,  " WWID%d\n", i);
 |  | ||||||
| -	}
 |  | ||||||
| +	fill_bindings(&buf, 0, 26);
 |  | ||||||
|  	print_strbuf(&buf, "MPATHzz WWID676\n"); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID703")); |  | ||||||
| @ -1,98 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 15:19:54 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: sort aliases by length and strcmp |  | ||||||
| 
 |  | ||||||
| The current sort order of aliases is alphabetical, which is does not match |  | ||||||
| the actual order of aliases, where "mpathaa" > "mpathz". Change the ordering as |  | ||||||
| follows: first sort by string length, then alphabetically. This will make |  | ||||||
| sure that for aliases with the same prefix, alias order is correct ("mpathaaa" |  | ||||||
| will be sorted after "mpathzz", etc). Even for mixed prefixes, the alias |  | ||||||
| order will be correct for every individual prefix, even though aliases with |  | ||||||
| different prefixes may alternate in the file.
 |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 45 +++++++++++++++++++++++++++++++++----------- |  | ||||||
|  1 file changed, 34 insertions(+), 11 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 58436ec0..af6565b1 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -117,6 +117,35 @@ static const struct binding *get_binding_for_wwid(const Bindings *bindings,
 |  | ||||||
|  	return NULL; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +/*
 |  | ||||||
| + * Sort order for aliases.
 |  | ||||||
| + *
 |  | ||||||
| + * The "numeric" ordering of aliases for a given prefix P is
 |  | ||||||
| + * Pa, ..., Pz, Paa, ..., Paz, Pba, ... , Pzz, Paaa, ..., Pzzz, Paaaa, ...
 |  | ||||||
| + * We use the fact that for equal prefix, longer strings are always
 |  | ||||||
| + * higher than shorter ones. Strings of equal length are sorted alphabetically.
 |  | ||||||
| + * This is achieved by sorting be length first, then using strcmp().
 |  | ||||||
| + * If multiple prefixes are in use, the aliases with a given prefix will
 |  | ||||||
| + * not necessarily be in a contiguous range of the vector, but they will
 |  | ||||||
| + * be ordered such that for a given prefix, numercally higher aliases will
 |  | ||||||
| + * always be sorted after lower ones.
 |  | ||||||
| + */
 |  | ||||||
| +static int alias_compar(const void *p1, const void *p2)
 |  | ||||||
| +{
 |  | ||||||
| +	const char *alias1 = *((char * const *)p1);
 |  | ||||||
| +	const char *alias2 = *((char * const *)p2);
 |  | ||||||
| +
 |  | ||||||
| +	if (alias1 && alias2) {
 |  | ||||||
| +		ssize_t ldif = strlen(alias1) - strlen(alias2);
 |  | ||||||
| +
 |  | ||||||
| +		if (ldif)
 |  | ||||||
| +			return ldif;
 |  | ||||||
| +		return strcmp(alias1, alias2);
 |  | ||||||
| +	} else
 |  | ||||||
| +		/* Move NULL alias to the end */
 |  | ||||||
| +		return alias1 ? -1 : alias2 ? 1 : 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static int add_binding(Bindings *bindings, const char *alias, const char *wwid) |  | ||||||
|  { |  | ||||||
|  	struct binding *bdg; |  | ||||||
| @@ -128,7 +157,7 @@ static int add_binding(Bindings *bindings, const char *alias, const char *wwid)
 |  | ||||||
|  	 * sorted already. |  | ||||||
|  	 */ |  | ||||||
|  	vector_foreach_slot_backwards(bindings, bdg, i) { |  | ||||||
| -		if ((cmp = strcmp(bdg->alias, alias)) <= 0)
 |  | ||||||
| +		if ((cmp = alias_compar(&bdg->alias, &alias)) <= 0)
 |  | ||||||
|  			break; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| @@ -657,16 +686,10 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
 |  | ||||||
|  	return rc; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int alias_compar(const void *p1, const void *p2)
 |  | ||||||
| +static int mp_alias_compar(const void *p1, const void *p2)
 |  | ||||||
|  { |  | ||||||
| -	const char *alias1 = (*(struct mpentry * const *)p1)->alias;
 |  | ||||||
| -	const char *alias2 = (*(struct mpentry * const *)p2)->alias;
 |  | ||||||
| -
 |  | ||||||
| -	if (alias1 && alias2)
 |  | ||||||
| -		return strcmp(alias1, alias2);
 |  | ||||||
| -	else
 |  | ||||||
| -		/* Move NULL alias to the end */
 |  | ||||||
| -		return alias1 ? -1 : alias2 ? 1 : 0;
 |  | ||||||
| +	return alias_compar(&((*(struct mpentry * const *)p1)->alias),
 |  | ||||||
| +			    &((*(struct mpentry * const *)p2)->alias));
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
| @@ -700,7 +723,7 @@ int check_alias_settings(const struct config *conf)
 |  | ||||||
|  	pthread_cleanup_push_cast(free_bindings, &bindings); |  | ||||||
|  	pthread_cleanup_push(cleanup_vector_free, mptable); |  | ||||||
|   |  | ||||||
| -	vector_sort(mptable, alias_compar);
 |  | ||||||
| +	vector_sort(mptable, mp_alias_compar);
 |  | ||||||
|  	vector_foreach_slot(mptable, mpe, i) { |  | ||||||
|  		if (!mpe->alias) |  | ||||||
|  			/* |  | ||||||
| @ -1,90 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 15:46:02 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools tests: fix alias test after sort order change |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 30 ++++++++++++------------------ |  | ||||||
|  1 file changed, 12 insertions(+), 18 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index d1cc487b..8ed95d7a 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -932,16 +932,15 @@ static void lb_nomatch_b_a_aa_zz(void **state)
 |  | ||||||
|   |  | ||||||
|  	/* |  | ||||||
|  	 * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...) |  | ||||||
| -	 * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is
 |  | ||||||
| -	 * found before MPATHb, and MPATHzz was in the bindings, too.
 |  | ||||||
| +	 * lookup_binding finds MPATHab as next free entry.
 |  | ||||||
|  	 */ |  | ||||||
|  	fill_bindings(&buf, 0, 26); |  | ||||||
|  	print_strbuf(&buf, "MPATHzz WWID676\n"); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID703")); |  | ||||||
| -	mock_unused_alias("MPATHaaa");
 |  | ||||||
| +	mock_unused_alias("MPATHab");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, 703);
 |  | ||||||
| +	assert_int_equal(rc, 28);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -998,13 +997,8 @@ static void lb_nomatch_b_a_3_used(void **state)
 |  | ||||||
|   |  | ||||||
|  #ifdef MPATH_ID_INT_MAX |  | ||||||
|  /* |  | ||||||
| - * The bindings will be sorted by alias, alphabetically, which is not
 |  | ||||||
| - * the same as the "numeric" sort order for user-friendly aliases.
 |  | ||||||
| - * get_free_id() selects the highest used ID + 1 if an unsorted entry
 |  | ||||||
| - * is encountered in the bindings table and it's id is equal to the
 |  | ||||||
| - * next "expected" id. This happens if all IDs from "a" to "aa" are
 |  | ||||||
| - * in the table. If the INT_MAX entry is in the table, too, it will
 |  | ||||||
| - * overflow.
 |  | ||||||
| + * The bindings will be sorted by alias. Therefore we have no chance to
 |  | ||||||
| + * simulate a "full" table.
 |  | ||||||
|   */ |  | ||||||
|  static void lb_nomatch_int_max(void **state) |  | ||||||
|  { |  | ||||||
| @@ -1016,9 +1010,9 @@ static void lb_nomatch_int_max(void **state)
 |  | ||||||
|  	print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); |  | ||||||
| -	expect_condlog(0, NOMORE_STR);
 |  | ||||||
| +	mock_unused_alias("MPATHab");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, -1);
 |  | ||||||
| +	assert_int_equal(rc, 28);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1049,9 +1043,9 @@ static void lb_nomatch_int_max_m1(void **state)
 |  | ||||||
|  	print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); |  | ||||||
| -	mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
 |  | ||||||
| +	mock_unused_alias("MPATHab");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, INT_MAX);
 |  | ||||||
| +	assert_int_equal(rc, 28);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1065,10 +1059,10 @@ static void lb_nomatch_int_max_m1_used(void **state)
 |  | ||||||
|  	print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); |  | ||||||
| -	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX");
 |  | ||||||
| -	expect_condlog(0, NOMORE_STR);
 |  | ||||||
| +	mock_used_alias("MPATHab", "WWIDMAX");
 |  | ||||||
| +	mock_unused_alias("MPATHac");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, -1);
 |  | ||||||
| +	assert_int_equal(rc, 29);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @ -1,122 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 19:50:51 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: simplify get_free_id() assuming total ordering |  | ||||||
| 
 |  | ||||||
| If we can assume that the bindings array is totally ordered for every |  | ||||||
| prefix, which the previous patch guarantees, the search for a free ID can be |  | ||||||
| simplified. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c | 85 ++++++++++---------------------------------- |  | ||||||
|  1 file changed, 18 insertions(+), 67 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index af6565b1..66e34e31 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -356,83 +356,34 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww
 |  | ||||||
|  { |  | ||||||
|  	const struct binding *bdg; |  | ||||||
|  	int i, id = 1; |  | ||||||
| -	int biggest_id = 1;
 |  | ||||||
| -	int smallest_bigger_id = INT_MAX;
 |  | ||||||
|   |  | ||||||
|  	vector_foreach_slot(bindings, bdg, i) { |  | ||||||
|  		int curr_id = scan_devname(bdg->alias, prefix); |  | ||||||
|   |  | ||||||
| -		/*
 |  | ||||||
| -		 * Find an unused index - explanation of the algorithm
 |  | ||||||
| -		 *
 |  | ||||||
| -		 * ID: 1 = mpatha, 2 = mpathb, ...
 |  | ||||||
| -		 *
 |  | ||||||
| -		 * We assume the bindings are unsorted. The only constraint
 |  | ||||||
| -		 * is that no ID occurs more than once. IDs that occur in the
 |  | ||||||
| -		 * bindings are called "used".
 |  | ||||||
| -		 *
 |  | ||||||
| -		 * We call the list 1,2,3,..., exactly in this order, the list
 |  | ||||||
| -		 * of "expected" IDs. The variable "id" always holds the next
 |  | ||||||
| -		 * "expected" ID, IOW the last "expected" ID encountered plus 1.
 |  | ||||||
| -		 * Thus all IDs below "id" are known to be used. However, at the
 |  | ||||||
| -		 * end of the loop, the value of "id" isn't necessarily unused.
 |  | ||||||
| -		 *
 |  | ||||||
| -		 * "smallest_bigger_id" is the smallest used ID that was
 |  | ||||||
| -		 * encountered while it was larger than the next "expected" ID
 |  | ||||||
| -		 * at that iteration. Let X be some used ID. If all IDs below X
 |  | ||||||
| -		 * are used and encountered in the right sequence before X, "id"
 |  | ||||||
| -		 * will be > X when the loop ends. Otherwise, X was encountered
 |  | ||||||
| -		 * "out of order", the condition (X > id) holds when X is
 |  | ||||||
| -		 * encountered, and "smallest_bigger_id" will be set to X; i.e.
 |  | ||||||
| -		 * it will be less or equal than X when the loop ends.
 |  | ||||||
| -		 *
 |  | ||||||
| -		 * At the end of the loop, (id < smallest_bigger_id) means that
 |  | ||||||
| -		 * the value of "id" had been encountered neither in order nor
 |  | ||||||
| -		 * out of order, and is thus unused. (id >= smallest_bigger_id)
 |  | ||||||
| -		 * means that "id"'s value is in use. In this case, we play safe
 |  | ||||||
| -		 * and use "biggest_id + 1" as the next value to try.
 |  | ||||||
| -		 *
 |  | ||||||
| -		 * biggest_id is always > smallest_bigger_id, except in the
 |  | ||||||
| -		 * "perfectly ordered" case.
 |  | ||||||
| -		 */
 |  | ||||||
| -		if (curr_id == id) {
 |  | ||||||
| -			if (id < INT_MAX)
 |  | ||||||
| -				id++;
 |  | ||||||
| -			else {
 |  | ||||||
| -				id = -1;
 |  | ||||||
| -				break;
 |  | ||||||
| -			}
 |  | ||||||
| +		if (curr_id == -1)
 |  | ||||||
| +			continue;
 |  | ||||||
| +		if (id > curr_id) {
 |  | ||||||
| +			condlog(0, "%s: ERROR: bindings are not sorted", __func__);
 |  | ||||||
| +			return -1;
 |  | ||||||
|  		} |  | ||||||
| -		if (curr_id > biggest_id)
 |  | ||||||
| -			biggest_id = curr_id;
 |  | ||||||
| -
 |  | ||||||
| -		if (curr_id > id && curr_id < smallest_bigger_id)
 |  | ||||||
| -			smallest_bigger_id = curr_id;
 |  | ||||||
| +		while (id < curr_id && id_already_taken(id, prefix, map_wwid))
 |  | ||||||
| +			id++;
 |  | ||||||
| +		if (id < curr_id)
 |  | ||||||
| +			return id;
 |  | ||||||
| +		id++;
 |  | ||||||
| +		if (id <= 0)
 |  | ||||||
| +			break;
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	if (id >= smallest_bigger_id)
 |  | ||||||
| -		id = biggest_id < INT_MAX ? biggest_id + 1 : -1;
 |  | ||||||
| -
 |  | ||||||
| -	if (id > 0) {
 |  | ||||||
| -		while(id_already_taken(id, prefix, map_wwid)) {
 |  | ||||||
| -			if (id == INT_MAX) {
 |  | ||||||
| -				id = -1;
 |  | ||||||
| -				break;
 |  | ||||||
| -			}
 |  | ||||||
| -			id++;
 |  | ||||||
| -			if (id == smallest_bigger_id) {
 |  | ||||||
| -				if (biggest_id == INT_MAX) {
 |  | ||||||
| -					id = -1;
 |  | ||||||
| -					break;
 |  | ||||||
| -				}
 |  | ||||||
| -				if (biggest_id >= smallest_bigger_id)
 |  | ||||||
| -					id = biggest_id + 1;
 |  | ||||||
| -			}
 |  | ||||||
| -		}
 |  | ||||||
| +	for (; id > 0; id++) {
 |  | ||||||
| +		if (!id_already_taken(id, prefix, map_wwid))
 |  | ||||||
| +			break;
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	if (id < 0)
 |  | ||||||
| +	if (id <= 0) {
 |  | ||||||
| +		id = -1;
 |  | ||||||
|  		condlog(0, "no more available user_friendly_names"); |  | ||||||
| +	}
 |  | ||||||
|  	return id; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @ -1,203 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 19:58:03 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools tests: adapt alias tests for total ordering |  | ||||||
| 
 |  | ||||||
| The "unsorted" test fail now, and are removed. The algorithm is now |  | ||||||
| better at finding "gaps". |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 88 ++++++++------------------------------------------- |  | ||||||
|  1 file changed, 14 insertions(+), 74 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 8ed95d7a..dff5f93b 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -439,27 +439,7 @@ static void mock_self_alias(const char *alias, const char *wwid)
 |  | ||||||
|  		expect_condlog(3, USED_STR(alias, wwid));		\ |  | ||||||
|  	} while(0) |  | ||||||
|   |  | ||||||
| -static int add_binding_unsorted(Bindings *bindings,
 |  | ||||||
| -				const char *alias, const char *wwid)
 |  | ||||||
| -{
 |  | ||||||
| -	struct binding *bdg = calloc(1, sizeof(*bdg));
 |  | ||||||
| -
 |  | ||||||
| -	if (!bdg)
 |  | ||||||
| -		return -1;
 |  | ||||||
| -	bdg->wwid = strdup(wwid);
 |  | ||||||
| -	bdg->alias = strdup(alias);
 |  | ||||||
| -	if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) {
 |  | ||||||
| -		free(bdg->alias);
 |  | ||||||
| -		free(bdg->wwid);
 |  | ||||||
| -		free(bdg);
 |  | ||||||
| -		return BINDING_ERROR;
 |  | ||||||
| -	}
 |  | ||||||
| -	vector_set_slot(bindings, bdg);
 |  | ||||||
| -	return BINDING_ADDED;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
| -static void __mock_bindings_file(const char *content,
 |  | ||||||
| -				 int (*add)(Bindings *, const char *, const char *))
 |  | ||||||
| +static void __mock_bindings_file(const char *content)
 |  | ||||||
|  { |  | ||||||
|  	char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; |  | ||||||
|  	char *token, *savep = NULL; |  | ||||||
| @@ -478,17 +458,13 @@ static void __mock_bindings_file(const char *content,
 |  | ||||||
|  		    == READ_BINDING_SKIP) |  | ||||||
|  			continue; |  | ||||||
|   |  | ||||||
| -		rc = add(&global_bindings, alias, wwid);
 |  | ||||||
| +		rc = add_binding(&global_bindings, alias, wwid);
 |  | ||||||
|  		assert_int_equal(rc, BINDING_ADDED); |  | ||||||
|  	} |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static void mock_bindings_file(const char *content) { |  | ||||||
| -	return __mock_bindings_file(content, add_binding);
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
| -static void mock_bindings_file_unsorted(const char *content) {
 |  | ||||||
| -	return __mock_bindings_file(content, add_binding_unsorted);
 |  | ||||||
| +	return __mock_bindings_file(content);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static int teardown_bindings(void **state) |  | ||||||
| @@ -861,10 +837,6 @@ static void lb_nomatch_b_z_a(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	/*
 |  | ||||||
| -	 * add_bindings() sorts alphabetically. Therefore get_free_id()
 |  | ||||||
| -	 * finds MPATHc as a free entry.
 |  | ||||||
| -	 */
 |  | ||||||
|  	mock_bindings_file("MPATHb WWID1\n" |  | ||||||
|  			   "MPATHz WWID26\n" |  | ||||||
|  			   "MPATHa WWID0\n"); |  | ||||||
| @@ -880,10 +852,6 @@ static void lb_nomatch_b_aa_a(void **state)
 |  | ||||||
|  	int rc; |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
| -	/*
 |  | ||||||
| -	 * add_bindings() sorts alphabetically. ("a", "aa", b").
 |  | ||||||
| -	 * The get_free_id() algorithm finds the "hole" after "b".
 |  | ||||||
| -	 */
 |  | ||||||
|  	mock_bindings_file("MPATHb WWID1\n" |  | ||||||
|  			   "MPATHz WWID26\n" |  | ||||||
|  			   "MPATHa WWID0\n"); |  | ||||||
| @@ -911,10 +879,6 @@ static void lb_nomatch_b_a_aa(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|  	STRBUF_ON_STACK(buf); |  | ||||||
|   |  | ||||||
| -	/*
 |  | ||||||
| -	 * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
 |  | ||||||
| -	 * lookup_binding finds MPATHac as next free entry.
 |  | ||||||
| -	 */
 |  | ||||||
|  	fill_bindings(&buf, 0, 26); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID28")); |  | ||||||
| @@ -930,10 +894,6 @@ static void lb_nomatch_b_a_aa_zz(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|  	STRBUF_ON_STACK(buf); |  | ||||||
|   |  | ||||||
| -	/*
 |  | ||||||
| -	 * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
 |  | ||||||
| -	 * lookup_binding finds MPATHab as next free entry.
 |  | ||||||
| -	 */
 |  | ||||||
|  	fill_bindings(&buf, 0, 26); |  | ||||||
|  	print_strbuf(&buf, "MPATHzz WWID676\n"); |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
| @@ -944,25 +904,6 @@ static void lb_nomatch_b_a_aa_zz(void **state)
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static void lb_nomatch_b_z_a_unsorted(void **state)
 |  | ||||||
| -{
 |  | ||||||
| -	int rc;
 |  | ||||||
| -	char *alias;
 |  | ||||||
| -
 |  | ||||||
| -	/*
 |  | ||||||
| -	 * With unsorted bindings (shouldn't happen normally), get_free_id()
 |  | ||||||
| -	 * plays safe and returns MPATHaa as first free entry.
 |  | ||||||
| -	 */
 |  | ||||||
| -	mock_bindings_file_unsorted("MPATHb WWID1\n"
 |  | ||||||
| -				    "MPATHz WWID26\n"
 |  | ||||||
| -				    "MPATHa WWID0\n");
 |  | ||||||
| -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
 |  | ||||||
| -	mock_unused_alias("MPATHaa");
 |  | ||||||
| -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
 |  | ||||||
| -	assert_int_equal(rc, 27);
 |  | ||||||
| -	assert_ptr_equal(alias, NULL);
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
|  static void lb_nomatch_b_a(void **state) |  | ||||||
|  { |  | ||||||
|  	int rc; |  | ||||||
| @@ -1027,9 +968,9 @@ static void lb_nomatch_int_max_used(void **state)
 |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE")); |  | ||||||
|  	mock_used_alias("MPATHa", "WWIDNOMORE"); |  | ||||||
| -	expect_condlog(0, NOMORE_STR);
 |  | ||||||
| +	mock_unused_alias("MPATHab");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, -1);
 |  | ||||||
| +	assert_int_equal(rc, 28);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1077,9 +1018,9 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
 |  | ||||||
|  	mock_bindings_file(get_strbuf_str(&buf)); |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); |  | ||||||
|  	mock_used_alias("MPATHa", "WWIDMAX"); |  | ||||||
| -	mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
 |  | ||||||
| +	mock_unused_alias("MPATHab");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, INT_MAX);
 |  | ||||||
| +	assert_int_equal(rc, 28);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1095,10 +1036,10 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
 |  | ||||||
|   |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX")); |  | ||||||
|  	mock_used_alias("MPATHa", "WWIDMAX"); |  | ||||||
| -	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX");
 |  | ||||||
| -	expect_condlog(0, NOMORE_STR);
 |  | ||||||
| +	mock_used_alias("MPATHab", "WWIDMAX");
 |  | ||||||
| +	mock_unused_alias("MPATHac");
 |  | ||||||
|  	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1); |  | ||||||
| -	assert_int_equal(rc, -1);
 |  | ||||||
| +	assert_int_equal(rc, 29);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|  #endif |  | ||||||
| @@ -1133,7 +1074,6 @@ static int test_lookup_binding(void)
 |  | ||||||
|  		cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings), |  | ||||||
|  		cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings), |  | ||||||
|  		cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings), |  | ||||||
| -		cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings),
 |  | ||||||
|  		cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings), |  | ||||||
|  		cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings), |  | ||||||
|  #ifdef MPATH_ID_INT_MAX |  | ||||||
| @@ -1593,14 +1533,14 @@ static void gufa_nomatch_b_f_a(void **state) {
 |  | ||||||
|  				 "MPATHf WWID6\n" |  | ||||||
|  				 "MPATHa WWID0\n"); |  | ||||||
|   |  | ||||||
| -	mock_bindings_file_unsorted(bindings);
 |  | ||||||
| +	mock_bindings_file(bindings);
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID7")); |  | ||||||
| -	mock_unused_alias("MPATHg");
 |  | ||||||
| +	mock_unused_alias("MPATHc");
 |  | ||||||
|   |  | ||||||
| -	mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1);
 |  | ||||||
| +	mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1);
 |  | ||||||
|   |  | ||||||
|  	alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false); |  | ||||||
| -	assert_string_equal(alias, "MPATHg");
 |  | ||||||
| +	assert_string_equal(alias, "MPATHc");
 |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @ -1,275 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 21:39:44 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools tests: add test for ordering of bindings |  | ||||||
| 
 |  | ||||||
| As the assignment of free aliases now relies on the bindings being |  | ||||||
| properly sorted, add some unit tests to make sure the sorting algorithm |  | ||||||
| works. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/alias.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++- |  | ||||||
|  1 file changed, 209 insertions(+), 3 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index dff5f93b..7f3ff38a 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -13,6 +13,9 @@
 |  | ||||||
|  #include "globals.c" |  | ||||||
|  #include "../libmultipath/alias.c" |  | ||||||
|   |  | ||||||
| +/* For verbose printing of all aliases in the ordering tests */
 |  | ||||||
| +#define ALIAS_DEBUG 0
 |  | ||||||
| +
 |  | ||||||
|  #if INT_MAX == 0x7fffffff |  | ||||||
|  /* user_friendly_name for map #INT_MAX */ |  | ||||||
|  #define MPATH_ID_INT_MAX "fxshrxw" |  | ||||||
| @@ -439,11 +442,12 @@ static void mock_self_alias(const char *alias, const char *wwid)
 |  | ||||||
|  		expect_condlog(3, USED_STR(alias, wwid));		\ |  | ||||||
|  	} while(0) |  | ||||||
|   |  | ||||||
| -static void __mock_bindings_file(const char *content)
 |  | ||||||
| +static void __mock_bindings_file(const char *content, bool conflict_ok)
 |  | ||||||
|  { |  | ||||||
|  	char *cnt __attribute__((cleanup(cleanup_charp))) = NULL; |  | ||||||
|  	char *token, *savep = NULL; |  | ||||||
|  	int i; |  | ||||||
| +	uintmax_t values[] = { BINDING_ADDED, BINDING_CONFLICT };
 |  | ||||||
|   |  | ||||||
|  	cnt = strdup(content); |  | ||||||
|  	assert_ptr_not_equal(cnt, NULL); |  | ||||||
| @@ -459,12 +463,12 @@ static void __mock_bindings_file(const char *content)
 |  | ||||||
|  			continue; |  | ||||||
|   |  | ||||||
|  		rc = add_binding(&global_bindings, alias, wwid); |  | ||||||
| -		assert_int_equal(rc, BINDING_ADDED);
 |  | ||||||
| +		assert_in_set(rc, values, conflict_ok ? 2 : 1);
 |  | ||||||
|  	} |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static void mock_bindings_file(const char *content) { |  | ||||||
| -	return __mock_bindings_file(content);
 |  | ||||||
| +	return __mock_bindings_file(content, false);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static int teardown_bindings(void **state) |  | ||||||
| @@ -1744,6 +1748,207 @@ static int test_get_user_friendly_alias()
 |  | ||||||
|  	return cmocka_run_group_tests(tests, NULL, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +/* Numbers 1-1000, randomly shuffled */
 |  | ||||||
| +static const int random_numbers[1000] = {
 |  | ||||||
| +	694, 977, 224, 178, 841, 818, 914, 549, 831, 942, 263, 834, 919, 800,
 |  | ||||||
| +	111, 517, 719, 297, 988, 98, 332, 516, 754, 772, 495, 488, 331, 529,
 |  | ||||||
| +	142, 747, 848, 618, 375, 624, 74, 753, 782, 944, 623, 468, 862, 997,
 |  | ||||||
| +	417, 258, 298, 774, 673, 904, 883, 766, 867, 400, 11, 950, 14, 784,
 |  | ||||||
| +	655, 155, 396, 9, 743, 93, 651, 245, 968, 306, 785, 581, 880, 486,
 |  | ||||||
| +	168, 631, 203, 4, 663, 294, 702, 762, 619, 684, 48, 181, 21, 443, 643,
 |  | ||||||
| +	863, 1000, 327, 26, 126, 382, 765, 586, 76, 49, 925, 319, 865, 797,
 |  | ||||||
| +	876, 693, 334, 433, 243, 419, 901, 854, 326, 985, 347, 874, 527, 282,
 |  | ||||||
| +	290, 380, 167, 95, 3, 257, 936, 60, 426, 227, 345, 577, 492, 467, 580,
 |  | ||||||
| +	967, 422, 823, 718, 610, 64, 700, 412, 163, 288, 506, 828, 432, 51,
 |  | ||||||
| +	356, 348, 539, 478, 17, 945, 602, 123, 450, 660, 429, 113, 310, 358,
 |  | ||||||
| +	512, 758, 508, 19, 542, 304, 286, 446, 918, 723, 333, 603, 731, 978,
 |  | ||||||
| +	230, 697, 109, 872, 175, 853, 947, 965, 121, 222, 101, 811, 117, 601,
 |  | ||||||
| +	191, 752, 384, 415, 938, 278, 915, 715, 240, 552, 912, 838, 150, 840,
 |  | ||||||
| +	627, 29, 636, 464, 861, 481, 992, 249, 934, 82, 368, 724, 807, 593,
 |  | ||||||
| +	157, 147, 199, 637, 41, 62, 902, 505, 621, 342, 174, 260, 729, 961,
 |  | ||||||
| +	219, 311, 629, 789, 81, 739, 860, 712, 223, 165, 741, 981, 485, 363,
 |  | ||||||
| +	346, 709, 125, 369, 279, 634, 399, 162, 193, 769, 149, 314, 868, 612,
 |  | ||||||
| +	524, 675, 341, 343, 476, 606, 388, 613, 850, 264, 903, 451, 908, 779,
 |  | ||||||
| +	453, 148, 497, 46, 132, 43, 885, 955, 269, 395, 72, 128, 767, 989,
 |  | ||||||
| +	929, 423, 742, 55, 13, 79, 924, 182, 295, 563, 668, 169, 974, 154,
 |  | ||||||
| +	970, 54, 674, 52, 437, 570, 550, 531, 554, 793, 678, 218, 367, 105,
 |  | ||||||
| +	197, 315, 958, 892, 86, 47, 284, 37, 561, 522, 198, 689, 817, 573,
 |  | ||||||
| +	877, 201, 803, 501, 881, 546, 530, 523, 780, 579, 953, 135, 23, 620,
 |  | ||||||
| +	84, 698, 303, 656, 357, 323, 494, 58, 131, 913, 995, 120, 70, 1, 195,
 |  | ||||||
| +	365, 210, 25, 898, 173, 307, 239, 77, 418, 952, 963, 92, 455, 425, 12,
 |  | ||||||
| +	536, 161, 328, 933, 401, 251, 735, 725, 362, 322, 557, 681, 302, 53,
 |  | ||||||
| +	786, 801, 391, 946, 748, 133, 717, 851, 7, 372, 993, 387, 906, 373,
 |  | ||||||
| +	667, 33, 670, 389, 209, 611, 896, 652, 69, 999, 344, 845, 633, 36,
 |  | ||||||
| +	487, 192, 180, 45, 640, 427, 707, 805, 188, 152, 905, 217, 30, 252,
 |  | ||||||
| +	386, 665, 299, 541, 410, 787, 5, 857, 751, 392, 44, 595, 146, 745,
 |  | ||||||
| +	641, 957, 866, 773, 806, 815, 659, 102, 704, 430, 106, 296, 129, 847,
 |  | ||||||
| +	130, 990, 669, 236, 225, 680, 159, 213, 438, 189, 447, 600, 232, 594,
 |  | ||||||
| +	32, 56, 390, 647, 855, 428, 330, 714, 738, 706, 666, 461, 469, 482,
 |  | ||||||
| +	558, 814, 559, 177, 575, 538, 309, 383, 261, 156, 420, 761, 630, 893,
 |  | ||||||
| +	10, 116, 940, 844, 71, 377, 662, 312, 520, 244, 143, 759, 119, 186,
 |  | ||||||
| +	592, 909, 864, 376, 768, 254, 265, 394, 511, 760, 574, 6, 436, 514,
 |  | ||||||
| +	59, 226, 644, 956, 578, 825, 548, 145, 736, 597, 378, 821, 987, 897,
 |  | ||||||
| +	354, 144, 722, 895, 589, 503, 826, 498, 543, 617, 763, 231, 808, 528,
 |  | ||||||
| +	89, 479, 607, 737, 170, 404, 371, 65, 103, 340, 283, 141, 313, 858,
 |  | ||||||
| +	289, 124, 971, 687, 954, 732, 39, 926, 176, 100, 267, 519, 890, 535,
 |  | ||||||
| +	276, 448, 27, 457, 899, 385, 184, 275, 770, 544, 614, 449, 160, 658,
 |  | ||||||
| +	259, 973, 108, 604, 24, 207, 562, 757, 744, 324, 444, 962, 591, 480,
 |  | ||||||
| +	398, 409, 998, 253, 325, 445, 979, 8, 35, 118, 73, 683, 208, 85, 190,
 |  | ||||||
| +	791, 408, 871, 657, 179, 18, 556, 496, 475, 20, 894, 484, 775, 889,
 |  | ||||||
| +	463, 241, 730, 57, 907, 551, 859, 943, 185, 416, 870, 590, 435, 471,
 |  | ||||||
| +	932, 268, 381, 626, 502, 565, 273, 534, 672, 778, 292, 473, 566, 104,
 |  | ||||||
| +	172, 285, 832, 411, 329, 628, 397, 472, 271, 910, 711, 690, 969, 585,
 |  | ||||||
| +	809, 941, 923, 555, 228, 685, 242, 94, 96, 211, 140, 61, 922, 795,
 |  | ||||||
| +	869, 34, 255, 38, 984, 676, 15, 560, 632, 434, 921, 355, 582, 351,
 |  | ||||||
| +	212, 200, 819, 960, 649, 852, 75, 771, 361, 996, 238, 316, 720, 671,
 |  | ||||||
| +	462, 112, 569, 171, 664, 625, 588, 405, 553, 270, 533, 353, 842, 114,
 |  | ||||||
| +	972, 83, 937, 63, 194, 237, 537, 980, 802, 916, 959, 688, 839, 350,
 |  | ||||||
| +	917, 650, 545, 615, 151, 352, 686, 726, 266, 509, 439, 491, 935, 608,
 |  | ||||||
| +	518, 653, 339, 609, 277, 635, 836, 88, 407, 440, 642, 927, 229, 727,
 |  | ||||||
| +	360, 477, 846, 413, 454, 616, 28, 598, 567, 540, 790, 424, 247, 317,
 |  | ||||||
| +	746, 911, 798, 321, 547, 248, 734, 829, 220, 138, 756, 500, 691, 196,
 |  | ||||||
| +	740, 930, 843, 733, 221, 827, 50, 813, 949, 525, 349, 474, 134, 875,
 |  | ||||||
| +	695, 513, 414, 515, 638, 99, 366, 490, 975, 246, 465, 206, 281, 583,
 |  | ||||||
| +	256, 587, 749, 2, 951, 679, 215, 364, 458, 402, 646, 991, 335, 982,
 |  | ||||||
| +	835, 300, 900, 703, 994, 983, 234, 888, 532, 804, 584, 305, 792, 442,
 |  | ||||||
| +	291, 964, 158, 370, 452, 250, 521, 166, 948, 812, 794, 272, 699, 205,
 |  | ||||||
| +	183, 507, 301, 920, 781, 233, 824, 137, 489, 833, 887, 966, 856, 78,
 |  | ||||||
| +	830, 153, 359, 696, 526, 216, 66, 701, 403, 891, 849, 571, 308, 483,
 |  | ||||||
| +	164, 293, 928, 677, 320, 837, 441, 639, 564, 510, 648, 274, 336, 661,
 |  | ||||||
| +	878, 777, 816, 976, 493, 810, 67, 87, 91, 187, 882, 986, 80, 22, 499,
 |  | ||||||
| +	90, 705, 139, 136, 122, 708, 716, 886, 572, 127, 40, 721, 764, 16,
 |  | ||||||
| +	379, 692, 645, 456, 710, 460, 783, 97, 776, 713, 884, 115, 466, 596,
 |  | ||||||
| +	374, 406, 110, 568, 68, 214, 622, 470, 107, 504, 682, 31, 421, 576,
 |  | ||||||
| +	654, 605, 788, 799, 280, 338, 931, 873, 204, 287, 459, 755, 939, 599,
 |  | ||||||
| +	431, 796, 235, 42, 750, 262, 318, 393, 202, 822, 879, 820, 728, 337,
 |  | ||||||
| +};
 |  | ||||||
| +
 |  | ||||||
| +static void fill_bindings_random(struct strbuf *buf, int start, int end,
 |  | ||||||
| +				 const char *prefix)
 |  | ||||||
| +{
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	for (i = start; i < end; i++) {
 |  | ||||||
| +		print_strbuf(buf,  "%s", prefix);
 |  | ||||||
| +		format_devname(buf, random_numbers[i]);
 |  | ||||||
| +		print_strbuf(buf,  " WWID%d\n", random_numbers[i]);
 |  | ||||||
| +	}
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +struct random_aliases {
 |  | ||||||
| +	int start;
 |  | ||||||
| +	int end;
 |  | ||||||
| +	const char *prefix;
 |  | ||||||
| +};
 |  | ||||||
| +
 |  | ||||||
| +static void order_test(int n, const struct random_aliases ra[], bool conflict_ok)
 |  | ||||||
| +{
 |  | ||||||
| +	STRBUF_ON_STACK(buf);
 |  | ||||||
| +	int i, j, prev, curr, tmp;
 |  | ||||||
| +	struct binding *bdg;
 |  | ||||||
| +	Bindings *bindings = &global_bindings;
 |  | ||||||
| +
 |  | ||||||
| +	for (j = 0; j < n; j++)
 |  | ||||||
| +		fill_bindings_random(&buf, ra[j].start, ra[j].end, ra[j].prefix);
 |  | ||||||
| +	__mock_bindings_file(get_strbuf_str(&buf), conflict_ok);
 |  | ||||||
| +
 |  | ||||||
| +	for (j = 0; j < n; j++) {
 |  | ||||||
| +		bdg = VECTOR_SLOT(bindings, 0);
 |  | ||||||
| +		if (ALIAS_DEBUG && j == 0)
 |  | ||||||
| +			printf("%d: %s\n", 0, bdg->alias);
 |  | ||||||
| +		prev = scan_devname(bdg->alias, ra[j].prefix);
 |  | ||||||
| +		i = 1;
 |  | ||||||
| +		vector_foreach_slot_after(bindings, bdg, i) {
 |  | ||||||
| +			if (ALIAS_DEBUG && j == 0)
 |  | ||||||
| +				printf("%d: %s\n", i, bdg->alias);
 |  | ||||||
| +			tmp = scan_devname(bdg->alias, ra[j].prefix);
 |  | ||||||
| +			if (tmp == -1)
 |  | ||||||
| +				continue;
 |  | ||||||
| +			curr = tmp;
 |  | ||||||
| +			if (prev > 0) {
 |  | ||||||
| +				if (curr <= prev)
 |  | ||||||
| +					printf("ERROR: %d (%s) %d >= %d\n",
 |  | ||||||
| +					       i, bdg->alias, prev, curr);
 |  | ||||||
| +				assert_true(curr > prev);
 |  | ||||||
| +			}
 |  | ||||||
| +			prev = curr;
 |  | ||||||
| +		}
 |  | ||||||
| +	}
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void order_01(void **state)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct random_aliases ra[] = {
 |  | ||||||
| +		{  0, 1000, "MPATH" },
 |  | ||||||
| +	};
 |  | ||||||
| +
 |  | ||||||
| +	order_test(ARRAY_SIZE(ra), ra, false);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void order_02(void **state)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct random_aliases ra[] = {
 |  | ||||||
| +		{   0, 500, "MPATH" },
 |  | ||||||
| +		{ 200, 700, "mpath" },
 |  | ||||||
| +	};
 |  | ||||||
| +	order_test(ARRAY_SIZE(ra), ra, false);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void order_03(void **state)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct random_aliases ra[] = {
 |  | ||||||
| +		{  500, 1000, "MPTH" },
 |  | ||||||
| +		{    0,  500, "MPATH" },
 |  | ||||||
| +	};
 |  | ||||||
| +	order_test(ARRAY_SIZE(ra), ra, false);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void order_04(void **state)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct random_aliases ra[] = {
 |  | ||||||
| +		{   0, 500, "mpa" },
 |  | ||||||
| +		{ 250, 750, "mp" },
 |  | ||||||
| +	};
 |  | ||||||
| +	order_test(ARRAY_SIZE(ra), ra, true);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void order_05(void **state)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct random_aliases ra[] = {
 |  | ||||||
| +		{  0, 100, "A" },
 |  | ||||||
| +		{  0, 100, "B" },
 |  | ||||||
| +		{  0, 100, "C" },
 |  | ||||||
| +		{  0, 100, "D" },
 |  | ||||||
| +	};
 |  | ||||||
| +	order_test(ARRAY_SIZE(ra), ra, false);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void order_06(void **state)
 |  | ||||||
| +{
 |  | ||||||
| +	const struct random_aliases ra[] = {
 |  | ||||||
| +		{  0, 100, "" },
 |  | ||||||
| +		{  0, 100, "a" },
 |  | ||||||
| +		{  0, 100, "aa" },
 |  | ||||||
| +		{  0, 100, "ab" },
 |  | ||||||
| +		{  0, 100, "aaa" },
 |  | ||||||
| +	};
 |  | ||||||
| +	order_test(ARRAY_SIZE(ra), ra, true);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static int test_bindings_order()
 |  | ||||||
| +{
 |  | ||||||
| +	const struct CMUnitTest tests[] = {
 |  | ||||||
| +		cmocka_unit_test_teardown(order_01, teardown_bindings),
 |  | ||||||
| +		cmocka_unit_test_teardown(order_02, teardown_bindings),
 |  | ||||||
| +		cmocka_unit_test_teardown(order_03, teardown_bindings),
 |  | ||||||
| +		cmocka_unit_test_teardown(order_04, teardown_bindings),
 |  | ||||||
| +		cmocka_unit_test_teardown(order_05, teardown_bindings),
 |  | ||||||
| +		cmocka_unit_test_teardown(order_06, teardown_bindings),
 |  | ||||||
| +	};
 |  | ||||||
| +
 |  | ||||||
| +	return cmocka_run_group_tests(tests, NULL, NULL);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  int main(void) |  | ||||||
|  { |  | ||||||
|  	int ret = 0; |  | ||||||
| @@ -1755,6 +1960,7 @@ int main(void)
 |  | ||||||
|  	ret += test_rlookup_binding(); |  | ||||||
|  	ret += test_allocate_binding(); |  | ||||||
|  	ret += test_get_user_friendly_alias(); |  | ||||||
| +	ret += test_bindings_order();
 |  | ||||||
|   |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| @ -1,597 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Thu, 7 Sep 2023 22:22:43 +0200 |  | ||||||
| Subject: [PATCH] multipathd: watch bindings file with inotify + timestamp |  | ||||||
| 
 |  | ||||||
| Since "libmultipath: keep bindings in memory", we don't re-read the |  | ||||||
| bindings file after every modification. Add a notification mechanism |  | ||||||
| that makes multipathd aware of changes to the bindings file. Because |  | ||||||
| multipathd itself will change the bindings file, it must compare |  | ||||||
| timestamps in order to avoid reading the file repeatedly. |  | ||||||
| 
 |  | ||||||
| Because select_alias() can be called from multiple thread contexts (uxlsnr, |  | ||||||
| uevent handler), we need to add locking for the bindings file. The |  | ||||||
| timestamp must also be protected by a lock, because it can't be read |  | ||||||
| or written atomically. |  | ||||||
| 
 |  | ||||||
| Note: The notification mechanism expects the bindings file to be |  | ||||||
| atomically replaced by rename(2). Changes must be made in a temporary file and |  | ||||||
| applied using rename(2), as in update_bindings_file(). The inotify |  | ||||||
| mechanism deliberately does not listen to close-after-write events |  | ||||||
| that would be generated by editing the bindings file directly. This |  | ||||||
| 
 |  | ||||||
| Note also: new bindings will only be read from add_map_with_path(), |  | ||||||
| i.e. either during reconfigure(), or when a new map is created during |  | ||||||
| runtime. Existing maps will not be renamed if the binding file changes, |  | ||||||
| unless the user runs "multipathd reconfigure". This is not a change |  | ||||||
| wrt the previous code, but it should be mentioned anyway. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c              | 256 +++++++++++++++++++++++++----- |  | ||||||
|  libmultipath/alias.h              |   3 +- |  | ||||||
|  libmultipath/libmultipath.version |   5 + |  | ||||||
|  multipathd/uxlsnr.c               |  36 ++++- |  | ||||||
|  tests/alias.c                     |   3 + |  | ||||||
|  5 files changed, 256 insertions(+), 47 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 66e34e31..964b8a7b 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -10,6 +10,7 @@
 |  | ||||||
|  #include <stdio.h> |  | ||||||
|  #include <stdbool.h> |  | ||||||
|  #include <assert.h> |  | ||||||
| +#include <sys/inotify.h>
 |  | ||||||
|   |  | ||||||
|  #include "debug.h" |  | ||||||
|  #include "util.h" |  | ||||||
| @@ -22,6 +23,7 @@
 |  | ||||||
|  #include "config.h" |  | ||||||
|  #include "devmapper.h" |  | ||||||
|  #include "strbuf.h" |  | ||||||
| +#include "time-util.h"
 |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
|   * significant parts of this file were taken from iscsi-bindings.c of the |  | ||||||
| @@ -50,6 +52,12 @@
 |  | ||||||
|  "# alias wwid\n" \ |  | ||||||
|  "#\n" |  | ||||||
|   |  | ||||||
| +/* uatomic access only */
 |  | ||||||
| +static int bindings_file_changed = 1;
 |  | ||||||
| +
 |  | ||||||
| +static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER;
 |  | ||||||
| +static struct timespec bindings_last_updated;
 |  | ||||||
| +
 |  | ||||||
|  struct binding { |  | ||||||
|  	char *alias; |  | ||||||
|  	char *wwid; |  | ||||||
| @@ -60,6 +68,9 @@ struct binding {
 |  | ||||||
|   * an abstract type. |  | ||||||
|   */ |  | ||||||
|  typedef struct _vector Bindings; |  | ||||||
| +
 |  | ||||||
| +/* Protect global_bindings */
 |  | ||||||
| +static pthread_mutex_t bindings_mutex = PTHREAD_MUTEX_INITIALIZER;
 |  | ||||||
|  static Bindings global_bindings = { .allocated = 0 }; |  | ||||||
|   |  | ||||||
|  enum { |  | ||||||
| @@ -78,6 +89,27 @@ static void _free_binding(struct binding *bdg)
 |  | ||||||
|  	free(bdg); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static void free_bindings(Bindings *bindings)
 |  | ||||||
| +{
 |  | ||||||
| +	struct binding *bdg;
 |  | ||||||
| +	int i;
 |  | ||||||
| +
 |  | ||||||
| +	vector_foreach_slot(bindings, bdg, i)
 |  | ||||||
| +		_free_binding(bdg);
 |  | ||||||
| +	vector_reset(bindings);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +static void set_global_bindings(Bindings *bindings)
 |  | ||||||
| +{
 |  | ||||||
| +	Bindings old_bindings;
 |  | ||||||
| +
 |  | ||||||
| +	pthread_mutex_lock(&bindings_mutex);
 |  | ||||||
| +	old_bindings = global_bindings;
 |  | ||||||
| +	global_bindings = *bindings;
 |  | ||||||
| +	pthread_mutex_unlock(&bindings_mutex);
 |  | ||||||
| +	free_bindings(&old_bindings);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static const struct binding *get_binding_for_alias(const Bindings *bindings, |  | ||||||
|  						   const char *alias) |  | ||||||
|  { |  | ||||||
| @@ -199,7 +231,8 @@ static int delete_binding(Bindings *bindings, const char *wwid)
 |  | ||||||
|  	return BINDING_DELETED; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int write_bindings_file(const Bindings *bindings, int fd)
 |  | ||||||
| +static int write_bindings_file(const Bindings *bindings, int fd,
 |  | ||||||
| +			       struct timespec *ts)
 |  | ||||||
|  { |  | ||||||
|  	struct binding *bnd; |  | ||||||
|  	STRBUF_ON_STACK(content); |  | ||||||
| @@ -227,9 +260,56 @@ static int write_bindings_file(const Bindings *bindings, int fd)
 |  | ||||||
|  		} |  | ||||||
|  		len -= n; |  | ||||||
|  	} |  | ||||||
| +	fsync(fd);
 |  | ||||||
| +	if (ts) {
 |  | ||||||
| +		struct stat st;
 |  | ||||||
| +
 |  | ||||||
| +		if (fstat(fd, &st) == 0)
 |  | ||||||
| +			*ts = st.st_mtim;
 |  | ||||||
| +		else
 |  | ||||||
| +			clock_gettime(CLOCK_REALTIME_COARSE, ts);
 |  | ||||||
| +	}
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +void handle_bindings_file_inotify(const struct inotify_event *event)
 |  | ||||||
| +{
 |  | ||||||
| +	struct config *conf;
 |  | ||||||
| +	const char *base;
 |  | ||||||
| +	bool changed = false;
 |  | ||||||
| +	struct stat st;
 |  | ||||||
| +	struct timespec ts = { 0, 0 };
 |  | ||||||
| +	int ret;
 |  | ||||||
| +
 |  | ||||||
| +	if (!(event->mask & IN_MOVED_TO))
 |  | ||||||
| +		return;
 |  | ||||||
| +
 |  | ||||||
| +	conf = get_multipath_config();
 |  | ||||||
| +	base = strrchr(conf->bindings_file, '/');
 |  | ||||||
| +	changed = base && base > conf->bindings_file &&
 |  | ||||||
| +		!strcmp(base + 1, event->name);
 |  | ||||||
| +	ret = stat(conf->bindings_file, &st);
 |  | ||||||
| +	put_multipath_config(conf);
 |  | ||||||
| +
 |  | ||||||
| +	if (!changed)
 |  | ||||||
| +		return;
 |  | ||||||
| +
 |  | ||||||
| +	pthread_mutex_lock(×tamp_mutex);
 |  | ||||||
| +	if (ret == 0) {
 |  | ||||||
| +		ts = st.st_mtim;
 |  | ||||||
| +		changed = timespeccmp(&ts, &bindings_last_updated) > 0;
 |  | ||||||
| +	}
 |  | ||||||
| +	pthread_mutex_unlock(×tamp_mutex);
 |  | ||||||
| +
 |  | ||||||
| +	if (changed) {
 |  | ||||||
| +		uatomic_xchg(&bindings_file_changed, 1);
 |  | ||||||
| +		condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld",
 |  | ||||||
| +			__func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000);
 |  | ||||||
| +	} else
 |  | ||||||
| +		condlog(3, "%s: bindings file is up-to-date, timestamp: %ld.%06ld",
 |  | ||||||
| +			__func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static int update_bindings_file(const Bindings *bindings, |  | ||||||
|  				const char *bindings_file) |  | ||||||
|  { |  | ||||||
| @@ -237,6 +317,7 @@ static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
|  	int fd = -1; |  | ||||||
|  	char tempname[PATH_MAX]; |  | ||||||
|  	mode_t old_umask; |  | ||||||
| +	struct timespec ts;
 |  | ||||||
|   |  | ||||||
|  	if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file)) |  | ||||||
|  		return -1; |  | ||||||
| @@ -248,7 +329,7 @@ static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
|  	} |  | ||||||
|  	umask(old_umask); |  | ||||||
|  	pthread_cleanup_push(cleanup_fd_ptr, &fd); |  | ||||||
| -	rc = write_bindings_file(bindings, fd);
 |  | ||||||
| +	rc = write_bindings_file(bindings, fd, &ts);
 |  | ||||||
|  	pthread_cleanup_pop(1); |  | ||||||
|  	if (rc == -1) { |  | ||||||
|  		condlog(1, "failed to write new bindings file"); |  | ||||||
| @@ -257,8 +338,12 @@ static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
|  	} |  | ||||||
|  	if ((rc = rename(tempname, bindings_file)) == -1) |  | ||||||
|  		condlog(0, "%s: rename: %m", __func__); |  | ||||||
| -	else
 |  | ||||||
| +	else {
 |  | ||||||
| +		pthread_mutex_lock(×tamp_mutex);
 |  | ||||||
| +		bindings_last_updated = ts;
 |  | ||||||
| +		pthread_mutex_unlock(×tamp_mutex);
 |  | ||||||
|  		condlog(1, "updated bindings file %s", bindings_file); |  | ||||||
| +	}
 |  | ||||||
|  	return rc; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -387,6 +472,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww
 |  | ||||||
|  	return id; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +/* Called with binding_mutex held */
 |  | ||||||
|  static char * |  | ||||||
|  allocate_binding(const char *filename, const char *wwid, int id, const char *prefix) |  | ||||||
|  { |  | ||||||
| @@ -423,6 +509,30 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre
 |  | ||||||
|  	return alias; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +enum {
 |  | ||||||
| +	BINDINGS_FILE_UP2DATE,
 |  | ||||||
| +	BINDINGS_FILE_READ,
 |  | ||||||
| +	BINDINGS_FILE_ERROR,
 |  | ||||||
| +	BINDINGS_FILE_BAD,
 |  | ||||||
| +};
 |  | ||||||
| +
 |  | ||||||
| +static int _read_bindings_file(const struct config *conf, Bindings *bindings,
 |  | ||||||
| +			       bool force);
 |  | ||||||
| +
 |  | ||||||
| +static void read_bindings_file(void)
 |  | ||||||
| +{
 |  | ||||||
| +	struct config *conf;
 |  | ||||||
| +	Bindings bindings = {.allocated = 0, };
 |  | ||||||
| +	int rc;
 |  | ||||||
| +
 |  | ||||||
| +	conf = get_multipath_config();
 |  | ||||||
| +	pthread_cleanup_push(put_multipath_config, conf);
 |  | ||||||
| +	rc = _read_bindings_file(conf, &bindings, false);
 |  | ||||||
| +	pthread_cleanup_pop(1);
 |  | ||||||
| +	if (rc == BINDINGS_FILE_READ)
 |  | ||||||
| +		set_global_bindings(&bindings);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  /* |  | ||||||
|   * get_user_friendly_alias() action table |  | ||||||
|   * |  | ||||||
| @@ -463,6 +573,11 @@ char *get_user_friendly_alias(const char *wwid, const char *file, const char *al
 |  | ||||||
|  	bool new_binding = false; |  | ||||||
|  	const struct binding *bdg; |  | ||||||
|   |  | ||||||
| +	read_bindings_file();
 |  | ||||||
| +
 |  | ||||||
| +	pthread_mutex_lock(&bindings_mutex);
 |  | ||||||
| +	pthread_cleanup_push(cleanup_mutex, &bindings_mutex);
 |  | ||||||
| +
 |  | ||||||
|  	if (!*alias_old) |  | ||||||
|  		goto new_alias; |  | ||||||
|   |  | ||||||
| @@ -514,40 +629,40 @@ new_alias:
 |  | ||||||
|  			alias, wwid); |  | ||||||
|   |  | ||||||
|  out: |  | ||||||
| +	/* unlock bindings_mutex */
 |  | ||||||
| +	pthread_cleanup_pop(1);
 |  | ||||||
|  	return alias; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  int get_user_friendly_wwid(const char *alias, char *buff) |  | ||||||
|  { |  | ||||||
|  	const struct binding *bdg; |  | ||||||
| +	int rc = -1;
 |  | ||||||
|   |  | ||||||
|  	if (!alias || *alias == '\0') { |  | ||||||
|  		condlog(3, "Cannot find binding for empty alias"); |  | ||||||
|  		return -1; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| +	read_bindings_file();
 |  | ||||||
| +
 |  | ||||||
| +	pthread_mutex_lock(&bindings_mutex);
 |  | ||||||
| +	pthread_cleanup_push(cleanup_mutex, &bindings_mutex);
 |  | ||||||
|  	bdg = get_binding_for_alias(&global_bindings, alias); |  | ||||||
| -	if (!bdg) {
 |  | ||||||
| +	if (bdg) {
 |  | ||||||
| +		strlcpy(buff, bdg->wwid, WWID_SIZE);
 |  | ||||||
| +		rc = 0;
 |  | ||||||
| +	} else
 |  | ||||||
|  		*buff = '\0'; |  | ||||||
| -		return -1;
 |  | ||||||
| -	}
 |  | ||||||
| -	strlcpy(buff, bdg->wwid, WWID_SIZE);
 |  | ||||||
| -	return 0;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
| -static void free_bindings(Bindings *bindings)
 |  | ||||||
| -{
 |  | ||||||
| -	struct binding *bdg;
 |  | ||||||
| -	int i;
 |  | ||||||
| -
 |  | ||||||
| -	vector_foreach_slot(bindings, bdg, i)
 |  | ||||||
| -		_free_binding(bdg);
 |  | ||||||
| -	vector_reset(bindings);
 |  | ||||||
| +	pthread_cleanup_pop(1);
 |  | ||||||
| +	return rc;
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  void cleanup_bindings(void) |  | ||||||
|  { |  | ||||||
| +	pthread_mutex_lock(&bindings_mutex);
 |  | ||||||
|  	free_bindings(&global_bindings); |  | ||||||
| +	pthread_mutex_unlock(&bindings_mutex);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  enum { |  | ||||||
| @@ -595,7 +710,20 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
 |  | ||||||
|  	char *line = NULL; |  | ||||||
|  	size_t line_len = 0; |  | ||||||
|  	ssize_t n; |  | ||||||
| -
 |  | ||||||
| +	char header[sizeof(BINDINGS_FILE_HEADER)];
 |  | ||||||
| +
 |  | ||||||
| +	header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0';
 |  | ||||||
| +	if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) {
 |  | ||||||
| +		condlog(2, "%s: failed to read header from %s", __func__,
 |  | ||||||
| +			conf->bindings_file);
 |  | ||||||
| +		fseek(file, 0, SEEK_SET);
 |  | ||||||
| +		rc = -1;
 |  | ||||||
| +	} else if (strcmp(header, BINDINGS_FILE_HEADER)) {
 |  | ||||||
| +		condlog(2, "%s: invalid header in %s", __func__,
 |  | ||||||
| +			conf->bindings_file);
 |  | ||||||
| +		fseek(file, 0, SEEK_SET);
 |  | ||||||
| +		rc = -1;
 |  | ||||||
| +	}
 |  | ||||||
|  	pthread_cleanup_push(cleanup_free_ptr, &line); |  | ||||||
|  	while ((n = getline(&line, &line_len, file)) >= 0) { |  | ||||||
|  		char *alias, *wwid; |  | ||||||
| @@ -643,6 +771,68 @@ static int mp_alias_compar(const void *p1, const void *p2)
 |  | ||||||
|  			    &((*(struct mpentry * const *)p2)->alias)); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static int _read_bindings_file(const struct config *conf, Bindings *bindings,
 |  | ||||||
| +			       bool force)
 |  | ||||||
| +{
 |  | ||||||
| +	int can_write;
 |  | ||||||
| +	int rc = 0, ret, fd;
 |  | ||||||
| +	FILE *file;
 |  | ||||||
| +	struct stat st;
 |  | ||||||
| +	int has_changed = uatomic_xchg(&bindings_file_changed, 0);
 |  | ||||||
| +
 |  | ||||||
| +	if (!force) {
 |  | ||||||
| +		if (!has_changed) {
 |  | ||||||
| +			condlog(4, "%s: bindings are unchanged", __func__);
 |  | ||||||
| +			return BINDINGS_FILE_UP2DATE;
 |  | ||||||
| +		}
 |  | ||||||
| +	}
 |  | ||||||
| +
 |  | ||||||
| +	fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
 |  | ||||||
| +	if (fd == -1)
 |  | ||||||
| +		return BINDINGS_FILE_ERROR;
 |  | ||||||
| +
 |  | ||||||
| +	file = fdopen(fd, "r");
 |  | ||||||
| +	if (file != NULL) {
 |  | ||||||
| +		condlog(3, "%s: reading %s", __func__, conf->bindings_file);
 |  | ||||||
| +
 |  | ||||||
| +		pthread_cleanup_push(cleanup_fclose, file);
 |  | ||||||
| +		ret = _check_bindings_file(conf, file, bindings);
 |  | ||||||
| +		if (ret == 0) {
 |  | ||||||
| +			struct timespec ts;
 |  | ||||||
| +
 |  | ||||||
| +			rc = BINDINGS_FILE_READ;
 |  | ||||||
| +			ret = fstat(fd, &st);
 |  | ||||||
| +			if (ret == 0)
 |  | ||||||
| +				ts = st.st_mtim;
 |  | ||||||
| +			else {
 |  | ||||||
| +				condlog(1, "%s: fstat failed (%m), using current time", __func__);
 |  | ||||||
| +				clock_gettime(CLOCK_REALTIME_COARSE, &ts);
 |  | ||||||
| +			}
 |  | ||||||
| +			pthread_mutex_lock(×tamp_mutex);
 |  | ||||||
| +			bindings_last_updated = ts;
 |  | ||||||
| +			pthread_mutex_unlock(×tamp_mutex);
 |  | ||||||
| +		} else if (ret == -1 && can_write && !conf->bindings_read_only) {
 |  | ||||||
| +			ret = update_bindings_file(bindings, conf->bindings_file);
 |  | ||||||
| +			if (ret == 0)
 |  | ||||||
| +				rc = BINDINGS_FILE_READ;
 |  | ||||||
| +			else
 |  | ||||||
| +				rc = BINDINGS_FILE_BAD;
 |  | ||||||
| +		} else {
 |  | ||||||
| +			condlog(0, "ERROR: bad settings in read-only bindings file %s",
 |  | ||||||
| +				conf->bindings_file);
 |  | ||||||
| +			rc = BINDINGS_FILE_BAD;
 |  | ||||||
| +		}
 |  | ||||||
| +		pthread_cleanup_pop(1);
 |  | ||||||
| +	} else {
 |  | ||||||
| +		condlog(1, "failed to fdopen %s: %m",
 |  | ||||||
| +			conf->bindings_file);
 |  | ||||||
| +		close(fd);
 |  | ||||||
| +		rc = BINDINGS_FILE_ERROR;
 |  | ||||||
| +	}
 |  | ||||||
| +
 |  | ||||||
| +	return rc;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  /* |  | ||||||
|   * check_alias_settings(): test for inconsistent alias configuration |  | ||||||
|   * |  | ||||||
| @@ -661,8 +851,7 @@ static int mp_alias_compar(const void *p1, const void *p2)
 |  | ||||||
|   */ |  | ||||||
|  int check_alias_settings(const struct config *conf) |  | ||||||
|  { |  | ||||||
| -	int can_write;
 |  | ||||||
| -	int rc = 0, i, fd;
 |  | ||||||
| +	int i, rc;
 |  | ||||||
|  	Bindings bindings = {.allocated = 0, }; |  | ||||||
|  	vector mptable = NULL; |  | ||||||
|  	struct mpentry *mpe; |  | ||||||
| @@ -695,27 +884,12 @@ int check_alias_settings(const struct config *conf)
 |  | ||||||
|  	pthread_cleanup_pop(1); |  | ||||||
|  	pthread_cleanup_pop(1); |  | ||||||
|   |  | ||||||
| -	fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
 |  | ||||||
| -	if (fd != -1) {
 |  | ||||||
| -		FILE *file = fdopen(fd, "r");
 |  | ||||||
| -
 |  | ||||||
| -		if (file != NULL) {
 |  | ||||||
| -			pthread_cleanup_push(cleanup_fclose, file);
 |  | ||||||
| -			rc = _check_bindings_file(conf, file, &bindings);
 |  | ||||||
| -			pthread_cleanup_pop(1);
 |  | ||||||
| -			if (rc == -1 && can_write && !conf->bindings_read_only)
 |  | ||||||
| -				rc = update_bindings_file(&bindings, conf->bindings_file);
 |  | ||||||
| -			else if (rc == -1)
 |  | ||||||
| -				condlog(0, "ERROR: bad settings in read-only bindings file %s",
 |  | ||||||
| -					conf->bindings_file);
 |  | ||||||
| -		} else {
 |  | ||||||
| -			condlog(1, "failed to fdopen %s: %m",
 |  | ||||||
| -				conf->bindings_file);
 |  | ||||||
| -			close(fd);
 |  | ||||||
| -		}
 |  | ||||||
| +	rc = _read_bindings_file(conf, &bindings, true);
 |  | ||||||
| +
 |  | ||||||
| +	if (rc == BINDINGS_FILE_READ) {
 |  | ||||||
| +		set_global_bindings(&bindings);
 |  | ||||||
| +		rc = 0;
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	cleanup_bindings();
 |  | ||||||
| -	global_bindings = bindings;
 |  | ||||||
|  	return rc; |  | ||||||
|  } |  | ||||||
| diff --git a/libmultipath/alias.h b/libmultipath/alias.h
 |  | ||||||
| index 5ef6720b..ca8911f4 100644
 |  | ||||||
| --- a/libmultipath/alias.h
 |  | ||||||
| +++ b/libmultipath/alias.h
 |  | ||||||
| @@ -10,5 +10,6 @@ char *get_user_friendly_alias(const char *wwid, const char *file,
 |  | ||||||
|  struct config; |  | ||||||
|  int check_alias_settings(const struct config *); |  | ||||||
|  void cleanup_bindings(void); |  | ||||||
| -
 |  | ||||||
| +struct inotify_event;
 |  | ||||||
| +void handle_bindings_file_inotify(const struct inotify_event *event);
 |  | ||||||
|  #endif /* _ALIAS_H */ |  | ||||||
| diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
 |  | ||||||
| index ddd302f5..57e50c12 100644
 |  | ||||||
| --- a/libmultipath/libmultipath.version
 |  | ||||||
| +++ b/libmultipath/libmultipath.version
 |  | ||||||
| @@ -238,3 +238,8 @@ global:
 |  | ||||||
|  local: |  | ||||||
|  	*; |  | ||||||
|  }; |  | ||||||
| +
 |  | ||||||
| +LIBMULTIPATH_20.1.0 {
 |  | ||||||
| +global:
 |  | ||||||
| +	handle_bindings_file_inotify;
 |  | ||||||
| +};
 |  | ||||||
| diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
 |  | ||||||
| index 02e89fb4..d1f8f234 100644
 |  | ||||||
| --- a/multipathd/uxlsnr.c
 |  | ||||||
| +++ b/multipathd/uxlsnr.c
 |  | ||||||
| @@ -41,6 +41,7 @@
 |  | ||||||
|  #include "cli.h" |  | ||||||
|  #include "uxlsnr.h" |  | ||||||
|  #include "strbuf.h" |  | ||||||
| +#include "alias.h"
 |  | ||||||
|   |  | ||||||
|  /* state of client connection */ |  | ||||||
|  enum { |  | ||||||
| @@ -190,6 +191,7 @@ void wakeup_cleanup(void *arg)
 |  | ||||||
|  struct watch_descriptors { |  | ||||||
|  	int conf_wd; |  | ||||||
|  	int dir_wd; |  | ||||||
| +	int mp_wd; /* /etc/multipath; for bindings file */
 |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
|  /* failing to set the watch descriptor is o.k. we just miss a warning |  | ||||||
| @@ -200,6 +202,8 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
 |  | ||||||
|  	struct config *conf; |  | ||||||
|  	int dir_reset = 0; |  | ||||||
|  	int conf_reset = 0; |  | ||||||
| +	int mp_reset = 0;
 |  | ||||||
| +	char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL;
 |  | ||||||
|   |  | ||||||
|  	if (notify_fd == -1) |  | ||||||
|  		return; |  | ||||||
| @@ -214,7 +218,10 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
 |  | ||||||
|  			conf_reset = 1; |  | ||||||
|  		if (wds->dir_wd == -1) |  | ||||||
|  			dir_reset = 1; |  | ||||||
| +		if (wds->mp_wd == -1)
 |  | ||||||
| +			mp_reset = 1;
 |  | ||||||
|  	} |  | ||||||
| +	bindings_file = strdup(conf->bindings_file);
 |  | ||||||
|  	put_multipath_config(conf); |  | ||||||
|   |  | ||||||
|  	if (dir_reset) { |  | ||||||
| @@ -235,7 +242,18 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
 |  | ||||||
|  		if (wds->conf_wd == -1) |  | ||||||
|  			condlog(3, "didn't set up notifications on /etc/multipath.conf: %m"); |  | ||||||
|  	} |  | ||||||
| -	return;
 |  | ||||||
| +	if (mp_reset && bindings_file) {
 |  | ||||||
| +		char *slash = strrchr(bindings_file, '/');
 |  | ||||||
| +
 |  | ||||||
| +		if (slash && slash > bindings_file) {
 |  | ||||||
| +			*slash = '\0';
 |  | ||||||
| +			wds->mp_wd = inotify_add_watch(notify_fd, bindings_file,
 |  | ||||||
| +						       IN_MOVED_TO|IN_ONLYDIR);
 |  | ||||||
| +			if (wds->mp_wd == -1)
 |  | ||||||
| +				condlog(3, "didn't set up notifications on %s: %m",
 |  | ||||||
| +					bindings_file);
 |  | ||||||
| +		}
 |  | ||||||
| +	}
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static void handle_inotify(int fd, struct watch_descriptors *wds) |  | ||||||
| @@ -256,12 +274,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds)
 |  | ||||||
|  					inotify_rm_watch(fd, wds->conf_wd); |  | ||||||
|  				if (wds->dir_wd != -1) |  | ||||||
|  					inotify_rm_watch(fd, wds->dir_wd); |  | ||||||
| -				wds->conf_wd = wds->dir_wd = -1;
 |  | ||||||
| +				if (wds->mp_wd != -1)
 |  | ||||||
| +					inotify_rm_watch(fd, wds->mp_wd);
 |  | ||||||
| +				wds->conf_wd = wds->dir_wd = wds->mp_wd = -1;
 |  | ||||||
|  			} |  | ||||||
|  			break; |  | ||||||
|  		} |  | ||||||
|   |  | ||||||
| -		got_notify = 1;
 |  | ||||||
|  		for (ptr = buff; ptr < buff + len; |  | ||||||
|  		     ptr += sizeof(struct inotify_event) + event->len) { |  | ||||||
|  			event = (const struct inotify_event *) ptr; |  | ||||||
| @@ -273,7 +292,13 @@ static void handle_inotify(int fd, struct watch_descriptors *wds)
 |  | ||||||
|  					wds->conf_wd = inotify_add_watch(notify_fd, DEFAULT_CONFIGFILE, IN_CLOSE_WRITE); |  | ||||||
|  				else if (wds->dir_wd == event->wd) |  | ||||||
|  					wds->dir_wd = -1; |  | ||||||
| +				else if (wds->mp_wd == event->wd)
 |  | ||||||
| +					wds->mp_wd = -1;
 |  | ||||||
|  			} |  | ||||||
| +			if (wds->mp_wd != -1 && wds->mp_wd == event->wd)
 |  | ||||||
| +				handle_bindings_file_inotify(event);
 |  | ||||||
| +			else
 |  | ||||||
| +				got_notify = 1;
 |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
|  	if (got_notify) |  | ||||||
| @@ -599,7 +624,7 @@ void *uxsock_listen(long ux_sock, void *trigger_data)
 |  | ||||||
|  	int max_pfds = MIN_POLLS + POLLFDS_BASE; |  | ||||||
|  	/* conf->sequence_nr will be 1 when uxsock_listen is first called */ |  | ||||||
|  	unsigned int sequence_nr = 0; |  | ||||||
| -	struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1 };
 |  | ||||||
| +	struct watch_descriptors wds = { .conf_wd = -1, .dir_wd = -1, .mp_wd = -1, };
 |  | ||||||
|  	struct vectors *vecs = trigger_data; |  | ||||||
|   |  | ||||||
|  	condlog(3, "uxsock: startup listener"); |  | ||||||
| @@ -666,7 +691,8 @@ void *uxsock_listen(long ux_sock, void *trigger_data)
 |  | ||||||
|   |  | ||||||
|  		reset_watch(notify_fd, &wds, &sequence_nr); |  | ||||||
|  		polls[POLLFD_NOTIFY].fd = notify_fd; |  | ||||||
| -		if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1))
 |  | ||||||
| +		if (notify_fd == -1 || (wds.conf_wd == -1 && wds.dir_wd == -1
 |  | ||||||
| +					&& wds.mp_wd == -1))
 |  | ||||||
|  			polls[POLLFD_NOTIFY].events = 0; |  | ||||||
|  		else |  | ||||||
|  			polls[POLLFD_NOTIFY].events = POLLIN; |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 7f3ff38a..9ae27567 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -1954,6 +1954,9 @@ int main(void)
 |  | ||||||
|  	int ret = 0; |  | ||||||
|  	init_test_verbosity(3); |  | ||||||
|   |  | ||||||
| +	/* avoid open_file() call in _read_bindings_file */
 |  | ||||||
| +	bindings_file_changed = 0;
 |  | ||||||
| +
 |  | ||||||
|  	ret += test_format_devname(); |  | ||||||
|  	ret += test_scan_devname(); |  | ||||||
|  	ret += test_lookup_binding(); |  | ||||||
| @ -1,102 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 19:54:07 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools tests: mock pthread_mutex_{lock,unlock} |  | ||||||
| 
 |  | ||||||
| If some test fails with a lock held, cmocka doesn't deal well with |  | ||||||
| pthread_cleanup_pop(). Such tests can cause deadlock with the locking |  | ||||||
| primitives in the alias code, because locks don't get properly unlocked.  Just |  | ||||||
| mock the lock/unlock functions and generate an error if they weren't paired at |  | ||||||
| the end of the test. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  tests/Makefile |  1 + |  | ||||||
|  tests/alias.c  | 46 ++++++++++++++++++++++++++++++++++++++++++++++ |  | ||||||
|  2 files changed, 47 insertions(+) |  | ||||||
| 
 |  | ||||||
| diff --git a/tests/Makefile b/tests/Makefile
 |  | ||||||
| index c777d07a..7dac8a8f 100644
 |  | ||||||
| --- a/tests/Makefile
 |  | ||||||
| +++ b/tests/Makefile
 |  | ||||||
| @@ -52,6 +52,7 @@ blacklist-test_LIBDEPS := -ludev
 |  | ||||||
|  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 |  | ||||||
|  valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o |  | ||||||
|  valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 9ae27567..94df36d8 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -89,6 +89,47 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
 |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static int lock_errors;
 |  | ||||||
| +static int bindings_locked;
 |  | ||||||
| +static int timestamp_locked;
 |  | ||||||
| +int __wrap_pthread_mutex_lock(pthread_mutex_t *mutex)
 |  | ||||||
| +{
 |  | ||||||
| +	if (mutex == &bindings_mutex) {
 |  | ||||||
| +		if (bindings_locked) {
 |  | ||||||
| +			fprintf(stderr, "%s: bindings_mutex LOCKED\n", __func__);
 |  | ||||||
| +			lock_errors++;
 |  | ||||||
| +		}
 |  | ||||||
| +		bindings_locked = 1;
 |  | ||||||
| +	}  else if (mutex == ×tamp_mutex) {
 |  | ||||||
| +		if (timestamp_locked) {
 |  | ||||||
| +			fprintf(stderr, "%s: timestamp_mutex LOCKED\n", __func__);
 |  | ||||||
| +			lock_errors++;
 |  | ||||||
| +		}
 |  | ||||||
| +		timestamp_locked = 1;
 |  | ||||||
| +	} else
 |  | ||||||
| +		  fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex);
 |  | ||||||
| +	return 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +int __wrap_pthread_mutex_unlock(pthread_mutex_t *mutex)
 |  | ||||||
| +{
 |  | ||||||
| +	if (mutex == &bindings_mutex) {
 |  | ||||||
| +		if (!bindings_locked) {
 |  | ||||||
| +			fprintf(stderr, "%s: bindings_mutex UNLOCKED\n", __func__);
 |  | ||||||
| +			lock_errors++;
 |  | ||||||
| +		}
 |  | ||||||
| +		bindings_locked = 0;
 |  | ||||||
| +	}  else if (mutex == ×tamp_mutex) {
 |  | ||||||
| +		if (!timestamp_locked) {
 |  | ||||||
| +			fprintf(stderr, "%s: timestamp_mutex UNLOCKED\n", __func__);
 |  | ||||||
| +			lock_errors++;
 |  | ||||||
| +		}
 |  | ||||||
| +		timestamp_locked = 0;
 |  | ||||||
| +	} else
 |  | ||||||
| +		  fprintf(stderr, "%s called for unknown mutex %p\n", __func__, mutex);
 |  | ||||||
| +	return 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  #define TEST_FDNO 1234 |  | ||||||
|  #define TEST_FPTR ((FILE *) 0xaffe) |  | ||||||
|   |  | ||||||
| @@ -1718,6 +1759,10 @@ static void gufa_old_nomatch_nowwidmatch(void **state) {
 |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +static void gufa_check_locking(void **state) {
 |  | ||||||
| +	assert_int_equal(lock_errors, 0);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
|  static int test_get_user_friendly_alias() |  | ||||||
|  { |  | ||||||
|  	const struct CMUnitTest tests[] = { |  | ||||||
| @@ -1743,6 +1788,7 @@ static int test_get_user_friendly_alias()
 |  | ||||||
|  		cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings), |  | ||||||
|  		cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings), |  | ||||||
|  		cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings), |  | ||||||
| +		cmocka_unit_test(gufa_check_locking),
 |  | ||||||
|  	}; |  | ||||||
|   |  | ||||||
|  	return cmocka_run_group_tests(tests, NULL, NULL); |  | ||||||
| @ -1,73 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 22:13:51 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools Makefile: sanitize paths for configuration |  | ||||||
|  files |  | ||||||
| 
 |  | ||||||
| Make the path to multipath.conf configurable, and use the same prefix |  | ||||||
| by default for multipath.conf and multipath/conf.d. For "usr-merged" |  | ||||||
| distributions with immutable /usr, we'll want to have the configuration |  | ||||||
| under a different prefix. This can be achieved by using e.g. |  | ||||||
| 
 |  | ||||||
|     make prefix=/usr etc_prefix="" |  | ||||||
| 
 |  | ||||||
| Note that with prefix=/usr, before this patch the code would use |  | ||||||
| /usr/etc/multipath/conf.d, but /etc/multipath.conf. If this (rather |  | ||||||
| inconsistent) behavior is desired, use the following command line: |  | ||||||
| 
 |  | ||||||
|     make prefix=/usr configfile=/etc/multipath.conf |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  Makefile.inc            | 9 ++++++--- |  | ||||||
|  libmultipath/defaults.h | 1 - |  | ||||||
|  2 files changed, 6 insertions(+), 4 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 |  | ||||||
| index 502cd0f1..39972d93 100644
 |  | ||||||
| --- a/Makefile.inc
 |  | ||||||
| +++ b/Makefile.inc
 |  | ||||||
| @@ -37,6 +37,8 @@ prefix		:=
 |  | ||||||
|  exec_prefix	:= $(prefix) |  | ||||||
|  # Prefix for non-essential libraries (libdmmp) |  | ||||||
|  usr_prefix	:= $(prefix) |  | ||||||
| +# Prefix for configfuration files (multipath.conf)
 |  | ||||||
| +etc_prefix	:= $(prefix)
 |  | ||||||
|  # Where to install systemd-related files. systemd is usually installed under /usr |  | ||||||
|  # Note: some systemd installations use separate "prefix" and "rootprefix". |  | ||||||
|  # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) |  | ||||||
| @@ -54,7 +56,8 @@ usrlibdir	:= $(usr_prefix)/$(LIB)
 |  | ||||||
|  includedir	:= $(usr_prefix)/include |  | ||||||
|  pkgconfdir	:= $(usrlibdir)/pkgconfig |  | ||||||
|  plugindir       := $(prefix)/$(LIB)/multipath |  | ||||||
| -configdir       := $(prefix)/etc/multipath/conf.d
 |  | ||||||
| +configdir       := $(etc_prefix)/etc/multipath/conf.d
 |  | ||||||
| +configfile      := $(etc_prefix)/etc/multipath.conf
 |  | ||||||
|  runtimedir      := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) |  | ||||||
|  devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) |  | ||||||
|  libudev_incdir	:= $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) |  | ||||||
| @@ -84,8 +87,8 @@ WARNFLAGS	:= -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici
 |  | ||||||
|  		  $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) |  | ||||||
|  CPPFLAGS	:= $(FORTIFY_OPT) $(CPPFLAGS) \ |  | ||||||
|  		   -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ |  | ||||||
| -		   -DRUNTIME_DIR=\"$(runtimedir)\" \
 |  | ||||||
| -		   -DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
 |  | ||||||
| +		   -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \
 |  | ||||||
| +		   -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
 |  | ||||||
|  CFLAGS		:= --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe |  | ||||||
|  BIN_CFLAGS	:= -fPIE -DPIE |  | ||||||
|  LIB_CFLAGS	:= -fPIC |  | ||||||
| diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
 |  | ||||||
| index b3f11d4c..bc2d6388 100644
 |  | ||||||
| --- a/libmultipath/defaults.h
 |  | ||||||
| +++ b/libmultipath/defaults.h
 |  | ||||||
| @@ -66,7 +66,6 @@
 |  | ||||||
|  #define MAX_DEV_LOSS_TMO	UINT_MAX |  | ||||||
|  #define DEFAULT_PIDFILE		RUNTIME_DIR "/multipathd.pid" |  | ||||||
|  #define DEFAULT_SOCKET		"/org/kernel/linux/storage/multipathd" |  | ||||||
| -#define DEFAULT_CONFIGFILE	"/etc/multipath.conf"
 |  | ||||||
|  #define DEFAULT_BINDINGS_FILE	"/etc/multipath/bindings" |  | ||||||
|  #define DEFAULT_WWIDS_FILE	"/etc/multipath/wwids" |  | ||||||
|  #define DEFAULT_PRKEYS_FILE    "/etc/multipath/prkeys" |  | ||||||
| @ -1,58 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 22:26:22 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools: add compile time configuration for |  | ||||||
|  "/etc/multipath" |  | ||||||
| 
 |  | ||||||
| Instead of hard-conding "/etc/multipath" as the path for the state |  | ||||||
| files "bindings", "prkeys", and "wwids", make this path configurable |  | ||||||
| via the "statedir" compile-time option. The default is currently still |  | ||||||
| /etc, it might change to /var/lib or similar in the future. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  Makefile.inc            | 4 +++- |  | ||||||
|  libmultipath/defaults.h | 6 +++--- |  | ||||||
|  2 files changed, 6 insertions(+), 4 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 |  | ||||||
| index 39972d93..96206b2f 100644
 |  | ||||||
| --- a/Makefile.inc
 |  | ||||||
| +++ b/Makefile.inc
 |  | ||||||
| @@ -58,6 +58,7 @@ pkgconfdir	:= $(usrlibdir)/pkgconfig
 |  | ||||||
|  plugindir       := $(prefix)/$(LIB)/multipath |  | ||||||
|  configdir       := $(etc_prefix)/etc/multipath/conf.d |  | ||||||
|  configfile      := $(etc_prefix)/etc/multipath.conf |  | ||||||
| +statedir        := $(etc_prefix)/etc/multipath
 |  | ||||||
|  runtimedir      := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) |  | ||||||
|  devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) |  | ||||||
|  libudev_incdir	:= $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) |  | ||||||
| @@ -88,7 +89,8 @@ WARNFLAGS	:= -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implici
 |  | ||||||
|  CPPFLAGS	:= $(FORTIFY_OPT) $(CPPFLAGS) \ |  | ||||||
|  		   -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ |  | ||||||
|  		   -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ |  | ||||||
| -		   -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
 |  | ||||||
| +		   -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \
 |  | ||||||
| +		   -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
 |  | ||||||
|  CFLAGS		:= --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe |  | ||||||
|  BIN_CFLAGS	:= -fPIE -DPIE |  | ||||||
|  LIB_CFLAGS	:= -fPIC |  | ||||||
| diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
 |  | ||||||
| index bc2d6388..d01f9712 100644
 |  | ||||||
| --- a/libmultipath/defaults.h
 |  | ||||||
| +++ b/libmultipath/defaults.h
 |  | ||||||
| @@ -66,9 +66,9 @@
 |  | ||||||
|  #define MAX_DEV_LOSS_TMO	UINT_MAX |  | ||||||
|  #define DEFAULT_PIDFILE		RUNTIME_DIR "/multipathd.pid" |  | ||||||
|  #define DEFAULT_SOCKET		"/org/kernel/linux/storage/multipathd" |  | ||||||
| -#define DEFAULT_BINDINGS_FILE	"/etc/multipath/bindings"
 |  | ||||||
| -#define DEFAULT_WWIDS_FILE	"/etc/multipath/wwids"
 |  | ||||||
| -#define DEFAULT_PRKEYS_FILE    "/etc/multipath/prkeys"
 |  | ||||||
| +#define DEFAULT_BINDINGS_FILE	STATE_DIR "/bindings"
 |  | ||||||
| +#define DEFAULT_WWIDS_FILE	STATE_DIR "/wwids"
 |  | ||||||
| +#define DEFAULT_PRKEYS_FILE	STATE_DIR "/prkeys"
 |  | ||||||
|  #define MULTIPATH_SHM_BASE	RUNTIME_DIR "/multipath/" |  | ||||||
|   |  | ||||||
|   |  | ||||||
| @ -1,366 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Fri, 8 Sep 2023 22:48:16 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools man pages: generate with correct paths |  | ||||||
| 
 |  | ||||||
| Generate the man pages using the compile-time settings for paths |  | ||||||
| to multipath.conf etc. |  | ||||||
| 
 |  | ||||||
| Add a paragraph about the CONFIGDIR (/etc/multipath/conf.d) |  | ||||||
| and the drop-in configuration files in the multipath.conf man page. |  | ||||||
| 
 |  | ||||||
| Also, make sure all generated man pages and other files are correctly |  | ||||||
| removed by "make clean". |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  .gitignore                                    |  4 +++ |  | ||||||
|  Makefile.inc                                  |  3 +++ |  | ||||||
|  mpathpersist/Makefile                         |  5 ++-- |  | ||||||
|  .../{mpathpersist.8 => mpathpersist.8.in}     |  2 +- |  | ||||||
|  multipath/Makefile                            | 13 +++++---- |  | ||||||
|  multipath/{multipath.8 => multipath.8.in}     | 10 +++---- |  | ||||||
|  .../{multipath.conf.5 => multipath.conf.5.in} | 27 ++++++++++++------- |  | ||||||
|  multipathd/Makefile                           |  9 ++++--- |  | ||||||
|  multipathd/{multipathd.8 => multipathd.8.in}  |  8 +++--- |  | ||||||
|  9 files changed, 49 insertions(+), 32 deletions(-) |  | ||||||
|  rename mpathpersist/{mpathpersist.8 => mpathpersist.8.in} (99%) |  | ||||||
|  rename multipath/{multipath.8 => multipath.8.in} (97%) |  | ||||||
|  rename multipath/{multipath.conf.5 => multipath.conf.5.in} (98%) |  | ||||||
|  rename multipathd/{multipathd.8 => multipathd.8.in} (97%) |  | ||||||
| 
 |  | ||||||
| diff --git a/.gitignore b/.gitignore
 |  | ||||||
| index 535353e5..2986578f 100644
 |  | ||||||
| --- a/.gitignore
 |  | ||||||
| +++ b/.gitignore
 |  | ||||||
| @@ -13,11 +13,15 @@ cscope.files
 |  | ||||||
|  cscope.out |  | ||||||
|  kpartx/kpartx |  | ||||||
|  multipath/multipath |  | ||||||
| +multipath/multipath.8
 |  | ||||||
| +multipath/multipath.conf.5
 |  | ||||||
|  multipath/multipath.rules |  | ||||||
|  multipath/tmpfiles.conf |  | ||||||
|  multipathd/multipathd |  | ||||||
| +multipathd/multipathd.8
 |  | ||||||
|  multipathd/multipathc |  | ||||||
|  mpathpersist/mpathpersist |  | ||||||
| +mpathpersist/mpathpersist.8
 |  | ||||||
|  abi.tar.gz |  | ||||||
|  abi |  | ||||||
|  abi-test |  | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 |  | ||||||
| index 96206b2f..79e521e1 100644
 |  | ||||||
| --- a/Makefile.inc
 |  | ||||||
| +++ b/Makefile.inc
 |  | ||||||
| @@ -133,3 +133,6 @@ NV_VERSION_SCRIPT = $(DEVLIB:%.so=%-nv.version)
 |  | ||||||
|  	@grep -P '^[ \t]+[a-zA-Z_][a-zA-Z0-9_]*;' $< >>$@ |  | ||||||
|  	@printf 'local:\n\t*;\n};\n' >>$@ |  | ||||||
|   |  | ||||||
| +%:	%.in
 |  | ||||||
| +	@echo creating $@
 |  | ||||||
| +	$(Q)sed 's:@CONFIGFILE@:'$(configfile)':g;s:@CONFIGDIR@:'$(configdir)':g;s:@STATE_DIR@:'$(statedir)':g;s:@RUNTIME_DIR@:'$(runtimedir)':g' $< >$@
 |  | ||||||
| diff --git a/mpathpersist/Makefile b/mpathpersist/Makefile
 |  | ||||||
| index f57c105c..f3749467 100644
 |  | ||||||
| --- a/mpathpersist/Makefile
 |  | ||||||
| +++ b/mpathpersist/Makefile
 |  | ||||||
| @@ -8,10 +8,11 @@ LIBDEPS += -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath \
 |  | ||||||
|  	-L$(mpathutildir) -lmpathutil -L$(mpathcmddir) -lmpathcmd -lpthread -ldevmapper -ludev |  | ||||||
|   |  | ||||||
|  EXEC = mpathpersist |  | ||||||
| +MANPAGES := mpathpersist.8
 |  | ||||||
|   |  | ||||||
|  OBJS = main.o |  | ||||||
|   |  | ||||||
| -all: $(EXEC)
 |  | ||||||
| +all: $(EXEC) $(MANPAGES)
 |  | ||||||
|   |  | ||||||
|  $(EXEC): $(OBJS) |  | ||||||
|  	$(Q)$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS) $(CFLAGS) $(LIBDEPS) |  | ||||||
| @@ -23,7 +24,7 @@ install:
 |  | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8 |  | ||||||
|   |  | ||||||
|  clean: dep_clean |  | ||||||
| -	$(Q)$(RM) core *.o $(EXEC)
 |  | ||||||
| +	$(Q)$(RM) core *.o $(EXEC) $(MANPAGES)
 |  | ||||||
|   |  | ||||||
|  include $(wildcard $(OBJS:.o=.d)) |  | ||||||
|   |  | ||||||
| diff --git a/mpathpersist/mpathpersist.8 b/mpathpersist/mpathpersist.8.in
 |  | ||||||
| similarity index 99% |  | ||||||
| rename from mpathpersist/mpathpersist.8 |  | ||||||
| rename to mpathpersist/mpathpersist.8.in |  | ||||||
| index 8d26b37c..fecef0d6 100644
 |  | ||||||
| --- a/mpathpersist/mpathpersist.8
 |  | ||||||
| +++ b/mpathpersist/mpathpersist.8.in
 |  | ||||||
| @@ -31,7 +31,7 @@ mpathpersist \- Manages SCSI persistent reservations on dm multipath devices.
 |  | ||||||
|  . |  | ||||||
|  This utility is used to manage SCSI persistent reservations on Device Mapper |  | ||||||
|  Multipath devices. To be able to use this functionality, the \fIreservation_key\fR |  | ||||||
| -attribute must be defined in the \fI/etc/multipath.conf\fR file. Otherwise the
 |  | ||||||
| +attribute must be defined in the \fI@CONFIGFILE@\fR file. Otherwise the
 |  | ||||||
|  \fBmultipathd\fR daemon will not check for persistent reservation for newly |  | ||||||
|  discovered paths or reinstated paths. |  | ||||||
|  . |  | ||||||
| diff --git a/multipath/Makefile b/multipath/Makefile
 |  | ||||||
| index 73db991a..68cb5ce7 100644
 |  | ||||||
| --- a/multipath/Makefile
 |  | ||||||
| +++ b/multipath/Makefile
 |  | ||||||
| @@ -3,7 +3,9 @@
 |  | ||||||
|  # |  | ||||||
|  include ../Makefile.inc |  | ||||||
|   |  | ||||||
| -EXEC := multipath
 |  | ||||||
| +EXEC      := multipath
 |  | ||||||
| +MANPAGES  := multipath.8 multipath.conf.5
 |  | ||||||
| +GENERATED := $(MANPAGES) multipath.rules tmpfiles.conf
 |  | ||||||
|   |  | ||||||
|  CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathcmddir) |  | ||||||
|  CFLAGS += $(BIN_CFLAGS) |  | ||||||
| @@ -13,7 +15,7 @@ LIBDEPS += -L$(multipathdir) -lmultipath -L$(mpathutildir) -lmpathutil \
 |  | ||||||
|   |  | ||||||
|  OBJS := main.o |  | ||||||
|   |  | ||||||
| -all: $(EXEC) multipath.rules tmpfiles.conf
 |  | ||||||
| +all: $(EXEC) $(GENERATED)
 |  | ||||||
|   |  | ||||||
|  $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so |  | ||||||
|  	@echo building $@ because of $? |  | ||||||
| @@ -47,15 +49,12 @@ uninstall:
 |  | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules |  | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8 |  | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5 |  | ||||||
| +	$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf
 |  | ||||||
|   |  | ||||||
|  clean: dep_clean |  | ||||||
| -	$(Q)$(RM) core *.o $(EXEC) multipath.rules tmpfiles.conf
 |  | ||||||
| +	$(Q)$(RM) core *.o $(EXEC) $(GENERATED)
 |  | ||||||
|   |  | ||||||
|  include $(wildcard $(OBJS:.o=.d)) |  | ||||||
|   |  | ||||||
|  dep_clean: |  | ||||||
|  	$(Q)$(RM) $(OBJS:.o=.d) |  | ||||||
| -
 |  | ||||||
| -%:	%.in
 |  | ||||||
| -	@echo creating $@
 |  | ||||||
| -	$(Q)sed 's,@RUNTIME_DIR@,$(runtimedir),' $< >$@
 |  | ||||||
| diff --git a/multipath/multipath.8 b/multipath/multipath.8.in
 |  | ||||||
| similarity index 97% |  | ||||||
| rename from multipath/multipath.8 |  | ||||||
| rename to multipath/multipath.8.in |  | ||||||
| index 5fed6df7..348eb220 100644
 |  | ||||||
| --- a/multipath/multipath.8
 |  | ||||||
| +++ b/multipath/multipath.8.in
 |  | ||||||
| @@ -185,7 +185,7 @@ Display the currently used multipathd configuration.
 |  | ||||||
|  .B \-T |  | ||||||
|  Display the currently used multipathd configuration, limiting the output to |  | ||||||
|  those devices actually present in the system. This can be used a template for |  | ||||||
| -creating \fImultipath.conf\fR.
 |  | ||||||
| +creating \fI@CONFIGFILE@\fR.
 |  | ||||||
|  . |  | ||||||
|  .\" ---------------------------------------------------------------------------- |  | ||||||
|  .SH OPTIONS |  | ||||||
| @@ -233,11 +233,11 @@ option from \fBmultipath.conf(5)\fR.
 |  | ||||||
|  .B \-i |  | ||||||
|  Ignore WWIDs file when processing devices. If |  | ||||||
|  \fIfind_multipaths strict\fR or \fIfind_multipaths no\fR is set in |  | ||||||
| -\fImultipath.conf\fR, multipath only considers devices that are
 |  | ||||||
| +\fI@CONFIGFILE@\fR, multipath only considers devices that are
 |  | ||||||
|  listed in the WWIDs file. This option overrides that behavior. For other values |  | ||||||
|  of \fIfind_multipaths\fR, this option has no effect. See the description of |  | ||||||
|  \fIfind_multipaths\fR in |  | ||||||
| -.BR multipath.conf (5).
 |  | ||||||
| +.BR @CONFIGFILE@ (5).
 |  | ||||||
|  This option should only be used in rare circumstances. |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
| @@ -246,8 +246,8 @@ Treat the bindings file as read only.
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .BI \-b " file" |  | ||||||
| -Set \fIuser_friendly_names\fR bindings file location. The default is
 |  | ||||||
| -\fI/etc/multipath/bindings\fR.
 |  | ||||||
| +(\fBdeprecated, do not use\fR) Set \fIuser_friendly_names\fR bindings file location. The default is
 |  | ||||||
| +\fI@STATE_DIR@/bindings\fR.
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B \-q |  | ||||||
| diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5.in
 |  | ||||||
| similarity index 98% |  | ||||||
| rename from multipath/multipath.conf.5 |  | ||||||
| rename to multipath/multipath.conf.5.in |  | ||||||
| index 93af17db..20df2232 100644
 |  | ||||||
| --- a/multipath/multipath.conf.5
 |  | ||||||
| +++ b/multipath/multipath.conf.5.in
 |  | ||||||
| @@ -13,14 +13,14 @@
 |  | ||||||
|  .SH NAME |  | ||||||
|  .\" ---------------------------------------------------------------------------- |  | ||||||
|  . |  | ||||||
| -multipath.conf \- multipath daemon configuration file.
 |  | ||||||
| +@CONFIGFILE@, @CONFIGDIR@/*.conf \- multipath daemon configuration file.
 |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
|  .\" ---------------------------------------------------------------------------- |  | ||||||
|  .SH DESCRIPTION |  | ||||||
|  .\" ---------------------------------------------------------------------------- |  | ||||||
|  . |  | ||||||
| -.B "/etc/multipath.conf"
 |  | ||||||
| +.B "@CONFIGFILE@"
 |  | ||||||
|  is the configuration file for the multipath daemon. It is used to |  | ||||||
|  overwrite the built-in configuration table of \fBmultipathd\fP. |  | ||||||
|  Any line whose first non-white-space character is a '#' is considered |  | ||||||
| @@ -29,6 +29,15 @@ a comment line. Empty lines are ignored.
 |  | ||||||
|  Currently used multipathd configuration can be displayed with the \fBmultipath -t\fR |  | ||||||
|  or \fBmultipathd show config\fR command. |  | ||||||
|  . |  | ||||||
| +.PP
 |  | ||||||
| +Additional configuration can be made in drop-in files under
 |  | ||||||
| +.B @CONFIGDIR@.
 |  | ||||||
| +Files ending in \fI.conf\fR in this directory are read
 |  | ||||||
| +in alphabetical order, after reading \fI@CONFIGFILE@\fR.
 |  | ||||||
| +They use the same syntax as \fI@CONFIGFILE@\fR itself,
 |  | ||||||
| +and support all sections and keywords. If a keyword occurs in the same section
 |  | ||||||
| +in multiple files, the last occurence will take precedence over all others.
 |  | ||||||
| +.
 |  | ||||||
|  . |  | ||||||
|  .\" ---------------------------------------------------------------------------- |  | ||||||
|  .SH SYNTAX |  | ||||||
| @@ -85,7 +94,7 @@ not mandatory.
 |  | ||||||
|  . |  | ||||||
|  .LP |  | ||||||
|  .B Note on regular expressions: |  | ||||||
| -The \fImultipath.conf\fR syntax allows many attribute values to be specified as POSIX
 |  | ||||||
| +The \fI@CONFIGFILE@\fR syntax allows many attribute values to be specified as POSIX
 |  | ||||||
|  Extended Regular Expressions (see \fBregex\fR(7)). These regular expressions |  | ||||||
|  are \fBcase sensitive\fR and \fBnot anchored\fR, thus the expression "bar" matches "barbie", |  | ||||||
|  "rhabarber", and "wunderbar", but not "Barbie". To avoid unwanted substring |  | ||||||
| @@ -711,7 +720,7 @@ The default is: \fBno\fR
 |  | ||||||
|  .B user_friendly_names |  | ||||||
|  If set to |  | ||||||
|  .I yes |  | ||||||
| -, using the bindings file \fI/etc/multipath/bindings\fR to assign a persistent
 |  | ||||||
| +, using the bindings file \fI@STATE_DIR@/bindings\fR to assign a persistent
 |  | ||||||
|  and unique alias to the multipath, in the form of mpath<n>. If set to |  | ||||||
|  .I no |  | ||||||
|  use the WWID as the alias. In either case this be will |  | ||||||
| @@ -790,7 +799,7 @@ The full pathname of the binding file to be used when the user_friendly_names
 |  | ||||||
|  option is set. |  | ||||||
|  .RS |  | ||||||
|  .TP |  | ||||||
| -The default is: \fB/etc/multipath/bindings\fR
 |  | ||||||
| +The default is: \fB@STATE_DIR@/bindings\fR
 |  | ||||||
|  .RE |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
| @@ -801,7 +810,7 @@ The full pathname of the WWIDs file, which is used by multipath to keep track
 |  | ||||||
|  of the WWIDs for LUNs it has created multipath devices on in the past. |  | ||||||
|  .RS |  | ||||||
|  .TP |  | ||||||
| -The default is: \fB/etc/multipath/wwids\fR
 |  | ||||||
| +The default is: \fB@STATE_DIR@/wwids\fR
 |  | ||||||
|  .RE |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
| @@ -813,7 +822,7 @@ track of the persistent reservation key used for a specific WWID, when
 |  | ||||||
|  \fIreservation_key\fR is set to \fBfile\fR. |  | ||||||
|  .RS |  | ||||||
|  .TP |  | ||||||
| -The default is: \fB/etc/multipath/prkeys\fR
 |  | ||||||
| +The default is: \fB@STATE_DIR@/prkeys\fR
 |  | ||||||
|  .RE |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
| @@ -872,7 +881,7 @@ The default is: \fBno\fR
 |  | ||||||
|  .I yes |  | ||||||
|  and the SCSI layer has already attached a hardware_handler to the device, |  | ||||||
|  multipath will not force the device to use the hardware_handler specified by |  | ||||||
| -multipath.conf. If the SCSI layer has not attached a hardware handler,
 |  | ||||||
| +@CONFIGFILE@. If the SCSI layer has not attached a hardware handler,
 |  | ||||||
|  multipath will continue to use its configured hardware handler. |  | ||||||
|  .RS |  | ||||||
|  .PP |  | ||||||
| @@ -1559,7 +1568,7 @@ given device, the attributes of all matching entries are applied to it.
 |  | ||||||
|  If an attribute is specified in several matching device subsections, |  | ||||||
|  later entries take precedence. Thus, entries in files under \fIconfig_dir\fR (in |  | ||||||
|  reverse alphabetical order) have the highest precedence, followed by entries |  | ||||||
| -in \fImultipath.conf\fR; the built-in hardware table has the lowest
 |  | ||||||
| +in \fI@CONFIGFILE@\fR; the built-in hardware table has the lowest
 |  | ||||||
|  precedence. Inside a configuration file, later entries have higher precedence |  | ||||||
|  than earlier ones. |  | ||||||
|  .LP |  | ||||||
| diff --git a/multipathd/Makefile b/multipathd/Makefile
 |  | ||||||
| index 0d0146c5..cdba3db1 100644
 |  | ||||||
| --- a/multipathd/Makefile
 |  | ||||||
| +++ b/multipathd/Makefile
 |  | ||||||
| @@ -1,7 +1,8 @@
 |  | ||||||
|  include ../Makefile.inc |  | ||||||
|   |  | ||||||
| -EXEC := multipathd
 |  | ||||||
| -CLI := multipathc
 |  | ||||||
| +EXEC     := multipathd
 |  | ||||||
| +CLI      := multipathc
 |  | ||||||
| +MANPAGES := multipathd.8
 |  | ||||||
|   |  | ||||||
|  CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \ |  | ||||||
|  	$(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \ |  | ||||||
| @@ -42,7 +43,7 @@ ifeq ($(FPIN_SUPPORT),1)
 |  | ||||||
|  OBJS += fpin_handlers.o |  | ||||||
|  endif |  | ||||||
|   |  | ||||||
| -all : $(EXEC) $(CLI)
 |  | ||||||
| +all : $(EXEC) $(CLI) $(MANPAGES)
 |  | ||||||
|   |  | ||||||
|  $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so |  | ||||||
|  	@echo building $@ because of $? |  | ||||||
| @@ -79,7 +80,7 @@ uninstall:
 |  | ||||||
|  	$(Q)$(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket |  | ||||||
|   |  | ||||||
|  clean: dep_clean |  | ||||||
| -	$(Q)$(RM) core *.o $(EXEC) $(CLI)
 |  | ||||||
| +	$(Q)$(RM) core *.o $(EXEC) $(CLI) $(MANPAGES)
 |  | ||||||
|   |  | ||||||
|  include $(wildcard $(OBJS:.o=.d) $(CLI_OBJS:.o=.d)) |  | ||||||
|   |  | ||||||
| diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8.in
 |  | ||||||
| similarity index 97% |  | ||||||
| rename from multipathd/multipathd.8 |  | ||||||
| rename to multipathd/multipathd.8.in |  | ||||||
| index cc72b775..e98c27fd 100644
 |  | ||||||
| --- a/multipathd/multipathd.8
 |  | ||||||
| +++ b/multipathd/multipathd.8.in
 |  | ||||||
| @@ -155,7 +155,7 @@ Show the format wildcards used in interactive commands taking $format.
 |  | ||||||
|  .TP |  | ||||||
|  .B list|show config |  | ||||||
|  Show the currently used configuration, derived from default values and values |  | ||||||
| -specified within the configuration file \fI/etc/multipath.conf\fR.
 |  | ||||||
| +specified within the configuration file \fI@CONFIGFILE@\fR.
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B list|show config local |  | ||||||
| @@ -165,7 +165,7 @@ the devices section to those devices that are actually present in the system.
 |  | ||||||
|  .TP |  | ||||||
|  .B list|show blacklist |  | ||||||
|  Show the currently used blacklist rules, derived from default values and values |  | ||||||
| -specified within the configuration file \fI/etc/multipath.conf\fR.
 |  | ||||||
| +specified within the configuration file \fI@CONFIGFILE@\fR.
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B list|show devices |  | ||||||
| @@ -290,13 +290,13 @@ Get the current persistent reservation key associated with $map.
 |  | ||||||
|  .B map|multipath $map setprkey key $key |  | ||||||
|  Set the persistent reservation key associated with $map to $key in the |  | ||||||
|  \fIprkeys_file\fR. This key will only be used by multipathd if |  | ||||||
| -\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
 |  | ||||||
| +\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR.
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B map|multipath $map unsetprkey |  | ||||||
|  Remove the persistent reservation key associated with $map from the |  | ||||||
|  \fIprkeys_file\fR. This will only unset the key used by multipathd if |  | ||||||
| -\fIreservation_key\fR is set to \fBfile\fR in \fI/etc/multipath.conf\fR.
 |  | ||||||
| +\fIreservation_key\fR is set to \fBfile\fR in \fI@CONFIGFILE@\fR.
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B path $path setmarginal |  | ||||||
| @ -1,25 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 11 Sep 2023 09:30:13 +0200 |  | ||||||
| Subject: [PATCH] libdmmp/Makefile: fix bug in install section |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libdmmp/Makefile | 2 +- |  | ||||||
|  1 file changed, 1 insertion(+), 1 deletion(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libdmmp/Makefile b/libdmmp/Makefile
 |  | ||||||
| index 078eca8f..172ba045 100644
 |  | ||||||
| --- a/libdmmp/Makefile
 |  | ||||||
| +++ b/libdmmp/Makefile
 |  | ||||||
| @@ -44,7 +44,7 @@ install:
 |  | ||||||
|  		$(DESTDIR)$(pkgconfdir)/$(PKGFILE) |  | ||||||
|  	$(Q)sed -i 's|__INCLUDEDIR__|$(includedir)|g' \ |  | ||||||
|  		$(DESTDIR)$(pkgconfdir)/$(PKGFILE) |  | ||||||
| -	$(Q)$(INSTALL_PROGRAM) -d 755 $(DESTDIR)$(mandir)/man3
 |  | ||||||
| +	$(Q)$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(mandir)/man3
 |  | ||||||
|  	$(Q)$(INSTALL_PROGRAM) -m 644 -t $(DESTDIR)$(mandir)/man3 docs/man/*.3 |  | ||||||
|   |  | ||||||
|  uninstall: |  | ||||||
| @ -1,75 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 11 Sep 2023 10:22:13 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools: README.md: improve documentation for |  | ||||||
|  compile-time options |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  README.md | 38 ++++++++++++++++++++++++++------------ |  | ||||||
|  1 file changed, 26 insertions(+), 12 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/README.md b/README.md
 |  | ||||||
| index a7f994ae..679e55bf 100644
 |  | ||||||
| --- a/README.md
 |  | ||||||
| +++ b/README.md
 |  | ||||||
| @@ -89,9 +89,17 @@ The following variables can be passed to the `make` command line:
 |  | ||||||
|   * `plugindir="/some/path"`: directory where libmultipath plugins (path |  | ||||||
|     checkers, prioritizers, and foreign multipath support) will be looked up. |  | ||||||
|     This used to be the run-time option `multipath_dir` in earlier versions. |  | ||||||
| - * `configdir="/some/path"` : directory to search for configuration files.
 |  | ||||||
| +   The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on
 |  | ||||||
| +   systems that have `/lib64`, and `lib` otherwise.
 |  | ||||||
| + * `configfile="/some/path`": The path to the main configuration file.
 |  | ||||||
| +    The defalt is `$(etc_prefix)/etc/multipath.conf`.
 |  | ||||||
| + * `configdir="/some/path"` : directory to search for additional configuration files.
 |  | ||||||
|      This used to be the run-time option `config_dir` in earlier versions. |  | ||||||
| -	The default is `/etc/multipath/conf.d`.
 |  | ||||||
| +	The default is `$(etc_prefix)/etc/multipath/conf.d`.
 |  | ||||||
| + * `statedir="/some/path"`: The path of the directory where multipath-tools
 |  | ||||||
| +    stores run-time settings that need persist between reboots, such as known
 |  | ||||||
| +	WWIDs, user-friendly names, and persistent reservation keys.
 |  | ||||||
| +	The default is `$(etc_prefix)/etc/multipath`.
 |  | ||||||
|   * `READLINE=libedit` or `READLINE=libreadline`: enable command line history |  | ||||||
|      and TAB completion in the interactive mode *(which is entered with `multipathd -k` or `multipathc`)*. |  | ||||||
|      The respective development package will be required for building. |  | ||||||
| @@ -119,21 +127,27 @@ The following variables can be passed to the `make` command line:
 |  | ||||||
|  ### Installation Paths |  | ||||||
|   |  | ||||||
|   * `prefix`: The directory prefix for (almost) all files to be installed. |  | ||||||
| -   Distributions may want to set this to `/usr`.
 |  | ||||||
| -   **Note**: for multipath-tools, unlike many other packages, `prefix`
 |  | ||||||
| -   defaults to the empty string, which resolves to the root directory (`/`).
 |  | ||||||
| +   "Usr-merged" distributions[^systemd] may want to set this to `/usr`. The
 |  | ||||||
| +   default is empty (`""`).
 |  | ||||||
|   * `usr_prefix`: where to install those parts of the code that aren't necessary |  | ||||||
| -   for booting. You may want to set this to `/usr` if `prefix` is empty.
 |  | ||||||
| - * `systemd_prefix`: Prefix for systemd-related files. It defaults to `/usr`.
 |  | ||||||
| -   Some systemd installations use separate `prefix` and `rootprefix`. On such
 |  | ||||||
| -   a distribution, set `prefix`, and override `unitdir` to use systemd's
 |  | ||||||
| -   `rootprefix`.
 |  | ||||||
| +   for booting. Non-usr-merged distributions[^systemd] may want to set this to
 |  | ||||||
| +   `/usr`. The default is `$(prefix)`.
 |  | ||||||
| + * `systemd_prefix`: Prefix for systemd-related files[^systemd]. The default is `/usr`.
 |  | ||||||
| + * `etc_prefix`: The prefix for configuration files. "Usr-merged"
 |  | ||||||
| +   distributions with immutable `/usr`[^systemd] may want to set this to
 |  | ||||||
| +   `/etc`. The default is `$(prefix)`.
 |  | ||||||
|   * `LIB`: the subdirectory under `prefix` where shared libraries will be |  | ||||||
|     installed. By default, the makefile uses `/lib64` if this directory is |  | ||||||
|     found on the build system, and `/lib` otherwise. |  | ||||||
|      |  | ||||||
| -See also `configdir` and `plugindir` above. See `Makefile.inc` for more
 |  | ||||||
| -fine-grained control.
 |  | ||||||
| +The options `configdir`, `plugindir`, `configfile`, and `statedir` above can
 |  | ||||||
| +be used for setting indvidual paths where the `prefix` variables don't provide
 |  | ||||||
| +sufficient control. See `Makefile.inc` for even more fine-grained control.
 |  | ||||||
| +
 |  | ||||||
| +[^systemd]: Some systemd installations use separate `prefix` and `rootprefix`. 
 |  | ||||||
| +	On such a distribution, set `prefix`, and override `unitdir` to use systemd's
 |  | ||||||
| +   `rootprefix`. Recent systemd releases generally require everything to be
 |  | ||||||
| +	installed under `/usr` (so-called "usr-merged" distribution). On "usr-
 |  | ||||||
|   |  | ||||||
|  ### Compiler Options |  | ||||||
|   |  | ||||||
| @ -1,55 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 11 Sep 2023 11:36:25 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: print built-in values for deprecated options |  | ||||||
| 
 |  | ||||||
| In the error messages we print when a deprecated option is encountered, |  | ||||||
| print the compile-time value of the option. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/dict.c | 16 +++++++++------- |  | ||||||
|  1 file changed, 9 insertions(+), 7 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/dict.c b/libmultipath/dict.c
 |  | ||||||
| index f81c84aa..dace343d 100644
 |  | ||||||
| --- a/libmultipath/dict.c
 |  | ||||||
| +++ b/libmultipath/dict.c
 |  | ||||||
| @@ -314,14 +314,16 @@ def_ ## option ## _handler (struct config *conf, vector strvec,		\
 |  | ||||||
|  static int deprecated_handler(struct config *conf, vector strvec, const char *file, |  | ||||||
|  			      int line_nr); |  | ||||||
|   |  | ||||||
| -#define declare_deprecated_handler(option)				\
 |  | ||||||
| +#define declare_deprecated_handler(option, default)				\
 |  | ||||||
|  static int								\ |  | ||||||
|  deprecated_ ## option ## _handler (struct config *conf, vector strvec,	\ |  | ||||||
|  				   const char *file, int line_nr)	\ |  | ||||||
|  {									\ |  | ||||||
|  	static bool warned;						\ |  | ||||||
|  	if (!warned) {							\ |  | ||||||
| -		condlog(1, "%s line %d: ignoring deprecated option \"" #option "\"", file, line_nr); \
 |  | ||||||
| +		condlog(1, "%s line %d: ignoring deprecated option \""	\
 |  | ||||||
| +			#option "\", using built-in value: \"%s\"",	\
 |  | ||||||
| +			file, line_nr, default);			\
 |  | ||||||
|  		warned = true;						\ |  | ||||||
|  	}								\ |  | ||||||
|  	return deprecated_handler(conf, strvec, file, line_nr);		\ |  | ||||||
| @@ -2057,11 +2059,11 @@ snprint_deprecated (struct config *conf, struct strbuf *buff, const void * data)
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  // Deprecated keywords |  | ||||||
| -declare_deprecated_handler(config_dir)
 |  | ||||||
| -declare_deprecated_handler(disable_changed_wwids)
 |  | ||||||
| -declare_deprecated_handler(getuid_callout)
 |  | ||||||
| -declare_deprecated_handler(multipath_dir)
 |  | ||||||
| -declare_deprecated_handler(pg_timeout)
 |  | ||||||
| +declare_deprecated_handler(config_dir, CONFIG_DIR)
 |  | ||||||
| +declare_deprecated_handler(disable_changed_wwids, "yes")
 |  | ||||||
| +declare_deprecated_handler(getuid_callout, "(not set)")
 |  | ||||||
| +declare_deprecated_handler(multipath_dir, MULTIPATH_DIR)
 |  | ||||||
| +declare_deprecated_handler(pg_timeout, "(not set)")
 |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
|   * If you add or remove a keyword also update multipath/multipath.conf.5 |  | ||||||
| @ -1,25 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 11 Sep 2023 11:37:37 +0200 |  | ||||||
| Subject: [PATCH] multipath: add a missing newline |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  multipath/main.c | 2 +- |  | ||||||
|  1 file changed, 1 insertion(+), 1 deletion(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/multipath/main.c b/multipath/main.c
 |  | ||||||
| index 45e9745f..b91289e8 100644
 |  | ||||||
| --- a/multipath/main.c
 |  | ||||||
| +++ b/multipath/main.c
 |  | ||||||
| @@ -1025,7 +1025,7 @@ main (int argc, char *argv[])
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	if (check_alias_settings(conf)) { |  | ||||||
| -		fprintf(stderr, "fatal configuration error, aborting");
 |  | ||||||
| +		fprintf(stderr, "fatal configuration error, aborting\n");
 |  | ||||||
|  		exit(RTVL_FAIL); |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| @ -1,66 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 11 Sep 2023 16:03:34 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools: allow prefixes with and w/o trailing slash |  | ||||||
| 
 |  | ||||||
| Add some logic to Makefile.inc that leads to the same result |  | ||||||
| for "prefix=" and "prefix=/", or "prefix=/usr" and "prefix=/usr/". |  | ||||||
| The logic does not work for multiple trailing slashes. It applies |  | ||||||
| to all XYZ_prefix variables in Makefile.inc. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  Makefile.inc | 35 ++++++++++++++++++++++------------- |  | ||||||
|  1 file changed, 22 insertions(+), 13 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 |  | ||||||
| index 79e521e1..6e384e68 100644
 |  | ||||||
| --- a/Makefile.inc
 |  | ||||||
| +++ b/Makefile.inc
 |  | ||||||
| @@ -43,22 +43,31 @@ etc_prefix	:= $(prefix)
 |  | ||||||
|  # Note: some systemd installations use separate "prefix" and "rootprefix". |  | ||||||
|  # In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix) |  | ||||||
|  systemd_prefix  := /usr |  | ||||||
| -unitdir		:= $(systemd_prefix)/lib/systemd/system
 |  | ||||||
| -tmpfilesdir	:= $(systemd_prefix)/lib/tmpfiles.d
 |  | ||||||
| -modulesloaddir	:= $(systemd_prefix)/lib/modules-load.d
 |  | ||||||
| -libudevdir	:= $(systemd_prefix)/lib/udev
 |  | ||||||
| +
 |  | ||||||
| +# Make sure all prefix variables end in "/"
 |  | ||||||
| +append-slash = $(1)$(if $(filter %/,$(1)),,/)
 |  | ||||||
| +override prefix          := $(call append-slash,$(prefix))
 |  | ||||||
| +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))
 |  | ||||||
| +
 |  | ||||||
| +unitdir		:= $(systemd_prefix)lib/systemd/system
 |  | ||||||
| +tmpfilesdir	:= $(systemd_prefix)lib/tmpfiles.d
 |  | ||||||
| +modulesloaddir	:= $(systemd_prefix)lib/modules-load.d
 |  | ||||||
| +libudevdir	:= $(systemd_prefix)lib/udev
 |  | ||||||
|  udevrulesdir	:= $(libudevdir)/rules.d |  | ||||||
| -bindir		:= $(exec_prefix)/sbin
 |  | ||||||
| -mandir		:= $(usr_prefix)/share/man
 |  | ||||||
| +bindir		:= $(exec_prefix)sbin
 |  | ||||||
| +mandir		:= $(usr_prefix)share/man
 |  | ||||||
|  LIB		:= $(if $(shell test -d /lib64 && echo 1),lib64,lib) |  | ||||||
| -syslibdir	:= $(prefix)/$(LIB)
 |  | ||||||
| -usrlibdir	:= $(usr_prefix)/$(LIB)
 |  | ||||||
| -includedir	:= $(usr_prefix)/include
 |  | ||||||
| +syslibdir	:= $(prefix)$(LIB)
 |  | ||||||
| +usrlibdir	:= $(usr_prefix)$(LIB)
 |  | ||||||
| +includedir	:= $(usr_prefix)include
 |  | ||||||
|  pkgconfdir	:= $(usrlibdir)/pkgconfig |  | ||||||
| -plugindir       := $(prefix)/$(LIB)/multipath
 |  | ||||||
| -configdir       := $(etc_prefix)/etc/multipath/conf.d
 |  | ||||||
| -configfile      := $(etc_prefix)/etc/multipath.conf
 |  | ||||||
| -statedir        := $(etc_prefix)/etc/multipath
 |  | ||||||
| +plugindir       := $(prefix)$(LIB)/multipath
 |  | ||||||
| +configdir       := $(etc_prefix)etc/multipath/conf.d
 |  | ||||||
| +configfile      := $(etc_prefix)etc/multipath.conf
 |  | ||||||
| +statedir        := $(etc_prefix)etc/multipath
 |  | ||||||
|  runtimedir      := $(if $(shell test -L /var/run -o ! -d /var/run && echo 1),/run,/var/run) |  | ||||||
|  devmapper_incdir := $(or $(shell $(PKG_CONFIG) --variable=includedir devmapper),/usr/include) |  | ||||||
|  libudev_incdir	:= $(or $(shell $(PKG_CONFIG) --variable=includedir libudev),/usr/include) |  | ||||||
| @ -1,897 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Mon, 11 Sep 2023 17:58:13 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: deprecate bindings_file, wwids_file, |  | ||||||
|  prkeys_file |  | ||||||
| 
 |  | ||||||
| The options bindings_file, wwids_file, and prkeys_file have been |  | ||||||
| deprecated since cb4d6db ("libmultipath: deprecate file and directory config |  | ||||||
| options") (multipath-tools 0.8.8). Deprecate and ignore them now. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  libmultipath/alias.c              | 43 +++++++++---------- |  | ||||||
|  libmultipath/alias.h              |  3 +- |  | ||||||
|  libmultipath/config.c             | 18 -------- |  | ||||||
|  libmultipath/config.h             |  3 -- |  | ||||||
|  libmultipath/dict.c               | 39 +++--------------- |  | ||||||
|  libmultipath/libmultipath.version |  8 +--- |  | ||||||
|  libmultipath/prkey.c              |  7 ++-- |  | ||||||
|  libmultipath/prkey.h              |  7 ++-- |  | ||||||
|  libmultipath/propsel.c            |  5 +-- |  | ||||||
|  libmultipath/wwids.c              | 18 ++------ |  | ||||||
|  multipath/main.c                  |  2 +- |  | ||||||
|  multipath/multipath.conf.5.in     | 23 +++++------ |  | ||||||
|  multipathd/uxlsnr.c               | 17 +++----- |  | ||||||
|  tests/alias.c                     | 68 +++++++++++++++---------------- |  | ||||||
|  14 files changed, 90 insertions(+), 171 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index 964b8a7b..e5d3f151 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -55,6 +55,8 @@
 |  | ||||||
|  /* uatomic access only */ |  | ||||||
|  static int bindings_file_changed = 1; |  | ||||||
|   |  | ||||||
| +static const char bindings_file_path[] = DEFAULT_BINDINGS_FILE;
 |  | ||||||
| +
 |  | ||||||
|  static pthread_mutex_t timestamp_mutex = PTHREAD_MUTEX_INITIALIZER; |  | ||||||
|  static struct timespec bindings_last_updated; |  | ||||||
|   |  | ||||||
| @@ -274,7 +276,6 @@ static int write_bindings_file(const Bindings *bindings, int fd,
 |  | ||||||
|   |  | ||||||
|  void handle_bindings_file_inotify(const struct inotify_event *event) |  | ||||||
|  { |  | ||||||
| -	struct config *conf;
 |  | ||||||
|  	const char *base; |  | ||||||
|  	bool changed = false; |  | ||||||
|  	struct stat st; |  | ||||||
| @@ -284,12 +285,9 @@ void handle_bindings_file_inotify(const struct inotify_event *event)
 |  | ||||||
|  	if (!(event->mask & IN_MOVED_TO)) |  | ||||||
|  		return; |  | ||||||
|   |  | ||||||
| -	conf = get_multipath_config();
 |  | ||||||
| -	base = strrchr(conf->bindings_file, '/');
 |  | ||||||
| -	changed = base && base > conf->bindings_file &&
 |  | ||||||
| -		!strcmp(base + 1, event->name);
 |  | ||||||
| -	ret = stat(conf->bindings_file, &st);
 |  | ||||||
| -	put_multipath_config(conf);
 |  | ||||||
| +	base = strrchr(bindings_file_path, '/');
 |  | ||||||
| +	changed = base && !strcmp(base + 1, event->name);
 |  | ||||||
| +	ret = stat(bindings_file_path, &st);
 |  | ||||||
|   |  | ||||||
|  	if (!changed) |  | ||||||
|  		return; |  | ||||||
| @@ -310,8 +308,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event)
 |  | ||||||
|  			__func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
| -				const char *bindings_file)
 |  | ||||||
| +static int update_bindings_file(const Bindings *bindings)
 |  | ||||||
|  { |  | ||||||
|  	int rc; |  | ||||||
|  	int fd = -1; |  | ||||||
| @@ -319,7 +316,7 @@ static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
|  	mode_t old_umask; |  | ||||||
|  	struct timespec ts; |  | ||||||
|   |  | ||||||
| -	if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file))
 |  | ||||||
| +	if (safe_sprintf(tempname, "%s.XXXXXX", bindings_file_path))
 |  | ||||||
|  		return -1; |  | ||||||
|  	/* coverity: SECURE_TEMP */ |  | ||||||
|  	old_umask = umask(0077); |  | ||||||
| @@ -336,13 +333,13 @@ static int update_bindings_file(const Bindings *bindings,
 |  | ||||||
|  		unlink(tempname); |  | ||||||
|  		return rc; |  | ||||||
|  	} |  | ||||||
| -	if ((rc = rename(tempname, bindings_file)) == -1)
 |  | ||||||
| +	if ((rc = rename(tempname, bindings_file_path)) == -1)
 |  | ||||||
|  		condlog(0, "%s: rename: %m", __func__); |  | ||||||
|  	else { |  | ||||||
|  		pthread_mutex_lock(×tamp_mutex); |  | ||||||
|  		bindings_last_updated = ts; |  | ||||||
|  		pthread_mutex_unlock(×tamp_mutex); |  | ||||||
| -		condlog(1, "updated bindings file %s", bindings_file);
 |  | ||||||
| +		condlog(1, "updated bindings file %s", bindings_file_path);
 |  | ||||||
|  	} |  | ||||||
|  	return rc; |  | ||||||
|  } |  | ||||||
| @@ -474,7 +471,7 @@ int get_free_id(const Bindings *bindings, const char *prefix, const char *map_ww
 |  | ||||||
|   |  | ||||||
|  /* Called with binding_mutex held */ |  | ||||||
|  static char * |  | ||||||
| -allocate_binding(const char *filename, const char *wwid, int id, const char *prefix)
 |  | ||||||
| +allocate_binding(const char *wwid, int id, const char *prefix)
 |  | ||||||
|  { |  | ||||||
|  	STRBUF_ON_STACK(buf); |  | ||||||
|  	char *alias; |  | ||||||
| @@ -498,7 +495,7 @@ allocate_binding(const char *filename, const char *wwid, int id, const char *pre
 |  | ||||||
|  		return NULL; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	if (update_bindings_file(&global_bindings, filename) == -1) {
 |  | ||||||
| +	if (update_bindings_file(&global_bindings) == -1) {
 |  | ||||||
|  		condlog(1, "%s: deleting binding %s for %s", __func__, alias, wwid); |  | ||||||
|  		delete_binding(&global_bindings, wwid); |  | ||||||
|  		free(alias); |  | ||||||
| @@ -565,7 +562,7 @@ static void read_bindings_file(void)
 |  | ||||||
|   *    that the mpvec corrcectly represents kernel state. |  | ||||||
|   */ |  | ||||||
|   |  | ||||||
| -char *get_user_friendly_alias(const char *wwid, const char *file, const char *alias_old,
 |  | ||||||
| +char *get_user_friendly_alias(const char *wwid, const char *alias_old,
 |  | ||||||
|  			      const char *prefix, bool bindings_read_only) |  | ||||||
|  { |  | ||||||
|  	char *alias = NULL; |  | ||||||
| @@ -622,7 +619,7 @@ new_alias:
 |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	if (!bindings_read_only && id > 0) |  | ||||||
| -		alias = allocate_binding(file, wwid, id, prefix);
 |  | ||||||
| +		alias = allocate_binding(wwid, id, prefix);
 |  | ||||||
|   |  | ||||||
|  	if (alias && !new_binding) |  | ||||||
|  		condlog(2, "Allocated existing binding [%s] for WWID [%s]", |  | ||||||
| @@ -715,12 +712,12 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
 |  | ||||||
|  	header[sizeof(BINDINGS_FILE_HEADER) - 1] = '\0'; |  | ||||||
|  	if (fread(header, sizeof(BINDINGS_FILE_HEADER) - 1, 1, file) < 1) { |  | ||||||
|  		condlog(2, "%s: failed to read header from %s", __func__, |  | ||||||
| -			conf->bindings_file);
 |  | ||||||
| +			bindings_file_path);
 |  | ||||||
|  		fseek(file, 0, SEEK_SET); |  | ||||||
|  		rc = -1; |  | ||||||
|  	} else if (strcmp(header, BINDINGS_FILE_HEADER)) { |  | ||||||
|  		condlog(2, "%s: invalid header in %s", __func__, |  | ||||||
| -			conf->bindings_file);
 |  | ||||||
| +			bindings_file_path);
 |  | ||||||
|  		fseek(file, 0, SEEK_SET); |  | ||||||
|  		rc = -1; |  | ||||||
|  	} |  | ||||||
| @@ -787,13 +784,13 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings,
 |  | ||||||
|  		} |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	fd = open_file(conf->bindings_file, &can_write, BINDINGS_FILE_HEADER);
 |  | ||||||
| +	fd = open_file(bindings_file_path, &can_write, BINDINGS_FILE_HEADER);
 |  | ||||||
|  	if (fd == -1) |  | ||||||
|  		return BINDINGS_FILE_ERROR; |  | ||||||
|   |  | ||||||
|  	file = fdopen(fd, "r"); |  | ||||||
|  	if (file != NULL) { |  | ||||||
| -		condlog(3, "%s: reading %s", __func__, conf->bindings_file);
 |  | ||||||
| +		condlog(3, "%s: reading %s", __func__, bindings_file_path);
 |  | ||||||
|   |  | ||||||
|  		pthread_cleanup_push(cleanup_fclose, file); |  | ||||||
|  		ret = _check_bindings_file(conf, file, bindings); |  | ||||||
| @@ -812,20 +809,20 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings,
 |  | ||||||
|  			bindings_last_updated = ts; |  | ||||||
|  			pthread_mutex_unlock(×tamp_mutex); |  | ||||||
|  		} else if (ret == -1 && can_write && !conf->bindings_read_only) { |  | ||||||
| -			ret = update_bindings_file(bindings, conf->bindings_file);
 |  | ||||||
| +			ret = update_bindings_file(bindings);
 |  | ||||||
|  			if (ret == 0) |  | ||||||
|  				rc = BINDINGS_FILE_READ; |  | ||||||
|  			else |  | ||||||
|  				rc = BINDINGS_FILE_BAD; |  | ||||||
|  		} else { |  | ||||||
|  			condlog(0, "ERROR: bad settings in read-only bindings file %s", |  | ||||||
| -				conf->bindings_file);
 |  | ||||||
| +				bindings_file_path);
 |  | ||||||
|  			rc = BINDINGS_FILE_BAD; |  | ||||||
|  		} |  | ||||||
|  		pthread_cleanup_pop(1); |  | ||||||
|  	} else { |  | ||||||
|  		condlog(1, "failed to fdopen %s: %m", |  | ||||||
| -			conf->bindings_file);
 |  | ||||||
| +			bindings_file_path);
 |  | ||||||
|  		close(fd); |  | ||||||
|  		rc = BINDINGS_FILE_ERROR; |  | ||||||
|  	} |  | ||||||
| diff --git a/libmultipath/alias.h b/libmultipath/alias.h
 |  | ||||||
| index ca8911f4..629e8d56 100644
 |  | ||||||
| --- a/libmultipath/alias.h
 |  | ||||||
| +++ b/libmultipath/alias.h
 |  | ||||||
| @@ -3,8 +3,7 @@
 |  | ||||||
|   |  | ||||||
|  int valid_alias(const char *alias); |  | ||||||
|  int get_user_friendly_wwid(const char *alias, char *buff); |  | ||||||
| -char *get_user_friendly_alias(const char *wwid, const char *file,
 |  | ||||||
| -			      const char *alias_old,
 |  | ||||||
| +char *get_user_friendly_alias(const char *wwid, const char *alias_old,
 |  | ||||||
|  			      const char *prefix, bool bindings_read_only); |  | ||||||
|   |  | ||||||
|  struct config; |  | ||||||
| diff --git a/libmultipath/config.c b/libmultipath/config.c
 |  | ||||||
| index 7b207590..b7dbc6f5 100644
 |  | ||||||
| --- a/libmultipath/config.c
 |  | ||||||
| +++ b/libmultipath/config.c
 |  | ||||||
| @@ -752,15 +752,6 @@ static void _uninit_config(struct config *conf)
 |  | ||||||
|  	if (conf->hwhandler) |  | ||||||
|  		free(conf->hwhandler); |  | ||||||
|   |  | ||||||
| -	if (conf->bindings_file)
 |  | ||||||
| -		free(conf->bindings_file);
 |  | ||||||
| -
 |  | ||||||
| -	if (conf->wwids_file)
 |  | ||||||
| -		free(conf->wwids_file);
 |  | ||||||
| -
 |  | ||||||
| -	if (conf->prkeys_file)
 |  | ||||||
| -		free(conf->prkeys_file);
 |  | ||||||
| -
 |  | ||||||
|  	if (conf->prio_name) |  | ||||||
|  		free(conf->prio_name); |  | ||||||
|   |  | ||||||
| @@ -922,9 +913,6 @@ int _init_config (const char *file, struct config *conf)
 |  | ||||||
|  	 * internal defaults |  | ||||||
|  	 */ |  | ||||||
|  	get_sys_max_fds(&conf->max_fds); |  | ||||||
| -	conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
 |  | ||||||
| -	conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
 |  | ||||||
| -	conf->prkeys_file = set_default(DEFAULT_PRKEYS_FILE);
 |  | ||||||
|  	conf->attribute_flags = 0; |  | ||||||
|  	conf->reassign_maps = DEFAULT_REASSIGN_MAPS; |  | ||||||
|  	conf->checkint = CHECKINT_UNDEF; |  | ||||||
| @@ -1078,12 +1066,6 @@ int _init_config (const char *file, struct config *conf)
 |  | ||||||
|  	merge_blacklist(conf->elist_wwid); |  | ||||||
|  	merge_blacklist_device(conf->elist_device); |  | ||||||
|   |  | ||||||
| -	if (conf->bindings_file == NULL)
 |  | ||||||
| -		conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
 |  | ||||||
| -
 |  | ||||||
| -	if (!conf->bindings_file || !conf->wwids_file || !conf->prkeys_file)
 |  | ||||||
| -		goto out;
 |  | ||||||
| -
 |  | ||||||
|  	libmp_verbosity = conf->verbosity; |  | ||||||
|  	return 0; |  | ||||||
|  out: |  | ||||||
| diff --git a/libmultipath/config.h b/libmultipath/config.h
 |  | ||||||
| index 0a2c297b..8c22ce75 100644
 |  | ||||||
| --- a/libmultipath/config.h
 |  | ||||||
| +++ b/libmultipath/config.h
 |  | ||||||
| @@ -207,9 +207,6 @@ struct config {
 |  | ||||||
|  	char * uid_attribute; |  | ||||||
|  	char * features; |  | ||||||
|  	char * hwhandler; |  | ||||||
| -	char * bindings_file;
 |  | ||||||
| -	char * wwids_file;
 |  | ||||||
| -	char * prkeys_file;
 |  | ||||||
|  	char * prio_name; |  | ||||||
|  	char * prio_args; |  | ||||||
|  	char * checker_name; |  | ||||||
| diff --git a/libmultipath/dict.c b/libmultipath/dict.c
 |  | ||||||
| index dace343d..044067af 100644
 |  | ||||||
| --- a/libmultipath/dict.c
 |  | ||||||
| +++ b/libmultipath/dict.c
 |  | ||||||
| @@ -168,27 +168,6 @@ fail:
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -static int
 |  | ||||||
| -set_path(vector strvec, void *ptr, const char *file, int line_nr)
 |  | ||||||
| -{
 |  | ||||||
| -	char **str_ptr = (char **)ptr;
 |  | ||||||
| -	char *old_str = *str_ptr;
 |  | ||||||
| -
 |  | ||||||
| -	*str_ptr = set_value(strvec);
 |  | ||||||
| -	if (!*str_ptr) {
 |  | ||||||
| -		free(old_str);
 |  | ||||||
| -		return 1;
 |  | ||||||
| -	}
 |  | ||||||
| -	if ((*str_ptr)[0] != '/'){
 |  | ||||||
| -		condlog(1, "%s line %d, %s is not an absolute path. Ignoring",
 |  | ||||||
| -			file, line_nr, *str_ptr);
 |  | ||||||
| -		free(*str_ptr);
 |  | ||||||
| -		*str_ptr = old_str;
 |  | ||||||
| -	} else
 |  | ||||||
| -		free(old_str);
 |  | ||||||
| -	return 0;
 |  | ||||||
| -}
 |  | ||||||
| -
 |  | ||||||
|  static int |  | ||||||
|  set_str_noslash(vector strvec, void *ptr, const char *file, int line_nr) |  | ||||||
|  { |  | ||||||
| @@ -831,15 +810,6 @@ declare_hw_snprint(user_friendly_names, print_yes_no_undef)
 |  | ||||||
|  declare_mp_handler(user_friendly_names, set_yes_no_undef) |  | ||||||
|  declare_mp_snprint(user_friendly_names, print_yes_no_undef) |  | ||||||
|   |  | ||||||
| -declare_def_warn_handler(bindings_file, set_path)
 |  | ||||||
| -declare_def_snprint(bindings_file, print_str)
 |  | ||||||
| -
 |  | ||||||
| -declare_def_warn_handler(wwids_file, set_path)
 |  | ||||||
| -declare_def_snprint(wwids_file, print_str)
 |  | ||||||
| -
 |  | ||||||
| -declare_def_warn_handler(prkeys_file, set_path)
 |  | ||||||
| -declare_def_snprint(prkeys_file, print_str)
 |  | ||||||
| -
 |  | ||||||
|  declare_def_handler(retain_hwhandler, set_yes_no_undef) |  | ||||||
|  declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef, |  | ||||||
|  			   DEFAULT_RETAIN_HWHANDLER) |  | ||||||
| @@ -2064,6 +2034,9 @@ declare_deprecated_handler(disable_changed_wwids, "yes")
 |  | ||||||
|  declare_deprecated_handler(getuid_callout, "(not set)") |  | ||||||
|  declare_deprecated_handler(multipath_dir, MULTIPATH_DIR) |  | ||||||
|  declare_deprecated_handler(pg_timeout, "(not set)") |  | ||||||
| +declare_deprecated_handler(bindings_file, DEFAULT_BINDINGS_FILE)
 |  | ||||||
| +declare_deprecated_handler(wwids_file, DEFAULT_WWIDS_FILE)
 |  | ||||||
| +declare_deprecated_handler(prkeys_file, DEFAULT_PRKEYS_FILE)
 |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
|   * If you add or remove a keyword also update multipath/multipath.conf.5 |  | ||||||
| @@ -2106,9 +2079,9 @@ init_keywords(vector keywords)
 |  | ||||||
|  	install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail); |  | ||||||
|  	install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss); |  | ||||||
|  	install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline); |  | ||||||
| -	install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file);
 |  | ||||||
| -	install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file);
 |  | ||||||
| -	install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file);
 |  | ||||||
| +	install_keyword("bindings_file", &deprecated_bindings_file_handler, &snprint_deprecated);
 |  | ||||||
| +	install_keyword("wwids_file", &deprecated_wwids_file_handler, &snprint_deprecated);
 |  | ||||||
| +	install_keyword("prkeys_file", &deprecated_prkeys_file_handler, &snprint_deprecated);
 |  | ||||||
|  	install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err); |  | ||||||
|  	install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key); |  | ||||||
|  	install_keyword("all_tg_pt", &def_all_tg_pt_handler, &snprint_def_all_tg_pt); |  | ||||||
| diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
 |  | ||||||
| index 57e50c12..8368ef7a 100644
 |  | ||||||
| --- a/libmultipath/libmultipath.version
 |  | ||||||
| +++ b/libmultipath/libmultipath.version
 |  | ||||||
| @@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 {
 |  | ||||||
|  	put_multipath_config; |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| -LIBMULTIPATH_20.0.0 {
 |  | ||||||
| +LIBMULTIPATH_21.0.0 {
 |  | ||||||
|  global: |  | ||||||
|  	/* symbols referenced by multipath and multipathd */ |  | ||||||
|  	add_foreign; |  | ||||||
| @@ -121,6 +121,7 @@ global:
 |  | ||||||
|  	get_used_hwes; |  | ||||||
|  	get_vpd_sgio; |  | ||||||
|  	group_by_prio; |  | ||||||
| +	handle_bindings_file_inotify;
 |  | ||||||
|  	has_dm_info; |  | ||||||
|  	init_checkers; |  | ||||||
|  	init_config; |  | ||||||
| @@ -238,8 +239,3 @@ global:
 |  | ||||||
|  local: |  | ||||||
|  	*; |  | ||||||
|  }; |  | ||||||
| -
 |  | ||||||
| -LIBMULTIPATH_20.1.0 {
 |  | ||||||
| -global:
 |  | ||||||
| -	handle_bindings_file_inotify;
 |  | ||||||
| -};
 |  | ||||||
| diff --git a/libmultipath/prkey.c b/libmultipath/prkey.c
 |  | ||||||
| index a215499d..c66d293b 100644
 |  | ||||||
| --- a/libmultipath/prkey.c
 |  | ||||||
| +++ b/libmultipath/prkey.c
 |  | ||||||
| @@ -157,8 +157,7 @@ static int do_prkey(int fd, char *wwid, char *keystr, int cmd)
 |  | ||||||
|  	return 0; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
 |  | ||||||
| -	      uint8_t *sa_flags)
 |  | ||||||
| +int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags)
 |  | ||||||
|  { |  | ||||||
|  	int fd; |  | ||||||
|  	int unused; |  | ||||||
| @@ -168,7 +167,7 @@ int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
 |  | ||||||
|  	if (!strlen(mpp->wwid)) |  | ||||||
|  		goto out; |  | ||||||
|   |  | ||||||
| -	fd = open_file(conf->prkeys_file, &unused, PRKEYS_FILE_HEADER);
 |  | ||||||
| +	fd = open_file(DEFAULT_PRKEYS_FILE, &unused, PRKEYS_FILE_HEADER);
 |  | ||||||
|  	if (fd < 0) |  | ||||||
|  		goto out; |  | ||||||
|  	ret = do_prkey(fd, mpp->wwid, keystr, PRKEY_READ); |  | ||||||
| @@ -201,7 +200,7 @@ int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey,
 |  | ||||||
|  		sa_flags &= MPATH_F_APTPL_MASK; |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
| -	fd = open_file(conf->prkeys_file, &can_write, PRKEYS_FILE_HEADER);
 |  | ||||||
| +	fd = open_file(DEFAULT_PRKEYS_FILE, &can_write, PRKEYS_FILE_HEADER);
 |  | ||||||
|  	if (fd < 0) |  | ||||||
|  		goto out; |  | ||||||
|  	if (!can_write) { |  | ||||||
| diff --git a/libmultipath/prkey.h b/libmultipath/prkey.h
 |  | ||||||
| index a16de106..43afd5e4 100644
 |  | ||||||
| --- a/libmultipath/prkey.h
 |  | ||||||
| +++ b/libmultipath/prkey.h
 |  | ||||||
| @@ -16,9 +16,8 @@
 |  | ||||||
|  int print_reservation_key(struct strbuf *buff, |  | ||||||
|  			  struct be64 key, uint8_t flags, int source); |  | ||||||
|  int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags); |  | ||||||
| -int set_prkey(struct config *conf, struct multipath *mpp, uint64_t prkey,
 |  | ||||||
| -	      uint8_t sa_flags);
 |  | ||||||
| -int get_prkey(struct config *conf, struct multipath *mpp, uint64_t *prkey,
 |  | ||||||
| -	      uint8_t *sa_flags);
 |  | ||||||
| +int set_prkey(struct config *conf, struct multipath *mpp,
 |  | ||||||
| +	      uint64_t prkey, uint8_t sa_flags);
 |  | ||||||
| +int get_prkey(struct multipath *mpp, uint64_t *prkey, uint8_t *sa_flags);
 |  | ||||||
|   |  | ||||||
|  #endif /* _PRKEY_H */ |  | ||||||
| diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
 |  | ||||||
| index 354e883f..44241e2a 100644
 |  | ||||||
| --- a/libmultipath/propsel.c
 |  | ||||||
| +++ b/libmultipath/propsel.c
 |  | ||||||
| @@ -401,8 +401,7 @@ int select_alias(struct config *conf, struct multipath * mp)
 |  | ||||||
|   |  | ||||||
|  	select_alias_prefix(conf, mp); |  | ||||||
|   |  | ||||||
| -	mp->alias = get_user_friendly_alias(mp->wwid, conf->bindings_file,
 |  | ||||||
| -					    mp->alias_old, mp->alias_prefix,
 |  | ||||||
| +	mp->alias = get_user_friendly_alias(mp->wwid, mp->alias_old, mp->alias_prefix,
 |  | ||||||
|  					    conf->bindings_read_only); |  | ||||||
|   |  | ||||||
|  	if (mp->alias && !strncmp(mp->alias, mp->alias_old, WWID_SIZE)) |  | ||||||
| @@ -992,7 +991,7 @@ int select_reservation_key(struct config *conf, struct multipath *mp)
 |  | ||||||
|  out: |  | ||||||
|  	if (mp->prkey_source == PRKEY_SOURCE_FILE) { |  | ||||||
|  		from_file = " (from prkeys file)"; |  | ||||||
| -		if (get_prkey(conf, mp, &prkey, &mp->sa_flags) != 0)
 |  | ||||||
| +		if (get_prkey(mp, &prkey, &mp->sa_flags) != 0)
 |  | ||||||
|  			put_be64(mp->reservation_key, 0); |  | ||||||
|  		else |  | ||||||
|  			put_be64(mp->reservation_key, prkey); |  | ||||||
| diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
 |  | ||||||
| index 89bb60ca..591cd09b 100644
 |  | ||||||
| --- a/libmultipath/wwids.c
 |  | ||||||
| +++ b/libmultipath/wwids.c
 |  | ||||||
| @@ -94,12 +94,8 @@ replace_wwids(vector mp)
 |  | ||||||
|  	struct multipath * mpp; |  | ||||||
|  	size_t len; |  | ||||||
|  	int ret = -1; |  | ||||||
| -	struct config *conf;
 |  | ||||||
|   |  | ||||||
| -	conf = get_multipath_config();
 |  | ||||||
| -	pthread_cleanup_push(put_multipath_config, conf);
 |  | ||||||
| -	fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
 |  | ||||||
| -	pthread_cleanup_pop(1);
 |  | ||||||
| +	fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
 |  | ||||||
|  	if (fd < 0) |  | ||||||
|  		goto out; |  | ||||||
|   |  | ||||||
| @@ -200,7 +196,6 @@ remove_wwid(char *wwid) {
 |  | ||||||
|  	int len, can_write; |  | ||||||
|  	char *str; |  | ||||||
|  	int ret = -1; |  | ||||||
| -	struct config *conf;
 |  | ||||||
|   |  | ||||||
|  	len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */ |  | ||||||
|  	str = malloc(len); |  | ||||||
| @@ -216,10 +211,7 @@ remove_wwid(char *wwid) {
 |  | ||||||
|  		goto out; |  | ||||||
|  	} |  | ||||||
|  	condlog(3, "removing line '%s' from wwids file", str); |  | ||||||
| -	conf = get_multipath_config();
 |  | ||||||
| -	pthread_cleanup_push(put_multipath_config, conf);
 |  | ||||||
| -	fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
 |  | ||||||
| -	pthread_cleanup_pop(1);
 |  | ||||||
| +	fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
 |  | ||||||
|   |  | ||||||
|  	if (fd < 0) { |  | ||||||
|  		ret = -1; |  | ||||||
| @@ -244,12 +236,8 @@ check_wwids_file(char *wwid, int write_wwid)
 |  | ||||||
|  { |  | ||||||
|  	int fd, can_write, found, ret; |  | ||||||
|  	FILE *f; |  | ||||||
| -	struct config *conf;
 |  | ||||||
|   |  | ||||||
| -	conf = get_multipath_config();
 |  | ||||||
| -	pthread_cleanup_push(put_multipath_config, conf);
 |  | ||||||
| -	fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
 |  | ||||||
| -	pthread_cleanup_pop(1);
 |  | ||||||
| +	fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
 |  | ||||||
|  	if (fd < 0) |  | ||||||
|  		return -1; |  | ||||||
|   |  | ||||||
| diff --git a/multipath/main.c b/multipath/main.c
 |  | ||||||
| index b91289e8..9e1c5052 100644
 |  | ||||||
| --- a/multipath/main.c
 |  | ||||||
| +++ b/multipath/main.c
 |  | ||||||
| @@ -856,7 +856,7 @@ main (int argc, char *argv[])
 |  | ||||||
|  			libmp_verbosity = atoi(optarg); |  | ||||||
|  			break; |  | ||||||
|  		case 'b': |  | ||||||
| -			conf->bindings_file = strdup(optarg);
 |  | ||||||
| +			condlog(1, "option -b ignored");
 |  | ||||||
|  			break; |  | ||||||
|  		case 'B': |  | ||||||
|  			conf->bindings_read_only = 1; |  | ||||||
| diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
 |  | ||||||
| index 20df2232..d320a88f 100644
 |  | ||||||
| --- a/multipath/multipath.conf.5.in
 |  | ||||||
| +++ b/multipath/multipath.conf.5.in
 |  | ||||||
| @@ -794,35 +794,28 @@ The default is: \fB<unset>\fR
 |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B bindings_file |  | ||||||
| -(Deprecated) This option is deprecated, and will be removed in a future release.
 |  | ||||||
| -The full pathname of the binding file to be used when the user_friendly_names
 |  | ||||||
| -option is set.
 |  | ||||||
| +(Deprecated) This option is not supported any more, and will be ignored.
 |  | ||||||
|  .RS |  | ||||||
|  .TP |  | ||||||
| -The default is: \fB@STATE_DIR@/bindings\fR
 |  | ||||||
| +The compiled-in value is: \fB@STATE_DIR@/bindings\fR
 |  | ||||||
|  .RE |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B wwids_file |  | ||||||
| -(Deprecated) This option is deprecated, and will be removed in a future release.
 |  | ||||||
| -The full pathname of the WWIDs file, which is used by multipath to keep track
 |  | ||||||
| -of the WWIDs for LUNs it has created multipath devices on in the past.
 |  | ||||||
| +(Deprecated) This option is not supported any more, and will be ignored.
 |  | ||||||
|  .RS |  | ||||||
|  .TP |  | ||||||
| -The default is: \fB@STATE_DIR@/wwids\fR
 |  | ||||||
| +The compiled-in value is: \fB@STATE_DIR@/wwids\fR
 |  | ||||||
|  .RE |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
|  .B prkeys_file |  | ||||||
| -(Deprecated) This option is deprecated, and will be removed in a future release.
 |  | ||||||
| -The full pathname of the prkeys file, which is used by multipathd to keep
 |  | ||||||
| -track of the persistent reservation key used for a specific WWID, when
 |  | ||||||
| -\fIreservation_key\fR is set to \fBfile\fR.
 |  | ||||||
| +(Deprecated) This option is not supported any more, and will be ignored.
 |  | ||||||
|  .RS |  | ||||||
|  .TP |  | ||||||
| -The default is: \fB@STATE_DIR@/prkeys\fR
 |  | ||||||
| +The compiled-in value is: \fB@STATE_DIR@/prkeys\fR
 |  | ||||||
|  .RE |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
| @@ -989,6 +982,10 @@ The default is: \fB<unset>\fR
 |  | ||||||
|  .TP |  | ||||||
|  .B config_dir |  | ||||||
|  (Deprecated) This option is not supported any more, and the value is ignored. |  | ||||||
| +.RS
 |  | ||||||
| +.TP
 |  | ||||||
| +The compiled-in value is: \fB@CONFIGDIR@\fR
 |  | ||||||
| +.RE
 |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
|  .TP |  | ||||||
| diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
 |  | ||||||
| index d1f8f234..4d6f258c 100644
 |  | ||||||
| --- a/multipathd/uxlsnr.c
 |  | ||||||
| +++ b/multipathd/uxlsnr.c
 |  | ||||||
| @@ -203,7 +203,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
 |  | ||||||
|  	int dir_reset = 0; |  | ||||||
|  	int conf_reset = 0; |  | ||||||
|  	int mp_reset = 0; |  | ||||||
| -	char *bindings_file __attribute__((cleanup(cleanup_charp))) = NULL;
 |  | ||||||
|   |  | ||||||
|  	if (notify_fd == -1) |  | ||||||
|  		return; |  | ||||||
| @@ -221,7 +220,6 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
 |  | ||||||
|  		if (wds->mp_wd == -1) |  | ||||||
|  			mp_reset = 1; |  | ||||||
|  	} |  | ||||||
| -	bindings_file = strdup(conf->bindings_file);
 |  | ||||||
|  	put_multipath_config(conf); |  | ||||||
|   |  | ||||||
|  	if (dir_reset) { |  | ||||||
| @@ -242,17 +240,12 @@ static void reset_watch(int notify_fd, struct watch_descriptors *wds,
 |  | ||||||
|  		if (wds->conf_wd == -1) |  | ||||||
|  			condlog(3, "didn't set up notifications on /etc/multipath.conf: %m"); |  | ||||||
|  	} |  | ||||||
| -	if (mp_reset && bindings_file) {
 |  | ||||||
| -		char *slash = strrchr(bindings_file, '/');
 |  | ||||||
| -
 |  | ||||||
| -		if (slash && slash > bindings_file) {
 |  | ||||||
| -			*slash = '\0';
 |  | ||||||
| -			wds->mp_wd = inotify_add_watch(notify_fd, bindings_file,
 |  | ||||||
| -						       IN_MOVED_TO|IN_ONLYDIR);
 |  | ||||||
| -			if (wds->mp_wd == -1)
 |  | ||||||
| +	if (mp_reset) {
 |  | ||||||
| +		wds->mp_wd = inotify_add_watch(notify_fd, STATE_DIR,
 |  | ||||||
| +					       IN_MOVED_TO|IN_ONLYDIR);
 |  | ||||||
| +		if (wds->mp_wd == -1)
 |  | ||||||
|  				condlog(3, "didn't set up notifications on %s: %m", |  | ||||||
| -					bindings_file);
 |  | ||||||
| -		}
 |  | ||||||
| +					STATE_DIR);
 |  | ||||||
|  	} |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| diff --git a/tests/alias.c b/tests/alias.c
 |  | ||||||
| index 94df36d8..f893d174 100644
 |  | ||||||
| --- a/tests/alias.c
 |  | ||||||
| +++ b/tests/alias.c
 |  | ||||||
| @@ -1264,10 +1264,10 @@ static void al_a(void **state)
 |  | ||||||
|  	will_return(__wrap_write, ln); |  | ||||||
|  	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); |  | ||||||
|  	will_return(__wrap_rename, 0); |  | ||||||
| -	expect_condlog(1, "updated bindings file foo");
 |  | ||||||
| +	expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);
 |  | ||||||
|  	expect_condlog(3, NEW_STR("MPATHa", "WWIDa")); |  | ||||||
|   |  | ||||||
| -	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", 1, "MPATH");
 |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	check_bindings_size(1); |  | ||||||
| @@ -1283,10 +1283,10 @@ static void al_zz(void **state)
 |  | ||||||
|  	will_return(__wrap_write, ln); |  | ||||||
|  	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln)); |  | ||||||
|  	will_return(__wrap_rename, 0); |  | ||||||
| -	expect_condlog(1, "updated bindings file foo");
 |  | ||||||
| +	expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);
 |  | ||||||
|  	expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz")); |  | ||||||
|   |  | ||||||
| -	alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDzz", 26*26 + 26, "MPATH");
 |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
|  	assert_string_equal(alias, "MPATHzz"); |  | ||||||
|  	check_bindings_size(1); |  | ||||||
| @@ -1298,7 +1298,7 @@ static void al_0(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n"); |  | ||||||
| -	alias = allocate_binding(0, "WWIDa", 0, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", 0, "MPATH");
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  	check_bindings_size(0); |  | ||||||
|  } |  | ||||||
| @@ -1308,7 +1308,7 @@ static void al_m2(void **state)
 |  | ||||||
|  	char *alias; |  | ||||||
|   |  | ||||||
|  	expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n"); |  | ||||||
| -	alias = allocate_binding(0, "WWIDa", -2, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", -2, "MPATH");
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  	check_bindings_size(0); |  | ||||||
|  } |  | ||||||
| @@ -1325,10 +1325,10 @@ static void al_write_partial(void **state)
 |  | ||||||
|  	will_return(__wrap_write, ln + sizeof(ln) - 2); |  | ||||||
|  	will_return(__wrap_write, 1); |  | ||||||
|  	will_return(__wrap_rename, 0); |  | ||||||
| -	expect_condlog(1, "updated bindings file foo");
 |  | ||||||
| +	expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);
 |  | ||||||
|  	expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n"); |  | ||||||
|   |  | ||||||
| -	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", 1, "MPATH");
 |  | ||||||
|  	assert_ptr_not_equal(alias, NULL); |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	check_bindings_size(1); |  | ||||||
| @@ -1350,7 +1350,7 @@ static void al_write_short(void **state)
 |  | ||||||
|  	expect_condlog(1, "failed to write new bindings file"); |  | ||||||
|  	expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); |  | ||||||
|   |  | ||||||
| -	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", 1, "MPATH");
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  	check_bindings_size(0); |  | ||||||
|  } |  | ||||||
| @@ -1366,7 +1366,7 @@ static void al_write_err(void **state)
 |  | ||||||
|  	expect_condlog(1, "failed to write new bindings file"); |  | ||||||
|  	expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); |  | ||||||
|   |  | ||||||
| -	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", 1, "MPATH");
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  	check_bindings_size(0); |  | ||||||
|  } |  | ||||||
| @@ -1383,7 +1383,7 @@ static void al_rename_err(void **state)
 |  | ||||||
|   |  | ||||||
|  	expect_condlog(0, "update_bindings_file: rename: Read-only file system"); |  | ||||||
|  	expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa"); |  | ||||||
| -	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
 |  | ||||||
| +	alias = allocate_binding("WWIDa", 1, "MPATH");
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  	check_bindings_size(0); |  | ||||||
|  } |  | ||||||
| @@ -1415,7 +1415,7 @@ static int test_allocate_binding(void)
 |  | ||||||
|  			    strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \ |  | ||||||
|  		will_return(__wrap_rename, err);			\ |  | ||||||
|  		if (err == 0) {						\ |  | ||||||
| -			expect_condlog(1, "updated bindings file x\n");	\
 |  | ||||||
| +			expect_condlog(1, "updated bindings file " DEFAULT_BINDINGS_FILE);	\
 |  | ||||||
|  			expect_condlog(3, NEW_STR(alias, wwid));	\ |  | ||||||
|  		} else {						\ |  | ||||||
|  			expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \ |  | ||||||
| @@ -1441,7 +1441,7 @@ static void gufa_empty_new_rw(void **state) {
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding("MPATHa", "WWID0"); |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1454,7 +1454,7 @@ static void gufa_empty_new_ro_1(void **state) {
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system"); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", false);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1465,7 +1465,7 @@ static void gufa_empty_new_ro_2(void **state) {
 |  | ||||||
|  	expect_condlog(3, NOMATCH_WWID_STR("WWID0")); |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1477,7 +1477,7 @@ static void gufa_match_a_unused(void **state) {
 |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|  	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1490,7 +1490,7 @@ static void gufa_match_a_self(void **state) {
 |  | ||||||
|  	mock_self_alias("MPATHa", "WWID0"); |  | ||||||
|  	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1503,7 +1503,7 @@ static void gufa_match_a_used(void **state) {
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_used_alias("MPATHa", "WWID0"); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", true);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1518,7 +1518,7 @@ static void gufa_nomatch_a_c(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings)); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID1", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHb"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1534,7 +1534,7 @@ static void gufa_nomatch_c_a(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID1", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHb"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1550,7 +1550,7 @@ static void gufa_nomatch_c_b(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1567,7 +1567,7 @@ static void gufa_nomatch_c_b_used(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID4", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHd"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1584,7 +1584,7 @@ static void gufa_nomatch_b_f_a(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID7", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHc"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1599,7 +1599,7 @@ static void gufa_nomatch_b_aa_a(void **state) {
 |  | ||||||
|  	mock_unused_alias("MPATHab"); |  | ||||||
|  	mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf)); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID28", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHab"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1616,7 +1616,7 @@ static void gufa_nomatch_b_f_a_sorted(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID7", "", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHc"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1632,7 +1632,7 @@ static void gufa_old_empty(void **state) {
 |  | ||||||
|  	mock_allocate_binding("MPATHz", "WWID0"); |  | ||||||
|  	expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHz"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1644,7 +1644,7 @@ static void gufa_old_match(void **state) {
 |  | ||||||
|  			   "MPATHz WWID0"); |  | ||||||
|  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHz"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1661,7 +1661,7 @@ static void gufa_old_match_other(void **state) {
 |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1678,7 +1678,7 @@ static void gufa_old_match_other_used(void **state) {
 |  | ||||||
|  	mock_unused_alias("MPATHb"); |  | ||||||
|   |  | ||||||
|  	mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1); |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHb"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1695,7 +1695,7 @@ static void gufa_old_match_other_wwidmatch(void **state) {
 |  | ||||||
|  	mock_unused_alias("MPATHc"); |  | ||||||
|  	expect_condlog(3, EXISTING_STR("MPATHc", "WWID2")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHc"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1711,7 +1711,7 @@ static void gufa_old_match_other_wwidmatch_used(void **state) {
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHc", "WWID2")); |  | ||||||
|  	mock_used_alias("MPATHc", "WWID2"); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID2", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1725,7 +1725,7 @@ static void gufa_old_nomatch_wwidmatch(void **state) {
 |  | ||||||
|  	mock_unused_alias("MPATHa"); |  | ||||||
|  	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHa"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @@ -1739,7 +1739,7 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) {
 |  | ||||||
|  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0")); |  | ||||||
|  	mock_used_alias("MPATHa", "WWID0"); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_ptr_equal(alias, NULL); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| @@ -1754,7 +1754,7 @@ static void gufa_old_nomatch_nowwidmatch(void **state) {
 |  | ||||||
|  	mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1); |  | ||||||
|  	expect_condlog(2, ALLOC_STR("MPATHz", "WWID0")); |  | ||||||
|   |  | ||||||
| -	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
 |  | ||||||
| +	alias = get_user_friendly_alias("WWID0", "MPATHz", "MPATH", false);
 |  | ||||||
|  	assert_string_equal(alias, "MPATHz"); |  | ||||||
|  	free(alias); |  | ||||||
|  } |  | ||||||
| @ -1,158 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Martin Wilck <mwilck@suse.com> |  | ||||||
| Date: Tue, 12 Sep 2023 11:54:47 +0200 |  | ||||||
| Subject: [PATCH] libmultipath: avoid -Warray-bounds error in uatomic |  | ||||||
|  operations |  | ||||||
| 
 |  | ||||||
| The use of uatomic_xchg() in alias.c causes a -Warray-bounds error |  | ||||||
| on distributions using gcc 12, such as Fedora 37. This is a similar |  | ||||||
| error to 2534c4f ("libmultipath: avoid -Warray-bounds error with gcc |  | ||||||
| 12 and musl libc"). This happens only with liburcu 0.13 and earlier, |  | ||||||
| and only with certain gcc versions. See liburcu commit 835b9ab |  | ||||||
| ("Fix: x86 and s390 uatomic: __hp() macro warning with gcc 11"). |  | ||||||
| 
 |  | ||||||
| Enhance the fix for 2534c4f by a adding a workaround for uatomic_xchg(), |  | ||||||
| and introduce the macro URCU_VERSION (originally only used for multipathd) |  | ||||||
| globally. |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  Makefile.inc         |  2 +- |  | ||||||
|  create-config.mk     |  5 +++++ |  | ||||||
|  libmultipath/alias.c |  5 +++-- |  | ||||||
|  libmultipath/lock.h  | 21 +++++++++++++-------- |  | ||||||
|  multipathd/Makefile  |  2 -- |  | ||||||
|  5 files changed, 22 insertions(+), 13 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/Makefile.inc b/Makefile.inc
 |  | ||||||
| index 6e384e68..04bfa56e 100644
 |  | ||||||
| --- a/Makefile.inc
 |  | ||||||
| +++ b/Makefile.inc
 |  | ||||||
| @@ -95,7 +95,7 @@ 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) |  | ||||||
| -CPPFLAGS	:= $(FORTIFY_OPT) $(CPPFLAGS) \
 |  | ||||||
| +CPPFLAGS	:= $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
 |  | ||||||
|  		   -DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \ |  | ||||||
|  		   -DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(configdir)\" \ |  | ||||||
|  		   -DDEFAULT_CONFIGFILE=\"$(configfile)\" -DSTATE_DIR=\"$(statedir)\" \ |  | ||||||
| diff --git a/create-config.mk b/create-config.mk
 |  | ||||||
| index d1255971..4d318b96 100644
 |  | ||||||
| --- a/create-config.mk
 |  | ||||||
| +++ b/create-config.mk
 |  | ||||||
| @@ -73,6 +73,10 @@ TEST_URCU_TYPE_LIMITS = $(shell \
 |  | ||||||
|  		$(CC) -c -Werror=type-limits -o /dev/null -xc - 2>/dev/null  \ |  | ||||||
|  	|| echo -Wno-type-limits ) |  | ||||||
|   |  | ||||||
| +URCU_VERSION = $(shell \
 |  | ||||||
| +	$(PKG_CONFIG) --modversion liburcu 2>/dev/null | \
 |  | ||||||
| +			awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }')
 |  | ||||||
| +
 |  | ||||||
|  DEFINES := |  | ||||||
|   |  | ||||||
|  ifneq ($(call check_func,dm_task_no_flush,$(devmapper_incdir)/libdevmapper.h),0) |  | ||||||
| @@ -168,6 +172,7 @@ $(TOPDIR)/config.mk:	$(multipathdir)/autoconfig.h
 |  | ||||||
|  	@echo creating $@ |  | ||||||
|  	@echo "FPIN_SUPPORT := $(FPIN_SUPPORT)" >$@ |  | ||||||
|  	@echo "FORTIFY_OPT := $(FORTIFY_OPT)" >>$@ |  | ||||||
| +	@echo "D_URCU_VERSION := $(call URCU_VERSION)" >>$@
 |  | ||||||
|  	@echo "SYSTEMD := $(SYSTEMD)" >>$@ |  | ||||||
|  	@echo "ANA_SUPPORT := $(ANA_SUPPORT)" >>$@ |  | ||||||
|  	@echo "STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)" >>$@ |  | ||||||
| diff --git a/libmultipath/alias.c b/libmultipath/alias.c
 |  | ||||||
| index e5d3f151..74431f3f 100644
 |  | ||||||
| --- a/libmultipath/alias.c
 |  | ||||||
| +++ b/libmultipath/alias.c
 |  | ||||||
| @@ -24,6 +24,7 @@
 |  | ||||||
|  #include "devmapper.h" |  | ||||||
|  #include "strbuf.h" |  | ||||||
|  #include "time-util.h" |  | ||||||
| +#include "lock.h"
 |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
|   * significant parts of this file were taken from iscsi-bindings.c of the |  | ||||||
| @@ -300,7 +301,7 @@ void handle_bindings_file_inotify(const struct inotify_event *event)
 |  | ||||||
|  	pthread_mutex_unlock(×tamp_mutex); |  | ||||||
|   |  | ||||||
|  	if (changed) { |  | ||||||
| -		uatomic_xchg(&bindings_file_changed, 1);
 |  | ||||||
| +		uatomic_xchg_int(&bindings_file_changed, 1);
 |  | ||||||
|  		condlog(3, "%s: bindings file must be re-read, new timestamp: %ld.%06ld", |  | ||||||
|  			__func__, (long)ts.tv_sec, (long)ts.tv_nsec / 1000); |  | ||||||
|  	} else |  | ||||||
| @@ -775,7 +776,7 @@ static int _read_bindings_file(const struct config *conf, Bindings *bindings,
 |  | ||||||
|  	int rc = 0, ret, fd; |  | ||||||
|  	FILE *file; |  | ||||||
|  	struct stat st; |  | ||||||
| -	int has_changed = uatomic_xchg(&bindings_file_changed, 0);
 |  | ||||||
| +	int has_changed = uatomic_xchg_int(&bindings_file_changed, 0);
 |  | ||||||
|   |  | ||||||
|  	if (!force) { |  | ||||||
|  		if (!has_changed) { |  | ||||||
| diff --git a/libmultipath/lock.h b/libmultipath/lock.h
 |  | ||||||
| index 9814be76..ac80d1d8 100644
 |  | ||||||
| --- a/libmultipath/lock.h
 |  | ||||||
| +++ b/libmultipath/lock.h
 |  | ||||||
| @@ -13,15 +13,20 @@ struct mutex_lock {
 |  | ||||||
|  	int waiters; /* uatomic access only */ |  | ||||||
|  }; |  | ||||||
|   |  | ||||||
| -#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12
 |  | ||||||
| +static inline void init_lock(struct mutex_lock *a)
 |  | ||||||
| +{
 |  | ||||||
| +	pthread_mutex_init(&a->mutex, NULL);
 |  | ||||||
| +	uatomic_set(&a->waiters, 0);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00
 |  | ||||||
|  #pragma GCC diagnostic push |  | ||||||
|  #pragma GCC diagnostic ignored "-Warray-bounds" |  | ||||||
|  #endif |  | ||||||
|   |  | ||||||
| -static inline void init_lock(struct mutex_lock *a)
 |  | ||||||
| +static inline int uatomic_xchg_int(int *ptr, int val)
 |  | ||||||
|  { |  | ||||||
| -	pthread_mutex_init(&a->mutex, NULL);
 |  | ||||||
| -	uatomic_set(&a->waiters, 0);
 |  | ||||||
| +	return uatomic_xchg(ptr, val);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  static inline void lock(struct mutex_lock *a) |  | ||||||
| @@ -31,6 +36,10 @@ static inline void lock(struct mutex_lock *a)
 |  | ||||||
|  	uatomic_dec(&a->waiters); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +#if defined(__GNUC__) && __GNUC__ == 12 && URCU_VERSION < 0xe00
 |  | ||||||
| +#pragma GCC diagnostic pop
 |  | ||||||
| +#endif
 |  | ||||||
| +
 |  | ||||||
|  static inline int trylock(struct mutex_lock *a) |  | ||||||
|  { |  | ||||||
|  	return pthread_mutex_trylock(&a->mutex); |  | ||||||
| @@ -51,10 +60,6 @@ static inline bool lock_has_waiters(struct mutex_lock *a)
 |  | ||||||
|  	return (uatomic_read(&a->waiters) > 0); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -#if !defined(__GLIBC__) && defined(__GNUC__) && __GNUC__ == 12
 |  | ||||||
| -#pragma GCC diagnostic pop
 |  | ||||||
| -#endif
 |  | ||||||
| -
 |  | ||||||
|  #define lock_cleanup_pop(a) pthread_cleanup_pop(1) |  | ||||||
|   |  | ||||||
|  void cleanup_lock (void * data); |  | ||||||
| diff --git a/multipathd/Makefile b/multipathd/Makefile
 |  | ||||||
| index cdba3db1..0ba6ecb7 100644
 |  | ||||||
| --- a/multipathd/Makefile
 |  | ||||||
| +++ b/multipathd/Makefile
 |  | ||||||
| @@ -5,8 +5,6 @@ CLI      := multipathc
 |  | ||||||
|  MANPAGES := multipathd.8 |  | ||||||
|   |  | ||||||
|  CPPFLAGS += -I$(multipathdir) -I$(mpathutildir) -I$(mpathpersistdir) -I$(mpathcmddir) -I$(thirdpartydir) \ |  | ||||||
| -	$(shell $(PKG_CONFIG) --modversion liburcu 2>/dev/null | \
 |  | ||||||
| -		awk -F. '{ printf("-DURCU_VERSION=0x%06x", 256 * ( 256 * $$1 + $$2) + $$3); }') \
 |  | ||||||
|  	-DBINDIR='"$(bindir)"' $(SYSTEMD_CPPFLAGS) |  | ||||||
|   |  | ||||||
|  # |  | ||||||
| @ -1,52 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Xose Vazquez Perez <xose.vazquez@gmail.com> |  | ||||||
| Date: Fri, 15 Sep 2023 22:22:06 +0200 |  | ||||||
| Subject: [PATCH] multipath-tools: fix spelling |  | ||||||
| 
 |  | ||||||
| Cc: Martin Wilck <mwilck@suse.com> |  | ||||||
| Cc: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Cc: Christophe Varoqui <christophe.varoqui@opensvc.com> |  | ||||||
| Cc: DM-DEVEL ML <dm-devel@redhat.com> |  | ||||||
| Signed-off-by: Xose Vazquez Perez <xose.vazquez@gmail.com> |  | ||||||
| Reviewed-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| ---
 |  | ||||||
|  README.md                     | 4 ++-- |  | ||||||
|  multipath/multipath.conf.5.in | 2 +- |  | ||||||
|  2 files changed, 3 insertions(+), 3 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/README.md b/README.md
 |  | ||||||
| index 679e55bf..524c9fb1 100644
 |  | ||||||
| --- a/README.md
 |  | ||||||
| +++ b/README.md
 |  | ||||||
| @@ -92,7 +92,7 @@ The following variables can be passed to the `make` command line:
 |  | ||||||
|     The default is `$(prefix)/$(LIB)/multipath`, where `$(LIB)` is `lib64` on |  | ||||||
|     systems that have `/lib64`, and `lib` otherwise. |  | ||||||
|   * `configfile="/some/path`": The path to the main configuration file. |  | ||||||
| -    The defalt is `$(etc_prefix)/etc/multipath.conf`.
 |  | ||||||
| +    The default is `$(etc_prefix)/etc/multipath.conf`.
 |  | ||||||
|   * `configdir="/some/path"` : directory to search for additional configuration files. |  | ||||||
|      This used to be the run-time option `config_dir` in earlier versions. |  | ||||||
|  	The default is `$(etc_prefix)/etc/multipath/conf.d`. |  | ||||||
| @@ -141,7 +141,7 @@ The following variables can be passed to the `make` command line:
 |  | ||||||
|     found on the build system, and `/lib` otherwise. |  | ||||||
|      |  | ||||||
|  The options `configdir`, `plugindir`, `configfile`, and `statedir` above can |  | ||||||
| -be used for setting indvidual paths where the `prefix` variables don't provide
 |  | ||||||
| +be used for setting individual paths where the `prefix` variables don't provide
 |  | ||||||
|  sufficient control. See `Makefile.inc` for even more fine-grained control. |  | ||||||
|   |  | ||||||
|  [^systemd]: Some systemd installations use separate `prefix` and `rootprefix`.  |  | ||||||
| diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
 |  | ||||||
| index d320a88f..226d0019 100644
 |  | ||||||
| --- a/multipath/multipath.conf.5.in
 |  | ||||||
| +++ b/multipath/multipath.conf.5.in
 |  | ||||||
| @@ -36,7 +36,7 @@ Files ending in \fI.conf\fR in this directory are read
 |  | ||||||
|  in alphabetical order, after reading \fI@CONFIGFILE@\fR. |  | ||||||
|  They use the same syntax as \fI@CONFIGFILE@\fR itself, |  | ||||||
|  and support all sections and keywords. If a keyword occurs in the same section |  | ||||||
| -in multiple files, the last occurence will take precedence over all others.
 |  | ||||||
| +in multiple files, the last occurrence will take precedence over all others.
 |  | ||||||
|  . |  | ||||||
|  . |  | ||||||
|  .\" ---------------------------------------------------------------------------- |  | ||||||
| @ -1,300 +0,0 @@ | |||||||
| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Muneendra <muneendra.kumar@broadcom.com> |  | ||||||
| Date: Wed, 20 Sep 2023 20:41:15 -0700 |  | ||||||
| Subject: [PATCH] multipathd: Added support to handle FPIN-Li events for |  | ||||||
|  FC-NVMe |  | ||||||
| 
 |  | ||||||
|     This patch adds the support to handle FPIN-Li for FC-NVMe. |  | ||||||
|     On receiving the FPIN-Li events this patch moves the devices paths |  | ||||||
|     which are affected due to link integrity to marginal path groups. |  | ||||||
|     The paths which are set to marginal path group will be unset |  | ||||||
|     on receiving the RSCN events |  | ||||||
| 
 |  | ||||||
| (mwilck: minor compile fix for 32-bit architectures) |  | ||||||
| 
 |  | ||||||
| Signed-off-by: Muneendra <muneendra.kumar@broadcom.com> |  | ||||||
| Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> |  | ||||||
| Reviewed-by: Martin Wilck <mwilck@suse.com> |  | ||||||
| ---
 |  | ||||||
|  multipathd/fpin_handlers.c | 206 +++++++++++++++++++++++++++---------- |  | ||||||
|  1 file changed, 151 insertions(+), 55 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/multipathd/fpin_handlers.c b/multipathd/fpin_handlers.c
 |  | ||||||
| index aa0f63c9..be087ca0 100644
 |  | ||||||
| --- a/multipathd/fpin_handlers.c
 |  | ||||||
| +++ b/multipathd/fpin_handlers.c
 |  | ||||||
| @@ -60,18 +60,15 @@ static void _udev_device_unref(void *p)
 |  | ||||||
|   |  | ||||||
|   |  | ||||||
|  /*set/unset the path state to marginal*/ |  | ||||||
| -static int fpin_set_pathstate(struct path *pp, bool set)
 |  | ||||||
| +static void fpin_set_pathstate(struct path *pp, bool set)
 |  | ||||||
|  { |  | ||||||
|  	const char *action = set ? "set" : "unset"; |  | ||||||
|   |  | ||||||
| -	if (!pp || !pp->mpp || !pp->mpp->alias)
 |  | ||||||
| -		return -1;
 |  | ||||||
| -
 |  | ||||||
| -	condlog(3, "\n%s: %s  marginal path %s (fpin)",
 |  | ||||||
| -		action, pp->mpp->alias, pp->dev_t);
 |  | ||||||
| +	condlog(3, "%s: %s marginal path %s (fpin)",
 |  | ||||||
| +		pp->mpp ? pp->mpp->alias : "orphan", action, pp->dev_t);
 |  | ||||||
|  	pp->marginal = set; |  | ||||||
| -	pp->mpp->fpin_must_reload = true;
 |  | ||||||
| -	return 0;
 |  | ||||||
| +	if (pp->mpp)
 |  | ||||||
| +		pp->mpp->fpin_must_reload = true;
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  /* This will unset marginal state of a device*/ |  | ||||||
| @@ -82,14 +79,14 @@ static void fpin_path_unsetmarginal(char *devname, struct vectors *vecs)
 |  | ||||||
|  	pp = find_path_by_dev(vecs->pathvec, devname); |  | ||||||
|  	if (!pp) |  | ||||||
|  		pp = find_path_by_devt(vecs->pathvec, devname); |  | ||||||
| -
 |  | ||||||
| -	fpin_set_pathstate(pp, false);
 |  | ||||||
| +	if (pp)
 |  | ||||||
| +		fpin_set_pathstate(pp, false);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  /*This will set the marginal state of a device*/ |  | ||||||
| -static int fpin_path_setmarginal(struct path *pp)
 |  | ||||||
| +static void  fpin_path_setmarginal(struct path *pp)
 |  | ||||||
|  { |  | ||||||
| -	return fpin_set_pathstate(pp, true);
 |  | ||||||
| +	fpin_set_pathstate(pp, true);
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  /* Unsets all the devices in the list from marginal state */ |  | ||||||
| @@ -183,8 +180,8 @@ static void fpin_set_rport_marginal(struct udev_device *rport_dev)
 |  | ||||||
|  					 udev_device_get_syspath(rport_dev)); |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| -/*Add the marginal devices info into the list*/
 |  | ||||||
| -static void
 |  | ||||||
| +/*Add the marginal devices info into the list and return 0 on success*/
 |  | ||||||
| +static int
 |  | ||||||
|  fpin_add_marginal_dev_info(uint32_t host_num, char *devname) |  | ||||||
|  { |  | ||||||
|  	struct marginal_dev_list *newdev = NULL; |  | ||||||
| @@ -199,65 +196,160 @@ fpin_add_marginal_dev_info(uint32_t host_num, char *devname)
 |  | ||||||
|  		list_add_tail(&(newdev->node), |  | ||||||
|  				&fpin_li_marginal_dev_list_head); |  | ||||||
|  		pthread_mutex_unlock(&fpin_li_marginal_dev_mutex); |  | ||||||
| -	}
 |  | ||||||
| +	} else
 |  | ||||||
| +		return -ENOMEM;
 |  | ||||||
| +	return 0;
 |  | ||||||
|  } |  | ||||||
|   |  | ||||||
|  /* |  | ||||||
| - * This function goes through the vecs->pathvec, and for
 |  | ||||||
| - * each path, check that the host  number,
 |  | ||||||
| - * the target WWPN associated with the path matches
 |  | ||||||
| - * with the els wwpn and sets the path and port state to
 |  | ||||||
| + * This function compares Transport Address Controller Port pn,
 |  | ||||||
| + * Host Transport Address Controller Port pn with the els wwpn ,attached_wwpn
 |  | ||||||
| + * and return 1 (match) or 0 (no match) or a negative error code
 |  | ||||||
| + */
 |  | ||||||
| +static int  extract_nvme_addresses_chk_path_pwwn(const char *address,
 |  | ||||||
| +		uint64_t els_wwpn, uint64_t els_attached_wwpn)
 |  | ||||||
| +
 |  | ||||||
| +{
 |  | ||||||
| +	uint64_t traddr;
 |  | ||||||
| +	uint64_t host_traddr;
 |  | ||||||
| +
 |  | ||||||
| +	/*
 |  | ||||||
| +	 *  Find the position of "traddr=" and "host_traddr="
 |  | ||||||
| +	 *  and the address will be in the below format
 |  | ||||||
| +	 *  "traddr=nn-0x200400110dff9400:pn-0x200400110dff9400,
 |  | ||||||
| +	 *  host_traddr=nn-0x200400110dff9400:pn-0x200400110dff9400"
 |  | ||||||
| +	 */
 |  | ||||||
| +	const char *traddr_start = strstr(address, "traddr=");
 |  | ||||||
| +	const char *host_traddr_start = strstr(address, "host_traddr=");
 |  | ||||||
| +
 |  | ||||||
| +	if (!traddr_start || !host_traddr_start)
 |  | ||||||
| +		return -EINVAL;
 |  | ||||||
| +
 |  | ||||||
| +	/* Extract traddr pn */
 |  | ||||||
| +	if (sscanf(traddr_start, "traddr=nn-%*[^:]:pn-%" SCNx64, &traddr) != 1)
 |  | ||||||
| +		return -EINVAL;
 |  | ||||||
| +
 |  | ||||||
| +	/* Extract host_traddr pn*/
 |  | ||||||
| +	if (sscanf(host_traddr_start, "host_traddr=nn-%*[^:]:pn-%" SCNx64,
 |  | ||||||
| +				&host_traddr) != 1)
 |  | ||||||
| +		return -EINVAL;
 |  | ||||||
| +	condlog(4, "traddr 0x%" PRIx64 " hosttraddr 0x%" PRIx64 " els_wwpn 0x%"
 |  | ||||||
| +		PRIx64" els_host_traddr 0x%" PRIx64,
 |  | ||||||
| +			traddr, host_traddr,
 |  | ||||||
| +			els_wwpn, els_attached_wwpn);
 |  | ||||||
| +	if ((host_traddr == els_attached_wwpn) && (traddr == els_wwpn))
 |  | ||||||
| +		return 1;
 |  | ||||||
| +	return 0;
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +/*
 |  | ||||||
| + * This function check that the Transport Address Controller Port pn,
 |  | ||||||
| + * Host Transport Address Controller Port pn associated with the path matches
 |  | ||||||
| + * with the els wwpn ,attached_wwpn and sets the path state to
 |  | ||||||
|   * Marginal |  | ||||||
|   */ |  | ||||||
| -static int  fpin_chk_wwn_setpath_marginal(uint16_t host_num,  struct vectors *vecs,
 |  | ||||||
| +static void fpin_check_set_nvme_path_marginal(uint16_t host_num, struct path *pp,
 |  | ||||||
| +		uint64_t els_wwpn, uint64_t attached_wwpn)
 |  | ||||||
| +{
 |  | ||||||
| +	struct udev_device *ctl = NULL;
 |  | ||||||
| +	const char *address = NULL;
 |  | ||||||
| +	int ret = 0;
 |  | ||||||
| +
 |  | ||||||
| +	ctl = udev_device_get_parent_with_subsystem_devtype(pp->udev, "nvme", NULL);
 |  | ||||||
| +	if (ctl == NULL) {
 |  | ||||||
| +		condlog(2, "%s: No parent device for ", pp->dev);
 |  | ||||||
| +		return;
 |  | ||||||
| +	}
 |  | ||||||
| +	address = udev_device_get_sysattr_value(ctl, "address");
 |  | ||||||
| +	if (!address) {
 |  | ||||||
| +		condlog(2, "%s: unable to get the address ", pp->dev);
 |  | ||||||
| +		return;
 |  | ||||||
| +	}
 |  | ||||||
| +	condlog(4, "\n address %s: dev :%s\n", address, pp->dev);
 |  | ||||||
| +	ret = extract_nvme_addresses_chk_path_pwwn(address, els_wwpn, attached_wwpn);
 |  | ||||||
| +	if (ret <= 0)
 |  | ||||||
| +		return;
 |  | ||||||
| +	ret = fpin_add_marginal_dev_info(host_num, pp->dev);
 |  | ||||||
| +	if (ret < 0)
 |  | ||||||
| +		return;
 |  | ||||||
| +	fpin_path_setmarginal(pp);
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +/*
 |  | ||||||
| + * This function check the host  number, the target WWPN
 |  | ||||||
| + * associated with the path matches with the els wwpn and
 |  | ||||||
| + * sets the path and port state to Marginal
 |  | ||||||
| + */
 |  | ||||||
| +static void fpin_check_set_scsi_path_marginal(uint16_t host_num, struct path *pp,
 |  | ||||||
|  		uint64_t els_wwpn) |  | ||||||
|  { |  | ||||||
| -	struct path *pp;
 |  | ||||||
| -	struct multipath *mpp;
 |  | ||||||
| -	int i, k;
 |  | ||||||
|  	char rport_id[42]; |  | ||||||
|  	const char *value = NULL; |  | ||||||
|  	struct udev_device *rport_dev = NULL; |  | ||||||
|  	uint64_t wwpn; |  | ||||||
|  	int ret = 0; |  | ||||||
| +	sprintf(rport_id, "rport-%d:%d-%d",
 |  | ||||||
| +			pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
 |  | ||||||
| +	rport_dev = udev_device_new_from_subsystem_sysname(udev,
 |  | ||||||
| +			"fc_remote_ports", rport_id);
 |  | ||||||
| +	if (!rport_dev) {
 |  | ||||||
| +		condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev,
 |  | ||||||
| +				rport_id);
 |  | ||||||
| +		return;
 |  | ||||||
| +	}
 |  | ||||||
| +	pthread_cleanup_push(_udev_device_unref, rport_dev);
 |  | ||||||
| +	value = udev_device_get_sysattr_value(rport_dev, "port_name");
 |  | ||||||
| +	if (!value)
 |  | ||||||
| +		goto unref;
 |  | ||||||
| +
 |  | ||||||
| +	wwpn =  strtol(value, NULL, 16);
 |  | ||||||
| +	/*
 |  | ||||||
| +	 * If the port wwpn matches sets the path and port state
 |  | ||||||
| +	 * to marginal
 |  | ||||||
| +	 */
 |  | ||||||
| +	if (wwpn == els_wwpn) {
 |  | ||||||
| +		ret = fpin_add_marginal_dev_info(host_num, pp->dev);
 |  | ||||||
| +		if (ret < 0)
 |  | ||||||
| +			goto unref;
 |  | ||||||
| +		fpin_path_setmarginal(pp);
 |  | ||||||
| +		fpin_set_rport_marginal(rport_dev);
 |  | ||||||
| +	}
 |  | ||||||
| +unref:
 |  | ||||||
| +	pthread_cleanup_pop(1);
 |  | ||||||
| +	return;
 |  | ||||||
| +
 |  | ||||||
| +}
 |  | ||||||
| +
 |  | ||||||
| +/*
 |  | ||||||
| + * This function goes through the vecs->pathvec, and for
 |  | ||||||
| + * each path, it checks and sets the path state to marginal
 |  | ||||||
| + * if the path's associated port wwpn ,hostnum  matches with
 |  | ||||||
| + * els wwnpn ,attached_wwpn
 |  | ||||||
| + */
 |  | ||||||
| +static int  fpin_chk_wwn_setpath_marginal(uint16_t host_num,  struct vectors *vecs,
 |  | ||||||
| +		uint64_t els_wwpn, uint64_t attached_wwpn)
 |  | ||||||
| +{
 |  | ||||||
| +	struct path *pp;
 |  | ||||||
| +	struct multipath *mpp;
 |  | ||||||
| +	int i, k;
 |  | ||||||
| +	int ret = 0;
 |  | ||||||
|   |  | ||||||
|  	pthread_cleanup_push(cleanup_lock, &vecs->lock); |  | ||||||
|  	lock(&vecs->lock); |  | ||||||
|  	pthread_testcancel(); |  | ||||||
|   |  | ||||||
|  	vector_foreach_slot(vecs->pathvec, pp, k) { |  | ||||||
| -		/* Checks the host number and also for the SCSI FCP */
 |  | ||||||
| -		if (pp->bus != SYSFS_BUS_SCSI || pp->sg_id.proto_id != SCSI_PROTOCOL_FCP || host_num !=  pp->sg_id.host_no)
 |  | ||||||
| +		if (!pp->mpp)
 |  | ||||||
|  			continue; |  | ||||||
| -		sprintf(rport_id, "rport-%d:%d-%d",
 |  | ||||||
| -				pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
 |  | ||||||
| -		rport_dev = udev_device_new_from_subsystem_sysname(udev,
 |  | ||||||
| -				"fc_remote_ports", rport_id);
 |  | ||||||
| -		if (!rport_dev) {
 |  | ||||||
| -			condlog(2, "%s: No fc_remote_port device for '%s'", pp->dev,
 |  | ||||||
| -					rport_id);
 |  | ||||||
| -			continue;
 |  | ||||||
| -		}
 |  | ||||||
| -		pthread_cleanup_push(_udev_device_unref, rport_dev);
 |  | ||||||
| -		value = udev_device_get_sysattr_value(rport_dev, "port_name");
 |  | ||||||
| -		if (!value)
 |  | ||||||
| -			goto unref;
 |  | ||||||
| -
 |  | ||||||
| -		if (value)
 |  | ||||||
| -			wwpn =  strtol(value, NULL, 16);
 |  | ||||||
| -		/*
 |  | ||||||
| -		 * If the port wwpn matches sets the path and port state
 |  | ||||||
| -		 * to marginal
 |  | ||||||
| -		 */
 |  | ||||||
| -		if (wwpn == els_wwpn) {
 |  | ||||||
| -			ret = fpin_path_setmarginal(pp);
 |  | ||||||
| -			if (ret < 0)
 |  | ||||||
| -				goto unref;
 |  | ||||||
| -			fpin_set_rport_marginal(rport_dev);
 |  | ||||||
| -			fpin_add_marginal_dev_info(host_num, pp->dev);
 |  | ||||||
| +		/*checks if the bus type is nvme  and the protocol is FC-NVMe*/
 |  | ||||||
| +		if ((pp->bus == SYSFS_BUS_NVME) && (pp->sg_id.proto_id == NVME_PROTOCOL_FC)) {
 |  | ||||||
| +			fpin_check_set_nvme_path_marginal(host_num, pp, els_wwpn, attached_wwpn);
 |  | ||||||
| +		} else if ((pp->bus == SYSFS_BUS_SCSI) &&
 |  | ||||||
| +			(pp->sg_id.proto_id == SCSI_PROTOCOL_FCP) &&
 |  | ||||||
| +			(host_num ==  pp->sg_id.host_no)) {
 |  | ||||||
| +			/* Checks the host number and also for the SCSI FCP */
 |  | ||||||
| +			fpin_check_set_scsi_path_marginal(host_num, pp, els_wwpn);
 |  | ||||||
|  		} |  | ||||||
| -unref:
 |  | ||||||
| -		pthread_cleanup_pop(1);
 |  | ||||||
|  	} |  | ||||||
|  	/* walk backwards because reload_and_sync_map() can remove mpp */ |  | ||||||
|  	vector_foreach_slot_backwards(vecs->mpvec, mpp, i) { |  | ||||||
| @@ -286,14 +378,18 @@ fpin_parse_li_els_setpath_marginal(uint16_t host_num, struct fc_tlv_desc *tlv,
 |  | ||||||
|  	struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv; |  | ||||||
|  	int count = 0; |  | ||||||
|  	int ret = 0; |  | ||||||
| +	uint64_t attached_wwpn;
 |  | ||||||
|   |  | ||||||
|  	/* Update the wwn to list */ |  | ||||||
|  	wwn_count = be32_to_cpu(li_desc->pname_count); |  | ||||||
| -	condlog(4, "Got wwn count as %d\n", wwn_count);
 |  | ||||||
| +	attached_wwpn = be64_to_cpu(li_desc->attached_wwpn);
 |  | ||||||
| +	condlog(4, "Got wwn count as %d detecting wwn 0x%" PRIx64
 |  | ||||||
| +		" attached_wwpn 0x%" PRIx64 "\n",
 |  | ||||||
| +			wwn_count, be64_to_cpu(li_desc->detecting_wwpn), attached_wwpn);
 |  | ||||||
|   |  | ||||||
|  	for (iter = 0; iter < wwn_count; iter++) { |  | ||||||
|  		wwpn = be64_to_cpu(li_desc->pname_list[iter]); |  | ||||||
| -		ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn);
 |  | ||||||
| +		ret = fpin_chk_wwn_setpath_marginal(host_num, vecs, wwpn, attached_wwpn);
 |  | ||||||
|  		if (ret < 0) |  | ||||||
|  			condlog(2, "failed to set the path marginal associated with wwpn: 0x%" PRIx64 "\n", wwpn); |  | ||||||
|   |  | ||||||
| @ -1,5 +1,5 @@ | |||||||
| Name:    device-mapper-multipath | Name:    device-mapper-multipath | ||||||
| Version: 0.9.6 | Version: 0.9.7 | ||||||
| Release: 1%{?dist} | Release: 1%{?dist} | ||||||
| Summary: Tools to manage multipath devices using device-mapper | Summary: Tools to manage multipath devices using device-mapper | ||||||
| License: GPLv2 | License: GPLv2 | ||||||
| @ -7,62 +7,22 @@ URL:     http://christophe.varoqui.free.fr/ | |||||||
| 
 | 
 | ||||||
| # The source for this package was pulled from upstream's git repo.  Use the | # The source for this package was pulled from upstream's git repo.  Use the | ||||||
| # following command to generate the tarball | # following command to generate the tarball | ||||||
| # curl -L https://github.com/opensvc/multipath-tools/archive/0.9.6.tar.gz -o multipath-tools-0.9.6.tgz | # curl -L https://github.com/opensvc/multipath-tools/archive/0.9.7.tar.gz -o multipath-tools-0.9.7.tgz | ||||||
| Source0: multipath-tools-0.9.6.tgz | Source0: multipath-tools-0.9.7.tgz | ||||||
| Source1: multipath.conf | Source1: multipath.conf | ||||||
| Patch0001: 0001-libmultipath-sysfs_set_scsi_tmo-do-nothing-for-ACT_D.patch | Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch | ||||||
| Patch0002: 0002-libmultipath-add-alias_already_taken.patch | Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch | ||||||
| Patch0003: 0003-libmultipath-unify-use_existing_alias-and-get_user_f.patch | Patch0003: 0003-RH-don-t-start-without-a-config-file.patch | ||||||
| Patch0004: 0004-libmultipath-never-allocate-an-alias-that-s-already-.patch | Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch | ||||||
| Patch0005: 0005-libmultipath-lookup_binding-add-comment-about-the-al.patch | Patch0005: 0005-RH-use-rpm-optflags-if-present.patch | ||||||
| Patch0006: 0006-multipath-tools-test-simplify-debugging-for-condlog-.patch | Patch0006: 0006-RH-add-mpathconf.patch | ||||||
| Patch0007: 0007-multipath-tools-tests-add-tests-for-get_user_friendl.patch | Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch | ||||||
| Patch0008: 0008-multipath-tools-test-consistent-use-of-macros-in-ali.patch | Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch | ||||||
| Patch0009: 0009-multipath-tools-tests-convert-mock_-failed-used-_ali.patch | Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch | ||||||
| Patch0010: 0010-multipath-tools-test-use-mock_bindings_file-consiste.patch | Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch | ||||||
| Patch0011: 0011-libmultipath-add-global-variable-for-current-binding.patch | Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch | ||||||
| Patch0012: 0012-libmultipath-rename-fix_bindings_file-to-update_bind.patch | Patch0012: 0012-RH-compile-with-libreadline-support.patch | ||||||
| Patch0013: 0013-libmultipath-alias.c-move-bindings-related-code-up.patch | Patch0013: 0013-RH-Add-mpathcleanup.patch | ||||||
| Patch0014: 0014-libmultipath-update_bindings_file-take-filename-argu.patch |  | ||||||
| Patch0015: 0015-libmultipath-update_bindings_file-use-a-single-write.patch |  | ||||||
| Patch0016: 0016-libmultipath-update_bindings_file-don-t-log-temp-fil.patch |  | ||||||
| Patch0017: 0017-libmultipath-alias.c-factor-out-read_binding.patch |  | ||||||
| Patch0018: 0018-libmultipath-keep-bindings-in-memory.patch |  | ||||||
| Patch0019: 0019-multipath-tools-tests-fix-alias-tests.patch |  | ||||||
| Patch0020: 0020-libmultipath-dm_get_uuid-return-emtpy-UUID-for-non-e.patch |  | ||||||
| Patch0021: 0021-libmultipath-adapt-to-new-semantics-of-dm_get_uuid.patch |  | ||||||
| Patch0022: 0022-libmultipath-sort-aliases-by-length-and-strcmp.patch |  | ||||||
| Patch0023: 0023-multipath-tools-tests-fix-alias-test-after-sort-orde.patch |  | ||||||
| Patch0024: 0024-libmultipath-simplify-get_free_id-assuming-total-ord.patch |  | ||||||
| Patch0025: 0025-multipath-tools-tests-adapt-alias-tests-for-total-or.patch |  | ||||||
| Patch0026: 0026-multipath-tools-tests-add-test-for-ordering-of-bindi.patch |  | ||||||
| Patch0027: 0027-multipathd-watch-bindings-file-with-inotify-timestam.patch |  | ||||||
| Patch0028: 0028-multipath-tools-tests-mock-pthread_mutex_-lock-unloc.patch |  | ||||||
| Patch0029: 0029-multipath-tools-Makefile-sanitize-paths-for-configur.patch |  | ||||||
| Patch0030: 0030-multipath-tools-add-compile-time-configuration-for-e.patch |  | ||||||
| Patch0031: 0031-multipath-tools-man-pages-generate-with-correct-path.patch |  | ||||||
| Patch0032: 0032-libdmmp-Makefile-fix-bug-in-install-section.patch |  | ||||||
| Patch0033: 0033-multipath-tools-README.md-improve-documentation-for-.patch |  | ||||||
| Patch0034: 0034-libmultipath-print-built-in-values-for-deprecated-op.patch |  | ||||||
| Patch0035: 0035-multipath-add-a-missing-newline.patch |  | ||||||
| Patch0036: 0036-multipath-tools-allow-prefixes-with-and-w-o-trailing.patch |  | ||||||
| Patch0037: 0037-libmultipath-deprecate-bindings_file-wwids_file-prke.patch |  | ||||||
| Patch0038: 0038-libmultipath-avoid-Warray-bounds-error-in-uatomic-op.patch |  | ||||||
| Patch0039: 0039-multipath-tools-fix-spelling.patch |  | ||||||
| Patch0040: 0040-multipathd-Added-support-to-handle-FPIN-Li-events-fo.patch |  | ||||||
| Patch0041: 0041-RH-fixup-udev-rules-for-redhat.patch |  | ||||||
| Patch0042: 0042-RH-Remove-the-property-blacklist-exception-builtin.patch |  | ||||||
| Patch0043: 0043-RH-don-t-start-without-a-config-file.patch |  | ||||||
| Patch0044: 0044-RH-Fix-nvme-function-missing-argument.patch |  | ||||||
| Patch0045: 0045-RH-use-rpm-optflags-if-present.patch |  | ||||||
| Patch0046: 0046-RH-add-mpathconf.patch |  | ||||||
| Patch0047: 0047-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch |  | ||||||
| Patch0048: 0048-RH-reset-default-find_mutipaths-value-to-off.patch |  | ||||||
| Patch0049: 0049-RH-attempt-to-get-ANA-info-via-sysfs-first.patch |  | ||||||
| Patch0050: 0050-RH-make-parse_vpd_pg83-match-scsi_id-output.patch |  | ||||||
| Patch0051: 0051-RH-add-scsi-device-handlers-to-modules-load.d.patch |  | ||||||
| Patch0052: 0052-RH-compile-with-libreadline-support.patch |  | ||||||
| Patch0053: 0053-RH-Add-mpathcleanup.patch |  | ||||||
| 
 | 
 | ||||||
| # runtime | # runtime | ||||||
| Requires: %{name}-libs = %{version}-%{release} | Requires: %{name}-libs = %{version}-%{release} | ||||||
| @ -149,7 +109,7 @@ This package contains the files needed to develop applications that use | |||||||
| device-mapper-multipath's libdmmp C API library | device-mapper-multipath's libdmmp C API library | ||||||
| 
 | 
 | ||||||
| %prep | %prep | ||||||
| %autosetup -n multipath-tools-0.9.6 -p1 | %autosetup -n multipath-tools-0.9.7 -p1 | ||||||
| cp %{SOURCE1} . | cp %{SOURCE1} . | ||||||
| 
 | 
 | ||||||
| %build | %build | ||||||
| @ -212,7 +172,6 @@ fi | |||||||
| %config /usr/lib/udev/rules.d/62-multipath.rules | %config /usr/lib/udev/rules.d/62-multipath.rules | ||||||
| %config /usr/lib/udev/rules.d/11-dm-mpath.rules | %config /usr/lib/udev/rules.d/11-dm-mpath.rules | ||||||
| %dir /usr/lib/modules-load.d | %dir /usr/lib/modules-load.d | ||||||
| /usr/lib/modules-load.d/multipath.conf |  | ||||||
| /usr/lib/modules-load.d/scsi_dh.conf | /usr/lib/modules-load.d/scsi_dh.conf | ||||||
| %{_tmpfilesdir}/multipath.conf | %{_tmpfilesdir}/multipath.conf | ||||||
| %doc README.md | %doc README.md | ||||||
| @ -272,6 +231,14 @@ fi | |||||||
| %{_pkgconfdir}/libdmmp.pc | %{_pkgconfdir}/libdmmp.pc | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Tue Nov 21 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-1 | ||||||
|  | - Update source to upstream version 0.9.7 | ||||||
|  |   * Previous patches 0001-0040 are included in the source tarball | ||||||
|  | - Rename redhat patches | ||||||
|  |   * Previous patches 0041-0053 are now patches 0001-0013 | ||||||
|  | - Remove /usr/lib/modules-load.d/multipath.conf | ||||||
|  |   * has been replaced with modprobe@dm_multipath.service unit Wants. | ||||||
|  | 
 | ||||||
| * Fri Sep 22 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.6-1 | * Fri Sep 22 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.6-1 | ||||||
| - Update to the head of the upstream staging branch | - Update to the head of the upstream staging branch | ||||||
| - Rename redhat patches | - Rename redhat patches | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								sources
									
									
									
									
									
								
							| @ -1,2 +1,2 @@ | |||||||
| SHA512 (multipath-tools-0.9.6.tgz) = 17d2b46ead9df6826b3266035bc077a2f4d4bea01e2cd59e32d3917cda40c320f11bc8572da7ba66251e312b46d9be317737069193d481d202d49f9aa5fd71b9 | SHA512 (multipath-tools-0.9.7.tgz) = 0f4c97179a3de5a0c77893fec229eb183293fed8e5e01a9945b261845ccf5d13f8ef2c2ff0c17c9345217d236275caed4765422ec95aed80821f11658bf96e26 | ||||||
| SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 | SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user