Merge pull request #23893 from yuwata/core-mount-re-read-mountinfo

core/mount: adjust deserialized state based on if the corresponding mountinfo entry exists or not
This commit is contained in:
Luca Boccassi 2022-08-23 12:46:39 +01:00 committed by GitHub
commit 712e0b4792
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 10 deletions

View 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) {
@ -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,

View file

@ -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" <<EOF
#!/bin/bash
sleep ".\$RANDOM"
exec -- $mount_path -t tmpfs tmpfs "\$2"
EOF
chmod +x "$mount_mytmpfs"
mkdir -p /run/systemd/system
cat >/run/systemd/system/tmp-hoge.mount <<EOF
[Mount]
What=mytmpfs
Where=/tmp/hoge
Type=mytmpfs
EOF
# shellcheck disable=SC2064
trap "rm -f /run/systemd/system/tmp-hoge.mount '$mount_mytmpfs'" RETURN
for ((i = 0; i < 10; i++)); do
systemctl --no-block start tmp-hoge.mount
sleep ".$RANDOM"
systemctl daemon-reexec
sleep 1
if [[ "$(systemctl is-failed tmp-hoge.mount)" == "failed" ]] || \
journalctl -u tmp-hoge.mount -q --grep "but there is no mount"; then
exit 1
fi
systemctl stop tmp-hoge.mount
done
}
: >/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