]>
Commit | Line | Data |
---|---|---|
62c5f3ad WB |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
3 | Date: Thu, 8 Jul 2021 12:04:05 +0200 | |
4 | Subject: [PATCH lxcfs] make meminfo and swaps cgroupv2 aware | |
5 | ||
6 | and deduplicate the corresponding code | |
7 | ||
8 | Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> | |
9 | --- | |
10 | src/bindings.c | 10 ++++++ | |
11 | src/bindings.h | 1 + | |
12 | src/proc_fuse.c | 89 +++++++++++++++++++++++++------------------------ | |
13 | 3 files changed, 57 insertions(+), 43 deletions(-) | |
14 | ||
15 | diff --git a/src/bindings.c b/src/bindings.c | |
16 | index b169af4..d4da43e 100644 | |
17 | --- a/src/bindings.c | |
18 | +++ b/src/bindings.c | |
19 | @@ -59,6 +59,7 @@ | |
20 | static bool can_use_pidfd; | |
21 | static int can_use_swap = -1; | |
22 | struct cgroup_ops *cgroup_ops; | |
23 | +static bool memory_is_cgroupv2; | |
24 | ||
25 | static volatile sig_atomic_t reload_successful; | |
26 | ||
27 | @@ -79,6 +80,11 @@ bool liblxcfs_can_use_swap(const char *cgroup) | |
28 | return can_use_swap; | |
29 | } | |
30 | ||
31 | +bool liblxcfs_memory_is_cgroupv2(void) | |
32 | +{ | |
33 | + return memory_is_cgroupv2; | |
34 | +} | |
35 | + | |
36 | /* Define pivot_root() if missing from the C library */ | |
37 | #ifndef HAVE_PIVOT_ROOT | |
38 | static int pivot_root(const char *new_root, const char *put_old) | |
39 | @@ -847,6 +853,7 @@ static void __attribute__((constructor)) lxcfs_init(void) | |
40 | pidfd = -EBADF; | |
41 | int i = 0; | |
42 | pid_t pid; | |
43 | + struct hierarchy *hierarchy; | |
44 | ||
45 | lxcfs_info("Running constructor %s to reload liblxcfs", __func__); | |
46 | ||
47 | @@ -898,6 +905,9 @@ static void __attribute__((constructor)) lxcfs_init(void) | |
48 | lxcfs_info("Kernel supports pidfds"); | |
49 | } | |
50 | ||
51 | + hierarchy = cgroup_ops->get_hierarchy(cgroup_ops, "memory"); | |
52 | + memory_is_cgroupv2 = hierarchy && is_unified_hierarchy(hierarchy); | |
53 | + | |
54 | lxcfs_info("api_extensions:"); | |
55 | for (i = 0; i < nr_api_extensions; i++) | |
56 | lxcfs_info("- %s", api_extensions[i]); | |
57 | diff --git a/src/bindings.h b/src/bindings.h | |
58 | index a334947..9ab989a 100644 | |
59 | --- a/src/bindings.h | |
60 | +++ b/src/bindings.h | |
61 | @@ -92,6 +92,7 @@ extern void prune_init_slice(char *cg); | |
62 | extern bool supports_pidfd(void); | |
63 | extern bool liblxcfs_functional(void); | |
64 | extern bool liblxcfs_can_use_swap(const char *cgroup); | |
65 | +extern bool liblxcfs_memory_is_cgroupv2(void); | |
66 | ||
67 | static inline int install_signal_handler(int signo, | |
68 | void (*handler)(int, siginfo_t *, void *)) | |
69 | diff --git a/src/proc_fuse.c b/src/proc_fuse.c | |
70 | index 9a5915c..6371b2c 100644 | |
71 | --- a/src/proc_fuse.c | |
72 | +++ b/src/proc_fuse.c | |
73 | @@ -315,6 +315,43 @@ static inline bool startswith(const char *line, const char *pref) | |
74 | return strncmp(line, pref, strlen(pref)) == 0; | |
75 | } | |
76 | ||
77 | +static void get_swap_info(const char *cgroup, uint64_t memlimit, | |
78 | + uint64_t memusage, uint64_t *swtotal, | |
79 | + uint64_t *swusage, uint64_t *memswpriority) | |
80 | +{ | |
81 | + __do_free char *memswusage_str = NULL, *memswpriority_str = NULL; | |
82 | + size_t memswlimit = 0, memswusage = 0; | |
83 | + int ret; | |
84 | + | |
85 | + *swtotal = *swusage = 0; | |
86 | + *memswpriority = 1; | |
87 | + | |
88 | + memswlimit = get_min_memlimit(cgroup, true); | |
89 | + if (memswlimit > 0) { | |
90 | + ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); | |
91 | + if (ret < 0 || safe_uint64(memswusage_str, &memswusage, 10) != 0) | |
92 | + return; | |
93 | + | |
94 | + if (liblxcfs_memory_is_cgroupv2()) { | |
95 | + *swtotal = memswlimit / 1024; | |
96 | + *swusage = memswusage / 1024; | |
97 | + } else { | |
98 | + if (memlimit > memswlimit) | |
99 | + *swtotal = 0; | |
100 | + else | |
101 | + *swtotal = (memswlimit - memlimit) / 1024; | |
102 | + if (memusage > memswusage || swtotal == 0) | |
103 | + *swusage = 0; | |
104 | + else | |
105 | + *swusage = (memswusage - memusage) / 1024; | |
106 | + } | |
107 | + | |
108 | + ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str); | |
109 | + if (ret >= 0) | |
110 | + safe_uint64(memswpriority_str, memswpriority, 10); | |
111 | + } | |
112 | +} | |
113 | + | |
114 | static int proc_swaps_read(char *buf, size_t size, off_t offset, | |
115 | struct fuse_file_info *fi) | |
116 | { | |
117 | @@ -323,7 +360,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, | |
118 | struct fuse_context *fc = fuse_get_context(); | |
119 | struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data; | |
120 | struct file_info *d = INTTYPE_TO_PTR(fi->fh); | |
121 | - uint64_t memswlimit = 0, memlimit = 0, memusage = 0, memswusage = 0, | |
122 | + uint64_t memlimit = 0, memusage = 0, | |
123 | swtotal = 0, swusage = 0, memswpriority = 1, | |
124 | hostswtotal = 0, hostswfree = 0; | |
125 | ssize_t total_len = 0; | |
126 | @@ -373,26 +410,8 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, | |
127 | if (safe_uint64(memusage_str, &memusage, 10) < 0) | |
128 | lxcfs_error("Failed to convert memusage %s", memusage_str); | |
129 | ||
130 | - if (wants_swap) { | |
131 | - memswlimit = get_min_memlimit(cgroup, true); | |
132 | - if (memswlimit > 0) { | |
133 | - ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); | |
134 | - if (ret >= 0 && safe_uint64(memswusage_str, &memswusage, 10) == 0) { | |
135 | - if (memlimit > memswlimit) | |
136 | - swtotal = 0; | |
137 | - else | |
138 | - swtotal = (memswlimit - memlimit) / 1024; | |
139 | - if (memusage > memswusage || swtotal == 0) | |
140 | - swusage = 0; | |
141 | - else | |
142 | - swusage = (memswusage - memusage) / 1024; | |
143 | - } | |
144 | - | |
145 | - ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str); | |
146 | - if (ret >= 0) | |
147 | - safe_uint64(memswpriority_str, &memswpriority, 10); | |
148 | - } | |
149 | - } | |
150 | + if (wants_swap) | |
151 | + get_swap_info(cgroup, memlimit, memusage, &swtotal, &swusage, &memswpriority); | |
152 | ||
153 | total_len = snprintf(d->buf, d->size, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); | |
154 | ||
155 | @@ -1162,7 +1181,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, | |
156 | struct fuse_context *fc = fuse_get_context(); | |
157 | struct lxcfs_opts *opts = (struct lxcfs_opts *)fuse_get_context()->private_data; | |
158 | struct file_info *d = INTTYPE_TO_PTR(fi->fh); | |
159 | - uint64_t memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, | |
160 | + uint64_t memlimit = 0, memusage = 0, | |
161 | hosttotal = 0, swfree = 0, swusage = 0, swtotal = 0, | |
162 | memswpriority = 1; | |
163 | struct memory_stat mstat = {}; | |
164 | @@ -1216,26 +1235,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, | |
165 | * Following values are allowed to fail, because swapaccount might be | |
166 | * turned off for current kernel. | |
167 | */ | |
168 | - if (wants_swap) { | |
169 | - memswlimit = get_min_memlimit(cgroup, true); | |
170 | - if (memswlimit > 0) { | |
171 | - ret = cgroup_ops->get_memory_swap_current(cgroup_ops, cgroup, &memswusage_str); | |
172 | - if (ret >= 0 && safe_uint64(memswusage_str, &memswusage, 10) == 0) { | |
173 | - if (memlimit > memswlimit) | |
174 | - swtotal = 0; | |
175 | - else | |
176 | - swtotal = (memswlimit - memlimit) / 1024; | |
177 | - if (memusage > memswusage || swtotal == 0) | |
178 | - swusage = 0; | |
179 | - else | |
180 | - swusage = (memswusage - memusage) / 1024; | |
181 | - } | |
182 | - } | |
183 | - | |
184 | - ret = cgroup_ops->get_memory_swappiness(cgroup_ops, cgroup, &memswpriority_str); | |
185 | - if (ret >= 0) | |
186 | - safe_uint64(memswpriority_str, &memswpriority, 10); | |
187 | - } | |
188 | + if (wants_swap) | |
189 | + get_swap_info(cgroup, memlimit, memusage, &swtotal, &swusage, &memswpriority); | |
190 | ||
191 | f = fopen_cached("/proc/meminfo", "re", &fopen_cache); | |
192 | if (!f) | |
193 | @@ -1274,7 +1275,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, | |
194 | This is because the kernel can swap as much as it | |
195 | wants and not only up to swtotal. */ | |
196 | ||
197 | - swtotal = memlimit + swtotal; | |
198 | + if (!liblxcfs_memory_is_cgroupv2()) | |
199 | + swtotal += memlimit; | |
200 | + | |
201 | if (hostswtotal < swtotal) { | |
202 | swtotal = hostswtotal; | |
203 | } |