[systemd-commits] 2 commits - src/core

Lennart Poettering lennart at kemper.freedesktop.org
Fri Apr 24 03:34:20 PDT 2015


 src/core/device.c  |   79 +++++++++++++++++++++++++++++++++++++++++++++--------
 src/core/device.h  |    3 --
 src/core/service.c |   22 +++++---------
 3 files changed, 77 insertions(+), 27 deletions(-)

New commits:
commit f62009410a72f5a89bfb8fdd7e48d9d472a6887b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 24 12:29:05 2015 +0200

    device: rework how we enter tentative state
    
    This reworks how we enter tentative state and does so only when a device
    was previously not announced via udev. The previous check actually just
    checked whether a new state bit was set, which is not correct.
    
    Also, to be able to reliably maintain the tentative state across daemon
    reloads, we need to serialize and deserialize it.

diff --git a/src/core/device.c b/src/core/device.c
index 43c4c67..a757230 100644
--- a/src/core/device.c
+++ b/src/core/device.c
@@ -149,14 +149,47 @@ static int device_coldplug(Unit *u, Hashmap *deferred_work) {
         if (d->found & DEVICE_FOUND_UDEV)
                 /* If udev says the device is around, it's around */
                 device_set_state(d, DEVICE_PLUGGED);
-        else if (d->found != DEVICE_NOT_FOUND)
+        else if (d->found != DEVICE_NOT_FOUND && d->deserialized_state != DEVICE_PLUGGED)
                 /* If a device is found in /proc/self/mountinfo or
-                 * /proc/swaps, it's "tentatively" around. */
+                 * /proc/swaps, and was not yet announced via udev,
+                 * it's "tentatively" around. */
                 device_set_state(d, DEVICE_TENTATIVE);
 
         return 0;
 }
 
