Skip to content

Commit

Permalink
[LibOS] Support /sys/devices/system/node/nodeX/meminfo files
Browse files Browse the repository at this point in the history
This commit adds basic support for NUMA node meminfo files by simply
"mimicking" a typical environment where each NUMA node returns:
- NodeMemTotal = PalMemTotal / numa_nodes_cnt
- NodeMemFree = PalMemAvailable / numa_nodes_cnt

Signed-off-by: Kailun Qin <kailun.qin@intel.com>
  • Loading branch information
kailun-qin authored and Dmitrii Kuvaiskii committed Sep 15, 2022
1 parent 5c312f9 commit bd2bd00
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions libos/include/libos_fs_pseudo.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ bool sys_resource_name_exists(struct libos_dentry* parent, const char* name);
int sys_resource_list_names(struct libos_dentry* parent, readdir_callback_t callback, void* arg);
int sys_node_general_load(struct libos_dentry* dent, char** out_data, size_t* out_size);
int sys_node_load(struct libos_dentry* dent, char** out_data, size_t* out_size);
int sys_node_meminfo_load(struct libos_dentry* dent, char** out_data, size_t* out_size);
int sys_cpu_general_load(struct libos_dentry* dent, char** out_data, size_t* out_size);
int sys_cpu_load_online(struct libos_dentry* dent, char** out_data, size_t* out_size);
int sys_cpu_load_topology(struct libos_dentry* dent, char** out_data, size_t* out_size);
Expand Down
1 change: 1 addition & 0 deletions libos/src/fs/sys/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ static void init_node_dir(struct pseudo_node* node) {

pseudo_add_str(nodeX, "cpumap", &sys_node_load);
pseudo_add_str(nodeX, "distance", &sys_node_load);
pseudo_add_str(nodeX, "meminfo", &sys_node_meminfo_load);

// TODO(mkow): Does this show up for offline nodes? I never succeeded in shutting down one, even
// after shutting down all CPUs inside the node it shows up as online on `node/online` list.
Expand Down
88 changes: 88 additions & 0 deletions libos/src/fs/sys/node_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,91 @@ int sys_node_load(struct libos_dentry* dent, char** out_data, size_t* out_size)

return sys_load(str, out_data, out_size);
}

int sys_node_meminfo_load(struct libos_dentry* dent, char** out_data, size_t* out_size) {
size_t numa_nodes_cnt = g_pal_public_state->topo_info.numa_nodes_cnt;
/* Simply "mimic" a typical environment: split memory evenly between each NUMA node */
size_t node_mem_total = g_pal_public_state->mem_total / numa_nodes_cnt;
size_t node_mem_free = PalMemoryAvailableQuota() / numa_nodes_cnt;

assert(node_mem_total >= node_mem_free);

unsigned int node_id;
int ret = sys_resource_find(dent, "node", &node_id);
if (ret < 0)
return ret;

size_t size = 0, max = 256;
char* str = malloc(max);
if (!str)
return -ENOMEM;

/*
* Enumerate minimum set of node meminfo stats (the default stats in Linux, without specific
* `#ifdef CONFIG_xxx`). This set is based on Linux v5.19, see below for details:
*
* - https://elixir.bootlin.com/linux/v5.19/source/drivers/base/node.c#L369
*/

struct {
const char* fmt;
unsigned long val;
} meminfo[] = {
{ "Node %u MemTotal: %8lu kB\n", node_mem_total / 1024 },
{ "Node %u MemFree: %8lu kB\n", node_mem_free / 1024 },
{ "Node %u MemUsed: %8lu kB\n", (node_mem_total - node_mem_free) / 1024 },
{ "Node %u SwapCached: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Active: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Inactive: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Active(anon): %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Inactive(anon): %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Active(file): %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Inactive(file): %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Unevictable: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Mlocked: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Dirty: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Writeback: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u FilePages: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Mapped: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u AnonPages: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Shmem: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u KernelStack: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u PageTables: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u NFS_Unstable: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Bounce: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u WritebackTmp: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u KReclaimable: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u Slab: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u SReclaimable: %8lu kB\n", /*dummy value=*/0 },
{ "Node %u SUnreclaim: %8lu kB\n", /*dummy value=*/0 },
};

size_t i = 0;
while (i < ARRAY_SIZE(meminfo)) {
ret = snprintf(str + size, max - size, meminfo[i].fmt, node_id, meminfo[i].val);
if (ret < 0) {
free(str);
return ret;
}

if (size + ret >= max) {
max *= 2;
size = 0;
i = 0;
free(str);
/* TODO: use `realloc()` once it's available. */
str = malloc(max);
if (!str)
return -ENOMEM;

continue;
}

size += ret;
i++;
}

*out_data = str;
*out_size = size;
return 0;
}

0 comments on commit bd2bd00

Please sign in to comment.