slabtop: adapted to exploit new alloc & sort interface
In addition to the new interface several other changes were made. In fact, there are so many I must apologize in advance to Craig, et al. for the hatchet I wielded. Among the changes was my attempt to shrink the body of that main() function. It's amazing how some folks must always cram as code much as possible into ol' main(). Personally, unless it's a throwaway quick & dirty pgm, all main function bodies should not exceed one screen. Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
5c3542c4e1
commit
e044559527
433
slabtop.c
433
slabtop.c
@ -21,18 +21,18 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <locale.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <ncurses.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/ioctl.h>
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <ncurses.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -44,36 +44,58 @@
|
|||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
#include <proc/slab.h>
|
#include <proc/slab.h>
|
||||||
|
|
||||||
#define DEFAULT_SORT_ITEM PROCPS_SLABNODE_OBJS
|
#define DEFAULT_SORT PROCPS_SLABNODE_OBJS
|
||||||
|
#define CHAINS_ALLOC 150
|
||||||
|
|
||||||
|
static unsigned short Cols, Rows;
|
||||||
|
static struct termios Saved_tty;
|
||||||
|
static long Delay = 3;
|
||||||
|
static int Run_once = 0;
|
||||||
|
|
||||||
|
static struct procps_slabinfo *Slab_info;
|
||||||
|
|
||||||
|
enum slabnode_item Sort_item = DEFAULT_SORT;
|
||||||
|
|
||||||
|
enum slabnode_item Node_items[] = {
|
||||||
|
PROCPS_SLABNODE_OBJS, PROCPS_SLABNODE_AOBJS, PROCPS_SLABNODE_USE,
|
||||||
|
PROCPS_SLABNODE_OBJ_SIZE, PROCPS_SLABNODE_SLABS, PROCPS_SLABNODE_OBJS_PER_SLAB,
|
||||||
|
PROCPS_SLABNODE_SIZE, PROCPS_SLABNODE_NAME,
|
||||||
|
/* last 2 are sortable but are not displayable,
|
||||||
|
thus they need not be represented in the Relative_enums */
|
||||||
|
PROCPS_SLABNODE_PAGES_PER_SLAB,
|
||||||
|
PROCPS_SLABNODE_ASLABS };
|
||||||
|
|
||||||
|
enum Relative_enums {
|
||||||
|
my_OBJS, my_AOBJS, my_USE, my_OSIZE,
|
||||||
|
my_SLABS, my_OPS, my_SIZE, my_NAME };
|
||||||
|
|
||||||
|
#define MAX_ITEMS (int)(sizeof(Node_items) / sizeof(Node_items[0]))
|
||||||
|
|
||||||
|
#define PRINT_line(fmt, ...) if (Run_once) printf(fmt, __VA_ARGS__); else printw(fmt, __VA_ARGS__)
|
||||||
|
|
||||||
static unsigned short cols, rows;
|
|
||||||
static struct termios saved_tty;
|
|
||||||
static long delay = 3;
|
|
||||||
static int run_once = 0;
|
|
||||||
|
|
||||||
#define print_line(fmt, ...) if (run_once) printf(fmt, __VA_ARGS__); else printw(fmt, __VA_ARGS__)
|
|
||||||
/*
|
/*
|
||||||
* term_size - set the globals 'cols' and 'rows' to the current terminal size
|
* term_resize - set the globals 'Cols' and 'Rows' to the current terminal size
|
||||||
*/
|
*/
|
||||||
static void term_size(int unusused __attribute__ ((__unused__)))
|
static void term_resize (int unusused __attribute__ ((__unused__)))
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
|
|
||||||
if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) && ws.ws_row > 10) {
|
if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) && ws.ws_row > 10) {
|
||||||
cols = ws.ws_col;
|
Cols = ws.ws_col;
|
||||||
rows = ws.ws_row;
|
Rows = ws.ws_row;
|
||||||
} else {
|
} else {
|
||||||
cols = 80;
|
Cols = 80;
|
||||||
rows = 24;
|
Rows = 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sigint_handler(int unused __attribute__ ((__unused__)))
|
static void sigint_handler (int unused __attribute__ ((__unused__)))
|
||||||
{
|
{
|
||||||
delay = 0;
|
Delay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((__noreturn__)) usage(FILE *out)
|
static void __attribute__((__noreturn__)) usage (FILE *out)
|
||||||
{
|
{
|
||||||
fputs(USAGE_HEADER, out);
|
fputs(USAGE_HEADER, out);
|
||||||
fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
|
fprintf(out, _(" %s [options]\n"), program_invocation_short_name);
|
||||||
@ -90,10 +112,10 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
|
|||||||
fputs(_(" b: sort by objects per slab\n"), out);
|
fputs(_(" b: sort by objects per slab\n"), out);
|
||||||
fputs(_(" c: sort by cache size\n"), out);
|
fputs(_(" c: sort by cache size\n"), out);
|
||||||
fputs(_(" l: sort by number of slabs\n"), out);
|
fputs(_(" l: sort by number of slabs\n"), out);
|
||||||
fputs(_(" v: sort by number of active slabs\n"), out);
|
fputs(_(" v: sort by (non display) number of active slabs\n"), out);
|
||||||
fputs(_(" n: sort by name\n"), out);
|
fputs(_(" n: sort by name\n"), out);
|
||||||
fputs(_(" o: sort by number of objects (the default)\n"), out);
|
fputs(_(" o: sort by number of objects (the default)\n"), out);
|
||||||
fputs(_(" p: sort by pages per slab\n"), out);
|
fputs(_(" p: sort by (non display) pages per slab\n"), out);
|
||||||
fputs(_(" s: sort by object size\n"), out);
|
fputs(_(" s: sort by object size\n"), out);
|
||||||
fputs(_(" u: sort by cache utilization\n"), out);
|
fputs(_(" u: sort by cache utilization\n"), out);
|
||||||
fprintf(out, USAGE_MAN_TAIL("slabtop(1)"));
|
fprintf(out, USAGE_MAN_TAIL("slabtop(1)"));
|
||||||
@ -103,11 +125,10 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* set_sort_func - return the slab_sort_func that matches the given key.
|
* set_sort_func - return the slab_sort_func that matches the given key.
|
||||||
* On unrecognizable key, DEF_SORT_FUNC is returned.
|
* On unrecognizable key, DEFAULT_SORT is returned.
|
||||||
*/
|
*/
|
||||||
static enum procps_slabinfo_nodeitem get_sort_item(
|
static enum slabnode_item set_sort_item (
|
||||||
const char key,
|
const char key)
|
||||||
enum procps_slabinfo_nodeitem old_sort)
|
|
||||||
{
|
{
|
||||||
switch (tolower(key)) {
|
switch (tolower(key)) {
|
||||||
case 'n':
|
case 'n':
|
||||||
@ -117,7 +138,7 @@ static enum procps_slabinfo_nodeitem get_sort_item(
|
|||||||
case 'a':
|
case 'a':
|
||||||
return PROCPS_SLABNODE_AOBJS;
|
return PROCPS_SLABNODE_AOBJS;
|
||||||
case 's':
|
case 's':
|
||||||
return PROCPS_SLABNODE_SIZE;
|
return PROCPS_SLABNODE_OBJ_SIZE;
|
||||||
case 'b':
|
case 'b':
|
||||||
return PROCPS_SLABNODE_OBJS_PER_SLAB;
|
return PROCPS_SLABNODE_OBJS_PER_SLAB;
|
||||||
case 'p':
|
case 'p':
|
||||||
@ -131,111 +152,136 @@ static enum procps_slabinfo_nodeitem get_sort_item(
|
|||||||
case 'u':
|
case 'u':
|
||||||
return PROCPS_SLABNODE_USE;
|
return PROCPS_SLABNODE_USE;
|
||||||
default:
|
default:
|
||||||
return old_sort;
|
return DEFAULT_SORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static void parse_opts (int argc, char **argv)
|
||||||
case 'Q':
|
|
||||||
delay = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void print_stats(struct procps_slabinfo *info)
|
|
||||||
{
|
{
|
||||||
#define STAT_VAL(e) stats[e].result
|
static const struct option longopts[] = {
|
||||||
enum stat_enums {
|
{ "delay", required_argument, NULL, 'd' },
|
||||||
|
{ "sort", required_argument, NULL, 's' },
|
||||||
|
{ "once", no_argument, NULL, 'o' },
|
||||||
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
{ "version", no_argument, NULL, 'V' },
|
||||||
|
{ NULL, 0, NULL, 0 }};
|
||||||
|
int o;
|
||||||
|
|
||||||
|
while ((o = getopt_long(argc, argv, "d:s:ohV", longopts, NULL)) != -1) {
|
||||||
|
switch (o) {
|
||||||
|
case 'd':
|
||||||
|
errno = 0;
|
||||||
|
Delay = strtol_or_err(optarg, _("illegal delay"));
|
||||||
|
if (Delay < 1)
|
||||||
|
xerrx(EXIT_FAILURE, _("delay must be positive integer"));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
Sort_item = set_sort_item(optarg[0]);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
Run_once=1;
|
||||||
|
Delay = 0;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
printf(PROCPS_NG_VERSION);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case 'h':
|
||||||
|
usage(stdout);
|
||||||
|
default:
|
||||||
|
usage(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_summary (void)
|
||||||
|
{
|
||||||
|
#define STAT_VAL(e) (int)stats[e].result
|
||||||
|
enum slabs_enums {
|
||||||
stat_AOBJS, stat_OBJS, stat_ASLABS, stat_SLABS,
|
stat_AOBJS, stat_OBJS, stat_ASLABS, stat_SLABS,
|
||||||
stat_ACACHES, stat_CACHES, stat_ACTIVE, stat_TOTAL,
|
stat_ACACHES, stat_CACHES, stat_ACTIVE, stat_TOTAL,
|
||||||
stat_MIN, stat_AVG, stat_MAX,
|
stat_MIN, stat_AVG, stat_MAX,
|
||||||
};
|
};
|
||||||
static struct procps_slabinfo_result stats[] = {
|
static struct slabs_result stats[] = {
|
||||||
{ PROCPS_SLABINFO_AOBJS, 0, &stats[1] },
|
{ PROCPS_SLABS_AOBJS, 0, &stats[1] },
|
||||||
{ PROCPS_SLABINFO_OBJS, 0, &stats[2] },
|
{ PROCPS_SLABS_OBJS, 0, &stats[2] },
|
||||||
{ PROCPS_SLABINFO_ASLABS, 0, &stats[3] },
|
{ PROCPS_SLABS_ASLABS, 0, &stats[3] },
|
||||||
{ PROCPS_SLABINFO_SLABS, 0, &stats[4] },
|
{ PROCPS_SLABS_SLABS, 0, &stats[4] },
|
||||||
{ PROCPS_SLABINFO_ACACHES, 0, &stats[5] },
|
{ PROCPS_SLABS_ACACHES, 0, &stats[5] },
|
||||||
{ PROCPS_SLABINFO_CACHES, 0, &stats[6] },
|
{ PROCPS_SLABS_CACHES, 0, &stats[6] },
|
||||||
{ PROCPS_SLABINFO_SIZE_ACTIVE, 0, &stats[7] },
|
{ PROCPS_SLABS_SIZE_ACTIVE, 0, &stats[7] },
|
||||||
{ PROCPS_SLABINFO_SIZE_TOTAL, 0, &stats[8] },
|
{ PROCPS_SLABS_SIZE_TOTAL, 0, &stats[8] },
|
||||||
{ PROCPS_SLABINFO_SIZE_MIN, 0, &stats[9] },
|
{ PROCPS_SLABS_SIZE_MIN, 0, &stats[9] },
|
||||||
{ PROCPS_SLABINFO_SIZE_AVG, 0, &stats[10] },
|
{ PROCPS_SLABS_SIZE_AVG, 0, &stats[10] },
|
||||||
{ PROCPS_SLABINFO_SIZE_MAX, 0, NULL },
|
{ PROCPS_SLABS_SIZE_MAX, 0, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (procps_slabinfo_stat_getchain(info, stats) < 0)
|
if (procps_slabs_getchain(Slab_info, stats) < 0) \
|
||||||
xerrx(EXIT_FAILURE,
|
xerrx(EXIT_FAILURE, _("Error getting slab summary results"));
|
||||||
_("Error getting slabinfo results"));
|
|
||||||
|
|
||||||
print_line(" %-35s: %d / %d (%.1f%%)\n"
|
PRINT_line(" %-35s: %d / %d (%.1f%%)\n"
|
||||||
" %-35s: %d / %d (%.1f%%)\n"
|
, /* Translation Hint: Next five strings must not
|
||||||
" %-35s: %d / %d (%.1f%%)\n"
|
* exceed a length of 35 characters. */
|
||||||
" %-35s: %.2fK / %.2fK (%.1f%%)\n"
|
/* xgettext:no-c-format */
|
||||||
" %-35s: %.2fK / %.2fK / %.2fK\n\n",
|
_("Active / Total Objects (% used)")
|
||||||
/* Translation Hint: Next five strings must not
|
, STAT_VAL(stat_AOBJS)
|
||||||
* exceed 35 length in characters. */
|
, STAT_VAL(stat_OBJS)
|
||||||
/* xgettext:no-c-format */
|
, 100.0 * STAT_VAL(stat_AOBJS) / STAT_VAL(stat_OBJS));
|
||||||
_("Active / Total Objects (% used)"),
|
PRINT_line(" %-35s: %d / %d (%.1f%%)\n"
|
||||||
STAT_VAL(stat_AOBJS), STAT_VAL(stat_OBJS),
|
, /* xgettext:no-c-format */
|
||||||
100.0 * STAT_VAL(stat_AOBJS) / STAT_VAL(stat_OBJS),
|
_("Active / Total Slabs (% used)")
|
||||||
/* xgettext:no-c-format */
|
, STAT_VAL(stat_ASLABS)
|
||||||
_("Active / Total Slabs (% used)"),
|
, STAT_VAL(stat_SLABS)
|
||||||
STAT_VAL(stat_ASLABS), STAT_VAL(stat_SLABS),
|
, 100.0 * STAT_VAL(stat_ASLABS) / STAT_VAL(stat_SLABS));
|
||||||
100.0 * STAT_VAL(stat_ASLABS) / STAT_VAL(stat_SLABS),
|
PRINT_line(" %-35s: %d / %d (%.1f%%)\n"
|
||||||
/* xgettext:no-c-format */
|
, /* xgettext:no-c-format */
|
||||||
_("Active / Total Caches (% used)"),
|
_("Active / Total Caches (% used)")
|
||||||
STAT_VAL(stat_ACACHES), STAT_VAL(stat_CACHES),
|
, STAT_VAL(stat_ACACHES)
|
||||||
100.0 * STAT_VAL(stat_ACACHES) / STAT_VAL(stat_CACHES),
|
, STAT_VAL(stat_CACHES)
|
||||||
/* xgettext:no-c-format */
|
, 100.0 * STAT_VAL(stat_ACACHES) / STAT_VAL(stat_CACHES));
|
||||||
_("Active / Total Size (% used)"),
|
PRINT_line(" %-35s: %.2fK / %.2fK (%.1f%%)\n"
|
||||||
STAT_VAL(stat_ACTIVE) / 1024.0 , STAT_VAL(stat_TOTAL) / 1024.0,
|
, /* xgettext:no-c-format */
|
||||||
100.0 * STAT_VAL(stat_ACTIVE) / STAT_VAL(stat_TOTAL),
|
_("Active / Total Size (% used)")
|
||||||
_("Minimum / Average / Maximum Object"),
|
, STAT_VAL(stat_ACTIVE) / 1024.0
|
||||||
STAT_VAL(stat_MIN) / 1024.0, STAT_VAL(stat_AVG) / 1024.0,
|
, STAT_VAL(stat_TOTAL) / 1024.0
|
||||||
STAT_VAL(stat_MAX) / 1024.0);
|
, 100.0 * STAT_VAL(stat_ACTIVE) / STAT_VAL(stat_TOTAL));
|
||||||
#undef STAT_VAL
|
PRINT_line(" %-35s: %.2fK / %.2fK / %.2fK\n\n"
|
||||||
|
, _("Minimum / Average / Maximum Object")
|
||||||
|
, STAT_VAL(stat_MIN) / 1024.0
|
||||||
|
, STAT_VAL(stat_AVG) / 1024.0
|
||||||
|
, STAT_VAL(stat_MAX) / 1024.0);
|
||||||
|
#undef STAT_VAL
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(const int is_tty, struct procps_slabinfo **slab_info)
|
static void print_headings (void)
|
||||||
{
|
{
|
||||||
if (is_tty)
|
/* Translation Hint: Please keep alignment of the
|
||||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_tty);
|
* following intact. */
|
||||||
if (!run_once)
|
PRINT_line("%-78s\n", _(" OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME"));
|
||||||
endwin();
|
|
||||||
procps_slabinfo_unref(slab_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_details (struct slabnode_chain *chain)
|
||||||
|
{
|
||||||
|
#define my_NUM(c,e) (unsigned)c->head[e].result.num
|
||||||
|
#define my_STR(c,e) c->head[e].result.str
|
||||||
|
|
||||||
|
PRINT_line("%6u %6u %3u%% %7.2fK %6u %8u %9uK %-23s\n"
|
||||||
|
, my_NUM(chain, my_OBJS), my_NUM(chain, my_AOBJS)
|
||||||
|
, my_NUM(chain, my_USE), my_NUM(chain, my_OSIZE) / 1024.0
|
||||||
|
, my_NUM(chain, my_SLABS), my_NUM(chain, my_OPS)
|
||||||
|
, my_NUM(chain, my_SIZE) / 1024
|
||||||
|
, my_STR(chain, my_NAME));
|
||||||
|
|
||||||
|
return;
|
||||||
|
#undef my_NUM
|
||||||
|
#undef my_STR
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int is_tty, o;
|
int is_tty, nr_slabs, rc = EXIT_SUCCESS;
|
||||||
int nr_slabs;
|
|
||||||
unsigned short old_rows;
|
unsigned short old_rows;
|
||||||
int retval = EXIT_SUCCESS;
|
struct slabnode_chain **v;
|
||||||
struct procps_slabinfo *slab_info;
|
|
||||||
enum procps_slabinfo_nodeitem sort_item = DEFAULT_SORT_ITEM;
|
|
||||||
|
|
||||||
static const struct option longopts[] = {
|
|
||||||
{ "delay", required_argument, NULL, 'd' },
|
|
||||||
{ "sort", required_argument, NULL, 's' },
|
|
||||||
{ "once", no_argument, NULL, 'o' },
|
|
||||||
{ "help", no_argument, NULL, 'h' },
|
|
||||||
{ "version", no_argument, NULL, 'V' },
|
|
||||||
{ NULL, 0, NULL, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct procps_slabnode_result result[] = {
|
|
||||||
{ PROCPS_SLABNODE_OBJS, 0, &result[1] },
|
|
||||||
{ PROCPS_SLABNODE_AOBJS, 0, &result[2] },
|
|
||||||
{ PROCPS_SLABNODE_USE, 0, &result[3] },
|
|
||||||
{ PROCPS_SLABNODE_OBJ_SIZE, 0, &result[4] },
|
|
||||||
{ PROCPS_SLABNODE_SLABS, 0, &result[5] },
|
|
||||||
{ PROCPS_SLABNODE_OBJS_PER_SLAB, 0, &result[6] },
|
|
||||||
{ PROCPS_SLABNODE_SIZE, 0, NULL } };
|
|
||||||
enum result_enums {
|
|
||||||
stat_OBJS, stat_AOBJS, stat_USE, stat_OSIZE, stat_SLABS,
|
|
||||||
stat_OPS, stat_SIZE };
|
|
||||||
|
|
||||||
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
||||||
program_invocation_name = program_invocation_short_name;
|
program_invocation_name = program_invocation_short_name;
|
||||||
@ -245,121 +291,84 @@ int main(int argc, char *argv[])
|
|||||||
textdomain(PACKAGE);
|
textdomain(PACKAGE);
|
||||||
atexit(close_stdout);
|
atexit(close_stdout);
|
||||||
|
|
||||||
while ((o = getopt_long(argc, argv, "d:s:ohV", longopts, NULL)) != -1) {
|
parse_opts(argc, argv);
|
||||||
switch (o) {
|
|
||||||
case 'd':
|
|
||||||
errno = 0;
|
|
||||||
delay = strtol_or_err(optarg, _("illegal delay"));
|
|
||||||
if (delay < 1)
|
|
||||||
xerrx(EXIT_FAILURE,
|
|
||||||
_("delay must be positive integer"));
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
sort_item = get_sort_item(optarg[0], sort_item);
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
run_once=1;
|
|
||||||
delay = 0;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
printf(PROCPS_NG_VERSION);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
case 'h':
|
|
||||||
usage(stdout);
|
|
||||||
default:
|
|
||||||
usage(stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (procps_slabinfo_new(&slab_info) < 0)
|
if (procps_slabinfo_new(&Slab_info) < 0)
|
||||||
xerrx(EXIT_FAILURE,
|
xerrx(EXIT_FAILURE, _("Unable to create slabinfo structure"));
|
||||||
_("Unable to create slabinfo structure"));
|
|
||||||
|
|
||||||
|
if (!(v = procps_slabnode_chains_alloc(Slab_info, CHAINS_ALLOC, 0, MAX_ITEMS, Node_items)))
|
||||||
|
xerrx(EXIT_FAILURE, _("Unable to allocate slabinfo nodes"));
|
||||||
|
|
||||||
is_tty = isatty(STDIN_FILENO);
|
if (!Run_once) {
|
||||||
if (is_tty && tcgetattr(STDIN_FILENO, &saved_tty) == -1)
|
is_tty = isatty(STDIN_FILENO);
|
||||||
xwarn(_("terminal setting retrieval"));
|
if (is_tty && tcgetattr(STDIN_FILENO, &Saved_tty) == -1)
|
||||||
|
xwarn(_("terminal setting retrieval"));
|
||||||
old_rows = rows;
|
old_rows = Rows;
|
||||||
term_size(0);
|
term_resize(0);
|
||||||
if (!run_once) {
|
|
||||||
initscr();
|
initscr();
|
||||||
resizeterm(rows, cols);
|
resizeterm(Rows, Cols);
|
||||||
signal(SIGWINCH, term_size);
|
signal(SIGWINCH, term_resize);
|
||||||
|
signal(SIGINT, sigint_handler);
|
||||||
}
|
}
|
||||||
signal(SIGINT, sigint_handler);
|
|
||||||
|
|
||||||
#define STAT_VAL(e) result[e].result
|
|
||||||
do {
|
do {
|
||||||
char *slab_name;
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
char c;
|
int i;
|
||||||
int i, myerrno;
|
|
||||||
|
|
||||||
if (procps_slabinfo_read(slab_info) < 0) {
|
// this next guy also performs the procps_slabnode_read() call
|
||||||
xwarn(_("Unable to read slabinfo"));
|
if ((nr_slabs = procps_slabnode_chains_fill(Slab_info, v, CHAINS_ALLOC)) < 0) {
|
||||||
retval = EXIT_FAILURE;
|
xwarn(_("Unable to get slabinfo node data"));
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(v = procps_slabnode_chains_sort(Slab_info, v, nr_slabs, Sort_item))) {
|
||||||
|
xwarn(_("Unable to sort slab nodes"));
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!run_once && old_rows != rows) {
|
if (Run_once) {
|
||||||
resizeterm(rows, cols);
|
print_summary();
|
||||||
old_rows = rows;
|
print_headings();
|
||||||
|
for (i = 0; i < nr_slabs; i++)
|
||||||
|
print_details(v[i]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old_rows != Rows) {
|
||||||
|
resizeterm(Rows, Cols);
|
||||||
|
old_rows = Rows;
|
||||||
|
}
|
||||||
move(0, 0);
|
move(0, 0);
|
||||||
print_stats(slab_info);
|
print_summary();
|
||||||
|
|
||||||
if (procps_slabinfo_sort(slab_info, sort_item) < 0) {
|
|
||||||
xwarn(_("Unable to sort slabnodes"));
|
|
||||||
retval= EXIT_FAILURE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
attron(A_REVERSE);
|
attron(A_REVERSE);
|
||||||
/* Translation Hint: Please keep alignment of the
|
print_headings();
|
||||||
* following intact. */
|
|
||||||
print_line("%-78s\n", _(" OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME"));
|
|
||||||
attroff(A_REVERSE);
|
attroff(A_REVERSE);
|
||||||
|
|
||||||
if ((nr_slabs = procps_slabinfo_node_count(slab_info)) < 0) {
|
for (i = 0; i < Rows - 8 && i < nr_slabs; i++)
|
||||||
xwarn(_("Unable to count slabinfo nodes"));
|
print_details(v[i]);
|
||||||
retval = EXIT_FAILURE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0 ; i < rows - 8 && i < nr_slabs; i++) {
|
refresh();
|
||||||
if (procps_slabinfo_node_getchain(slab_info, result, i) < 0) {
|
FD_ZERO(&readfds);
|
||||||
xwarn(_("Unable to get slabinfo node data"));
|
FD_SET(STDIN_FILENO, &readfds);
|
||||||
retval = EXIT_FAILURE;
|
tv.tv_sec = Delay;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
if (select(STDOUT_FILENO, &readfds, NULL, NULL, &tv) > 0) {
|
||||||
|
char c;
|
||||||
|
if (read(STDIN_FILENO, &c, 1) != 1
|
||||||
|
|| (c == 'Q' || c == 'q'))
|
||||||
break;
|
break;
|
||||||
}
|
Sort_item = set_sort_item(c);
|
||||||
slab_name= procps_slabinfo_node_getname(slab_info, i);
|
|
||||||
print_line("%6u %6u %3u%% %7.2fK %6u %8u %9uK %-23s\n",
|
|
||||||
STAT_VAL(stat_OBJS), STAT_VAL(stat_AOBJS),
|
|
||||||
STAT_VAL(stat_USE),
|
|
||||||
STAT_VAL(stat_OSIZE) / 1024.0, STAT_VAL(stat_SLABS),
|
|
||||||
STAT_VAL(stat_OPS),
|
|
||||||
(unsigned)(STAT_VAL(stat_SIZE) / 1024),
|
|
||||||
slab_name?slab_name:"(unknown)");
|
|
||||||
}
|
}
|
||||||
if (!run_once) {
|
// made zero by sigint_handler()
|
||||||
refresh();
|
} while (Delay);
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_SET(STDIN_FILENO, &readfds);
|
|
||||||
tv.tv_sec = delay;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
if (select(STDOUT_FILENO, &readfds, NULL, NULL, &tv) > 0) {
|
|
||||||
if (read(STDIN_FILENO, &c, 1) != 1)
|
|
||||||
break;
|
|
||||||
if (c == 'Q' || c == 'q')
|
|
||||||
delay = 0;
|
|
||||||
else
|
|
||||||
sort_item = get_sort_item(c, sort_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (delay);
|
|
||||||
cleanup(is_tty, &slab_info);
|
|
||||||
|
|
||||||
|
if (!Run_once) {
|
||||||
|
if (is_tty)
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &Saved_tty);
|
||||||
|
endwin();
|
||||||
|
}
|
||||||
|
procps_slabinfo_unref(&Slab_info);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user