]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/cgroups/cgroup.c
2e9670e3b190b015a6b33c727f38a3fc7acf61ff
[mirror_lxc.git] / src / lxc / cgroups / cgroup.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <unistd.h>
10
11 #include "cgroup.h"
12 #include "cgroup2_devices.h"
13 #include "conf.h"
14 #include "config.h"
15 #include "initutils.h"
16 #include "log.h"
17 #include "start.h"
18
19 lxc_log_define(cgroup, lxc);
20
21 extern struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf);
22
23 struct cgroup_ops *cgroup_init(struct lxc_conf *conf)
24 {
25 struct cgroup_ops *cgroup_ops;
26
27 if (!conf)
28 return log_error_errno(NULL, EINVAL, "No valid conf given");
29
30 cgroup_ops = cgfsng_ops_init(conf);
31 if (!cgroup_ops)
32 return log_error_errno(NULL, errno, "Failed to initialize cgroup driver");
33
34 if (cgroup_ops->data_init(cgroup_ops)) {
35 cgroup_exit(cgroup_ops);
36 return log_error_errno(NULL, errno,
37 "Failed to initialize cgroup data");
38 }
39
40 TRACE("Initialized cgroup driver %s", cgroup_ops->driver);
41
42 if (cgroup_ops->cgroup_layout == CGROUP_LAYOUT_LEGACY)
43 TRACE("Running with legacy cgroup layout");
44 else if (cgroup_ops->cgroup_layout == CGROUP_LAYOUT_HYBRID)
45 TRACE("Running with hybrid cgroup layout");
46 else if (cgroup_ops->cgroup_layout == CGROUP_LAYOUT_UNIFIED)
47 TRACE("Running with unified cgroup layout");
48 else
49 WARN("Running with unknown cgroup layout");
50
51 return cgroup_ops;
52 }
53
54 void cgroup_exit(struct cgroup_ops *ops)
55 {
56 char **cur;
57 struct hierarchy **it;
58
59 if (!ops)
60 return;
61
62 for (cur = ops->cgroup_use; cur && *cur; cur++)
63 free(*cur);
64
65 free(ops->cgroup_pattern);
66 free(ops->container_cgroup);
67 free(ops->monitor_cgroup);
68
69 if (ops->cgroup2_devices)
70 bpf_program_free(ops->cgroup2_devices);
71
72 for (it = ops->hierarchies; it && *it; it++) {
73 char **p;
74
75 for (p = (*it)->controllers; p && *p; p++)
76 free(*p);
77 free((*it)->controllers);
78
79 for (p = (*it)->cgroup2_chown; p && *p; p++)
80 free(*p);
81 free((*it)->cgroup2_chown);
82
83 free((*it)->mountpoint);
84 free((*it)->container_base_path);
85 free((*it)->container_full_path);
86 free((*it)->monitor_full_path);
87 if ((*it)->cgfd_mon >= 0)
88 close((*it)->cgfd_con);
89 if ((*it)->cgfd_mon >= 0)
90 close((*it)->cgfd_mon);
91 free(*it);
92 }
93 free(ops->hierarchies);
94
95 free(ops);
96
97 return;
98 }
99
100 #define INIT_SCOPE "/init.scope"
101 void prune_init_scope(char *cg)
102 {
103 char *point;
104
105 if (!cg)
106 return;
107
108 point = cg + strlen(cg) - strlen(INIT_SCOPE);
109 if (point < cg)
110 return;
111
112 if (strcmp(point, INIT_SCOPE) == 0) {
113 if (point == cg)
114 *(point + 1) = '\0';
115 else
116 *point = '\0';
117 }
118 }