summaryrefslogtreecommitdiff
path: root/src/core/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/device.c')
-rw-r--r--src/core/device.c95
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,