2
* Copyright (c) 2004, 2005 Christophe Varoqui
3
* Copyright (c) 2005 Kiyoshi Ueda, NEC
4
* Copyright (c) 2005 Benjamin Marzinski, Redhat
5
* Copyright (c) 2005 Edward Goggin, EMC
8
#include <libdevmapper.h>
17
#include "structs_vec.h"
18
#include "devmapper.h"
23
pthread_attr_t waiter_attr;
25
struct event_thread *alloc_waiter (void)
28
struct event_thread *wp;
30
wp = (struct event_thread *)MALLOC(sizeof(struct event_thread));
35
void free_waiter (void *data)
38
struct event_thread *wp = (struct event_thread *)data;
41
* indicate in mpp that the wp is already freed storage
43
block_signal(SIGHUP, &old);
48
* be careful, mpp may already be freed -- null if so
50
wp->mpp->waiter = NULL;
53
* This is OK condition during shutdown.
55
condlog(3, "free_waiter, mpp freed before wp=%p (%s).", wp, wp->mapname);
57
unlock(wp->vecs->lock);
58
pthread_sigmask(SIG_SETMASK, &old, NULL);
61
dm_task_destroy(wp->dmt);
66
void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
68
struct event_thread *wp = (struct event_thread *)mpp->waiter;
72
condlog(3, "%s: no waiter thread", mpp->alias);
76
condlog(2, "%s: stop event checker thread (%lu)", wp->mapname, thread);
78
pthread_kill(thread, SIGUSR1);
81
static sigset_t unblock_signals(void)
86
sigaddset(&set, SIGHUP);
87
sigaddset(&set, SIGUSR1);
88
pthread_sigmask(SIG_UNBLOCK, &set, &old);
93
* returns the reschedule delay
94
* negative means *stop*
96
int waiteventloop (struct event_thread *waiter)
102
if (!waiter->event_nr)
103
waiter->event_nr = dm_geteventnr(waiter->mapname);
105
if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT))) {
106
condlog(0, "%s: devmap event #%i dm_task_create error",
107
waiter->mapname, waiter->event_nr);
111
if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
112
condlog(0, "%s: devmap event #%i dm_task_set_name error",
113
waiter->mapname, waiter->event_nr);
114
dm_task_destroy(waiter->dmt);
118
if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
120
condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
121
waiter->mapname, waiter->event_nr);
122
dm_task_destroy(waiter->dmt);
126
dm_task_no_open_count(waiter->dmt);
128
/* accept wait interruption */
129
set = unblock_signals();
132
r = dm_task_run(waiter->dmt);
134
/* wait is over : event or interrupt */
135
pthread_sigmask(SIG_SETMASK, &set, NULL);
137
if (!r) /* wait interrupted by signal */
140
dm_task_destroy(waiter->dmt);
148
condlog(3, "%s: devmap event #%i",
149
waiter->mapname, waiter->event_nr);
154
* 1) a table reload, which means our mpp structure is
155
* obsolete : refresh it through update_multipath()
156
* 2) a path failed by DM : mark as such through
158
* 3) map has gone away : stop the thread.
159
* 4) a path reinstate : nothing to do
160
* 5) a switch group : nothing to do
162
pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
163
lock(waiter->vecs->lock);
164
r = update_multipath(waiter->vecs, waiter->mapname);
165
lock_cleanup_pop(waiter->vecs->lock);
168
condlog(2, "%s: event checker exit",
170
return -1; /* stop the thread */
173
event_nr = dm_geteventnr(waiter->mapname);
175
if (waiter->event_nr == event_nr)
176
return 1; /* upon problem reschedule 1s later */
178
waiter->event_nr = event_nr;
180
return -1; /* never reach there */
183
void *waitevent (void *et)
186
struct event_thread *waiter;
188
mlockall(MCL_CURRENT | MCL_FUTURE);
190
waiter = (struct event_thread *)et;
191
pthread_cleanup_push(free_waiter, et);
193
block_signal(SIGUSR1, NULL);
194
block_signal(SIGHUP, NULL);
196
r = waiteventloop(waiter);
204
pthread_cleanup_pop(1);
208
int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
210
struct event_thread *wp;
220
mpp->waiter = (void *)wp;
221
strncpy(wp->mapname, mpp->alias, WWID_SIZE);
225
if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
226
condlog(0, "%s: cannot create event checker", wp->mapname);
229
condlog(2, "%s: event checker started", wp->mapname);
236
condlog(0, "failed to start waiter thread");