[lxc-devel] [libresource/master] making memory related information cgroup aware.
rahuyada on Github
lxc-bot at linuxcontainers.org
Tue Apr 23 21:43:45 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 548 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190423/35cfe206/attachment-0001.bin>
-------------- next part --------------
From 0600cd30ccf1ccedf58ac9be62a9f2162780c8e6 Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Tue, 23 Apr 2019 12:18:46 -0700
Subject: [PATCH 1/2] Made code changes to make memory information cgroup
aware.
---
resmem.c | 444 ++++++++++++++++++++++++++++++++++++++++++++----
resmem.h | 2 +
resnet.c | 4 +-
resource.c | 4 +-
resource_impl.h | 86 +++++++++-
5 files changed, 495 insertions(+), 45 deletions(-)
diff --git a/resmem.c b/resmem.c
index d0820e0..97a0eb4 100644
--- a/resmem.c
+++ b/resmem.c
@@ -19,7 +19,6 @@
#ifndef _RESOURCE_H
#include "resource.h"
#endif
-#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -27,6 +26,9 @@
#include "resmem.h"
#include "resource_impl.h"
#include <errno.h>
+#include <libgen.h>
+
+#define startswith(str, buf) strncmp(str, buf, sizeof(str) - 1)
/* read a specific information from file on the basis of a string.
* String should tell what information is being read.
@@ -36,7 +38,7 @@ static inline int get_info_infile(char *fname, char *res, void *out)
const char *loc;
char buf[MEMBUF_2048];
- if (file_to_buf(fname, buf) == -1)
+ if (file_to_buf(fname, buf, MEMBUF_2048) == -1)
return -1;
loc = strstr(buf, res);
@@ -50,37 +52,295 @@ static inline int get_info_infile(char *fname, char *res, void *out)
return 0;
}
+/* read information from a cgroup file.
+ */
+static inline size_t cgmemread(char *cg, char *file)
+{
+ char buf[MEMBUF_128];
+ char fn[FNAMELEN];
+
+ snprintf(fn, FNAMELEN, "%s/%s%s/%s", DEFAULTCGFS,
+ MEMCGNAME, cg, file);
+
+ if (file_to_buf(fn, buf, MEMBUF_128) == -1)
+ return 0;
+
+ return (strtoul(buf, NULL, 10) / 1024);
+}
+
+/* read memory limit from cgorup file
+ */
+static size_t cgmemlimit(char *cg, char *f)
+{
+ char *copy;
+ char *dir;
+ size_t mem = 0, retmem = 0;
+
+ /* read memory limit for cgroup */
+ if ((retmem = cgmemread(cg, f)) == -1) {
+ return 0;
+ }
+
+ copy = strdup(cg);
+ dir = dirname(copy);
+
+ /*read memory limit for parant cg */
+ if (strcmp(dir, "/") != 0) {
+ if((mem = cgmemread(dir, f)) == 0) {
+ free(copy);
+ return 0;
+ }
+ if (mem < retmem) {
+ retmem = mem;
+ }
+ }
+
+ free(copy);
+ return retmem;
+}
+
+/* get memory stat from memory.stat file */
+static inline size_t cgmemstat(char *cg, char *stat)
+{
+ char fn[FNAMELEN];
+ size_t ret;
+
+ snprintf(fn, FNAMELEN, "%s/%s%s/%s", DEFAULTCGFS,
+ MEMCGNAME, cg, "memory.stat");
+
+ if (get_info_infile(fn, stat, &ret) == -1)
+ return 0;
+
+ return (ret / 1024);
+}
+
+/* Get all memory info for a cgroup */
+static int getmeminfoall(char *cg, void *out)
+{
+ size_t memtotal, mmusage, mmtot, cache, active_anon, inactive_anon,
+ active_file, inactive_file, swaptotal, swapfree, swusage,
+ swtot;
+ char fn[FNAMELEN];
+ FILE *fp;
+ int err;
+ char buf[MEMBUF_128];
+
+ snprintf(fn, FNAMELEN, "%s/%s%s/%s", DEFAULTCGFS,
+ MEMCGNAME, cg, "memory.stat");
+
+ fp = fopen(fn, "r");
+
+ if (fp == NULL) {
+ err = errno;
+ eprintf("while opening File %s with errno: %d", fn, errno);
+ errno = err;
+ return -1;
+ }
+
+ while(fgets(buf, sizeof(buf), fp) != NULL) {
+ if (startswith("cache", buf) == 0) {
+ sscanf(buf, "%*s%zu", &cache);
+ cache /= 1024;
+ } else if (startswith("active_anon", buf) == 0) {
+ sscanf(buf, "%*s%zu", &active_anon);
+ active_anon /= 1024;
+ } else if (startswith("inactive_anon", buf) == 0) {
+ sscanf(buf, "%*s%zu", &inactive_anon);
+ inactive_anon /= 1024;
+ } else if (startswith("active_file", buf) == 0) {
+ sscanf(buf, "%*s%zu", &active_file);
+ active_file /= 1024;
+ } else if (startswith("inactive_file", buf) == 0) {
+ sscanf(buf, "%*s%zu", &inactive_file);
+ inactive_file /= 1024;
+ }
+ }
+ fclose(fp);
+
+ fp = fopen(MEMINFO_FILE, "r");
+ if (fp == NULL) {
+ err = errno;
+ eprintf("while opening File %s with errno: %d",
+ MEMINFO_FILE, errno);
+ errno = err;
+ return -1;
+ }
+
+ while(fgets(buf, sizeof(buf), fp) != NULL) {
+ if (startswith("MemTotal", buf) == 0) {
+ sscanf(buf, "%*s%zu", &memtotal);
+ } else if (startswith("SwapTotal", buf) == 0) {
+ sscanf(buf, "%*s%zu", &swaptotal);
+ } else if (startswith("SwapFree", buf) == 0) {
+ sscanf(buf, "%*s%zu", &swapfree);
+ }
+ }
+ fclose(fp);
+
+ mmusage = cgmemread(cg, "memory.usage_in_bytes");
+ mmtot = cgmemlimit(cg, "memory.limit_in_bytes");
+ if (memtotal < mmtot) {
+ mmtot = memtotal;
+ }
+
+ ((res_mem_infoall_t *)out)->memfree = mmtot - mmusage;
+ ((res_mem_infoall_t *)out)->memavailable = mmtot - mmusage + cache;
+ ((res_mem_infoall_t *)out)->memtotal = mmtot;
+ ((res_mem_infoall_t *)out)->active = active_anon + active_file;
+ ((res_mem_infoall_t *)out)->inactive = inactive_anon + inactive_file;
+
+ swusage = cgmemread(cg, "memory.memsw.usage_in_bytes");
+ swtot = cgmemlimit(cg, "memory.memsw.limit_in_bytes");
+
+ if (swtot > 0 && swtot < swaptotal)
+ swaptotal = swtot;
+
+ if (swtot > 0 && swusage > 0) {
+ swusage = swusage - mmusage;
+ swapfree = (swusage < swaptotal) ? swaptotal - swusage : 0;
+ }
+
+ ((res_mem_infoall_t *)out)->swaptotal = swaptotal;
+ ((res_mem_infoall_t *)out)->swapfree = swapfree;
+
+ return 0;
+}
+
/* Read resource information corresponding to res_id */
int getmeminfo(int res_id, void *out, void *hint, int pid, int flags)
{
char buf[MEMBUF_128];
FILE *fp;
int err = 0;
+ size_t active_anon, active_file, inactive_anon, inactive_file, cache,
+ swaptotal, swapfree, swtot, swusage, mmusage, mmtot, memtotal;
+ int ret = 0;
- switch (res_id) {
+ char *cg = get_cgroup(pid, MEMCGNAME);
+
+ if (cg) {
+ clean_init(cg);
+ }
+ switch (res_id) {
+ /* if process is part of a cgroup then return memory info
+ *for that cgroup only.
+ */
case RES_MEM_FREE:
- return get_info_infile(MEMINFO_FILE, "MemFree:", out);
+ if (cg) {
+ mmusage = cgmemread(cg, "memory.usage_in_bytes");
+ if (get_info_infile(MEMINFO_FILE, "MemTotal:",
+ &memtotal) == -1)
+ return -1;
+ mmtot = cgmemlimit(cg, "memory.limit_in_bytes");
+ if (memtotal < mmtot) {
+ mmtot = memtotal;
+ }
+
+ *(size_t *)out = mmtot - mmusage;
+ return 0;
+ } else {
+ return get_info_infile(MEMINFO_FILE, "MemFree:", out);
+ }
case RES_MEM_AVAILABLE:
- return get_info_infile(MEMINFO_FILE, "MemAvailable:", out);
+ if (cg) {
+ mmusage = cgmemread(cg, "memory.usage_in_bytes");
+ if (get_info_infile(MEMINFO_FILE, "MemTotal:",
+ &memtotal) == -1)
+ return -1;
+
+ mmtot = cgmemlimit(cg, "memory.limit_in_bytes");
+
+ if (memtotal < mmtot) {
+ mmtot = memtotal;
+ }
+ cache = cgmemstat(cg, "cache");
+
+ *(size_t *)out = mmtot - mmusage + cache;
+ return 0;
+ } else {
+ return get_info_infile(MEMINFO_FILE, "MemAvailable:",
+ out);
+ }
case RES_MEM_TOTAL:
- return get_info_infile(MEMINFO_FILE, "MemTotal:", out);
+ ret = get_info_infile(MEMINFO_FILE, "MemTotal:", out);
+ if (cg) {
+ mmtot = cgmemlimit(cg, "memory.limit_in_bytes");
+ if (ret != -1 && *(size_t *)out > mmtot) {
+ *(size_t *)out = mmtot;
+ }
+ }
+ return ret;
case RES_MEM_ACTIVE:
- return get_info_infile(MEMINFO_FILE, "Active:", out);
+ if (cg) {
+ active_anon = cgmemstat(cg, "\nactive_anon");
+ active_file = cgmemstat(cg, "\nactive_file");
+ *(size_t *)out = active_anon + active_file;
+ return 0;
+ } else {
+ return get_info_infile(MEMINFO_FILE, "Active:", out);
+ }
case RES_MEM_INACTIVE:
- return get_info_infile(MEMINFO_FILE, "Inactive:", out);
+ if (cg) {
+ inactive_anon = cgmemstat(cg, "\ninactive_anon");
+ inactive_file = cgmemstat(cg, "\ninactive_file");
+ *(size_t *)out = inactive_anon + inactive_file;
+ return 0;
+ } else {
+ return get_info_infile(MEMINFO_FILE, "Inactive:", out);
+ }
case RES_MEM_SWAPTOTAL:
- return get_info_infile(MEMINFO_FILE, "SwapTotal:", out);
+ ret = get_info_infile(MEMINFO_FILE, "SwapTotal:", out);
+ if (cg) {
+ swtot = cgmemlimit(cg,
+ "memory.memsw.limit_in_bytes");
+ if (ret != -1 && swtot > 0 && *(size_t *)out > swtot) {
+ *(size_t *)out = swtot;
+ }
+ }
+ return ret;
case RES_MEM_SWAPFREE:
+ if (cg) {
+ swusage = cgmemread(cg, "memory.memsw.usage_in_bytes");
+ swtot = cgmemlimit(cg,
+ "memory.memsw.limit_in_bytes");
+
+ if (swusage > 0 && swtot > 0) {
+ mmusage = cgmemread(cg,
+ "memory.usage_in_bytes");
+ if (get_info_infile(MEMINFO_FILE,
+ "SwapTotal:", &swaptotal) == -1)
+ return -1;
+
+ if (swtot > swaptotal) {
+ swtot = swaptotal;
+ }
+
+ swusage = swusage - mmusage;
+ if (swusage < swtot)
+ swapfree = swtot - swusage;
+ else
+ swapfree = 0;
+ *(size_t *)out = swapfree;
+ return 0;
+ }
+ }
return get_info_infile(MEMINFO_FILE, "SwapFree:", out);
case RES_MEM_INFOALL:
+ if (cg) {
+ if (getmeminfoall(cg, out) == -1) {
+ return -1;
+ }
+ break;
+ }
+
fp = fopen(MEMINFO_FILE, "r");
if (fp == NULL) {
err = errno;
@@ -93,33 +353,28 @@ int getmeminfo(int res_id, void *out, void *hint, int pid, int flags)
* is required.
*/
while (fgets(buf, sizeof(buf), fp) != NULL) {
- if (strncmp("MemTotal:", buf, MEMBUF_8) == 0)
+ if (startswith("MemTotal:", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->memtotal);
-
- else if (strncmp("MemFree:", buf, MEMBUF_8) == 0)
+ } else if (startswith("MemFree:", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->memfree);
-
- else if (strncmp("MemAvailable:", buf, MEMBUF_8) == 0)
+ } else if (startswith("MemAvailable:", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->memavailable);
-
- else if (strncmp("Active:", buf, MEMBUF_8) == 0)
+ } else if (startswith("Active", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->active);
-
- else if (strncmp("Inactive:", buf, MEMBUF_8) == 0)
+ } else if (startswith("Inactive", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->inactive);
-
- else if (strncmp("SwapTotal:", buf, MEMBUF_8) == 0)
+ } else if (startswith("SwapTotal", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->swaptotal);
-
- else if (strncmp("SwapFree:", buf, MEMBUF_8) == 0)
+ } else if (startswith("SwapFree", buf) == 0) {
sscanf(buf, "%*s%zu",
&((res_mem_infoall_t *)out)->swapfree);
+ }
}
fclose(fp);
break;
@@ -139,11 +394,20 @@ int getmeminfo(int res_id, void *out, void *hint, int pid, int flags)
int populate_meminfo(res_blk_t *res, int pid, int flags)
{
- size_t temp;
const char *loc;
char buf[MEMBUF_2048];
+ size_t active_anon = 0, active_file = 0, inactive_anon = 0,
+ inactive_file = 0, cache = 0, swaptotal = 0, swapfree = 0,
+ swtot = 0, swusage = 0, mmusage = 0, mmtot = 0, memtotal = 0,
+ memavailable = 0, memfree = 0, memactive = 0, meminactive = 0;
+
+ char *cg = get_cgroup(pid, MEMCGNAME);
+
+ if (cg) {
+ clean_init(cg);
+ }
- if (file_to_buf(MEMINFO_FILE, buf) == -1) {
+ if (file_to_buf(MEMINFO_FILE, buf, MEMBUF_2048) == -1) {
for (int i = 0 ; i < res->res_count; i++)
res->res_unit[i]->status = errno;
return -1;
@@ -152,14 +416,14 @@ int populate_meminfo(res_blk_t *res, int pid, int flags)
/* Macro to read memory related information corresponding to a string
* from buffer.
*/
-#define SCANMEMSTR(str) do {\
+#define SCANMEMSTR(str, info) do {\
loc = strstr(buf, str);\
if (loc == NULL) {\
eprintf("%s is not found in file %s", str, MEMINFO_FILE);\
res->res_unit[i]->status = ENODATA;\
} else {\
- sscanf(loc, "%*s%zu", &temp);\
- (res->res_unit[i]->data).sz = temp;\
+ sscanf(loc, "%*s%zu", &info);\
+ (res->res_unit[i]->data).sz = info;\
res->res_unit[i]->status = RES_STATUS_FILLED;\
} \
} while (0)\
@@ -169,31 +433,132 @@ int populate_meminfo(res_blk_t *res, int pid, int flags)
loc = NULL;
switch (res->res_unit[i]->res_id) {
case RES_MEM_FREE:
- SCANMEMSTR("MemFree:");
+ if (cg) {
+ if (!mmusage)
+ mmusage = cgmemread(cg,
+ "memory.usage_in_bytes");
+ if (!memtotal)
+ SCANMEMSTR("MemTotal:", memtotal);
+ if (!mmtot)
+ mmtot = cgmemlimit(cg,
+ "memory.limit_in_bytes");
+
+ if (memtotal < mmtot) {
+ mmtot = memtotal;
+ }
+
+ (res->res_unit[i]->data).sz = mmtot - mmusage;
+ res->res_unit[i]->status = RES_STATUS_FILLED;
+ } else {
+ SCANMEMSTR("MemFree:", memfree);
+ }
break;
case RES_MEM_AVAILABLE:
- SCANMEMSTR("MemAvailable:");
+ if (cg) {
+ if (!mmusage)
+ mmusage = cgmemread(cg,
+ "memory.usage_in_bytes");
+ if (!memtotal)
+ SCANMEMSTR("MemTotal:", memtotal);
+ if (!mmtot)
+ mmtot = cgmemlimit(cg,
+ "memory.limit_in_bytes");
+
+ if (memtotal < mmtot) {
+ mmtot = memtotal;
+ }
+
+ cache = cgmemstat(cg, "cache");
+ (res->res_unit[i]->data).sz =
+ mmtot - mmusage + cache;
+ res->res_unit[i]->status = RES_STATUS_FILLED;
+ } else {
+ SCANMEMSTR("MemAvailable:", memavailable);
+ }
break;
case RES_MEM_TOTAL:
- SCANMEMSTR("MemTotal:");
+ if (!memtotal)
+ SCANMEMSTR("MemTotal:", memtotal);
+ if (cg) {
+ if (!mmtot)
+ mmtot = cgmemlimit(cg,
+ "memory.limit_in_bytes");
+ if (memtotal > mmtot)
+ (res->res_unit[i]->data).sz = mmtot;
+ }
+ res->res_unit[i]->status = RES_STATUS_FILLED;
break;
case RES_MEM_ACTIVE:
- SCANMEMSTR("Active:");
+ if (cg) {
+ active_anon = cgmemstat(cg, "active_anon");
+ active_file = cgmemstat(cg, "active_file");
+ (res->res_unit[i]->data).sz =
+ active_anon + active_file;
+ res->res_unit[i]->status = RES_STATUS_FILLED;
+ } else {
+ SCANMEMSTR("Active:", memactive);
+ }
break;
case RES_MEM_INACTIVE:
- SCANMEMSTR("Inactive:");
+ if (cg) {
+ inactive_anon = cgmemstat(cg, "inactive_anon");
+ inactive_file = cgmemstat(cg, "inactive_file");
+ (res->res_unit[i]->data).sz =
+ inactive_anon + inactive_file;
+ res->res_unit[i]->status = RES_STATUS_FILLED;
+ } else {
+ SCANMEMSTR("Inactive:", meminactive);
+ }
break;
case RES_MEM_SWAPTOTAL:
- SCANMEMSTR("SwapTotal:");
+ if (!swaptotal)
+ SCANMEMSTR("SwapTotal:", swaptotal);
+ if (cg) {
+ swtot = cgmemlimit(cg,
+ "memory.memsw.limit_in_bytes");
+ if (swtot > 0 && swaptotal > swtot) {
+ (res->res_unit[i]->data).sz = swtot;
+ }
+ }
+ res->res_unit[i]->status = RES_STATUS_FILLED;
break;
case RES_MEM_SWAPFREE:
- SCANMEMSTR("SwapFree:");
+ SCANMEMSTR("SwapFree:", swapfree);
+
+ if (cg) {
+ swusage = cgmemread(cg,
+ "memory.memsw.usage_in_bytes");
+ swtot = cgmemlimit(cg,
+ "memory.memsw.limit_in_bytes");
+
+ if (!swusage || !swtot) {
+ break;
+ }
+
+ if (!mmusage)
+ mmusage = cgmemread(cg,
+ "memory.usage_in_bytes");
+ if (!swaptotal)
+ SCANMEMSTR("SwapTotal:", swaptotal);
+
+ if (swtot > swaptotal) {
+ swtot = swaptotal;
+ }
+
+ swusage = swusage - mmusage;
+ if (swusage < swtot)
+ swapfree = swtot - swusage;
+ else
+ swapfree = 0;
+ (res->res_unit[i]->data).sz = swapfree;
+ res->res_unit[i]->status = RES_STATUS_FILLED;
+ }
break;
case RES_MEM_PAGESIZE:
@@ -201,6 +566,16 @@ int populate_meminfo(res_blk_t *res, int pid, int flags)
break;
case RES_MEM_INFOALL:
+ if (cg) {
+ if (getmeminfoall(cg,
+ (res->res_unit[i]->data).ptr) == -1) {
+ res->res_unit[i]->status = ENODATA;
+ return -1;
+ }
+ res->res_unit[i]->status = RES_STATUS_FILLED;
+ break;
+ }
+
loc = strstr(buf, "MemTotal:");
sscanf(loc, "%*s%zu", &((res_mem_infoall_t *)
(res->res_unit[i]->data).ptr)->memtotal);
@@ -231,4 +606,3 @@ int populate_meminfo(res_blk_t *res, int pid, int flags)
}
return 0;
}
-
diff --git a/resmem.h b/resmem.h
index 7180ea9..96f5a93 100644
--- a/resmem.h
+++ b/resmem.h
@@ -26,6 +26,8 @@
#define MEMBUF_128 128
#define MEMBUF_2048 2048
+#define MEMCGNAME "memory"
+
extern int populate_meminfo(struct res_blk *res, int pid, int flags);
extern int getmeminfo(int res_id, void *out, void *hint, int pid, int flags);
diff --git a/resnet.c b/resnet.c
index 2b8cc81..4f8c44a 100644
--- a/resnet.c
+++ b/resnet.c
@@ -198,8 +198,8 @@ static inline int getallnetinfo(void *out, void *hint)
while (fgets(buf, sizeof(buf), fp) != NULL) {
if (i == NET_ALLIFSTAT_SZ) {
- msz = (sizeof(res_net_ifstat_t) * inum) +
- NET_ALLIFSTAT_SZ;
+ msz = sizeof(res_net_ifstat_t) * (inum +
+ NET_ALLIFSTAT_SZ);
rlst = (res_net_ifstat_t *)realloc(lst, msz);
if(rlst == NULL) {
fclose(fp);
diff --git a/resource.c b/resource.c
index 030157b..20471d7 100644
--- a/resource.c
+++ b/resource.c
@@ -150,6 +150,7 @@ int res_read(int res_id, void *out, void *hint, int pid, int flags)
int ret;
int err;
+
if (out == NULL) {
switch (res_id) {
/* In case of RES_NET_ALLIFSTAT memory is allocated on the
@@ -171,8 +172,9 @@ int res_read(int res_id, void *out, void *hint, int pid, int flags)
return getmeminfo(res_id, out, hint, pid, flags);
/* Check if net proc file is needed to open */
- if (res_id >= NET_MIN && res_id < NET_MAX)
+ if (res_id >= NET_MIN && res_id < NET_MAX) {
return getnetinfo(res_id, out, hint, pid, flags);
+ }
switch (res_id) {
case RES_KERN_RELEASE:
diff --git a/resource_impl.h b/resource_impl.h
index 35863b9..65ab9e9 100644
--- a/resource_impl.h
+++ b/resource_impl.h
@@ -23,26 +23,97 @@
#include <errno.h>
#define RESOURCE_64 64
+#define RESOURCE_256 256
#define RESOURCE_2048 2048
+#define FNAMELEN RESOURCE_256
+
+#define INITSCOPE "/init.scope"
+#define DEFAULTCGFS "/sys/fs/cgroup"
+
#define eprintf(msg, ...) fprintf(stderr,\
"Err at line %d in file %s: "msg"\n",\
__LINE__, __FILE__, ##__VA_ARGS__)\
+static inline void clean_init(char *cg)
+{
+ char *p;
+ size_t cg_len = strlen(cg), init_len = strlen(INITSCOPE);
+
+ if (cg_len < init_len)
+ return;
+
+ p = cg + cg_len - init_len;
+ if (strcmp(p, INITSCOPE) == 0) {
+ if (p == cg)
+ *(p+1) = '\0';
+ else
+ *p = '\0';
+ }
+}
+
+static inline char *get_cgroup(pid_t pid, const char *contrl)
+{
+ char fn[FNAMELEN];
+ FILE *f;
+ char *line = NULL;
+ size_t len = 0;
+ size_t l = 0;
+ int ret;
+ char *cgrp = NULL;
+ char *c1, *c2;
+
+ if (pid) {
+ ret = snprintf(fn, FNAMELEN, "/proc/%d/cgroup", pid);
+ } else {
+ ret = snprintf(fn, FNAMELEN, "/proc/self/cgroup");
+ }
+ if (ret < 0 || ret >= FNAMELEN)
+ return NULL;
+
+ if (!(f = fopen(fn, "r")))
+ return NULL;
+
+ while (getline(&line, &len, f) != -1) {
+ if (!line[0])
+ continue;
+ c1 = strchr(line, ':');
+ if (!c1)
+ goto out;
+ c1++;
+ c2 = strchr(c1, ':');
+ if (!c2)
+ goto out;
+ *c2 = '\0';
+ if (strcmp(c1, contrl) != 0)
+ continue;
+ c2++;
+ l = strlen(c2);
+ if (l && c2[l-1] == '\n')
+ c2[l-1] = '\0';
+ if(strcmp(c2, "/") == 0)
+ goto out;
+ do {
+ cgrp = strdup(c2);
+ } while (!cgrp);
+ break;
+ }
+
+out:
+ fclose(f);
+ free(line);
+ return cgrp;
+}
-static inline int file_to_buf(char *fname, char *buf)
+static inline int file_to_buf(char *fname, char *buf, unsigned int bufsz)
{
int fd = 0;
size_t rdsz = 0;
int err = 0;
fd = open(fname, O_RDONLY);
- if (fd == -1) {
- err = errno;
- eprintf("in opening File %s with errno: %d", fname, errno);
- errno = err;
+ if (fd == -1)
return -1;
- }
if (lseek(fd, 0L, SEEK_SET) == -1) {
err = errno;
@@ -52,7 +123,7 @@ static inline int file_to_buf(char *fname, char *buf)
return -1;
}
- rdsz = read(fd, buf, RESOURCE_2048 - 1);
+ rdsz = read(fd, buf, bufsz - 1);
if (rdsz < 0) {
err = errno;
eprintf("in read from File %s with errno: %d", fname, errno);
@@ -65,4 +136,5 @@ static inline int file_to_buf(char *fname, char *buf)
return rdsz;
}
+
#endif /* _RESOURCE_IMPL_H */
From 56f427a7306956c759ed43600fde8fd4a342825f Mon Sep 17 00:00:00 2001
From: Rahul Yadav <rahul.x.yadav at oracle.com>
Date: Tue, 23 Apr 2019 14:37:40 -0700
Subject: [PATCH 2/2] extra space removal and comments
---
resource.c | 4 +---
resource_impl.h | 10 +++++++++-
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/resource.c b/resource.c
index 20471d7..030157b 100644
--- a/resource.c
+++ b/resource.c
@@ -150,7 +150,6 @@ int res_read(int res_id, void *out, void *hint, int pid, int flags)
int ret;
int err;
-
if (out == NULL) {
switch (res_id) {
/* In case of RES_NET_ALLIFSTAT memory is allocated on the
@@ -172,9 +171,8 @@ int res_read(int res_id, void *out, void *hint, int pid, int flags)
return getmeminfo(res_id, out, hint, pid, flags);
/* Check if net proc file is needed to open */
- if (res_id >= NET_MIN && res_id < NET_MAX) {
+ if (res_id >= NET_MIN && res_id < NET_MAX)
return getnetinfo(res_id, out, hint, pid, flags);
- }
switch (res_id) {
case RES_KERN_RELEASE:
diff --git a/resource_impl.h b/resource_impl.h
index 65ab9e9..428dd77 100644
--- a/resource_impl.h
+++ b/resource_impl.h
@@ -29,6 +29,11 @@
#define FNAMELEN RESOURCE_256
#define INITSCOPE "/init.scope"
+
+/* We are assuming that cgroup is mounted at its usual location,
+ * If we have reeust from applications who do not mount cgroup at
+ * usual location, then we need to change this.
+ */
#define DEFAULTCGFS "/sys/fs/cgroup"
#define eprintf(msg, ...) fprintf(stderr,\
@@ -52,6 +57,7 @@ static inline void clean_init(char *cg)
}
}
+/* Get cgroup path for a particular controller */
static inline char *get_cgroup(pid_t pid, const char *contrl)
{
char fn[FNAMELEN];
@@ -63,11 +69,14 @@ static inline char *get_cgroup(pid_t pid, const char *contrl)
char *cgrp = NULL;
char *c1, *c2;
+ /* If no pid is provided then return cgroup info for current process.
+ */
if (pid) {
ret = snprintf(fn, FNAMELEN, "/proc/%d/cgroup", pid);
} else {
ret = snprintf(fn, FNAMELEN, "/proc/self/cgroup");
}
+
if (ret < 0 || ret >= FNAMELEN)
return NULL;
@@ -136,5 +145,4 @@ static inline int file_to_buf(char *fname, char *buf, unsigned int bufsz)
return rdsz;
}
-
#endif /* _RESOURCE_IMPL_H */
More information about the lxc-devel
mailing list