diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-23 02:05:10 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-05-23 02:05:10 +0200 |
commit | bad79d577c8b7e87de5113bbb03c3de72c06f4a1 (patch) | |
tree | 2ea1ac5bc936ec5c9b1a154b52d9acf21cac0a09 | |
parent | 6f4e22c2fb1bf412e84fe4ca105944921a8c7c5d (diff) |
implement /proc/slabinfo
-rw-r--r-- | procfs/Makefile | 22 | ||||
-rw-r--r-- | procfs/rootdir.c | 96 |
2 files changed, 117 insertions, 1 deletions
diff --git a/procfs/Makefile b/procfs/Makefile index 5c51c1d2..28205962 100644 --- a/procfs/Makefile +++ b/procfs/Makefile @@ -1,6 +1,6 @@ TARGET = procfs OBJS = procfs.o netfs.o procfs_dir.o \ - process.o proclist.o rootdir.o dircat.o main.o + process.o proclist.o rootdir.o dircat.o main.o mach_debugUser.o LIBS = -lnetfs -lps -lfshelp -lpthread CC = gcc @@ -19,8 +19,28 @@ CPPFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 all: $(TARGET) +rootdir.o: rootdir.c mach_debug_U.h + $(TARGET): $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) clean: $(RM) $(TARGET) $(OBJS) + +# This is the gist of the MIG user stub handling from Hurd's build +# system: + +# Where to find .defs files. +vpath %.defs /usr/include/mach_debug + +MIG = mig +MIGCOM = $(MIG) -cc cat - /dev/null +MIGCOMFLAGS := -subrprefix __ + +%.udefsi: %.defs + $(CPP) -x c $(CPPFLAGS) $(MIGUFLAGS) $($*-MIGUFLAGS) \ + $< -o $*.udefsi + +%_U.h %User.c: %.udefsi + $(MIGCOM) $(MIGCOMFLAGS) $(MIGCOMUFLAGS) $($*-MIGCOMUFLAGS) < $< \ + -user $*User.c -server /dev/null -header $*_U.h diff --git a/procfs/rootdir.c b/procfs/rootdir.c index 94b0ddb2..bba98116 100644 --- a/procfs/rootdir.c +++ b/procfs/rootdir.c @@ -22,6 +22,7 @@ #include <mach/vm_statistics.h> #include <mach/vm_cache_statistics.h> #include <mach/default_pager.h> +#include <mach_debug/mach_debug_types.h> #include <hurd/paths.h> #include <stdio.h> #include <unistd.h> @@ -35,6 +36,8 @@ #include "procfs_dir.h" #include "main.h" +#include "mach_debug_U.h" + /* This implements a directory node with the static files in /proc. NB: the libps functions for host information return static storage; using them would require locking and as a consequence it would be @@ -470,6 +473,92 @@ rootdir_mounts_exists (void *dir_hook, const void *entry_hook) translator_exists = access (MTAB_TRANSLATOR, F_OK|X_OK) == 0; return translator_exists; } + +static error_t +rootdir_gc_slabinfo (void *hook, char **contents, ssize_t *contents_len) +{ + error_t err; + const char header[] = + "cache obj slab bufs objs bufs" + " total reclaimable\n" + "name flags size size /slab usage count" + " memory memory\n"; + char **infos, *p; + ssize_t length, written; + cache_info_array_t cache_info; + size_t mem_usage, mem_reclaimable, mem_total, mem_total_reclaimable; + mach_msg_type_number_t cache_info_count; + int i, j; + + cache_info = NULL; + cache_info_count = 0; + + err = host_slab_info (mach_host_self(), &cache_info, &cache_info_count); + if (err) + return err; + + infos = malloc ((cache_info_count + 1) * sizeof *infos); + if (infos == NULL) + return ENOMEM; + + length = sizeof header; /* Includes the terminating 0. */ + mem_total = 0; + mem_total_reclaimable = 0; + + for (i = 0; i < cache_info_count; i++) + { + mem_usage = (cache_info[i].nr_slabs * cache_info[i].slab_size) + >> 10; + mem_total += mem_usage; + mem_reclaimable = (cache_info[i].flags & CACHE_FLAGS_NO_RECLAIM) + ? 0 : (cache_info[i].nr_free_slabs + * cache_info[i].slab_size) >> 10; + mem_total_reclaimable += mem_reclaimable; + length += written = + asprintf (&infos[i], + "%-21s %04x %7zu %3zuk %4lu %6lu %6lu %7zuk %10zuk\n", + cache_info[i].name, cache_info[i].flags, + cache_info[i].obj_size, cache_info[i].slab_size >> 10, + cache_info[i].bufs_per_slab, cache_info[i].nr_objs, + cache_info[i].nr_bufs, mem_usage, mem_reclaimable); + if (written == -1) + goto out; + } + + length += written = + asprintf (&infos[i], "total: %zuk, reclaimable: %zuk\n", + mem_total, mem_total_reclaimable); + if (written == -1) + goto out; + + *contents = p = malloc (length); + if (p == NULL) + goto out; + + strcpy (p, header); + p += sizeof header - 1; /* Without the 0. */ + + for (i = 0; i < cache_info_count + 1; i++) + { + size_t l = strlen (infos[i]); + memcpy (p, infos[i], l); + p += l; + free (infos[i]); + } + free (infos); + + *p = 0; + p += 1; + assert (p == *contents + length); + *contents_len = length; + return 0; + + out: + for (j = 0; j < i; j++) + free (infos[j]); + free (infos); + return ENOMEM; +} /* Glue logic and entries table */ @@ -563,6 +652,13 @@ static const struct procfs_dir_entry rootdir_entries[] = { .exists = rootdir_mounts_exists, } }, + { + .name = "slabinfo", + .hook = & (struct procfs_node_ops) { + .get_contents = rootdir_gc_slabinfo, + .cleanup_contents = procfs_cleanup_contents_with_free, + }, + }, #ifdef PROFILE /* In order to get a usable gmon.out file, we must apparently use exit(). */ { |