Increase accuracy of disk utility percentage
authorJens Axboe <jens.axboe@oracle.com>
Wed, 27 May 2009 11:11:20 +0000 (13:11 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Wed, 27 May 2009 11:11:20 +0000 (13:11 +0200)
If a job file contains more than one job that works on separate
disks, then the job that finishes first will get more idle time
accounted to it.

Fix this by only doing disk util stats when we have files open
on that device.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
diskutil.c
fio.h
ioengines.c

index a78ae74b61646eb9d4a49d295d0b411dcecc6ef9..3cbd6fc3b04e1d2f7dba60375dcf1c5d65683583 100644 (file)
@@ -8,11 +8,23 @@
 #include <math.h>
 
 #include "fio.h"
+#include "smalloc.h"
 
 static int last_majdev, last_mindev;
+static struct disk_util *last_du;
 
 static struct flist_head disk_list = FLIST_HEAD_INIT(disk_list);
 
+static void disk_util_free(struct disk_util *du)
+{
+       if (du == last_du)
+               last_du = NULL;
+
+       fio_mutex_remove(du->lock);
+       sfree(du->name);
+       sfree(du);
+}
+
 static int get_io_ticks(struct disk_util *du, struct disk_util_stat *dus)
 {
        unsigned in_flight;
@@ -53,6 +65,8 @@ static void update_io_tick_disk(struct disk_util *du)
 
        if (get_io_ticks(du, &__dus))
                return;
+       if (!du->users)
+               return;
 
        dus = &du->dus;
        ldus = &du->last_dus;
@@ -167,9 +181,8 @@ static int read_block_dev_entry(char *path, int *maj, int *min)
        return 0;
 }
 
-
-static void __init_per_file_disk_util(struct thread_data *td, int majdev,
-               int mindev, char * path);
+static struct disk_util *__init_per_file_disk_util(struct thread_data *td,
+               int majdev, int mindev, char * path);
 
 static void find_add_disk_slaves(struct thread_data *td, char *path,
                struct disk_util *masterdu)
@@ -221,26 +234,26 @@ static void find_add_disk_slaves(struct thread_data *td, char *path,
        return;
 }
 
-
-
-static void disk_util_add(struct thread_data * td, int majdev, int mindev,
-               char *path)
+static struct disk_util *disk_util_add(struct thread_data * td, int majdev,
+                                      int mindev, char *path)
 {
        struct disk_util *du, *__du;
        struct flist_head *entry;
 
        dprint(FD_DISKUTIL, "add maj/min %d/%d: %s\n", majdev, mindev, path);
 
-       du = malloc(sizeof(*du));
+       du = smalloc(sizeof(*du));
        memset(du, 0, sizeof(*du));
        INIT_FLIST_HEAD(&du->list);
        sprintf(du->path, "%s/stat", path);
-       du->name = strdup(basename(path));
+       du->name = smalloc_strdup(basename(path));
        du->sysfs_root = path;
        du->major = majdev;
        du->minor = mindev;
        INIT_FLIST_HEAD(&du->slavelist);
        INIT_FLIST_HEAD(&du->slaves);
+       du->lock = fio_mutex_init(1);
+       du->users = 0;
 
        flist_for_each(entry, &disk_list) {
                __du = flist_entry(entry, struct disk_util, list);
@@ -248,9 +261,8 @@ static void disk_util_add(struct thread_data * td, int majdev, int mindev,
                dprint(FD_DISKUTIL, "found %s in list\n", __du->name);
 
                if (!strcmp(du->name, __du->name)) {
-                       free(du->name);
-                       free(du);
-                       return;
+                       disk_util_free(du);
+                       return __du;
                }
        }
 
@@ -261,6 +273,7 @@ static void disk_util_add(struct thread_data * td, int majdev, int mindev,
 
        flist_add_tail(&du->list, &disk_list);
        find_add_disk_slaves(td, path, du);
+       return du;
 }
 
 
@@ -271,9 +284,8 @@ static int check_dev_match(int majdev, int mindev, char *path)
        if (read_block_dev_entry(path, &major, &minor))
                return 1;
 
-       if (majdev == major && mindev == minor) {
+       if (majdev == major && mindev == minor)
                return 0;
-       }
 
        return 1;
 }
@@ -330,9 +342,9 @@ static int find_block_dir(int majdev, int mindev, char *path, int link_ok)
        return found;
 }
 
-
-static void __init_per_file_disk_util(struct thread_data *td, int majdev,
-               int mindev, char * path)
+static struct disk_util *__init_per_file_disk_util(struct thread_data *td,
+                                                  int majdev, int mindev,
+                                                  char *path)
 {
        struct stat st;
        char tmp[PATH_MAX];
@@ -349,7 +361,7 @@ static void __init_per_file_disk_util(struct thread_data *td, int majdev,
                sprintf(tmp, "%s/queue", p);
                if (stat(tmp, &st)) {
                        log_err("unknown sysfs layout\n");
-                       return;
+                       return NULL;
                }
                strncpy(tmp, p, PATH_MAX - 1);
                sprintf(path, "%s", tmp);
@@ -358,20 +370,19 @@ static void __init_per_file_disk_util(struct thread_data *td, int majdev,
        if (td->o.ioscheduler && !td->sysfs_root)
                td->sysfs_root = strdup(path);
 
-       disk_util_add(td, majdev, mindev, path);
+       return disk_util_add(td, majdev, mindev, path);
 }
 
-
-
-static void init_per_file_disk_util(struct thread_data *td, char * filename)
+static struct disk_util *init_per_file_disk_util(struct thread_data *td,
+                                                char *filename)
 {
 
        char foo[PATH_MAX];
        struct disk_util *du;
        int mindev, majdev;
 
-       if(get_device_numbers(filename, &majdev, &mindev))
-               return;
+       if (get_device_numbers(filename, &majdev, &mindev))
+               return NULL;
 
        dprint(FD_DISKUTIL, "%s belongs to maj/min %d/%d\n", filename, majdev,
                        mindev);
@@ -381,7 +392,7 @@ static void init_per_file_disk_util(struct thread_data *td, char * filename)
                if (td->o.ioscheduler && !td->sysfs_root)
                        td->sysfs_root = strdup(du->sysfs_root);
 
-               return;
+               return du;
        }
 
        /*
@@ -391,20 +402,20 @@ static void init_per_file_disk_util(struct thread_data *td, char * filename)
         * everything again.
         */
        if (mindev == last_mindev && majdev == last_majdev)
-               return;
+               return last_du;
 
        last_mindev = mindev;
        last_majdev = majdev;
 
        sprintf(foo, "/sys/block");
        if (!find_block_dir(majdev, mindev, foo, 1))
-               return;
-
-       __init_per_file_disk_util(td, majdev, mindev, foo);
+               return NULL;
 
+       return __init_per_file_disk_util(td, majdev, mindev, foo);
 }
 
-static void __init_disk_util(struct thread_data *td, struct fio_file *f)
+static struct disk_util *__init_disk_util(struct thread_data *td,
+                                         struct fio_file *f)
 {
        return init_per_file_disk_util(td, f->file_name);
 }
@@ -419,7 +430,7 @@ void init_disk_util(struct thread_data *td)
                return;
 
        for_each_file(td, f, i)
-               __init_disk_util(td, f);
+               f->du = __init_disk_util(td, f);
 }
 
 static void aggregate_slaves_stats(struct disk_util *masterdu)
@@ -471,8 +482,6 @@ static void aggregate_slaves_stats(struct disk_util *masterdu)
 
 }
 
