gfio: ignore group stats for now
[fio.git] / gfio.c
diff --git a/gfio.c b/gfio.c
index 8f84638c356c2223aea9d24b984773e6bcdad9ca..ead2c3d3a3f3f031dd4aaf9a5a1ce1d8fccdb83d 100644 (file)
--- a/gfio.c
+++ b/gfio.c
@@ -23,6 +23,7 @@
  */
 #include <locale.h>
 #include <malloc.h>
+#include <string.h>
 
 #include <glib.h>
 #include <cairo.h>
 #include "graph.h"
 
 static int gfio_server_running;
+static const char *gfio_graph_font;
 
 static void gfio_update_thread_status(char *status_message, double perc);
+static void view_log(GtkWidget *w, gpointer data);
 
 #define ARRAYSIZE(x) (sizeof((x)) / (sizeof((x)[0])))
 
@@ -41,6 +44,7 @@ typedef void (*clickfunction)(GtkWidget *widget, gpointer data);
 
 static void connect_clicked(GtkWidget *widget, gpointer data);
 static void start_job_clicked(GtkWidget *widget, gpointer data);
+static void send_clicked(GtkWidget *widget, gpointer data);
 
 static struct button_spec {
        const char *buttontext;
@@ -49,10 +53,11 @@ static struct button_spec {
        const int start_insensitive;
 } buttonspeclist[] = {
 #define CONNECT_BUTTON 0
-#define START_JOB_BUTTON 1
+#define SEND_BUTTON 1
+#define START_JOB_BUTTON 2
        { "Connect", connect_clicked, "Connect to host", 0 },
-       { "Start Job",
-               start_job_clicked,
+       { "Send", send_clicked, "Send job description to host", 1 },
+       { "Start Job", start_job_clicked,
                "Send current fio job to fio server to be executed", 1 },
 };
 
@@ -93,6 +98,8 @@ struct gui {
 #define DRAWING_AREA_XDIM 1000
 #define DRAWING_AREA_YDIM 400
        GtkWidget *drawing_area;
+       int drawing_area_xdim;
+       int drawing_area_ydim;
        GtkWidget *error_info_bar;
        GtkWidget *error_label;
        GtkWidget *results_notebook;
@@ -109,45 +116,51 @@ struct gui {
 
        struct graph *iops_graph;
        struct graph *bandwidth_graph;
-       struct fio_client *client;
+       struct gfio_client *client;
        int nr_job_files;
        char **job_files;
 } ui;
 
 struct gfio_client {
        struct gui *ui;
+       struct fio_client *client;
        GtkWidget *results_widget;
        GtkWidget *disk_util_frame;
+       GtkWidget *err_entry;
+       unsigned int job_added;
+       struct thread_options o;
 };
 
 static void setup_iops_graph(struct gui *ui)
 {
        if (ui->iops_graph)
                graph_free(ui->iops_graph);
-       ui->iops_graph = graph_new((int) DRAWING_AREA_XDIM / 2.0,
-                                       (int) DRAWING_AREA_YDIM);
+       ui->iops_graph = graph_new(DRAWING_AREA_XDIM / 2.0,
+                                       DRAWING_AREA_YDIM, gfio_graph_font);
        graph_title(ui->iops_graph, "IOPS");
-       graph_x_title(ui->iops_graph, "Time");
-       graph_y_title(ui->iops_graph, "IOPS");
+       graph_x_title(ui->iops_graph, "Time (secs)");
+       graph_y_title(ui->iops_graph, "IOs / sec");
        graph_add_label(ui->iops_graph, "Read IOPS");
        graph_add_label(ui->iops_graph, "Write IOPS");
-       graph_set_color(ui->iops_graph, "Read IOPS", 0.7, 0.0, 0.0);
-       graph_set_color(ui->iops_graph, "Write IOPS", 0.0, 0.0, 0.7);
+       graph_set_color(ui->iops_graph, "Read IOPS", 0.13, 0.54, 0.13);
+       graph_set_color(ui->iops_graph, "Write IOPS", 1.0, 0.0, 0.0);
+       line_graph_set_data_count_limit(ui->iops_graph, 100);
 }
 
 static void setup_bandwidth_graph(struct gui *ui)
 {
        if (ui->bandwidth_graph)
                graph_free(ui->bandwidth_graph);
-       ui->bandwidth_graph = graph_new((int) DRAWING_AREA_XDIM / 2.0,
-                                       (int) DRAWING_AREA_YDIM);
+       ui->bandwidth_graph = graph_new(DRAWING_AREA_XDIM / 2.0,
+                                       DRAWING_AREA_YDIM, gfio_graph_font);
        graph_title(ui->bandwidth_graph, "Bandwidth");
-       graph_x_title(ui->bandwidth_graph, "Time");
-       graph_y_title(ui->bandwidth_graph, "Bandwidth");
+       graph_x_title(ui->bandwidth_graph, "Time (secs)");
+       graph_y_title(ui->bandwidth_graph, "Kbytes / sec");
        graph_add_label(ui->bandwidth_graph, "Read Bandwidth");
        graph_add_label(ui->bandwidth_graph, "Write Bandwidth");
-       graph_set_color(ui->bandwidth_graph, "Read Bandwidth", 0.7, 0.0, 0.0);
-       graph_set_color(ui->bandwidth_graph, "Write Bandwidth", 0.0, 0.0, 0.7);
+       graph_set_color(ui->bandwidth_graph, "Read Bandwidth", 0.13, 0.54, 0.13);
+       graph_set_color(ui->bandwidth_graph, "Write Bandwidth", 1.0, 0.0, 0.0);
+       line_graph_set_data_count_limit(ui->bandwidth_graph, 100);
 }
 
 static void clear_ui_info(struct gui *ui)
@@ -213,13 +226,14 @@ static GtkWidget *create_spinbutton(GtkWidget *hbox, double min, double max, dou
 static void gfio_set_connected(struct gui *ui, int connected)
 {
        if (connected) {
-               gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+               gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1);
                ui->connected = 1;
                gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Disconnect");
                gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
        } else {
                ui->connected = 0;
                gtk_button_set_label(GTK_BUTTON(ui->button[CONNECT_BUTTON]), "Connect");
+               gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0);
                gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
                gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 1);
        }
@@ -809,6 +823,7 @@ static GtkWidget *get_results_window(struct gui *ui)
 
        win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_title(GTK_WINDOW(win), "Results");
+       gtk_window_set_default_size(GTK_WINDOW(win), 1024, 768);
        g_signal_connect(win, "delete-event", G_CALLBACK(results_window_delete), ui);
        g_signal_connect(win, "destroy", G_CALLBACK(results_window_delete), ui);
 
@@ -823,19 +838,25 @@ static GtkWidget *get_results_window(struct gui *ui)
 static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
                            struct group_run_stats *rs)
 {
-       GtkWidget *res_win, *box, *vbox, *entry;
+       GtkWidget *res_win, *box, *vbox, *entry, *scroll;
        struct gfio_client *gc = client->client_data;
 
        gdk_threads_enter();
 
        res_win = get_results_window(gc->ui);
 
+       scroll = gtk_scrolled_window_new(NULL, NULL);
+       gtk_container_set_border_width(GTK_CONTAINER(scroll), 5);
+       gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
        vbox = gtk_vbox_new(FALSE, 3);
 
-       box = gtk_hbox_new(TRUE, 3);
-       gtk_box_pack_start(GTK_BOX(vbox), box, FALSE, FALSE, 5);
+       box = gtk_hbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(vbox), box, TRUE, FALSE, 5);
 
-       gtk_notebook_append_page(GTK_NOTEBOOK(res_win), vbox, gtk_label_new(ts->name));
+       gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), vbox);
+
+       gtk_notebook_append_page(GTK_NOTEBOOK(res_win), scroll, gtk_label_new(ts->name));
 
        gc->results_widget = vbox;
 
