[dm-devel] User friendly names patch.

Benjamin Marzinski bmarzins at redhat.com
Mon Oct 24 15:23:41 UTC 2005


On Sat, Oct 22, 2005 at 09:36:35AM +0200, Christophe Varoqui wrote:
> On ven, 2005-10-21 at 18:35 -0500, Benjamin Marzinski wrote:
> > This is a patch to add the option of more user friendly names for the
> > multipath maps, in the form of mpath<n>.  It adds a configuration option
> > "user_friendly_names". If set, it will cause multipath to check a bindings
> > file for the names. The bindings file (/var/lib/multipath/bindings) has
> > alias to wwid mappings. If multipath finds its wwid in the file, it uses
> > the associated alias. If not, it creates a new alias, and adds the binding
> > to the bindings file. If the config option is not set, multipath defaults
> > to it's regular behavior. Specific aliases in /etc/multipath.conf override
> > this behavior.
> > 
> You forgot to attach the patch :/
> I'll review it again.

Oops.

Here.
 
> Last time I remember I had some worries about it, though I'm perfectly
> happy with the feature. Others' review is welcome.
> 
> Regards,
> cvaroqui
> 
> 
> --
> dm-devel mailing list
> dm-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
-------------- next part --------------
diff -urpN mp-devel-clean/libmultipath/alias.c mp-devel-patched/libmultipath/alias.c
--- mp-devel-clean/libmultipath/alias.c	1969-12-31 18:00:00.000000000 -0600
+++ mp-devel-patched/libmultipath/alias.c	2005-10-21 18:21:42.000000000 -0500
@@ -0,0 +1,271 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include "debug.h"
+#include "uxsock.h"
+#include "alias.h"
+
+
+/*
+ * significant parts of this file were taken from iscsi-bindings.c of the
+ * linux-iscsi project.
+ * Copyright (C) 2002 Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+static int
+ensure_directories_exist(char *str, mode_t dir_mode)
+{
+	char *pathname;
+	char *end;
+	int err;
+
+	pathname = strdup(str);
+	if (!pathname){
+		condlog(0, "Cannot copy bindings file pathname : %s",
+			strerror(errno));
+		return -1;
+	}
+	end = pathname;
+	/* skip leading slashes */
+	while (end && *end && (*end == '/'))
+		end++;
+
+	while ((end = strchr(end, '/'))) {
+		/* if there is another slash, make the dir. */
+		*end = '\0';
+		err = mkdir(pathname, dir_mode);
+		if (err && errno != EEXIST) {
+			condlog(0, "Cannot make directory [%s] : %s",
+				pathname, strerror(errno));
+			free(pathname);
+			return -1;
+		}
+		if (!err)
+			condlog(3, "Created dir [%s]", pathname);
+		*end = '/';
+		end++;
+	}
+	free(pathname);
+	return 0;
+}
+
+static int
+lock_bindings_file(int fd)
+{
+	struct flock lock;
+	int retrys = BINDINGS_FILE_RETRYS;
+	
+	memset(&lock, 0, sizeof(lock));
+	lock.l_type = F_WRLCK;
+	lock.l_whence = SEEK_SET;
+
+	while (fcntl(fd, F_SETLK, &lock) < 0) {
+		if (errno != EACCES && errno != EAGAIN) {
+			condlog(0, "Cannot lock bindings file : %s",
+				strerror(errno));
+			return -1;
+		} else {
+			condlog(0, "Bindings file is currently locked");
+			if ((retrys--) == 0)
+				return -1;
+		}
+		/* because I'm paranoid */
+		memset(&lock, 0, sizeof(lock));
+		lock.l_type = F_WRLCK;
+		lock.l_whence = SEEK_SET;
+		
+		condlog(0, "retrying");
+		sleep(1);
+	}
+	return 0;
+}
+
+
+static int
+open_bindings_file(char *file)
+{
+	int fd;
+	struct stat s;
+
+	if (ensure_directories_exist(file, 0700))
+		return -1;
+	fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+	if (fd < 0) {
+		condlog(0, "Cannot open bindings file [%s] : %s", file,
+			strerror(errno));
+		return -1;
+	}
+
+	if (lock_bindings_file(fd) < 0)
+		goto fail;
+	
+	memset(&s, 0, sizeof(s));
+	if (fstat(fd, &s) < 0){
+		condlog(0, "Cannot stat bindings file : %s", strerror(errno));
+		goto fail;
+	}
+	if (s.st_size == 0) {
+		/* If bindings file is empty, write the header */
+		size_t len = strlen(BINDINGS_FILE_HEADER);
+		if (write_all(fd, BINDINGS_FILE_HEADER, len) != len) {
+			condlog(0,
+				"Cannot write header to bindings file : %s",
+				strerror(errno));
+			/* cleanup partially written header */
+			ftruncate(fd, 0);
+			goto fail;
+		}
+		fsync(fd);
+		condlog(3, "Initialized new bindings file [%s]", file);
+	}
+	
+	return fd;
+
+fail:
+	close(fd);
+	return -1;
+}
+
+
+static int
+lookup_binding(int fd, char *map_wwid, char **map_alias)
+{
+	char buf[LINE_MAX];
+	FILE *f;
+	unsigned int line_nr = 0;
+	int scan_fd;
+	int id = 0;
+
+	*map_alias = NULL;
+	scan_fd = dup(fd);
+	if (scan_fd < 0) {
+		condlog(0, "Cannot dup bindings file descriptor : %s",
+			strerror(errno));
+		return -1;
+	}
+	f = fdopen(scan_fd, "r");
+	if (!f) {
+		condlog(0, "cannot fdopen on bindings file descriptor : %s",
+			strerror(errno));
+		close(scan_fd);
+		return -1;
+	}
+	while (fgets(buf, LINE_MAX, f)) {
+		char *c, *alias, *wwid;
+		int curr_id;
+
+		line_nr++;
+		c = strpbrk(buf, "#\n\r");
+		if (c)
+			*c = '\0';
+		alias = strtok(buf, " \t");
+		if (!alias) /* blank line */
+			continue;
+		if (sscanf(alias, "mpath%d", &curr_id) == 1 && curr_id >= id)
+			id = curr_id + 1;
+		wwid = strtok(NULL, " \t");
+		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."
+				"\nSetting alias to %s", wwid, alias);
+			*map_alias = strdup(alias);
+			if (*map_alias == NULL)
+				condlog(0, "Cannot copy alias from bindings "
+					"file : %s", strerror(errno));
+			fclose(f);
+			return id;
+		}
+	}
+	condlog(3, "No matching wwid [%s] in bindings file.", map_wwid);
+	fclose(f);
+	return id;
+}	
+
+static char *
+allocate_binding(int fd, char *wwid, int id)
+{
+	char buf[LINE_MAX];
+	off_t offset;
+	char *alias, *c;
+	
+	if (id < 0) {
+		condlog(0, "Bindings file full. Cannot allocate new binding");
+		return NULL;
+	}
+	
+	snprintf(buf, LINE_MAX, "mpath%d %s\n", id, wwid);
+	buf[LINE_MAX - 1] = '\0';
+
+	offset = lseek(fd, 0, SEEK_END);
+	if (offset < 0){
+		condlog(0, "Cannot seek to end of bindings file : %s",
+			strerror(errno));
+		return NULL;
+	}
+	if (write_all(fd, buf, strlen(buf)) != strlen(buf)){
+		condlog(0, "Cannot write binding to bindings file : %s",
+			strerror(errno));
+		/* clear partial write */
+		ftruncate(fd, offset);
+		return NULL;
+	}
+	c = strchr(buf, ' ');
+	*c = '\0';
+	alias = strdup(buf);
+	if (alias == NULL)
+		condlog(0, "cannot copy new alias from bindings file : %s",
+			strerror(errno));
+	else
+		condlog(3, "Created new binding [%s] for WWID [%s]", alias,
+			wwid);
+	return alias;
+}		
+
+char *
+get_user_friendly_alias(char *wwid)
+{
+	char *alias;
+	int fd, id;
+
+	if (!wwid || *wwid == '\0') {
+		condlog(3, "Cannot find binding for empty WWID");
+		return NULL;
+	}
+
+	fd = open_bindings_file(BINDINGS_FILE_NAME);
+	if (fd < 0)
+		return NULL;
+	id = lookup_binding(fd, wwid, &alias);
+	if (id < 0) {
+		close(fd);
+		return NULL;
+	}
+	if (!alias)
+		alias = allocate_binding(fd, wwid, id);
+
+	close(fd);
+	return alias;
+}
diff -urpN mp-devel-clean/libmultipath/alias.h mp-devel-patched/libmultipath/alias.h
--- mp-devel-clean/libmultipath/alias.h	1969-12-31 18:00:00.000000000 -0600
+++ mp-devel-patched/libmultipath/alias.h	2005-10-21 18:21:42.000000000 -0500
@@ -0,0 +1,13 @@
+#define BINDINGS_FILE_NAME "/var/lib/multipath/bindings"
+#define BINDINGS_FILE_RETRYS 3
+#define BINDINGS_FILE_HEADER \
+"# Multipath bindings, Version : 1.0\n" \
+"# NOTE: this file is automatically maintained by the multipath program.\n" \
+"# You should not need to edit this file in normal circumstances.\n" \
+"#\n" \
+"# Format:\n" \
+"# alias wwid\n" \
+"#\n"
+
+
+char *get_user_friendly_alias(char *wwid);
diff -urpN mp-devel-clean/libmultipath/config.h mp-devel-patched/libmultipath/config.h
--- mp-devel-clean/libmultipath/config.h	2005-10-21 17:55:11.000000000 -0500
+++ mp-devel-patched/libmultipath/config.h	2005-10-21 18:21:42.000000000 -0500
@@ -58,6 +58,7 @@ struct config {
 	int remove;
 	int rr_weight;
 	int no_path_retry;
+	int user_friendly_names;
 
 	char * dev;
 	char * udev_dir;
diff -urpN mp-devel-clean/libmultipath/devmapper.h mp-devel-patched/libmultipath/devmapper.h
--- mp-devel-clean/libmultipath/devmapper.h	2005-10-21 17:55:11.000000000 -0500
+++ mp-devel-patched/libmultipath/devmapper.h	2005-10-21 18:21:42.000000000 -0500
@@ -19,6 +19,7 @@ int dm_geteventnr (char *name);
 int dm_get_minor (char *name);
 char * dm_mapname(int major, int minor);
 int dm_remove_partmaps (char * mapname);
+int dm_get_uuid(char *name, char *uuid);
 
 #if 0
 int dm_rename (char * old, char * new);
diff -urpN mp-devel-clean/libmultipath/dict.c mp-devel-patched/libmultipath/dict.c
--- mp-devel-clean/libmultipath/dict.c	2005-10-21 17:55:11.000000000 -0500
+++ mp-devel-patched/libmultipath/dict.c	2005-10-21 18:21:42.000000000 -0500
@@ -191,6 +191,25 @@ def_no_path_retry_handler(vector strvec)
 	return 0;
 }
 
