]>
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 | |
47819977 | 16 | index eb62ddb..e417a13 100644 |
62c5f3ad WB |
17 | --- a/src/bindings.c |
18 | +++ b/src/bindings.c | |
47819977 WB |
19 | @@ -44,6 +44,7 @@ static bool can_use_pidfd; |
20 | static bool can_use_swap; | |
21 | static bool can_use_sys_cpu; | |
22 | static bool has_versioned_opts; | |
62c5f3ad WB |
23 | +static bool memory_is_cgroupv2; |
24 | ||
25 | static volatile sig_atomic_t reload_successful; | |
26 | ||
47819977 WB |
27 | @@ -67,6 +68,11 @@ bool liblxcfs_has_versioned_opts(void) |
28 | return has_versioned_opts; | |
62c5f3ad WB |
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) | |
47819977 | 39 | @@ -837,6 +843,7 @@ static void __attribute__((constructor)) lxcfs_init(void) |
62c5f3ad WB |
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 | ||
47819977 WB |
47 | @@ -894,6 +901,9 @@ static void __attribute__((constructor)) lxcfs_init(void) |
48 | else | |
49 | lxcfs_info("Kernel does not support swap accounting"); | |
62c5f3ad WB |
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:"); | |
47819977 WB |
55 | for (size_t nr = 0; nr < nr_api_extensions; nr++) |
56 | lxcfs_info("- %s", api_extensions[nr]); | |
62c5f3ad | 57 | diff --git a/src/bindings.h b/src/bindings.h |
47819977 | 58 | index cd7d466..2b7c8f4 100644 |
62c5f3ad WB |
59 | --- a/src/bindings.h |
60 | +++ b/src/bindings.h | |
47819977 | 61 | @@ -98,6 +98,7 @@ extern void prune_init_slice(char *cg); |
62c5f3ad WB |
62 | extern bool supports_pidfd(void); |
63 | extern bool liblxcfs_functional(void); | |
47819977 | 64 | extern bool liblxcfs_can_use_swap(void); |
62c5f3ad | 65 | +extern bool liblxcfs_memory_is_cgroupv2(void); |
47819977 WB |
66 | extern bool liblxcfs_can_use_sys_cpu(void); |
67 | extern bool liblxcfs_has_versioned_opts(void); | |
62c5f3ad | 68 | |
62c5f3ad | 69 | diff --git a/src/proc_fuse.c b/src/proc_fuse.c |
47819977 | 70 | index 94168c9..a07e8d6 100644 |
62c5f3ad WB |
71 | --- a/src/proc_fuse.c |
72 | +++ b/src/proc_fuse.c | |
47819977 | 73 | @@ -299,6 +299,43 @@ static inline bool startswith(const char *line, const char *pref) |
62c5f3ad WB |
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 | { | |
47819977 | 117 | @@ -307,7 +344,7 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, |
62c5f3ad | 118 | struct fuse_context *fc = fuse_get_context(); |
47819977 | 119 | bool wants_swap = lxcfs_has_opt(fuse_get_context()->private_data, LXCFS_SWAP_ON); |
62c5f3ad WB |
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; | |
47819977 | 126 | @@ -353,26 +390,8 @@ static int proc_swaps_read(char *buf, size_t size, off_t offset, |
62c5f3ad WB |
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 | ||
47819977 | 155 | @@ -1141,7 +1160,7 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, |
62c5f3ad | 156 | struct fuse_context *fc = fuse_get_context(); |
47819977 | 157 | bool wants_swap = lxcfs_has_opt(fuse_get_context()->private_data, LXCFS_SWAP_ON); |
62c5f3ad WB |
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 = {}; | |
47819977 | 164 | @@ -1193,26 +1212,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, |
62c5f3ad WB |
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) | |
47819977 | 193 | @@ -1251,7 +1252,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, |
62c5f3ad WB |
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 | } |