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
,
92 size_t size
= strlen(expected
) + 1;
99 if (cg_read(cgroup
, control
, buf
, size
))
102 return strcmp(expected
, buf
);
105 int cg_read_strstr(const char *cgroup
, const char *control
, const char *needle
)
109 if (cg_read(cgroup
, control
, buf
, sizeof(buf
)))
112 return strstr(buf
, needle
) ? 0 : -1;
115 long cg_read_long(const char *cgroup
, const char *control
)
119 if (cg_read(cgroup
, control
, buf
, sizeof(buf
)))
125 long cg_read_key_long(const char *cgroup
, const char *control
, const char *key
)
130 if (cg_read(cgroup
, control
, buf
, sizeof(buf
)))
133 ptr
= strstr(buf
, key
);
137 return atol(ptr
+ strlen(key
));
140 int cg_write(const char *cgroup
, const char *control
, char *buf
)
143 ssize_t len
= strlen(buf
);
145 snprintf(path
, sizeof(path
), "%s/%s", cgroup
, control
);
147 if (write_text(path
, buf
, len
) == len
)
153 int cg_find_unified_root(char *root
, size_t len
)
155 char buf
[10 * PAGE_SIZE
];
156 char *fs
, *mount
, *type
;
157 const char delim
[] = "\n\t ";
159 if (read_text("/proc/self/mounts", buf
, sizeof(buf
)) <= 0)
164 * cgroup /sys/fs/cgroup cgroup2 rw,seclabel,noexec,relatime 0 0
166 for (fs
= strtok(buf
, delim
); fs
; fs
= strtok(NULL
, delim
)) {
167 mount
= strtok(NULL
, delim
);
168 type
= strtok(NULL
, delim
);
173 if (strcmp(fs
, "cgroup") == 0 &&
174 strcmp(type
, "cgroup2") == 0) {
175 strncpy(root
, mount
, len
);
183 int cg_create(const char *cgroup
)
185 return mkdir(cgroup
, 0644);
188 static int cg_killall(const char *cgroup
)
193 if (cg_read(cgroup
, "cgroup.procs", buf
, sizeof(buf
)))
196 while (ptr
< buf
+ sizeof(buf
)) {
197 int pid
= strtol(ptr
, &ptr
, 10);
205 if (kill(pid
, SIGKILL
))
212 int cg_destroy(const char *cgroup
)
218 if (ret
&& errno
== EBUSY
) {
219 ret
= cg_killall(cgroup
);
226 if (ret
&& errno
== ENOENT
)
232 int cg_enter_current(const char *cgroup
)
236 snprintf(pidbuf
, sizeof(pidbuf
), "%d", getpid());
237 return cg_write(cgroup
, "cgroup.procs", pidbuf
);
240 int cg_run(const char *cgroup
,
241 int (*fn
)(const char *cgroup
, void *arg
),
249 } else if (pid
== 0) {
252 snprintf(buf
, sizeof(buf
), "%d", getpid());
253 if (cg_write(cgroup
, "cgroup.procs", buf
))
255 exit(fn(cgroup
, arg
));
257 waitpid(pid
, &retcode
, 0);
258 if (WIFEXITED(retcode
))
259 return WEXITSTATUS(retcode
);
265 int cg_run_nowait(const char *cgroup
,
266 int (*fn
)(const char *cgroup
, void *arg
),
275 snprintf(buf
, sizeof(buf
), "%d", getpid());
276 if (cg_write(cgroup
, "cgroup.procs", buf
))
278 exit(fn(cgroup
, arg
));
284 int get_temp_fd(void)
286 return open(".", O_TMPFILE
| O_RDWR
| O_EXCL
);
289 int alloc_pagecache(int fd
, size_t size
)
300 if (ftruncate(fd
, size
))
303 for (i
= 0; i
< size
; i
+= sizeof(buf
))
304 read(fd
, buf
, sizeof(buf
));
312 int alloc_anon(const char *cgroup
, void *arg
)
314 size_t size
= (unsigned long)arg
;
318 for (ptr
= buf
; ptr
< buf
+ size
; ptr
+= PAGE_SIZE
)
325 int is_swap_enabled(void)
328 const char delim
[] = "\n";
332 if (read_text("/proc/swaps", buf
, sizeof(buf
)) <= 0)
335 for (line
= strtok(buf
, delim
); line
; line
= strtok(NULL
, delim
))