summaryrefslogtreecommitdiff
path: root/src/shutdown
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-08-24 11:55:14 +0200
committerLennart Poettering <lennart@poettering.net>2022-08-31 22:53:18 +0200
commit05768ae36b4af0c18b4837fa6041fd66a05f5e36 (patch)
tree7f3bee56475048771824ca6194c003503fb3bd38 /src/shutdown
parentf11efcbeb17781a3e03596fe6b1016fbb5c31360 (diff)
downloadsystemd-05768ae36b4af0c18b4837fa6041fd66a05f5e36.tar.gz
shutdown: rework log_umount_blockers() a bit
Let's go directly from opening /proc/ to opening /proc/$PID/fd/ instead of indirectly via opening /proc/$PID/ first. Saves a syscall. Also, add error logging about all unexpected errors. Finally, drop redundant denylist for /proc/, /sys/, /dev/ prefix checking, should be redundant, given the ealier check against the 'mnt' prefix.
Diffstat (limited to 'src/shutdown')
-rw-r--r--src/shutdown/umount.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c
index 7ddeb67e97..e650b82170 100644
--- a/src/shutdown/umount.c
+++ b/src/shutdown/umount.c
@@ -529,11 +529,12 @@ static bool nonunmountable_path(const char *path) {
}
static void log_umount_blockers(const char *mnt) {
+ _cleanup_free_ char *blockers = NULL;
+ int r;
+
_cleanup_closedir_ DIR *dir = opendir("/proc");
if (!dir)
- return (void) log_warning_errno(errno, "opendir(/proc) failed: %m");
-
- _cleanup_free_ char *blockers = NULL;
+ return (void) log_warning_errno(errno, "Failed to open /proc/: %m");
FOREACH_DIRENT_ALL(de, dir, break) {
if (!IN_SET(de->d_type, DT_DIR, DT_UNKNOWN))
@@ -543,37 +544,50 @@ static void log_umount_blockers(const char *mnt) {
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_free_ char *fdp = path_join(de->d_name, "fd");
+ if (!fdp)
+ return (void) log_oom();
- _cleanup_closedir_ DIR *fd_dir = xopendirat(dirfd(pid_dir), "fd", 0);
- if (!fd_dir)
+ _cleanup_closedir_ DIR *fd_dir = xopendirat(dirfd(dir), fdp, 0);
+ if (!fd_dir) {
+ if (errno != ENOENT) /* process gone by now? */
+ log_debug_errno(errno, "Failed to open /proc/%s/, ignoring: %m",fdp);
continue;
+ }
+ bool culprit = false;
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;
+ _cleanup_free_ char *open_file = NULL;
- if (!path_startswith(open_file, mnt))
+ r = readlinkat_malloc(dirfd(fd_dir), fd_de->d_name, &open_file);
+ if (r < 0) {
+ if (r != -ENOENT) /* fd closed by now */
+ log_debug_errno(r, "Failed to read link /proc/%s/%s, ignoring: %m", fdp, fd_de->d_name);
continue;
+ }
- if (PATH_STARTSWITH_SET(open_file, "/dev", "/sys", "/proc"))
- continue;
+ if (path_startswith(open_file, mnt)) {
+ culprit = true;
+ break;
+ }
+ }
- if (get_process_comm(pid, &comm) < 0)
- continue;
+ if (!culprit)
+ continue;
- if (!strextend_with_separator(&blockers, ", ", comm))
- return (void) log_oom();
+ _cleanup_free_ char *comm = NULL;
+ r = get_process_comm(pid, &comm);
+ if (r < 0) {
+ if (r != -ESRCH) /* process gone by now */
+ log_debug_errno(r, "Failed to read process name of PID " PID_FMT ": %m", pid);
+ continue;
+ }
- if (!strextend(&blockers, "(", de->d_name, ")"))
- return (void) log_oom();
+ if (!strextend_with_separator(&blockers, ", ", comm))
+ return (void) log_oom();
- break;
- }
+ if (!strextend(&blockers, "(", de->d_name, ")"))
+ return (void) log_oom();
}
if (blockers)