+static int device_serialize(Unit *u, FILE *f, FDSet *fds) {
+        Device *d = DEVICE(u);
+
+        assert(u);
+        assert(f);
+        assert(fds);
+
+        unit_serialize_item(u, f, "state", device_state_to_string(d->state));
+}
+
+static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
+        Device *d = DEVICE(u);
+
+        assert(u);
+        assert(key);
+        assert(value);
+        assert(fds);
+
+        if (streq(key, "state")) {
+                DeviceState state;
+
+                state = device_state_from_string(value);
+                if (state < 0)
+                        log_unit_debug(u->id, "Failed to parse state value %s", value);
+                else
+                        d->deserialized_state = state;
+        } else
+                log_unit_debug(u->id, "Unknown serialization key '%s'", key);
+
+        return 0;
+}
+
 static void device_dump(Unit *u, FILE *f, const char *prefix) {
         Device *d = DEVICE(u);
 
@@ -406,7 +439,7 @@ static int device_process_new(Manager *m, struct udev_device *dev) {
 }
 
 static void device_update_found_one(Device *d, bool add, DeviceFound found, bool now) {
-        DeviceFound n;
+        DeviceFound n, previous;
 
         assert(d);
 
@@ -414,16 +447,27 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool
         if (n == d->found)
                 return;
 
+        previous = d->found;
         d->found = n;
 
-        if (now) {
-                if (d->found & DEVICE_FOUND_UDEV)
-                        device_set_state(d, DEVICE_PLUGGED);
-                else if (add && d->found != DEVICE_NOT_FOUND)
-                        device_set_state(d, DEVICE_TENTATIVE);
-                else
-                        device_set_state(d, DEVICE_DEAD);
-        }
+        if (!now)
+                return;
+
+        if (d->found & DEVICE_FOUND_UDEV)
+                /* When the device is known to udev we consider it
+                 * plugged. */
+                device_set_state(d, DEVICE_PLUGGED);
+        else if (d->found != DEVICE_NOT_FOUND && (previous & DEVICE_FOUND_UDEV) == 0)
+                /* If the device has not been seen by udev yet, but is
+                 * now referenced by the kernel, then we assume the
+                 * kernel knows it now, and udev might soon too. */
+                device_set_state(d, DEVICE_TENTATIVE);
+        else
+                /* If nobody sees the device, or if the device was
+                 * previously seen by udev and now is only referenced
+                 * from the kernel, then we consider the device is
+                 * gone, the kernel just hasn't noticed it yet. */
+                device_set_state(d, DEVICE_DEAD);
 }
 
 static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
@@ -733,6 +777,16 @@ int device_found_node(Manager *m, const char *node, bool add, DeviceFound found,
                 if (!path_startswith(node, "/dev"))
                         return 0;
 
+                /* We make an extra check here, if the device node
+                 * actually exists. If it's missing, then this is an
+                 * indication that device was unplugged but is still
+                 * referenced in /proc/swaps or
+                 * /proc/self/mountinfo. Note that this check doesn't
+                 * really cover all cases where a device might be gone
+                 * away, since drives that can have a medium inserted
+                 * will still have a device node even when the medium
+                 * is not there... */
+
                 if (stat(node, &st) < 0) {
                         if (errno == ENOENT)
                                 return 0;
@@ -786,6 +840,9 @@ const UnitVTable device_vtable = {
 
         .coldplug = device_coldplug,
 
+        .serialize = device_serialize,
+        .deserialize_item = device_deserialize_item,
+
         .dump = device_dump,
 
         .active_state = device_active_state,
diff --git a/src/core/device.h b/src/core/device.h
index 9f46e08..10ab113 100644
--- a/src/core/device.h
+++ b/src/core/device.h
@@ -23,7 +23,6 @@
 
 typedef struct Device Device;
 
-
 /* We simply watch devices, we cannot plug/unplug them. That
  * simplifies the state engine greatly */
 typedef enum DeviceState {
@@ -52,7 +51,7 @@ struct Device {
         devices for the same sysfs path. We chain them up here. */
         LIST_FIELDS(struct Device, same_sysfs);
 
-        DeviceState state;
+        DeviceState state, deserialized_state;
 };
 
 extern const UnitVTable device_vtable;

commit f06db33455f5134c5c94b71a5b1d94cc9d0d630c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Apr 24 12:25:55 2015 +0200

    service: improve readability, by reducing line-breaks

diff --git a/src/core/service.c b/src/core/service.c
index 201218e..0e2f114 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1958,8 +1958,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result));
 
         if (s->control_pid > 0)
-                unit_serialize_item_format(u, f, "control-pid", PID_FMT,
-                                           s->control_pid);
+                unit_serialize_item_format(u, f, "control-pid", PID_FMT, s->control_pid);
 
         if (s->main_pid_known && s->main_pid > 0)
                 unit_serialize_item_format(u, f, "main-pid", PID_FMT, s->main_pid);
@@ -1973,8 +1972,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
          * multiple commands attached here, we will start from the
          * first one again */
         if (s->control_command_id >= 0)
-                unit_serialize_item(u, f, "control-command",
-                                    service_exec_command_to_string(s->control_command_id));
+                unit_serialize_item(u, f, "control-command", service_exec_command_to_string(s->control_command_id));
 
         if (s->socket_fd >= 0) {
                 int copy;
@@ -2007,20 +2005,16 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
         }
 
         if (s->main_exec_status.pid > 0) {
-                unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT,
-                                           s->main_exec_status.pid);
-                dual_timestamp_serialize(f, "main-exec-status-start",
-                                         &s->main_exec_status.start_timestamp);
-                dual_timestamp_serialize(f, "main-exec-status-exit",
-                                         &s->main_exec_status.exit_timestamp);
+                unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT, s->main_exec_status.pid);
+                dual_timestamp_serialize(f, "main-exec-status-start", &s->main_exec_status.start_timestamp);
+                dual_timestamp_serialize(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp);
 
                 if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) {
-                        unit_serialize_item_format(u, f, "main-exec-status-code", "%i",
-                                                   s->main_exec_status.code);
-                        unit_serialize_item_format(u, f, "main-exec-status-status", "%i",
-                                                   s->main_exec_status.status);
+                        unit_serialize_item_format(u, f, "main-exec-status-code", "%i", s->main_exec_status.code);
+                        unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status);
                 }
         }
+
         if (dual_timestamp_is_set(&s->watchdog_timestamp))
                 dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp);
 



More information about the systemd-commits mailing list