]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/device.c
treewide: auto-convert the simple cases to log_*_errno()
[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
5cb5a6ff 26#include "strv.h"
25ac040b 27#include "log.h"
9e2f7c11 28#include "unit-name.h"
4139c1b2 29#include "dbus-device.h"
f6a6225e 30#include "def.h"
9eb977db 31#include "path-util.h"
718db961 32#include "udev-util.h"
9670d583
LP
33#include "unit.h"
34#include "swap.h"
35#include "device.h"
5cb5a6ff 36
f50e0a01
LP
37static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
38 [DEVICE_DEAD] = UNIT_INACTIVE,
73608ed9 39 [DEVICE_PLUGGED] = UNIT_ACTIVE
f50e0a01
LP
40};
41
718db961
LP
42static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
43
8fe914ec 44static void device_unset_sysfs(Device *d) {
f1421cc6 45 Hashmap *devices;
8fe914ec
LP
46 Device *first;
47
48 assert(d);
49
a7f241db
LP
50 if (!d->sysfs)
51 return;
52
53 /* Remove this unit from the chain of devices which share the
54 * same sysfs path. */
f1421cc6
LP
55 devices = UNIT(d)->manager->devices_by_sysfs;
56 first = hashmap_get(devices, d->sysfs);
71fda00f 57 LIST_REMOVE(same_sysfs, first, d);
8fe914ec 58
a7f241db 59 if (first)
f1421cc6 60 hashmap_remove_and_replace(devices, d->sysfs, first->sysfs, first);
a7f241db 61 else
f1421cc6 62 hashmap_remove(devices, d->sysfs);
a7f241db
LP
63
64 free(d->sysfs);
65 d->sysfs = NULL;
8fe914ec
LP
66}
67
faf919f1
LP
68static void device_init(Unit *u) {
69 Device *d = DEVICE(u);
70
71 assert(d);
1124fe6f 72 assert(UNIT(d)->load_state == UNIT_STUB);
faf919f1 73
8fe914ec
LP
74 /* In contrast to all other unit types we timeout jobs waiting
75 * for devices by default. This is because they otherwise wait
35b8ca3a 76 * indefinitely for plugged in devices, something which cannot
8fe914ec
LP
77 * happen for the other units since their operations time out
78 * anyway. */
f1421cc6 79 u->job_timeout = u->manager->default_timeout_start_usec;
c8f4d764 80
f1421cc6
LP
81 u->ignore_on_isolate = true;
82 u->ignore_on_snapshot = true;
faf919f1
LP
83}
84
87f0e418
LP
85static void device_done(Unit *u) {
86 Device *d = DEVICE(u);
034c6ed7
LP
87
88 assert(d);
e537352b 89
8fe914ec 90 device_unset_sysfs(d);
e537352b
LP
91}
92
f50e0a01
LP
93static void device_set_state(Device *d, DeviceState state) {
94 DeviceState old_state;
95 assert(d);
5cb5a6ff 96
f50e0a01
LP
97 old_state = d->state;
98 d->state = state;
5cb5a6ff 99
e537352b 100 if (state != old_state)
79008bdd 101 log_unit_debug(UNIT(d)->id,
66870f90
ZJS
102 "%s changed %s -> %s", UNIT(d)->id,
103 device_state_to_string(old_state),
104 device_state_to_string(state));
f50e0a01 105
e2f3b44c 106 unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
f50e0a01
LP
107}
108
109static 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)
73608ed9 116 device_set_state(d, DEVICE_PLUGGED);
f50e0a01
LP
117
118 return 0;
119}
120
121static void device_dump(Unit *u, FILE *f, const char *prefix) {
25ac040b 122 Device *d = DEVICE(u);
5cb5a6ff 123
25ac040b 124 assert(d);
5cb5a6ff
LP
125
126 fprintf(f,
25ac040b
LP
127 "%sDevice State: %s\n"
128 "%sSysfs Path: %s\n",
a16e1123 129 prefix, device_state_to_string(d->state),
f50e0a01
LP
130 prefix, strna(d->sysfs));
131}
132
44a6b1b6 133_pure_ static UnitActiveState device_active_state(Unit *u) {
f50e0a01
LP
134 assert(u);
135
136 return state_translation_table[DEVICE(u)->state];
25ac040b
LP
137}
138
44a6b1b6 139_pure_ static const char *device_sub_state_to_string(Unit *u) {
10a94420
LP
140 assert(u);
141
a16e1123 142 return device_state_to_string(DEVICE(u)->state);
10a94420
LP
143}
144
8fe914ec 145static int device_add_escaped_name(Unit *u, const char *dn) {
718db961 146 _cleanup_free_ char *e = NULL;
25ac040b
LP
147 int r;
148
149 assert(u);
150 assert(dn);
151 assert(dn[0] == '/');
152
b0193f1c
LP
153 e = unit_name_from_path(dn, ".device");
154 if (!e)
25ac040b
LP
155 return -ENOMEM;
156
157 r = unit_add_name(u, e);
25ac040b
LP
158 if (r < 0 && r != -EEXIST)
159 return r;
160
161 return 0;
162}
163
aab14b13 164static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
718db961 165 _cleanup_free_ char *e = NULL;
aab14b13
LP
166 Unit *u;
167
168 assert(m);
169 assert(dn);
170 assert(dn[0] == '/');
171 assert(_u);
172
b0193f1c
LP
173 e = unit_name_from_path(dn, ".device");
174 if (!e)
aab14b13
LP
175 return -ENOMEM;
176
177 u = manager_get_unit(m, e);
aab14b13
LP
178 if (u) {
179 *_u = u;
180 return 1;
181 }
182
183 return 0;
184}
185
965e5c5d
LP
186static 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
221static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
222 const char *wants;
a2a5291b 223 const char *word, *state;
965e5c5d
LP
224 size_t l;
225 int r;
b2fadec6 226 const char *property;
965e5c5d
LP
227
228 assert(u);
229 assert(dev);
230
b2fadec6
ZJS
231 property = u->manager->running_as == SYSTEMD_USER ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS";
232 wants = udev_device_get_property_value(dev, property);
965e5c5d
LP
233 if (!wants)
234 return 0;
235
a2a5291b 236 FOREACH_WORD_QUOTED(word, l, wants, state) {
965e5c5d
LP
237 _cleanup_free_ char *n = NULL;
238 char e[l+1];
239
a2a5291b 240 memcpy(e, word, l);
965e5c5d
LP
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 }
b2fadec6 251 if (!isempty(state))
79008bdd 252 log_unit_warning(u->id, "Property %s on %s has trailing garbage, ignoring.",
b2fadec6 253 property, strna(udev_device_get_syspath(dev)));
965e5c5d
LP
254
255 return 0;
256}
257
8fe914ec 258static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
965e5c5d 259 const char *sysfs;
25ac040b 260 Unit *u = NULL;
25ac040b 261 bool delete;
965e5c5d 262 int r;
25ac040b
LP
263
264 assert(m);
965e5c5d
LP
265 assert(dev);
266 assert(path);
25ac040b 267
b47d419c
ZJS
268 sysfs = udev_device_get_syspath(dev);
269 if (!sysfs)
f1421cc6 270 return 0;
7f275a9f 271
b47d419c
ZJS
272 r = device_find_escape_name(m, path, &u);
273 if (r < 0)
aab14b13 274 return r;
25ac040b 275
5845b46b 276 if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
8fe914ec 277 return -EEXIST;
25ac040b 278
aab14b13
LP
279 if (!u) {
280 delete = true;
281
7d17cfbc
MS
282 u = unit_new(m, sizeof(Device));
283 if (!u)
f1421cc6 284 return log_oom();
25ac040b 285
7d17cfbc
MS
286 r = device_add_escaped_name(u, path);
287 if (r < 0)
25ac040b
LP
288 goto fail;
289
ee6cb288
LP
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
718db961
LP
301 DEVICE(u)->sysfs = strdup(sysfs);
302 if (!DEVICE(u)->sysfs) {
25ac040b
LP
303 r = -ENOMEM;
304 goto fail;
305 }
306
d5099efc 307 r = hashmap_ensure_allocated(&m->devices_by_sysfs, &string_hash_ops);
718db961
LP
308 if (r < 0)
309 goto fail;
25ac040b 310
8fe914ec 311 first = hashmap_get(m->devices_by_sysfs, sysfs);
71fda00f 312 LIST_PREPEND(same_sysfs, first, DEVICE(u));
8fe914ec 313
b47d419c
ZJS
314 r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first);
315 if (r < 0)
25ac040b 316 goto fail;
ee6cb288 317 }
8fe914ec 318
965e5c5d 319 device_make_description(u, dev, path);
aab14b13 320
8fe914ec
LP
321 if (main) {
322 /* The additional systemd udev properties we only
323 * interpret for the main object */
25ac040b 324
965e5c5d
LP
325 r = device_add_udev_wants(u, dev);
326 if (r < 0)
327 goto fail;
a7f241db 328 }
f94ea366 329
f1421cc6
LP
330 /* Note that this won't dispatch the load queue, the caller
331 * has to do that if needed and appropriate */
332
c1e1601e 333 unit_add_to_dbus_queue(u);
25ac040b
LP
334 return 0;
335
336fail:
0a1beeb6 337 log_warning_errno(-r, "Failed to load device unit: %m");
ee5f3479 338
25ac040b
LP
339 if (delete && u)
340 unit_free(u);
ee5f3479 341
25ac040b
LP
342 return r;
343}
344
f1421cc6
LP
345static int device_process_new_device(Manager *m, struct udev_device *dev) {
346 const char *sysfs, *dn, *alias;
8fe914ec 347 struct udev_list_entry *item = NULL, *first = NULL;
003ac9d0 348 int r;
8fe914ec
LP
349
350 assert(m);
351
718db961
LP
352 sysfs = udev_device_get_syspath(dev);
353 if (!sysfs)
f1421cc6 354 return 0;
8fe914ec
LP
355
356 /* Add the main unit named after the sysfs path */
003ac9d0
HH
357 r = device_update_unit(m, dev, sysfs, true);
358 if (r < 0)
359 return r;
8fe914ec
LP
360
361 /* Add an additional unit for the device node */
f1421cc6
LP
362 dn = udev_device_get_devnode(dev);
363 if (dn)
8fe914ec
LP
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;
5845b46b 370 struct stat st;
8fe914ec
LP
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
5845b46b
LP
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
8fe914ec
LP
391 device_update_unit(m, dev, p, false);
392 }
393
f1421cc6
LP
394 /* Add additional units for all explicitly configured
395 * aliases */
396 alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
397 if (alias) {
a2a5291b 398 const char *word, *state;
f1421cc6 399 size_t l;
8fe914ec 400
a2a5291b 401 FOREACH_WORD_QUOTED(word, l, alias, state) {
f1421cc6 402 char e[l+1];
8fe914ec 403
a2a5291b 404 memcpy(e, word, l);
f1421cc6
LP
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 }
b2fadec6
ZJS
412 if (!isempty(state))
413 log_warning("SYSTEMD_ALIAS for %s has trailing garbage, ignoring.", sysfs);
8fe914ec
LP
414 }
415
416 return 0;
417}
418
f1421cc6
LP
419static void device_set_path_plugged(Manager *m, struct udev_device *dev) {
420 const char *sysfs;
421 Device *d, *l;
25ac040b
LP
422
423 assert(m);
f1421cc6 424 assert(dev);
25ac040b 425
f1421cc6
LP
426 sysfs = udev_device_get_syspath(dev);
427 if (!sysfs)
428 return;
25ac040b 429
f1421cc6
LP
430 l = hashmap_get(m->devices_by_sysfs, sysfs);
431 LIST_FOREACH(same_sysfs, d, l)
432 device_set_state(d, DEVICE_PLUGGED);
25ac040b
LP
433}
434
f94ea366
LP
435static int device_process_removed_device(Manager *m, struct udev_device *dev) {
436 const char *sysfs;
f94ea366
LP
437 Device *d;
438
439 assert(m);
440 assert(dev);
441
f1421cc6
LP
442 sysfs = udev_device_get_syspath(dev);
443 if (!sysfs)
f94ea366
LP
444 return -ENOMEM;
445
8fe914ec
LP
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 }
f94ea366 451
f94ea366
LP
452 return 0;
453}
454
f1421cc6
LP
455static 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
467static 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
a7f241db
LP
483static Unit *device_following(Unit *u) {
484 Device *d = DEVICE(u);
485 Device *other, *first = NULL;
486
487 assert(d);
488
ac155bb8 489 if (startswith(u->id, "sys-"))
a7f241db
LP
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)
1124fe6f 494 if (startswith(UNIT(other)->id, "sys-"))
a7f241db
LP
495 return UNIT(other);
496
497 for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
1124fe6f 498 if (startswith(UNIT(other)->id, "sys-"))
a7f241db
LP
499 return UNIT(other);
500
501 first = other;
502 }
503
504 return UNIT(first);
505}
506
f1421cc6
LP
507static int device_following_set(Unit *u, Set **_set) {
508 Device *d = DEVICE(u), *other;
509 Set *set;
6210e7fc
LP
510 int r;
511
512 assert(d);
f1421cc6 513 assert(_set);
6210e7fc 514
f1421cc6
LP
515 if (LIST_JUST_US(same_sysfs, d)) {
516 *_set = NULL;
6210e7fc
LP
517 return 0;
518 }
519
d5099efc 520 set = set_new(NULL);
f1421cc6 521 if (!set)
6210e7fc
LP
522 return -ENOMEM;
523
f1421cc6
LP
524 LIST_FOREACH_AFTER(same_sysfs, other, d) {
525 r = set_put(set, other);
526 if (r < 0)
6210e7fc 527 goto fail;
f1421cc6 528 }
6210e7fc 529
f1421cc6
LP
530 LIST_FOREACH_BEFORE(same_sysfs, other, d) {
531 r = set_put(set, other);
532 if (r < 0)
6210e7fc 533 goto fail;
f1421cc6 534 }
6210e7fc 535
f1421cc6 536 *_set = set;
6210e7fc
LP
537 return 1;
538
539fail:
f1421cc6 540 set_free(set);
6210e7fc
LP
541 return r;
542}
543
25ac040b
LP
544static void device_shutdown(Manager *m) {
545 assert(m);
546
718db961
LP
547 m->udev_event_source = sd_event_source_unref(m->udev_event_source);
548
a16e1123 549 if (m->udev_monitor) {
f94ea366 550 udev_monitor_unref(m->udev_monitor);
a16e1123
LP
551 m->udev_monitor = NULL;
552 }
f94ea366 553
8fe914ec
LP
554 hashmap_free(m->devices_by_sysfs);
555 m->devices_by_sysfs = NULL;
25ac040b
LP
556}
557
558static int device_enumerate(Manager *m) {
718db961 559 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
25ac040b 560 struct udev_list_entry *item = NULL, *first = NULL;
718db961 561 int r;
25ac040b
LP
562
563 assert(m);
564
9670d583 565 if (!m->udev_monitor) {
718db961
LP
566 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
567 if (!m->udev_monitor) {
a16e1123
LP
568 r = -ENOMEM;
569 goto fail;
570 }
f94ea366 571
47ae6e67
LP
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);
99448c1f 576
718db961
LP
577 r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd");
578 if (r < 0)
e1ce2c27 579 goto fail;
e1ce2c27 580
718db961
LP
581 r = udev_monitor_enable_receiving(m->udev_monitor);
582 if (r < 0)
a16e1123 583 goto fail;
f94ea366 584
151b9b96 585 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
586 if (r < 0)
587 goto fail;
a16e1123 588 }
f94ea366 589
718db961
LP
590 e = udev_enumerate_new(m->udev);
591 if (!e) {
4f2d528d
LP
592 r = -ENOMEM;
593 goto fail;
594 }
718db961
LP
595
596 r = udev_enumerate_add_match_tag(e, "systemd");
597 if (r < 0)
e1ce2c27 598 goto fail;
25ac040b 599
e1202047
LP
600 r = udev_enumerate_add_match_is_initialized(e);
601 if (r < 0)
602 goto fail;
603
718db961
LP
604 r = udev_enumerate_scan_devices(e);
605 if (r < 0)
4f2d528d 606 goto fail;
25ac040b 607
4f2d528d
LP
608 first = udev_enumerate_get_list_entry(e);
609 udev_list_entry_foreach(item, first)
f1421cc6 610 device_process_new_path(m, udev_list_entry_get_name(item));
25ac040b 611
25ac040b
LP
612 return 0;
613
614fail:
25ac040b
LP
615 device_shutdown(m);
616 return r;
5cb5a6ff
LP
617}
618
718db961
LP
619static 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;
718db961 621 Manager *m = userdata;
f1421cc6 622 const char *action;
718db961 623 int r;
f94ea366
LP
624
625 assert(m);
99448c1f 626
718db961 627 if (revents != EPOLLIN) {
99448c1f
KS
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");
718db961
LP
632 if (!(revents & EPOLLIN))
633 return 0;
99448c1f 634 }
f94ea366 635
718db961
LP
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;
f94ea366 643
718db961
LP
644 action = udev_device_get_action(dev);
645 if (!action) {
f94ea366 646 log_error("Failed to get udev action string.");
718db961 647 return 0;
f94ea366
LP
648 }
649
f1421cc6 650 if (streq(action, "remove") || !device_is_ready(dev)) {
718db961
LP
651 r = device_process_removed_device(m, dev);
652 if (r < 0)
0a1beeb6 653 log_error_errno(-r, "Failed to process device remove event: %m");
9670d583
LP
654
655 r = swap_process_removed_device(m, dev);
656 if (r < 0)
0a1beeb6 657 log_error_errno(-r, "Failed to process swap device remove event: %m");
9670d583 658
f94ea366 659 } else {
f1421cc6 660 r = device_process_new_device(m, dev);
718db961 661 if (r < 0)
0a1beeb6 662 log_error_errno(-r, "Failed to process device new event: %m");
f1421cc6 663
9670d583
LP
664 r = swap_process_new_device(m, dev);
665 if (r < 0)
0a1beeb6 666 log_error_errno(-r, "Failed to process swap device new event: %m");
9670d583 667
f1421cc6
LP
668 manager_dispatch_load_queue(m);
669
670 device_set_path_plugged(m, dev);
f94ea366
LP
671 }
672
718db961 673 return 0;
f94ea366
LP
674}
675
a16e1123
LP
676static const char* const device_state_table[_DEVICE_STATE_MAX] = {
677 [DEVICE_DEAD] = "dead",
73608ed9 678 [DEVICE_PLUGGED] = "plugged"
a16e1123
LP
679};
680
681DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
682
87f0e418 683const UnitVTable device_vtable = {
7d17cfbc 684 .object_size = sizeof(Device),
f975e971
LP
685 .sections =
686 "Unit\0"
687 "Device\0"
688 "Install\0",
5cb5a6ff 689
9e2f7c11
LP
690 .no_instances = true,
691
faf919f1 692 .init = device_init,
034c6ed7 693 .done = device_done,
718db961
LP
694 .load = unit_load_fragment_and_dropin_optional,
695
f50e0a01
LP
696 .coldplug = device_coldplug,
697
5cb5a6ff
LP
698 .dump = device_dump,
699
f50e0a01 700 .active_state = device_active_state,
10a94420 701 .sub_state_to_string = device_sub_state_to_string,
25ac040b 702
c4e2ceae 703 .bus_interface = "org.freedesktop.systemd1.Device",
718db961 704 .bus_vtable = bus_device_vtable,
4139c1b2 705
a7f241db 706 .following = device_following,
6210e7fc 707 .following_set = device_following_set,
a7f241db 708
f50e0a01 709 .enumerate = device_enumerate,
c6918296
MS
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 },
5cb5a6ff 721};