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