]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/device.c
test: add test for DynamicUser= + StateDirectory=
[thirdparty/systemd.git] / src / core / device.c
index c572a6737cd75a177fdaffac48fd58b3afd5bc79..87186f135bf817f15fcd5205980a94f49aa08dd9 100644 (file)
@@ -112,7 +112,7 @@ static void device_init(Unit *u) {
          * indefinitely for plugged in devices, something which cannot
          * happen for the other units since their operations time out
          * anyway. */
-        u->job_timeout = u->manager->default_timeout_start_usec;
+        u->job_running_timeout = u->manager->default_timeout_start_usec;
 
         u->ignore_on_isolate = true;
 }
@@ -285,6 +285,37 @@ static int device_add_udev_wants(Unit *u, struct udev_device *dev) {
         }
 }
 
+static bool device_is_bound_by_mounts(Unit *d, struct udev_device *dev) {
+        const char *bound_by;
+        int r = false;
+
+        assert(d);
+        assert(dev);
+
+        bound_by = udev_device_get_property_value(dev, "SYSTEMD_MOUNT_DEVICE_BOUND");
+        if (bound_by)
+                r = parse_boolean(bound_by) > 0;
+
+        DEVICE(d)->bind_mounts = r;
+        return r;
+}
+
+static int device_upgrade_mount_deps(Unit *u) {
+        Unit *other;
+        Iterator i;
+        int r;
+
+        SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i) {
+                if (other->type != UNIT_MOUNT)
+                        continue;
+
+                r = unit_add_dependency(other, UNIT_BINDS_TO, u, true);
+                if (r < 0)
+                        return r;
+        }
+        return 0;
+}
+
 static int device_setup_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
         _cleanup_free_ char *e = NULL;
         const char *sysfs = NULL;
@@ -349,6 +380,13 @@ static int device_setup_unit(Manager *m, struct udev_device *dev, const char *pa
                         (void) device_add_udev_wants(u, dev);
         }
 
+        /* So the user wants the mount units to be bound to the device but a
+         * mount unit might has been seen by systemd before the device appears
+         * on its radar. In this case the device unit is partially initialized
+         * and includes the deps on the mount unit but at that time the "bind
+         * mounts" flag wasn't not present. Fix this up now. */
+        if (dev && device_is_bound_by_mounts(u, dev))
+                device_upgrade_mount_deps(u);
 
         /* Note that this won't dispatch the load queue, the caller
          * has to do that if needed and appropriate */
@@ -418,7 +456,7 @@ static int device_process_new(Manager *m, struct udev_device *dev) {
          * aliases */
         alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS");
         for (;;) {
-                _cleanup_free_ char *word = NULL, *k = NULL;
+                _cleanup_free_ char *word = NULL;
 
                 r = extract_first_word(&alias, &word, NULL, EXTRACT_QUOTES);
                 if (r == 0)
@@ -463,16 +501,20 @@ static void device_update_found_one(Device *d, bool add, DeviceFound found, bool
                  * 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
+        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);
+                device_unset_sysfs(d);
+        }
+
 }
 
 static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add, DeviceFound found, bool now) {
-        Device *d, *l;
+        Device *d, *l, *n;
 
         assert(m);
         assert(sysfs);
@@ -481,7 +523,7 @@ static int device_update_found_by_sysfs(Manager *m, const char *sysfs, bool add,
                 return 0;
 
         l = hashmap_get(m->devices_by_sysfs, sysfs);
-        LIST_FOREACH(same_sysfs, d, l)
+        LIST_FOREACH_SAFE(same_sysfs, d, n, l)
                 device_update_found_one(d, add, found, now);
 
         return 0;
@@ -824,6 +866,14 @@ int device_found_node(Manager *m, const char *node, bool add, DeviceFound found,
         return device_update_found_by_name(m, node, add, found, now);
 }
 
+bool device_shall_be_bound_by(Unit *device, Unit *u) {
+
+        if (u->type != UNIT_MOUNT)
+                return false;
+
+        return DEVICE(device)->bind_mounts;
+}
+
 const UnitVTable device_vtable = {
         .object_size = sizeof(Device),
         .sections =
@@ -831,6 +881,8 @@ const UnitVTable device_vtable = {
                 "Device\0"
                 "Install\0",
 
+        .gc_jobs = true,
+
         .init = device_init,
         .done = device_done,
         .load = unit_load_fragment_and_dropin_optional,