+static int
+names_handler(vector strvec)
+{
+	char * buff;
+
+	buff = set_value(strvec);
+
+	if (!buff)
+		return 1;
+
+	if (!strncmp(buff, "no", 2) || !strncmp(buff, "0", 1))
+		conf->user_friendly_names = 0;
+	else if (!strncmp(buff, "yes", 2) || !strncmp(buff, "1", 1))
+		conf->user_friendly_names = 1;
+
+	FREE(buff);
+	return 0;
+}
+
 /*
  * blacklist block handlers
  */
@@ -641,6 +660,7 @@ init_keywords(void)
 	install_keyword("rr_min_io", &def_minio_handler);
 	install_keyword("rr_weight", &def_weight_handler);
 	install_keyword("no_path_retry", &def_no_path_retry_handler);
+	install_keyword("user_friendly_names", &names_handler);
 
 	/*
 	 * deprecated synonyms
diff -urpN mp-devel-clean/libmultipath/Makefile mp-devel-patched/libmultipath/Makefile
--- mp-devel-clean/libmultipath/Makefile	2005-10-21 17:55:11.000000000 -0500
+++ mp-devel-patched/libmultipath/Makefile	2005-10-21 18:21:42.000000000 -0500
@@ -10,7 +10,7 @@ OBJS = memory.o parser.o vector.o devmap
        hwtable.o blacklist.o util.o dmparser.o config.o \
        structs.o cache.o discovery.o propsel.o dict.o \
        pgpolicies.o debug.o regex.o defaults.o uevent.o \
-       switchgroup.o uxsock.o print.o
+       switchgroup.o uxsock.o print.o alias.o
 
 CFLAGS = -pipe -g -Wall -Wunused -Wstrict-prototypes
 
diff -urpN mp-devel-clean/libmultipath/propsel.c mp-devel-patched/libmultipath/propsel.c
--- mp-devel-clean/libmultipath/propsel.c	2005-10-21 17:55:11.000000000 -0500
+++ mp-devel-patched/libmultipath/propsel.c	2005-10-21 18:21:42.000000000 -0500
@@ -5,6 +5,7 @@
 #include "config.h"
 #include "debug.h"
 #include "pgpolicies.h"
+#include "alias.h"
 
 #include "../libcheckers/checkers.h"
 
@@ -126,8 +127,13 @@ select_alias (struct multipath * mp)
 {
 	if (mp->mpe && mp->mpe->alias)
 		mp->alias = mp->mpe->alias;
-	else
-		mp->alias = mp->wwid;
+	else {
+		mp->alias = NULL;
+		if (conf->user_friendly_names)
+			mp->alias = get_user_friendly_alias(mp->wwid);
+		if (mp->alias == NULL)
+			mp->alias = mp->wwid;
+	}
 
 	return 0;
 }
diff -urpN mp-devel-clean/libmultipath/uxsock.h mp-devel-patched/libmultipath/uxsock.h
--- mp-devel-clean/libmultipath/uxsock.h	2005-10-21 17:55:11.000000000 -0500
+++ mp-devel-patched/libmultipath/uxsock.h	2005-10-21 18:21:42.000000000 -0500
@@ -3,4 +3,5 @@ int ux_socket_connect(const char *name);
 int ux_socket_listen(const char *name);
 int send_packet(int fd, const char *buf, size_t len);
 int recv_packet(int fd, char **buf, size_t *len);
-
+size_t write_all(int fd, const void *buf, size_t len);
+size_t read_all(int fd, void *buf, size_t len);
diff -urpN mp-devel-clean/multipath/main.c mp-devel-patched/multipath/main.c
--- mp-devel-clean/multipath/main.c	2005-10-21 17:59:04.000000000 -0500
+++ mp-devel-patched/multipath/main.c	2005-10-21 18:21:42.000000000 -0500
@@ -744,10 +744,10 @@ coalesce_paths (vector curmp, vector pat
 
 		mpp->mpe = find_mpe(pp1->wwid);
 		mpp->hwe = pp1->hwe;
+		strcpy(mpp->wwid, pp1->wwid);
 		select_alias(mpp);
 
 		pp1->mpp = mpp;
-		strcpy(mpp->wwid, pp1->wwid);
 		mpp->size = pp1->size;
 		mpp->paths = vector_alloc();
 
diff -urpN mp-devel-clean/multipath.conf.annotated mp-devel-patched/multipath.conf.annotated
--- mp-devel-clean/multipath.conf.annotated	2005-10-21 17:57:58.000000000 -0500
+++ mp-devel-patched/multipath.conf.annotated	2005-10-21 18:21:42.000000000 -0500
@@ -110,6 +110,20 @@
 #	# default : (null)
 #	#
 #	#no_path_retry  queue
+#
+#	#
+#	# name    : user_friendly_names
+#	# scope   : multipath
+#	# desc    : If set to "yes", using the bindings file
+#	#           /var/lib/multipath/bindings to assign a persistent and
+#	#           unique alias to the multipath, in the form of mpath<n>.
+#	#           If set to "no" use the WWID as the alias. In either case
+#	#           this be will be overriden by any specific aliases in this
+#	#           file.
+#	# values  : yes|no
+#	# default : no
+#	user_friendly_names no
+#
 #}
 #	
 ##
diff -urpN mp-devel-clean/multipath.conf.synthetic mp-devel-patched/multipath.conf.synthetic
--- mp-devel-clean/multipath.conf.synthetic	2005-10-21 17:57:58.000000000 -0500
+++ mp-devel-patched/multipath.conf.synthetic	2005-10-21 18:21:42.000000000 -0500
@@ -14,6 +14,7 @@
 #	rr_weight		priorities
 #	failback		immediate
 #	no_path_retry		fail
+#	user_friendly_name	no
 #}
 #devnode_blacklist {
 #       wwid 26353900f02796769
diff -urpN mp-devel-clean/multipathd/main.c mp-devel-patched/multipathd/main.c
--- mp-devel-clean/multipathd/main.c	2005-10-21 17:57:58.000000000 -0500
+++ mp-devel-patched/multipathd/main.c	2005-10-21 18:21:42.000000000 -0500
@@ -213,15 +213,10 @@ update_multipath_strings (struct multipa
 static void
 set_multipath_wwid (struct multipath * mpp)
 {
-	char * wwid;
-
-	wwid = get_mpe_wwid(mpp->alias);
+	if (mpp->wwid)
+		return;
 
-	if (wwid) {
-		strncpy(mpp->wwid, wwid, WWID_SIZE);
-		wwid = NULL;
-	} else
-		strncpy(mpp->wwid, mpp->alias, WWID_SIZE);
+	dm_get_uuid(mpp->alias, mpp->wwid);
 }
 
 static int


More information about the dm-devel mailing list