device-mapper-multipath/0009-move-waiter-code-from-libmultipath-to-multipathd.patch

794 lines
18 KiB
Diff
Raw Normal View History

device-mapper-multipath-0.7.4-1.git07e7bd5 Update Source to the latest upstream commit * Previous patches 0001-0006 are included in this commit * Previous patches 0007-0014 are now patches 0015-0022 Add 0001-libmultipath-fix-tur-checker-locking.patch * Fixed spinlock bug. posted upstream Add 0002-multipath-fix-DEF_TIMEOUT-use.patch * Add missing sec to ms conversion. posted upstream Add 0003-multipathd-remove-coalesce_paths-from-ev_add_map.patch * Remove unused code. posted upstream Add 0004-multipathd-remove-unused-configure-parameter.patch * Remove unused code. posted upstream Add 0005-Fix-set_no_path_retry-regression.patch * Fix issue with queueing and path addition. posted upstream Add 0006-multipathd-change-spurious-uevent-msg-priority.patch * Change message priority to Notice. posted upstream Add 0007-multipath-print-sysfs-state-in-fast-list-mode.patch * Show sysfs state correctly in fast list mode (-l). posted upstream Add 0008-libmultipath-move-remove_map-waiter-code-to-multipat.patch * Move code around. posted upstream Add 0009-move-waiter-code-from-libmultipath-to-multipathd.patch * Move code around. posted upstream Add 0010-call-start_waiter_thread-before-setup_multipath.patch * Fix race on multipath device creations. posted upstream Add 0011-libmultipath-add-helper-functions.patch * posted upstream Add 0012-multipathd-RFC-add-new-polling-dmevents-waiter-threa.patch * Add alternate method of getting dmevents, that doesn't require a thread per device. posted upstream Add 0013-libmultipath-condlog-log-to-stderr.patch * change condlog to log to stderr instead of stdout. posted upstream Add 0014-multipathd-fix-compiler-warning-for-uev_pathfail_che.patch * fix indentation issue. posted upstream
2018-02-15 19:17:53 +00:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 5 Feb 2018 18:50:45 -0600
Subject: [PATCH] move waiter code from libmultipath to multipathd
Only multipathd uses the code in waiter.[ch] and the functions that call
it directly, so they should all live in the multipathd directory. This
patch is simply moving the waiter.[ch] files and the functions in
structs_vec that use them. None of the moved code has been changed.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/Makefile | 2 +-
libmultipath/structs_vec.c | 98 ---------------------
libmultipath/structs_vec.h | 4 +-
libmultipath/waiter.c | 215 ---------------------------------------------
libmultipath/waiter.h | 17 ----
multipathd/Makefile | 2 +-
multipathd/main.c | 96 ++++++++++++++++++++
multipathd/waiter.c | 215 +++++++++++++++++++++++++++++++++++++++++++++
multipathd/waiter.h | 17 ++++
9 files changed, 332 insertions(+), 334 deletions(-)
delete mode 100644 libmultipath/waiter.c
delete mode 100644 libmultipath/waiter.h
create mode 100644 multipathd/waiter.c
create mode 100644 multipathd/waiter.h
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index 6447d8d..a1005b2 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -42,7 +42,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
pgpolicies.o debug.o defaults.o uevent.o time-util.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 file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
+ lock.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
io_err_stat.o
all: $(LIBS)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index abf5327..77b045b 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -10,7 +10,6 @@
#include "structs.h"
#include "structs_vec.h"
#include "sysfs.h"
-#include "waiter.h"
#include "devmapper.h"
#include "dmparser.h"
#include "propsel.h"
@@ -107,17 +106,6 @@ void orphan_paths(vector pathvec, struct multipath *mpp)
}
}
-static void
-set_multipath_wwid (struct multipath * mpp)
-{
- if (strlen(mpp->wwid))
- return;
-
- dm_get_uuid(mpp->alias, mpp->wwid);
-}
-
-#define PURGE_VEC 1
-
void
remove_map(struct multipath * mpp, struct vectors * vecs, int purge_vec)
{
@@ -379,92 +367,6 @@ sync_map_state(struct multipath *mpp)
}
}
-int
-update_map (struct multipath *mpp, struct vectors *vecs)
-{
- int retries = 3;
- char params[PARAMS_SIZE] = {0};
-
-retry:
- condlog(4, "%s: updating new map", mpp->alias);
- if (adopt_paths(vecs->pathvec, mpp)) {
- condlog(0, "%s: failed to adopt paths for new map update",
- mpp->alias);
- retries = -1;
- goto fail;
- }
- verify_paths(mpp, vecs);
- mpp->action = ACT_RELOAD;
-
- extract_hwe_from_path(mpp);
- if (setup_map(mpp, params, PARAMS_SIZE)) {
- condlog(0, "%s: failed to setup new map in update", mpp->alias);
- retries = -1;
- goto fail;
- }
- if (domap(mpp, params, 1) <= 0 && retries-- > 0) {
- condlog(0, "%s: map_udate sleep", mpp->alias);
- sleep(1);
- goto retry;
- }
- dm_lib_release();
-
-fail:
- if (setup_multipath(vecs, mpp))
- return 1;
-
- sync_map_state(mpp);
-
- if (retries < 0)
- condlog(0, "%s: failed reload in new map update", mpp->alias);
- return 0;
-}
-
-struct multipath *add_map_without_path (struct vectors *vecs, char *alias)
-{
- struct multipath * mpp = alloc_multipath();
- struct config *conf;
-
- if (!mpp)
- return NULL;
- if (!alias) {
- FREE(mpp);
- return NULL;
- }
-
- mpp->alias = STRDUP(alias);
-
- if (dm_get_info(mpp->alias, &mpp->dmi)) {
- condlog(3, "%s: cannot access table", mpp->alias);
- goto out;
- }
- set_multipath_wwid(mpp);
- conf = get_multipath_config();
- mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
- put_multipath_config(conf);
-
- if (update_multipath_table(mpp, vecs->pathvec, 1))
- goto out;
- if (update_multipath_status(mpp))
- goto out;
-
- if (!vector_alloc_slot(vecs->mpvec))
- goto out;
-
- vector_set_slot(vecs->mpvec, mpp);
-
- if (update_map(mpp, vecs) != 0) /* map removed */
- return NULL;
-
- if (start_waiter_thread(mpp, vecs))
- goto out;
-
- return mpp;
-out:
- remove_map(mpp, vecs, PURGE_VEC);
- return NULL;
-}
-
static void
find_existing_alias (struct multipath * mpp,
struct vectors *vecs)
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index d6e17bb..ceab6d9 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -26,12 +26,12 @@ int update_multipath_strings (struct multipath *mpp, vector pathvec,
int is_daemon);
void extract_hwe_from_path(struct multipath * mpp);
+#define PURGE_VEC 1
+
void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec);
void remove_maps (struct vectors * vecs);
void sync_map_state (struct multipath *);
-int update_map (struct multipath *mpp, struct vectors *vecs);
-struct multipath * add_map_without_path (struct vectors * vecs, char * alias);
struct multipath * add_map_with_path (struct vectors * vecs,
struct path * pp, int add_vec);
int update_multipath (struct vectors *vecs, char *mapname, int reset);
diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c
deleted file mode 100644
index cb9708b..0000000
--- a/libmultipath/waiter.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 2004, 2005 Christophe Varoqui
- * Copyright (c) 2005 Kiyoshi Ueda, NEC
- * Copyright (c) 2005 Benjamin Marzinski, Redhat
- * Copyright (c) 2005 Edward Goggin, EMC
- */
-#include <unistd.h>
-#include <libdevmapper.h>
-#include <sys/mman.h>
-#include <pthread.h>
-#include <signal.h>
-#include <urcu.h>
-
-#include "vector.h"
-#include "memory.h"
-#include "checkers.h"
-#include "config.h"
-#include "structs.h"
-#include "structs_vec.h"
-#include "devmapper.h"
-#include "debug.h"
-#include "lock.h"
-#include "waiter.h"
-
-pthread_attr_t waiter_attr;
-
-static struct event_thread *alloc_waiter (void)
-{
-
- struct event_thread *wp;
-
- wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
- memset(wp, 0, sizeof(struct event_thread));
-
- return wp;
-}
-
-static void free_waiter (void *data)
-{
- struct event_thread *wp = (struct event_thread *)data;
-
- if (wp->dmt)
- dm_task_destroy(wp->dmt);
-
- rcu_unregister_thread();
- FREE(wp);
-}
-
-void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
-{
- pthread_t thread;
-
- if (mpp->waiter == (pthread_t)0) {
- condlog(3, "%s: event checker thread already stopped",
- mpp->alias);
- return;
- }
- condlog(2, "%s: stop event checker thread (%lu)", mpp->alias,
- mpp->waiter);
- thread = mpp->waiter;
- mpp->waiter = (pthread_t)0;
- pthread_cancel(thread);
- pthread_kill(thread, SIGUSR2);
-}
-
-/*
- * returns the reschedule delay
- * negative means *stop*
- */
-static int waiteventloop (struct event_thread *waiter)
-{
- sigset_t set, oldset;
- int event_nr;
- int r;
-
- if (!waiter->event_nr)
- waiter->event_nr = dm_geteventnr(waiter->mapname);
-
- if (!(waiter->dmt = libmp_dm_task_create(DM_DEVICE_WAITEVENT))) {
- condlog(0, "%s: devmap event #%i dm_task_create error",
- waiter->mapname, waiter->event_nr);
- return 1;
- }
-
- if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
- condlog(0, "%s: devmap event #%i dm_task_set_name error",
- waiter->mapname, waiter->event_nr);
- dm_task_destroy(waiter->dmt);
- waiter->dmt = NULL;
- return 1;
- }
-
- if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
- waiter->event_nr)) {
- condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
- waiter->mapname, waiter->event_nr);
- dm_task_destroy(waiter->dmt);
- waiter->dmt = NULL;
- return 1;
- }
-
- dm_task_no_open_count(waiter->dmt);
-
- /* wait */
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
-
- pthread_testcancel();
- r = dm_task_run(waiter->dmt);
- pthread_testcancel();
-
- pthread_sigmask(SIG_SETMASK, &oldset, NULL);
- dm_task_destroy(waiter->dmt);
- waiter->dmt = NULL;
-
- if (!r) /* wait interrupted by signal */
- return -1;
-
- waiter->event_nr++;
-
- /*
- * upon event ...
- */
- while (1) {
- condlog(3, "%s: devmap event #%i",
- waiter->mapname, waiter->event_nr);
-
- /*
- * event might be :
- *
- * 1) a table reload, which means our mpp structure is
- * obsolete : refresh it through update_multipath()
- * 2) a path failed by DM : mark as such through
- * update_multipath()
- * 3) map has gone away : stop the thread.
- * 4) a path reinstate : nothing to do
- * 5) a switch group : nothing to do
- */
- pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
- lock(&waiter->vecs->lock);
- pthread_testcancel();
- r = update_multipath(waiter->vecs, waiter->mapname, 1);
- lock_cleanup_pop(waiter->vecs->lock);
-
- if (r) {
- condlog(2, "%s: event checker exit",
- waiter->mapname);
- return -1; /* stop the thread */
- }
-
- event_nr = dm_geteventnr(waiter->mapname);
-
- if (waiter->event_nr == event_nr)
- return 1; /* upon problem reschedule 1s later */
-
- waiter->event_nr = event_nr;
- }
- return -1; /* never reach there */
-}
-
-static void *waitevent (void *et)
-{
- int r;
- struct event_thread *waiter;
-
- mlockall(MCL_CURRENT | MCL_FUTURE);
-
- waiter = (struct event_thread *)et;
- pthread_cleanup_push(free_waiter, et);
-
- rcu_register_thread();
- while (1) {
- r = waiteventloop(waiter);
-
- if (r < 0)
- break;
-
- sleep(r);
- }
-
- pthread_cleanup_pop(1);
- return NULL;
-}
-
-int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
-{
- struct event_thread *wp;
-
- if (!mpp)
- return 0;
-
- wp = alloc_waiter();
-
- if (!wp)
- goto out;
-
- strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1);
- wp->vecs = vecs;
-
- if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
- condlog(0, "%s: cannot create event checker", wp->mapname);
- goto out1;
- }
- mpp->waiter = wp->thread;
- condlog(2, "%s: event checker started", wp->mapname);
-
- return 0;
-out1:
- free_waiter(wp);
- mpp->waiter = (pthread_t)0;
-out:
- condlog(0, "failed to start waiter thread");
- return 1;
-}
diff --git a/libmultipath/waiter.h b/libmultipath/waiter.h
deleted file mode 100644
index 0cfae46..0000000
--- a/libmultipath/waiter.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _WAITER_H
-#define _WAITER_H
-
-extern pthread_attr_t waiter_attr;
-
-struct event_thread {
- struct dm_task *dmt;
- pthread_t thread;
- int event_nr;
- char mapname[WWID_SIZE];
- struct vectors *vecs;
-};
-
-void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs);
-int start_waiter_thread (struct multipath *mpp, struct vectors *vecs);
-
-#endif /* _WAITER_H */
diff --git a/multipathd/Makefile b/multipathd/Makefile
index e6f140b..85f29a7 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -22,7 +22,7 @@ ifdef SYSTEMD
endif
endif
-OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o
+OBJS = main.o pidfile.o uxlsnr.o uxclnt.o cli.o cli_handlers.o waiter.o
EXEC = multipathd
diff --git a/multipathd/main.c b/multipathd/main.c
index 72c3c2f..94b2406 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -311,6 +311,102 @@ remove_maps_and_stop_waiters(struct vectors *vecs)
remove_maps(vecs);
}
+static void
+set_multipath_wwid (struct multipath * mpp)
+{
+ if (strlen(mpp->wwid))
+ return;
+
+ dm_get_uuid(mpp->alias, mpp->wwid);
+}
+
+static int
+update_map (struct multipath *mpp, struct vectors *vecs)
+{
+ int retries = 3;
+ char params[PARAMS_SIZE] = {0};
+
+retry:
+ condlog(4, "%s: updating new map", mpp->alias);
+ if (adopt_paths(vecs->pathvec, mpp)) {
+ condlog(0, "%s: failed to adopt paths for new map update",
+ mpp->alias);
+ retries = -1;
+ goto fail;
+ }
+ verify_paths(mpp, vecs);
+ mpp->action = ACT_RELOAD;
+
+ extract_hwe_from_path(mpp);
+ if (setup_map(mpp, params, PARAMS_SIZE)) {
+ condlog(0, "%s: failed to setup new map in update", mpp->alias);
+ retries = -1;
+ goto fail;
+ }
+ if (domap(mpp, params, 1) <= 0 && retries-- > 0) {
+ condlog(0, "%s: map_udate sleep", mpp->alias);
+ sleep(1);
+ goto retry;
+ }
+ dm_lib_release();
+
+fail:
+ if (setup_multipath(vecs, mpp))
+ return 1;
+
+ sync_map_state(mpp);
+
+ if (retries < 0)
+ condlog(0, "%s: failed reload in new map update", mpp->alias);
+ return 0;
+}
+
+static struct multipath *
+add_map_without_path (struct vectors *vecs, char *alias)
+{
+ struct multipath * mpp = alloc_multipath();
+ struct config *conf;
+
+ if (!mpp)
+ return NULL;
+ if (!alias) {
+ FREE(mpp);
+ return NULL;
+ }
+
+ mpp->alias = STRDUP(alias);
+
+ if (dm_get_info(mpp->alias, &mpp->dmi)) {
+ condlog(3, "%s: cannot access table", mpp->alias);
+ goto out;
+ }
+ set_multipath_wwid(mpp);
+ conf = get_multipath_config();
+ mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
+ put_multipath_config(conf);
+
+ if (update_multipath_table(mpp, vecs->pathvec, 1))
+ goto out;
+ if (update_multipath_status(mpp))
+ goto out;
+
+ if (!vector_alloc_slot(vecs->mpvec))
+ goto out;
+
+ vector_set_slot(vecs->mpvec, mpp);
+
+ if (update_map(mpp, vecs) != 0) /* map removed */
+ return NULL;
+
+ if (start_waiter_thread(mpp, vecs))
+ goto out;
+
+ return mpp;
+out:
+ remove_map(mpp, vecs, PURGE_VEC);
+ return NULL;
+}
+
static int
coalesce_maps(struct vectors *vecs, vector nmpv)
{
diff --git a/multipathd/waiter.c b/multipathd/waiter.c
new file mode 100644
index 0000000..cb9708b
--- /dev/null
+++ b/multipathd/waiter.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2004, 2005 Christophe Varoqui
+ * Copyright (c) 2005 Kiyoshi Ueda, NEC
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
+ * Copyright (c) 2005 Edward Goggin, EMC
+ */
+#include <unistd.h>
+#include <libdevmapper.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <signal.h>
+#include <urcu.h>
+
+#include "vector.h"
+#include "memory.h"
+#include "checkers.h"
+#include "config.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "devmapper.h"
+#include "debug.h"
+#include "lock.h"
+#include "waiter.h"
+
+pthread_attr_t waiter_attr;
+
+static struct event_thread *alloc_waiter (void)
+{
+
+ struct event_thread *wp;
+
+ wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
+ memset(wp, 0, sizeof(struct event_thread));
+
+ return wp;
+}
+
+static void free_waiter (void *data)
+{
+ struct event_thread *wp = (struct event_thread *)data;
+
+ if (wp->dmt)
+ dm_task_destroy(wp->dmt);
+
+ rcu_unregister_thread();
+ FREE(wp);
+}
+
+void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
+{
+ pthread_t thread;
+
+ if (mpp->waiter == (pthread_t)0) {
+ condlog(3, "%s: event checker thread already stopped",
+ mpp->alias);
+ return;
+ }
+ condlog(2, "%s: stop event checker thread (%lu)", mpp->alias,
+ mpp->waiter);
+ thread = mpp->waiter;
+ mpp->waiter = (pthread_t)0;
+ pthread_cancel(thread);
+ pthread_kill(thread, SIGUSR2);
+}
+
+/*
+ * returns the reschedule delay
+ * negative means *stop*
+ */
+static int waiteventloop (struct event_thread *waiter)
+{
+ sigset_t set, oldset;
+ int event_nr;
+ int r;
+
+ if (!waiter->event_nr)
+ waiter->event_nr = dm_geteventnr(waiter->mapname);
+
+ if (!(waiter->dmt = libmp_dm_task_create(DM_DEVICE_WAITEVENT))) {
+ condlog(0, "%s: devmap event #%i dm_task_create error",
+ waiter->mapname, waiter->event_nr);
+ return 1;
+ }
+
+ if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
+ condlog(0, "%s: devmap event #%i dm_task_set_name error",
+ waiter->mapname, waiter->event_nr);
+ dm_task_destroy(waiter->dmt);
+ waiter->dmt = NULL;
+ return 1;
+ }
+
+ if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
+ waiter->event_nr)) {
+ condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
+ waiter->mapname, waiter->event_nr);
+ dm_task_destroy(waiter->dmt);
+ waiter->dmt = NULL;
+ return 1;
+ }
+
+ dm_task_no_open_count(waiter->dmt);
+
+ /* wait */
+ sigemptyset(&set);
+ sigaddset(&set, SIGUSR2);
+ pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
+
+ pthread_testcancel();
+ r = dm_task_run(waiter->dmt);
+ pthread_testcancel();
+
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ dm_task_destroy(waiter->dmt);
+ waiter->dmt = NULL;
+
+ if (!r) /* wait interrupted by signal */
+ return -1;
+
+ waiter->event_nr++;
+
+ /*
+ * upon event ...
+ */
+ while (1) {
+ condlog(3, "%s: devmap event #%i",
+ waiter->mapname, waiter->event_nr);
+
+ /*
+ * event might be :
+ *
+ * 1) a table reload, which means our mpp structure is
+ * obsolete : refresh it through update_multipath()
+ * 2) a path failed by DM : mark as such through
+ * update_multipath()
+ * 3) map has gone away : stop the thread.
+ * 4) a path reinstate : nothing to do
+ * 5) a switch group : nothing to do
+ */
+ pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
+ lock(&waiter->vecs->lock);
+ pthread_testcancel();
+ r = update_multipath(waiter->vecs, waiter->mapname, 1);
+ lock_cleanup_pop(waiter->vecs->lock);
+
+ if (r) {
+ condlog(2, "%s: event checker exit",
+ waiter->mapname);
+ return -1; /* stop the thread */
+ }
+
+ event_nr = dm_geteventnr(waiter->mapname);
+
+ if (waiter->event_nr == event_nr)
+ return 1; /* upon problem reschedule 1s later */
+
+ waiter->event_nr = event_nr;
+ }
+ return -1; /* never reach there */
+}
+
+static void *waitevent (void *et)
+{
+ int r;
+ struct event_thread *waiter;
+
+ mlockall(MCL_CURRENT | MCL_FUTURE);
+
+ waiter = (struct event_thread *)et;
+ pthread_cleanup_push(free_waiter, et);
+
+ rcu_register_thread();
+ while (1) {
+ r = waiteventloop(waiter);
+
+ if (r < 0)
+ break;
+
+ sleep(r);
+ }
+
+ pthread_cleanup_pop(1);
+ return NULL;
+}
+
+int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
+{
+ struct event_thread *wp;
+
+ if (!mpp)
+ return 0;
+
+ wp = alloc_waiter();
+
+ if (!wp)
+ goto out;
+
+ strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1);
+ wp->vecs = vecs;
+
+ if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
+ condlog(0, "%s: cannot create event checker", wp->mapname);
+ goto out1;
+ }
+ mpp->waiter = wp->thread;
+ condlog(2, "%s: event checker started", wp->mapname);
+
+ return 0;
+out1:
+ free_waiter(wp);
+ mpp->waiter = (pthread_t)0;
+out:
+ condlog(0, "failed to start waiter thread");
+ return 1;
+}
diff --git a/multipathd/waiter.h b/multipathd/waiter.h
new file mode 100644
index 0000000..0cfae46
--- /dev/null
+++ b/multipathd/waiter.h
@@ -0,0 +1,17 @@
+#ifndef _WAITER_H
+#define _WAITER_H
+
+extern pthread_attr_t waiter_attr;
+
+struct event_thread {
+ struct dm_task *dmt;
+ pthread_t thread;
+ int event_nr;
+ char mapname[WWID_SIZE];
+ struct vectors *vecs;
+};
+
+void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs);
+int start_waiter_thread (struct multipath *mpp, struct vectors *vecs);
+
+#endif /* _WAITER_H */
--
2.7.4