chiark / gitweb /
comment out udev's is_initialized call until the problem is sorted out
[elogind.git] / src / core / device.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <sys/epoll.h>
24 #include <libudev.h>
25
26 #include "strv.h"
27 #include "log.h"
28 #include "unit-name.h"
29 #include "dbus-device.h"
30 #include "def.h"
31 #include "path-util.h"
32 #include "udev-util.h"
33 #include "unit.h"
34 #include "swap.h"
35 #include "device.h"
36
37 static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
38         [DEVICE_DEAD] = UNIT_INACTIVE,
39         [DEVICE_PLUGGED] = UNIT_ACTIVE
40 };
41
42 static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
43
44 static void device_unset_sysfs(Device *d) {
45         Hashmap *devices;
46         Device *first;
47
48         assert(d);
49
50         if (!d->sysfs)
51                 return;
52
53         /* Remove this unit from the chain of devices which share the
54          * same sysfs path. */
55         devices = UNIT(d)->manager->devices_by_sysfs;
56         first = hashmap_get(devices, d->sysfs);
57         LIST_REMOVE(same_sysfs, first, d);
58
59         if (first)
60                 hashmap_remove_and_replace(devices, d->sysfs, first->sysfs, first);
61         else
62                 hashmap_remove(devices, d->sysfs);
63
64         free(d->sysfs);
65         d->sysfs = NULL;
66 }
67
68 static void device_init(Unit *u) {
69         Device *d = DEVICE(u);
70
71         assert(d);
72         assert(UNIT(d)->load_state == UNIT_STUB);
73
74         /* In contrast to all other unit types we timeout jobs waiting
75          * for devices by default. This is because they otherwise wait
76          * indefinitely for plugged in devices, something which cannot
77          * happen for the other units since their operations time out
78          * anyway. */
79         u->job_timeout = u->manager->default_timeout_start_usec;
80
81         u->ignore_on_isolate = true;
82         u->ignore_on_snapshot = true;
83 }
84
85 static void device_done(Unit *u) {
86         Device *d = DEVICE(u);
87
88         assert(d);
89
90         device_unset_sysfs(d);
91 }
92
93 static void device_set_state(Device *d, DeviceState state) {
94         DeviceState old_state;
95         assert(d);
96
97         old_state = d->state;
98         d->state = state;
99
100         if (state != old_state)
101                 log_debug_unit(UNIT(d)->id,
102                                "%s changed %s -> %s", UNIT(d)->id,
103                                device_state_to_string(old_state),
104                                device_state_to_string(state));
105
106         unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
107 }
108
109 static int device_coldplug(Unit *u) {
110         Device *d = DEVICE(u);
111
112         assert(d);
113         assert(d->state == DEVICE_DEAD);
114
115         if (d->sysfs)
116                 device_set_state(d, DEVICE_PLUGGED);
117
118         return 0;
119 }
120
121 static void device_dump(Unit *u, FILE *f, const char *prefix) {
122         Device *d = DEVICE(u);
123
124         assert(d);
125
126         fprintf(f,
127                 "%sDevice State: %s\n"
128                 "%sSysfs Path: %s\n",
129                 prefix, device_state_to_string(d->state),
130                 prefix, strna(d->sysfs));
131 }
132
133 _pure_ static UnitActiveState device_active_state(Unit *u) {
134         assert(u);
135
136         return state_translation_table[DEVICE(u)->state];
137 }
138
139 _pure_ static const char *device_sub_state_to_string(Unit *u) {
140         assert(u);
141
142         return device_state_to_string(DEVICE(u)->state);
143 }
144
145 static int device_add_escaped_name(Unit *u, const char *dn) {
146         _cleanup_free_ char *e = NULL;
147         int r;
148
149         assert(u);
150         assert(dn);
151         assert(dn[0] == '/');
152
153         e = unit_name_from_path(dn, ".device");
154         if (!e)
155                 return -ENOMEM;
156
157         r = unit_add_name(u, e);
158         if (r < 0 && r != -EEXIST)
159                 return r;
160
161         return 0;
162 }
163
164 static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
165         _cleanup_free_ char *e = NULL;
166         Unit *u;
167
168         assert(m);
169         assert(dn);
170         assert(dn[0] == '/');
171         assert(_u);
172
173         e = unit_name_from_path(dn, ".device");
174         if (!e)
175                 return -ENOMEM;
176
177         u = manager_get_unit(m, e);
178         if (u) {
179                 *_u = u;
180                 return 1;
181         }
182
183         return 0;
184 }
185
186 static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
187         const char *sysfs, *model;
188         Unit *u = NULL;
189         int r;
190         bool delete;
191
192         assert(m);
193
194         sysfs = udev_device_get_syspath(dev);
195         if (!sysfs)
196                 return 0;
197
198         r = device_find_escape_name(m, path, &u);
199         if (r < 0)
200                 return r;
201
202         if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
203                 return -EEXIST;
204
205         if (!u) {
206                 delete = true;
207
208                 u = unit_new(m, sizeof(Device));
209                 if (!u)
210                         return log_oom();
211
212                 r = device_add_escaped_name(u, path);
213                 if (r < 0)
214                         goto fail;
215
216                 unit_add_to_load_queue(u);
217         } else
218                 delete = false;
219
220         /* If this was created via some dependency and has not
221          * actually been seen yet ->sysfs will not be
222          * initialized. Hence initialize it if necessary. */
223
224         if (!DEVICE(u)->sysfs) {
225                 Device *first;
226
227                 DEVICE(u)->sysfs = strdup(sysfs);
228                 if (!DEVICE(u)->sysfs) {
229                         r = -ENOMEM;
230                         goto fail;
231                 }
232
233                 r = hashmap_ensure_allocated(&m->devices_by_sysfs, string_hash_func, string_compare_func);
234                 if (r < 0)
235                         goto fail;
236
237                 first = hashmap_get(m->devices_by_sysfs, sysfs);
238                 LIST_PREPEND(same_sysfs, first, DEVICE(u));
239
240                 r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first);
241                 if (r < 0)
242                         goto fail;
243         }
244
245         if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
246             (model = udev_device_get_property_value(dev, "ID_MODEL")))
247                 r = unit_set_description(u, model);
248         else
249                 r = unit_set_description(u, path);
250         if (r < 0)
251                 goto fail;
252
253         if (main) {
254                 const char *wants;
255
256                 /* The additional systemd udev properties we only
257                  * interpret for the main object */
258
259                 wants = udev_device_get_property_value(dev, m->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS");
260                 if (wants) {
261                         char *state, *w;
262                         size_t l;
263
264                         FOREACH_WORD_QUOTED(w, l, wants, state) {
265                                 _cleanup_free_ char *n = NULL;
266                                 char e[l+1];
267
268                                 memcpy(e, w, l);
269                                 e[l] = 0;
270
271                                 n = unit_name_mangle(e);
272                                 if (!n) {
273                                         r = -ENOMEM;
274                                         goto fail;
275                                 }
276
277                                 r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
278                                 if (r < 0)
279                                         goto fail;
280                         }
281                 }
282         }
283
284         /* Note that this won't dispatch the load queue, the caller
285          * has to do that if needed and appropriate */
286
287         unit_add_to_dbus_queue(u);
288         return 0;
289
290 fail:
291         log_warning("Failed to load device unit: %s", strerror(-r));
292
293         if (delete && u)
294                 unit_free(u);
295
296         return r;
297 }
298
299 static int device_process_new_device(Manager *m, struct udev_device *dev) {
300         const char *sysfs, *dn, *alias;
301         struct udev_list_entry *item = NULL, *first = NULL;
302         int r;
303
304         assert(m);
305
306 #if 0
307         /* FIXME: this is always false for devices received from udev_monitor */
308
309         /* Don't pick up devices before udev finished initialization for them */
310         if (!udev_device_get_is_initialized(dev))
311                 return 0;
312 #endif
313
314         sysfs = udev_device_get_syspath(dev);
315         if (!sysfs)
316                 return 0;
317
318         /* Add the main unit named after the sysfs path */
319         r = device_update_unit(m, dev, sysfs, true);
320         if (r < 0)
321                 return r;
322
323         /* Add an additional unit for the device node */
324         dn = udev_device_get_devnode(dev);
325         if (dn)
326                 device_update_unit(m, dev, dn, false);
327
328         /* Add additional units for all symlinks */
329         first = udev_device_get_devlinks_list_entry(dev);
330         udev_list_entry_foreach(item, first) {
331                 const char *p;
332                 struct stat st;
333
334                 /* Don't bother with the /dev/block links */
335                 p = udev_list_entry_get_name(item);
336
337                 if (path_startswith(p, "/dev/block/") ||
338                     path_startswith(p, "/dev/char/"))
339                         continue;
340
341                 /* Verify that the symlink in the FS actually belongs
342                  * to this device. This is useful to deal with
343                  * conflicting devices, e.g. when two disks want the
344                  * same /dev/disk/by-label/xxx link because they have
345                  * the same label. We want to make sure that the same
346                  * device that won the symlink wins in systemd, so we
347                  * check the device node major/minor*/
348                 if (stat(p, &st) >= 0)
349                         if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
350                             st.st_rdev != udev_device_get_devnum(dev))
351                                 continue;
352
353                 device_update_unit(m, dev, p, false);
354         }
355
356         /* Add additional units for all explicitly configured
357          * aliases */
358         alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
359         if (alias) {
360                 char *state, *w;
361                 size_t l;
362
363                 FOREACH_WORD_QUOTED(w, l, alias, state) {
364                         char e[l+1];
365
366                         memcpy(e, w, l);
367                         e[l] = 0;
368
369                         if (path_is_absolute(e))
370                                 device_update_unit(m, dev, e, false);
371                         else
372                                 log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, e);
373                 }
374         }
375
376         return 0;
377 }
378
379 static void device_set_path_plugged(Manager *m, struct udev_device *dev) {
380         const char *sysfs;
381         Device *d, *l;
382
383         assert(m);
384         assert(dev);
385
386         sysfs = udev_device_get_syspath(dev);
387         if (!sysfs)
388                 return;
389
390         l = hashmap_get(m->devices_by_sysfs, sysfs);
391         LIST_FOREACH(same_sysfs, d, l)
392                 device_set_state(d, DEVICE_PLUGGED);
393 }
394
395 static int device_process_removed_device(Manager *m, struct udev_device *dev) {
396         const char *sysfs;
397         Device *d;
398
399         assert(m);
400         assert(dev);
401
402         sysfs = udev_device_get_syspath(dev);
403         if (!sysfs)
404                 return -ENOMEM;
405
406         /* Remove all units of this sysfs path */
407         while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
408                 device_unset_sysfs(d);
409                 device_set_state(d, DEVICE_DEAD);
410         }
411
412         return 0;
413 }
414
415 static bool device_is_ready(struct udev_device *dev) {
416         const char *ready;
417
418         assert(dev);
419
420         ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
421         if (!ready)
422                 return true;
423
424         return parse_boolean(ready) != 0;
425 }
426
427 static int device_process_new_path(Manager *m, const char *path) {
428         _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
429
430         assert(m);
431         assert(path);
432
433         dev = udev_device_new_from_syspath(m->udev, path);
434         if (!dev)
435                 return log_oom();
436
437         if (!device_is_ready(dev))
438                 return 0;
439
440         return device_process_new_device(m, dev);
441 }
442
443 static Unit *device_following(Unit *u) {
444         Device *d = DEVICE(u);
445         Device *other, *first = NULL;
446
447         assert(d);
448
449         if (startswith(u->id, "sys-"))
450                 return NULL;
451
452         /* Make everybody follow the unit that's named after the sysfs path */
453         for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
454                 if (startswith(UNIT(other)->id, "sys-"))
455                         return UNIT(other);
456
457         for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
458                 if (startswith(UNIT(other)->id, "sys-"))
459                         return UNIT(other);
460
461                 first = other;
462         }
463
464         return UNIT(first);
465 }
466
467 static int device_following_set(Unit *u, Set **_set) {
468         Device *d = DEVICE(u), *other;
469         Set *set;
470         int r;
471
472         assert(d);
473         assert(_set);
474
475         if (LIST_JUST_US(same_sysfs, d)) {
476                 *_set = NULL;
477                 return 0;
478         }
479
480         set = set_new(NULL, NULL);
481         if (!set)
482                 return -ENOMEM;
483
484         LIST_FOREACH_AFTER(same_sysfs, other, d) {
485                 r = set_put(set, other);
486                 if (r < 0)
487                         goto fail;
488         }
489
490         LIST_FOREACH_BEFORE(same_sysfs, other, d) {
491                 r = set_put(set, other);
492                 if (r < 0)
493                         goto fail;
494         }
495
496         *_set = set;
497         return 1;
498
499 fail:
500         set_free(set);
501         return r;
502 }
503
504 static void device_shutdown(Manager *m) {
505         assert(m);
506
507         m->udev_event_source = sd_event_source_unref(m->udev_event_source);
508
509         if (m->udev_monitor) {
510                 udev_monitor_unref(m->udev_monitor);
511                 m->udev_monitor = NULL;
512         }
513
514         hashmap_free(m->devices_by_sysfs);
515         m->devices_by_sysfs = NULL;
516 }
517
518 static int device_enumerate(Manager *m) {
519         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
520         struct udev_list_entry *item = NULL, *first = NULL;
521         int r;
522
523         assert(m);
524
525         if (!m->udev_monitor) {
526                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
527                 if (!m->udev_monitor) {
528                         r = -ENOMEM;
529                         goto fail;
530                 }
531
532                 /* This will fail if we are unprivileged, but that
533                  * should not matter much, as user instances won't run
534                  * during boot. */
535                 udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
536
537                 r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
538                 if (r < 0)
539                         goto fail;
540
541                 r = udev_monitor_enable_receiving(m->udev_monitor);
542                 if (r < 0)
543                         goto fail;
544
545                 r = sd_event_add_io(m->event, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m, &m->udev_event_source);
546                 if (r < 0)
547                         goto fail;
548         }
549
550         e = udev_enumerate_new(m->udev);
551         if (!e) {
552                 r = -ENOMEM;
553                 goto fail;
554         }
555
556         r = udev_enumerate_add_match_tag(e, "systemd");
557         if (r < 0)
558                 goto fail;
559
560         r = udev_enumerate_scan_devices(e);
561         if (r < 0)
562                 goto fail;
563
564         first = udev_enumerate_get_list_entry(e);
565         udev_list_entry_foreach(item, first)
566                 device_process_new_path(m, udev_list_entry_get_name(item));
567
568         return 0;
569
570 fail:
571         device_shutdown(m);
572         return r;
573 }
574
575 static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
576         _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
577         Manager *m = userdata;
578         const char *action;
579         int r;
580
581         assert(m);
582
583         if (revents != EPOLLIN) {
584                 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
585
586                 if (!ratelimit_test(&limit))
587                         log_error("Failed to get udev event: %m");
588                 if (!(revents & EPOLLIN))
589                         return 0;
590         }
591
592         /*
593          * libudev might filter-out devices which pass the bloom
594          * filter, so getting NULL here is not necessarily an error.
595          */
596         dev = udev_monitor_receive_device(m->udev_monitor);
597         if (!dev)
598                 return 0;
599
600         action = udev_device_get_action(dev);
601         if (!action) {
602                 log_error("Failed to get udev action string.");
603                 return 0;
604         }
605
606         if (streq(action, "remove") || !device_is_ready(dev))  {
607                 r = device_process_removed_device(m, dev);
608                 if (r < 0)
609                         log_error("Failed to process device remove event: %s", strerror(-r));
610
611                 r = swap_process_removed_device(m, dev);
612                 if (r < 0)
613                         log_error("Failed to process swap device remove event: %s", strerror(-r));
614
615         } else {
616                 r = device_process_new_device(m, dev);
617                 if (r < 0)
618                         log_error("Failed to process device new event: %s", strerror(-r));
619
620                 r = swap_process_new_device(m, dev);
621                 if (r < 0)
622                         log_error("Failed to process swap device new event: %s", strerror(-r));
623
624                 manager_dispatch_load_queue(m);
625
626                 device_set_path_plugged(m, dev);
627         }
628
629         return 0;
630 }
631
632 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
633         [DEVICE_DEAD] = "dead",
634         [DEVICE_PLUGGED] = "plugged"
635 };
636
637 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
638
639 const UnitVTable device_vtable = {
640         .object_size = sizeof(Device),
641         .sections =
642                 "Unit\0"
643                 "Device\0"
644                 "Install\0",
645
646         .no_instances = true,
647
648         .init = device_init,
649         .done = device_done,
650         .load = unit_load_fragment_and_dropin_optional,
651
652         .coldplug = device_coldplug,
653
654         .dump = device_dump,
655
656         .active_state = device_active_state,
657         .sub_state_to_string = device_sub_state_to_string,
658
659         .bus_interface = "org.freedesktop.systemd1.Device",
660         .bus_changing_properties = bus_device_changing_properties,
661         .bus_vtable = bus_device_vtable,
662
663         .following = device_following,
664         .following_set = device_following_set,
665
666         .enumerate = device_enumerate,
667         .shutdown = device_shutdown,
668
669         .status_message_formats = {
670                 .starting_stopping = {
671                         [0] = "Expecting device %s...",
672                 },
673                 .finished_start_job = {
674                         [JOB_DONE]       = "Found device %s.",
675                         [JOB_TIMEOUT]    = "Timed out waiting for device %s.",
676                 },
677         },
678 };