@@ -849,7 +870,7 @@ static void gfio_display_ts(struct fio_client *client, struct thread_stat *ts,
        entry_set_int_value(entry, ts->groupid);
        entry = new_info_entry_in_frame(box, "Jobs");
        entry_set_int_value(entry, ts->members);
-       entry = new_info_entry_in_frame(box, "Error");
+       gc->err_entry = entry = new_info_entry_in_frame(box, "Error");
        entry_set_int_value(entry, ts->error);
        entry = new_info_entry_in_frame(box, "PID");
        entry_set_int_value(entry, ts->pid);
@@ -889,6 +910,9 @@ static void gfio_text_op(struct fio_client *client, struct fio_net_cmd *cmd)
        gtk_list_store_set(gc->ui->log_model, &iter, 2, p->level, -1);
        gtk_list_store_set(gc->ui->log_model, &iter, 3, p->buf, -1);
 
+       if (p->level == FIO_LOG_ERR)
+               view_log(NULL, (gpointer) gc->ui);
+
        gdk_threads_leave();
 }
 
@@ -897,13 +921,13 @@ static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd
        struct cmd_du_pdu *p = (struct cmd_du_pdu *) cmd->payload;
        struct gfio_client *gc = client->client_data;
        GtkWidget *box, *frame, *entry, *vbox;
