]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/device.c
core: annotate event sources
[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
25ac040b 26#include "log.h"
9e2f7c11 27#include "unit-name.h"
4139c1b2 28#include "dbus-device.h"
9eb977db 29#include "path-util.h"
718db961 30#include "udev-util.h"
9670d583
LP
31#include "unit.h"
32#include "swap.h"
33#include "device.h"
5cb5a6ff 34
f50e0a01
LP
35static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
36 [DEVICE_DEAD] = UNIT_INACTIVE,
628c89cc
LP
37 [DEVICE_TENTATIVE] = UNIT_ACTIVATING,
38 [DEVICE_PLUGGED] = UNIT_ACTIVE,
f50e0a01
LP
39};
40
718db961
LP
41static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
42
8fe914ec 43static void device_unset_sysfs(Device *d) {
f1421cc6 44 Hashmap *devices;
8fe914ec
LP
45 Device *first;
46
47 assert(d);
48
a7f241db
LP
49 if (!d->sysfs)
50 return;
51
52 /* Remove this unit from the chain of devices which share the
53 * same sysfs path. */
f1421cc6
LP
54 devices = UNIT(d)->manager->devices_by_sysfs;
55 first = hashmap_get(devices, d->sysfs);
71fda00f 56 LIST_REMOVE(same_sysfs, first, d);
8fe914ec 57
a7f241db 58 if (first)
f1421cc6 59 hashmap_remove_and_replace(devices, d->sysfs, first->sysfs, first);
a7f241db 60 else
f1421cc6 61 hashmap_remove(devices, d->sysfs);
a7f241db
LP
62
63 free(d->sysfs);
64 d->sysfs = NULL;
8fe914ec
LP
65}
66
628c89cc
LP
67static int device_set_sysfs(Device *d, const char *sysfs) {
68 Device *first;
69 char *copy;
70 int r;
71
72 assert(d);
73
74 if (streq_ptr(d->sysfs, sysfs))
75 return 0;
76
77 r = hashmap_ensure_allocated(&UNIT(d)->manager->devices_by_sysfs, &string_hash_ops);
78 if (r < 0)
79 return r;
80
81 copy = strdup(sysfs);
82 if (!copy)
83 return -ENOMEM;
84
85 device_unset_sysfs(d);
86
87 first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, sysfs);
88 LIST_PREPEND(same_sysfs, first, d);
89
90 r = hashmap_replace(UNIT(d)->manager->devices_by_sysfs, copy, first);
91 if (r < 0) {
92 LIST_REMOVE(same_sysfs, first, d);
93 free(copy);
94 return r;
95 }
96
97 d->sysfs = copy;
98
99 return 0;
100}
101
faf919f1
LP
102static void device_init(Unit *u) {
103 Device *d = DEVICE(u);
104
105 assert(d);
1124fe6f 106 assert(UNIT(d)->load_state == UNIT_STUB);
faf919f1 107
8fe914ec
LP
108 /* In contrast to all other unit types we timeout jobs waiting
109 * for devices by default. This is because they otherwise wait
35b8ca3a 110 * indefinitely for plugged in devices, something which cannot
8fe914ec
LP
111 * happen for the other units since their operations time out
112 * anyway. */
f1421cc6 113 u->job_timeout = u->manager->default_timeout_start_usec;
c8f4d764 114
f1421cc6
LP
115 u->ignore_on_isolate = true;
116 u->ignore_on_snapshot = true;
faf919f1
LP
117}
118
87f0e418
LP
119static void device_done(Unit *u) {
120 Device *d = DEVICE(u);
034c6ed7
LP
121
122 assert(d);
e537352b 123
8fe914ec 124 device_unset_sysfs(d);
e537352b
LP
125}
126
f50e0a01
LP
127static void device_set_state(Device *d, DeviceState state) {
128 DeviceState old_state;
129 assert(d);
5cb5a6ff 130
f50e0a01
LP
131 old_state = d->state;
132 d->state = state;
5cb5a6ff 133
e537352b 134 if (state != old_state)
79008bdd 135 log_unit_debug(UNIT(d)->id,
66870f90
ZJS
136 "%s changed %s -> %s", UNIT(d)->id,
137 device_state_to_string(old_state),
138 device_state_to_string(state));
f50e0a01 139
e2f3b44c 140 unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
f50e0a01
LP
141}
142
be847e82 143static int device_coldplug(Unit *u) {
f50e0a01
LP
144 Device *d = DEVICE(u);
145
146 assert(d);
147 assert(d->state == DEVICE_DEAD);
148
628c89cc
LP
149 if (d->found & DEVICE_FOUND_UDEV)
150 /* If udev says the device is around, it's around */
73608ed9 151 device_set_state(d, DEVICE_PLUGGED);
f6200941 152 else if (d->found != DEVICE_NOT_FOUND && d->deserialized_state != DEVICE_PLUGGED)
628c89cc 153 /* If a device is found in /proc/self/mountinfo or
f6200941
LP
154 * /proc/swaps, and was not yet announced via udev,
155 * it's "tentatively" around. */
628c89cc 156 device_set_state(d, DEVICE_TENTATIVE);
f50e0a01
LP
157
158 return 0;
159}
160
f6200941
LP
161static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
162 Device *d = DEVICE(u);
163
164 assert(u);
165 assert(f);
166 assert(fds);
167
168 unit_serialize_item(u, f, "state", device_state_to_string(d->state));
0108f6ec
DM
169
170 return 0;
f6200941
LP
171}
172
173static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
174 Device *d = DEVICE(u);
175
176 assert(u);
177 assert(key);
178 assert(value);
179 assert(fds);
180
181 if (streq(key, "state")) {
182 DeviceState state;
183
184 state = device_state_from_string(value);
185 if (state < 0)
186 log_unit_debug(u->id, "Failed to parse state value %s", value);
187 else
188 d->deserialized_state = state;
189 } else
190 log_unit_debug(u->id, "Unknown serialization key '%s'", key);
191
192 return 0;
193}
194
f50e0a01 195static void device_dump(Unit *u, FILE *f, const char *prefix) {
25ac040b 196 Device *d = DEVICE(u);
5cb5a6ff 197
25ac040b 198 assert(d);
5cb5a6ff
LP
199
200 fprintf(f,
25ac040b
LP
201 "%sDevice State: %s\n"
202 "%sSysfs Path: %s\n",
a16e1123 203 prefix, device_state_to_string(d->state),
f50e0a01
LP
204 prefix, strna(d->sysfs));
205}
206
44a6b1b6 207_pure_ static UnitActiveState device_active_state(Unit *u) {
f50e0a01
LP
208 assert(u);
209
210 return state_translation_table[DEVICE(u)->state];
25ac040b
LP
211}
212
44a6b1b6 213_pure_ static const char *device_sub_state_to_string(Unit *u) {
10a94420
LP
214 assert(u);
215
a16e1123 216 return device_state_to_string(DEVICE(u)->state);
10a94420
LP
217}
218
628c89cc 219static int device_update_description(Unit *u, struct udev_device *dev, const char *path) {
965e5c5d 220 const char *model;
628c89cc 221 int r;
965e5c5d
LP
222
223 assert(u);
224 assert(dev);
225 assert(path);
226
227 model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE");
228 if (!model)
229 model = udev_device_get_property_value(dev, "ID_MODEL");
230
231 if (model) {
232 const char *label;
233
234 /* Try to concatenate the device model string with a label, if there is one */
235 label = udev_device_get_property_value(dev, "ID_FS_LABEL");
236 if (!label)
237 label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME");
238 if (!label)
239 label = udev_device_get_property_value(dev, "ID_PART_ENTRY_NUMBER");
240
241 if (label) {
242 _cleanup_free_ char *j;
243
244 j = strjoin(model, " ", label, NULL);
245 if (j)
628c89cc 246 r = unit_set_description(u, j);
c43b2132
TA
247 else
248 r = -ENOMEM;
628c89cc
LP
249 } else
250 r = unit_set_description(u, model);
251 } else
252 r = unit_set_description(u, path);
965e5c5d 253
628c89cc
LP
254 if (r < 0)
255 log_unit_error_errno(u->id, r, "Failed to set device description: %m");
965e5c5d 256
628c89cc 257 return r;
965e5c5d
LP
258}
259
260static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
261 const char *wants;
a2a5291b 262 const char *word, *state;
965e5c5d
LP
263 size_t l;
264 int r;
b2fadec6 265 const char *property;
965e5c5d
LP
266
267 assert(u);
268 assert(dev);
269
b2fadec6
ZJS
270 property = u->manager->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
271 wants = udev_device_get_property_value(dev, property);
965e5c5d
LP
272 if (!wants)
273 return 0;
274
a2a5291b 275 FOREACH_WORD_QUOTED(word, l, wants, state) {
965e5c5d
LP
276 _cleanup_free_ char *n = NULL;
277 char e[l+1];
278
a2a5291b 279 memcpy(e, word, l);
965e5c5d
LP
280 e[l] = 0;
281
282 n = unit_name_mangle(e, MANGLE_NOGLOB);
283 if (!n)
628c89cc 284 return log_oom();
965e5c5d
LP
285
286 r = unit_add_dependency_by_name(u, UNIT_WANTS, n, NULL, true);
287 if (r < 0)
628c89cc 288 return log_unit_error_errno(u->id, r, "Failed to add wants dependency: %m");
965e5c5d 289 }
b2fadec6 290 if (!isempty(state))
628c89cc 291 log_unit_warning(u->id, "Property %s on %s has trailing garbage, ignoring.", property, strna(udev_device_get_syspath(dev)));
965e5c5d
LP
292
293 return 0;
294}
295
628c89cc
LP
296static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
297 _cleanup_free_ char *e = NULL;
965e5c5d 298 const char *sysfs;
25ac040b 299 Unit *u = NULL;
25ac040b 300 bool delete;
965e5c5d 301 int r;
25ac040b
LP
302
303 assert(m);
965e5c5d
LP
304 assert(dev);
305 assert(path);
25ac040b 306
b47d419c
ZJS
307 sysfs = udev_device_get_syspath(dev);
308 if (!sysfs)
f1421cc6 309 return 0;
7f275a9f 310
628c89cc
LP
311 e = unit_name_from_path(path, ".device");
312 if (!e)
313 return log_oom();
314
315 u = manager_get_unit(m, e);
25ac040b 316
628c89cc
LP
317 if (u &&
318 DEVICE(u)->sysfs &&
319 !path_equal(DEVICE(u)->sysfs, sysfs)) {
5259bcf6 320 log_unit_debug(u->id, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs);
8fe914ec 321 return -EEXIST;
628c89cc 322 }
25ac040b 323
aab14b13
LP
324 if (!u) {
325 delete = true;
326
7d17cfbc
MS
327 u = unit_new(m, sizeof(Device));
328 if (!u)
f1421cc6 329 return log_oom();
25ac040b 330
628c89cc 331 r = unit_add_name(u, e);
7d17cfbc 332 if (r < 0)
25ac040b
LP
333 goto fail;
334
ee6cb288
LP
335 unit_add_to_load_queue(u);
336 } else
337 delete = false;
338
339 /* If this was created via some dependency and has not
340 * actually been seen yet ->sysfs will not be
341 * initialized. Hence initialize it if necessary. */
342
628c89cc
LP
343 r = device_set_sysfs(DEVICE(u), sysfs);
344 if (r < 0)
345 goto fail;
aab14b13 346
628c89cc 347 (void) device_update_description(u, dev, path);
25ac040b 348
628c89cc
LP
349 /* The additional systemd udev properties we only interpret
350 * for the main object */
351 if (main)
352 (void) device_add_udev_wants(u, dev);
f94ea366 353
f1421cc6
LP
354 /* Note that this won't dispatch the load queue, the caller
355 * has to do that if needed and appropriate */
356
c1e1601e 357 unit_add_to_dbus_queue(u);
25ac040b
LP
358 return 0;
359
360fail:
628c89cc 361 log_unit_warning_errno(u->id, r, "Failed to set up device unit: %m");
ee5f3479 362
2bb9e620 363 if (delete)
25ac040b 364 unit_free(u);
ee5f3479 365
25ac040b
LP
366 return r;
367}
368
628c89cc 369static int device_process_new(Manager *m, struct udev_device *dev) {
f1421cc6 370 const char *sysfs, *dn, *alias;
8fe914ec 371 struct udev_list_entry *item = NULL, *first = NULL;
003ac9d0 372 int r;
8fe914ec
LP
373
374 assert(m);
375
718db961
LP
376 sysfs = udev_device_get_syspath(dev);
377 if (!sysfs)
f1421cc6 378 return 0;
8fe914ec
LP
379
380 /* Add the main unit named after the sysfs path */
628c89cc 381 r = device_setup_unit(m, dev, sysfs, true);
003ac9d0
HH
382 if (r < 0)
383 return r;
8fe914ec
LP
384
385 /* Add an additional unit for the device node */
f1421cc6
LP
386 dn = udev_device_get_devnode(dev);
387 if (dn)
628c89cc 388 (void) device_setup_unit(m, dev, dn, false);
8fe914ec
LP
389
390 /* Add additional units for all symlinks */
391 first = udev_device_get_devlinks_list_entry(dev);
392 udev_list_entry_foreach(item, first) {
393 const char *p;
5845b46b 394 struct stat st;
8fe914ec
LP
395
396 /* Don't bother with the /dev/block links */
397 p = udev_list_entry_get_name(item);
398
399 if (path_startswith(p, "/dev/block/") ||
400 path_startswith(p, "/dev/char/"))
401 continue;
402
5845b46b
LP
403 /* Verify that the symlink in the FS actually belongs
404 * to this device. This is useful to deal with
405 * conflicting devices, e.g. when two disks want the
406 * same /dev/disk/by-label/xxx link because they have
407 * the same label. We want to make sure that the same
408 * device that won the symlink wins in systemd, so we
ee33e53a 409 * check the device node major/minor */
5845b46b
LP
410 if (stat(p, &st) >= 0)
411 if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
412 st.st_rdev != udev_device_get_devnum(dev))
413 continue;
414
628c89cc 415 (void) device_setup_unit(m, dev, p, false);
8fe914ec
LP
416 }
417
f1421cc6
LP
418 /* Add additional units for all explicitly configured
419 * aliases */
420 alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
421 if (alias) {
a2a5291b 422 const char *word, *state;
f1421cc6 423 size_t l;
8fe914ec 424
a2a5291b 425 FOREACH_WORD_QUOTED(word, l, alias, state) {
f1421cc6 426 char e[l+1];
8fe914ec 427
a2a5291b 428 memcpy(e, word, l);
f1421cc6
LP
429 e[l] = 0;
430
431 if (path_is_absolute(e))
628c89cc 432 (void) device_setup_unit(m, dev, e, false);
f1421cc6
LP
433 else
434 log_warning("SYSTEMD_ALIAS for %s is not an absolute path, ignoring: %s", sysfs, e);
435 }
b2fadec6
ZJS
436 if (!isempty(state))
437 log_warning("SYSTEMD_ALIAS for %s has trailing garbage, ignoring.", sysfs);
8fe914ec
LP
438 }
439
440 return 0;
441}
442
628c89cc 443static void device_update_found_one(Device *d, bool add, DeviceFound found, bool now) {
f6200941 444 DeviceFound n, previous;
628c89cc
LP
445
446 assert(d);
447
448 n = add ? (d->found | found) : (d->found & ~found);
449 if (n == d->found)
450 return;
451
f6200941 452 previous = d->found;
628c89cc
LP
453 d->found = n;
454
f6200941
LP
455 if (!now)
456 return;
457
458 if (d->found & DEVICE_FOUND_UDEV)
459 /* When the device is known to udev we consider it
460 * plugged. */
461 device_set_state(d, DEVICE_PLUGGED);
462 else if (d->found != DEVICE_NOT_FOUND && (previous & DEVICE_FOUND_UDEV) == 0)
463 /* If the device has not been seen by udev yet, but is
464 * now referenced by the kernel, then we assume the
465 * kernel knows it now, and udev might soon too. */
466 device_set_state(d, DEVICE_TENTATIVE);
467 else
468 /* If nobody sees the device, or if the device was
469 * previously seen by udev and now is only referenced
470 * from the kernel, then we consider the device is
471 * gone, the kernel just hasn't noticed it yet. */
472 device_set_state(d, DEVICE_DEAD);
628c89cc
LP
473}
474
475static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
f1421cc6 476 Device *d, *l;
25ac040b
LP
477
478 assert(m);
628c89cc 479 assert(sysfs);
25ac040b 480
628c89cc
LP
481 if (found == DEVICE_NOT_FOUND)
482 return 0;
25ac040b 483
f1421cc6
LP
484 l = hashmap_get(m->devices_by_sysfs, sysfs);
485 LIST_FOREACH(same_sysfs, d, l)
628c89cc
LP
486 device_update_found_one(d, add, found, now);
487
488 return 0;
25ac040b
LP
489}
490
628c89cc
LP
491static int device_update_found_by_name(Manager *m, const char *path, bool add, DeviceFound found, bool now) {
492 _cleanup_free_ char *e = NULL;
493 Unit *u;
f94ea366
LP
494
495 assert(m);
628c89cc 496 assert(path);
f94ea366 497
628c89cc
LP
498 if (found == DEVICE_NOT_FOUND)
499 return 0;
f94ea366 500
628c89cc
LP
501 e = unit_name_from_path(path, ".device");
502 if (!e)
503 return log_oom();
f94ea366 504
628c89cc
LP
505 u = manager_get_unit(m, e);
506 if (!u)
507 return 0;
508
509 device_update_found_one(DEVICE(u), add, found, now);
f94ea366
LP
510 return 0;
511}
512
f1421cc6
LP
513static bool device_is_ready(struct udev_device *dev) {
514 const char *ready;
515
516 assert(dev);
517
518 ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
519 if (!ready)
520 return true;
521
522 return parse_boolean(ready) != 0;
523}
524
a7f241db
LP
525static Unit *device_following(Unit *u) {
526 Device *d = DEVICE(u);
527 Device *other, *first = NULL;
528
529 assert(d);
530
ac155bb8 531 if (startswith(u->id, "sys-"))
a7f241db
LP
532 return NULL;
533
534 /* Make everybody follow the unit that's named after the sysfs path */
535 for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
1124fe6f 536 if (startswith(UNIT(other)->id, "sys-"))
a7f241db
LP
537 return UNIT(other);
538
539 for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
1124fe6f 540 if (startswith(UNIT(other)->id, "sys-"))
a7f241db
LP
541 return UNIT(other);
542
543 first = other;
544 }
545
546 return UNIT(first);
547}
548
f1421cc6
LP
549static int device_following_set(Unit *u, Set **_set) {
550 Device *d = DEVICE(u), *other;
551 Set *set;
6210e7fc
LP
552 int r;
553
554 assert(d);
f1421cc6 555 assert(_set);
6210e7fc 556
f1421cc6
LP
557 if (LIST_JUST_US(same_sysfs, d)) {
558 *_set = NULL;
6210e7fc
LP
559 return 0;
560 }
561
d5099efc 562 set = set_new(NULL);
f1421cc6 563 if (!set)
6210e7fc
LP
564 return -ENOMEM;
565
f1421cc6
LP
566 LIST_FOREACH_AFTER(same_sysfs, other, d) {
567 r = set_put(set, other);
568 if (r < 0)
6210e7fc 569 goto fail;
f1421cc6 570 }
6210e7fc 571
f1421cc6
LP
572 LIST_FOREACH_BEFORE(same_sysfs, other, d) {
573 r = set_put(set, other);
574 if (r < 0)
6210e7fc 575 goto fail;
f1421cc6 576 }
6210e7fc 577
f1421cc6 578 *_set = set;
6210e7fc
LP
579 return 1;
580
581fail:
f1421cc6 582 set_free(set);
6210e7fc
LP
583 return r;
584}
585
25ac040b
LP
586static void device_shutdown(Manager *m) {
587 assert(m);
588
718db961
LP
589 m->udev_event_source = sd_event_source_unref(m->udev_event_source);
590
a16e1123 591 if (m->udev_monitor) {
f94ea366 592 udev_monitor_unref(m->udev_monitor);
a16e1123
LP
593 m->udev_monitor = NULL;
594 }
f94ea366 595
8fe914ec
LP
596 hashmap_free(m->devices_by_sysfs);
597 m->devices_by_sysfs = NULL;
25ac040b
LP
598}
599
600static int device_enumerate(Manager *m) {
718db961 601 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
25ac040b 602 struct udev_list_entry *item = NULL, *first = NULL;
718db961 603 int r;
25ac040b
LP
604
605 assert(m);
606
9670d583 607 if (!m->udev_monitor) {
718db961
LP
608 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
609 if (!m->udev_monitor) {
a16e1123
LP
610 r = -ENOMEM;
611 goto fail;
612 }
f94ea366 613
47ae6e67
LP
614 /* This will fail if we are unprivileged, but that
615 * should not matter much, as user instances won't run
616 * during boot. */
8fa158e7 617 (void) udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
99448c1f 618
718db961
LP
619 r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
620 if (r < 0)
e1ce2c27 621 goto fail;
e1ce2c27 622
718db961
LP
623 r = udev_monitor_enable_receiving(m->udev_monitor);
624 if (r < 0)
a16e1123 625 goto fail;
f94ea366 626
151b9b96 627 r = sd_event_add_io(m->event, &m->udev_event_source, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m);
718db961
LP
628 if (r < 0)
629 goto fail;
7dfbe2e3
TG
630
631 (void) sd_event_source_set_description(m->udev_event_source, "device");
a16e1123 632 }
f94ea366 633
718db961
LP
634 e = udev_enumerate_new(m->udev);
635 if (!e) {
4f2d528d
LP
636 r = -ENOMEM;
637 goto fail;
638 }
718db961
LP
639
640 r = udev_enumerate_add_match_tag(e, "systemd");
641 if (r < 0)
e1ce2c27 642 goto fail;
25ac040b 643
e1202047
LP
644 r = udev_enumerate_add_match_is_initialized(e);
645 if (r < 0)
646 goto fail;
647
718db961
LP
648 r = udev_enumerate_scan_devices(e);
649 if (r < 0)
4f2d528d 650 goto fail;
25ac040b 651
4f2d528d 652 first = udev_enumerate_get_list_entry(e);
628c89cc
LP
653 udev_list_entry_foreach(item, first) {
654 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
655 const char *sysfs;
656
657 sysfs = udev_list_entry_get_name(item);
658
659 dev = udev_device_new_from_syspath(m->udev, sysfs);
660 if (!dev) {
661 log_oom();
662 continue;
663 }
664
665 if (!device_is_ready(dev))
666 continue;
667
668 (void) device_process_new(m, dev);
669
670 device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false);
671 }
25ac040b 672
25ac040b
LP
673 return 0;
674
675fail:
628c89cc
LP
676 log_error_errno(r, "Failed to enumerate devices: %m");
677
25ac040b
LP
678 device_shutdown(m);
679 return r;
5cb5a6ff
LP
680}
681
718db961
LP
682static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
683 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
718db961 684 Manager *m = userdata;
628c89cc 685 const char *action, *sysfs;
718db961 686 int r;
f94ea366
LP
687
688 assert(m);
99448c1f 689
718db961 690 if (revents != EPOLLIN) {
99448c1f
KS
691 static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
692
693 if (!ratelimit_test(&limit))
56f64d95 694 log_error_errno(errno, "Failed to get udev event: %m");
718db961
LP
695 if (!(revents & EPOLLIN))
696 return 0;
99448c1f 697 }
f94ea366 698
718db961
LP
699 /*
700 * libudev might filter-out devices which pass the bloom
701 * filter, so getting NULL here is not necessarily an error.
702 */
703 dev = udev_monitor_receive_device(m->udev_monitor);
704 if (!dev)
705 return 0;
f94ea366 706
628c89cc
LP
707 sysfs = udev_device_get_syspath(dev);
708 if (!sysfs) {
709 log_error("Failed to get udev sys path.");
710 return 0;
711 }
712
718db961
LP
713 action = udev_device_get_action(dev);
714 if (!action) {
f94ea366 715 log_error("Failed to get udev action string.");
718db961 716 return 0;
f94ea366
LP
717 }
718
628c89cc
LP
719 if (streq(action, "remove")) {
720 r = swap_process_device_remove(m, dev);
9670d583 721 if (r < 0)
da927ba9 722 log_error_errno(r, "Failed to process swap device remove event: %m");
9670d583 723
628c89cc
LP
724 /* If we get notified that a device was removed by
725 * udev, then it's completely gone, hence unset all
726 * found bits */
727 device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP, true);
f1421cc6 728
628c89cc
LP
729 } else if (device_is_ready(dev)) {
730
731 (void) device_process_new(m, dev);
732
733 r = swap_process_device_new(m, dev);
9670d583 734 if (r < 0)
da927ba9 735 log_error_errno(r, "Failed to process swap device new event: %m");
9670d583 736
f1421cc6
LP
737 manager_dispatch_load_queue(m);
738
628c89cc
LP
739 /* The device is found now, set the udev found bit */
740 device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, true);
741
742 } else {
743 /* The device is nominally around, but not ready for
744 * us. Hence unset the udev bit, but leave the rest
745 * around. */
746
747 device_update_found_by_sysfs(m, sysfs, false, DEVICE_FOUND_UDEV, true);
f94ea366
LP
748 }
749
718db961 750 return 0;
f94ea366
LP
751}
752
0faacd47
LP
753static bool device_supported(Manager *m) {
754 static int read_only = -1;
755 assert(m);
756
757 /* If /sys is read-only we don't support device units, and any
758 * attempts to start one should fail immediately. */
759
760 if (read_only < 0)
761 read_only = path_is_read_only_fs("/sys");
762
763 return read_only <= 0;
764}
765
628c89cc
LP
766int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now) {
767 _cleanup_udev_device_unref_ struct udev_device *dev = NULL;
768 struct stat st;
769
770 assert(m);
771 assert(node);
772
773 /* This is called whenever we find a device referenced in
774 * /proc/swaps or /proc/self/mounts. Such a device might be
775 * mounted/enabled at a time where udev has not finished
776 * probing it yet, and we thus haven't learned about it
777 * yet. In this case we will set the device unit to
778 * "tentative" state. */
779
780 if (add) {
781 if (!path_startswith(node, "/dev"))
782 return 0;
783
f6200941
LP
784 /* We make an extra check here, if the device node
785 * actually exists. If it's missing, then this is an
786 * indication that device was unplugged but is still
787 * referenced in /proc/swaps or
788 * /proc/self/mountinfo. Note that this check doesn't
789 * really cover all cases where a device might be gone
790 * away, since drives that can have a medium inserted
791 * will still have a device node even when the medium
792 * is not there... */
793
628c89cc
LP
794 if (stat(node, &st) < 0) {
795 if (errno == ENOENT)
796 return 0;
797
798 return log_error_errno(errno, "Failed to stat device node file %s: %m", node);
799 }
800
801 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
802 return 0;
803
804 dev = udev_device_new_from_devnum(m->udev, S_ISBLK(st.st_mode) ? 'b' : 'c', st.st_rdev);
805 if (!dev) {
806 if (errno == ENOENT)
807 return 0;
808
809 return log_oom();
810 }
811
812 /* If the device is known in the kernel and newly
813 * appeared, then we'll create a device unit for it,
814 * under the name referenced in /proc/swaps or
815 * /proc/self/mountinfo. */
816
817 (void) device_setup_unit(m, dev, node, false);
818 }
819
820 /* Update the device unit's state, should it exist */
821 return device_update_found_by_name(m, node, add, found, now);
822}
823
a16e1123
LP
824static const char* const device_state_table[_DEVICE_STATE_MAX] = {
825 [DEVICE_DEAD] = "dead",
628c89cc
LP
826 [DEVICE_TENTATIVE] = "tentative",
827 [DEVICE_PLUGGED] = "plugged",
a16e1123
LP
828};
829
830DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
831
87f0e418 832const UnitVTable device_vtable = {
7d17cfbc 833 .object_size = sizeof(Device),
f975e971
LP
834 .sections =
835 "Unit\0"
836 "Device\0"
837 "Install\0",
5cb5a6ff 838
9e2f7c11
LP
839 .no_instances = true,
840
faf919f1 841 .init = device_init,
034c6ed7 842 .done = device_done,
718db961
LP
843 .load = unit_load_fragment_and_dropin_optional,
844
f50e0a01
LP
845 .coldplug = device_coldplug,
846
f6200941
LP
847 .serialize = device_serialize,
848 .deserialize_item = device_deserialize_item,
849
5cb5a6ff
LP
850 .dump = device_dump,
851
f50e0a01 852 .active_state = device_active_state,
10a94420 853 .sub_state_to_string = device_sub_state_to_string,
25ac040b 854
c4e2ceae 855 .bus_interface = "org.freedesktop.systemd1.Device",
718db961 856 .bus_vtable = bus_device_vtable,
4139c1b2 857
a7f241db 858 .following = device_following,
6210e7fc 859 .following_set = device_following_set,
a7f241db 860
f50e0a01 861 .enumerate = device_enumerate,
c6918296 862 .shutdown = device_shutdown,
0faacd47 863 .supported = device_supported,
c6918296
MS
864
865 .status_message_formats = {
866 .starting_stopping = {
867 [0] = "Expecting device %s...",
868 },
869 .finished_start_job = {
870 [JOB_DONE] = "Found device %s.",
871 [JOB_TIMEOUT] = "Timed out waiting for device %s.",
872 },
873 },
5cb5a6ff 874};