diff --git a/lmon16d.c b/lmon16d.c deleted file mode 100644 index 36270d1..0000000 --- a/lmon16d.c +++ /dev/null @@ -1,8554 +0,0 @@ -/* - * lmon.c -- Curses based Performance Monitor for Linux - * with saving performance stats to a CSV file mode. - * Developer: Nigel Griffiths. - */ - -/* - * Use the following Makefile (for Linux on POWER) -CFLAGS=-g -D JFS -D GETUSER -Wall -D LARGEMEM -D POWER -D KERNEL_2_6_18lmon15ibeta10.c -LDFLAGS=-lcurses -lm -nmon: lmon.o - * end of Makefile - */ -/* Other #ifdef's for specific features or platforms -Platforms: POWER MAINFRAME X86 - only one of these at a time -Specific Linux versions: RHEL7 SLES113 SLES12 -Specific feature: NVIDIA_GPU -Bug / missing feature workarounds: - REREAD - for RHEL3 - LSBLK_NO_TYPE - SLES11.3 has not lsblk disk TYPE option - -Options which should always but switched on: -GETUSER - U optio to load user details -JFS - include FileSystem stats (most of which are now Journeled) -LARGMEM - most Linux's do not have older LOW and High Memory memory -KERNEL_2_6_18 1 kernel level and above adds the following to the disk stats - pi_num_threads, - pi_rt_priority, - pi_policy, - pi_delayacct_blkio_ticks -*/ - -/* note: RAW assumes you are using the index "i" to select the CPU */ -#define RAW(member) (long)((long)(p->cpuN[i].member) - (long)(q->cpuN[i].member)) -#define RAWTOTAL(member) (long)((long)(p->cpu_total.member) - (long)(q->cpu_total.member)) - -#define VERSION "16d" -char version[] = VERSION; -static char *SccsId = "nmon " VERSION; - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Windows moved here so they can be cleared when the screen mode changes */ -WINDOW *padwelcome = NULL; -WINDOW *padtop = NULL; -WINDOW *padmem = NULL; -WINDOW *padlarge = NULL; -WINDOW *padpage = NULL; -WINDOW *padker = NULL; -WINDOW *padnet = NULL; -WINDOW *padneterr = NULL; -WINDOW *padnfs = NULL; -WINDOW *padres = NULL; -WINDOW *padsmp = NULL; -WINDOW *padutil = NULL; -WINDOW *padwide = NULL; -WINDOW *padgpu = NULL; -WINDOW *padmhz = NULL; -WINDOW *padlong = NULL; -WINDOW *paddisk = NULL; -WINDOW *paddg = NULL; -WINDOW *padmap = NULL; -WINDOW *padjfs = NULL; -#ifdef POWER -WINDOW *padlpar = NULL; -#endif -WINDOW *padverb = NULL; -WINDOW *padhelp = NULL; - - -/* for Disk Busy rain style output covering 100's of diskss on one screen */ -const char disk_busy_map_ch[] = - "_____.....----------++++++++++oooooooooo0000000000OOOOOOOOOO8888888888XXXXXXXXXX##########@@@@@@@@@@*"; -/*"00000555551111111111222222222233333333334444444444555555555566666666667777777777888888888899999999991"*/ - -int extended_disk = 0; /* report additional data from /proc/diskstats to spreadsheet output */ - -#define FLIP(variable) if(variable) variable=0; else variable=1; - -#ifdef MALLOC_DEBUG -#define MALLOC(argument) mymalloc(argument,__LINE__) -#define FREE(argument) myfree(argument,__LINE__) -#define REALLOC(argument1,argument2) myrealloc(argument1,argument2,__LINE__) -void *mymalloc(int size, int line) -{ - void *ptr; - ptr = malloc(size); - fprintf(stderr, "0x%x = malloc(%d) at line=%d\n", ptr, size, line); - return ptr; -} - -void myfree(void *ptr, int line) -{ - fprintf(stderr, "free(0x%x) at line=%d\n", ptr, line); - free(ptr); -} - -void *myrealloc(void *oldptr, int size, int line) -{ - void *ptr; - ptr = realloc(oldptr, size); - fprintf(stderr, "0x%x = realloc(0x%x, %d) at line=%d\n", ptr, oldptr, - size, line); - return ptr; -} -#else -#define MALLOC(argument) malloc(argument) -#define FREE(argument) free(argument) -#define REALLOC(argument1,argument2) realloc(argument1,argument2) -#endif /* MALLOC STUFF */ - -#ifdef NVIDIA_GPU -typedef int nvmlReturn_t; -#define NVML_SUCCESS 0 - -typedef struct nvmlUtilization_st { - unsigned int gpu; - unsigned int memory; -} nvmlUtilization_t; - -struct nvmlDevice_st; -typedef struct nvmlDevice_st *nvmlDevice_t; - -nvmlReturn_t nvmlInit(void); -nvmlReturn_t nvmlShutdown(void); -nvmlReturn_t nvmlDeviceGetCount(unsigned int *count); -nvmlReturn_t nvmlDeviceGetHandleByIndex(unsigned int index, - nvmlDevice_t * device); -nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, - nvmlUtilization_t * - utilization); -nvmlReturn_t nvmlSystemGetDriverVersion(char *version, int count); -nvmlReturn_t nvmlSystemGetNVMLVersion(char *version, int count); -nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, int count); -nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, int type, - unsigned int *temp); -nvmlReturn_t nvmlDeviceGetPowerUsage(nvmlDevice_t device, - unsigned int *watts); -nvmlReturn_t nvmlDeviceGetClockInfo(nvmlDevice_t device, int type, - unsigned int *mhz); - -#define NVML_TEMPERATURE_GPU 0 -#define NVML_CLOCK_GRAPHICS 0 - -nvmlDevice_t gpu_device[4]; -nvmlUtilization_t gpu_util[4]; -unsigned int gpu_devices; -char gpu_name[4][1024]; -unsigned int gpu_temp[4]; -unsigned int gpu_watts[4]; -unsigned int gpu_clock[4]; -char gpu_driver_version[1024]; -char gpu_nvml_version[1024]; -int first_time_gpu = 1; - -void gpu_init() -{ - int i; - nvmlReturn_t nvres; - if ((nvres = nvmlInit()) != NVML_SUCCESS) { - printf("nvmlInit failed %d\n", nvres); - return; - } - - if ((nvres = - nvmlSystemGetDriverVersion(&gpu_driver_version[0], - 1024)) != NVML_SUCCESS) { - printf("nvmlSystemGetDriverVersion failed %d\n", nvres); - return; - } - if ((nvres = - nvmlSystemGetNVMLVersion(&gpu_nvml_version[0], - 1024)) != NVML_SUCCESS) { - printf("nvmlSystemGetDriverVersion failed %d\n", nvres); - return; - } - - if ((nvres = nvmlDeviceGetCount(&gpu_devices)) != NVML_SUCCESS) { - printf("nvmlDeviceGetCount failed %d\n", nvres); - return; - } - if (gpu_devices > 4) - gpu_devices = 4; - - for (i = 0; i < gpu_devices; i++) { - if (nvmlDeviceGetHandleByIndex(i, &gpu_device[i]) != NVML_SUCCESS) { - printf("nvmlDeviceGetHandleByIndex(%d) failed %d\n", i, nvres); - return; - } - } -} -#endif /* NVIDIA_GPU */ - -#define P_CPUINFO 0 -#define P_STAT 1 -#define P_VERSION 2 -#define P_MEMINFO 3 -#define P_UPTIME 4 -#define P_LOADAVG 5 -#define P_NFS 6 -#define P_NFSD 7 -#define P_VMSTAT 8 /* new in 13h */ -#define P_NUMBER 9 /* one more than the max */ - -char *month[12] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", - "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" -}; - -/* Cut of everything after the first space in callback - * Delete any '&' just before the space - */ -char *check_call_string(char *callback, const char *name) -{ - char *tmp_ptr = callback; - - if (strlen(callback) > 256) { - fprintf(stderr, "ERROR nmon: ignoring %s - too long\n", name); - return (char *) NULL; - } - - for (; *tmp_ptr != '\0' && *tmp_ptr != ' ' && *tmp_ptr != '&'; - ++tmp_ptr); - - *tmp_ptr = '\0'; - - if (tmp_ptr == callback) - return (char *) NULL; - else - return callback; -} - -/* Remove error output to this buffer and display it if NMONDEBUG=1 */ -char errorstr[70]; -int error_on = 0; -void error(char *err) -{ - strncpy(errorstr, err, 69); -} - -/* - * lscpu command output save -*/ -/* lscpu -x86 Ubuntu 15.04 -nag@violet:~$ lscpu -Architecture: x86_64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 8 -On-line CPU(s) list: 0-7 -Thread(s) per core: 1 -Core(s) per socket: 2 -Socket(s): 4 -NUMA node(s): 1 -Vendor ID: GenuineIntel -CPU family: 15 -Model: 6 -Model name: Genuine Intel(R) CPU 3.33GHz -Stepping: 8 -CPU MHz: 3336.183 -BogoMIPS: 6672.64 -Virtualisation: VT-x -L1d cache: 16K -L2 cache: 1024K -L3 cache: 16384K -NUMA node0 CPU(s): 0-7 - -x86 Ubuntu 14.10 -nag@ultraviolet:~$ lscpu -Architecture: x86_64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Little Endian -CPU(s): 12 -On-line CPU(s) list: 0-11 -Thread(s) per core: 2 -Core(s) per socket: 6 -Socket(s): 1 -NUMA node(s): 1 -Vendor ID: GenuineIntel -CPU family: 6 -Model: 44 -Model name: Intel(R) Xeon(R) CPU E5645 @ 2.40GHz -Stepping: 2 -CPU MHz: 2394.000 -CPU max MHz: 2394.0000 -CPU min MHz: 1596.0000 -BogoMIPS: 4800.36 -Virtualization: VT-x -L1d cache: 32K -L1i cache: 32K -L2 cache: 256K -L3 cache: 12288K -NUMA node0 CPU(s): 0-11 - -POWER PowerKVM host SMT=off fout POWER8 with 5 cores each -[root@lemon ~]# lscpu -Architecture: ppc64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Big Endian -CPU(s): 160 -On-line CPU(s) list: 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152 -Off-line CPU(s) list: 1-7,9-15,17-23,25-31,33-39,41-47,49-55,57-63,65-71,73-79,81-87,89-95,97-103,105-111,113-119,121-127,129-135,137-143,145-151,153-159 -Thread(s) per core: 1 -Core(s) per socket: 5 -Socket(s): 4 -NUMA node(s): 4 -Model: 8247-22L -CPU max MHz: 3690.0000 -CPU min MHz: 2061.0000 -L1d cache: 64K -L1i cache: 32K -L2 cache: 512K -L3 cache: 8192K -NUMA node0 CPU(s): 0,8,16,24,32 -NUMA node1 CPU(s): 40,48,56,64,72 -NUMA node16 CPU(s): 80,88,96,104,112 -NUMA node17 CPU(s): 120,128,136,144,152 - -POWER8 S812LC single 10 core POWER SMT=8 Ubuntu 14.04.03 -user1@maroon:~$ lscpu -Architecture: ppc64le -Byte Order: Little Endian -CPU(s): 80 -On-line CPU(s) list: 0-79 -Thread(s) per core: 8 -Core(s) per socket: 10 -Socket(s): 1 -NUMA node(s): 1 -Model: 8348-21C -L1d cache: 64K -L1i cache: 32K -L2 cache: 512K -L3 cache: 8192K -NUMA node0 CPU(s): 0-79 - -POWER8 S824 four POWER8 with 8 cores each SMT=8 RHEL 7.1 BE -[root@vm17 ~]# lscpu -Architecture: ppc64 -CPU op-mode(s): 32-bit, 64-bit -Byte Order: Big Endian -CPU(s): 32 -On-line CPU(s) list: 0-31 -Thread(s) per core: 8 -Core(s) per socket: 1 -Socket(s): 4 -NUMA node(s): 3 -Model: IBM,8286-42A -L1d cache: 64K -L1i cache: 32K -NUMA node0 CPU(s): 0-31 -NUMA node2 CPU(s): -NUMA node3 CPU(s): - -POWER8 SLES 11.3 S822A CPU count is WRONG! -vm20:~ # lscpu -Architecture: ppc64 -Byte Order: Big Endian -CPU(s): 64 -On-line CPU(s) list: 0-31 -Off-line CPU(s) list: 32-63 -Thread(s) per core: 8 -Core(s) per socket: 1 -Socket(s): 4 -NUMA node(s): 2 -Model: IBM,8284-22A -Hypervisor vendor: pHyp -Virtualization type: full -L1d cache: 64K -L1i cache: 32K -NUMA node0 CPU(s): 0-31 -NUMA node1 CPU(s): -*/ -int lscpu_available = 0; - -struct { - char *arch; - char *byte_order; -#define ORDER_UNKNOWN 0 -#define ORDER_LITTLE 1 -#define ORDER_BIG 2 - int order; - int cpus; - char *cpu_online; - char *cpu_offline; - int threads; - int cores; - int sockets; - int numa_nodes; - char *model; - char *model_name; - int mhz; - int mhz_min; - int mhz_max; -} lscpu; - -void lscpu_init() -{ - FILE *pop; - int i; -#define LSCPU_STRLEN 256 -#define NUMBER_COL 23 - char tmpstr[LSCPU_STRLEN + 1]; - - if (lscpu_available == 1) - return; - pop = popen("/usr/bin/lscpu 2>/dev/null", "r"); - if (pop != NULL) { - lscpu_available = 1; - tmpstr[0] = 0; - for (i = 0;; i++) { - if (fgets(tmpstr, LSCPU_STRLEN, pop) == NULL) - break; - tmpstr[strlen(tmpstr) - 1] = 0; /* remove newline */ - if (strncmp("Architecture:", tmpstr, strlen("Architecture:")) - == 0) { - lscpu.arch = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); - strcpy(lscpu.arch, &tmpstr[NUMBER_COL]); - } - if (strncmp("Byte Order:", tmpstr, strlen("Byte Order:")) == 0) { - lscpu.byte_order = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); - strcpy(lscpu.byte_order, &tmpstr[NUMBER_COL]); - if (strncmp - ("Little Endian", lscpu.byte_order, - strlen("Little Endian")) == 0) { - lscpu.order = ORDER_LITTLE; - } - if (strncmp - ("Big Endian", lscpu.byte_order, - strlen("Big Endian")) == 0) { - lscpu.order = ORDER_BIG; - } - } - if (strncmp("CPU(s):", tmpstr, strlen("CPU(s):")) == 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.cpus); - } - if (strncmp - ("On-line CPU(s) list:", tmpstr, - strlen("On-line CPU(s) list:")) == 0) { - lscpu.cpu_online = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); - strcpy(lscpu.cpu_online, &tmpstr[NUMBER_COL]); - } - if (strncmp - ("Off-line CPU(s) list:", tmpstr, - strlen("Off-line CPU(s) list:")) == 0) { - lscpu.cpu_offline = - malloc(strlen(&tmpstr[NUMBER_COL]) + 1); - strcpy(lscpu.cpu_offline, &tmpstr[NUMBER_COL]); - } - if (strncmp("Model:", tmpstr, strlen("Model:")) == 0) { - lscpu.model = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); - strcpy(lscpu.model, &tmpstr[NUMBER_COL]); - } - if (strncmp("Model name:", tmpstr, strlen("Model name:")) == 0) { - lscpu.model_name = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); - strcpy(lscpu.model_name, &tmpstr[NUMBER_COL]); - } - if (strncmp - ("Thread(s) per core:", tmpstr, - strlen("Thread(s) per core:")) == 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.threads); - } - if (strncmp - ("Core(s) per socket:", tmpstr, - strlen("Core(s) per socket:")) == 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.cores); - } - if (strncmp("Socket(s):", tmpstr, strlen("Socket(s):")) == 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.sockets); - } - if (strncmp("NUMA node(s):", tmpstr, strlen("NUMA node(s):")) - == 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.numa_nodes); - } - if (strncmp("CPU MHz:", tmpstr, strlen("CPU MHz:")) == 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.mhz); - } - if (strncmp("CPU max MHz:", tmpstr, strlen("CPU max MHz:")) == - 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.mhz_max); - } - if (strncmp("CPU min MHz:", tmpstr, strlen("CPU min MHz:")) == - 0) { - sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.mhz_min); - } - } - pclose(pop); - } - -} - -/* Maximum number of lines in /proc files */ -/* Intel already has 26 (so here 30) per Hypterthread CPU (max 128*2 CPUs here) */ -/* POWER has only 6 to 7 lines but gets 1536 SMT threads soon */ -/* Erring on the saf side below */ -#define PROC_MAXLINES (16*1024) /*MAGIC COOKIE WARNING */ - - -int proc_cpu_done = 0; /* Flag if we have run function proc_cpu() already in this interval */ - -int reread = 0; -struct { - FILE *fp; - char *filename; - int size; - int lines; - char *line[PROC_MAXLINES]; - char *buf; - int read_this_interval; /* track updates for each update to stop double data collection */ -} proc[P_NUMBER]; - -void proc_init() -{ - proc[P_CPUINFO].filename = "/proc/cpuinfo"; - proc[P_STAT].filename = "/proc/stat"; - proc[P_VERSION].filename = "/proc/version"; - proc[P_MEMINFO].filename = "/proc/meminfo"; - proc[P_UPTIME].filename = "/proc/uptime"; - proc[P_LOADAVG].filename = "/proc/loadavg"; - proc[P_NFS].filename = "/proc/net/rpc/nfs"; - proc[P_NFSD].filename = "/proc/net/rpc/nfsd"; - proc[P_VMSTAT].filename = "/proc/vmstat"; -} - -void proc_read(int num) -{ - int i; - int size; - int found; - char buf[1024]; - - if (proc[num].read_this_interval == 1) - return; - - if (proc[num].fp == 0) { - if ((proc[num].fp = fopen(proc[num].filename, "r")) == NULL) { - sprintf(buf, "failed to open file %s", proc[num].filename); - error(buf); - proc[num].fp = 0; - return; - } - } - rewind(proc[num].fp); - - /* We re-read P_STAT, now flag proc_cpu() that it has to re-process that data */ - if (num == P_STAT) - proc_cpu_done = 0; - - if (proc[num].size == 0) { - /* first time so allocate initial now */ - proc[num].buf = MALLOC(512); - proc[num].size = 512; - } - - for (i = 0; i < 4096; i++) { /* MAGIC COOKIE WARNING POWER8 default install can have 2655 processes */ - size = fread(proc[num].buf, 1, proc[num].size - 1, proc[num].fp); - if (size < proc[num].size - 1) - break; - proc[num].size += 512; - proc[num].buf = REALLOC(proc[num].buf, proc[num].size); - rewind(proc[num].fp); - } - - proc[num].buf[size] = 0; - proc[num].lines = 0; - proc[num].line[0] = &proc[num].buf[0]; - if (num == P_VERSION) { - found = 0; - for (i = 0; i < size; i++) { /* remove some weird stuff found the hard way in various Linux versions and device drivers */ - /* place ") (" on two lines */ - if (found == 0 && - proc[num].buf[i] == ')' && - proc[num].buf[i + 1] == ' ' && - proc[num].buf[i + 2] == '(') { - proc[num].buf[i + 1] = '\n'; - found = 1; - } else { - /* place ") #" on two lines */ - if (proc[num].buf[i] == ')' && - proc[num].buf[i + 1] == ' ' && - proc[num].buf[i + 2] == '#') { - proc[num].buf[i + 1] = '\n'; - } - /* place "#1" on two lines */ - if (proc[num].buf[i] == '#' && proc[num].buf[i + 2] == '1') { - proc[num].buf[i] = '\n'; - } - } - } - } - for (i = 0; i < size; i++) { - /* replace Tab characters with space */ - if (proc[num].buf[i] == '\t') { - proc[num].buf[i] = ' '; - } else if (proc[num].buf[i] == '\n') { - /* replace newline characters with null */ - proc[num].lines++; - proc[num].buf[i] = '\0'; - proc[num].line[proc[num].lines] = &proc[num].buf[i + 1]; - } - if (proc[num].lines == PROC_MAXLINES - 1) - break; - } - if (reread) { - fclose(proc[num].fp); - proc[num].fp = 0; - } - /* Set flag so we do not re-read the data even if called multiple times in same interval */ - proc[num].read_this_interval = 1; -} - -#include - -struct procsinfo { - int pi_pid; - char pi_comm[64]; - char pi_state; - int pi_ppid; - int pi_pgrp; - int pi_session; - int pi_tty_nr; - int pi_tty_pgrp; - unsigned long pi_flags; - unsigned long pi_minflt; - unsigned long pi_cmin_flt; - unsigned long pi_majflt; - unsigned long pi_cmaj_flt; - unsigned long pi_utime; - unsigned long pi_stime; - long pi_cutime; - long pi_cstime; - long pi_pri; - long pi_nice; -#ifndef KERNEL_2_6_18 - long junk /* removed */ ; -#else - long pi_num_threads; -#endif - long pi_it_real_value; - unsigned long pi_start_time; - unsigned long pi_vsize; - long pi_rss; /* - 3 */ - unsigned long pi_rlim_cur; - unsigned long pi_start_code; - unsigned long pi_end_code; - unsigned long pi_start_stack; - unsigned long pi_esp; - unsigned long pi_eip; - /* The signal information here is obsolete. */ - unsigned long pi_pending_signal; - unsigned long pi_blocked_sig; - unsigned long pi_sigign; - unsigned long pi_sigcatch; - unsigned long pi_wchan; - unsigned long pi_nswap; - unsigned long pi_cnswap; - int pi_exit_signal; - int pi_cpu; -#ifdef KERNEL_2_6_18 - unsigned long pi_rt_priority; - unsigned long pi_policy; - unsigned long long pi_delayacct_blkio_ticks; -#endif - unsigned long statm_size; /* total program size */ - unsigned long statm_resident; /* resident set size */ - unsigned long statm_share; /* shared pages */ - unsigned long statm_trs; /* text (code) */ - unsigned long statm_drs; /* data/stack */ - unsigned long statm_lrs; /* library */ - unsigned long statm_dt; /* dirty pages */ - - unsigned long long read_io; /* storage read bytes */ - unsigned long long write_io; /* storage write bytes */ -}; -int isroot = 0; - -#include -#include -#include -#include -#include - -int debug = 0; -time_t timer; /* used to work out the hour/min/second */ - -/* Counts of resources */ -int cpus = 1; /* number of CPUs in system (lets hope its more than zero!) */ -#if X86 || ARM -int cores = 0; -int siblings = 0; -int processorchips = 0; -int hyperthreads = 0; -char *vendor_ptr = "-"; -char *model_ptr = "-"; -char *mhz_ptr = "-"; -char *bogo_ptr = "-"; -#endif -int old_cpus = 1; /* Number of CPU seen in previuos interval */ -int max_cpus = 1; /* highest number of CPUs in DLPAR */ -int networks = 0; /* number of networks in system */ -int partitions = 0; /* number of partitions in system */ -int partitions_short = 0; /* partitions file data short form (i.e. data missing) */ -int disks = 0; /* number of disks in system */ -int seconds = -1; /* pause interval */ -int maxloops = -1; /* stop after this number of updates */ -char hostname[256]; -char run_name[256]; -int run_name_set = 0; -char fullhostname[256]; -int loop; - -#define DPL 150 /* Disks per line for file output to ensure it - does not overflow the spreadsheet input line max */ - -int disks_per_line = DPL; - -#define NEWDISKGROUP(disk) ( (disk) % disks_per_line == 0) - -/* Mode of output variables */ -int show_aaa = 1; -int show_para = 1; -int show_headings = 1; -int show_res = 0; -int show_smp = 0; -int show_util = 0; -int first_util = 1; -int show_wide = 0; -int show_gpu = 0; -int show_mhz = 0; -int show_longterm = 0; -int show_disk = 0; -#define SHOW_DISK_NONE 0 -#define SHOW_DISK_STATS 1 -#define SHOW_DISK_GRAPH 2 -int show_diskmap = 0; -int show_memory = 0; -int show_large = 0; -int show_kernel = 0; -int show_nfs = 0; -int show_net = 0; -int show_neterror = 0; -int show_help = 0; -int show_top = 0; -int show_topmode = 1; -#define ARGS_NONE 0 -#define ARGS_ONLY 1 -int show_args = 0; -int show_all = 1; /* 1=all procs& disk 0=only if 1% or more busy */ -int show_verbose = 0; -int show_jfs = 0; -int flash_on = 0; -int first_huge = 1; -int first_steal = 1; -long huge_peak = 0; -int welcome = 1; -int dotline = 0; -int show_rrd = 0; -int show_lpar = 0; -int show_vm = 0; -int show_dgroup = 0; /* disk groups */ -int auto_dgroup = 0; /* disk groups defined via -g auto */ -int disk_only_mode = 0; /* disk stats shows disks only if user used -g auto */ -int dgroup_loaded = 0; /* 0 = no, 1=needed, 2=loaded */ - -#define RRD if(show_rrd) - -double ignore_procdisk_threshold = 0.1; -double ignore_io_threshold = 0.1; -/* Curses support */ -#define CURSE if(cursed) /* Only use this for single line curses calls */ -#define COLOUR if(colour) /* Only use this for single line colour curses calls */ -int cursed = 1; /* 1 = using curses and - 0 = loging output for a spreadsheet */ -int colour = 1; /* 1 = using colour curses and - 0 = using black and white curses (see -b flag) */ -#define MVPRINTW(row,col,string) {move((row),(col)); \ - attron(A_STANDOUT); \ - printw(string); \ - attroff(A_STANDOUT); } -FILE *fp; /* filepointer for spreadsheet output */ - - -char *timestamp(int loop, time_t eon) -{ - static char string[64]; - if (show_rrd) - sprintf(string, "%ld", (long) eon); - else - sprintf(string, "T%04d", loop); - return string; -} - -#define LOOP timestamp(loop,timer) - -char *easy[5] = { "not found", 0, 0, 0, 0 }; -char *lsb_release[5] = { "not found", 0, 0, 0, 0 }; - -void find_release() -{ - FILE *pop; - int i; - char tmpstr[71]; - -#ifdef SLES12 - pop = popen("cat /etc/os-release 2>/dev/null", "r"); -#else - pop = popen("cat /etc/*ease 2>/dev/null", "r"); -#endif /* SLES12 */ - if (pop != NULL) { - tmpstr[0] = 0; - for (i = 0; i < 4; i++) { - if (fgets(tmpstr, 70, pop) == NULL) - break; - tmpstr[strlen(tmpstr) - 1] = 0; /* remove newline */ - easy[i] = MALLOC(strlen(tmpstr) + 1); - strcpy(easy[i], tmpstr); - } - pclose(pop); - } - pop = popen("/usr/bin/lsb_release -idrc 2>/dev/null", "r"); - if (pop != NULL) { - tmpstr[0] = 0; - for (i = 0; i < 4; i++) { - if (fgets(tmpstr, 70, pop) == NULL) - break; - tmpstr[strlen(tmpstr) - 1] = 0; /* remove newline */ - lsb_release[i] = MALLOC(strlen(tmpstr) + 1); - strcpy(lsb_release[i], tmpstr); - } - pclose(pop); - } -} - - - -/* Full Args Mode stuff here */ - -#define ARGSMAX 1024*8 -#define CMDLEN 4096 - -struct { - int pid; - char *args; -} arglist[ARGSMAX]; - -void args_output(int pid, int loop, char *progname) -{ - FILE *pop; - int i, j, n; - char tmpstr[CMDLEN]; - static int arg_first_time = 1; - - if (pid == 0) - return; /* ignore init */ - for (i = 0; i < ARGSMAX - 1; i++) { /* clear data out */ - if (arglist[i].pid == pid) { - return; - } - if (arglist[i].pid == 0) /* got to empty slot */ - break; - } - sprintf(tmpstr, "ps -p %d -o args 2>/dev/null", pid); - pop = popen(tmpstr, "r"); - if (pop == NULL) { - return; - } else { - if (fgets(tmpstr, CMDLEN, pop) == NULL) { /* throw away header */ - pclose(pop); - return; - } - tmpstr[0] = 0; - if (fgets(tmpstr, CMDLEN, pop) == NULL) { - pclose(pop); - return; - } - tmpstr[strlen(tmpstr) - 1] = 0; - if (tmpstr[strlen(tmpstr) - 1] == ' ') - tmpstr[strlen(tmpstr) - 1] = 0; - arglist[i].pid = pid; - if (arg_first_time) { - fprintf(fp, "UARG,+Time,PID,ProgName,FullCommand\n"); - arg_first_time = 0; - } - n = strlen(tmpstr); - for (i = 0; i < n; i++) { - /*strip out stuff that confused Excel i.e. starting with maths symbol */ - if (tmpstr[i] == ',' && - ((tmpstr[i + 1] == '-') || tmpstr[i + 1] == '+')) - tmpstr[i + 1] = '_'; - /*strip out double spaces */ - if (tmpstr[i] == ' ' && tmpstr[i + 1] == ' ') { - for (j = 0; j < n - i; j++) - tmpstr[i + j] = tmpstr[i + j + 1]; - i--; /* rescan to remove triple space etc */ - } - } - - fprintf(fp, "UARG,%s,%07d,%s,%s\n", LOOP, pid, progname, tmpstr); - pclose(pop); - return; - } -} - -void args_load() -{ - FILE *pop; - int i; - char tmpstr[CMDLEN]; - - for (i = 0; i < ARGSMAX; i++) { /* clear data out */ - if (arglist[i].pid == -1) - break; - if (arglist[i].pid != 0) { - arglist[i].pid = -1; - free(arglist[i].args); - } - } - pop = popen("ps -eo pid,args 2>/dev/null", "r"); - if (pop == NULL) { - return; - } else { - if (fgets(tmpstr, CMDLEN, pop) == NULL) { /* throw away header */ - pclose(pop); - return; - } - for (i = 0; i < ARGSMAX; i++) { - tmpstr[0] = 0; - if (fgets(tmpstr, CMDLEN, pop) == NULL) { - pclose(pop); - return; - } - tmpstr[strlen(tmpstr) - 1] = 0; - if (tmpstr[strlen(tmpstr) - 1] == ' ') - tmpstr[strlen(tmpstr) - 1] = 0; - arglist[i].pid = atoi(tmpstr); - arglist[i].args = MALLOC(strlen(tmpstr)); - strcpy(arglist[i].args, &tmpstr[6]); - } - pclose(pop); - } -} - -char *args_lookup(int pid, char *progname) -{ - int i; - for (i = 0; i < ARGSMAX; i++) { - if (arglist[i].pid == pid) - return arglist[i].args; - if (arglist[i].pid == -1) - return progname; - } - return progname; -} - -/* end args mode stuff here */ - -void linux_bbbp(char *name, char *cmd, char *err) -{ - int i; - int j; - int len; -#define STRLEN 4096 - char str[STRLEN]; - FILE *pop; - static int lineno = 0; - - pop = popen(cmd, "r"); - if (pop == NULL) { - fprintf(fp, "BBBP,%03d,%s failed to run %s\n", lineno++, cmd, err); - } else { - fprintf(fp, "BBBP,%03d,%s\n", lineno++, name); - for (i = 0; i < 2048 && (fgets(str, STRLEN, pop) != NULL); i++) { /* 2048=sanity check only */ - len = strlen(str); - if (len > STRLEN) - len = STRLEN; - if (str[len - 1] == '\n') /*strip off the newline */ - str[len - 1] = 0; - /* fix text starting characters that confuses spread sheets */ - if (str[0] == '+') - str[0] = 'p'; - if (str[0] == '*') - str[0] = 'm'; - if (str[0] == '-') - str[0] = 'n'; - if (str[0] == '/') - str[0] = 'd'; - if (str[0] == '=') - str[0] = 'e'; - /* remove double quotes as it confuses spread sheets */ - for (j = 0; str[j] != 0; j++) - if (str[j] == '"') - str[j] = 'Q'; - fprintf(fp, "BBBP,%03d,%s,\"%s\"\n", lineno++, name, str); - } - pclose(pop); - } -} - -#define WARNING "needs root permission or file not present" - -/* Global name of programme for printing it */ -char *progname; - -/* Main data structure for collected stats. - * Two versions are previous and current data. - * Often its the difference that is printed. - * The pointers are swaped i.e. current becomes the previous - * and the previous over written rather than moving data around. - */ -struct cpu_stat { /* changed the order here to match this years kernel (man 5 /proc/stat) */ - long long user; - long long nice; - long long sys; - long long idle; - long long wait; /* for IO */ - long long irq; - long long softirq; - long long steal; - long long guest; - long long guest_nice; - /* below are non-cpu based numbers in the same file */ - long long intr; - long long ctxt; - long long btime; - long long procs; - long long running; - long long blocked; - float uptime; - float idletime; - float mins1; - float mins5; - float mins15; -}; - -#define ulong unsigned long -struct dsk_stat { - char dk_name[32]; - int dk_major; - int dk_minor; - long dk_noinfo; - ulong dk_reads; - ulong dk_rmerge; - ulong dk_rmsec; - ulong dk_rkb; - ulong dk_writes; - ulong dk_wmerge; - ulong dk_wmsec; - ulong dk_wkb; - ulong dk_xfers; - ulong dk_bsize; - ulong dk_time; - ulong dk_inflight; - ulong dk_backlog; - ulong dk_partition; - ulong dk_blocks; /* in /proc/partitions only */ - ulong dk_use; - ulong dk_aveq; -}; - -struct mem_stat { - long memtotal; - long memfree; - long memshared; - long buffers; - long cached; - long swapcached; - long active; - long inactive; - long hightotal; - long highfree; - long lowtotal; - long lowfree; - long swaptotal; - long swapfree; -#ifdef LARGEMEM - long dirty; - long writeback; - long mapped; - long slab; - long committed_as; - long pagetables; - long hugetotal; - long hugefree; - long hugesize; -#else - long bigfree; -#endif /*LARGEMEM*/ -}; - -struct vm_stat { - long long nr_dirty; - long long nr_writeback; - long long nr_unstable; - long long nr_page_table_pages; - long long nr_mapped; - long long nr_slab; - long long pgpgin; - long long pgpgout; - long long pswpin; - long long pswpout; - long long pgalloc_high; - long long pgalloc_normal; - long long pgalloc_dma; - long long pgfree; - long long pgactivate; - long long pgdeactivate; - long long pgfault; - long long pgmajfault; - long long pgrefill_high; - long long pgrefill_normal; - long long pgrefill_dma; - long long pgsteal_high; - long long pgsteal_normal; - long long pgsteal_dma; - long long pgscan_kswapd_high; - long long pgscan_kswapd_normal; - long long pgscan_kswapd_dma; - long long pgscan_direct_high; - long long pgscan_direct_normal; - long long pgscan_direct_dma; - long long pginodesteal; - long long slabs_scanned; - long long kswapd_steal; - long long kswapd_inodesteal; - long long pageoutrun; - long long allocstall; - long long pgrotated; -}; - - -#define NFS_V2_NAMES_COUNT 18 -char *nfs_v2_names[NFS_V2_NAMES_COUNT] = { - "null", "getattr", "setattr", "root", "lookup", "readlink", - "read", "wrcache", "write", "create", "remove", "rename", - "link", "symlink", "mkdir", "rmdir", "readdir", "fsstat" -}; - -#define NFS_V3_NAMES_COUNT 22 -char *nfs_v3_names[22] = { - "null", "getattr", "setattr", "lookup", "access", "readlink", - "read", "write", "create", "mkdir", "symlink", "mknod", - "remove", "rmdir", "rename", "link", "readdir", "readdirplus", - "fsstat", "fsinfo", "pathconf", "commit" -}; - -#define NFS_V4S_NAMES_COUNT 72 -int nfs_v4s_names_count = NFS_V4S_NAMES_COUNT; -char *nfs_v4s_names[NFS_V4S_NAMES_COUNT] = { /* get these names from nfsstat as they are NOT documented */ - "op0-unused", "op1-unused", "op2-future", "access", "close", "commit", /* 1 - 6 */ - "create", "delegpurge", "delegreturn", "getattr", "getfh", "link", /* 7 - 12 */ - "lock", "lockt", "locku", "lookup", "lookup_root", "nverify", /* 13 - 18 */ - "open", "openattr", "open_conf", "open_dgrd", "putfh", "putpubfh", /* 19 - 24 */ - "putrootfh", "read", "readdir", "readlink", "remove", "rename", /* 25 - 30 */ - "renew", "restorefh", "savefh", "secinfo", "setattr", "setcltid", /* 31 - 36 */ - "setcltidconf", "verify", "write", "rellockowner", "bc_ctl", "blind_conn", /* 37 - 42 */ - "exchange_id", "create_ses", "destroy_ses", "free_statid", "getdirdelag", "getdevinfo", /* 43 - 48 */ - "getdevlist", "layoutcommit", "layoutget", "layoutreturn", "secunfononam", "sequence", /* 49 - 54 */ - "set_ssv", "test_stateid", "want_deleg", "destory_clid", "reclaim_comp", "stat60", /* 55 - 60 */ - "stat61", "stat62", "stat63", "stat64", "stat65", "stat66", /* 61 - 66 */ - "stat67", "stat68", "stat69", "stat70", "stat71", "stat72" /* 67 - 72 */ -}; - -#define NFS_V4C_NAMES_COUNT 60 -int nfs_v4c_names_count = NFS_V4C_NAMES_COUNT; -char *nfs_v4c_names[NFS_V4C_NAMES_COUNT] = { /* get these names from nfsstat as they are NOT documented */ - "null", "read", "write", "commit", "open", "open_conf", /* 1 - 6 */ - "open_noat", "open_dgrd", "close", "setattr", "fsinfo", "renew", /* 7 - 12 */ - "setclntid", "confirm", "lock", "lockt", "locku", "access", /* 13 - 18 */ - "getattr", "lookup", "lookup_root", "remove", "rename", "link", /* 19 - 24 */ - "symlink", "create", "pathconf", "statfs", "readlink", "readdir", /* 25 - 30 */ - "server_caps", "delegreturn", "getacl", "setacl", "fs_locations", "rel_lkowner", /* 31 - 36 */ - "secinfo", "exchange_id", "create_ses", "destroy_ses", "sequence", "get_lease_t", /* 37 - 42 */ - "reclaim_comp", "layoutget", "getdevinfo", "layoutcommit", "layoutreturn", "getdevlist", /* 43 - 48 */ - "stat49", "stat50", "stat51", "stat52", "start53", "stat54", /* 49 - 54 */ - "stat55", "stat56", "stat57", "stat58", "start59", "stat60" /* 55 - 60 */ -}; - - -int nfs_v2c_found = 0; -int nfs_v2s_found = 0; -int nfs_v3c_found = 0; -int nfs_v3s_found = 0; -int nfs_v4c_found = 0; -int nfs_v4s_found = 0; -int nfs_clear = 0; - -struct nfs_stat { - long v2c[NFS_V2_NAMES_COUNT]; /* verison 2 client */ - long v3c[NFS_V3_NAMES_COUNT]; /* verison 3 client */ - long v4c[NFS_V4C_NAMES_COUNT]; /* verison 4 client */ - long v2s[NFS_V2_NAMES_COUNT]; /* verison 2 SERVER */ - long v3s[NFS_V3_NAMES_COUNT]; /* verison 3 SERVER */ - long v4s[NFS_V4S_NAMES_COUNT]; /* verison 4 SERVER */ -}; - -#define NETMAX 32 -struct net_stat { - unsigned long if_name[17]; - unsigned long long if_ibytes; - unsigned long long if_obytes; - unsigned long long if_ipackets; - unsigned long long if_opackets; - unsigned long if_ierrs; - unsigned long if_oerrs; - unsigned long if_idrop; - unsigned long if_ififo; - unsigned long if_iframe; - unsigned long if_odrop; - unsigned long if_ofifo; - unsigned long if_ocarrier; - unsigned long if_ocolls; -}; -#ifdef PARTITIONS -#define PARTMAX 256 -struct part_stat { - int part_major; - int part_minor; - unsigned long part_blocks; - char part_name[16]; - unsigned long part_rio; - unsigned long part_rmerge; - unsigned long part_rsect; - unsigned long part_ruse; - unsigned long part_wio; - unsigned long part_wmerge; - unsigned long part_wsect; - unsigned long part_wuse; - unsigned long part_run; - unsigned long part_use; - unsigned long part_aveq; -}; -#endif /*PARTITIONS*/ -#ifdef POWER -#define VM_UNKNOWN 0 -#define VM_POWERVM 1 -#define VM_POWERKVM_GUEST 2 -#define VM_POWERKVM_HOST 3 -#define VM_NATIVE 4 -int power_vm_type = VM_UNKNOWN; - -/* XXXXXXX need to test if rewind() worked or not for lparcfg */ -int lparcfg_reread = 1; -/* Reset at end of each interval so LPAR cfg is only read once each interval - * even if proc_lparcfg() is called multiple times - * Note: lparcfg is not read via proc_read() ! - */ -int lparcfg_processed = 0; - -struct { - char version_string[16]; /*lparcfg 1.3 */ - int version; - char serial_number[16]; /*HAL,0210033EA */ - char system_type[64]; /*HAL,9124-720 */ - /* new record is "IBM pSeries (emulated by qemu)" instead of "IBM 9119-MME" */ - int partition_id; /*11 */ -/* -R4=0x14 -R5=0x0 -R6=0x800b0000 -R7=0x1000000040004 -*/ - int BoundThrds; /*=1*/ - int CapInc; /*=1*/ - long long DisWheRotPer; /*=2070000*/ - int MinEntCap; /*=10*/ - int MinEntCapPerVP; /*=10*/ - int MinMem; /*=2048*/ - int DesMem; /*=4096*/ - int MinProcs; /*=1*/ - int partition_max_entitled_capacity;/*=400*/ - int system_potential_processors; /*=4*/ - /**/ int partition_entitled_capacity; - /*=20*/ - int system_active_processors; /*=4*/ - int pool_capacity; /*=4*/ - int unallocated_capacity_weight; /*=0*/ - int capacity_weight; /*=0*/ - int capped; /*=1*/ - int unallocated_capacity; /*=0*/ - long long pool_idle_time; /*=0*/ - long long pool_idle_saved; - long long pool_idle_diff; - int pool_num_procs; /*=0*/ - long long purr; /*=0*/ - long long purr_saved; - long long purr_diff; - long long timebase; - int partition_active_processors; /*=1*/ - int partition_potential_processors; /*=40*/ - int shared_processor_mode; /*=1*/ - int smt_mode; /* 1: off, 2: SMT-2, 4: SMT-4 */ - int cmo_enabled; /* 1 means AMS is Active */ - int entitled_memory_pool_number; /* pool number = 0 */ - int entitled_memory_weight; /* 0 to 255 */ - long cmo_faults; /* Hypervisor Page-in faults = big number */ - long cmo_faults_save; /* above saved */ - long cmo_faults_diff; /* delta */ - long cmo_fault_time_usec; /* Hypervisor time in micro seconds = big */ - long cmo_fault_time_usec_save; /* above saved */ - long cmo_fault_time_usec_diff; /* delta */ - long backing_memory; /* AIX pmem in bytes */ - long cmo_page_size; /* AMS page size in bytes */ - long entitled_memory_pool_size; /* AMS whole pool size in bytes */ - long entitled_memory_loan_request; /* AMS requesting more memory loaning */ - -#ifdef EXPERIMENTAL -/* new data in SLES11 for POWER 2.6.27 (may be a little earlier too) */ - long DesEntCap; - long DesProcs; - long DesVarCapWt; - long DedDonMode; - long group; - long pool; - long entitled_memory; - long entitled_memory_group_number; - long unallocated_entitled_memory_weight; - long unallocated_io_mapping_entitlement; -/* new data in SLES11 for POWER 2.6.27 */ -#endif /* EXPERIMENTAL */ - -} lparcfg; - -int lpar_count = 0; - -#define LPAR_LINE_MAX 100 /* MAGIC COOKIE WARNING */ -#define LPAR_LINE_WIDTH 80 -char lpar_buffer[LPAR_LINE_MAX][LPAR_LINE_WIDTH]; - -int lpar_sanity = 55; - -char *locate(char *s) -{ - int i; - int len; - len = strlen(s); - for (i = 0; i < lpar_count; i++) - if (!strncmp(s, lpar_buffer[i], len)) - return lpar_buffer[i]; - return ""; -} - -#define NUMBER_NOT_VALID -999 - -long long read_longlong(char *s) -{ - long long x; - int ret; - int len; - int i; - char *str; - str = locate(s); - len = strlen(str); - if (len == 0) { - return NUMBER_NOT_VALID; - } - for (i = 0; i < len; i++) { - if (str[i] == '=') { - ret = sscanf(&str[i + 1], "%lld", &x); - if (ret != 1) { - fprintf(stderr, - "sscanf for %s failed returned = %d line=%s\n", s, - ret, str); - return -1; - } -/* fprintf(fp,"DEBUG read %s value %lld\n",s,x);*/ - return x; - } - } - fprintf(stderr, "read_long_long failed returned line=%s\n", str); - return -2; -} - - -/* Return of 0 means data not available */ -int proc_lparcfg() -{ - static FILE *fp = (FILE *) - 1; -/* Only try to read /proc/ppc64/lparcfg once - remember if it's readable */ - static int lparinfo_not_available = 0; - int i; - char *str; - /* If we already read and processed /proc/lparcfg in this interval - just return */ - if (lparcfg_processed == 1) - return 1; - - if (lparinfo_not_available == 1) - return 0; - - if (fp == (FILE *) - 1) { - if ((fp = fopen("/proc/ppc64/lparcfg", "r")) == NULL) { - error("failed to open - /proc/ppc64/lparcfg"); - fp = (FILE *) - 1; - lparinfo_not_available = 1; - if (power_vm_type == VM_UNKNOWN) { - /* Heuristics for spotting PowerKVM Host - a) inside ifdef POWER so can't be x86 - b) /proc/ppc64/lparcfg is missing - c) /etc/ *ease files have hints - Confirmed true for IBM_POWERKVM 2.1 - */ - if (strncmp("IBM_PowerKVM", easy[1], 12) == 0) - power_vm_type = VM_POWERKVM_HOST; - else - power_vm_type = VM_NATIVE; - } - return 0; - } - } - - for (lpar_count = 0; lpar_count < LPAR_LINE_MAX - 1; lpar_count++) { - if (fgets(lpar_buffer[lpar_count], LPAR_LINE_WIDTH - 1, fp) == - NULL) - break; - } - if (lparcfg_reread) { /* XXXX unclear if close+open is necessary - unfortunately this requires version many of Linux on POWER install to test early releases */ - fclose(fp); - fp = (FILE *) - 1; - } else - rewind(fp); - - str = locate("lparcfg"); - sscanf(str, "lparcfg %s", lparcfg.version_string); - str = locate("serial_number"); - sscanf(str, "serial_number=%s", lparcfg.serial_number); - str = locate("system_type"); - for (i = 0; i < strlen(str); i++) /* Remove new spaces in massive string meaning PowerKVM Guest !! */ - if (str[i] == ' ') - str[i] = '-'; - sscanf(str, "system_type=%s", lparcfg.system_type); - if (power_vm_type == VM_UNKNOWN) { - /* Heuristics for spotting PowerKVM Guest - a) inside ifdef POWER so can't be x86 - b) we have a /proc/ppc64/lparcfg - probably mostly missing (1.9) - c) system type string includes "qemu" - Confirmed true for SLES11.3 RHEL6.5 and Ubuntu 14.4.1 - */ - if (strstr(lparcfg.system_type, "(emulated-by-qemu)") == 0) - power_vm_type = VM_POWERVM; /* not found */ - else - power_vm_type = VM_POWERKVM_GUEST; - } -#define GETDATA(variable) lparcfg.variable = read_longlong( __STRING(variable) ); - - GETDATA(partition_id); - GETDATA(BoundThrds); - GETDATA(CapInc); - GETDATA(DisWheRotPer); - GETDATA(MinEntCap); - GETDATA(MinEntCapPerVP); - GETDATA(MinMem); - GETDATA(DesMem); - GETDATA(MinProcs); - GETDATA(partition_max_entitled_capacity); - GETDATA(system_potential_processors); - GETDATA(partition_entitled_capacity); - GETDATA(system_active_processors); - GETDATA(pool_capacity); - GETDATA(unallocated_capacity_weight); - GETDATA(capacity_weight); - GETDATA(capped); - GETDATA(unallocated_capacity); - lparcfg.pool_idle_saved = lparcfg.pool_idle_time; - GETDATA(pool_idle_time); - lparcfg.pool_idle_diff = - lparcfg.pool_idle_time - lparcfg.pool_idle_saved; - GETDATA(pool_num_procs); - lparcfg.purr_saved = lparcfg.purr; - GETDATA(purr); - lparcfg.purr_diff = lparcfg.purr - lparcfg.purr_saved; - GETDATA(partition_active_processors); - GETDATA(partition_potential_processors); - GETDATA(shared_processor_mode); - /* Brute force, may provide temporary incorrect data during - * dynamic reconfiguraiton envents - */ - lparcfg.smt_mode = cpus / lparcfg.partition_active_processors; - - /* AMS additions */ - GETDATA(cmo_enabled); - if (lparcfg.cmo_enabled == NUMBER_NOT_VALID) { - lparcfg.cmo_enabled = 0; - } - if (lparcfg.cmo_enabled) { - GETDATA(entitled_memory_pool_number); /* pool number = 0 */ - GETDATA(entitled_memory_weight); /* 0 to 255 */ - - lparcfg.cmo_faults_save = lparcfg.cmo_faults; - GETDATA(cmo_faults); /* Hypervisor Page-in faults = big number */ - lparcfg.cmo_faults_diff = - lparcfg.cmo_faults - lparcfg.cmo_faults_save; - - lparcfg.cmo_fault_time_usec_save = lparcfg.cmo_fault_time_usec; - GETDATA(cmo_fault_time_usec); /* Hypervisor time in micro seconds = big number */ - lparcfg.cmo_fault_time_usec_diff = - lparcfg.cmo_fault_time_usec - lparcfg.cmo_fault_time_usec_save; - - GETDATA(backing_memory); /* AIX pmem in bytes */ - GETDATA(cmo_page_size); /* AMS page size in bytes */ - GETDATA(entitled_memory_pool_size); /* AMS whole pool size in bytes */ - GETDATA(entitled_memory_loan_request); /* AMS requesting more memory loaning */ - - } -#ifdef EXPERIMENTAL - GETDATA(DesEntCap); - GETDATA(DesProcs); - GETDATA(DesVarCapWt); - GETDATA(DedDonMode); - GETDATA(group); - GETDATA(pool); - GETDATA(entitled_memory); - GETDATA(entitled_memory_group_number); - GETDATA(unallocated_entitled_memory_weight); - GETDATA(unallocated_io_mapping_entitlement); -#endif /* EXPERIMENTAL */ - - lparcfg_processed = 1; - return 1; -} -#endif /*POWER*/ -#define DISKMIN 256 -#define DISKMAX diskmax -int diskmax = DISKMIN; - -/* Supports up to 780, but not POWER6 595 follow-up with POWER7 */ -/* XXXX needs rework to cope to with fairly rare but interesting higher numbers of CPU machines */ -#define CPUMAX (192 * 8) /* MAGIC COOKIE WARNING */ - -struct data { - struct dsk_stat *dk; - struct cpu_stat cpu_total; - struct cpu_stat cpuN[CPUMAX]; - struct mem_stat mem; - struct vm_stat vm; - struct nfs_stat nfs; - struct net_stat ifnets[NETMAX]; -#ifdef PARTITIONS - struct part_stat parts[PARTMAX]; -#endif /*PARTITIONS*/ - struct timeval tv; - double time; - struct procsinfo *procs; - - int nprocs; -} database[2], *p, *q; - - -long long get_vm_value(char *s) -{ - int currline; - int currchar; - long long result = -1; - char *check; - int len; - int found; - - for (currline = 0; currline < proc[P_VMSTAT].lines; currline++) { - len = strlen(s); - for (currchar = 0, found = 1; currchar < len; currchar++) { - if (proc[P_VMSTAT].line[currline][currchar] == 0 || - s[currchar] != proc[P_VMSTAT].line[currline][currchar]) { - found = 0; - break; - } - } - if (found && proc[P_VMSTAT].line[currline][currchar] == ' ') { - result = - strtoll(&proc[P_VMSTAT].line[currline][currchar + 1], - &check, 10); - if (*check == proc[P_VMSTAT].line[currline][currchar + 1]) { - fprintf(stderr, "%s has an unexpected format: >%s<\n", - proc[P_VMSTAT].filename, - proc[P_VMSTAT].line[currline]); - return -1; - } - return result; - } - } - return -1; -} - -#define GETVM(variable) p->vm.variable = get_vm_value(__STRING(variable) ); - -int read_vmstat() -{ - proc_read(P_VMSTAT); - if (proc[P_VMSTAT].read_this_interval == 0 - || proc[P_VMSTAT].lines == 0) - return (-1); - - /* Note: if the variable requested is not found in /proc/vmstat then it is set to -1 */ - GETVM(nr_dirty); - GETVM(nr_writeback); - GETVM(nr_unstable); - GETVM(nr_page_table_pages); - GETVM(nr_mapped); - GETVM(nr_slab); - GETVM(pgpgin); - GETVM(pgpgout); - GETVM(pswpin); - GETVM(pswpout); - GETVM(pgalloc_high); - GETVM(pgalloc_normal); - GETVM(pgalloc_dma); - GETVM(pgfree); - GETVM(pgactivate); - GETVM(pgdeactivate); - GETVM(pgfault); - GETVM(pgmajfault); - GETVM(pgrefill_high); - GETVM(pgrefill_normal); - GETVM(pgrefill_dma); - GETVM(pgsteal_high); - GETVM(pgsteal_normal); - GETVM(pgsteal_dma); - GETVM(pgscan_kswapd_high); - GETVM(pgscan_kswapd_normal); - GETVM(pgscan_kswapd_dma); - GETVM(pgscan_direct_high); - GETVM(pgscan_direct_normal); - GETVM(pgscan_direct_dma); - GETVM(pginodesteal); - GETVM(slabs_scanned); - GETVM(kswapd_steal); - GETVM(kswapd_inodesteal); - GETVM(pageoutrun); - GETVM(allocstall); - GETVM(pgrotated); - return 1; -} - - -/* These macro simplify the access to the Main data structure */ -#define DKDELTA(member) ( (q->dk[i].member > p->dk[i].member) ? 0 : (p->dk[i].member - q->dk[i].member)) -#define SIDELTA(member) ( (q->si.member > p->si.member) ? 0 : (p->si.member - q->si.member)) - -#define IFNAME 64 - -#define TIMEDELTA(member,index1,index2) ((p->procs[index1].member) - (q->procs[index2].member)) -#define COUNTDELTA(member) ( (q->procs[topper[j].other].member > p->procs[i].member) ? 0 : (p->procs[i].member - q->procs[topper[j].other].member) ) - -#define TIMED(member) ((double)(p->procs[i].member.tv_sec)) - -double *cpu_peak; /* ptr to array - 1 for each cpu - 0 = average for machine */ -double *disk_busy_peak; -double *disk_rate_peak; -double net_read_peak[NETMAX]; -double net_write_peak[NETMAX]; -int aiorunning; -int aiorunning_max = 0; -int aiocount; -int aiocount_max = 0; -float aiotime; -float aiotime_max = 0.0; - -char *dskgrp(int i) -{ - static char error_string[] = { "Too-Many-Disks" }; - static char *string[16] = { "", "1", "2", "3", - "4", "5", "6", "7", - "8", "9", "10", "11", - "12", "13", "14", "15" - }; - - i = (int) ((float) i / (float) disks_per_line); - if (0 <= i && i <= 15) - return string[i]; - return error_string; -} - -/* command checking against a list */ - -#define CMDMAX 64 - -char *cmdlist[CMDMAX]; -int cmdfound = 0; - -int cmdcheck(char *cmd) -{ - int i; -#ifdef CMDDEBUG - fprintf(stderr, "cmdfound=%d\n", cmdfound); - for (i = 0; i < cmdfound; i++) - fprintf(stderr, "cmdlist[%d]=\"%s\"\n", i, cmdlist[i]); -#endif /* CMDDEBUG */ - for (i = 0; i < cmdfound; i++) { - if (strlen(cmdlist[i]) == 0) - continue; - if (!strncmp(cmdlist[i], cmd, strlen(cmdlist[i]))) - return 1; - } - return 0; -} - -/* Convert secs + micro secs to a double */ -double doubletime(void) -{ - - gettimeofday(&p->tv, 0); - return ((double) p->tv.tv_sec + p->tv.tv_usec * 1.0e-6); -} - -void get_cpu_cnt() -{ - int i; - - /* Get CPU info from /proc/stat and populate proc[P_STAT] */ - proc_read(P_STAT); - - /* Start with index [1] as [0] contains overall CPU statistics */ - for (i = 1; i < proc[P_STAT].lines; i++) { - if (strncmp("cpu", proc[P_STAT].line[i], 3) == 0) - cpus = i; - else - break; - } - if (cpus >= CPUMAX) { - printf - ("This nmon supports only %d CPU threads (Logical CPUs) and the machine appears to have %d.\nnmon stopping as its unsafe to continue.\n", - CPUMAX, cpus); - exit(44); - } -} - -#if X86 || ARM -void get_intel_spec() -{ - int i; - int physicalcpu[256]; - int id; - - /* Get CPU info from /proc/stat and populate proc[P_STAT] */ - proc_read(P_CPUINFO); - - for (i = 0; i < 256; i++) - physicalcpu[i] = 0; - - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("vendor_id", proc[P_CPUINFO].line[i], 9) == 0) { - vendor_ptr = &proc[P_CPUINFO].line[i][12]; - } - } - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("model name", proc[P_CPUINFO].line[i], 10) == 0) { - model_ptr = &proc[P_CPUINFO].line[i][13]; - } - } - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("cpu MHz", proc[P_CPUINFO].line[i], 7) == 0) { - mhz_ptr = &proc[P_CPUINFO].line[i][11]; - } - } - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("bogomips", proc[P_CPUINFO].line[i], 8) == 0) { - bogo_ptr = &proc[P_CPUINFO].line[i][11]; - } - } - - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("physical id", proc[P_CPUINFO].line[i], 11) == 0) { - id = atoi(&proc[P_CPUINFO].line[i][15]); - if (id < 256) - physicalcpu[id] = 1; - } - } - for (i = 0; i < 256; i++) - if (physicalcpu[i] == 1) - processorchips++; - - /* Start with index [1] as [0] contains overall CPU statistics */ - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("siblings", proc[P_CPUINFO].line[i], 8) == 0) { - siblings = atoi(&proc[P_CPUINFO].line[i][11]); - break; - } - } - for (i = 0; i < proc[P_CPUINFO].lines; i++) { - if (strncmp("cpu cores", proc[P_CPUINFO].line[i], 9) == 0) { - cores = atoi(&proc[P_CPUINFO].line[i][12]); - break; - } - } - if (siblings > cores) - hyperthreads = siblings / cores; - else - hyperthreads = 0; -} -#endif - -int stat8 = 0; /* used to determine the number of variables on a cpu line in /proc/stat */ -int stat10 = 0; /* used to determine the number of variables on a cpu line in /proc/stat */ - - -void proc_cpu() -{ - int i; - int row; - static int intr_line = 0; - static int ctxt_line = 0; - static int btime_line = 0; - static int proc_line = 0; - static int run_line = 0; - static int block_line = 0; - static int proc_cpu_first_time = 1; - long long user; - long long nice; - long long sys; - long long idle; - long long iowait; - long long hardirq; - long long softirq; - long long steal; - long long guest; - long long guest_nice; - - /* Only read data once per interval */ - if (proc_cpu_done == 1) - return; - - /* If number of CPUs changed, then we need to find the index of intr_line, ... again */ - if (old_cpus != cpus) - intr_line = 0; - - if (proc_cpu_first_time) { - stat8 = - sscanf(&proc[P_STAT].line[0][5], - "%lld %lld %lld %lld %lld %lld %lld %lld", &user, &nice, - &sys, &idle, &iowait, &hardirq, &softirq, &steal); - stat10 = - sscanf(&proc[P_STAT].line[0][5], - "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", - &user, &nice, &sys, &idle, &iowait, &hardirq, &softirq, - &steal, &guest, &guest_nice); - proc_cpu_first_time = 0; - } - user = nice = sys = idle = iowait = hardirq = softirq = steal = guest = - guest_nice = 0; - if (stat10 == 10) { - sscanf(&proc[P_STAT].line[0][5], - "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", &user, - &nice, &sys, &idle, &iowait, &hardirq, &softirq, &steal, - &guest, &guest_nice); - } else { - if (stat8 == 8) { - sscanf(&proc[P_STAT].line[0][5], - "%lld %lld %lld %lld %lld %lld %lld %lld", &user, &nice, - &sys, &idle, &iowait, &hardirq, &softirq, &steal); - } else { /* stat 4 variables here as older Linux proc */ - sscanf(&proc[P_STAT].line[0][5], "%lld %lld %lld %lld", - &user, &nice, &sys, &idle); - } - } - p->cpu_total.user = user; - p->cpu_total.nice = nice; - p->cpu_total.idle = idle; - p->cpu_total.sys = sys; - p->cpu_total.wait = iowait; /* in the case of 4 variables = 0 */ - /* p->cpu_total.sys = sys + hardirq + softirq + steal; */ - - p->cpu_total.irq = hardirq; - p->cpu_total.softirq = softirq; - p->cpu_total.steal = steal; - p->cpu_total.guest = guest; - p->cpu_total.guest_nice = guest_nice; - -#ifdef DEBUG - if (debug) - fprintf(stderr, "XX user=%lld wait=%lld sys=%lld idle=%lld\n", - p->cpu_total.user, - p->cpu_total.wait, p->cpu_total.sys, p->cpu_total.idle); -#endif /*DEBUG*/ - for (i = 0; i < cpus; i++) { - user = nice = sys = idle = iowait = hardirq = softirq = steal = 0; - - /* allow for large CPU numbers */ - if (i + 1 > 1000) - row = 8; - else if (i + 1 > 100) - row = 7; - else if (i + 1 > 10) - row = 6; - else - row = 5; - - if (stat10 == 10) { - sscanf(&proc[P_STAT].line[i + 1][row], - "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", - &user, - &nice, - &sys, - &idle, - &iowait, - &hardirq, &softirq, &steal, &guest, &guest_nice); - - } else if (stat8 == 8) { - sscanf(&proc[P_STAT].line[i + 1][row], - "%lld %lld %lld %lld %lld %lld %lld %lld", - &user, - &nice, - &sys, &idle, &iowait, &hardirq, &softirq, &steal); - } else { - sscanf(&proc[P_STAT].line[i + 1][row], "%lld %lld %lld %lld", - &user, &nice, &sys, &idle); - } - p->cpuN[i].user = user; - p->cpuN[i].nice = nice; - p->cpuN[i].sys = sys; - p->cpuN[i].idle = idle; - p->cpuN[i].wait = iowait; - p->cpuN[i].irq = hardirq; - p->cpuN[i].softirq = softirq; - p->cpuN[i].steal = steal; - p->cpuN[i].guest = guest; - p->cpuN[i].guest_nice = guest_nice; - } - - if (intr_line == 0) { - if (proc[P_STAT].line[i + 1][0] == 'p' && - proc[P_STAT].line[i + 1][1] == 'a' && - proc[P_STAT].line[i + 1][2] == 'g' && - proc[P_STAT].line[i + 1][3] == 'e') { - /* 2.4 kernel */ - intr_line = i + 3; - ctxt_line = i + 5; - btime_line = i + 6; - proc_line = i + 7; - run_line = i + 8; - block_line = i + 9; - } else { - /* 2.6 kernel */ - intr_line = i + 1; - ctxt_line = i + 2; - btime_line = i + 3; - proc_line = i + 4; - run_line = i + 5; - block_line = i + 6; - } - } - p->cpu_total.intr = -1; - p->cpu_total.ctxt = -1; - p->cpu_total.btime = -1; - p->cpu_total.procs = -1; - p->cpu_total.running = -1; - p->cpu_total.blocked = -1; - if (proc[P_STAT].lines >= intr_line) - sscanf(&proc[P_STAT].line[intr_line][0], "intr %lld", - &p->cpu_total.intr); - if (proc[P_STAT].lines >= ctxt_line) - sscanf(&proc[P_STAT].line[ctxt_line][0], "ctxt %lld", - &p->cpu_total.ctxt); - if (proc[P_STAT].lines >= btime_line) - sscanf(&proc[P_STAT].line[btime_line][0], "btime %lld", - &p->cpu_total.btime); - if (proc[P_STAT].lines >= proc_line) - sscanf(&proc[P_STAT].line[proc_line][0], "processes %lld", - &p->cpu_total.procs); - if (proc[P_STAT].lines >= run_line) - sscanf(&proc[P_STAT].line[run_line][0], "procs_running %lld", - &p->cpu_total.running); - if (proc[P_STAT].lines >= block_line) - sscanf(&proc[P_STAT].line[block_line][0], "procs_blocked %lld", - &p->cpu_total.blocked); - - /* If we had a change in the number of CPUs, copy current interval data to the previous, so we - * get a "0" utilization interval, but better than negative or 100%. - * Heads-up - This effects POWER SMT changes too. - */ - if (old_cpus != cpus) { - memcpy((void *) &(q->cpu_total), (void *) &(p->cpu_total), - sizeof(struct cpu_stat)); - memcpy((void *) q->cpuN, (void *) p->cpuN, - sizeof(struct cpu_stat) * cpus); - } - - /* Flag that we processed /proc/stat data; re-set in proc_read() when we re-read /proc/stat */ - proc_cpu_done = 1; -} - -void proc_nfs() -{ - int i; - int j; - int len; - int lineno; - -/* sample /proc/net/rpc/nfs -net 0 0 0 0 -rpc 70137 0 0 -proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -proc3 22 0 27364 0 32 828 22 40668 0 1 0 0 0 0 0 0 0 0 1212 6 2 1 0 -proc4 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -*/ - if (proc[P_NFS].fp != 0) { - for (lineno = 0; lineno < proc[P_NFS].lines; lineno++) { - if (!strncmp("proc2 ", proc[P_NFS].line[lineno], 6)) { - /* client version 2 line readers "proc2 18 num num etc" */ - len = strlen(proc[P_NFS].line[lineno]); - for (j = 0, i = 8; i < len && j < NFS_V2_NAMES_COUNT; i++) { - if (proc[P_NFS].line[lineno][i] == ' ') { - p->nfs.v2c[j] = - atol(&proc[P_NFS].line[lineno][i + 1]); - nfs_v2c_found = 1; - j++; - } - } - } - if (!strncmp("proc3 ", proc[P_NFS].line[lineno], 6)) { - /* client version 3 line readers "proc3 22 num num etc" */ - len = strlen(proc[P_NFS].line[lineno]); - for (j = 0, i = 8; i < len && j < NFS_V3_NAMES_COUNT; i++) { - if (proc[P_NFS].line[lineno][i] == ' ') { - p->nfs.v3c[j] = - atol(&proc[P_NFS].line[lineno][i + 1]); - nfs_v3c_found = 1; - j++; - } - } - } - if (!strncmp("proc4 ", proc[P_NFS].line[lineno], 6)) { - /* client version 4 line readers "proc4 35 num num etc" */ - nfs_v4c_names_count = atoi(&proc[P_NFS].line[lineno][6]); - len = strlen(proc[P_NFS].line[lineno]); - for (j = 0, i = 8; i < len && j < nfs_v4c_names_count; i++) { - if (proc[P_NFS].line[lineno][i] == ' ') { - p->nfs.v4c[j] = - atol(&proc[P_NFS].line[lineno][i + 1]); - nfs_v4c_found = 1; - j++; - } - } - } - } - } -/* sample /proc/net/rpc/nfsd -rc 0 0 0 -fh 0 0 0 0 0 -io 0 0 -th 4 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 -ra 32 0 0 0 0 0 0 0 0 0 0 0 -net 0 0 0 0 -rpc 0 0 0 0 0 -proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -proc3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -proc4 2 0 0 -proc4ops 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -*/ - if (proc[P_NFSD].fp != 0) { - for (lineno = 0; lineno < proc[P_NFSD].lines; lineno++) { - if (!strncmp("proc2 ", proc[P_NFSD].line[lineno], 6)) { - /* server version 2 line readers "proc2 18 num num etc" */ - len = strlen(proc[P_NFSD].line[lineno]); - for (j = 0, i = 8; i < len && j < NFS_V2_NAMES_COUNT; i++) { - if (proc[P_NFSD].line[lineno][i] == ' ') { - p->nfs.v2s[j] = - atol(&proc[P_NFSD].line[lineno][i + 1]); - nfs_v2s_found = 1; - j++; - } - } - } - if (!strncmp("proc3 ", proc[P_NFSD].line[lineno], 6)) { - /* server version 3 line readers "proc3 22 num num etc" */ - len = strlen(proc[P_NFSD].line[lineno]); - for (j = 0, i = 8; i < len && j < NFS_V2_NAMES_COUNT; i++) { - if (proc[P_NFSD].line[lineno][i] == ' ') { - p->nfs.v3s[j] = - atol(&proc[P_NFSD].line[lineno][i + 1]); - nfs_v3s_found = 1; - j++; - } - } - } - if (!strncmp("proc4ops ", proc[P_NFSD].line[lineno], 9)) { - /* server version 4 line readers "proc4ops 40 num num etc" - NOTE: the "ops" hence starting in column 9 */ - nfs_v4s_names_count = atol(&proc[P_NFSD].line[lineno][9]); - len = strlen(proc[P_NFSD].line[lineno]); - for (j = 0, i = 11; i < len && j < nfs_v4s_names_count; - i++) { - if (proc[P_NFSD].line[lineno][i] == ' ') { - p->nfs.v4s[j] = - atol(&proc[P_NFSD].line[lineno][i + 1]); - nfs_v4s_found = 1; - j++; - } - } - } - } - } -} - -void proc_kernel() -{ - int i; - p->cpu_total.uptime = 0.0; - p->cpu_total.idletime = 0.0; - p->cpu_total.uptime = atof(proc[P_UPTIME].line[0]); - for (i = 0; i < strlen(proc[P_UPTIME].line[0]); i++) { - if (proc[P_UPTIME].line[0][i] == ' ') { - p->cpu_total.idletime = atof(&proc[P_UPTIME].line[0][i + 1]); - break; - } - } - - sscanf(&proc[P_LOADAVG].line[0][0], "%f %f %f", - &p->cpu_total.mins1, &p->cpu_total.mins5, &p->cpu_total.mins15); - -} - -char *proc_find_sb(char *p) -{ - for (; *p != 0; p++) - if (*p == ' ' && *(p + 1) == '(') - return p; - return 0; -} - -#define DISK_MODE_IO 1 -#define DISK_MODE_DISKSTATS 2 -#define DISK_MODE_PARTITIONS 3 - -int disk_mode = 0; - -void proc_disk_io(double elapsed) -{ - int diskline; - int i; - int ret; - char *str; - int fudged_busy; - - disks = 0; - for (diskline = 0; diskline < proc[P_STAT].lines; diskline++) { - if (strncmp("disk_io", proc[P_STAT].line[diskline], 7) == 0) - break; - } - for (i = 8; i < strlen(proc[P_STAT].line[diskline]); i++) { - if (proc[P_STAT].line[diskline][i] == ':') - disks++; - } - - str = &proc[P_STAT].line[diskline][0]; - for (i = 0; i < disks; i++) { - str = proc_find_sb(str); - if (str == 0) - break; - ret = sscanf(str, " (%d,%d):(%ld,%ld,%ld,%ld,%ld", - &p->dk[i].dk_major, - &p->dk[i].dk_minor, - &p->dk[i].dk_noinfo, - &p->dk[i].dk_reads, - &p->dk[i].dk_rkb, - &p->dk[i].dk_writes, &p->dk[i].dk_wkb); - if (ret != 7) - exit(7); - p->dk[i].dk_xfers = p->dk[i].dk_noinfo; - /* blocks are 512 bytes */ - p->dk[i].dk_rkb = p->dk[i].dk_rkb / 2; - p->dk[i].dk_wkb = p->dk[i].dk_wkb / 2; - - p->dk[i].dk_bsize = - (p->dk[i].dk_rkb + p->dk[i].dk_wkb) / p->dk[i].dk_xfers * 1024; - - /* assume a disk does 200 op per second */ - fudged_busy = (p->dk[i].dk_reads + p->dk[i].dk_writes) / 2; - if (fudged_busy > 100 * elapsed) - p->dk[i].dk_time += 100 * elapsed; - p->dk[i].dk_time = fudged_busy; - - sprintf(p->dk[i].dk_name, "dev-%d-%d", p->dk[i].dk_major, - p->dk[i].dk_minor); -/* fprintf(stderr,"disk=%d name=\"%s\" major=%d minor=%d\n", i,p->dk[i].dk_name, p->dk[i].dk_major,p->dk[i].dk_minor); */ - str++; - } -} - -void proc_diskstats(double elapsed) -{ - static FILE *fp = (FILE *) - 1; - char buf[1024]; - int i; - int ret; - - if (fp == (FILE *) - 1) { - if ((fp = fopen("/proc/diskstats", "r")) == NULL) { - /* DEBUG if( (fp = fopen("diskstats","r")) == NULL) { */ - error("failed to open - /proc/diskstats"); - disks = 0; - return; - } - } -/* - 2 0 fd0 1 0 2 13491 0 0 0 0 0 13491 13491 - 3 0 hda 41159 53633 1102978 620181 39342 67538 857108 4042631 0 289150 4668250 - 3 1 hda1 58209 58218 0 0 - 3 2 hda2 148 4794 10 20 - 3 3 hda3 65 520 0 0 - 3 4 hda4 35943 1036092 107136 857088 - 22 0 hdc 167 5394 22308 32250 0 0 0 0 0 22671 32250 <-- USB !! - 8 0 sda 990 2325 4764 6860 9 3 12 417 0 6003 7277 - 8 1 sda1 3264 4356 12 12 -*/ - for (i = 0; i < DISKMAX;) { - if (fgets(buf, 1024, fp) == NULL) - break; - /* zero the data ready for reading */ - p->dk[i].dk_major = - p->dk[i].dk_minor = - p->dk[i].dk_name[0] = - p->dk[i].dk_reads = - p->dk[i].dk_rmerge = - p->dk[i].dk_rkb = - p->dk[i].dk_rmsec = - p->dk[i].dk_writes = - p->dk[i].dk_wmerge = - p->dk[i].dk_wkb = - p->dk[i].dk_wmsec = - p->dk[i].dk_inflight = - p->dk[i].dk_time = p->dk[i].dk_backlog = 0; - - ret = - sscanf(&buf[0], - "%d %d %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", - &p->dk[i].dk_major, &p->dk[i].dk_minor, - &p->dk[i].dk_name[0], &p->dk[i].dk_reads, - &p->dk[i].dk_rmerge, &p->dk[i].dk_rkb, - &p->dk[i].dk_rmsec, &p->dk[i].dk_writes, - &p->dk[i].dk_wmerge, &p->dk[i].dk_wkb, - &p->dk[i].dk_wmsec, &p->dk[i].dk_inflight, - &p->dk[i].dk_time, &p->dk[i].dk_backlog); - if (ret == 7) { /* shuffle the data around due to missing columns for partitions */ - p->dk[i].dk_partition = 1; - p->dk[i].dk_wkb = p->dk[i].dk_rmsec; - p->dk[i].dk_writes = p->dk[i].dk_rkb; - p->dk[i].dk_rkb = p->dk[i].dk_rmerge; - p->dk[i].dk_rmsec = 0; - p->dk[i].dk_rmerge = 0; - - } else if (ret == 14) - p->dk[i].dk_partition = 0; - else - fprintf(stderr, - "disk sscanf wanted 14 but returned=%d line=%s\n", ret, - buf); - - p->dk[i].dk_rkb /= 2; /* sectors = 512 bytes */ - p->dk[i].dk_wkb /= 2; - p->dk[i].dk_xfers = p->dk[i].dk_reads + p->dk[i].dk_writes; - if (p->dk[i].dk_xfers == 0) - p->dk[i].dk_bsize = 0; - else - p->dk[i].dk_bsize = - ((p->dk[i].dk_rkb + - p->dk[i].dk_wkb) / p->dk[i].dk_xfers) * 1024; - - p->dk[i].dk_time /= 10.0; /* in milli-seconds to make it upto 100%, 1000/100 = 10 */ - - if (p->dk[i].dk_xfers > 0) - i++; - } - if (reread) { - fclose(fp); - fp = (FILE *) - 1; - } else - rewind(fp); - disks = i; -} - -void strip_spaces(char *s) -{ - char *p; - int spaced = 1; - - p = s; - for (p = s; *p != 0; p++) { - if (*p == ':') - *p = ' '; - if (*p != ' ') { - *s = *p; - s++; - spaced = 0; - } else if (spaced) { - /* do no thing as this is second space */ - } else { - *s = *p; - s++; - spaced = 1; - } - - } - *s = 0; -} - -void proc_partitions(double elapsed) -{ - static FILE *fp = (FILE *) - 1; - char buf[1024]; - int i = 0; - int ret; - - if (fp == (FILE *) - 1) { - if ((fp = fopen("/proc/partitions", "r")) == NULL) { - error("failed to open - /proc/partitions"); - partitions = 0; - return; - } - } - if (fgets(buf, 1024, fp) == NULL) - goto end; /* throw away the header lines */ - if (fgets(buf, 1024, fp) == NULL) - goto end; -/* -major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq - - 33 0 1052352 hde 2855 15 2890 4760 0 0 0 0 -4 7902400 11345292 - 33 1 1050304 hde1 2850 0 2850 3930 0 0 0 0 0 3930 3930 - 3 0 39070080 hda 9287 19942 226517 90620 8434 25707 235554 425790 -12 7954830 33997658 - 3 1 31744408 hda1 651 90 5297 2030 0 0 0 0 0 2030 2030 - 3 2 6138720 hda2 7808 19561 218922 79430 7299 20529 222872 241980 0 59950 321410 - 3 3 771120 hda3 13 41 168 80 0 0 0 0 0 80 80 - 3 4 1 hda4 0 0 0 0 0 0 0 0 0 0 0 - 3 5 408208 hda5 812 241 2106 9040 1135 5178 12682 183810 0 11230 192850 -*/ - for (i = 0; i < DISKMAX; i++) { - if (fgets(buf, 1024, fp) == NULL) - break; - strip_spaces(buf); - ret = - sscanf(&buf[0], - "%d %d %lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", - &p->dk[i].dk_major, &p->dk[i].dk_minor, - &p->dk[i].dk_blocks, (char *) &p->dk[i].dk_name, - &p->dk[i].dk_reads, &p->dk[i].dk_rmerge, - &p->dk[i].dk_rkb, &p->dk[i].dk_rmsec, - &p->dk[i].dk_writes, &p->dk[i].dk_wmerge, - &p->dk[i].dk_wkb, &p->dk[i].dk_wmsec, - &p->dk[i].dk_inflight, &p->dk[i].dk_use, - &p->dk[i].dk_aveq); - p->dk[i].dk_rkb /= 2; /* sectors = 512 bytes */ - p->dk[i].dk_wkb /= 2; - p->dk[i].dk_xfers = p->dk[i].dk_rkb + p->dk[i].dk_wkb; - if (p->dk[i].dk_xfers == 0) - p->dk[i].dk_bsize = 0; - else - p->dk[i].dk_bsize = - (p->dk[i].dk_rkb + - p->dk[i].dk_wkb) / p->dk[i].dk_xfers * 1024; - - p->dk[i].dk_time /= 10.0; /* in milli-seconds to make it upto 100%, 1000/100 = 10 */ - - if (ret != 15) { -#ifdef DEBUG - if (debug) - fprintf(stderr, "sscanf wanted 15 returned = %d line=%s\n", - ret, buf); -#endif /*DEBUG*/ - partitions_short = 1; - } else - partitions_short = 0; - } - end: - if (reread) { - fclose(fp); - fp = (FILE *) - 1; - } else - rewind(fp); - disks = i; -} - -void proc_disk(double elapsed) -{ - struct stat buf; - int ret; - if (disk_mode == 0) { - ret = stat("/proc/diskstats", &buf); - if (ret == 0) { - disk_mode = DISK_MODE_DISKSTATS; - } else { - ret = stat("/proc/partitions", &buf); - if (ret == 0) { - disk_mode = DISK_MODE_PARTITIONS; - } else { - disk_mode = DISK_MODE_IO; - } - } - } - switch (disk_mode) { - case DISK_MODE_IO: - proc_disk_io(elapsed); - break; - case DISK_MODE_DISKSTATS: - proc_diskstats(elapsed); - break; - case DISK_MODE_PARTITIONS: - proc_partitions(elapsed); - break; - } -} - -#undef isdigit -#define isdigit(ch) ( ( '0' <= (ch) && (ch) >= '9')? 0: 1 ) - -long proc_mem_search(char *s) -{ - int i; - int j; - int len; - len = strlen(s); - for (i = 0; i < proc[P_MEMINFO].lines; i++) { - if (!strncmp(s, proc[P_MEMINFO].line[i], len)) { - for (j = len; - !isdigit(proc[P_MEMINFO].line[i][j]) && - proc[P_MEMINFO].line[i][j] != 0; j++) - /* do nothing */ ; - return atol(&proc[P_MEMINFO].line[i][j]); - } - } - return -1; -} - -void proc_mem() -{ - if (proc[P_MEMINFO].read_this_interval == 0) - proc_read(P_MEMINFO); - - p->mem.memtotal = proc_mem_search("MemTotal"); - p->mem.memfree = proc_mem_search("MemFree"); - p->mem.memshared = proc_mem_search("MemShared"); - p->mem.buffers = proc_mem_search("Buffers"); - p->mem.cached = proc_mem_search("Cached"); - p->mem.swapcached = proc_mem_search("SwapCached"); - p->mem.active = proc_mem_search("Active"); - p->mem.inactive = proc_mem_search("Inactive"); - p->mem.hightotal = proc_mem_search("HighTotal"); - p->mem.highfree = proc_mem_search("HighFree"); - p->mem.lowtotal = proc_mem_search("LowTotal"); - p->mem.lowfree = proc_mem_search("LowFree"); - p->mem.swaptotal = proc_mem_search("SwapTotal"); - p->mem.swapfree = proc_mem_search("SwapFree"); -#ifdef LARGEMEM - p->mem.dirty = proc_mem_search("Dirty"); - p->mem.writeback = proc_mem_search("Writeback"); - p->mem.mapped = proc_mem_search("Mapped"); - p->mem.slab = proc_mem_search("Slab"); - p->mem.committed_as = proc_mem_search("Committed_AS"); - p->mem.pagetables = proc_mem_search("PageTables"); - p->mem.hugetotal = proc_mem_search("HugePages_Total"); - p->mem.hugefree = proc_mem_search("HugePages_Free"); - p->mem.hugesize = proc_mem_search("Hugepagesize"); -#else - p->mem.bigfree = proc_mem_search("BigFree"); -#endif /*LARGEMEM*/ -} - -#define MAX_SNAPS 72 -#define MAX_SNAP_ROWS 20 -#define SNAP_OFFSET 6 - -int next_cpu_snap = 0; -int cpu_snap_all = 0; - -struct { - double user; - double kernel; - double iowait; - double idle; - double steal; -} cpu_snap[MAX_SNAPS]; - -int snap_average() -{ - int i; - int end; - int total = 0; - - if (cpu_snap_all) - end = MAX_SNAPS; - else - end = next_cpu_snap; - - for (i = 0; i < end; i++) { - total = total + cpu_snap[i].user + cpu_snap[i].kernel; - } - return (total / end); -} - -void snap_clear() -{ - int i; - for (i = 0; i < MAX_SNAPS; i++) { - cpu_snap[i].user = 0; - cpu_snap[i].kernel = 0; - cpu_snap[i].iowait = 0; - cpu_snap[i].idle = 0; - cpu_snap[i].steal = 0; - } - next_cpu_snap = 0; - cpu_snap_all = 0; -} - -void plot_snap(WINDOW * pad) -{ - int i; - int j; - double k; - if (cursed) { - mvwprintw(pad, 0, 0, - " CPU +---Long-Term-------------------------------------------------------------+"); - mvwprintw(pad, 1, 0, "100%%-|"); - mvwprintw(pad, 2, 1, "95%%-|"); - mvwprintw(pad, 3, 1, "90%%-|"); - mvwprintw(pad, 4, 1, "85%%-|"); - mvwprintw(pad, 5, 1, "80%%-|"); - mvwprintw(pad, 6, 1, "75%%-|"); - mvwprintw(pad, 7, 1, "70%%-|"); - mvwprintw(pad, 8, 1, "65%%-|"); - mvwprintw(pad, 9, 1, "60%%-|"); - mvwprintw(pad, 10, 1, "55%%-|"); - mvwprintw(pad, 11, 1, "50%%-|"); - mvwprintw(pad, 12, 1, "45%%-|"); - mvwprintw(pad, 13, 1, "40%%-|"); - mvwprintw(pad, 14, 1, "35%%-|"); - mvwprintw(pad, 15, 1, "30%%-|"); - mvwprintw(pad, 16, 1, "25%%-|"); - mvwprintw(pad, 17, 1, "20%%-|"); - mvwprintw(pad, 18, 1, "15%%-|"); - mvwprintw(pad, 19, 1, "10%%-|"); - mvwprintw(pad, 20, 1, " 5%%-|"); - - mvwprintw(pad, 21, 4, - " +-------------------------------------------------------------------------+"); - if (colour) { - COLOUR wattrset(pad, COLOR_PAIR(2)); - mvwprintw(pad, 0, 26, "User%%"); - COLOUR wattrset(pad, COLOR_PAIR(1)); - mvwprintw(pad, 0, 36, "System%%"); - COLOUR wattrset(pad, COLOR_PAIR(4)); - mvwprintw(pad, 0, 49, "Wait%%"); - COLOUR wattrset(pad, COLOR_PAIR(5)); - mvwprintw(pad, 0, 59, "Steal%%"); - COLOUR wattrset(pad, COLOR_PAIR(0)); - } - - for (j = 0; j < MAX_SNAPS; j++) { - for (i = 0; i < MAX_SNAP_ROWS; i++) { - wmove(pad, MAX_SNAP_ROWS - i, j + SNAP_OFFSET); - if (cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait + cpu_snap[j].idle + cpu_snap[j].steal == 0) { /* if not all zeros */ - COLOUR wattrset(pad, COLOR_PAIR(0)); - wprintw(pad, " "); - } else if ((cpu_snap[j].user / 100 * MAX_SNAP_ROWS) > - i + 0.5) { - COLOUR wattrset(pad, COLOR_PAIR(9)); - wprintw(pad, "U"); - } else if ((cpu_snap[j].user + cpu_snap[j].kernel) / 100 * - MAX_SNAP_ROWS > i + 0.5) { - COLOUR wattrset(pad, COLOR_PAIR(8)); - wprintw(pad, "s"); - } else - if ((cpu_snap[j].user + cpu_snap[j].kernel + - cpu_snap[j].iowait) / 100 * MAX_SNAP_ROWS > - i + 0.5) { - COLOUR wattrset(pad, COLOR_PAIR(10)); - wprintw(pad, "w"); - } else if ((cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait + cpu_snap[j].idle) / 100 * MAX_SNAP_ROWS > i) { /*no +0.5 or too few Steal's */ - COLOUR wattrset(pad, COLOR_PAIR(0)); - wprintw(pad, " "); - } else if (cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait + cpu_snap[j].idle + cpu_snap[j].steal > i) { /* if not all zeros */ - COLOUR wattrset(pad, COLOR_PAIR(5)); - wprintw(pad, "S"); - } - } - k = cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait; - if (0.1 < k && k < 5.0) { /* not zero but less than 5% */ - wmove(pad, MAX_SNAP_ROWS, j + SNAP_OFFSET); - COLOUR wattrset(pad, COLOR_PAIR(2)); - wprintw(pad, "_"); - } - } - COLOUR wattrset(pad, COLOR_PAIR(0)); - for (i = 0; i < MAX_SNAP_ROWS; i++) { - wmove(pad, MAX_SNAP_ROWS - i, next_cpu_snap + SNAP_OFFSET); - wprintw(pad, "|"); - } - wmove(pad, MAX_SNAP_ROWS + 1 - (snap_average() / 5), - next_cpu_snap + SNAP_OFFSET); - wprintw(pad, "+"); - if (dotline) { - for (i = 0; i < MAX_SNAPS; i++) { - wmove(pad, MAX_SNAP_ROWS + 1 - dotline * 2, - i + SNAP_OFFSET); - wprintw(pad, "+"); - } - dotline = 0; - } - } -} - -/* This saves the CPU overall usage for later ploting on the screen */ -void save_snap(double user, double kernel, double iowait, double idle, - double steal) -{ - cpu_snap[next_cpu_snap].user = user; - cpu_snap[next_cpu_snap].kernel = kernel; - cpu_snap[next_cpu_snap].iowait = iowait; - cpu_snap[next_cpu_snap].idle = idle; - cpu_snap[next_cpu_snap].steal = steal; - next_cpu_snap++; - if (next_cpu_snap >= MAX_SNAPS) { - next_cpu_snap = 0; - cpu_snap_all = 1; - } -} - -void plot_smp(WINDOW * pad, int cpu_no, int row, double user, - double kernel, double iowait, double idle, double steal) -{ - int i; - int peak_col; - - if (show_rrd) - return; - - if (cpu_peak[cpu_no] < (user + kernel + iowait)) - cpu_peak[cpu_no] = - (double) ((int) user / 2 + (int) kernel / 2 + - (int) iowait / 2) * 2.0; - - if (cursed) { - if (cpu_no == 0) - mvwprintw(pad, row, 0, "Avg"); - else - mvwprintw(pad, row, 0, "%3d", cpu_no); - mvwprintw(pad, row, 3, "% 6.1lf", user); - mvwprintw(pad, row, 9, "% 6.1lf", kernel); - mvwprintw(pad, row, 15, "% 6.1lf", iowait); - if (steal) { - mvwprintw(pad, row, 21, "% 6.1lf", steal); - } else { - mvwprintw(pad, row, 21, "% 6.1lf", idle); - } - mvwprintw(pad, row, 27, "|"); - wmove(pad, row, 28); - for (i = 0; i < (int) (user / 2); i++) { - COLOUR wattrset(pad, COLOR_PAIR(9)); - wprintw(pad, "U"); - } - for (i = 0; i < (int) (kernel / 2); i++) { - COLOUR wattrset(pad, COLOR_PAIR(8)); - wprintw(pad, "s"); - } - for (i = 0; i < (int) (iowait / 2); i++) { - COLOUR wattrset(pad, COLOR_PAIR(10)); - wprintw(pad, "W"); - } - COLOUR wattrset(pad, COLOR_PAIR(0)); - for (i = 0; i <= (int) (idle / 2); i++) { /* added "=" to try to conteract missing halves */ -#ifdef POWER - if (lparcfg.smt_mode > 1 - && ((cpu_no - 1) % lparcfg.smt_mode) == 0 && (i % 2)) - wprintw(pad, "."); - else -#endif - wprintw(pad, " "); - } - for (i = 0; i < (int) ((steal + 1) / 2); i++) { - COLOUR wattrset(pad, COLOR_PAIR(5)); - wprintw(pad, "S"); - } - COLOUR wattrset(pad, COLOR_PAIR(0)); - mvwprintw(pad, row, 77, "| "); - - peak_col = 28 + (int) (cpu_peak[cpu_no] / 2); - if (peak_col > 77) - peak_col = 77; - mvwprintw(pad, row, peak_col, ">"); - } else { - /* Sanity check the numnbers */ - if (user < 0.0 || kernel < 0.0 || iowait < 0.0 || idle < 0.0 - || idle > 100.0 || steal < 0) { - user = kernel = iowait = idle = steal = 0; - } - - if (first_steal && steal > 0) { - fprintf(fp, "AAA,steal,1\n"); - first_steal = 0; - } - if (cpu_no == 0) - fprintf(fp, "CPU_ALL,%s,%.1lf,%.1lf,%.1lf,%.1f,%.1lf,,%d\n", - LOOP, user, kernel, iowait, idle, steal, cpus); - else { - fprintf(fp, "CPU%03d,%s,%.1lf,%.1lf,%.1lf,%.1lf,%.1f\n", - cpu_no, LOOP, user, kernel, iowait, idle, steal); - } - } -} - -/* Added variable to remember started children - * 0 - start - * 1 - snap - * 2 - end -*/ -#define CHLD_START 0 -#define CHLD_SNAP 1 -#define CHLD_END 2 -int nmon_children[3] = { -1, -1, -1 }; - -void init_pairs() -{ - COLOUR init_pair((short) 0, (short) 7, (short) 0); /* White */ - COLOUR init_pair((short) 1, (short) 1, (short) 0); /* Red */ - COLOUR init_pair((short) 2, (short) 2, (short) 0); /* Green */ - COLOUR init_pair((short) 3, (short) 3, (short) 0); /* Yellow */ - COLOUR init_pair((short) 4, (short) 4, (short) 0); /* Blue */ - COLOUR init_pair((short) 5, (short) 5, (short) 0); /* Magenta */ - COLOUR init_pair((short) 6, (short) 6, (short) 0); /* Cyan */ - COLOUR init_pair((short) 7, (short) 7, (short) 0); /* White */ - COLOUR init_pair((short) 8, (short) 0, (short) 1); /* Red background, red text */ - COLOUR init_pair((short) 9, (short) 0, (short) 2); /* Green background, green text */ - COLOUR init_pair((short) 10, (short) 0, (short) 4); /* Blue background, blue text */ - COLOUR init_pair((short) 11, (short) 0, (short) 3); /* Yellow background, yellow text */ - COLOUR init_pair((short) 12, (short) 0, (short) 6); /* Cyan background, cyan text */ -} - -/* Signal handler - * SIGUSR1 or 2 is used to stop nmon cleanly - * SIGWINCH is used when the window size is changed - */ -void interrupt(int signum) -{ - int child_pid; - int waitstatus; - if (signum == SIGCHLD) { - while ((child_pid = waitpid(0, &waitstatus, 0)) == -1) { - if (errno == EINTR) /* retry */ - continue; - return; /* ECHLD, EFAULT */ - } - if (child_pid == nmon_children[CHLD_SNAP]) - nmon_children[CHLD_SNAP] = -1; - signal(SIGCHLD, interrupt); - return; - } - if (signum == SIGUSR1 || signum == SIGUSR2) { - maxloops = loop; - return; - } - if (signum == SIGWINCH) { - CURSE endwin(); /* stop + start curses so it works out the # of row and cols */ - CURSE initscr(); - CURSE cbreak(); - signal(SIGWINCH, interrupt); - COLOUR colour = has_colors(); - COLOUR start_color(); - COLOUR init_pairs(); - CURSE clear(); - return; - } - CURSE endwin(); - exit(0); -} - - -/* only place the q=previous and p=currect pointers are modified */ -void switcher(void) -{ - static int which = 1; - int i; - - if (which) { - p = &database[0]; - q = &database[1]; - which = 0; - } else { - p = &database[1]; - q = &database[0]; - which = 1; - } - if (flash_on) - flash_on = 0; - else - flash_on = 1; - - /* Reset flags so /proc/... is re-read in next interval */ - for (i = 0; i < P_NUMBER; i++) { - proc[i].read_this_interval = 0; - } -#ifdef POWER - lparcfg_processed = 0; -#endif -} - - -/* Lookup the right string */ -char *status(int n) -{ - switch (n) { - case 0: - return "Run "; - default: - return "Sleep"; - } -} - -/* Lookup the right process state string */ -char *get_state(char n) -{ - static char duff[64]; - switch (n) { - case 'R': - return "Running "; - case 'S': - return "Sleeping "; - case 'D': - return "DiskSleep"; - case 'Z': - return "Zombie "; - case 'T': - return "Traced "; - case 'W': - return "Paging "; - default: - sprintf(duff, "%d", n); - return duff; - } -} - -#ifdef GETUSER -/* Convert User id (UID) to a name with caching for speed - * getpwuid() should be NFS/yellow pages safe - */ -char *getuser(uid_t uid) -{ -#define NAMESIZE 16 - struct user_info { - uid_t uid; - char name[NAMESIZE]; - }; - static struct user_info *u = NULL; - static int used = 0; - int i; - struct passwd *pw; - - i = 0; - if (u != NULL) { - for (i = 0; i < used; i++) { - if (u[i].uid == uid) { - return u[i].name; - } - } - u = (struct user_info *) REALLOC(u, - (sizeof(struct user_info) * - (i + 1))); - } else - u = (struct user_info *) MALLOC(sizeof(struct user_info)); - used++; - - /* failed to find a match so add it */ - u[i].uid = uid; - pw = getpwuid(uid); - - if (pw != NULL) - strncpy(u[i].name, pw->pw_name, NAMESIZE); - else - sprintf(u[i].name, "unknown%d", uid); - return u[i].name; -} -#endif /* GETUSER */ - -/* User Defined Disk Groups */ - -char *save_word(char *in, char *out) -{ - int len; - int i; - len = strlen(in); - out[0] = 0; - for (i = 0; i < len; i++) { - if (isalnum(in[i]) || in[i] == '_' || in[i] == '-' || in[i] == '/') { - out[i] = in[i]; - out[i + 1] = 0; - } else - break; - } - for (; i < len; i++) - if (isalnum(in[i])) - return &in[i]; - return &in[i]; -} - -#define DGROUPS 64 -#define DGROUPITEMS 512 - -char *dgroup_filename; -char *dgroup_name[DGROUPS]; -int *dgroup_data; -int dgroup_disks[DGROUPS]; -int dgroup_total_disks = 0; -int dgroup_total_groups; - -void load_dgroup(struct dsk_stat *dk) -{ - FILE *gp; - char line[4096]; - char name[1024]; - int i, j; - char *nextp; - - if (dgroup_loaded == 2) - return; - dgroup_data = MALLOC(sizeof(int) * DGROUPS * DGROUPITEMS); - for (i = 0; i < DGROUPS; i++) - for (j = 0; j < DGROUPITEMS; j++) - dgroup_data[i * DGROUPITEMS + j] = -1; - - gp = fopen(dgroup_filename, "r"); - - if (gp == NULL) { - perror("opening disk group file"); - fprintf(stderr, "ERROR: failed to open %s\n", dgroup_filename); - exit(9); - } - - for (dgroup_total_groups = 0; - fgets(line, 4096 - 1, gp) != NULL - && dgroup_total_groups < DGROUPS; dgroup_total_groups++) { - /* ignore lines starting with # */ - if (line[0] == '#') { /* was a comment line */ - /* Decrement dgroup_total_groups by 1 to correct index for next loop */ - --dgroup_total_groups; - continue; - } - /* save the name */ - nextp = save_word(line, name); - if (strlen(name) == 0) { /* was a blank line */ - fprintf(stderr, - "ERROR nmon:ignoring odd line in diskgroup file \"%s\"\n", - line); - /* Decrement dgroup_total_groups by 1 to correct index for next loop */ - --dgroup_total_groups; - continue; - } - /* Added +1 to be able to correctly store the terminating \0 character */ - dgroup_name[dgroup_total_groups] = MALLOC(strlen(name) + 1); - strcpy(dgroup_name[dgroup_total_groups], name); - - /* save the hdisks */ - for (i = 0; i < DGROUPITEMS && *nextp != 0; i++) { - nextp = save_word(nextp, name); - for (j = 0; j < disks; j++) { - if (strcmp(dk[j].dk_name, name) == 0) { - /*DEBUG printf("DGadd group=%s,name=%s,disk=%s,dgroup_total_groups=%d,dgroup_total_disks=%d,j=%d,i=%d,index=%d.\n", - dgroup_name[dgroup_total_groups], - name, dk[j].dk_name, dgroup_total_groups, dgroup_total_disks, j, i,dgroup_total_groups*DGROUPITEMS+i); - */ - dgroup_data[dgroup_total_groups * DGROUPITEMS + i] = j; - dgroup_disks[dgroup_total_groups]++; - dgroup_total_disks++; - break; - } - } - if (j == disks) - fprintf(stderr, - "ERROR nmon:diskgroup file - failed to find disk=%s for group=%s disks known=%d\n", - name, dgroup_name[dgroup_total_groups], disks); - } - } - fclose(gp); - dgroup_loaded = 2; -} - - -void list_dgroup(struct dsk_stat *dk) -{ - int i, j, k, n; - int first = 1; - - /* DEBUG for (n = 0, i = 0; i < dgroup_total_groups; i++) { - fprintf(fp, "CCCG,%03d,%s", n++, dgroup_name[i]); - for (j = 0; j < dgroup_disks[i]; j++) { - if (dgroup_data[i*DGROUPITEMS+j] != -1) { - fprintf(fp, ",%d=%d", j, dgroup_data[i*DGROUPITEMS+j]); - } - } - fprintf(fp, "\n"); - } - */ - if (!show_dgroup) - return; - - for (n = 0, i = 0; i < dgroup_total_groups; i++) { - if (first) { - fprintf(fp, "BBBG,%03d,User Defined Disk Groups Name,Disks\n", - n++); - first = 0; - } - fprintf(fp, "BBBG,%03d,%s", n++, dgroup_name[i]); - for (k = 0, j = 0; j < dgroup_disks[i]; j++) { - if (dgroup_data[i * DGROUPITEMS + j] != -1) { - fprintf(fp, ",%s", - dk[dgroup_data[i * DGROUPITEMS + j]].dk_name); - k++; - } - /* add extra line if we have lots to stop spreadsheet line width problems */ - if (k == 128) { - fprintf(fp, "\nBBBG,%03d,%s continued", n++, - dgroup_name[i]); - } - } - fprintf(fp, "\n"); - } - fprintf(fp, "DGBUSY,Disk Group Busy %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGREAD,Disk Group Read KB/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGWRITE,Disk Group Write KB/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGSIZE,Disk Group Block Size KB %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGXFER,Disk Group Transfers/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - - /* If requested provide additional data available in /proc/diskstats */ - if (extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS) { - fprintf(fp, "DGREADS,Disk Group read/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGREADMERGE,Disk Group merged read/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGREADSERV,Disk Group read service time (SUM ms) %s", - hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGWRITES,Disk Group write/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGWRITEMERGE,Disk Group merged write/s %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, - "DGWRITESERV,Disk Group write service time (SUM ms) %s", - hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGINFLIGHT,Disk Group in flight IO %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGIOTIME,Disk Group time spent for IO (ms) %s", - hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - fprintf(fp, "DGBACKLOG,Disk Group Backlog time (ms) %s", hostname); - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] != 0) - fprintf(fp, ",%s", dgroup_name[i]); - } - fprintf(fp, "\n"); - } -} - -int is_dgroup_name(char *name) -{ - int i; - for (i = 0; i < DGROUPS; i++) { - if (dgroup_name[i] == (char *) 0) - return 0; - if (strncmp(name, dgroup_name[i], strlen(name)) == 0) - return 1; - } - return 0; -} - - - -void hint(void) -{ - printf("Hint for %s version %s\n", progname, VERSION); - printf("\tFull Help Info : %s -h\n\n", progname); - printf("\tOn-screen Stats: %s\n", progname); - printf - ("\tData Collection: %s -f [-s ] [-c ] [-t|-T]\n", - progname); - printf("\tCapacity Plan : %s -x\n", progname); - printf("Interactive-Mode:\n"); - printf - ("\tRead the Welcome screen & at any time type: \"h\" for more help\n"); - printf("\tType \"q\" to exit nmon\n\n"); - printf("For Data-Collect-Mode\n"); - printf - ("\t-f Must be the first option on the line (switches off interactive mode)\n"); - printf - ("\t Saves data to a CSV Spreadsheet format .nmon file in then local directory\n"); - printf - ("\t Note: -f sets a defaults -s300 -c288 which you can then modify\n"); - printf("\tFurther Data Collection Options:\n"); - printf("\t-s time between data snapshots\n"); - printf("\t-c of snapshots before exiting\n"); - printf - ("\t-t Includes Top Processes stats (-T also collects command arguments)\n"); - printf - ("\t-x Capacity Planning=15 min snapshots for 1 day. (nmon -ft -s 900 -c 96)\n"); - printf("---- End of Hints\n"); -} - -void help(void) -{ - hint(); - printf("---- Full Help Information for %s\n\n", SccsId); - printf("For Interactive and Data Collection Mode:\n"); - printf("\tUser Defined Disk Groups (DG) - This works in both modes\n"); - printf ("\tIt is a work around Linux issues, where disks & partitions are mixed up in /proc files\n"); - printf ("\t& drive driver developers use bizarre device names, making it trick to separate them.\n"); - printf("\t-g Use this file to define the groups\n"); - printf ("\t - On each line: group-name (space separated list)\n"); - printf("\t - Example line: database sdb sdc sdd sde\n"); - printf("\t - Up to 64 disk groups, 512 disks per line\n"); - printf ("\t - Disks names can appear more than one group\n"); - printf ("\t-g auto - Will generate a file called \"auto\" with just disks from \"lsblk|grep disk\" output\n"); - printf("\t For Interactive use define the groups then type: g or G\n"); - printf ("\t For Data Capture defining the groups switches on data collection\n"); - printf("\n"); - printf ("Data-Collect-Mode = spreadsheet format (i.e. comma separated values)\n"); - printf ("\tNote: Use only one of f, F, R, x, X or z to switch on Data Collection mode\n"); - printf ("\tNote: Make it the first argument then use other options to modify the defaults\n"); - printf ("\tNote: Don't collect data that you don't want - it just makes the files too large\n"); - printf ("\tNote: Too many snapshots = too much data and crashes Analyser and other tools\n"); - printf ("\tNote: 500 to 800 snapshots make a good graph on a normal size screen\n"); - printf ("\tRecommended normal minimal options: snapshots every 2 minutes all day: \n"); - printf("\t\tSimple capture: nmon -f -s 120 -c 720\n"); - printf("\t\tWith Top Procs: nmon -fT -s 120 -c 720\n"); - printf ("\t\tSet the directory: nmon -fT -s 120 -c 720 -m /home/nag/nmon\n"); - printf - ("\t\tCapture a busy hour: nmon -fT -s 5 -c 720 -m /home/nag/nmon\n"); - printf("\n"); - printf("For Data-Collect-Mode Options\n"); - printf - ("\t-f spreadsheet output format [note: default -s300 -c288]\n"); - printf("\t\t\t output file is _YYYYMMDD_HHMM.nmon\n"); - printf("\t-F same as -f but user supplied filename\n"); - printf("\t\t\t Not recommended as the default file name is perfect\n"); - printf("\tThe other options in alphabetical order:\n"); - printf("\t-a Include Accelerator GPU stats\n"); - printf - ("\t-b Online only: for black and white mode (switch off colour)\n"); - printf("\t-c The number of snapshots before nmon stops\n"); - printf - ("\t-d To set the maximum number of disks [default 256]\n"); - printf - ("\t Ignores disks if the systems has 100's of disk or the config is odd!\n"); - printf - ("\t-D Use with -g to add the Disk Wait/Service Time & in-flight stats\n"); - printf("\t-f and -F See above\n"); - printf - ("\t-g User Defined Disk Groups (see above) - Data Capture: Generates BBBG & DG lines\n"); - printf - ("\t-g auto See above but makes the file \"auto\" for you of just the disks like sda etc.\n"); - printf("\t-h This help output\n"); - printf - ("\t-I Set the ignore process & disks busy threshold (default 0.1%%)\n"); - printf - ("\t Don't save or show proc/disk using less than this percent\n"); - printf - ("\t-l Disks per line in data capture to avoid spreadsheet width issues. Default 150. EMC=64.\n"); - printf - ("\t-m nmon changes to this directory before saving to file\n"); - printf("\t Useful when starting nmon via cron\n"); - printf - ("\t-M Adds MHz stats for each CPU thread. Some POWER8 model CPU cores can be different frequencies\n"); - printf - ("\t-N Include NFS Network File System for V2, V3 and V4\n"); - printf - ("\t-p nmon outputs the PID when it starts. Useful in scripts to capture the PID for a later safe stop.\n"); - printf - ("\t-r Use in a benchmark to record the run details for later analysis [default hostname]\n"); - printf - ("\t-R Old rrdtool format used by some - may be removed in the future. If you use this email Nigel\n"); - printf - ("\t-s Time between snap shots - with \"-c count\" decides duration of the data capture\n"); - printf("\t-t Include Top Processes in the output\n"); - printf - ("\t-T As -t plus it saves command line arguments in UARG section\n"); - printf - ("\t-U Include the Linux 10 CPU utilisation stats (CPUUTIL lines in the file)\n"); - printf("\t-V Print nmon version & exit immediately\n"); - printf("\n"); - printf("\tTo manually load nmon files into a spreadsheet:\n"); - printf("\t\tsort -A *nmon >stats.csv\n"); - printf("\t\tTransfer the stats.csv file to your PC\n"); - printf - ("\t\tStart spreadsheet & then Open with type=comma-separated-value ASCII file\n"); - printf("\t\tThis puts every datum in a different cell\n"); - printf - ("\t\tNow select the data of one type (same 1st column) and graph it\n"); - printf - ("\t\tThe nmon Analyser & other tools do not need the file sorted.\n"); - printf("\n"); - printf("Capacity Planning mode - use cron to run each day\n"); - printf("\t-x Sensible spreadsheet output for one day\n"); - printf - ("\t Every 15 mins for 1 day ( i.e. -ft -s 900 -c 96)\n"); - printf("\t-X Sensible spreadsheet output for busy hour\n"); - printf - ("\t Every 30 secs for 1 hour ( i.e. -ft -s 30 -c 120)\n"); - printf - ("\t-z Like -x but the output saved in /var/perf/tmp assuming root user\n"); - printf("\n"); - - printf("Interactive Mode Keys in Alphabetical Order\n"); - printf - (" Start nmon then type the letters below to switch on & off particular stats\n"); - printf(" The stats are always in the same order on-screen\n"); - printf - (" To see more stats: make the font smaller or use two windows\n\n"); - printf("\tKey --- Toggles on off to control what is displayed ---\n"); -#ifdef NVIDIA_GPU - printf("\ta = Accelerator from Nvidia GPUs\n"); -#endif /*NVIDIA_GPU */ - printf - ("\tb = Black and white mode (or use -b command line option)\n"); - printf - ("\tc = CPU Utilisation stats with bar graphs (CPU core threads)\n"); - printf - ("\tC = CPU Utilisation as above but concise wide view (up to 192 CPUs)\n"); - printf("\td = Disk I/O Busy%% & Graphs of Read and Write KB/s\n"); - printf - ("\tD = Disk I/O Numbers including Transfers, Average Block Size & Peaks (type: 0 to reset)\n"); - printf - ("\tg = User Defined Disk Groups (assumes -g when starting nmon)\n"); - printf - ("\tG = Change Disk stats (d) to just disks (assumes -g auto when starting nmon)\n"); - printf("\th = This help information\n"); - printf("\tj = File Systems including Journal File Systems\n"); - printf - ("\tk = Kernel stats Run Queue, context-switch, fork, Load Average & Uptime\n"); - printf - ("\tl = Long term Total CPU (over 75 snapshots) via bar graphs\n"); - printf("\tL = Large and =Huge memory page stats\n"); - printf("\tm = Memory & Swap stats\n"); - printf - ("\tM = MHz for machines with variable frequency 1st=Threads 2nd=Cores 3=Graphs\n"); - printf - ("\tn = Network stats & errors (if no errors it disappears)\n"); - printf("\tN = NFS - Network File System\n"); - printf("\t 1st NFS V2 & V3, 2nd=NFS4-Client & 3rd=NFS4-Server\n"); - printf - ("\to = Disk I/O Map (one character per disk pixels showing how busy it is)\n"); - printf("\t Particularly good if you have 100's of disks \n"); -#ifdef PARTITIONS - printf("\tP = Partitions Disk I/O Stats\n"); -#endif -#ifdef POWER - printf("\tp = PowerVM LPAR Stats from /proc/ppc64/lparcfg\n"); -#endif - printf("\tq = Quit\n"); - printf - ("\tr = Resources: Machine type, name, cache details & OS version & Distro + LPAR\n"); - printf - ("\tt = Top Processes: select the data & order 1=Basic, 3=Perf 4=Size 5=I/O=root only\n"); - printf("\tu = Top Process with command line details\n"); - printf("\tU = CPU utilisation stats - all 10 Linux stats:\n"); - printf - ("\t user, user_nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice\n"); - printf - ("\tv = Experimental Verbose mode - tries to make recommendations\n"); - printf("\tV = Virtual Memory stats\n"); - printf("\n"); - printf("\tKey --- Other Interactive Controls ---\n"); - printf("\t+ = Double the screen refresh time\n"); - printf("\t- = Halves the screen refresh time\n"); - printf - ("\t0 = Reset peak counts to zero (peak highlight with \">\")\n"); - printf("\t1 = Top Processes mode 1 Nice, Priority, Status\n"); - printf("\t3 = Top Processes mode 3 CPU, Memory, Faults\n"); - printf("\t4 = Top Processes mode 4 as 3 but order by memory\n"); - printf - ("\t5 = Top Processes mode 5 as 3 but order by I/O (if root user)\n"); - printf("\t6 = Highlights 60%% row on Long Term CPU view\n"); - printf("\t7 = Highlights 70%% row on Long Term CPU view\n"); - printf("\t8 = Highlights 80%% row on Long Term CPU view\n"); - printf("\t9 = Highlights 90%% row on Long Term CPU view\n"); - printf - ("\t. = Minimum mode i.e. only busy disks and processes shown\n"); - printf("\tspace = Refresh screen now\n"); - - printf("\n"); - printf("Interactive Start-up Control\n"); - printf - ("\tIf you find you always type the same toggles every time you start\n"); - printf("\tthen place them in the NMON shell variable. For example:\n"); - printf("\t export NMON=cmdrtn\n"); - - printf("\n"); - printf("Other items for Interactive and Data Collection mode:\n"); - printf - ("\ta) To limit the processes nmon lists (online and to a file)\n"); - printf - ("\t either set NMONCMD0 to NMONCMD63 to the program names\n"); - printf("\t or use -C cmd:cmd:cmd etc. example: -C ksh:vi:syncd\n"); - printf("Other items for Data Collection mode:\n"); - printf("\tb) To you want to stop nmon use: kill -USR2 \n"); - printf("\tc) Use -p and nmon outputs the background process pid\n"); - printf - ("\td) If you want to pipe nmon output to other commands use a FIFO:\n"); - printf("\t mkfifo /tmp/mypipe\n"); - printf("\t nmon -F /tmp/mypipe &\n"); - printf("\t tail -f /tmp/mypipe\n"); - printf("\te) If nmon fails please report it with:\n"); - printf("\t 1) nmon version like: %s\n", VERSION); - printf - ("\t 2) the output of: cd /proc; cat cpuinfo meminfo partitions stat vmstat\n"); - printf("\t 3) some clue of what you were doing\n"); - printf - ("\t 4) I may ask you to run the debug version or collect data files\n"); - printf - ("\tf) If box & line characters are letters then check: terminal emulator & $TERM\n"); - printf - ("\tg) External Data Collectors - nmon will execute a command or script at each snapshot time\n"); - printf - ("\t They must output to a different file which is merge afterwards with the nmon output\n"); - printf("\t Set the following shell variables:\n"); - printf - ("\t NMON_START = script to generate CVS Header test line explaining the columns\n"); - printf - ("\t Generate: TabName,DataDescription,Column_name_and_units,Column_name_and_units ... \n"); - printf - ("\t NMON_SNAP = script for each snapshots data, the parameter is the T0000 snapshot number\n"); - printf("\t Generate: TabName,T00NN,Data,Data,Data ...\n"); - printf - ("\t NMON_END = script to clean up or finalise the data\n"); - printf - ("\t NMON_ONE_IN = call NMON_START less often (if it is heavy in CPU terms)\n"); - printf - ("\t Once capture done: cat nmon-file data-file >merged-file ; ready for Analyser or other tools\n"); - printf - ("\t The nmon Analyser will automatically do its best to graph the data on a new Tab sheet\n"); - printf("\n"); - printf - ("\tDeveloper: Nigel Griffiths See http://nmon.sourceforge.net\n"); - printf("\tFeedback welcome - On the current release only\n"); - printf("\tNo warranty given or implied. Copyright GPLv3\n"); - exit(0); -} - -#define JFSMAX 128 -#define LOAD 1 -#define UNLOAD 0 -#define JFSNAMELEN 64 -#define JFSTYPELEN 8 - -struct jfs { - char name[JFSNAMELEN]; - char device[JFSNAMELEN]; - char type[JFSNAMELEN]; - int fd; - int mounted; -} jfs[JFSMAX]; - -int jfses = 0; -void jfs_load(int load) -{ - int i; - struct stat stat_buffer; - FILE *mfp; /* FILE pointer for mtab file */ - struct mntent *mp; /* mnt point stats */ - static int jfs_loaded = 0; - - if (load == LOAD) { - if (jfs_loaded == 0) { - mfp = setmntent("/etc/mtab", "r"); - for (i = 0; i < JFSMAX && (mp = getmntent(mfp)) != NULL; i++) { - strncpy(jfs[i].device, mp->mnt_fsname, JFSNAMELEN); - strncpy(jfs[i].name, mp->mnt_dir, JFSNAMELEN); - strncpy(jfs[i].type, mp->mnt_type, JFSTYPELEN); - mp->mnt_fsname[JFSNAMELEN - 1] = 0; - mp->mnt_dir[JFSNAMELEN - 1] = 0; - mp->mnt_type[JFSTYPELEN - 1] = 0; - } - endfsent(); - jfs_loaded = 1; - jfses = i; - } - - /* 1st or later time - just reopen the mount points */ - for (i = 0; i < JFSMAX && jfs[i].name[0] != 0; i++) { - if (stat(jfs[i].name, &stat_buffer) != -1) { - - jfs[i].fd = open(jfs[i].name, O_RDONLY); - if (jfs[i].fd != -1) - jfs[i].mounted = 1; - else - jfs[i].mounted = 0; - } else - jfs[i].mounted = 0; - } - } else { /* this is an unload request */ - if (jfs_loaded) - for (i = 0; i < JFSMAX && jfs[i].name[0] != 0; i++) { - if (jfs[i].mounted) - close(jfs[i].fd); - jfs[i].fd = 0; - } else - /* do nothing */ ; - } -} - -/* We order this array rather than the actual process tables - * the index is the position in the process table and - * the size is the memory used in bytes - * the io is the storge I/O performed in the the last period in bytes - * the time is the CPU used in the last period in seconds - */ -struct topper { - int index; - int other; - double size; - double io; - int time; -} *topper; -int topper_size = 200; - -/* Routine used by qsort to order the processes by CPU usage */ -int cpu_compare(const void *a, const void *b) -{ - return (int) (((struct topper *) b)->time - - ((struct topper *) a)->time); -} - -int size_compare(const void *a, const void *b) -{ - return (int) ((((struct topper *) b)->size - - ((struct topper *) a)->size)); -} - -int disk_compare(const void *a, const void *b) -{ - return (int) ((((struct topper *) b)->io - ((struct topper *) a)->io)); -} - - -/* checkinput is the subroutine to handle user input */ -int checkinput(void) -{ - static int use_env = 1; - char buf[1024]; - int bytes; - int chars; - int i; - char *p; - - if (!cursed) /* not user input so stop with control-C */ - return 0; - ioctl(fileno(stdin), FIONREAD, &bytes); - - if (bytes > 0 || use_env) { - if (use_env) { - use_env = 0; - p = getenv("NMON"); - if (p != 0) { - strcpy(buf, p); - chars = strlen(buf); - } else - chars = 0; - } else - chars = read(fileno(stdin), buf, bytes); - if (chars > 0) { - welcome = 0; - for (i = 0; i < chars; i++) { - switch (buf[i]) { - case '1': - show_topmode = 1; - show_top = 1; - wclear(padtop); - break; -/* case '2': - show_topmode = 2; - show_top = 1; - clear(); - break; -*/ - case '3': - show_topmode = 3; - show_top = 1; - wclear(padtop); - break; - case '4': - show_topmode = 4; - show_top = 1; - wclear(padtop); - break; - case '5': - if (isroot) { - show_topmode = 5; - show_top = 1; - wclear(padtop); - } - break; - case '0': - for (i = 0; i < (max_cpus + 1); i++) - cpu_peak[i] = 0; - for (i = 0; i < networks; i++) { - net_read_peak[i] = 0.0; - net_write_peak[i] = 0.0; - } - for (i = 0; i < disks; i++) { - disk_busy_peak[i] = 0.0; - disk_rate_peak[i] = 0.0; - } - snap_clear(); - aiocount_max = 0; - aiotime_max = 0.0; - aiorunning_max = 0; - huge_peak = 0; - break; - case '6': - case '7': - case '8': - case '9': - dotline = buf[i] - '0'; - break; - case ' ': /* attempt to refresh the screen */ - clear(); - break; - case '+': - seconds = seconds * 2; - break; - case '-': - seconds = seconds / 2; - if (seconds < 1) - seconds = 1; - break; - case '.': /* limit output to processes and disks actually doing work */ - if (show_all) - show_all = 0; - else { - show_all = 1; - show_disk = SHOW_DISK_STATS; - show_top = 1; - show_topmode = 3; - } - wclear(paddisk); - break; - case '?': - case 'h': - case 'H': - if (show_help) - show_help = 0; - else { - show_help = 1; - show_verbose = 0; - } - wclear(padhelp); - break; -/* alphabetic order from here */ -#ifdef NVIDIA_GPU - case 'a': /* Accelerator */ - case 'E': /* Emily mode */ - FLIP(show_gpu); - wclear(padgpu); - break; -#endif /* NVIDIA_GPU */ - case 'b': - FLIP(colour); - clear(); - break; - case 'c': - FLIP(show_smp); - wclear(padsmp); - break; - case 'C': - FLIP(show_wide); - wclear(padwide); - break; - case 'D': - switch (show_disk) { - case SHOW_DISK_NONE: - show_disk = SHOW_DISK_STATS; - break; - case SHOW_DISK_STATS: - show_disk = SHOW_DISK_NONE; - break; - case SHOW_DISK_GRAPH: - show_disk = SHOW_DISK_STATS; - break; - } - wclear(paddisk); - break; - case 'd': - switch (show_disk) { - case SHOW_DISK_NONE: - show_disk = SHOW_DISK_GRAPH; - break; - case SHOW_DISK_STATS: - show_disk = SHOW_DISK_GRAPH; - break; - case SHOW_DISK_GRAPH: - show_disk = 0; - break; - } - wclear(paddisk); - break; - - break; - case 'G': - if (auto_dgroup) { - FLIP(disk_only_mode); - clear(); - } - break; - case 'g': - FLIP(show_dgroup); - wclear(paddg); - break; - - case 'j': - FLIP(show_jfs); - jfs_load(show_jfs); - wclear(padjfs); - break; - case 'k': - FLIP(show_kernel); - wclear(padker); - break; - case 'l': - FLIP(show_longterm); - wclear(padlong); - break; - case 'L': - FLIP(show_large); - wclear(padlarge); - break; - case 'm': - FLIP(show_memory); - wclear(padmem); - break; - case 'M': - show_mhz++; - if (show_mhz == 4) - show_mhz = 0; - wclear(padmhz); - break; - case 'n': - if (show_net) { - show_net = 0; - show_neterror = 0; - } else { - show_net = 1; - show_neterror = 3; - } - wclear(padnet); - break; - case 'N': - if (show_nfs == 0) - show_nfs = 1; - else if (show_nfs == 1) - show_nfs = 2; - else if (show_nfs == 2) - show_nfs = 3; - else if (show_nfs == 3) - show_nfs = 0; - nfs_clear = 1; - wclear(padnfs); - break; - case 'o': - FLIP(show_diskmap); - wclear(padmap); - break; -#ifdef POWER - case 'p': - FLIP(show_lpar); - wclear(padlpar); - break; -#endif - case 'r': - FLIP(show_res); - wclear(padres); - break; - case 't': - show_topmode = 3; /* Fall Through */ - case 'T': - FLIP(show_top); - wclear(padtop); - break; - case 'v': - FLIP(show_verbose); - wclear(padverb); - break; - case 'u': - if (show_args == ARGS_NONE) { - args_load(); - show_args = ARGS_ONLY; - show_top = 1; - if (show_topmode != 3 && - show_topmode != 4 && show_topmode != 5) - show_topmode = 3; - } else - show_args = ARGS_NONE; - wclear(padtop); - break; - case 'U': - FLIP(show_util); - wclear(padutil); - break; - case 'V': - FLIP(show_vm); - wclear(padpage); - break; - case 'x': - case 'q': - nocbreak(); - endwin(); - exit(0); - default: - return 0; - } - } - return 1; - } - } - return 0; -} - -void go_background(int def_loops, int def_secs) -{ - cursed = 0; - if (maxloops == -1) - maxloops = def_loops; - if (seconds == -1) - seconds = def_secs; - show_res = 1; - show_smp = 1; - show_disk = SHOW_DISK_STATS; - show_jfs = 1; - show_memory = 1; - show_large = 1; - show_kernel = 1; - show_net = 1; - show_all = 1; - show_top = 0; /* top process */ - show_topmode = 3; - show_lpar = 1; - show_vm = 1; -} - -void proc_net() -{ - static FILE *fp = (FILE *) - 1; - char buf[1024]; - int i = 0; - int ret; - unsigned long junk; - - if (fp == (FILE *) - 1) { - if ((fp = fopen("/proc/net/dev", "r")) == NULL) { - error("failed to open - /proc/net/dev"); - networks = 0; - return; - } - } - if (fgets(buf, 1024, fp) == NULL) - goto end; /* throw away the header lines */ - if (fgets(buf, 1024, fp) == NULL) - goto end; /* throw away the header lines */ -/* -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed - lo: 1956 30 0 0 0 0 0 0 1956 30 0 0 0 0 0 0 - eth0: 0 0 0 0 0 0 0 0 458718 0 781 0 0 0 781 0 - sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - eth1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -*/ - for (i = 0; i < NETMAX; i++) { - if (fgets(buf, 1024, fp) == NULL) - break; - strip_spaces(buf); - /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ - ret = - sscanf(&buf[0], - "%s %llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu", - (char *) &p->ifnets[i].if_name, &p->ifnets[i].if_ibytes, - &p->ifnets[i].if_ipackets, &p->ifnets[i].if_ierrs, - &p->ifnets[i].if_idrop, &p->ifnets[i].if_ififo, - &p->ifnets[i].if_iframe, &junk, &junk, - &p->ifnets[i].if_obytes, &p->ifnets[i].if_opackets, - &p->ifnets[i].if_oerrs, &p->ifnets[i].if_odrop, - &p->ifnets[i].if_ofifo, &p->ifnets[i].if_ocolls, - &p->ifnets[i].if_ocarrier); - if (ret != 16) - fprintf(stderr, "sscanf wanted 16 returned = %d line=%s\n", - ret, (char *) buf); - } - end: - if (reread) { - fclose(fp); - fp = (FILE *) - 1; - } else - rewind(fp); - networks = i; -} - - -int proc_procsinfo(int pid, int index) -{ - FILE *fp; - char filename[64]; - char buf[1024 * 4]; - int size = 0; - int ret = 0; - int count = 0; - int i; - - sprintf(filename, "/proc/%d/stat", pid); - if ((fp = fopen(filename, "r")) == NULL) { - sprintf(buf, "failed to open file %s", filename); - error(buf); - return 0; - } - size = fread(buf, 1, 1024 - 1, fp); - fclose(fp); - if (size == -1) { -#ifdef DEBUG - fprintf(stderr, - "procsinfo read returned = %d assuming process stopped pid=%d\n", - ret, pid); -#endif /*DEBUG*/ - return 0; - } - ret = sscanf(buf, "%d (%s)", - &p->procs[index].pi_pid, &p->procs[index].pi_comm[0]); - if (ret != 2) { - fprintf(stderr, "procsinfo sscanf returned = %d line=%s\n", ret, - buf); - return 0; - } - p->procs[index].pi_comm[strlen(p->procs[index].pi_comm) - 1] = 0; - - for (count = 0; count < size; count++) /* now look for ") " as dumb Infiniban driver includes "()" */ - if (buf[count] == ')' && buf[count + 1] == ' ') - break; - - if (count == size) { -#ifdef DEBUG - fprintf(stderr, "procsinfo failed to find end of command buf=%s\n", - buf); -#endif /*DEBUG*/ - return 0; - } - count++; - count++; - - ret = sscanf(&buf[count], -#ifndef KERNEL_2_6_18 - "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d", -#else - "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu", -#endif - &p->procs[index].pi_state, - &p->procs[index].pi_ppid, - &p->procs[index].pi_pgrp, - &p->procs[index].pi_session, - &p->procs[index].pi_tty_nr, - &p->procs[index].pi_tty_pgrp, - &p->procs[index].pi_flags, - &p->procs[index].pi_minflt, - &p->procs[index].pi_cmin_flt, - &p->procs[index].pi_majflt, - &p->procs[index].pi_cmaj_flt, - &p->procs[index].pi_utime, - &p->procs[index].pi_stime, - &p->procs[index].pi_cutime, - &p->procs[index].pi_cstime, - &p->procs[index].pi_pri, &p->procs[index].pi_nice, -#ifndef KERNEL_2_6_18 - &p->procs[index].junk, -#else - &p->procs[index].pi_num_threads, -#endif - &p->procs[index].pi_it_real_value, - &p->procs[index].pi_start_time, - &p->procs[index].pi_vsize, - &p->procs[index].pi_rss, - &p->procs[index].pi_rlim_cur, - &p->procs[index].pi_start_code, - &p->procs[index].pi_end_code, - &p->procs[index].pi_start_stack, - &p->procs[index].pi_esp, - &p->procs[index].pi_eip, - &p->procs[index].pi_pending_signal, - &p->procs[index].pi_blocked_sig, - &p->procs[index].pi_sigign, - &p->procs[index].pi_sigcatch, - &p->procs[index].pi_wchan, - &p->procs[index].pi_nswap, - &p->procs[index].pi_cnswap, - &p->procs[index].pi_exit_signal, &p->procs[index].pi_cpu -#ifdef KERNEL_2_6_18 - , - &p->procs[index].pi_rt_priority, - &p->procs[index].pi_policy, - &p->procs[index].pi_delayacct_blkio_ticks -#endif - ); -#ifndef KERNEL_2_6_18 - if (ret != 37) { - fprintf(stderr, - "procsinfo2 sscanf wanted 37 returned = %d pid=%d line=%s\n", - ret, pid, buf); -#else - if (ret != 40) { - fprintf(stderr, - "procsinfo2 sscanf wanted 40 returned = %d pid=%d line=%s\n", - ret, pid, buf); -#endif - return 0; - } - - sprintf(filename, "/proc/%d/statm", pid); - if ((fp = fopen(filename, "r")) == NULL) { - sprintf(buf, "failed to open file %s", filename); - error(buf); - return 0; - } - size = fread(buf, 1, 1024 * 4 - 1, fp); - fclose(fp); /* close it even if the read failed, the file could have been removed - between open & read i.e. the device driver does not behave like a file */ - if (size == -1) { - sprintf(buf, "failed to read file %s", filename); - error(buf); - return 0; - } - - ret = sscanf(&buf[0], "%lu %lu %lu %lu %lu %lu %lu", - &p->procs[index].statm_size, - &p->procs[index].statm_resident, - &p->procs[index].statm_share, - &p->procs[index].statm_trs, - &p->procs[index].statm_lrs, - &p->procs[index].statm_drs, &p->procs[index].statm_dt); - if (ret != 7) { - fprintf(stderr, "sscanf wanted 7 returned = %d line=%s\n", ret, - buf); - return 0; - } - if (isroot) { - p->procs[index].read_io = 0; - p->procs[index].write_io = 0; - sprintf(filename, "/proc/%d/io", pid); - if ((fp = fopen(filename, "r")) != NULL) { - for (i = 0; i < 6; i++) { - if (fgets(buf, 1024, fp) == NULL) { - break; - } - if (strncmp("read_bytes:", buf, 11) == 0) - sscanf(&buf[12], "%lld", &p->procs[index].read_io); - if (strncmp("write_bytes:", buf, 12) == 0) - sscanf(&buf[13], "%lld", &p->procs[index].write_io); - } - } - - if (fp != NULL) - fclose(fp); - } - return 1; -} - -#ifdef DEBUGPROC -print_procs(int index) -{ - printf("procs[%d].pid =%d\n", index, procs[index].pi_pid); - printf("procs[%d].comm[0] =%s\n", index, - &procs[index].pi_comm[0]); - printf("procs[%d].state =%c\n", index, procs[index].pi_state); - printf("procs[%d].ppid =%d\n", index, procs[index].pi_ppid); - printf("procs[%d].pgrp =%d\n", index, procs[index].pi_pgrp); - printf("procs[%d].session =%d\n", index, - procs[index].pi_session); - printf("procs[%d].tty_nr =%d\n", index, procs[index].pi_tty_nr); - printf("procs[%d].tty_pgrp =%d\n", index, - procs[index].pi_tty_pgrp); - printf("procs[%d].flags =%lu\n", index, procs[index].pi_flags); - printf("procs[%d].minflt =%lu\n", index, procs[index].pi_minflt); - printf("procs[%d].cmin_flt =%lu\n", index, - procs[index].pi_cmin_flt); - printf("procs[%d].majflt =%lu\n", index, procs[index].pi_majflt); - printf("procs[%d].cmaj_flt =%lu\n", index, - procs[index].pi_cmaj_flt); - printf("procs[%d].utime =%lu\n", index, procs[index].pi_utime); - printf("procs[%d].stime =%lu\n", index, procs[index].pi_stime); - printf("procs[%d].cutime =%ld\n", index, procs[index].pi_cutime); - printf("procs[%d].cstime =%ld\n", index, procs[index].pi_cstime); - printf("procs[%d].pri =%d\n", index, procs[index].pi_pri); - printf("procs[%d].nice =%d\n", index, procs[index].pi_nice); -#ifndef KERNEL_2_6_18 - printf("procs[%d].junk =%d\n", index, procs[index].junk); -#else - printf("procs[%d].num_threads =%ld\n", index, - procs[index].num_threads); -#endif - printf("procs[%d].it_real_value =%lu\n", index, - procs[index].pi_it_real_value); - printf("procs[%d].start_time =%lu\n", index, - procs[index].pi_start_time); - printf("procs[%d].vsize =%lu\n", index, procs[index].pi_vsize); - printf("procs[%d].rss =%lu\n", index, procs[index].pi_rss); - printf("procs[%d].rlim_cur =%lu\n", index, - procs[index].pi_rlim_cur); - printf("procs[%d].start_code =%lu\n", index, - procs[index].pi_start_code); - printf("procs[%d].end_code =%lu\n", index, - procs[index].pi_end_code); - printf("procs[%d].start_stack =%lu\n", index, - procs[index].pi_start_stack); - printf("procs[%d].esp =%lu\n", index, procs[index].pi_esp); - printf("procs[%d].eip =%lu\n", index, procs[index].pi_eip); - printf("procs[%d].pending_signal=%lu\n", index, - procs[index].pi_pending_signal); - printf("procs[%d].blocked_sig =%lu\n", index, - procs[index].pi_blocked_sig); - printf("procs[%d].sigign =%lu\n", index, - procs[index].pi_sigign); - printf("procs[%d].sigcatch =%lu\n", index, - procs[index].pi_sigcatch); - printf("procs[%d].wchan =%lu\n", index, procs[index].pi_wchan); - printf("procs[%d].nswap =%lu\n", index, procs[index].pi_nswap); - printf("procs[%d].cnswap =%lu\n", index, - procs[index].pi_cnswap); - printf("procs[%d].exit_signal =%d\n", index, - procs[index].pi_exit_signal); - printf("procs[%d].cpu =%d\n", index, procs[index].pi_cpu); -#ifdef KERNEL_2_6_18 - printf("procs[%d].rt_priority =%lu\n", index, - procs[index].pi_rt_priority); - printf("procs[%d].policy =%lu\n", index, - procs[index].pi_policy); - printf("procs[%d].delayacct_blkio_ticks=%llu\n", index, - procs[index].pi_delayacct_blkio_ticks); -#endif - printf("OK\n"); -} -#endif /*DEBUG*/ -/* --- */ -int isnumbers(char *s) -{ - while (*s != 0) { - if (*s < '0' || *s > '9') - return 0; - s++; - } - return 1; -} - -int getprocs(int details) -{ - struct dirent *dent; - DIR *procdir; - int count = 0; - - if ((char *) (procdir = opendir("/proc")) == NULL) { - printf("opendir(/proc) failed"); - return 0; - } - while ((char *) (dent = readdir(procdir)) != NULL) { - if (dent->d_type == 4) { /* is this a directlory */ -/* mainframes report 0 = unknown every time !!!! */ -/* - printf("inode=%d type=%d name=%s\n", - dent->d_ino, - dent->d_type, - dent->d_name); -*/ - if (isnumbers(dent->d_name)) { -/* printf("%s pid\n",dent->d_name); */ - if (details) { - count = - count + proc_procsinfo(atoi(dent->d_name), count); - } else { - count++; - } - } -/* - else - printf("NOT numbers\n"); -*/ - } - } - closedir(procdir); - return count; -} - -/* --- */ - -char cpu_line[] = - "---------------------------+-------------------------------------------------+"; -/* Start process as specified in cmd in a child process without waiting - * for completion - * not sure if want to prevent this funcitonality for root user - * when: CHLD_START, CHLD_SNAP or CHLD_END - * cmd: pointer to command string - assumed to be cleansed .... - * timestamp_type: 0 - T%04d, 1 - detailed time stamp - * loop: loop id (0 for CHLD_START) - * the_time: time to use for timestamp generation - */ -void child_start(int when, - char *cmd, int timestamp_type, int loop, time_t the_time) -{ - int i; - pid_t child_pid; - char time_stamp_str[20] = ""; - char *when_info = ""; - struct tm *tim; /* used to work out the hour/min/second */ - -#ifdef DEBUG2 - fprintf(fp, "child start when=%d cmd=%s time=%d loop=%d\n", when, cmd, - timestamp_type, loop); -#endif - /* Validate parameter and initialize error text */ - switch (when) { - case CHLD_START: - when_info = "nmon fork exec failure CHLD_START"; - break; - case CHLD_END: - when_info = "nmon fork exec failure CHLD_END"; - break; - - case CHLD_SNAP: - /* check if old child has finished - otherwise we do nothing */ - if (nmon_children[CHLD_SNAP] != -1) { - if (!cursed) - fprintf(fp, - "ERROR,T%04d, Starting snap command \"%s\" failed as previous child still running - killing it now\n", - loop, cmd); - kill(nmon_children[CHLD_SNAP], 9); - } - - when_info = "nmon fork exec failure CHLD_SNAP"; - break; - } - - - /* now fork off a child process. */ - switch (child_pid = fork()) { - case -1: /* fork failed. */ - perror(when_info); - return; - - case 0: /* inside child process. */ - /* create requested timestamp */ - if (timestamp_type == 1) { - tim = localtime(&the_time); - sprintf(time_stamp_str, "%02d:%02d:%02d,%02d,%02d,%04d", - tim->tm_hour, tim->tm_min, tim->tm_sec, - tim->tm_mday, tim->tm_mon + 1, tim->tm_year + 1900); - } else { - sprintf(time_stamp_str, "T%04d", loop); - } - - /* close all open file pointers except the defaults */ - for (i = 3; i < 5; ++i) - close(i); - - /* Now switch to the defined command */ - execlp(cmd, cmd, time_stamp_str, (void *) 0); - - /* If we get here the specified command could not be started */ - perror(when_info); - exit(1); /* We can't do anything more */ - /* never reached */ - - default: /* inside parent process. */ - /* In father - remember child pid for future */ - nmon_children[when] = child_pid; - } -} - -int main(int argc, char **argv) -{ - int secs; - int cpu_idle; - int cpu_user; - int cpu_sys; - int cpu_wait; - int cpu_steal; - int n = 0; /* reusable counters */ - int i = 0; - int j = 0; - int k = 0; - int ret = 0; - int max_sorted; - int skipped; - int x = 0; /* curses row */ - int y = 0; /* curses column */ - double elapsed; /* actual seconds between screen updates */ - double cpu_sum; - double ftmp; - int top_first_time = 1; - int disk_first_time = 1; - int nfs_first_time = 1; - int vm_first_time = 1; - int bbbr_line = 0; - double cpu_busy; -#ifdef POWER - int lpar_first_time = 1; -#endif /* POWER */ - int smp_first_time = 1; - int wide_first_time = 1; - int proc_first_time = 1; - int first_key_pressed = 0; - pid_t childpid = -1; - int ralfmode = 0; - char pgrp[32]; - struct tm *tim; /* used to work out the hour/min/second */ - float total_busy; /* general totals */ - float total_rbytes; /* general totals */ - float total_wbytes; - float total_xfers; - struct utsname uts; /* UNIX name, version, etc */ - double top_disk_busy = 0.0; - char *top_disk_name = ""; - int disk_mb; - double disk_total; - double disk_busy; - double disk_read; - double disk_read_tmp; - double disk_write; - double disk_write_tmp; - double disk_size; - double disk_xfers; - double total_disk_read; - double total_disk_write; - double total_disk_xfers; - double readers; - double writers; - - /* for popen on oslevel */ - char str[512]; - char *str_p; - int varperftmp = 0; - char *formatstring; - char user_filename[512]; - char user_filename_set = 0; - struct statfs statfs_buffer; - float fs_size; - float fs_bsize; - float fs_free; - float fs_size_used; - char cmdstr[256]; - long updays, uphours, upmins; - float v2c_total; - float v2s_total; - float v3c_total; - float v3s_total; - float v4c_total; - float v4s_total; - int errors = 0; - - char *nmon_start = (char *) NULL; - char *nmon_end = (char *) NULL; - char *nmon_snap = (char *) NULL; - char *nmon_tmp = (char *) NULL; - int nmon_one_in = 1; - /* Flag what kind of time stamp we give to started children - * 0: "T%04d" - * 1: "hh:mm:ss,dd,mm,yyyy" - */ - int time_stamp_type = 0; - long ticks = 100; /* Clock ticks per second used in /proc/stat cpu lines */ - unsigned long pagesize = 1024 * 4; /* Default page size is 4 KB but newer servers compiled with 64 KB pages */ - float average; - struct timeval nmon_tv; /* below is used to workout the nmon run, accumalate it and the - allow for in in the sleep time to reduce time drift */ - double nmon_start_time = 0.0; - double nmon_end_time = 0.0; - double nmon_run_time = -1.0; - int seconds_over = 0; - float mhz; - float min_mhz; - float max_mhz; - float avg_mhz = 0.0; - - -#define MAXROWS 256 -#define MAXCOLS 150 /* changed to allow maximum column widths */ -#define BANNER(pad,string) {mvwhline(pad, 0, 0, ACS_HLINE,COLS-2); \ - wmove(pad,0,0); \ - wattron(pad,A_STANDOUT); \ - wprintw(pad," "); \ - wprintw(pad,string); \ - wprintw(pad," "); \ - wattroff(pad,A_STANDOUT); } - -#define DISPLAY(pad,rows) { \ - if(x+2+(rows)>LINES)\ - pnoutrefresh(pad, 0,0,x,1,LINES-2, COLS-2); \ - else \ - pnoutrefresh(pad, 0,0,x,1,x+rows+1,COLS-2); \ - x=x+(rows); \ - if(x+4>LINES) { \ - mvwprintw(stdscr,LINES-1,10,"Warning: Some Statistics may not shown"); \ - } \ - } - - /* check the user supplied options */ - progname = argv[0]; - for (i = (int) strlen(progname) - 1; i > 0; i--) - if (progname[i] == '/') { - progname = &progname[i + 1]; - } - - if (getenv("NMONDEBUG") != NULL) - debug = 1; - if (getenv("NMONERROR") != NULL) - error_on = 1; - if (getenv("NMONBUG1") != NULL) - reread = 1; - -/* External Data Collector Controls */ - if ((nmon_start = getenv("NMON_START")) != NULL) { - nmon_start = check_call_string(nmon_start, "NMON_START"); - } - if ((nmon_end = getenv("NMON_END")) != NULL) { - nmon_end = check_call_string(nmon_end, "NMON_END"); - } - if ((nmon_tmp = getenv("NMON_ONE_IN")) != NULL) { - nmon_one_in = atoi(nmon_tmp); - if (errno != 0) { - fprintf(stderr, - "ERROR nmon: invalid NMON_ONE_IN shell variable\n"); - nmon_one_in = 1; - } - } - if ((nmon_snap = getenv("NMON_SNAP")) != NULL) { - nmon_snap = check_call_string(nmon_snap, "NMON_SNAP"); - } - if ((nmon_tmp = getenv("NMON_TIMESTAMP")) != NULL) { - time_stamp_type = atoi(nmon_tmp); - if (time_stamp_type != 0 && time_stamp_type != 1) - time_stamp_type = 1; - } -#ifdef DEBUG2 - printf("NMON_START=%s.\n", nmon_start); - printf("NMON_END=%s.\n", nmon_end); - printf("NMON_SNAP=%s.\n", nmon_snap); - printf("ONE_IN=%d.\n", nmon_one_in); - printf("TIMESTAMP=%d.\n", time_stamp_type); -#endif - -#ifdef REREAD - reread = 1; -#endif - for (i = 0; i < CMDMAX; i++) { - sprintf(cmdstr, "NMONCMD%d", i); - cmdlist[i] = getenv(cmdstr); - if (cmdlist[i] != 0) - cmdfound = i + 1; - } - /* Setup long and short Hostname */ - gethostname(hostname, sizeof(hostname)); - strcpy(fullhostname, hostname); - for (i = 0; i < sizeof(hostname); i++) - if (hostname[i] == '.') - hostname[i] = 0; - if (run_name_set == 0) - strcpy(run_name, hostname); - - if (getuid() == 0) - isroot = 1; - - /* Check the version of OS */ - uname(&uts); - /* Get the clock ticks persecond for CPU counters in /proc/stat cpu stats */ - ticks = sysconf(_SC_CLK_TCK); - if (ticks == -1 || ticks == 0) - ticks = 100; - /* Check if we have the large 64 KB memory page sizes compiled into the kernel */ - if (sysconf(_SC_PAGESIZE) > 1024 * 4) - pagesize = sysconf(_SC_PAGESIZE); - proc_init(); - - while (-1 != - (i = - getopt(argc, argv, - "?abc:C:Dd:EfF:g:hI:l:m:MNpr:Rs:tTUVxXz"))) { - switch (i) { - case '?': - hint(); - exit(0); - case 'a': /* Acelerator */ - case 'E': /* Emily */ - show_gpu = 1; - break; - case 'b': - colour = 0; - break; - case 'c': - maxloops = atoi(optarg); - break; - case 'C': /* commandlist argument */ - cmdlist[0] = MALLOC(strlen(optarg) + 1); /* create buffer */ - strcpy(cmdlist[0], optarg); - if (cmdlist[0][0] != 0) - cmdfound = 1; - for (i = 0, j = 1; cmdlist[0][i] != 0; i++) { - if (cmdlist[0][i] == ':') { - cmdlist[0][i] = 0; - cmdlist[j] = &cmdlist[0][i + 1]; - j++; - cmdfound = j; - if (j >= CMDMAX) - break; - } - } - break; - case 'd': - diskmax = atoi(optarg); - if (diskmax < DISKMIN) { - printf - ("nmon: ignoring -d %d option as the minimum is %d\n", - diskmax, DISKMIN); - diskmax = DISKMIN; - } - break; - case 'D': - extended_disk = 1; - break; - case 'F': /* background mode with user supplied filename */ - strcpy(user_filename, optarg); - user_filename_set++; - go_background(288, 300); - break; - case 'f': /* background mode i.e. for spread sheet output */ - go_background(288, 300); - break; - case 'g': /* disk groups */ - show_dgroup = 1; - dgroup_loaded = 1; - dgroup_filename = optarg; - if (strncmp("auto", dgroup_filename, 5) == 0) { - auto_dgroup++; - printf - ("Generating disk group file from lsblk output to file: \"auto\"\n"); -#ifdef SLES113 -#define LSBLK_NO_TYPE /* define this to work around missing --output TYPE feature */ -#endif /* SLES113 */ - -#ifdef LSBLK_NO_TYPE - ret = - system - ("lsblk --nodeps --output NAME --noheadings | awk 'BEGIN {printf \"# This file created by: nmon -g auto\\n# It is an automatically generated disk-group file which excluses disk paritions\\n\" } { printf \"%s %s\\n\", $1, $1 }' >auto"); -#else - ret = - system - ("lsblk --nodeps --output NAME,TYPE --raw | grep disk | awk 'BEGIN {printf \"# This file created by: nmon -g auto\\n# It is an automatically generated disk-group file which excluses disk paritions\\n\" } { printf \"%s %s\\n\", $1, $1 }' >auto"); -#endif /* LSBLK_NO_TYPE */ - if (ret != 0) { - printf("Create auto file command was: %s\n", - "lsblk --nodeps --output NAME,TYPE --raw | grep disk | awk '{ printf \"%s %s\\n\", $1, $1 }' >auto"); - printf("Creating auto file returned a status of %d\n", - ret); - } - } - break; - case 'h': - help(); - break; - case 'I': - ignore_procdisk_threshold = atof(optarg); - break; - case 'l': - disks_per_line = atoi(optarg); - if (disks_per_line < 3 || disks_per_line > 250) - disks_per_line = 100; - break; - case 'm': - if (chdir(optarg) == -1) { - perror("changing directory failed"); - printf("Directory attempted was:%s\n", optarg); - exit(993); - } - break; - case 'M': /* MHz */ - show_mhz = 1; - break; - case 'N': - show_nfs = 1; - break; - case 'p': - ralfmode = 1; - break; - case 'R': - show_rrd = 1; - go_background(288, 300); - show_aaa = 0; - show_para = 0; - show_headings = 0; - break; - case 'r': - strcpy(run_name, optarg); - run_name_set++; - break; - case 's': - seconds = atoi(optarg); - break; - case 'T': - show_args = ARGS_ONLY; /* drop through */ - case 't': - show_top = 1; /* put top process output in spreadsheet mode */ - show_topmode = 3; - break; - case 'U': - show_util = 1; - break; - case 'V': /* nmon version */ - printf("nmon version %s\n", VERSION); - exit(0); - break; - case 'x': /* background mode for 1 day capacity planning */ - go_background(4 * 24, 15 * 60); - show_top = 1; - show_topmode = 3; - break; - case 'X': /* background mode for 1 hour capacity planning */ - go_background(120, 30); - show_top = 1; - show_topmode = 3; - break; - case 'z': /* background mode for 1 day output to /var/perf/tmp */ - varperftmp++; - go_background(4 * 24, 15 * 60); - break; - } - } - /* Set parameters if not set by above */ - if (maxloops == -1) - maxloops = 9999999; - if (seconds == -1) - seconds = 2; - if (cursed) - show_dgroup = 0; - - /* -D need -g filename */ - if (extended_disk == 1 && show_dgroup == 0) { - printf - ("nmon: ignoring -D (extended disk stats) as -g filename is missing\n"); - extended_disk = 0; - } -#ifdef NVIDIA_GPU - if (cursed) { - gpu_init(); - } -#endif /* NVIDIA_GPU */ - - /* To get the pointers setup */ - switcher(); - - /* Initialise the time stamps for the first loop */ - p->time = doubletime(); - q->time = doubletime(); - - find_release(); - - /* Determine number of active LOGICAL cpu - depends on SMT mode ! */ - get_cpu_cnt(); - max_cpus = old_cpus = cpus; -#if X86 || ARM - get_intel_spec(); -#endif - proc_read(P_STAT); - proc_cpu(); - proc_read(P_UPTIME); - proc_read(P_LOADAVG); - proc_kernel(); - memcpy(&q->cpu_total, &p->cpu_total, sizeof(struct cpu_stat)); - - p->dk = MALLOC(sizeof(struct dsk_stat) * diskmax + 1); - q->dk = MALLOC(sizeof(struct dsk_stat) * diskmax + 1); - disk_busy_peak = MALLOC(sizeof(double) * diskmax); - disk_rate_peak = MALLOC(sizeof(double) * diskmax); - for (i = 0; i < diskmax; i++) { - disk_busy_peak[i] = 0.0; - disk_rate_peak[i] = 0.0; - } - - cpu_peak = MALLOC(sizeof(double) * (CPUMAX + 1)); /* MAGIC */ - for (i = 0; i < max_cpus + 1; i++) - cpu_peak[i] = 0.0; - - n = getprocs(0); - p->procs = MALLOC(sizeof(struct procsinfo) * n + 8); - q->procs = MALLOC(sizeof(struct procsinfo) * n + 8); - p->nprocs = q->nprocs = n; - - /* Initialise the top processes table */ - topper = MALLOC(sizeof(struct topper) * topper_size); /* round up */ - - /* Get Disk Stats. */ - proc_disk(0.0); - memcpy(q->dk, p->dk, sizeof(struct dsk_stat) * disks); - - /* load dgroup - if required */ - if (dgroup_loaded == 1) { - load_dgroup(p->dk); - } - - /* Get Network Stats. */ - proc_net(); - memcpy(q->ifnets, p->ifnets, sizeof(struct net_stat) * networks); - for (i = 0; i < networks; i++) { - net_read_peak[i] = 0.0; - net_write_peak[i] = 0.0; - } - - /* If we are running in spreadsheet mode initialize all other data sets as well - * so we do not get incorrect data for the first reported interval - */ - if (!cursed) { - /* Get VM Stats */ - read_vmstat(); - - /* Get Memory info */ - proc_mem(); - -#ifdef POWER - /* Get LPAR Stats */ - proc_lparcfg(); -#endif - } - /* Set the pointer ready for the next round */ - switcher(); - - /* Initialise signal handlers so we can tidy up curses on exit */ - signal(SIGUSR1, interrupt); - signal(SIGUSR2, interrupt); - signal(SIGINT, interrupt); - signal(SIGWINCH, interrupt); - signal(SIGCHLD, interrupt); - - /* Start Curses */ - if (cursed) { - initscr(); - cbreak(); - move(0, 0); - refresh(); - COLOUR colour = has_colors(); - COLOUR start_color(); - COLOUR init_pairs(); - clear(); -#ifdef POWER - padlpar = newpad(11, MAXCOLS); -#endif - padwelcome = newpad(24, MAXCOLS); - padmap = newpad(24, MAXCOLS); - padhelp = newpad(24, MAXCOLS); - padmem = newpad(20, MAXCOLS); - padlarge = newpad(20, MAXCOLS); - padpage = newpad(20, MAXCOLS); - padres = newpad(20, MAXCOLS); - padsmp = newpad(MAXROWS, MAXCOLS); - padutil = newpad(MAXROWS, MAXCOLS); - padlong = newpad(MAXROWS, MAXCOLS); - padwide = newpad(MAXROWS, MAXCOLS); - padmhz = newpad(24, MAXCOLS); - padgpu = newpad(10, MAXCOLS); - padnet = newpad(MAXROWS, MAXCOLS); - padneterr = newpad(MAXROWS, MAXCOLS); - paddisk = newpad(MAXROWS, MAXCOLS); - paddg = newpad(MAXROWS, MAXCOLS); - padjfs = newpad(MAXROWS, MAXCOLS); - padker = newpad(12, MAXCOLS); - padverb = newpad(8, MAXCOLS); - padnfs = newpad(25, MAXCOLS); - padtop = newpad(MAXROWS, MAXCOLS * 2); - - - } else { - /* Output the header lines for the spread sheet */ - timer = time(0); - tim = localtime(&timer); - tim->tm_year += 1900 - 2000; /* read localtime() manual page!! */ - tim->tm_mon += 1; /* because it is 0 to 11 */ - if (varperftmp) - sprintf(str, "/var/perf/tmp/%s_%02d.nmon", hostname, - tim->tm_mday); - else if (user_filename_set) - strcpy(str, user_filename); - else - sprintf(str, "%s_%02d%02d%02d_%02d%02d.nmon", - hostname, - tim->tm_year, - tim->tm_mon, tim->tm_mday, tim->tm_hour, tim->tm_min); - if ((fp = fopen(str, "w")) == 0) { - perror("nmon: failed to open output file"); - printf("nmon: output filename=%s\n", str); - exit(42); - } - /* disconnect from terminal */ - fflush(NULL); - if (!debug && (childpid = fork()) != 0) { - if (ralfmode) - printf("%d\n", childpid); - exit(0); /* parent returns OK */ - } - if (!debug) { - close(0); - close(1); - close(2); - setpgrp(); /* become process group leader */ - signal(SIGHUP, SIG_IGN); /* ignore hangups */ - } - /* Do the nmon_start activity early on */ - if (nmon_start) { - timer = time(0); - child_start(CHLD_START, nmon_start, time_stamp_type, 1, timer); - } - - if (show_aaa) { - fprintf(fp, "AAA,progname,%s\n", progname); - fprintf(fp, "AAA,command,"); - for (i = 0; i < argc; i++) - fprintf(fp, "%s ", argv[i]); - fprintf(fp, "\n"); - fprintf(fp, "AAA,version,%s\n", VERSION); - fprintf(fp, "AAA,disks_per_line,%d\n", disks_per_line); - fprintf(fp, "AAA,max_disks,%d,set by -d option\n", diskmax); - fprintf(fp, "AAA,disks,%d,\n", disks); - - fprintf(fp, "AAA,host,%s\n", hostname); - fprintf(fp, "AAA,user,%s\n", getenv("USER")); - fprintf(fp, "AAA,OS,Linux,%s,%s,%s\n", uts.release, - uts.version, uts.machine); - fprintf(fp, "AAA,runname,%s\n", run_name); - fprintf(fp, "AAA,time,%02d:%02d.%02d\n", tim->tm_hour, - tim->tm_min, tim->tm_sec); - fprintf(fp, "AAA,date,%02d-%3s-%02d\n", tim->tm_mday, - month[tim->tm_mon - 1], tim->tm_year + 2000); - fprintf(fp, "AAA,interval,%d\n", seconds); - fprintf(fp, "AAA,snapshots,%d\n", maxloops); -#ifdef POWER - fprintf(fp, "AAA,cpus,%d,%d\n", cpus / lparcfg.smt_mode, cpus); /* physical CPU, logical CPU */ - fprintf(fp, "AAA,CPU ID length,3\n"); /* Give analyzer a chance to easily find length of CPU number - 3 digits here! */ -#else - fprintf(fp, "AAA,cpus,%d\n", cpus); -#endif -#ifdef X86 - fprintf(fp, "AAA,x86,VendorId,%s\n", vendor_ptr); - fprintf(fp, "AAA,x86,ModelName,%s\n", model_ptr); - fprintf(fp, "AAA,x86,MHz,%s\n", mhz_ptr); - fprintf(fp, "AAA,x86,bogomips,%s\n", bogo_ptr); - fprintf(fp, "AAA,x86,ProcessorChips,%d\n", processorchips); - fprintf(fp, "AAA,x86,Cores,%d\n", cores); - fprintf(fp, "AAA,x86,hyperthreads,%d\n", hyperthreads); - fprintf(fp, "AAA,x86,VirtualCPUs,%d\n", cpus); -#endif -#ifdef ARM - fprintf(fp, "AAA,ARM,VendorId,%s\n", vendor_ptr); - fprintf(fp, "AAA,ARM,ModelName,%s\n", model_ptr); - fprintf(fp, "AAA,ARM,MHz,%s\n", mhz_ptr); - fprintf(fp, "AAA,ARM,bogomips,%s\n", bogo_ptr); - fprintf(fp, "AAA,ARM,ProcessorChips,%d\n", processorchips); - fprintf(fp, "AAA,ARM,Cores,%d\n", cores); - fprintf(fp, "AAA,ARM,hyperthreads,%d\n", hyperthreads); - fprintf(fp, "AAA,ARM,VirtualCPUs,%d\n", cpus); -#endif - fprintf(fp, "AAA,proc_stat_variables,%d\n", stat8); - - fprintf(fp, - "AAA,note0, Warning - use the UNIX sort command to order this file before loading into a spreadsheet\n"); - fprintf(fp, - "AAA,note1, The First Column is simply to get the output sorted in the right order\n"); - fprintf(fp, - "AAA,note2, The T0001-T9999 column is a snapshot number. To work out the actual time; see the ZZZ section at the end\n"); - } - fflush(NULL); - - for (i = 1; i <= cpus; i++) - fprintf(fp, - "CPU%03d,CPU %d %s,User%%,Sys%%,Wait%%,Idle%%,Steal%%\n", - i, i, run_name); - fprintf(fp, - "CPU_ALL,CPU Total %s,User%%,Sys%%,Wait%%,Idle%%,Steal%%,Busy,CPUs\n", - run_name); - if (show_mhz) { - fprintf(fp, "MHZ,Clock Speed (MHz) %s", run_name); - for (i = 1; i <= cpus; i++) - fprintf(fp, ",CPU%03d", i); - fprintf(fp, "\n"); - } - fprintf(fp, - "MEM,Memory MB %s,memtotal,hightotal,lowtotal,swaptotal,memfree,highfree,lowfree,swapfree,memshared,cached,active,bigfree,buffers,swapcached,inactive\n", - run_name); - -#ifdef POWER - proc_lparcfg(); - if (lparcfg.cmo_enabled) - fprintf(fp, - "MEMAMS,AMS %s,Poolid,Weight,Hypervisor-Page-in/s,HypervisorTime(seconds),not_available_1,not_available_2,not_available_3,Physical-Memory(MB),Page-Size(KB),Pool-Size(MB),Loan-Request(KB)\n", - run_name); - -#ifdef EXPERIMENTAL - fprintf(fp, - "MEMEXPERIMENTAL,New lparcfg numbers %s,DesEntCap,DesProcs,DesVarCapWt,DedDonMode,group,pool,entitled_memory,entitled_memory_group_number,unallocated_entitled_memory_weight,unallocated_io_mapping_entitlement\n", - run_name); -#endif /* EXPERIMENTAL */ -#endif /* POWER */ - - fprintf(fp, - "PROC,Processes %s,Runnable,Blocked,pswitch,syscall,read,write,fork,exec,sem,msg\n", - run_name); -/* - fprintf(fp,"PAGE,Paging %s,faults,pgin,pgout,pgsin,pgsout,reclaims,scans,cycles\n", run_name); - fprintf(fp,"FILE,File I/O %s,iget,namei,dirblk,readch,writech,ttyrawch,ttycanch,ttyoutch\n", run_name); -*/ - - - fprintf(fp, "NET,Network I/O %s", run_name); - for (i = 0; i < networks; i++) - fprintf(fp, ",%-2s-read-KB/s", (char *) p->ifnets[i].if_name); - for (i = 0; i < networks; i++) - fprintf(fp, ",%-2s-write-KB/s", (char *) p->ifnets[i].if_name); - fprintf(fp, "\n"); - fprintf(fp, "NETPACKET,Network Packets %s", run_name); - for (i = 0; i < networks; i++) - fprintf(fp, ",%-2s-read/s", (char *) p->ifnets[i].if_name); - for (i = 0; i < networks; i++) - fprintf(fp, ",%-2s-write/s", (char *) p->ifnets[i].if_name); - /* iremoved as it is not below in the BUSY line fprintf(fp,"\n"); */ -#ifdef DEBUG - if (debug) - printf("disks=%d x%sx\n", (char *) disks, p->dk[0].dk_name); -#endif /*DEBUG*/ - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKBUSY%s,Disk %%Busy %s", dskgrp(i), - run_name); - fprintf(fp, ",%s", (char *) p->dk[i].dk_name); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKREAD%s,Disk Read KB/s %s", dskgrp(i), - run_name); - fprintf(fp, ",%s", (char *) p->dk[i].dk_name); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKWRITE%s,Disk Write KB/s %s", - (char *) dskgrp(i), run_name); - fprintf(fp, ",%s", (char *) p->dk[i].dk_name); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKXFER%s,Disk transfers per second %s", - (char *) dskgrp(i), run_name); - fprintf(fp, ",%s", p->dk[i].dk_name); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKBSIZE%s,Disk Block Size %s", dskgrp(i), - run_name); - fprintf(fp, ",%s", (char *) p->dk[i].dk_name); - } - if (extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS) { - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKREADS%s,Disk Rd/s %s", dskgrp(i), - run_name); - fprintf(fp, ",%s", (char *) p->dk[i].dk_name); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, "\nDISKWRITES%s,Disk Wrt/s %s", dskgrp(i), - run_name); - fprintf(fp, ",%s", (char *) p->dk[i].dk_name); - } - } - - fprintf(fp, "\n"); - list_dgroup(p->dk); - jfs_load(LOAD); - fprintf(fp, "JFSFILE,JFS Filespace %%Used %s", hostname); - for (k = 0; k < jfses; k++) { - if (jfs[k].mounted && strncmp(jfs[k].name, "/proc", 5) - && strncmp(jfs[k].name, "/sys", 4) - && strncmp(jfs[k].name, "/run/", 5) - && strncmp(jfs[k].name, "/dev/", 5) - && strncmp(jfs[k].name, "/var/lib/nfs/rpc", 16) - ) /* /proc gives invalid/insane values */ - fprintf(fp, ",%s", jfs[k].name); - } - fprintf(fp, "\n"); - jfs_load(UNLOAD); -#ifdef POWER - if (proc_lparcfg() && lparcfg.shared_processor_mode != 0 - && power_vm_type == VM_POWERVM) { - fprintf(fp, - "LPAR,Shared CPU LPAR Stats %s,PhysicalCPU,capped,shared_processor_mode,system_potential_processors,system_active_processors,pool_capacity,MinEntCap,partition_entitled_capacity,partition_max_entitled_capacity,MinProcs,Logical CPU,partition_active_processors,partition_potential_processors,capacity_weight,unallocated_capacity_weight,BoundThrds,MinMem,unallocated_capacity,pool_idle_time,smt_mode\n", - hostname); - - } -#endif /*POWER*/ - if (show_top) { - fprintf(fp, "TOP,%%CPU Utilisation\n"); -#ifndef KERNEL_2_6_18 - fprintf(fp, - "TOP,+PID,Time,%%CPU,%%Usr,%%Sys,Size,ResSet,ResText,ResData,ShdLib,MinorFault,MajorFault,Command\n"); -#else - fprintf(fp, - "TOP,+PID,Time,%%CPU,%%Usr,%%Sys,Size,ResSet,ResText,ResData,ShdLib,MinorFault,MajorFault,Command,Threads,IOwaitTime\n"); -#endif - } - linux_bbbp("/etc/release", "/bin/cat /etc/*ease 2>/dev/null", - WARNING); - linux_bbbp("lsb_release", "/usr/bin/lsb_release -a 2>/dev/null", - WARNING); - linux_bbbp("fdisk-l", "/sbin/fdisk -l 2>/dev/null", WARNING); - linux_bbbp("lsblk", "/usr/bin/lsblk 2>/dev/null", WARNING); - linux_bbbp("lscpu", "/usr/bin/lscpu 2>/dev/null", WARNING); - linux_bbbp("lshw", "/usr/bin/lshw 2>/dev/null", WARNING); - linux_bbbp("/proc/cpuinfo", "/bin/cat /proc/cpuinfo 2>/dev/null", - WARNING); - linux_bbbp("/proc/meminfo", "/bin/cat /proc/meminfo 2>/dev/null", - WARNING); - linux_bbbp("/proc/stat", "/bin/cat /proc/stat 2>/dev/null", - WARNING); - linux_bbbp("/proc/version", "/bin/cat /proc/version 2>/dev/null", - WARNING); - linux_bbbp("/proc/net/dev", "/bin/cat /proc/net/dev 2>/dev/null", - WARNING); -#ifdef POWER - linux_bbbp("ppc64_utils - lscfg", "/usr/sbin/lscfg 2>/dev/null", - WARNING); - linux_bbbp("ppc64_utils - ls-vdev", - "/usr/sbin/ls-vdev 2>/dev/null", WARNING); - linux_bbbp("ppc64_utils - ls-veth", - "/usr/sbin/ls-veth 2>/dev/null", WARNING); - linux_bbbp("ppc64_utils - ls-vscsi", - "/usr/sbin/ls-vscsi 2>/dev/null", WARNING); - linux_bbbp("ppc64_utils - lsmcode", - "/usr/sbin/lsmcode 2>/dev/null", WARNING); - linux_bbbp("ppc64_cpu - smt", - "/usr/sbin/ppc64_cpu --smt 2>/dev/null", WARNING); - linux_bbbp("ppc64_cpu - cores", - "/usr/sbin/ppc64_cpu --cores-present 2>/dev/null", - WARNING); - linux_bbbp("ppc64_cpu - DSCR", - "/usr/sbin/ppc64_cpu --dscr 2>/dev/null", WARNING); - linux_bbbp("ppc64_cpu - snooze", - "/usr/sbin/ppc64_cpu --smt-snooze-delay 2>/dev/null", - WARNING); - linux_bbbp("ppc64_cpu - run-mode", - "/usr/sbin/ppc64_cpu --run-mode 2>/dev/null", WARNING); - linux_bbbp("ppc64_cpu - frequency", - "/usr/sbin/ppc64_cpu --frequency 2>/dev/null", WARNING); - - linux_bbbp("bootlist -m nmonal -o", - "/usr/sbin/bootlist -m normal -o 2>/dev/null", WARNING); - linux_bbbp("lsslot", "/usr/sbin/lsslot 2>/dev/null", WARNING); - linux_bbbp("lparstat -i", "/usr/sbin/lparstat -i 2>/dev/null", - WARNING); - linux_bbbp("lsdevinfo", "/usr/sbin/lsdevinfo 2>/dev/null", - WARNING); - linux_bbbp("ls-vdev", "/usr/sbin/ls-vdev 2>/dev/null", WARNING); - linux_bbbp("ls-veth", "/usr/sbin/ls-veth 2>/dev/null", WARNING); - linux_bbbp("ls-vscsi", "/usr/sbin/ls-vscsi 2>/dev/null", WARNING); - -#endif - linux_bbbp("/proc/diskinfo", "/bin/cat /proc/diskinfo 2>/dev/null", - WARNING); - linux_bbbp("/proc/diskstats", - "/bin/cat /proc/diskstats 2>/dev/null", WARNING); - - linux_bbbp("/sbin/multipath", "/sbin/multipath -l 2>/dev/null", - WARNING); - linux_bbbp("/dev/mapper", "ls -l /dev/mapper 2>/dev/null", - WARNING); - linux_bbbp("/dev/mpath", "ls -l /dev/mpath 2>/dev/null", WARNING); - linux_bbbp("/dev/dm-*", "ls -l /dev/dm-* 2>/dev/null", WARNING); - linux_bbbp("/dev/md*", "ls -l /dev/md* 2>/dev/null", WARNING); - linux_bbbp("/dev/sd*", "ls -l /dev/sd* 2>/dev/null", WARNING); - linux_bbbp("/proc/partitions", - "/bin/cat /proc/partitions 2>/dev/null", WARNING); - linux_bbbp("/proc/1/stat", "/bin/cat /proc/1/stat 2>/dev/null", - WARNING); -#ifndef KERNEL_2_6_18 - linux_bbbp("/proc/1/statm", "/bin/cat /proc/1/statm 2>/dev/null", - WARNING); -#endif -#ifdef MAINFRAME - linux_bbbp("/proc/sysinfo", "/bin/cat /proc/sysinfo 2>/dev/null", - WARNING); -#endif - linux_bbbp("/proc/net/rpc/nfs", - "/bin/cat /proc/net/rpc/nfs 2>/dev/null", WARNING); - linux_bbbp("/proc/net/rpc/nfsd", - "/bin/cat /proc/net/rpc/nfsd 2>/dev/null", WARNING); - linux_bbbp("/proc/modules", "/bin/cat /proc/modules 2>/dev/null", - WARNING); - linux_bbbp("ifconfig", "/sbin/ifconfig 2>/dev/null", WARNING); - linux_bbbp("/bin/df-m", "/bin/df -m 2>/dev/null", WARNING); - linux_bbbp("/bin/mount", "/bin/mount 2>/dev/null", WARNING); - linux_bbbp("/etc/fstab", "/bin/cat /etc/fstab 2>/dev/null", - WARNING); - linux_bbbp("netstat -r", "/bin/netstat -r 2>/dev/null", WARNING); - linux_bbbp("uptime", "/usr/bin/uptime 2>/dev/null", WARNING); - linux_bbbp("getconf PAGESIZE", - "/usr/bin/getconf PAGESIZE 2>/dev/null", WARNING); - -#ifdef POWER - linux_bbbp("/proc/ppc64/lparcfg", - "/bin/cat /proc/ppc64/lparcfg 2>/dev/null", WARNING); - linux_bbbp("lscfg-v", "/usr/sbin/lscfg -v 2>/dev/null", WARNING); -#endif - sleep(1); /* to get the first stats to cover this one second and avoids divide by zero issues */ - } - /* To get the pointers setup */ - /* Was already done earlier, DONT'T switch back here to the old pointer! - switcher(); */ - /*checkinput(); */ - clear(); - fflush(NULL); -#ifdef POWER - lparcfg.timebase = -1; -#endif - - /* Main loop of the code */ - for (loop = 1;; loop++) { - /* Save the time and work out how long we were actually asleep - * Do this as early as possible and close to reading the CPU statistics in /proc/stat - */ - p->time = doubletime(); - elapsed = p->time - q->time; - timer = time(0); - tim = localtime(&timer); - - /* Get current count of CPU - * As side effect /proc/stat is read - */ - old_cpus = cpus; - get_cpu_cnt(); -#ifdef POWER - /* Always get lpar info as well so we can report physical CPU usage - * to make data more meaningful. Return value is ignored here, but - * remembered in proc_lparcfg() ! - */ - proc_lparcfg(); -#endif - - if (loop <= 3) /* This stops the nmon causing the cpu peak at startup */ - for (i = 0; i < max_cpus + 1; i++) - cpu_peak[i] = 0.0; - - /* Reset the cursor position to top left */ - y = x = 0; - - if (cursed) { /* Top line */ - box(stdscr, 0, 0); - mvprintw(x, 1, "nmon"); - mvprintw(x, 6, "%s", VERSION); - if (flash_on) - mvprintw(x, 15, "[H for help]"); - mvprintw(x, 30, "Hostname=%s", hostname); - mvprintw(x, 52, "Refresh=%2.0fsecs ", elapsed); - mvprintw(x, 70, "%02d:%02d.%02d", - tim->tm_hour, tim->tm_min, tim->tm_sec); - wnoutrefresh(stdscr); - x = x + 1; - - if (welcome && getenv("NMON") == 0) { - - COLOUR wattrset(padwelcome, COLOR_PAIR(2)); -/* -mvwprintw(padwelcome,x+1, 3, "------------------------------"); -mvwprintw(padwelcome,x+2, 3, "# # # # #### # #"); -mvwprintw(padwelcome,x+3, 3, "## # ## ## # # ## #"); -mvwprintw(padwelcome,x+4, 3, "# # # # ## # # # # # #"); -mvwprintw(padwelcome,x+5, 3, "# # # # # # # # # #"); -mvwprintw(padwelcome,x+6, 3, "# ## # # # # # ##"); -mvwprintw(padwelcome,x+7, 3, "# # # # #### # #"); -mvwprintw(padwelcome,x+8, 3, "------------------------------"); -*/ - mvwprintw(padwelcome, x + 0, 3, - "------------------------------"); - mvwprintw(padwelcome, x + 1, 3, - " _ __ _ __ ___ ___ _ __ "); - mvwprintw(padwelcome, x + 2, 3, - "| '_ \\| '_ ` _ \\ / _ \\| '_ \\ "); - mvwprintw(padwelcome, x + 3, 3, - "| | | | | | | | | (_) | | | | "); - mvwprintw(padwelcome, x + 4, 3, - "|_| |_|_| |_| |_|\\___/|_| |_| "); - mvwprintw(padwelcome, x + 5, 3, - " "); - mvwprintw(padwelcome, x + 6, 3, - "------------------------------"); - - COLOUR wattrset(padwelcome, COLOR_PAIR(0)); - mvwprintw(padwelcome, x + 1, 40, "For help type H or ..."); - mvwprintw(padwelcome, x + 2, 40, " nmon -? - hint"); - mvwprintw(padwelcome, x + 3, 40, - " nmon -h - full details"); - mvwprintw(padwelcome, x + 5, 40, - "To stop nmon type q to Quit"); - COLOUR wattrset(padwelcome, COLOR_PAIR(1)); -#ifdef POWER - get_cpu_cnt(); - proc_read(P_CPUINFO); - - lscpu_init(); - - switch (power_vm_type) { - case VM_POWERKVM_GUEST: - get_cpu_cnt(); -#ifdef RHEL7 - mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], - easy[1]); -#else -#ifdef SLES113 - mvwprintw(padwelcome, x + 8, 3, "%s", easy[2]); -#else - mvwprintw(padwelcome, x + 8, 3, "%s", easy[3]); -#endif /* SLES113 */ -#endif /* RHEL7 */ - mvwprintw(padwelcome, x + 9, 3, "PowerKVM Guest %s", - &proc[P_CPUINFO].line[1][7]); - mvwprintw(padwelcome, x + 10, 3, - "PowerKVM Guest VirtualCPUs=%d LogicalCPUs=%d", - (int) lparcfg.partition_active_processors, - cpus); - mvwprintw(padwelcome, x + 11, 3, - "PowerKVM Guest SMT=%d", lparcfg.smt_mode); - break; - case VM_POWERKVM_HOST: - mvwprintw(padwelcome, x + 8, 3, "%s", easy[0]); - mvwprintw(padwelcome, x + 9, 3, "PowerKVM Host %s", - &proc[P_CPUINFO].line[1][7]); - mvwprintw(padwelcome, x + 10, 3, - "PowerKVM Host owns all %d CPUs & SMT=%d in the Hosting OS", - cpus, lscpu.threads); - mvwprintw(padwelcome, x + 11, 3, "PowerKVM Host %s", - proc[P_CPUINFO].line[proc[P_CPUINFO].lines - - 2]); - break; - case VM_NATIVE: - mvwprintw(padwelcome, x + 8, 3, "%s", easy[0]); - mvwprintw(padwelcome, x + 9, 3, "Native %s", - &proc[P_CPUINFO].line[1][7]); - mvwprintw(padwelcome, x + 10, 3, - "Native owns all %d CPUs & SMT=%d", cpus, - lscpu.threads); - mvwprintw(padwelcome, x + 11, 3, "Native %s", - proc[P_CPUINFO].line[proc[P_CPUINFO].lines - - 2]); - break; - default: - case VM_POWERVM: -#ifdef SLES113 - mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], - easy[2]); -#else -#ifdef RHEL7 - mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], - easy[1]); -#else - mvwprintw(padwelcome, x + 8, 3, "%s", easy[3]); -#endif -#endif - mvwprintw(padwelcome, x + 9, 3, "PowerVM %s %s", - &proc[P_CPUINFO].line[1][7], - &proc[P_CPUINFO].line[proc[P_CPUINFO].lines - - 1][11]); - mvwprintw(padwelcome, x + 10, 3, - "PowerVM Entitlement=%-6.2f VirtualCPUs=%d LogicalCPUs=%d", - (double) lparcfg. - partition_entitled_capacity / 100.0, - (int) lparcfg.partition_active_processors, - cpus); - mvwprintw(padwelcome, x + 11, 3, - "PowerVM SMT=%d Capped=%d", lparcfg.smt_mode, - lparcfg.capped); - break; - } - - mvwprintw(padwelcome, x + 12, 3, - "Processor Clock=%s %s", - &proc[P_CPUINFO].line[2][9], lscpu.byte_order); - -#endif /*POWER*/ -#ifdef MAINFRAME - get_cpu_cnt(); - proc_read(P_CPUINFO); - lscpu_init(); - -#ifdef SLES113 - mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], - easy[2]); -#else -#ifdef RHEL7 - mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], - easy[1]); -#else - mvwprintw(padwelcome, x + 8, 3, "%s", easy[3]); -#endif /*RHEL*/ -#endif /*SLES*/ - - mvwprintw(padwelcome, x + 10, 3, - "Mainframe VM %d CPUs & SMT=%d", - cpus, lscpu.threads); - mvwprintw(padwelcome, x + 11, 3, - "Mainframe VM Arch %s", lscpu.arch); - mvwprintw(padwelcome, x + 12, 3, - "Processor %s", lscpu.byte_order); -#endif /*MAINFRAME */ -#if X86 || ARM - get_cpu_cnt(); - mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], easy[2]); - mvwprintw(padwelcome, x + 9, 3, "%s %s", vendor_ptr, - model_ptr); - mvwprintw(padwelcome, x + 10, 3, "MHz=%s bogomips=%s", - mhz_ptr, bogo_ptr); - if (processorchips || cores || hyperthreads || cpus) { - mvwprintw(padwelcome, x + 11, 3, "ProcessorChips=%d PhyscalCores=%d", processorchips, cores); - mvwprintw(padwelcome, x + 12, 3, "Hyperthreads =%d VirtualCPUs =%d", hyperthreads, cpus); - } -#endif - COLOUR wattrset(padwelcome, COLOR_PAIR(0)); - mvwprintw(padwelcome, x + 14, 3, - "Use these keys to toggle statistics on/off:"); - mvwprintw(padwelcome, x + 15, 3, - " c = CPU l = CPU Long-term - = Faster screen updates"); - mvwprintw(padwelcome, x + 16, 3, - " m = Memory V = Virtual memory + = Slower screen updates"); - mvwprintw(padwelcome, x + 17, 3, - " d = Disks n = Network j = File Systems"); - mvwprintw(padwelcome, x + 18, 3, - " r = Resource N = NFS . = only busy disks/procs"); - mvwprintw(padwelcome, x + 19, 3, - " k = Kernel t = Top-processes h = more options"); - mvwprintw(padwelcome, x + 20, 3, - " q = Quit"); - pnoutrefresh(padwelcome, 0, 0, x, 1, LINES - 2, COLS - 2); - wnoutrefresh(stdscr); - x = x + 22; - } - } else { - if (!cursed && nmon_snap && (loop % nmon_one_in) == 0) { - child_start(CHLD_SNAP, nmon_snap, time_stamp_type, loop, - timer); - } - - - if (!show_rrd) - fprintf(fp, "ZZZZ,%s,%02d:%02d:%02d,%02d-%s-%4d\n", LOOP, - tim->tm_hour, tim->tm_min, tim->tm_sec, - tim->tm_mday, month[tim->tm_mon], - tim->tm_year + 1900); - fflush(NULL); - } - if (show_verbose && cursed) { - BANNER(padverb, "Verbose Mode"); - mvwprintw(padverb, 1, 0, - " Code Resource Stats Now\tWarn\tDanger "); - /* DISPLAY(padverb,7); */ - /* move(x,0); */ - x = x + 6; - } - if (show_help && cursed) { - - COLOUR wattrset(padhelp, COLOR_PAIR(2)); - BANNER(padhelp, - "HELP: Hit h to remove this Info Hit q to Quit"); - mvwprintw(padhelp, 1, 1, - "Letters which toggle on/off statistics:"); - mvwprintw(padhelp, 2, 1, - "h = This help | r = Resources OS & Proc"); - mvwprintw(padhelp, 3, 1, - "c = CPU Util C = wide view | l = longer term CPU averages"); - mvwprintw(padhelp, 4, 1, - "m = Memory & Swap L=Huge | V = Virtual Memory"); - mvwprintw(padhelp, 5, 1, - "n = Network | N = NFS"); - mvwprintw(padhelp, 6, 1, - "d = Disk I/O Graphs D=Stats | o = Disks %%Busy Map"); - mvwprintw(padhelp, 7, 1, - "k = Kernel stats & loadavg | j = Filesystem Usage"); - mvwprintw(padhelp, 8, 1, "M = MHz by thread & CPU"); -#ifdef NVIDIA_GPU - mvwprintw(padhelp, 8, 39, "| a = Accelerator Nvidia GPU "); -#else /*NVIDIA_GPU */ -#ifdef POWER - mvwprintw(padhelp, 8, 39, "| p = if(PowerVM) LPAR details"); -#endif /*POWER*/ -#endif /*NVIDIA_GPU */ - mvwprintw(padhelp, 9, 1, - "t = TopProcess 1=Priority/Nice/State | u = TopProc with command line"); - mvwprintw(padhelp, 10, 1, - " ReOrder by: 3=CPU 4=RAM 5=I/O | Hit u twice to update"); - mvwprintw(padhelp, 11, 1, - "g = User Defined Disk Groups | G = with -g switches Disk graphs"); - mvwprintw(padhelp, 12, 1, - " [start nmon with -g ] | to disk groups only"); - mvwprintw(padhelp, 13, 39, "| b = black & white mode"); - mvwprintw(padhelp, 14, 1, - "Other Controls: |"); - mvwprintw(padhelp, 15, 1, - "+ = double the screen refresh time | 0 = reset peak marks (\">\") to zero"); - mvwprintw(padhelp, 16, 1, - "- = half the screen refresh time | space refresh screen now"); - mvwprintw(padhelp, 17, 1, - ". = Display only busy disks & CPU | q = Quit"); -/* mvwprintw(padhelp,18, 1, "v = Verbose Simple Checks - OK/Warnings/Danger"); */ - - mvwprintw(padhelp, 19, 1, - "Developer: Nigel Griffiths | See http://nmon.sourceforge.net"); - mvwprintw(padhelp, 20, 1, "Colour:"); - for (i = 0; i < 13; i++) { - COLOUR wattrset(padhelp, COLOR_PAIR(i)); - mvwprintw(padhelp, 20, 8 + i * 5, "#%d#", i); - } - COLOUR wattrset(padhelp, COLOR_PAIR(0)); - DISPLAY(padhelp, 21); - - } -/* for debugging use only - if(error_on && errorstr[0] != 0) { - mvprintw(x, 0, "Error: %s ",errorstr); - x = x + 1; - } -*/ - if (show_res && cursed) { - proc_read(P_CPUINFO); - proc_read(P_VERSION); - - BANNER(padres, "Resources Linux & Processor"); - COLOUR wattrset(padres, COLOR_PAIR(2)); - mvwprintw(padres, 1, 4, "Linux: %s", proc[P_VERSION].line[0]); - mvwprintw(padres, 2, 4, "Build: %s", proc[P_VERSION].line[1]); - mvwprintw(padres, 3, 4, "Release : %s", uts.release); - mvwprintw(padres, 4, 4, "Version : %s", uts.version); - COLOUR wattrset(padres, COLOR_PAIR(3)); -#ifdef POWER - mvwprintw(padres, 5, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[1]); - mvwprintw(padres, 6, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[2]); - mvwprintw(padres, 7, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[3]); - mvwprintw(padres, 8, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[proc[P_CPUINFO].lines - 1]); - /* needs lparcfg to be already processed */ - proc_lparcfg(); - switch (power_vm_type) { - case VM_POWERKVM_GUEST: - mvwprintw(padres, 9, 4, - "PowerKVM Guest Physcal CPU:%d & Virtual CPU (SMT):%d %s", - lparcfg.partition_active_processors, cpus, - lscpu.byte_order); - break; - case VM_POWERKVM_HOST: - mvwprintw(padres, 9, 4, - "PowerKVM Host Physical CPU:%d %s", cpus, - lscpu.byte_order); - break; - case VM_POWERVM: - mvwprintw(padres, 9, 4, - "PowerVM Physcal CPU:%d & Logical CPU:%d %s", - lparcfg.partition_active_processors, cpus, - lscpu.byte_order); - break; - case VM_NATIVE: - mvwprintw(padres, 9, 4, "Native Mode Physical CPU:%d %s", - cpus, lscpu.byte_order); - break; - } -#else -#ifdef MAINFRAME - mvwprintw(padres, 5, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[1]); - mvwprintw(padres, 6, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[2]); - mvwprintw(padres, 7, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[3]); - mvwprintw(padres, 8, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[4]); -#else /* MAINFRAME */ -#if X86 || ARM - mvwprintw(padres, 5, 4, "cpuinfo: %s %s", vendor_ptr, - model_ptr); - mvwprintw(padres, 6, 4, "cpuinfo: Hz=%s bogomips=%s", mhz_ptr, - bogo_ptr); - if (processorchips || cores || hyperthreads || cpus) { - mvwprintw(padres, 7, 4, - "cpuinfo: ProcessorChips=%d PhyscalCores=%d", - processorchips, cores); - mvwprintw(padres, 8, 4, - "cpuinfo: Hyperthreads =%d VirtualCPUs =%d", - hyperthreads, cpus); - } -#else /* other platform perhaps ARM */ - mvwprintw(padres, 5, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[4]); - mvwprintw(padres, 6, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[1]); - mvwprintw(padres, 7, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[6]); - mvwprintw(padres, 8, 4, "cpuinfo: %s", - proc[P_CPUINFO].line[17]); -#endif /* X86 */ -#endif /* MAINFRAME */ -#endif /* POWER */ - mvwprintw(padres, 9, 4, "# of CPUs: %d", cpus); - COLOUR wattrset(padres, COLOR_PAIR(5)); - mvwprintw(padres, 10, 4, "Machine : %s", uts.machine); - mvwprintw(padres, 11, 4, "Nodename : %s", uts.nodename); - COLOUR wattrset(padres, COLOR_PAIR(6)); - mvwprintw(padres, 12, 4, "/etc/*ease[1]: %s", easy[0]); - mvwprintw(padres, 13, 4, "/etc/*ease[2]: %s", easy[1]); - mvwprintw(padres, 14, 4, "/etc/*ease[3]: %s", easy[2]); - mvwprintw(padres, 15, 4, "/etc/*ease[4]: %s", easy[3]); - COLOUR wattrset(padres, COLOR_PAIR(2)); - mvwprintw(padres, 16, 4, "lsb_release: %s", lsb_release[0]); - mvwprintw(padres, 17, 4, "lsb_release: %s", lsb_release[1]); - mvwprintw(padres, 18, 4, "lsb_release: %s", lsb_release[2]); - mvwprintw(padres, 19, 4, "lsb_release: %s", lsb_release[3]); - COLOUR wattrset(padres, COLOR_PAIR(0)); - DISPLAY(padres, 20); - } - if (show_longterm) { - proc_read(P_STAT); - proc_cpu(); - cpu_user = RAWTOTAL(user) + RAWTOTAL(nice); - cpu_sys = - RAWTOTAL(sys) + RAWTOTAL(irq) + RAWTOTAL(softirq) + - RAWTOTAL(guest) + RAWTOTAL(guest_nice); - cpu_wait = RAWTOTAL(wait); - cpu_idle = RAWTOTAL(idle); - cpu_steal = RAWTOTAL(steal); - /* DEBUG inject steal cpu_steal = cpu_sys; */ - cpu_sum = cpu_idle + cpu_user + cpu_sys + cpu_wait + cpu_steal; - - save_snap((double) cpu_user / (double) cpu_sum * 100.0, - (double) cpu_sys / (double) cpu_sum * 100.0, - (double) cpu_wait / (double) cpu_sum * 100.0, - (double) cpu_idle / (double) cpu_sum * 100.0, - (double) cpu_steal / (double) cpu_sum * 100.0); - plot_snap(padlong); - DISPLAY(padlong, MAX_SNAP_ROWS + 2); - } - if (show_smp || show_verbose || show_wide) { - proc_read(P_STAT); - proc_cpu(); - if (cpus > max_cpus && !cursed) { - for (i = max_cpus + 1; i <= cpus; i++) - fprintf(fp, - "CPU%03d,CPU %d %s,User%%,Sys%%,Wait%%,Idle%%\n", - i, i, run_name); - max_cpus = cpus; - } - if (old_cpus != cpus) { - if (!cursed) { - if (bbbr_line == 0) { - fprintf(fp, "BBBR,0,Reconfig,action,old,new\n"); - bbbr_line++; - } - fprintf(fp, "BBBR,%03d,%s,cpuchg,%d,%d\n", bbbr_line++, - LOOP, old_cpus, cpus); - } else { - /* wmove(padsmp,0,0); */ - /* doesn't work CURSE wclrtobot(padsmp); */ - /* Do BRUTE force overwrite of previous data */ - if (cpus < old_cpus) { - for (i = cpus; i < old_cpus; i++) - mvwprintw(padsmp, i + 4, 0, - " "); - } - } - } - if (show_smp) { - if (cursed) { - BANNER(padsmp, "CPU Utilisation"); - - /* mvwprintw(padsmp,1, 0, cpu_line); */ - /* - *mvwprintw(padsmp,2, 0, "CPU User%% Sys%% Wait%% Idle|0 |25 |50 |75 100|"); - */ - mvwprintw(padsmp, 1, 0, cpu_line); - mvwprintw(padsmp, 2, 0, "CPU "); - COLOUR wattrset(padsmp, COLOR_PAIR(2)); /* Green */ - mvwprintw(padsmp, 2, 4, "User%%"); - COLOUR wattrset(padsmp, COLOR_PAIR(1)); /* Red */ - mvwprintw(padsmp, 2, 9, " Sys%%"); - COLOUR wattrset(padsmp, COLOR_PAIR(4)); /* Blue */ - mvwprintw(padsmp, 2, 15, " Wait%%"); - if (p->cpu_total.steal != q->cpu_total.steal) { - COLOUR wattrset(padsmp, COLOR_PAIR(5)); - mvwprintw(padsmp, 2, 22, "Steal"); - } else { - COLOUR wattrset(padsmp, COLOR_PAIR(0)); - mvwprintw(padsmp, 2, 22, " Idle"); - } - COLOUR wattrset(padsmp, COLOR_PAIR(0)); - mvwprintw(padsmp, 2, 27, - "|0 |25 |50 |75 100|"); - } /* if (show_smp) AND if(cursed) */ -#ifdef POWER - /* Always get lpar info as well so we can report physical CPU usage - * to make data more meaningful - * This assumes that LPAR info is available in q and p ! - */ - if (proc_lparcfg() > 0) { - if (lparcfg.shared_processor_mode == 1) { - if (lparcfg.timebase == -1) { - lparcfg.timebase = 0; - proc_read(P_CPUINFO); - for (i = 0; i < proc[P_CPUINFO].lines - 1; i++) { - if (!strncmp - ("timebase", proc[P_CPUINFO].line[i], - 8)) { - sscanf(proc[P_CPUINFO].line[i], - "timebase : %lld", - &lparcfg.timebase); - break; - } - } - } else { - /* PowerKVM Host or Guest or Native have not Entitlement stats */ - if (power_vm_type == VM_POWERVM) - mvwprintw(padsmp, 1, 30, - "EntitledCPU=% 6.3f", - (double) lparcfg. - partition_entitled_capacity / - 100.0); - /* Only if the calculation is working */ - if (lparcfg.purr_diff != 0) - mvwprintw(padsmp, 1, 50, - "PhysicalCPUused=% 7.3f", - (double) lparcfg.purr_diff / - (double) lparcfg.timebase / - elapsed); - } - } - } -#endif - for (i = 0; i < cpus; i++) { - cpu_user = RAW(user) + RAW(nice); - cpu_sys = - RAW(sys) + RAW(irq) + RAW(softirq) + RAW(guest) + - RAW(guest_nice); - cpu_wait = RAW(wait); - cpu_idle = RAW(idle); - cpu_steal = RAW(steal); -/* DEBUG inject steal cpu_steal = cpu_sys; */ - cpu_sum = - cpu_idle + cpu_user + cpu_sys + cpu_wait + - cpu_steal; - /* Check if we had a CPU # change and have to set idle to 100 */ - if (cpu_sum == 0) - cpu_sum = cpu_idle = 100.0; - if (smp_first_time && cursed) { - if (i == 0) - mvwprintw(padsmp, 3 + i, 27, - "| Please wait gathering CPU statistics"); - else - mvwprintw(padsmp, 3 + i, 27, "|"); - mvwprintw(padsmp, 3 + i, 77, "|"); - } else { -#ifdef POWER - /* lparcfg gathered above */ - if (lparcfg.smt_mode > 1 - && i % lparcfg.smt_mode == 0) { - mvwprintw(padsmp, 3 + i, 27, "*"); - mvwprintw(padsmp, 3 + i, 77, "*"); - } -#endif - plot_smp(padsmp, i + 1, 3 + i, - (double) cpu_user / (double) cpu_sum * - 100.0, - (double) cpu_sys / (double) cpu_sum * - 100.0, - (double) cpu_wait / (double) cpu_sum * - 100.0, - (double) cpu_idle / (double) cpu_sum * - 100.0, - (double) cpu_steal / (double) cpu_sum * - 100.0); -#ifdef POWER - /* lparcfg gathered above */ - if (lparcfg.smt_mode > 1 - && i % lparcfg.smt_mode == 0) { - mvwprintw(padsmp, 3 + i, 27, "*"); - mvwprintw(padsmp, 3 + i, 77, "*"); - } -#endif - - RRD fprintf(fp, - "rrdtool update cpu%02d.rrd %s:%.1f:%.1f:%.1f:%.1f\n", - i, LOOP, - (double) cpu_user / (double) cpu_sum * - 100.0, - (double) cpu_sys / (double) cpu_sum * - 100.0, - (double) cpu_wait / (double) cpu_sum * - 100.0, - (double) cpu_idle / (double) cpu_sum * - 100.0); - } - } /* for (i = 0; i < cpus; i++) */ - CURSE mvwprintw(padsmp, i + 3, 0, cpu_line); -#ifdef POWER - /* proc_lparcfg called above in previous ifdef - */ - if (lparcfg.shared_processor_mode == 1) { - if (lparcfg.timebase == -1) { - lparcfg.timebase = 0; - proc_read(P_CPUINFO); - for (i = 0; i < proc[P_CPUINFO].lines - 1; i++) { - if (!strncmp - ("timebase", proc[P_CPUINFO].line[i], 8)) { - sscanf(proc[P_CPUINFO].line[i], - "timebase : %lld", - &lparcfg.timebase); - break; - } - } - } else { - mvwprintw(padsmp, i + 3, 29, "%s", - lparcfg. - shared_processor_mode ? "Shared" : - "Dedicated"); - mvwprintw(padsmp, i + 3, 39, "|"); - /* PowerKVM has no Capped concept */ - if (power_vm_type == VM_POWERVM) - mvwprintw(padsmp, i + 3, 41, "%s", - lparcfg. - capped ? "--Capped" : "Uncapped"); - mvwprintw(padsmp, i + 3, 51, "|"); - mvwprintw(padsmp, i + 3, 54, "SMT=%d", - lparcfg.smt_mode); - mvwprintw(padsmp, i + 3, 64, "|"); - mvwprintw(padsmp, i + 3, 67, "VP=%.0f", - (float) lparcfg. - partition_active_processors); - } - } -#endif - cpu_user = RAWTOTAL(user) + RAWTOTAL(nice); - cpu_sys = - RAWTOTAL(sys) + RAWTOTAL(irq) + RAWTOTAL(softirq) + - RAWTOTAL(guest) + RAWTOTAL(guest_nice); - cpu_wait = RAWTOTAL(wait); - cpu_idle = RAWTOTAL(idle); - cpu_steal = RAWTOTAL(steal); -/* DEBUG inject steal cpu_steal = cpu_sys; */ - cpu_sum = - cpu_idle + cpu_user + cpu_sys + cpu_wait + cpu_steal; - - /* Check if we had a CPU # change and have to set idle to 100 */ - if (cpu_sum == 0) - cpu_sum = cpu_idle = 100.0; - - RRD fprintf(fp, - "rrdtool update cpu.rrd %s:%.1f:%.1f:%.1f:%.1f%.1f\n", - LOOP, - (double) cpu_user / (double) cpu_sum * 100.0, - (double) cpu_sys / (double) cpu_sum * 100.0, - (double) cpu_wait / (double) cpu_sum * 100.0, - (double) cpu_idle / (double) cpu_sum * 100.0, - (double) cpu_steal / (double) cpu_sum * 100.0); - if (cpus > 1 || !cursed) { - if (!smp_first_time || !cursed) { - plot_smp(padsmp, 0, 4 + i, - (double) cpu_user / (double) cpu_sum * - 100.0, - (double) cpu_sys / (double) cpu_sum * - 100.0, - (double) cpu_wait / (double) cpu_sum * - 100.0, - (double) cpu_idle / (double) cpu_sum * - 100.0, - (double) cpu_steal / (double) cpu_sum * - 100.0); - } - - CURSE mvwprintw(padsmp, i + 5, 0, cpu_line); - i = i + 2; - } /* if (cpus > 1 || !cursed) */ - smp_first_time = 0; - DISPLAY(padsmp, i + 4); - } /* if (show_smp) */ - if (show_wide) { - if (cursed) { - int rows = 0; - BANNER(padwide, "CPU Utilisation Wide View"); - char *wide1 = - "100%%-+--------+---------+---------+---------+---------+---------+-----+100%%"; - char *wide2 = - " 90%%-| |-90%%"; - char *wide3 = - " 80%%-| |-80%%"; - char *wide4 = - " 70%%-| |-70%%"; - char *wide5 = - " 60%%-| |-60%%"; - char *wide6 = - " 50%%-| |-50%%"; - char *wide7 = - " 40%%-| |-40%%"; - char *wide8 = - " 30%%-| |-30%%"; - char *wide9 = - " 20%%-| |-20%%"; - char *wide10 = - " 10%%-| |-10%%"; - - mvwprintw(padwide, 1, 0, wide1); - mvwprintw(padwide, 2, 0, wide2); - mvwprintw(padwide, 3, 0, wide3); - mvwprintw(padwide, 4, 0, wide4); - mvwprintw(padwide, 5, 0, wide5); - mvwprintw(padwide, 6, 0, wide6); - mvwprintw(padwide, 7, 0, wide7); - mvwprintw(padwide, 8, 0, wide8); - mvwprintw(padwide, 9, 0, wide9); - mvwprintw(padwide, 10, 0, wide10); - mvwprintw(padwide, 11, 0, - " CPU +1--------+10-------+20-------+30-------+40-------+50-------+60--+--0%%"); - mvwprintw(padwide, 1, 6, "CPU(s)=%d", cpus); - if (wide_first_time) { - mvwprintw(padwide, 3, 7, - " Please wait gathering CPU statistics"); - } else { - for (i = 0; i < cpus && i < 64; i++) { - cpu_user = RAW(user) + RAW(nice); - cpu_sys = - RAW(sys) + RAW(irq) + RAW(softirq) + - RAW(guest) + RAW(guest_nice); - cpu_sum = cpu_user + cpu_sys; - COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ - if (i % 2) { - mvwprintw(padwide, 6, 6 + i, "."); - } - if (cpu_sum > 75) { - COLOUR wattrset(padwide, COLOR_PAIR(1)); /*red */ - } else { - if (cpu_sum > 50) { - COLOUR wattrset(padwide, COLOR_PAIR(5)); /*magenta */ - } else { - COLOUR wattrset(padwide, COLOR_PAIR(2)); /*green */ - } - } - for (j = 1, k = 10; j < 10; j++, k--) - if (cpu_sum > j * 10.0) - mvwprintw(padwide, k, 6 + i, "#"); - COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ - if (0.1 < cpu_sum && cpu_sum < 5.0) - mvwprintw(padwide, 10, 6 + i, "."); - if (5.1 <= cpu_sum && cpu_sum < 10.0) - mvwprintw(padwide, 10, 6 + i, "o"); - } - if (cpus < 64) - for (j = 2; j <= 10; j++) - mvwprintw(padwide, j, 6 + i, "|"); - rows = 12; - } - if (cpus > 63) { - mvwprintw(padwide, rows + 0, 0, wide1); - mvwprintw(padwide, rows + 1, 0, wide2); - mvwprintw(padwide, rows + 2, 0, wide3); - mvwprintw(padwide, rows + 3, 0, wide4); - mvwprintw(padwide, rows + 4, 0, wide5); - mvwprintw(padwide, rows + 5, 0, wide6); - mvwprintw(padwide, rows + 6, 0, wide7); - mvwprintw(padwide, rows + 7, 0, wide8); - mvwprintw(padwide, rows + 8, 0, wide9); - mvwprintw(padwide, rows + 9, 0, wide10); - mvwprintw(padwide, rows + 10, 0, - " CPU +65---+70-------+80-------+90-------+100------+110------+120-----+--0%%"); - if (wide_first_time) { - mvwprintw(padwide, rows + 3, 7, - " Please wait gathering CPU statistics"); - } else { - for (i = 64; i < cpus && i < 128; i++) { - cpu_user = RAW(user) + RAW(nice); - cpu_sys = - RAW(sys) + RAW(irq) + RAW(softirq) + - RAW(guest) + RAW(guest_nice); - cpu_sum = cpu_user + cpu_sys; - COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ - if (i % 2) { - mvwprintw(padwide, rows + 5, - 6 + i - 64, "."); - } - if (cpu_sum > 75) { - COLOUR wattrset(padwide, COLOR_PAIR(1)); /*red */ - } else { - if (cpu_sum > 50) { - COLOUR wattrset(padwide, COLOR_PAIR(5)); /*magenta */ - } else { - COLOUR wattrset(padwide, COLOR_PAIR(2)); /*green */ - } - } - for (j = 1, k = rows + 9; j < 10; j++, k--) - if (cpu_sum > j * 10.0) - mvwprintw(padwide, k, 6 + i - 64, - "#"); - COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ - if (0.1 < cpu_sum && cpu_sum < 5.0) - mvwprintw(padwide, rows + 9, - 6 + i - 64, "."); - if (5.1 <= cpu_sum && cpu_sum < 10.0) - mvwprintw(padwide, rows + 9, - 6 + i - 64, "o"); - } - - if (cpus < 128) - COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ - for (j = rows; j <= rows + 9; j++) - mvwprintw(padwide, j, 6 + i - 64, "<"); - COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ - } - rows = 23; - } - if (cpus > 127) { - mvwprintw(padwide, rows + 0, 0, wide1); - mvwprintw(padwide, rows + 1, 0, wide2); - mvwprintw(padwide, rows + 2, 0, wide3); - mvwprintw(padwide, rows + 3, 0, wide4); - mvwprintw(padwide, rows + 4, 0, wide5); - mvwprintw(padwide, rows + 5, 0, wide6); - mvwprintw(padwide, rows + 6, 0, wide7); - mvwprintw(padwide, rows + 7, 0, wide8); - mvwprintw(padwide, rows + 8, 0, wide9); - mvwprintw(padwide, rows + 9, 0, wide10); - mvwprintw(padwide, rows + 10, 0, - " CPU +129--------+140------+150------+160------+170------+180------+190--0%%"); - if (wide_first_time) { - mvwprintw(padwide, rows + 3, 7, - " Please wait gathering CPU statistics"); - } else { - for (i = 128; i < cpus && i < 196; i++) { - cpu_user = RAW(user) + RAW(nice); - cpu_sys = - RAW(sys) + RAW(irq) + RAW(softirq) + - RAW(guest) + RAW(guest_nice); - cpu_sum = cpu_user + cpu_sys; - COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ - if (i % 2) { - mvwprintw(padwide, rows + 5, - 6 + i - 128, "."); - } - if (cpu_sum > 75) { - COLOUR wattrset(padwide, COLOR_PAIR(1)); /*red */ - } else { - if (cpu_sum > 50) { - COLOUR wattrset(padwide, COLOR_PAIR(5)); /*magenta */ - } else { - COLOUR wattrset(padwide, COLOR_PAIR(2)); /*green */ - } - } - for (j = 1, k = rows + 9; j < 10; j++, k--) - if (cpu_sum > j * 10.0) - mvwprintw(padwide, k, 6 + i - 128, - "#"); - COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ - if (0.1 < cpu_sum && cpu_sum < 5.0) - mvwprintw(padwide, rows + 9, - 6 + i - 128, "."); - if (5.1 <= cpu_sum && cpu_sum < 10.0) - mvwprintw(padwide, rows + 9, - 6 + i - 128, "o"); - } - - if (cpus < 196) - COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ - for (j = rows; j <= rows + 9; j++) - mvwprintw(padwide, j, 6 + i - 128, "<"); - COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ - } - rows = 34; - } - wide_first_time = 0; - DISPLAY(padwide, rows); - } - proc_read(P_STAT); - proc_cpu(); - - if (show_verbose && cursed) { - cpu_user = RAWTOTAL(user) + RAWTOTAL(nice); - cpu_sys = - RAWTOTAL(sys) + RAWTOTAL(irq) + RAWTOTAL(softirq) + - RAWTOTAL(guest) + RAWTOTAL(guest_nice); - cpu_wait = RAWTOTAL(wait); - cpu_idle = RAWTOTAL(idle) + RAWTOTAL(steal); - cpu_sum = cpu_idle + cpu_user + cpu_sys + cpu_wait; - - cpu_busy = - (double) (cpu_user + - cpu_sys) / (double) cpu_sum *100.0; - mvwprintw(padverb, 2, 0, - " -> CPU %%busy %5.1f%%\t>80%%\t>90%% ", - cpu_busy); - if (cpu_busy > 90.0) { - COLOUR wattrset(padverb, COLOR_PAIR(1)); - mvwprintw(padverb, 2, 0, " DANGER"); - } else if (cpu_busy > 80.0) { - COLOUR wattrset(padverb, COLOR_PAIR(4)); - mvwprintw(padverb, 2, 0, "Warning"); - } else { - COLOUR wattrset(padverb, COLOR_PAIR(2)); - mvwprintw(padverb, 2, 0, " OK"); - } - COLOUR wattrset(padverb, COLOR_PAIR(0)); - } - - } /* if (cursed) */ - } /* if (show_smp || show_verbose) */ - if (show_util) { - proc_read(P_STAT); - proc_cpu(); - if (cursed) { - BANNER(padutil, "CPU Utilisation Stats"); - mvwprintw(padutil, 2, 0, "CPU"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 0, "%3d", i + 1); - mvwprintw(padutil, 1, 0, "ALL"); - if (first_util) { - mvwprintw(padutil, 5, 27, - " Please wait gathering CPU statistics"); - } else { - COLOUR wattrset(padutil, COLOR_PAIR(2)); /* Green */ - mvwprintw(padutil, 2, 4, " User%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 4, "%7.1f", - RAW(user) / elapsed); - mvwprintw(padutil, 1, 4, "%7.1f", - RAWTOTAL(user) / elapsed); - mvwprintw(padutil, 2, 11, " Nice%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 11, "%7.1f", - RAW(nice) / elapsed); - mvwprintw(padutil, 1, 11, "%7.1f", - RAWTOTAL(nice) / elapsed); - - COLOUR wattrset(padutil, COLOR_PAIR(1)); /* Red */ - mvwprintw(padutil, 2, 18, " Sys%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 18, "%7.1f", - RAW(sys) / elapsed); - mvwprintw(padutil, 1, 18, "%7.1f", - RAWTOTAL(sys) / elapsed); - - COLOUR wattrset(padutil, COLOR_PAIR(3)); /* Yellow */ - mvwprintw(padutil, 2, 25, " Idle%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 25, "%7.1f", - RAW(idle) / elapsed); - mvwprintw(padutil, 1, 25, "%7.1f", - RAWTOTAL(idle) / elapsed); - mvwprintw(padutil, 2, 32, " Wait%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 32, "%7.1f", - RAW(wait) / elapsed); - mvwprintw(padutil, 1, 32, "%7.1f", - RAWTOTAL(wait) / elapsed); - - COLOUR wattrset(padutil, COLOR_PAIR(1)); /* Red */ - mvwprintw(padutil, 2, 39, " HWirq%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 39, "%7.1f", - RAW(irq) / elapsed); - mvwprintw(padutil, 1, 39, "%7.1f", - RAWTOTAL(irq) / elapsed); - mvwprintw(padutil, 2, 46, " SWirq%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 46, "%7.1f", - RAW(softirq) / elapsed); - mvwprintw(padutil, 1, 46, "%7.1f", - RAWTOTAL(softirq) / elapsed); - - COLOUR wattrset(padutil, COLOR_PAIR(5)); /* Magenta */ - mvwprintw(padutil, 2, 53, " Steal%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 53, "%7.1f", - RAW(steal) / elapsed); - mvwprintw(padutil, 1, 53, "%7.1f", - RAWTOTAL(steal) / elapsed); - - COLOUR wattrset(padutil, COLOR_PAIR(6)); /* Cyan */ - mvwprintw(padutil, 2, 60, " Guest%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 60, "%7.1f", - RAW(guest) / elapsed); - mvwprintw(padutil, 1, 60, "%7.1f", - RAWTOTAL(guest) / elapsed); - mvwprintw(padutil, 2, 67, " GuestNice%%"); - for (i = 0; i < cpus; i++) - mvwprintw(padutil, 3 + i, 67, "%7.1f", - RAW(guest_nice) / elapsed); - mvwprintw(padutil, 1, 67, "%7.1f", - RAWTOTAL(guest_nice) / elapsed); - } - COLOUR wattrset(padutil, COLOR_PAIR(0)); - DISPLAY(padutil, i + 3); - } else { - if (first_util) { - fprintf(fp, - "CPUUTIL_ALL,CPU Util Stats %s,User%%,Nice%%,Sys%%,Idle%%,Wait%%,Irq%%,Softirq%%,Steal%%,Guest%%,Guest_nice%%\n", - run_name); - for (i = 1; i <= cpus; i++) - fprintf(fp, - "CPUUTIL%03d,CPU Util Stats CPU%d %s,User%%,Nice%%,Sys%%,Idle%%,Wait%%,Irq%%,Softirq%%,Steal%%,Guest%%,Guest_nice%%\n", - i, i, run_name); - } - fprintf(fp, - "CPUUTIL_ALL,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\n", - LOOP, RAWTOTAL(user) / elapsed, - RAWTOTAL(nice) / elapsed, RAWTOTAL(sys) / elapsed, - RAWTOTAL(idle) / elapsed, RAWTOTAL(wait) / elapsed, - RAWTOTAL(irq) / elapsed, - RAWTOTAL(softirq) / elapsed, - RAWTOTAL(steal) / elapsed, - RAWTOTAL(guest) / elapsed, - RAWTOTAL(guest_nice) / elapsed); - for (i = 0; i < cpus; i++) { - fprintf(fp, - "CPUUTIL%03d,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\n", - i, LOOP, RAW(user) / elapsed, - RAW(nice) / elapsed, RAW(sys) / elapsed, - RAW(idle) / elapsed, RAW(wait) / elapsed, - RAW(irq) / elapsed, RAW(softirq) / elapsed, - RAW(steal) / elapsed, RAW(guest) / elapsed, - RAW(guest_nice) / elapsed); - } - } - first_util = 0; - } -#ifdef POWER - if (show_lpar) { - if (lparcfg.timebase == -1) { - lparcfg.timebase = 0; - proc_read(P_CPUINFO); - for (i = 0; i < proc[P_CPUINFO].lines - 1; i++) { - if (!strncmp("timebase", proc[P_CPUINFO].line[i], 8)) { - sscanf(proc[P_CPUINFO].line[i], "timebase : %lld", - &lparcfg.timebase); - break; - } - } - } - ret = proc_lparcfg(); - if (cursed) { - BANNER(padlpar, "PowerVM LPAR"); - if (ret == 0) { - COLOUR wattrset(padlpar, COLOR_PAIR(1)); - mvwprintw(padlpar, 2, 0, - "Reading data from /proc/ppc64/lparcfg failed"); - mvwprintw(padlpar, 3, 0, - "This is probably a Native Virtual Machine"); - COLOUR wattrset(padlpar, COLOR_PAIR(0)); - } else - if (power_vm_type == VM_POWERKVM_HOST - || power_vm_type == VM_POWERKVM_GUEST) { - COLOUR wattrset(padlpar, COLOR_PAIR(5)); - mvwprintw(padlpar, 2, 0, - "Reading data from /proc/ppc64/lparcfg mostly failed"); - mvwprintw(padlpar, 3, 0, - "PowerKVM does not many of these stats"); - COLOUR wattrset(padlpar, COLOR_PAIR(0)); - } else { - mvwprintw(padlpar, 1, 0, - "LPAR=%d SerialNumber=%s Type=%s", - lparcfg.partition_id, lparcfg.serial_number, - lparcfg.system_type); - mvwprintw(padlpar, 2, 0, - "Flags: Shared-CPU=%-5s Capped=%-5s SMT-mode=%d", - lparcfg. - shared_processor_mode ? "true" : "false", - lparcfg.capped ? "true" : "false", - lparcfg.smt_mode); - COLOUR wattrset(padlpar, COLOR_PAIR(2)); - mvwprintw(padlpar, 3, 0, - "Systems CPU Pool=%8.2f Active=%8.2f Total=%8.2f", - (float) lparcfg.pool_capacity, - (float) lparcfg.system_active_processors, - (float) lparcfg.system_potential_processors); - COLOUR wattrset(padlpar, COLOR_PAIR(3)); - mvwprintw(padlpar, 4, 0, - "LPARs CPU Min=%8.2f Entitlement=%8.2f Max=%8.2f", - lparcfg.MinEntCap / 100.0, - lparcfg.partition_entitled_capacity / 100.0, - lparcfg.partition_max_entitled_capacity / - 100.0); - COLOUR wattrset(padlpar, COLOR_PAIR(5)); - mvwprintw(padlpar, 5, 0, - "Virtual CPU Min=%8.2f VP Now=%8.2f Max=%8.2f", - (float) lparcfg.MinProcs, - (float) lparcfg.partition_active_processors, - (float) lparcfg. - partition_potential_processors); - COLOUR wattrset(padlpar, COLOR_PAIR(6)); - mvwprintw(padlpar, 6, 0, - "Memory Min= unknown Now=%8.2f Max=%8.2f", - (float) lparcfg.MinMem, - (float) lparcfg.DesMem); - COLOUR wattrset(padlpar, COLOR_PAIR(0)); - mvwprintw(padlpar, 7, 0, - "Other Weight=%8.2f UnallocWeight=%8.2f Capacity=%8.2f", - (float) lparcfg.capacity_weight, - (float) lparcfg.unallocated_capacity_weight, - (float) lparcfg.CapInc / 100.0); - - mvwprintw(padlpar, 8, 0, - " BoundThrds=%8.2f UnallocCapacity=%8.2f Increment", - (float) lparcfg.BoundThrds, - (float) lparcfg.unallocated_capacity); - if (lparcfg.purr_diff == 0 || lparcfg.timebase < 1) { - mvwprintw(padlpar, 9, 0, - "lparcfg: purr field always zero, upgrade to SLES9+sp1 or RHEL4+u1"); - } else { - if (lpar_first_time) { - mvwprintw(padlpar, 9, 0, - "Please wait gathering data"); - - lpar_first_time = 0; - } else { - COLOUR wattrset(padlpar, COLOR_PAIR(1)); - mvwprintw(padlpar, 9, 0, - "Physical CPU use=%8.3f ", - (double) lparcfg.purr_diff / - (double) lparcfg.timebase / elapsed); - if (lparcfg.pool_idle_time != NUMBER_NOT_VALID - && lparcfg.pool_idle_saved != 0) - mvwprintw(padlpar, 9, 29, - "PoolIdleTime=%8.2f", - (double) lparcfg.pool_idle_diff / - (double) lparcfg.timebase / - elapsed); - COLOUR wattrset(padlpar, COLOR_PAIR(0)); - mvwprintw(padlpar, 9, 54, "[timebase=%lld]", - lparcfg.timebase); - } - } - } - DISPLAY(padlpar, 10); - } else { - /* Only print LPAR info to spreadsheet if in shared processor mode */ - if (ret != 0 && lparcfg.shared_processor_mode > 0 - && power_vm_type == VM_POWERVM) - fprintf(fp, "LPAR,%s,%9.6f,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d,%d,%d,%d,%d,%.2f,%d\n", LOOP, (double) lparcfg.purr_diff / (double) lparcfg.timebase / elapsed, lparcfg.capped, lparcfg.shared_processor_mode, lparcfg.system_potential_processors, lparcfg.system_active_processors, lparcfg.pool_capacity, lparcfg.MinEntCap / 100.0, lparcfg.partition_entitled_capacity / 100.0, lparcfg.partition_max_entitled_capacity / 100.0, lparcfg.MinProcs, cpus, /* report logical CPU here so analyser graph CPU% vs VPs reports correctly */ - lparcfg.partition_active_processors, - lparcfg.partition_potential_processors, - lparcfg.capacity_weight, - lparcfg.unallocated_capacity_weight, - lparcfg.BoundThrds, - lparcfg.MinMem, - lparcfg.unallocated_capacity, - (double) lparcfg.pool_idle_diff / - (double) lparcfg.timebase / elapsed, - lparcfg.smt_mode); - } - } -#endif /*POWER*/ -#ifdef NVIDIA_GPU - if (show_gpu) { - if (!cursed && first_time_gpu) - gpu_init(); - for (i = 0; i < gpu_devices; i++) { - if (cursed && first_time_gpu) { - if (nvmlDeviceGetName - (gpu_device[i], &gpu_name[i][0], - 1024) != NVML_SUCCESS) - strcpy(gpu_name[i], "NVML API Failed"); - } - if (nvmlDeviceGetUtilizationRates - (gpu_device[i], &gpu_util[i]) != NVML_SUCCESS) { - gpu_util[i].gpu = 999; - gpu_util[i].memory = 999; - } - if (nvmlDeviceGetTemperature - (gpu_device[i], NVML_TEMPERATURE_GPU, - &gpu_temp[i]) != NVML_SUCCESS) - gpu_temp[i] = 999; - if (nvmlDeviceGetPowerUsage(gpu_device[i], &gpu_watts[i]) - != NVML_SUCCESS) - gpu_watts[i] = 999000; - if (nvmlDeviceGetClockInfo - (gpu_device[i], NVML_CLOCK_GRAPHICS, - &gpu_clock[i]) != NVML_SUCCESS) - gpu_clock[i] = 999; - } - if (cursed) { - first_time_gpu = 0; - BANNER(padgpu, "NVIDIA GPU Accelerator"); - - mvwprintw(padgpu, 1, 1, - "Driver Version:%s NVML Version: %s", - gpu_driver_version, gpu_nvml_version); - - mvwprintw(padgpu, 2, 1, "GPU"); - mvwprintw(padgpu, 3, 1, "No."); - COLOUR wattrset(padgpu, COLOR_PAIR(1)); - mvwprintw(padgpu, 3, 5, "GPU-MHz"); - COLOUR wattrset(padgpu, COLOR_PAIR(2)); - mvwprintw(padgpu, 2, 14, "GPU-Utilisation"); - mvwprintw(padgpu, 3, 14, "Processor-Memory"); - COLOUR wattrset(padgpu, COLOR_PAIR(3)); - mvwprintw(padgpu, 2, 31, "Temperature"); - mvwprintw(padgpu, 3, 31, " Centigrade"); - COLOUR wattrset(padgpu, COLOR_PAIR(5)); - mvwprintw(padgpu, 2, 44, "Power-Use"); - mvwprintw(padgpu, 3, 44, " Watts"); - COLOUR wattrset(padgpu, COLOR_PAIR(0)); - mvwprintw(padgpu, 2, 55, "Name"); - - for (i = 0; i < gpu_devices; i++) { - mvwprintw(padgpu, 4 + i, 1, "%3d", i); - COLOUR wattrset(padgpu, COLOR_PAIR(1)); - mvwprintw(padgpu, 4 + i, 5, "%7d", (int) gpu_clock[i]); - COLOUR wattrset(padgpu, COLOR_PAIR(2)); - mvwprintw(padgpu, 4 + i, 14, "%7d%% %7d%%", - (int) gpu_util[i].gpu, - (int) gpu_util[i].memory); - COLOUR wattrset(padgpu, COLOR_PAIR(3)); - mvwprintw(padgpu, 4 + i, 31, "%7d", (int) gpu_temp[i]); - COLOUR wattrset(padgpu, COLOR_PAIR(5)); - mvwprintw(padgpu, 4 + i, 44, "%7.2f", - (int) gpu_watts[i] / 1000.0); - COLOUR wattrset(padgpu, COLOR_PAIR(0)); - mvwprintw(padgpu, 4 + i, 55, "%-s", &gpu_name[i][0]); - } - DISPLAY(padgpu, 8); - } else { - if (!show_rrd) { - if (first_time_gpu) { - first_time_gpu = 0; - fprintf(fp, - "GPU_UTIL,NVidia GPU Utilisation Percent"); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",GPU%d", i + 1); - fprintf(fp, "\n"); - fprintf(fp, - "GPU_MEM,NVidia Memory Utilisation Percent"); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",GPU%d", i + 1); - fprintf(fp, "\n"); - fprintf(fp, "GPU_TEMP,NVidia Temperature C"); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",GPU%d", i + 1); - fprintf(fp, "\n"); - fprintf(fp, "GPU_WATTS,NVidia Power Draw Watts"); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",GPU%d", i + 1); - fprintf(fp, "\n"); - fprintf(fp, "GPU_MHZ,NVidia GPU MHz"); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",GPU%d", i + 1); - fprintf(fp, "\n"); - } - fprintf(fp, "GPU_UTIL,%s", LOOP); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",%d", (int) gpu_util[i].gpu); - fprintf(fp, "\n"); - fprintf(fp, "GPU_MEM,%s", LOOP); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",%d", (int) gpu_util[i].memory); - fprintf(fp, "\n"); - fprintf(fp, "GPU_TEMP,%s", LOOP); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",%d", (int) gpu_temp[i]); - fprintf(fp, "\n"); - fprintf(fp, "GPU_WATTS,%s", LOOP); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",%d", (int) gpu_watts[i] / 1000); - fprintf(fp, "\n"); - fprintf(fp, "GPU_MHZ,%s", LOOP); - for (i = 0; i < gpu_devices; i++) - fprintf(fp, ",%d", (int) gpu_clock[i]); - fprintf(fp, "\n"); - } - } - } -#endif /*NVIDIA_GPU */ - if (show_mhz) { - int padline, lineno, cpuno, col, thrds, cores; -#ifdef POWER - char *clockstr = "clock "; -#define DATACOL 9 -#else - char *clockstr = "cpu MHz"; -#define DATACOL 11 -#endif /* POWER */ - proc_read(P_CPUINFO); - - if (cursed) { - /* - 0123456789012345678 - cpu MHz : 3336.183 Intel - clock : 3425.000000MHz Power - */ - lscpu_init(); -#ifdef POWER - if (lparcfg.smt_mode > lscpu.threads) - thrds = lparcfg.smt_mode; - else -#endif /*POWER*/ - thrds = lscpu.threads; - if (thrds < 1) - thrds = 1; - BANNER(padmhz, "CPU MHz per Core and Thread"); -#ifdef POWER - mvwprintw(padmhz, 1, 10, - "lparcfgSMT=%d lscpu.threads=%d mode=%d [1=AllCPUs 2=Cores 3=Graphs]", - lparcfg.smt_mode, lscpu.threads, show_mhz); -#else /*POWER */ - mvwprintw(padmhz, 1, 10, - "lscpu.threads=%d mode=%d [1=AllCPUs 2=Cores 3=Graphs]", - lscpu.threads, show_mhz); -#endif /*POWER */ - if (show_mhz == 1) - mvwprintw(padmhz, 2, 1, "CPU MHz "); - else - mvwprintw(padmhz, 2, 1, "Core MHz "); - if (show_mhz == 3) - mvwprintw(padmhz, 2, 10, - "---------1---------2---------3---------4---------5---------6 GHz"); - - col = 0; - cpuno = 1; - cores = 0; - padline = 3; - min_mhz = 999999999999999999.0; - max_mhz = 0.0; - for (lineno = 0; lineno < proc[P_CPUINFO].lines; lineno++) { - if (strncmp - (clockstr, proc[P_CPUINFO].line[lineno], - strlen(clockstr)) == 0) { - if (show_mhz == 1 - || ((show_mhz == 2 || show_mhz == 3) - && ((cpuno + 7) % thrds) == 0)) { - cores++; - mhz = 0.0; - sscanf(&proc[P_CPUINFO].line[lineno][DATACOL], - "%f", &mhz); - mvwprintw(padmhz, padline, col, "%3d=%4.0f", - (show_mhz != 1) ? cores : cpuno, - mhz); - if (show_mhz == 3) { - if (mhz > avg_mhz) { - COLOUR wattrset(padmhz, COLOR_PAIR(1)); - } else { - COLOUR wattrset(padmhz, COLOR_PAIR(2)); - } - for (i = 1; i < mhz / 100; i++) - mvwprintw(padmhz, padline, col + 9 + i, - "#"); - COLOUR wattrset(padmhz, COLOR_PAIR(0)); - for (; i < 60; i++) - mvwprintw(padmhz, padline, col + 9 + i, - " "); - } - padline++; - if (padline > 22) { - padline = 3; - col = col + 9; - } - if (mhz != 0.0) { - if (mhz < min_mhz) - min_mhz = mhz; - if (mhz > max_mhz) - max_mhz = mhz; - } - } - cpuno++; - } - if (cpuno > 160) - break; - } - avg_mhz = (min_mhz + max_mhz) / 2; - DISPLAY(padmhz, 23); - } else { - if (!show_rrd) - fprintf(fp, "MHZ,%s", LOOP); - for (lineno = 0; lineno < proc[P_CPUINFO].lines; lineno++) { - if (strncmp - (clockstr, proc[P_CPUINFO].line[lineno], - strlen(clockstr)) == 0) { - mhz = 0.0; - sscanf(&proc[P_CPUINFO].line[lineno][DATACOL], - "%f", &mhz); - if (!show_rrd) - fprintf(fp, ",%.0f", mhz); - } - } - if (!show_rrd) - fprintf(fp, "\n"); - } - } - if (show_memory) { - proc_read(P_MEMINFO); - proc_mem(); - if (cursed) { -#define RAMCOL 18 -#define SWAPCOL 30 -#define HIGHCOL 45 -#define LOWCOL 60 - - BANNER(padmem, "Memory and Swap"); - - COLOUR wattrset(padmem, COLOR_PAIR(1)); - mvwprintw(padmem, 1, 1, "PageSize:%dKB", pagesize / 1024); - COLOUR wattrset(padmem, COLOR_PAIR(0)); - mvwprintw(padmem, 2, 1, "Total in MB"); - mvwprintw(padmem, 3, 1, "Free in MB"); - mvwprintw(padmem, 4, 1, "Free Percent"); - - COLOUR wattrset(padmem, COLOR_PAIR(2)); - mvwprintw(padmem, 1, RAMCOL, "RAM-Memory"); - mvwprintw(padmem, 2, RAMCOL, "%10.1f", - p->mem.memtotal / 1024.0); - mvwprintw(padmem, 3, RAMCOL, "%10.1f", - p->mem.memfree / 1024.0); - mvwprintw(padmem, 4, RAMCOL, "%10.1f%%", - p->mem.memfree == - 0 ? 0.0 : 100.0 * (float) p->mem.memfree / - (float) p->mem.memtotal); - COLOUR wattrset(padmem, COLOR_PAIR(3)); - mvwprintw(padmem, 1, SWAPCOL, "Swap-space"); - mvwprintw(padmem, 2, SWAPCOL, "%10.1f", - p->mem.swaptotal / 1024.0); - mvwprintw(padmem, 3, SWAPCOL, "%10.1f", - p->mem.swapfree / 1024.0); - mvwprintw(padmem, 4, SWAPCOL, "%10.1f%%", - p->mem.swapfree == - 0 ? 0.0 : 100.0 * (float) p->mem.swapfree / - (float) p->mem.swaptotal); - COLOUR wattrset(padmem, COLOR_PAIR(5)); - mvwprintw(padmem, 1, HIGHCOL, "High-Memory"); - if (p->mem.hightotal > 0.0) { - mvwprintw(padmem, 2, HIGHCOL, "%8.1f", - p->mem.hightotal / 1024.0); - mvwprintw(padmem, 3, HIGHCOL, "%8.1f", - p->mem.highfree / 1024.0); - mvwprintw(padmem, 4, HIGHCOL, "%8.1f%%", - p->mem.highfree == - 0 ? 0.0 : 100.0 * (float) p->mem.highfree / - (float) p->mem.hightotal); - } else - mvwprintw(padmem, 2, HIGHCOL, "- not in use"); - COLOUR wattrset(padmem, COLOR_PAIR(6)); - mvwprintw(padmem, 1, LOWCOL, " Low-Memory"); - if (p->mem.lowtotal > 0.0) { - mvwprintw(padmem, 2, LOWCOL, "%8.1f", - p->mem.lowtotal / 1024.0); - mvwprintw(padmem, 3, LOWCOL, "%8.1f", - p->mem.lowfree / 1024.0); - mvwprintw(padmem, 4, LOWCOL, "%8.1f%%", - p->mem.lowfree == - 0 ? 0.0 : 100.0 * (float) p->mem.lowfree / - (float) p->mem.lowtotal); - } else - mvwprintw(padmem, 2, LOWCOL, "- not in use"); - COLOUR wattrset(padmem, COLOR_PAIR(5)); - - - mvwprintw(padmem, 5, 1, - "Linux Kernel Internal Memory (MB)"); -#ifdef LARGEMEM - mvwprintw(padmem, 6, 1, - " Cached=%10.1f Active=%10.1f", - p->mem.cached / 1024.0, p->mem.active / 1024.0); -#else - mvwprintw(padmem, 6, 1, - " Shared=%10.1f Cached=%10.1f Active=%10.1f", - p->mem.memshared / 1024.0, - p->mem.cached / 1024.0, p->mem.active / 1024.0); - mvwprintw(padmem, 5, 68, "MB"); - mvwprintw(padmem, 6, 55, "bigfree=%10.1f", - p->mem.bigfree / 1024); -#endif /*LARGEMEM*/ - mvwprintw(padmem, 7, 1, - "Buffers=%10.1f Swapcached=%10.1f Inactive =%10.1f", - p->mem.buffers / 1024.0, - p->mem.swapcached / 1024.0, - p->mem.inactive / 1024.0); - - mvwprintw(padmem, 8, 1, - "Dirty =%10.1f Writeback =%10.1f Mapped =%10.1f", - p->mem.dirty / 1024.0, p->mem.writeback / 1024.0, - p->mem.mapped / 1024.0); - mvwprintw(padmem, 9, 1, - "Slab =%10.1f Commit_AS =%10.1f PageTables=%10.1f", - p->mem.slab / 1024.0, - p->mem.committed_as / 1024.0, - p->mem.pagetables / 1024.0); -#ifdef POWER - if (!show_lpar) /* check if already called above */ - proc_lparcfg(); - if (lparcfg.cmo_enabled == 0) - mvwprintw(padmem, 10, 1, "AMS is not active"); - else - mvwprintw(padmem, 10, 1, - "AMS id=%d Weight=%-3d pmem=%ldMB hpi=%.1f/s hpit=%.1f(sec) Pool=%ldMB Loan=%ldKB ", - (int) lparcfg.entitled_memory_pool_number, - (int) lparcfg.entitled_memory_weight, - (long) (lparcfg.backing_memory) / 1024 / - 1024, - (double) (lparcfg.cmo_faults_diff) / elapsed, - (double) (lparcfg.cmo_fault_time_usec_diff) / - 1000 / 1000 / elapsed, - (long) lparcfg.entitled_memory_pool_size / - 1024 / 1024, - (long) lparcfg.entitled_memory_loan_request / - 1024); - - COLOUR wattrset(padmem, COLOR_PAIR(0)); - DISPLAY(padmem, 11); -#else /* POWER */ - COLOUR wattrset(padmem, COLOR_PAIR(0)); - DISPLAY(padmem, 10); -#endif /* POWER */ - } else { - - if (show_rrd) - str_p = - "rrdtool update mem.rrd %s:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f\n"; - else - str_p = - "MEM,%s,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n"; - fprintf(fp, str_p, LOOP, p->mem.memtotal / 1024.0, - p->mem.hightotal / 1024.0, - p->mem.lowtotal / 1024.0, - p->mem.swaptotal / 1024.0, p->mem.memfree / 1024.0, - p->mem.highfree / 1024.0, p->mem.lowfree / 1024.0, - p->mem.swapfree / 1024.0, - p->mem.memshared / 1024.0, p->mem.cached / 1024.0, - p->mem.active / 1024.0, -#ifdef LARGEMEM - -1.0, -#else - p->mem.bigfree / 1024.0, -#endif /*LARGEMEM*/ - p->mem.buffers / 1024.0, - p->mem.swapcached / 1024.0, - p->mem.inactive / 1024.0); -#ifdef POWER - if (lparcfg.cmo_enabled != 0) { - if (!show_rrd) - fprintf(fp, - "MEMAMS,%s,%d,%d,%.1f,%.3lf,0,0,0,%.1f,%ld,%ld,%ld\n", - LOOP, - (int) lparcfg.entitled_memory_pool_number, - (int) lparcfg.entitled_memory_weight, - (float) (lparcfg.cmo_faults_diff) / - elapsed, - (float) (lparcfg. - cmo_fault_time_usec_diff) / 1000 / - 1000 / elapsed, - /* three zeros here */ - (float) (lparcfg.backing_memory) / 1024 / - 1024, lparcfg.cmo_page_size / 1024, - lparcfg.entitled_memory_pool_size / 1024 / - 1024, - lparcfg.entitled_memory_loan_request / - 1024); - } -#ifdef EXPERIMENTAL - if (!show_rrd) - fprintf(fp, - "MEMEXPERIMENTAL,%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld\n", - LOOP, (long) lparcfg.DesEntCap, - (long) lparcfg.DesProcs, - (long) lparcfg.DesVarCapWt, - (long) lparcfg.DedDonMode, - (long) lparcfg.group, (long) lparcfg.pool, - (long) lparcfg.entitled_memory, - (long) lparcfg.entitled_memory_group_number, - (long) lparcfg. - unallocated_entitled_memory_weight, - (long) lparcfg. - unallocated_io_mapping_entitlement); -#endif /* EXPERIMENTAL */ -#endif /* POWER */ - } -/* for testing large page - p->mem.hugefree = 250; - p->mem.hugetotal = 1000; - p->mem.hugesize = 16*1024; -*/ - } - if (show_large) { - proc_read(P_MEMINFO); - proc_mem(); - if (cursed) { - BANNER(padlarge, "Large (Huge) Page"); - if (p->mem.hugetotal > 0) { - if (p->mem.hugetotal - p->mem.hugefree > huge_peak) - huge_peak = p->mem.hugetotal - p->mem.hugefree; - mvwprintw(padlarge, 1, 1, - "Total Pages=%7ld 100.0%% Huge Page Size =%ld KB", - p->mem.hugetotal, p->mem.hugesize); - mvwprintw(padlarge, 2, 1, - "Used Pages=%7ld %5.1f%% Used Pages Peak=%-8ld", - (long) (p->mem.hugetotal - p->mem.hugefree), - (p->mem.hugetotal - - p->mem.hugefree) / - (float) p->mem.hugetotal * 100.0, huge_peak); - mvwprintw(padlarge, 3, 1, "Free Pages=%7ld %5.1f%%", - p->mem.hugefree, - p->mem.hugefree / (float) p->mem.hugetotal * - 100.0); - } else { - mvwprintw(padlarge, 1, 1, " There are no Huge Pages"); - mvwprintw(padlarge, 2, 1, " - see /proc/meminfo"); - } - DISPLAY(padlarge, 4); - } else { - if (p->mem.hugetotal > 0) { - if (first_huge == 1) { - first_huge = 0; - fprintf(fp, - "HUGEPAGES,Huge Page Use %s,HugeTotal,HugeFree,HugeSizeMB\n", - run_name); - } - fprintf(fp, "HUGEPAGES,%s,%ld,%ld,%.1f\n", - LOOP, - p->mem.hugetotal, - p->mem.hugefree, p->mem.hugesize / 1024.0); - } - } - } - if (show_vm) { -#define VMDELTA(variable) (p->vm.variable - q->vm.variable) -#define VMCOUNT(variable) (p->vm.variable ) - ret = read_vmstat(); - if (cursed) { - BANNER(padpage, "Virtual Memory"); - - COLOUR wattrset(padpage, COLOR_PAIR(6)); - if (ret < 0) { - mvwprintw(padpage, 2, 2, - "Virtual Memory stats not supported with this kernel"); - mvwprintw(padpage, 3, 2, - "/proc/vmstat only seems to appear in 2.6 onwards"); - - } else { - if (vm_first_time) { - mvwprintw(padpage, 2, 2, - "Please wait - collecting data"); - vm_first_time = 0; - } else { - mvwprintw(padpage, 1, 0, - "nr_dirty =%9lld pgpgin =%8lld", - VMCOUNT(nr_dirty), VMDELTA(pgpgin)); - mvwprintw(padpage, 2, 0, - "nr_writeback=%9lld pgpgout =%8lld", - VMCOUNT(nr_writeback), VMDELTA(pgpgout)); - mvwprintw(padpage, 3, 0, - "nr_unstable =%9lld pgpswpin =%8lld", - VMCOUNT(nr_unstable), VMDELTA(pswpin)); - mvwprintw(padpage, 4, 0, - "nr_table_pgs=%9lld pgpswpout =%8lld", - VMCOUNT(nr_page_table_pages), - VMDELTA(pswpout)); - mvwprintw(padpage, 5, 0, - "nr_mapped =%9lld pgfree =%8lld", - VMCOUNT(nr_mapped), VMDELTA(pgfree)); - mvwprintw(padpage, 6, 0, - "nr_slab =%9lld pgactivate =%8lld", - VMCOUNT(nr_slab), VMDELTA(pgactivate)); - mvwprintw(padpage, 7, 0, - " pgdeactivate=%8lld", - VMDELTA(pgdeactivate)); - mvwprintw(padpage, 8, 0, - "allocstall =%9lld pgfault =%8lld kswapd_steal =%7lld", - VMDELTA(allocstall), VMDELTA(pgfault), - VMDELTA(kswapd_steal)); - mvwprintw(padpage, 9, 0, - "pageoutrun =%9lld pgmajfault =%8lld kswapd_inodesteal=%7lld", - VMDELTA(pageoutrun), VMDELTA(pgmajfault), - VMDELTA(kswapd_inodesteal)); - mvwprintw(padpage, 10, 0, - "slabs_scanned=%8lld pgrotated =%8lld pginodesteal =%7lld", - VMDELTA(slabs_scanned), - VMDELTA(pgrotated), - VMDELTA(pginodesteal)); - - - - mvwprintw(padpage, 1, 46, - " High Normal DMA"); - mvwprintw(padpage, 2, 46, - "alloc %7lld%7lld%7lld", - VMDELTA(pgalloc_high), - VMDELTA(pgalloc_normal), - VMDELTA(pgalloc_dma)); - mvwprintw(padpage, 3, 46, - "refill %7lld%7lld%7lld", - VMDELTA(pgrefill_high), - VMDELTA(pgrefill_normal), - VMDELTA(pgrefill_dma)); - mvwprintw(padpage, 4, 46, - "steal %7lld%7lld%7lld", - VMDELTA(pgsteal_high), - VMDELTA(pgsteal_normal), - VMDELTA(pgsteal_dma)); - mvwprintw(padpage, 5, 46, - "scan_kswapd%7lld%7lld%7lld", - VMDELTA(pgscan_kswapd_high), - VMDELTA(pgscan_kswapd_normal), - VMDELTA(pgscan_kswapd_dma)); - mvwprintw(padpage, 6, 46, - "scan_direct%7lld%7lld%7lld", - VMDELTA(pgscan_direct_high), - VMDELTA(pgscan_direct_normal), - VMDELTA(pgscan_direct_dma)); - } - } - COLOUR wattrset(padpage, COLOR_PAIR(0)); - DISPLAY(padpage, 11); - } else { - if (ret < 0) { - show_vm = 0; - } else if (vm_first_time) { - vm_first_time = 0; - fprintf(fp, - "VM,Paging and Virtual Memory,nr_dirty,nr_writeback,nr_unstable,nr_page_table_pages,nr_mapped,nr_slab,pgpgin,pgpgout,pswpin,pswpout,pgfree,pgactivate,pgdeactivate,pgfault,pgmajfault,pginodesteal,slabs_scanned,kswapd_steal,kswapd_inodesteal,pageoutrun,allocstall,pgrotated,pgalloc_high,pgalloc_normal,pgalloc_dma,pgrefill_high,pgrefill_normal,pgrefill_dma,pgsteal_high,pgsteal_normal,pgsteal_dma,pgscan_kswapd_high,pgscan_kswapd_normal,pgscan_kswapd_dma,pgscan_direct_high,pgscan_direct_normal,pgscan_direct_dma\n"); - } - if (show_rrd) - str_p = "rrdtool update vm.rrd %s" - ":%lld:%lld:%lld:%lld:%lld" - ":%lld:%lld:%lld:%lld:%lld" - ":%lld:%lld:%lld:%lld:%lld" - ":%lld:%lld:%lld:%lld:%lld" - ":%lld:%lld:%lld:%lld:%lld" - ":%lld:%lld:%lld:%lld:%lld" - ":%lld:%lld:%lld:%lld:%lld" ":%lld:%lld\n"; - else - str_p = "VM,%s" - ",%lld,%lld,%lld,%lld,%lld" - ",%lld,%lld,%lld,%lld,%lld" - ",%lld,%lld,%lld,%lld,%lld" - ",%lld,%lld,%lld,%lld,%lld" - ",%lld,%lld,%lld,%lld,%lld" - ",%lld,%lld,%lld,%lld,%lld" - ",%lld,%lld,%lld,%lld,%lld" ",%lld,%lld\n"; - - fprintf(fp, str_p, - LOOP, - VMCOUNT(nr_dirty), - VMCOUNT(nr_writeback), - VMCOUNT(nr_unstable), - VMCOUNT(nr_page_table_pages), - VMCOUNT(nr_mapped), - VMCOUNT(nr_slab), - VMDELTA(pgpgin), - VMDELTA(pgpgout), - VMDELTA(pswpin), - VMDELTA(pswpout), - VMDELTA(pgfree), - VMDELTA(pgactivate), - VMDELTA(pgdeactivate), - VMDELTA(pgfault), - VMDELTA(pgmajfault), - VMDELTA(pginodesteal), - VMDELTA(slabs_scanned), - VMDELTA(kswapd_steal), - VMDELTA(kswapd_inodesteal), - VMDELTA(pageoutrun), - VMDELTA(allocstall), - VMDELTA(pgrotated), - VMDELTA(pgalloc_high), - VMDELTA(pgalloc_normal), - VMDELTA(pgalloc_dma), - VMDELTA(pgrefill_high), - VMDELTA(pgrefill_normal), - VMDELTA(pgrefill_dma), - VMDELTA(pgsteal_high), - VMDELTA(pgsteal_normal), - VMDELTA(pgsteal_dma), - VMDELTA(pgscan_kswapd_high), - VMDELTA(pgscan_kswapd_normal), - VMDELTA(pgscan_kswapd_dma), - VMDELTA(pgscan_direct_high), - VMDELTA(pgscan_direct_normal), - VMDELTA(pgscan_direct_dma)); - } - } - if (show_kernel) { - proc_read(P_STAT); - proc_cpu(); - proc_read(P_UPTIME); - proc_read(P_LOADAVG); - proc_kernel(); - if (cursed) { - BANNER(padker, "Kernel and Load Average"); -#define MORECOL 21 -#define LOADCOL 41 -#define BOOTCOL 55 - COLOUR wattrset(padker, COLOR_PAIR(1)); - mvwprintw(padker, 1, 0, "Global-CPU-Stats---->"); - mvwprintw(padker, 2, 0, " /proc/stat line 1"); - mvwprintw(padker, 3, 0, "%ld ticks per second", ticks); - mvwprintw(padker, 4, 0, "100%%=1 CPUcoreThread"); - COLOUR wattrset(padker, COLOR_PAIR(2)); - mvwprintw(padker, 5, 0, "%8lld RunQueue", - p->cpu_total.running); - mvwprintw(padker, 6, 0, "%8lld Blocked", - p->cpu_total.blocked); - mvwprintw(padker, 7, 0, "%10.1f Context", - (float) (p->cpu_total.ctxt - - q->cpu_total.ctxt) / elapsed); - mvwprintw(padker, 8, 0, " Switch"); - mvwprintw(padker, 9, 0, "%10.1f Forks", - (float) (p->cpu_total.procs - - q->cpu_total.procs) / elapsed); - mvwprintw(padker, 10, 0, "%10.1f Interrupts", - (float) (p->cpu_total.intr - - q->cpu_total.intr) / elapsed); - - COLOUR wattrset(padker, COLOR_PAIR(1)); - mvwprintw(padker, 1, MORECOL, "%8.1f%% user", - (float) (RAWTOTAL(user)) / elapsed); - mvwprintw(padker, 2, MORECOL, "%8.1f%% user_nice", - (float) (RAWTOTAL(nice)) / elapsed); - mvwprintw(padker, 3, MORECOL, "%8.1f%% system", - (float) (RAWTOTAL(sys)) / elapsed); - mvwprintw(padker, 4, MORECOL, "%8.1f%% idle", - (float) (RAWTOTAL(idle)) / elapsed); - mvwprintw(padker, 5, MORECOL, "%8.1f%% iowait", - (float) (RAWTOTAL(wait)) / elapsed); - mvwprintw(padker, 6, MORECOL, "%8.1f%% irq", - (float) (RAWTOTAL(irq)) / elapsed); - mvwprintw(padker, 7, MORECOL, "%8.1f%% softirq", - (float) (RAWTOTAL(softirq)) / elapsed); - mvwprintw(padker, 8, MORECOL, "%8.1f%% steal", - (float) (RAWTOTAL(steal)) / elapsed); - mvwprintw(padker, 9, MORECOL, "%8.1f%% guest", - (float) (RAWTOTAL(guest)) / elapsed); - mvwprintw(padker, 10, MORECOL, "%8.1f%% guest_nice", - (float) (RAWTOTAL(guest_nice)) / elapsed); - - COLOUR wattrset(padker, COLOR_PAIR(3)); - mvwprintw(padker, 1, LOADCOL, "Load Average"); - mvwprintw(padker, 2, LOADCOL, " 1 mins %5.2f", - (float) p->cpu_total.mins1); - mvwprintw(padker, 3, LOADCOL, " 5 mins %5.2f", - (float) p->cpu_total.mins5); - mvwprintw(padker, 4, LOADCOL, "15 mins %5.2f", - (float) p->cpu_total.mins15); - - - COLOUR wattrset(padker, COLOR_PAIR(5)); - mvwprintw(padker, 1, BOOTCOL, "CPU use since boottime"); - - updays = p->cpu_total.uptime / 60 / 60 / 24; - uphours = - (p->cpu_total.uptime - - updays * 60 * 60 * 24) / 60 / 60; - upmins = - (p->cpu_total.uptime - updays * 60 * 60 * 24 - - uphours * 60 * 60) / 60; - mvwprintw(padker, 2, BOOTCOL, "Uptime Days Hours Mins"); - mvwprintw(padker, 3, BOOTCOL, "Uptime %4ld %5ld %4ld", - updays, uphours, upmins); - - updays = p->cpu_total.idletime / 60 / 60 / 24 / cpus; - uphours = - (p->cpu_total.idletime - - updays * 60 * 60 * 24) / 60 / 60 / cpus; - upmins = - (p->cpu_total.idletime - updays * 60 * 60 * 24 - - uphours * 60 * 60) / 60 / cpus; - mvwprintw(padker, 4, BOOTCOL, "Idle %4ld %5ld %4ld", - updays, uphours, upmins); - - average = - (p->cpu_total.uptime - - p->cpu_total.idletime) / p->cpu_total.uptime * 100.0; - if (average > 0.0) - mvwprintw(padker, 5, BOOTCOL, - "Average CPU use=%6.2f%%", average); - else - mvwprintw(padker, 5, BOOTCOL, "Uptime has overflowed"); - mvwprintw(padker, 7, BOOTCOL, "%d CPU core threads", cpus); - mvwprintw(padker, 9, BOOTCOL, "%8lld Bootime", - p->cpu_total.btime); - COLOUR wattrset(padker, COLOR_PAIR(0)); - DISPLAY(padker, 11); - } else { - if (proc_first_time) { - q->cpu_total.ctxt = p->cpu_total.ctxt; - q->cpu_total.procs = p->cpu_total.procs; - proc_first_time = 0; - } - if (show_rrd) - str_p = - "rrdtool update proc.rrd %s:%.0f:%.0f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f\n"; - else - str_p = - "PROC,%s,%.0f,%.0f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n"; - - /* These "-1"'s looks bad but it keeps the nmon for AIX format */ - /* The stats are not available in Linux . . . unless you know better! */ - fprintf(fp, str_p, LOOP, (float) p->cpu_total.running, /*runqueue */ - (float) p->cpu_total.blocked, /*swapin (# of processes waiting for IO completion */ - /*pswitch */ - (float) (p->cpu_total.ctxt - q->cpu_total.ctxt) / elapsed, -1.0, /*syscall */ - -1.0, /*read */ - -1.0, /*write */ - /*fork */ - (float) (p->cpu_total.procs - q->cpu_total.procs) / elapsed, -1.0, /*exec */ - -1.0, /*sem */ - -1.0); /*msg */ - } - } - - if (show_nfs) { - proc_read(P_NFS); - proc_read(P_NFSD); - proc_nfs(); - - if (cursed) { - if (nfs_first_time) { - memcpy(&q->nfs, &p->nfs, sizeof(struct nfs_stat)); - nfs_first_time = 0; - } - if (nfs_clear) { - nfs_clear = 0; - for (i = 0; i < 25; i++) - mvwprintw(padnfs, i, 0, - " "); - } - BANNER(padnfs, - "Network Filesystem (NFS) I/O Operations per second"); - if (show_nfs == 1) { - if (nfs_v2c_found || nfs_v2s_found) - mvwprintw(padnfs, 1, 0, - " Version 2 Client Server"); - else - mvwprintw(padnfs, 1, 0, " Version 2 not active"); - - if (nfs_v3c_found || nfs_v3s_found) - mvwprintw(padnfs, 1, 41, - "Version 3 Client Server"); - else - mvwprintw(padnfs, 1, 41, " Version 3 not active"); - } - if (show_nfs == 2) { - if (nfs_v4c_found) - mvwprintw(padnfs, 1, 0, - " Version 4 Client (%d Stats found)", - nfs_v4c_names_count); - else - mvwprintw(padnfs, 1, 0, - " Version 4 Client side not active"); - } - if (show_nfs == 3) { - if (nfs_v4s_found) - mvwprintw(padnfs, 1, 0, - " Version 4 Server (%d Stats found)", - nfs_v4s_names_count); - else - mvwprintw(padnfs, 1, 0, - " Version 4 Server side not active"); - } -#define NFS_TOTAL(member) (double)(p->member) -#define NFS_DELTA(member) (((double)(p->member - q->member)/elapsed)) - v2c_total = 0; - v2s_total = 0; - v3c_total = 0; - v3s_total = 0; - v4c_total = 0; - v4s_total = 0; - if (nfs_v3c_found || nfs_v3s_found) { - for (i = 0; i < 18; i++) { /* NFS V2 Client & Server */ - if (show_nfs == 1) - mvwprintw(padnfs, 2 + i, 3, "%12s %8.1f %8.1f", - nfs_v2_names[i], - NFS_DELTA(nfs.v2c[i]), - NFS_DELTA(nfs.v2s[i])); - v2c_total += NFS_DELTA(nfs.v2c[i]); - v2s_total += NFS_DELTA(nfs.v2s[i]); - } - } - if (nfs_v3c_found || nfs_v3s_found) { - for (i = 0; i < 22; i++) { /* NFS V3 Client & Server */ - if (show_nfs == 1) - mvwprintw(padnfs, 2 + i, 41, - "%12s %8.1f %8.1f", nfs_v3_names[i], - NFS_DELTA(nfs.v3c[i]), - NFS_DELTA(nfs.v3s[i])); - v3c_total += NFS_DELTA(nfs.v3c[i]); - v3s_total += NFS_DELTA(nfs.v3s[i]); - } - } - - if (nfs_v4c_found) { - for (i = 0; i < 18; i++) { /* NFS V4 Client */ - if (show_nfs == 2) { - mvwprintw(padnfs, 2 + i, 0, "%12s%7.1f", - nfs_v4c_names[i], - NFS_DELTA(nfs.v4c[i])); - } - v4c_total += NFS_DELTA(nfs.v4c[i]); - } - for (i = 18; i < 35; i++) { /* NFS V4 Client */ - if (show_nfs == 2) { - mvwprintw(padnfs, 2 + i - 18, 20, "%12s%7.1f", - nfs_v4c_names[i], - NFS_DELTA(nfs.v4c[i])); - } - v4c_total += NFS_DELTA(nfs.v4c[i]); - } - } - - if (nfs_v4s_found) { - for (i = 0; i < 18; i++) { /* NFS V4 Server */ - if (show_nfs == 3) { - mvwprintw(padnfs, 2 + i, 0, "%12s%7.1f", - nfs_v4s_names[i], - NFS_DELTA(nfs.v4s[i])); - } - v4s_total += NFS_DELTA(nfs.v4s[i]); - } - for (i = 18; i < 36; i++) { /* NFS V4 Server */ - if (show_nfs == 3) { - mvwprintw(padnfs, 2 + i - 18, 19, "%12s%7.1f", - nfs_v4s_names[i], - NFS_DELTA(nfs.v4s[i])); - } - v4s_total += NFS_DELTA(nfs.v4s[i]); - } - for (i = 36; i < 54 && i < nfs_v4s_names_count; i++) { /* NFS V4 Server */ - if (show_nfs == 3) { - mvwprintw(padnfs, 2 + i - 36, 39, "%12s%7.1f", - nfs_v4s_names[i], - NFS_DELTA(nfs.v4s[i])); - } - v4s_total += NFS_DELTA(nfs.v4s[i]); - } - for (i = 54; i <= 70 && i < nfs_v4s_names_count; i++) { /* NFS V4 Server */ - if (show_nfs == 3) { - mvwprintw(padnfs, 2 + i - 54, 59, "%12s%7.1f", - nfs_v4s_names[i], - NFS_DELTA(nfs.v4s[i])); - } - v4s_total += NFS_DELTA(nfs.v4s[i]); - } - } - mvwprintw(padnfs, 2 + 18, 1, - "--NFS-Totals->---Client----Server--"); - /* if(nfs_v2c_found || nfs_v2s_found) */ - mvwprintw(padnfs, 2 + 19, 1, "NFSv2 Totals->%9.1f %9.1f", - v2c_total, v2s_total); - /* if(nfs_v3c_found || nfs_v3s_found) */ - mvwprintw(padnfs, 2 + 20, 1, "NFSv3 Totals->%9.1f %9.1f", - v3c_total, v3s_total); - /* if(nfs_v4c_found || nfs_v4s_found) */ - mvwprintw(padnfs, 2 + 21, 1, "NFSv4 Totals->%9.1f %9.1f", - v4c_total, v4s_total); - - DISPLAY(padnfs, 24); - } else { - if (nfs_first_time && !show_rrd) { - if (nfs_v2c_found) { - fprintf(fp, "NFSCLIV2,NFS Client v2"); - for (i = 0; i < 18; i++) - fprintf(fp, ",%s", nfs_v2_names[i]); - fprintf(fp, "\n"); - } - if (nfs_v2s_found) { - fprintf(fp, "NFSSVRV2,NFS Server v2"); - for (i = 0; i < 18; i++) - fprintf(fp, ",%s", nfs_v2_names[i]); - fprintf(fp, "\n"); - } - - if (nfs_v3c_found) { - fprintf(fp, "NFSCLIV3,NFS Client v3"); - for (i = 0; i < 22; i++) - fprintf(fp, ",%s", nfs_v3_names[i]); - fprintf(fp, "\n"); - } - if (nfs_v3s_found) { - fprintf(fp, "NFSSVRV3,NFS Server v3"); - for (i = 0; i < 22; i++) - fprintf(fp, ",%s", nfs_v3_names[i]); - fprintf(fp, "\n"); - } - - if (nfs_v4c_found) { - fprintf(fp, "NFSCLIV4,NFS Client v4"); - for (i = 0; i < nfs_v4c_names_count; i++) - fprintf(fp, ",%s", nfs_v4c_names[i]); - fprintf(fp, "\n"); - } - if (nfs_v4s_found) { - fprintf(fp, "NFSSVRV4,NFS Server v4"); - for (i = 0; i < nfs_v4s_names_count; i++) - fprintf(fp, ",%s", nfs_v4s_names[i]); - fprintf(fp, "\n"); - } - memcpy(&q->nfs, &p->nfs, sizeof(struct nfs_stat)); - nfs_first_time = 0; - } - if (nfs_v2c_found) { - fprintf(fp, - show_rrd ? "rrdtool update nfscliv2.rrd %s" : - "NFSCLIV2,%s", LOOP); - for (i = 0; i < 18; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (double) NFS_DELTA(nfs.v2c[i])); - } - fprintf(fp, "\n"); - } - if (nfs_v2s_found) { - fprintf(fp, - show_rrd ? "rrdtool update nfsvrv2.rrd %s" : - "NFSSVRV2,%s", LOOP); - for (i = 0; i < 18; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (double) NFS_DELTA(nfs.v2s[i])); - } - fprintf(fp, "\n"); - } - if (nfs_v3c_found) { - fprintf(fp, - show_rrd ? "rrdtool update nfscliv3.rrd %s" : - "NFSCLIV3,%s", LOOP); - for (i = 0; i < 22; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (double) NFS_DELTA(nfs.v3c[i])); - } - fprintf(fp, "\n"); - } - if (nfs_v3s_found) { - fprintf(fp, - show_rrd ? "rrdtool update nfsvrv3.rrd %s" : - "NFSSVRV3,%s", LOOP); - for (i = 0; i < 22; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (double) NFS_DELTA(nfs.v3s[i])); - } - fprintf(fp, "\n"); - } - - if (nfs_v4c_found) { - fprintf(fp, - show_rrd ? "rrdtool update nfscliv4.rrd %s" : - "NFSCLIV4,%s", LOOP); - for (i = 0; i < nfs_v4c_names_count; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (double) NFS_DELTA(nfs.v4c[i])); - } - fprintf(fp, "\n"); - } - if (nfs_v4s_found) { - fprintf(fp, - show_rrd ? "rrdtool update nfsvrv4.rrd %s" : - "NFSSVRV4,%s", LOOP); - for (i = 0; i < nfs_v4c_names_count; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (double) NFS_DELTA(nfs.v4s[i])); - } - fprintf(fp, "\n"); - } - } - } - if (show_net) { - if (cursed) { - BANNER(padnet, "Network I/O"); -#define RKB 9 -#define TKB 19 -#define PIN 30 -#define POUT 37 -#define SIN 45 -#define SOUT 52 -#define PKHEAD 60 -#define PKIN 66 -#define PKOUT 71 -/* - 1 2 3 4 5 6 7 - 01234567890123456789012345678901234567890123456789012345678901234567890123456789 - mvwprintw(padnet,1, 0, "I/F Name Recv=KB/s Trans=KB/s packin packout insize outsize Peak->Recv Trans"); -*/ - COLOUR wattrset(padnet, COLOR_PAIR(0)); - mvwprintw(padnet, 1, 0, "I/F Name"); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 1, RKB, "Recv=KB/s"); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 1, TKB, "Trans=KB/s"); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 1, PIN, "packin"); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 1, POUT, "packout"); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 1, SIN, "insize"); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 1, SOUT, "outsize"); - COLOUR wattrset(padnet, COLOR_PAIR(0)); - mvwprintw(padnet, 1, PKHEAD, "Peak->"); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 1, PKIN, "Recv"); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 1, PKOUT, "Trans"); - COLOUR wattrset(padnet, COLOR_PAIR(0)); - } - proc_net(); - for (i = 0; i < networks; i++) { - -#define IFDELTA(member) ((float)( (q->ifnets[i].member > p->ifnets[i].member) ? 0 : (p->ifnets[i].member - q->ifnets[i].member)/elapsed) ) -#define IFDELTA_ZERO(member1,member2) ((IFDELTA(member1) == 0) || (IFDELTA(member2)== 0)? 0.0 : IFDELTA(member1)/IFDELTA(member2) ) - - if (net_read_peak[i] < IFDELTA(if_ibytes) / 1024.0) - net_read_peak[i] = IFDELTA(if_ibytes) / 1024.0; - if (net_write_peak[i] < IFDELTA(if_obytes) / 1024.0) - net_write_peak[i] = IFDELTA(if_obytes) / 1024.0; -/* - 1 2 3 4 5 6 7 -01234567890123456789012345678901234567890123456789012345678901234567890123456789 -I/F Name Recv=KB/s Trans=KB/s packin packout insize outsize Peak->Recv Trans - eth3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - lo 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - eth2 0.5 0.2 8.5 0.5 64.0 314.0 53.4 24.6 - eth1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 - eth0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 -*/ - if (cursed) { - COLOUR wattrset(padnet, COLOR_PAIR(0)); - mvwprintw(padnet, 2 + i, 0, "%8s", - &p->ifnets[i].if_name[0]); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 2 + i, RKB, "%8.1f", - IFDELTA(if_ibytes) / 1024.0); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 2 + i, TKB, "%8.1f", - IFDELTA(if_obytes) / 1024.0); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 2 + i, PIN, "%7.1f", - IFDELTA(if_ipackets)); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 2 + i, POUT, "%7.1f", - IFDELTA(if_opackets)); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 2 + i, SIN, "%7.1f", - IFDELTA_ZERO(if_ibytes, if_ipackets)); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 2 + i, SOUT, "%7.1f", - IFDELTA_ZERO(if_obytes, if_opackets)); - COLOUR wattrset(padnet, COLOR_PAIR(2)); - mvwprintw(padnet, 2 + i, PKIN - 4, "%8.1f", - net_read_peak[i]); - COLOUR wattrset(padnet, COLOR_PAIR(3)); - mvwprintw(padnet, 2 + i, PKOUT, "%8.1f", - net_write_peak[i]); - } - } - DISPLAY(padnet, networks + 2); - if (!cursed) { - fprintf(fp, - show_rrd ? "rrdtool update net.rrd %s" : "NET,%s", - LOOP); - for (i = 0; i < networks; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - IFDELTA(if_ibytes) / 1024.0); - } - for (i = 0; i < networks; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - IFDELTA(if_obytes) / 1024.0); - } - fprintf(fp, "\n"); - fprintf(fp, - show_rrd ? "rrdtool update netpacket.rrd %s" : - "NETPACKET,%s", LOOP); - for (i = 0; i < networks; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - IFDELTA(if_ipackets)); - } - for (i = 0; i < networks; i++) { - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - IFDELTA(if_opackets)); - } - fprintf(fp, "\n"); - } - } - errors = 0; - for (i = 0; i < networks; i++) { - errors += p->ifnets[i].if_ierrs - q->ifnets[i].if_ierrs - + p->ifnets[i].if_oerrs - q->ifnets[i].if_oerrs - + p->ifnets[i].if_ocolls - q->ifnets[i].if_ocolls; - } - if (errors) - show_neterror = 3; - if (show_neterror) { - if (cursed) { - BANNER(padneterr, "Network Error Counters"); - mvwprintw(padneterr, 1, 0, - "I/F Name iErrors iDrop iOverrun iFrame oErrors oDrop oOverrun oCarrier oColls "); - } - for (i = 0; i < networks; i++) { - CURSE mvwprintw(padneterr, 2 + i, 0, - "%8s %7lu %7lu %7lu %7lu %7lu %7lu %7lu %7lu %7lu", - &p->ifnets[i].if_name[0], - p->ifnets[i].if_ierrs, - p->ifnets[i].if_idrop, - p->ifnets[i].if_ififo, - p->ifnets[i].if_iframe, - p->ifnets[i].if_oerrs, - p->ifnets[i].if_odrop, - p->ifnets[i].if_ofifo, - p->ifnets[i].if_ocarrier, - p->ifnets[i].if_ocolls); - - } - DISPLAY(padneterr, networks + 2); - if (show_neterror > 0) - show_neterror--; - } -#ifdef JFS - if (show_jfs) { - if (cursed) { - BANNER(padjfs, "File Systems"); - mvwprintw(padjfs, 1, 0, - "Filesystem SizeMB FreeMB Use%% Type MountPoint"); - - for (k = 0; k < jfses; k++) { - fs_size = 0; - fs_bsize = 0; - fs_free = 0; - fs_size_used = 100.0; - if (jfs[k].mounted) { - if (!strncmp(jfs[k].name, "/proc/", 6) /* sub directorys have to be fake too */ - ||!strncmp(jfs[k].name, "/sys/", 5) - || !strncmp(jfs[k].name, "/dev/", 5) - || !strncmp(jfs[k].name, "/proc", 6) /* one more than the string to ensure the NULL */ - ||!strncmp(jfs[k].name, "/sys", 5) - || !strncmp(jfs[k].name, "/dev", 5) - || !strncmp(jfs[k].name, "/rpc_pipe", 10) - ) { /* /proc gives invalid/insane values */ - mvwprintw(padjfs, 2 + k, 0, "%-14s", - jfs[k].name); - mvwprintw(padjfs, 2 + k, 27, "-"); - mvwprintw(padjfs, 2 + k, 35, "-"); - mvwprintw(padjfs, 2 + k, 41, "-"); - COLOUR wattrset(padjfs, COLOR_PAIR(4)); - mvwprintw(padjfs, 2 + k, 43, - "%-8s not a real filesystem", - jfs[k].type); - COLOUR wattrset(padjfs, COLOR_PAIR(0)); - } else { - statfs_buffer.f_blocks = 0; - if ((ret = - fstatfs(jfs[k].fd, - &statfs_buffer)) != -1) { - if (statfs_buffer.f_blocks != 0) { - /* older Linux seemed to always report in 4KB blocks but - newer Linux release use the f_bsize block sizes but - the man statfs docs the field as the natural I/O size so - the blocks reported here are ambigous in size */ - if (statfs_buffer.f_bsize == 0) - fs_bsize = 4.0 * 1024.0; - else - fs_bsize = statfs_buffer.f_bsize; - /* convert blocks to MB */ - fs_size = - (float) statfs_buffer.f_blocks * - fs_bsize / 1024.0 / 1024.0; - - /* find the best size info available f_bavail is like df reports - otherwise use f_bsize (this includes inode blocks) */ - if (statfs_buffer.f_bavail == 0) - fs_free = - (float) statfs_buffer.f_bfree * - fs_bsize / 1024.0 / 1024.0; - else - fs_free = - (float) statfs_buffer. - f_bavail * fs_bsize / 1024.0 / - 1024.0; - - /* this is a percentage */ - fs_size_used = - (fs_size - - (float) statfs_buffer.f_bfree * - fs_bsize / 1024.0 / 1024.0) / - fs_size * 100.0; - /* try to get the same number as df using kludge */ - /*fs_size_used += 1.0; */ - if (fs_size_used > 100.0) - fs_size_used = 100.0; - - if ((i = strlen(jfs[k].device)) < 20) - str_p = &jfs[k].device[0]; - else { - str_p = &jfs[k].device[i - 20]; - } - mvwprintw(padjfs, 2 + k, 0, - "%-20s %7.0f %7.0f %4.0f%% %-8s %s", - str_p, fs_size, fs_free, - ceil(fs_size_used), - jfs[k].type, jfs[k].name); - - } else { - mvwprintw(padjfs, 2 + k, 0, "%s", - jfs[k].name); - COLOUR wattrset(padjfs, COLOR_PAIR(5)); - mvwprintw(padjfs, 2 + k, 43, - "%-8s size=zero blocks!", - jfs[k].type); - COLOUR wattrset(padjfs, COLOR_PAIR(0)); - } - } else { - mvwprintw(padjfs, 2 + k, 0, "%s", - jfs[k].name); - COLOUR wattrset(padjfs, COLOR_PAIR(3)); - mvwprintw(padjfs, 2 + k, 43, - "%-8s statfs failed", - jfs[k].type); - COLOUR wattrset(padjfs, COLOR_PAIR(0)); - } - } - } else { - mvwprintw(padjfs, 2 + k, 0, "%-14s", jfs[k].name); - COLOUR wattrset(padjfs, COLOR_PAIR(1)); - mvwprintw(padjfs, 2 + k, 43, "%-8s not mounted", - jfs[k].type); - COLOUR wattrset(padjfs, COLOR_PAIR(0)); - } - } - DISPLAY(padjfs, 2 + jfses); - } else { - jfs_load(LOAD); - fprintf(fp, - show_rrd ? "rrdtool update jfsfile.rrd %s" : - "JFSFILE,%s", LOOP); - for (k = 0; k < jfses; k++) { - if (jfs[k].mounted && strncmp(jfs[k].name, "/proc", 5) - && strncmp(jfs[k].name, "/sys", 4) - && strncmp(jfs[k].name, "/dev/", 5) - && strncmp(jfs[k].name, "/run/", 5) - && strncmp(jfs[k].name, "/var/lib/nfs/rpc", 16) - ) { /* /proc gives invalid/insane values */ - if (fstatfs(jfs[k].fd, &statfs_buffer) != -1) { - if (statfs_buffer.f_bsize == 0) - fs_bsize = 4.0 * 1024.0; - else - fs_bsize = statfs_buffer.f_bsize; - /* convert blocks to MB */ - fs_size = - (float) statfs_buffer.f_blocks * fs_bsize / - 1024.0 / 1024.0; - - /* find the best size info available f_bavail is like df reports - otherwise use f_bsize (this includes inode blocks) */ - if (statfs_buffer.f_bavail == 0) - fs_free = - (float) statfs_buffer.f_bfree * - fs_bsize / 1024.0 / 1024.0; - else - fs_free = - (float) statfs_buffer.f_bavail * - fs_bsize / 1024.0 / 1024.0; - - - - if (fs_size <= 0.0 || fs_bsize <= 0.0) /* some pseudo filesystems have zero size but we get a -nan result */ - fs_size_used = 0.0; - else - fs_size_used = - (fs_size - - (float) statfs_buffer.f_bfree * - fs_bsize / 1024.0 / 1024.0) / - fs_size * 100.0; - - if (fs_size_used > 100.0) - fs_size_used = 100.0; - - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - fs_size_used); - } else - fprintf(fp, show_rrd ? ":U" : ",0.0"); - } - } - fprintf(fp, "\n"); - jfs_load(UNLOAD); - } - } -#endif /* JFS */ - - if (show_disk || show_verbose || show_diskmap || show_dgroup) { - proc_read(P_STAT); - proc_disk(elapsed); - } - if (show_diskmap) { - BANNER(padmap, "Disk %%Busy Map"); - mvwprintw(padmap, 0, 18, - "Key: @=90 #=80 X=70 8=60 O=50 0=40 o=30 +=20 -=10 .=5 _=0%%"); - mvwprintw(padmap, 1, 0, - " Disk No. 1 2 3 4 5 6 "); - if (disk_first_time) { - disk_first_time = 0; - mvwprintw(padmap, 2, 0, - "Please wait - collecting disk data"); - } else { - mvwprintw(padmap, 2, 0, - "Disks=%-4d 0123456789012345678901234567890123456789012345678901234567890123", - disks); - mvwprintw(padmap, 3, 0, "disk 0 to 63 "); - for (i = 0; i < disks; i++) { - disk_busy = DKDELTA(dk_time) / elapsed; - disk_read = DKDELTA(dk_rkb) / elapsed; - disk_write = DKDELTA(dk_wkb) / elapsed; - /* ensure boundaries */ - if (disk_busy < 0) - disk_busy = 0; - else if (disk_busy > 99) - disk_busy = 99; - -#define MAPWRAP 64 - mvwprintw(padmap, 3 + (int) (i / MAPWRAP), - 13 + (i % MAPWRAP), "%c", - disk_busy_map_ch[(int) disk_busy]); - } - } - DISPLAY(padmap, 4 + disks / MAPWRAP); - } - if (show_verbose) { - top_disk_busy = 0.0; - top_disk_name = ""; - for (i = 0, k = 0; i < disks; i++) { - disk_busy = DKDELTA(dk_time) / elapsed; - if (disk_busy > top_disk_busy) { - top_disk_busy = disk_busy; - top_disk_name = p->dk[i].dk_name; - } - } - if (top_disk_busy > 80.0) { - COLOUR wattrset(padverb, COLOR_PAIR(1)); - mvwprintw(padverb, 3, 0, " DANGER"); - } else if (top_disk_busy > 60.0) { - COLOUR wattrset(padverb, COLOR_PAIR(4)); - mvwprintw(padverb, 3, 0, "Warning"); - } else { - COLOUR wattrset(padverb, COLOR_PAIR(2)); - mvwprintw(padverb, 3, 0, " OK"); - } - COLOUR wattrset(padverb, COLOR_PAIR(0)); - mvwprintw(padverb, 3, 8, - "-> Top Disk %8s %%busy %5.1f%%\t>40%%\t>60%% ", - top_disk_name, top_disk_busy); - move(x, 0); - } - if (show_disk) { - if (cursed) { - if (show_disk) { - BANNER(paddisk, "Disk I/O"); - switch (disk_mode) { - case DISK_MODE_PARTITIONS: - mvwprintw(paddisk, 0, 12, "/proc/partitions"); - break; - case DISK_MODE_DISKSTATS: - mvwprintw(paddisk, 0, 12, "/proc/diskstats"); - break; - case DISK_MODE_IO: - mvwprintw(paddisk, 0, 12, "/proc/stat+disk_io"); - break; - } - mvwprintw(paddisk, 0, 31, "mostly in KB/s"); - mvwprintw(paddisk, 0, 50, - "Warning:contains duplicates"); - switch (show_disk) { - case SHOW_DISK_STATS: - mvwprintw(paddisk, 1, 0, "DiskName Busy"); - COLOUR wattrset(paddisk, COLOR_PAIR(6)); - mvwprintw(paddisk, 1, 17, "Read"); - COLOUR wattrset(paddisk, COLOR_PAIR(3)); - mvwprintw(paddisk, 1, 25, "Write"); - COLOUR wattrset(paddisk, COLOR_PAIR(0)); - mvwprintw(paddisk, 1, 37, - "Xfers Size Peak%% Peak-RW InFlight "); - break; - case SHOW_DISK_GRAPH: - mvwprintw(paddisk, 1, 0, "DiskName Busy "); - COLOUR wattrset(paddisk, COLOR_PAIR(6)); - mvwprintw(paddisk, 1, 15, "Read "); - COLOUR wattrset(paddisk, COLOR_PAIR(3)); - mvwprintw(paddisk, 1, 20, "Write"); - COLOUR wattrset(paddisk, COLOR_PAIR(0)); - mvwprintw(paddisk, 1, 25, - "KB|0 |25 |50 |75 100|"); - break; - } - } - if (disk_first_time) { - disk_first_time = 0; - mvwprintw(paddisk, 2, 0, - "Please wait - collecting disk data"); - } else { - total_disk_read = 0.0; - total_disk_write = 0.0; - total_disk_xfers = 0.0; - disk_mb = 0; - for (i = 0, k = 0; i < disks; i++) { - disk_read = DKDELTA(dk_rkb) / elapsed; - disk_write = DKDELTA(dk_wkb) / elapsed; - if ((show_disk == SHOW_DISK_GRAPH) - && (disk_read > 9999.9 - || disk_write > 9999.9)) { - disk_mb = 1; - COLOUR wattrset(paddisk, COLOR_PAIR(1)); - mvwprintw(paddisk, 1, 25, "MB"); - COLOUR wattrset(paddisk, COLOR_PAIR(0)); - break; - } - } - for (i = 0, k = 0; i < disks; i++) { - if (disk_only_mode - && is_dgroup_name(p->dk[i].dk_name) == 0) - continue; - -/* - if(p->dk[i].dk_name[0] == 'h') - continue; -*/ - disk_busy = DKDELTA(dk_time) / elapsed; - disk_read = DKDELTA(dk_rkb) / elapsed; - disk_write = DKDELTA(dk_wkb) / elapsed; - disk_xfers = DKDELTA(dk_xfers); - - total_disk_read += disk_read; - total_disk_write += disk_write; - total_disk_xfers += disk_xfers; - - if (disk_busy_peak[i] < disk_busy) - disk_busy_peak[i] = disk_busy; - if (disk_rate_peak[i] < (disk_read + disk_write)) - disk_rate_peak[i] = disk_read + disk_write; - if (!show_all && disk_busy < 1) - continue; - - if (strlen(p->dk[i].dk_name) > 8) - str_p = - &p->dk[i]. - dk_name[strlen(p->dk[i].dk_name) - 8]; - else - str_p = &p->dk[i].dk_name[0]; - - if (show_disk == SHOW_DISK_STATS) { - /* output disks stats */ - mvwprintw(paddisk, 2 + k, 0, "%-8s%4.0f%%", - str_p, disk_busy); - COLOUR wattrset(paddisk, COLOR_PAIR(6)); - mvwprintw(paddisk, 2 + k, 13, "%9.1f", - disk_read); - COLOUR wattrset(paddisk, COLOR_PAIR(3)); - mvwprintw(paddisk, 2 + k, 22, "%9.1fKB/s", - disk_write); - COLOUR wattrset(paddisk, COLOR_PAIR(0)); - mvwprintw(paddisk, 2 + k, 31, - "KB/s %6.1f %5.1fKB %3.0f%% %9.1fKB/s %3d", - disk_xfers / elapsed, - disk_xfers == - 0.0 ? 0.0 : (DKDELTA(dk_rkb) + - DKDELTA(dk_wkb)) / - disk_xfers, disk_busy_peak[i], - disk_rate_peak[i], - p->dk[i].dk_inflight); - k++; - } - if (show_disk == SHOW_DISK_GRAPH) { - /* output disk bar graphs */ - if (disk_mb) { - disk_read_tmp = disk_read / 1024.0; - disk_write_tmp = disk_write / 1024.0; - } else { - disk_read_tmp = disk_read; - disk_write_tmp = disk_write; - } - - mvwprintw(paddisk, 2 + k, 0, "%-8s %3.0f%%", - str_p, disk_busy); - COLOUR wattrset(paddisk, COLOR_PAIR(6)); - mvwprintw(paddisk, 2 + k, 13, "%7.1f", - disk_read_tmp); - COLOUR wattrset(paddisk, COLOR_PAIR(3)); - mvwprintw(paddisk, 2 + k, 20, "%7.1f", - disk_write_tmp); - COLOUR wattrset(paddisk, COLOR_PAIR(0)); - - mvwprintw(paddisk, 2 + k, 27, - "| "); - wmove(paddisk, 2 + k, 28); - if (disk_busy > 100) - disk_busy = 100; - if (disk_busy > 0.0 - && (disk_write + disk_read) > 0.1) { - /* 50 columns in the disk graph area so divide % by two */ - readers = - disk_busy * disk_read / (disk_write + - disk_read) / - 2; - writers = - disk_busy * disk_write / (disk_write + - disk_read) / - 2; - if (readers + writers > 50) { - readers = 0; - writers = 0; - } - /* don't go beyond row 78 i.e. j = 28 + 50 */ - for (j = 0; j < readers && j < 50; j++) { - COLOUR wattrset(paddisk, - COLOR_PAIR(12)); - wprintw(paddisk, "R"); - COLOUR wattrset(paddisk, - COLOR_PAIR(0)); - } - for (; j < readers + writers && j < 50; - j++) { - COLOUR wattrset(paddisk, - COLOR_PAIR(11)); - wprintw(paddisk, "W"); - COLOUR wattrset(paddisk, - COLOR_PAIR(0)); - } - for (j = disk_busy; j < 50; j++) - wprintw(paddisk, " "); - } else { - for (j = 0; j < 50; j++) - wprintw(paddisk, " "); - if (p->dk[i].dk_time == 0.0) - mvwprintw(paddisk, 2 + k, 27, - "| disk busy not available"); - } - if (disk_busy_peak[i] > 100) - disk_busy_peak[i] = 100; - - mvwprintw(paddisk, 2 + i, 77, "|"); - /* check rounding has not got the peak ">" over the 100% */ - j = 28 + (int) (disk_busy_peak[i] / 2); - if (j > 77) - j = 77; - mvwprintw(paddisk, 2 + i, j, ">"); - k++; - } - } - mvwprintw(paddisk, 2 + k, 0, - "Totals Read-MB/s=%-8.1f Writes-MB/s=%-8.1f Transfers/sec=%-8.1f", - total_disk_read / 1024.0, - total_disk_write / 1024.0, - total_disk_xfers / elapsed); - - } - DISPLAY(paddisk, 3 + k); - } else { - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, - show_rrd ? - "%srrdtool update diskbusy%s.rrd %s" : - "%sDISKBUSY%s,%s", i == 0 ? "" : "\n", - dskgrp(i), LOOP); - /* check percentage is correct */ - ftmp = DKDELTA(dk_time) / elapsed; - if (ftmp > 100.0 || ftmp < 0.0) - fprintf(fp, show_rrd ? ":U" : ",101.00"); - else - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - DKDELTA(dk_time) / elapsed); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, - show_rrd ? - "\nrrdtool update diskread%s.rrd %s" : - "\nDISKREAD%s,%s", dskgrp(i), LOOP); - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - DKDELTA(dk_rkb) / elapsed); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, - show_rrd ? - "\nrrdtool update diskwrite%s.rrd %s" : - "\nDISKWRITE%s,%s", dskgrp(i), LOOP); - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - DKDELTA(dk_wkb) / elapsed); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, - show_rrd ? - "\nrrdtool update diskxfer%s.rrd %s" : - "\nDISKXFER%s,%s", dskgrp(i), LOOP); - disk_xfers = DKDELTA(dk_xfers); - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - disk_xfers / elapsed); - } - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) - fprintf(fp, - show_rrd ? - "\nrrdtool update diskbsize%s.rrd %s" : - "\nDISKBSIZE%s,%s", dskgrp(i), LOOP); - disk_xfers = DKDELTA(dk_xfers); - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - disk_xfers == 0.0 ? 0.0 : - (DKDELTA(dk_rkb) + - DKDELTA(dk_wkb)) / disk_xfers); - } - - if (extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS) { - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) { - fprintf(fp, "\nDISKREADS%s,%s", dskgrp(i), - LOOP); - } - disk_read = DKDELTA(dk_reads); - fprintf(fp, ",%.1f", disk_read / elapsed); - } - - for (i = 0; i < disks; i++) { - if (NEWDISKGROUP(i)) { - fprintf(fp, "\nDISKWRITES%s,%s", dskgrp(i), - LOOP); - } - disk_write = DKDELTA(dk_writes); - fprintf(fp, ",%.1f", disk_write / elapsed); - } - } - fprintf(fp, "\n"); - } - } - if ((show_dgroup || (!cursed && dgroup_loaded))) { - if (cursed) { - BANNER(paddg, "Disk Group I/O"); - if (dgroup_loaded != 2 || dgroup_total_disks == 0) { - mvwprintw(paddg, 1, 1, - "No Disk Groups found use -g groupfile when starting nmon"); - n = 0; - } else if (disk_first_time) { - disk_first_time = 0; - mvwprintw(paddg, 1, 1, - "Please wait - collecting disk data"); - } else { - mvwprintw(paddg, 1, 1, - "Name Disks AvgBusy | TotalMB/s xfers/s BlockSizeKB"); - COLOUR wattrset(paddg, COLOR_PAIR(6)); - mvwprintw(paddg, 1, 29, "Read-KB/s"); - COLOUR wattrset(paddg, COLOR_PAIR(3)); - mvwprintw(paddg, 1, 39, "Write"); - COLOUR wattrset(paddg, COLOR_PAIR(0)); - total_busy = 0.0; - total_rbytes = 0.0; - total_wbytes = 0.0; - total_xfers = 0.0; - for (k = n = 0; k < dgroup_total_groups; k++) { -/* - if (dgroup_name[k] == 0 ) - continue; -*/ - disk_busy = 0.0; - disk_read = 0.0; - disk_write = 0.0; - disk_xfers = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_busy += DKDELTA(dk_time) / elapsed; -/* - disk_read += DKDELTA(dk_reads) * p->dk[i].dk_bsize / 1024.0 /elapsed; - disk_write += DKDELTA(dk_writes) * p->dk[i].dk_bsize / 1024.0 /elapsed; -*/ - disk_read += DKDELTA(dk_rkb) / elapsed; - disk_write += DKDELTA(dk_wkb) / elapsed; - disk_xfers += DKDELTA(dk_xfers) / elapsed; - } - } - if (dgroup_disks[k] == 0) - disk_busy = 0.0; - else - disk_busy = disk_busy / dgroup_disks[k]; - total_busy += disk_busy; - total_rbytes += disk_read; - total_wbytes += disk_write; - total_xfers += disk_xfers; -/* if (!show_all && (disk_read < 1.0 && disk_write < 1.0)) - continue; -*/ - if ((disk_read + disk_write) == 0 - || disk_xfers == 0) - disk_size = 0.0; - else - disk_size = - ((float) disk_read + - (float) disk_write) / (float) disk_xfers; - mvwprintw(paddg, n + 2, 1, "%-14s %3d %5.1f%% | %6.1f %9.1f %6.1f ", dgroup_name[k], dgroup_disks[k], disk_busy, (disk_read + disk_write) / 1024, /* in MB */ - disk_xfers, disk_size); - COLOUR wattrset(paddg, COLOR_PAIR(6)); - mvwprintw(paddg, n + 2, 29, "%9.1f", disk_read); - COLOUR wattrset(paddg, COLOR_PAIR(3)); - mvwprintw(paddg, n + 2, 39, "%-9.1f", disk_write); - COLOUR wattrset(paddg, COLOR_PAIR(0)); - n++; - } - mvwprintw(paddg, n + 2, 1, "Groups=%2d TOTALS %3d %5.1f%% %9.1f|%-9.1f %6.1f %9.1f", n, dgroup_total_disks, total_busy / dgroup_total_disks, total_rbytes, total_wbytes, (((double) total_rbytes + (double) total_wbytes)) / 1024, /* in MB */ - total_xfers); - } - DISPLAY(paddg, 3 + dgroup_total_groups); - } else { - if (dgroup_loaded == 2) { - fprintf(fp, - show_rrd ? "rrdtool update dgbusy.rdd %s" : - "DGBUSY,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += - DKDELTA(dk_time) / elapsed; - } - } - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - (float) (disk_total / - dgroup_disks[k])); - } - } - fprintf(fp, "\n"); - fprintf(fp, - show_rrd ? "rrdtool update dgread.rdd %s" : - "DGREAD,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { -/* - disk_total += DKDELTA(dk_reads) * p->dk[i].dk_bsize / 1024.0; -*/ - disk_total += DKDELTA(dk_rkb); - } - } - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - disk_total / elapsed); - } - } - fprintf(fp, "\n"); - fprintf(fp, - show_rrd ? "rrdtool update dgwrite.rdd %s" : - "DGWRITE,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { -/* - disk_total += DKDELTA(dk_writes) * p->dk[i].dk_bsize / 1024.0; -*/ - disk_total += DKDELTA(dk_wkb); - } - } - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - disk_total / elapsed); - } - } - fprintf(fp, "\n"); - fprintf(fp, - show_rrd ? "rrdtool update dgbsize.rdd %s" : - "DGSIZE,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_write = 0.0; - disk_xfers = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { -/* - disk_write += (DKDELTA(dk_reads) + DKDELTA(dk_writes) ) * p->dk[i].dk_bsize / 1024.0; -*/ - disk_write += - (DKDELTA(dk_rkb) + - DKDELTA(dk_wkb)); - disk_xfers += DKDELTA(dk_xfers); - } - } - if (disk_write == 0.0 || disk_xfers == 0.0) - disk_size = 0.0; - else - disk_size = disk_write / disk_xfers; - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - disk_size); - } - } - fprintf(fp, "\n"); - fprintf(fp, - show_rrd ? "rrdtool update dgxfer.rdd %s" : - "DGXFER,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_xfers); - } - } - fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", - disk_total / elapsed); - } - } - fprintf(fp, "\n"); - - if (extended_disk == 1 - && disk_mode == DISK_MODE_DISKSTATS) { - fprintf(fp, "DGREADS,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_reads); - } - } - fprintf(fp, ",%.1f", disk_total / elapsed); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGREADMERGE,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_rmerge); - } - } - fprintf(fp, ",%.1f", disk_total / elapsed); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGREADSERV,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_rmsec); - } - } - fprintf(fp, ",%.1f", disk_total); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGWRITES,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_writes); - } - } - fprintf(fp, ",%.1f", disk_total / elapsed); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGWRITEMERGE,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_wmerge); - } - } - fprintf(fp, ",%.1f", disk_total / elapsed); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGWRITESERV,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_wmsec); - } - } - fprintf(fp, ",%.1f", disk_total); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGINFLIGHT,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += p->dk[i].dk_inflight; - } - } - fprintf(fp, ",%.1f", disk_total); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGIOTIME,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_time); - } - } - fprintf(fp, ",%.1f", disk_total); - } - } - fprintf(fp, "\n"); - fprintf(fp, "DGBACKLOG,%s", LOOP); - for (k = 0; k < dgroup_total_groups; k++) { - if (dgroup_name[k] != 0) { - disk_total = 0.0; - for (j = 0; j < dgroup_disks[k]; j++) { - i = dgroup_data[k * DGROUPITEMS + j]; - if (i != -1) { - disk_total += DKDELTA(dk_backlog); - } - } - fprintf(fp, ",%.1f", disk_total); - } - } - fprintf(fp, "\n"); - } /* if( extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS */ - } /* if (dgroup_loaded == 2) */ - } /* else from if(cursed) */ - } - /* if ((show_dgroup || (!cursed && dgroup_loaded))) */ - if (show_top) { - wmove(padtop, 1, 1); - wclrtobot(padtop); - /* Get the details of the running processes */ - skipped = 0; - n = getprocs(0); - if (n > p->nprocs) { - n = n + 128; /* allow for growth in the number of processes in the mean time */ - p->procs = REALLOC(p->procs, sizeof(struct procsinfo) * (n + 1)); /* add one to avoid overrun */ - p->nprocs = n; - } - - n = getprocs(1); - - if (topper_size < n) { - topper = REALLOC(topper, sizeof(struct topper) * (n + 1)); /* add one to avoid overrun */ - topper_size = n; - } - /* Sort the processes by CPU utilisation */ - for (i = 0, max_sorted = 0; i < n; i++) { - /* move forward in the previous array to find a match */ - for (j = 0; j < q->nprocs; j++) { - if (p->procs[i].pi_pid == q->procs[j].pi_pid) { /* found a match */ - topper[max_sorted].index = i; - topper[max_sorted].other = j; - topper[max_sorted].time = - TIMEDELTA(pi_utime, i, j) + TIMEDELTA(pi_stime, - i, j); - topper[max_sorted].size = - p->procs[i].statm_resident; - if (isroot) - topper[max_sorted].io = - COUNTDELTA(read_io) + COUNTDELTA(write_io); - - max_sorted++; - break; - } - } - } - switch (show_topmode) { - default: - case 3: - qsort((void *) &topper[0], max_sorted, - sizeof(struct topper), &cpu_compare); - break; - case 4: - qsort((void *) &topper[0], max_sorted, - sizeof(struct topper), &size_compare); - break; - case 5: - qsort((void *) &topper[0], max_sorted, - sizeof(struct topper), &disk_compare); - break; - } - CURSE BANNER(padtop, "Top Processes"); - if (isroot) { - CURSE mvwprintw(padtop, 0, 15, - "Procs=%d mode=%d (1=Basic, 3=Perf 4=Size 5=I/O)", - n, show_topmode); - } else { - CURSE mvwprintw(padtop, 0, 15, - "Procs=%d mode=%d (1=Basic, 3=Perf 4=Size 5=I/O[root-only])", - n, show_topmode); - } - if (cursed && top_first_time) { - top_first_time = 0; - mvwprintw(padtop, 1, 1, - "Please wait - information being collected"); - } else { - switch (show_topmode) { - case 1: - CURSE mvwprintw(padtop, 1, 1, - " PID PPID Pgrp Nice Prior Status proc-Flag Command"); - for (j = 0; j < max_sorted; j++) { - i = topper[j].index; - if (p->procs[i].pi_pgrp == p->procs[i].pi_pid) - strcpy(pgrp, "none"); - else - sprintf(&pgrp[0], "%d", p->procs[i].pi_pgrp); - /* skip over processes with 0 CPU */ - if (!show_all - && (topper[j].time / elapsed < - ignore_procdisk_threshold) && !cmdfound) - break; - if (x + j + 2 - skipped > LINES + 2) /* +2 to for safety :-) */ - break; - CURSE mvwprintw(padtop, j + 2 - skipped, 1, - "%7d %7d %6s %4d %4d %9s 0x%08x %1s %-32s", - p->procs[i].pi_pid, - p->procs[i].pi_ppid, pgrp, - p->procs[i].pi_nice, - p->procs[i].pi_pri, - (topper[j].time * 100 / - elapsed) ? "Running " : - get_state(p->procs[i].pi_state), - p->procs[i].pi_flags, - (p->procs[i]. - pi_tty_nr ? "F" : " "), - p->procs[i].pi_comm); - } - break; - case 3: - case 4: - case 5: - - if (show_args == ARGS_ONLY) { - formatstring = - " PID %%CPU ResSize Command "; - } else if (COLS > 119) { - if (show_topmode == 5) - formatstring = - " PID %%CPU Size Res Res Res Res Shared StorageKB Command"; - else - formatstring = - " PID %%CPU Size Res Res Res Res Shared Faults Command"; - } else { - if (show_topmode == 5) - formatstring = - " PID %%CPU Size Res Res Res Res Shared StorageKB Command"; - else - formatstring = - " PID %%CPU Size Res Res Res Res Shared Faults Command"; - } - CURSE mvwprintw(padtop, 1, y, formatstring); - - if (show_args == ARGS_ONLY) { - formatstring = - " Used KB "; - } else if (COLS > 119) { - if (show_topmode == 5) - formatstring = - " Used KB Set Text Data Lib KB Read Write"; - else - formatstring = - " Used KB Set Text Data Lib KB Min Maj"; - } else { - if (show_topmode == 5) - formatstring = - " Used KB Set Text Data Lib KB ReadWrite "; - else - formatstring = - " Used KB Set Text Data Lib KB Min Maj "; - } - CURSE mvwprintw(padtop, 2, 1, formatstring); - for (j = 0; j < max_sorted; j++) { - i = topper[j].index; - if (!show_all) { - /* skip processes with zero CPU/io */ - if (show_topmode == 3 - && (topper[j].time / elapsed) < - ignore_procdisk_threshold && !cmdfound) - break; - if (show_topmode == 5 - && (topper[j].io < ignore_io_threshold - && !cmdfound)) - break; - } - if (cursed) { - if (x + j + 3 - skipped > LINES + 2) /* +2 to for safety :-) XYZXYZ */ - break; - if (cmdfound && !cmdcheck(p->procs[i].pi_comm)) { - skipped++; - continue; - } - if (show_args == ARGS_ONLY) { - mvwprintw(padtop, j + 3 - skipped, 1, "%7d %5.1f %7lu %-120s", p->procs[i].pi_pid, topper[j].time / elapsed, p->procs[i].statm_resident * pagesize / 1024, /* in KB */ - args_lookup(p->procs[i].pi_pid, - p->procs[i]. - pi_comm)); - } else { - if (COLS > 119) - formatstring = - "%8d %7.1f %7lu %7lu %7lu %7lu %7lu %5lu %6d %6d %-32s"; - else - formatstring = - "%7d %5.1f %5lu %5lu %5lu %5lu %5lu %5lu %4d %4d %-32s"; - - mvwprintw(padtop, j + 3 - skipped, 1, - formatstring, p->procs[i].pi_pid, - topper[j].time / elapsed, - /* topper[j].time /1000.0 / elapsed, */ - p->procs[i].statm_size * pagesize / 1024UL, /* in KB */ - p->procs[i].statm_resident * pagesize / 1024UL, /* in KB */ - p->procs[i].statm_trs * pagesize / 1024UL, /* in KB */ - p->procs[i].statm_drs * pagesize / 1024UL, /* in KB */ - p->procs[i].statm_lrs * pagesize / 1024UL, /* in KB */ - p->procs[i].statm_share * pagesize / 1024UL, /* in KB */ - show_topmode == - 5 ? (int) (COUNTDELTA(read_io) / - elapsed / - 1024) - : (int) (COUNTDELTA(pi_minflt) / - elapsed), - show_topmode == - 5 ? (int) (COUNTDELTA(write_io) / - elapsed / - 1024) - : (int) (COUNTDELTA(pi_majflt) / - elapsed), - p->procs[i].pi_comm); - } - } else { - if ((cmdfound && cmdcheck(p->procs[i].pi_comm)) - || (!cmdfound - && ((topper[j].time / elapsed) > - ignore_procdisk_threshold))) { -#ifndef KERNEL_2_6_18 - fprintf(fp, - "TOP,%07d,%s,%.2f,%.2f,%.2f,%lu,%lu,%lu,%lu,%lu,%d,%d,%s\n", -#else - fprintf(fp, - "TOP,%07d,%s,%.2f,%.2f,%.2f,%lu,%lu,%lu,%lu,%lu,%d,%d,%s,%ld,%llu\n", -#endif - /* 1 */ p->procs[i].pi_pid, - /* 2 */ LOOP, - /* 3 */ topper[j].time / elapsed, - /* 4 */ TIMEDELTA(pi_utime, i, - topper[j]. - other) / elapsed, - /* 5 */ TIMEDELTA(pi_stime, i, - topper[j]. - other) / elapsed, - /* 6 */ p->procs[i].statm_size * pagesize / 1024UL, - /* in KB */ - /* 7 */ p->procs[i].statm_resident * pagesize / 1024UL, - /* in KB */ - /* 8 */ p->procs[i].statm_trs * pagesize / 1024UL, - /* in KB */ - /* 9 */ p->procs[i].statm_drs * pagesize / 1024UL, - /* in KB */ - /* 10 */ p->procs[i].statm_share * pagesize / 1024UL, - /* in KB */ - /* 11 */ - (int) (COUNTDELTA(pi_minflt) / - elapsed), - /* 12 */ - (int) (COUNTDELTA(pi_majflt) / - elapsed), - /* 13 */ p->procs[i].pi_comm -#ifndef KERNEL_2_6_18 - ); -#else - , - p->procs[i].pi_num_threads, - COUNTDELTA - (pi_delayacct_blkio_ticks) - ); -#endif - - if (show_args) - args_output(p->procs[i].pi_pid, loop, - p->procs[i].pi_comm); - - } else - skipped++; - } - } - break; - } - } - DISPLAY(padtop, 3 + j); - } - - if (cursed) { - if (show_verbose) { - y = x; - x = 1; - DISPLAY(padverb, 4); - x = y; - } - /* underline the end of the stats area border */ - if (x < LINES - 2) - mvwhline(stdscr, x, 1, ACS_HLINE, COLS - 2); - - wmove(stdscr, 0, 0); - wrefresh(stdscr); - doupdate(); - - for (i = 0; i < seconds; i++) { - sleep(1); - if (checkinput()) - break; - } - if (x < LINES - 2) - mvwhline(stdscr, x, 1, ' ', COLS - 2); - if (first_key_pressed == 0) { - first_key_pressed = 1; - wmove(stdscr, 0, 0); - wclear(stdscr); - wmove(stdscr, 0, 0); - wclrtobot(stdscr); - wrefresh(stdscr); - doupdate(); - } - - } else { - fflush(NULL); - - gettimeofday(&nmon_tv, 0); - nmon_end_time = - (double) nmon_tv.tv_sec + - (double) nmon_tv.tv_usec * 1.0e-6; - if (nmon_run_time < 0.0) { - nmon_start_time = nmon_end_time; - nmon_run_time = 0.0; - } - nmon_run_time += (nmon_end_time - nmon_start_time); - if (nmon_run_time < 1.0) { - secs = seconds; /* sleep for the requested number of seconds */ - } else { - seconds_over = (int) nmon_run_time; /* reduce the sleep time by whole number of seconds */ - secs = seconds - seconds_over; - nmon_run_time -= (double) seconds_over; - } - if (secs < 1) /* sanity check in case CPUs are flat out and nmon taking far to long to complete */ - secs = 1; - - redo: - errno = 0; - ret = sleep(secs); - if ((ret != 0 || errno != 0) && loop != maxloops) { - fprintf(fp, - "ERROR,%s, sleep interrupted, sleep(%d seconds), return value=%d", - LOOP, secs, ret); - fprintf(fp, ", errno=%d\n", errno); - secs = ret; - goto redo; - } - gettimeofday(&nmon_tv, 0); - nmon_start_time = - (double) nmon_tv.tv_sec + - (double) nmon_tv.tv_usec * 1.0e-6; - } - - switcher(); - - if (loop >= maxloops) { - CURSE endwin(); - if (nmon_end) { - child_start(CHLD_END, nmon_end, time_stamp_type, loop, - timer); - /* Give the end - processing some time - 5s for now */ - sleep(5); - } - - fflush(NULL); - exit(0); - } - } -} diff --git a/lmon16e.c b/lmon16e.c new file mode 100644 index 0000000..80a97d9 --- /dev/null +++ b/lmon16e.c @@ -0,0 +1,8561 @@ +/* + * lmon.c -- Curses based Performance Monitor for Linux + * with saving performance stats to a CSV file mode. + * Developer: Nigel Griffiths. + * (C) Copyright 2009 Nigel Griffiths + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/* + * Use the following Makefile (for Linux on POWER) +CFLAGS=-g -D JFS -D GETUSER -Wall -D LARGEMEM -D POWER -D KERNEL_2_6_18lmon15ibeta10.c +LDFLAGS=-lcurses -lm +nmon: lmon.o + * end of Makefile + */ +/* Other #ifdef's for specific features or platforms +Platforms: POWER MAINFRAME X86 - only one of these at a time +Specific Linux versions: RHEL7 SLES113 SLES12 +Specific feature: NVIDIA_GPU +Bug / missing feature workarounds: + REREAD - for RHEL3 + LSBLK_NO_TYPE - SLES11.3 has not lsblk disk TYPE option + +Options which should always but switched on: +GETUSER - U optio to load user details +JFS - include FileSystem stats (most of which are now Journeled) +LARGMEM - most Linux's do not have older LOW and High Memory memory +KERNEL_2_6_18 1 kernel level and above adds the following to the disk stats + pi_num_threads, + pi_rt_priority, + pi_policy, + pi_delayacct_blkio_ticks +*/ + +/* note: RAW assumes you are using the index "i" to select the CPU */ +#define RAW(member) (long)((long)(p->cpuN[i].member) - (long)(q->cpuN[i].member)) +#define RAWTOTAL(member) (long)((long)(p->cpu_total.member) - (long)(q->cpu_total.member)) + +#define VERSION "16e" +char version[] = VERSION; +static char *SccsId = "nmon " VERSION; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Windows moved here so they can be cleared when the screen mode changes */ +WINDOW *padwelcome = NULL; +WINDOW *padtop = NULL; +WINDOW *padmem = NULL; +WINDOW *padlarge = NULL; +WINDOW *padpage = NULL; +WINDOW *padker = NULL; +WINDOW *padnet = NULL; +WINDOW *padneterr = NULL; +WINDOW *padnfs = NULL; +WINDOW *padres = NULL; +WINDOW *padsmp = NULL; +WINDOW *padutil = NULL; +WINDOW *padwide = NULL; +WINDOW *padgpu = NULL; +WINDOW *padmhz = NULL; +WINDOW *padlong = NULL; +WINDOW *paddisk = NULL; +WINDOW *paddg = NULL; +WINDOW *padmap = NULL; +WINDOW *padjfs = NULL; +#ifdef POWER +WINDOW *padlpar = NULL; +#endif +WINDOW *padverb = NULL; +WINDOW *padhelp = NULL; + + +/* for Disk Busy rain style output covering 100's of diskss on one screen */ +const char disk_busy_map_ch[] = + "_____.....----------++++++++++oooooooooo0000000000OOOOOOOOOO8888888888XXXXXXXXXX##########@@@@@@@@@@*"; +/*"00000555551111111111222222222233333333334444444444555555555566666666667777777777888888888899999999991"*/ + +int extended_disk = 0; /* report additional data from /proc/diskstats to spreadsheet output */ + +#define FLIP(variable) if(variable) variable=0; else variable=1; + +#ifdef MALLOC_DEBUG +#define MALLOC(argument) mymalloc(argument,__LINE__) +#define FREE(argument) myfree(argument,__LINE__) +#define REALLOC(argument1,argument2) myrealloc(argument1,argument2,__LINE__) +void *mymalloc(int size, int line) +{ + void *ptr; + ptr = malloc(size); + fprintf(stderr, "0x%x = malloc(%d) at line=%d\n", ptr, size, line); + return ptr; +} + +void myfree(void *ptr, int line) +{ + fprintf(stderr, "free(0x%x) at line=%d\n", ptr, line); + free(ptr); +} + +void *myrealloc(void *oldptr, int size, int line) +{ + void *ptr; + ptr = realloc(oldptr, size); + fprintf(stderr, "0x%x = realloc(0x%x, %d) at line=%d\n", ptr, oldptr, + size, line); + return ptr; +} +#else +#define MALLOC(argument) malloc(argument) +#define FREE(argument) free(argument) +#define REALLOC(argument1,argument2) realloc(argument1,argument2) +#endif /* MALLOC STUFF */ + +#ifdef NVIDIA_GPU +typedef int nvmlReturn_t; +#define NVML_SUCCESS 0 + +typedef struct nvmlUtilization_st { + unsigned int gpu; + unsigned int memory; +} nvmlUtilization_t; + +struct nvmlDevice_st; +typedef struct nvmlDevice_st *nvmlDevice_t; + +nvmlReturn_t nvmlInit(void); +nvmlReturn_t nvmlShutdown(void); +nvmlReturn_t nvmlDeviceGetCount(unsigned int *count); +nvmlReturn_t nvmlDeviceGetHandleByIndex(unsigned int index, + nvmlDevice_t * device); +nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, + nvmlUtilization_t * + utilization); +nvmlReturn_t nvmlSystemGetDriverVersion(char *version, int count); +nvmlReturn_t nvmlSystemGetNVMLVersion(char *version, int count); +nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, int count); +nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, int type, + unsigned int *temp); +nvmlReturn_t nvmlDeviceGetPowerUsage(nvmlDevice_t device, + unsigned int *watts); +nvmlReturn_t nvmlDeviceGetClockInfo(nvmlDevice_t device, int type, + unsigned int *mhz); + +#define NVML_TEMPERATURE_GPU 0 +#define NVML_CLOCK_GRAPHICS 0 + +nvmlDevice_t gpu_device[4]; +nvmlUtilization_t gpu_util[4]; +unsigned int gpu_devices; +char gpu_name[4][1024]; +unsigned int gpu_temp[4]; +unsigned int gpu_watts[4]; +unsigned int gpu_clock[4]; +char gpu_driver_version[1024]; +char gpu_nvml_version[1024]; +int first_time_gpu = 1; + +void gpu_init() +{ + int i; + nvmlReturn_t nvres; + if ((nvres = nvmlInit()) != NVML_SUCCESS) { + printf("nvmlInit failed %d\n", nvres); + return; + } + + if ((nvres = + nvmlSystemGetDriverVersion(&gpu_driver_version[0], + 1024)) != NVML_SUCCESS) { + printf("nvmlSystemGetDriverVersion failed %d\n", nvres); + return; + } + if ((nvres = + nvmlSystemGetNVMLVersion(&gpu_nvml_version[0], + 1024)) != NVML_SUCCESS) { + printf("nvmlSystemGetDriverVersion failed %d\n", nvres); + return; + } + + if ((nvres = nvmlDeviceGetCount(&gpu_devices)) != NVML_SUCCESS) { + printf("nvmlDeviceGetCount failed %d\n", nvres); + return; + } + if (gpu_devices > 4) + gpu_devices = 4; + + for (i = 0; i < gpu_devices; i++) { + if (nvmlDeviceGetHandleByIndex(i, &gpu_device[i]) != NVML_SUCCESS) { + printf("nvmlDeviceGetHandleByIndex(%d) failed %d\n", i, nvres); + return; + } + } +} +#endif /* NVIDIA_GPU */ + +#define P_CPUINFO 0 +#define P_STAT 1 +#define P_VERSION 2 +#define P_MEMINFO 3 +#define P_UPTIME 4 +#define P_LOADAVG 5 +#define P_NFS 6 +#define P_NFSD 7 +#define P_VMSTAT 8 /* new in 13h */ +#define P_NUMBER 9 /* one more than the max */ + +char *month[12] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", + "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" +}; + +/* Cut of everything after the first space in callback + * Delete any '&' just before the space + */ +char *check_call_string(char *callback, const char *name) +{ + char *tmp_ptr = callback; + + if (strlen(callback) > 256) { + fprintf(stderr, "ERROR nmon: ignoring %s - too long\n", name); + return (char *) NULL; + } + + for (; *tmp_ptr != '\0' && *tmp_ptr != ' ' && *tmp_ptr != '&'; + ++tmp_ptr); + + *tmp_ptr = '\0'; + + if (tmp_ptr == callback) + return (char *) NULL; + else + return callback; +} + +/* Remove error output to this buffer and display it if NMONDEBUG=1 */ +char errorstr[70]; +int error_on = 0; +void error(char *err) +{ + strncpy(errorstr, err, 69); +} + +/* + * lscpu command output save +*/ +/* lscpu +x86 Ubuntu 15.04 +nag@violet:~$ lscpu +Architecture: x86_64 +CPU op-mode(s): 32-bit, 64-bit +Byte Order: Little Endian +CPU(s): 8 +On-line CPU(s) list: 0-7 +Thread(s) per core: 1 +Core(s) per socket: 2 +Socket(s): 4 +NUMA node(s): 1 +Vendor ID: GenuineIntel +CPU family: 15 +Model: 6 +Model name: Genuine Intel(R) CPU 3.33GHz +Stepping: 8 +CPU MHz: 3336.183 +BogoMIPS: 6672.64 +Virtualisation: VT-x +L1d cache: 16K +L2 cache: 1024K +L3 cache: 16384K +NUMA node0 CPU(s): 0-7 + +x86 Ubuntu 14.10 +nag@ultraviolet:~$ lscpu +Architecture: x86_64 +CPU op-mode(s): 32-bit, 64-bit +Byte Order: Little Endian +CPU(s): 12 +On-line CPU(s) list: 0-11 +Thread(s) per core: 2 +Core(s) per socket: 6 +Socket(s): 1 +NUMA node(s): 1 +Vendor ID: GenuineIntel +CPU family: 6 +Model: 44 +Model name: Intel(R) Xeon(R) CPU E5645 @ 2.40GHz +Stepping: 2 +CPU MHz: 2394.000 +CPU max MHz: 2394.0000 +CPU min MHz: 1596.0000 +BogoMIPS: 4800.36 +Virtualization: VT-x +L1d cache: 32K +L1i cache: 32K +L2 cache: 256K +L3 cache: 12288K +NUMA node0 CPU(s): 0-11 + +POWER PowerKVM host SMT=off fout POWER8 with 5 cores each +[root@lemon ~]# lscpu +Architecture: ppc64 +CPU op-mode(s): 32-bit, 64-bit +Byte Order: Big Endian +CPU(s): 160 +On-line CPU(s) list: 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152 +Off-line CPU(s) list: 1-7,9-15,17-23,25-31,33-39,41-47,49-55,57-63,65-71,73-79,81-87,89-95,97-103,105-111,113-119,121-127,129-135,137-143,145-151,153-159 +Thread(s) per core: 1 +Core(s) per socket: 5 +Socket(s): 4 +NUMA node(s): 4 +Model: 8247-22L +CPU max MHz: 3690.0000 +CPU min MHz: 2061.0000 +L1d cache: 64K +L1i cache: 32K +L2 cache: 512K +L3 cache: 8192K +NUMA node0 CPU(s): 0,8,16,24,32 +NUMA node1 CPU(s): 40,48,56,64,72 +NUMA node16 CPU(s): 80,88,96,104,112 +NUMA node17 CPU(s): 120,128,136,144,152 + +POWER8 S812LC single 10 core POWER SMT=8 Ubuntu 14.04.03 +user1@maroon:~$ lscpu +Architecture: ppc64le +Byte Order: Little Endian +CPU(s): 80 +On-line CPU(s) list: 0-79 +Thread(s) per core: 8 +Core(s) per socket: 10 +Socket(s): 1 +NUMA node(s): 1 +Model: 8348-21C +L1d cache: 64K +L1i cache: 32K +L2 cache: 512K +L3 cache: 8192K +NUMA node0 CPU(s): 0-79 + +POWER8 S824 four POWER8 with 8 cores each SMT=8 RHEL 7.1 BE +[root@vm17 ~]# lscpu +Architecture: ppc64 +CPU op-mode(s): 32-bit, 64-bit +Byte Order: Big Endian +CPU(s): 32 +On-line CPU(s) list: 0-31 +Thread(s) per core: 8 +Core(s) per socket: 1 +Socket(s): 4 +NUMA node(s): 3 +Model: IBM,8286-42A +L1d cache: 64K +L1i cache: 32K +NUMA node0 CPU(s): 0-31 +NUMA node2 CPU(s): +NUMA node3 CPU(s): + +POWER8 SLES 11.3 S822A CPU count is WRONG! +vm20:~ # lscpu +Architecture: ppc64 +Byte Order: Big Endian +CPU(s): 64 +On-line CPU(s) list: 0-31 +Off-line CPU(s) list: 32-63 +Thread(s) per core: 8 +Core(s) per socket: 1 +Socket(s): 4 +NUMA node(s): 2 +Model: IBM,8284-22A +Hypervisor vendor: pHyp +Virtualization type: full +L1d cache: 64K +L1i cache: 32K +NUMA node0 CPU(s): 0-31 +NUMA node1 CPU(s): +*/ +int lscpu_available = 0; + +struct { + char *arch; + char *byte_order; +#define ORDER_UNKNOWN 0 +#define ORDER_LITTLE 1 +#define ORDER_BIG 2 + int order; + int cpus; + char *cpu_online; + char *cpu_offline; + int threads; + int cores; + int sockets; + int numa_nodes; + char *model; + char *model_name; + int mhz; + int mhz_min; + int mhz_max; +} lscpu; + +void lscpu_init() +{ + FILE *pop; + int i; +#define LSCPU_STRLEN 256 +#define NUMBER_COL 23 + char tmpstr[LSCPU_STRLEN + 1]; + + if (lscpu_available == 1) + return; + pop = popen("/usr/bin/lscpu 2>/dev/null", "r"); + if (pop != NULL) { + lscpu_available = 1; + tmpstr[0] = 0; + for (i = 0;; i++) { + if (fgets(tmpstr, LSCPU_STRLEN, pop) == NULL) + break; + tmpstr[strlen(tmpstr) - 1] = 0; /* remove newline */ + if (strncmp("Architecture:", tmpstr, strlen("Architecture:")) + == 0) { + lscpu.arch = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); + strcpy(lscpu.arch, &tmpstr[NUMBER_COL]); + } + if (strncmp("Byte Order:", tmpstr, strlen("Byte Order:")) == 0) { + lscpu.byte_order = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); + strcpy(lscpu.byte_order, &tmpstr[NUMBER_COL]); + if (strncmp + ("Little Endian", lscpu.byte_order, + strlen("Little Endian")) == 0) { + lscpu.order = ORDER_LITTLE; + } + if (strncmp + ("Big Endian", lscpu.byte_order, + strlen("Big Endian")) == 0) { + lscpu.order = ORDER_BIG; + } + } + if (strncmp("CPU(s):", tmpstr, strlen("CPU(s):")) == 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.cpus); + } + if (strncmp + ("On-line CPU(s) list:", tmpstr, + strlen("On-line CPU(s) list:")) == 0) { + lscpu.cpu_online = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); + strcpy(lscpu.cpu_online, &tmpstr[NUMBER_COL]); + } + if (strncmp + ("Off-line CPU(s) list:", tmpstr, + strlen("Off-line CPU(s) list:")) == 0) { + lscpu.cpu_offline = + malloc(strlen(&tmpstr[NUMBER_COL]) + 1); + strcpy(lscpu.cpu_offline, &tmpstr[NUMBER_COL]); + } + if (strncmp("Model:", tmpstr, strlen("Model:")) == 0) { + lscpu.model = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); + strcpy(lscpu.model, &tmpstr[NUMBER_COL]); + } + if (strncmp("Model name:", tmpstr, strlen("Model name:")) == 0) { + lscpu.model_name = malloc(strlen(&tmpstr[NUMBER_COL]) + 1); + strcpy(lscpu.model_name, &tmpstr[NUMBER_COL]); + } + if (strncmp + ("Thread(s) per core:", tmpstr, + strlen("Thread(s) per core:")) == 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.threads); + } + if (strncmp + ("Core(s) per socket:", tmpstr, + strlen("Core(s) per socket:")) == 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.cores); + } + if (strncmp("Socket(s):", tmpstr, strlen("Socket(s):")) == 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.sockets); + } + if (strncmp("NUMA node(s):", tmpstr, strlen("NUMA node(s):")) + == 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.numa_nodes); + } + if (strncmp("CPU MHz:", tmpstr, strlen("CPU MHz:")) == 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.mhz); + } + if (strncmp("CPU max MHz:", tmpstr, strlen("CPU max MHz:")) == + 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.mhz_max); + } + if (strncmp("CPU min MHz:", tmpstr, strlen("CPU min MHz:")) == + 0) { + sscanf(&tmpstr[NUMBER_COL], "%d", &lscpu.mhz_min); + } + } + pclose(pop); + } + +} + +/* Maximum number of lines in /proc files */ +/* Intel already has 26 (so here 30) per Hypterthread CPU (max 128*2 CPUs here) */ +/* POWER has only 6 to 7 lines but gets 1536 SMT threads soon */ +/* Erring on the saf side below */ +#define PROC_MAXLINES (16*1024) /*MAGIC COOKIE WARNING */ + + +int proc_cpu_done = 0; /* Flag if we have run function proc_cpu() already in this interval */ + +int reread = 0; +struct { + FILE *fp; + char *filename; + int size; + int lines; + char *line[PROC_MAXLINES]; + char *buf; + int read_this_interval; /* track updates for each update to stop double data collection */ +} proc[P_NUMBER]; + +void proc_init() +{ + proc[P_CPUINFO].filename = "/proc/cpuinfo"; + proc[P_STAT].filename = "/proc/stat"; + proc[P_VERSION].filename = "/proc/version"; + proc[P_MEMINFO].filename = "/proc/meminfo"; + proc[P_UPTIME].filename = "/proc/uptime"; + proc[P_LOADAVG].filename = "/proc/loadavg"; + proc[P_NFS].filename = "/proc/net/rpc/nfs"; + proc[P_NFSD].filename = "/proc/net/rpc/nfsd"; + proc[P_VMSTAT].filename = "/proc/vmstat"; +} + +void proc_read(int num) +{ + int i; + int size; + int found; + char buf[1024]; + + if (proc[num].read_this_interval == 1) + return; + + if (proc[num].fp == 0) { + if ((proc[num].fp = fopen(proc[num].filename, "r")) == NULL) { + sprintf(buf, "failed to open file %s", proc[num].filename); + error(buf); + proc[num].fp = 0; + return; + } + } + rewind(proc[num].fp); + + /* We re-read P_STAT, now flag proc_cpu() that it has to re-process that data */ + if (num == P_STAT) + proc_cpu_done = 0; + + if (proc[num].size == 0) { + /* first time so allocate initial now */ + proc[num].buf = MALLOC(512); + proc[num].size = 512; + } + + for (i = 0; i < 4096; i++) { /* MAGIC COOKIE WARNING POWER8 default install can have 2655 processes */ + size = fread(proc[num].buf, 1, proc[num].size - 1, proc[num].fp); + if (size < proc[num].size - 1) + break; + proc[num].size += 512; + proc[num].buf = REALLOC(proc[num].buf, proc[num].size); + rewind(proc[num].fp); + } + + proc[num].buf[size] = 0; + proc[num].lines = 0; + proc[num].line[0] = &proc[num].buf[0]; + if (num == P_VERSION) { + found = 0; + for (i = 0; i < size; i++) { /* remove some weird stuff found the hard way in various Linux versions and device drivers */ + /* place ") (" on two lines */ + if (found == 0 && + proc[num].buf[i] == ')' && + proc[num].buf[i + 1] == ' ' && + proc[num].buf[i + 2] == '(') { + proc[num].buf[i + 1] = '\n'; + found = 1; + } else { + /* place ") #" on two lines */ + if (proc[num].buf[i] == ')' && + proc[num].buf[i + 1] == ' ' && + proc[num].buf[i + 2] == '#') { + proc[num].buf[i + 1] = '\n'; + } + /* place "#1" on two lines */ + if (proc[num].buf[i] == '#' && proc[num].buf[i + 2] == '1') { + proc[num].buf[i] = '\n'; + } + } + } + } + for (i = 0; i < size; i++) { + /* replace Tab characters with space */ + if (proc[num].buf[i] == '\t') { + proc[num].buf[i] = ' '; + } else if (proc[num].buf[i] == '\n') { + /* replace newline characters with null */ + proc[num].lines++; + proc[num].buf[i] = '\0'; + proc[num].line[proc[num].lines] = &proc[num].buf[i + 1]; + } + if (proc[num].lines == PROC_MAXLINES - 1) + break; + } + if (reread) { + fclose(proc[num].fp); + proc[num].fp = 0; + } + /* Set flag so we do not re-read the data even if called multiple times in same interval */ + proc[num].read_this_interval = 1; +} + +#include + +struct procsinfo { + int pi_pid; + char pi_comm[64]; + char pi_state; + int pi_ppid; + int pi_pgrp; + int pi_session; + int pi_tty_nr; + int pi_tty_pgrp; + unsigned long pi_flags; + unsigned long pi_minflt; + unsigned long pi_cmin_flt; + unsigned long pi_majflt; + unsigned long pi_cmaj_flt; + unsigned long pi_utime; + unsigned long pi_stime; + long pi_cutime; + long pi_cstime; + long pi_pri; + long pi_nice; +#ifndef KERNEL_2_6_18 + long junk /* removed */ ; +#else + long pi_num_threads; +#endif + long pi_it_real_value; + unsigned long pi_start_time; + unsigned long pi_vsize; + long pi_rss; /* - 3 */ + unsigned long pi_rlim_cur; + unsigned long pi_start_code; + unsigned long pi_end_code; + unsigned long pi_start_stack; + unsigned long pi_esp; + unsigned long pi_eip; + /* The signal information here is obsolete. */ + unsigned long pi_pending_signal; + unsigned long pi_blocked_sig; + unsigned long pi_sigign; + unsigned long pi_sigcatch; + unsigned long pi_wchan; + unsigned long pi_nswap; + unsigned long pi_cnswap; + int pi_exit_signal; + int pi_cpu; +#ifdef KERNEL_2_6_18 + unsigned long pi_rt_priority; + unsigned long pi_policy; + unsigned long long pi_delayacct_blkio_ticks; +#endif + unsigned long statm_size; /* total program size */ + unsigned long statm_resident; /* resident set size */ + unsigned long statm_share; /* shared pages */ + unsigned long statm_trs; /* text (code) */ + unsigned long statm_drs; /* data/stack */ + unsigned long statm_lrs; /* library */ + unsigned long statm_dt; /* dirty pages */ + + unsigned long long read_io; /* storage read bytes */ + unsigned long long write_io; /* storage write bytes */ +}; +int isroot = 0; + +#include +#include +#include +#include +#include + +int debug = 0; +time_t timer; /* used to work out the hour/min/second */ + +/* Counts of resources */ +int cpus = 1; /* number of CPUs in system (lets hope its more than zero!) */ +#if X86 || ARM +int cores = 0; +int siblings = 0; +int processorchips = 0; +int hyperthreads = 0; +char *vendor_ptr = "-"; +char *model_ptr = "-"; +char *mhz_ptr = "-"; +char *bogo_ptr = "-"; +#endif +int old_cpus = 1; /* Number of CPU seen in previuos interval */ +int max_cpus = 1; /* highest number of CPUs in DLPAR */ +int networks = 0; /* number of networks in system */ +int partitions = 0; /* number of partitions in system */ +int partitions_short = 0; /* partitions file data short form (i.e. data missing) */ +int disks = 0; /* number of disks in system */ +int seconds = -1; /* pause interval */ +int maxloops = -1; /* stop after this number of updates */ +char hostname[256]; +char run_name[256]; +int run_name_set = 0; +char fullhostname[256]; +int loop; + +#define DPL 150 /* Disks per line for file output to ensure it + does not overflow the spreadsheet input line max */ + +int disks_per_line = DPL; + +#define NEWDISKGROUP(disk) ( (disk) % disks_per_line == 0) + +/* Mode of output variables */ +int show_aaa = 1; +int show_para = 1; +int show_headings = 1; +int show_res = 0; +int show_smp = 0; +int show_util = 0; +int first_util = 1; +int show_wide = 0; +int show_gpu = 0; +int show_mhz = 0; +int show_longterm = 0; +int show_disk = 0; +#define SHOW_DISK_NONE 0 +#define SHOW_DISK_STATS 1 +#define SHOW_DISK_GRAPH 2 +int show_diskmap = 0; +int show_memory = 0; +int show_large = 0; +int show_kernel = 0; +int show_nfs = 0; +int show_net = 0; +int show_neterror = 0; +int show_help = 0; +int show_top = 0; +int show_topmode = 1; +#define ARGS_NONE 0 +#define ARGS_ONLY 1 +int show_args = 0; +int show_all = 1; /* 1=all procs& disk 0=only if 1% or more busy */ +int show_verbose = 0; +int show_jfs = 0; +int flash_on = 0; +int first_huge = 1; +int first_steal = 1; +long huge_peak = 0; +int welcome = 1; +int dotline = 0; +int show_rrd = 0; +int show_lpar = 0; +int show_vm = 0; +int show_dgroup = 0; /* disk groups */ +int auto_dgroup = 0; /* disk groups defined via -g auto */ +int disk_only_mode = 0; /* disk stats shows disks only if user used -g auto */ +int dgroup_loaded = 0; /* 0 = no, 1=needed, 2=loaded */ + +#define RRD if(show_rrd) + +double ignore_procdisk_threshold = 0.1; +double ignore_io_threshold = 0.1; +/* Curses support */ +#define CURSE if(cursed) /* Only use this for single line curses calls */ +#define COLOUR if(colour) /* Only use this for single line colour curses calls */ +int cursed = 1; /* 1 = using curses and + 0 = loging output for a spreadsheet */ +int colour = 1; /* 1 = using colour curses and + 0 = using black and white curses (see -b flag) */ +#define MVPRINTW(row,col,string) {move((row),(col)); \ + attron(A_STANDOUT); \ + printw(string); \ + attroff(A_STANDOUT); } +FILE *fp; /* filepointer for spreadsheet output */ + + +char *timestamp(int loop, time_t eon) +{ + static char string[64]; + if (show_rrd) + sprintf(string, "%ld", (long) eon); + else + sprintf(string, "T%04d", loop); + return string; +} + +#define LOOP timestamp(loop,timer) + +char *easy[5] = { "not found", 0, 0, 0, 0 }; +char *lsb_release[5] = { "not found", 0, 0, 0, 0 }; + +void find_release() +{ + FILE *pop; + int i; + char tmpstr[71]; + +#ifdef SLES12 + pop = popen("cat /etc/os-release 2>/dev/null", "r"); +#else + pop = popen("cat /etc/*ease 2>/dev/null", "r"); +#endif /* SLES12 */ + if (pop != NULL) { + tmpstr[0] = 0; + for (i = 0; i < 4; i++) { + if (fgets(tmpstr, 70, pop) == NULL) + break; + tmpstr[strlen(tmpstr) - 1] = 0; /* remove newline */ + easy[i] = MALLOC(strlen(tmpstr) + 1); + strcpy(easy[i], tmpstr); + } + pclose(pop); + } + pop = popen("/usr/bin/lsb_release -idrc 2>/dev/null", "r"); + if (pop != NULL) { + tmpstr[0] = 0; + for (i = 0; i < 4; i++) { + if (fgets(tmpstr, 70, pop) == NULL) + break; + tmpstr[strlen(tmpstr) - 1] = 0; /* remove newline */ + lsb_release[i] = MALLOC(strlen(tmpstr) + 1); + strcpy(lsb_release[i], tmpstr); + } + pclose(pop); + } +} + + + +/* Full Args Mode stuff here */ + +#define ARGSMAX 1024*8 +#define CMDLEN 4096 + +struct { + int pid; + char *args; +} arglist[ARGSMAX]; + +void args_output(int pid, int loop, char *progname) +{ + FILE *pop; + int i, j, n; + char tmpstr[CMDLEN]; + static int arg_first_time = 1; + + if (pid == 0) + return; /* ignore init */ + for (i = 0; i < ARGSMAX - 1; i++) { /* clear data out */ + if (arglist[i].pid == pid) { + return; + } + if (arglist[i].pid == 0) /* got to empty slot */ + break; + } + sprintf(tmpstr, "ps -p %d -o args 2>/dev/null", pid); + pop = popen(tmpstr, "r"); + if (pop == NULL) { + return; + } else { + if (fgets(tmpstr, CMDLEN, pop) == NULL) { /* throw away header */ + pclose(pop); + return; + } + tmpstr[0] = 0; + if (fgets(tmpstr, CMDLEN, pop) == NULL) { + pclose(pop); + return; + } + tmpstr[strlen(tmpstr) - 1] = 0; + if (tmpstr[strlen(tmpstr) - 1] == ' ') + tmpstr[strlen(tmpstr) - 1] = 0; + arglist[i].pid = pid; + if (arg_first_time) { + fprintf(fp, "UARG,+Time,PID,ProgName,FullCommand\n"); + arg_first_time = 0; + } + n = strlen(tmpstr); + for (i = 0; i < n; i++) { + /*strip out stuff that confused Excel i.e. starting with maths symbol */ + if (tmpstr[i] == ',' && + ((tmpstr[i + 1] == '-') || tmpstr[i + 1] == '+')) + tmpstr[i + 1] = '_'; + /*strip out double spaces */ + if (tmpstr[i] == ' ' && tmpstr[i + 1] == ' ') { + for (j = 0; j < n - i; j++) + tmpstr[i + j] = tmpstr[i + j + 1]; + i--; /* rescan to remove triple space etc */ + } + } + + fprintf(fp, "UARG,%s,%07d,%s,%s\n", LOOP, pid, progname, tmpstr); + pclose(pop); + return; + } +} + +void args_load() +{ + FILE *pop; + int i; + char tmpstr[CMDLEN]; + + for (i = 0; i < ARGSMAX; i++) { /* clear data out */ + if (arglist[i].pid == -1) + break; + if (arglist[i].pid != 0) { + arglist[i].pid = -1; + free(arglist[i].args); + } + } + pop = popen("ps -eo pid,args 2>/dev/null", "r"); + if (pop == NULL) { + return; + } else { + if (fgets(tmpstr, CMDLEN, pop) == NULL) { /* throw away header */ + pclose(pop); + return; + } + for (i = 0; i < ARGSMAX; i++) { + tmpstr[0] = 0; + if (fgets(tmpstr, CMDLEN, pop) == NULL) { + pclose(pop); + return; + } + tmpstr[strlen(tmpstr) - 1] = 0; + if (tmpstr[strlen(tmpstr) - 1] == ' ') + tmpstr[strlen(tmpstr) - 1] = 0; + arglist[i].pid = atoi(tmpstr); + arglist[i].args = MALLOC(strlen(tmpstr)); + strcpy(arglist[i].args, &tmpstr[6]); + } + pclose(pop); + } +} + +char *args_lookup(int pid, char *progname) +{ + int i; + for (i = 0; i < ARGSMAX; i++) { + if (arglist[i].pid == pid) + return arglist[i].args; + if (arglist[i].pid == -1) + return progname; + } + return progname; +} + +/* end args mode stuff here */ + +void linux_bbbp(char *name, char *cmd, char *err) +{ + int i; + int j; + int len; +#define STRLEN 4096 + char str[STRLEN]; + FILE *pop; + static int lineno = 0; + + pop = popen(cmd, "r"); + if (pop == NULL) { + fprintf(fp, "BBBP,%03d,%s failed to run %s\n", lineno++, cmd, err); + } else { + fprintf(fp, "BBBP,%03d,%s\n", lineno++, name); + for (i = 0; i < 2048 && (fgets(str, STRLEN, pop) != NULL); i++) { /* 2048=sanity check only */ + len = strlen(str); + if (len > STRLEN) + len = STRLEN; + if (str[len - 1] == '\n') /*strip off the newline */ + str[len - 1] = 0; + /* fix text starting characters that confuses spread sheets */ + if (str[0] == '+') + str[0] = 'p'; + if (str[0] == '*') + str[0] = 'm'; + if (str[0] == '-') + str[0] = 'n'; + if (str[0] == '/') + str[0] = 'd'; + if (str[0] == '=') + str[0] = 'e'; + /* remove double quotes as it confuses spread sheets */ + for (j = 0; str[j] != 0; j++) + if (str[j] == '"') + str[j] = 'Q'; + fprintf(fp, "BBBP,%03d,%s,\"%s\"\n", lineno++, name, str); + } + pclose(pop); + } +} + +#define WARNING "needs root permission or file not present" + +/* Global name of programme for printing it */ +char *progname; + +/* Seconds since epoc and the sting version */ +long long boottime = 0; +char boottime_str[64] = "not found"; +/* Main data structure for collected stats. + * Two versions are previous and current data. + * Often its the difference that is printed. + * The pointers are swaped i.e. current becomes the previous + * and the previous over written rather than moving data around. + */ +struct cpu_stat { /* changed the order here to match this years kernel (man 5 /proc/stat) */ + long long user; + long long nice; + long long sys; + long long idle; + long long wait; /* for IO */ + long long irq; + long long softirq; + long long steal; + long long guest; + long long guest_nice; + /* below are non-cpu based numbers in the same file */ + long long intr; + long long ctxt; + long long procs; + long long running; + long long blocked; + float uptime; + float idletime; + float mins1; + float mins5; + float mins15; +}; + +#define ulong unsigned long +struct dsk_stat { + char dk_name[32]; + int dk_major; + int dk_minor; + long dk_noinfo; + ulong dk_reads; + ulong dk_rmerge; + ulong dk_rmsec; + ulong dk_rkb; + ulong dk_writes; + ulong dk_wmerge; + ulong dk_wmsec; + ulong dk_wkb; + ulong dk_xfers; + ulong dk_bsize; + ulong dk_time; + ulong dk_inflight; + ulong dk_backlog; + ulong dk_partition; + ulong dk_blocks; /* in /proc/partitions only */ + ulong dk_use; + ulong dk_aveq; +}; + +struct mem_stat { + long memtotal; + long memfree; + long memshared; + long buffers; + long cached; + long swapcached; + long active; + long inactive; + long hightotal; + long highfree; + long lowtotal; + long lowfree; + long swaptotal; + long swapfree; +#ifdef LARGEMEM + long dirty; + long writeback; + long mapped; + long slab; + long committed_as; + long pagetables; + long hugetotal; + long hugefree; + long hugesize; +#else + long bigfree; +#endif /*LARGEMEM*/ +}; + +struct vm_stat { + long long nr_dirty; + long long nr_writeback; + long long nr_unstable; + long long nr_page_table_pages; + long long nr_mapped; + long long nr_slab; + long long pgpgin; + long long pgpgout; + long long pswpin; + long long pswpout; + long long pgalloc_high; + long long pgalloc_normal; + long long pgalloc_dma; + long long pgfree; + long long pgactivate; + long long pgdeactivate; + long long pgfault; + long long pgmajfault; + long long pgrefill_high; + long long pgrefill_normal; + long long pgrefill_dma; + long long pgsteal_high; + long long pgsteal_normal; + long long pgsteal_dma; + long long pgscan_kswapd_high; + long long pgscan_kswapd_normal; + long long pgscan_kswapd_dma; + long long pgscan_direct_high; + long long pgscan_direct_normal; + long long pgscan_direct_dma; + long long pginodesteal; + long long slabs_scanned; + long long kswapd_steal; + long long kswapd_inodesteal; + long long pageoutrun; + long long allocstall; + long long pgrotated; +}; + + +#define NFS_V2_NAMES_COUNT 18 +char *nfs_v2_names[NFS_V2_NAMES_COUNT] = { + "null", "getattr", "setattr", "root", "lookup", "readlink", + "read", "wrcache", "write", "create", "remove", "rename", + "link", "symlink", "mkdir", "rmdir", "readdir", "fsstat" +}; + +#define NFS_V3_NAMES_COUNT 22 +char *nfs_v3_names[22] = { + "null", "getattr", "setattr", "lookup", "access", "readlink", + "read", "write", "create", "mkdir", "symlink", "mknod", + "remove", "rmdir", "rename", "link", "readdir", "readdirplus", + "fsstat", "fsinfo", "pathconf", "commit" +}; + +#define NFS_V4S_NAMES_COUNT 72 +int nfs_v4s_names_count = NFS_V4S_NAMES_COUNT; +char *nfs_v4s_names[NFS_V4S_NAMES_COUNT] = { /* get these names from nfsstat as they are NOT documented */ + "op0-unused", "op1-unused", "op2-future", "access", "close", "commit", /* 1 - 6 */ + "create", "delegpurge", "delegreturn", "getattr", "getfh", "link", /* 7 - 12 */ + "lock", "lockt", "locku", "lookup", "lookup_root", "nverify", /* 13 - 18 */ + "open", "openattr", "open_conf", "open_dgrd", "putfh", "putpubfh", /* 19 - 24 */ + "putrootfh", "read", "readdir", "readlink", "remove", "rename", /* 25 - 30 */ + "renew", "restorefh", "savefh", "secinfo", "setattr", "setcltid", /* 31 - 36 */ + "setcltidconf", "verify", "write", "rellockowner", "bc_ctl", "blind_conn", /* 37 - 42 */ + "exchange_id", "create_ses", "destroy_ses", "free_statid", "getdirdelag", "getdevinfo", /* 43 - 48 */ + "getdevlist", "layoutcommit", "layoutget", "layoutreturn", "secunfononam", "sequence", /* 49 - 54 */ + "set_ssv", "test_stateid", "want_deleg", "destory_clid", "reclaim_comp", "stat60", /* 55 - 60 */ + "stat61", "stat62", "stat63", "stat64", "stat65", "stat66", /* 61 - 66 */ + "stat67", "stat68", "stat69", "stat70", "stat71", "stat72" /* 67 - 72 */ +}; + +#define NFS_V4C_NAMES_COUNT 60 +int nfs_v4c_names_count = NFS_V4C_NAMES_COUNT; +char *nfs_v4c_names[NFS_V4C_NAMES_COUNT] = { /* get these names from nfsstat as they are NOT documented */ + "null", "read", "write", "commit", "open", "open_conf", /* 1 - 6 */ + "open_noat", "open_dgrd", "close", "setattr", "fsinfo", "renew", /* 7 - 12 */ + "setclntid", "confirm", "lock", "lockt", "locku", "access", /* 13 - 18 */ + "getattr", "lookup", "lookup_root", "remove", "rename", "link", /* 19 - 24 */ + "symlink", "create", "pathconf", "statfs", "readlink", "readdir", /* 25 - 30 */ + "server_caps", "delegreturn", "getacl", "setacl", "fs_locations", "rel_lkowner", /* 31 - 36 */ + "secinfo", "exchange_id", "create_ses", "destroy_ses", "sequence", "get_lease_t", /* 37 - 42 */ + "reclaim_comp", "layoutget", "getdevinfo", "layoutcommit", "layoutreturn", "getdevlist", /* 43 - 48 */ + "stat49", "stat50", "stat51", "stat52", "start53", "stat54", /* 49 - 54 */ + "stat55", "stat56", "stat57", "stat58", "start59", "stat60" /* 55 - 60 */ +}; + + +int nfs_v2c_found = 0; +int nfs_v2s_found = 0; +int nfs_v3c_found = 0; +int nfs_v3s_found = 0; +int nfs_v4c_found = 0; +int nfs_v4s_found = 0; +int nfs_clear = 0; + +struct nfs_stat { + long v2c[NFS_V2_NAMES_COUNT]; /* verison 2 client */ + long v3c[NFS_V3_NAMES_COUNT]; /* verison 3 client */ + long v4c[NFS_V4C_NAMES_COUNT]; /* verison 4 client */ + long v2s[NFS_V2_NAMES_COUNT]; /* verison 2 SERVER */ + long v3s[NFS_V3_NAMES_COUNT]; /* verison 3 SERVER */ + long v4s[NFS_V4S_NAMES_COUNT]; /* verison 4 SERVER */ +}; + +#define NETMAX 32 +struct net_stat { + unsigned long if_name[17]; + unsigned long long if_ibytes; + unsigned long long if_obytes; + unsigned long long if_ipackets; + unsigned long long if_opackets; + unsigned long if_ierrs; + unsigned long if_oerrs; + unsigned long if_idrop; + unsigned long if_ififo; + unsigned long if_iframe; + unsigned long if_odrop; + unsigned long if_ofifo; + unsigned long if_ocarrier; + unsigned long if_ocolls; +}; +#ifdef PARTITIONS +#define PARTMAX 256 +struct part_stat { + int part_major; + int part_minor; + unsigned long part_blocks; + char part_name[16]; + unsigned long part_rio; + unsigned long part_rmerge; + unsigned long part_rsect; + unsigned long part_ruse; + unsigned long part_wio; + unsigned long part_wmerge; + unsigned long part_wsect; + unsigned long part_wuse; + unsigned long part_run; + unsigned long part_use; + unsigned long part_aveq; +}; +#endif /*PARTITIONS*/ +#ifdef POWER +#define VM_UNKNOWN 0 +#define VM_POWERVM 1 +#define VM_POWERKVM_GUEST 2 +#define VM_POWERKVM_HOST 3 +#define VM_NATIVE 4 +int power_vm_type = VM_UNKNOWN; + +/* XXXXXXX need to test if rewind() worked or not for lparcfg */ +int lparcfg_reread = 1; +/* Reset at end of each interval so LPAR cfg is only read once each interval + * even if proc_lparcfg() is called multiple times + * Note: lparcfg is not read via proc_read() ! + */ +int lparcfg_processed = 0; + +struct { + char version_string[16]; /*lparcfg 1.3 */ + int version; + char serial_number[16]; /*HAL,0210033EA */ + char system_type[64]; /*HAL,9124-720 */ + /* new record is "IBM pSeries (emulated by qemu)" instead of "IBM 9119-MME" */ + int partition_id; /*11 */ +/* +R4=0x14 +R5=0x0 +R6=0x800b0000 +R7=0x1000000040004 +*/ + int BoundThrds; /*=1*/ + int CapInc; /*=1*/ + long long DisWheRotPer; /*=2070000*/ + int MinEntCap; /*=10*/ + int MinEntCapPerVP; /*=10*/ + int MinMem; /*=2048*/ + int DesMem; /*=4096*/ + int MinProcs; /*=1*/ + int partition_max_entitled_capacity;/*=400*/ + int system_potential_processors; /*=4*/ + /**/ int partition_entitled_capacity; + /*=20*/ + int system_active_processors; /*=4*/ + int pool_capacity; /*=4*/ + int unallocated_capacity_weight; /*=0*/ + int capacity_weight; /*=0*/ + int capped; /*=1*/ + int unallocated_capacity; /*=0*/ + long long pool_idle_time; /*=0*/ + long long pool_idle_saved; + long long pool_idle_diff; + int pool_num_procs; /*=0*/ + long long purr; /*=0*/ + long long purr_saved; + long long purr_diff; + long long timebase; + int partition_active_processors; /*=1*/ + int partition_potential_processors; /*=40*/ + int shared_processor_mode; /*=1*/ + int smt_mode; /* 1: off, 2: SMT-2, 4: SMT-4 */ + int cmo_enabled; /* 1 means AMS is Active */ + int entitled_memory_pool_number; /* pool number = 0 */ + int entitled_memory_weight; /* 0 to 255 */ + long cmo_faults; /* Hypervisor Page-in faults = big number */ + long cmo_faults_save; /* above saved */ + long cmo_faults_diff; /* delta */ + long cmo_fault_time_usec; /* Hypervisor time in micro seconds = big */ + long cmo_fault_time_usec_save; /* above saved */ + long cmo_fault_time_usec_diff; /* delta */ + long backing_memory; /* AIX pmem in bytes */ + long cmo_page_size; /* AMS page size in bytes */ + long entitled_memory_pool_size; /* AMS whole pool size in bytes */ + long entitled_memory_loan_request; /* AMS requesting more memory loaning */ + +#ifdef EXPERIMENTAL +/* new data in SLES11 for POWER 2.6.27 (may be a little earlier too) */ + long DesEntCap; + long DesProcs; + long DesVarCapWt; + long DedDonMode; + long group; + long pool; + long entitled_memory; + long entitled_memory_group_number; + long unallocated_entitled_memory_weight; + long unallocated_io_mapping_entitlement; +/* new data in SLES11 for POWER 2.6.27 */ +#endif /* EXPERIMENTAL */ + +} lparcfg; + +int lpar_count = 0; + +#define LPAR_LINE_MAX 100 /* MAGIC COOKIE WARNING */ +#define LPAR_LINE_WIDTH 80 +char lpar_buffer[LPAR_LINE_MAX][LPAR_LINE_WIDTH]; + +int lpar_sanity = 55; + +char *locate(char *s) +{ + int i; + int len; + len = strlen(s); + for (i = 0; i < lpar_count; i++) + if (!strncmp(s, lpar_buffer[i], len)) + return lpar_buffer[i]; + return ""; +} + +#define NUMBER_NOT_VALID -999 + +long long read_longlong(char *s) +{ + long long x; + int ret; + int len; + int i; + char *str; + str = locate(s); + len = strlen(str); + if (len == 0) { + return NUMBER_NOT_VALID; + } + for (i = 0; i < len; i++) { + if (str[i] == '=') { + ret = sscanf(&str[i + 1], "%lld", &x); + if (ret != 1) { + fprintf(stderr, + "sscanf for %s failed returned = %d line=%s\n", s, + ret, str); + return -1; + } +/* fprintf(fp,"DEBUG read %s value %lld\n",s,x);*/ + return x; + } + } + fprintf(stderr, "read_long_long failed returned line=%s\n", str); + return -2; +} + + +/* Return of 0 means data not available */ +int proc_lparcfg() +{ + static FILE *fp = (FILE *) - 1; +/* Only try to read /proc/ppc64/lparcfg once - remember if it's readable */ + static int lparinfo_not_available = 0; + int i; + char *str; + /* If we already read and processed /proc/lparcfg in this interval - just return */ + if (lparcfg_processed == 1) + return 1; + + if (lparinfo_not_available == 1) + return 0; + + if (fp == (FILE *) - 1) { + if ((fp = fopen("/proc/ppc64/lparcfg", "r")) == NULL) { + error("failed to open - /proc/ppc64/lparcfg"); + fp = (FILE *) - 1; + lparinfo_not_available = 1; + if (power_vm_type == VM_UNKNOWN) { + /* Heuristics for spotting PowerKVM Host + a) inside ifdef POWER so can't be x86 + b) /proc/ppc64/lparcfg is missing + c) /etc/ *ease files have hints + Confirmed true for IBM_POWERKVM 2.1 + */ + if (strncmp("IBM_PowerKVM", easy[1], 12) == 0) + power_vm_type = VM_POWERKVM_HOST; + else + power_vm_type = VM_NATIVE; + } + return 0; + } + } + + for (lpar_count = 0; lpar_count < LPAR_LINE_MAX - 1; lpar_count++) { + if (fgets(lpar_buffer[lpar_count], LPAR_LINE_WIDTH - 1, fp) == + NULL) + break; + } + if (lparcfg_reread) { /* XXXX unclear if close+open is necessary - unfortunately this requires version many of Linux on POWER install to test early releases */ + fclose(fp); + fp = (FILE *) - 1; + } else + rewind(fp); + + str = locate("lparcfg"); + sscanf(str, "lparcfg %s", lparcfg.version_string); + str = locate("serial_number"); + sscanf(str, "serial_number=%s", lparcfg.serial_number); + str = locate("system_type"); + for (i = 0; i < strlen(str); i++) /* Remove new spaces in massive string meaning PowerKVM Guest !! */ + if (str[i] == ' ') + str[i] = '-'; + sscanf(str, "system_type=%s", lparcfg.system_type); + if (power_vm_type == VM_UNKNOWN) { + /* Heuristics for spotting PowerKVM Guest + a) inside ifdef POWER so can't be x86 + b) we have a /proc/ppc64/lparcfg - probably mostly missing (1.9) + c) system type string includes "qemu" + Confirmed true for SLES11.3 RHEL6.5 and Ubuntu 14.4.1 + */ + if (strstr(lparcfg.system_type, "(emulated-by-qemu)") == 0) + power_vm_type = VM_POWERVM; /* not found */ + else + power_vm_type = VM_POWERKVM_GUEST; + } +#define GETDATA(variable) lparcfg.variable = read_longlong( __STRING(variable) ); + + GETDATA(partition_id); + GETDATA(BoundThrds); + GETDATA(CapInc); + GETDATA(DisWheRotPer); + GETDATA(MinEntCap); + GETDATA(MinEntCapPerVP); + GETDATA(MinMem); + GETDATA(DesMem); + GETDATA(MinProcs); + GETDATA(partition_max_entitled_capacity); + GETDATA(system_potential_processors); + GETDATA(partition_entitled_capacity); + GETDATA(system_active_processors); + GETDATA(pool_capacity); + GETDATA(unallocated_capacity_weight); + GETDATA(capacity_weight); + GETDATA(capped); + GETDATA(unallocated_capacity); + lparcfg.pool_idle_saved = lparcfg.pool_idle_time; + GETDATA(pool_idle_time); + lparcfg.pool_idle_diff = + lparcfg.pool_idle_time - lparcfg.pool_idle_saved; + GETDATA(pool_num_procs); + lparcfg.purr_saved = lparcfg.purr; + GETDATA(purr); + lparcfg.purr_diff = lparcfg.purr - lparcfg.purr_saved; + GETDATA(partition_active_processors); + GETDATA(partition_potential_processors); + GETDATA(shared_processor_mode); + /* Brute force, may provide temporary incorrect data during + * dynamic reconfiguraiton envents + */ + lparcfg.smt_mode = cpus / lparcfg.partition_active_processors; + + /* AMS additions */ + GETDATA(cmo_enabled); + if (lparcfg.cmo_enabled == NUMBER_NOT_VALID) { + lparcfg.cmo_enabled = 0; + } + if (lparcfg.cmo_enabled) { + GETDATA(entitled_memory_pool_number); /* pool number = 0 */ + GETDATA(entitled_memory_weight); /* 0 to 255 */ + + lparcfg.cmo_faults_save = lparcfg.cmo_faults; + GETDATA(cmo_faults); /* Hypervisor Page-in faults = big number */ + lparcfg.cmo_faults_diff = + lparcfg.cmo_faults - lparcfg.cmo_faults_save; + + lparcfg.cmo_fault_time_usec_save = lparcfg.cmo_fault_time_usec; + GETDATA(cmo_fault_time_usec); /* Hypervisor time in micro seconds = big number */ + lparcfg.cmo_fault_time_usec_diff = + lparcfg.cmo_fault_time_usec - lparcfg.cmo_fault_time_usec_save; + + GETDATA(backing_memory); /* AIX pmem in bytes */ + GETDATA(cmo_page_size); /* AMS page size in bytes */ + GETDATA(entitled_memory_pool_size); /* AMS whole pool size in bytes */ + GETDATA(entitled_memory_loan_request); /* AMS requesting more memory loaning */ + + } +#ifdef EXPERIMENTAL + GETDATA(DesEntCap); + GETDATA(DesProcs); + GETDATA(DesVarCapWt); + GETDATA(DedDonMode); + GETDATA(group); + GETDATA(pool); + GETDATA(entitled_memory); + GETDATA(entitled_memory_group_number); + GETDATA(unallocated_entitled_memory_weight); + GETDATA(unallocated_io_mapping_entitlement); +#endif /* EXPERIMENTAL */ + + lparcfg_processed = 1; + return 1; +} +#endif /*POWER*/ +#define DISKMIN 256 +#define DISKMAX diskmax +int diskmax = DISKMIN; + +/* Supports up to 780, but not POWER6 595 follow-up with POWER7 */ +/* XXXX needs rework to cope to with fairly rare but interesting higher numbers of CPU machines */ +#define CPUMAX (192 * 8) /* MAGIC COOKIE WARNING */ + +struct data { + struct dsk_stat *dk; + struct cpu_stat cpu_total; + struct cpu_stat cpuN[CPUMAX]; + struct mem_stat mem; + struct vm_stat vm; + struct nfs_stat nfs; + struct net_stat ifnets[NETMAX]; +#ifdef PARTITIONS + struct part_stat parts[PARTMAX]; +#endif /*PARTITIONS*/ + struct timeval tv; + double time; + struct procsinfo *procs; + + int proc_records; + int processes; +} database[2], *p, *q; + + +long long get_vm_value(char *s) +{ + int currline; + int currchar; + long long result = -1; + char *check; + int len; + int found; + + for (currline = 0; currline < proc[P_VMSTAT].lines; currline++) { + len = strlen(s); + for (currchar = 0, found = 1; currchar < len; currchar++) { + if (proc[P_VMSTAT].line[currline][currchar] == 0 || + s[currchar] != proc[P_VMSTAT].line[currline][currchar]) { + found = 0; + break; + } + } + if (found && proc[P_VMSTAT].line[currline][currchar] == ' ') { + result = + strtoll(&proc[P_VMSTAT].line[currline][currchar + 1], + &check, 10); + if (*check == proc[P_VMSTAT].line[currline][currchar + 1]) { + fprintf(stderr, "%s has an unexpected format: >%s<\n", + proc[P_VMSTAT].filename, + proc[P_VMSTAT].line[currline]); + return -1; + } + return result; + } + } + return -1; +} + +#define GETVM(variable) p->vm.variable = get_vm_value(__STRING(variable) ); + +int read_vmstat() +{ + proc_read(P_VMSTAT); + if (proc[P_VMSTAT].read_this_interval == 0 + || proc[P_VMSTAT].lines == 0) + return (-1); + + /* Note: if the variable requested is not found in /proc/vmstat then it is set to -1 */ + GETVM(nr_dirty); + GETVM(nr_writeback); + GETVM(nr_unstable); + GETVM(nr_page_table_pages); + GETVM(nr_mapped); + GETVM(nr_slab); + GETVM(pgpgin); + GETVM(pgpgout); + GETVM(pswpin); + GETVM(pswpout); + GETVM(pgalloc_high); + GETVM(pgalloc_normal); + GETVM(pgalloc_dma); + GETVM(pgfree); + GETVM(pgactivate); + GETVM(pgdeactivate); + GETVM(pgfault); + GETVM(pgmajfault); + GETVM(pgrefill_high); + GETVM(pgrefill_normal); + GETVM(pgrefill_dma); + GETVM(pgsteal_high); + GETVM(pgsteal_normal); + GETVM(pgsteal_dma); + GETVM(pgscan_kswapd_high); + GETVM(pgscan_kswapd_normal); + GETVM(pgscan_kswapd_dma); + GETVM(pgscan_direct_high); + GETVM(pgscan_direct_normal); + GETVM(pgscan_direct_dma); + GETVM(pginodesteal); + GETVM(slabs_scanned); + GETVM(kswapd_steal); + GETVM(kswapd_inodesteal); + GETVM(pageoutrun); + GETVM(allocstall); + GETVM(pgrotated); + return 1; +} + + +/* These macro simplify the access to the Main data structure */ +#define DKDELTA(member) ( (q->dk[i].member > p->dk[i].member) ? 0 : (p->dk[i].member - q->dk[i].member)) +#define SIDELTA(member) ( (q->si.member > p->si.member) ? 0 : (p->si.member - q->si.member)) + +#define IFNAME 64 + +#define TIMEDELTA(member,index1,index2) ((p->procs[index1].member) - (q->procs[index2].member)) +#define IODELTA(member,index1,index2) ( (q->procs[index2].member > p->procs[index1].member) ? 0 : (p->procs[index1].member - q->procs[index2].member) ) +#define COUNTDELTA(member) ( (q->procs[topper[j].other].member > p->procs[i].member) ? 0 : (p->procs[i].member - q->procs[topper[j].other].member) ) + +#define TIMED(member) ((double)(p->procs[i].member.tv_sec)) + +double *cpu_peak; /* ptr to array - 1 for each cpu - 0 = average for machine */ +double *disk_busy_peak; +double *disk_rate_peak; +double net_read_peak[NETMAX]; +double net_write_peak[NETMAX]; +int aiorunning; +int aiorunning_max = 0; +int aiocount; +int aiocount_max = 0; +float aiotime; +float aiotime_max = 0.0; + +char *dskgrp(int i) +{ + static char error_string[] = { "Too-Many-Disks" }; + static char *string[16] = { "", "1", "2", "3", + "4", "5", "6", "7", + "8", "9", "10", "11", + "12", "13", "14", "15" + }; + + i = (int) ((float) i / (float) disks_per_line); + if (0 <= i && i <= 15) + return string[i]; + return error_string; +} + +/* command checking against a list */ + +#define CMDMAX 64 + +char *cmdlist[CMDMAX]; +int cmdfound = 0; + +int cmdcheck(char *cmd) +{ + int i; +#ifdef CMDDEBUG + fprintf(stderr, "cmdfound=%d\n", cmdfound); + for (i = 0; i < cmdfound; i++) + fprintf(stderr, "cmdlist[%d]=\"%s\"\n", i, cmdlist[i]); +#endif /* CMDDEBUG */ + for (i = 0; i < cmdfound; i++) { + if (strlen(cmdlist[i]) == 0) + continue; + if (!strncmp(cmdlist[i], cmd, strlen(cmdlist[i]))) + return 1; + } + return 0; +} + +/* Convert secs + micro secs to a double */ +double doubletime(void) +{ + + gettimeofday(&p->tv, 0); + return ((double) p->tv.tv_sec + p->tv.tv_usec * 1.0e-6); +} + +void get_cpu_cnt() +{ + int i; + + /* Get CPU info from /proc/stat and populate proc[P_STAT] */ + proc_read(P_STAT); + + /* Start with index [1] as [0] contains overall CPU statistics */ + for (i = 1; i < proc[P_STAT].lines; i++) { + if (strncmp("cpu", proc[P_STAT].line[i], 3) == 0) + cpus = i; + else + break; + } + if (cpus >= CPUMAX) { + printf + ("This nmon supports only %d CPU threads (Logical CPUs) and the machine appears to have %d.\nnmon stopping as its unsafe to continue.\n", + CPUMAX, cpus); + exit(44); + } +} + +#if X86 || ARM +void get_intel_spec() +{ + int i; + int physicalcpu[256]; + int id; + + /* Get CPU info from /proc/stat and populate proc[P_STAT] */ + proc_read(P_CPUINFO); + + for (i = 0; i < 256; i++) + physicalcpu[i] = 0; + + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("vendor_id", proc[P_CPUINFO].line[i], 9) == 0) { + vendor_ptr = &proc[P_CPUINFO].line[i][12]; + } + } + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("model name", proc[P_CPUINFO].line[i], 10) == 0) { + model_ptr = &proc[P_CPUINFO].line[i][13]; + } + } + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("cpu MHz", proc[P_CPUINFO].line[i], 7) == 0) { + mhz_ptr = &proc[P_CPUINFO].line[i][11]; + } + } + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("bogomips", proc[P_CPUINFO].line[i], 8) == 0) { + bogo_ptr = &proc[P_CPUINFO].line[i][11]; + } + } + + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("physical id", proc[P_CPUINFO].line[i], 11) == 0) { + id = atoi(&proc[P_CPUINFO].line[i][15]); + if (id < 256) + physicalcpu[id] = 1; + } + } + for (i = 0; i < 256; i++) + if (physicalcpu[i] == 1) + processorchips++; + + /* Start with index [1] as [0] contains overall CPU statistics */ + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("siblings", proc[P_CPUINFO].line[i], 8) == 0) { + siblings = atoi(&proc[P_CPUINFO].line[i][11]); + break; + } + } + for (i = 0; i < proc[P_CPUINFO].lines; i++) { + if (strncmp("cpu cores", proc[P_CPUINFO].line[i], 9) == 0) { + cores = atoi(&proc[P_CPUINFO].line[i][12]); + break; + } + } + if (siblings > cores) + hyperthreads = siblings / cores; + else + hyperthreads = 0; +} +#endif + +int stat8 = 0; /* used to determine the number of variables on a cpu line in /proc/stat */ +int stat10 = 0; /* used to determine the number of variables on a cpu line in /proc/stat */ + + +void proc_cpu() +{ + int i; + int row; + static int intr_line = 0; + static int ctxt_line = 0; + static int btime_line = 0; + static int proc_line = 0; + static int run_line = 0; + static int block_line = 0; + static int proc_cpu_first_time = 1; + long long user; + long long nice; + long long sys; + long long idle; + long long iowait; + long long hardirq; + long long softirq; + long long steal; + long long guest; + long long guest_nice; + + /* Only read data once per interval */ + if (proc_cpu_done == 1) + return; + + /* If number of CPUs changed, then we need to find the index of intr_line, ... again */ + if (old_cpus != cpus) + intr_line = 0; + + if (proc_cpu_first_time) { + stat8 = + sscanf(&proc[P_STAT].line[0][5], + "%lld %lld %lld %lld %lld %lld %lld %lld", &user, &nice, + &sys, &idle, &iowait, &hardirq, &softirq, &steal); + stat10 = + sscanf(&proc[P_STAT].line[0][5], + "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", + &user, &nice, &sys, &idle, &iowait, &hardirq, &softirq, + &steal, &guest, &guest_nice); + proc_cpu_first_time = 0; + } + user = nice = sys = idle = iowait = hardirq = softirq = steal = guest = + guest_nice = 0; + if (stat10 == 10) { + sscanf(&proc[P_STAT].line[0][5], + "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", &user, + &nice, &sys, &idle, &iowait, &hardirq, &softirq, &steal, + &guest, &guest_nice); + } else { + if (stat8 == 8) { + sscanf(&proc[P_STAT].line[0][5], + "%lld %lld %lld %lld %lld %lld %lld %lld", &user, &nice, + &sys, &idle, &iowait, &hardirq, &softirq, &steal); + } else { /* stat 4 variables here as older Linux proc */ + sscanf(&proc[P_STAT].line[0][5], "%lld %lld %lld %lld", + &user, &nice, &sys, &idle); + } + } + p->cpu_total.user = user; + p->cpu_total.nice = nice; + p->cpu_total.idle = idle; + p->cpu_total.sys = sys; + p->cpu_total.wait = iowait; /* in the case of 4 variables = 0 */ + /* p->cpu_total.sys = sys + hardirq + softirq + steal; */ + + p->cpu_total.irq = hardirq; + p->cpu_total.softirq = softirq; + p->cpu_total.steal = steal; + p->cpu_total.guest = guest; + p->cpu_total.guest_nice = guest_nice; + +#ifdef DEBUG + if (debug) + fprintf(stderr, "XX user=%lld wait=%lld sys=%lld idle=%lld\n", + p->cpu_total.user, + p->cpu_total.wait, p->cpu_total.sys, p->cpu_total.idle); +#endif /*DEBUG*/ + for (i = 0; i < cpus; i++) { + user = nice = sys = idle = iowait = hardirq = softirq = steal = 0; + + /* allow for large CPU numbers */ + if (i + 1 > 1000) + row = 8; + else if (i + 1 > 100) + row = 7; + else if (i + 1 > 10) + row = 6; + else + row = 5; + + if (stat10 == 10) { + sscanf(&proc[P_STAT].line[i + 1][row], + "%lld %lld %lld %lld %lld %lld %lld %lld %lld %lld", + &user, + &nice, + &sys, + &idle, + &iowait, + &hardirq, &softirq, &steal, &guest, &guest_nice); + + } else if (stat8 == 8) { + sscanf(&proc[P_STAT].line[i + 1][row], + "%lld %lld %lld %lld %lld %lld %lld %lld", + &user, + &nice, + &sys, &idle, &iowait, &hardirq, &softirq, &steal); + } else { + sscanf(&proc[P_STAT].line[i + 1][row], "%lld %lld %lld %lld", + &user, &nice, &sys, &idle); + } + p->cpuN[i].user = user; + p->cpuN[i].nice = nice; + p->cpuN[i].sys = sys; + p->cpuN[i].idle = idle; + p->cpuN[i].wait = iowait; + p->cpuN[i].irq = hardirq; + p->cpuN[i].softirq = softirq; + p->cpuN[i].steal = steal; + p->cpuN[i].guest = guest; + p->cpuN[i].guest_nice = guest_nice; + } + + if (intr_line == 0) { + if (proc[P_STAT].line[i + 1][0] == 'p' && + proc[P_STAT].line[i + 1][1] == 'a' && + proc[P_STAT].line[i + 1][2] == 'g' && + proc[P_STAT].line[i + 1][3] == 'e') { + /* 2.4 kernel */ + intr_line = i + 3; + ctxt_line = i + 5; + btime_line = i + 6; + proc_line = i + 7; + run_line = i + 8; + block_line = i + 9; + } else { + /* 2.6 kernel */ + intr_line = i + 1; + ctxt_line = i + 2; + btime_line = i + 3; + proc_line = i + 4; + run_line = i + 5; + block_line = i + 6; + } + } + p->cpu_total.intr = -1; + p->cpu_total.ctxt = -1; + p->cpu_total.procs = -1; + p->cpu_total.running = -1; + p->cpu_total.blocked = -1; + if (proc[P_STAT].lines >= intr_line) + sscanf(&proc[P_STAT].line[intr_line][0], "intr %lld", + &p->cpu_total.intr); + if (proc[P_STAT].lines >= ctxt_line) + sscanf(&proc[P_STAT].line[ctxt_line][0], "ctxt %lld", + &p->cpu_total.ctxt); + if(boottime == 0) { + struct tm ts; + if (proc[P_STAT].lines >= btime_line) + sscanf(&proc[P_STAT].line[btime_line][0], "btime %lld", &boottime); + ts = *localtime((time_t *)&boottime); + strftime (boottime_str, 64, "%I:%M %p %d-%b-%Y", &ts); + } + if (proc[P_STAT].lines >= proc_line) + sscanf(&proc[P_STAT].line[proc_line][0], "processes %lld", + &p->cpu_total.procs); + if (proc[P_STAT].lines >= run_line) + sscanf(&proc[P_STAT].line[run_line][0], "procs_running %lld", + &p->cpu_total.running); + if (proc[P_STAT].lines >= block_line) + sscanf(&proc[P_STAT].line[block_line][0], "procs_blocked %lld", + &p->cpu_total.blocked); + + /* If we had a change in the number of CPUs, copy current interval data to the previous, so we + * get a "0" utilization interval, but better than negative or 100%. + * Heads-up - This effects POWER SMT changes too. + */ + if (old_cpus != cpus) { + memcpy((void *) &(q->cpu_total), (void *) &(p->cpu_total), + sizeof(struct cpu_stat)); + memcpy((void *) q->cpuN, (void *) p->cpuN, + sizeof(struct cpu_stat) * cpus); + } + + /* Flag that we processed /proc/stat data; re-set in proc_read() when we re-read /proc/stat */ + proc_cpu_done = 1; +} + +void proc_nfs() +{ + int i; + int j; + int len; + int lineno; + +/* sample /proc/net/rpc/nfs +net 0 0 0 0 +rpc 70137 0 0 +proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +proc3 22 0 27364 0 32 828 22 40668 0 1 0 0 0 0 0 0 0 0 1212 6 2 1 0 +proc4 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +*/ + if (proc[P_NFS].fp != 0) { + for (lineno = 0; lineno < proc[P_NFS].lines; lineno++) { + if (!strncmp("proc2 ", proc[P_NFS].line[lineno], 6)) { + /* client version 2 line readers "proc2 18 num num etc" */ + len = strlen(proc[P_NFS].line[lineno]); + for (j = 0, i = 8; i < len && j < NFS_V2_NAMES_COUNT; i++) { + if (proc[P_NFS].line[lineno][i] == ' ') { + p->nfs.v2c[j] = + atol(&proc[P_NFS].line[lineno][i + 1]); + nfs_v2c_found = 1; + j++; + } + } + } + if (!strncmp("proc3 ", proc[P_NFS].line[lineno], 6)) { + /* client version 3 line readers "proc3 22 num num etc" */ + len = strlen(proc[P_NFS].line[lineno]); + for (j = 0, i = 8; i < len && j < NFS_V3_NAMES_COUNT; i++) { + if (proc[P_NFS].line[lineno][i] == ' ') { + p->nfs.v3c[j] = + atol(&proc[P_NFS].line[lineno][i + 1]); + nfs_v3c_found = 1; + j++; + } + } + } + if (!strncmp("proc4 ", proc[P_NFS].line[lineno], 6)) { + /* client version 4 line readers "proc4 35 num num etc" */ + nfs_v4c_names_count = atoi(&proc[P_NFS].line[lineno][6]); + len = strlen(proc[P_NFS].line[lineno]); + for (j = 0, i = 8; i < len && j < nfs_v4c_names_count; i++) { + if (proc[P_NFS].line[lineno][i] == ' ') { + p->nfs.v4c[j] = + atol(&proc[P_NFS].line[lineno][i + 1]); + nfs_v4c_found = 1; + j++; + } + } + } + } + } +/* sample /proc/net/rpc/nfsd +rc 0 0 0 +fh 0 0 0 0 0 +io 0 0 +th 4 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 +ra 32 0 0 0 0 0 0 0 0 0 0 0 +net 0 0 0 0 +rpc 0 0 0 0 0 +proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +proc3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +proc4 2 0 0 +proc4ops 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +*/ + if (proc[P_NFSD].fp != 0) { + for (lineno = 0; lineno < proc[P_NFSD].lines; lineno++) { + if (!strncmp("proc2 ", proc[P_NFSD].line[lineno], 6)) { + /* server version 2 line readers "proc2 18 num num etc" */ + len = strlen(proc[P_NFSD].line[lineno]); + for (j = 0, i = 8; i < len && j < NFS_V2_NAMES_COUNT; i++) { + if (proc[P_NFSD].line[lineno][i] == ' ') { + p->nfs.v2s[j] = + atol(&proc[P_NFSD].line[lineno][i + 1]); + nfs_v2s_found = 1; + j++; + } + } + } + if (!strncmp("proc3 ", proc[P_NFSD].line[lineno], 6)) { + /* server version 3 line readers "proc3 22 num num etc" */ + len = strlen(proc[P_NFSD].line[lineno]); + for (j = 0, i = 8; i < len && j < NFS_V2_NAMES_COUNT; i++) { + if (proc[P_NFSD].line[lineno][i] == ' ') { + p->nfs.v3s[j] = + atol(&proc[P_NFSD].line[lineno][i + 1]); + nfs_v3s_found = 1; + j++; + } + } + } + if (!strncmp("proc4ops ", proc[P_NFSD].line[lineno], 9)) { + /* server version 4 line readers "proc4ops 40 num num etc" + NOTE: the "ops" hence starting in column 9 */ + nfs_v4s_names_count = atol(&proc[P_NFSD].line[lineno][9]); + len = strlen(proc[P_NFSD].line[lineno]); + for (j = 0, i = 11; i < len && j < nfs_v4s_names_count; + i++) { + if (proc[P_NFSD].line[lineno][i] == ' ') { + p->nfs.v4s[j] = + atol(&proc[P_NFSD].line[lineno][i + 1]); + nfs_v4s_found = 1; + j++; + } + } + } + } + } +} + +void proc_kernel() +{ + int i; + p->cpu_total.uptime = 0.0; + p->cpu_total.idletime = 0.0; + p->cpu_total.uptime = atof(proc[P_UPTIME].line[0]); + for (i = 0; i < strlen(proc[P_UPTIME].line[0]); i++) { + if (proc[P_UPTIME].line[0][i] == ' ') { + p->cpu_total.idletime = atof(&proc[P_UPTIME].line[0][i + 1]); + break; + } + } + + sscanf(&proc[P_LOADAVG].line[0][0], "%f %f %f", + &p->cpu_total.mins1, &p->cpu_total.mins5, &p->cpu_total.mins15); + +} + +char *proc_find_sb(char *p) +{ + for (; *p != 0; p++) + if (*p == ' ' && *(p + 1) == '(') + return p; + return 0; +} + +#define DISK_MODE_IO 1 +#define DISK_MODE_DISKSTATS 2 +#define DISK_MODE_PARTITIONS 3 + +int disk_mode = 0; + +void proc_disk_io(double elapsed) +{ + int diskline; + int i; + int ret; + char *str; + int fudged_busy; + + disks = 0; + for (diskline = 0; diskline < proc[P_STAT].lines; diskline++) { + if (strncmp("disk_io", proc[P_STAT].line[diskline], 7) == 0) + break; + } + for (i = 8; i < strlen(proc[P_STAT].line[diskline]); i++) { + if (proc[P_STAT].line[diskline][i] == ':') + disks++; + } + + str = &proc[P_STAT].line[diskline][0]; + for (i = 0; i < disks; i++) { + str = proc_find_sb(str); + if (str == 0) + break; + ret = sscanf(str, " (%d,%d):(%ld,%ld,%ld,%ld,%ld", + &p->dk[i].dk_major, + &p->dk[i].dk_minor, + &p->dk[i].dk_noinfo, + &p->dk[i].dk_reads, + &p->dk[i].dk_rkb, + &p->dk[i].dk_writes, &p->dk[i].dk_wkb); + if (ret != 7) + exit(7); + p->dk[i].dk_xfers = p->dk[i].dk_noinfo; + /* blocks are 512 bytes */ + p->dk[i].dk_rkb = p->dk[i].dk_rkb / 2; + p->dk[i].dk_wkb = p->dk[i].dk_wkb / 2; + + p->dk[i].dk_bsize = + (p->dk[i].dk_rkb + p->dk[i].dk_wkb) / p->dk[i].dk_xfers * 1024; + + /* assume a disk does 200 op per second */ + fudged_busy = (p->dk[i].dk_reads + p->dk[i].dk_writes) / 2; + if (fudged_busy > 100 * elapsed) + p->dk[i].dk_time += 100 * elapsed; + p->dk[i].dk_time = fudged_busy; + + sprintf(p->dk[i].dk_name, "dev-%d-%d", p->dk[i].dk_major, + p->dk[i].dk_minor); +/* fprintf(stderr,"disk=%d name=\"%s\" major=%d minor=%d\n", i,p->dk[i].dk_name, p->dk[i].dk_major,p->dk[i].dk_minor); */ + str++; + } +} + +void proc_diskstats(double elapsed) +{ + static FILE *fp = (FILE *) - 1; + char buf[1024]; + int i; + int ret; + + if (fp == (FILE *) - 1) { + if ((fp = fopen("/proc/diskstats", "r")) == NULL) { + /* DEBUG if( (fp = fopen("diskstats","r")) == NULL) { */ + error("failed to open - /proc/diskstats"); + disks = 0; + return; + } + } +/* + 2 0 fd0 1 0 2 13491 0 0 0 0 0 13491 13491 + 3 0 hda 41159 53633 1102978 620181 39342 67538 857108 4042631 0 289150 4668250 + 3 1 hda1 58209 58218 0 0 + 3 2 hda2 148 4794 10 20 + 3 3 hda3 65 520 0 0 + 3 4 hda4 35943 1036092 107136 857088 + 22 0 hdc 167 5394 22308 32250 0 0 0 0 0 22671 32250 <-- USB !! + 8 0 sda 990 2325 4764 6860 9 3 12 417 0 6003 7277 + 8 1 sda1 3264 4356 12 12 +*/ + for (i = 0; i < DISKMAX;) { + if (fgets(buf, 1024, fp) == NULL) + break; + /* zero the data ready for reading */ + p->dk[i].dk_major = + p->dk[i].dk_minor = + p->dk[i].dk_name[0] = + p->dk[i].dk_reads = + p->dk[i].dk_rmerge = + p->dk[i].dk_rkb = + p->dk[i].dk_rmsec = + p->dk[i].dk_writes = + p->dk[i].dk_wmerge = + p->dk[i].dk_wkb = + p->dk[i].dk_wmsec = + p->dk[i].dk_inflight = + p->dk[i].dk_time = p->dk[i].dk_backlog = 0; + + ret = + sscanf(&buf[0], + "%d %d %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + &p->dk[i].dk_major, &p->dk[i].dk_minor, + &p->dk[i].dk_name[0], &p->dk[i].dk_reads, + &p->dk[i].dk_rmerge, &p->dk[i].dk_rkb, + &p->dk[i].dk_rmsec, &p->dk[i].dk_writes, + &p->dk[i].dk_wmerge, &p->dk[i].dk_wkb, + &p->dk[i].dk_wmsec, &p->dk[i].dk_inflight, + &p->dk[i].dk_time, &p->dk[i].dk_backlog); + if (ret == 7) { /* shuffle the data around due to missing columns for partitions */ + p->dk[i].dk_partition = 1; + p->dk[i].dk_wkb = p->dk[i].dk_rmsec; + p->dk[i].dk_writes = p->dk[i].dk_rkb; + p->dk[i].dk_rkb = p->dk[i].dk_rmerge; + p->dk[i].dk_rmsec = 0; + p->dk[i].dk_rmerge = 0; + + } else if (ret == 14) + p->dk[i].dk_partition = 0; + else + fprintf(stderr, + "disk sscanf wanted 14 but returned=%d line=%s\n", ret, + buf); + + p->dk[i].dk_rkb /= 2; /* sectors = 512 bytes */ + p->dk[i].dk_wkb /= 2; + p->dk[i].dk_xfers = p->dk[i].dk_reads + p->dk[i].dk_writes; + if (p->dk[i].dk_xfers == 0) + p->dk[i].dk_bsize = 0; + else + p->dk[i].dk_bsize = + ((p->dk[i].dk_rkb + + p->dk[i].dk_wkb) / p->dk[i].dk_xfers) * 1024; + + p->dk[i].dk_time /= 10.0; /* in milli-seconds to make it upto 100%, 1000/100 = 10 */ + + if (p->dk[i].dk_xfers > 0) + i++; + } + if (reread) { + fclose(fp); + fp = (FILE *) - 1; + } else + rewind(fp); + disks = i; +} + +void strip_spaces(char *s) +{ + char *p; + int spaced = 1; + + p = s; + for (p = s; *p != 0; p++) { + if (*p == ':') + *p = ' '; + if (*p != ' ') { + *s = *p; + s++; + spaced = 0; + } else if (spaced) { + /* do no thing as this is second space */ + } else { + *s = *p; + s++; + spaced = 1; + } + + } + *s = 0; +} + +void proc_partitions(double elapsed) +{ + static FILE *fp = (FILE *) - 1; + char buf[1024]; + int i = 0; + int ret; + + if (fp == (FILE *) - 1) { + if ((fp = fopen("/proc/partitions", "r")) == NULL) { + error("failed to open - /proc/partitions"); + partitions = 0; + return; + } + } + if (fgets(buf, 1024, fp) == NULL) + goto end; /* throw away the header lines */ + if (fgets(buf, 1024, fp) == NULL) + goto end; +/* +major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq + + 33 0 1052352 hde 2855 15 2890 4760 0 0 0 0 -4 7902400 11345292 + 33 1 1050304 hde1 2850 0 2850 3930 0 0 0 0 0 3930 3930 + 3 0 39070080 hda 9287 19942 226517 90620 8434 25707 235554 425790 -12 7954830 33997658 + 3 1 31744408 hda1 651 90 5297 2030 0 0 0 0 0 2030 2030 + 3 2 6138720 hda2 7808 19561 218922 79430 7299 20529 222872 241980 0 59950 321410 + 3 3 771120 hda3 13 41 168 80 0 0 0 0 0 80 80 + 3 4 1 hda4 0 0 0 0 0 0 0 0 0 0 0 + 3 5 408208 hda5 812 241 2106 9040 1135 5178 12682 183810 0 11230 192850 +*/ + for (i = 0; i < DISKMAX; i++) { + if (fgets(buf, 1024, fp) == NULL) + break; + strip_spaces(buf); + ret = + sscanf(&buf[0], + "%d %d %lu %s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + &p->dk[i].dk_major, &p->dk[i].dk_minor, + &p->dk[i].dk_blocks, (char *) &p->dk[i].dk_name, + &p->dk[i].dk_reads, &p->dk[i].dk_rmerge, + &p->dk[i].dk_rkb, &p->dk[i].dk_rmsec, + &p->dk[i].dk_writes, &p->dk[i].dk_wmerge, + &p->dk[i].dk_wkb, &p->dk[i].dk_wmsec, + &p->dk[i].dk_inflight, &p->dk[i].dk_use, + &p->dk[i].dk_aveq); + p->dk[i].dk_rkb /= 2; /* sectors = 512 bytes */ + p->dk[i].dk_wkb /= 2; + p->dk[i].dk_xfers = p->dk[i].dk_rkb + p->dk[i].dk_wkb; + if (p->dk[i].dk_xfers == 0) + p->dk[i].dk_bsize = 0; + else + p->dk[i].dk_bsize = + (p->dk[i].dk_rkb + + p->dk[i].dk_wkb) / p->dk[i].dk_xfers * 1024; + + p->dk[i].dk_time /= 10.0; /* in milli-seconds to make it upto 100%, 1000/100 = 10 */ + + if (ret != 15) { +#ifdef DEBUG + if (debug) + fprintf(stderr, "sscanf wanted 15 returned = %d line=%s\n", + ret, buf); +#endif /*DEBUG*/ + partitions_short = 1; + } else + partitions_short = 0; + } + end: + if (reread) { + fclose(fp); + fp = (FILE *) - 1; + } else + rewind(fp); + disks = i; +} + +void proc_disk(double elapsed) +{ + struct stat buf; + int ret; + if (disk_mode == 0) { + ret = stat("/proc/diskstats", &buf); + if (ret == 0) { + disk_mode = DISK_MODE_DISKSTATS; + } else { + ret = stat("/proc/partitions", &buf); + if (ret == 0) { + disk_mode = DISK_MODE_PARTITIONS; + } else { + disk_mode = DISK_MODE_IO; + } + } + } + switch (disk_mode) { + case DISK_MODE_IO: + proc_disk_io(elapsed); + break; + case DISK_MODE_DISKSTATS: + proc_diskstats(elapsed); + break; + case DISK_MODE_PARTITIONS: + proc_partitions(elapsed); + break; + } +} + +#undef isdigit +#define isdigit(ch) ( ( '0' <= (ch) && (ch) >= '9')? 0: 1 ) + +long proc_mem_search(char *s) +{ + int i; + int j; + int len; + len = strlen(s); + for (i = 0; i < proc[P_MEMINFO].lines; i++) { + if (!strncmp(s, proc[P_MEMINFO].line[i], len)) { + for (j = len; + !isdigit(proc[P_MEMINFO].line[i][j]) && + proc[P_MEMINFO].line[i][j] != 0; j++) + /* do nothing */ ; + return atol(&proc[P_MEMINFO].line[i][j]); + } + } + return -1; +} + +void proc_mem() +{ + if (proc[P_MEMINFO].read_this_interval == 0) + proc_read(P_MEMINFO); + + p->mem.memtotal = proc_mem_search("MemTotal"); + p->mem.memfree = proc_mem_search("MemFree"); + p->mem.memshared = proc_mem_search("MemShared"); + p->mem.buffers = proc_mem_search("Buffers"); + p->mem.cached = proc_mem_search("Cached"); + p->mem.swapcached = proc_mem_search("SwapCached"); + p->mem.active = proc_mem_search("Active"); + p->mem.inactive = proc_mem_search("Inactive"); + p->mem.hightotal = proc_mem_search("HighTotal"); + p->mem.highfree = proc_mem_search("HighFree"); + p->mem.lowtotal = proc_mem_search("LowTotal"); + p->mem.lowfree = proc_mem_search("LowFree"); + p->mem.swaptotal = proc_mem_search("SwapTotal"); + p->mem.swapfree = proc_mem_search("SwapFree"); +#ifdef LARGEMEM + p->mem.dirty = proc_mem_search("Dirty"); + p->mem.writeback = proc_mem_search("Writeback"); + p->mem.mapped = proc_mem_search("Mapped"); + p->mem.slab = proc_mem_search("Slab"); + p->mem.committed_as = proc_mem_search("Committed_AS"); + p->mem.pagetables = proc_mem_search("PageTables"); + p->mem.hugetotal = proc_mem_search("HugePages_Total"); + p->mem.hugefree = proc_mem_search("HugePages_Free"); + p->mem.hugesize = proc_mem_search("Hugepagesize"); +#else + p->mem.bigfree = proc_mem_search("BigFree"); +#endif /*LARGEMEM*/ +} + +#define MAX_SNAPS 72 +#define MAX_SNAP_ROWS 20 +#define SNAP_OFFSET 6 + +int next_cpu_snap = 0; +int cpu_snap_all = 0; + +struct { + double user; + double kernel; + double iowait; + double idle; + double steal; +} cpu_snap[MAX_SNAPS]; + +int snap_average() +{ + int i; + int end; + int total = 0; + + if (cpu_snap_all) + end = MAX_SNAPS; + else + end = next_cpu_snap; + + for (i = 0; i < end; i++) { + total = total + cpu_snap[i].user + cpu_snap[i].kernel; + } + return (total / end); +} + +void snap_clear() +{ + int i; + for (i = 0; i < MAX_SNAPS; i++) { + cpu_snap[i].user = 0; + cpu_snap[i].kernel = 0; + cpu_snap[i].iowait = 0; + cpu_snap[i].idle = 0; + cpu_snap[i].steal = 0; + } + next_cpu_snap = 0; + cpu_snap_all = 0; +} + +void plot_snap(WINDOW * pad) +{ + int i; + int j; + double k; + if (cursed) { + mvwprintw(pad, 0, 0, + " CPU +---Long-Term-------------------------------------------------------------+"); + mvwprintw(pad, 1, 0, "100%%-|"); + mvwprintw(pad, 2, 1, "95%%-|"); + mvwprintw(pad, 3, 1, "90%%-|"); + mvwprintw(pad, 4, 1, "85%%-|"); + mvwprintw(pad, 5, 1, "80%%-|"); + mvwprintw(pad, 6, 1, "75%%-|"); + mvwprintw(pad, 7, 1, "70%%-|"); + mvwprintw(pad, 8, 1, "65%%-|"); + mvwprintw(pad, 9, 1, "60%%-|"); + mvwprintw(pad, 10, 1, "55%%-|"); + mvwprintw(pad, 11, 1, "50%%-|"); + mvwprintw(pad, 12, 1, "45%%-|"); + mvwprintw(pad, 13, 1, "40%%-|"); + mvwprintw(pad, 14, 1, "35%%-|"); + mvwprintw(pad, 15, 1, "30%%-|"); + mvwprintw(pad, 16, 1, "25%%-|"); + mvwprintw(pad, 17, 1, "20%%-|"); + mvwprintw(pad, 18, 1, "15%%-|"); + mvwprintw(pad, 19, 1, "10%%-|"); + mvwprintw(pad, 20, 1, " 5%%-|"); + + mvwprintw(pad, 21, 4, + " +-------------------------------------------------------------------------+"); + if (colour) { + COLOUR wattrset(pad, COLOR_PAIR(2)); + mvwprintw(pad, 0, 26, "User%%"); + COLOUR wattrset(pad, COLOR_PAIR(1)); + mvwprintw(pad, 0, 36, "System%%"); + COLOUR wattrset(pad, COLOR_PAIR(4)); + mvwprintw(pad, 0, 49, "Wait%%"); + COLOUR wattrset(pad, COLOR_PAIR(5)); + mvwprintw(pad, 0, 59, "Steal%%"); + COLOUR wattrset(pad, COLOR_PAIR(0)); + } + + for (j = 0; j < MAX_SNAPS; j++) { + for (i = 0; i < MAX_SNAP_ROWS; i++) { + wmove(pad, MAX_SNAP_ROWS - i, j + SNAP_OFFSET); + if (cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait + cpu_snap[j].idle + cpu_snap[j].steal == 0) { /* if not all zeros */ + COLOUR wattrset(pad, COLOR_PAIR(0)); + wprintw(pad, " "); + } else if ((cpu_snap[j].user / 100 * MAX_SNAP_ROWS) > + i + 0.5) { + COLOUR wattrset(pad, COLOR_PAIR(9)); + wprintw(pad, "U"); + } else if ((cpu_snap[j].user + cpu_snap[j].kernel) / 100 * + MAX_SNAP_ROWS > i + 0.5) { + COLOUR wattrset(pad, COLOR_PAIR(8)); + wprintw(pad, "s"); + } else + if ((cpu_snap[j].user + cpu_snap[j].kernel + + cpu_snap[j].iowait) / 100 * MAX_SNAP_ROWS > + i + 0.5) { + COLOUR wattrset(pad, COLOR_PAIR(10)); + wprintw(pad, "w"); + } else if ((cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait + cpu_snap[j].idle) / 100 * MAX_SNAP_ROWS > i) { /*no +0.5 or too few Steal's */ + COLOUR wattrset(pad, COLOR_PAIR(0)); + wprintw(pad, " "); + } else if (cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait + cpu_snap[j].idle + cpu_snap[j].steal > i) { /* if not all zeros */ + COLOUR wattrset(pad, COLOR_PAIR(5)); + wprintw(pad, "S"); + } + } + k = cpu_snap[j].user + cpu_snap[j].kernel + cpu_snap[j].iowait; + if (0.1 < k && k < 5.0) { /* not zero but less than 5% */ + wmove(pad, MAX_SNAP_ROWS, j + SNAP_OFFSET); + COLOUR wattrset(pad, COLOR_PAIR(2)); + wprintw(pad, "_"); + } + } + COLOUR wattrset(pad, COLOR_PAIR(0)); + for (i = 0; i < MAX_SNAP_ROWS; i++) { + wmove(pad, MAX_SNAP_ROWS - i, next_cpu_snap + SNAP_OFFSET); + wprintw(pad, "|"); + } + wmove(pad, MAX_SNAP_ROWS + 1 - (snap_average() / 5), + next_cpu_snap + SNAP_OFFSET); + wprintw(pad, "+"); + if (dotline) { + for (i = 0; i < MAX_SNAPS; i++) { + wmove(pad, MAX_SNAP_ROWS + 1 - dotline * 2, + i + SNAP_OFFSET); + wprintw(pad, "+"); + } + dotline = 0; + } + } +} + +/* This saves the CPU overall usage for later ploting on the screen */ +void save_snap(double user, double kernel, double iowait, double idle, + double steal) +{ + cpu_snap[next_cpu_snap].user = user; + cpu_snap[next_cpu_snap].kernel = kernel; + cpu_snap[next_cpu_snap].iowait = iowait; + cpu_snap[next_cpu_snap].idle = idle; + cpu_snap[next_cpu_snap].steal = steal; + next_cpu_snap++; + if (next_cpu_snap >= MAX_SNAPS) { + next_cpu_snap = 0; + cpu_snap_all = 1; + } +} + +void plot_smp(WINDOW * pad, int cpu_no, int row, double user, + double kernel, double iowait, double idle, double steal) +{ + int i; + int peak_col; + + if (show_rrd) + return; + + if (cpu_peak[cpu_no] < (user + kernel + iowait)) + cpu_peak[cpu_no] = + (double) ((int) user / 2 + (int) kernel / 2 + + (int) iowait / 2) * 2.0; + + if (cursed) { + if (cpu_no == 0) + mvwprintw(pad, row, 0, "Avg"); + else + mvwprintw(pad, row, 0, "%3d", cpu_no); + mvwprintw(pad, row, 3, "% 6.1lf", user); + mvwprintw(pad, row, 9, "% 6.1lf", kernel); + mvwprintw(pad, row, 15, "% 6.1lf", iowait); + if (steal) { + mvwprintw(pad, row, 21, "% 6.1lf", steal); + } else { + mvwprintw(pad, row, 21, "% 6.1lf", idle); + } + mvwprintw(pad, row, 27, "|"); + wmove(pad, row, 28); + for (i = 0; i < (int) (user / 2); i++) { + COLOUR wattrset(pad, COLOR_PAIR(9)); + wprintw(pad, "U"); + } + for (i = 0; i < (int) (kernel / 2); i++) { + COLOUR wattrset(pad, COLOR_PAIR(8)); + wprintw(pad, "s"); + } + for (i = 0; i < (int) (iowait / 2); i++) { + COLOUR wattrset(pad, COLOR_PAIR(10)); + wprintw(pad, "W"); + } + COLOUR wattrset(pad, COLOR_PAIR(0)); + for (i = 0; i <= (int) (idle / 2); i++) { /* added "=" to try to conteract missing halves */ +#ifdef POWER + if (lparcfg.smt_mode > 1 + && ((cpu_no - 1) % lparcfg.smt_mode) == 0 && (i % 2)) + wprintw(pad, "."); + else +#endif + wprintw(pad, " "); + } + for (i = 0; i < (int) ((steal + 1) / 2); i++) { + COLOUR wattrset(pad, COLOR_PAIR(5)); + wprintw(pad, "S"); + } + COLOUR wattrset(pad, COLOR_PAIR(0)); + mvwprintw(pad, row, 77, "| "); + + peak_col = 28 + (int) (cpu_peak[cpu_no] / 2); + if (peak_col > 77) + peak_col = 77; + mvwprintw(pad, row, peak_col, ">"); + } else { + /* Sanity check the numnbers */ + if (user < 0.0 || kernel < 0.0 || iowait < 0.0 || idle < 0.0 + || idle > 100.0 || steal < 0) { + user = kernel = iowait = idle = steal = 0; + } + + if (first_steal && steal > 0) { + fprintf(fp, "AAA,steal,1\n"); + first_steal = 0; + } + if (cpu_no == 0) + fprintf(fp, "CPU_ALL,%s,%.1lf,%.1lf,%.1lf,%.1f,%.1lf,,%d\n", + LOOP, user, kernel, iowait, idle, steal, cpus); + else { + fprintf(fp, "CPU%03d,%s,%.1lf,%.1lf,%.1lf,%.1lf,%.1f\n", + cpu_no, LOOP, user, kernel, iowait, idle, steal); + } + } +} + +/* Added variable to remember started children + * 0 - start + * 1 - snap + * 2 - end +*/ +#define CHLD_START 0 +#define CHLD_SNAP 1 +#define CHLD_END 2 +int nmon_children[3] = { -1, -1, -1 }; + +void init_pairs() +{ + COLOUR init_pair((short) 0, (short) 7, (short) 0); /* White */ + COLOUR init_pair((short) 1, (short) 1, (short) 0); /* Red */ + COLOUR init_pair((short) 2, (short) 2, (short) 0); /* Green */ + COLOUR init_pair((short) 3, (short) 3, (short) 0); /* Yellow */ + COLOUR init_pair((short) 4, (short) 4, (short) 0); /* Blue */ + COLOUR init_pair((short) 5, (short) 5, (short) 0); /* Magenta */ + COLOUR init_pair((short) 6, (short) 6, (short) 0); /* Cyan */ + COLOUR init_pair((short) 7, (short) 7, (short) 0); /* White */ + COLOUR init_pair((short) 8, (short) 0, (short) 1); /* Red background, red text */ + COLOUR init_pair((short) 9, (short) 0, (short) 2); /* Green background, green text */ + COLOUR init_pair((short) 10, (short) 0, (short) 4); /* Blue background, blue text */ + COLOUR init_pair((short) 11, (short) 0, (short) 3); /* Yellow background, yellow text */ + COLOUR init_pair((short) 12, (short) 0, (short) 6); /* Cyan background, cyan text */ +} + +/* Signal handler + * SIGUSR1 or 2 is used to stop nmon cleanly + * SIGWINCH is used when the window size is changed + */ +void interrupt(int signum) +{ + int child_pid; + int waitstatus; + if (signum == SIGCHLD) { + while ((child_pid = waitpid(0, &waitstatus, 0)) == -1) { + if (errno == EINTR) /* retry */ + continue; + return; /* ECHLD, EFAULT */ + } + if (child_pid == nmon_children[CHLD_SNAP]) + nmon_children[CHLD_SNAP] = -1; + signal(SIGCHLD, interrupt); + return; + } + if (signum == SIGUSR1 || signum == SIGUSR2) { + maxloops = loop; + return; + } + if (signum == SIGWINCH) { + CURSE endwin(); /* stop + start curses so it works out the # of row and cols */ + CURSE initscr(); + CURSE cbreak(); + signal(SIGWINCH, interrupt); + COLOUR colour = has_colors(); + COLOUR start_color(); + COLOUR init_pairs(); + CURSE clear(); + return; + } + CURSE endwin(); + exit(0); +} + + +/* only place the q=previous and p=currect pointers are modified */ +void switcher(void) +{ + static int which = 1; + int i; + + if (which) { + p = &database[0]; + q = &database[1]; + which = 0; + } else { + p = &database[1]; + q = &database[0]; + which = 1; + } + if (flash_on) + flash_on = 0; + else + flash_on = 1; + + /* Reset flags so /proc/... is re-read in next interval */ + for (i = 0; i < P_NUMBER; i++) { + proc[i].read_this_interval = 0; + } +#ifdef POWER + lparcfg_processed = 0; +#endif +} + + +/* Lookup the right string */ +char *status(int n) +{ + switch (n) { + case 0: + return "Run "; + default: + return "Sleep"; + } +} + +/* Lookup the right process state string */ +char *get_state(char n) +{ + static char duff[64]; + switch (n) { + case 'R': + return "Running "; + case 'S': + return "Sleeping "; + case 'D': + return "DiskSleep"; + case 'Z': + return "Zombie "; + case 'T': + return "Traced "; + case 'W': + return "Paging "; + default: + sprintf(duff, "%d", n); + return duff; + } +} + +#ifdef GETUSER +/* Convert User id (UID) to a name with caching for speed + * getpwuid() should be NFS/yellow pages safe + */ +char *getuser(uid_t uid) +{ +#define NAMESIZE 16 + struct user_info { + uid_t uid; + char name[NAMESIZE]; + }; + static struct user_info *u = NULL; + static int used = 0; + int i; + struct passwd *pw; + + i = 0; + if (u != NULL) { + for (i = 0; i < used; i++) { + if (u[i].uid == uid) { + return u[i].name; + } + } + u = (struct user_info *) REALLOC(u, + (sizeof(struct user_info) * + (i + 1))); + } else + u = (struct user_info *) MALLOC(sizeof(struct user_info)); + used++; + + /* failed to find a match so add it */ + u[i].uid = uid; + pw = getpwuid(uid); + + if (pw != NULL) + strncpy(u[i].name, pw->pw_name, NAMESIZE); + else + sprintf(u[i].name, "unknown%d", uid); + return u[i].name; +} +#endif /* GETUSER */ + +/* User Defined Disk Groups */ + +char *save_word(char *in, char *out) +{ + int len; + int i; + len = strlen(in); + out[0] = 0; + for (i = 0; i < len; i++) { + if (isalnum(in[i]) || in[i] == '_' || in[i] == '-' || in[i] == '/') { + out[i] = in[i]; + out[i + 1] = 0; + } else + break; + } + for (; i < len; i++) + if (isalnum(in[i])) + return &in[i]; + return &in[i]; +} + +#define DGROUPS 64 +#define DGROUPITEMS 512 + +char *dgroup_filename; +char *dgroup_name[DGROUPS]; +int *dgroup_data; +int dgroup_disks[DGROUPS]; +int dgroup_total_disks = 0; +int dgroup_total_groups; + +void load_dgroup(struct dsk_stat *dk) +{ + FILE *gp; + char line[4096]; + char name[1024]; + int i, j; + char *nextp; + + if (dgroup_loaded == 2) + return; + dgroup_data = MALLOC(sizeof(int) * DGROUPS * DGROUPITEMS); + for (i = 0; i < DGROUPS; i++) + for (j = 0; j < DGROUPITEMS; j++) + dgroup_data[i * DGROUPITEMS + j] = -1; + + gp = fopen(dgroup_filename, "r"); + + if (gp == NULL) { + perror("opening disk group file"); + fprintf(stderr, "ERROR: failed to open %s\n", dgroup_filename); + exit(9); + } + + for (dgroup_total_groups = 0; + fgets(line, 4096 - 1, gp) != NULL + && dgroup_total_groups < DGROUPS; dgroup_total_groups++) { + /* ignore lines starting with # */ + if (line[0] == '#') { /* was a comment line */ + /* Decrement dgroup_total_groups by 1 to correct index for next loop */ + --dgroup_total_groups; + continue; + } + /* save the name */ + nextp = save_word(line, name); + if (strlen(name) == 0) { /* was a blank line */ + fprintf(stderr, + "ERROR nmon:ignoring odd line in diskgroup file \"%s\"\n", + line); + /* Decrement dgroup_total_groups by 1 to correct index for next loop */ + --dgroup_total_groups; + continue; + } + /* Added +1 to be able to correctly store the terminating \0 character */ + dgroup_name[dgroup_total_groups] = MALLOC(strlen(name) + 1); + strcpy(dgroup_name[dgroup_total_groups], name); + + /* save the hdisks */ + for (i = 0; i < DGROUPITEMS && *nextp != 0; i++) { + nextp = save_word(nextp, name); + for (j = 0; j < disks; j++) { + if (strcmp(dk[j].dk_name, name) == 0) { + /*DEBUG printf("DGadd group=%s,name=%s,disk=%s,dgroup_total_groups=%d,dgroup_total_disks=%d,j=%d,i=%d,index=%d.\n", + dgroup_name[dgroup_total_groups], + name, dk[j].dk_name, dgroup_total_groups, dgroup_total_disks, j, i,dgroup_total_groups*DGROUPITEMS+i); + */ + dgroup_data[dgroup_total_groups * DGROUPITEMS + i] = j; + dgroup_disks[dgroup_total_groups]++; + dgroup_total_disks++; + break; + } + } + if (j == disks) + fprintf(stderr, + "ERROR nmon:diskgroup file - failed to find disk=%s for group=%s disks known=%d\n", + name, dgroup_name[dgroup_total_groups], disks); + } + } + fclose(gp); + dgroup_loaded = 2; +} + + +void list_dgroup(struct dsk_stat *dk) +{ + int i, j, k, n; + int first = 1; + + /* DEBUG for (n = 0, i = 0; i < dgroup_total_groups; i++) { + fprintf(fp, "CCCG,%03d,%s", n++, dgroup_name[i]); + for (j = 0; j < dgroup_disks[i]; j++) { + if (dgroup_data[i*DGROUPITEMS+j] != -1) { + fprintf(fp, ",%d=%d", j, dgroup_data[i*DGROUPITEMS+j]); + } + } + fprintf(fp, "\n"); + } + */ + if (!show_dgroup) + return; + + for (n = 0, i = 0; i < dgroup_total_groups; i++) { + if (first) { + fprintf(fp, "BBBG,%03d,User Defined Disk Groups Name,Disks\n", + n++); + first = 0; + } + fprintf(fp, "BBBG,%03d,%s", n++, dgroup_name[i]); + for (k = 0, j = 0; j < dgroup_disks[i]; j++) { + if (dgroup_data[i * DGROUPITEMS + j] != -1) { + fprintf(fp, ",%s", + dk[dgroup_data[i * DGROUPITEMS + j]].dk_name); + k++; + } + /* add extra line if we have lots to stop spreadsheet line width problems */ + if (k == 128) { + fprintf(fp, "\nBBBG,%03d,%s continued", n++, + dgroup_name[i]); + } + } + fprintf(fp, "\n"); + } + fprintf(fp, "DGBUSY,Disk Group Busy %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGREAD,Disk Group Read KB/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGWRITE,Disk Group Write KB/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGSIZE,Disk Group Block Size KB %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGXFER,Disk Group Transfers/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + + /* If requested provide additional data available in /proc/diskstats */ + if (extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS) { + fprintf(fp, "DGREADS,Disk Group read/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGREADMERGE,Disk Group merged read/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGREADSERV,Disk Group read service time (SUM ms) %s", + hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGWRITES,Disk Group write/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGWRITEMERGE,Disk Group merged write/s %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, + "DGWRITESERV,Disk Group write service time (SUM ms) %s", + hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGINFLIGHT,Disk Group in flight IO %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGIOTIME,Disk Group time spent for IO (ms) %s", + hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + fprintf(fp, "DGBACKLOG,Disk Group Backlog time (ms) %s", hostname); + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] != 0) + fprintf(fp, ",%s", dgroup_name[i]); + } + fprintf(fp, "\n"); + } +} + +int is_dgroup_name(char *name) +{ + int i; + for (i = 0; i < DGROUPS; i++) { + if (dgroup_name[i] == (char *) 0) + return 0; + if (strncmp(name, dgroup_name[i], strlen(name)) == 0) + return 1; + } + return 0; +} + + + +void hint(void) +{ + printf("Hint for %s version %s\n", progname, VERSION); + printf("\tFull Help Info : %s -h\n\n", progname); + printf("\tOn-screen Stats: %s\n", progname); + printf + ("\tData Collection: %s -f [-s ] [-c ] [-t|-T]\n", + progname); + printf("\tCapacity Plan : %s -x\n", progname); + printf("Interactive-Mode:\n"); + printf + ("\tRead the Welcome screen & at any time type: \"h\" for more help\n"); + printf("\tType \"q\" to exit nmon\n\n"); + printf("For Data-Collect-Mode\n"); + printf + ("\t-f Must be the first option on the line (switches off interactive mode)\n"); + printf + ("\t Saves data to a CSV Spreadsheet format .nmon file in then local directory\n"); + printf + ("\t Note: -f sets a defaults -s300 -c288 which you can then modify\n"); + printf("\tFurther Data Collection Options:\n"); + printf("\t-s time between data snapshots\n"); + printf("\t-c of snapshots before exiting\n"); + printf + ("\t-t Includes Top Processes stats (-T also collects command arguments)\n"); + printf + ("\t-x Capacity Planning=15 min snapshots for 1 day. (nmon -ft -s 900 -c 96)\n"); + printf("---- End of Hints\n"); +} + +void help(void) +{ + hint(); + printf("---- Full Help Information for %s\n\n", SccsId); + printf("For Interactive and Data Collection Mode:\n"); + printf("\tUser Defined Disk Groups (DG) - This works in both modes\n"); + printf ("\tIt is a work around Linux issues, where disks & partitions are mixed up in /proc files\n"); + printf ("\t& drive driver developers use bizarre device names, making it trick to separate them.\n"); + printf("\t-g Use this file to define the groups\n"); + printf ("\t - On each line: group-name (space separated list)\n"); + printf("\t - Example line: database sdb sdc sdd sde\n"); + printf("\t - Up to 64 disk groups, 512 disks per line\n"); + printf ("\t - Disks names can appear more than one group\n"); + printf ("\t-g auto - Will generate a file called \"auto\" with just disks from \"lsblk|grep disk\" output\n"); + printf("\t For Interactive use define the groups then type: g or G\n"); + printf ("\t For Data Capture defining the groups switches on data collection\n"); + printf("\n"); + printf ("Data-Collect-Mode = spreadsheet format (i.e. comma separated values)\n"); + printf ("\tNote: Use only one of f, F, R, x, X or z to switch on Data Collection mode\n"); + printf ("\tNote: Make it the first argument then use other options to modify the defaults\n"); + printf ("\tNote: Don't collect data that you don't want - it just makes the files too large\n"); + printf ("\tNote: Too many snapshots = too much data and crashes Analyser and other tools\n"); + printf ("\tNote: 500 to 800 snapshots make a good graph on a normal size screen\n"); + printf ("\tRecommended normal minimal options: snapshots every 2 minutes all day: \n"); + printf("\t\tSimple capture: nmon -f -s 120 -c 720\n"); + printf("\t\tWith Top Procs: nmon -fT -s 120 -c 720\n"); + printf ("\t\tSet the directory: nmon -fT -s 120 -c 720 -m /home/nag/nmon\n"); + printf + ("\t\tCapture a busy hour: nmon -fT -s 5 -c 720 -m /home/nag/nmon\n"); + printf("\n"); + printf("For Data-Collect-Mode Options\n"); + printf + ("\t-f spreadsheet output format [note: default -s300 -c288]\n"); + printf("\t\t\t output file is _YYYYMMDD_HHMM.nmon\n"); + printf("\t-F same as -f but user supplied filename\n"); + printf("\t\t\t Not recommended as the default file name is perfect\n"); + printf("\tThe other options in alphabetical order:\n"); + printf("\t-a Include Accelerator GPU stats\n"); + printf + ("\t-b Online only: for black and white mode (switch off colour)\n"); + printf("\t-c The number of snapshots before nmon stops\n"); + printf + ("\t-d To set the maximum number of disks [default 256]\n"); + printf + ("\t Ignores disks if the systems has 100's of disk or the config is odd!\n"); + printf + ("\t-D Use with -g to add the Disk Wait/Service Time & in-flight stats\n"); + printf("\t-f and -F See above\n"); + printf + ("\t-g User Defined Disk Groups (see above) - Data Capture: Generates BBBG & DG lines\n"); + printf + ("\t-g auto See above but makes the file \"auto\" for you of just the disks like sda etc.\n"); + printf("\t-h This help output\n"); + printf + ("\t-I Set the ignore process & disks busy threshold (default 0.1%%)\n"); + printf + ("\t Don't save or show proc/disk using less than this percent\n"); + printf + ("\t-l Disks per line in data capture to avoid spreadsheet width issues. Default 150. EMC=64.\n"); + printf + ("\t-m nmon changes to this directory before saving to file\n"); + printf("\t Useful when starting nmon via cron\n"); + printf + ("\t-M Adds MHz stats for each CPU thread. Some POWER8 model CPU cores can be different frequencies\n"); + printf + ("\t-N Include NFS Network File System for V2, V3 and V4\n"); + printf + ("\t-p nmon outputs the PID when it starts. Useful in scripts to capture the PID for a later safe stop.\n"); + printf + ("\t-r Use in a benchmark to record the run details for later analysis [default hostname]\n"); + printf + ("\t-R Old rrdtool format used by some - may be removed in the future. If you use this email Nigel\n"); + printf + ("\t-s Time between snap shots - with \"-c count\" decides duration of the data capture\n"); + printf("\t-t Include Top Processes in the output\n"); + printf + ("\t-T As -t plus it saves command line arguments in UARG section\n"); + printf + ("\t-U Include the Linux 10 CPU utilisation stats (CPUUTIL lines in the file)\n"); + printf("\t-V Print nmon version & exit immediately\n"); + printf("\n"); + printf("\tTo manually load nmon files into a spreadsheet:\n"); + printf("\t\tsort -A *nmon >stats.csv\n"); + printf("\t\tTransfer the stats.csv file to your PC\n"); + printf + ("\t\tStart spreadsheet & then Open with type=comma-separated-value ASCII file\n"); + printf("\t\tThis puts every datum in a different cell\n"); + printf + ("\t\tNow select the data of one type (same 1st column) and graph it\n"); + printf + ("\t\tThe nmon Analyser & other tools do not need the file sorted.\n"); + printf("\n"); + printf("Capacity Planning mode - use cron to run each day\n"); + printf("\t-x Sensible spreadsheet output for one day\n"); + printf + ("\t Every 15 mins for 1 day ( i.e. -ft -s 900 -c 96)\n"); + printf("\t-X Sensible spreadsheet output for busy hour\n"); + printf + ("\t Every 30 secs for 1 hour ( i.e. -ft -s 30 -c 120)\n"); + printf + ("\t-z Like -x but the output saved in /var/perf/tmp assuming root user\n"); + printf("\n"); + + printf("Interactive Mode Keys in Alphabetical Order\n"); + printf + (" Start nmon then type the letters below to switch on & off particular stats\n"); + printf(" The stats are always in the same order on-screen\n"); + printf + (" To see more stats: make the font smaller or use two windows\n\n"); + printf("\tKey --- Toggles on off to control what is displayed ---\n"); +#ifdef NVIDIA_GPU + printf("\ta = Accelerator from Nvidia GPUs\n"); +#endif /*NVIDIA_GPU */ + printf + ("\tb = Black and white mode (or use -b command line option)\n"); + printf + ("\tc = CPU Utilisation stats with bar graphs (CPU core threads)\n"); + printf + ("\tC = CPU Utilisation as above but concise wide view (up to 192 CPUs)\n"); + printf("\td = Disk I/O Busy%% & Graphs of Read and Write KB/s\n"); + printf + ("\tD = Disk I/O Numbers including Transfers, Average Block Size & Peaks (type: 0 to reset)\n"); + printf + ("\tg = User Defined Disk Groups (assumes -g when starting nmon)\n"); + printf + ("\tG = Change Disk stats (d) to just disks (assumes -g auto when starting nmon)\n"); + printf("\th = This help information\n"); + printf("\tj = File Systems including Journal File Systems\n"); + printf + ("\tk = Kernel stats Run Queue, context-switch, fork, Load Average & Uptime\n"); + printf + ("\tl = Long term Total CPU (over 75 snapshots) via bar graphs\n"); + printf("\tL = Large and =Huge memory page stats\n"); + printf("\tm = Memory & Swap stats\n"); + printf + ("\tM = MHz for machines with variable frequency 1st=Threads 2nd=Cores 3=Graphs\n"); + printf + ("\tn = Network stats & errors (if no errors it disappears)\n"); + printf("\tN = NFS - Network File System\n"); + printf("\t 1st NFS V2 & V3, 2nd=NFS4-Client & 3rd=NFS4-Server\n"); + printf + ("\to = Disk I/O Map (one character per disk pixels showing how busy it is)\n"); + printf("\t Particularly good if you have 100's of disks \n"); +#ifdef PARTITIONS + printf("\tP = Partitions Disk I/O Stats\n"); +#endif +#ifdef POWER + printf("\tp = PowerVM LPAR Stats from /proc/ppc64/lparcfg\n"); +#endif + printf("\tq = Quit\n"); + printf + ("\tr = Resources: Machine type, name, cache details & OS version & Distro + LPAR\n"); + printf + ("\tt = Top Processes: select the data & order 1=Basic, 3=Perf 4=Size 5=I/O=root only\n"); + printf("\tu = Top Process with command line details\n"); + printf("\tU = CPU utilisation stats - all 10 Linux stats:\n"); + printf + ("\t user, user_nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice\n"); + printf + ("\tv = Experimental Verbose mode - tries to make recommendations\n"); + printf("\tV = Virtual Memory stats\n"); + printf("\n"); + printf("\tKey --- Other Interactive Controls ---\n"); + printf("\t+ = Double the screen refresh time\n"); + printf("\t- = Halves the screen refresh time\n"); + printf + ("\t0 = Reset peak counts to zero (peak highlight with \">\")\n"); + printf("\t1 = Top Processes mode 1 Nice, Priority, Status\n"); + printf("\t3 = Top Processes mode 3 CPU, Memory, Faults\n"); + printf("\t4 = Top Processes mode 4 as 3 but order by memory\n"); + printf + ("\t5 = Top Processes mode 5 as 3 but order by I/O (if root user)\n"); + printf("\t6 = Highlights 60%% row on Long Term CPU view\n"); + printf("\t7 = Highlights 70%% row on Long Term CPU view\n"); + printf("\t8 = Highlights 80%% row on Long Term CPU view\n"); + printf("\t9 = Highlights 90%% row on Long Term CPU view\n"); + printf + ("\t. = Minimum mode i.e. only busy disks and processes shown\n"); + printf("\tspace = Refresh screen now\n"); + + printf("\n"); + printf("Interactive Start-up Control\n"); + printf + ("\tIf you find you always type the same toggles every time you start\n"); + printf("\tthen place them in the NMON shell variable. For example:\n"); + printf("\t export NMON=cmdrtn\n"); + + printf("\n"); + printf("Other items for Interactive and Data Collection mode:\n"); + printf + ("\ta) To limit the processes nmon lists (online and to a file)\n"); + printf + ("\t either set NMONCMD0 to NMONCMD63 to the program names\n"); + printf("\t or use -C cmd:cmd:cmd etc. example: -C ksh:vi:syncd\n"); + printf("Other items for Data Collection mode:\n"); + printf("\tb) To you want to stop nmon use: kill -USR2 \n"); + printf("\tc) Use -p and nmon outputs the background process pid\n"); + printf + ("\td) If you want to pipe nmon output to other commands use a FIFO:\n"); + printf("\t mkfifo /tmp/mypipe\n"); + printf("\t nmon -F /tmp/mypipe &\n"); + printf("\t tail -f /tmp/mypipe\n"); + printf("\te) If nmon fails please report it with:\n"); + printf("\t 1) nmon version like: %s\n", VERSION); + printf + ("\t 2) the output of: cd /proc; cat cpuinfo meminfo partitions stat vmstat\n"); + printf("\t 3) some clue of what you were doing\n"); + printf + ("\t 4) I may ask you to run the debug version or collect data files\n"); + printf + ("\tf) If box & line characters are letters then check: terminal emulator & $TERM\n"); + printf + ("\tg) External Data Collectors - nmon will execute a command or script at each snapshot time\n"); + printf + ("\t They must output to a different file which is merge afterwards with the nmon output\n"); + printf("\t Set the following shell variables:\n"); + printf + ("\t NMON_START = script to generate CVS Header test line explaining the columns\n"); + printf + ("\t Generate: TabName,DataDescription,Column_name_and_units,Column_name_and_units ... \n"); + printf + ("\t NMON_SNAP = script for each snapshots data, the parameter is the T0000 snapshot number\n"); + printf("\t Generate: TabName,T00NN,Data,Data,Data ...\n"); + printf + ("\t NMON_END = script to clean up or finalise the data\n"); + printf + ("\t NMON_ONE_IN = call NMON_START less often (if it is heavy in CPU terms)\n"); + printf + ("\t Once capture done: cat nmon-file data-file >merged-file ; ready for Analyser or other tools\n"); + printf + ("\t The nmon Analyser will automatically do its best to graph the data on a new Tab sheet\n"); + printf("\n"); + printf + ("\tDeveloper: Nigel Griffiths See http://nmon.sourceforge.net\n"); + printf("\tFeedback welcome - On the current release only\n"); + printf("\tNo warranty given or implied. (C) Copyright 2009 Nigel Griffiths GPLv3\n"); + exit(0); +} + +#define JFSMAX 128 +#define LOAD 1 +#define UNLOAD 0 +#define JFSNAMELEN 64 +#define JFSTYPELEN 8 + +struct jfs { + char name[JFSNAMELEN]; + char device[JFSNAMELEN]; + char type[JFSNAMELEN]; + int fd; + int mounted; +} jfs[JFSMAX]; + +int jfses = 0; +void jfs_load(int load) +{ + int i; + struct stat stat_buffer; + FILE *mfp; /* FILE pointer for mtab file */ + struct mntent *mp; /* mnt point stats */ + static int jfs_loaded = 0; + + if (load == LOAD) { + if (jfs_loaded == 0) { + mfp = setmntent("/etc/mtab", "r"); + for (i = 0; i < JFSMAX && (mp = getmntent(mfp)) != NULL; i++) { + strncpy(jfs[i].device, mp->mnt_fsname, JFSNAMELEN); + strncpy(jfs[i].name, mp->mnt_dir, JFSNAMELEN); + strncpy(jfs[i].type, mp->mnt_type, JFSTYPELEN); + mp->mnt_fsname[JFSNAMELEN - 1] = 0; + mp->mnt_dir[JFSNAMELEN - 1] = 0; + mp->mnt_type[JFSTYPELEN - 1] = 0; + } + endfsent(); + jfs_loaded = 1; + jfses = i; + } + + /* 1st or later time - just reopen the mount points */ + for (i = 0; i < JFSMAX && jfs[i].name[0] != 0; i++) { + if (stat(jfs[i].name, &stat_buffer) != -1) { + + jfs[i].fd = open(jfs[i].name, O_RDONLY); + if (jfs[i].fd != -1) + jfs[i].mounted = 1; + else + jfs[i].mounted = 0; + } else + jfs[i].mounted = 0; + } + } else { /* this is an unload request */ + if (jfs_loaded) + for (i = 0; i < JFSMAX && jfs[i].name[0] != 0; i++) { + if (jfs[i].mounted) + close(jfs[i].fd); + jfs[i].fd = 0; + } else + /* do nothing */ ; + } +} + +/* We order this array rather than the actual process tables + * the index is the position in the process table and + * the size is the memory used in bytes + * the io is the storge I/O performed in the the last period in bytes + * the time is the CPU used in the last period in seconds + */ +struct topper { + int index; + int other; + double size; + double io; + int time; +} *topper; +int topper_size = 200; + +/* Routine used by qsort to order the processes by CPU usage */ +int cpu_compare(const void *a, const void *b) +{ + return (int) (((struct topper *) b)->time - + ((struct topper *) a)->time); +} + +int size_compare(const void *a, const void *b) +{ + return (int) ((((struct topper *) b)->size - + ((struct topper *) a)->size)); +} + +int disk_compare(const void *a, const void *b) +{ + return (int) ((((struct topper *) b)->io - ((struct topper *) a)->io)); +} + + +/* checkinput is the subroutine to handle user input */ +int checkinput(void) +{ + static int use_env = 1; + char buf[1024]; + int bytes; + int chars; + int i; + char *p; + + if (!cursed) /* not user input so stop with control-C */ + return 0; + ioctl(fileno(stdin), FIONREAD, &bytes); + + if (bytes > 0 || use_env) { + if (use_env) { + use_env = 0; + p = getenv("NMON"); + if (p != 0) { + strcpy(buf, p); + chars = strlen(buf); + } else + chars = 0; + } else + chars = read(fileno(stdin), buf, bytes); + if (chars > 0) { + welcome = 0; + for (i = 0; i < chars; i++) { + switch (buf[i]) { + case '1': + show_topmode = 1; + show_top = 1; + wclear(padtop); + break; +/* case '2': + show_topmode = 2; + show_top = 1; + clear(); + break; +*/ + case '3': + show_topmode = 3; + show_top = 1; + wclear(padtop); + break; + case '4': + show_topmode = 4; + show_top = 1; + wclear(padtop); + break; + case '5': + if (isroot) { + show_topmode = 5; + show_top = 1; + wclear(padtop); + } + break; + case '0': + for (i = 0; i < (max_cpus + 1); i++) + cpu_peak[i] = 0; + for (i = 0; i < networks; i++) { + net_read_peak[i] = 0.0; + net_write_peak[i] = 0.0; + } + for (i = 0; i < disks; i++) { + disk_busy_peak[i] = 0.0; + disk_rate_peak[i] = 0.0; + } + snap_clear(); + aiocount_max = 0; + aiotime_max = 0.0; + aiorunning_max = 0; + huge_peak = 0; + break; + case '6': + case '7': + case '8': + case '9': + dotline = buf[i] - '0'; + break; + case ' ': /* attempt to refresh the screen */ + clear(); + break; + case '+': + seconds = seconds * 2; + break; + case '-': + seconds = seconds / 2; + if (seconds < 1) + seconds = 1; + break; + case '.': /* limit output to processes and disks actually doing work */ + if (show_all) + show_all = 0; + else { + show_all = 1; +/* Switching to Nigel's favourite view is confusing to others + so disable this feature. + show_disk = SHOW_DISK_STATS; + show_top = 1; + show_topmode = 3; +*/ + } + wclear(paddisk); + break; + case '?': + case 'h': + case 'H': + if (show_help) + show_help = 0; + else { + show_help = 1; + show_verbose = 0; + } + wclear(padhelp); + break; +/* alphabetic order from here */ +#ifdef NVIDIA_GPU + case 'a': /* Accelerator */ + case 'E': /* Emily mode */ + FLIP(show_gpu); + wclear(padgpu); + break; +#endif /* NVIDIA_GPU */ + case 'b': + FLIP(colour); + clear(); + break; + case 'c': + FLIP(show_smp); + wclear(padsmp); + break; + case 'C': + FLIP(show_wide); + wclear(padwide); + break; + case 'D': + switch (show_disk) { + case SHOW_DISK_NONE: + show_disk = SHOW_DISK_STATS; + break; + case SHOW_DISK_STATS: + show_disk = SHOW_DISK_NONE; + break; + case SHOW_DISK_GRAPH: + show_disk = SHOW_DISK_STATS; + break; + } + wclear(paddisk); + break; + case 'd': + switch (show_disk) { + case SHOW_DISK_NONE: + show_disk = SHOW_DISK_GRAPH; + break; + case SHOW_DISK_STATS: + show_disk = SHOW_DISK_GRAPH; + break; + case SHOW_DISK_GRAPH: + show_disk = 0; + break; + } + wclear(paddisk); + break; + + break; + case 'G': + if (auto_dgroup) { + FLIP(disk_only_mode); + clear(); + } + break; + case 'g': + FLIP(show_dgroup); + wclear(paddg); + break; + + case 'j': + FLIP(show_jfs); + jfs_load(show_jfs); + wclear(padjfs); + break; + case 'k': + FLIP(show_kernel); + wclear(padker); + break; + case 'l': + FLIP(show_longterm); + wclear(padlong); + break; + case 'L': + FLIP(show_large); + wclear(padlarge); + break; + case 'm': + FLIP(show_memory); + wclear(padmem); + break; + case 'M': + show_mhz++; + if (show_mhz == 4) + show_mhz = 0; + wclear(padmhz); + break; + case 'n': + if (show_net) { + show_net = 0; + show_neterror = 0; + } else { + show_net = 1; + show_neterror = 3; + } + wclear(padnet); + break; + case 'N': + if (show_nfs == 0) + show_nfs = 1; + else if (show_nfs == 1) + show_nfs = 2; + else if (show_nfs == 2) + show_nfs = 3; + else if (show_nfs == 3) + show_nfs = 0; + nfs_clear = 1; + wclear(padnfs); + break; + case 'o': + FLIP(show_diskmap); + wclear(padmap); + break; +#ifdef POWER + case 'p': + FLIP(show_lpar); + wclear(padlpar); + break; +#endif + case 'r': + FLIP(show_res); + wclear(padres); + break; + case 't': + show_topmode = 3; /* Fall Through */ + case 'T': + FLIP(show_top); + wclear(padtop); + break; + case 'v': + FLIP(show_verbose); + wclear(padverb); + break; + case 'u': + if (show_args == ARGS_NONE) { + args_load(); + show_args = ARGS_ONLY; + show_top = 1; + if (show_topmode != 3 && + show_topmode != 4 && show_topmode != 5) + show_topmode = 3; + } else + show_args = ARGS_NONE; + wclear(padtop); + break; + case 'U': + FLIP(show_util); + wclear(padutil); + break; + case 'V': + FLIP(show_vm); + wclear(padpage); + break; + case 'x': + case 'q': + nocbreak(); + endwin(); + exit(0); + default: + return 0; + } + } + return 1; + } + } + return 0; +} + +void go_background(int def_loops, int def_secs) +{ + cursed = 0; + if (maxloops == -1) + maxloops = def_loops; + if (seconds == -1) + seconds = def_secs; + show_res = 1; + show_smp = 1; + show_disk = SHOW_DISK_STATS; + show_jfs = 1; + show_memory = 1; + show_large = 1; + show_kernel = 1; + show_net = 1; + show_all = 1; + show_top = 0; /* top process */ + show_topmode = 3; + show_lpar = 1; + show_vm = 1; +} + +void proc_net() +{ + static FILE *fp = (FILE *) - 1; + char buf[1024]; + int i = 0; + int ret; + unsigned long junk; + + if (fp == (FILE *) - 1) { + if ((fp = fopen("/proc/net/dev", "r")) == NULL) { + error("failed to open - /proc/net/dev"); + networks = 0; + return; + } + } + if (fgets(buf, 1024, fp) == NULL) + goto end; /* throw away the header lines */ + if (fgets(buf, 1024, fp) == NULL) + goto end; /* throw away the header lines */ +/* +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed + lo: 1956 30 0 0 0 0 0 0 1956 30 0 0 0 0 0 0 + eth0: 0 0 0 0 0 0 0 0 458718 0 781 0 0 0 781 0 + sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + eth1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +*/ + for (i = 0; i < NETMAX; i++) { + if (fgets(buf, 1024, fp) == NULL) + break; + strip_spaces(buf); + /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 */ + ret = + sscanf(&buf[0], + "%s %llu %llu %lu %lu %lu %lu %lu %lu %llu %llu %lu %lu %lu %lu %lu", + (char *) &p->ifnets[i].if_name, &p->ifnets[i].if_ibytes, + &p->ifnets[i].if_ipackets, &p->ifnets[i].if_ierrs, + &p->ifnets[i].if_idrop, &p->ifnets[i].if_ififo, + &p->ifnets[i].if_iframe, &junk, &junk, + &p->ifnets[i].if_obytes, &p->ifnets[i].if_opackets, + &p->ifnets[i].if_oerrs, &p->ifnets[i].if_odrop, + &p->ifnets[i].if_ofifo, &p->ifnets[i].if_ocolls, + &p->ifnets[i].if_ocarrier); + if (ret != 16) + fprintf(stderr, "sscanf wanted 16 returned = %d line=%s\n", + ret, (char *) buf); + } + end: + if (reread) { + fclose(fp); + fp = (FILE *) - 1; + } else + rewind(fp); + networks = i; +} + + +int proc_procsinfo(int pid, int index) +{ + FILE *fp; + char filename[64]; + char buf[1024 * 4]; + int size = 0; + int ret = 0; + int count = 0; + int i; + + sprintf(filename, "/proc/%d/stat", pid); + if ((fp = fopen(filename, "r")) == NULL) { + sprintf(buf, "failed to open file %s", filename); + error(buf); + return 0; + } + size = fread(buf, 1, 1024 - 1, fp); + fclose(fp); + if (size == -1) { +#ifdef DEBUG + fprintf(stderr, + "procsinfo read returned = %d assuming process stopped pid=%d\n", + ret, pid); +#endif /*DEBUG*/ + return 0; + } + ret = sscanf(buf, "%d (%s)", + &p->procs[index].pi_pid, &p->procs[index].pi_comm[0]); + if (ret != 2) { + fprintf(stderr, "procsinfo sscanf returned = %d line=%s\n", ret, + buf); + return 0; + } + p->procs[index].pi_comm[strlen(p->procs[index].pi_comm) - 1] = 0; + + for (count = 0; count < size; count++) /* now look for ") " as dumb Infiniban driver includes "()" */ + if (buf[count] == ')' && buf[count + 1] == ' ') + break; + + if (count == size) { +#ifdef DEBUG + fprintf(stderr, "procsinfo failed to find end of command buf=%s\n", + buf); +#endif /*DEBUG*/ + return 0; + } + count++; + count++; + + ret = sscanf(&buf[count], +#ifndef KERNEL_2_6_18 + "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d", +#else + "%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %d %d %lu %lu %llu", +#endif + &p->procs[index].pi_state, + &p->procs[index].pi_ppid, + &p->procs[index].pi_pgrp, + &p->procs[index].pi_session, + &p->procs[index].pi_tty_nr, + &p->procs[index].pi_tty_pgrp, + &p->procs[index].pi_flags, + &p->procs[index].pi_minflt, + &p->procs[index].pi_cmin_flt, + &p->procs[index].pi_majflt, + &p->procs[index].pi_cmaj_flt, + &p->procs[index].pi_utime, + &p->procs[index].pi_stime, + &p->procs[index].pi_cutime, + &p->procs[index].pi_cstime, + &p->procs[index].pi_pri, &p->procs[index].pi_nice, +#ifndef KERNEL_2_6_18 + &p->procs[index].junk, +#else + &p->procs[index].pi_num_threads, +#endif + &p->procs[index].pi_it_real_value, + &p->procs[index].pi_start_time, + &p->procs[index].pi_vsize, + &p->procs[index].pi_rss, + &p->procs[index].pi_rlim_cur, + &p->procs[index].pi_start_code, + &p->procs[index].pi_end_code, + &p->procs[index].pi_start_stack, + &p->procs[index].pi_esp, + &p->procs[index].pi_eip, + &p->procs[index].pi_pending_signal, + &p->procs[index].pi_blocked_sig, + &p->procs[index].pi_sigign, + &p->procs[index].pi_sigcatch, + &p->procs[index].pi_wchan, + &p->procs[index].pi_nswap, + &p->procs[index].pi_cnswap, + &p->procs[index].pi_exit_signal, &p->procs[index].pi_cpu +#ifdef KERNEL_2_6_18 + , + &p->procs[index].pi_rt_priority, + &p->procs[index].pi_policy, + &p->procs[index].pi_delayacct_blkio_ticks +#endif + ); +#ifndef KERNEL_2_6_18 + if (ret != 37) { + fprintf(stderr, + "procsinfo2 sscanf wanted 37 returned = %d pid=%d line=%s\n", + ret, pid, buf); +#else + if (ret != 40) { + fprintf(stderr, + "procsinfo2 sscanf wanted 40 returned = %d pid=%d line=%s\n", + ret, pid, buf); +#endif + return 0; + } + + sprintf(filename, "/proc/%d/statm", pid); + if ((fp = fopen(filename, "r")) == NULL) { + sprintf(buf, "failed to open file %s", filename); + error(buf); + return 0; + } + size = fread(buf, 1, 1024 * 4 - 1, fp); + fclose(fp); /* close it even if the read failed, the file could have been removed + between open & read i.e. the device driver does not behave like a file */ + if (size == -1) { + sprintf(buf, "failed to read file %s", filename); + error(buf); + return 0; + } + + ret = sscanf(&buf[0], "%lu %lu %lu %lu %lu %lu %lu", + &p->procs[index].statm_size, + &p->procs[index].statm_resident, + &p->procs[index].statm_share, + &p->procs[index].statm_trs, + &p->procs[index].statm_lrs, + &p->procs[index].statm_drs, &p->procs[index].statm_dt); + if (ret != 7) { + fprintf(stderr, "sscanf wanted 7 returned = %d line=%s\n", ret, + buf); + return 0; + } + if (isroot) { + p->procs[index].read_io = 0; + p->procs[index].write_io = 0; + sprintf(filename, "/proc/%d/io", pid); + if ((fp = fopen(filename, "r")) != NULL) { + for (i = 0; i < 6; i++) { + if (fgets(buf, 1024, fp) == NULL) { + break; + } + if (strncmp("read_bytes:", buf, 11) == 0) + sscanf(&buf[12], "%lld", &p->procs[index].read_io); + if (strncmp("write_bytes:", buf, 12) == 0) + sscanf(&buf[13], "%lld", &p->procs[index].write_io); + } + } + + if (fp != NULL) + fclose(fp); + } + return 1; +} + +#ifdef DEBUGPROC +print_procs(int index) +{ + printf("procs[%d].pid =%d\n", index, procs[index].pi_pid); + printf("procs[%d].comm[0] =%s\n", index, + &procs[index].pi_comm[0]); + printf("procs[%d].state =%c\n", index, procs[index].pi_state); + printf("procs[%d].ppid =%d\n", index, procs[index].pi_ppid); + printf("procs[%d].pgrp =%d\n", index, procs[index].pi_pgrp); + printf("procs[%d].session =%d\n", index, + procs[index].pi_session); + printf("procs[%d].tty_nr =%d\n", index, procs[index].pi_tty_nr); + printf("procs[%d].tty_pgrp =%d\n", index, + procs[index].pi_tty_pgrp); + printf("procs[%d].flags =%lu\n", index, procs[index].pi_flags); + printf("procs[%d].minflt =%lu\n", index, procs[index].pi_minflt); + printf("procs[%d].cmin_flt =%lu\n", index, + procs[index].pi_cmin_flt); + printf("procs[%d].majflt =%lu\n", index, procs[index].pi_majflt); + printf("procs[%d].cmaj_flt =%lu\n", index, + procs[index].pi_cmaj_flt); + printf("procs[%d].utime =%lu\n", index, procs[index].pi_utime); + printf("procs[%d].stime =%lu\n", index, procs[index].pi_stime); + printf("procs[%d].cutime =%ld\n", index, procs[index].pi_cutime); + printf("procs[%d].cstime =%ld\n", index, procs[index].pi_cstime); + printf("procs[%d].pri =%d\n", index, procs[index].pi_pri); + printf("procs[%d].nice =%d\n", index, procs[index].pi_nice); +#ifndef KERNEL_2_6_18 + printf("procs[%d].junk =%d\n", index, procs[index].junk); +#else + printf("procs[%d].num_threads =%ld\n", index, + procs[index].num_threads); +#endif + printf("procs[%d].it_real_value =%lu\n", index, + procs[index].pi_it_real_value); + printf("procs[%d].start_time =%lu\n", index, + procs[index].pi_start_time); + printf("procs[%d].vsize =%lu\n", index, procs[index].pi_vsize); + printf("procs[%d].rss =%lu\n", index, procs[index].pi_rss); + printf("procs[%d].rlim_cur =%lu\n", index, + procs[index].pi_rlim_cur); + printf("procs[%d].start_code =%lu\n", index, + procs[index].pi_start_code); + printf("procs[%d].end_code =%lu\n", index, + procs[index].pi_end_code); + printf("procs[%d].start_stack =%lu\n", index, + procs[index].pi_start_stack); + printf("procs[%d].esp =%lu\n", index, procs[index].pi_esp); + printf("procs[%d].eip =%lu\n", index, procs[index].pi_eip); + printf("procs[%d].pending_signal=%lu\n", index, + procs[index].pi_pending_signal); + printf("procs[%d].blocked_sig =%lu\n", index, + procs[index].pi_blocked_sig); + printf("procs[%d].sigign =%lu\n", index, + procs[index].pi_sigign); + printf("procs[%d].sigcatch =%lu\n", index, + procs[index].pi_sigcatch); + printf("procs[%d].wchan =%lu\n", index, procs[index].pi_wchan); + printf("procs[%d].nswap =%lu\n", index, procs[index].pi_nswap); + printf("procs[%d].cnswap =%lu\n", index, + procs[index].pi_cnswap); + printf("procs[%d].exit_signal =%d\n", index, + procs[index].pi_exit_signal); + printf("procs[%d].cpu =%d\n", index, procs[index].pi_cpu); +#ifdef KERNEL_2_6_18 + printf("procs[%d].rt_priority =%lu\n", index, + procs[index].pi_rt_priority); + printf("procs[%d].policy =%lu\n", index, + procs[index].pi_policy); + printf("procs[%d].delayacct_blkio_ticks=%llu\n", index, + procs[index].pi_delayacct_blkio_ticks); +#endif + printf("OK\n"); +} +#endif /*DEBUG*/ +/* --- */ +int isnumbers(char *s) +{ + while (*s != 0) { + if (*s < '0' || *s > '9') + return 0; + s++; + } + return 1; +} + +int getprocs(int records) +{ + struct dirent *dent; + DIR *procdir; + int count = 0; + + if ((char *) (procdir = opendir("/proc")) == NULL) { + printf("opendir(/proc) failed"); + return 0; + } + while ((char *) (dent = readdir(procdir)) != NULL) { + if (dent->d_type == 4) { /* is this a directlory */ + /* mainframes report 0 = unknown every time !!!! */ + if (isnumbers(dent->d_name)) { + if (records != 0) { + /* getting the details mode */ + count = count + proc_procsinfo(atoi(dent->d_name), count); + if(count == records) { + break; + } + } else { + /* just counting the processes mode */ + count++; + } + } + } + } + closedir(procdir); + return count; +} + +/* --- */ + +char cpu_line[] = + "---------------------------+-------------------------------------------------+"; +/* Start process as specified in cmd in a child process without waiting + * for completion + * not sure if want to prevent this funcitonality for root user + * when: CHLD_START, CHLD_SNAP or CHLD_END + * cmd: pointer to command string - assumed to be cleansed .... + * timestamp_type: 0 - T%04d, 1 - detailed time stamp + * loop: loop id (0 for CHLD_START) + * the_time: time to use for timestamp generation + */ +void child_start(int when, + char *cmd, int timestamp_type, int loop, time_t the_time) +{ + int i; + pid_t child_pid; + char time_stamp_str[20] = ""; + char *when_info = ""; + struct tm *tim; /* used to work out the hour/min/second */ + +#ifdef DEBUG2 + fprintf(fp, "child start when=%d cmd=%s time=%d loop=%d\n", when, cmd, + timestamp_type, loop); +#endif + /* Validate parameter and initialize error text */ + switch (when) { + case CHLD_START: + when_info = "nmon fork exec failure CHLD_START"; + break; + case CHLD_END: + when_info = "nmon fork exec failure CHLD_END"; + break; + + case CHLD_SNAP: + /* check if old child has finished - otherwise we do nothing */ + if (nmon_children[CHLD_SNAP] != -1) { + if (!cursed) + fprintf(fp, + "ERROR,T%04d, Starting snap command \"%s\" failed as previous child still running - killing it now\n", + loop, cmd); + kill(nmon_children[CHLD_SNAP], 9); + } + + when_info = "nmon fork exec failure CHLD_SNAP"; + break; + } + + + /* now fork off a child process. */ + switch (child_pid = fork()) { + case -1: /* fork failed. */ + perror(when_info); + return; + + case 0: /* inside child process. */ + /* create requested timestamp */ + if (timestamp_type == 1) { + tim = localtime(&the_time); + sprintf(time_stamp_str, "%02d:%02d:%02d,%02d,%02d,%04d", + tim->tm_hour, tim->tm_min, tim->tm_sec, + tim->tm_mday, tim->tm_mon + 1, tim->tm_year + 1900); + } else { + sprintf(time_stamp_str, "T%04d", loop); + } + + /* close all open file pointers except the defaults */ + for (i = 3; i < 5; ++i) + close(i); + + /* Now switch to the defined command */ + execlp(cmd, cmd, time_stamp_str, (void *) 0); + + /* If we get here the specified command could not be started */ + perror(when_info); + exit(1); /* We can't do anything more */ + /* never reached */ + + default: /* inside parent process. */ + /* In father - remember child pid for future */ + nmon_children[when] = child_pid; + } +} + +int main(int argc, char **argv) +{ + int secs; + int cpu_idle; + int cpu_user; + int cpu_sys; + int cpu_wait; + int cpu_steal; + int current_procs = 0; + int adjusted_procs = 0; + int n = 0; /* reusable counters */ + int i = 0; + int j = 0; + int k = 0; + int ret = 0; + int max_sorted; + int skipped; + int x = 0; /* curses row */ + int y = 0; /* curses column */ + double elapsed; /* actual seconds between screen updates */ + double cpu_sum; + double ftmp; + int top_first_time = 1; + int disk_first_time = 1; + int nfs_first_time = 1; + int vm_first_time = 1; + int bbbr_line = 0; + double cpu_busy; +#ifdef POWER + int lpar_first_time = 1; +#endif /* POWER */ + int smp_first_time = 1; + int wide_first_time = 1; + int proc_first_time = 1; + int first_key_pressed = 0; + pid_t childpid = -1; + int ralfmode = 0; + char pgrp[32]; + struct tm *tim; /* used to work out the hour/min/second */ + float total_busy; /* general totals */ + float total_rbytes; /* general totals */ + float total_wbytes; + float total_xfers; + struct utsname uts; /* UNIX name, version, etc */ + double top_disk_busy = 0.0; + char *top_disk_name = ""; + int disk_mb; + double disk_total; + double disk_busy; + double disk_read; + double disk_read_tmp; + double disk_write; + double disk_write_tmp; + double disk_size; + double disk_xfers; + double total_disk_read; + double total_disk_write; + double total_disk_xfers; + double readers; + double writers; + + /* for popen on oslevel */ + char str[512]; + char *str_p; + int varperftmp = 0; + char *formatstring; + char user_filename[512]; + char user_filename_set = 0; + char using_stdout = 0; + struct statfs statfs_buffer; + float fs_size; + float fs_bsize; + float fs_free; + float fs_size_used; + char cmdstr[256]; + long updays, uphours, upmins; + float v2c_total; + float v2s_total; + float v3c_total; + float v3s_total; + float v4c_total; + float v4s_total; + int errors = 0; + + char *nmon_start = (char *) NULL; + char *nmon_end = (char *) NULL; + char *nmon_snap = (char *) NULL; + char *nmon_tmp = (char *) NULL; + int nmon_one_in = 1; + /* Flag what kind of time stamp we give to started children + * 0: "T%04d" + * 1: "hh:mm:ss,dd,mm,yyyy" + */ + int time_stamp_type = 0; + long ticks = 100; /* Clock ticks per second used in /proc/stat cpu lines */ + unsigned long pagesize = 1024 * 4; /* Default page size is 4 KB but newer servers compiled with 64 KB pages */ + float average; + struct timeval nmon_tv; /* below is used to workout the nmon run, accumalate it and the + allow for in in the sleep time to reduce time drift */ + double nmon_start_time = 0.0; + double nmon_end_time = 0.0; + double nmon_run_time = -1.0; + int seconds_over = 0; + float mhz; + float min_mhz; + float max_mhz; + float avg_mhz = 0.0; + + +#define MAXROWS 256 +#define MAXCOLS 150 /* changed to allow maximum column widths */ +#define BANNER(pad,string) {mvwhline(pad, 0, 0, ACS_HLINE,COLS-2); \ + wmove(pad,0,0); \ + wattron(pad,A_STANDOUT); \ + wprintw(pad," "); \ + wprintw(pad,string); \ + wprintw(pad," "); \ + wattroff(pad,A_STANDOUT); } + +#define DISPLAY(pad,rows) { \ + if(x+2+(rows)>LINES)\ + pnoutrefresh(pad, 0,0,x,1,LINES-2, COLS-2); \ + else \ + pnoutrefresh(pad, 0,0,x,1,x+rows+1,COLS-2); \ + x=x+(rows); \ + if(x+4>LINES) { \ + mvwprintw(stdscr,LINES-1,10,"Warning: Some Statistics may not shown"); \ + } \ + } + + /* check the user supplied options */ + progname = argv[0]; + for (i = (int) strlen(progname) - 1; i > 0; i--) + if (progname[i] == '/') { + progname = &progname[i + 1]; + } + + if (getenv("NMONDEBUG") != NULL) + debug = 1; + if (getenv("NMONERROR") != NULL) + error_on = 1; + if (getenv("NMONBUG1") != NULL) + reread = 1; + +/* External Data Collector Controls */ + if ((nmon_start = getenv("NMON_START")) != NULL) { + nmon_start = check_call_string(nmon_start, "NMON_START"); + } + if ((nmon_end = getenv("NMON_END")) != NULL) { + nmon_end = check_call_string(nmon_end, "NMON_END"); + } + if ((nmon_tmp = getenv("NMON_ONE_IN")) != NULL) { + nmon_one_in = atoi(nmon_tmp); + if (errno != 0) { + fprintf(stderr, + "ERROR nmon: invalid NMON_ONE_IN shell variable\n"); + nmon_one_in = 1; + } + } + if ((nmon_snap = getenv("NMON_SNAP")) != NULL) { + nmon_snap = check_call_string(nmon_snap, "NMON_SNAP"); + } + if ((nmon_tmp = getenv("NMON_TIMESTAMP")) != NULL) { + time_stamp_type = atoi(nmon_tmp); + if (time_stamp_type != 0 && time_stamp_type != 1) + time_stamp_type = 1; + } +#ifdef DEBUG2 + printf("NMON_START=%s.\n", nmon_start); + printf("NMON_END=%s.\n", nmon_end); + printf("NMON_SNAP=%s.\n", nmon_snap); + printf("ONE_IN=%d.\n", nmon_one_in); + printf("TIMESTAMP=%d.\n", time_stamp_type); +#endif + +#ifdef REREAD + reread = 1; +#endif + for (i = 0; i < CMDMAX; i++) { + sprintf(cmdstr, "NMONCMD%d", i); + cmdlist[i] = getenv(cmdstr); + if (cmdlist[i] != 0) + cmdfound = i + 1; + } + /* Setup long and short Hostname */ + gethostname(hostname, sizeof(hostname)); + strcpy(fullhostname, hostname); + for (i = 0; i < sizeof(hostname); i++) + if (hostname[i] == '.') + hostname[i] = 0; + if (run_name_set == 0) + strcpy(run_name, hostname); + + if (getuid() == 0) + isroot = 1; + + /* Check the version of OS */ + uname(&uts); + /* Get the clock ticks persecond for CPU counters in /proc/stat cpu stats */ + ticks = sysconf(_SC_CLK_TCK); + if (ticks == -1 || ticks == 0) + ticks = 100; + /* Check if we have the large 64 KB memory page sizes compiled into the kernel */ + if (sysconf(_SC_PAGESIZE) > 1024 * 4) + pagesize = sysconf(_SC_PAGESIZE); + proc_init(); + + while (-1 != + (i = + getopt(argc, argv, + "?abc:C:Dd:EfF:g:hI:l:m:MNpr:Rs:tTUVxXz"))) { + switch (i) { + case '?': + hint(); + exit(0); + case 'a': /* Acelerator */ + case 'E': /* Emily */ + show_gpu = 1; + break; + case 'b': + colour = 0; + break; + case 'c': + maxloops = atoi(optarg); + break; + case 'C': /* commandlist argument */ + cmdlist[0] = MALLOC(strlen(optarg) + 1); /* create buffer */ + strcpy(cmdlist[0], optarg); + if (cmdlist[0][0] != 0) + cmdfound = 1; + for (i = 0, j = 1; cmdlist[0][i] != 0; i++) { + if (cmdlist[0][i] == ':') { + cmdlist[0][i] = 0; + cmdlist[j] = &cmdlist[0][i + 1]; + j++; + cmdfound = j; + if (j >= CMDMAX) + break; + } + } + break; + case 'd': + diskmax = atoi(optarg); + if (diskmax < DISKMIN) { + printf + ("nmon: ignoring -d %d option as the minimum is %d\n", + diskmax, DISKMIN); + diskmax = DISKMIN; + } + break; + case 'D': + extended_disk = 1; + break; + case 'F': /* background mode with user supplied filename */ + strcpy(user_filename, optarg); + user_filename_set++; + go_background(288, 300); + break; + case 'f': /* background mode i.e. for spread sheet output */ + go_background(288, 300); + break; + case 'g': /* disk groups */ + show_dgroup = 1; + dgroup_loaded = 1; + dgroup_filename = optarg; + if (strncmp("auto", dgroup_filename, 5) == 0) { + auto_dgroup++; + printf + ("Generating disk group file from lsblk output to file: \"auto\"\n"); +#ifdef SLES113 +#define LSBLK_NO_TYPE /* define this to work around missing --output TYPE feature */ +#endif /* SLES113 */ + +#ifdef LSBLK_NO_TYPE + ret = + system + ("lsblk --nodeps --output NAME --noheadings | awk 'BEGIN {printf \"# This file created by: nmon -g auto\\n# It is an automatically generated disk-group file which excluses disk paritions\\n\" } { printf \"%s %s\\n\", $1, $1 }' >auto"); +#else + ret = + system + ("lsblk --nodeps --output NAME,TYPE --raw | grep disk | awk 'BEGIN {printf \"# This file created by: nmon -g auto\\n# It is an automatically generated disk-group file which excluses disk paritions\\n\" } { printf \"%s %s\\n\", $1, $1 }' >auto"); +#endif /* LSBLK_NO_TYPE */ + if (ret != 0) { + printf("Create auto file command was: %s\n", + "lsblk --nodeps --output NAME,TYPE --raw | grep disk | awk '{ printf \"%s %s\\n\", $1, $1 }' >auto"); + printf("Creating auto file returned a status of %d\n", + ret); + } + } + break; + case 'h': + help(); + break; + case 'I': + ignore_procdisk_threshold = atof(optarg); + break; + case 'l': + disks_per_line = atoi(optarg); + if (disks_per_line < 3 || disks_per_line > 250) + disks_per_line = 100; + break; + case 'm': + if (chdir(optarg) == -1) { + perror("changing directory failed"); + printf("Directory attempted was:%s\n", optarg); + exit(993); + } + break; + case 'M': /* MHz */ + show_mhz = 1; + break; + case 'N': + show_nfs = 1; + break; + case 'p': + ralfmode = 1; + break; + case 'R': + show_rrd = 1; + go_background(288, 300); + show_aaa = 0; + show_para = 0; + show_headings = 0; + break; + case 'r': + strcpy(run_name, optarg); + run_name_set++; + break; + case 's': + seconds = atoi(optarg); + break; + case 'T': + show_args = ARGS_ONLY; /* drop through */ + case 't': + show_top = 1; /* put top process output in spreadsheet mode */ + show_topmode = 3; + break; + case 'U': + show_util = 1; + break; + case 'V': /* nmon version */ + printf("nmon version %s\n", VERSION); + exit(0); + break; + case 'x': /* background mode for 1 day capacity planning */ + go_background(4 * 24, 15 * 60); + show_top = 1; + show_topmode = 3; + break; + case 'X': /* background mode for 1 hour capacity planning */ + go_background(120, 30); + show_top = 1; + show_topmode = 3; + break; + case 'z': /* background mode for 1 day output to /var/perf/tmp */ + varperftmp++; + go_background(4 * 24, 15 * 60); + break; + } + } + /* Set parameters if not set by above */ + if (maxloops == -1) + maxloops = 9999999; + if (seconds == -1) + seconds = 2; + if (cursed) + show_dgroup = 0; + + /* -D need -g filename */ + if (extended_disk == 1 && show_dgroup == 0) { + printf + ("nmon: ignoring -D (extended disk stats) as -g filename is missing\n"); + extended_disk = 0; + } +#ifdef NVIDIA_GPU + if (cursed) { + gpu_init(); + } +#endif /* NVIDIA_GPU */ + + /* To get the pointers setup */ + switcher(); + + /* Initialise the time stamps for the first loop */ + p->time = doubletime(); + q->time = doubletime(); + + find_release(); + + /* Determine number of active LOGICAL cpu - depends on SMT mode ! */ + get_cpu_cnt(); + max_cpus = old_cpus = cpus; +#if X86 || ARM + get_intel_spec(); +#endif + proc_read(P_STAT); + proc_cpu(); + proc_read(P_UPTIME); + proc_read(P_LOADAVG); + proc_kernel(); + memcpy(&q->cpu_total, &p->cpu_total, sizeof(struct cpu_stat)); + + p->dk = MALLOC(sizeof(struct dsk_stat) * diskmax + 1); + q->dk = MALLOC(sizeof(struct dsk_stat) * diskmax + 1); + disk_busy_peak = MALLOC(sizeof(double) * diskmax); + disk_rate_peak = MALLOC(sizeof(double) * diskmax); + for (i = 0; i < diskmax; i++) { + disk_busy_peak[i] = 0.0; + disk_rate_peak[i] = 0.0; + } + + cpu_peak = MALLOC(sizeof(double) * (CPUMAX + 1)); /* MAGIC */ + for (i = 0; i < max_cpus + 1; i++) + cpu_peak[i] = 0.0; + + current_procs = getprocs(0); + adjusted_procs = current_procs + 128; /*allows for more processes */ + p->procs = MALLOC(sizeof(struct procsinfo) * adjusted_procs); + q->procs = MALLOC(sizeof(struct procsinfo) * adjusted_procs); + p->proc_records = adjusted_procs; + q->proc_records = adjusted_procs; + p->processes = 0; + q->processes = 0; + + /* Initialise the top processes table */ + topper_size = n; + topper = MALLOC(sizeof(struct topper) * topper_size); /* round up */ + + /* Get Disk Stats. */ + proc_disk(0.0); + memcpy(q->dk, p->dk, sizeof(struct dsk_stat) * disks); + + /* load dgroup - if required */ + if (dgroup_loaded == 1) { + load_dgroup(p->dk); + } + + /* Get Network Stats. */ + proc_net(); + memcpy(q->ifnets, p->ifnets, sizeof(struct net_stat) * networks); + for (i = 0; i < networks; i++) { + net_read_peak[i] = 0.0; + net_write_peak[i] = 0.0; + } + + /* If we are running in spreadsheet mode initialize all other data sets as well + * so we do not get incorrect data for the first reported interval + */ + if (!cursed) { + /* Get VM Stats */ + read_vmstat(); + + /* Get Memory info */ + proc_mem(); + +#ifdef POWER + /* Get LPAR Stats */ + proc_lparcfg(); +#endif + } + /* Set the pointer ready for the next round */ + switcher(); + + /* Initialise signal handlers so we can tidy up curses on exit */ + signal(SIGUSR1, interrupt); + signal(SIGUSR2, interrupt); + signal(SIGINT, interrupt); + signal(SIGWINCH, interrupt); + signal(SIGCHLD, interrupt); + + /* Start Curses */ + if (cursed) { + initscr(); + cbreak(); + move(0, 0); + refresh(); + COLOUR colour = has_colors(); + COLOUR start_color(); + COLOUR init_pairs(); + clear(); +#ifdef POWER + padlpar = newpad(11, MAXCOLS); +#endif + padwelcome = newpad(24, MAXCOLS); + padmap = newpad(24, MAXCOLS); + padhelp = newpad(24, MAXCOLS); + padmem = newpad(20, MAXCOLS); + padlarge = newpad(20, MAXCOLS); + padpage = newpad(20, MAXCOLS); + padres = newpad(20, MAXCOLS); + padsmp = newpad(MAXROWS, MAXCOLS); + padutil = newpad(MAXROWS, MAXCOLS); + padlong = newpad(MAXROWS, MAXCOLS); + padwide = newpad(MAXROWS, MAXCOLS); + padmhz = newpad(24, MAXCOLS); + padgpu = newpad(10, MAXCOLS); + padnet = newpad(MAXROWS, MAXCOLS); + padneterr = newpad(MAXROWS, MAXCOLS); + paddisk = newpad(MAXROWS, MAXCOLS); + paddg = newpad(MAXROWS, MAXCOLS); + padjfs = newpad(MAXROWS, MAXCOLS); + padker = newpad(12, MAXCOLS); + padverb = newpad(8, MAXCOLS); + padnfs = newpad(25, MAXCOLS); + padtop = newpad(MAXROWS, MAXCOLS * 2); + + + } else { + /* Output the header lines for the spread sheet */ + timer = time(0); + tim = localtime(&timer); + tim->tm_year += 1900 - 2000; /* read localtime() manual page!! */ + tim->tm_mon += 1; /* because it is 0 to 11 */ + if (varperftmp) + sprintf(str, "/var/perf/tmp/%s_%02d.nmon", hostname, + tim->tm_mday); + else if (user_filename_set) + strcpy(str, user_filename); + else + sprintf(str, "%s_%02d%02d%02d_%02d%02d.nmon", + hostname, + tim->tm_year, + tim->tm_mon, tim->tm_mday, tim->tm_hour, tim->tm_min); + if (!strncmp(str, "stdout", 6)) { + using_stdout = 1; + if ((fp = fdopen(1, "w")) == 0) { + perror("nmon: failed to open standard output"); + exit(41); + } + } else { + if ((fp = fopen(str, "w")) == 0) { + perror("nmon: failed to open output file"); + printf("nmon: output filename=%s\n", str); + exit(42); + } + } + /* disconnect from terminal */ + fflush(NULL); + if (!debug && (childpid = fork()) != 0) { + if (ralfmode) + printf("%d\n", childpid); + exit(0); /* parent returns OK */ + } + if (!debug) { + close(0); + if(using_stdout == 0) + close(1); + close(2); + setpgrp(); /* become process group leader */ + signal(SIGHUP, SIG_IGN); /* ignore hangups */ + } + /* Do the nmon_start activity early on */ + if (nmon_start) { + timer = time(0); + child_start(CHLD_START, nmon_start, time_stamp_type, 1, timer); + } + + if (show_aaa) { + fprintf(fp, "AAA,progname,%s\n", progname); + fprintf(fp, "AAA,command,"); + for (i = 0; i < argc; i++) + fprintf(fp, "%s ", argv[i]); + fprintf(fp, "\n"); + fprintf(fp, "AAA,version,%s\n", VERSION); + fprintf(fp, "AAA,disks_per_line,%d\n", disks_per_line); + fprintf(fp, "AAA,max_disks,%d,set by -d option\n", diskmax); + fprintf(fp, "AAA,disks,%d,\n", disks); + + fprintf(fp, "AAA,host,%s\n", hostname); + fprintf(fp, "AAA,user,%s\n", getenv("USER")); + fprintf(fp, "AAA,OS,Linux,%s,%s,%s\n", uts.release, + uts.version, uts.machine); + fprintf(fp, "AAA,runname,%s\n", run_name); + fprintf(fp, "AAA,time,%02d:%02d.%02d\n", tim->tm_hour, + tim->tm_min, tim->tm_sec); + fprintf(fp, "AAA,date,%02d-%3s-%02d\n", tim->tm_mday, + month[tim->tm_mon - 1], tim->tm_year + 2000); + fprintf(fp, "AAA,interval,%d\n", seconds); + fprintf(fp, "AAA,snapshots,%d\n", maxloops); +#ifdef POWER + fprintf(fp, "AAA,cpus,%d,%d\n", cpus / lparcfg.smt_mode, cpus); /* physical CPU, logical CPU */ + fprintf(fp, "AAA,CPU ID length,3\n"); /* Give analyzer a chance to easily find length of CPU number - 3 digits here! */ +#else + fprintf(fp, "AAA,cpus,%d\n", cpus); +#endif +#ifdef X86 + fprintf(fp, "AAA,x86,VendorId,%s\n", vendor_ptr); + fprintf(fp, "AAA,x86,ModelName,%s\n", model_ptr); + fprintf(fp, "AAA,x86,MHz,%s\n", mhz_ptr); + fprintf(fp, "AAA,x86,bogomips,%s\n", bogo_ptr); + fprintf(fp, "AAA,x86,ProcessorChips,%d\n", processorchips); + fprintf(fp, "AAA,x86,Cores,%d\n", cores); + fprintf(fp, "AAA,x86,hyperthreads,%d\n", hyperthreads); + fprintf(fp, "AAA,x86,VirtualCPUs,%d\n", cpus); +#endif +#ifdef ARM + fprintf(fp, "AAA,ARM,VendorId,%s\n", vendor_ptr); + fprintf(fp, "AAA,ARM,ModelName,%s\n", model_ptr); + fprintf(fp, "AAA,ARM,MHz,%s\n", mhz_ptr); + fprintf(fp, "AAA,ARM,bogomips,%s\n", bogo_ptr); + fprintf(fp, "AAA,ARM,ProcessorChips,%d\n", processorchips); + fprintf(fp, "AAA,ARM,Cores,%d\n", cores); + fprintf(fp, "AAA,ARM,hyperthreads,%d\n", hyperthreads); + fprintf(fp, "AAA,ARM,VirtualCPUs,%d\n", cpus); +#endif + fprintf(fp, "AAA,proc_stat_variables,%d\n", stat8); + fprintf(fp, "AAA,boottime,%s\n", boottime_str); + + fprintf(fp, + "AAA,note0, Warning - use the UNIX sort command to order this file before loading into a spreadsheet\n"); + fprintf(fp, + "AAA,note1, The First Column is simply to get the output sorted in the right order\n"); + fprintf(fp, + "AAA,note2, The T0001-T9999 column is a snapshot number. To work out the actual time; see the ZZZ section at the end\n"); + } + fflush(NULL); + + for (i = 1; i <= cpus; i++) + fprintf(fp, + "CPU%03d,CPU %d %s,User%%,Sys%%,Wait%%,Idle%%,Steal%%\n", + i, i, run_name); + fprintf(fp, + "CPU_ALL,CPU Total %s,User%%,Sys%%,Wait%%,Idle%%,Steal%%,Busy,CPUs\n", + run_name); + if (show_mhz) { + fprintf(fp, "MHZ,Clock Speed (MHz) %s", run_name); + for (i = 1; i <= cpus; i++) + fprintf(fp, ",CPU%03d", i); + fprintf(fp, "\n"); + } + fprintf(fp, + "MEM,Memory MB %s,memtotal,hightotal,lowtotal,swaptotal,memfree,highfree,lowfree,swapfree,memshared,cached,active,bigfree,buffers,swapcached,inactive\n", + run_name); + +#ifdef POWER + proc_lparcfg(); + if (lparcfg.cmo_enabled) + fprintf(fp, + "MEMAMS,AMS %s,Poolid,Weight,Hypervisor-Page-in/s,HypervisorTime(seconds),not_available_1,not_available_2,not_available_3,Physical-Memory(MB),Page-Size(KB),Pool-Size(MB),Loan-Request(KB)\n", + run_name); + +#ifdef EXPERIMENTAL + fprintf(fp, + "MEMEXPERIMENTAL,New lparcfg numbers %s,DesEntCap,DesProcs,DesVarCapWt,DedDonMode,group,pool,entitled_memory,entitled_memory_group_number,unallocated_entitled_memory_weight,unallocated_io_mapping_entitlement\n", + run_name); +#endif /* EXPERIMENTAL */ +#endif /* POWER */ + + fprintf(fp, + "PROC,Processes %s,Runnable,Blocked,pswitch,syscall,read,write,fork,exec,sem,msg\n", + run_name); +/* + fprintf(fp,"PAGE,Paging %s,faults,pgin,pgout,pgsin,pgsout,reclaims,scans,cycles\n", run_name); + fprintf(fp,"FILE,File I/O %s,iget,namei,dirblk,readch,writech,ttyrawch,ttycanch,ttyoutch\n", run_name); +*/ + + + fprintf(fp, "NET,Network I/O %s", run_name); + for (i = 0; i < networks; i++) + fprintf(fp, ",%-2s-read-KB/s", (char *) p->ifnets[i].if_name); + for (i = 0; i < networks; i++) + fprintf(fp, ",%-2s-write-KB/s", (char *) p->ifnets[i].if_name); + fprintf(fp, "\n"); + fprintf(fp, "NETPACKET,Network Packets %s", run_name); + for (i = 0; i < networks; i++) + fprintf(fp, ",%-2s-read/s", (char *) p->ifnets[i].if_name); + for (i = 0; i < networks; i++) + fprintf(fp, ",%-2s-write/s", (char *) p->ifnets[i].if_name); + /* iremoved as it is not below in the BUSY line fprintf(fp,"\n"); */ +#ifdef DEBUG + if (debug) + printf("disks=%d x%sx\n", (char *) disks, p->dk[0].dk_name); +#endif /*DEBUG*/ + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKBUSY%s,Disk %%Busy %s", dskgrp(i), + run_name); + fprintf(fp, ",%s", (char *) p->dk[i].dk_name); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKREAD%s,Disk Read KB/s %s", dskgrp(i), + run_name); + fprintf(fp, ",%s", (char *) p->dk[i].dk_name); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKWRITE%s,Disk Write KB/s %s", + (char *) dskgrp(i), run_name); + fprintf(fp, ",%s", (char *) p->dk[i].dk_name); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKXFER%s,Disk transfers per second %s", + (char *) dskgrp(i), run_name); + fprintf(fp, ",%s", p->dk[i].dk_name); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKBSIZE%s,Disk Block Size %s", dskgrp(i), + run_name); + fprintf(fp, ",%s", (char *) p->dk[i].dk_name); + } + if (extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS) { + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKREADS%s,Disk Rd/s %s", dskgrp(i), + run_name); + fprintf(fp, ",%s", (char *) p->dk[i].dk_name); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, "\nDISKWRITES%s,Disk Wrt/s %s", dskgrp(i), + run_name); + fprintf(fp, ",%s", (char *) p->dk[i].dk_name); + } + } + + fprintf(fp, "\n"); + list_dgroup(p->dk); + jfs_load(LOAD); + fprintf(fp, "JFSFILE,JFS Filespace %%Used %s", hostname); + for (k = 0; k < jfses; k++) { + if (jfs[k].mounted && strncmp(jfs[k].name, "/proc", 5) + && strncmp(jfs[k].name, "/sys", 4) + && strncmp(jfs[k].name, "/run/", 5) + && strncmp(jfs[k].name, "/dev/", 5) + && strncmp(jfs[k].name, "/var/lib/nfs/rpc", 16) + ) /* /proc gives invalid/insane values */ + fprintf(fp, ",%s", jfs[k].name); + } + fprintf(fp, "\n"); + jfs_load(UNLOAD); +#ifdef POWER + if (proc_lparcfg() && lparcfg.shared_processor_mode != 0 + && power_vm_type == VM_POWERVM) { + fprintf(fp, + "LPAR,Shared CPU LPAR Stats %s,PhysicalCPU,capped,shared_processor_mode,system_potential_processors,system_active_processors,pool_capacity,MinEntCap,partition_entitled_capacity,partition_max_entitled_capacity,MinProcs,Logical CPU,partition_active_processors,partition_potential_processors,capacity_weight,unallocated_capacity_weight,BoundThrds,MinMem,unallocated_capacity,pool_idle_time,smt_mode\n", + hostname); + + } +#endif /*POWER*/ + if (show_top) { + fprintf(fp, "TOP,%%CPU Utilisation\n"); +#ifndef KERNEL_2_6_18 + fprintf(fp, + "TOP,+PID,Time,%%CPU,%%Usr,%%Sys,Size,ResSet,ResText,ResData,ShdLib,MinorFault,MajorFault,Command\n"); +#else + fprintf(fp, + "TOP,+PID,Time,%%CPU,%%Usr,%%Sys,Size,ResSet,ResText,ResData,ShdLib,MinorFault,MajorFault,Command,Threads,IOwaitTime\n"); +#endif + } + linux_bbbp("/etc/release", "/bin/cat /etc/*ease 2>/dev/null", + WARNING); + linux_bbbp("lsb_release", "/usr/bin/lsb_release -a 2>/dev/null", + WARNING); + linux_bbbp("fdisk-l", "/sbin/fdisk -l 2>/dev/null", WARNING); + linux_bbbp("lsblk", "/usr/bin/lsblk 2>/dev/null", WARNING); + linux_bbbp("lscpu", "/usr/bin/lscpu 2>/dev/null", WARNING); + linux_bbbp("lshw", "/usr/bin/lshw 2>/dev/null", WARNING); + linux_bbbp("/proc/cpuinfo", "/bin/cat /proc/cpuinfo 2>/dev/null", + WARNING); + linux_bbbp("/proc/meminfo", "/bin/cat /proc/meminfo 2>/dev/null", + WARNING); + linux_bbbp("/proc/stat", "/bin/cat /proc/stat 2>/dev/null", + WARNING); + linux_bbbp("/proc/version", "/bin/cat /proc/version 2>/dev/null", + WARNING); + linux_bbbp("/proc/net/dev", "/bin/cat /proc/net/dev 2>/dev/null", + WARNING); +#ifdef POWER + /* PowerKVM useful information */ + linux_bbbp("/proc/device-tree/host-model", + "/bin/cat /proc/device-tree/host-model 2>/dev/null", WARNING); + linux_bbbp("/proc/device-tree/host-serial", + "/bin/cat /proc/device-tree/host-serial 2>/dev/null", WARNING); + linux_bbbp("/proc/device-tree/ibm,partition-name", + "/bin/cat /proc/device-tree/ibm,partition-name 2>/dev/null", WARNING); + + linux_bbbp("ppc64_utils - lscfg", "/usr/sbin/lscfg 2>/dev/null", WARNING); + linux_bbbp("ppc64_utils - ls-vdev", + "/usr/sbin/ls-vdev 2>/dev/null", WARNING); + linux_bbbp("ppc64_utils - ls-veth", + "/usr/sbin/ls-veth 2>/dev/null", WARNING); + linux_bbbp("ppc64_utils - ls-vscsi", + "/usr/sbin/ls-vscsi 2>/dev/null", WARNING); + linux_bbbp("ppc64_utils - lsmcode", + "/usr/sbin/lsmcode 2>/dev/null", WARNING); + linux_bbbp("ppc64_cpu - smt", + "/usr/sbin/ppc64_cpu --smt 2>/dev/null", WARNING); + linux_bbbp("ppc64_cpu - cores", + "/usr/sbin/ppc64_cpu --cores-present 2>/dev/null", WARNING); + linux_bbbp("ppc64_cpu - DSCR", + "/usr/sbin/ppc64_cpu --dscr 2>/dev/null", WARNING); + linux_bbbp("ppc64_cpu - snooze", + "/usr/sbin/ppc64_cpu --smt-snooze-delay 2>/dev/null", WARNING); + linux_bbbp("ppc64_cpu - run-mode", + "/usr/sbin/ppc64_cpu --run-mode 2>/dev/null", WARNING); + linux_bbbp("ppc64_cpu - frequency", + "/usr/sbin/ppc64_cpu --frequency 2>/dev/null", WARNING); + + linux_bbbp("bootlist -m nmonal -o", + "/usr/sbin/bootlist -m normal -o 2>/dev/null", WARNING); + linux_bbbp("lsslot", "/usr/sbin/lsslot 2>/dev/null", WARNING); + linux_bbbp("lparstat -i", "/usr/sbin/lparstat -i 2>/dev/null", WARNING); + linux_bbbp("lsdevinfo", "/usr/sbin/lsdevinfo 2>/dev/null", WARNING); + linux_bbbp("ls-vdev", "/usr/sbin/ls-vdev 2>/dev/null", WARNING); + linux_bbbp("ls-veth", "/usr/sbin/ls-veth 2>/dev/null", WARNING); + linux_bbbp("ls-vscsi", "/usr/sbin/ls-vscsi 2>/dev/null", WARNING); + +#endif + linux_bbbp("/proc/diskinfo", "/bin/cat /proc/diskinfo 2>/dev/null", + WARNING); + linux_bbbp("/proc/diskstats", + "/bin/cat /proc/diskstats 2>/dev/null", WARNING); + + linux_bbbp("/sbin/multipath", "/sbin/multipath -l 2>/dev/null", + WARNING); + linux_bbbp("/dev/mapper", "ls -l /dev/mapper 2>/dev/null", + WARNING); + linux_bbbp("/dev/mpath", "ls -l /dev/mpath 2>/dev/null", WARNING); + linux_bbbp("/dev/dm-*", "ls -l /dev/dm-* 2>/dev/null", WARNING); + linux_bbbp("/dev/md*", "ls -l /dev/md* 2>/dev/null", WARNING); + linux_bbbp("/dev/sd*", "ls -l /dev/sd* 2>/dev/null", WARNING); + linux_bbbp("/proc/partitions", + "/bin/cat /proc/partitions 2>/dev/null", WARNING); + linux_bbbp("/proc/1/stat", "/bin/cat /proc/1/stat 2>/dev/null", + WARNING); +#ifndef KERNEL_2_6_18 + linux_bbbp("/proc/1/statm", "/bin/cat /proc/1/statm 2>/dev/null", + WARNING); +#endif +#ifdef MAINFRAME + linux_bbbp("/proc/sysinfo", "/bin/cat /proc/sysinfo 2>/dev/null", + WARNING); +#endif + linux_bbbp("/proc/net/rpc/nfs", + "/bin/cat /proc/net/rpc/nfs 2>/dev/null", WARNING); + linux_bbbp("/proc/net/rpc/nfsd", + "/bin/cat /proc/net/rpc/nfsd 2>/dev/null", WARNING); + linux_bbbp("/proc/modules", "/bin/cat /proc/modules 2>/dev/null", + WARNING); + linux_bbbp("ifconfig", "/sbin/ifconfig 2>/dev/null", WARNING); + linux_bbbp("/bin/df-m", "/bin/df -m 2>/dev/null", WARNING); + linux_bbbp("/bin/mount", "/bin/mount 2>/dev/null", WARNING); + linux_bbbp("/etc/fstab", "/bin/cat /etc/fstab 2>/dev/null", + WARNING); + linux_bbbp("netstat -r", "/bin/netstat -r 2>/dev/null", WARNING); + linux_bbbp("uptime", "/usr/bin/uptime 2>/dev/null", WARNING); + linux_bbbp("getconf PAGESIZE", + "/usr/bin/getconf PAGESIZE 2>/dev/null", WARNING); + +#ifdef POWER + linux_bbbp("/proc/ppc64/lparcfg", + "/bin/cat /proc/ppc64/lparcfg 2>/dev/null", WARNING); + linux_bbbp("lscfg-v", "/usr/sbin/lscfg -v 2>/dev/null", WARNING); +#endif + sleep(1); /* to get the first stats to cover this one second and avoids divide by zero issues */ + } + /* To get the pointers setup */ + /* Was already done earlier, DONT'T switch back here to the old pointer! - switcher(); */ + /*checkinput(); */ + clear(); + fflush(NULL); +#ifdef POWER + lparcfg.timebase = -1; +#endif + + /* Main loop of the code */ + for (loop = 1;; loop++) { + /* Save the time and work out how long we were actually asleep + * Do this as early as possible and close to reading the CPU statistics in /proc/stat + */ + p->time = doubletime(); + elapsed = p->time - q->time; + timer = time(0); + tim = localtime(&timer); + + /* Get current count of CPU + * As side effect /proc/stat is read + */ + old_cpus = cpus; + get_cpu_cnt(); +#ifdef POWER + /* Always get lpar info as well so we can report physical CPU usage + * to make data more meaningful. Return value is ignored here, but + * remembered in proc_lparcfg() ! + */ + proc_lparcfg(); +#endif + + if (loop <= 3) /* This stops the nmon causing the cpu peak at startup */ + for (i = 0; i < max_cpus + 1; i++) + cpu_peak[i] = 0.0; + + /* Reset the cursor position to top left */ + y = x = 0; + + if (cursed) { /* Top line */ + box(stdscr, 0, 0); + mvprintw(x, 1, "nmon"); + mvprintw(x, 6, "%s", VERSION); + if (flash_on) + mvprintw(x, 15, "[H for help]"); + mvprintw(x, 30, "Hostname=%s", hostname); + mvprintw(x, 52, "Refresh=%2.0fsecs ", elapsed); + mvprintw(x, 70, "%02d:%02d.%02d", + tim->tm_hour, tim->tm_min, tim->tm_sec); + wnoutrefresh(stdscr); + x = x + 1; + + if (welcome && getenv("NMON") == 0) { + + COLOUR wattrset(padwelcome, COLOR_PAIR(2)); +/* +mvwprintw(padwelcome,x+1, 3, "------------------------------"); +mvwprintw(padwelcome,x+2, 3, "# # # # #### # #"); +mvwprintw(padwelcome,x+3, 3, "## # ## ## # # ## #"); +mvwprintw(padwelcome,x+4, 3, "# # # # ## # # # # # #"); +mvwprintw(padwelcome,x+5, 3, "# # # # # # # # # #"); +mvwprintw(padwelcome,x+6, 3, "# ## # # # # # ##"); +mvwprintw(padwelcome,x+7, 3, "# # # # #### # #"); +mvwprintw(padwelcome,x+8, 3, "------------------------------"); +*/ + mvwprintw(padwelcome, x + 0, 3, + "------------------------------"); + mvwprintw(padwelcome, x + 1, 3, + " _ __ _ __ ___ ___ _ __ "); + mvwprintw(padwelcome, x + 2, 3, + "| '_ \\| '_ ` _ \\ / _ \\| '_ \\ "); + mvwprintw(padwelcome, x + 3, 3, + "| | | | | | | | | (_) | | | | "); + mvwprintw(padwelcome, x + 4, 3, + "|_| |_|_| |_| |_|\\___/|_| |_| "); + mvwprintw(padwelcome, x + 5, 3, + " "); + mvwprintw(padwelcome, x + 6, 3, + "------------------------------"); + + COLOUR wattrset(padwelcome, COLOR_PAIR(0)); + mvwprintw(padwelcome, x + 1, 40, "For help type H or ..."); + mvwprintw(padwelcome, x + 2, 40, " nmon -? - hint"); + mvwprintw(padwelcome, x + 3, 40, + " nmon -h - full details"); + mvwprintw(padwelcome, x + 5, 40, + "To stop nmon type q to Quit"); + COLOUR wattrset(padwelcome, COLOR_PAIR(1)); +#ifdef POWER + get_cpu_cnt(); + proc_read(P_CPUINFO); + + lscpu_init(); + + switch (power_vm_type) { + case VM_POWERKVM_GUEST: + get_cpu_cnt(); +#ifdef RHEL7 + mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], + easy[1]); +#else +#ifdef SLES113 + mvwprintw(padwelcome, x + 8, 3, "%s", easy[2]); +#else + mvwprintw(padwelcome, x + 8, 3, "%s", easy[3]); +#endif /* SLES113 */ +#endif /* RHEL7 */ + mvwprintw(padwelcome, x + 9, 3, "PowerKVM Guest %s", + &proc[P_CPUINFO].line[1][7]); + mvwprintw(padwelcome, x + 10, 3, + "PowerKVM Guest VirtualCPUs=%d LogicalCPUs=%d", + (int) lparcfg.partition_active_processors, + cpus); + mvwprintw(padwelcome, x + 11, 3, + "PowerKVM Guest SMT=%d", lparcfg.smt_mode); + break; + case VM_POWERKVM_HOST: + mvwprintw(padwelcome, x + 8, 3, "%s", easy[0]); + mvwprintw(padwelcome, x + 9, 3, "PowerKVM Host %s", + &proc[P_CPUINFO].line[1][7]); + mvwprintw(padwelcome, x + 10, 3, + "PowerKVM Host owns all %d CPUs & SMT=%d in the Hosting OS", + cpus, lscpu.threads); + mvwprintw(padwelcome, x + 11, 3, "PowerKVM Host %s", + proc[P_CPUINFO].line[proc[P_CPUINFO].lines - + 2]); + break; + case VM_NATIVE: + mvwprintw(padwelcome, x + 8, 3, "%s", easy[0]); + mvwprintw(padwelcome, x + 9, 3, "Native %s", + &proc[P_CPUINFO].line[1][7]); + mvwprintw(padwelcome, x + 10, 3, + "Native owns all %d CPUs & SMT=%d", cpus, + lscpu.threads); + mvwprintw(padwelcome, x + 11, 3, "Native %s", + proc[P_CPUINFO].line[proc[P_CPUINFO].lines - + 2]); + break; + default: + case VM_POWERVM: +#ifdef SLES113 + mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], + easy[2]); +#else +#ifdef RHEL7 + mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], + easy[1]); +#else + mvwprintw(padwelcome, x + 8, 3, "%s", easy[3]); +#endif +#endif + mvwprintw(padwelcome, x + 9, 3, "PowerVM %s %s", + &proc[P_CPUINFO].line[1][7], + &proc[P_CPUINFO].line[proc[P_CPUINFO].lines - + 1][11]); + mvwprintw(padwelcome, x + 10, 3, + "PowerVM Entitlement=%-6.2f VirtualCPUs=%d LogicalCPUs=%d", + (double) lparcfg. + partition_entitled_capacity / 100.0, + (int) lparcfg.partition_active_processors, + cpus); + mvwprintw(padwelcome, x + 11, 3, + "PowerVM SMT=%d Capped=%d", lparcfg.smt_mode, + lparcfg.capped); + break; + } + + mvwprintw(padwelcome, x + 12, 3, + "Processor Clock=%s %s", + &proc[P_CPUINFO].line[2][9], lscpu.byte_order); + +#endif /*POWER*/ +#ifdef MAINFRAME + get_cpu_cnt(); + proc_read(P_CPUINFO); + lscpu_init(); + +#ifdef SLES113 + mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], + easy[2]); +#else +#ifdef RHEL7 + mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], + easy[1]); +#else + mvwprintw(padwelcome, x + 8, 3, "%s", easy[3]); +#endif /*RHEL*/ +#endif /*SLES*/ + + mvwprintw(padwelcome, x + 10, 3, + "Mainframe VM %d CPUs & SMT=%d", + cpus, lscpu.threads); + mvwprintw(padwelcome, x + 11, 3, + "Mainframe VM Arch %s", lscpu.arch); + mvwprintw(padwelcome, x + 12, 3, + "Processor %s", lscpu.byte_order); +#endif /*MAINFRAME */ +#if X86 || ARM + get_cpu_cnt(); + mvwprintw(padwelcome, x + 8, 3, "%s %s", easy[0], easy[2]); + mvwprintw(padwelcome, x + 9, 3, "%s %s", vendor_ptr, + model_ptr); + mvwprintw(padwelcome, x + 10, 3, "MHz=%s bogomips=%s", + mhz_ptr, bogo_ptr); + if (processorchips || cores || hyperthreads || cpus) { + mvwprintw(padwelcome, x + 11, 3, "ProcessorChips=%d PhyscalCores=%d", processorchips, cores); + mvwprintw(padwelcome, x + 12, 3, "Hyperthreads =%d VirtualCPUs =%d", hyperthreads, cpus); + } +#endif + COLOUR wattrset(padwelcome, COLOR_PAIR(0)); + mvwprintw(padwelcome, x + 14, 3, + "Use these keys to toggle statistics on/off:"); + mvwprintw(padwelcome, x + 15, 3, " c = CPU l = CPU Long-term - = Faster screen updates"); + mvwprintw(padwelcome, x + 16, 3, " C = \" WideView U = Utilisation + = Slower screen updates"); + mvwprintw(padwelcome, x + 17, 3, " m = Memory V = Virtual memory j = File Systems"); + mvwprintw(padwelcome, x + 18, 3, " d = Disks n = Network . = only busy disks/procs"); + mvwprintw(padwelcome, x + 19, 3, " r = Resource N = NFS h = more options"); + mvwprintw(padwelcome, x + 20, 3, " k = Kernel t = Top-processes q = Quit"); + pnoutrefresh(padwelcome, 0, 0, x, 1, LINES - 2, COLS - 2); + wnoutrefresh(stdscr); + x = x + 22; + } + } else { + if (!cursed && nmon_snap && (loop % nmon_one_in) == 0) { + child_start(CHLD_SNAP, nmon_snap, time_stamp_type, loop, + timer); + } + + + if (!show_rrd) + fprintf(fp, "ZZZZ,%s,%02d:%02d:%02d,%02d-%s-%4d\n", LOOP, + tim->tm_hour, tim->tm_min, tim->tm_sec, + tim->tm_mday, month[tim->tm_mon], + tim->tm_year + 1900); + fflush(NULL); + } + if (show_verbose && cursed) { + BANNER(padverb, "Verbose Mode"); + mvwprintw(padverb, 1, 0, + " Code Resource Stats Now\tWarn\tDanger "); + /* DISPLAY(padverb,7); */ + /* move(x,0); */ + x = x + 6; + } + if (show_help && cursed) { + + COLOUR wattrset(padhelp, COLOR_PAIR(2)); + BANNER(padhelp, + "HELP: Hit h to remove this Info Hit q to Quit"); + mvwprintw(padhelp, 1, 1, + "Letters which toggle on/off statistics:"); + mvwprintw(padhelp, 2, 1, + "h = This help | r = Resources OS & Proc"); + mvwprintw(padhelp, 3, 1, + "c = CPU Util C = wide view | l = longer term CPU averages"); + mvwprintw(padhelp, 4, 1, + "m = Memory & Swap L=Huge | V = Virtual Memory"); + mvwprintw(padhelp, 5, 1, + "n = Network | N = NFS"); + mvwprintw(padhelp, 6, 1, + "d = Disk I/O Graphs D=Stats | o = Disks %%Busy Map"); + mvwprintw(padhelp, 7, 1, + "k = Kernel stats & loadavg | j = Filesystem Usage"); + mvwprintw(padhelp, 8, 1, "M = MHz by thread & CPU"); +#ifdef NVIDIA_GPU + mvwprintw(padhelp, 8, 39, "| a = Accelerator Nvidia GPU "); +#else /*NVIDIA_GPU */ +#ifdef POWER + mvwprintw(padhelp, 8, 39, "| p = if(PowerVM) LPAR details"); +#endif /*POWER*/ +#endif /*NVIDIA_GPU */ + mvwprintw(padhelp, 9, 1, + "t = TopProcess 1=Priority/Nice/State | u = TopProc with command line"); + mvwprintw(padhelp, 10, 1, + " ReOrder by: 3=CPU 4=RAM 5=I/O | Hit u twice to update"); + mvwprintw(padhelp, 11, 1, + "g = User Defined Disk Groups | G = with -g switches Disk graphs"); + mvwprintw(padhelp, 12, 1, + " [start nmon with -g ] | to disk groups only"); + mvwprintw(padhelp, 13, 39, "| b = black & white mode"); + mvwprintw(padhelp, 14, 1, + "Other Controls: |"); + mvwprintw(padhelp, 15, 1, + "+ = double the screen refresh time | 0 = reset peak marks (\">\") to zero"); + mvwprintw(padhelp, 16, 1, + "- = half the screen refresh time | space refresh screen now"); + mvwprintw(padhelp, 17, 1, + ". = Display only busy disks & CPU | q = Quit"); +/* mvwprintw(padhelp,18, 1, "v = Verbose Simple Checks - OK/Warnings/Danger"); */ + + mvwprintw(padhelp, 19, 1, + "(C) Copyright 2009 Nigel Griffiths | See http://nmon.sourceforge.net"); + mvwprintw(padhelp, 20, 1, "Colour:"); + for (i = 0; i < 13; i++) { + COLOUR wattrset(padhelp, COLOR_PAIR(i)); + mvwprintw(padhelp, 20, 8 + i * 5, "#%d#", i); + } + COLOUR wattrset(padhelp, COLOR_PAIR(0)); + DISPLAY(padhelp, 21); + + } +/* for debugging use only + if(error_on && errorstr[0] != 0) { + mvprintw(x, 0, "Error: %s ",errorstr); + x = x + 1; + } +*/ + if (show_res && cursed) { + proc_read(P_CPUINFO); + proc_read(P_VERSION); + + BANNER(padres, "Resources Linux & Processor"); + COLOUR wattrset(padres, COLOR_PAIR(2)); + mvwprintw(padres, 1, 4, "Linux: %s", proc[P_VERSION].line[0]); + mvwprintw(padres, 2, 4, "Build: %s", proc[P_VERSION].line[1]); + mvwprintw(padres, 3, 4, "Release : %s", uts.release); + mvwprintw(padres, 4, 4, "Version : %s", uts.version); + COLOUR wattrset(padres, COLOR_PAIR(3)); +#ifdef POWER + mvwprintw(padres, 5, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[1]); + mvwprintw(padres, 6, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[2]); + mvwprintw(padres, 7, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[3]); + mvwprintw(padres, 8, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[proc[P_CPUINFO].lines - 1]); + /* needs lparcfg to be already processed */ + proc_lparcfg(); + switch (power_vm_type) { + case VM_POWERKVM_GUEST: + mvwprintw(padres, 9, 4, + "PowerKVM Guest Physcal CPU:%d & Virtual CPU (SMT):%d %s", + lparcfg.partition_active_processors, cpus, + lscpu.byte_order); + break; + case VM_POWERKVM_HOST: + mvwprintw(padres, 9, 4, + "PowerKVM Host Physical CPU:%d %s", cpus, + lscpu.byte_order); + break; + case VM_POWERVM: + mvwprintw(padres, 9, 4, + "PowerVM Physcal CPU:%d & Logical CPU:%d %s", + lparcfg.partition_active_processors, cpus, + lscpu.byte_order); + break; + case VM_NATIVE: + mvwprintw(padres, 9, 4, "Native Mode Physical CPU:%d %s", + cpus, lscpu.byte_order); + break; + } +#else +#ifdef MAINFRAME + mvwprintw(padres, 5, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[1]); + mvwprintw(padres, 6, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[2]); + mvwprintw(padres, 7, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[3]); + mvwprintw(padres, 8, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[4]); +#else /* MAINFRAME */ +#if X86 || ARM + mvwprintw(padres, 5, 4, "cpuinfo: %s %s", vendor_ptr, + model_ptr); + mvwprintw(padres, 6, 4, "cpuinfo: Hz=%s bogomips=%s", mhz_ptr, + bogo_ptr); + if (processorchips || cores || hyperthreads || cpus) { + mvwprintw(padres, 7, 4, + "cpuinfo: ProcessorChips=%d PhyscalCores=%d", + processorchips, cores); + mvwprintw(padres, 8, 4, + "cpuinfo: Hyperthreads =%d VirtualCPUs =%d", + hyperthreads, cpus); + } +#else /* other platform perhaps ARM */ + mvwprintw(padres, 5, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[4]); + mvwprintw(padres, 6, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[1]); + mvwprintw(padres, 7, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[6]); + mvwprintw(padres, 8, 4, "cpuinfo: %s", + proc[P_CPUINFO].line[17]); +#endif /* X86 */ +#endif /* MAINFRAME */ +#endif /* POWER */ + mvwprintw(padres, 9, 4, "# of CPUs: %d", cpus); + COLOUR wattrset(padres, COLOR_PAIR(5)); + mvwprintw(padres, 10, 4, "Machine : %s", uts.machine); + mvwprintw(padres, 11, 4, "Nodename : %s", uts.nodename); + COLOUR wattrset(padres, COLOR_PAIR(6)); + mvwprintw(padres, 12, 4, "/etc/*ease[1]: %s", easy[0]); + mvwprintw(padres, 13, 4, "/etc/*ease[2]: %s", easy[1]); + mvwprintw(padres, 14, 4, "/etc/*ease[3]: %s", easy[2]); + mvwprintw(padres, 15, 4, "/etc/*ease[4]: %s", easy[3]); + COLOUR wattrset(padres, COLOR_PAIR(2)); + mvwprintw(padres, 16, 4, "lsb_release: %s", lsb_release[0]); + mvwprintw(padres, 17, 4, "lsb_release: %s", lsb_release[1]); + mvwprintw(padres, 18, 4, "lsb_release: %s", lsb_release[2]); + mvwprintw(padres, 19, 4, "lsb_release: %s", lsb_release[3]); + COLOUR wattrset(padres, COLOR_PAIR(0)); + DISPLAY(padres, 20); + } + if (show_longterm) { + proc_read(P_STAT); + proc_cpu(); + cpu_user = RAWTOTAL(user) + RAWTOTAL(nice); + cpu_sys = + RAWTOTAL(sys) + RAWTOTAL(irq) + RAWTOTAL(softirq) ; + /* + RAWTOTAL(guest) + RAWTOTAL(guest_nice); these are in addition to the 100% */ + cpu_wait = RAWTOTAL(wait); + cpu_idle = RAWTOTAL(idle); + cpu_steal = RAWTOTAL(steal); + /* DEBUG inject steal cpu_steal = cpu_sys; */ + cpu_sum = cpu_idle + cpu_user + cpu_sys + cpu_wait + cpu_steal; + + save_snap((double) cpu_user / (double) cpu_sum * 100.0, + (double) cpu_sys / (double) cpu_sum * 100.0, + (double) cpu_wait / (double) cpu_sum * 100.0, + (double) cpu_idle / (double) cpu_sum * 100.0, + (double) cpu_steal / (double) cpu_sum * 100.0); + plot_snap(padlong); + DISPLAY(padlong, MAX_SNAP_ROWS + 2); + } + if (show_smp || show_verbose || show_wide) { + proc_read(P_STAT); + proc_cpu(); + if (cpus > max_cpus && !cursed) { + for (i = max_cpus + 1; i <= cpus; i++) + fprintf(fp, + "CPU%03d,CPU %d %s,User%%,Sys%%,Wait%%,Idle%%\n", + i, i, run_name); + max_cpus = cpus; + } + if (old_cpus != cpus) { + if (!cursed) { + if (bbbr_line == 0) { + fprintf(fp, "BBBR,0,Reconfig,action,old,new\n"); + bbbr_line++; + } + fprintf(fp, "BBBR,%03d,%s,cpuchg,%d,%d\n", bbbr_line++, + LOOP, old_cpus, cpus); + } else { + /* wmove(padsmp,0,0); */ + /* doesn't work CURSE wclrtobot(padsmp); */ + /* Do BRUTE force overwrite of previous data */ + if (cpus < old_cpus) { + for (i = cpus; i < old_cpus; i++) + mvwprintw(padsmp, i + 4, 0, + " "); + } + } + } + if (show_smp) { + if (cursed) { + BANNER(padsmp, "CPU Utilisation"); + + /* mvwprintw(padsmp,1, 0, cpu_line); */ + /* + *mvwprintw(padsmp,2, 0, "CPU User%% Sys%% Wait%% Idle|0 |25 |50 |75 100|"); + */ + mvwprintw(padsmp, 1, 0, cpu_line); + mvwprintw(padsmp, 2, 0, "CPU "); + COLOUR wattrset(padsmp, COLOR_PAIR(2)); /* Green */ + mvwprintw(padsmp, 2, 4, "User%%"); + COLOUR wattrset(padsmp, COLOR_PAIR(1)); /* Red */ + mvwprintw(padsmp, 2, 9, " Sys%%"); + COLOUR wattrset(padsmp, COLOR_PAIR(4)); /* Blue */ + mvwprintw(padsmp, 2, 15, " Wait%%"); + if (p->cpu_total.steal != q->cpu_total.steal) { + COLOUR wattrset(padsmp, COLOR_PAIR(5)); + mvwprintw(padsmp, 2, 22, "Steal"); + } else { + COLOUR wattrset(padsmp, COLOR_PAIR(0)); + mvwprintw(padsmp, 2, 22, " Idle"); + } + COLOUR wattrset(padsmp, COLOR_PAIR(0)); + mvwprintw(padsmp, 2, 27, + "|0 |25 |50 |75 100|"); + } /* if (show_smp) AND if(cursed) */ +#ifdef POWER + /* Always get lpar info as well so we can report physical CPU usage + * to make data more meaningful + * This assumes that LPAR info is available in q and p ! + */ + if (proc_lparcfg() > 0) { + if (lparcfg.shared_processor_mode == 1) { + if (lparcfg.timebase == -1) { + lparcfg.timebase = 0; + proc_read(P_CPUINFO); + for (i = 0; i < proc[P_CPUINFO].lines - 1; i++) { + if (!strncmp + ("timebase", proc[P_CPUINFO].line[i], + 8)) { + sscanf(proc[P_CPUINFO].line[i], + "timebase : %lld", + &lparcfg.timebase); + break; + } + } + } else { + /* PowerKVM Host or Guest or Native have not Entitlement stats */ + if (power_vm_type == VM_POWERVM) + mvwprintw(padsmp, 1, 30, + "EntitledCPU=% 6.3f", + (double) lparcfg. + partition_entitled_capacity / + 100.0); + /* Only if the calculation is working */ + if (lparcfg.purr_diff != 0) + mvwprintw(padsmp, 1, 50, + "PhysicalCPUused=% 7.3f", + (double) lparcfg.purr_diff / + (double) lparcfg.timebase / + elapsed); + } + } + } +#endif + for (i = 0; i < cpus; i++) { + cpu_user = RAW(user) + RAW(nice); + cpu_sys = + RAW(sys) + RAW(irq) + RAW(softirq); + /* + RAW(guest) + RAW(guest_nice); these are in addition to the 100% */ + cpu_wait = RAW(wait); + cpu_idle = RAW(idle); + cpu_steal = RAW(steal); +/* DEBUG inject steal cpu_steal = cpu_sys; */ + cpu_sum = + cpu_idle + cpu_user + cpu_sys + cpu_wait + + cpu_steal; + /* Check if we had a CPU # change and have to set idle to 100 */ + if (cpu_sum == 0) + cpu_sum = cpu_idle = 100.0; + if (smp_first_time && cursed) { + if (i == 0) + mvwprintw(padsmp, 3 + i, 27, + "| Please wait gathering CPU statistics"); + else + mvwprintw(padsmp, 3 + i, 27, "|"); + mvwprintw(padsmp, 3 + i, 77, "|"); + } else { +#ifdef POWER + /* lparcfg gathered above */ + if (lparcfg.smt_mode > 1 + && i % lparcfg.smt_mode == 0) { + mvwprintw(padsmp, 3 + i, 27, "*"); + mvwprintw(padsmp, 3 + i, 77, "*"); + } +#endif + plot_smp(padsmp, i + 1, 3 + i, + (double) cpu_user / (double) cpu_sum * + 100.0, + (double) cpu_sys / (double) cpu_sum * + 100.0, + (double) cpu_wait / (double) cpu_sum * + 100.0, + (double) cpu_idle / (double) cpu_sum * + 100.0, + (double) cpu_steal / (double) cpu_sum * + 100.0); +#ifdef POWER + /* lparcfg gathered above */ + if (lparcfg.smt_mode > 1 + && i % lparcfg.smt_mode == 0) { + mvwprintw(padsmp, 3 + i, 27, "*"); + mvwprintw(padsmp, 3 + i, 77, "*"); + } +#endif + + RRD fprintf(fp, + "rrdtool update cpu%02d.rrd %s:%.1f:%.1f:%.1f:%.1f\n", + i, LOOP, + (double) cpu_user / (double) cpu_sum * + 100.0, + (double) cpu_sys / (double) cpu_sum * + 100.0, + (double) cpu_wait / (double) cpu_sum * + 100.0, + (double) cpu_idle / (double) cpu_sum * + 100.0); + } + } /* for (i = 0; i < cpus; i++) */ + CURSE mvwprintw(padsmp, i + 3, 0, cpu_line); +#ifdef POWER + /* proc_lparcfg called above in previous ifdef + */ + if (lparcfg.shared_processor_mode == 1) { + if (lparcfg.timebase == -1) { + lparcfg.timebase = 0; + proc_read(P_CPUINFO); + for (i = 0; i < proc[P_CPUINFO].lines - 1; i++) { + if (!strncmp + ("timebase", proc[P_CPUINFO].line[i], 8)) { + sscanf(proc[P_CPUINFO].line[i], + "timebase : %lld", + &lparcfg.timebase); + break; + } + } + } else { + mvwprintw(padsmp, i + 3, 29, "%s", + lparcfg. + shared_processor_mode ? "Shared" : + "Dedicated"); + mvwprintw(padsmp, i + 3, 39, "|"); + /* PowerKVM has no Capped concept */ + if (power_vm_type == VM_POWERVM) + mvwprintw(padsmp, i + 3, 41, "%s", + lparcfg. + capped ? "--Capped" : "Uncapped"); + mvwprintw(padsmp, i + 3, 51, "|"); + mvwprintw(padsmp, i + 3, 54, "SMT=%d", + lparcfg.smt_mode); + mvwprintw(padsmp, i + 3, 64, "|"); + mvwprintw(padsmp, i + 3, 67, "VP=%.0f", + (float) lparcfg. + partition_active_processors); + } + } +#endif + cpu_user = RAWTOTAL(user) + RAWTOTAL(nice); + cpu_sys = + RAWTOTAL(sys) + RAWTOTAL(irq) + RAWTOTAL(softirq); + /* + RAWTOTAL(guest) + RAWTOTAL(guest_nice); these are in addition to the 100% */ + cpu_wait = RAWTOTAL(wait); + cpu_idle = RAWTOTAL(idle); + cpu_steal = RAWTOTAL(steal); +/* DEBUG inject steal cpu_steal = cpu_sys; */ + cpu_sum = + cpu_idle + cpu_user + cpu_sys + cpu_wait + cpu_steal; + + /* Check if we had a CPU # change and have to set idle to 100 */ + if (cpu_sum == 0) + cpu_sum = cpu_idle = 100.0; + + RRD fprintf(fp, + "rrdtool update cpu.rrd %s:%.1f:%.1f:%.1f:%.1f%.1f\n", + LOOP, + (double) cpu_user / (double) cpu_sum * 100.0, + (double) cpu_sys / (double) cpu_sum * 100.0, + (double) cpu_wait / (double) cpu_sum * 100.0, + (double) cpu_idle / (double) cpu_sum * 100.0, + (double) cpu_steal / (double) cpu_sum * 100.0); + if (cpus > 1 || !cursed) { + if (!smp_first_time || !cursed) { + plot_smp(padsmp, 0, 4 + i, + (double) cpu_user / (double) cpu_sum * + 100.0, + (double) cpu_sys / (double) cpu_sum * + 100.0, + (double) cpu_wait / (double) cpu_sum * + 100.0, + (double) cpu_idle / (double) cpu_sum * + 100.0, + (double) cpu_steal / (double) cpu_sum * + 100.0); + } + + CURSE mvwprintw(padsmp, i + 5, 0, cpu_line); + i = i + 2; + } /* if (cpus > 1 || !cursed) */ + smp_first_time = 0; + DISPLAY(padsmp, i + 4); + } /* if (show_smp) */ + if (show_wide) { + if (cursed) { + int rows = 0; + BANNER(padwide, "CPU Utilisation Wide View"); + char *wide1 = + "100%%-+--------+---------+---------+---------+---------+---------+-----+100%%"; + char *wide2 = + " 90%%-| |-90%%"; + char *wide3 = + " 80%%-| |-80%%"; + char *wide4 = + " 70%%-| |-70%%"; + char *wide5 = + " 60%%-| |-60%%"; + char *wide6 = + " 50%%-| |-50%%"; + char *wide7 = + " 40%%-| |-40%%"; + char *wide8 = + " 30%%-| |-30%%"; + char *wide9 = + " 20%%-| |-20%%"; + char *wide10 = + " 10%%-| |-10%%"; + + mvwprintw(padwide, 1, 0, wide1); + mvwprintw(padwide, 2, 0, wide2); + mvwprintw(padwide, 3, 0, wide3); + mvwprintw(padwide, 4, 0, wide4); + mvwprintw(padwide, 5, 0, wide5); + mvwprintw(padwide, 6, 0, wide6); + mvwprintw(padwide, 7, 0, wide7); + mvwprintw(padwide, 8, 0, wide8); + mvwprintw(padwide, 9, 0, wide9); + mvwprintw(padwide, 10, 0, wide10); + mvwprintw(padwide, 11, 0, + " CPU +1--------+10-------+20-------+30-------+40-------+50-------+60--+--0%%"); + mvwprintw(padwide, 1, 6, "CPU(s)=%d", cpus); + if (wide_first_time) { + mvwprintw(padwide, 3, 7, + " Please wait gathering CPU statistics"); + } else { + for (i = 0; i < cpus && i < 64; i++) { + cpu_user = RAW(user) + RAW(nice); + cpu_sys = + RAW(sys) + RAW(irq) + RAW(softirq); + /* + RAW(guest) + RAW(guest_nice); these are in addition to the 100% */ + cpu_sum = cpu_user + cpu_sys; + COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ + if (i % 2) { + mvwprintw(padwide, 6, 6 + i, "."); + } + if (cpu_sum > 75) { + COLOUR wattrset(padwide, COLOR_PAIR(1)); /*red */ + } else { + if (cpu_sum > 50) { + COLOUR wattrset(padwide, COLOR_PAIR(5)); /*magenta */ + } else { + COLOUR wattrset(padwide, COLOR_PAIR(2)); /*green */ + } + } + for (j = 1, k = 10; j < 10; j++, k--) + if (cpu_sum > j * 10.0) + mvwprintw(padwide, k, 6 + i, "#"); + COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ + if (0.1 < cpu_sum && cpu_sum < 5.0) + mvwprintw(padwide, 10, 6 + i, "."); + if (5.1 <= cpu_sum && cpu_sum < 10.0) + mvwprintw(padwide, 10, 6 + i, "o"); + } + if (cpus < 64) + for (j = 2; j <= 10; j++) + mvwprintw(padwide, j, 6 + i, "|"); + rows = 12; + } + if (cpus > 63) { + mvwprintw(padwide, rows + 0, 0, wide1); + mvwprintw(padwide, rows + 1, 0, wide2); + mvwprintw(padwide, rows + 2, 0, wide3); + mvwprintw(padwide, rows + 3, 0, wide4); + mvwprintw(padwide, rows + 4, 0, wide5); + mvwprintw(padwide, rows + 5, 0, wide6); + mvwprintw(padwide, rows + 6, 0, wide7); + mvwprintw(padwide, rows + 7, 0, wide8); + mvwprintw(padwide, rows + 8, 0, wide9); + mvwprintw(padwide, rows + 9, 0, wide10); + mvwprintw(padwide, rows + 10, 0, + " CPU +65---+70-------+80-------+90-------+100------+110------+120-----+--0%%"); + if (wide_first_time) { + mvwprintw(padwide, rows + 3, 7, + " Please wait gathering CPU statistics"); + } else { + for (i = 64; i < cpus && i < 128; i++) { + cpu_user = RAW(user) + RAW(nice); + cpu_sys = + RAW(sys) + RAW(irq) + RAW(softirq); + /* + RAW(guest) + RAW(guest_nice); these are in addition to the 100% */ + cpu_sum = cpu_user + cpu_sys; + COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ + if (i % 2) { + mvwprintw(padwide, rows + 5, + 6 + i - 64, "."); + } + if (cpu_sum > 75) { + COLOUR wattrset(padwide, COLOR_PAIR(1)); /*red */ + } else { + if (cpu_sum > 50) { + COLOUR wattrset(padwide, COLOR_PAIR(5)); /*magenta */ + } else { + COLOUR wattrset(padwide, COLOR_PAIR(2)); /*green */ + } + } + for (j = 1, k = rows + 9; j < 10; j++, k--) + if (cpu_sum > j * 10.0) + mvwprintw(padwide, k, 6 + i - 64, + "#"); + COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ + if (0.1 < cpu_sum && cpu_sum < 5.0) + mvwprintw(padwide, rows + 9, + 6 + i - 64, "."); + if (5.1 <= cpu_sum && cpu_sum < 10.0) + mvwprintw(padwide, rows + 9, + 6 + i - 64, "o"); + } + + if (cpus < 128) + COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ + for (j = rows; j <= rows + 9; j++) + mvwprintw(padwide, j, 6 + i - 64, "<"); + COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ + } + rows = 23; + } + if (cpus > 127) { + mvwprintw(padwide, rows + 0, 0, wide1); + mvwprintw(padwide, rows + 1, 0, wide2); + mvwprintw(padwide, rows + 2, 0, wide3); + mvwprintw(padwide, rows + 3, 0, wide4); + mvwprintw(padwide, rows + 4, 0, wide5); + mvwprintw(padwide, rows + 5, 0, wide6); + mvwprintw(padwide, rows + 6, 0, wide7); + mvwprintw(padwide, rows + 7, 0, wide8); + mvwprintw(padwide, rows + 8, 0, wide9); + mvwprintw(padwide, rows + 9, 0, wide10); + mvwprintw(padwide, rows + 10, 0, + " CPU +129--------+140------+150------+160------+170------+180------+190--0%%"); + if (wide_first_time) { + mvwprintw(padwide, rows + 3, 7, + " Please wait gathering CPU statistics"); + } else { + for (i = 128; i < cpus && i < 196; i++) { + cpu_user = RAW(user) + RAW(nice); + cpu_sys = + RAW(sys) + RAW(irq) + RAW(softirq); + /* + RAW(guest) + RAW(guest_nice); these are in addition of the 100% */ + cpu_sum = cpu_user + cpu_sys; + COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ + if (i % 2) { + mvwprintw(padwide, rows + 5, + 6 + i - 128, "."); + } + if (cpu_sum > 75) { + COLOUR wattrset(padwide, COLOR_PAIR(1)); /*red */ + } else { + if (cpu_sum > 50) { + COLOUR wattrset(padwide, COLOR_PAIR(5)); /*magenta */ + } else { + COLOUR wattrset(padwide, COLOR_PAIR(2)); /*green */ + } + } + for (j = 1, k = rows + 9; j < 10; j++, k--) + if (cpu_sum > j * 10.0) + mvwprintw(padwide, k, 6 + i - 128, + "#"); + COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ + if (0.1 < cpu_sum && cpu_sum < 5.0) + mvwprintw(padwide, rows + 9, + 6 + i - 128, "."); + if (5.1 <= cpu_sum && cpu_sum < 10.0) + mvwprintw(padwide, rows + 9, + 6 + i - 128, "o"); + } + + if (cpus < 196) + COLOUR wattrset(padwide, COLOR_PAIR(4)); /* blue */ + for (j = rows; j <= rows + 9; j++) + mvwprintw(padwide, j, 6 + i - 128, "<"); + COLOUR wattrset(padwide, COLOR_PAIR(0)); /* white */ + } + rows = 34; + } + wide_first_time = 0; + DISPLAY(padwide, rows); + } + proc_read(P_STAT); + proc_cpu(); + + if (show_verbose && cursed) { + cpu_user = RAWTOTAL(user) + RAWTOTAL(nice); + cpu_sys = + RAWTOTAL(sys) + RAWTOTAL(irq) + RAWTOTAL(softirq); + /* + RAWTOTAL(guest) + RAWTOTAL(guest_nice); these are in addition to the 100% */ + cpu_wait = RAWTOTAL(wait); + cpu_idle = RAWTOTAL(idle) + RAWTOTAL(steal); + cpu_sum = cpu_idle + cpu_user + cpu_sys + cpu_wait; + + cpu_busy = + (double) (cpu_user + + cpu_sys) / (double) cpu_sum *100.0; + mvwprintw(padverb, 2, 0, + " -> CPU %%busy %5.1f%%\t>80%%\t>90%% ", + cpu_busy); + if (cpu_busy > 90.0) { + COLOUR wattrset(padverb, COLOR_PAIR(1)); + mvwprintw(padverb, 2, 0, " DANGER"); + } else if (cpu_busy > 80.0) { + COLOUR wattrset(padverb, COLOR_PAIR(4)); + mvwprintw(padverb, 2, 0, "Warning"); + } else { + COLOUR wattrset(padverb, COLOR_PAIR(2)); + mvwprintw(padverb, 2, 0, " OK"); + } + COLOUR wattrset(padverb, COLOR_PAIR(0)); + } + + } /* if (cursed) */ + } /* if (show_smp || show_verbose) */ + if (show_util) { + proc_read(P_STAT); + proc_cpu(); + if (cursed) { + BANNER(padutil, "CPU Utilisation Stats"); + mvwprintw(padutil, 2, 0, "CPU"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 0, "%3d", i + 1); + mvwprintw(padutil, 1, 0, "ALL"); + if (first_util) { + mvwprintw(padutil, 5, 27, + " Please wait gathering CPU statistics"); + } else { + COLOUR wattrset(padutil, COLOR_PAIR(2)); /* Green */ + mvwprintw(padutil, 2, 4, " User%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 4, "%7.1f", + RAW(user) / elapsed); + mvwprintw(padutil, 1, 4, "%7.1f", + RAWTOTAL(user) / elapsed); + mvwprintw(padutil, 2, 11, " Nice%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 11, "%7.1f", + RAW(nice) / elapsed); + mvwprintw(padutil, 1, 11, "%7.1f", + RAWTOTAL(nice) / elapsed); + + COLOUR wattrset(padutil, COLOR_PAIR(1)); /* Red */ + mvwprintw(padutil, 2, 18, " Sys%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 18, "%7.1f", + RAW(sys) / elapsed); + mvwprintw(padutil, 1, 18, "%7.1f", + RAWTOTAL(sys) / elapsed); + + COLOUR wattrset(padutil, COLOR_PAIR(3)); /* Yellow */ + mvwprintw(padutil, 2, 25, " Idle%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 25, "%7.1f", + RAW(idle) / elapsed); + mvwprintw(padutil, 1, 25, "%7.1f", + RAWTOTAL(idle) / elapsed); + mvwprintw(padutil, 2, 32, " Wait%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 32, "%7.1f", + RAW(wait) / elapsed); + mvwprintw(padutil, 1, 32, "%7.1f", + RAWTOTAL(wait) / elapsed); + + COLOUR wattrset(padutil, COLOR_PAIR(1)); /* Red */ + mvwprintw(padutil, 2, 39, " HWirq%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 39, "%7.1f", + RAW(irq) / elapsed); + mvwprintw(padutil, 1, 39, "%7.1f", + RAWTOTAL(irq) / elapsed); + mvwprintw(padutil, 2, 46, " SWirq%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 46, "%7.1f", + RAW(softirq) / elapsed); + mvwprintw(padutil, 1, 46, "%7.1f", + RAWTOTAL(softirq) / elapsed); + + COLOUR wattrset(padutil, COLOR_PAIR(5)); /* Magenta */ + mvwprintw(padutil, 2, 53, " Steal%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 53, "%7.1f", + RAW(steal) / elapsed); + mvwprintw(padutil, 1, 53, "%7.1f", + RAWTOTAL(steal) / elapsed); + + COLOUR wattrset(padutil, COLOR_PAIR(6)); /* Cyan */ + mvwprintw(padutil, 2, 60, " Guest%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 60, "%7.1f", + RAW(guest) / elapsed); + mvwprintw(padutil, 1, 60, "%7.1f", + RAWTOTAL(guest) / elapsed); + mvwprintw(padutil, 2, 67, " GuestNice%%"); + for (i = 0; i < cpus; i++) + mvwprintw(padutil, 3 + i, 67, "%7.1f", + RAW(guest_nice) / elapsed); + mvwprintw(padutil, 1, 67, "%7.1f", + RAWTOTAL(guest_nice) / elapsed); + } + COLOUR wattrset(padutil, COLOR_PAIR(0)); + DISPLAY(padutil, i + 3); + } else { + if (first_util) { + fprintf(fp, + "CPUUTIL_ALL,CPU Util Stats %s,User%%,Nice%%,Sys%%,Idle%%,Wait%%,Irq%%,Softirq%%,Steal%%,Guest%%,Guest_nice%%\n", + run_name); + for (i = 1; i <= cpus; i++) + fprintf(fp, + "CPUUTIL%03d,CPU Util Stats CPU%d %s,User%%,Nice%%,Sys%%,Idle%%,Wait%%,Irq%%,Softirq%%,Steal%%,Guest%%,Guest_nice%%\n", + i, i, run_name); + } + fprintf(fp, + "CPUUTIL_ALL,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\n", + LOOP, RAWTOTAL(user) / elapsed, + RAWTOTAL(nice) / elapsed, RAWTOTAL(sys) / elapsed, + RAWTOTAL(idle) / elapsed, RAWTOTAL(wait) / elapsed, + RAWTOTAL(irq) / elapsed, + RAWTOTAL(softirq) / elapsed, + RAWTOTAL(steal) / elapsed, + RAWTOTAL(guest) / elapsed, + RAWTOTAL(guest_nice) / elapsed); + for (i = 0; i < cpus; i++) { + fprintf(fp, + "CPUUTIL%03d,%s,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f\n", + i, LOOP, RAW(user) / elapsed, + RAW(nice) / elapsed, RAW(sys) / elapsed, + RAW(idle) / elapsed, RAW(wait) / elapsed, + RAW(irq) / elapsed, RAW(softirq) / elapsed, + RAW(steal) / elapsed, RAW(guest) / elapsed, + RAW(guest_nice) / elapsed); + } + } + first_util = 0; + } +#ifdef POWER + if (show_lpar) { + if (lparcfg.timebase == -1) { + lparcfg.timebase = 0; + proc_read(P_CPUINFO); + for (i = 0; i < proc[P_CPUINFO].lines - 1; i++) { + if (!strncmp("timebase", proc[P_CPUINFO].line[i], 8)) { + sscanf(proc[P_CPUINFO].line[i], "timebase : %lld", + &lparcfg.timebase); + break; + } + } + } + ret = proc_lparcfg(); + if (cursed) { + BANNER(padlpar, "PowerVM LPAR"); + if (ret == 0) { + COLOUR wattrset(padlpar, COLOR_PAIR(1)); + mvwprintw(padlpar, 2, 0, + "Reading data from /proc/ppc64/lparcfg failed"); + mvwprintw(padlpar, 3, 0, + "This is probably a Native Virtual Machine"); + COLOUR wattrset(padlpar, COLOR_PAIR(0)); + } else + if (power_vm_type == VM_POWERKVM_HOST + || power_vm_type == VM_POWERKVM_GUEST) { + COLOUR wattrset(padlpar, COLOR_PAIR(5)); + mvwprintw(padlpar, 2, 0, + "Reading data from /proc/ppc64/lparcfg mostly failed"); + mvwprintw(padlpar, 3, 0, + "PowerKVM does not many of these stats"); + COLOUR wattrset(padlpar, COLOR_PAIR(0)); + } else { + mvwprintw(padlpar, 1, 0, + "LPAR=%d SerialNumber=%s Type=%s", + lparcfg.partition_id, lparcfg.serial_number, + lparcfg.system_type); + mvwprintw(padlpar, 2, 0, + "Flags: Shared-CPU=%-5s Capped=%-5s SMT-mode=%d", + lparcfg. + shared_processor_mode ? "true" : "false", + lparcfg.capped ? "true" : "false", + lparcfg.smt_mode); + COLOUR wattrset(padlpar, COLOR_PAIR(2)); + mvwprintw(padlpar, 3, 0, + "Systems CPU Pool=%8.2f Active=%8.2f Total=%8.2f", + (float) lparcfg.pool_capacity, + (float) lparcfg.system_active_processors, + (float) lparcfg.system_potential_processors); + COLOUR wattrset(padlpar, COLOR_PAIR(3)); + mvwprintw(padlpar, 4, 0, + "LPARs CPU Min=%8.2f Entitlement=%8.2f Max=%8.2f", + lparcfg.MinEntCap / 100.0, + lparcfg.partition_entitled_capacity / 100.0, + lparcfg.partition_max_entitled_capacity / + 100.0); + COLOUR wattrset(padlpar, COLOR_PAIR(5)); + mvwprintw(padlpar, 5, 0, + "Virtual CPU Min=%8.2f VP Now=%8.2f Max=%8.2f", + (float) lparcfg.MinProcs, + (float) lparcfg.partition_active_processors, + (float) lparcfg. + partition_potential_processors); + COLOUR wattrset(padlpar, COLOR_PAIR(6)); + mvwprintw(padlpar, 6, 0, + "Memory Min= unknown Now=%8.2f Max=%8.2f", + (float) lparcfg.MinMem, + (float) lparcfg.DesMem); + COLOUR wattrset(padlpar, COLOR_PAIR(0)); + mvwprintw(padlpar, 7, 0, + "Other Weight=%8.2f UnallocWeight=%8.2f Capacity=%8.2f", + (float) lparcfg.capacity_weight, + (float) lparcfg.unallocated_capacity_weight, + (float) lparcfg.CapInc / 100.0); + + mvwprintw(padlpar, 8, 0, + " BoundThrds=%8.2f UnallocCapacity=%8.2f Increment", + (float) lparcfg.BoundThrds, + (float) lparcfg.unallocated_capacity); + if (lparcfg.purr_diff == 0 || lparcfg.timebase < 1) { + mvwprintw(padlpar, 9, 0, + "lparcfg: purr field always zero, upgrade to SLES9+sp1 or RHEL4+u1"); + } else { + if (lpar_first_time) { + mvwprintw(padlpar, 9, 0, + "Please wait gathering data"); + + lpar_first_time = 0; + } else { + COLOUR wattrset(padlpar, COLOR_PAIR(1)); + mvwprintw(padlpar, 9, 0, + "Physical CPU use=%8.3f ", + (double) lparcfg.purr_diff / + (double) lparcfg.timebase / elapsed); + if (lparcfg.pool_idle_time != NUMBER_NOT_VALID + && lparcfg.pool_idle_saved != 0) + mvwprintw(padlpar, 9, 29, + "PoolIdleTime=%8.2f", + (double) lparcfg.pool_idle_diff / + (double) lparcfg.timebase / + elapsed); + COLOUR wattrset(padlpar, COLOR_PAIR(0)); + mvwprintw(padlpar, 9, 54, "[timebase=%lld]", + lparcfg.timebase); + } + } + } + DISPLAY(padlpar, 10); + } else { + /* Only print LPAR info to spreadsheet if in shared processor mode */ + if (ret != 0 && lparcfg.shared_processor_mode > 0 + && power_vm_type == VM_POWERVM) + fprintf(fp, "LPAR,%s,%9.6f,%d,%d,%d,%d,%d,%.2f,%.2f,%.2f,%d,%d,%d,%d,%d,%d,%d,%d,%d,%.2f,%d\n", LOOP, (double) lparcfg.purr_diff / (double) lparcfg.timebase / elapsed, lparcfg.capped, lparcfg.shared_processor_mode, lparcfg.system_potential_processors, lparcfg.system_active_processors, lparcfg.pool_capacity, lparcfg.MinEntCap / 100.0, lparcfg.partition_entitled_capacity / 100.0, lparcfg.partition_max_entitled_capacity / 100.0, lparcfg.MinProcs, cpus, /* report logical CPU here so analyser graph CPU% vs VPs reports correctly */ + lparcfg.partition_active_processors, + lparcfg.partition_potential_processors, + lparcfg.capacity_weight, + lparcfg.unallocated_capacity_weight, + lparcfg.BoundThrds, + lparcfg.MinMem, + lparcfg.unallocated_capacity, + (double) lparcfg.pool_idle_diff / + (double) lparcfg.timebase / elapsed, + lparcfg.smt_mode); + } + } +#endif /*POWER*/ +#ifdef NVIDIA_GPU + if (show_gpu) { + if (!cursed && first_time_gpu) + gpu_init(); + for (i = 0; i < gpu_devices; i++) { + if (cursed && first_time_gpu) { + if (nvmlDeviceGetName + (gpu_device[i], &gpu_name[i][0], + 1024) != NVML_SUCCESS) + strcpy(gpu_name[i], "NVML API Failed"); + } + if (nvmlDeviceGetUtilizationRates + (gpu_device[i], &gpu_util[i]) != NVML_SUCCESS) { + gpu_util[i].gpu = 999; + gpu_util[i].memory = 999; + } + if (nvmlDeviceGetTemperature + (gpu_device[i], NVML_TEMPERATURE_GPU, + &gpu_temp[i]) != NVML_SUCCESS) + gpu_temp[i] = 999; + if (nvmlDeviceGetPowerUsage(gpu_device[i], &gpu_watts[i]) + != NVML_SUCCESS) + gpu_watts[i] = 999000; + if (nvmlDeviceGetClockInfo + (gpu_device[i], NVML_CLOCK_GRAPHICS, + &gpu_clock[i]) != NVML_SUCCESS) + gpu_clock[i] = 999; + } + if (cursed) { + first_time_gpu = 0; + BANNER(padgpu, "NVIDIA GPU Accelerator"); + + mvwprintw(padgpu, 1, 1, + "Driver Version:%s NVML Version: %s", + gpu_driver_version, gpu_nvml_version); + + mvwprintw(padgpu, 2, 1, "GPU"); + mvwprintw(padgpu, 3, 1, "No."); + COLOUR wattrset(padgpu, COLOR_PAIR(1)); + mvwprintw(padgpu, 3, 5, "GPU-MHz"); + COLOUR wattrset(padgpu, COLOR_PAIR(2)); + mvwprintw(padgpu, 2, 14, "GPU-Utilisation"); + mvwprintw(padgpu, 3, 14, "Processor-Memory"); + COLOUR wattrset(padgpu, COLOR_PAIR(3)); + mvwprintw(padgpu, 2, 31, "Temperature"); + mvwprintw(padgpu, 3, 31, " Centigrade"); + COLOUR wattrset(padgpu, COLOR_PAIR(5)); + mvwprintw(padgpu, 2, 44, "Power-Use"); + mvwprintw(padgpu, 3, 44, " Watts"); + COLOUR wattrset(padgpu, COLOR_PAIR(0)); + mvwprintw(padgpu, 2, 55, "Name"); + + for (i = 0; i < gpu_devices; i++) { + mvwprintw(padgpu, 4 + i, 1, "%3d", i); + COLOUR wattrset(padgpu, COLOR_PAIR(1)); + mvwprintw(padgpu, 4 + i, 5, "%7d", (int) gpu_clock[i]); + COLOUR wattrset(padgpu, COLOR_PAIR(2)); + mvwprintw(padgpu, 4 + i, 14, "%7d%% %7d%%", + (int) gpu_util[i].gpu, + (int) gpu_util[i].memory); + COLOUR wattrset(padgpu, COLOR_PAIR(3)); + mvwprintw(padgpu, 4 + i, 31, "%7d", (int) gpu_temp[i]); + COLOUR wattrset(padgpu, COLOR_PAIR(5)); + mvwprintw(padgpu, 4 + i, 44, "%7.2f", + (int) gpu_watts[i] / 1000.0); + COLOUR wattrset(padgpu, COLOR_PAIR(0)); + mvwprintw(padgpu, 4 + i, 55, "%-s", &gpu_name[i][0]); + } + DISPLAY(padgpu, 8); + } else { + if (!show_rrd) { + if (first_time_gpu) { + first_time_gpu = 0; + fprintf(fp, + "GPU_UTIL,NVidia GPU Utilisation Percent"); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",GPU%d", i + 1); + fprintf(fp, "\n"); + fprintf(fp, + "GPU_MEM,NVidia Memory Utilisation Percent"); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",GPU%d", i + 1); + fprintf(fp, "\n"); + fprintf(fp, "GPU_TEMP,NVidia Temperature C"); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",GPU%d", i + 1); + fprintf(fp, "\n"); + fprintf(fp, "GPU_WATTS,NVidia Power Draw Watts"); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",GPU%d", i + 1); + fprintf(fp, "\n"); + fprintf(fp, "GPU_MHZ,NVidia GPU MHz"); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",GPU%d", i + 1); + fprintf(fp, "\n"); + } + fprintf(fp, "GPU_UTIL,%s", LOOP); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",%d", (int) gpu_util[i].gpu); + fprintf(fp, "\n"); + fprintf(fp, "GPU_MEM,%s", LOOP); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",%d", (int) gpu_util[i].memory); + fprintf(fp, "\n"); + fprintf(fp, "GPU_TEMP,%s", LOOP); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",%d", (int) gpu_temp[i]); + fprintf(fp, "\n"); + fprintf(fp, "GPU_WATTS,%s", LOOP); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",%d", (int) gpu_watts[i] / 1000); + fprintf(fp, "\n"); + fprintf(fp, "GPU_MHZ,%s", LOOP); + for (i = 0; i < gpu_devices; i++) + fprintf(fp, ",%d", (int) gpu_clock[i]); + fprintf(fp, "\n"); + } + } + } +#endif /*NVIDIA_GPU */ + if (show_mhz) { + int padline, lineno, cpuno, col, thrds, cores; +#ifdef POWER + char *clockstr = "clock "; +#define DATACOL 9 +#else + char *clockstr = "cpu MHz"; +#define DATACOL 11 +#endif /* POWER */ + proc_read(P_CPUINFO); + + if (cursed) { + /* + 0123456789012345678 + cpu MHz : 3336.183 Intel + clock : 3425.000000MHz Power + */ + lscpu_init(); +#ifdef POWER + if (lparcfg.smt_mode > lscpu.threads) + thrds = lparcfg.smt_mode; + else +#endif /*POWER*/ + thrds = lscpu.threads; + if (thrds < 1) + thrds = 1; + BANNER(padmhz, "CPU MHz per Core and Thread"); +#ifdef POWER + mvwprintw(padmhz, 1, 10, + "lparcfgSMT=%d lscpu.threads=%d mode=%d [1=AllCPUs 2=Cores 3=Graphs]", + lparcfg.smt_mode, lscpu.threads, show_mhz); +#else /*POWER */ + mvwprintw(padmhz, 1, 10, + "lscpu.threads=%d mode=%d [1=AllCPUs 2=Cores 3=Graphs]", + lscpu.threads, show_mhz); +#endif /*POWER */ + if (show_mhz == 1) + mvwprintw(padmhz, 2, 1, "CPU MHz "); + else + mvwprintw(padmhz, 2, 1, "Core MHz "); + if (show_mhz == 3) + mvwprintw(padmhz, 2, 10, + "---------1---------2---------3---------4---------5---------6 GHz"); + + col = 0; + cpuno = 1; + cores = 0; + padline = 3; + min_mhz = 999999999999999999.0; + max_mhz = 0.0; + for (lineno = 0; lineno < proc[P_CPUINFO].lines; lineno++) { + if (strncmp + (clockstr, proc[P_CPUINFO].line[lineno], + strlen(clockstr)) == 0) { + if (show_mhz == 1 + || ((show_mhz == 2 || show_mhz == 3) + && ((cpuno + 7) % thrds) == 0)) { + cores++; + mhz = 0.0; + sscanf(&proc[P_CPUINFO].line[lineno][DATACOL], + "%f", &mhz); + mvwprintw(padmhz, padline, col, "%3d=%4.0f", + (show_mhz != 1) ? cores : cpuno, + mhz); + if (show_mhz == 3) { + if (mhz > avg_mhz) { + COLOUR wattrset(padmhz, COLOR_PAIR(1)); + } else { + COLOUR wattrset(padmhz, COLOR_PAIR(2)); + } + for (i = 1; i < mhz / 100; i++) + mvwprintw(padmhz, padline, col + 9 + i, + "#"); + COLOUR wattrset(padmhz, COLOR_PAIR(0)); + for (; i < 60; i++) + mvwprintw(padmhz, padline, col + 9 + i, + " "); + } + padline++; + if (padline > 22) { + padline = 3; + col = col + 9; + } + if (mhz != 0.0) { + if (mhz < min_mhz) + min_mhz = mhz; + if (mhz > max_mhz) + max_mhz = mhz; + } + } + cpuno++; + } + if (cpuno > 160) + break; + } + avg_mhz = (min_mhz + max_mhz) / 2; + DISPLAY(padmhz, 23); + } else { + if (!show_rrd) + fprintf(fp, "MHZ,%s", LOOP); + for (lineno = 0; lineno < proc[P_CPUINFO].lines; lineno++) { + if (strncmp + (clockstr, proc[P_CPUINFO].line[lineno], + strlen(clockstr)) == 0) { + mhz = 0.0; + sscanf(&proc[P_CPUINFO].line[lineno][DATACOL], + "%f", &mhz); + if (!show_rrd) + fprintf(fp, ",%.0f", mhz); + } + } + if (!show_rrd) + fprintf(fp, "\n"); + } + } + if (show_memory) { + proc_read(P_MEMINFO); + proc_mem(); + if (cursed) { +#define RAMCOL 18 +#define SWAPCOL 30 +#define HIGHCOL 45 +#define LOWCOL 60 + + BANNER(padmem, "Memory and Swap"); + + COLOUR wattrset(padmem, COLOR_PAIR(1)); + mvwprintw(padmem, 1, 1, "PageSize:%dKB", pagesize / 1024); + COLOUR wattrset(padmem, COLOR_PAIR(0)); + mvwprintw(padmem, 2, 1, "Total in MB"); + mvwprintw(padmem, 3, 1, "Free in MB"); + mvwprintw(padmem, 4, 1, "Free Percent"); + + COLOUR wattrset(padmem, COLOR_PAIR(2)); + mvwprintw(padmem, 1, RAMCOL, "RAM-Memory"); + mvwprintw(padmem, 2, RAMCOL, "%10.1f", + p->mem.memtotal / 1024.0); + mvwprintw(padmem, 3, RAMCOL, "%10.1f", + p->mem.memfree / 1024.0); + mvwprintw(padmem, 4, RAMCOL, "%10.1f%%", + p->mem.memfree == + 0 ? 0.0 : 100.0 * (float) p->mem.memfree / + (float) p->mem.memtotal); + COLOUR wattrset(padmem, COLOR_PAIR(3)); + mvwprintw(padmem, 1, SWAPCOL, "Swap-space"); + mvwprintw(padmem, 2, SWAPCOL, "%10.1f", + p->mem.swaptotal / 1024.0); + mvwprintw(padmem, 3, SWAPCOL, "%10.1f", + p->mem.swapfree / 1024.0); + mvwprintw(padmem, 4, SWAPCOL, "%10.1f%%", + p->mem.swapfree == + 0 ? 0.0 : 100.0 * (float) p->mem.swapfree / + (float) p->mem.swaptotal); + COLOUR wattrset(padmem, COLOR_PAIR(5)); + mvwprintw(padmem, 1, HIGHCOL, "High-Memory"); + if (p->mem.hightotal > 0.0) { + mvwprintw(padmem, 2, HIGHCOL, "%8.1f", + p->mem.hightotal / 1024.0); + mvwprintw(padmem, 3, HIGHCOL, "%8.1f", + p->mem.highfree / 1024.0); + mvwprintw(padmem, 4, HIGHCOL, "%8.1f%%", + p->mem.highfree == + 0 ? 0.0 : 100.0 * (float) p->mem.highfree / + (float) p->mem.hightotal); + } else + mvwprintw(padmem, 2, HIGHCOL, "- not in use"); + COLOUR wattrset(padmem, COLOR_PAIR(6)); + mvwprintw(padmem, 1, LOWCOL, " Low-Memory"); + if (p->mem.lowtotal > 0.0) { + mvwprintw(padmem, 2, LOWCOL, "%8.1f", + p->mem.lowtotal / 1024.0); + mvwprintw(padmem, 3, LOWCOL, "%8.1f", + p->mem.lowfree / 1024.0); + mvwprintw(padmem, 4, LOWCOL, "%8.1f%%", + p->mem.lowfree == + 0 ? 0.0 : 100.0 * (float) p->mem.lowfree / + (float) p->mem.lowtotal); + } else + mvwprintw(padmem, 2, LOWCOL, "- not in use"); + COLOUR wattrset(padmem, COLOR_PAIR(5)); + + + mvwprintw(padmem, 5, 1, + "Linux Kernel Internal Memory (MB)"); +#ifdef LARGEMEM + mvwprintw(padmem, 6, 1, + " Cached=%10.1f Active=%10.1f", + p->mem.cached / 1024.0, p->mem.active / 1024.0); +#else + mvwprintw(padmem, 6, 1, + " Shared=%10.1f Cached=%10.1f Active=%10.1f", + p->mem.memshared / 1024.0, + p->mem.cached / 1024.0, p->mem.active / 1024.0); + mvwprintw(padmem, 5, 68, "MB"); + mvwprintw(padmem, 6, 55, "bigfree=%10.1f", + p->mem.bigfree / 1024); +#endif /*LARGEMEM*/ + mvwprintw(padmem, 7, 1, + "Buffers=%10.1f Swapcached=%10.1f Inactive =%10.1f", + p->mem.buffers / 1024.0, + p->mem.swapcached / 1024.0, + p->mem.inactive / 1024.0); + + mvwprintw(padmem, 8, 1, + "Dirty =%10.1f Writeback =%10.1f Mapped =%10.1f", + p->mem.dirty / 1024.0, p->mem.writeback / 1024.0, + p->mem.mapped / 1024.0); + mvwprintw(padmem, 9, 1, + "Slab =%10.1f Commit_AS =%10.1f PageTables=%10.1f", + p->mem.slab / 1024.0, + p->mem.committed_as / 1024.0, + p->mem.pagetables / 1024.0); +#ifdef POWER + if (!show_lpar) /* check if already called above */ + proc_lparcfg(); + if (lparcfg.cmo_enabled == 0) + mvwprintw(padmem, 10, 1, "AMS is not active"); + else + mvwprintw(padmem, 10, 1, + "AMS id=%d Weight=%-3d pmem=%ldMB hpi=%.1f/s hpit=%.1f(sec) Pool=%ldMB Loan=%ldKB ", + (int) lparcfg.entitled_memory_pool_number, + (int) lparcfg.entitled_memory_weight, + (long) (lparcfg.backing_memory) / 1024 / + 1024, + (double) (lparcfg.cmo_faults_diff) / elapsed, + (double) (lparcfg.cmo_fault_time_usec_diff) / + 1000 / 1000 / elapsed, + (long) lparcfg.entitled_memory_pool_size / + 1024 / 1024, + (long) lparcfg.entitled_memory_loan_request / + 1024); + + COLOUR wattrset(padmem, COLOR_PAIR(0)); + DISPLAY(padmem, 11); +#else /* POWER */ + COLOUR wattrset(padmem, COLOR_PAIR(0)); + DISPLAY(padmem, 10); +#endif /* POWER */ + } else { + + if (show_rrd) + str_p = + "rrdtool update mem.rrd %s:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f\n"; + else + str_p = + "MEM,%s,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n"; + fprintf(fp, str_p, LOOP, p->mem.memtotal / 1024.0, + p->mem.hightotal / 1024.0, + p->mem.lowtotal / 1024.0, + p->mem.swaptotal / 1024.0, p->mem.memfree / 1024.0, + p->mem.highfree / 1024.0, p->mem.lowfree / 1024.0, + p->mem.swapfree / 1024.0, + p->mem.memshared / 1024.0, p->mem.cached / 1024.0, + p->mem.active / 1024.0, +#ifdef LARGEMEM + -1.0, +#else + p->mem.bigfree / 1024.0, +#endif /*LARGEMEM*/ + p->mem.buffers / 1024.0, + p->mem.swapcached / 1024.0, + p->mem.inactive / 1024.0); +#ifdef POWER + if (lparcfg.cmo_enabled != 0) { + if (!show_rrd) + fprintf(fp, + "MEMAMS,%s,%d,%d,%.1f,%.3lf,0,0,0,%.1f,%ld,%ld,%ld\n", + LOOP, + (int) lparcfg.entitled_memory_pool_number, + (int) lparcfg.entitled_memory_weight, + (float) (lparcfg.cmo_faults_diff) / + elapsed, + (float) (lparcfg. + cmo_fault_time_usec_diff) / 1000 / + 1000 / elapsed, + /* three zeros here */ + (float) (lparcfg.backing_memory) / 1024 / + 1024, lparcfg.cmo_page_size / 1024, + lparcfg.entitled_memory_pool_size / 1024 / + 1024, + lparcfg.entitled_memory_loan_request / + 1024); + } +#ifdef EXPERIMENTAL + if (!show_rrd) + fprintf(fp, + "MEMEXPERIMENTAL,%s,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld\n", + LOOP, (long) lparcfg.DesEntCap, + (long) lparcfg.DesProcs, + (long) lparcfg.DesVarCapWt, + (long) lparcfg.DedDonMode, + (long) lparcfg.group, (long) lparcfg.pool, + (long) lparcfg.entitled_memory, + (long) lparcfg.entitled_memory_group_number, + (long) lparcfg. + unallocated_entitled_memory_weight, + (long) lparcfg. + unallocated_io_mapping_entitlement); +#endif /* EXPERIMENTAL */ +#endif /* POWER */ + } +/* for testing large page + p->mem.hugefree = 250; + p->mem.hugetotal = 1000; + p->mem.hugesize = 16*1024; +*/ + } + if (show_large) { + proc_read(P_MEMINFO); + proc_mem(); + if (cursed) { + BANNER(padlarge, "Large (Huge) Page"); + if (p->mem.hugetotal > 0) { + if (p->mem.hugetotal - p->mem.hugefree > huge_peak) + huge_peak = p->mem.hugetotal - p->mem.hugefree; + mvwprintw(padlarge, 1, 1, + "Total Pages=%7ld 100.0%% Huge Page Size =%ld KB", + p->mem.hugetotal, p->mem.hugesize); + mvwprintw(padlarge, 2, 1, + "Used Pages=%7ld %5.1f%% Used Pages Peak=%-8ld", + (long) (p->mem.hugetotal - p->mem.hugefree), + (p->mem.hugetotal - + p->mem.hugefree) / + (float) p->mem.hugetotal * 100.0, huge_peak); + mvwprintw(padlarge, 3, 1, "Free Pages=%7ld %5.1f%%", + p->mem.hugefree, + p->mem.hugefree / (float) p->mem.hugetotal * + 100.0); + } else { + mvwprintw(padlarge, 1, 1, " There are no Huge Pages"); + mvwprintw(padlarge, 2, 1, " - see /proc/meminfo"); + } + DISPLAY(padlarge, 4); + } else { + if (p->mem.hugetotal > 0) { + if (first_huge == 1) { + first_huge = 0; + fprintf(fp, + "HUGEPAGES,Huge Page Use %s,HugeTotal,HugeFree,HugeSizeMB\n", + run_name); + } + fprintf(fp, "HUGEPAGES,%s,%ld,%ld,%.1f\n", + LOOP, + p->mem.hugetotal, + p->mem.hugefree, p->mem.hugesize / 1024.0); + } + } + } + if (show_vm) { +#define VMDELTA(variable) (p->vm.variable - q->vm.variable) +#define VMCOUNT(variable) (p->vm.variable ) + ret = read_vmstat(); + if (cursed) { + BANNER(padpage, "Virtual Memory"); + + COLOUR wattrset(padpage, COLOR_PAIR(6)); + if (ret < 0) { + mvwprintw(padpage, 2, 2, + "Virtual Memory stats not supported with this kernel"); + mvwprintw(padpage, 3, 2, + "/proc/vmstat only seems to appear in 2.6 onwards"); + + } else { + if (vm_first_time) { + mvwprintw(padpage, 2, 2, + "Please wait - collecting data"); + vm_first_time = 0; + } else { + mvwprintw(padpage, 1, 0, + "nr_dirty =%9lld pgpgin =%8lld", + VMCOUNT(nr_dirty), VMDELTA(pgpgin)); + mvwprintw(padpage, 2, 0, + "nr_writeback=%9lld pgpgout =%8lld", + VMCOUNT(nr_writeback), VMDELTA(pgpgout)); + mvwprintw(padpage, 3, 0, + "nr_unstable =%9lld pgpswpin =%8lld", + VMCOUNT(nr_unstable), VMDELTA(pswpin)); + mvwprintw(padpage, 4, 0, + "nr_table_pgs=%9lld pgpswpout =%8lld", + VMCOUNT(nr_page_table_pages), + VMDELTA(pswpout)); + mvwprintw(padpage, 5, 0, + "nr_mapped =%9lld pgfree =%8lld", + VMCOUNT(nr_mapped), VMDELTA(pgfree)); + mvwprintw(padpage, 6, 0, + "nr_slab =%9lld pgactivate =%8lld", + VMCOUNT(nr_slab), VMDELTA(pgactivate)); + mvwprintw(padpage, 7, 0, + " pgdeactivate=%8lld", + VMDELTA(pgdeactivate)); + mvwprintw(padpage, 8, 0, + "allocstall =%9lld pgfault =%8lld kswapd_steal =%7lld", + VMDELTA(allocstall), VMDELTA(pgfault), + VMDELTA(kswapd_steal)); + mvwprintw(padpage, 9, 0, + "pageoutrun =%9lld pgmajfault =%8lld kswapd_inodesteal=%7lld", + VMDELTA(pageoutrun), VMDELTA(pgmajfault), + VMDELTA(kswapd_inodesteal)); + mvwprintw(padpage, 10, 0, + "slabs_scanned=%8lld pgrotated =%8lld pginodesteal =%7lld", + VMDELTA(slabs_scanned), + VMDELTA(pgrotated), + VMDELTA(pginodesteal)); + + + + mvwprintw(padpage, 1, 46, + " High Normal DMA"); + mvwprintw(padpage, 2, 46, + "alloc %7lld%7lld%7lld", + VMDELTA(pgalloc_high), + VMDELTA(pgalloc_normal), + VMDELTA(pgalloc_dma)); + mvwprintw(padpage, 3, 46, + "refill %7lld%7lld%7lld", + VMDELTA(pgrefill_high), + VMDELTA(pgrefill_normal), + VMDELTA(pgrefill_dma)); + mvwprintw(padpage, 4, 46, + "steal %7lld%7lld%7lld", + VMDELTA(pgsteal_high), + VMDELTA(pgsteal_normal), + VMDELTA(pgsteal_dma)); + mvwprintw(padpage, 5, 46, + "scan_kswapd%7lld%7lld%7lld", + VMDELTA(pgscan_kswapd_high), + VMDELTA(pgscan_kswapd_normal), + VMDELTA(pgscan_kswapd_dma)); + mvwprintw(padpage, 6, 46, + "scan_direct%7lld%7lld%7lld", + VMDELTA(pgscan_direct_high), + VMDELTA(pgscan_direct_normal), + VMDELTA(pgscan_direct_dma)); + } + } + COLOUR wattrset(padpage, COLOR_PAIR(0)); + DISPLAY(padpage, 11); + } else { + if (ret < 0) { + show_vm = 0; + } else if (vm_first_time) { + vm_first_time = 0; + fprintf(fp, + "VM,Paging and Virtual Memory,nr_dirty,nr_writeback,nr_unstable,nr_page_table_pages,nr_mapped,nr_slab,pgpgin,pgpgout,pswpin,pswpout,pgfree,pgactivate,pgdeactivate,pgfault,pgmajfault,pginodesteal,slabs_scanned,kswapd_steal,kswapd_inodesteal,pageoutrun,allocstall,pgrotated,pgalloc_high,pgalloc_normal,pgalloc_dma,pgrefill_high,pgrefill_normal,pgrefill_dma,pgsteal_high,pgsteal_normal,pgsteal_dma,pgscan_kswapd_high,pgscan_kswapd_normal,pgscan_kswapd_dma,pgscan_direct_high,pgscan_direct_normal,pgscan_direct_dma\n"); + } + if (show_rrd) + str_p = "rrdtool update vm.rrd %s" + ":%lld:%lld:%lld:%lld:%lld" + ":%lld:%lld:%lld:%lld:%lld" + ":%lld:%lld:%lld:%lld:%lld" + ":%lld:%lld:%lld:%lld:%lld" + ":%lld:%lld:%lld:%lld:%lld" + ":%lld:%lld:%lld:%lld:%lld" + ":%lld:%lld:%lld:%lld:%lld" ":%lld:%lld\n"; + else + str_p = "VM,%s" + ",%lld,%lld,%lld,%lld,%lld" + ",%lld,%lld,%lld,%lld,%lld" + ",%lld,%lld,%lld,%lld,%lld" + ",%lld,%lld,%lld,%lld,%lld" + ",%lld,%lld,%lld,%lld,%lld" + ",%lld,%lld,%lld,%lld,%lld" + ",%lld,%lld,%lld,%lld,%lld" ",%lld,%lld\n"; + + fprintf(fp, str_p, + LOOP, + VMCOUNT(nr_dirty), + VMCOUNT(nr_writeback), + VMCOUNT(nr_unstable), + VMCOUNT(nr_page_table_pages), + VMCOUNT(nr_mapped), + VMCOUNT(nr_slab), + VMDELTA(pgpgin), + VMDELTA(pgpgout), + VMDELTA(pswpin), + VMDELTA(pswpout), + VMDELTA(pgfree), + VMDELTA(pgactivate), + VMDELTA(pgdeactivate), + VMDELTA(pgfault), + VMDELTA(pgmajfault), + VMDELTA(pginodesteal), + VMDELTA(slabs_scanned), + VMDELTA(kswapd_steal), + VMDELTA(kswapd_inodesteal), + VMDELTA(pageoutrun), + VMDELTA(allocstall), + VMDELTA(pgrotated), + VMDELTA(pgalloc_high), + VMDELTA(pgalloc_normal), + VMDELTA(pgalloc_dma), + VMDELTA(pgrefill_high), + VMDELTA(pgrefill_normal), + VMDELTA(pgrefill_dma), + VMDELTA(pgsteal_high), + VMDELTA(pgsteal_normal), + VMDELTA(pgsteal_dma), + VMDELTA(pgscan_kswapd_high), + VMDELTA(pgscan_kswapd_normal), + VMDELTA(pgscan_kswapd_dma), + VMDELTA(pgscan_direct_high), + VMDELTA(pgscan_direct_normal), + VMDELTA(pgscan_direct_dma)); + } + } + if (show_kernel) { + proc_read(P_STAT); + proc_cpu(); + proc_read(P_UPTIME); + proc_read(P_LOADAVG); + proc_kernel(); + if (cursed) { + BANNER(padker, "Kernel and Load Average"); +#define MORECOL 21 +#define LOADCOL 41 +#define BOOTCOL 55 + COLOUR wattrset(padker, COLOR_PAIR(1)); + mvwprintw(padker, 1, 0, "Global-CPU-Stats---->"); + mvwprintw(padker, 2, 0, " /proc/stat line 1"); + mvwprintw(padker, 3, 0, "%ld ticks per second", ticks); + mvwprintw(padker, 4, 0, "100%%=1 CPUcoreThread"); + COLOUR wattrset(padker, COLOR_PAIR(2)); + mvwprintw(padker, 5, 0, "%8lld RunQueue", + p->cpu_total.running); + mvwprintw(padker, 6, 0, "%8lld Blocked", + p->cpu_total.blocked); + mvwprintw(padker, 7, 0, "%10.1f Context", + (float) (p->cpu_total.ctxt - + q->cpu_total.ctxt) / elapsed); + mvwprintw(padker, 8, 0, " Switch"); + mvwprintw(padker, 9, 0, "%10.1f Forks", + (float) (p->cpu_total.procs - + q->cpu_total.procs) / elapsed); + mvwprintw(padker, 10, 0, "%10.1f Interrupts", + (float) (p->cpu_total.intr - + q->cpu_total.intr) / elapsed); + + COLOUR wattrset(padker, COLOR_PAIR(1)); + mvwprintw(padker, 1, MORECOL, "%8.1f%% user", + (float) (RAWTOTAL(user)) / elapsed); + mvwprintw(padker, 2, MORECOL, "%8.1f%% user_nice", + (float) (RAWTOTAL(nice)) / elapsed); + mvwprintw(padker, 3, MORECOL, "%8.1f%% system", + (float) (RAWTOTAL(sys)) / elapsed); + mvwprintw(padker, 4, MORECOL, "%8.1f%% idle", + (float) (RAWTOTAL(idle)) / elapsed); + mvwprintw(padker, 5, MORECOL, "%8.1f%% iowait", + (float) (RAWTOTAL(wait)) / elapsed); + mvwprintw(padker, 6, MORECOL, "%8.1f%% irq", + (float) (RAWTOTAL(irq)) / elapsed); + mvwprintw(padker, 7, MORECOL, "%8.1f%% softirq", + (float) (RAWTOTAL(softirq)) / elapsed); + mvwprintw(padker, 8, MORECOL, "%8.1f%% steal", + (float) (RAWTOTAL(steal)) / elapsed); + mvwprintw(padker, 9, MORECOL, "%8.1f%% guest", + (float) (RAWTOTAL(guest)) / elapsed); + mvwprintw(padker, 10, MORECOL, "%8.1f%% guest_nice", + (float) (RAWTOTAL(guest_nice)) / elapsed); + + COLOUR wattrset(padker, COLOR_PAIR(3)); + mvwprintw(padker, 1, LOADCOL, "Load Average"); + mvwprintw(padker, 2, LOADCOL, " 1 mins %5.2f", + (float) p->cpu_total.mins1); + mvwprintw(padker, 3, LOADCOL, " 5 mins %5.2f", + (float) p->cpu_total.mins5); + mvwprintw(padker, 4, LOADCOL, "15 mins %5.2f", + (float) p->cpu_total.mins15); + + + COLOUR wattrset(padker, COLOR_PAIR(5)); + mvwprintw(padker, 1, BOOTCOL, "CPU use since boottime"); + + updays = p->cpu_total.uptime / 60 / 60 / 24; + uphours = + (p->cpu_total.uptime - + updays * 60 * 60 * 24) / 60 / 60; + upmins = + (p->cpu_total.uptime - updays * 60 * 60 * 24 - + uphours * 60 * 60) / 60; + mvwprintw(padker, 2, BOOTCOL, "Uptime Days Hours Mins"); + mvwprintw(padker, 3, BOOTCOL, "Uptime %4ld %5ld %4ld", + updays, uphours, upmins); + + updays = p->cpu_total.idletime / 60 / 60 / 24 / cpus; + uphours = + (p->cpu_total.idletime - + updays * 60 * 60 * 24) / 60 / 60 / cpus; + upmins = + (p->cpu_total.idletime - updays * 60 * 60 * 24 - + uphours * 60 * 60) / 60 / cpus; + mvwprintw(padker, 4, BOOTCOL, "Idle %4ld %5ld %4ld", + updays, uphours, upmins); + + average = + (p->cpu_total.uptime - + p->cpu_total.idletime) / p->cpu_total.uptime * 100.0; + if (average > 0.0) + mvwprintw(padker, 5, BOOTCOL, + "Average CPU use=%6.2f%%", average); + else + mvwprintw(padker, 5, BOOTCOL, "Uptime has overflowed"); + mvwprintw(padker, 7, BOOTCOL, "%d CPU core threads", cpus); + mvwprintw(padker, 9, BOOTCOL, "Boot time %d", boottime); + mvwprintw(padker,10, BOOTCOL, "%s", boottime_str); + COLOUR wattrset(padker, COLOR_PAIR(0)); + DISPLAY(padker, 11); + } else { + if (proc_first_time) { + q->cpu_total.ctxt = p->cpu_total.ctxt; + q->cpu_total.procs = p->cpu_total.procs; + proc_first_time = 0; + } + if (show_rrd) + str_p = + "rrdtool update proc.rrd %s:%.0f:%.0f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f\n"; + else + str_p = + "PROC,%s,%.0f,%.0f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n"; + + /* These "-1"'s looks bad but it keeps the nmon for AIX format */ + /* The stats are not available in Linux . . . unless you know better! */ + fprintf(fp, str_p, LOOP, (float) p->cpu_total.running, /*runqueue */ + (float) p->cpu_total.blocked, /*swapin (# of processes waiting for IO completion */ + /*pswitch */ + (float) (p->cpu_total.ctxt - q->cpu_total.ctxt) / elapsed, -1.0, /*syscall */ + -1.0, /*read */ + -1.0, /*write */ + /*fork */ + (float) (p->cpu_total.procs - q->cpu_total.procs) / elapsed, -1.0, /*exec */ + -1.0, /*sem */ + -1.0); /*msg */ + } + } + + if (show_nfs) { + proc_read(P_NFS); + proc_read(P_NFSD); + proc_nfs(); + + if (cursed) { + if (nfs_first_time) { + memcpy(&q->nfs, &p->nfs, sizeof(struct nfs_stat)); + nfs_first_time = 0; + } + if (nfs_clear) { + nfs_clear = 0; + for (i = 0; i < 25; i++) + mvwprintw(padnfs, i, 0, + " "); + } + BANNER(padnfs, + "Network Filesystem (NFS) I/O Operations per second"); + if (show_nfs == 1) { + if (nfs_v2c_found || nfs_v2s_found) + mvwprintw(padnfs, 1, 0, + " Version 2 Client Server"); + else + mvwprintw(padnfs, 1, 0, " Version 2 not active"); + + if (nfs_v3c_found || nfs_v3s_found) + mvwprintw(padnfs, 1, 41, + "Version 3 Client Server"); + else + mvwprintw(padnfs, 1, 41, " Version 3 not active"); + } + if (show_nfs == 2) { + if (nfs_v4c_found) + mvwprintw(padnfs, 1, 0, + " Version 4 Client (%d Stats found)", + nfs_v4c_names_count); + else + mvwprintw(padnfs, 1, 0, + " Version 4 Client side not active"); + } + if (show_nfs == 3) { + if (nfs_v4s_found) + mvwprintw(padnfs, 1, 0, + " Version 4 Server (%d Stats found)", + nfs_v4s_names_count); + else + mvwprintw(padnfs, 1, 0, + " Version 4 Server side not active"); + } +#define NFS_TOTAL(member) (double)(p->member) +#define NFS_DELTA(member) (((double)(p->member - q->member)/elapsed)) + v2c_total = 0; + v2s_total = 0; + v3c_total = 0; + v3s_total = 0; + v4c_total = 0; + v4s_total = 0; + if (nfs_v3c_found || nfs_v3s_found) { + for (i = 0; i < 18; i++) { /* NFS V2 Client & Server */ + if (show_nfs == 1) + mvwprintw(padnfs, 2 + i, 3, "%12s %8.1f %8.1f", + nfs_v2_names[i], + NFS_DELTA(nfs.v2c[i]), + NFS_DELTA(nfs.v2s[i])); + v2c_total += NFS_DELTA(nfs.v2c[i]); + v2s_total += NFS_DELTA(nfs.v2s[i]); + } + } + if (nfs_v3c_found || nfs_v3s_found) { + for (i = 0; i < 22; i++) { /* NFS V3 Client & Server */ + if (show_nfs == 1) + mvwprintw(padnfs, 2 + i, 41, + "%12s %8.1f %8.1f", nfs_v3_names[i], + NFS_DELTA(nfs.v3c[i]), + NFS_DELTA(nfs.v3s[i])); + v3c_total += NFS_DELTA(nfs.v3c[i]); + v3s_total += NFS_DELTA(nfs.v3s[i]); + } + } + + if (nfs_v4c_found) { + for (i = 0; i < 18; i++) { /* NFS V4 Client */ + if (show_nfs == 2) { + mvwprintw(padnfs, 2 + i, 0, "%12s%7.1f", + nfs_v4c_names[i], + NFS_DELTA(nfs.v4c[i])); + } + v4c_total += NFS_DELTA(nfs.v4c[i]); + } + for (i = 18; i < 35; i++) { /* NFS V4 Client */ + if (show_nfs == 2) { + mvwprintw(padnfs, 2 + i - 18, 20, "%12s%7.1f", + nfs_v4c_names[i], + NFS_DELTA(nfs.v4c[i])); + } + v4c_total += NFS_DELTA(nfs.v4c[i]); + } + } + + if (nfs_v4s_found) { + for (i = 0; i < 18; i++) { /* NFS V4 Server */ + if (show_nfs == 3) { + mvwprintw(padnfs, 2 + i, 0, "%12s%7.1f", + nfs_v4s_names[i], + NFS_DELTA(nfs.v4s[i])); + } + v4s_total += NFS_DELTA(nfs.v4s[i]); + } + for (i = 18; i < 36; i++) { /* NFS V4 Server */ + if (show_nfs == 3) { + mvwprintw(padnfs, 2 + i - 18, 19, "%12s%7.1f", + nfs_v4s_names[i], + NFS_DELTA(nfs.v4s[i])); + } + v4s_total += NFS_DELTA(nfs.v4s[i]); + } + for (i = 36; i < 54 && i < nfs_v4s_names_count; i++) { /* NFS V4 Server */ + if (show_nfs == 3) { + mvwprintw(padnfs, 2 + i - 36, 39, "%12s%7.1f", + nfs_v4s_names[i], + NFS_DELTA(nfs.v4s[i])); + } + v4s_total += NFS_DELTA(nfs.v4s[i]); + } + for (i = 54; i <= 70 && i < nfs_v4s_names_count; i++) { /* NFS V4 Server */ + if (show_nfs == 3) { + mvwprintw(padnfs, 2 + i - 54, 59, "%12s%7.1f", + nfs_v4s_names[i], + NFS_DELTA(nfs.v4s[i])); + } + v4s_total += NFS_DELTA(nfs.v4s[i]); + } + } + mvwprintw(padnfs, 2 + 18, 1, + "--NFS-Totals->---Client----Server--"); + /* if(nfs_v2c_found || nfs_v2s_found) */ + mvwprintw(padnfs, 2 + 19, 1, "NFSv2 Totals->%9.1f %9.1f", + v2c_total, v2s_total); + /* if(nfs_v3c_found || nfs_v3s_found) */ + mvwprintw(padnfs, 2 + 20, 1, "NFSv3 Totals->%9.1f %9.1f", + v3c_total, v3s_total); + /* if(nfs_v4c_found || nfs_v4s_found) */ + mvwprintw(padnfs, 2 + 21, 1, "NFSv4 Totals->%9.1f %9.1f", + v4c_total, v4s_total); + + DISPLAY(padnfs, 24); + } else { + if (nfs_first_time && !show_rrd) { + if (nfs_v2c_found) { + fprintf(fp, "NFSCLIV2,NFS Client v2"); + for (i = 0; i < 18; i++) + fprintf(fp, ",%s", nfs_v2_names[i]); + fprintf(fp, "\n"); + } + if (nfs_v2s_found) { + fprintf(fp, "NFSSVRV2,NFS Server v2"); + for (i = 0; i < 18; i++) + fprintf(fp, ",%s", nfs_v2_names[i]); + fprintf(fp, "\n"); + } + + if (nfs_v3c_found) { + fprintf(fp, "NFSCLIV3,NFS Client v3"); + for (i = 0; i < 22; i++) + fprintf(fp, ",%s", nfs_v3_names[i]); + fprintf(fp, "\n"); + } + if (nfs_v3s_found) { + fprintf(fp, "NFSSVRV3,NFS Server v3"); + for (i = 0; i < 22; i++) + fprintf(fp, ",%s", nfs_v3_names[i]); + fprintf(fp, "\n"); + } + + if (nfs_v4c_found) { + fprintf(fp, "NFSCLIV4,NFS Client v4"); + for (i = 0; i < nfs_v4c_names_count; i++) + fprintf(fp, ",%s", nfs_v4c_names[i]); + fprintf(fp, "\n"); + } + if (nfs_v4s_found) { + fprintf(fp, "NFSSVRV4,NFS Server v4"); + for (i = 0; i < nfs_v4s_names_count; i++) + fprintf(fp, ",%s", nfs_v4s_names[i]); + fprintf(fp, "\n"); + } + memcpy(&q->nfs, &p->nfs, sizeof(struct nfs_stat)); + nfs_first_time = 0; + } + if (nfs_v2c_found) { + fprintf(fp, + show_rrd ? "rrdtool update nfscliv2.rrd %s" : + "NFSCLIV2,%s", LOOP); + for (i = 0; i < 18; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (double) NFS_DELTA(nfs.v2c[i])); + } + fprintf(fp, "\n"); + } + if (nfs_v2s_found) { + fprintf(fp, + show_rrd ? "rrdtool update nfsvrv2.rrd %s" : + "NFSSVRV2,%s", LOOP); + for (i = 0; i < 18; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (double) NFS_DELTA(nfs.v2s[i])); + } + fprintf(fp, "\n"); + } + if (nfs_v3c_found) { + fprintf(fp, + show_rrd ? "rrdtool update nfscliv3.rrd %s" : + "NFSCLIV3,%s", LOOP); + for (i = 0; i < 22; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (double) NFS_DELTA(nfs.v3c[i])); + } + fprintf(fp, "\n"); + } + if (nfs_v3s_found) { + fprintf(fp, + show_rrd ? "rrdtool update nfsvrv3.rrd %s" : + "NFSSVRV3,%s", LOOP); + for (i = 0; i < 22; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (double) NFS_DELTA(nfs.v3s[i])); + } + fprintf(fp, "\n"); + } + + if (nfs_v4c_found) { + fprintf(fp, + show_rrd ? "rrdtool update nfscliv4.rrd %s" : + "NFSCLIV4,%s", LOOP); + for (i = 0; i < nfs_v4c_names_count; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (double) NFS_DELTA(nfs.v4c[i])); + } + fprintf(fp, "\n"); + } + if (nfs_v4s_found) { + fprintf(fp, + show_rrd ? "rrdtool update nfsvrv4.rrd %s" : + "NFSSVRV4,%s", LOOP); + for (i = 0; i < nfs_v4c_names_count; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (double) NFS_DELTA(nfs.v4s[i])); + } + fprintf(fp, "\n"); + } + } + } + if (show_net) { + if (cursed) { + BANNER(padnet, "Network I/O"); +#define RKB 9 +#define TKB 19 +#define PIN 30 +#define POUT 37 +#define SIN 45 +#define SOUT 52 +#define PKHEAD 60 +#define PKIN 66 +#define PKOUT 71 +/* + 1 2 3 4 5 6 7 + 01234567890123456789012345678901234567890123456789012345678901234567890123456789 + mvwprintw(padnet,1, 0, "I/F Name Recv=KB/s Trans=KB/s packin packout insize outsize Peak->Recv Trans"); +*/ + COLOUR wattrset(padnet, COLOR_PAIR(0)); + mvwprintw(padnet, 1, 0, "I/F Name"); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 1, RKB, "Recv=KB/s"); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 1, TKB, "Trans=KB/s"); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 1, PIN, "packin"); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 1, POUT, "packout"); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 1, SIN, "insize"); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 1, SOUT, "outsize"); + COLOUR wattrset(padnet, COLOR_PAIR(0)); + mvwprintw(padnet, 1, PKHEAD, "Peak->"); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 1, PKIN, "Recv"); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 1, PKOUT, "Trans"); + COLOUR wattrset(padnet, COLOR_PAIR(0)); + } + proc_net(); + for (i = 0; i < networks; i++) { + +#define IFDELTA(member) ((float)( (q->ifnets[i].member > p->ifnets[i].member) ? 0 : (p->ifnets[i].member - q->ifnets[i].member)/elapsed) ) +#define IFDELTA_ZERO(member1,member2) ((IFDELTA(member1) == 0) || (IFDELTA(member2)== 0)? 0.0 : IFDELTA(member1)/IFDELTA(member2) ) + + if (net_read_peak[i] < IFDELTA(if_ibytes) / 1024.0) + net_read_peak[i] = IFDELTA(if_ibytes) / 1024.0; + if (net_write_peak[i] < IFDELTA(if_obytes) / 1024.0) + net_write_peak[i] = IFDELTA(if_obytes) / 1024.0; +/* + 1 2 3 4 5 6 7 +01234567890123456789012345678901234567890123456789012345678901234567890123456789 +I/F Name Recv=KB/s Trans=KB/s packin packout insize outsize Peak->Recv Trans + eth3 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + lo 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + eth2 0.5 0.2 8.5 0.5 64.0 314.0 53.4 24.6 + eth1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 + eth0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +*/ + if (cursed) { + COLOUR wattrset(padnet, COLOR_PAIR(0)); + mvwprintw(padnet, 2 + i, 0, "%8s", + &p->ifnets[i].if_name[0]); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 2 + i, RKB, "%8.1f", + IFDELTA(if_ibytes) / 1024.0); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 2 + i, TKB, "%8.1f", + IFDELTA(if_obytes) / 1024.0); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 2 + i, PIN, "%7.1f", + IFDELTA(if_ipackets)); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 2 + i, POUT, "%7.1f", + IFDELTA(if_opackets)); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 2 + i, SIN, "%7.1f", + IFDELTA_ZERO(if_ibytes, if_ipackets)); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 2 + i, SOUT, "%7.1f", + IFDELTA_ZERO(if_obytes, if_opackets)); + COLOUR wattrset(padnet, COLOR_PAIR(2)); + mvwprintw(padnet, 2 + i, PKIN - 4, "%8.1f", + net_read_peak[i]); + COLOUR wattrset(padnet, COLOR_PAIR(3)); + mvwprintw(padnet, 2 + i, PKOUT, "%8.1f", + net_write_peak[i]); + } + } + DISPLAY(padnet, networks + 2); + if (!cursed) { + fprintf(fp, + show_rrd ? "rrdtool update net.rrd %s" : "NET,%s", + LOOP); + for (i = 0; i < networks; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + IFDELTA(if_ibytes) / 1024.0); + } + for (i = 0; i < networks; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + IFDELTA(if_obytes) / 1024.0); + } + fprintf(fp, "\n"); + fprintf(fp, + show_rrd ? "rrdtool update netpacket.rrd %s" : + "NETPACKET,%s", LOOP); + for (i = 0; i < networks; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + IFDELTA(if_ipackets)); + } + for (i = 0; i < networks; i++) { + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + IFDELTA(if_opackets)); + } + fprintf(fp, "\n"); + } + } + errors = 0; + for (i = 0; i < networks; i++) { + errors += p->ifnets[i].if_ierrs - q->ifnets[i].if_ierrs + + p->ifnets[i].if_oerrs - q->ifnets[i].if_oerrs + + p->ifnets[i].if_ocolls - q->ifnets[i].if_ocolls; + } + if (errors) + show_neterror = 3; + if (show_neterror) { + if (cursed) { + BANNER(padneterr, "Network Error Counters"); + mvwprintw(padneterr, 1, 0, + "I/F Name iErrors iDrop iOverrun iFrame oErrors oDrop oOverrun oCarrier oColls "); + } + for (i = 0; i < networks; i++) { + CURSE mvwprintw(padneterr, 2 + i, 0, + "%8s %7lu %7lu %7lu %7lu %7lu %7lu %7lu %7lu %7lu", + &p->ifnets[i].if_name[0], + p->ifnets[i].if_ierrs, + p->ifnets[i].if_idrop, + p->ifnets[i].if_ififo, + p->ifnets[i].if_iframe, + p->ifnets[i].if_oerrs, + p->ifnets[i].if_odrop, + p->ifnets[i].if_ofifo, + p->ifnets[i].if_ocarrier, + p->ifnets[i].if_ocolls); + + } + DISPLAY(padneterr, networks + 2); + if (show_neterror > 0) + show_neterror--; + } +#ifdef JFS + if (show_jfs) { + if (cursed) { + BANNER(padjfs, "File Systems"); + mvwprintw(padjfs, 1, 0, + "Filesystem SizeMB FreeMB Use%% Type MountPoint"); + + for (k = 0; k < jfses; k++) { + fs_size = 0; + fs_bsize = 0; + fs_free = 0; + fs_size_used = 100.0; + if (jfs[k].mounted) { + if (!strncmp(jfs[k].name, "/proc/", 6) /* sub directorys have to be fake too */ + ||!strncmp(jfs[k].name, "/sys/", 5) + || !strncmp(jfs[k].name, "/dev/", 5) + || !strncmp(jfs[k].name, "/proc", 6) /* one more than the string to ensure the NULL */ + ||!strncmp(jfs[k].name, "/sys", 5) + || !strncmp(jfs[k].name, "/dev", 5) + || !strncmp(jfs[k].name, "/rpc_pipe", 10) + ) { /* /proc gives invalid/insane values */ + mvwprintw(padjfs, 2 + k, 0, "%-14s", + jfs[k].name); + mvwprintw(padjfs, 2 + k, 27, "-"); + mvwprintw(padjfs, 2 + k, 35, "-"); + mvwprintw(padjfs, 2 + k, 41, "-"); + COLOUR wattrset(padjfs, COLOR_PAIR(4)); + mvwprintw(padjfs, 2 + k, 43, + "%-8s not a real filesystem", + jfs[k].type); + COLOUR wattrset(padjfs, COLOR_PAIR(0)); + } else { + statfs_buffer.f_blocks = 0; + if ((ret = + fstatfs(jfs[k].fd, + &statfs_buffer)) != -1) { + if (statfs_buffer.f_blocks != 0) { + /* older Linux seemed to always report in 4KB blocks but + newer Linux release use the f_bsize block sizes but + the man statfs docs the field as the natural I/O size so + the blocks reported here are ambigous in size */ + if (statfs_buffer.f_bsize == 0) + fs_bsize = 4.0 * 1024.0; + else + fs_bsize = statfs_buffer.f_bsize; + /* convert blocks to MB */ + fs_size = + (float) statfs_buffer.f_blocks * + fs_bsize / 1024.0 / 1024.0; + + /* find the best size info available f_bavail is like df reports + otherwise use f_bsize (this includes inode blocks) */ + if (statfs_buffer.f_bavail == 0) + fs_free = + (float) statfs_buffer.f_bfree * + fs_bsize / 1024.0 / 1024.0; + else + fs_free = + (float) statfs_buffer. + f_bavail * fs_bsize / 1024.0 / + 1024.0; + + /* this is a percentage */ + fs_size_used = + (fs_size - + (float) statfs_buffer.f_bfree * + fs_bsize / 1024.0 / 1024.0) / + fs_size * 100.0; + /* try to get the same number as df using kludge */ + /*fs_size_used += 1.0; */ + if (fs_size_used > 100.0) + fs_size_used = 100.0; + + if ((i = strlen(jfs[k].device)) < 20) + str_p = &jfs[k].device[0]; + else { + str_p = &jfs[k].device[i - 20]; + } + mvwprintw(padjfs, 2 + k, 0, + "%-20s %7.0f %7.0f %4.0f%% %-8s %s", + str_p, fs_size, fs_free, + ceil(fs_size_used), + jfs[k].type, jfs[k].name); + + } else { + mvwprintw(padjfs, 2 + k, 0, "%s", + jfs[k].name); + COLOUR wattrset(padjfs, COLOR_PAIR(5)); + mvwprintw(padjfs, 2 + k, 43, + "%-8s size=zero blocks!", + jfs[k].type); + COLOUR wattrset(padjfs, COLOR_PAIR(0)); + } + } else { + mvwprintw(padjfs, 2 + k, 0, "%s", + jfs[k].name); + COLOUR wattrset(padjfs, COLOR_PAIR(3)); + mvwprintw(padjfs, 2 + k, 43, + "%-8s statfs failed", + jfs[k].type); + COLOUR wattrset(padjfs, COLOR_PAIR(0)); + } + } + } else { + mvwprintw(padjfs, 2 + k, 0, "%-14s", jfs[k].name); + COLOUR wattrset(padjfs, COLOR_PAIR(1)); + mvwprintw(padjfs, 2 + k, 43, "%-8s not mounted", + jfs[k].type); + COLOUR wattrset(padjfs, COLOR_PAIR(0)); + } + } + DISPLAY(padjfs, 2 + jfses); + } else { + jfs_load(LOAD); + fprintf(fp, + show_rrd ? "rrdtool update jfsfile.rrd %s" : + "JFSFILE,%s", LOOP); + for (k = 0; k < jfses; k++) { + if (jfs[k].mounted && strncmp(jfs[k].name, "/proc", 5) + && strncmp(jfs[k].name, "/sys", 4) + && strncmp(jfs[k].name, "/dev/", 5) + && strncmp(jfs[k].name, "/run/", 5) + && strncmp(jfs[k].name, "/var/lib/nfs/rpc", 16) + ) { /* /proc gives invalid/insane values */ + if (fstatfs(jfs[k].fd, &statfs_buffer) != -1) { + if (statfs_buffer.f_bsize == 0) + fs_bsize = 4.0 * 1024.0; + else + fs_bsize = statfs_buffer.f_bsize; + /* convert blocks to MB */ + fs_size = + (float) statfs_buffer.f_blocks * fs_bsize / + 1024.0 / 1024.0; + + /* find the best size info available f_bavail is like df reports + otherwise use f_bsize (this includes inode blocks) */ + if (statfs_buffer.f_bavail == 0) + fs_free = + (float) statfs_buffer.f_bfree * + fs_bsize / 1024.0 / 1024.0; + else + fs_free = + (float) statfs_buffer.f_bavail * + fs_bsize / 1024.0 / 1024.0; + + + + if (fs_size <= 0.0 || fs_bsize <= 0.0) /* some pseudo filesystems have zero size but we get a -nan result */ + fs_size_used = 0.0; + else + fs_size_used = + (fs_size - + (float) statfs_buffer.f_bfree * + fs_bsize / 1024.0 / 1024.0) / + fs_size * 100.0; + + if (fs_size_used > 100.0) + fs_size_used = 100.0; + + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + fs_size_used); + } else + fprintf(fp, show_rrd ? ":U" : ",0.0"); + } + } + fprintf(fp, "\n"); + jfs_load(UNLOAD); + } + } +#endif /* JFS */ + + if (show_disk || show_verbose || show_diskmap || show_dgroup) { + proc_read(P_STAT); + proc_disk(elapsed); + } + if (show_diskmap) { + BANNER(padmap, "Disk %%Busy Map"); + mvwprintw(padmap, 0, 18, + "Key: @=90 #=80 X=70 8=60 O=50 0=40 o=30 +=20 -=10 .=5 _=0%%"); + mvwprintw(padmap, 1, 0, + " Disk No. 1 2 3 4 5 6 "); + if (disk_first_time) { + disk_first_time = 0; + mvwprintw(padmap, 2, 0, + "Please wait - collecting disk data"); + } else { + mvwprintw(padmap, 2, 0, + "Disks=%-4d 0123456789012345678901234567890123456789012345678901234567890123", + disks); + mvwprintw(padmap, 3, 0, "disk 0 to 63 "); + for (i = 0; i < disks; i++) { + disk_busy = DKDELTA(dk_time) / elapsed; + disk_read = DKDELTA(dk_rkb) / elapsed; + disk_write = DKDELTA(dk_wkb) / elapsed; + /* ensure boundaries */ + if (disk_busy < 0) + disk_busy = 0; + else if (disk_busy > 99) + disk_busy = 99; + +#define MAPWRAP 64 + mvwprintw(padmap, 3 + (int) (i / MAPWRAP), + 13 + (i % MAPWRAP), "%c", + disk_busy_map_ch[(int) disk_busy]); + } + } + DISPLAY(padmap, 4 + disks / MAPWRAP); + } + if (show_verbose) { + top_disk_busy = 0.0; + top_disk_name = ""; + for (i = 0, k = 0; i < disks; i++) { + disk_busy = DKDELTA(dk_time) / elapsed; + if (disk_busy > top_disk_busy) { + top_disk_busy = disk_busy; + top_disk_name = p->dk[i].dk_name; + } + } + if (top_disk_busy > 80.0) { + COLOUR wattrset(padverb, COLOR_PAIR(1)); + mvwprintw(padverb, 3, 0, " DANGER"); + } else if (top_disk_busy > 60.0) { + COLOUR wattrset(padverb, COLOR_PAIR(4)); + mvwprintw(padverb, 3, 0, "Warning"); + } else { + COLOUR wattrset(padverb, COLOR_PAIR(2)); + mvwprintw(padverb, 3, 0, " OK"); + } + COLOUR wattrset(padverb, COLOR_PAIR(0)); + mvwprintw(padverb, 3, 8, + "-> Top Disk %8s %%busy %5.1f%%\t>40%%\t>60%% ", + top_disk_name, top_disk_busy); + move(x, 0); + } + if (show_disk) { + if (cursed) { + if (show_disk) { + BANNER(paddisk, "Disk I/O"); + switch (disk_mode) { + case DISK_MODE_PARTITIONS: + mvwprintw(paddisk, 0, 12, "/proc/partitions"); + break; + case DISK_MODE_DISKSTATS: + mvwprintw(paddisk, 0, 12, "/proc/diskstats"); + break; + case DISK_MODE_IO: + mvwprintw(paddisk, 0, 12, "/proc/stat+disk_io"); + break; + } + mvwprintw(paddisk, 0, 31, "mostly in KB/s"); + mvwprintw(paddisk, 0, 50, + "Warning:contains duplicates"); + switch (show_disk) { + case SHOW_DISK_STATS: + mvwprintw(paddisk, 1, 0, "DiskName Busy"); + COLOUR wattrset(paddisk, COLOR_PAIR(6)); + mvwprintw(paddisk, 1, 17, "Read"); + COLOUR wattrset(paddisk, COLOR_PAIR(3)); + mvwprintw(paddisk, 1, 25, "Write"); + COLOUR wattrset(paddisk, COLOR_PAIR(0)); + mvwprintw(paddisk, 1, 37, + "Xfers Size Peak%% Peak-RW InFlight "); + break; + case SHOW_DISK_GRAPH: + mvwprintw(paddisk, 1, 0, "DiskName Busy "); + COLOUR wattrset(paddisk, COLOR_PAIR(6)); + mvwprintw(paddisk, 1, 15, "Read "); + COLOUR wattrset(paddisk, COLOR_PAIR(3)); + mvwprintw(paddisk, 1, 20, "Write"); + COLOUR wattrset(paddisk, COLOR_PAIR(0)); + mvwprintw(paddisk, 1, 25, + "KB|0 |25 |50 |75 100|"); + break; + } + } + if (disk_first_time) { + disk_first_time = 0; + mvwprintw(paddisk, 2, 0, + "Please wait - collecting disk data"); + } else { + total_disk_read = 0.0; + total_disk_write = 0.0; + total_disk_xfers = 0.0; + disk_mb = 0; + for (i = 0, k = 0; i < disks; i++) { + disk_read = DKDELTA(dk_rkb) / elapsed; + disk_write = DKDELTA(dk_wkb) / elapsed; + if ((show_disk == SHOW_DISK_GRAPH) + && (disk_read > 9999.9 + || disk_write > 9999.9)) { + disk_mb = 1; + COLOUR wattrset(paddisk, COLOR_PAIR(1)); + mvwprintw(paddisk, 1, 25, "MB"); + COLOUR wattrset(paddisk, COLOR_PAIR(0)); + break; + } + } + for (i = 0, k = 0; i < disks; i++) { + if (disk_only_mode + && is_dgroup_name(p->dk[i].dk_name) == 0) + continue; + +/* + if(p->dk[i].dk_name[0] == 'h') + continue; +*/ + disk_busy = DKDELTA(dk_time) / elapsed; + disk_read = DKDELTA(dk_rkb) / elapsed; + disk_write = DKDELTA(dk_wkb) / elapsed; + disk_xfers = DKDELTA(dk_xfers); + + total_disk_read += disk_read; + total_disk_write += disk_write; + total_disk_xfers += disk_xfers; + + if (disk_busy_peak[i] < disk_busy) + disk_busy_peak[i] = disk_busy; + if (disk_rate_peak[i] < (disk_read + disk_write)) + disk_rate_peak[i] = disk_read + disk_write; + if (!show_all && disk_busy < 1) + continue; + + if (strlen(p->dk[i].dk_name) > 8) + str_p = + &p->dk[i]. + dk_name[strlen(p->dk[i].dk_name) - 8]; + else + str_p = &p->dk[i].dk_name[0]; + + if (show_disk == SHOW_DISK_STATS) { + /* output disks stats */ + mvwprintw(paddisk, 2 + k, 0, "%-8s%4.0f%%", + str_p, disk_busy); + COLOUR wattrset(paddisk, COLOR_PAIR(6)); + mvwprintw(paddisk, 2 + k, 13, "%9.1f", + disk_read); + COLOUR wattrset(paddisk, COLOR_PAIR(3)); + mvwprintw(paddisk, 2 + k, 22, "%9.1fKB/s", + disk_write); + COLOUR wattrset(paddisk, COLOR_PAIR(0)); + mvwprintw(paddisk, 2 + k, 31, + "KB/s %6.1f %5.1fKB %3.0f%% %9.1fKB/s %3d", + disk_xfers / elapsed, + disk_xfers == + 0.0 ? 0.0 : (DKDELTA(dk_rkb) + + DKDELTA(dk_wkb)) / + disk_xfers, disk_busy_peak[i], + disk_rate_peak[i], + p->dk[i].dk_inflight); + k++; + } + if (show_disk == SHOW_DISK_GRAPH) { + /* output disk bar graphs */ + if (disk_mb) { + disk_read_tmp = disk_read / 1024.0; + disk_write_tmp = disk_write / 1024.0; + } else { + disk_read_tmp = disk_read; + disk_write_tmp = disk_write; + } + + mvwprintw(paddisk, 2 + k, 0, "%-8s %3.0f%%", + str_p, disk_busy); + COLOUR wattrset(paddisk, COLOR_PAIR(6)); + mvwprintw(paddisk, 2 + k, 13, "%7.1f", + disk_read_tmp); + COLOUR wattrset(paddisk, COLOR_PAIR(3)); + mvwprintw(paddisk, 2 + k, 20, "%7.1f", + disk_write_tmp); + COLOUR wattrset(paddisk, COLOR_PAIR(0)); + + mvwprintw(paddisk, 2 + k, 27, + "| "); + wmove(paddisk, 2 + k, 28); + if (disk_busy > 100) + disk_busy = 100; + if (disk_busy > 0.0 + && (disk_write + disk_read) > 0.1) { + /* 50 columns in the disk graph area so divide % by two */ + readers = + disk_busy * disk_read / (disk_write + + disk_read) / + 2; + writers = + disk_busy * disk_write / (disk_write + + disk_read) / + 2; + if (readers + writers > 50) { + readers = 0; + writers = 0; + } + /* don't go beyond row 78 i.e. j = 28 + 50 */ + for (j = 0; j < readers && j < 50; j++) { + COLOUR wattrset(paddisk, + COLOR_PAIR(12)); + wprintw(paddisk, "R"); + COLOUR wattrset(paddisk, + COLOR_PAIR(0)); + } + for (; j < readers + writers && j < 50; + j++) { + COLOUR wattrset(paddisk, + COLOR_PAIR(11)); + wprintw(paddisk, "W"); + COLOUR wattrset(paddisk, + COLOR_PAIR(0)); + } + for (j = disk_busy; j < 50; j++) + wprintw(paddisk, " "); + } else { + for (j = 0; j < 50; j++) + wprintw(paddisk, " "); + if (p->dk[i].dk_time == 0.0) + mvwprintw(paddisk, 2 + k, 27, + "| disk busy not available"); + } + if (disk_busy_peak[i] > 100) + disk_busy_peak[i] = 100; + + mvwprintw(paddisk, 2 + i, 77, "|"); + /* check rounding has not got the peak ">" over the 100% */ + j = 28 + (int) (disk_busy_peak[i] / 2); + if (j > 77) + j = 77; + mvwprintw(paddisk, 2 + i, j, ">"); + k++; + } + } + mvwprintw(paddisk, 2 + k, 0, + "Totals Read-MB/s=%-8.1f Writes-MB/s=%-8.1f Transfers/sec=%-8.1f", + total_disk_read / 1024.0, + total_disk_write / 1024.0, + total_disk_xfers / elapsed); + + } + DISPLAY(paddisk, 3 + k); + } else { + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, + show_rrd ? + "%srrdtool update diskbusy%s.rrd %s" : + "%sDISKBUSY%s,%s", i == 0 ? "" : "\n", + dskgrp(i), LOOP); + /* check percentage is correct */ + ftmp = DKDELTA(dk_time) / elapsed; + if (ftmp > 100.0 || ftmp < 0.0) + fprintf(fp, show_rrd ? ":U" : ",101.00"); + else + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + DKDELTA(dk_time) / elapsed); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, + show_rrd ? + "\nrrdtool update diskread%s.rrd %s" : + "\nDISKREAD%s,%s", dskgrp(i), LOOP); + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + DKDELTA(dk_rkb) / elapsed); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, + show_rrd ? + "\nrrdtool update diskwrite%s.rrd %s" : + "\nDISKWRITE%s,%s", dskgrp(i), LOOP); + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + DKDELTA(dk_wkb) / elapsed); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, + show_rrd ? + "\nrrdtool update diskxfer%s.rrd %s" : + "\nDISKXFER%s,%s", dskgrp(i), LOOP); + disk_xfers = DKDELTA(dk_xfers); + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + disk_xfers / elapsed); + } + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) + fprintf(fp, + show_rrd ? + "\nrrdtool update diskbsize%s.rrd %s" : + "\nDISKBSIZE%s,%s", dskgrp(i), LOOP); + disk_xfers = DKDELTA(dk_xfers); + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + disk_xfers == 0.0 ? 0.0 : + (DKDELTA(dk_rkb) + + DKDELTA(dk_wkb)) / disk_xfers); + } + + if (extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS) { + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) { + fprintf(fp, "\nDISKREADS%s,%s", dskgrp(i), + LOOP); + } + disk_read = DKDELTA(dk_reads); + fprintf(fp, ",%.1f", disk_read / elapsed); + } + + for (i = 0; i < disks; i++) { + if (NEWDISKGROUP(i)) { + fprintf(fp, "\nDISKWRITES%s,%s", dskgrp(i), + LOOP); + } + disk_write = DKDELTA(dk_writes); + fprintf(fp, ",%.1f", disk_write / elapsed); + } + } + fprintf(fp, "\n"); + } + } + if ((show_dgroup || (!cursed && dgroup_loaded))) { + if (cursed) { + BANNER(paddg, "Disk Group I/O"); + if (dgroup_loaded != 2 || dgroup_total_disks == 0) { + mvwprintw(paddg, 1, 1, + "No Disk Groups found use -g groupfile when starting nmon"); + } else if (disk_first_time) { + disk_first_time = 0; + mvwprintw(paddg, 1, 1, + "Please wait - collecting disk data"); + } else { + mvwprintw(paddg, 1, 1, + "Name Disks AvgBusy | TotalMB/s xfers/s BlockSizeKB"); + COLOUR wattrset(paddg, COLOR_PAIR(6)); + mvwprintw(paddg, 1, 29, "Read-KB/s"); + COLOUR wattrset(paddg, COLOR_PAIR(3)); + mvwprintw(paddg, 1, 39, "Write"); + COLOUR wattrset(paddg, COLOR_PAIR(0)); + total_busy = 0.0; + total_rbytes = 0.0; + total_wbytes = 0.0; + total_xfers = 0.0; + for (k = n = 0; k < dgroup_total_groups; k++) { +/* + if (dgroup_name[k] == 0 ) + continue; +*/ + disk_busy = 0.0; + disk_read = 0.0; + disk_write = 0.0; + disk_xfers = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_busy += DKDELTA(dk_time) / elapsed; +/* + disk_read += DKDELTA(dk_reads) * p->dk[i].dk_bsize / 1024.0 /elapsed; + disk_write += DKDELTA(dk_writes) * p->dk[i].dk_bsize / 1024.0 /elapsed; +*/ + disk_read += DKDELTA(dk_rkb) / elapsed; + disk_write += DKDELTA(dk_wkb) / elapsed; + disk_xfers += DKDELTA(dk_xfers) / elapsed; + } + } + if (dgroup_disks[k] == 0) + disk_busy = 0.0; + else + disk_busy = disk_busy / dgroup_disks[k]; + total_busy += disk_busy; + total_rbytes += disk_read; + total_wbytes += disk_write; + total_xfers += disk_xfers; +/* if (!show_all && (disk_read < 1.0 && disk_write < 1.0)) + continue; +*/ + if ((disk_read + disk_write) == 0 + || disk_xfers == 0) + disk_size = 0.0; + else + disk_size = + ((float) disk_read + + (float) disk_write) / (float) disk_xfers; + mvwprintw(paddg, n + 2, 1, "%-14s %3d %5.1f%% | %6.1f %9.1f %6.1f ", dgroup_name[k], dgroup_disks[k], disk_busy, (disk_read + disk_write) / 1024, /* in MB */ + disk_xfers, disk_size); + COLOUR wattrset(paddg, COLOR_PAIR(6)); + mvwprintw(paddg, n + 2, 29, "%9.1f", disk_read); + COLOUR wattrset(paddg, COLOR_PAIR(3)); + mvwprintw(paddg, n + 2, 39, "%-9.1f", disk_write); + COLOUR wattrset(paddg, COLOR_PAIR(0)); + n++; + } + mvwprintw(paddg, n + 2, 1, "Groups=%2d TOTALS %3d %5.1f%% %9.1f|%-9.1f %6.1f %9.1f", n, dgroup_total_disks, total_busy / dgroup_total_disks, total_rbytes, total_wbytes, (((double) total_rbytes + (double) total_wbytes)) / 1024, /* in MB */ + total_xfers); + } + DISPLAY(paddg, 3 + dgroup_total_groups); + } else { + if (dgroup_loaded == 2) { + fprintf(fp, + show_rrd ? "rrdtool update dgbusy.rdd %s" : + "DGBUSY,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += + DKDELTA(dk_time) / elapsed; + } + } + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + (float) (disk_total / + dgroup_disks[k])); + } + } + fprintf(fp, "\n"); + fprintf(fp, + show_rrd ? "rrdtool update dgread.rdd %s" : + "DGREAD,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { +/* + disk_total += DKDELTA(dk_reads) * p->dk[i].dk_bsize / 1024.0; +*/ + disk_total += DKDELTA(dk_rkb); + } + } + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + disk_total / elapsed); + } + } + fprintf(fp, "\n"); + fprintf(fp, + show_rrd ? "rrdtool update dgwrite.rdd %s" : + "DGWRITE,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { +/* + disk_total += DKDELTA(dk_writes) * p->dk[i].dk_bsize / 1024.0; +*/ + disk_total += DKDELTA(dk_wkb); + } + } + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + disk_total / elapsed); + } + } + fprintf(fp, "\n"); + fprintf(fp, + show_rrd ? "rrdtool update dgbsize.rdd %s" : + "DGSIZE,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_write = 0.0; + disk_xfers = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { +/* + disk_write += (DKDELTA(dk_reads) + DKDELTA(dk_writes) ) * p->dk[i].dk_bsize / 1024.0; +*/ + disk_write += + (DKDELTA(dk_rkb) + + DKDELTA(dk_wkb)); + disk_xfers += DKDELTA(dk_xfers); + } + } + if (disk_write == 0.0 || disk_xfers == 0.0) + disk_size = 0.0; + else + disk_size = disk_write / disk_xfers; + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + disk_size); + } + } + fprintf(fp, "\n"); + fprintf(fp, + show_rrd ? "rrdtool update dgxfer.rdd %s" : + "DGXFER,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_xfers); + } + } + fprintf(fp, show_rrd ? ":%.1f" : ",%.1f", + disk_total / elapsed); + } + } + fprintf(fp, "\n"); + + if (extended_disk == 1 + && disk_mode == DISK_MODE_DISKSTATS) { + fprintf(fp, "DGREADS,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_reads); + } + } + fprintf(fp, ",%.1f", disk_total / elapsed); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGREADMERGE,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_rmerge); + } + } + fprintf(fp, ",%.1f", disk_total / elapsed); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGREADSERV,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_rmsec); + } + } + fprintf(fp, ",%.1f", disk_total); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGWRITES,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_writes); + } + } + fprintf(fp, ",%.1f", disk_total / elapsed); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGWRITEMERGE,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_wmerge); + } + } + fprintf(fp, ",%.1f", disk_total / elapsed); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGWRITESERV,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_wmsec); + } + } + fprintf(fp, ",%.1f", disk_total); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGINFLIGHT,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += p->dk[i].dk_inflight; + } + } + fprintf(fp, ",%.1f", disk_total); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGIOTIME,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_time); + } + } + fprintf(fp, ",%.1f", disk_total); + } + } + fprintf(fp, "\n"); + fprintf(fp, "DGBACKLOG,%s", LOOP); + for (k = 0; k < dgroup_total_groups; k++) { + if (dgroup_name[k] != 0) { + disk_total = 0.0; + for (j = 0; j < dgroup_disks[k]; j++) { + i = dgroup_data[k * DGROUPITEMS + j]; + if (i != -1) { + disk_total += DKDELTA(dk_backlog); + } + } + fprintf(fp, ",%.1f", disk_total); + } + } + fprintf(fp, "\n"); + } /* if( extended_disk == 1 && disk_mode == DISK_MODE_DISKSTATS */ + } /* if (dgroup_loaded == 2) */ + } /* else from if(cursed) */ + } + /* if ((show_dgroup || (!cursed && dgroup_loaded))) */ + if (show_top) { + wmove(padtop, 1, 1); + wclrtobot(padtop); + /* Get the details of the running processes */ + skipped = 0; + current_procs = getprocs(0); + if (current_procs > p->proc_records) { + adjusted_procs = current_procs + 128; /* allow for growth in the number of processes in the mean time */ + p->procs = REALLOC(p->procs, sizeof(struct procsinfo) * adjusted_procs); + p->proc_records = adjusted_procs; + } + + p->processes = getprocs(p->proc_records); + + if (topper_size < p->processes) { + topper = REALLOC(topper, sizeof(struct topper) * (p->processes +1));/* add one to avoid overrun */ + topper_size = p->processes; + } + /* Sort the processes by CPU utilisation */ + for (i = 0, max_sorted = 0; i < p->processes; i++) { + /* move forward in the previous array to find a match */ + for (j = 0; j < q->processes; j++) { + if (p->procs[i].pi_pid == q->procs[j].pi_pid) { /* found a match */ + topper[max_sorted].index = i; + topper[max_sorted].other = j; + topper[max_sorted].time = + TIMEDELTA(pi_utime, i, j) + TIMEDELTA(pi_stime, i, j); + topper[max_sorted].size = + p->procs[i].statm_resident; + if (isroot && cursed) /* we don't sort on this in data capture */ + topper[max_sorted].io = + IODELTA(read_io, i, j) + IODELTA(write_io, i, j); + + max_sorted++; + break; + } + } + } + switch (show_topmode) { + default: + case 3: + qsort((void *) &topper[0], max_sorted, + sizeof(struct topper), &cpu_compare); + break; + case 4: + qsort((void *) &topper[0], max_sorted, + sizeof(struct topper), &size_compare); + break; + case 5: + qsort((void *) &topper[0], max_sorted, + sizeof(struct topper), &disk_compare); + break; + } + CURSE BANNER(padtop, "Top Processes"); + if (isroot) { + CURSE mvwprintw(padtop, 0, 15, + "Procs=%d mode=%d (1=Basic, 3=Perf 4=Size 5=I/O)", + n, show_topmode); + } else { + CURSE mvwprintw(padtop, 0, 15, + "Procs=%d mode=%d (1=Basic, 3=Perf 4=Size 5=I/O[root-only])", + n, show_topmode); + } + if (cursed && top_first_time) { + top_first_time = 0; + mvwprintw(padtop, 1, 1, + "Please wait - information being collected"); + } else { + switch (show_topmode) { + case 1: + CURSE mvwprintw(padtop, 1, 1, + " PID PPID Pgrp Nice Prior Status proc-Flag Command"); + for (j = 0; j < max_sorted; j++) { + i = topper[j].index; + if (p->procs[i].pi_pgrp == p->procs[i].pi_pid) + strcpy(pgrp, "none"); + else + sprintf(&pgrp[0], "%d", p->procs[i].pi_pgrp); + /* skip over processes with 0 CPU */ + if (!show_all + && (topper[j].time / elapsed < + ignore_procdisk_threshold) && !cmdfound) + break; + if (x + j + 2 - skipped > LINES + 2) /* +2 to for safety :-) */ + break; + CURSE mvwprintw(padtop, j + 2 - skipped, 1, + "%7d %7d %6s %4d %4d %9s 0x%08x %1s %-32s", + p->procs[i].pi_pid, + p->procs[i].pi_ppid, pgrp, + p->procs[i].pi_nice, + p->procs[i].pi_pri, + (topper[j].time * 100 / + elapsed) ? "Running " : + get_state(p->procs[i].pi_state), + p->procs[i].pi_flags, + (p->procs[i]. + pi_tty_nr ? "F" : " "), + p->procs[i].pi_comm); + } + break; + case 3: + case 4: + case 5: + + if (show_args == ARGS_ONLY) { + formatstring = + " PID %%CPU ResSize Command "; + } else if (COLS > 119) { + if (show_topmode == 5) + formatstring = + " PID %%CPU Size Res Res Res Res Shared StorageKB Command"; + else + formatstring = + " PID %%CPU Size Res Res Res Res Shared Faults Command"; + } else { + if (show_topmode == 5) + formatstring = + " PID %%CPU Size Res Res Res Res Shared StorageKB Command"; + else + formatstring = + " PID %%CPU Size Res Res Res Res Shared Faults Command"; + } + CURSE mvwprintw(padtop, 1, y, formatstring); + + if (show_args == ARGS_ONLY) { + formatstring = + " Used KB "; + } else if (COLS > 119) { + if (show_topmode == 5) + formatstring = + " Used KB Set Text Data Lib KB Read Write"; + else + formatstring = + " Used KB Set Text Data Lib KB Min Maj"; + } else { + if (show_topmode == 5) + formatstring = + " Used KB Set Text Data Lib KB ReadWrite "; + else + formatstring = + " Used KB Set Text Data Lib KB Min Maj "; + } + CURSE mvwprintw(padtop, 2, 1, formatstring); + for (j = 0; j < max_sorted; j++) { + i = topper[j].index; + if (!show_all) { + /* skip processes with zero CPU/io */ + if (show_topmode == 3 + && (topper[j].time / elapsed) < + ignore_procdisk_threshold && !cmdfound) + break; + if (show_topmode == 5 + && (topper[j].io < ignore_io_threshold + && !cmdfound)) + break; + } + if (cursed) { + if (x + j + 3 - skipped > LINES + 2) /* +2 to for safety :-) XYZXYZ */ + break; + if (cmdfound && !cmdcheck(p->procs[i].pi_comm)) { + skipped++; + continue; + } + if (show_args == ARGS_ONLY) { + mvwprintw(padtop, j + 3 - skipped, 1, "%7d %5.1f %7lu %-120s", p->procs[i].pi_pid, topper[j].time / elapsed, p->procs[i].statm_resident * pagesize / 1024, /* in KB */ + args_lookup(p->procs[i].pi_pid, + p->procs[i]. + pi_comm)); + } else { + if (COLS > 119) + formatstring = + "%8d %7.1f %7lu %7lu %7lu %7lu %7lu %5lu %6d %6d %-32s"; + else + formatstring = + "%7d %5.1f %5lu %5lu %5lu %5lu %5lu %5lu %4d %4d %-32s"; + + mvwprintw(padtop, j + 3 - skipped, 1, + formatstring, p->procs[i].pi_pid, + topper[j].time / elapsed, + /* topper[j].time /1000.0 / elapsed, */ + p->procs[i].statm_size * pagesize / 1024UL, /* in KB */ + p->procs[i].statm_resident * pagesize / 1024UL, /* in KB */ + p->procs[i].statm_trs * pagesize / 1024UL, /* in KB */ + p->procs[i].statm_drs * pagesize / 1024UL, /* in KB */ + p->procs[i].statm_lrs * pagesize / 1024UL, /* in KB */ + p->procs[i].statm_share * pagesize / 1024UL, /* in KB */ + show_topmode == + 5 ? (int) (COUNTDELTA(read_io) / elapsed / 1024) : (int) (COUNTDELTA(pi_minflt) / elapsed), + show_topmode == + 5 ? (int) (COUNTDELTA(write_io) / elapsed / 1024) : (int) (COUNTDELTA(pi_majflt) / elapsed), + p->procs[i].pi_comm); + } + } else { + if ((cmdfound && cmdcheck(p->procs[i].pi_comm)) + || (!cmdfound + && ((topper[j].time / elapsed) > + ignore_procdisk_threshold))) { +#ifndef KERNEL_2_6_18 + fprintf(fp, + "TOP,%07d,%s,%.2f,%.2f,%.2f,%lu,%lu,%lu,%lu,%lu,%d,%d,%s\n", +#else + fprintf(fp, + "TOP,%07d,%s,%.2f,%.2f,%.2f,%lu,%lu,%lu,%lu,%lu,%d,%d,%s,%ld,%llu\n", +#endif + /* 1 */ p->procs[i].pi_pid, + /* 2 */ LOOP, + /* 3 */ topper[j].time / elapsed, + /* 4 */ TIMEDELTA(pi_utime, i, topper[j]. other) / elapsed, + /* 5 */ TIMEDELTA(pi_stime, i, topper[j]. other) / elapsed, + /* 6 */ p->procs[i].statm_size * pagesize / 1024UL, /* in KB */ + /* 7 */ p->procs[i].statm_resident * pagesize / 1024UL, /* in KB */ + /* 8 */ p->procs[i].statm_trs * pagesize / 1024UL, /* in KB */ + /* 9 */ p->procs[i].statm_drs * pagesize / 1024UL, /* in KB */ + /* 10 */ p->procs[i].statm_share * pagesize / 1024UL, /* in KB */ + /* 11 */ (int) (COUNTDELTA(pi_minflt) / elapsed), + /* 12 */ (int) (COUNTDELTA(pi_majflt) / elapsed), + /* 13 */ p->procs[i].pi_comm +#ifndef KERNEL_2_6_18 + ); +#else + , + p->procs[i].pi_num_threads, COUNTDELTA(pi_delayacct_blkio_ticks) + ); +#endif + + if (show_args) + args_output(p->procs[i].pi_pid, loop, + p->procs[i].pi_comm); + + } else + skipped++; + } + } + break; + } + } + DISPLAY(padtop, 3 + j); + } + + if (cursed) { + if (show_verbose) { + y = x; + x = 1; + DISPLAY(padverb, 4); + x = y; + } + /* underline the end of the stats area border */ + if (x < LINES - 2) + mvwhline(stdscr, x, 1, ACS_HLINE, COLS - 2); + + wmove(stdscr, 0, 0); + wrefresh(stdscr); + doupdate(); + + for (i = 0; i < seconds; i++) { + sleep(1); + if (checkinput()) + break; + } + if (x < LINES - 2) + mvwhline(stdscr, x, 1, ' ', COLS - 2); + if (first_key_pressed == 0) { + first_key_pressed = 1; + wmove(stdscr, 0, 0); + wclear(stdscr); + wmove(stdscr, 0, 0); + wclrtobot(stdscr); + wrefresh(stdscr); + doupdate(); + } + + } else { + fflush(NULL); + + gettimeofday(&nmon_tv, 0); + nmon_end_time = + (double) nmon_tv.tv_sec + + (double) nmon_tv.tv_usec * 1.0e-6; + if (nmon_run_time < 0.0) { + nmon_start_time = nmon_end_time; + nmon_run_time = 0.0; + } + nmon_run_time += (nmon_end_time - nmon_start_time); + if (nmon_run_time < 1.0) { + secs = seconds; /* sleep for the requested number of seconds */ + } else { + seconds_over = (int) nmon_run_time; /* reduce the sleep time by whole number of seconds */ + secs = seconds - seconds_over; + nmon_run_time -= (double) seconds_over; + } + if (secs < 1) /* sanity check in case CPUs are flat out and nmon taking far to long to complete */ + secs = 1; + + redo: + errno = 0; + ret = sleep(secs); + if ((ret != 0 || errno != 0) && loop != maxloops) { + fprintf(fp, + "ERROR,%s, sleep interrupted, sleep(%d seconds), return value=%d", + LOOP, secs, ret); + fprintf(fp, ", errno=%d\n", errno); + secs = ret; + goto redo; + } + gettimeofday(&nmon_tv, 0); + nmon_start_time = + (double) nmon_tv.tv_sec + + (double) nmon_tv.tv_usec * 1.0e-6; + } + + switcher(); + + if (loop >= maxloops) { + CURSE endwin(); + if (nmon_end) { + child_start(CHLD_END, nmon_end, time_stamp_type, loop, + timer); + /* Give the end - processing some time - 5s for now */ + sleep(5); + } + + fflush(NULL); + exit(0); + } + } +} diff --git a/nmon.spec b/nmon.spec index a9e7e00..5c3d9de 100644 --- a/nmon.spec +++ b/nmon.spec @@ -1,6 +1,6 @@ Name: nmon -Version: 16d -Release: 2%{?dist} +Version: 16e +Release: 1%{?dist} Summary: Nigel's performance Monitor for Linux License: GPLv3 @@ -48,6 +48,9 @@ install -D -p -m 0644 %{SOURCE2} %{buildroot}%{_mandir}/man1/%{name}.1 %changelog +* Sun Apr 10 2016 Peter Oliver - 16e-1 +- Update to version 16e. + * Sun Feb 28 2016 Peter Oliver - 16d-2 - Fix build failure.