summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Roth <robert.roth.off@gmail.com>2017-05-23 00:02:47 +0300
committerRobert Roth <robert.roth.off@gmail.com>2017-05-23 00:02:47 +0300
commit43740ddab78203c0042587535987fe1a9f8b254a (patch)
tree117b69e29955a287a7fc70776646a7c1c8cdb2d9
parent2e2215c5b64eca4674e31724725c6e36f1f43aae (diff)
parent063de1a7126e0b4d978f51bb7e408c474a8c7755 (diff)
downloadlibgtop-43740ddab78203c0042587535987fe1a9f8b254a.tar.gz
Merge branch 'wip/diskio'
-rw-r--r--.gitignore1
-rw-r--r--examples/Makefile.am6
-rw-r--r--examples/diskio.c39
-rw-r--r--examples/sysdeps.c7
-rw-r--r--examples/timings.c20
-rw-r--r--features.def1
-rw-r--r--include/glibtop/Makefile.am1
-rw-r--r--include/glibtop/command.h3
-rw-r--r--include/glibtop/procio.h93
-rw-r--r--include/glibtop/sysdeps.h4
-rw-r--r--include/glibtop/union.h2
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/command.c1
-rw-r--r--lib/libgtop.sym2
-rw-r--r--lib/sysdeps.c9
-rw-r--r--src/daemon/main.c6
-rw-r--r--src/daemon/slave.c8
-rw-r--r--sysdeps/common/default.c15
-rw-r--r--sysdeps/common/sysdeps_suid.c3
-rw-r--r--sysdeps/freebsd/Makefile.am1
-rw-r--r--sysdeps/freebsd/glibtop_server.h1
-rw-r--r--sysdeps/freebsd/procio.c80
-rw-r--r--sysdeps/linux/Makefile.am2
-rw-r--r--sysdeps/linux/glibtop_server.h1
-rw-r--r--sysdeps/linux/procio.c70
-rw-r--r--sysdeps/stub/procio.c43
-rw-r--r--sysdeps/stub_suid/glibtop_server.h1
27 files changed, 414 insertions, 8 deletions
diff --git a/.gitignore b/.gitignore
index b4738458..5446f725 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,6 +70,7 @@ examples/smp
examples/sysdeps
examples/timings
examples/wd
+examples/diskio
gtk-doc.make
install-sh
lib/GTop-2.0.gir
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 48ac4849..25585e04 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -11,7 +11,7 @@ AM_LDFLAGS = $(LIBGTOP_EXTRA_LIBS)
noinst_PROGRAMS = first second pprint procargs df netlist \
mountlist procmap netload sysdeps timings \
- openfiles smp proclist free wd affinity
+ openfiles smp proclist free wd affinity diskio
first_SOURCES = first.c
first_LDADD = $(top_builddir)/lib/libgtop-2.0.la
@@ -43,6 +43,7 @@ pprint_LDADD = $(top_builddir)/lib/libgtop-2.0.la
procargs_SOURCES = procargs.c
procargs_LDADD = $(top_builddir)/lib/libgtop-2.0.la
+
df_SOURCES = df.c
df_LDADD = $(top_builddir)/lib/libgtop-2.0.la
@@ -63,3 +64,6 @@ free_LDADD = $(top_builddir)/lib/libgtop-2.0.la
affinity_SOURCES = affinity.c
affinity_LDADD = $(top_builddir)/lib/libgtop-2.0.la
+
+diskio_SOURCES = diskio.c
+diskio_LDADD = $(top_builddir)/lib/libgtop-2.0.la
diff --git a/examples/diskio.c b/examples/diskio.c
new file mode 100644
index 00000000..de6d775c
--- /dev/null
+++ b/examples/diskio.c
@@ -0,0 +1,39 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glibtop.h>
+#include <glibtop/procio.h>
+
+#include <stdlib.h>
+
+#include <unistd.h>
+
+static void show_diskio(pid_t pid)
+{
+ glibtop_proc_io io;
+
+ glibtop_get_proc_io (&io, pid);
+
+ printf("<%ld>\t", (long)pid);
+
+ printf("flags: %08lx disk_rchar : %lu, disk_wchar : %lu, disk_read_bytes : %lu, disk_write_bytes : %lu\n", (unsigned long)io.flags, io.disk_rchar, io.disk_wchar, io.disk_rbytes, io.disk_wbytes);
+
+}
+
+
+int main(int argc, char **argv)
+{
+ glibtop_init();
+
+ while(*++argv)
+ {
+ pid_t pid = strtol(*argv, NULL, 10);
+ show_diskio(pid);
+ }
+
+ glibtop_close();
+
+ return 0;
+}
+
diff --git a/examples/sysdeps.c b/examples/sysdeps.c
index 5d55142c..559f93ef 100644
--- a/examples/sysdeps.c
+++ b/examples/sysdeps.c
@@ -92,9 +92,10 @@ main (int argc, char *argv [])
"\tproc_time:\t%d\t0x%08lx\n"
"\tproc_signal:\t%d\t0x%08lx\n"
"\tproc_kernel:\t%d\t0x%08lx\n"
- "\tproc_segment:\t%d\t0x%08lx\n\n"
+ "\tproc_segment:\t%d\t0x%08lx\n"
"\tproc_args:\t%d\t0x%08lx\n"
- "\tproc_map:\t%d\t0x%08lx\n\n"
+ "\tproc_map:\t%d\t0x%08lx\n"
+ "\tproc_io:\t%d\t0x%08lx\n\n"
"\tmountlist:\t%d\t0x%08lx\n"
"\tfsusage:\t%d\t0x%08lx\n\n"
"\tnetload:\t%d\t0x%08lx\n"
@@ -137,6 +138,8 @@ main (int argc, char *argv [])
(unsigned long) sysdeps.proc_args,
FEATURE_CHECK(PROC_MAP),
(unsigned long) sysdeps.proc_map,
+ FEATURE_CHECK(PROC_IO),
+ (unsigned long) sysdeps.proc_io,
FEATURE_CHECK(MOUNTLIST),
(unsigned long) sysdeps.mountlist,
FEATURE_CHECK(FSUSAGE),
diff --git a/examples/timings.c b/examples/timings.c
index 6c85da0f..15bc1973 100644
--- a/examples/timings.c
+++ b/examples/timings.c
@@ -412,6 +412,26 @@ main (int argc, char *argv [])
(long double) ELAPSED_UTIME / PROFILE_COUNT,
(long double) ELAPSED_STIME / PROFILE_COUNT);
+
+ getrusage (RUSAGE_SELF, &rusage_start);
+
+ for (c = 0; c < PROFILE_COUNT; c++)
+ glibtop_get_proc_io (&data.proc_io, pid);
+
+ getrusage (RUSAGE_SELF, &rusage_end);
+
+ libgtop_timersub (&rusage_end.ru_utime, &rusage_start.ru_utime,
+ &elapsed_utime);
+
+ libgtop_timersub (&rusage_end.ru_stime, &rusage_start.ru_stime,
+ &elapsed_stime);
+
+ printf ("Proc_Io (0x%08lx): %7lu - %9.2Lf - %9.2Lf\n",
+ (unsigned long) data.proc_io.flags, PROFILE_COUNT,
+ (long double) ELAPSED_UTIME / PROFILE_COUNT,
+ (long double) ELAPSED_STIME / PROFILE_COUNT);
+
+
getrusage (RUSAGE_SELF, &total_end);
libgtop_timersub (&total_end.ru_utime, &total_start.ru_utime,
diff --git a/features.def b/features.def
index 1025313e..faab87b1 100644
--- a/features.def
+++ b/features.def
@@ -24,4 +24,5 @@ void|ppp|ushort(device)
char **|netlist
char **|proc_wd|pid_t(pid)
guint16*|proc_affinity|pid_t(pid)
+void|proc_io|pid_t(pid)
diff --git a/include/glibtop/Makefile.am b/include/glibtop/Makefile.am
index 66bdd344..6d0e055f 100644
--- a/include/glibtop/Makefile.am
+++ b/include/glibtop/Makefile.am
@@ -9,6 +9,7 @@ glibtop_HEADERS = close.h loadavg.h prockernel.h procstate.h \
parameter.h mountlist.h fsusage.h procmap.h signal.h \
sysinfo.h ppp.h procargs.h netload.h \
procwd.h procaffinity.h \
+ procio.h \
netlist.h procopenfiles.h open.h
noinst_HEADERS = error.h write.h read_data.h read.h init_hooks.h machine.h \
diff --git a/include/glibtop/command.h b/include/glibtop/command.h
index 1d4d630c..9a0e47b1 100644
--- a/include/glibtop/command.h
+++ b/include/glibtop/command.h
@@ -59,8 +59,9 @@ G_BEGIN_DECLS
#define GLIBTOP_CMND_PROC_OPEN_FILES 25
#define GLIBTOP_CMND_PROC_WD 26
#define GLIBTOP_CMND_PROC_AFFINITY 27
+#define GLIBTOP_CMND_PROC_IO 28
-#define GLIBTOP_MAX_CMND 28
+#define GLIBTOP_MAX_CMND 29
#define _GLIBTOP_PARAM_SIZE 16
diff --git a/include/glibtop/procio.h b/include/glibtop/procio.h
new file mode 100644
index 00000000..86c06e5d
--- /dev/null
+++ b/include/glibtop/procio.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 2017 Robert Roth
+ This file is part of LibGTop.
+
+ Contributed by Robert Roth <robert.roth.off@gmail.com>, February 2017.
+
+ LibGTop 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 2 of the License,
+ or (at your option) any later version.
+
+ LibGTop 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 LibGTop; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GLIBTOP_PROCIO_H__
+#define __GLIBTOP_PROCIO_H__
+
+#include <glibtop.h>
+#include <glibtop/global.h>
+
+G_BEGIN_DECLS
+
+#define GLIBTOP_PROC_IO_DISK_RCHAR 0
+#define GLIBTOP_PROC_IO_DISK_WCHAR 1
+#define GLIBTOP_PROC_IO_DISK_RBYTES 2
+#define GLIBTOP_PROC_IO_DISK_WBYTES 3
+
+#define GLIBTOP_MAX_PROC_IO 3
+
+typedef struct _glibtop_proc_io glibtop_proc_io;
+
+/* Time section */
+
+/**
+ * glibtop_proc_io:
+ * @disk_rchar: The number of bytes which this task has caused to be read from storage. This
+ * is simply the sum of bytes which this process passed to read() and pread(), also including tty IO,
+ * and it is unaffected by whether or not actual physical disk IO was required.
+ * @disk_wchar: The number of bytes which this task has caused, or shall cause to be written
+ * to disk. Similar caveats apply here as with rchar.
+ * @disk_rbytes: Attempt to count the number of bytes which this process really did cause to
+ * be fetched from the storage layer. Done at the submit_bio() level, so it is
+ * accurate for block-backed filesystems.
+ * @disk_wbytes: Attempt to count the number of bytes which this process caused to be sent to
+ * the storage layer. This is done at page-dirtying time.
+ *
+ * Process disk io data filled by glibtop_get_proc_io().
+ *
+ */
+struct _glibtop_proc_io
+{
+ /*< private >*/
+ guint64 flags;
+ /*< public >*/
+ guint64 disk_rchar;
+ guint64 disk_wchar;
+ guint64 disk_rbytes;
+ guint64 disk_wbytes;
+
+ /* reserved for future extensions, e.g. per-process netio */
+ guint64 reserved[10];
+};
+
+
+void glibtop_get_proc_io (glibtop_proc_io *buf, pid_t pid);
+
+#if GLIBTOP_SUID_PROC_IO
+#define glibtop_get_proc_io_r glibtop_get_proc_io_p
+#else
+#define glibtop_get_proc_io_r glibtop_get_proc_io_s
+#endif
+
+void glibtop_get_proc_io_l (glibtop *server, glibtop_proc_io *buf, pid_t pid);
+
+#if GLIBTOP_SUID_PROC_IO
+void _glibtop_init_proc_io_p (glibtop *server);
+void glibtop_get_proc_io_p (glibtop *server, glibtop_proc_io *buf, pid_t pid);
+#else
+void _glibtop_init_proc_io_s (glibtop *server);
+void glibtop_get_proc_io_s (glibtop *server, glibtop_proc_io *buf, pid_t pid);
+#endif
+
+
+G_END_DECLS
+
+#endif
diff --git a/include/glibtop/sysdeps.h b/include/glibtop/sysdeps.h
index 61006a0a..6b5682df 100644
--- a/include/glibtop/sysdeps.h
+++ b/include/glibtop/sysdeps.h
@@ -53,8 +53,9 @@ G_BEGIN_DECLS
#define GLIBTOP_SYSDEPS_PROC_OPEN_FILES 24
#define GLIBTOP_SYSDEPS_PROC_WD 25
#define GLIBTOP_SYSDEPS_PROC_AFFINITY 26
+#define GLIBTOP_SYSDEPS_PROC_IO 27
-#define GLIBTOP_MAX_SYSDEPS 27
+#define GLIBTOP_MAX_SYSDEPS 28
/* The 'features' args to glibtop_init_* is an unsigned long */
G_STATIC_ASSERT((1UL << (GLIBTOP_MAX_SYSDEPS - 1)) <= ULONG_MAX);
@@ -93,6 +94,7 @@ struct _glibtop_sysdeps
guint64 ppp; /* glibtop_ppp */
guint64 proc_wd; /* glibtop_proc_wd */
guint64 proc_affinity; /* glibtop_proc_affinity */
+ guint64 proc_io; /* glibtop_proc_io */
};
void glibtop_get_sysdeps (glibtop_sysdeps *buf);
diff --git a/include/glibtop/union.h b/include/glibtop/union.h
index a140d71a..334f0217 100644
--- a/include/glibtop/union.h
+++ b/include/glibtop/union.h
@@ -44,6 +44,7 @@
#include <glibtop/procopenfiles.h>
#include <glibtop/procwd.h>
#include <glibtop/procaffinity.h>
+#include <glibtop/procio.h>
#include <glibtop/mountlist.h>
#include <glibtop/fsusage.h>
@@ -84,6 +85,7 @@ union _glibtop_union
glibtop_proc_open_files proc_open_files;
glibtop_proc_wd proc_wd;
glibtop_proc_affinity proc_affinity;
+ glibtop_proc_io proc_io;
};
G_END_DECLS
diff --git a/lib/Makefile.am b/lib/Makefile.am
index dec24a04..90b82861 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -35,7 +35,7 @@ introspection_sources = $(libgtop_2_0_la_SOURCES) lib.c ../glibtop.h ../libgtopc
../include/glibtop/procsignal.h ../include/glibtop/union.h ../include/glibtop/gnuserv.h \
../include/glibtop/parameter.h ../include/glibtop/mountlist.h ../include/glibtop/fsusage.h ../include/glibtop/procmap.h ../include/glibtop/signal.h \
../include/glibtop/sysinfo.h ../include/glibtop/ppp.h ../include/glibtop/procargs.h ../include/glibtop/netload.h \
- ../include/glibtop/procwd.h ../include/glibtop/procaffinity.h \
+ ../include/glibtop/procwd.h ../include/glibtop/procaffinity.h ../include/glibtop/procio.h \
../include/glibtop/netlist.h ../include/glibtop/procopenfiles.h ../include/glibtop/open.h
GTop-2.0.gir: libgtop-2.0.la
diff --git a/lib/command.c b/lib/command.c
index 414081c3..b6ccf1f2 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -68,6 +68,7 @@ glibtop_call_l (glibtop *server, unsigned command, size_t send_size,
CHECK_CMND(GLIBTOP_CMND_PROC_OPEN_FILES);
CHECK_CMND(GLIBTOP_CMND_PROC_WD);
CHECK_CMND(GLIBTOP_CMND_PROC_AFFINITY);
+ CHECK_CMND(GLIBTOP_CMND_PROC_IO);
default:
glibtop_error_r(server, "CALL: command UNKNOWN(%d) sending %lu bytes", command, (unsigned long)send_size); break;
}
diff --git a/lib/libgtop.sym b/lib/libgtop.sym
index d15adcc6..afa9d070 100644
--- a/lib/libgtop.sym
+++ b/lib/libgtop.sym
@@ -52,6 +52,8 @@ glibtop_get_shm_limits
glibtop_get_shm_limits_l
glibtop_get_proc_affinity
glibtop_get_proc_affinity_l
+glibtop_get_proc_io
+glibtop_get_proc_io_l
glibtop_get_swap
glibtop_get_swap_l
glibtop_get_sysdeps
diff --git a/lib/sysdeps.c b/lib/sysdeps.c
index 3a90a54c..e942fd4a 100644
--- a/lib/sysdeps.c
+++ b/lib/sysdeps.c
@@ -48,7 +48,8 @@ GLIBTOP_SUID_NETLOAD +
GLIBTOP_SUID_NETLIST +
GLIBTOP_SUID_PROC_WD +
GLIBTOP_SUID_PROC_AFFINITY +
-GLIBTOP_SUID_PPP;
+GLIBTOP_SUID_PPP +
+GLIBTOP_SUID_PROC_IO;
const _glibtop_init_func_t _glibtop_init_hook_s [] = {
#if !GLIBTOP_SUID_CPU
@@ -120,6 +121,9 @@ const _glibtop_init_func_t _glibtop_init_hook_s [] = {
#if !GLIBTOP_SUID_PPP
_glibtop_init_ppp_s,
#endif
+#if !GLIBTOP_SUID_PROC_IO
+ _glibtop_init_proc_io_s,
+#endif
NULL
};
@@ -193,6 +197,9 @@ const _glibtop_init_func_t _glibtop_init_hook_p [] = {
#if GLIBTOP_SUID_PPP
_glibtop_init_ppp_p,
#endif
+#if GLIBTOP_SUID_PROC_IO
+ _glibtop_init_proc_io_p,
+#endif
NULL
};
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 11364229..b51addf6 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -221,6 +221,12 @@ handle_parent_connection (int s)
do_output (s, resp, _offset_data (fsusage),
0, NULL);
break;
+ case GLIBTOP_CMND_PROC_IO:
+ glibtop_get_proc_io_l
+ (server, &resp->u.data.proc_io, parameter);
+ do_output (s, resp, _offset_data (proc_io),
+ 0, NULL);
+ break;
case GLIBTOP_CMND_PPP:
memcpy (&device, parameter, sizeof (device));
glibtop_get_ppp_l
diff --git a/src/daemon/slave.c b/src/daemon/slave.c
index 2858ee8a..e15f1efc 100644
--- a/src/daemon/slave.c
+++ b/src/daemon/slave.c
@@ -209,6 +209,14 @@ handle_slave_command (glibtop_command *cmnd, glibtop_response *resp,
resp->offset = _offset_data (proc_time);
break;
#endif
+#if GLIBTOP_SUID_PROC_IO
+ case GLIBTOP_CMND_PROC_IO:
+ memcpy (&pid, parameter, sizeof (pid_t));
+ glibtop_get_proc_io_p
+ (server, &resp->u.data.proc_io, pid);
+ resp->offset = _offset_data (proc_time);
+ break;
+#endif
#if GLIBTOP_SUID_PROC_SIGNAL
case GLIBTOP_CMND_PROC_SIGNAL:
memcpy (&pid, parameter, sizeof (pid_t));
diff --git a/sysdeps/common/default.c b/sysdeps/common/default.c
index 2df25ee6..e3b096f2 100644
--- a/sysdeps/common/default.c
+++ b/sysdeps/common/default.c
@@ -431,3 +431,18 @@ glibtop_get_proc_affinity(glibtop_proc_affinity *buf, pid_t pid)
{
return glibtop_get_proc_affinity_l(glibtop_global_server, buf, pid);
}
+
+/**
+ * glibtop_get_proc_io: Get the io stats for the given pid
+ * @buf: Buffer where the result will be given
+ * @pid: Process id to get the io stats for
+ *
+ * Get the io stats for a process
+ *
+ * Returns: A list of processor ID of 'buf.number' elements.
+ */
+void
+glibtop_get_proc_io(glibtop_proc_io *buf, pid_t pid)
+{
+ return glibtop_get_proc_io_l(glibtop_global_server, buf, pid);
+}
diff --git a/sysdeps/common/sysdeps_suid.c b/sysdeps/common/sysdeps_suid.c
index 91ff806c..24953176 100644
--- a/sysdeps/common/sysdeps_suid.c
+++ b/sysdeps/common/sysdeps_suid.c
@@ -90,6 +90,9 @@ const _glibtop_init_func_t _glibtop_init_hook_p [] = {
#if GLIBTOP_SUID_PPP
_glibtop_init_ppp_p,
#endif
+#if GLIBTOP_SUID_PROC_IO
+ _glibtop_init_proc_io_p,
+#endif
NULL
};
diff --git a/sysdeps/freebsd/Makefile.am b/sysdeps/freebsd/Makefile.am
index 6bd15894..7cacb707 100644
--- a/sysdeps/freebsd/Makefile.am
+++ b/sysdeps/freebsd/Makefile.am
@@ -16,6 +16,7 @@ libgtop_sysdeps_suid_2_0_la_SOURCES = suid_open.c close.c swap.c \
proclist.c procstate.c procuid.c \
proctime.c procmem.c procsignal.c \
prockernel.c procsegment.c procargs.c \
+ procio.c \
procmap.c netload.c ppp.c
libgtop_sysdeps_suid_2_0_la_LDFLAGS = $(LT_VERSION_INFO)
diff --git a/sysdeps/freebsd/glibtop_server.h b/sysdeps/freebsd/glibtop_server.h
index d9ea12d6..d908ea7c 100644
--- a/sysdeps/freebsd/glibtop_server.h
+++ b/sysdeps/freebsd/glibtop_server.h
@@ -47,6 +47,7 @@ G_BEGIN_DECLS
#define GLIBTOP_SUID_NETLIST 0
#define GLIBTOP_SUID_PROC_WD 0
#define GLIBTOP_SUID_PROC_AFFINITY 0
+#define GLIBTOP_SUID_PROC_IO (1 << GLIBTOP_SYSDEPS_PROC_IO)
G_END_DECLS
diff --git a/sysdeps/freebsd/procio.c b/sysdeps/freebsd/procio.c
new file mode 100644
index 00000000..0525a2a7
--- /dev/null
+++ b/sysdeps/freebsd/procio.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2017 Robert Roth
+ This file is part of LibGTop.
+
+ Contributed by Robert Roth <robert.roth.off@gmail.com>, February 2017.
+
+ LibGTop 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 2 of the License,
+ or (at your option) any later version.
+
+ LibGTop 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 LibGTop; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+#include <glibtop.h>
+#include <glibtop/procio.h>
+#include <glibtop/error.h>
+#include <glibtop_suid.h>
+
+static const unsigned long _glibtop_sysdeps_proc_io =
+ (1UL << GLIBTOP_PROC_IO_DISK_RBYTES) + (1UL << GLIBTOP_PROC_IO_DISK_WBYTES);
+
+/* Init function. */
+
+void
+_glibtop_init_proc_io_p (glibtop *server)
+{
+ server->sysdeps.proc_io = _glibtop_sysdeps_proc_io;
+}
+
+/* Provides detailed information about a process. */
+
+void
+glibtop_get_proc_io_p (glibtop *server, glibtop_proc_io *buf,
+ pid_t pid)
+{
+ memset (buf, 0, sizeof (glibtop_proc_io));
+
+ struct kinfo_proc *pinfo;
+ int count;
+
+ glibtop_suid_enter (server);
+
+ /* Get the process information */
+ pinfo = kvm_getprocs (server->machine->kd, KERN_PROC_PID, pid, &count);
+ if ((pinfo == NULL) || (count != 1)) {
+ glibtop_warn_io_r (server, "kvm_getprocs (%d)", pid);
+ glibtop_suid_leave (server);
+ return;
+ }
+
+ glibtop_suid_leave (server);
+
+ /* man getrusage
+
+ long ru_inblock; == block input operations
+ long ru_oublock; == block output operations
+
+ ru_inblock the number of times the file system had to perform input.
+ ru_oublock the number of times the file system had to perform output.
+
+ And then it says 'account only for real IO'.
+
+ But if I write 1MB in a process, I can see ru_oublock increased
+ 1024. So it's neither a number of operations or times.
+
+ FIXME: seems the blocksize is 1024 but ...
+ */
+ buf->disk_rbytes = pinfo->ki_rusage.ru_inblock << 10;
+ buf->disk_wbytes = pinfo->ki_rusage.ru_oublock << 10;
+ buf->flags = _glibtop_sysdeps_proc_io;
+}
diff --git a/sysdeps/linux/Makefile.am b/sysdeps/linux/Makefile.am
index ae480f1f..7baabe0b 100644
--- a/sysdeps/linux/Makefile.am
+++ b/sysdeps/linux/Makefile.am
@@ -10,7 +10,7 @@ libgtop_sysdeps_2_0_la_SOURCES = open.c close.c cpu.c mem.c swap.c \
proctime.c procmem.c procsignal.c prockernel.c \
procsegment.c procargs.c procmap.c siglist.c \
sysinfo.c netload.c ppp.c glibtop_private.c \
- mountlist.c procaffinity.c \
+ mountlist.c procaffinity.c procio.c \
fsusage.c netlist.c procopenfiles.c procwd.c
libgtop_sysdeps_2_0_la_LIBADD = @GLIB_LIBS@
diff --git a/sysdeps/linux/glibtop_server.h b/sysdeps/linux/glibtop_server.h
index 5912ad05..8e591eab 100644
--- a/sysdeps/linux/glibtop_server.h
+++ b/sysdeps/linux/glibtop_server.h
@@ -46,5 +46,6 @@
#define GLIBTOP_SUID_PROC_AFFINITY 0
#define GLIBTOP_SUID_PPP 0
#define GLIBTOP_SUID_PROC_FILE 0
+#define GLIBTOP_SUID_PROC_IO 0
#endif /* __LINUX__GLIBTOP_SERVER_H__ */
diff --git a/sysdeps/linux/procio.c b/sysdeps/linux/procio.c
new file mode 100644
index 00000000..2240022f
--- /dev/null
+++ b/sysdeps/linux/procio.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2017 Robert Roth
+ This file is part of LibGTop.
+
+ Contributed by Robert Roth <robert.roth.off@gmail.com>, February 2017.
+
+ LibGTop 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 2 of the License,
+ or (at your option) any later version.
+
+ LibGTop 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 LibGTop; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+#include <glibtop.h>
+#include <glibtop/error.h>
+#include <glibtop/procio.h>
+
+#include "glibtop_private.h"
+
+static const unsigned long _glibtop_sysdeps_proc_io =
+(1L << GLIBTOP_PROC_IO_DISK_RCHAR) + (1L << GLIBTOP_PROC_IO_DISK_WCHAR) +
+(1L << GLIBTOP_PROC_IO_DISK_RBYTES) + (1L << GLIBTOP_PROC_IO_DISK_WBYTES);
+
+/* Init function. */
+
+void
+_glibtop_init_proc_io_s (glibtop *server)
+{
+ server->sysdeps.proc_io = _glibtop_sysdeps_proc_io;
+}
+
+/* Provides detailed information about a process. */
+
+void
+glibtop_get_proc_io_s (glibtop *server, glibtop_proc_io *buf, pid_t pid)
+{
+ char buffer [BUFSIZ], *p;
+ memset (buf, 0, sizeof (glibtop_proc_io));
+
+ if (server->os_version_code < LINUX_VERSION_CODE(2, 6, 20))
+ return;
+
+ if (proc_file_to_buffer(buffer, sizeof buffer, "/proc/%d/io", pid))
+ return;
+
+ p = skip_token (buffer);
+ buf->disk_rchar = g_ascii_strtoull (p, &p, 10);
+ p = skip_line (p);
+ p = skip_token (p);
+ buf->disk_wchar = g_ascii_strtoull (p, &p, 10);
+ p = skip_line (p);
+ p = skip_line (p);
+ p = skip_line (p);
+ p = skip_token (p);
+ buf->disk_rbytes = g_ascii_strtoull (p, &p, 10);
+ p = skip_line (p);
+ p = skip_token (p);
+ buf->disk_wbytes = g_ascii_strtoull (p, &p, 10);
+
+ buf->flags = _glibtop_sysdeps_proc_io;
+}
diff --git a/sysdeps/stub/procio.c b/sysdeps/stub/procio.c
new file mode 100644
index 00000000..a4846aee
--- /dev/null
+++ b/sysdeps/stub/procio.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2017 Robert Roth
+ This file is part of LibGTop.
+
+ Contributed by Robert Roth <robert.roth.off@gmail.com>, February 2017.
+
+ LibGTop 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 2 of the License,
+ or (at your option) any later version.
+
+ LibGTop 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 LibGTop; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+#include <glibtop.h>
+#include <glibtop/procio.h>
+
+static const unsigned long _glibtop_sysdeps_proc_io = 0;
+
+/* Init function. */
+
+void
+_glibtop_init_proc_io_s (glibtop *server)
+{
+ server->sysdeps.proc_io = _glibtop_sysdeps_proc_io;
+}
+
+/* Provides detailed information about a process. */
+
+void
+glibtop_get_proc_io_s (glibtop *server, glibtop_proc_io *buf,
+ pid_t pid)
+{
+ memset (buf, 0, sizeof (glibtop_proc_io));
+}
diff --git a/sysdeps/stub_suid/glibtop_server.h b/sysdeps/stub_suid/glibtop_server.h
index cf121212..15fe2e11 100644
--- a/sysdeps/stub_suid/glibtop_server.h
+++ b/sysdeps/stub_suid/glibtop_server.h
@@ -45,6 +45,7 @@ G_BEGIN_DECLS
#define GLIBTOP_SUID_NETLOAD (1 << GLIBTOP_SYSDEPS_NETLOAD)
#define GLIBTOP_SUID_NETLIST 0
#define GLIBTOP_SUID_PPP (1 << GLIBTOP_SYSDEPS_PPP)
+#define GLIBTOP_SUID_PROC_IO (1 << GLIBTOP_SYSDEPS_PROC_IO)
G_END_DECLS