+       double util;
+       char tmp[16];
 
        gdk_threads_enter();
 
-       if (!gc->results_widget) {
-               printf("no results!\n");
+       if (!gc->results_widget)
                goto out;
-       }
 
        if (!gc->disk_util_frame) {
                gc->disk_util_frame = gtk_frame_new("Disk utilization");
@@ -954,6 +978,16 @@ static void gfio_disk_util_op(struct fio_client *client, struct fio_net_cmd *cmd
        entry = new_info_entry_in_frame(vbox, "Time in queue");
        entry_set_int_value(entry, p->dus.time_in_queue);
 
+       util = 0.0;
+       if (p->dus.msec)
+               util = (double) 100 * p->dus.io_ticks / (double) p->dus.msec;
+       if (util > 100.0)
+               util = 100.0;
+
+       sprintf(tmp, "%3.2f%%", util);
+       entry = new_info_entry_in_frame(vbox, "Disk utilization");
+       gtk_entry_set_text(GTK_ENTRY(entry), tmp);
+
        gtk_widget_show_all(gc->results_widget);
 out:
        gdk_threads_leave();
@@ -990,10 +1024,14 @@ static void gfio_thread_status_op(struct fio_client *client,
 static void gfio_group_stats_op(struct fio_client *client,
                                struct fio_net_cmd *cmd)
 {
-       gdk_threads_enter();
-       printf("gfio_group_stats_op called\n");
-       fio_client_ops.group_stats(client, cmd);
-       gdk_threads_leave();
+       /* We're ignoring group stats for now */
+}
+
+static gint on_config_drawing_area(GtkWidget *w, GdkEventConfigure *event)
+{
+       ui.drawing_area_xdim = w->allocation.width;
+       ui.drawing_area_ydim = w->allocation.height;
+       return TRUE;
 }
 
 static int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p)
@@ -1001,6 +1039,10 @@ static int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p)
        struct gui *ui = (struct gui *) p;
        cairo_t *cr;
 
+       graph_set_size(ui->iops_graph, ui->drawing_area_xdim / 2.0,
+                                       ui->drawing_area_ydim);
+       graph_set_size(ui->bandwidth_graph, ui->drawing_area_xdim / 2.0,
+                                       ui->drawing_area_ydim);
        cr = gdk_cairo_create(w->window);
 
        cairo_set_source_rgb(cr, 0, 0, 0);
@@ -1012,8 +1054,7 @@ static int on_expose_drawing_area(GtkWidget *w, GdkEvent *event, gpointer p)
        cairo_restore(cr);
 
        cairo_save(cr);
-       cairo_translate(cr, DRAWING_AREA_XDIM / 2.0, 0);
-                               // DRAWING_AREA_YDIM * 0.05);
+       cairo_translate(cr, ui->drawing_area_xdim / 2.0, 0);
        line_graph_draw(ui->iops_graph, cr);
        cairo_stroke(cr);
        cairo_restore(cr);
@@ -1168,30 +1209,23 @@ static void gfio_add_job_op(struct fio_client *client, struct fio_net_cmd *cmd)
 {
        struct cmd_add_job_pdu *p = (struct cmd_add_job_pdu *) cmd->payload;
        struct gfio_client *gc = client->client_data;
+       struct thread_options *o = &gc->o;
        struct gui *ui = gc->ui;
        char tmp[8];
-       int i;
 
-       p->iodepth              = le32_to_cpu(p->iodepth);
-       p->rw                   = le32_to_cpu(p->rw);
-
-       for (i = 0; i < 2; i++) {
-               p->min_bs[i]    = le32_to_cpu(p->min_bs[i]);
-               p->max_bs[i]    = le32_to_cpu(p->max_bs[i]);
-       }
-
-       p->numjobs              = le32_to_cpu(p->numjobs);
-       p->group_reporting      = le32_to_cpu(p->group_reporting);
+       convert_thread_options_to_cpu(o, &p->top);
 
        gdk_threads_enter();
 
-       gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) p->jobname);
-       gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(p->rw));
-       gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) p->ioengine);
+       gtk_entry_set_text(GTK_ENTRY(ui->eta.name), (gchar *) o->name);
+       gtk_entry_set_text(GTK_ENTRY(ui->eta.iotype), ddir_str(o->td_ddir));
+       gtk_entry_set_text(GTK_ENTRY(ui->eta.ioengine), (gchar *) o->ioengine);
 
