From ef23b7821e870c2b3bc9a4f40b274b73b7059b8e Mon Sep 17 00:00:00 2001 From: hanjinpeng Date: Mon, 14 Jul 2025 10:13:19 +0800 Subject: [PATCH] fix start mount unit failed --- ...t-deserialized-state-based-on-proc-s.patch | 118 ++++++++++++++++++ ...isting-mounting-unit-from-proc-self-.patch | 54 ++++++++ systemd.spec | 7 +- 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 backport-core-mount-adjust-deserialized-state-based-on-proc-s.patch create mode 100644 backport-mount-mark-an-existing-mounting-unit-from-proc-self-.patch diff --git a/backport-core-mount-adjust-deserialized-state-based-on-proc-s.patch b/backport-core-mount-adjust-deserialized-state-based-on-proc-s.patch new file mode 100644 index 0000000..f79947c --- /dev/null +++ b/backport-core-mount-adjust-deserialized-state-based-on-proc-s.patch @@ -0,0 +1,118 @@ +From d3cf70a9d8bcc72f1f8de1a374bad6135e64c0d6 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 6 Jul 2022 15:15:09 +0900 +Subject: [PATCH] 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 29c3404..0629840 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -50,6 +50,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) { +@@ -682,23 +685,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) +@@ -709,15 +706,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(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) { + char buf[FORMAT_TIMESPAN_MAX]; + Mount *m = MOUNT(u); +@@ -1987,6 +2021,7 @@ const UnitVTable mount_vtable = { + .done = mount_done, + + .coldplug = mount_coldplug, ++ .catchup = mount_catchup, + + .dump = mount_dump, + +-- +2.23.0 + diff --git a/backport-mount-mark-an-existing-mounting-unit-from-proc-self-.patch b/backport-mount-mark-an-existing-mounting-unit-from-proc-self-.patch new file mode 100644 index 0000000..9eeedbf --- /dev/null +++ b/backport-mount-mark-an-existing-mounting-unit-from-proc-self-.patch @@ -0,0 +1,54 @@ +From d9a75979bec8d1d9fbd70e46b4442f2b66ea12fe Mon Sep 17 00:00:00 2001 +From: Jun'ichi Nomura +Date: Tue, 3 Dec 2019 16:52:02 +0900 +Subject: [PATCH] mount: mark an existing "mounting" unit from + /proc/self/mountinfo as "just_mounted" + +When starting a mount unit, systemd invokes mount command and moves the +unit's internal state to "mounting". Then it watches for updates of +/proc/self/mountinfo. When the expected mount entry newly appears in +mountinfo, the unit internal state is changed to "mounting-done". +Finally, when systemd finds the mount command has finished, it checks +whether the unit internal state is "mounting-done" and changes the state +to "mounted". +If the state was not "mounting-done" in the last step though mount command +was successfully finished, the unit is marked as "failed" with following +log messages: + Mount process finished, but there is no mount. + Failed with result 'protocol'. + +If daemon-reload is done in parallel with starting mount unit, it is +possible that things happen in following order and result in above failure. + 1. the mount unit state changes to "mounting" + 2. daemon-reload saves the unit state + 3. kernel completes the mount and /proc/self/mountinfo is updated + 4. daemon-reload restores the saved unit state, that is "mounting" + 5. systemd notices the mount command has finished but the unit state + is still "mounting" though it should be "mounting-done" + +mount_setup_existing_unit() should take into account that MOUNT_MOUNTING +is transitional state and set MOUNT_PROC_JUST_MOUNTED flag if the unit +comes from /proc/self/mountinfo so that mount_process_proc_self_mountinfo() +later can make state transition from "mounting" to "mounting-done". + +Fixes: #10872 +--- + src/core/mount.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 1b64011..29c3404 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1530,7 +1530,7 @@ static int mount_setup_existing_unit( + if (r > 0) + flags |= MOUNT_PROC_JUST_CHANGED; + +- if (!MOUNT(u)->from_proc_self_mountinfo || FLAGS_SET(MOUNT(u)->proc_flags, MOUNT_PROC_JUST_MOUNTED)) ++ if (!MOUNT(u)->from_proc_self_mountinfo || FLAGS_SET(MOUNT(u)->proc_flags, MOUNT_PROC_JUST_MOUNTED) || MOUNT(u)->state == MOUNT_MOUNTING) + flags |= MOUNT_PROC_JUST_MOUNTED; + + MOUNT(u)->from_proc_self_mountinfo = true; +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index c5202b3..7d695bf 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://systemd.io/ Version: 243 -Release: 83 +Release: 84 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -311,6 +311,8 @@ Patch0263: backport-fix-cgtop-sscanf-return-code-checks.patch Patch0264: backport-pid1-set-SYSTEMD_NSS_DYNAMIC_BYPASS-1-env-var-for-db.patch Patch0265: backport-pid1-lookup-owning-PID-of-BusName-name-of-services-a.patch Patch0266: backport-pid1-watch-bus-name-always-when-we-have-it.patch +Patch0267: backport-mount-mark-an-existing-mounting-unit-from-proc-self-.patch +Patch0268: backport-core-mount-adjust-deserialized-state-based-on-proc-s.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1719,6 +1721,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Jul 14 2025 Han Jinpeng - 243-84 +- Fix mount units failed issue, which mount process finished, but there is no mount. + * Thu Jan 2 2025 Han Jinpeng - 243-83 - Enhance the logging function of the systemctl command Add process-util-log-more-information-when-runnin.patch -- Gitee