diff options
author | Michael Paquier <mpaquier@vmware.com> | 2013-06-09 23:36:25 -0700 |
---|---|---|
committer | Mark Wong <markwkm@gmail.com> | 2013-06-10 20:15:30 -0700 |
commit | 81be58eb547b0e14f06ec232d93554e502d40535 (patch) | |
tree | 050a899740c24ae771f97431f9df319e03fd3dba | |
parent | cda7c8e8cf19ccbaec9bb9d286b021ea7fbd5228 (diff) |
monitor the disk I/O of the server
In this patch only Linux platform is supported by parsing
/proc/diskstats to get some disk info. A new generic API adapted to the
machine/m_* files has been added.
-rw-r--r-- | Porting | 10 | ||||
-rw-r--r-- | display.c | 25 | ||||
-rw-r--r-- | display.h | 2 | ||||
-rw-r--r-- | layout.h | 12 | ||||
-rw-r--r-- | machine.h | 14 | ||||
-rw-r--r-- | machine/m_aix43.c | 7 | ||||
-rw-r--r-- | machine/m_aix5.c | 7 | ||||
-rw-r--r-- | machine/m_decosf1.c | 7 | ||||
-rw-r--r-- | machine/m_freebsd.c | 7 | ||||
-rw-r--r-- | machine/m_hpux10.c | 7 | ||||
-rw-r--r-- | machine/m_hpux7.c | 7 | ||||
-rw-r--r-- | machine/m_hpux9.c | 7 | ||||
-rw-r--r-- | machine/m_irix5.c | 7 | ||||
-rw-r--r-- | machine/m_irixsgi.c | 7 | ||||
-rw-r--r-- | machine/m_linux.c | 77 | ||||
-rw-r--r-- | machine/m_linuxthr.c | 7 | ||||
-rw-r--r-- | machine/m_macosx.c | 11 | ||||
-rw-r--r-- | machine/m_netbsd.c | 7 | ||||
-rw-r--r-- | machine/m_openbsd.c | 7 | ||||
-rw-r--r-- | machine/m_sco5.c | 7 | ||||
-rw-r--r-- | machine/m_sunos4.c | 7 | ||||
-rw-r--r-- | machine/m_sunos5.c | 7 | ||||
-rw-r--r-- | machine/m_svr4.c | 7 | ||||
-rw-r--r-- | machine/m_svr5.c | 7 | ||||
-rw-r--r-- | pg_top.c | 13 |
25 files changed, 274 insertions, 9 deletions
@@ -74,6 +74,15 @@ struct system_info int *memory; /* memory information */ }; +The io_info struct is filled in by get_io_info. +struct io_info { + int64_t reads; + int64_t readsectors; + int64_t writes; + int64_t writesectors; +}; + + The last three pointers each point to an array of integers. The length of the array is determined by the length of the corresponding _names array in the statics structure. Furthermore, if an entry in a @@ -122,6 +131,7 @@ uid_t proc_owner(pid_t) This function is VERY IMPORTANT. If it fails to do its job, then pg_top may pose a security risk. +void get_io_info(struct io_info *) get_process_info is called immediately after get_system_info. In fact, the two functions could be rolled in to one. The reason they @@ -75,6 +75,8 @@ static int y_swap = -1; static int y_message = Y_MESSAGE; static int x_db = X_DB; static int y_db = Y_DB; +static int x_io = X_IO; +static int y_io = Y_IO; static int x_header = X_HEADER; static int y_header = Y_HEADER; static int x_idlecursor = X_IDLECURSOR; @@ -1247,6 +1249,29 @@ u_db(struct db_info *db_info) } /* + * *_io(io_info) - print "DB I/O: " followed by IO summary + */ +void +i_io(struct io_info *io_info) +{ + char buf[128]; + display_write(x_io, y_io, 0, 0, "DB I/O: "); + + snprintf(buf, 80, "%5ld reads/s, %5ld KB/s, %5ld writes/s, %5ld KB/s ", + io_info->reads, + io_info->readsectors / 2, + io_info->writes, + io_info->writesectors / 2); + display_write(-1, -1, 0, 0, buf); +} + +void +u_io(struct io_info *io_info) +{ + i_io(io_info); +} + +/* * *_message() - print the next pending message line, or erase the one * that is there. * @@ -31,6 +31,8 @@ void i_swap(long *stats); void u_swap(long *stats); void i_db(struct db_info *db_info); void u_db(struct db_info *db_info); +void i_io(struct io_info *io_info); +void u_io(struct io_info *io_info); void i_message(); void u_message(); void i_header(char *text); @@ -31,13 +31,15 @@ #define Y_MEM 3 #define X_DB 0 #define Y_DB 4 +#define X_IO 0 +#define Y_IO 5 #define X_SWAP 6 -#define Y_SWAP 5 -#define Y_MESSAGE 5 +#define Y_SWAP 6 +#define Y_MESSAGE 6 #define X_HEADER 0 -#define Y_HEADER 6 +#define Y_HEADER 7 #define X_IDLECURSOR 0 -#define Y_IDLECURSOR 5 -#define Y_PROCS 7 +#define Y_IDLECURSOR 6 +#define Y_PROCS 8 #endif /* _LAYOUT_H_ */ @@ -97,6 +97,17 @@ struct db_info { }; /* + * Info on reads/writes happening on disk. + * On Linux, this can be obtained from /proc/diskstats. + */ +struct io_info { + int64_t reads; + int64_t readsectors; + int64_t writes; + int64_t writesectors; +}; + +/* * the process_select struct tells get_process_info what processes we * are interested in seeing */ @@ -119,7 +130,8 @@ caddr_t get_process_info(struct system_info *, struct process_select *, int, caddr_t get_process_info(struct system_info *, struct process_select *, int, char *); #endif /* __linux__ */ -void get_database_info(struct db_info *db_info, char *conninfo); +void get_database_info(struct db_info *, char *); +void get_io_info(struct io_info *); char *format_header(char *); char *format_next_io(caddr_t, char *(*) (uid_t)); char *format_next_process(caddr_t, char *(*) (uid_t)); diff --git a/machine/m_aix43.c b/machine/m_aix43.c index 24887f2..381fef5 100644 --- a/machine/m_aix43.c +++ b/machine/m_aix43.c @@ -741,3 +741,10 @@ proc_owner(int pid) return (-1); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_aix5.c b/machine/m_aix5.c index 4946000..c540933 100644 --- a/machine/m_aix5.c +++ b/machine/m_aix5.c @@ -818,3 +818,10 @@ int pid; return (-1); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_decosf1.c b/machine/m_decosf1.c index 2397fe5..7408203 100644 --- a/machine/m_decosf1.c +++ b/machine/m_decosf1.c @@ -1012,3 +1012,10 @@ setpriority(int dummy, int procnum, int niceval) } return (syscall(SYS_setpriority, PRIO_PROCESS, procnum, niceval)); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_freebsd.c b/machine/m_freebsd.c index 6fcad46..621e238 100644 --- a/machine/m_freebsd.c +++ b/machine/m_freebsd.c @@ -1077,3 +1077,10 @@ swapmode(int *retavail, int *retfree) (double) swapary[0].ksw_total); return (n); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_hpux10.c b/machine/m_hpux10.c index e6b64da..d4d637f 100644 --- a/machine/m_hpux10.c +++ b/machine/m_hpux10.c @@ -712,3 +712,10 @@ int *m; ttynames[*m].name[0] = '\0'; free(namelist); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_hpux7.c b/machine/m_hpux7.c index 96970b7..724cdb2 100644 --- a/machine/m_hpux7.c +++ b/machine/m_hpux7.c @@ -881,3 +881,10 @@ int pid; } return (-1); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_hpux9.c b/machine/m_hpux9.c index 61a9cd3..9547ecb 100644 --- a/machine/m_hpux9.c +++ b/machine/m_hpux9.c @@ -835,3 +835,10 @@ int pid; } return (-1); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_irix5.c b/machine/m_irix5.c index c20eb8b..2c3a98f 100644 --- a/machine/m_irix5.c +++ b/machine/m_irix5.c @@ -776,3 +776,10 @@ struct prpsinfo *baseptr; lasttime = thistime; } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_irixsgi.c b/machine/m_irixsgi.c index bdcdf77..af62385 100644 --- a/machine/m_irixsgi.c +++ b/machine/m_irixsgi.c @@ -1154,3 +1154,10 @@ getptable(struct prpsinfo * baseptr) op->oldpct = weighted_cpu(currproc); } } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_linux.c b/machine/m_linux.c index b00480a..00faa36 100644 --- a/machine/m_linux.c +++ b/machine/m_linux.c @@ -15,6 +15,8 @@ * AUTHOR: Richard Henderson <rth@tamu.edu> * Order support added by Alexey Klimkin <kad@klon.tme.mcst.ru> * Ported to 2.4 by William LeFebvre + * + * Portions Copyright (c) 2013 VMware, Inc. All Rights Reserved. */ #include "config.h" @@ -1305,7 +1307,7 @@ compare_cmd( return result == 0 ? 0 : result < 0 ? -1 : 1; } -int +int compare_pid(struct top_proc ** pp1, struct top_proc ** pp2) { register struct top_proc *p1; @@ -1656,3 +1658,76 @@ upsert_io_stats(struct io_node *head, pid_t pid, long long rchar, head = insert_io_stats(head, c); return head; } + +/* + * Get IO information for the SCSI devices in the system. Returns + * read/write IOs per second and bandwidth by comparing current values + * with previous values. + */ +void +get_io_info(struct io_info *io_info) +{ + struct timeval thistime; + double timediff; + static struct timeval lasttime; + struct io_info cur_info; + static struct io_info last_io_info; + FILE *fp; + char line[256]; + int major, minor; + char dev_name[32]; + int64_t reads, readsectors, skip, writes, writesectors; + int i; + + /* calculate the time difference since our last check */ + gettimeofday(&thistime, 0); + if (lasttime.tv_sec) + timediff = ((thistime.tv_sec - lasttime.tv_sec) + + (thistime.tv_usec - lasttime.tv_usec) * 1e-6); + else + timediff = 0; + + lasttime = thistime; + + fp = fopen("/proc/diskstats", "r"); + if (fp == NULL) + { + memset(io_info, 0, sizeof(*io_info)); + return; + } + + memset(&cur_info, 0, sizeof(cur_info)); + while (fgets(line, 256, fp) != NULL) + { + i = sscanf(line, "%d %d %31s %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", + &major, &minor, dev_name, + &reads, &skip, &readsectors, &skip, + &writes, &skip, &writesectors, &skip, + &skip, &skip, &skip); + if (i != 14) + continue; + + /* Total up full scsi devices (not partitions) */ + if (major == 8 && (minor % 16) == 0) + { + cur_info.reads += reads; + cur_info.readsectors += readsectors; + cur_info.writes += writes; + cur_info.writesectors += writesectors; + } + } + fclose(fp); + if (timediff == 0) + { + last_io_info = cur_info; + memset(io_info, 0, sizeof(*io_info)); + return; + } + + /* Compute the rate information */ + io_info->reads = (double)(cur_info.reads - last_io_info.reads) / timediff; + io_info->readsectors = (double)(cur_info.readsectors - last_io_info.readsectors) / timediff; + io_info->writes = (double)(cur_info.writes - last_io_info.writes) / timediff; + io_info->writesectors = (double)(cur_info.writesectors - last_io_info.writesectors) / timediff; + last_io_info = cur_info; +} diff --git a/machine/m_linuxthr.c b/machine/m_linuxthr.c index 415e215..b74899a 100644 --- a/machine/m_linuxthr.c +++ b/machine/m_linuxthr.c @@ -1109,3 +1109,10 @@ proc_owner(int pid) else return (int) sb.st_uid; } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_macosx.c b/machine/m_macosx.c index 6823fb6..cab01c4 100644 --- a/machine/m_macosx.c +++ b/machine/m_macosx.c @@ -598,9 +598,9 @@ get_process_info(struct system_info * si, struct process_select * sel, int x, buffer = (struct kinfo_proc *) malloc( len * sizeof(struct kinfo_proc) ); for (i = 0; i < nproc ; i++) { - size_t size = sizeof(struct kinfo_proc); + size_t size = sizeof(struct kinfo_proc); mib[3] = atoi(PQgetvalue(pgresult, i, 0)); - + if (sysctl(mib, sizeof(mib)/sizeof(int), &buffer[i], &size, NULL, 0) == -1) { perror("sysctl atoi loop"); @@ -953,3 +953,10 @@ proc_owner(pid_t pid) } return (-1); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_netbsd.c b/machine/m_netbsd.c index ed2ddae..29eb6ed 100644 --- a/machine/m_netbsd.c +++ b/machine/m_netbsd.c @@ -892,3 +892,10 @@ u_int64_t *diffs; for (i = 0; i < cnt; i++) *out++ = (int) ((*diffs++ * 1000 + half_total) / total_change); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_openbsd.c b/machine/m_openbsd.c index e4ad34d..2b92717 100644 --- a/machine/m_openbsd.c +++ b/machine/m_openbsd.c @@ -715,3 +715,10 @@ swapmode(long *used, long *total) free(swdev); return 1; } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_sco5.c b/machine/m_sco5.c index d4e968f..d858d3d 100644 --- a/machine/m_sco5.c +++ b/machine/m_sco5.c @@ -864,3 +864,10 @@ compare_time(struct proc ** pp1, struct proc ** pp2) return (result); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_sunos4.c b/machine/m_sunos4.c index d0b82b2..47d826f 100644 --- a/machine/m_sunos4.c +++ b/machine/m_sunos4.c @@ -957,3 +957,10 @@ int pid; } return (-1); } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_sunos5.c b/machine/m_sunos5.c index 67e0416..e5a9a54 100644 --- a/machine/m_sunos5.c +++ b/machine/m_sunos5.c @@ -1799,3 +1799,10 @@ reallocproc(int n) op->oldpid = -1; } } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_svr4.c b/machine/m_svr4.c index 81494b1..3171d03 100644 --- a/machine/m_svr4.c +++ b/machine/m_svr4.c @@ -747,3 +747,10 @@ struct sysinfo *percpu_si; percpu_p++; } } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} diff --git a/machine/m_svr5.c b/machine/m_svr5.c index c5f7024..ca2c963 100644 --- a/machine/m_svr5.c +++ b/machine/m_svr5.c @@ -1437,3 +1437,10 @@ kmet_verify( } return; } + +void +get_io_info(struct io_info *io_info) +{ + /* Not supported yet */ + memset(io_info, 0, sizeof(*io_info)); +} @@ -103,6 +103,7 @@ void (*d_cpustates) (int64_t *) = i_cpustates; void (*d_memory) (long *) = i_memory; void (*d_swap) (long *) = i_swap; void (*d_db) (struct db_info *) = i_db; +void (*d_io) (struct io_info *) = i_io; void (*d_message) () = i_message; void (*d_header) (char *) = i_header; void (*d_process) (int, char *) = i_process; @@ -172,6 +173,7 @@ reset_display() d_memory = i_memory; d_swap = i_swap; d_db = i_db; + d_io = i_io; d_message = i_message; d_header = i_header; d_process = i_process; @@ -324,6 +326,7 @@ main(int argc, char *argv[]) struct statics statics; caddr_t processes; struct db_info db_info; + struct io_info io_info; static char tempbuf1[50]; static char tempbuf2[50]; @@ -889,6 +892,9 @@ main(int argc, char *argv[]) /* Get database activity information */ get_database_info(&db_info, conninfo); + /* Get database I/O information */ + get_io_info(&io_info); + timeout.tv_sec = 1; timeout.tv_usec = 0; select(0, NULL, NULL, NULL, &timeout); @@ -934,6 +940,9 @@ main(int argc, char *argv[]) /* Get database activity information */ get_database_info(&db_info, conninfo); + /* Get database I/O information */ + get_io_info(&io_info); + /* display the load averages */ (*d_loadave) (system_info.last_pid, system_info.load_avg); @@ -979,6 +988,9 @@ main(int argc, char *argv[]) /* display database activity */ (*d_db) (&db_info); + /* display database I/O */ + (*d_io) (&io_info); + /* display swap stats */ (*d_swap) (system_info.swap); @@ -1077,6 +1089,7 @@ main(int argc, char *argv[]) d_cpustates = u_cpustates; d_memory = u_memory; d_db = u_db; + d_io = u_io; d_swap = u_swap; d_message = u_message; d_header = u_header; |