summaryrefslogtreecommitdiff
path: root/proc/slab.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc/slab.c')
-rw-r--r--proc/slab.c211
1 files changed, 123 insertions, 88 deletions
diff --git a/proc/slab.c b/proc/slab.c
index b0bccaa..13cbbd3 100644
--- a/proc/slab.c
+++ b/proc/slab.c
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <limits.h>
#include <ctype.h>
+#include <errno.h>
#include "slab.h"
#include "procps.h"
@@ -36,25 +37,65 @@
#define SLABINFO_VER_LEN 100
#define SLABINFO_FILE "/proc/slabinfo"
-static struct slab_info *free_index;
+/*
+ * procps_slabinfo_new:
+ * @slabinfo: procps slabinfo
+ *
+ * Create a new slabinfo structure
+ */
+int procps_slabinfo_new(struct procps_slabinfo **slabinfo)
+{
+ struct procps_slabinfo *si;
+ si = calloc(1, sizeof(struct procps_slabinfo));
+ if (!si)
+ return -ENOMEM;
+ *slabinfo = si;
+ return 0;
+}
+
+/*
+ * procps_slab_free:
+ * @slabinfo procps slabinfo strucutre
+ *
+ * Deallacate or free all memory in the slabinfo structure including in
+ * the lists
+ */
+void procps_slabinfo_free(struct procps_slabinfo *slabinfo)
+{
+ struct slab_node *curr, *next;
+
+ curr = slabinfo->slab_list;
+ while (curr) {
+ next = curr->next;
+ free(curr);
+ curr = next;
+ }
+ curr = slabinfo->free_head;
+ while (curr) {
+ next = curr->next;
+ free(curr);
+ curr = next;
+ }
+ free(slabinfo);
+}
/*
- * get_slabnode - allocate slab_info structures using a free list
+ * get_slabnode - allocate slab_node structures using a free list
*
* In the fast path, we simply return a node off the free list. In the slow
* list, we malloc() a new node. The free list is never automatically reaped,
* both for simplicity and because the number of slab caches is fairly
* constant.
*/
-static struct slab_info *get_slabnode(void)
+static struct slab_node *get_slabnode(struct procps_slabinfo *slabinfo)
{
- struct slab_info *node;
+ struct slab_node *node;
- if (free_index) {
- node = free_index;
- free_index = free_index->next;
+ if (slabinfo->free_next) {
+ node = slabinfo->free_next;
+ slabinfo->free_next = slabinfo->free_next->next;
} else {
- node = xmalloc(sizeof(struct slab_info));
+ node = xmalloc(sizeof(struct procps_slabinfo));
}
return node;
@@ -80,25 +121,18 @@ static int slab_badname_detect(const char *restrict buffer)
}
/*
- * put_slabinfo - return all allocated nodes to the free list
+ * procps_slabinfo_clear:
+ * @slabinfo: slab information
+ *
+ * Put all of the slabs into the free index
*/
-void put_slabinfo(struct slab_info *head)
+void procps_slabinfo_clear(struct procps_slabinfo *slabinfo)
{
- free_index = head;
+ slabinfo->free_head = slabinfo->slab_list;
+ slabinfo->free_next = slabinfo->free_head;
+ slabinfo->slab_list = NULL;
}
-/*
- * free_slabinfo - deallocate the memory associated with each node in the
- * slab_info linked list
- */
-void free_slabinfo(struct slab_info *list)
-{
- while (list) {
- struct slab_info *temp = list->next;
- free(list);
- list = temp;
- }
-}
// parse_slabinfo20 - actual parse routine for slabinfo 2.x (2.6 kernels)
// Note: difference between 2.0 and 2.1 is in the ": globalstat" part where version 2.1
@@ -129,16 +163,15 @@ void free_slabinfo(struct slab_info *list)
// : slabdata <active_slabs> <num_slabs> <sharedavail> \
// : globalstat <listallocs> <maxobjs> <grown> <reaped> <error> <maxfreeable> <freelimit> \
// : cpustat <allochit> <allocmiss> <freehit> <freemiss>
-static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
- FILE *f)
+static int parse_slabinfo20(struct procps_slabinfo *slabinfo, FILE *f)
{
- struct slab_info *curr = NULL, *prev = NULL;
+ struct slab_node *curr = NULL, *prev = NULL;
char buffer[SLABINFO_LINE_LEN];
int entries = 0;
int page_size = getpagesize();
- stats->min_obj_size = INT_MAX;
- stats->max_obj_size = 0;
+ slabinfo->min_obj_size = INT_MAX;
+ slabinfo->max_obj_size = 0;
while (fgets(buffer, SLABINFO_LINE_LEN, f)) {
int assigned;
@@ -146,12 +179,12 @@ static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
if (buffer[0] == '#')
continue;
- curr = get_slabnode();
+ curr = get_slabnode(slabinfo);
if (!curr)
break;
if (entries++ == 0)
- *list = curr;
+ slabinfo->slab_list = curr;
else
if (prev)
prev->next = curr;
@@ -170,26 +203,26 @@ static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
break;
}
- if (curr->obj_size < stats->min_obj_size)
- stats->min_obj_size = curr->obj_size;
- if (curr->obj_size > stats->max_obj_size)
- stats->max_obj_size = curr->obj_size;
+ if (curr->obj_size < slabinfo->min_obj_size)
+ slabinfo->min_obj_size = curr->obj_size;
+ if (curr->obj_size > slabinfo->max_obj_size)
+ slabinfo->max_obj_size = curr->obj_size;
curr->cache_size = (unsigned long)curr->nr_slabs * curr->pages_per_slab * page_size;
if (curr->nr_objs) {
curr->use = 100 * curr->nr_active_objs / curr->nr_objs;
- stats->nr_active_caches++;
+ slabinfo->nr_active_caches++;
} else
curr->use = 0;
- stats->nr_objs += curr->nr_objs;
- stats->nr_active_objs += curr->nr_active_objs;
- stats->total_size += (unsigned long)curr->nr_objs * curr->obj_size;
- stats->active_size += (unsigned long)curr->nr_active_objs * curr->obj_size;
- stats->nr_pages += curr->nr_slabs * curr->pages_per_slab;
- stats->nr_slabs += curr->nr_slabs;
- stats->nr_active_slabs += curr->nr_active_slabs;
+ slabinfo->nr_objs += curr->nr_objs;
+ slabinfo->nr_active_objs += curr->nr_active_objs;
+ slabinfo->total_size += (unsigned long)curr->nr_objs * curr->obj_size;
+ slabinfo->active_size += (unsigned long)curr->nr_active_objs * curr->obj_size;
+ slabinfo->nr_pages += curr->nr_slabs * curr->pages_per_slab;
+ slabinfo->nr_slabs += curr->nr_slabs;
+ slabinfo->nr_active_slabs += curr->nr_active_slabs;
prev = curr;
}
@@ -200,9 +233,9 @@ static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
}
curr->next = NULL;
- stats->nr_caches = entries;
- if (stats->nr_objs)
- stats->avg_obj_size = stats->total_size / stats->nr_objs;
+ slabinfo->nr_caches = entries;
+ if (slabinfo->nr_objs)
+ slabinfo->avg_obj_size = slabinfo->total_size / slabinfo->nr_objs;
return 0;
}
@@ -210,26 +243,25 @@ static int parse_slabinfo20(struct slab_info **list, struct slab_stat *stats,
/*
* parse_slabinfo11 - actual parsing routine for slabinfo 1.1 (2.4 kernels)
*/
-static int parse_slabinfo11(struct slab_info **list, struct slab_stat *stats,
- FILE *f)
+static int parse_slabinfo11(struct procps_slabinfo *slabinfo, FILE *f)
{
- struct slab_info *curr = NULL, *prev = NULL;
+ struct slab_node *curr = NULL, *prev = NULL;
char buffer[SLABINFO_LINE_LEN];
int entries = 0;
int page_size = getpagesize();
- stats->min_obj_size = INT_MAX;
- stats->max_obj_size = 0;
+ slabinfo->min_obj_size = INT_MAX;
+ slabinfo->max_obj_size = 0;
while (fgets(buffer, SLABINFO_LINE_LEN, f)) {
int assigned;
- curr = get_slabnode();
+ curr = get_slabnode(slabinfo);
if (!curr)
break;
if (entries++ == 0)
- *list = curr;
+ slabinfo->slab_list = curr;
else
if (prev)
prev->next = curr;
@@ -249,16 +281,16 @@ static int parse_slabinfo11(struct slab_info **list, struct slab_stat *stats,
break;
}
- if (curr->obj_size < stats->min_obj_size)
- stats->min_obj_size = curr->obj_size;
- if (curr->obj_size > stats->max_obj_size)
- stats->max_obj_size = curr->obj_size;
+ if (curr->obj_size < slabinfo->min_obj_size)
+ slabinfo->min_obj_size = curr->obj_size;
+ if (curr->obj_size > slabinfo->max_obj_size)
+ slabinfo->max_obj_size = curr->obj_size;
curr->cache_size = (unsigned long)curr->nr_slabs * curr->pages_per_slab * page_size;
if (curr->nr_objs) {
curr->use = 100 * curr->nr_active_objs / curr->nr_objs;
- stats->nr_active_caches++;
+ slabinfo->nr_active_caches++;
} else
curr->use = 0;
@@ -266,26 +298,26 @@ static int parse_slabinfo11(struct slab_info **list, struct slab_stat *stats,
curr->objs_per_slab = curr->pages_per_slab *
page_size / curr->obj_size;
- stats->nr_objs += curr->nr_objs;
- stats->nr_active_objs += curr->nr_active_objs;
- stats->total_size += (unsigned long)curr->nr_objs * curr->obj_size;
- stats->active_size += (unsigned long)curr->nr_active_objs * curr->obj_size;
- stats->nr_pages += curr->nr_slabs * curr->pages_per_slab;
- stats->nr_slabs += curr->nr_slabs;
- stats->nr_active_slabs += curr->nr_active_slabs;
+ slabinfo->nr_objs += curr->nr_objs;
+ slabinfo->nr_active_objs += curr->nr_active_objs;
+ slabinfo->total_size += (unsigned long)curr->nr_objs * curr->obj_size;
+ slabinfo->active_size += (unsigned long)curr->nr_active_objs * curr->obj_size;
+ slabinfo->nr_pages += curr->nr_slabs * curr->pages_per_slab;
+ slabinfo->nr_slabs += curr->nr_slabs;
+ slabinfo->nr_active_slabs += curr->nr_active_slabs;
prev = curr;
}
if (!curr) {
fprintf(stderr, "\rerror reading slabinfo!\n");
- return 1;
+ return -1;
}
curr->next = NULL;
- stats->nr_caches = entries;
- if (stats->nr_objs)
- stats->avg_obj_size = stats->total_size / stats->nr_objs;
+ slabinfo->nr_caches = entries;
+ if (slabinfo->nr_objs)
+ slabinfo->avg_obj_size = slabinfo->total_size / slabinfo->nr_objs;
return 0;
}
@@ -295,56 +327,59 @@ static int parse_slabinfo11(struct slab_info **list, struct slab_stat *stats,
*
* Not yet implemented. Please feel free.
*/
-static int parse_slabinfo10(struct slab_info **list, struct slab_stat *stats,
- FILE *f)
+static int parse_slabinfo10(struct procps_slabinfo *slabinfo, FILE *f)
{
- (void) list, (void) stats, (void) f;
fprintf(stderr, "slabinfo version 1.0 not yet supported\n");
- return 1;
+ return -1;
}
/*
- * slabinfo - parse the system's slabinfo and fill out both a linked list of
- * slab_info structures and the slab_stat structure
+ * procps_slabinfo_read:
+ * @slabinfo: structure to place data into
+ * @filename: optional filename instead of system default to read slab stats
*
- * The function returns zero on success, in which case 'list' and 'stats' are
- * valid. Nonzero is returned on failure and the state of 'list' and 'stats'
- * are undefined.
+ * The function returns zero on success
*/
-int get_slabinfo(struct slab_info **list, struct slab_stat *stats)
+int procps_slabinfo_read(struct procps_slabinfo *slabinfo, const char *filename)
{
FILE *slabfile;
char buffer[SLABINFO_VER_LEN];
int major, minor, ret = 0;
- slabfile = fopen(SLABINFO_FILE, "r");
- if (!slabfile) {
- perror("fopen " SLABINFO_FILE);
- return 1;
+ if (filename == NULL) {
+ slabfile = fopen(SLABINFO_FILE, "r");
+ if (!slabfile) {
+ return -errno;
+ }
+ } else {
+ slabfile = fopen(filename, "r");
+ if (!slabfile) {
+ return -errno;
+ }
}
if (!fgets(buffer, SLABINFO_VER_LEN, slabfile)) {
fprintf(stderr, "cannot read from slabinfo\n");
fclose(slabfile);
- return 1;
+ return -1;
}
if (sscanf(buffer, "slabinfo - version: %d.%d", &major, &minor) != 2) {
fprintf(stderr, "not the good old slabinfo we know\n");
fclose(slabfile);
- return 1;
+ return -1;
}
if (major == 2)
- ret = parse_slabinfo20(list, stats, slabfile);
+ ret = parse_slabinfo20(slabinfo, slabfile);
else if (major == 1 && minor == 1)
- ret = parse_slabinfo11(list, stats, slabfile);
+ ret = parse_slabinfo11(slabinfo, slabfile);
else if (major == 1 && minor == 0)
- ret = parse_slabinfo10(list, stats, slabfile);
+ ret = parse_slabinfo10(slabinfo, slabfile);
else {
fprintf(stderr, "unrecognizable slabinfo version\n");
fclose(slabfile);
- return 1;
+ return -1;
}
fclose(slabfile);