core: retry unmounting until we are done, in case of stacked mounts
This commit is contained in:
parent
b1acce80cd
commit
7d54a03a87
|
@ -45,6 +45,8 @@
|
||||||
#include "exit-status.h"
|
#include "exit-status.h"
|
||||||
#include "def.h"
|
#include "def.h"
|
||||||
|
|
||||||
|
#define RETRY_UMOUNT_MAX 32
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
|
||||||
|
|
||||||
|
@ -867,20 +869,28 @@ static void mount_enter_unmounting(Mount *m) {
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
|
/* Start counting our attempts */
|
||||||
|
if (!IN_SET(m->state,
|
||||||
|
MOUNT_UNMOUNTING,
|
||||||
|
MOUNT_UNMOUNTING_SIGTERM,
|
||||||
|
MOUNT_UNMOUNTING_SIGKILL))
|
||||||
|
m->n_retry_umount = 0;
|
||||||
|
|
||||||
m->control_command_id = MOUNT_EXEC_UNMOUNT;
|
m->control_command_id = MOUNT_EXEC_UNMOUNT;
|
||||||
m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
|
m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT;
|
||||||
|
|
||||||
if ((r = exec_command_set(
|
r = exec_command_set(m->control_command,
|
||||||
m->control_command,
|
|
||||||
"/bin/umount",
|
"/bin/umount",
|
||||||
"-n",
|
"-n",
|
||||||
m->where,
|
m->where,
|
||||||
NULL)) < 0)
|
NULL);
|
||||||
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
mount_unwatch_control_pid(m);
|
mount_unwatch_control_pid(m);
|
||||||
|
|
||||||
if ((r = mount_spawn(m, m->control_command, &m->control_pid)) < 0)
|
r = mount_spawn(m, m->control_command, &m->control_pid);
|
||||||
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
mount_set_state(m, MOUNT_UNMOUNTING);
|
mount_set_state(m, MOUNT_UNMOUNTING);
|
||||||
|
@ -1239,9 +1249,31 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||||
case MOUNT_UNMOUNTING_SIGKILL:
|
case MOUNT_UNMOUNTING_SIGKILL:
|
||||||
case MOUNT_UNMOUNTING_SIGTERM:
|
case MOUNT_UNMOUNTING_SIGTERM:
|
||||||
|
|
||||||
if (f == MOUNT_SUCCESS)
|
if (f == MOUNT_SUCCESS) {
|
||||||
|
|
||||||
|
if (m->from_proc_self_mountinfo) {
|
||||||
|
|
||||||
|
/* Still a mount point? If so, let's
|
||||||
|
* try again. Most likely there were
|
||||||
|
* multiple mount points stacked on
|
||||||
|
* top of each other. Note that due to
|
||||||
|
* the io event priority logic we can
|
||||||
|
* be sure the new mountinfo is loaded
|
||||||
|
* before we process the SIGCHLD for
|
||||||
|
* the mount command. */
|
||||||
|
|
||||||
|
if (m->n_retry_umount < RETRY_UMOUNT_MAX) {
|
||||||
|
log_unit_debug(u->id, "%s: mount still present, trying again.", u->id);
|
||||||
|
m->n_retry_umount++;
|
||||||
|
mount_enter_unmounting(m);
|
||||||
|
} else {
|
||||||
|
log_unit_debug(u->id, "%s: mount still present after %u attempts to unmount, giving up.", u->id, m->n_retry_umount);
|
||||||
|
mount_enter_mounted(m, f);
|
||||||
|
}
|
||||||
|
} else
|
||||||
mount_enter_dead(m, f);
|
mount_enter_dead(m, f);
|
||||||
else if (m->from_proc_self_mountinfo)
|
|
||||||
|
} else if (m->from_proc_self_mountinfo)
|
||||||
mount_enter_mounted(m, f);
|
mount_enter_mounted(m, f);
|
||||||
else
|
else
|
||||||
mount_enter_dead(m, f);
|
mount_enter_dead(m, f);
|
||||||
|
|
|
@ -112,6 +112,8 @@ struct Mount {
|
||||||
pid_t control_pid;
|
pid_t control_pid;
|
||||||
|
|
||||||
sd_event_source *timer_event_source;
|
sd_event_source *timer_event_source;
|
||||||
|
|
||||||
|
unsigned n_retry_umount;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const UnitVTable mount_vtable;
|
extern const UnitVTable mount_vtable;
|
||||||
|
|
Loading…
Reference in a new issue