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