Add 'opendir' option
authorJens Axboe <jens.axboe@oracle.com>
Tue, 13 Mar 2007 14:28:55 +0000 (15:28 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 13 Mar 2007 14:28:55 +0000 (15:28 +0100)
This option adds all files from a directory and downward in the
filesystem hierarchy.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
filesetup.c
fio.h
init.c

diff --git a/HOWTO b/HOWTO
index ec4f3e21170a49a0cbae4a26571739f36c1e0d6a..e54b37b14dbb67911af1d19723cbb29581fdf6a6 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -211,6 +211,9 @@ filename=str        Fio normally makes up a filename based on the job name,
                a job to open /dev/sda and /dev/sdb as the two working files,
                you would use filename=/dev/sda:/dev/sdb
 
+opendir=str    Tell fio to recursively add any file it can find in this
+               directory and down the file system tree.
+
 rw=str         Type of io pattern. Accepted values are:
 
                        read            Sequential reads
index 2a7e7cf55e33e31e9bd1e6a23eb260d1ee895c9b..0a4e77ef33e3aef63b597cc9af118d19b54a0fa9 100644 (file)
@@ -2,8 +2,10 @@
 #include <fcntl.h>
 #include <string.h>
 #include <assert.h>
+#include <dirent.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/types.h>
 
 #include "fio.h"
 #include "os.h"
@@ -473,3 +475,50 @@ void put_file(struct thread_data *td, struct fio_file *f)
        td->nr_open_files--;
        f->flags &= ~FIO_FILE_OPEN;
 }
+
+static int recurse_dir(struct thread_data *td, const char *dirname)
+{
+       struct dirent *dir;
+       int ret = 0;
+       DIR *D;
+
+       D = opendir(dirname);
+       if (!D) {
+               td_verror(td, errno, "opendir");
+               return 1;
+       }
+
+       while ((dir = readdir(D)) != NULL) {
+               char full_path[PATH_MAX];
+               struct stat sb;
+
+               sprintf(full_path, "%s/%s", dirname, dir->d_name);
+
+               if (lstat(full_path, &sb) == -1) {
+                       if (errno != ENOENT) {
+                               td_verror(td, errno, "stat");
+                               return 1;
+                       }
+               }
+
+               if (S_ISREG(sb.st_mode)) {
+                       add_file(td, full_path);
+                       td->nr_files++;
+                       continue;
+               }
+
+               if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
+                       continue;
+
+               if ((ret = recurse_dir(td, full_path)) != 0)
+                       break;
+       }
+
+       closedir(D);
+       return ret;
+}
+
+int add_dir_files(struct thread_data *td, const char *path)
+{
+       return recurse_dir(td, path);
+}
diff --git a/fio.h b/fio.h
index 7db30909e563a3b51ab683bcd9ce9016e5001485..51734641d3c59dd83e960a95ee84a94e53e42b30 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -393,6 +393,7 @@ struct thread_data {
        unsigned int file_service_type;
        unsigned int group_reporting;
        unsigned int open_files;
+       char *opendir;
 
        char *read_iolog_file;
        char *write_iolog_file;
@@ -660,6 +661,7 @@ extern void generic_close_file(struct thread_data *, struct fio_file *);
 extern void add_file(struct thread_data *, const char *);
 extern void get_file(struct fio_file *);
 extern void put_file(struct thread_data *, struct fio_file *);
+extern int add_dir_files(struct thread_data *, const char *);
 
 /*
  * ETA/status stuff
diff --git a/init.c b/init.c
index cf66ec0e8ee9875ded959cb616be5c633c4e13fc..ee0f36fdee54b2e6e2838df4d9d02eeab70f642b 100644 (file)
--- a/init.c
+++ b/init.c
@@ -33,6 +33,7 @@ static int str_cpumask_cb(void *, unsigned int *);
 static int str_fst_cb(void *, const char *);
 static int str_filename_cb(void *, const char *);
 static int str_directory_cb(void *, const char *);
+static int str_opendir_cb(void *, const char *);
 
 #define __stringify_1(x)       #x
 #define __stringify(x)         __stringify_1(x)
@@ -67,6 +68,13 @@ static struct fio_option options[] = {
                .cb     = str_filename_cb,
                .help   = "File(s) to use for the workload",
        },
+       {
+               .name   = "opendir",
+               .type   = FIO_OPT_STR_STORE,
+               .off1   = td_var_offset(opendir),
+               .cb     = str_opendir_cb,
+               .help   = "Recursively add files from this directory and down",
+       },
        {
                .name   = "rw",
                .type   = FIO_OPT_STR,
@@ -759,9 +767,7 @@ static void fixup_options(struct thread_data *td)
        if (td->iodepth_batch > td->iodepth || !td->iodepth_batch)
                td->iodepth_batch = td->iodepth;
 
-       if (!td->nr_files)
-               td->nr_files = td->files_index;
-       else if (td->nr_files > td->files_index)
+       if (td->nr_files > td->files_index)
                td->nr_files = td->files_index;
 
        if (td->open_files > td->nr_files || !td->open_files)
@@ -839,7 +845,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
        if (td->odirect)
                td->io_ops->flags |= FIO_RAWIO;
 
-       if (!td->filename) {
+       if (!td->filename && !td->files_index) {
                td->filename = strdup(jobname);
 
                if (td->nr_files == 1)
@@ -1121,10 +1127,14 @@ static int str_filename_cb(void *data, const char *input)
        strip_blank_front(&str);
        strip_blank_end(str);
 
+       if (!td->files_index)
+               td->nr_files = 0;
+
        while ((fname = strsep(&str, ":")) != NULL) {
                if (!strlen(fname))
                        break;
                add_file(td, fname);
+               td->nr_files++;
        }
 
        free(p);
@@ -1149,6 +1159,16 @@ static int str_directory_cb(void *data, const char fio_unused *str)
        return 0;
 }
 
+static int str_opendir_cb(void *data, const char fio_unused *str)
+{
+       struct thread_data *td = data;
+
+       if (!td->files_index)
+               td->nr_files = 0;
+
+       return add_dir_files(td, td->opendir);
+}
+
 /*
  * This is our [ini] type file parser.
  */