device-mapper-multipath/0009-RH-add-find-multipaths.patch

825 lines
21 KiB
Diff
Raw Normal View History

---
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 | 4 -
multipathd/main.c | 6 +
14 files changed, 437 insertions(+), 151 deletions(-)
Index: multipath-tools-111219/libmultipath/alias.c
===================================================================
--- multipath-tools-111219.orig/libmultipath/alias.c
+++ multipath-tools-111219/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-111219/libmultipath/alias.h
===================================================================
--- multipath-tools-111219.orig/libmultipath/alias.h
+++ multipath-tools-111219/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-111219/libmultipath/config.c
===================================================================
--- multipath-tools-111219.orig/libmultipath/config.c
+++ multipath-tools-111219/libmultipath/config.c
@@ -504,6 +504,7 @@ load_config (char * file)
conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
conf->checkint = DEFAULT_CHECKINT;
conf->max_checkint = MAX_CHECKINT(conf->checkint);
+ conf->find_multipaths = DEFAULT_FIND_MULTIPATHS;
/*
* preload default hwtable
Index: multipath-tools-111219/libmultipath/configure.c
===================================================================
--- multipath-tools-111219.orig/libmultipath/configure.c
+++ multipath-tools-111219/libmultipath/configure.c
@@ -36,6 +36,7 @@
#include "prio.h"
#include "util.h"
#include "uxsock.h"
+#include "finder.h"
extern int
setup_map (struct multipath * mpp, char * params, int params_size)
@@ -405,6 +406,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);
@@ -492,6 +495,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;
@@ -521,6 +528,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-111219/libmultipath/defaults.h
===================================================================
--- multipath-tools-111219.orig/libmultipath/defaults.h
+++ multipath-tools-111219/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-111219/libmultipath/dict.c
===================================================================
--- multipath-tools-111219.orig/libmultipath/dict.c
+++ multipath-tools-111219/libmultipath/dict.c
@@ -544,6 +544,27 @@ def_log_checker_err_handler(vector strve
}
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;
@@ -2365,6 +2386,18 @@ snprint_def_log_checker_err (char * buff
}
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)
@@ -2456,6 +2489,7 @@ init_keywords(void)
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("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
+ 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-111219/libmultipath/file.c
===================================================================
--- /dev/null
+++ multipath-tools-111219/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-111219/libmultipath/file.h
===================================================================
--- /dev/null
+++ multipath-tools-111219/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-111219/libmultipath/finder.c
===================================================================
--- /dev/null
+++ multipath-tools-111219/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-111219/libmultipath/finder.h
===================================================================
--- /dev/null
+++ multipath-tools-111219/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-111219/multipath/main.c
===================================================================
--- multipath-tools-111219.orig/multipath/main.c
+++ multipath-tools-111219/multipath/main.c
@@ -53,6 +53,7 @@
#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <finder.h>
#include "dev_t.h"
int logsink;
@@ -209,6 +210,7 @@ get_dm_mpvec (vector curmp, vector pathv
if (!conf->dry_run)
reinstate_paths(mpp);
+ remember_wwid(mpp->wwid);
}
return 0;
}
@@ -316,7 +318,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-111219/multipathd/main.c
===================================================================
--- multipath-tools-111219.orig/multipathd/main.c
+++ multipath-tools-111219/multipathd/main.c
@@ -48,6 +48,7 @@
#include <print.h>
#include <configure.h>
#include <prio.h>
+#include <finder.h>
#include <pgpolicies.h>
#include <uevent.h>
@@ -471,6 +472,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-111219/libmultipath/Makefile
===================================================================
--- multipath-tools-111219.orig/libmultipath/Makefile
+++ multipath-tools-111219/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-111219/libmultipath/config.h
===================================================================
--- multipath-tools-111219.orig/libmultipath/config.h
+++ multipath-tools-111219/libmultipath/config.h
@@ -95,6 +95,7 @@ struct config {
unsigned int dev_loss;
int log_checker_err;
int allow_queueing;
+ int find_multipaths;
uid_t uid;
gid_t gid;
mode_t mode;