diff --git a/src/core/mount.c b/src/core/mount.c index 9dc04cd07e..9dd9fe1293 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -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) { @@ -762,23 +765,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) @@ -789,15 +786,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; @@ -2227,6 +2261,7 @@ const UnitVTable mount_vtable = { .done = mount_done, .coldplug = mount_coldplug, + .catchup = mount_catchup, .dump = mount_dump, diff --git a/test/units/testsuite-60.sh b/test/units/testsuite-60.sh index 13fe139a38..a29364568d 100755 --- a/test/units/testsuite-60.sh +++ b/test/units/testsuite-60.sh @@ -202,6 +202,45 @@ EOF } } +test_issue_23796() { + local mount_path mount_mytmpfs + + mount_path="$(command -v mount 2>/dev/null)" + mount_mytmpfs="${mount_path/\/bin/\/sbin}.mytmpfs" + cat >"$mount_mytmpfs" </run/systemd/system/tmp-hoge.mount </failed systemd-analyze log-level debug @@ -263,6 +302,9 @@ test_dependencies # test that handling of mount start jobs is delayed when /proc/self/mouninfo monitor is rate limited test_issue_20329 +# test for reexecuting with background mount job +test_issue_23796 + systemd-analyze log-level info touch /testok