Skip to content

Commit 375d162

Browse files
authored
MCOL-5500 This patch adds cgroup v2 support with some sanity checks for (mariadb-corporation#2849)
values reported by cgroups v1
1 parent ab9b95e commit 375d162

File tree

2 files changed

+75
-186
lines changed

2 files changed

+75
-186
lines changed

utils/common/cgroupconfigurator.cpp

+64-174
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
#include "cgroupconfigurator.h"
1919
#include "configcpp.h"
2020
#include "logger.h"
21+
#include <charconv>
2122
#include <fstream>
2223
#include <iostream>
24+
#include <limits>
2325
#include <sys/sysinfo.h>
2426

2527
using namespace boost;
@@ -77,9 +79,8 @@ CGroupConfigurator::CGroupConfigurator()
7779
else
7880
cGroupDefined = true;
7981

80-
totalMemory = 0;
81-
totalSwap = 0;
82-
printedWarning = false;
82+
ifstream v2Check("/sys/fs/cgroup/cgroup.controllers");
83+
cGroupVersion_ = (v2Check) ? v2 : v1;
8384
}
8485

8586
CGroupConfigurator::~CGroupConfigurator()
@@ -88,9 +89,16 @@ CGroupConfigurator::~CGroupConfigurator()
8889

8990
uint32_t CGroupConfigurator::getNumCoresFromCGroup()
9091
{
91-
ostringstream filename_os;
92-
filename_os << "/sys/fs/cgroup/cpuset/" << cGroupName << "/cpus";
93-
string filename = filename_os.str();
92+
ostringstream filenameOs;
93+
if (cGroupVersion_ == v1)
94+
{
95+
filenameOs << "/sys/fs/cgroup/cpuset/" << cGroupName << "/cpuset.cpus";
96+
}
97+
else
98+
{
99+
filenameOs << "/sys/fs/cgroup/" << cGroupName << "/cpuset.cpus";
100+
}
101+
string filename = filenameOs.str();
94102

95103
ifstream in(filename.c_str());
96104
string cpusString;
@@ -141,7 +149,7 @@ uint32_t CGroupConfigurator::getNumCoresFromCGroup()
141149
first = last + 1;
142150
}
143151

144-
// cout << "found " << cpus << " CPUS in the string " << cpusString << endl;
152+
cout << "found " << cpus << " CPUS in the string " << cpusString << endl;
145153
return cpus;
146154
}
147155

@@ -155,7 +163,7 @@ uint32_t CGroupConfigurator::getNumCoresFromProc()
155163
uint32_t CGroupConfigurator::getNumCores()
156164
{
157165
/*
158-
Detect if InfiniDB is in a C-Group
166+
Detect if MCS is in a C-Group
159167
- get the group ID
160168
If not, get the number of cores from /proc
161169
*/
@@ -171,7 +179,7 @@ uint32_t CGroupConfigurator::getNumCores()
171179
ret = getNumCoresFromProc();
172180
}
173181

174-
// cout << "There are " << ret << " cores available" << endl;
182+
cout << "There are " << ret << " cores available" << endl;
175183
return ret;
176184
}
177185

@@ -188,11 +196,11 @@ uint64_t CGroupConfigurator::getTotalMemory()
188196
{
189197
ret = getTotalMemoryFromCGroup();
190198

191-
if (ret == 0)
199+
if (ret == 0 || ret == std::numeric_limits<uint64_t>::max())
192200
ret = getTotalMemoryFromProc();
193201
}
194202

