Improve ETA for fill_device based job files
authorJens Axboe <jens.axboe@oracle.com>
Mon, 17 May 2010 10:29:57 +0000 (12:29 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Mon, 17 May 2010 10:29:57 +0000 (12:29 +0200)
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
eta.c
filesetup.c
fio.h
os/os-linux.h
os/os.h

diff --git a/eta.c b/eta.c
index 53dcc93aa4d6b157d7d64037d34ad99526cb10ce..81dbfa7ef2833438ab9344431e6024f31e33075b 100644 (file)
--- a/eta.c
+++ b/eta.c
@@ -110,6 +110,13 @@ static int thread_eta(struct thread_data *td)
 
        bytes_total = td->total_io_size;
 
+       if (td->o.fill_device && td->o.size  == -1ULL) {
+               if (!td->fill_device_size || td->fill_device_size == -1ULL)
+                       return 0;
+
+               bytes_total = td->fill_device_size;
+       }
+
        /*
         * if writing, bytes_total will be twice the size. If mixing,
         * assume a 50/50 split and thus bytes_total will be 50% larger.
@@ -124,9 +131,6 @@ static int thread_eta(struct thread_data *td)
        if (td->o.zone_size && td->o.zone_skip)
                bytes_total /= (td->o.zone_skip / td->o.zone_size);
 
-       if (td->o.fill_device && td->o.size  == -1ULL)
-               return 0;
-
        if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING) {
                double perc, perc_t;
 
index 32b8b2e4d47ad4bae1e51e3c8958f4041511c12b..ec5d781ed0dea0e8c98c5a05289340969123e4c5 100644 (file)
@@ -503,6 +503,75 @@ static int get_file_sizes(struct thread_data *td)
        return err;
 }
 
+struct fio_mount {
+       struct flist_head list;
+       const char *base;
+       char __base[256];
+       unsigned int key;
+};
+
+/*
+ * Get free number of bytes for each file on each unique mount.
+ */
+static unsigned long long get_fs_free_counts(struct thread_data *td)
+{
+       struct flist_head *n, *tmp;
+       unsigned long long ret;
+       struct fio_mount *fm;
+       FLIST_HEAD(list);
+       struct fio_file *f;
+       unsigned int i;
+
+       for_each_file(td, f, i) {
+               struct stat sb;
+               char buf[256];
+
+               strcpy(buf, f->file_name);
+
+               if (stat(buf, &sb) < 0) {
+                       if (errno != ENOENT)
+                               break;
+                       strcpy(buf, ".");
+                       if (stat(buf, &sb) < 0)
+                               break;
+               }
+
+               fm = NULL;
+               flist_for_each(n, &list) {
+                       fm = flist_entry(n, struct fio_mount, list);
+                       if (fm->key == sb.st_dev)
+                               break;
+
+                       fm = NULL;
+               }
+
+               if (fm)
+                       continue;
+
+               fm = malloc(sizeof(*fm));
+               strcpy(fm->__base, buf);
+               fm->base = basename(fm->__base);
+               fm->key = sb.st_dev;
+               flist_add(&fm->list, &list);
+       }
+
+       ret = 0;
+       flist_for_each_safe(n, tmp, &list) {
+               unsigned long long sz;
+
+               fm = flist_entry(n, struct fio_mount, list);
+               flist_del(&fm->list);
+
+               sz = get_fs_size(fm->base);
+               if (sz && sz != -1ULL)
+                       ret += sz;
+
+               free(fm);
+       }
+
+       return ret;
+}
+
 /*
  * Open the files and setup files sizes, creating files if necessary.
  */
@@ -543,6 +612,9 @@ int setup_files(struct thread_data *td)
                        total_size += f->real_file_size;
        }
 
+       if (td->o.fill_device)
+               td->fill_device_size = get_fs_free_counts(td);
+
        /*
         * device/file sizes are zero and no size given, punt
         */
diff --git a/fio.h b/fio.h
index 5dc0352af65d50c1bd7c66ecb7cc38016bbb7b76..56aa9b6e803117dcfdd2e6784a66008fc75f0234 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -373,6 +373,7 @@ struct thread_data {
        struct timeval lastrate[2];
 
        unsigned long long total_io_size;
+       unsigned long long fill_device_size;
 
        unsigned long io_issues[2];
        unsigned long long io_blocks[2];
index 8c61cc05fda6a73f2e79ca1b830abf3aad00c42f..b6ba569a46f603a389a12d959b19820be801079a 100644 (file)
@@ -4,6 +4,7 @@
 #include <sys/ioctl.h>
 #include <sys/uio.h>
 #include <sys/syscall.h>
+#include <sys/vfs.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
@@ -35,6 +36,7 @@
 #define FIO_HAVE_CGROUPS
 #define FIO_HAVE_FDATASYNC
 #define FIO_HAVE_SYNC_FILE_RANGE
+#define FIO_HAVE_FS_STAT
 
 #define OS_MAP_ANON            MAP_ANONYMOUS
 
@@ -280,4 +282,17 @@ static inline int arch_cache_line_size(void)
                return atoi(size);
 }
 
+static inline unsigned long long get_fs_size(const char *path)
+{
+       unsigned long long ret;
+       struct statfs s;
+
+       if (statfs(path, &s) < 0)
+               return -1ULL;
+
+       ret = s.f_bsize;
+       ret *= (unsigned long long) s.f_bfree;
+       return ret;
+}
+
 #endif
diff --git a/os/os.h b/os/os.h
index b7fce80c6f7ce0070146a2f3986e15891108f045..218766ab1fee160a252dc3bc14a8c5ee69705c79 100644 (file)
--- a/os/os.h
+++ b/os/os.h
@@ -147,4 +147,11 @@ static inline long os_random_long(os_random_state_t *rs)
 }
 #endif
 
+#ifndef FIO_HAVE_FS_STAT
+static inline unsigned long long get_fs_size(const char *path)
+{
+       return 0;
+}
+#endif
+
 #endif