From 2c8198c9c2ff82b8ec84737a595a18956378a2f8 Mon Sep 17 00:00:00 2001 From: James Muir Date: Fri, 14 Feb 2025 16:06:42 -0500 Subject: [PATCH 1/2] WIP 1 Share the first part of the Cisco patch authored by Oleksiy Obitotskyy to fix reading from /proc/schedstat post-switch-root (see #60). More changes are needed since writing the svg file fails. --- src/store.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/store.c b/src/store.c index 785d408..e64af79 100644 --- a/src/store.c +++ b/src/store.c @@ -20,6 +20,8 @@ along with systemd; If not, see . ***/ +#define _POSIX_C_SOURCE + #include #include #include @@ -29,6 +31,7 @@ #include #include #include +#include #include "alloc-util.h" #include "bootchart.h" @@ -119,6 +122,68 @@ static void garbage_collect_dead_processes(struct ps_struct *ps_first) { } } +static int proc_read_full_file(int procfd, const char *fn, char **contents, size_t *size) { + int fd = -1; + size_t n, l; + _cleanup_free_ char *buf = NULL; + struct stat st; + + fd = openat(procfd, fn, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return log_error_errno(errno, "Failed to openat /proc/<>: %m"); + + if (fstatat(procfd, fn, &st, 0) < 0) + return log_error_errno(errno, "Failed to fstatat /proc/<>: %m"); + + n = LINE_MAX; + if (S_ISREG(st.st_mode)) { + + /* Safety check */ + if (st.st_size > 4*1024*1024) + return -E2BIG; + + /* Start with the right file size, but be prepared for + * files from /proc which generally report a file size + * of 0 */ + if (st.st_size > 0) + n = st.st_size; + } + + l = 0; + for (;;) { + char *t; + ssize_t k; + + t = realloc(buf, n+1); + if (!t) + return -ENOMEM; + + buf = t; + k = pread(fd, buf + l, n - l, l); + + if (k < 0) + return log_error_errno(errno, "Failed to pread /proc/<>: %m"); + if (k == 0) + break; + + l += k; + n *= 2; + + /* Safety check */ + if (n > 4*1024*1024) + return -E2BIG; + } + + buf[l] = 0; + *contents = buf; + buf = NULL; /* do not free */ + + if (size) + *size = l; + + safe_close(fd); + return 0; +} int log_sample(DIR *proc, int sample, @@ -189,7 +254,7 @@ int log_sample(DIR *proc, } /* Parse "/proc/schedstat" for overall CPU utilization */ - r = read_full_file("/proc/schedstat", &buf_schedstat, NULL); + r = proc_read_full_file(procfd, "schedstat", &buf_schedstat, NULL); if (r < 0) return log_error_errno(r, "Unable to read schedstat: %m"); From 3f1dccd4d03373504a3a722bbcc63198d16fa027 Mon Sep 17 00:00:00 2001 From: James Muir Date: Fri, 21 Feb 2025 08:17:15 -0500 Subject: [PATCH 2/2] use fstat(), include filename in error messages. --- src/store.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/store.c b/src/store.c index e64af79..9670042 100644 --- a/src/store.c +++ b/src/store.c @@ -130,10 +130,10 @@ static int proc_read_full_file(int procfd, const char *fn, char **contents, size fd = openat(procfd, fn, O_RDONLY|O_CLOEXEC); if (fd < 0) - return log_error_errno(errno, "Failed to openat /proc/<>: %m"); + return log_error_errno(errno, "Failed to openat /proc/%s: %m", fn); - if (fstatat(procfd, fn, &st, 0) < 0) - return log_error_errno(errno, "Failed to fstatat /proc/<>: %m"); + if (fstat(fd, &st) < 0) + return log_error_errno(errno, "Failed to fstat /proc/%s: %m", fn); n = LINE_MAX; if (S_ISREG(st.st_mode)) { @@ -162,7 +162,7 @@ static int proc_read_full_file(int procfd, const char *fn, char **contents, size k = pread(fd, buf + l, n - l, l); if (k < 0) - return log_error_errno(errno, "Failed to pread /proc/<>: %m"); + return log_error_errno(errno, "Failed to pread /proc/%s: %m", fn); if (k == 0) break;