-
-
 void show_disk_util(void)
 {
        struct disk_util_stat *dus;
@@ -526,7 +535,6 @@ void show_disk_util(void)
        flist_for_each_safe(entry, next, &disk_list) {
                flist_del(entry);
                du = flist_entry(entry, struct disk_util, list);
-               free(du->name);
-               free(du);
+               disk_util_free(du);
        }
 }
diff --git a/fio.h b/fio.h
index b1360dd3504f69dde093e5fd518f0fc23556a558..932ee83f4b7b6047f1c15cfd2ad9a3c55a0ee3ce 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -343,6 +343,8 @@ struct fio_file {
 
        int references;
        enum fio_file_flags flags;
+
+       struct disk_util *du;
 };
 
 /*
@@ -786,8 +788,29 @@ struct disk_util {
 
        unsigned long msec;
        struct timeval time;
+
+       struct fio_mutex *lock;
+       unsigned long users;
 };
 
+static inline void disk_util_inc(struct disk_util *du)
+{
+       if (du) {
+               fio_mutex_down(du->lock);
+               du->users++;
+               fio_mutex_up(du->lock);
+       }
+}
+
+static inline void disk_util_dec(struct disk_util *du)
+{
+       if (du) {
+               fio_mutex_down(du->lock);
+               du->users--;
+               fio_mutex_up(du->lock);
+       }
+}
+
 #define DISK_UTIL_MSEC (250)
 
 /*
index 2969840706d18f75965c083c574531d9ff2fa7e0..17e076a3038c617d85408c4891d55a0718f5fd0f 100644 (file)
@@ -332,6 +332,7 @@ int td_io_open_file(struct thread_data *td, struct fio_file *f)
        fio_file_reset(f);
        f->flags |= FIO_FILE_OPEN;
        f->flags &= ~FIO_FILE_CLOSING;
+       disk_util_inc(f->du);
 
        td->nr_open_files++;
        get_file(f);
@@ -386,6 +387,7 @@ done:
        log_file(td, f, FIO_LOG_OPEN_FILE);
        return 0;
 err:
+       disk_util_dec(f->du);
        if (td->io_ops->close_file)
                td->io_ops->close_file(td, f);
        return 1;
@@ -401,6 +403,7 @@ int td_io_close_file(struct thread_data *td, struct fio_file *f)
         */
        f->flags |= FIO_FILE_CLOSING;
 
+       disk_util_dec(f->du);
        unlock_file_all(td, f);
 
        return put_file(td, f);