summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Paquier <mpaquier@vmware.com>2013-06-09 23:36:25 -0700
committerMark Wong <markwkm@gmail.com>2013-06-10 20:15:30 -0700
commit81be58eb547b0e14f06ec232d93554e502d40535 (patch)
tree050a899740c24ae771f97431f9df319e03fd3dba
parentcda7c8e8cf19ccbaec9bb9d286b021ea7fbd5228 (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--Porting10
-rw-r--r--display.c25
-rw-r--r--display.h2
-rw-r--r--layout.h12
-rw-r--r--machine.h14
-rw-r--r--machine/m_aix43.c7
-rw-r--r--machine/m_aix5.c7
-rw-r--r--machine/m_decosf1.c7
-rw-r--r--machine/m_freebsd.c7
-rw-r--r--machine/m_hpux10.c7
-rw-r--r--machine/m_hpux7.c7
-rw-r--r--machine/m_hpux9.c7
-rw-r--r--machine/m_irix5.c7
-rw-r--r--machine/m_irixsgi.c7
-rw-r--r--machine/m_linux.c77
-rw-r--r--machine/m_linuxthr.c7
-rw-r--r--machine/m_macosx.c11
-rw-r--r--machine/m_netbsd.c7
-rw-r--r--machine/m_openbsd.c7
-rw-r--r--machine/m_sco5.c7
-rw-r--r--machine/m_sunos4.c7
-rw-r--r--machine/m_sunos5.c7
-rw-r--r--machine/m_svr4.c7
-rw-r--r--machine/m_svr5.c7
-rw-r--r--pg_top.c13
25 files changed, 274 insertions, 9 deletions
diff --git a/Porting b/Porting
index 7e28680..4c8bca0 100644
--- a/Porting
+++ b/Porting
@@ -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
diff --git a/display.c b/display.c
index 66806aa..30a8f9d 100644
--- a/display.c
+++ b/display.c
@@ -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.
*
diff --git a/display.h b/display.h
index ec04806..732e473 100644
--- a/display.h
+++ b/display.h
@@ -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);
diff --git a/layout.h b/layout.h
index b62b0dc..b0633de 100644
--- a/layout.h
+++ b/layout.h
@@ -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_ */
diff --git a/machine.h b/machine.h
index bf0b083..5d81983 100644
--- a/machine.h
+++ b/machine.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));
+}
diff --git a/pg_top.c b/pg_top.c
index c997955..2ed5ba6 100644
--- a/pg_top.c
+++ b/pg_top.c
@@ -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;