From 01400460ae16c6522d11d08dd9a4b0928e7980d9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Jul 2022 15:15:09 +0900 Subject: [PATCH 1/2] core/mount: adjust deserialized state based on /proc/self/mountinfo Fixes #23796. Replaces #23803 and #23851. --- src/core/mount.c | 55 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/core/mount.c b/src/core/mount.c index 836ba132cb..5ec3526c70 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) { @@ -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, From 864d1a4f66a6324af03a361291687a6487dee59e Mon Sep 17 00:00:00 2001 From: licunlong Date: Sat, 2 Jul 2022 02:41:40 +0900 Subject: [PATCH 2/2] test: add a testcase for reexecuting with background mount job --- test/units/testsuite-60.sh | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/units/testsuite-60.sh b/test/units/testsuite-60.sh index 3c391c8efa..186a05686c 100755 --- a/test/units/testsuite-60.sh +++ b/test/units/testsuite-60.sh @@ -53,6 +53,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 @@ -111,6 +150,9 @@ timeout 2m bash -c 'while systemctl list-units -t mount tmp-meow* | grep -q tmp- # 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