195-
// cout << "Total mem available is " << ret << endl;
203+
cout << "Total mem available is " << ret << endl;
196204
totalMemory = ret;
197205
return totalMemory;
198206
}
@@ -201,23 +209,11 @@ uint64_t CGroupConfigurator::getTotalMemoryFromProc()
201209
{
202210
size_t memTot;
203211

204-
#if defined(__FreeBSD__)
205-
string cmd("sysctl -a | awk '/realmem/ {print int(($2+1023)/1024);}'");
206-
FILE* cmdPipe;
207-
char input[80];
208-
cmdPipe = popen(cmd.c_str(), "r");
209-
input[0] = '\0';
210-
fgets(input, 80, cmdPipe);
211-
input[79] = '\0';
212-
pclose(cmdPipe);
213-
memTot = atoi(input);
214-
#else
215212
ifstream in("/proc/meminfo");
216213
string x;
217214

218215
in >> x;
219216
in >> memTot;
220-
#endif
221217

222218
// memTot is now in KB, convert to bytes
223219
memTot *= 1024;
@@ -227,61 +223,88 @@ uint64_t CGroupConfigurator::getTotalMemoryFromProc()
227223

228224
uint64_t CGroupConfigurator::getTotalMemoryFromCGroup()
229225
{
230-
ifstream in;
231-
uint64_t ret;
226+
std::string memLimitStr;
227+
uint64_t memLimit = std::numeric_limits<uint64_t>::max();
232228
ostringstream os;
233-
string filename;
234229

235-
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.limit_in_bytes";
236-
filename = os.str();
230+
if (cGroupVersion_ == v1)
231+
{
232+
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.limit_in_bytes";
233+
}
234+
else
235+
{
236+
os << "/sys/fs/cgroup/" << cGroupName << "/memory.max";
237+
}
238+
string filename = os.str();
237239

238-
in.open(filename.c_str());
240+
ifstream in(filename.c_str());
239241

240242
if (!in)
241243
RETURN_NO_GROUP(0);
242244

243245
try
244246
{
245-
in >> ret;
247+
in >> memLimitStr;
246248
}
247249
catch (...)
248250
{
249251
RETURN_READ_ERROR(0);
250252
}
251253

252-
return ret;
254+
if (cGroupVersion_ == v2 && memLimitStr == "max")
255+
{
256+
return std::numeric_limits<uint64_t>::max();
257+
}
258+
259+
auto [ch, ec] = std::from_chars(memLimitStr.c_str(), memLimitStr.c_str() + memLimitStr.size(), memLimit);
260+
if (ec != std::errc())
261+
{
262+
return std::numeric_limits<uint64_t>::max();
263+
}
264+
265+
if (cGroupVersion_ == v1)
266+
{
267+
return std::min(getTotalMemoryFromProc(), memLimit);
268+
}
269+
return memLimit;
253270
}
254271

255272
uint64_t CGroupConfigurator::getFreeMemory()
256273
{
257274
uint64_t ret;
258-
259275
if (!cGroupDefined)
260276
ret = getFreeMemoryFromProc();
261277
else
262278
{
263279
uint64_t usage = getMemUsageFromCGroup();
280+
cout << "usage " << usage << endl;
264281

265282
if (usage == 0)
266283
ret = getFreeMemoryFromProc();
267284
else
268285
ret = getTotalMemory() - usage;
269286
}
270287

271-
// cout << "free memory = " << ret << endl;
288+
cout << "free memory = " << ret << endl;
272289
return ret;
273290
}
274291

275292
uint64_t CGroupConfigurator::getMemUsageFromCGroup()
276293
{
277-
uint64_t ret = 0;
278-
bool found = false;
279294
char oneline[80];
280-
281295
if (memUsageFilename.empty())
282296
{
283297
ostringstream filename;
284-
filename << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.stat";
298+
if (cGroupVersion_ == v1)
299+
{
300+
memStatePrefix = "rss ";
301+
filename << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.stat";
302+
}
303+
else
304+
{
305+
memStatePrefix = "anon ";
306+
filename << "/sys/fs/cgroup/" << cGroupName << "/memory.stat";
307+
}
285308
memUsageFilename = filename.str();
286309
}
287310

@@ -293,14 +316,13 @@ uint64_t CGroupConfigurator::getMemUsageFromCGroup()
293316

294317
try
295318
{
296-
while (in && !found)
319+
while (in)
297320
{
298321
in.getline(oneline, 80);
299322

300-
if (strncmp(oneline, "rss", 2) == 0)
323+
if (strncmp(oneline, memStatePrefix.c_str(), memStatePrefix.size() - 1) == 0)
301324
{
302-
ret = atoll(&oneline[3]);
303-
found = true;
325+
return atoll(&oneline[memStatePrefix.size()]);
304326
}
305327
}
306328
}
@@ -309,7 +331,7 @@ uint64_t CGroupConfigurator::getMemUsageFromCGroup()
309331
RETURN_READ_ERROR(0);
310332
}
311333

312-
return ret;
334+
return 0;
313335
}
314336

