mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-07 17:17:44 +03:00
shutdown: Log processes that block umount
This commit is contained in:
parent
5125b67742
commit
20596876e3
@ -25,13 +25,17 @@
|
||||
#include "blockdev-util.h"
|
||||
#include "def.h"
|
||||
#include "device-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "fstab-util.h"
|
||||
#include "libmount-util.h"
|
||||
#include "mount-setup.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
@ -524,6 +528,58 @@ static bool nonunmountable_path(const char *path) {
|
||||
|| path_startswith(path, "/run/initramfs");
|
||||
}
|
||||
|
||||
static void log_umount_blockers(const char *mnt) {
|
||||
_cleanup_closedir_ DIR *dir = opendir("/proc");
|
||||
if (!dir)
|
||||
return (void) log_warning_errno(errno, "opendir(/proc) failed: %m");
|
||||
|
||||
_cleanup_free_ char *blockers = NULL;
|
||||
|
||||
FOREACH_DIRENT_ALL(de, dir, break) {
|
||||
if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
|
||||
continue;
|
||||
|
||||
pid_t pid;
|
||||
if (parse_pid(de->d_name, &pid) < 0)
|
||||
continue;
|
||||
|
||||
_cleanup_closedir_ DIR *pid_dir = xopendirat(dirfd(dir), de->d_name, 0);
|
||||
if (!pid_dir)
|
||||
continue;
|
||||
|
||||
_cleanup_closedir_ DIR *fd_dir = xopendirat(dirfd(pid_dir), "fd", 0);
|
||||
if (!fd_dir)
|
||||
continue;
|
||||
|
||||
FOREACH_DIRENT(fd_de, fd_dir, break) {
|
||||
_cleanup_free_ char *open_file = NULL, *comm = NULL;
|
||||
|
||||
if (readlinkat_malloc(dirfd(fd_dir), fd_de->d_name, &open_file) < 0)
|
||||
continue;
|
||||
|
||||
if (!path_startswith(open_file, mnt))
|
||||
continue;
|
||||
|
||||
if (PATH_STARTSWITH_SET(open_file, "/dev", "/sys", "/proc"))
|
||||
continue;
|
||||
|
||||
if (get_process_comm(pid, &comm) < 0)
|
||||
continue;
|
||||
|
||||
if (!strextend_with_separator(&blockers, ", ", comm))
|
||||
return (void) log_oom();
|
||||
|
||||
if (!strextend(&blockers, "(", de->d_name, ")"))
|
||||
return (void) log_oom();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockers)
|
||||
log_warning("Unmounting '%s' blocked by: %s", mnt, blockers);
|
||||
}
|
||||
|
||||
static int remount_with_timeout(MountPoint *m, bool last_try) {
|
||||
pid_t pid;
|
||||
int r;
|
||||
@ -586,9 +642,13 @@ static int umount_with_timeout(MountPoint *m, bool last_try) {
|
||||
* "busy", this may allow processes to die, thus making the
|
||||
* filesystem less busy so the unmount might succeed (rather
|
||||
* than return EBUSY). */
|
||||
r = umount2(m->path, MNT_FORCE);
|
||||
if (r < 0)
|
||||
log_full_errno(last_try ? LOG_ERR : LOG_INFO, errno, "Failed to unmount %s: %m", m->path);
|
||||
r = RET_NERRNO(umount2(m->path, MNT_FORCE));
|
||||
if (r < 0) {
|
||||
log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Failed to unmount %s: %m", m->path);
|
||||
|
||||
if (r == -EBUSY && last_try)
|
||||
log_umount_blockers(m->path);
|
||||
}
|
||||
|
||||
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user