[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