* [PATCH] multipath: add find_multipaths feature.
@ 2011-07-25 18:57 Benjamin Marzinski
2011-09-01 2:55 ` [PATCH v2] " Benjamin Marzinski
0 siblings, 1 reply; 12+ messages in thread
From: Benjamin Marzinski @ 2011-07-25 18:57 UTC (permalink / raw)
To: device-mapper development
This adds a new default feature, find_multipaths. When this is set to yes,
multipath will no longer try to create a multipath device for every
non-blacklisted device. Instead, it will only create a device when one of
three conditions are met.
1. Three are at least two non-blacklisted paths with the same wwid
2. The user manually forces the creation, by specifying a device with the
multipath command.
3. A path has the same wwid as a multipath device that was previously crreated
(even if that multipath device doesn't currently exist).
To do 3, multipath stores the wwid of every path that it creates in
/etc/multipath/wwids. Whenever a path is added it's wwid is checked against
this file. If there's a match, it is multipathed, even if it's the only path.
This should allow multipath to automatically choose the correct paths to make
into multipath devics in most cases, without needing the user to edit the
blacklist.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/Makefile | 2
libmultipath/alias.c | 151 ---------------------------------------
libmultipath/alias.h | 1
libmultipath/config.c | 1
libmultipath/config.h | 1
libmultipath/configure.c | 14 +++
libmultipath/defaults.h | 2
libmultipath/dict.c | 34 ++++++++
libmultipath/file.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++
libmultipath/file.h | 11 ++
libmultipath/finder.c | 165 +++++++++++++++++++++++++++++++++++++++++++
libmultipath/finder.h | 18 ++++
multipath/main.c | 2
multipathd/main.c | 6 +
14 files changed, 435 insertions(+), 151 deletions(-)
Index: multipath-tools-110713/libmultipath/alias.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/alias.c
+++ multipath-tools-110713/libmultipath/alias.c
@@ -3,19 +3,16 @@
* Copyright (c) 2005 Benjamin Marzinski, Redhat
*/
#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 <signal.h>
#include "debug.h"
#include "uxsock.h"
#include "alias.h"
+#include "file.h"
/*
@@ -36,148 +33,6 @@
* 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 void
-sigalrm(int sig)
-{
- /* do nothing */
-}
-
-static int
-lock_bindings_file(int fd)
-{
- struct sigaction act, oldact;
- sigset_t set, oldset;
- struct flock lock;
- int err;
-
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
-
- act.sa_handler = sigalrm;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- sigemptyset(&set);
- sigaddset(&set, SIGALRM);
-
- sigaction(SIGALRM, &act, &oldact);
- sigprocmask(SIG_UNBLOCK, &set, &oldset);
-
- alarm(BINDINGS_FILE_TIMEOUT);
- err = fcntl(fd, F_SETLKW, &lock);
- alarm(0);
-
- if (err) {
- if (errno != EINTR)
- condlog(0, "Cannot lock bindings file : %s",
- strerror(errno));
- else
- condlog(0, "Bindings file is locked. Giving up.");
- }
-
- sigprocmask(SIG_SETMASK, &oldset, NULL);
- sigaction(SIGALRM, &oldact, NULL);
- return err;
-
-}
-
-
-static int
-open_bindings_file(char *file, int *can_write)
-{
- int fd;
- struct stat s;
-
- if (ensure_directories_exist(file, 0700))
- return -1;
- *can_write = 1;
- fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
- if (fd < 0) {
- if (errno == EROFS) {
- *can_write = 0;
- condlog(3, "Cannot open bindings file [%s] read/write. "
- " trying readonly", file);
- fd = open(file, O_RDONLY);
- if (fd < 0) {
- condlog(0, "Cannot open bindings file [%s] "
- "readonly : %s", file, strerror(errno));
- return -1;
- }
- }
- else {
- condlog(0, "Cannot open bindings file [%s] : %s", file,
- strerror(errno));
- return -1;
- }
- }
- if (*can_write && 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 (*can_write == 0)
- goto fail;
- /* 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
format_devname(char *name, int id, int len, char *prefix)
@@ -366,7 +221,7 @@ get_user_friendly_alias(char *wwid, char
return NULL;
}
- fd = open_bindings_file(file, &can_write);
+ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
if (fd < 0)
return NULL;
@@ -416,7 +271,7 @@ get_user_friendly_wwid(char *alias, char
return NULL;
}
- fd = open_bindings_file(file, &unused);
+ fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
if (fd < 0)
return NULL;
Index: multipath-tools-110713/libmultipath/alias.h
===================================================================
--- multipath-tools-110713.orig/libmultipath/alias.h
+++ multipath-tools-110713/libmultipath/alias.h
@@ -1,4 +1,3 @@
-#define BINDINGS_FILE_TIMEOUT 30
#define BINDINGS_FILE_HEADER \
"# Multipath bindings, Version : 1.0\n" \
"# NOTE: this file is automatically maintained by the multipath program.\n" \
Index: multipath-tools-110713/libmultipath/config.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/config.c
+++ multipath-tools-110713/libmultipath/config.c
@@ -497,6 +497,7 @@ load_config (char * file)
conf->flush_on_last_del = 0;
conf->attribute_flags = 0;
conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
+ conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
/*
* preload default hwtable
Index: multipath-tools-110713/libmultipath/config.h
===================================================================
--- multipath-tools-110713.orig/libmultipath/config.h
+++ multipath-tools-110713/libmultipath/config.h
@@ -92,6 +92,7 @@ struct config {
int attribute_flags;
int fast_io_fail;
unsigned int dev_loss;
+ int find_multipaths;
uid_t uid;
gid_t gid;
mode_t mode;
Index: multipath-tools-110713/libmultipath/configure.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/configure.c
+++ multipath-tools-110713/libmultipath/configure.c
@@ -35,6 +35,7 @@
#include "alias.h"
#include "prio.h"
#include "util.h"
+#include "finder.h"
extern int
setup_map (struct multipath * mpp, char * params, int params_size)
@@ -404,6 +405,8 @@ domap (struct multipath * mpp, char * pa
* DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
* succeeded
*/
+ if (mpp->action == ACT_CREATE)
+ remember_wwid(mpp->wwid);
if (!conf->daemon) {
/* multipath client mode */
dm_switchgroup(mpp->alias, mpp->bestpg);
@@ -463,6 +466,10 @@ coalesce_paths (struct vectors * vecs, v
memset(empty_buff, 0, WWID_SIZE);
+ /* ignore refwwid if it's empty */
+ if (refwwid && !strlen(refwwid))
+ refwwid = NULL;
+
if (force_reload) {
vector_foreach_slot (pathvec, pp1, k) {
pp1->mpp = NULL;
@@ -492,6 +499,13 @@ coalesce_paths (struct vectors * vecs, v
if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
continue;
+ /* If find_multipaths was selected check if the path is valid */
+ if (conf->find_multipaths && !refwwid &&
+ !should_multipath(pp1, pathvec)) {
+ orphan_path(pp1);
+ continue;
+ }
+
/*
* at this point, we know we really got a new mp
*/
Index: multipath-tools-110713/libmultipath/defaults.h
===================================================================
--- multipath-tools-110713.orig/libmultipath/defaults.h
+++ multipath-tools-110713/libmultipath/defaults.h
@@ -15,6 +15,7 @@
#define DEFAULT_USER_FRIENDLY_NAMES 0
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 1
+#define DEFAULT_FIND_MULTIPATHS 0
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
@@ -24,5 +25,6 @@
#define DEFAULT_SOCKET "/var/run/multipathd.sock"
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
+#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
char * set_default (char * str);
Index: multipath-tools-110713/libmultipath/dict.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/dict.c
+++ multipath-tools-110713/libmultipath/dict.c
@@ -525,6 +525,27 @@ def_flush_on_last_del_handler(vector str
}
static int
+def_find_multipaths_handler(vector strvec)
+{
+ char * buff;
+
+ buff = set_value(strvec);
+
+ if (!buff)
+ return 1;
+
+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "0")))
+ conf->find_multipaths = 0;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+ conf->find_multipaths = 1;
+
+ FREE(buff);
+ return 0;
+}
+
+static int
names_handler(vector strvec)
{
char * buff;
@@ -2338,6 +2359,18 @@ snprint_def_flush_on_last_del (char * bu
}
static int
+snprint_def_find_multipaths (char * buff, int len, void * data)
+{
+ if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS)
+ return 0;
+ if (!conf->find_multipaths)
+ return snprintf(buff, len, "no");
+
+ return snprintf(buff, len, "yes");
+}
+
+
+static int
snprint_def_user_friendly_names (char * buff, int len, void * data)
{
if (!conf->user_friendly_names)
@@ -2428,6 +2461,7 @@ init_keywords(void)
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("bindings_file", &bindings_file_handler, &snprint_def_bindings_file);
+ install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
__deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
Index: multipath-tools-110713/libmultipath/file.c
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/file.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2005 Christophe Varoqui
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
+ */
+#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 <signal.h>
+
+#include "file.h"
+#include "debug.h"
+#include "uxsock.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 file pathname %s : %s",
+ str, 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 void
+sigalrm(int sig)
+{
+ /* do nothing */
+}
+
+static int
+lock_file(int fd, char *file_name)
+{
+ struct sigaction act, oldact;
+ sigset_t set, oldset;
+ struct flock lock;
+ int err;
+
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+
+ act.sa_handler = sigalrm;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+
+ sigaction(SIGALRM, &act, &oldact);
+ sigprocmask(SIG_UNBLOCK, &set, &oldset);
+
+ alarm(FILE_TIMEOUT);
+ err = fcntl(fd, F_SETLKW, &lock);
+ alarm(0);
+
+ if (err) {
+ if (errno != EINTR)
+ condlog(0, "Cannot lock %s : %s", file_name,
+ strerror(errno));
+ else
+ condlog(0, "%s is locked. Giving up.", file_name);
+ }
+
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ sigaction(SIGALRM, &oldact, NULL);
+ return err;
+}
+
+int
+open_file(char *file, int *can_write, char *header)
+{
+ int fd;
+ struct stat s;
+
+ if (ensure_directories_exist(file, 0700))
+ return -1;
+ *can_write = 1;
+ fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ if (errno == EROFS) {
+ *can_write = 0;
+ condlog(3, "Cannot open file [%s] read/write. "
+ " trying readonly", file);
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ condlog(0, "Cannot open file [%s] "
+ "readonly : %s", file, strerror(errno));
+ return -1;
+ }
+ }
+ else {
+ condlog(0, "Cannot open file [%s] : %s", file,
+ strerror(errno));
+ return -1;
+ }
+ }
+ if (*can_write && lock_file(fd, file) < 0)
+ goto fail;
+
+ memset(&s, 0, sizeof(s));
+ if (fstat(fd, &s) < 0){
+ condlog(0, "Cannot stat file %s : %s", file, strerror(errno));
+ goto fail;
+ }
+ if (s.st_size == 0) {
+ if (*can_write == 0)
+ goto fail;
+ /* If file is empty, write the header */
+ size_t len = strlen(header);
+ if (write_all(fd, header, len) != len) {
+ condlog(0,
+ "Cannot write header to file %s : %s", file,
+ strerror(errno));
+ /* cleanup partially written header */
+ ftruncate(fd, 0);
+ goto fail;
+ }
+ fsync(fd);
+ condlog(3, "Initialized new file [%s]", file);
+ }
+
+ return fd;
+
+fail:
+ close(fd);
+ return -1;
+}
Index: multipath-tools-110713/libmultipath/file.h
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/file.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+#ifndef _FILE_H
+#define _FILE_H
+
+#define FILE_TIMEOUT 30
+int open_file(char *file, int *can_write, char *header);
+
+#endif /* _FILE_H */
Index: multipath-tools-110713/libmultipath/finder.c
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/finder.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "checkers.h"
+#include "vector.h"
+#include "structs.h"
+#include "debug.h"
+#include "uxsock.h"
+#include "file.h"
+#include "finder.h"
+#include "defaults.h"
+
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+static int
+lookup_wwid(FILE *f, char *wwid) {
+ int c;
+ char buf[LINE_MAX];
+ int count;
+
+ while ((c = fgetc(f)) != EOF){
+ if (c != '/') {
+ if (fgets(buf, LINE_MAX, f) == NULL)
+ return 0;
+ else
+ continue;
+ }
+ count = 0;
+ while ((c = fgetc(f)) != '/') {
+ if (c == EOF)
+ return 0;
+ if (count >= WWID_SIZE - 1)
+ goto next;
+ if (wwid[count] == '\0')
+ goto next;
+ if (c != wwid[count++])
+ goto next;
+ }
+ if (wwid[count] == '\0')
+ return 1;
+next:
+ if (fgets(buf, LINE_MAX, f) == NULL)
+ return 0;
+ }
+ return 0;
+}
+
+static int
+write_out_wwid(int fd, char *wwid) {
+ int ret;
+ off_t offset;
+ char buf[WWID_SIZE + 3];
+
+ ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
+ if (ret >= (WWID_SIZE + 3) || ret < 0){
+ condlog(0, "can't format wwid for writing (%d) : %s",
+ ret, strerror(errno));
+ return -1;
+ }
+ offset = lseek(fd, 0, SEEK_END);
+ if (offset < 0) {
+ condlog(0, "can't seek to the end of wwids file : %s",
+ strerror(errno));
+ return -1;
+ }
+ if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
+ condlog(0, "cannot write wwid to wwids file : %s",
+ strerror(errno));
+ ftruncate(fd, offset);
+ return -1;
+ }
+ return 1;
+}
+
+static int
+check_wwids_file(char *wwid, int write_wwid)
+{
+ int scan_fd, fd, can_write, found, ret;
+ FILE *f;
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
+ if (fd < 0)
+ return -1;
+
+ scan_fd = dup(fd);
+ if (scan_fd < 0) {
+ condlog(0, "can't dup wwids file descriptor : %s",
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+ f = fdopen(scan_fd, "r");
+ if (!f) {
+ condlog(0,"can't fdopen wwids file : %s", strerror(errno));
+ close(fd);
+ close(scan_fd);
+ return -1;
+ }
+ found = lookup_wwid(f, wwid);
+ if (found) {
+ ret = 0;
+ goto out;
+ }
+ if (!write_wwid) {
+ ret = -1;
+ goto out;
+ }
+ if (!can_write) {
+ condlog(0, "wwids file is read-only. Can't write wwid");
+ ret = -1;
+ goto out;
+ }
+ ret = write_out_wwid(fd, wwid);
+out:
+ fclose(f);
+ close(scan_fd);
+ close(fd);
+ return ret;
+}
+
+int
+should_multipath(struct path *pp1, vector pathvec)
+{
+ int i;
+ struct path *pp2;
+
+ condlog(4, "checking if %s should be multipathed", pp1->dev);
+ vector_foreach_slot(pathvec, pp2, i) {
+ if (pp1->dev == pp2->dev)
+ continue;
+ if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
+ condlog(3, "found multiple paths with wwid %s, "
+ "multipathing %s", pp1->wwid, pp1->dev);
+ return 1;
+ }
+ }
+ if (check_wwids_file(pp1->wwid, 0) < 0) {
+ condlog(3, "wwid %s not in wwids file, skipping %s",
+ pp1->wwid, pp1->dev);
+ return 0;
+ }
+ condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid,
+ pp1->dev);
+ return 1;
+}
+
+int
+remember_wwid(char *wwid)
+{
+ int ret = check_wwids_file(wwid, 1);
+ if (ret < 0){
+ condlog(3, "failed writing wwid %s to wwids file", wwid);
+ return -1;
+ }
+ if (ret == 1)
+ condlog(3, "wrote wwid %s to wwids file", wwid);
+ else
+ condlog(4, "wwid %s already in wwids file", wwid);
+ return 0;
+}
Index: multipath-tools-110713/libmultipath/finder.h
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/finder.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+#ifndef _FINDER_H
+#define _FINDER_H
+
+#define WWIDS_FILE_HEADER \
+"# Multipath wwids, Version : 1.0\n" \
+"# NOTE: This file is automatically maintained by multipath and multipathd.\n" \
+"# You should not need to edit this file in normal circumstances.\n" \
+"#\n" \
+"# Valid WWIDs:\n"
+
+int should_multipath(struct path *pp, vector pathvec);
+int remember_wwid(char *wwid);
+
+#endif /* _FINDER_H */
Index: multipath-tools-110713/multipath/main.c
===================================================================
--- multipath-tools-110713.orig/multipath/main.c
+++ multipath-tools-110713/multipath/main.c
@@ -313,7 +313,7 @@ configure (void)
/*
* core logic entry point
*/
- r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
+ r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload);
out:
if (refwwid)
Index: multipath-tools-110713/multipathd/main.c
===================================================================
--- multipath-tools-110713.orig/multipathd/main.c
+++ multipath-tools-110713/multipathd/main.c
@@ -47,6 +47,7 @@
#include <print.h>
#include <configure.h>
#include <prio.h>
+#include <finder.h>
#include <pgpolicies.h>
#include <uevent.h>
@@ -447,6 +448,11 @@ rescan:
return 1;
}
+ if (conf->find_multipaths &&
+ !should_multipath(pp, vecs->pathvec)) {
+ orphan_path(pp);
+ return 0;
+ }
condlog(4,"%s: creating new map", pp->dev);
if ((mpp = add_map_with_path(vecs, pp, 1))) {
mpp->action = ACT_CREATE;
Index: multipath-tools-110713/libmultipath/Makefile
===================================================================
--- multipath-tools-110713.orig/libmultipath/Makefile
+++ multipath-tools-110713/libmultipath/Makefile
@@ -15,7 +15,7 @@ OBJS = memory.o parser.o vector.o devmap
pgpolicies.o debug.o regex.o defaults.o uevent.o \
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
- lock.o waiter.o
+ lock.o waiter.o file.o finder.o
LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-07-25 18:57 [PATCH] multipath: add find_multipaths feature Benjamin Marzinski
@ 2011-09-01 2:55 ` Benjamin Marzinski
2011-09-01 7:14 ` Christophe Varoqui
0 siblings, 1 reply; 12+ messages in thread
From: Benjamin Marzinski @ 2011-09-01 2:55 UTC (permalink / raw)
To: device-mapper development; +Cc: Christophe Varoqui
This adds a new default feature, find_multipaths. When this is set to yes,
multipath will no longer try to create a multipath device for every
non-blacklisted device. Instead, it will only create a device when one of
three conditions are met.
1. Three are at least two non-blacklisted paths with the same wwid
2. The user manually forces the creation, by specifying a device with the
multipath command.
3. A path has the same wwid as a multipath device that was previously crreated
(even if that multipath device doesn't currently exist).
To do 3, multipath stores the wwid of every path that it creates in
/etc/multipath/wwids. Whenever a path is added it's wwid is checked against
this file. If there's a match, it is multipathed, even if it's the only path.
This should allow multipath to automatically choose the correct paths to make
into multipath devics in most cases, without needing the user to edit the
blacklist.
This is identical to my first post, except that it includes a previously
missing call to remember_wwid.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/Makefile | 2
libmultipath/alias.c | 151 ---------------------------------------
libmultipath/alias.h | 1
libmultipath/config.c | 1
libmultipath/config.h | 1
libmultipath/configure.c | 14 +++
libmultipath/defaults.h | 2
libmultipath/dict.c | 34 ++++++++
libmultipath/file.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++
libmultipath/file.h | 11 ++
libmultipath/finder.c | 165 +++++++++++++++++++++++++++++++++++++++++++
libmultipath/finder.h | 18 ++++
multipath/main.c | 2
multipathd/main.c | 6 +
14 files changed, 435 insertions(+), 151 deletions(-)
Index: multipath-tools-110713/libmultipath/alias.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/alias.c
+++ multipath-tools-110713/libmultipath/alias.c
@@ -3,19 +3,16 @@
* Copyright (c) 2005 Benjamin Marzinski, Redhat
*/
#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 <signal.h>
#include "debug.h"
#include "uxsock.h"
#include "alias.h"
+#include "file.h"
/*
@@ -36,148 +33,6 @@
* 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 void
-sigalrm(int sig)
-{
- /* do nothing */
-}
-
-static int
-lock_bindings_file(int fd)
-{
- struct sigaction act, oldact;
- sigset_t set, oldset;
- struct flock lock;
- int err;
-
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
-
- act.sa_handler = sigalrm;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- sigemptyset(&set);
- sigaddset(&set, SIGALRM);
-
- sigaction(SIGALRM, &act, &oldact);
- sigprocmask(SIG_UNBLOCK, &set, &oldset);
-
- alarm(BINDINGS_FILE_TIMEOUT);
- err = fcntl(fd, F_SETLKW, &lock);
- alarm(0);
-
- if (err) {
- if (errno != EINTR)
- condlog(0, "Cannot lock bindings file : %s",
- strerror(errno));
- else
- condlog(0, "Bindings file is locked. Giving up.");
- }
-
- sigprocmask(SIG_SETMASK, &oldset, NULL);
- sigaction(SIGALRM, &oldact, NULL);
- return err;
-
-}
-
-
-static int
-open_bindings_file(char *file, int *can_write)
-{
- int fd;
- struct stat s;
-
- if (ensure_directories_exist(file, 0700))
- return -1;
- *can_write = 1;
- fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
- if (fd < 0) {
- if (errno == EROFS) {
- *can_write = 0;
- condlog(3, "Cannot open bindings file [%s] read/write. "
- " trying readonly", file);
- fd = open(file, O_RDONLY);
- if (fd < 0) {
- condlog(0, "Cannot open bindings file [%s] "
- "readonly : %s", file, strerror(errno));
- return -1;
- }
- }
- else {
- condlog(0, "Cannot open bindings file [%s] : %s", file,
- strerror(errno));
- return -1;
- }
- }
- if (*can_write && 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 (*can_write == 0)
- goto fail;
- /* 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
format_devname(char *name, int id, int len, char *prefix)
@@ -366,7 +221,7 @@ get_user_friendly_alias(char *wwid, char
return NULL;
}
- fd = open_bindings_file(file, &can_write);
+ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
if (fd < 0)
return NULL;
@@ -416,7 +271,7 @@ get_user_friendly_wwid(char *alias, char
return NULL;
}
- fd = open_bindings_file(file, &unused);
+ fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
if (fd < 0)
return NULL;
Index: multipath-tools-110713/libmultipath/alias.h
===================================================================
--- multipath-tools-110713.orig/libmultipath/alias.h
+++ multipath-tools-110713/libmultipath/alias.h
@@ -1,4 +1,3 @@
-#define BINDINGS_FILE_TIMEOUT 30
#define BINDINGS_FILE_HEADER \
"# Multipath bindings, Version : 1.0\n" \
"# NOTE: this file is automatically maintained by the multipath program.\n" \
Index: multipath-tools-110713/libmultipath/config.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/config.c
+++ multipath-tools-110713/libmultipath/config.c
@@ -497,6 +497,7 @@ load_config (char * file)
conf->flush_on_last_del = 0;
conf->attribute_flags = 0;
conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
+ conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
/*
* preload default hwtable
Index: multipath-tools-110713/libmultipath/config.h
===================================================================
--- multipath-tools-110713.orig/libmultipath/config.h
+++ multipath-tools-110713/libmultipath/config.h
@@ -92,6 +92,7 @@ struct config {
int attribute_flags;
int fast_io_fail;
unsigned int dev_loss;
+ int find_multipaths;
uid_t uid;
gid_t gid;
mode_t mode;
Index: multipath-tools-110713/libmultipath/configure.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/configure.c
+++ multipath-tools-110713/libmultipath/configure.c
@@ -35,6 +35,7 @@
#include "alias.h"
#include "prio.h"
#include "util.h"
+#include "finder.h"
extern int
setup_map (struct multipath * mpp, char * params, int params_size)
@@ -404,6 +405,8 @@ domap (struct multipath * mpp, char * pa
* DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
* succeeded
*/
+ if (mpp->action == ACT_CREATE)
+ remember_wwid(mpp->wwid);
if (!conf->daemon) {
/* multipath client mode */
dm_switchgroup(mpp->alias, mpp->bestpg);
@@ -463,6 +466,10 @@ coalesce_paths (struct vectors * vecs, v
memset(empty_buff, 0, WWID_SIZE);
+ /* ignore refwwid if it's empty */
+ if (refwwid && !strlen(refwwid))
+ refwwid = NULL;
+
if (force_reload) {
vector_foreach_slot (pathvec, pp1, k) {
pp1->mpp = NULL;
@@ -492,6 +499,13 @@ coalesce_paths (struct vectors * vecs, v
if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
continue;
+ /* If find_multipaths was selected check if the path is valid */
+ if (conf->find_multipaths && !refwwid &&
+ !should_multipath(pp1, pathvec)) {
+ orphan_path(pp1);
+ continue;
+ }
+
/*
* at this point, we know we really got a new mp
*/
Index: multipath-tools-110713/libmultipath/defaults.h
===================================================================
--- multipath-tools-110713.orig/libmultipath/defaults.h
+++ multipath-tools-110713/libmultipath/defaults.h
@@ -15,6 +15,7 @@
#define DEFAULT_USER_FRIENDLY_NAMES 0
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 1
+#define DEFAULT_FIND_MULTIPATHS 0
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
@@ -24,5 +25,6 @@
#define DEFAULT_SOCKET "/var/run/multipathd.sock"
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
+#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
char * set_default (char * str);
Index: multipath-tools-110713/libmultipath/dict.c
===================================================================
--- multipath-tools-110713.orig/libmultipath/dict.c
+++ multipath-tools-110713/libmultipath/dict.c
@@ -525,6 +525,27 @@ def_flush_on_last_del_handler(vector str
}
static int
+def_find_multipaths_handler(vector strvec)
+{
+ char * buff;
+
+ buff = set_value(strvec);
+
+ if (!buff)
+ return 1;
+
+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "0")))
+ conf->find_multipaths = 0;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+ conf->find_multipaths = 1;
+
+ FREE(buff);
+ return 0;
+}
+
+static int
names_handler(vector strvec)
{
char * buff;
@@ -2338,6 +2359,18 @@ snprint_def_flush_on_last_del (char * bu
}
static int
+snprint_def_find_multipaths (char * buff, int len, void * data)
+{
+ if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS)
+ return 0;
+ if (!conf->find_multipaths)
+ return snprintf(buff, len, "no");
+
+ return snprintf(buff, len, "yes");
+}
+
+
+static int
snprint_def_user_friendly_names (char * buff, int len, void * data)
{
if (!conf->user_friendly_names)
@@ -2428,6 +2461,7 @@ init_keywords(void)
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("bindings_file", &bindings_file_handler, &snprint_def_bindings_file);
+ install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
__deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
Index: multipath-tools-110713/libmultipath/file.c
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/file.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2005 Christophe Varoqui
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
+ */
+#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 <signal.h>
+
+#include "file.h"
+#include "debug.h"
+#include "uxsock.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 file pathname %s : %s",
+ str, 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 void
+sigalrm(int sig)
+{
+ /* do nothing */
+}
+
+static int
+lock_file(int fd, char *file_name)
+{
+ struct sigaction act, oldact;
+ sigset_t set, oldset;
+ struct flock lock;
+ int err;
+
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+
+ act.sa_handler = sigalrm;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+
+ sigaction(SIGALRM, &act, &oldact);
+ sigprocmask(SIG_UNBLOCK, &set, &oldset);
+
+ alarm(FILE_TIMEOUT);
+ err = fcntl(fd, F_SETLKW, &lock);
+ alarm(0);
+
+ if (err) {
+ if (errno != EINTR)
+ condlog(0, "Cannot lock %s : %s", file_name,
+ strerror(errno));
+ else
+ condlog(0, "%s is locked. Giving up.", file_name);
+ }
+
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ sigaction(SIGALRM, &oldact, NULL);
+ return err;
+}
+
+int
+open_file(char *file, int *can_write, char *header)
+{
+ int fd;
+ struct stat s;
+
+ if (ensure_directories_exist(file, 0700))
+ return -1;
+ *can_write = 1;
+ fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ if (errno == EROFS) {
+ *can_write = 0;
+ condlog(3, "Cannot open file [%s] read/write. "
+ " trying readonly", file);
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ condlog(0, "Cannot open file [%s] "
+ "readonly : %s", file, strerror(errno));
+ return -1;
+ }
+ }
+ else {
+ condlog(0, "Cannot open file [%s] : %s", file,
+ strerror(errno));
+ return -1;
+ }
+ }
+ if (*can_write && lock_file(fd, file) < 0)
+ goto fail;
+
+ memset(&s, 0, sizeof(s));
+ if (fstat(fd, &s) < 0){
+ condlog(0, "Cannot stat file %s : %s", file, strerror(errno));
+ goto fail;
+ }
+ if (s.st_size == 0) {
+ if (*can_write == 0)
+ goto fail;
+ /* If file is empty, write the header */
+ size_t len = strlen(header);
+ if (write_all(fd, header, len) != len) {
+ condlog(0,
+ "Cannot write header to file %s : %s", file,
+ strerror(errno));
+ /* cleanup partially written header */
+ ftruncate(fd, 0);
+ goto fail;
+ }
+ fsync(fd);
+ condlog(3, "Initialized new file [%s]", file);
+ }
+
+ return fd;
+
+fail:
+ close(fd);
+ return -1;
+}
Index: multipath-tools-110713/libmultipath/file.h
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/file.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+#ifndef _FILE_H
+#define _FILE_H
+
+#define FILE_TIMEOUT 30
+int open_file(char *file, int *can_write, char *header);
+
+#endif /* _FILE_H */
Index: multipath-tools-110713/libmultipath/finder.c
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/finder.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "checkers.h"
+#include "vector.h"
+#include "structs.h"
+#include "debug.h"
+#include "uxsock.h"
+#include "file.h"
+#include "finder.h"
+#include "defaults.h"
+
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+static int
+lookup_wwid(FILE *f, char *wwid) {
+ int c;
+ char buf[LINE_MAX];
+ int count;
+
+ while ((c = fgetc(f)) != EOF){
+ if (c != '/') {
+ if (fgets(buf, LINE_MAX, f) == NULL)
+ return 0;
+ else
+ continue;
+ }
+ count = 0;
+ while ((c = fgetc(f)) != '/') {
+ if (c == EOF)
+ return 0;
+ if (count >= WWID_SIZE - 1)
+ goto next;
+ if (wwid[count] == '\0')
+ goto next;
+ if (c != wwid[count++])
+ goto next;
+ }
+ if (wwid[count] == '\0')
+ return 1;
+next:
+ if (fgets(buf, LINE_MAX, f) == NULL)
+ return 0;
+ }
+ return 0;
+}
+
+static int
+write_out_wwid(int fd, char *wwid) {
+ int ret;
+ off_t offset;
+ char buf[WWID_SIZE + 3];
+
+ ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
+ if (ret >= (WWID_SIZE + 3) || ret < 0){
+ condlog(0, "can't format wwid for writing (%d) : %s",
+ ret, strerror(errno));
+ return -1;
+ }
+ offset = lseek(fd, 0, SEEK_END);
+ if (offset < 0) {
+ condlog(0, "can't seek to the end of wwids file : %s",
+ strerror(errno));
+ return -1;
+ }
+ if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
+ condlog(0, "cannot write wwid to wwids file : %s",
+ strerror(errno));
+ ftruncate(fd, offset);
+ return -1;
+ }
+ return 1;
+}
+
+static int
+check_wwids_file(char *wwid, int write_wwid)
+{
+ int scan_fd, fd, can_write, found, ret;
+ FILE *f;
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
+ if (fd < 0)
+ return -1;
+
+ scan_fd = dup(fd);
+ if (scan_fd < 0) {
+ condlog(0, "can't dup wwids file descriptor : %s",
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+ f = fdopen(scan_fd, "r");
+ if (!f) {
+ condlog(0,"can't fdopen wwids file : %s", strerror(errno));
+ close(fd);
+ close(scan_fd);
+ return -1;
+ }
+ found = lookup_wwid(f, wwid);
+ if (found) {
+ ret = 0;
+ goto out;
+ }
+ if (!write_wwid) {
+ ret = -1;
+ goto out;
+ }
+ if (!can_write) {
+ condlog(0, "wwids file is read-only. Can't write wwid");
+ ret = -1;
+ goto out;
+ }
+ ret = write_out_wwid(fd, wwid);
+out:
+ fclose(f);
+ close(scan_fd);
+ close(fd);
+ return ret;
+}
+
+int
+should_multipath(struct path *pp1, vector pathvec)
+{
+ int i;
+ struct path *pp2;
+
+ condlog(4, "checking if %s should be multipathed", pp1->dev);
+ vector_foreach_slot(pathvec, pp2, i) {
+ if (pp1->dev == pp2->dev)
+ continue;
+ if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
+ condlog(3, "found multiple paths with wwid %s, "
+ "multipathing %s", pp1->wwid, pp1->dev);
+ return 1;
+ }
+ }
+ if (check_wwids_file(pp1->wwid, 0) < 0) {
+ condlog(3, "wwid %s not in wwids file, skipping %s",
+ pp1->wwid, pp1->dev);
+ return 0;
+ }
+ condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid,
+ pp1->dev);
+ return 1;
+}
+
+int
+remember_wwid(char *wwid)
+{
+ int ret = check_wwids_file(wwid, 1);
+ if (ret < 0){
+ condlog(3, "failed writing wwid %s to wwids file", wwid);
+ return -1;
+ }
+ if (ret == 1)
+ condlog(3, "wrote wwid %s to wwids file", wwid);
+ else
+ condlog(4, "wwid %s already in wwids file", wwid);
+ return 0;
+}
Index: multipath-tools-110713/libmultipath/finder.h
===================================================================
--- /dev/null
+++ multipath-tools-110713/libmultipath/finder.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+#ifndef _FINDER_H
+#define _FINDER_H
+
+#define WWIDS_FILE_HEADER \
+"# Multipath wwids, Version : 1.0\n" \
+"# NOTE: This file is automatically maintained by multipath and multipathd.\n" \
+"# You should not need to edit this file in normal circumstances.\n" \
+"#\n" \
+"# Valid WWIDs:\n"
+
+int should_multipath(struct path *pp, vector pathvec);
+int remember_wwid(char *wwid);
+
+#endif /* _FINDER_H */
Index: multipath-tools-110713/multipath/main.c
===================================================================
--- multipath-tools-110713.orig/multipath/main.c
+++ multipath-tools-110713/multipath/main.c
@@ -313,7 +313,7 @@ configure (void)
/*
* core logic entry point
*/
- r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
+ r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload);
out:
if (refwwid)
Index: multipath-tools-110713/multipathd/main.c
===================================================================
--- multipath-tools-110713.orig/multipathd/main.c
+++ multipath-tools-110713/multipathd/main.c
@@ -47,6 +47,7 @@
#include <print.h>
#include <configure.h>
#include <prio.h>
+#include <finder.h>
#include <pgpolicies.h>
#include <uevent.h>
@@ -447,6 +448,11 @@ rescan:
return 1;
}
+ if (conf->find_multipaths &&
+ !should_multipath(pp, vecs->pathvec)) {
+ orphan_path(pp);
+ return 0;
+ }
condlog(4,"%s: creating new map", pp->dev);
if ((mpp = add_map_with_path(vecs, pp, 1))) {
mpp->action = ACT_CREATE;
Index: multipath-tools-110713/libmultipath/Makefile
===================================================================
--- multipath-tools-110713.orig/libmultipath/Makefile
+++ multipath-tools-110713/libmultipath/Makefile
@@ -15,7 +15,7 @@ OBJS = memory.o parser.o vector.o devmap
pgpolicies.o debug.o regex.o defaults.o uevent.o \
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
- lock.o waiter.o
+ lock.o waiter.o file.o finder.o
LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-09-01 2:55 ` [PATCH v2] " Benjamin Marzinski
@ 2011-09-01 7:14 ` Christophe Varoqui
2011-09-01 12:57 ` Benjamin Marzinski
0 siblings, 1 reply; 12+ messages in thread
From: Christophe Varoqui @ 2011-09-01 7:14 UTC (permalink / raw)
To: Hannes Reinecke; +Cc: device-mapper development
On mer., 2011-08-31 at 21:55 -0500, Benjamin Marzinski wrote:
> This adds a new default feature, find_multipaths. When this is set to yes,
> multipath will no longer try to create a multipath device for every
> non-blacklisted device. Instead, it will only create a device when one of
> three conditions are met.
>
> 1. Three are at least two non-blacklisted paths with the same wwid
> 2. The user manually forces the creation, by specifying a device with the
> multipath command.
> 3. A path has the same wwid as a multipath device that was previously crreated
> (even if that multipath device doesn't currently exist).
>
Hannes,
this patch implements complex semantics and mis-use /etc to store
variable data (/run was suggested as a replacement). Though I realize
the benefits, I'm not at ease merging it.
Mike Snitzer pushed for its inclusion, but I don't remember your
commenting. Would your care to ?
Regards,
--
Christophe Varoqui
OpenSVC - Tools to scale
http://www.opensvc.com/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-09-01 7:14 ` Christophe Varoqui
@ 2011-09-01 12:57 ` Benjamin Marzinski
2011-09-01 14:21 ` Benjamin Marzinski
2011-09-01 14:35 ` Hannes Reinecke
0 siblings, 2 replies; 12+ messages in thread
From: Benjamin Marzinski @ 2011-09-01 12:57 UTC (permalink / raw)
To: christophe.varoqui, device-mapper development
On Thu, Sep 01, 2011 at 09:14:23AM +0200, Christophe Varoqui wrote:
> On mer., 2011-08-31 at 21:55 -0500, Benjamin Marzinski wrote:
> > This adds a new default feature, find_multipaths. When this is set to yes,
> > multipath will no longer try to create a multipath device for every
> > non-blacklisted device. Instead, it will only create a device when one of
> > three conditions are met.
> >
> > 1. Three are at least two non-blacklisted paths with the same wwid
> > 2. The user manually forces the creation, by specifying a device with the
> > multipath command.
> > 3. A path has the same wwid as a multipath device that was previously crreated
> > (even if that multipath device doesn't currently exist).
> >
> Hannes,
>
> this patch implements complex semantics and mis-use /etc to store
> variable data (/run was suggested as a replacement). Though I realize
> the benefits, I'm not at ease merging it.
This will add wwids to the wwids file at the same times that new bindings
get added to the bindings file. We decided to move the bindings file to
/etc/multipath/bindings because it caused problems during bootup, if
/var/run was not mounted. This will have the same problems where you
will be writing to a file that eventually gets mounted over. So I am
against using /var/run
-Ben
>
> Mike Snitzer pushed for its inclusion, but I don't remember your
> commenting. Would your care to ?
>
> Regards,
>
> --
> Christophe Varoqui
> OpenSVC - Tools to scale
> http://www.opensvc.com/
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-09-01 12:57 ` Benjamin Marzinski
@ 2011-09-01 14:21 ` Benjamin Marzinski
2011-09-01 20:43 ` Benjamin Marzinski
2011-09-01 14:35 ` Hannes Reinecke
1 sibling, 1 reply; 12+ messages in thread
From: Benjamin Marzinski @ 2011-09-01 14:21 UTC (permalink / raw)
To: christophe.varoqui, device-mapper development
On Thu, Sep 01, 2011 at 07:57:20AM -0500, Benjamin Marzinski wrote:
> On Thu, Sep 01, 2011 at 09:14:23AM +0200, Christophe Varoqui wrote:
> > On mer., 2011-08-31 at 21:55 -0500, Benjamin Marzinski wrote:
> > > This adds a new default feature, find_multipaths. When this is set to yes,
> > > multipath will no longer try to create a multipath device for every
> > > non-blacklisted device. Instead, it will only create a device when one of
> > > three conditions are met.
> > >
> > > 1. Three are at least two non-blacklisted paths with the same wwid
> > > 2. The user manually forces the creation, by specifying a device with the
> > > multipath command.
> > > 3. A path has the same wwid as a multipath device that was previously crreated
> > > (even if that multipath device doesn't currently exist).
> > >
> > Hannes,
> >
> > this patch implements complex semantics and mis-use /etc to store
> > variable data (/run was suggested as a replacement). Though I realize
> > the benefits, I'm not at ease merging it.
>
> This will add wwids to the wwids file at the same times that new bindings
> get added to the bindings file. We decided to move the bindings file to
> /etc/multipath/bindings because it caused problems during bootup, if
> /var/run was not mounted. This will have the same problems where you
> will be writing to a file that eventually gets mounted over. So I am
> against using /var/run
although it looks like the systemd folks have made /run a tmpfs
filesystem, and /var/run a pointer to it (at least in Fedora), so I
guess I'm not opposed to moving things back to /var/run anymore.
-Ben
>
> -Ben
>
> >
> > Mike Snitzer pushed for its inclusion, but I don't remember your
> > commenting. Would your care to ?
> >
> > Regards,
> >
> > --
> > Christophe Varoqui
> > OpenSVC - Tools to scale
> > http://www.opensvc.com/
> >
> > --
> > dm-devel mailing list
> > dm-devel@redhat.com
> > https://www.redhat.com/mailman/listinfo/dm-devel
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-09-01 14:21 ` Benjamin Marzinski
@ 2011-09-01 20:43 ` Benjamin Marzinski
0 siblings, 0 replies; 12+ messages in thread
From: Benjamin Marzinski @ 2011-09-01 20:43 UTC (permalink / raw)
To: christophe.varoqui, device-mapper development
On Thu, Sep 01, 2011 at 09:21:06AM -0500, Benjamin Marzinski wrote:
>
> although it looks like the systemd folks have made /run a tmpfs
> filesystem, and /var/run a pointer to it (at least in Fedora), so I
> guess I'm not opposed to moving things back to /var/run anymore.
>
When I wrote this, I had just finished writing an email about how
/var/run being on tmpfs made it o.k. for pidfiles, and my brain had
obviously not switched gears. While I have no problem with pidfiles on
/var/run, storing permanent configuration files on it is obviously not
an option if it is a tmpfs filesystem.
-Ben
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-09-01 12:57 ` Benjamin Marzinski
2011-09-01 14:21 ` Benjamin Marzinski
@ 2011-09-01 14:35 ` Hannes Reinecke
2011-09-01 18:54 ` Benjamin Marzinski
1 sibling, 1 reply; 12+ messages in thread
From: Hannes Reinecke @ 2011-09-01 14:35 UTC (permalink / raw)
To: Benjamin Marzinski; +Cc: device-mapper development
On 09/01/2011 02:57 PM, Benjamin Marzinski wrote:
> On Thu, Sep 01, 2011 at 09:14:23AM +0200, Christophe Varoqui wrote:
>> On mer., 2011-08-31 at 21:55 -0500, Benjamin Marzinski wrote:
>>> This adds a new default feature, find_multipaths. When this is set to yes,
>>> multipath will no longer try to create a multipath device for every
>>> non-blacklisted device. Instead, it will only create a device when one of
>>> three conditions are met.
>>>
>>> 1. Three are at least two non-blacklisted paths with the same wwid
>>> 2. The user manually forces the creation, by specifying a device with the
>>> multipath command.
>>> 3. A path has the same wwid as a multipath device that was previously crreated
>>> (even if that multipath device doesn't currently exist).
>>>
>> Hannes,
>>
>> this patch implements complex semantics and mis-use /etc to store
>> variable data (/run was suggested as a replacement). Though I realize
>> the benefits, I'm not at ease merging it.
>
> This will add wwids to the wwids file at the same times that new bindings
> get added to the bindings file. We decided to move the bindings file to
> /etc/multipath/bindings because it caused problems during bootup, if
> /var/run was not mounted. This will have the same problems where you
> will be writing to a file that eventually gets mounted over. So I am
> against using /var/run
>
I already did a patch to allow for a different location for the
bindings file (methinks it's upstream, isn't it?)
But that's not the issue.
The issue here is an inversion in behaviour.
Normally multipath would access / manage all devices except those
blacklisted in /etc/multipath.conf
With the patch multipath would access / manage _no_ devices except
those listed in /etc/multipath.conf
Which is the main point of contention.
So as such I'm not happy with this, too.
However, we definitely need to figure out how integrate with systemd.
From my understanding we need to have some 'trigger', telling
systemd to ignore any disks multipath might hook onto.
Sure, the find_multipaths feature would be a possible solution here,
as then systemd could evaluate the config file any everything would
be dandy.
However, I would prefer to modify 'multipath' (which is in the
process on becoming obsoleted currently). This could program could
then be used to provide systemd with the required information, ie if
a device should be ignored or not.
Cheers,
Hannes
--
Dr. Hannes Reinecke zSeries & Storage
hare@suse.de +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] multipath: add find_multipaths feature.
2011-09-01 14:35 ` Hannes Reinecke
@ 2011-09-01 18:54 ` Benjamin Marzinski
0 siblings, 0 replies; 12+ messages in thread
From: Benjamin Marzinski @ 2011-09-01 18:54 UTC (permalink / raw)
To: Hannes Reinecke; +Cc: device-mapper development
On Thu, Sep 01, 2011 at 04:35:16PM +0200, Hannes Reinecke wrote:
> I already did a patch to allow for a different location for the bindings
> file (methinks it's upstream, isn't it?)
It is.
> The issue here is an inversion in behaviour.
> Normally multipath would access / manage all devices except those
> blacklisted in /etc/multipath.conf
> With the patch multipath would access / manage _no_ devices except those
> listed in /etc/multipath.conf
Or any devices that have two paths to them. Or devices that have, in the
past, had two paths to them. The idea behind this was to make multipath
"just work", without users needing to bother touching
/etc/multipath.conf at all, for common storage arrays.
multipathd will find all the devices with multiple paths (except the
blacklisted ones), and remember them so that in the future, as soon as
the first path becomes available, multipathd knows that it should be
multipathed. Blacklisting works just as before. The only difference is
that you no longer need to use the blacklist to keep multipath from
grabbing devices that don't have multiple paths. You only use it if you
have multiple paths, but for some reason you don't want to have
multipath manage them.
For devices with only one path, the user will need to specifically add
them. But if the user want's to use multipath on single path devices,
then just don't turn on find_multipaths.
So I'm not sure I understand your objection.
> However, we definitely need to figure out how integrate with systemd.
> From my understanding we need to have some 'trigger', telling systemd to
> ignore any disks multipath might hook onto.
With the wwids file, it's simple to be able to tell if a disk belongs to
multipath after multipath has already been setup on it once. The only
issue is on the first time the disk is seen. With find_multipaths this
is problem, since multipath won't know until it sees a second path to
the disk if it should be multipathed. Without find_multipaths, we could
just assume that if the device is not blacklisted, it belongs to
multipath.
-Ben
> Sure, the find_multipaths feature would be a possible solution here, as
> then systemd could evaluate the config file any everything would be dandy.
>
> However, I would prefer to modify 'multipath' (which is in the process on
> becoming obsoleted currently). This could program could then be used to
> provide systemd with the required information, ie if a device should be
> ignored or not.
>
> Cheers,
>
> Hannes
> --
> Dr. Hannes Reinecke zSeries & Storage
> hare@suse.de +49 911 74053 688
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
> GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] multipath: add find_multipaths feature.
@ 2010-11-16 23:25 Benjamin Marzinski
2010-11-16 23:51 ` Christophe Varoqui
2010-12-07 23:00 ` Christophe Varoqui
0 siblings, 2 replies; 12+ messages in thread
From: Benjamin Marzinski @ 2010-11-16 23:25 UTC (permalink / raw)
To: device-mapper development
This adds a new default feature, find_multipaths. When this is set to yes,
multipath will no longer try to create multipath devices using every
non-blacklisted device. Instead, it will only create a device when one of
three conditions are met.
1. Three are at least two non-blacklisted paths with the same wwid
2. The user manually forces the creation, by specifying a device with the
multipath command.
3. A path has the same wwid as a multipath device that was previously crreated
(even if that multipath device doesn't currently exist).
To do 3, multipath stores the wwid of every path that it creates in
/etc/multipath/wwids. Whenever a path is added, its wwid is checked against
this file. If there's a match, it is multipathed, even if it's the only path.
This should allow multipath to automatically choose the correct paths to make
into multipath devics in most cases, without needing the user to edit the
blacklist.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/Makefile | 2
libmultipath/alias.c | 152 --------------------------------------
libmultipath/alias.h | 1
libmultipath/config.c | 1
libmultipath/config.h | 1
libmultipath/configure.c | 14 +++
libmultipath/defaults.h | 2
libmultipath/dict.c | 34 ++++++++
libmultipath/file.c | 178 +++++++++++++++++++++++++++++++++++++++++++++
libmultipath/file.h | 11 ++
libmultipath/finder.c | 165 +++++++++++++++++++++++++++++++++++++++++
libmultipath/finder.h | 18 ++++
multipath/main.c | 4 -
multipath/multipath.conf.5 | 19 ++++
multipathd/main.c | 6 +
15 files changed, 456 insertions(+), 152 deletions(-)
Index: multipath-tools-101104/libmultipath/alias.c
===================================================================
--- multipath-tools-101104.orig/libmultipath/alias.c
+++ multipath-tools-101104/libmultipath/alias.c
@@ -3,19 +3,16 @@
* Copyright (c) 2005 Benjamin Marzinski, Redhat
*/
#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 <signal.h>
#include "debug.h"
#include "uxsock.h"
#include "alias.h"
+#include "file.h"
/*
@@ -37,149 +34,6 @@
*/
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 void
-sigalrm(int sig)
-{
- /* do nothing */
-}
-
-static int
-lock_bindings_file(int fd)
-{
- struct sigaction act, oldact;
- sigset_t set, oldset;
- struct flock lock;
- int err;
-
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
-
- act.sa_handler = sigalrm;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- sigemptyset(&set);
- sigaddset(&set, SIGALRM);
-
- sigaction(SIGALRM, &act, &oldact);
- sigprocmask(SIG_UNBLOCK, &set, &oldset);
-
- alarm(BINDINGS_FILE_TIMEOUT);
- err = fcntl(fd, F_SETLKW, &lock);
- alarm(0);
-
- if (err) {
- if (errno != EINTR)
- condlog(0, "Cannot lock bindings file : %s",
- strerror(errno));
- else
- condlog(0, "Bindings file is locked. Giving up.");
- }
-
- sigprocmask(SIG_SETMASK, &oldset, NULL);
- sigaction(SIGALRM, &oldact, NULL);
- return err;
-
-}
-
-
-static int
-open_bindings_file(char *file, int *can_write)
-{
- int fd;
- struct stat s;
-
- if (ensure_directories_exist(file, 0700))
- return -1;
- *can_write = 1;
- fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
- if (fd < 0) {
- if (errno == EROFS) {
- *can_write = 0;
- condlog(3, "Cannot open bindings file [%s] read/write. "
- " trying readonly", file);
- fd = open(file, O_RDONLY);
- if (fd < 0) {
- condlog(0, "Cannot open bindings file [%s] "
- "readonly : %s", file, strerror(errno));
- return -1;
- }
- }
- else {
- condlog(0, "Cannot open bindings file [%s] : %s", file,
- strerror(errno));
- return -1;
- }
- }
- if (*can_write && 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 (*can_write == 0)
- goto fail;
- /* 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
format_devname(char *name, int id, int len, char *prefix)
{
int pos;
@@ -366,7 +220,7 @@ get_user_friendly_alias(char *wwid, char
return NULL;
}
- fd = open_bindings_file(file, &can_write);
+ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
if (fd < 0)
return NULL;
@@ -416,7 +270,7 @@ get_user_friendly_wwid(char *alias, char
return NULL;
}
- fd = open_bindings_file(file, &unused);
+ fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
if (fd < 0)
return NULL;
Index: multipath-tools-101104/libmultipath/alias.h
===================================================================
--- multipath-tools-101104.orig/libmultipath/alias.h
+++ multipath-tools-101104/libmultipath/alias.h
@@ -1,4 +1,3 @@
-#define BINDINGS_FILE_TIMEOUT 30
#define BINDINGS_FILE_HEADER \
"# Multipath bindings, Version : 1.0\n" \
"# NOTE: this file is automatically maintained by the multipath program.\n" \
Index: multipath-tools-101104/libmultipath/config.c
===================================================================
--- multipath-tools-101104.orig/libmultipath/config.c
+++ multipath-tools-101104/libmultipath/config.c
@@ -462,6 +462,7 @@ load_config (char * file)
conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
conf->flush_on_last_del = 0;
conf->attribute_flags = 0;
+ conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
/*
* preload default hwtable
Index: multipath-tools-101104/libmultipath/config.h
===================================================================
--- multipath-tools-101104.orig/libmultipath/config.h
+++ multipath-tools-101104/libmultipath/config.h
@@ -84,6 +84,7 @@ struct config {
int attribute_flags;
int fast_io_fail;
unsigned int dev_loss;
+ int find_multipaths;
uid_t uid;
gid_t gid;
mode_t mode;
Index: multipath-tools-101104/libmultipath/configure.c
===================================================================
--- multipath-tools-101104.orig/libmultipath/configure.c
+++ multipath-tools-101104/libmultipath/configure.c
@@ -35,6 +35,7 @@
#include "alias.h"
#include "prio.h"
#include "util.h"
+#include "finder.h"
extern int
setup_map (struct multipath * mpp)
@@ -403,6 +404,8 @@ domap (struct multipath * mpp)
* DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
* succeeded
*/
+ if (mpp->action == ACT_CREATE)
+ remember_wwid(mpp->wwid);
if (!conf->daemon) {
/* multipath client mode */
dm_switchgroup(mpp->alias, mpp->bestpg);
@@ -462,6 +465,10 @@ coalesce_paths (struct vectors * vecs, v
memset(empty_buff, 0, WWID_SIZE);
+ /* ignore refwwid if it's empty */
+ if (refwwid && !strlen(refwwid))
+ refwwid = NULL;
+
if (force_reload) {
vector_foreach_slot (pathvec, pp1, k) {
pp1->mpp = NULL;
@@ -491,6 +498,13 @@ coalesce_paths (struct vectors * vecs, v
if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
continue;
+ /* If find_multipaths was selected check if the path is valid */
+ if (conf->find_multipaths && !refwwid &&
+ !should_multipath(pp1, pathvec)){
+ orphan_path(pp1);
+ continue;
+ }
+
/*
* at this point, we know we really got a new mp
*/
Index: multipath-tools-101104/libmultipath/defaults.h
===================================================================
--- multipath-tools-101104.orig/libmultipath/defaults.h
+++ multipath-tools-101104/libmultipath/defaults.h
@@ -13,6 +13,7 @@
#define DEFAULT_PGTIMEOUT -PGTIMEOUT_NONE
#define DEFAULT_USER_FRIENDLY_NAMES 0
#define DEFAULT_VERBOSITY 2
+#define DEFAULT_FIND_MULTIPATHS 0
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
@@ -21,5 +22,6 @@
#define DEFAULT_SOCKET "/var/run/multipathd.sock"
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
#define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
+#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
char * set_default (char * str);
Index: multipath-tools-101104/libmultipath/dict.c
===================================================================
--- multipath-tools-101104.orig/libmultipath/dict.c
+++ multipath-tools-101104/libmultipath/dict.c
@@ -454,6 +454,27 @@ def_flush_on_last_del_handler(vector str
}
static int
+def_find_multipaths_handler(vector strvec)
+{
+ char * buff;
+
+ buff = set_value(strvec);
+
+ if (!buff)
+ return 1;
+
+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "0")))
+ conf->find_multipaths = 0;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+ conf->find_multipaths = 1;
+
+ FREE(buff);
+ return 0;
+}
+
+static int
names_handler(vector strvec)
{
char * buff;
@@ -2105,6 +2126,18 @@ snprint_def_flush_on_last_del (char * bu
}
static int
+snprint_def_find_multipaths (char * buff, int len, void * data)
+{
+ if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS)
+ return 0;
+ if (!conf->find_multipaths)
+ return snprintf(buff, len, "no");
+
+ return snprintf(buff, len, "yes");
+}
+
+
+static int
snprint_def_user_friendly_names (char * buff, int len, void * data)
{
if (conf->user_friendly_names == DEFAULT_USER_FRIENDLY_NAMES)
@@ -2182,6 +2215,7 @@ init_keywords(void)
install_keyword("gid", &def_gid_handler, &snprint_def_gid);
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("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
__deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
Index: multipath-tools-101104/libmultipath/file.c
===================================================================
--- /dev/null
+++ multipath-tools-101104/libmultipath/file.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2005 Christophe Varoqui
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
+ */
+#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 <signal.h>
+
+#include "file.h"
+#include "debug.h"
+#include "uxsock.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 file pathname %s : %s",
+ str, 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 void
+sigalrm(int sig)
+{
+ /* do nothing */
+}
+
+static int
+lock_file(int fd, char *file_name)
+{
+ struct sigaction act, oldact;
+ sigset_t set, oldset;
+ struct flock lock;
+ int err;
+
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+
+ act.sa_handler = sigalrm;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+
+ sigaction(SIGALRM, &act, &oldact);
+ sigprocmask(SIG_UNBLOCK, &set, &oldset);
+
+ alarm(FILE_TIMEOUT);
+ err = fcntl(fd, F_SETLKW, &lock);
+ alarm(0);
+
+ if (err) {
+ if (errno != EINTR)
+ condlog(0, "Cannot lock %s : %s", file_name,
+ strerror(errno));
+ else
+ condlog(0, "%s is locked. Giving up.", file_name);
+ }
+
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ sigaction(SIGALRM, &oldact, NULL);
+ return err;
+}
+
+int
+open_file(char *file, int *can_write, char *header)
+{
+ int fd;
+ struct stat s;
+
+ if (ensure_directories_exist(file, 0700))
+ return -1;
+ *can_write = 1;
+ fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ if (errno == EROFS) {
+ *can_write = 0;
+ condlog(3, "Cannot open file [%s] read/write. "
+ " trying readonly", file);
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ condlog(0, "Cannot open file [%s] "
+ "readonly : %s", file, strerror(errno));
+ return -1;
+ }
+ }
+ else {
+ condlog(0, "Cannot open file [%s] : %s", file,
+ strerror(errno));
+ return -1;
+ }
+ }
+ if (*can_write && lock_file(fd, file) < 0)
+ goto fail;
+
+ memset(&s, 0, sizeof(s));
+ if (fstat(fd, &s) < 0){
+ condlog(0, "Cannot stat file %s : %s", file, strerror(errno));
+ goto fail;
+ }
+ if (s.st_size == 0) {
+ if (*can_write == 0)
+ goto fail;
+ /* If file is empty, write the header */
+ size_t len = strlen(header);
+ if (write_all(fd, header, len) != len) {
+ condlog(0,
+ "Cannot write header to file %s : %s", file,
+ strerror(errno));
+ /* cleanup partially written header */
+ ftruncate(fd, 0);
+ goto fail;
+ }
+ fsync(fd);
+ condlog(3, "Initialized new file [%s]", file);
+ }
+
+ return fd;
+
+fail:
+ close(fd);
+ return -1;
+}
Index: multipath-tools-101104/libmultipath/file.h
===================================================================
--- /dev/null
+++ multipath-tools-101104/libmultipath/file.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+#ifndef _FILE_H
+#define _FILE_H
+
+#define FILE_TIMEOUT 30
+int open_file(char *file, int *can_write, char *header);
+
+#endif /* _FILE_H */
Index: multipath-tools-101104/libmultipath/finder.c
===================================================================
--- /dev/null
+++ multipath-tools-101104/libmultipath/finder.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+#include "checkers.h"
+#include "vector.h"
+#include "structs.h"
+#include "debug.h"
+#include "uxsock.h"
+#include "file.h"
+#include "finder.h"
+#include "defaults.h"
+
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+static int
+lookup_wwid(FILE *f, char *wwid) {
+ int c;
+ char buf[LINE_MAX];
+ int count;
+
+ while ((c = fgetc(f)) != EOF){
+ if (c != '/') {
+ if (fgets(buf, LINE_MAX, f) == NULL)
+ return 0;
+ else
+ continue;
+ }
+ count = 0;
+ while ((c = fgetc(f)) != '/') {
+ if (c == EOF)
+ return 0;
+ if (count >= WWID_SIZE - 1)
+ goto next;
+ if (wwid[count] == '\0')
+ goto next;
+ if (c != wwid[count++])
+ goto next;
+ }
+ if (wwid[count] == '\0')
+ return 1;
+next:
+ if (fgets(buf, LINE_MAX, f) == NULL)
+ return 0;
+ }
+ return 0;
+}
+
+static int
+write_out_wwid(int fd, char *wwid) {
+ int ret;
+ off_t offset;
+ char buf[WWID_SIZE + 3];
+
+ ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
+ if (ret >= (WWID_SIZE + 3) || ret < 0){
+ condlog(0, "can't format wwid for writing (%d) : %s",
+ ret, strerror(errno));
+ return -1;
+ }
+ offset = lseek(fd, 0, SEEK_END);
+ if (offset < 0) {
+ condlog(0, "can't seek to the end of wwids file : %s",
+ strerror(errno));
+ return -1;
+ }
+ if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
+ condlog(0, "cannot write wwid to wwids file : %s",
+ strerror(errno));
+ ftruncate(fd, offset);
+ return -1;
+ }
+ return 1;
+}
+
+static int
+check_wwids_file(char *wwid, int write_wwid)
+{
+ int scan_fd, fd, can_write, found, ret;
+ FILE *f;
+ fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
+ if (fd < 0)
+ return -1;
+
+ scan_fd = dup(fd);
+ if (scan_fd < 0) {
+ condlog(0, "can't dup wwids file descriptor : %s",
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+ f = fdopen(scan_fd, "r");
+ if (!f) {
+ condlog(0,"can't fdopen wwids file : %s", strerror(errno));
+ close(fd);
+ close(scan_fd);
+ return -1;
+ }
+ found = lookup_wwid(f, wwid);
+ if (found) {
+ ret = 0;
+ goto out;
+ }
+ if (!write_wwid) {
+ ret = -1;
+ goto out;
+ }
+ if (!can_write) {
+ condlog(0, "wwids file is read-only. Can't write wwid");
+ ret = -1;
+ goto out;
+ }
+ ret = write_out_wwid(fd, wwid);
+out:
+ fclose(f);
+ close(scan_fd);
+ close(fd);
+ return ret;
+}
+
+int
+should_multipath(struct path *pp1, vector pathvec)
+{
+ int i;
+ struct path *pp2;
+
+ condlog(4, "checking if %s should be multipathed", pp1->dev);
+ vector_foreach_slot(pathvec, pp2, i) {
+ if (pp1->dev == pp2->dev)
+ continue;
+ if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
+ condlog(3, "found multiple paths with wwid %s, "
+ "multipathing %s", pp1->wwid, pp1->dev);
+ return 1;
+ }
+ }
+ if (check_wwids_file(pp1->wwid, 0) < 0) {
+ condlog(3, "wwid %s not in wwids file, skipping %s",
+ pp1->wwid, pp1->dev);
+ return 0;
+ }
+ condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid,
+ pp1->dev);
+ return 1;
+}
+
+int
+remember_wwid(char *wwid)
+{
+ int ret = check_wwids_file(wwid, 1);
+ if (ret < 0){
+ condlog(3, "failed writing wwid %s to wwids file", wwid);
+ return -1;
+ }
+ if (ret == 1)
+ condlog(3, "wrote wwid %s to wwids file", wwid);
+ else
+ condlog(4, "wwid %s already in wwids file", wwid);
+ return 0;
+}
Index: multipath-tools-101104/libmultipath/finder.h
===================================================================
--- /dev/null
+++ multipath-tools-101104/libmultipath/finder.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Benjamin Marzinski, Redhat
+ */
+
+#ifndef _FINDER_H
+#define _FINDER_H
+
+#define WWIDS_FILE_HEADER \
+"# Multipath wwids, Version : 1.0\n" \
+"# NOTE: This file is automatically maintained by multipath and multipathd.\n" \
+"# You should not need to edit this file in normal circumstances.\n" \
+"#\n" \
+"# Valid WWIDs:\n"
+
+int should_multipath(struct path *pp, vector pathvec);
+int remember_wwid(char *wwid);
+
+#endif /* _FINDER_H */
Index: multipath-tools-101104/multipath/main.c
===================================================================
--- multipath-tools-101104.orig/multipath/main.c
+++ multipath-tools-101104/multipath/main.c
@@ -51,6 +51,7 @@
#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <finder.h>
int logsink;
@@ -200,6 +201,7 @@ get_dm_mpvec (vector curmp, vector pathv
if (!conf->dry_run)
reinstate_paths(mpp);
+ remember_wwid(mpp->wwid);
}
return 0;
}
@@ -307,7 +309,7 @@ configure (void)
/*
* core logic entry point
*/
- r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
+ r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload);
out:
if (refwwid)
Index: multipath-tools-101104/multipathd/main.c
===================================================================
--- multipath-tools-101104.orig/multipathd/main.c
+++ multipath-tools-101104/multipathd/main.c
@@ -48,6 +48,7 @@
#include <configure.h>
#include <prio.h>
#include <pgpolicies.h>
+#include <finder.h>
#include "main.h"
#include "pidfile.h"
@@ -425,6 +426,11 @@ rescan:
mpp->action = ACT_RELOAD;
}
else {
+ if (conf->find_multipaths &&
+ !should_multipath(pp, vecs->pathvec)) {
+ orphan_path(pp);
+ return 0;
+ }
if (!pp->size) {
condlog(0, "%s: failed to create new map,"
" %s device size is 0 ", devname, pp->dev);
Index: multipath-tools-101104/libmultipath/Makefile
===================================================================
--- multipath-tools-101104.orig/libmultipath/Makefile
+++ multipath-tools-101104/libmultipath/Makefile
@@ -15,7 +15,7 @@ OBJS = memory.o parser.o vector.o devmap
pgpolicies.o debug.o regex.o defaults.o uevent.o \
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
- lock.o waiter.o
+ lock.o waiter.o file.o finder.o
LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
Index: multipath-tools-101104/multipath/multipath.conf.5
===================================================================
--- multipath-tools-101104.orig/multipath/multipath.conf.5
+++ multipath-tools-101104/multipath/multipath.conf.5
@@ -77,6 +77,25 @@ default is
directory where udev creates its device nodes; default is
.I /dev
.TP
+.B find_multipaths
+If set to
+.I yes
+, instead of trying to create a multipath device for every non-blacklisted
+path, multipath will only create a device if one of three condidions are
+met.
+.I 1
+There are at least two non-blacklisted paths with the same wwid,
+.I 2
+the user manually forces the creation, by specifying a device with the multipath
+command, or
+.I 3
+a path has the same WWID as a multipath device that was previously created
+(even if that multipath device doesn't currently exist).
+Whenever a multipath device is created, multipath will remeber the WWID of the
+device, so that it will automatically create the device again, as soon as it
+sees a path with that WWID. This should allow most users to have multipath automatically choose the correct paths to make intousers to have multipath automatically choose the correct paths to make into multipath devices, without having to edit the blacklist; Default is
+.I no
+.TP
.B verbosity
default verbosity. Higher values increase the verbosity level. Valid
levels are between 0 and 6; default is
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] multipath: add find_multipaths feature.
2010-11-16 23:25 [PATCH] " Benjamin Marzinski
@ 2010-11-16 23:51 ` Christophe Varoqui
2010-11-18 17:21 ` Benjamin Marzinski
2010-12-07 23:00 ` Christophe Varoqui
1 sibling, 1 reply; 12+ messages in thread
From: Christophe Varoqui @ 2010-11-16 23:51 UTC (permalink / raw)
To: device-mapper development
On mar., 2010-11-16 at 17:25 -0600, Benjamin Marzinski wrote:
> This adds a new default feature, find_multipaths. When this is set to yes,
> multipath will no longer try to create multipath devices using every
> non-blacklisted device. Instead, it will only create a device when one of
> three conditions are met.
>
> 1. Three are at least two non-blacklisted paths with the same wwid
> 2. The user manually forces the creation, by specifying a device with the
> multipath command.
> 3. A path has the same wwid as a multipath device that was previously crreated
> (even if that multipath device doesn't currently exist).
I'm confused. A blacklist/whitelist system may be hard to configure
properly but the rules are simple. I fear this new rule set will
increase confusion.
Could you elaborate on what problems this new rule set is trying to
address ?
Best regards,
--
Christophe Varoqui <christophe.varoqui@opensvc.com>
OpenSVC
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] multipath: add find_multipaths feature.
2010-11-16 23:51 ` Christophe Varoqui
@ 2010-11-18 17:21 ` Benjamin Marzinski
0 siblings, 0 replies; 12+ messages in thread
From: Benjamin Marzinski @ 2010-11-18 17:21 UTC (permalink / raw)
To: christophe.varoqui, device-mapper development
On Wed, Nov 17, 2010 at 12:51:15AM +0100, Christophe Varoqui wrote:
> On mar., 2010-11-16 at 17:25 -0600, Benjamin Marzinski wrote:
> > This adds a new default feature, find_multipaths. When this is set to yes,
> > multipath will no longer try to create multipath devices using every
> > non-blacklisted device. Instead, it will only create a device when one of
> > three conditions are met.
> >
> > 1. Three are at least two non-blacklisted paths with the same wwid
> > 2. The user manually forces the creation, by specifying a device with the
> > multipath command.
> > 3. A path has the same wwid as a multipath device that was previously crreated
> > (even if that multipath device doesn't currently exist).
>
> I'm confused. A blacklist/whitelist system may be hard to configure
> properly but the rules are simple. I fear this new rule set will
> increase confusion.
>
> Could you elaborate on what problems this new rule set is trying to
> address ?
The request was to have multipath do the right thing by default for the
common setups, without needing anyone to edit the config file by hand
(which is frequently done wrong). In this case, if you have a
multipath.conf file that just sets find_multipaths, multipath will
automatically create multipath devices for all the LUNs that have
multiple paths, and (assuming they use the right storage devices)
autoconfigure them correctly. Users only need to use the blacklist if
they have a LUN with multiple paths to it, but don't want in multipathed
for some reason.
Condition 1 takes care of the common case, where multipath notices that
two devices are just paths to the same LUN, and creates a multipath
device.
Condition 2 is mostly for testing.
Condition 3 means that after a multipath device has been created once, in
the future, it will be created right away, even if only one path is
currently active.
There's an added benefit in keeping the list of multipathed wwids. I'll
shortly be sending a patch that adds a multipath option to check if a
path belongs to a multipath device, which it does by checking this file.
This allows things like udev to find out as soon as a path appears that
it will be multipathed, which lets us avoid races where something else
opens the device before multipathd can.
-Ben
>
> Best regards,
> --
> Christophe Varoqui <christophe.varoqui@opensvc.com>
> OpenSVC
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] multipath: add find_multipaths feature.
2010-11-16 23:25 [PATCH] " Benjamin Marzinski
2010-11-16 23:51 ` Christophe Varoqui
@ 2010-12-07 23:00 ` Christophe Varoqui
1 sibling, 0 replies; 12+ messages in thread
From: Christophe Varoqui @ 2010-12-07 23:00 UTC (permalink / raw)
To: device-mapper development
On mar., 2010-11-16 at 17:25 -0600, Benjamin Marzinski wrote:
> This adds a new default feature, find_multipaths. When this is set to yes,
> multipath will no longer try to create multipath devices using every
> non-blacklisted device. Instead, it will only create a device when one of
> three conditions are met.
>
> 1. Three are at least two non-blacklisted paths with the same wwid
> 2. The user manually forces the creation, by specifying a device with the
> multipath command.
> 3. A path has the same wwid as a multipath device that was previously crreated
> (even if that multipath device doesn't currently exist).
>
> To do 3, multipath stores the wwid of every path that it creates in
> /etc/multipath/wwids. Whenever a path is added, its wwid is checked against
> this file. If there's a match, it is multipathed, even if it's the only path.
> This should allow multipath to automatically choose the correct paths to make
> into multipath devics in most cases, without needing the user to edit the
> blacklist.
>
Hi Ben,
I just merged the patches you queued for upstream the last weeks, except
this one. I'm still not convinced, but that may be because I have not
understood yet. I'll try and give it more brain.
Thanks,
cvaroqui
> Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
> ---
> libmultipath/Makefile | 2
> libmultipath/alias.c | 152 --------------------------------------
> libmultipath/alias.h | 1
> libmultipath/config.c | 1
> libmultipath/config.h | 1
> libmultipath/configure.c | 14 +++
> libmultipath/defaults.h | 2
> libmultipath/dict.c | 34 ++++++++
> libmultipath/file.c | 178 +++++++++++++++++++++++++++++++++++++++++++++
> libmultipath/file.h | 11 ++
> libmultipath/finder.c | 165 +++++++++++++++++++++++++++++++++++++++++
> libmultipath/finder.h | 18 ++++
> multipath/main.c | 4 -
> multipath/multipath.conf.5 | 19 ++++
> multipathd/main.c | 6 +
> 15 files changed, 456 insertions(+), 152 deletions(-)
>
> Index: multipath-tools-101104/libmultipath/alias.c
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/alias.c
> +++ multipath-tools-101104/libmultipath/alias.c
> @@ -3,19 +3,16 @@
> * Copyright (c) 2005 Benjamin Marzinski, Redhat
> */
> #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 <signal.h>
>
> #include "debug.h"
> #include "uxsock.h"
> #include "alias.h"
> +#include "file.h"
>
>
> /*
> @@ -37,149 +34,6 @@
> */
>
> 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 void
> -sigalrm(int sig)
> -{
> - /* do nothing */
> -}
> -
> -static int
> -lock_bindings_file(int fd)
> -{
> - struct sigaction act, oldact;
> - sigset_t set, oldset;
> - struct flock lock;
> - int err;
> -
> - memset(&lock, 0, sizeof(lock));
> - lock.l_type = F_WRLCK;
> - lock.l_whence = SEEK_SET;
> -
> - act.sa_handler = sigalrm;
> - sigemptyset(&act.sa_mask);
> - act.sa_flags = 0;
> - sigemptyset(&set);
> - sigaddset(&set, SIGALRM);
> -
> - sigaction(SIGALRM, &act, &oldact);
> - sigprocmask(SIG_UNBLOCK, &set, &oldset);
> -
> - alarm(BINDINGS_FILE_TIMEOUT);
> - err = fcntl(fd, F_SETLKW, &lock);
> - alarm(0);
> -
> - if (err) {
> - if (errno != EINTR)
> - condlog(0, "Cannot lock bindings file : %s",
> - strerror(errno));
> - else
> - condlog(0, "Bindings file is locked. Giving up.");
> - }
> -
> - sigprocmask(SIG_SETMASK, &oldset, NULL);
> - sigaction(SIGALRM, &oldact, NULL);
> - return err;
> -
> -}
> -
> -
> -static int
> -open_bindings_file(char *file, int *can_write)
> -{
> - int fd;
> - struct stat s;
> -
> - if (ensure_directories_exist(file, 0700))
> - return -1;
> - *can_write = 1;
> - fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
> - if (fd < 0) {
> - if (errno == EROFS) {
> - *can_write = 0;
> - condlog(3, "Cannot open bindings file [%s] read/write. "
> - " trying readonly", file);
> - fd = open(file, O_RDONLY);
> - if (fd < 0) {
> - condlog(0, "Cannot open bindings file [%s] "
> - "readonly : %s", file, strerror(errno));
> - return -1;
> - }
> - }
> - else {
> - condlog(0, "Cannot open bindings file [%s] : %s", file,
> - strerror(errno));
> - return -1;
> - }
> - }
> - if (*can_write && 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 (*can_write == 0)
> - goto fail;
> - /* 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
> format_devname(char *name, int id, int len, char *prefix)
> {
> int pos;
> @@ -366,7 +220,7 @@ get_user_friendly_alias(char *wwid, char
> return NULL;
> }
>
> - fd = open_bindings_file(file, &can_write);
> + fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
> if (fd < 0)
> return NULL;
>
> @@ -416,7 +270,7 @@ get_user_friendly_wwid(char *alias, char
> return NULL;
> }
>
> - fd = open_bindings_file(file, &unused);
> + fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
> if (fd < 0)
> return NULL;
>
> Index: multipath-tools-101104/libmultipath/alias.h
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/alias.h
> +++ multipath-tools-101104/libmultipath/alias.h
> @@ -1,4 +1,3 @@
> -#define BINDINGS_FILE_TIMEOUT 30
> #define BINDINGS_FILE_HEADER \
> "# Multipath bindings, Version : 1.0\n" \
> "# NOTE: this file is automatically maintained by the multipath program.\n" \
> Index: multipath-tools-101104/libmultipath/config.c
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/config.c
> +++ multipath-tools-101104/libmultipath/config.c
> @@ -462,6 +462,7 @@ load_config (char * file)
> conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
> conf->flush_on_last_del = 0;
> conf->attribute_flags = 0;
> + conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
>
> /*
> * preload default hwtable
> Index: multipath-tools-101104/libmultipath/config.h
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/config.h
> +++ multipath-tools-101104/libmultipath/config.h
> @@ -84,6 +84,7 @@ struct config {
> int attribute_flags;
> int fast_io_fail;
> unsigned int dev_loss;
> + int find_multipaths;
> uid_t uid;
> gid_t gid;
> mode_t mode;
> Index: multipath-tools-101104/libmultipath/configure.c
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/configure.c
> +++ multipath-tools-101104/libmultipath/configure.c
> @@ -35,6 +35,7 @@
> #include "alias.h"
> #include "prio.h"
> #include "util.h"
> +#include "finder.h"
>
> extern int
> setup_map (struct multipath * mpp)
> @@ -403,6 +404,8 @@ domap (struct multipath * mpp)
> * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
> * succeeded
> */
> + if (mpp->action == ACT_CREATE)
> + remember_wwid(mpp->wwid);
> if (!conf->daemon) {
> /* multipath client mode */
> dm_switchgroup(mpp->alias, mpp->bestpg);
> @@ -462,6 +465,10 @@ coalesce_paths (struct vectors * vecs, v
>
> memset(empty_buff, 0, WWID_SIZE);
>
> + /* ignore refwwid if it's empty */
> + if (refwwid && !strlen(refwwid))
> + refwwid = NULL;
> +
> if (force_reload) {
> vector_foreach_slot (pathvec, pp1, k) {
> pp1->mpp = NULL;
> @@ -491,6 +498,13 @@ coalesce_paths (struct vectors * vecs, v
> if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
> continue;
>
> + /* If find_multipaths was selected check if the path is valid */
> + if (conf->find_multipaths && !refwwid &&
> + !should_multipath(pp1, pathvec)){
> + orphan_path(pp1);
> + continue;
> + }
> +
> /*
> * at this point, we know we really got a new mp
> */
> Index: multipath-tools-101104/libmultipath/defaults.h
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/defaults.h
> +++ multipath-tools-101104/libmultipath/defaults.h
> @@ -13,6 +13,7 @@
> #define DEFAULT_PGTIMEOUT -PGTIMEOUT_NONE
> #define DEFAULT_USER_FRIENDLY_NAMES 0
> #define DEFAULT_VERBOSITY 2
> +#define DEFAULT_FIND_MULTIPATHS 0
>
> #define DEFAULT_CHECKINT 5
> #define MAX_CHECKINT(a) (a << 2)
> @@ -21,5 +22,6 @@
> #define DEFAULT_SOCKET "/var/run/multipathd.sock"
> #define DEFAULT_CONFIGFILE "/etc/multipath.conf"
> #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
> +#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
>
> char * set_default (char * str);
> Index: multipath-tools-101104/libmultipath/dict.c
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/dict.c
> +++ multipath-tools-101104/libmultipath/dict.c
> @@ -454,6 +454,27 @@ def_flush_on_last_del_handler(vector str
> }
>
> static int
> +def_find_multipaths_handler(vector strvec)
> +{
> + char * buff;
> +
> + buff = set_value(strvec);
> +
> + if (!buff)
> + return 1;
> +
> + if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
> + (strlen(buff) == 1 && !strcmp(buff, "0")))
> + conf->find_multipaths = 0;
> + else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
> + (strlen(buff) == 1 && !strcmp(buff, "1")))
> + conf->find_multipaths = 1;
> +
> + FREE(buff);
> + return 0;
> +}
> +
> +static int
> names_handler(vector strvec)
> {
> char * buff;
> @@ -2105,6 +2126,18 @@ snprint_def_flush_on_last_del (char * bu
> }
>
> static int
> +snprint_def_find_multipaths (char * buff, int len, void * data)
> +{
> + if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS)
> + return 0;
> + if (!conf->find_multipaths)
> + return snprintf(buff, len, "no");
> +
> + return snprintf(buff, len, "yes");
> +}
> +
> +
> +static int
> snprint_def_user_friendly_names (char * buff, int len, void * data)
> {
> if (conf->user_friendly_names == DEFAULT_USER_FRIENDLY_NAMES)
> @@ -2182,6 +2215,7 @@ init_keywords(void)
> install_keyword("gid", &def_gid_handler, &snprint_def_gid);
> 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("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
> __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
> __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
> __deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
> Index: multipath-tools-101104/libmultipath/file.c
> ===================================================================
> --- /dev/null
> +++ multipath-tools-101104/libmultipath/file.c
> @@ -0,0 +1,178 @@
> +/*
> + * Copyright (c) 2005 Christophe Varoqui
> + * Copyright (c) 2005 Benjamin Marzinski, Redhat
> + */
> +#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 <signal.h>
> +
> +#include "file.h"
> +#include "debug.h"
> +#include "uxsock.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 file pathname %s : %s",
> + str, 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 void
> +sigalrm(int sig)
> +{
> + /* do nothing */
> +}
> +
> +static int
> +lock_file(int fd, char *file_name)
> +{
> + struct sigaction act, oldact;
> + sigset_t set, oldset;
> + struct flock lock;
> + int err;
> +
> + memset(&lock, 0, sizeof(lock));
> + lock.l_type = F_WRLCK;
> + lock.l_whence = SEEK_SET;
> +
> + act.sa_handler = sigalrm;
> + sigemptyset(&act.sa_mask);
> + act.sa_flags = 0;
> + sigemptyset(&set);
> + sigaddset(&set, SIGALRM);
> +
> + sigaction(SIGALRM, &act, &oldact);
> + sigprocmask(SIG_UNBLOCK, &set, &oldset);
> +
> + alarm(FILE_TIMEOUT);
> + err = fcntl(fd, F_SETLKW, &lock);
> + alarm(0);
> +
> + if (err) {
> + if (errno != EINTR)
> + condlog(0, "Cannot lock %s : %s", file_name,
> + strerror(errno));
> + else
> + condlog(0, "%s is locked. Giving up.", file_name);
> + }
> +
> + sigprocmask(SIG_SETMASK, &oldset, NULL);
> + sigaction(SIGALRM, &oldact, NULL);
> + return err;
> +}
> +
> +int
> +open_file(char *file, int *can_write, char *header)
> +{
> + int fd;
> + struct stat s;
> +
> + if (ensure_directories_exist(file, 0700))
> + return -1;
> + *can_write = 1;
> + fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
> + if (fd < 0) {
> + if (errno == EROFS) {
> + *can_write = 0;
> + condlog(3, "Cannot open file [%s] read/write. "
> + " trying readonly", file);
> + fd = open(file, O_RDONLY);
> + if (fd < 0) {
> + condlog(0, "Cannot open file [%s] "
> + "readonly : %s", file, strerror(errno));
> + return -1;
> + }
> + }
> + else {
> + condlog(0, "Cannot open file [%s] : %s", file,
> + strerror(errno));
> + return -1;
> + }
> + }
> + if (*can_write && lock_file(fd, file) < 0)
> + goto fail;
> +
> + memset(&s, 0, sizeof(s));
> + if (fstat(fd, &s) < 0){
> + condlog(0, "Cannot stat file %s : %s", file, strerror(errno));
> + goto fail;
> + }
> + if (s.st_size == 0) {
> + if (*can_write == 0)
> + goto fail;
> + /* If file is empty, write the header */
> + size_t len = strlen(header);
> + if (write_all(fd, header, len) != len) {
> + condlog(0,
> + "Cannot write header to file %s : %s", file,
> + strerror(errno));
> + /* cleanup partially written header */
> + ftruncate(fd, 0);
> + goto fail;
> + }
> + fsync(fd);
> + condlog(3, "Initialized new file [%s]", file);
> + }
> +
> + return fd;
> +
> +fail:
> + close(fd);
> + return -1;
> +}
> Index: multipath-tools-101104/libmultipath/file.h
> ===================================================================
> --- /dev/null
> +++ multipath-tools-101104/libmultipath/file.h
> @@ -0,0 +1,11 @@
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +#ifndef _FILE_H
> +#define _FILE_H
> +
> +#define FILE_TIMEOUT 30
> +int open_file(char *file, int *can_write, char *header);
> +
> +#endif /* _FILE_H */
> Index: multipath-tools-101104/libmultipath/finder.c
> ===================================================================
> --- /dev/null
> +++ multipath-tools-101104/libmultipath/finder.c
> @@ -0,0 +1,165 @@
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <limits.h>
> +#include <stdio.h>
> +
> +#include "checkers.h"
> +#include "vector.h"
> +#include "structs.h"
> +#include "debug.h"
> +#include "uxsock.h"
> +#include "file.h"
> +#include "finder.h"
> +#include "defaults.h"
> +
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +static int
> +lookup_wwid(FILE *f, char *wwid) {
> + int c;
> + char buf[LINE_MAX];
> + int count;
> +
> + while ((c = fgetc(f)) != EOF){
> + if (c != '/') {
> + if (fgets(buf, LINE_MAX, f) == NULL)
> + return 0;
> + else
> + continue;
> + }
> + count = 0;
> + while ((c = fgetc(f)) != '/') {
> + if (c == EOF)
> + return 0;
> + if (count >= WWID_SIZE - 1)
> + goto next;
> + if (wwid[count] == '\0')
> + goto next;
> + if (c != wwid[count++])
> + goto next;
> + }
> + if (wwid[count] == '\0')
> + return 1;
> +next:
> + if (fgets(buf, LINE_MAX, f) == NULL)
> + return 0;
> + }
> + return 0;
> +}
> +
> +static int
> +write_out_wwid(int fd, char *wwid) {
> + int ret;
> + off_t offset;
> + char buf[WWID_SIZE + 3];
> +
> + ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
> + if (ret >= (WWID_SIZE + 3) || ret < 0){
> + condlog(0, "can't format wwid for writing (%d) : %s",
> + ret, strerror(errno));
> + return -1;
> + }
> + offset = lseek(fd, 0, SEEK_END);
> + if (offset < 0) {
> + condlog(0, "can't seek to the end of wwids file : %s",
> + strerror(errno));
> + return -1;
> + }
> + if (write_all(fd, buf, strlen(buf)) != strlen(buf)) {
> + condlog(0, "cannot write wwid to wwids file : %s",
> + strerror(errno));
> + ftruncate(fd, offset);
> + return -1;
> + }
> + return 1;
> +}
> +
> +static int
> +check_wwids_file(char *wwid, int write_wwid)
> +{
> + int scan_fd, fd, can_write, found, ret;
> + FILE *f;
> + fd = open_file(DEFAULT_WWIDS_FILE, &can_write, WWIDS_FILE_HEADER);
> + if (fd < 0)
> + return -1;
> +
> + scan_fd = dup(fd);
> + if (scan_fd < 0) {
> + condlog(0, "can't dup wwids file descriptor : %s",
> + strerror(errno));
> + close(fd);
> + return -1;
> + }
> + f = fdopen(scan_fd, "r");
> + if (!f) {
> + condlog(0,"can't fdopen wwids file : %s", strerror(errno));
> + close(fd);
> + close(scan_fd);
> + return -1;
> + }
> + found = lookup_wwid(f, wwid);
> + if (found) {
> + ret = 0;
> + goto out;
> + }
> + if (!write_wwid) {
> + ret = -1;
> + goto out;
> + }
> + if (!can_write) {
> + condlog(0, "wwids file is read-only. Can't write wwid");
> + ret = -1;
> + goto out;
> + }
> + ret = write_out_wwid(fd, wwid);
> +out:
> + fclose(f);
> + close(scan_fd);
> + close(fd);
> + return ret;
> +}
> +
> +int
> +should_multipath(struct path *pp1, vector pathvec)
> +{
> + int i;
> + struct path *pp2;
> +
> + condlog(4, "checking if %s should be multipathed", pp1->dev);
> + vector_foreach_slot(pathvec, pp2, i) {
> + if (pp1->dev == pp2->dev)
> + continue;
> + if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) {
> + condlog(3, "found multiple paths with wwid %s, "
> + "multipathing %s", pp1->wwid, pp1->dev);
> + return 1;
> + }
> + }
> + if (check_wwids_file(pp1->wwid, 0) < 0) {
> + condlog(3, "wwid %s not in wwids file, skipping %s",
> + pp1->wwid, pp1->dev);
> + return 0;
> + }
> + condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid,
> + pp1->dev);
> + return 1;
> +}
> +
> +int
> +remember_wwid(char *wwid)
> +{
> + int ret = check_wwids_file(wwid, 1);
> + if (ret < 0){
> + condlog(3, "failed writing wwid %s to wwids file", wwid);
> + return -1;
> + }
> + if (ret == 1)
> + condlog(3, "wrote wwid %s to wwids file", wwid);
> + else
> + condlog(4, "wwid %s already in wwids file", wwid);
> + return 0;
> +}
> Index: multipath-tools-101104/libmultipath/finder.h
> ===================================================================
> --- /dev/null
> +++ multipath-tools-101104/libmultipath/finder.h
> @@ -0,0 +1,18 @@
> +/*
> + * Copyright (c) 2010 Benjamin Marzinski, Redhat
> + */
> +
> +#ifndef _FINDER_H
> +#define _FINDER_H
> +
> +#define WWIDS_FILE_HEADER \
> +"# Multipath wwids, Version : 1.0\n" \
> +"# NOTE: This file is automatically maintained by multipath and multipathd.\n" \
> +"# You should not need to edit this file in normal circumstances.\n" \
> +"#\n" \
> +"# Valid WWIDs:\n"
> +
> +int should_multipath(struct path *pp, vector pathvec);
> +int remember_wwid(char *wwid);
> +
> +#endif /* _FINDER_H */
> Index: multipath-tools-101104/multipath/main.c
> ===================================================================
> --- multipath-tools-101104.orig/multipath/main.c
> +++ multipath-tools-101104/multipath/main.c
> @@ -51,6 +51,7 @@
> #include <errno.h>
> #include <sys/time.h>
> #include <sys/resource.h>
> +#include <finder.h>
>
> int logsink;
>
> @@ -200,6 +201,7 @@ get_dm_mpvec (vector curmp, vector pathv
>
> if (!conf->dry_run)
> reinstate_paths(mpp);
> + remember_wwid(mpp->wwid);
> }
> return 0;
> }
> @@ -307,7 +309,7 @@ configure (void)
> /*
> * core logic entry point
> */
> - r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload);
> + r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload);
>
> out:
> if (refwwid)
> Index: multipath-tools-101104/multipathd/main.c
> ===================================================================
> --- multipath-tools-101104.orig/multipathd/main.c
> +++ multipath-tools-101104/multipathd/main.c
> @@ -48,6 +48,7 @@
> #include <configure.h>
> #include <prio.h>
> #include <pgpolicies.h>
> +#include <finder.h>
>
> #include "main.h"
> #include "pidfile.h"
> @@ -425,6 +426,11 @@ rescan:
> mpp->action = ACT_RELOAD;
> }
> else {
> + if (conf->find_multipaths &&
> + !should_multipath(pp, vecs->pathvec)) {
> + orphan_path(pp);
> + return 0;
> + }
> if (!pp->size) {
> condlog(0, "%s: failed to create new map,"
> " %s device size is 0 ", devname, pp->dev);
> Index: multipath-tools-101104/libmultipath/Makefile
> ===================================================================
> --- multipath-tools-101104.orig/libmultipath/Makefile
> +++ multipath-tools-101104/libmultipath/Makefile
> @@ -15,7 +15,7 @@ OBJS = memory.o parser.o vector.o devmap
> pgpolicies.o debug.o regex.o defaults.o uevent.o \
> switchgroup.o uxsock.o print.o alias.o log_pthread.o \
> log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
> - lock.o waiter.o
> + lock.o waiter.o file.o finder.o
>
> LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
>
> Index: multipath-tools-101104/multipath/multipath.conf.5
> ===================================================================
> --- multipath-tools-101104.orig/multipath/multipath.conf.5
> +++ multipath-tools-101104/multipath/multipath.conf.5
> @@ -77,6 +77,25 @@ default is
> directory where udev creates its device nodes; default is
> .I /dev
> .TP
> +.B find_multipaths
> +If set to
> +.I yes
> +, instead of trying to create a multipath device for every non-blacklisted
> +path, multipath will only create a device if one of three condidions are
> +met.
> +.I 1
> +There are at least two non-blacklisted paths with the same wwid,
> +.I 2
> +the user manually forces the creation, by specifying a device with the multipath
> +command, or
> +.I 3
> +a path has the same WWID as a multipath device that was previously created
> +(even if that multipath device doesn't currently exist).
> +Whenever a multipath device is created, multipath will remeber the WWID of the
> +device, so that it will automatically create the device again, as soon as it
> +sees a path with that WWID. This should allow most users to have multipath automatically choose the correct paths to make intousers to have multipath automatically choose the correct paths to make into multipath devices, without having to edit the blacklist; Default is
> +.I no
> +.TP
> .B verbosity
> default verbosity. Higher values increase the verbosity level. Valid
> levels are between 0 and 6; default is
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-09-01 20:43 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-25 18:57 [PATCH] multipath: add find_multipaths feature Benjamin Marzinski
2011-09-01 2:55 ` [PATCH v2] " Benjamin Marzinski
2011-09-01 7:14 ` Christophe Varoqui
2011-09-01 12:57 ` Benjamin Marzinski
2011-09-01 14:21 ` Benjamin Marzinski
2011-09-01 20:43 ` Benjamin Marzinski
2011-09-01 14:35 ` Hannes Reinecke
2011-09-01 18:54 ` Benjamin Marzinski
-- strict thread matches above, loose matches on Subject: below --
2010-11-16 23:25 [PATCH] " Benjamin Marzinski
2010-11-16 23:51 ` Christophe Varoqui
2010-11-18 17:21 ` Benjamin Marzinski
2010-12-07 23:00 ` Christophe Varoqui
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.