diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c index e69c4a9fa6..2a72f1c396 100644 --- a/src/core/exec-credential.c +++ b/src/core/exec-credential.c @@ -12,6 +12,7 @@ #include "label-util.h" #include "mkdir-label.h" #include "mount-util.h" +#include "mount.h" #include "mountpoint-util.h" #include "process-util.h" #include "random-util.h" @@ -138,19 +139,21 @@ int unit_add_default_credential_dependencies(Unit *u, const ExecContext *c) { return unit_add_dependency_by_name(u, UNIT_AFTER, m, /* add_reference= */ true, UNIT_DEPENDENCY_FILE); } -int exec_context_destroy_credentials(const ExecContext *c, const char *runtime_prefix, const char *unit) { +int exec_context_destroy_credentials(Unit *u) { _cleanup_free_ char *p = NULL; int r; - assert(c); + assert(u); - r = get_credential_directory(runtime_prefix, unit, &p); + r = get_credential_directory(u->manager->prefix[EXEC_DIRECTORY_RUNTIME], u->id, &p); if (r <= 0) return r; /* This is either a tmpfs/ramfs of its own, or a plain directory. Either way, let's first try to * unmount it, and afterwards remove the mount point */ - (void) umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW); + if (umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW) >= 0) + (void) mount_invalidate_state_by_path(u->manager, p); + (void) rm_rf(p, REMOVE_ROOT|REMOVE_CHMOD); return 0; diff --git a/src/core/exec-credential.h b/src/core/exec-credential.h index 9e6f665621..6f836fbd0b 100644 --- a/src/core/exec-credential.h +++ b/src/core/exec-credential.h @@ -45,7 +45,7 @@ int exec_context_get_credential_directory( int unit_add_default_credential_dependencies(Unit *u, const ExecContext *c); -int exec_context_destroy_credentials(const ExecContext *c, const char *runtime_root, const char *unit); +int exec_context_destroy_credentials(Unit *u); int exec_setup_credentials( const ExecContext *context, const ExecParameters *params, diff --git a/src/core/mount.c b/src/core/mount.c index f93bad7074..931075a1ee 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -1284,6 +1284,11 @@ static int mount_stop(Unit *u) { assert(m); + /* When we directly call umount() for a path, then the state of the corresponding mount unit may be + * outdated. Let's re-read mountinfo now and update the state. */ + if (m->invalidated_state) + (void) mount_process_proc_self_mountinfo(u->manager); + switch (m->state) { case MOUNT_UNMOUNTING: @@ -1318,6 +1323,11 @@ static int mount_stop(Unit *u) { mount_enter_signal(m, MOUNT_UNMOUNTING_SIGKILL, MOUNT_SUCCESS); return 0; + case MOUNT_DEAD: + case MOUNT_FAILED: + /* The mount has just been unmounted by somebody else. */ + return 0; + default: assert_not_reached(); } @@ -2067,6 +2077,8 @@ static int mount_process_proc_self_mountinfo(Manager *m) { LIST_FOREACH(units_by_type, u, m->units_by_type[UNIT_MOUNT]) { Mount *mount = MOUNT(u); + mount->invalidated_state = false; + if (!mount_is_mounted(mount)) { /* A mount point is not around right now. It might be gone, or might never have @@ -2160,6 +2172,26 @@ static int mount_dispatch_io(sd_event_source *source, int fd, uint32_t revents, return mount_process_proc_self_mountinfo(m); } +int mount_invalidate_state_by_path(Manager *manager, const char *path) { + _cleanup_free_ char *name = NULL; + Unit *u; + int r; + + assert(manager); + assert(path); + + r = unit_name_from_path(path, ".mount", &name); + if (r < 0) + return log_debug_errno(r, "Failed to generate unit name from path \"%s\", ignoring: %m", path); + + u = manager_get_unit(manager, name); + if (!u) + return -ENOENT; + + MOUNT(u)->invalidated_state = true; + return 0; +} + static void mount_reset_failed(Unit *u) { Mount *m = MOUNT(u); diff --git a/src/core/mount.h b/src/core/mount.h index d6d6d335a4..2560674719 100644 --- a/src/core/mount.h +++ b/src/core/mount.h @@ -49,6 +49,8 @@ struct Mount { MountParameters parameters_proc_self_mountinfo; MountParameters parameters_fragment; + bool invalidated_state:1; /* Set when the 'state' of the mount unit may be outdated, and we need to + * re-read /proc/self/mountinfo. */ bool from_proc_self_mountinfo:1; bool from_fragment:1; @@ -92,6 +94,8 @@ extern const UnitVTable mount_vtable; void mount_fd_event(Manager *m, int events); +int mount_invalidate_state_by_path(Manager *manager, const char *path); + const char* mount_exec_command_to_string(MountExecCommand i) _const_; MountExecCommand mount_exec_command_from_string(const char *s) _pure_; diff --git a/src/core/unit.c b/src/core/unit.c index 56af1253ad..34cbde690b 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5994,7 +5994,7 @@ void unit_destroy_runtime_data(Unit *u, const ExecContext *context) { if (context->runtime_directory_preserve_mode == EXEC_PRESERVE_NO) exec_context_destroy_runtime_directory(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME]); - exec_context_destroy_credentials(context, u->manager->prefix[EXEC_DIRECTORY_RUNTIME], u->id); + exec_context_destroy_credentials(u); exec_context_destroy_mount_ns_dir(u); }