-       sprintf(tmp, "%u", p->iodepth);
+       sprintf(tmp, "%u", o->iodepth);
        gtk_entry_set_text(GTK_ENTRY(ui->eta.iodepth), tmp);
 
+       gc->job_added++;
+
        gdk_threads_leave();
 }
 
@@ -1213,7 +1247,9 @@ static void gfio_client_timed_out(struct fio_client *client)
                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                        GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
 
-       content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+       /* gtk_dialog_get_content_area() is 2.14 and newer */
+       content = GTK_DIALOG(dialog)->vbox;
+
        label = gtk_label_new((const gchar *) buf);
        gtk_container_add(GTK_CONTAINER(content), label);
        gtk_widget_show_all(dialog);
@@ -1225,6 +1261,20 @@ static void gfio_client_timed_out(struct fio_client *client)
        gdk_threads_leave();
 }
 
+static void gfio_client_stop(struct fio_client *client, struct fio_net_cmd *cmd)
+{
+       struct gfio_client *gc = client->client_data;
+
+       gdk_threads_enter();
+
+       gfio_set_connected(gc->ui, 0);
+
+       if (gc->err_entry)
+               entry_set_int_value(gc->err_entry, client->error);
+
+       gdk_threads_leave();
+}
+
 struct client_ops gfio_client_ops = {
        .text_op                = gfio_text_op,
        .disk_util              = gfio_disk_util_op,
@@ -1235,6 +1285,7 @@ struct client_ops gfio_client_ops = {
        .quit                   = gfio_quit_op,
        .add_job                = gfio_add_job_op,
        .timed_out              = gfio_client_timed_out,
+       .stop                   = gfio_client_stop,
        .stay_connected         = 1,
 };
 
@@ -1271,15 +1322,6 @@ static int send_job_files(struct gui *ui)
        return ret;
 }
 
