diff mbox series

[v2,04/37] libmultipath: never allocate an alias that's already taken

Message ID 20230911163846.27197-5-mwilck@suse.com (mailing list archive)
State Not Applicable, archived
Delegated to: christophe varoqui
Headers show
Series multipath-tools: user-friendly names rework | expand

Commit Message

Martin Wilck Sept. 11, 2023, 4:38 p.m. UTC
From: Martin Wilck <mwilck@suse.com>

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>
---
 libmultipath/alias.c | 33 ++++++++++++++++++++++++---------
 tests/alias.c        |  2 +-
 2 files changed, 25 insertions(+), 10 deletions(-)

Comments

Benjamin Marzinski Sept. 12, 2023, 11 p.m. UTC | #1
On Mon, Sep 11, 2023 at 06:38:13PM +0200, mwilck@suse.com wrote:
> From: Martin Wilck <mwilck@suse.com>
> 
> 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>
> ---
>  libmultipath/alias.c | 33 ++++++++++++++++++++++++---------
>  tests/alias.c        |  2 +-
>  2 files changed, 25 insertions(+), 10 deletions(-)
> 
> diff --git a/libmultipath/alias.c b/libmultipath/alias.c
> index 68f5d84..b5248f2 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,32 +359,47 @@ 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);
> -			goto new_alias;

Double semicolon. Doesn't really hurt anything, and it gets removed
later in the patchset, so:

Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>

> +			goto new_alias;		     ;
>  		}
>  	}
>  
> -	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 3ca6c28..11f209e 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)
>  {
> -- 
> 2.42.0
--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel
diff mbox series

Patch

diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 68f5d84..b5248f2 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,32 +359,47 @@  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);
-			goto new_alias;
+			goto new_alias;		     ;
 		}
 	}
 
-	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 3ca6c28..11f209e 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)
 {