]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/mount: adjust deserialized state based on /proc/self/mountinfo
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 6 Jul 2022 06:15:09 +0000 (15:15 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 20 Jul 2022 12:06:08 +0000 (21:06 +0900)
Fixes #23796.
Replaces #23803 and #23851.

src/core/mount.c

index 836ba132cb912f1a23fc08c52ec43fe81ca86bd0..5ec3526c7089bf84ec427bd317abe3afd873740d 100644 (file)
@@ -51,6 +51,9 @@ static const UnitActiveState state_translation_table[_MOUNT_STATE_MAX] = {
 
 static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
 static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
+static void mount_enter_dead(Mount *m, MountResult f);
+static void mount_enter_mounted(Mount *m, MountResult f);
+static void mount_cycle_clear(Mount *m);
 static int mount_process_proc_self_mountinfo(Manager *m);
 
 static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
@@ -753,23 +756,17 @@ static void mount_set_state(Mount *m, MountState state) {
 
 static int mount_coldplug(Unit *u) {
         Mount *m = MOUNT(u);
-        MountState new_state = MOUNT_DEAD;
         int r;
 
         assert(m);
         assert(m->state == MOUNT_DEAD);
 
-        if (m->deserialized_state != m->state)
-                new_state = m->deserialized_state;
-        else if (m->from_proc_self_mountinfo)
-                new_state = MOUNT_MOUNTED;
-
-        if (new_state == m->state)
+        if (m->deserialized_state == m->state)
                 return 0;
 
         if (m->control_pid > 0 &&
             pid_is_unwaited(m->control_pid) &&
-            MOUNT_STATE_WITH_PROCESS(new_state)) {
+            MOUNT_STATE_WITH_PROCESS(m->deserialized_state)) {
 
                 r = unit_watch_pid(UNIT(m), m->control_pid, false);
                 if (r < 0)
@@ -780,15 +777,52 @@ static int mount_coldplug(Unit *u) {
                         return r;
         }
 
-        if (!IN_SET(new_state, MOUNT_DEAD, MOUNT_FAILED)) {
+        if (!IN_SET(m->deserialized_state, MOUNT_DEAD, MOUNT_FAILED)) {
                 (void) unit_setup_dynamic_creds(u);
                 (void) unit_setup_exec_runtime(u);
         }
 
-        mount_set_state(m, new_state);
+        mount_set_state(m, m->deserialized_state);
         return 0;
 }
 
+static void mount_catchup(Unit *u) {
+        Mount *m = MOUNT(ASSERT_PTR(u));
+
+        assert(m);
+
+        /* Adjust the deserialized state. See comments in mount_process_proc_self_mountinfo(). */
+        if (m->from_proc_self_mountinfo)
+                switch (m->state) {
+                case MOUNT_DEAD:
+                case MOUNT_FAILED:
+                        assert(m->control_pid == 0);
+                        unit_acquire_invocation_id(u);
+                        mount_cycle_clear(m);
+                        mount_enter_mounted(m, MOUNT_SUCCESS);
+                        break;
+                case MOUNT_MOUNTING:
+                        assert(m->control_pid > 0);
+                        mount_set_state(m, MOUNT_MOUNTING_DONE);
+                        break;
+                default:
+                        break;
+                }
+        else
+                switch (m->state) {
+                case MOUNT_MOUNTING_DONE:
+                        assert(m->control_pid > 0);
+                        mount_set_state(m, MOUNT_MOUNTING);
+                        break;
+                case MOUNT_MOUNTED:
+                        assert(m->control_pid == 0);
+                        mount_enter_dead(m, MOUNT_SUCCESS);
+                        break;
+                default:
+                        break;
+                }
+}
+
 static void mount_dump(Unit *u, FILE *f, const char *prefix) {
         Mount *m = MOUNT(u);
         MountParameters *p;
@@ -2247,6 +2281,7 @@ const UnitVTable mount_vtable = {
         .done = mount_done,
 
         .coldplug = mount_coldplug,
+        .catchup = mount_catchup,
 
         .dump = mount_dump,