Skip to content

Commit 2c8198c

Browse files
committed
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.
1 parent 65c3927 commit 2c8198c

File tree

1 file changed

+66
-1
lines changed

1 file changed

+66
-1
lines changed

src/store.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
along with systemd; If not, see <http://www.gnu.org/licenses/>.
2121
***/
2222

23+
#define _POSIX_C_SOURCE
24+
2325
#include <dirent.h>
2426
#include <errno.h>
2527
#include <fcntl.h>
@@ -29,6 +31,7 @@
2931
#include <string.h>
3032
#include <time.h>
3133
#include <unistd.h>
34+
#include <sys/stat.h>
3235

3336
#include "alloc-util.h"
3437
#include "bootchart.h"
@@ -119,6 +122,68 @@ static void garbage_collect_dead_processes(struct ps_struct *ps_first) {
119122
}
120123
}
121124

125+
static int proc_read_full_file(int procfd, const char *fn, char **contents, size_t *size) {
126+
int fd = -1;
127+
size_t n, l;
128+
_cleanup_free_ char *buf = NULL;
129+
struct stat st;
130+
131+
fd = openat(procfd, fn, O_RDONLY|O_CLOEXEC);
132+
if (fd < 0)
133+
return log_error_errno(errno, "Failed to openat /proc/<>: %m");
134+
135+
if (fstatat(procfd, fn, &st, 0) < 0)
136+
return log_error_errno(errno, "Failed to fstatat /proc/<>: %m");
137+
138+
n = LINE_MAX;
139+
if (S_ISREG(st.st_mode)) {
140+
141+
/* Safety check */
142+
if (st.st_size > 4*1024*1024)
143+
return -E2BIG;
144+
145+
/* Start with the right file size, but be prepared for
146+
* files from /proc which generally report a file size
147+
* of 0 */
148+
if (st.st_size > 0)
149+
n = st.st_size;
150+
}
151+
152+
l = 0;
153+
for (;;) {
154+
char *t;
155+
ssize_t k;
156+
157+
t = realloc(buf, n+1);
158+
if (!t)
159+
return -ENOMEM;
160+
161+
buf = t;
162+
k = pread(fd, buf + l, n - l, l);
163+
164+
if (k < 0)
165+
return log_error_errno(errno, "Failed to pread /proc/<>: %m");
166+
if (k == 0)
167+
break;
168+
169+
l += k;
170+
n *= 2;
171+
172+
/* Safety check */
173+
if (n > 4*1024*1024)
174+
return -E2BIG;
175+
}
176+
177+
buf[l] = 0;
178+
*contents = buf;
179+
buf = NULL; /* do not free */
180+
181+
if (size)
182+
*size = l;
183+
184+
safe_close(fd);
185+
return 0;
186+
}
122187

123188
int log_sample(DIR *proc,
124189
int sample,
@@ -189,7 +254,7 @@ int log_sample(DIR *proc,
189254
}
190255

191256
/* Parse "/proc/schedstat" for overall CPU utilization */
192-
r = read_full_file("/proc/schedstat", &buf_schedstat, NULL);
257+
r = proc_read_full_file(procfd, "schedstat", &buf_schedstat, NULL);
193258
if (r < 0)
194259
return log_error_errno(r, "Unable to read schedstat: %m");
195260

0 commit comments

Comments
 (0)