The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxcfs/pull/332
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === dirty/writeback ... and so on Closes #315. Signed-off-by LiMing Wu <19092...@suning.com> Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From acff9786e82ba239743521e923bb9afc51c88555 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Thu, 27 Feb 2020 14:55:43 +0100 Subject: [PATCH] meminfo: add some more metrics dirty/writeback ... and so on Closes #315. Signed-off-by LiMing Wu <19092...@suning.com> Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- cgroups/cgfsng.c | 14 +++ cgroups/cgroup.h | 1 + proc_fuse.c | 251 +++++++++++++++++++++++++++++------------------ proc_loadavg.c | 21 ++-- 4 files changed, 182 insertions(+), 105 deletions(-) diff --git a/cgroups/cgfsng.c b/cgroups/cgfsng.c index b4912b3..d5b6aff 100644 --- a/cgroups/cgfsng.c +++ b/cgroups/cgfsng.c @@ -593,6 +593,19 @@ static int cgfsng_get_memory(struct cgroup_ops *ops, const char *cgroup, return ret; } +static int cgfsng_get_memory_stats_fd(struct cgroup_ops *ops, const char *cgroup) +{ + __do_free char *path = NULL; + struct hierarchy *h; + + h = ops->get_hierarchy(ops, "memory"); + if (!h) + return -1; + + path = must_make_path(dot_or_empty(cgroup), cgroup, "memory.stat", NULL); + return openat(h->fd, path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); +} + static int cgfsng_get_memory_current(struct cgroup_ops *ops, const char *cgroup, char **value) { @@ -964,6 +977,7 @@ struct cgroup_ops *cgfsng_ops_init(void) cgfsng_ops->mount = cgfsng_mount; /* memory */ + cgfsng_ops->get_memory_stats_fd = cgfsng_get_memory_stats_fd; cgfsng_ops->get_memory_stats = cgfsng_get_memory_stats; cgfsng_ops->get_memory_max = cgfsng_get_memory_max; cgfsng_ops->get_memory_swap_max = cgfsng_get_memory_swap_max; diff --git a/cgroups/cgroup.h b/cgroups/cgroup.h index bd87994..dfcee0e 100644 --- a/cgroups/cgroup.h +++ b/cgroups/cgroup.h @@ -136,6 +136,7 @@ struct cgroup_ops { const char *cgroup, const char *file, char **value); /* memory */ + int (*get_memory_stats_fd)(struct cgroup_ops *ops, const char *cgroup); int (*get_memory_stats)(struct cgroup_ops *ops, const char *cgroup, char **value); int (*get_memory_current)(struct cgroup_ops *ops, const char *cgroup, diff --git a/proc_fuse.c b/proc_fuse.c index 037fa32..5688d83 100644 --- a/proc_fuse.c +++ b/proc_fuse.c @@ -50,6 +50,28 @@ #include "proc_cpuview.h" #include "utils.h" +struct memory_stat { + uint64_t hierarchical_memory_limit; + uint64_t hierarchical_memsw_limit; + uint64_t total_cache; + uint64_t total_rss; + uint64_t total_rss_huge; + uint64_t total_shmem; + uint64_t total_mapped_file; + uint64_t total_dirty; + uint64_t total_writeback; + uint64_t total_swap; + uint64_t total_pgpgin; + uint64_t total_pgpgout; + uint64_t total_pgfault; + uint64_t total_pgmajfault; + uint64_t total_inactive_anon; + uint64_t total_active_anon; + uint64_t total_inactive_file; + uint64_t total_active_file; + uint64_t total_unevictable; +}; + int proc_getattr(const char *path, struct stat *sb) { struct timespec now; @@ -937,60 +959,69 @@ static int proc_stat_read(char *buf, size_t size, off_t offset, } /* Note that "memory.stat" in cgroup2 is hierarchical by default. */ -static void parse_memstat(int version, - char *memstat, - unsigned long *cached, - unsigned long *active_anon, - unsigned long *inactive_anon, - unsigned long *active_file, - unsigned long *inactive_file, - unsigned long *unevictable, - unsigned long *shmem) +static bool cgroup_parse_memory_stat(const char *cgroup, struct memory_stat *mstat) { - char *eol; + __do_close_prot_errno int fd = -EBADF; + __do_fclose FILE *f = NULL; + __do_free char *line = NULL; + bool unified; + size_t len = 0; + ssize_t linelen; - while (*memstat) { - if (startswith(memstat, is_unified_controller(version) - ? "cache" - : "total_cache")) { - sscanf(memstat + 11, "%lu", cached); - *cached /= 1024; - } else if (startswith(memstat, is_unified_controller(version) - ? "active_anon" - : "total_active_anon")) { - sscanf(memstat + 17, "%lu", active_anon); - *active_anon /= 1024; - } else if (startswith(memstat, is_unified_controller(version) - ? "inactive_anon" - : "total_inactive_anon")) { - sscanf(memstat + 19, "%lu", inactive_anon); - *inactive_anon /= 1024; - } else if (startswith(memstat, is_unified_controller(version) - ? "active_file" - : "total_active_file")) { - sscanf(memstat + 17, "%lu", active_file); - *active_file /= 1024; - } else if (startswith(memstat, is_unified_controller(version) - ? "inactive_file" - : "total_inactive_file")) { - sscanf(memstat + 19, "%lu", inactive_file); - *inactive_file /= 1024; - } else if (startswith(memstat, is_unified_controller(version) - ? "unevictable" - : "total_unevictable")) { - sscanf(memstat + 17, "%lu", unevictable); - *unevictable /= 1024; - } else if (startswith(memstat, is_unified_controller(version) - ? "shmem" - : "total_shmem")) { - sscanf(memstat + 11, "%lu", shmem); - *shmem /= 1024; + fd = cgroup_ops->get_memory_stats_fd(cgroup_ops, cgroup); + if (fd < 0) + return false; + + f = fdopen(fd, "re"); + if (!f) + return false; + /* Transferring ownership to fdopen(). */ + move_fd(fd); + + unified = pure_unified_layout(cgroup_ops); + while ((linelen = getline(&line, &len, f)) != -1) { + if (!unified && startswith(line, "hierarchical_memory_limit")) { + sscanf(line, "hierarchical_memory_limit %" PRIu64, &(mstat->hierarchical_memory_limit)); + } else if (!unified && startswith(line, "hierarchical_memsw_limit")) { + sscanf(line, "hierarchical_memsw_limit %" PRIu64, &(mstat->hierarchical_memsw_limit)); + } else if (!unified && startswith(line, "total_cache")) { + sscanf(line, "total_cache %" PRIu64, &(mstat->total_cache)); + } else if (!unified && startswith(line, "total_rss")) { + sscanf(line, "total_rss %" PRIu64, &(mstat->total_rss)); + } else if (!unified && startswith(line, "total_rss_huge")) { + sscanf(line, "total_rss_huge %" PRIu64, &(mstat->total_rss_huge)); + } else if (startswith(line, unified ? "shmem" : "total_shmem")) { + sscanf(line, unified ? "shmem %" PRIu64 : "total_shmem %" PRIu64, &(mstat->total_shmem)); + } else if (startswith(line, unified ? "file_mapped" : "total_mapped_file")) { + sscanf(line, unified ? "file_mapped %" PRIu64 : "total_mapped_file %" PRIu64, &(mstat->total_mapped_file)); + } else if (!unified && startswith(line, "total_dirty")) { + sscanf(line, "total_dirty %" PRIu64, &(mstat->total_dirty)); + } else if (!unified && startswith(line, "total_writeback")) { + sscanf(line, "total_writeback %" PRIu64, &(mstat->total_writeback)); + } else if (!unified && startswith(line, "total_swap")) { + sscanf(line, "total_swap %" PRIu64, &(mstat->total_swap)); + } else if (!unified && startswith(line, "total_pgpgin")) { + sscanf(line, "total_pgpgin %" PRIu64, &(mstat->total_pgpgin)); + } else if (!unified && startswith(line, "total_pgpgout")) { + sscanf(line, "total_pgpgout %" PRIu64, &(mstat->total_pgpgout)); + } else if (startswith(line, unified ? "pgfault" : "total_pgfault")) { + sscanf(line, unified ? "pgfault %" PRIu64 : "total_pgfault %" PRIu64, &(mstat->total_pgfault)); + } else if (startswith(line, unified ? "pgmajfault" : "total_pgmajfault")) { + sscanf(line, unified ? "pgmajfault %" PRIu64 : "total_pgmajfault %" PRIu64, &(mstat->total_pgmajfault)); + } else if (startswith(line, unified ? "inactive_anon" : "total_inactive_anon")) { + sscanf(line, unified ? "inactive_anon %" PRIu64 : "total_inactive_anon %" PRIu64, &(mstat->total_inactive_anon)); + } else if (startswith(line, unified ? "active_anon" : "total_active_anon")) { + sscanf(line, unified ? "active_anon %" PRIu64 : "total_active_anon %" PRIu64, &(mstat->total_active_anon)); + } else if (startswith(line, unified ? "inactive_file" : "total_inactive_file")) { + sscanf(line, unified ? "inactive_file %" PRIu64 : "total_inactive_file %" PRIu64, &(mstat->total_inactive_file)); + } else if (startswith(line, unified ? "active_file" : "total_active_file")) { + sscanf(line, unified ? "active_file %" PRIu64 : "total_active_file %" PRIu64, &(mstat->total_active_file)); + } else if (startswith(line, unified ? "unevictable" : "total_unevictable")) { + sscanf(line, unified ? "unevictable %" PRIu64 : "total_unevictable %" PRIu64, &(mstat->total_unevictable)); } - eol = strchr(memstat, '\n'); - if (!eol) - return; - memstat = eol+1; } + + return true; } static int proc_meminfo_read(char *buf, size_t size, off_t offset, @@ -1003,10 +1034,9 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, struct fuse_context *fc = fuse_get_context(); struct lxcfs_opts *opts = (struct lxcfs_opts *) fuse_get_context()->private_data; struct file_info *d = INTTYPE_TO_PTR(fi->fh); - unsigned long memlimit = 0, memusage = 0, memswlimit = 0, - memswusage = 0, cached = 0, hosttotal = 0, active_anon = 0, - inactive_anon = 0, active_file = 0, inactive_file = 0, - unevictable = 0, shmem = 0, hostswtotal = 0; + uint64_t memlimit = 0, memusage = 0, memswlimit = 0, memswusage = 0, + hosttotal = 0; + struct memory_stat mstat; size_t linelen = 0, total_len = 0; char *cache = d->buf; size_t cache_size = d->buflen; @@ -1044,11 +1074,8 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, if (ret < 0) return 0; - ret = cgroup_ops->get_memory_stats(cgroup_ops, cgroup, &memstat_str); - if (ret < 0) + if (!cgroup_parse_memory_stat(cgroup, &mstat)) return 0; - parse_memstat(ret, memstat_str, &cached, &active_anon, &inactive_anon, - &active_file, &inactive_file, &unevictable, &shmem); /* * Following values are allowed to fail, because swapaccount might be @@ -1078,93 +1105,125 @@ static int proc_meminfo_read(char *buf, size_t size, off_t offset, memset(lbuf, 0, 100); if (startswith(line, "MemTotal:")) { - sscanf(line+sizeof("MemTotal:")-1, "%lu", &hosttotal); + sscanf(line+sizeof("MemTotal:")-1, "%" PRIu64, &hosttotal); if (hosttotal < memlimit) memlimit = hosttotal; - snprintf(lbuf, 100, "MemTotal: %8lu kB\n", memlimit); + snprintf(lbuf, 100, "MemTotal: %8" PRIu64 " kB\n", memlimit); printme = lbuf; } else if (startswith(line, "MemFree:")) { - snprintf(lbuf, 100, "MemFree: %8lu kB\n", memlimit - memusage); + snprintf(lbuf, 100, "MemFree: %8" PRIu64 " kB\n", memlimit - memusage); printme = lbuf; } else if (startswith(line, "MemAvailable:")) { - snprintf(lbuf, 100, "MemAvailable: %8lu kB\n", memlimit - memusage + cached); + snprintf(lbuf, 100, "MemAvailable: %8" PRIu64 " kB\n", memlimit - memusage + mstat.total_cache / 1024); printme = lbuf; } else if (startswith(line, "SwapTotal:") && memswlimit > 0 && opts && opts->swap_off == false) { - sscanf(line+sizeof("SwapTotal:")-1, "%lu", &hostswtotal); - if (hostswtotal < memswlimit) - memswlimit = hostswtotal; - snprintf(lbuf, 100, "SwapTotal: %8lu kB\n", memswlimit); + memswlimit -= memlimit; + snprintf(lbuf, 100, "SwapTotal: %8" PRIu64 " kB\n", memswlimit); printme = lbuf; } else if (startswith(line, "SwapTotal:") && opts && opts->swap_off == true) { - snprintf(lbuf, 100, "SwapTotal: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "SwapTotal: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "SwapFree:") && memswlimit > 0 && memswusage > 0 && opts && opts->swap_off == false) { - unsigned long swaptotal = memswlimit, - swapusage = memusage > memswusage - ? 0 - : memswusage - memusage, - swapfree = swapusage < swaptotal - ? swaptotal - swapusage - : 0; - snprintf(lbuf, 100, "SwapFree: %8lu kB\n", swapfree); + uint64_t swaptotal = memswlimit, + swapusage = memusage > memswusage + ? 0 + : memswusage - memusage, + swapfree = swapusage < swaptotal + ? swaptotal - swapusage + : 0; + snprintf(lbuf, 100, "SwapFree: %8" PRIu64 " kB\n", swapfree); printme = lbuf; } else if (startswith(line, "SwapFree:") && opts && opts->swap_off == true) { - snprintf(lbuf, 100, "SwapFree: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "SwapFree: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "Slab:")) { - snprintf(lbuf, 100, "Slab: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "Slab: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "Buffers:")) { - snprintf(lbuf, 100, "Buffers: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "Buffers: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "Cached:")) { - snprintf(lbuf, 100, "Cached: %8lu kB\n", cached); + snprintf(lbuf, 100, "Cached: %8" PRIu64 " kB\n", + mstat.total_cache / 1024); printme = lbuf; } else if (startswith(line, "SwapCached:")) { - snprintf(lbuf, 100, "SwapCached: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "SwapCached: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "Active:")) { - snprintf(lbuf, 100, "Active: %8lu kB\n", - active_anon + active_file); + snprintf(lbuf, 100, "Active: %8" PRIu64 " kB\n", + (mstat.total_active_anon + + mstat.total_active_file) / + 1024); printme = lbuf; } else if (startswith(line, "Inactive:")) { - snprintf(lbuf, 100, "Inactive: %8lu kB\n", - inactive_anon + inactive_file); + snprintf(lbuf, 100, "Inactive: %8" PRIu64 " kB\n", + (mstat.total_inactive_anon + + mstat.total_inactive_file) / + 1024); printme = lbuf; } else if (startswith(line, "Active(anon)")) { - snprintf(lbuf, 100, "Active(anon): %8lu kB\n", active_anon); + snprintf(lbuf, 100, "Active(anon): %8" PRIu64 " kB\n", + mstat.total_active_anon / 1024); printme = lbuf; } else if (startswith(line, "Inactive(anon)")) { - snprintf(lbuf, 100, "Inactive(anon): %8lu kB\n", inactive_anon); + snprintf(lbuf, 100, "Inactive(anon): %8" PRIu64 " kB\n", + mstat.total_inactive_anon / 1024); printme = lbuf; } else if (startswith(line, "Active(file)")) { - snprintf(lbuf, 100, "Active(file): %8lu kB\n", active_file); + snprintf(lbuf, 100, "Active(file): %8" PRIu64 " kB\n", + mstat.total_active_file / 1024); printme = lbuf; } else if (startswith(line, "Inactive(file)")) { - snprintf(lbuf, 100, "Inactive(file): %8lu kB\n", inactive_file); + snprintf(lbuf, 100, "Inactive(file): %8" PRIu64 " kB\n", + mstat.total_inactive_file / 1024); printme = lbuf; } else if (startswith(line, "Unevictable")) { - snprintf(lbuf, 100, "Unevictable: %8lu kB\n", unevictable); + snprintf(lbuf, 100, "Unevictable: %8" PRIu64 " kB\n", + mstat.total_unevictable / 1024); + printme = lbuf; + } else if (startswith(line, "Dirty")) { + snprintf(lbuf, 100, "Dirty: %8" PRIu64 " kB\n", + mstat.total_dirty / 1024); + printme = lbuf; + } else if (startswith(line, "Writeback")) { + snprintf(lbuf, 100, "Writeback: %8" PRIu64 " kB\n", + mstat.total_writeback / 1024); + printme = lbuf; + } else if (startswith(line, "AnonPages")) { + snprintf(lbuf, 100, "AnonPages: %8" PRIu64 " kB\n", + (mstat.total_active_anon + + mstat.total_inactive_anon - mstat.total_shmem) / + 1024); + printme = lbuf; + } else if (startswith(line, "Mapped")) { + snprintf(lbuf, 100, "Mapped: %8" PRIu64 " kB\n", + mstat.total_mapped_file / 1024); printme = lbuf; } else if (startswith(line, "SReclaimable")) { - snprintf(lbuf, 100, "SReclaimable: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "SReclaimable: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "SUnreclaim")) { - snprintf(lbuf, 100, "SUnreclaim: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "SUnreclaim: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "Shmem:")) { - snprintf(lbuf, 100, "Shmem: %8lu kB\n", shmem); + snprintf(lbuf, 100, "Shmem: %8" PRIu64 " kB\n", + mstat.total_shmem / 1024); printme = lbuf; } else if (startswith(line, "ShmemHugePages")) { - snprintf(lbuf, 100, "ShmemHugePages: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "ShmemHugePages: %8" PRIu64 " kB\n", (uint64_t)0); printme = lbuf; } else if (startswith(line, "ShmemPmdMapped")) { - snprintf(lbuf, 100, "ShmemPmdMapped: %8lu kB\n", 0UL); + snprintf(lbuf, 100, "ShmemPmdMapped: %8" PRIu64 " kB\n", (uint64_t)0); + printme = lbuf; + } else if (startswith(line, "AnonHugePages")) { + snprintf(lbuf, 100, "AnonHugePages: %8" PRIu64 " kB\n", + mstat.total_rss_huge / 1024); printme = lbuf; - } else - printme = line; + } else { + printme = line; + } l = snprintf(cache, cache_size, "%s", printme); if (l < 0) { diff --git a/proc_loadavg.c b/proc_loadavg.c index 9fc602b..31dd968 100644 --- a/proc_loadavg.c +++ b/proc_loadavg.c @@ -393,11 +393,12 @@ static int refresh_load(struct load_node *p, char *path) __do_closedir DIR *dp = NULL; /*clean up '\n' */ - length = strlen(idbuf[i])-1; + length = strlen(idbuf[i]) - 1; idbuf[i][length] = '\0'; ret = snprintf(proc_path, 256, "/proc/%s/task", idbuf[i]); if (ret < 0 || ret > 255) { - lxcfs_error("%s\n", "snprintf() failed in refresh_load."); + lxcfs_error("%s\n", + "snprintf() failed in refresh_load."); i = sum; sum = -1; goto err_out; @@ -405,7 +406,8 @@ static int refresh_load(struct load_node *p, char *path) dp = opendir(proc_path); if (!dp) { - lxcfs_error("%s\n", "Open proc_path failed in refresh_load."); + lxcfs_error("%s\n", + "Open proc_path failed in refresh_load."); continue; } while ((file = readdir(dp)) != NULL) { @@ -420,7 +422,8 @@ static int refresh_load(struct load_node *p, char *path) ret = atof(file->d_name); last_pid = (ret > last_pid) ? ret : last_pid; - ret = snprintf(proc_path, 256, "/proc/%s/task/%s/status", idbuf[i], file->d_name); + ret = snprintf(proc_path, 256, "/proc/%s/task/%s/status", + idbuf[i], file->d_name); if (ret < 0 || ret > 255) { lxcfs_error("%s\n", "snprintf() failed in refresh_load."); i = sum; @@ -432,12 +435,12 @@ static int refresh_load(struct load_node *p, char *path) if (f != NULL) { while (getline(&line, &linelen, f) != -1) { /* Find State */ - if ((line[0] == 'S') && (line[1] == 't')) - break; + if ((strncmp(line, "State", 5) == 0) && + (strncmp(line, "State R", 7) == 0 || + strncmp(line, "State D", 7) == 0)) + run_pid++; + break; } - - if ((line[7] == 'R') || (line[7] == 'D')) - run_pid++; } } }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel