1 /* SPDX-License-Identifier: GPL-2.0 */
7 #include <linux/limits.h>
13 #include <sys/types.h>
17 #include "cgroup_util.h"
19 static ssize_t
read_text(const char *path
, char *buf
, size_t max_len
)
24 fd
= open(path
, O_RDONLY
);
28 len
= read(fd
, buf
, max_len
- 1);
38 static ssize_t
write_text(const char *path
, char *buf
, ssize_t len
)
42 fd
= open(path
, O_WRONLY
| O_APPEND
);
46 len
= write(fd
, buf
, len
);
57 char *cg_name(const char *root
, const char *name
)
59 size_t len
= strlen(root
) + strlen(name
) + 2;
60 char *ret
= malloc(len
);
62 snprintf(ret
, len
, "%s/%s", root
, name
);
67 char *cg_name_indexed(const char *root
, const char *name
, int index
)
69 size_t len
= strlen(root
) + strlen(name
) + 10;
70 char *ret
= malloc(len
);
72 snprintf(ret
, len
, "%s/%s_%d", root
, name
, index
);
77 int cg_read(const char *cgroup
, const char *control
, char *buf
, size_t len
)
81 snprintf(path
, sizeof(path
), "%s/%s", cgroup
, control
);
83 if (read_text(path
, buf
, len
) >= 0)
89 int cg_read_strcmp(const char *cgroup
, const char *control
,
96 /* Handle the case of comparing against empty string */
100 size
= strlen(expected
) + 1;
106 if (cg_read(cgroup
, control
, buf
, size
)) {
111 ret
= strcmp(expected
, buf
);
116 int cg_read_strstr(const char *cgroup
, const char *control
, const char *needle
)
120 if (cg_read(cgroup
, control
, buf
, sizeof(buf
)))
123 return strstr(buf
, needle
) ? 0 : -1;
126 long cg_read_long(const char *cgroup
, const char *control
)
130 if (cg_read(cgroup
, control
, buf
, sizeof(buf
)))
136 long cg_read_key_long(const char *cgroup
, const char *control
, const char *key
)
141 if (cg_read(cgroup
, control
, buf
, sizeof(buf
)))
144 ptr
= strstr(buf
, key
);
148 return atol(ptr
+ strlen(key
));
151 int cg_write(const char *cgroup
, const char *control
, char *buf
)
154 ssize_t len
= strlen(buf
);
156 snprintf(path
, sizeof(path
), "%s/%s", cgroup
, control
);
158 if (write_text(path
, buf
, len
) == len
)
164 int cg_find_unified_root(char *root
, size_t len
)
166 char buf
[10 * PAGE_SIZE
];
167 char *fs
, *mount
, *type
;
168 const char delim
[] = "\n\t ";
170 if (read_text("/proc/self/mounts", buf
, sizeof(buf
)) <= 0)
175 * cgroup /sys/fs/cgroup cgroup2 rw,seclabel,noexec,relatime 0 0
177 for (fs
= strtok(buf
, delim
); fs
; fs
= strtok(NULL
, delim
)) {
178 mount
= strtok(NULL
, delim
);
179 type
= strtok(NULL
, delim
);
184 if (strcmp(type
, "cgroup2") == 0) {
185 strncpy(root
, mount
, len
);
193 int cg_create(const char *cgroup
)
195 return mkdir(cgroup
, 0644);
198 static int cg_killall(const char *cgroup
)
203 if (cg_read(cgroup
, "cgroup.procs", buf
, sizeof(buf
)))
206 while (ptr
< buf
+ sizeof(buf
)) {
207 int pid
= strtol(ptr
, &ptr
, 10);
215 if (kill(pid
, SIGKILL
))
222 int cg_destroy(const char *cgroup
)
228 if (ret
&& errno
== EBUSY
) {
229 ret
= cg_killall(cgroup
);
236 if (ret
&& errno
== ENOENT
)
242 int cg_enter_current(const char *cgroup
)
246 snprintf(pidbuf
, sizeof(pidbuf
), "%d", getpid());
247 return cg_write(cgroup
, "cgroup.procs", pidbuf
);
250 int cg_run(const char *cgroup
,
251 int (*fn
)(const char *cgroup
, void *arg
),
259 } else if (pid
== 0) {
262 snprintf(buf
, sizeof(buf
), "%d", getpid());
263 if (cg_write(cgroup
, "cgroup.procs", buf
))
265 exit(fn(cgroup
, arg
));
267 waitpid(pid
, &retcode
, 0);
268 if (WIFEXITED(retcode
))
269 return WEXITSTATUS(retcode
);
275 int cg_run_nowait(const char *cgroup
,
276 int (*fn
)(const char *cgroup
, void *arg
),
285 snprintf(buf
, sizeof(buf
), "%d", getpid());
286 if (cg_write(cgroup
, "cgroup.procs", buf
))
288 exit(fn(cgroup
, arg
));
294 int get_temp_fd(void)
296 return open(".", O_TMPFILE
| O_RDWR
| O_EXCL
);
299 int alloc_pagecache(int fd
, size_t size
)
310 if (ftruncate(fd
, size
))
313 for (i
= 0; i
< size
; i
+= sizeof(buf
))
314 read(fd
, buf
, sizeof(buf
));
322 int alloc_anon(const char *cgroup
, void *arg
)
324 size_t size
= (unsigned long)arg
;
328 for (ptr
= buf
; ptr
< buf
+ size
; ptr
+= PAGE_SIZE
)
335 int is_swap_enabled(void)
338 const char delim
[] = "\n";
342 if (read_text("/proc/swaps", buf
, sizeof(buf
)) <= 0)
345 for (line
= strtok(buf
, delim
); line
; line
= strtok(NULL
, delim
))
351 int set_oom_adj_score(int pid
, int score
)
356 sprintf(path
, "/proc/%d/oom_score_adj", pid
);
358 fd
= open(path
, O_WRONLY
| O_APPEND
);
362 len
= dprintf(fd
, "%d", score
);