[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