0b0d0ce9ba55b7f0740467d089538e5a07e54102
[multipath-tools/.git] / multipathd / dmevents.c
1 /*
2  * Copyright (c) 2004, 2005 Christophe Varoqui
3  * Copyright (c) 2005 Kiyoshi Ueda, NEC
4  * Copyright (c) 2005 Edward Goggin, EMC
5  * Copyright (c) 2005, 2018 Benjamin Marzinski, Redhat
6  */
7 #include <unistd.h>
8 #include <libdevmapper.h>
9 #include <sys/mman.h>
10 #include <pthread.h>
11 #include <urcu.h>
12 #include <poll.h>
13 #include <sys/ioctl.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <linux/dm-ioctl.h>
18 #include <errno.h>
19
20 #include "vector.h"
21 #include "structs.h"
22 #include "structs_vec.h"
23 #include "devmapper.h"
24 #include "debug.h"
25 #include "main.h"
26 #include "dmevents.h"
27
28 #ifndef DM_DEV_ARM_POLL
29 #define DM_DEV_ARM_POLL _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD + 1, struct dm_ioctl)
30 #endif
31
32 enum event_actions {
33         EVENT_NOTHING,
34         EVENT_REMOVE,
35         EVENT_UPDATE,
36 };
37
38 struct dev_event {
39         char name[WWID_SIZE];
40         uint32_t evt_nr;
41         enum event_actions action;
42 };
43
44 struct dmevent_waiter {
45         int fd;
46         struct vectors *vecs;
47         vector events;
48         pthread_mutex_t events_lock;
49 };
50
51 static struct dmevent_waiter *waiter;
52
53 int dmevent_poll_supported(void)
54 {
55         unsigned int minv[3] = {4, 37, 0};
56         unsigned int v[3];
57
58         if (dm_drv_version(v))
59                 return 0;
60
61         if (VERSION_GE(v, minv))
62                 return 1;
63         return 0;
64 }
65
66
67 int init_dmevent_waiter(struct vectors *vecs)
68 {
69         if (!vecs) {
70                 condlog(0, "can't create waiter structure. invalid vectors");
71                 goto fail;
72         }
73         waiter = (struct dmevent_waiter *)malloc(sizeof(struct dmevent_waiter));
74         if (!waiter) {
75                 condlog(0, "failed to allocate waiter structure");
76                 goto fail;
77         }
78         memset(waiter, 0, sizeof(struct dmevent_waiter));
79         waiter->events = vector_alloc();
80         if (!waiter->events) {
81                 condlog(0, "failed to allocate waiter events vector");
82                 goto fail_waiter;
83         }
84         waiter->fd = open("/dev/mapper/control", O_RDWR);
85         if (waiter->fd < 0) {
86                 condlog(0, "failed to open /dev/mapper/control for waiter");
87                 goto fail_events;
88         }
89         pthread_mutex_init(&waiter->events_lock, NULL);
90         waiter->vecs = vecs;
91
92         return 0;
93 fail_events:
94         vector_free(waiter->events);
95 fail_waiter:
96         free(waiter);
97 fail:
98         waiter = NULL;
99         return -1;
100 }
101
102 void cleanup_dmevent_waiter(void)
103 {
104         struct dev_event *dev_evt;
105         int i;
106
107         if (!waiter)
108                 return;
109         pthread_mutex_destroy(&waiter->events_lock);
110         close(waiter->fd);
111         vector_foreach_slot(waiter->events, dev_evt, i)
112                 free(dev_evt);
113         vector_free(waiter->events);
114         free(waiter);
115         waiter = NULL;
116 }
117
118 static int arm_dm_event_poll(int fd)
119 {
120         struct dm_ioctl dmi;
121         memset(&dmi, 0, sizeof(dmi));
122         dmi.version[0] = DM_VERSION_MAJOR;
123         dmi.version[1] = DM_VERSION_MINOR;
124         dmi.version[2] = DM_VERSION_PATCHLEVEL;
125         /* This flag currently does nothing. It simply exists to
126          * duplicate the behavior of libdevmapper */
127         dmi.flags = 0x4;
128         dmi.data_start = offsetof(struct dm_ioctl, data);
129         dmi.data_size = sizeof(dmi);
130         return ioctl(fd, DM_DEV_ARM_POLL, &dmi);
131 }
132
133 /*
134  * As of version 4.37.0 device-mapper stores the event number in the
135  * dm_names structure after the name, when DM_DEVICE_LIST is called
136  */
137 static uint32_t dm_event_nr(struct dm_names *n)
138 {
139         return *(uint32_t *)(((uintptr_t)(strchr(n->name, 0) + 1) + 7) & ~7);
140 }
141
142 static int dm_get_events(void)
143 {
144         struct dm_task *dmt;
145         struct dm_names *names;
146         struct dev_event *dev_evt;
147         int i;
148
149         if (!(dmt = libmp_dm_task_create(DM_DEVICE_LIST)))
150                 return -1;
151
152         dm_task_no_open_count(dmt);
153
154         if (!dm_task_run(dmt))
155                 goto fail;
156
157         if (!(names = dm_task_get_names(dmt)))
158                 goto fail;
159
160         pthread_mutex_lock(&waiter->events_lock);
161         vector_foreach_slot(waiter->events, dev_evt, i)
162                 dev_evt->action = EVENT_REMOVE;
163         while (names->dev) {
164                 uint32_t event_nr;
165
166                 if (!dm_is_mpath(names->name))
167                         goto next;
168
169                 event_nr = dm_event_nr(names);
170                 vector_foreach_slot(waiter->events, dev_evt, i) {
171                         if (!strcmp(dev_evt->name, names->name)) {
172                                 if (event_nr != dev_evt->evt_nr) {
173                                         dev_evt->evt_nr = event_nr;
174                                         dev_evt->action = EVENT_UPDATE;
175                                 } else
176                                         dev_evt->action = EVENT_NOTHING;
177                                 break;
178                         }
179                 }
180 next:
181                 if (!names->next)
182                         break;
183                 names = (void *)names + names->next;
184         }
185         pthread_mutex_unlock(&waiter->events_lock);
186         dm_task_destroy(dmt);
187         return 0;
188
189 fail:
190         dm_task_destroy(dmt);
191         return -1;
192 }
193
194 /* You must call __setup_multipath() after calling this function, to
195  * deal with any events that came in before the device was added */
196 int watch_dmevents(char *name)
197 {
198         int event_nr;
199         struct dev_event *dev_evt, *old_dev_evt;
200         int i;
201
202         if (!dm_is_mpath(name)) {
203                 condlog(0, "%s: not a multipath device. can't watch events",
204                         name);
205                 return -1;
206         }
207
208         if ((event_nr = dm_geteventnr(name)) < 0)
209                 return -1;
210
211         dev_evt = (struct dev_event *)malloc(sizeof(struct dev_event));
212         if (!dev_evt) {
213                 condlog(0, "%s: can't allocate event waiter structure", name);
214                 return -1;
215         }
216
217         strncpy(dev_evt->name, name, WWID_SIZE);
218         dev_evt->name[WWID_SIZE - 1] = 0;
219         dev_evt->evt_nr = event_nr;
220         dev_evt->action = EVENT_NOTHING;
221
222         pthread_mutex_lock(&waiter->events_lock);
223         vector_foreach_slot(waiter->events, old_dev_evt, i){
224                 if (!strcmp(dev_evt->name, old_dev_evt->name)) {
225                         /* caller will be updating this device */
226                         old_dev_evt->evt_nr = event_nr;
227                         old_dev_evt->action = EVENT_NOTHING;
228                         pthread_mutex_unlock(&waiter->events_lock);
229                         condlog(2, "%s: already waiting for events on device",
230                                 name);
231                         free(dev_evt);
232                         return 0;
233                 }
234         }
235         if (!vector_alloc_slot(waiter->events)) {
236                 pthread_mutex_unlock(&waiter->events_lock);
237                 free(dev_evt);
238                 return -1;
239         }
240         vector_set_slot(waiter->events, dev_evt);
241         pthread_mutex_unlock(&waiter->events_lock);
242         return 0;
243 }
244
245 void unwatch_all_dmevents(void)
246 {
247         struct dev_event *dev_evt;
248         int i;
249
250         pthread_mutex_lock(&waiter->events_lock);
251         vector_foreach_slot(waiter->events, dev_evt, i)
252                 free(dev_evt);
253         vector_reset(waiter->events);
254         pthread_mutex_unlock(&waiter->events_lock);
255 }
256
257 static void unwatch_dmevents(char *name)
258 {
259         struct dev_event *dev_evt;
260         int i;
261
262         pthread_mutex_lock(&waiter->events_lock);
263         vector_foreach_slot(waiter->events, dev_evt, i) {
264                 if (!strcmp(dev_evt->name, name)) {
265                         vector_del_slot(waiter->events, i);
266                         free(dev_evt);
267                         break;
268                 }
269         }
270         pthread_mutex_unlock(&waiter->events_lock);
271 }
272
273 /*
274  * returns the reschedule delay
275  * negative means *stop*
276  */
277
278 /* poll, arm, update, return */
279 static int dmevent_loop (void)
280 {
281         int r, i = 0;
282         struct pollfd pfd;
283         struct dev_event *dev_evt;
284
285         pfd.fd = waiter->fd;
286         pfd.events = POLLIN;
287         r = poll(&pfd, 1, -1);
288         if (r <= 0) {
289                 condlog(0, "failed polling for dm events: %s", strerror(errno));
290                 /* sleep 1s and hope things get better */
291                 return 1;
292         }
293
294         if (arm_dm_event_poll(waiter->fd) != 0) {
295                 condlog(0, "Cannot re-arm event polling: %s", strerror(errno));
296                 /* sleep 1s and hope things get better */
297                 return 1;
298         }
299
300         if (dm_get_events() != 0) {
301                 condlog(0, "failed getting dm events: %s", strerror(errno));
302                 /* sleep 1s and hope things get better */
303                 return 1;
304         }
305
306         /*
307          * upon event ...
308          */
309
310         while (1) {
311                 int done = 1;
312                 struct dev_event curr_dev;
313
314                 pthread_mutex_lock(&waiter->events_lock);
315                 vector_foreach_slot(waiter->events, dev_evt, i) {
316                         if (dev_evt->action != EVENT_NOTHING) {
317                                 curr_dev = *dev_evt;
318                                 if (dev_evt->action == EVENT_REMOVE) {
319                                         vector_del_slot(waiter->events, i);
320                                         free(dev_evt);
321                                 } else
322                                         dev_evt->action = EVENT_NOTHING;
323                                 done = 0;
324                                 break;
325                         }
326                 }
327                 pthread_mutex_unlock(&waiter->events_lock);
328                 if (done)
329                         return 1;
330
331                 condlog(3, "%s: devmap event #%i", curr_dev.name,
332                         curr_dev.evt_nr);
333
334                 /*
335                  * event might be :
336                  *
337                  * 1) a table reload, which means our mpp structure is
338                  *    obsolete : refresh it through update_multipath()
339                  * 2) a path failed by DM : mark as such through
340                  *    update_multipath()
341                  * 3) map has gone away : stop the thread.
342                  * 4) a path reinstate : nothing to do
343                  * 5) a switch group : nothing to do
344                  */
345                 pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
346                 lock(&waiter->vecs->lock);
347                 pthread_testcancel();
348                 r = 0;
349                 if (curr_dev.action == EVENT_REMOVE)
350                         remove_map_by_alias(curr_dev.name, waiter->vecs, 1);
351                 else
352                         r = update_multipath(waiter->vecs, curr_dev.name, 1);
353                 lock_cleanup_pop(&waiter->vecs->lock);
354
355                 if (r) {
356                         condlog(2, "%s: stopped watching dmevents",
357                                 curr_dev.name);
358                         unwatch_dmevents(curr_dev.name);
359                 }
360         }
361         condlog(0, "dmevent waiter thread unexpectedly quit");
362         return -1; /* never reach there */
363 }
364
365 static void rcu_unregister(void *param)
366 {
367         rcu_unregister_thread();
368 }
369
370 void *wait_dmevents (void *unused)
371 {
372         int r;
373
374
375         if (!waiter) {
376                 condlog(0, "dmevents waiter not intialized");
377                 return NULL;
378         }
379
380         pthread_cleanup_push(rcu_unregister, NULL);
381         rcu_register_thread();
382         mlockall(MCL_CURRENT | MCL_FUTURE);
383
384         while (1) {
385                 r = dmevent_loop();
386
387                 if (r < 0)
388                         break;
389
390                 sleep(r);
391         }
392
393         pthread_cleanup_pop(1);
394         return NULL;
395 }