]> git.pld-linux.org Git - packages/dovecot.git/blob - proc-status.patch
Rel 2; handle /proc/self/status from newer kernels
[packages/dovecot.git] / proc-status.patch
1 From f359c6ee179aad5e077711c188fc8422106cbead Mon Sep 17 00:00:00 2001
2 From: Aki Tuomi <aki.tuomi@open-xchange.com>
3 Date: Tue, 21 Mar 2023 08:55:55 +0200
4 Subject: [PATCH 1/3] lib: process-stat - Use buffer_append_full_istream() to
5  read files
6
7 ---
8  src/lib/process-stat.c | 84 ++++++++++++++++++++++--------------------
9  1 file changed, 44 insertions(+), 40 deletions(-)
10
11 diff --git a/src/lib/process-stat.c b/src/lib/process-stat.c
12 index 782503e60b..60eddbc3ec 100644
13 --- a/src/lib/process-stat.c
14 +++ b/src/lib/process-stat.c
15 @@ -1,6 +1,9 @@
16  /* Copyright (c) 2008-2021 Dovecot authors, see the included COPYING file */
17  
18  #include "lib.h"
19 +#include "buffer.h"
20 +#include "str.h"
21 +#include "istream.h"
22  #include "process-stat.h"
23  #include "time-util.h"
24  #include <limits.h>
25 @@ -12,8 +15,12 @@
26  #include <stdio.h>
27  
28  #define PROC_STAT_PATH "/proc/self/stat"
29 +#define PROC_STAT_MAX_SIZE 1024
30  #define PROC_STATUS_PATH "/proc/self/status"
31 +#define PROC_STATUS_MAX_SIZE 2048
32  #define PROC_IO_PATH "/proc/self/io"
33 +#define PROC_IO_MAX_SIZE 1024
34 +#define PROC_BUFFER_INITIAL_SIZE 512
35  
36  static const uint64_t stat_undefined = 0xFFFFFFFFFFFFFFFF;
37  
38 @@ -71,39 +78,38 @@ static int open_fd(const char *path, struct event *event)
39  }
40  
41  static int
42 -read_file(int fd, const char *path, char *buf_r, size_t buf_size, struct event *event)
43 +read_file_buffer(const char *path, string_t *buf, size_t max_size, struct event *event)
44  {
45 -       ssize_t ret;
46 -       ret = read(fd, buf_r, buf_size);
47 -       if (ret <= 0) {
48 -               if (ret == -1)
49 -                       e_error(event, "read(%s) failed: %m", path);
50 -               else
51 -                       e_error(event, "read(%s) returned EOF", path);
52 -       } else if (ret == (ssize_t)buf_size) {
53 -               e_error(event, "%s is larger than expected", path);
54 -               buf_r[buf_size - 1] = '\0';
55 -       } else {
56 -               buf_r[ret] = '\0';
57 +       const char *error;
58 +       int fd = open_fd(path, event);
59 +       if (fd < 0)
60 +               return -1;
61 +       struct istream *is = i_stream_create_fd_autoclose(&fd, max_size);
62 +       i_stream_set_name(is, path);
63 +       enum buffer_append_result res =
64 +               buffer_append_full_istream(buf, is, max_size, &error);
65 +       i_stream_unref(&is);
66 +       if (res == BUFFER_APPEND_READ_MAX_SIZE)
67 +               e_error(event, "%s is larger than expected (%zu)", path, max_size);
68 +       else if (res != BUFFER_APPEND_OK) {
69 +               e_error(event, "read(%s) failed: %s", path, error);
70 +               return -1;
71         }
72 -       i_close_fd(&fd);
73 -       return ret <= 0 ? -1 : 0;
74 +       return 0;
75  }
76  
77  static int parse_key_val_file(const char *path,
78 +                             size_t max_size,
79                               struct key_val *fields,
80                               struct event *event)
81  {
82 -       char buf[2048];
83 -       int fd;
84 -
85 -       fd = open_fd(path, event);
86 -       if (fd == -1 || read_file(fd, path, buf, sizeof(buf), event) < 0) {
87 +       string_t *buf = t_str_new(PROC_BUFFER_INITIAL_SIZE);
88 +       if (read_file_buffer(path, buf, max_size, event) < 0) {
89                 for (; fields->key != NULL; fields++)
90                         *fields->value = stat_undefined;
91                 return -1;
92         }
93 -       buffer_parse(buf, fields);
94 +       buffer_parse(str_c(buf), fields);
95         return 0;
96  }
97  
98 @@ -117,7 +123,8 @@ static int parse_proc_io(struct process_stat *stat_r, struct event *event)
99                 { NULL, NULL, 0 },
100         };
101         if (stat_r->proc_io_failed ||
102 -           parse_key_val_file(PROC_IO_PATH, fields, event) < 0) {
103 +           parse_key_val_file(PROC_IO_PATH, PROC_IO_MAX_SIZE, fields,
104 +                              event) < 0) {
105                 stat_r->proc_io_failed = TRUE;
106                 return -1;
107         }
108 @@ -132,7 +139,8 @@ static int parse_proc_status(struct process_stat *stat_r, struct event *event)
109                 { NULL, NULL, 0 },
110         };
111         if (stat_r->proc_status_failed ||
112 -           parse_key_val_file(PROC_STATUS_PATH, fields, event) < 0) {
113 +           parse_key_val_file(PROC_STATUS_PATH, PROC_STATUS_MAX_SIZE,
114 +                              fields, event) < 0) {
115                 stat_r->proc_status_failed = TRUE;
116                 return -1;
117         }
118 @@ -156,8 +164,7 @@ static int stat_get_rusage(struct process_stat *stat_r)
119  
120  static int parse_stat_file(struct process_stat *stat_r, struct event *event)
121  {
122 -       int fd = -1;
123 -       char buf[1024];
124 +       string_t *buf = t_str_new(PROC_BUFFER_INITIAL_SIZE);
125         unsigned int i;
126         const char *const *tmp;
127         struct {
128 @@ -171,9 +178,8 @@ static int parse_stat_file(struct process_stat *stat_r, struct event *event)
129                 { &stat_r->vsz, 22 },
130                 { &stat_r->rss, 23 },
131         };
132 -       if (!stat_r->proc_stat_failed)
133 -               fd = open_fd(PROC_STAT_PATH, event);
134 -       if (fd == -1) {
135 +       if (stat_r->proc_stat_failed ||
136 +           read_file_buffer(PROC_STAT_PATH, buf, PROC_STAT_MAX_SIZE, event) < 0) {
137                 stat_r->proc_stat_failed = TRUE;
138                 /* vsz and rss are not provided by getrusage(), setting to undefined */
139                 stat_r->vsz = stat_undefined;
140 @@ -187,11 +193,7 @@ static int parse_stat_file(struct process_stat *stat_r, struct event *event)
141                 }
142                 return 0;
143         }
144 -       if (read_file(fd, PROC_STAT_PATH, buf, sizeof(buf), event) < 0) {
145 -               stat_r->proc_stat_failed = TRUE;
146 -               return -1;
147 -       }
148 -       tmp = t_strsplit(buf, " ");
149 +       tmp = t_strsplit(str_c(buf), " ");
150         unsigned int tmp_count = str_array_length(tmp);
151  
152         for (i = 0; i < N_ELEMENTS(fields); i++) {
153 @@ -208,13 +210,15 @@ static int parse_all_stats(struct process_stat *stat_r, struct event *event)
154  {
155         bool has_fields = FALSE;
156  
157 -       if (parse_stat_file(stat_r, event) == 0)
158 -               has_fields = TRUE;
159 -       if (parse_proc_io(stat_r, event) == 0)
160 -               has_fields = TRUE;
161 -       if ((!stat_r->proc_stat_failed || stat_r->rusage_failed) &&
162 -           parse_proc_status(stat_r, event) == 0)
163 -               has_fields = TRUE;
164 +       T_BEGIN {
165 +               if (parse_stat_file(stat_r, event) == 0)
166 +                       has_fields = TRUE;
167 +               if (parse_proc_io(stat_r, event) == 0)
168 +                       has_fields = TRUE;
169 +               if ((!stat_r->proc_stat_failed || stat_r->rusage_failed) &&
170 +                   parse_proc_status(stat_r, event) == 0)
171 +                       has_fields = TRUE;
172 +       } T_END;
173  
174         if (has_fields)
175                 return 0;
176
177 From 218a79a48bb0e5d2be44bb46c51836fd406b0c50 Mon Sep 17 00:00:00 2001
178 From: Aki Tuomi <aki.tuomi@open-xchange.com>
179 Date: Tue, 21 Mar 2023 09:05:12 +0200
180 Subject: [PATCH 2/3] lib: process-stat - Increase maximum /proc/self/status
181  size
182
183 Kernel 6.x has larger status file.
184 ---
185  src/lib/process-stat.c | 2 +-
186  1 file changed, 1 insertion(+), 1 deletion(-)
187
188 diff --git a/src/lib/process-stat.c b/src/lib/process-stat.c
189 index 60eddbc3ec..1d23c89964 100644
190 --- a/src/lib/process-stat.c
191 +++ b/src/lib/process-stat.c
192 @@ -17,7 +17,7 @@
193  #define PROC_STAT_PATH "/proc/self/stat"
194  #define PROC_STAT_MAX_SIZE 1024
195  #define PROC_STATUS_PATH "/proc/self/status"
196 -#define PROC_STATUS_MAX_SIZE 2048
197 +#define PROC_STATUS_MAX_SIZE 4096
198  #define PROC_IO_PATH "/proc/self/io"
199  #define PROC_IO_MAX_SIZE 1024
200  #define PROC_BUFFER_INITIAL_SIZE 512
201
202 From d93c31d51b05d43eaa6eeef9cdc0f7a4157f7d0e Mon Sep 17 00:00:00 2001
203 From: Aki Tuomi <aki.tuomi@open-xchange.com>
204 Date: Tue, 21 Mar 2023 09:13:35 +0200
205 Subject: [PATCH 3/3] lib: process-stat - Use eacces_error_get() for EACCES
206  errno
207
208 This tells better why the open failed.
209 ---
210  src/lib/process-stat.c | 5 ++++-
211  1 file changed, 4 insertions(+), 1 deletion(-)
212
213 diff --git a/src/lib/process-stat.c b/src/lib/process-stat.c
214 index 1d23c89964..454d9335d2 100644
215 --- a/src/lib/process-stat.c
216 +++ b/src/lib/process-stat.c
217 @@ -4,6 +4,7 @@
218  #include "buffer.h"
219  #include "str.h"
220  #include "istream.h"
221 +#include "eacces-error.h"
222  #include "process-stat.h"
223  #include "time-util.h"
224  #include <limits.h>
225 @@ -69,8 +70,10 @@ static int open_fd(const char *path, struct event *event)
226                 errno = EACCES;
227         }
228         if (fd == -1) {
229 -               if (errno == ENOENT || errno == EACCES)
230 +               if (errno == ENOENT)
231                         e_debug(event, "open(%s) failed: %m", path);
232 +               else if (errno == EACCES)
233 +                       e_debug(event, "%s", eacces_error_get("open", path));
234                 else
235                         e_error(event, "open(%s) failed: %m", path);
236         }
This page took 0.058554 seconds and 3 git commands to generate.