diff options
Diffstat (limited to 'src/core/device.c')
-rw-r--r-- | src/core/device.c | 95 |
1 files changed, 52 insertions, 43 deletions
diff --git a/src/core/device.c b/src/core/device.c index e7efcf0f0a..8a3e888e5e 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -21,16 +19,21 @@ #include <errno.h> #include <sys/epoll.h> -#include <libudev.h> -#include "log.h" -#include "unit-name.h" +#include "libudev.h" + +#include "alloc-util.h" #include "dbus-device.h" +#include "device.h" +#include "log.h" +#include "parse-util.h" #include "path-util.h" +#include "stat-util.h" +#include "string-util.h" +#include "swap.h" #include "udev-util.h" +#include "unit-name.h" #include "unit.h" -#include "swap.h" -#include "device.h" static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = { [DEVICE_DEAD] = UNIT_INACTIVE, @@ -60,8 +63,7 @@ static void device_unset_sysfs(Device *d) { else hashmap_remove(devices, d->sysfs); - free(d->sysfs); - d->sysfs = NULL; + d->sysfs = mfree(d->sysfs); } static int device_set_sysfs(Device *d, const char *sysfs) { @@ -113,7 +115,6 @@ static void device_init(Unit *u) { u->job_timeout = u->manager->default_timeout_start_usec; u->ignore_on_isolate = true; - u->ignore_on_snapshot = true; } static void device_done(Unit *u) { @@ -264,7 +265,7 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) { assert(u); assert(dev); - property = u->manager->running_as == MANAGER_USER ? "MANAGER_USER_WANTS" : "SYSTEMD_WANTS"; + property = MANAGER_IS_USER(u->manager) ? "SYSTEMD_USER_WANTS" : "SYSTEMD_WANTS"; wants = udev_device_get_property_value(dev, property); if (!wants) return 0; @@ -312,12 +313,19 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa u = manager_get_unit(m, e); - if (u && - sysfs && - DEVICE(u)->sysfs && - !path_equal(DEVICE(u)->sysfs, sysfs)) { - log_unit_debug(u, "Device %s appeared twice with different sysfs paths %s and %s", e, DEVICE(u)->sysfs, sysfs); - return -EEXIST; + /* The device unit can still be present even if the device was + * unplugged: a mount unit can reference it hence preventing + * the GC to have garbaged it. That's desired since the device + * unit may have a dependency on the mount unit which was + * added during the loading of the later. */ + if (dev && u && DEVICE(u)->state == DEVICE_PLUGGED) { + /* This unit is in plugged state: we're sure it's + * attached to a device. */ + if (!path_equal(DEVICE(u)->sysfs, sysfs)) { + log_unit_debug(u, "Dev %s appeared twice with different sysfs paths %s and %s", + e, DEVICE(u)->sysfs, sysfs); + return -EEXIST; + } } if (!u) { @@ -456,6 +464,10 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool if (!now) return; + /* Didn't exist before, but does now? if so, generate a new invocation ID for it */ + if (previous == DEVICE_NOT_FOUND && d->found != DEVICE_NOT_FOUND) + (void) unit_acquire_invocation_id(UNIT(d)); + if (d->found & DEVICE_FOUND_UDEV) /* When the device is known to udev we consider it * plugged. */ @@ -595,11 +607,10 @@ static void device_shutdown(Manager *m) { m->udev_monitor = NULL; } - hashmap_free(m->devices_by_sysfs); - m->devices_by_sysfs = NULL; + m->devices_by_sysfs = hashmap_free(m->devices_by_sysfs); } -static int device_enumerate(Manager *m) { +static void device_enumerate(Manager *m) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; struct udev_list_entry *item = NULL, *first = NULL; int r; @@ -609,7 +620,7 @@ static int device_enumerate(Manager *m) { if (!m->udev_monitor) { m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_monitor) { - r = -ENOMEM; + log_oom(); goto fail; } @@ -619,37 +630,49 @@ static int device_enumerate(Manager *m) { (void) udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024); r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd"); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to add udev tag match: %m"); goto fail; + } r = udev_monitor_enable_receiving(m->udev_monitor); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to enable udev event reception: %m"); goto fail; + } r = sd_event_add_io(m->event, &m->udev_event_source, udev_monitor_get_fd(m->udev_monitor), EPOLLIN, device_dispatch_io, m); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to watch udev file descriptor: %m"); goto fail; + } (void) sd_event_source_set_description(m->udev_event_source, "device"); } e = udev_enumerate_new(m->udev); if (!e) { - r = -ENOMEM; + log_oom(); goto fail; } r = udev_enumerate_add_match_tag(e, "systemd"); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to create udev tag enumeration: %m"); goto fail; + } r = udev_enumerate_add_match_is_initialized(e); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to install initialization match into enumeration: %m"); goto fail; + } r = udev_enumerate_scan_devices(e); - if (r < 0) + if (r < 0) { + log_error_errno(r, "Failed to enumerate devices: %m"); goto fail; + } first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { @@ -672,13 +695,10 @@ static int device_enumerate(Manager *m) { device_update_found_by_sysfs(m, sysfs, true, DEVICE_FOUND_UDEV, false); } - return 0; + return; fail: - log_error_errno(r, "Failed to enumerate devices: %m"); - device_shutdown(m); - return r; } static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { @@ -818,14 +838,6 @@ int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, return device_update_found_by_name(m, node, add, found, now); } -static const char* const device_state_table[_DEVICE_STATE_MAX] = { - [DEVICE_DEAD] = "dead", - [DEVICE_TENTATIVE] = "tentative", - [DEVICE_PLUGGED] = "plugged", -}; - -DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState); - const UnitVTable device_vtable = { .object_size = sizeof(Device), .sections = @@ -833,8 +845,6 @@ const UnitVTable device_vtable = { "Device\0" "Install\0", - .no_instances = true, - .init = device_init, .done = device_done, .load = unit_load_fragment_and_dropin_optional, @@ -849,7 +859,6 @@ const UnitVTable device_vtable = { .active_state = device_active_state, .sub_state_to_string = device_sub_state_to_string, - .bus_interface = "org.freedesktop.systemd1.Device", .bus_vtable = bus_device_vtable, .following = device_following, |