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));
31 memset(wp, 0, sizeof(struct event_thread));
36 void free_waiter (void *data)
38 struct event_thread *wp = (struct event_thread *)data;
41 dm_task_destroy(wp->dmt);
46 void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
50 if (mpp->waiter == (pthread_t)0) {
51 condlog(3, "%s: event checker thread already stopped",
55 condlog(2, "%s: stop event checker thread (%lu)", mpp->alias,
58 mpp->waiter = (pthread_t)0;
59 pthread_cancel(thread);
63 * returns the reschedule delay
64 * negative means *stop*
66 int waiteventloop (struct event_thread *waiter)
71 if (!waiter->event_nr)
72 waiter->event_nr = dm_geteventnr(waiter->mapname);
74 if (!(waiter->dmt = dm_task_create(DM_DEVICE_WAITEVENT))) {
75 condlog(0, "%s: devmap event #%i dm_task_create error",
76 waiter->mapname, waiter->event_nr);
80 if (!dm_task_set_name(waiter->dmt, waiter->mapname)) {
81 condlog(0, "%s: devmap event #%i dm_task_set_name error",
82 waiter->mapname, waiter->event_nr);
83 dm_task_destroy(waiter->dmt);
88 if (waiter->event_nr && !dm_task_set_event_nr(waiter->dmt,
90 condlog(0, "%s: devmap event #%i dm_task_set_event_nr error",
91 waiter->mapname, waiter->event_nr);
92 dm_task_destroy(waiter->dmt);
97 dm_task_no_open_count(waiter->dmt);
100 r = dm_task_run(waiter->dmt);
102 dm_task_destroy(waiter->dmt);
105 if (!r) /* wait interrupted by signal */
114 condlog(3, "%s: devmap event #%i",
115 waiter->mapname, waiter->event_nr);
120 * 1) a table reload, which means our mpp structure is
121 * obsolete : refresh it through update_multipath()
122 * 2) a path failed by DM : mark as such through
124 * 3) map has gone away : stop the thread.
125 * 4) a path reinstate : nothing to do
126 * 5) a switch group : nothing to do
128 pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
129 lock(waiter->vecs->lock);
130 pthread_testcancel();
131 r = update_multipath(waiter->vecs, waiter->mapname, 1);
132 lock_cleanup_pop(waiter->vecs->lock);
135 condlog(2, "%s: event checker exit",
137 return -1; /* stop the thread */
140 event_nr = dm_geteventnr(waiter->mapname);
142 if (waiter->event_nr == event_nr)
143 return 1; /* upon problem reschedule 1s later */
145 waiter->event_nr = event_nr;
147 return -1; /* never reach there */
150 void *waitevent (void *et)
153 struct event_thread *waiter;
155 mlockall(MCL_CURRENT | MCL_FUTURE);
157 waiter = (struct event_thread *)et;
158 pthread_cleanup_push(free_waiter, et);
161 r = waiteventloop(waiter);
169 pthread_cleanup_pop(1);
173 int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
175 struct event_thread *wp;
185 strncpy(wp->mapname, mpp->alias, WWID_SIZE);
188 if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
189 condlog(0, "%s: cannot create event checker", wp->mapname);
192 mpp->waiter = wp->thread;
193 condlog(2, "%s: event checker started", wp->mapname);
198 mpp->waiter = (pthread_t)0;
200 condlog(0, "failed to start waiter thread");