1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-18 10:04:04 +03:00

core/mount: if mount is gone eventually, consider it success

Currently, if unmount initiated by us fails, we record
that in result. Later, if we tried again and succeeded,
or someone else successfully unmounted it, the unit
state is still considered failed. Let's be more tolerant
instead, and forget about previous failure.

Alternative to #32002
This commit is contained in:
Mike Yuan 2024-03-29 00:43:25 +08:00
parent 9c7c3d9cdb
commit e3783068c6
No known key found for this signature in database
GPG Key ID: 417471C0A40F58B3

View File

@ -55,7 +55,7 @@ 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_dead(Mount *m, MountResult f, bool flush_result);
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);
@ -800,7 +800,7 @@ static void mount_catchup(Unit *u) {
break;
case MOUNT_MOUNTED:
assert(!pidref_is_set(&m->control_pid));
mount_enter_dead(m, MOUNT_SUCCESS);
mount_enter_dead(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
default:
break;
@ -899,10 +899,10 @@ static int mount_spawn(Mount *m, ExecCommand *c, PidRef *ret_pid) {
return 0;
}
static void mount_enter_dead(Mount *m, MountResult f) {
static void mount_enter_dead(Mount *m, MountResult f, bool flush_result) {
assert(m);
if (m->result == MOUNT_SUCCESS)
if (m->result == MOUNT_SUCCESS || flush_result)
m->result = f;
unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result));
@ -930,17 +930,20 @@ static void mount_enter_mounted(Mount *m, MountResult f) {
mount_set_state(m, MOUNT_MOUNTED);
}
static void mount_enter_dead_or_mounted(Mount *m, MountResult f) {
static void mount_enter_dead_or_mounted(Mount *m, MountResult f, bool flush_result) {
assert(m);
/* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point. We use this
* whenever we executed an operation, so that our internal state reflects what the kernel says again, after all
* ultimately we just mirror the kernel's internal state on this. */
/* Enter DEAD or MOUNTED state, depending on what the kernel currently says about the mount point.
* We use this whenever we executed an operation, so that our internal state reflects what
* the kernel says again, after all ultimately we just mirror the kernel's internal state on this.
*
* Note that flush_result only applies to mount_enter_dead(), since that's when the result gets
* turned into unit end state. */
if (m->from_proc_self_mountinfo)
mount_enter_mounted(m, f);
else
mount_enter_dead(m, f);
mount_enter_dead(m, f, flush_result);
}
static int state_to_kill_operation(MountState state) {
@ -990,12 +993,12 @@ static void mount_enter_signal(Mount *m, MountState state, MountResult f) {
else if (state == MOUNT_UNMOUNTING_SIGTERM && m->kill_context.send_sigkill)
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS);
else
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
return;
fail:
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
}
static int mount_set_umount_command(Mount *m, ExecCommand *c) {
@ -1057,7 +1060,7 @@ static void mount_enter_unmounting(Mount *m) {
return;
fail:
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
}
static int mount_set_mount_command(Mount *m, ExecCommand *c, const MountParameters *p) {
@ -1201,7 +1204,7 @@ static void mount_enter_mounting(Mount *m) {
return;
fail:
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES);
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_RESOURCES, /* flush_result = */ false);
}
static void mount_set_reload_result(Mount *m, MountResult result) {
@ -1267,7 +1270,7 @@ static void mount_enter_remounting(Mount *m) {
fail:
mount_set_reload_result(m, MOUNT_FAILURE_RESOURCES);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
}
static void mount_cycle_clear(Mount *m) {
@ -1547,7 +1550,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
log_unit_warning(UNIT(m), "Mount process finished, but there is no mount.");
f = MOUNT_FAILURE_PROTOCOL;
}
mount_enter_dead(m, f);
mount_enter_dead(m, f, /* flush_result = */ false);
break;
case MOUNT_MOUNTING_DONE:
@ -1557,7 +1560,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
case MOUNT_REMOUNTING:
case MOUNT_REMOUNTING_SIGTERM:
case MOUNT_REMOUNTING_SIGKILL:
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
case MOUNT_UNMOUNTING:
@ -1578,22 +1581,27 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
/* Hmm, umount process spawned by us failed, but the mount disappeared anyway?
* Maybe someone else is trying to unmount at the same time. */
log_unit_notice(u, "Mount disappeared even though umount process failed, continuing.");
mount_enter_dead(m, MOUNT_SUCCESS);
mount_enter_dead(m, MOUNT_SUCCESS, /* flush_result = */ true);
} else
mount_enter_dead_or_mounted(m, f);
/* At this point, either the unmount succeeded or unexpected error occurred. We usually
* remember the first error in 'result', but here let's update that forcibly, since
* there could previous failed attempts yet we only care about the most recent
* attempt. IOW, if we eventually managed to unmount the stuff, don't enter failed
* end state. */
mount_enter_dead_or_mounted(m, f, /* flush_result = */ true);
break;
case MOUNT_UNMOUNTING_SIGTERM:
case MOUNT_UNMOUNTING_SIGKILL:
mount_enter_dead_or_mounted(m, f);
mount_enter_dead_or_mounted(m, f, /* flush_result = */ false);
break;
case MOUNT_CLEANING:
if (m->clean_result == MOUNT_SUCCESS)
m->clean_result = f;
mount_enter_dead(m, MOUNT_SUCCESS);
mount_enter_dead(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
default:
@ -1631,7 +1639,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_enter_signal(m, MOUNT_REMOUNTING_SIGKILL, MOUNT_SUCCESS);
} else {
log_unit_warning(UNIT(m), "Remounting timed out. Skipping SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
}
break;
@ -1639,7 +1647,7 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_set_reload_result(m, MOUNT_FAILURE_TIMEOUT);
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS);
mount_enter_dead_or_mounted(m, MOUNT_SUCCESS, /* flush_result = */ false);
break;
case MOUNT_UNMOUNTING:
@ -1653,13 +1661,13 @@ static int mount_dispatch_timer(sd_event_source *source, usec_t usec, void *user
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_FAILURE_TIMEOUT);
} else {
log_unit_warning(UNIT(m), "Mount process timed out. Skipping SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT, /* flush_result = */ false);
}
break;
case MOUNT_UNMOUNTING_SIGKILL:
log_unit_warning(UNIT(m), "Mount process still around after SIGKILL. Ignoring.");
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT);
mount_enter_dead_or_mounted(m, MOUNT_FAILURE_TIMEOUT, /* flush_result = */ false);
break;
case MOUNT_CLEANING:
@ -2121,8 +2129,11 @@ static int mount_process_proc_self_mountinfo(Manager *m) {
switch (mount->state) {
case MOUNT_MOUNTED:
/* This has just been unmounted by somebody else, follow the state change. */
mount_enter_dead(mount, MOUNT_SUCCESS);
/* This has just been unmounted by somebody else, follow the state change.
* Also explicitly override the result (see the comment in mount_sigchld_event()),
* but more aggressively here since the state change is extrinsic. */
mount_cycle_clear(mount);
mount_enter_dead(mount, MOUNT_SUCCESS, /* flush_result = */ true);
break;
case MOUNT_MOUNTING_DONE:
@ -2290,7 +2301,7 @@ static int mount_can_start(Unit *u) {
r = unit_test_start_limit(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT, /* flush_result = */ false);
return r;
}