-static void start_job_thread(struct gui *ui)
-{
-       if (send_job_files(ui)) {
-               printf("Yeah, I didn't really like those options too much.\n");
-               gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
-               return;
-       }
-}
-
 static void *server_thread(void *arg)
 {
        is_backend = 1;
@@ -1302,9 +1344,10 @@ static void start_job_clicked(__attribute__((unused)) GtkWidget *widget,
                 gpointer data)
 {
        struct gui *ui = data;
+       struct gfio_client *gc = ui->client;
 
        gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 0);
-       start_job_thread(ui);
+       fio_net_send_simple_cmd(gc->client->fd, FIO_NET_CMD_RUN, 0, NULL);
 }
 
 static void file_open(GtkWidget *w, gpointer data);
@@ -1321,6 +1364,7 @@ static void connect_clicked(GtkWidget *widget, gpointer data)
                if (!fio_clients_connect()) {
                        pthread_create(&ui->t, NULL, job_thread, NULL);
                        gtk_widget_set_sensitive(ui->button[CONNECT_BUTTON], 0);
+                       gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 1);
                }
        } else {
                fio_clients_terminate();
@@ -1329,6 +1373,19 @@ static void connect_clicked(GtkWidget *widget, gpointer data)
        }
 }
 
+static void send_clicked(GtkWidget *widget, gpointer data)
+{
+       struct gui *ui = data;
+
+       if (send_job_files(ui)) {
+               printf("Yeah, I didn't really like those options too much.\n");
+               gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+       }
+
+       gtk_widget_set_sensitive(ui->button[SEND_BUTTON], 0);
+       gtk_widget_set_sensitive(ui->button[START_JOB_BUTTON], 1);
+}
+
 static void add_button(struct gui *ui, int i, GtkWidget *buttonbox,
                        struct button_spec *buttonspec)
 {
@@ -1436,7 +1493,8 @@ static int get_connection_details(char **host, int *port, int *type,
                        GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL);
 
        frame = gtk_frame_new("Hostname / socket name");
-       vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+       /* gtk_dialog_get_content_area() is 2.14 and newer */
+       vbox = GTK_DIALOG(dialog)->vbox;
        gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
 
        box = gtk_vbox_new(FALSE, 6);
@@ -1524,6 +1582,9 @@ static void gfio_client_added(struct gui *ui, struct fio_client *client)
        gc = malloc(sizeof(*gc));
        memset(gc, 0, sizeof(*gc));
        gc->ui = ui;
+       gc->client = client;
+
+       ui->client = gc;
 
        client->client_data = gc;
 }
@@ -1662,7 +1723,7 @@ static void view_log(GtkWidget *w, gpointer data)
 
 static void preferences(GtkWidget *w, gpointer data)
 {
-       GtkWidget *dialog, *frame, *box, **buttons;
+       GtkWidget *dialog, *frame, *box, **buttons, *vbox, *font;
        int i;
 
        dialog = gtk_dialog_new_with_buttons("Preferences",
@@ -1674,17 +1735,35 @@ static void preferences(GtkWidget *w, gpointer data)
 
        frame = gtk_frame_new("Debug logging");
        gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+
+       vbox = gtk_vbox_new(FALSE, 6);
+       gtk_container_add(GTK_CONTAINER(frame), vbox);
+
        box = gtk_hbox_new(FALSE, 6);
-       gtk_container_add(GTK_CONTAINER(frame), box);
+       gtk_container_add(GTK_CONTAINER(vbox), box);
 
        buttons = malloc(sizeof(GtkWidget *) * FD_DEBUG_MAX);
 
        for (i = 0; i < FD_DEBUG_MAX; i++) {
+               if (i == 7) {
+                       box = gtk_hbox_new(FALSE, 6);
+                       gtk_container_add(GTK_CONTAINER(vbox), box);
+               }
+
+
                buttons[i] = gtk_check_button_new_with_label(debug_levels[i].name);
                gtk_widget_set_tooltip_text(buttons[i], debug_levels[i].help);
                gtk_box_pack_start(GTK_BOX(box), buttons[i], FALSE, FALSE, 6);
        }
 
+       frame = gtk_frame_new("Graph font");
+       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), frame, FALSE, FALSE, 5);
+       vbox = gtk_vbox_new(FALSE, 6);
+       gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+       font = gtk_font_button_new();
+       gtk_box_pack_start(GTK_BOX(vbox), font, FALSE, FALSE, 5);
+
        gtk_widget_show_all(dialog);
 
        if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
