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