315337
uint64_t CGroupConfigurator::getFreeMemoryFromProc()
@@ -320,10 +342,6 @@ uint64_t CGroupConfigurator::getFreeMemoryFromProc()
320342
uint64_t memTotal = 0;
321343
uint64_t memAvailable = 0;
322344

323-
#if defined(__FreeBSD__)
324-
// FreeBSD is not supported, no optimization.
325-
memAvailable = 0;
326-
#else
327345
ifstream in("/proc/meminfo");
328346
string x;
329347

@@ -354,137 +372,9 @@ uint64_t CGroupConfigurator::getFreeMemoryFromProc()
354372
memAvailable = memFree + buffers + cached;
355373
}
356374

357-
#endif
358-
359375
// amount available for application
360376
memAvailable *= 1024;
361377
return memAvailable;
362378
}
363379

364-
uint64_t CGroupConfigurator::getTotalSwapSpace()
365-
{
366-
int64_t ret;
367-
368-
if (totalSwap != 0)
369-
return totalSwap;
370-
371-
if (!cGroupDefined)
372-
ret = getTotalSwapFromSysinfo();
373-
else
374-
{
375-
ret = getTotalMemAndSwapFromCGroup();
376-
377-
// if no limit is set in the cgroup, the file contains maxint64. Use sysinfo in that case.
378-
if (ret == -1 || ret == numeric_limits<int64_t>::max())
379-
ret = getTotalSwapFromSysinfo();
380-
else
381-
ret -= getTotalMemory();
382-
}
383-
384-
// cout << "total swap=" << ret << endl;
385-
totalSwap = ret;
386-
return ret;
387-
}
388-
389-
uint64_t CGroupConfigurator::getTotalSwapFromSysinfo()
390-
{
391-
struct sysinfo si;
392-
393-
sysinfo(&si);
394-
return si.totalswap;
395-
}
396-
397-
int64_t CGroupConfigurator::getTotalMemAndSwapFromCGroup()
398-
{
399-
int64_t ret;
400-
ifstream in;
401-
string filename;
402-
ostringstream os;
403-
404-
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.memsw.limit_in_bytes";
405-
filename = os.str();
406-
in.open(filename.c_str());
407-
408-
if (!in)
409-
RETURN_NO_GROUP(-1);
410-
411-
try
412-
{
413-
in >> ret;
414-
}
415-
catch (...)
416-
{
417-
RETURN_READ_ERROR(-1);
418-
}
419-
420-
return ret;
421-
}
422-
423-
uint64_t CGroupConfigurator::getSwapInUse()
424-
{
425-
int64_t ret;
426-
427-
if (!cGroupDefined)
428-
ret = getSwapInUseFromSysinfo();
429-
else
430-
{
431-
ret = getSwapInUseFromCGroup();
432-
433-
if (ret == -1)
434-
ret = getSwapInUseFromSysinfo();
435-
}
436-
437-
// cout << "current swap in use=" << ret << endl;
438-
return ret;
439-
}
440-
441-
int64_t CGroupConfigurator::getSwapInUseFromCGroup()
442-
{
443-
int64_t ret = -1;
444-
ifstream in;
445-
bool found = false;
446-
char oneline[80];
447-
448-
if (usedSwapFilename.empty())
449-
{
450-
ostringstream os;
451-
os << "/sys/fs/cgroup/memory/" << cGroupName << "/memory.stat";
452-
usedSwapFilename = os.str();
453-
}
454-
455-
string& filename = usedSwapFilename;
456-
in.open(filename.c_str());
457-
458-
if (!in)
459-
RETURN_NO_GROUP(-1);
460-
461-
try
462-
{
463-
while (in && !found)
464-
{
465-
in.getline(oneline, 80);
466-
467-
if (strncmp(oneline, "swap", 4) == 0)
468-
{
469-
ret = atoll(&oneline[5]);
470-
found = true;
471-
}
472-
}
473-
}
474-
catch (...)
475-
{
476-
RETURN_READ_ERROR(-1);
477-
}
478-
479-
return ret;
480-
}
481-
482-
uint64_t CGroupConfigurator::getSwapInUseFromSysinfo()
483-
{
484-
struct sysinfo si;
485-
486-
sysinfo(&si);
487-
return si.totalswap - si.freeswap;
488-
}
489-
490380
} // namespace utils

0 commit comments

Comments
 (0)