@@ -1700,21 +1779,49 @@ static void preferences(GtkWidget *w, gpointer data)
                        fio_debug |= (1UL << i);
        }
 
+       gfio_graph_font = strdup(gtk_font_button_get_font_name(GTK_FONT_BUTTON(font)));
        gtk_widget_destroy(dialog);
 }
 
 static void about_dialog(GtkWidget *w, gpointer data)
 {
+       const char *authors[] = {
+               "Jens Axboe <axboe@kernel.dk>",
+               "Stephen Carmeron <stephenmcameron@gmail.com>",
+               NULL
+       };
+       const char *license[] = {
+               "Fio 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.\n",
+               "Fio 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.\n",
+               "You should have received a copy of the GNU General Public License "
+               "along with Fio; if not, write to the Free Software Foundation, Inc., "
+               "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA\n"
+       };
+       char *license_trans;
+
+       license_trans = g_strconcat(license[0], "\n", license[1], "\n",
+                                    license[2], "\n", NULL);
+
        gtk_show_about_dialog(NULL,
                "program-name", "gfio",
                "comments", "Gtk2 UI for fio",
-               "license", "GPLv2",
+               "license", license_trans,
+               "website", "http://git.kernel.dk/?p=fio.git;a=summary",
+               "authors", authors,
                "version", fio_version_string,
-               "copyright", "Jens Axboe <axboe@kernel.dk> 2012",
+               "copyright", "© 2012 Jens Axboe <axboe@kernel.dk>",
                "logo-icon-name", "fio",
                /* Must be last: */
-               NULL, NULL,
+               "wrap-license", TRUE,
                NULL);
+
+       g_free (license_trans);
 }
 
 static GtkActionEntry menu_items[] = {
@@ -1778,6 +1885,7 @@ static void init_ui(int *argc, char **argv[], struct gui *ui)
        GtkSettings *settings;
        GtkUIManager *uimanager;
        GtkWidget *menu, *probe, *probe_frame, *probe_box;
+       GdkColor white;
 
        memset(ui, 0, sizeof(*ui));
 
@@ -1796,7 +1904,7 @@ static void init_ui(int *argc, char **argv[], struct gui *ui)
        
        ui->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
         gtk_window_set_title(GTK_WINDOW(ui->window), "fio");
-       gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 500);
+       gtk_window_set_default_size(GTK_WINDOW(ui->window), 700, 700);
 
        g_signal_connect(ui->window, "delete-event", G_CALLBACK(quit_clicked), NULL);
        g_signal_connect(ui->window, "destroy", G_CALLBACK(quit_clicked), NULL);
@@ -1863,11 +1971,17 @@ static void init_ui(int *argc, char **argv[], struct gui *ui)
        /*
         * Set up a drawing area and IOPS and bandwidth graphs
         */
+       gdk_color_parse("white", &white);
        ui->drawing_area = gtk_drawing_area_new();
+       ui->drawing_area_xdim = DRAWING_AREA_XDIM;
+       ui->drawing_area_ydim = DRAWING_AREA_YDIM;
        gtk_widget_set_size_request(GTK_WIDGET(ui->drawing_area), 
-                       DRAWING_AREA_XDIM, DRAWING_AREA_YDIM);
+                       ui->drawing_area_xdim, ui->drawing_area_ydim);
+       gtk_widget_modify_bg(ui->drawing_area, GTK_STATE_NORMAL, &white);
        g_signal_connect(G_OBJECT(ui->drawing_area), "expose_event",
                                G_CALLBACK (on_expose_drawing_area), ui);
+       g_signal_connect(G_OBJECT(ui->drawing_area), "configure_event",
+                               G_CALLBACK (on_config_drawing_area), ui);
        ui->scrolled_window = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ui->scrolled_window),
                                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);