chiark / gitweb /
manager: do not print timing when running in test mode
[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_make_description(Unit *u, struct udev_device *dev, const char *path) {
187         const char *model;
188
189         assert(u);
190         assert(dev);
191         assert(path);
192
193         model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
194         if (!model)
195                 model = udev_device_get_property_value(dev, "ID_MODEL");
196
197         if (model) {
198                 const char *label;
199
200                 /* Try to concatenate the device model string with a label, if there is one */
201                 label = udev_device_get_property_value(dev, "ID_FS_LABEL");
202                 if (!label)
203                         label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME");
204                 if (!label)
205                         label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER");
206
207                 if (label) {
208                         _cleanup_free_ char *j;
209
210                         j = strjoin(model, " ", label, NULL);
211                         if (j)
212                                 return unit_set_description(u, j);
213                 }
214
215                 return unit_set_description(u, model);
216         }
217
218         return unit_set_description(u, path);
219 }
220
221 static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
222         const char *wants;
223         const char *word, *state;
224         size_t l;
225         int r;
226         const char *property;
227
228         assert(u);
229         assert(dev);
230
231         property = u->manager->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
232         wants = udev_device_get_property_value(dev, property);
233         if (!wants)
234                 return 0;
235
236         FOREACH_WORD_QUOTED(word, l, wants, state) {
237                 _cleanup_free_ char *n = NULL;
238                 char e[l+1];
239
240                 memcpy(e, word, l);
241                 e[l] = 0;
242
243                 n = unit_name_mangle(e, MANGLE_NOGLOB);
244                 if (!n)
245                         return -ENOMEM;
246
247                 r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
248                 if (r < 0)
249                         return r;
250         }
251         if (!isempty(state))
252                 log_warning_unit(u->id, "Property %s on %s has trailing garbage, ignoring.",
253                                  property, strna(udev_device_get_syspath(dev)));
254
255         return 0;
256 }
257
258 static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
259         const char *sysfs;
260         Unit *u = NULL;
261         bool delete;
262         int r;
263
264         assert(m);
265         assert(dev);
266         assert(path);
267
268         sysfs = udev_device_get_syspath(dev);
269         if (!sysfs)
270                 return 0;
271
272         r = device_find_escape_name(m, path, &u);
273         if (r < 0)
274                 return r;
275
276         if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
277                 return -EEXIST;
278
279         if (!u) {
280                 delete = true;
281
282                 u = unit_new(m, sizeof(Device));
283                 if (!u)
284                         return log_oom();
285
286                 r = device_add_escaped_name(u, path);
287                 if (r < 0)
288                         goto fail;
289
290                 unit_add_to_load_queue(u);
291         } else
292                 delete = false;
293
294         /* If this was created via some dependency and has not
295          * actually been seen yet ->sysfs will not be
296          * initialized. Hence initialize it if necessary. */
297
298         if (!DEVICE(u)->sysfs) {
299                 Device *first;
300
301                 DEVICE(u)->sysfs = strdup(sysfs);
302                 if (!DEVICE(u)->sysfs) {
303                         r = -ENOMEM;
304                         goto fail;
305                 }
306
307                 r = hashmap_ensure_allocated(&m->devices_by_sysfs, &string_hash_ops);
308                 if (r < 0)
309                         goto fail;
310
311                 first = hashmap_get(m->devices_by_sysfs, sysfs);
312                 LIST_PREPEND(same_sysfs, first, DEVICE(u));
313
314                 r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first);
315                 if (r < 0)
316                         goto fail;
317         }
318
319         device_make_description(u, dev, path);
320
321         if (main) {
322                 /* The additional systemd udev properties we only
323                  * interpret for the main object */
324
325                 r = device_add_udev_wants(u, dev);
326                 if (r < 0)
327                         goto fail;
328         }
329
330         /* Note that this won't dispatch the load queue, the caller
331          * has to do that if needed and appropriate */
332
333         unit_add_to_dbus_queue(u);
334         return 0;
335
336 fail:
337         log_warning("Failed to load device unit: %s", strerror(-r));
338
339         if (delete && u)
340                 unit_free(u);
341
342         return r;
343 }
344
345 static int device_process_new_device(Manager *m, struct udev_device *dev) {
346         const char *sysfs, *dn, *alias;
347         struct udev_list_entry *item = NULL, *first = NULL;
348         int r;
349
350         assert(m);
351
352         sysfs = udev_device_get_syspath(dev);
353         if (!sysfs)
354                 return 0;
355
356         /* Add the main unit named after the sysfs path */
357         r = device_update_unit(m, dev, sysfs, true);
358         if (r < 0)
359                 return r;
360
361         /* Add an additional unit for the device node */
362         dn = udev_device_get_devnode(dev);
363         if (dn)
364                 device_update_unit(m, dev, dn, false);
365
366         /* Add additional units for all symlinks */
367         first = udev_device_get_devlinks_list_entry(dev);
368         udev_list_entry_foreach(item, first) {
369                 const char *p;
370                 struct stat st;
371
372                 /* Don't bother with the /dev/block links */
373                 p = udev_list_entry_get_name(item);
374
375                 if (path_startswith(p, "/dev/block/") ||
376                     path_startswith(p, "/dev/char/"))
377                         continue;
378
379                 /* Verify that the symlink in the FS actually belongs
380                  * to this device. This is useful to deal with
381                  * conflicting devices, e.g. when two disks want the
382                  * same /dev/disk/by-label/xxx link because they have
383                  * the same label. We want to make sure that the same
384                  * device that won the symlink wins in systemd, so we
385                  * check the device node major/minor*/
386                 if (stat(p, &st) >= 0)
387                         if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
388                             st.st_rdev != udev_device_get_devnum(dev))
389                                 continue;
390
391                 device_update_unit(m, dev, p, false);
392         }
393
394         /* Add additional units for all explicitly configured
395          * aliases */
396         alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
397         if (alias) {
398                 const char *word, *state;
399                 size_t l;
400
401                 FOREACH_WORD_QUOTED(word, l, alias, state) {
402                         char e[l+1];
403
404                         memcpy(e, word, l);
405                         e[l] = 0;
406
407                         if (path_is_absolute(e))
408                                 device_update_unit(m, dev, e, false);
409                         else
410                                 log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, e);
411                 }
412                 if (!isempty(state))
413                         log_warning("SYSTEMD_ALIAS for %s has trailing garbage, ignoring.", sysfs);
414         }
415
416         return 0;
417 }
418
419 static void device_set_path_plugged(Manager *m, struct udev_device *dev) {
420         const char *sysfs;
421         Device *d, *l;
422
423         assert(m);
424         assert(dev);
425
426         sysfs = udev_device_get_syspath(dev);
427         if (!sysfs)
428                 return;
429
430         l = hashmap_get(m->devices_by_sysfs, sysfs);
431         LIST_FOREACH(same_sysfs, d, l)
432                 device_set_state(d, DEVICE_PLUGGED);
433 }
434
435 static int device_process_removed_device(Manager *m, struct udev_device *dev) {
436         const char *sysfs;
437         Device *d;
438
439         assert(m);
440         assert(dev);
441
442         sysfs = udev_device_get_syspath(dev);
443         if (!sysfs)
444                 return -ENOMEM;
445
446         /* Remove all units of this sysfs path */
447         while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
448                 device_unset_sysfs(d);
449                 device_set_state(d, DEVICE_DEAD);
450         }
451
452         return 0;
453 }
454
455 static bool device_is_ready(struct udev_device *dev) {
456         const char *ready;
457
458         assert(dev);
459
460         ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
461         if (!ready)
462                 return true;
463
464         return parse_boolean(ready) != 0;
465 }
466
467 static int device_process_new_path(Manager *m, const char *path) {
468         _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
469
470         assert(m);
471         assert(path);
472
473         dev = udev_device_new_from_syspath(m->udev, path);
474         if (!dev)
475                 return log_oom();
476
477         if (!device_is_ready(dev))
478                 return 0;
479
480         return device_process_new_device(m, dev);
481 }
482
483 static Unit *device_following(Unit *u) {
484         Device *d = DEVICE(u);
485         Device *other, *first = NULL;
486
487         assert(d);
488
489         if (startswith(u->id, "sys-"))
490                 return NULL;
491
492         /* Make everybody follow the unit that's named after the sysfs path */
493         for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
494                 if (startswith(UNIT(other)->id, "sys-"))
495                         return UNIT(other);
496
497         for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
498                 if (startswith(UNIT(other)->id, "sys-"))
499                         return UNIT(other);
500
501                 first = other;
502         }
503
504         return UNIT(first);
505 }
506
507 static int device_following_set(Unit *u, Set **_set) {
508         Device *d = DEVICE(u), *other;
509         Set *set;
510         int r;
511
512         assert(d);
513         assert(_set);
514
515         if (LIST_JUST_US(same_sysfs, d)) {
516                 *_set = NULL;
517                 return 0;
518         }
519
520         set = set_new(NULL);
521         if (!set)
522                 return -ENOMEM;
523
524         LIST_FOREACH_AFTER(same_sysfs, other, d) {
525                 r = set_put(set, other);
526                 if (r < 0)
527                         goto fail;
528         }
529
530         LIST_FOREACH_BEFORE(same_sysfs, other, d) {
531                 r = set_put(set, other);
532                 if (r < 0)
533                         goto fail;
534         }
535
536         *_set = set;
537         return 1;
538
539 fail:
540         set_free(set);
541         return r;
542 }
543
544 static void device_shutdown(Manager *m) {
545         assert(m);
546
547         m->udev_event_source = sd_event_source_unref(m->udev_event_source);
548
549         if (m->udev_monitor) {
550                 udev_monitor_unref(m->udev_monitor);
551                 m->udev_monitor = NULL;
552         }
553
554         hashmap_free(m->devices_by_sysfs);
555         m->devices_by_sysfs = NULL;
556 }
557
558 static int device_enumerate(Manager *m) {
559         _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
560         struct udev_list_entry *item = NULL, *first = NULL;
561         int r;
562
563         assert(m);
564
565         if (!m->udev_monitor) {
566                 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
567                 if (!m->udev_monitor) {
568                         r = -ENOMEM;
569                         goto fail;
570                 }
571
572                 /* This will fail if we are unprivileged, but that
573                  * should not matter much, as user instances won't run
574                  * during boot. */
575                 udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
576
577                 r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
578                 if (r < 0)
579                         goto fail;
580
581                 r = udev_monitor_enable_receiving(m->udev_monitor);
582                 if (r < 0)
583                         goto fail;
584
585                 r = sd_event_add_io(m->event, &m->udev_event_source, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m);
586                 if (r < 0)
587                         goto fail;
588         }
589
590         e = udev_enumerate_new(m->udev);
591         if (!e) {
592                 r = -ENOMEM;
593                 goto fail;
594         }
595
596         r = udev_enumerate_add_match_tag(e, "systemd");
597         if (r < 0)
598                 goto fail;
599
600         r = udev_enumerate_add_match_is_initialized(e);
601         if (r < 0)
602                 goto fail;
603
604         r = udev_enumerate_scan_devices(e);
605         if (r < 0)
606                 goto fail;
607
608         first = udev_enumerate_get_list_entry(e);
609         udev_list_entry_foreach(item, first)
610                 device_process_new_path(m, udev_list_entry_get_name(item));
611
612         return 0;
613
614 fail:
615         device_shutdown(m);
616         return r;
617 }
618
619 static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
620         _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
621         Manager *m = userdata;
622         const char *action;
623         int r;
624
625         assert(m);
626
627         if (revents != EPOLLIN) {
628                 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
629
630                 if (!ratelimit_test(&limit))
631                         log_error("Failed to get udev event: %m");
632                 if (!(revents & EPOLLIN))
633                         return 0;
634         }
635
636         /*
637          * libudev might filter-out devices which pass the bloom
638          * filter, so getting NULL here is not necessarily an error.
639          */
640         dev = udev_monitor_receive_device(m->udev_monitor);
641         if (!dev)
642                 return 0;
643
644         action = udev_device_get_action(dev);
645         if (!action) {
646                 log_error("Failed to get udev action string.");
647                 return 0;
648         }
649
650         if (streq(action, "remove") || !device_is_ready(dev))  {
651                 r = device_process_removed_device(m, dev);
652                 if (r < 0)
653                         log_error("Failed to process device remove event: %s", strerror(-r));
654
655                 r = swap_process_removed_device(m, dev);
656                 if (r < 0)
657                         log_error("Failed to process swap device remove event: %s", strerror(-r));
658
659         } else {
660                 r = device_process_new_device(m, dev);
661                 if (r < 0)
662                         log_error("Failed to process device new event: %s", strerror(-r));
663
664                 r = swap_process_new_device(m, dev);
665                 if (r < 0)
666                         log_error("Failed to process swap device new event: %s", strerror(-r));
667
668                 manager_dispatch_load_queue(m);
669
670                 device_set_path_plugged(m, dev);
671         }
672
673         return 0;
674 }
675
676 static const char* const device_state_table[_DEVICE_STATE_MAX] = {
677         [DEVICE_DEAD] = "dead",
678         [DEVICE_PLUGGED] = "plugged"
679 };
680
681 DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
682
683 const UnitVTable device_vtable = {
684         .object_size = sizeof(Device),
685         .sections =
686                 "Unit\0"
687                 "Device\0"
688                 "Install\0",
689
690         .no_instances = true,
691
692         .init = device_init,
693         .done = device_done,
694         .load = unit_load_fragment_and_dropin_optional,
695
696         .coldplug = device_coldplug,
697
698         .dump = device_dump,
699
700         .active_state = device_active_state,
701         .sub_state_to_string = device_sub_state_to_string,
702
703         .bus_interface = "org.freedesktop.systemd1.Device",
704         .bus_vtable = bus_device_vtable,
705
706         .following = device_following,
707         .following_set = device_following_set,
708
709         .enumerate = device_enumerate,
710         .shutdown = device_shutdown,
711
712         .status_message_formats = {
713                 .starting_stopping = {
714                         [0] = "Expecting device %s...",
715                 },
716                 .finished_start_job = {
717                         [JOB_DONE]       = "Found device %s.",
718                         [JOB_TIMEOUT]    = "Timed out waiting for device %s.",
719                 },
720         },
721 };