diff --git a/Makefile b/Makefile index 1d5278b..846c496 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -g -Wall -Werror -fPIC -std=gnu99 DEPS = resource.h resource_impl.h resmem.h resnet.h resproc.h resvm.h rescpu.h resfs.h stat.h -OBJ = resource.o resmem.o resnet.o resproc.o reskern.o resvm.o rescpu.o resfs.o net_if.o net_route.o net_arp.o stat.o +OBJ = resource.o resmem.o resnet.o resproc.o reskern.o resvm.o rescpu.o resfs.o net_if.o net_route.o net_arp.o stat.o resmem_cg.o TEST = test RM = rm -rf CP = cp diff --git a/net_route.c b/net_route.c index 136f7b3..87e5835 100644 --- a/net_route.c +++ b/net_route.c @@ -348,6 +348,10 @@ static int handle_route_resp(int net_sock, void **out) #endif parse_attr(at, RTM_RTA(rt), len); if (rt->rtm_family == AF_INET || rt->rtm_family == AF_INET6) { + if ((rt->rtm_type == RTN_BROADCAST) || + (rt->rtm_type == RTN_MULTICAST)) + continue; + get_attr(at, iroutes, rt); #ifdef TESTING fp = fopen ("./route_info.txt", "w"); diff --git a/resmem.c b/resmem.c index cdb1b15..5a0a221 100644 --- a/resmem.c +++ b/resmem.c @@ -28,193 +28,6 @@ #include #include -#define startswith(str, buf) (strncmp(str, buf, sizeof(str) - 1) == 0) - -/* read a specific information from file on the basis of a string. - * String should tell what information is being read. - */ -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, MEMBUF_2048) == -1) - return -1; - - loc = strstr(buf, res); - if (loc == NULL) { - eprintf("%s is not found in buffer of file %s", res, fname); - errno = ENODATA; - return -1; - } - - sscanf(loc, "%*s%zu", (size_t *)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]; - unsigned long ret; - - snprintf(fn, FNAMELEN, "%s/%s%s/%s", DEFAULTCGFS, - MEMCGNAME, cg, file); - - if (file_to_buf(fn, buf, MEMBUF_128) == -1) - return 0; - - if (libres_ulong(buf, &ret) != 0) { - return 0; - } else { - return ret / 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; - } - - if ((copy = strdup(cg)) == NULL) { - return 0; - } - - dir = dirname(copy); - - /*read memory limit for parent 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]; - res_mem_infoall_t *memall = out; - - 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)) { - sscanf(buf, "%*s%zu", &cache); - cache /= 1024; - } else if (startswith("active_anon", buf)) { - sscanf(buf, "%*s%zu", &active_anon); - active_anon /= 1024; - } else if (startswith("inactive_anon", buf)) { - sscanf(buf, "%*s%zu", &inactive_anon); - inactive_anon /= 1024; - } else if (startswith("active_file", buf)) { - sscanf(buf, "%*s%zu", &active_file); - active_file /= 1024; - } else if (startswith("inactive_file", buf)) { - 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)) { - sscanf(buf, "%*s%zu", &memtotal); - } else if (startswith("SwapTotal", buf)) { - sscanf(buf, "%*s%zu", &swaptotal); - } else if (startswith("SwapFree", buf)) { - 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; - } - - memall->memfree = mmtot - mmusage; - memall->memavailable = mmtot - mmusage + cache; - memall->memtotal = mmtot; - memall->active = active_anon + active_file; - memall->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; - } - - memall->swaptotal = swaptotal; - memall->swapfree = swapfree; - - return 0; -} - struct mem_table { char *mem_name; unsigned long *mem_value; @@ -353,432 +166,89 @@ int getmemexist(int res_id, void *exist, size_t sz, void *hint, int flags) int getmeminfo(int res_id, void *out, size_t sz, void **hint, int pid, int flags) { char buf[4096]; - //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; - //res_mem_infoall_t *mminfo; - - char *cg = get_cgroup(pid, MEMCGNAME); - - if (cg) { - clean_init(cg); - } + int ret; switch (res_id) { /* if process is part of a cgroup then return memory info * for that cgroup only. */ case RES_MEM_FREE: - CHECK_SIZE(sz, sizeof(size_t)); - - 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); - } + return get_info_infile(MEMINFO_FILE, "MemFree:", out); case RES_MEM_AVAILABLE: - CHECK_SIZE(sz, sizeof(size_t)); - - 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); - } + return get_info_infile(MEMINFO_FILE, "MemAvailable:", out); case RES_MEM_TOTAL: - CHECK_SIZE(sz, sizeof(size_t)); - - 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; + return get_info_infile(MEMINFO_FILE, "MemTotal:", out); case RES_MEM_ACTIVE: - CHECK_SIZE(sz, sizeof(size_t)); - - 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); - } + return get_info_infile(MEMINFO_FILE, "Active:", out); case RES_MEM_INACTIVE: - CHECK_SIZE(sz, sizeof(size_t)); - - 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); - } + return get_info_infile(MEMINFO_FILE, "Inactive:", out); case RES_MEM_SWAPTOTAL: - CHECK_SIZE(sz, sizeof(size_t)); - - 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; + return get_info_infile(MEMINFO_FILE, "SwapTotal:", out); case RES_MEM_SWAPFREE: - CHECK_SIZE(sz, sizeof(size_t)); - - 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: - CHECK_SIZE(sz, sizeof(res_mem_infoall_t)); - - if (cg) { - if (getmeminfoall(cg, out) == -1) { - return -1; - } - break; - } #ifdef TESTING ret = file_to_buf("./mem_info.orig", buf, sizeof(buf)); #else ret = file_to_buf(MEMINFO_FILE, buf, sizeof(buf)); #endif - if (ret == -1) - return -1; + if (ret < 0) + return ret; ret = populate_minfo(buf, out, 0); - break; + return ret; case RES_MEM_PAGESIZE: - CHECK_SIZE(sz, sizeof(long)); - *(size_t *)out = sysconf(_SC_PAGESIZE); - break; + return 0; default: eprintf("Resource Id is invalid"); - errno = EINVAL; - return -1; + return -EINVAL; } - -#undef CHECK_SIZE - - return ret; + return 0; } int populate_meminfo(res_blk_t *res, int pid, int flags) { - 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); - res_mem_infoall_t *mminfo; - - if (cg) { - clean_init(cg); - } - - if (file_to_buf(MEMINFO_FILE, buf, MEMBUF_2048) == -1) { - for (int i = 0 ; i < res->res_count; i++) { - switch (res->res_unit[i]->res_id) { - case RES_MEM_FREE: - case RES_MEM_AVAILABLE: - case RES_MEM_TOTAL: - case RES_MEM_ACTIVE: - case RES_MEM_INACTIVE: - case RES_MEM_SWAPTOTAL: - case RES_MEM_SWAPFREE: - case RES_MEM_INFOALL: - res->res_unit[i]->status = errno; - } - } - return -1; - } - -/* Macro to read memory related information corresponding to a string - * from buffer. - */ -#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", &info);\ - (res->res_unit[i]->data).sz = info;\ - res->res_unit[i]->status = RES_STATUS_FILLED;\ - } \ -} while (0)\ - -/* Macro to check if enough memory is allocated to hold the data. - */ -#define CHECK_SIZE(sz, data_sz) \ - if (sz < data_sz) { \ - eprintf("memory (%ld) is not enough to hold data (%ld)",\ - sz, data_sz); \ - res->res_unit[i]->status = ENOMEM; \ - break; \ - } - for (int i = 0; i < res->res_count; i++) { - loc = NULL; switch (res->res_unit[i]->res_id) { case RES_MEM_FREE: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - 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; + return get_info_infile(MEMINFO_FILE, "MemFree:", + &((res->res_unit[i]->data).sz)); case RES_MEM_AVAILABLE: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - 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; + return get_info_infile(MEMINFO_FILE, "MemAvailable:", + &((res->res_unit[i]->data).sz)); case RES_MEM_TOTAL: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - if (!memtotal) - SCANMEMSTR("MemTotal:", memtotal); - else - (res->res_unit[i]->data).sz = 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; + return get_info_infile(MEMINFO_FILE, "MemTotal:", + &((res->res_unit[i]->data).sz)); case RES_MEM_ACTIVE: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - if (cg) { - active_anon = cgmemstat(cg, "\nactive_anon"); - active_file = cgmemstat(cg, "\nactive_file"); - (res->res_unit[i]->data).sz = - active_anon + active_file; - res->res_unit[i]->status = RES_STATUS_FILLED; - } else { - SCANMEMSTR("Active:", memactive); - } - break; + return get_info_infile(MEMINFO_FILE, "Active:", + &((res->res_unit[i]->data).sz)); case RES_MEM_INACTIVE: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - if (cg) { - inactive_anon = cgmemstat(cg, - "\ninactive_anon"); - inactive_file = cgmemstat(cg, - "\ninactive_file"); - (res->res_unit[i]->data).sz = - inactive_anon + inactive_file; - res->res_unit[i]->status = RES_STATUS_FILLED; - } else { - SCANMEMSTR("Inactive:", meminactive); - } - break; + return get_info_infile(MEMINFO_FILE, "Inactive:", + &((res->res_unit[i]->data).sz)); case RES_MEM_SWAPTOTAL: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - if (!swaptotal) - SCANMEMSTR("SwapTotal:", swaptotal); - else - (res->res_unit[i]->data).sz = 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; + return get_info_infile(MEMINFO_FILE, "SwapTotal:", + &((res->res_unit[i]->data).sz)); case RES_MEM_SWAPFREE: - CHECK_SIZE(res->res_unit[i]->data_sz, sizeof(size_t)); - - 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); + return get_info_infile(MEMINFO_FILE, "SwapFree:", + &((res->res_unit[i]->data).sz)); - 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_INFOALL: - CHECK_SIZE(res->res_unit[i]->data_sz, - sizeof(res_mem_infoall_t)); - - 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; - } - mminfo = (res_mem_infoall_t *) - (res->res_unit[i]->data).ptr; - - loc = strstr(buf, "MemTotal:"); - sscanf(loc, "%*s%zu", &mminfo->memtotal); - loc = strstr(buf, "MemFree:"); - sscanf(loc, "%*s%zu", &mminfo->memfree); - loc = strstr(buf, "MemAvailable:"); - sscanf(loc, "%*s%zu", &mminfo->memavailable); - loc = strstr(buf, "Active:"); - sscanf(loc, "%*s%zu", &mminfo->active); - loc = strstr(buf, "Inactive:"); - sscanf(loc, "%*s%zu", &mminfo->inactive); - loc = strstr(buf, "SwapTotal:"); - sscanf(loc, "%*s%zu", &mminfo->swaptotal); - loc = strstr(buf, "SwapFree:"); - sscanf(loc, "%*s%zu", &mminfo->swapfree); - - res->res_unit[i]->status = RES_STATUS_FILLED; - break; } } - -#undef CHECK_SIZE - return 0; } diff --git a/resmem.h b/resmem.h index 6d7acb1..8d3d767 100644 --- a/resmem.h +++ b/resmem.h @@ -30,7 +30,10 @@ extern int populate_meminfo(struct res_blk *res, int pid, int flags); extern int getmeminfo(int res_id, void *out, size_t sz, void **hint, int pid, int flags); +extern int getmeminfo_cg(int res_id, void *out, size_t sz, + void **hint, int pid, int flags); extern int getmemexist(int res_id, void *exist, size_t sz, void *hint, int flags); +extern int get_info_infile(char *fname, char *res, void *out); #endif /* _RESMEM_H */ diff --git a/resmem_cg.c b/resmem_cg.c new file mode 100644 index 0000000..da7f37b --- /dev/null +++ b/resmem_cg.c @@ -0,0 +1,251 @@ +/* Copyright (C) 2024, Oracle and/or its affiliates. All rights reserved + * + * This file is part of libresource. + * + * libresource is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libresource is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libresource. If not, see . + */ +#ifndef _RESOURCE_H +#include "resource.h" +#endif +#include +#include +#include +#include +#include "resmem.h" +#include "resource_impl.h" +#include +#include + +static int cg_error; + +/* read a specific information from file on the basis of a string. + * String should tell what information is being read. + */ +int get_info_infile(char *fname, char *res, void *out) +{ + const char *loc; + char buf[MEMBUF_2048]; + int err; + + if ((err = file_to_buf(fname, buf, MEMBUF_2048)) < 0) + return err; + + loc = strstr(buf, res); + if (loc == NULL) { + eprintf("%s is not found in buffer of file %s", res, fname); + return -ENODATA; + } + + sscanf(loc, "%*s%zu", (size_t *)out); + return 0; +} + +/*static inline void scan_mem_str(str, info, res) +{ + char *loc = NULL; + + 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", &info); + (res->res_unit[i]->data).sz = info; + res->res_unit[i]->status = RES_STATUS_FILLED; + } +}*/ + +/* read information from a cgroup file. + */ +static inline size_t cgmemread(char *cg, char *name, char *elem) +{ + char fn[FNAMELEN]; + unsigned long ret; + + snprintf(fn, FNAMELEN, "%s/%s%s/%s", DEFAULTCGFS, + MEMCGNAME, cg, name); + + cg_error = get_info_infile(fn, elem, &ret); + + return ret / 1024; +} + +/* Get all memory info for a cgroup */ +static int getmeminfoall(char *cg, void *out) +{ + res_mem_infoall_t *memall = out; + + memall->memfree = (size_t) + (cgmemread(cg, "memory", "limit_in_bytes") + - + cgmemread(cg, "memory", "usage_in_bytes")); + memall->memavailable = (size_t) + (cgmemread(cg, "memory", "limit_in_bytes") + - + cgmemread(cg, "memory", "usage_in_bytes") + + + cgmemread(cg, "memory.stat", "cache")); + memall->memtotal = (size_t) cgmemread(cg, "memory", "limit_in_bytes"); + memall->active = (size_t) (cgmemread(cg, "memory", "\nactive_anon") + + + cgmemread(cg, "memory", "\nactive_file")); + memall->inactive = (size_t) (cgmemread(cg, "memory", "\ninactive_anon") + + + cgmemread(cg, "memory", "\ninactive_file")); + memall->swaptotal = (size_t) + cgmemread(cg, "memory", "memsw.limit_in_bytes"); + memall->swapfree = (size_t) + (cgmemread(cg, "memory", "memsw.limit_in_bytes") + - + cgmemread(cg, "memory", "memsw.usage_in_bytes")); + return cg_error; +} + +/* + * Returns: -1 on error, 0 on success + */ +int getmeminfo_cg(int res_id, void *out, size_t sz, void **hint, int pid, int flags) +{ + char *cg; + + cg = get_cgroup(pid, MEMCGNAME); + if (!cg) { + printf("get_cgroups error\n"); + return -1; + } + + clean_init(cg); + + switch (res_id) { + case RES_MEM_FREE: + *(size_t *)out = (size_t) + (cgmemread(cg, "memory", "limit_in_bytes") + - + cgmemread(cg, "memory", "usage_in_bytes")); + break; + + case RES_MEM_AVAILABLE: + *(size_t *)out = (size_t) + (cgmemread(cg, "memory", "limit_in_bytes") + - + cgmemread(cg, "memory", "usage_in_bytes") + + + cgmemread(cg, "memory.stat", "cache")); + break; + + case RES_MEM_TOTAL: + *(size_t *)out = (size_t) + cgmemread(cg, "memory", "limit_in_bytes"); + break; + + case RES_MEM_ACTIVE: + *(size_t *)out = (size_t) (cgmemread(cg, "memory", "\nactive_anon") + + + cgmemread(cg, "memory", "\nactive_file")); + break; + + case RES_MEM_INACTIVE: + *(size_t *)out = (size_t) (cgmemread(cg, "memory", "\ninactive_anon") + + cgmemread(cg, "memory", "\ninactive_file")); + break; + + case RES_MEM_SWAPTOTAL: + *(size_t *)out = (size_t) + cgmemread(cg, "memory", "memsw.limit_in_bytes"); + break; + + case RES_MEM_SWAPFREE: + *(size_t *)out = (size_t) + (cgmemread(cg, "memory", "memsw.limit_in_bytes") + - + cgmemread(cg, "memory", "memsw.usage_in_bytes")); + break; + + case RES_MEM_INFOALL: + return (getmeminfoall(cg, out)); + } + + return cg_error; +} + +int populate_meminfo_cg(res_blk_t *res, int pid, int flags) +{ + char *cg; + char buf[MEMBUF_2048]; + int err; + + cg = get_cgroup(pid, MEMCGNAME); + if (!cg) { + printf("%s: get_cgroups error\n", __FUNCTION__); + return -1; + } + + clean_init(cg); + + if ((err = file_to_buf(MEMINFO_FILE, buf, MEMBUF_2048)) < 0) + return err; + + for (int i = 0; i < res->res_count; i++) { + switch (res->res_unit[i]->res_id) { + case RES_MEM_FREE: + (res->res_unit[i]->data).sz = (size_t) + (cgmemread(cg, "memory", "limit_in_bytes") + - + cgmemread(cg, "memory", "usage_in_bytes")); + break; + + case RES_MEM_AVAILABLE: + (res->res_unit[i]->data).sz = (size_t) + (cgmemread(cg, "memory", "limit_in_bytes") + - + cgmemread(cg, "memory", "usage_in_bytes") + + + cgmemread(cg, "memory.stat", "cache")); + break; + + case RES_MEM_TOTAL: + (res->res_unit[i]->data).sz = (size_t) + cgmemread(cg, "memory", "limit_in_bytes"); + break; + + case RES_MEM_ACTIVE: + (res->res_unit[i]->data).sz = (size_t) + (cgmemread(cg, "memory.stat", "\nactive_anon") + + + cgmemread(cg, "memory.stat", "\nactive_file")); + break; + + case RES_MEM_INACTIVE: + (res->res_unit[i]->data).sz = (size_t) + (cgmemread(cg, "memory.stat", "\ninactive_anon") + + + cgmemread(cg, "memory.stat", "\ninactive_file")); + break; + + case RES_MEM_SWAPTOTAL: + (res->res_unit[i]->data).sz = + cgmemread(cg, "memory", "memsw.limit_in_bytes"); + break; + + case RES_MEM_SWAPFREE: + (res->res_unit[i]->data).sz = + (cgmemread(cg, "memory", "memsw.limit_in_bytes") + - + cgmemread(cg, "memory", "memsw.usage_in_bytes")); + break; + } + res->res_unit[i]->status = cg_error; + } + return 0; +} diff --git a/resnet.c b/resnet.c index d889e22..748debc 100644 --- a/resnet.c +++ b/resnet.c @@ -386,8 +386,9 @@ int populate_netinfo(res_blk_t *res, int pid, int flags) res->res_unit[i]->data_sz, res->res_unit[i]->hint, 0, 0) == -1) { res->res_unit[i]->status = errno; - } else - res->res_unit[i]->status = RES_STATUS_FILLED; + } else { + res->res_unit[i]->status = 0; + } break; case RES_NET_ALLIFSTAT: /* Currently we don't support RES_NET_ALLIFSTAT with @@ -399,7 +400,7 @@ int populate_netinfo(res_blk_t *res, int pid, int flags) &(res->res_unit[i]->hint), 0, 0) == -1) { res->res_unit[i]->status = errno; } else { - res->res_unit[i]->status = RES_STATUS_FILLED; + res->res_unit[i]->status = 0; res->res_unit[i]->data.ptr = p; } break; diff --git a/resource.c b/resource.c index a3f22fe..ad7e67d 100644 --- a/resource.c +++ b/resource.c @@ -69,7 +69,6 @@ res_blk_t *res_build_blk(int *res_ids, int res_count) return NULL; } memset(temp, 0, sizeof(res_unit_t)); - temp->status = RES_STATUS_EMPTY; /* Some resource information are big and need extra allocation. * In these cases an address is returned which hold actual @@ -190,11 +189,13 @@ int res_read(int res_id, void *out, size_t out_sz, void **hint, int pid, int fla if (res_id >= PROC_MIN && res_id < PROC_MAX) return getprocinfo(res_id, out, out_sz, hint, pid, flags); - /* Check if memory proc file is needed to open */ if (res_id >= MEM_MIN && res_id < MEM_MAX) +#ifdef CGROUPS + return getmeminfo_cg(res_id, out, out_sz, hint, pid, flags); +#else return getmeminfo(res_id, out, out_sz, hint, pid, flags); +#endif - /* Check if net proc file is needed to open */ if (res_id >= NET_MIN && res_id < NET_MAX) return getnetinfo(res_id, out, out_sz, hint, pid, flags); @@ -267,7 +268,7 @@ int res_read_blk(res_blk_t *res, int pid, int flags) res->res_unit[i]->status = ENOMEM; } else { (res->res_unit[i]->data).sz = sysconf(_SC_PAGESIZE); - res->res_unit[i]->status = RES_STATUS_FILLED; + res->res_unit[i]->status = 0; } break; @@ -280,7 +281,7 @@ int res_read_blk(res_blk_t *res, int pid, int flags) len = sizeof(union r_data); strncpy(out, t.release, len-1); out[len-1] = '\0'; - res->res_unit[i]->status = RES_STATUS_FILLED; + res->res_unit[i]->status = 0; } break; @@ -295,7 +296,7 @@ int res_read_blk(res_blk_t *res, int pid, int flags) len = sizeof(union r_data); strncpy(out, rawdata, len-1); out[len-1] = '\0'; - res->res_unit[i]->status = RES_STATUS_FILLED; + res->res_unit[i]->status = 0; } break; @@ -307,14 +308,18 @@ int res_read_blk(res_blk_t *res, int pid, int flags) isprocreq = 1; default: - res->res_unit[i]->status = RES_STATUS_NOTSUPPORTED; + res->res_unit[i]->status = -1; } } if (isprocreq) populate_procinfo(res, pid, flags); if (ismeminforeq) - populate_meminfo(res, pid, flags); +#ifdef CGROUPS + return (populate_meminfo_cg(res, pid, flags)); +#else + return (populate_meminfo(res, pid, flags)); +#endif if (isnetdevreq) populate_netinfo(res, pid, flags); diff --git a/resource.h b/resource.h index 8f92e3c..9e86a3f 100644 --- a/resource.h +++ b/resource.h @@ -29,22 +29,6 @@ /* libresource version */ #define LIBRESOURCE_API_VERSION (1.0.0) -/* Possible status for libresource information returned */ -/* libresource information was fetched correctly */ -#define RES_STATUS_FILLED 0 -/* There was some error in fetching libresource information. In most cases - * errno will be set. - */ -#define RES_STATUS_EMPTY -1 -/* Resource information is not supported yet, or Invalid resource - * information. - */ -#define RES_STATUS_NOTSUPPORTED -2 -/* If partial information was read for a libresource information. For example - * a string was read partially. - */ -#define RES_STATUS_TRUNCATED -3 - /* Maximum size of a resource information data type which can be returned * without explicitly allocating memory for it. If resource information diff --git a/resource_impl.h b/resource_impl.h index 6b8e1f7..073d0de 100644 --- a/resource_impl.h +++ b/resource_impl.h @@ -72,23 +72,6 @@ static inline char *skip_spaces(char *s, size_t len, int n) { return NULL; } -static inline int libres_ulong(char *numstr, unsigned long *converted) -{ - char *endptr = NULL; - unsigned long uli; - - errno = 0; - uli = strtoul(numstr, &endptr, 10); - - if (errno == ERANGE || endptr == numstr || - (*endptr != '\0' && *endptr != '\n')) { - return -EINVAL; - } - - *converted = uli; - return 0; -} - static inline void clean_init(char *cg) { char *p; @@ -176,17 +159,16 @@ static inline char *get_cgroup(pid_t pid, const char *contrl) static inline int file_to_buf(char *fname, char *buf, unsigned int bufsz) { - int fd = 0; - size_t rdsz = 0; - int err = 0; + int fd; + size_t rdsz; + int err; fd = open(fname, O_RDONLY); if (fd == -1) { err = errno; eprintf("Error opening File %s with errno: %d", fname, errno); - errno = err; - return -1; + return -err; } rdsz = read(fd, buf, bufsz - 1); @@ -194,8 +176,7 @@ static inline int file_to_buf(char *fname, char *buf, unsigned int bufsz) err = errno; eprintf("in read from File %s with errno: %d", fname, errno); close(fd); - errno = err; - return -1; + return -err; } buf[rdsz] = '\0'; close(fd); diff --git a/resproc.c b/resproc.c index aca256b..a4eaec2 100644 --- a/resproc.c +++ b/resproc.c @@ -185,7 +185,7 @@ int populate_procinfo(res_blk_t *res, int pid, int flags) (res->res_unit[i]->data).ptr, res->res_unit[i]->data_sz, NULL, pid, flags); - res->res_unit[i]->status = RES_STATUS_FILLED; + res->res_unit[i]->status = 0; } } return 0;