Fix crash in setup_files() if no files are defined
[fio.git] / filesetup.c
index 5ce0f6803ae7d952c262d25728b1a60ec7bff86f..bf05b6f000e4caf6158c4f0783ca9d5806fa6cc8 100644 (file)
@@ -194,7 +194,7 @@ err:
 
 static int pre_read_file(struct thread_data *td, struct fio_file *f)
 {
-       int r, did_open = 0, old_runstate;
+       int ret = 0, r, did_open = 0, old_runstate;
        unsigned long long left;
        unsigned int bs;
        char *b;
@@ -216,7 +216,13 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
        b = malloc(bs);
        memset(b, 0, bs);
 
-       lseek(f->fd, f->file_offset, SEEK_SET);
+       if (lseek(f->fd, f->file_offset, SEEK_SET) < 0) {
+               td_verror(td, errno, "lseek");
+               log_err("fio: failed to lseek pre-read file\n");
+               ret = 1;
+               goto error;
+       }
+
        left = f->io_size;
 
        while (left && !td->terminate) {
@@ -234,12 +240,14 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
                }
        }
 
+error:
        td_restore_runstate(td, old_runstate);
 
        if (did_open)
                td->io_ops->close_file(td, f);
+
        free(b);
-       return 0;
+       return ret;
 }
 
 static unsigned long long get_rand_file_size(struct thread_data *td)
@@ -798,7 +806,7 @@ int setup_files(struct thread_data *td)
         * Calculate per-file size and potential extra size for the
         * first files, if needed.
         */
-       if (!o->file_size_low) {
+       if (!o->file_size_low && o->nr_files) {
                uint64_t all_fs;
 
                fs = o->size / o->nr_files;
@@ -1109,45 +1117,89 @@ static void get_file_type(struct fio_file *f)
        }
 }
 
-static void set_already_allocated(const char *fname) {
-       struct file_name *fn;
+static int __is_already_allocated(const char *fname)
+{
+       struct flist_head *entry;
+       char *filename;
 
-       fn = malloc(sizeof(struct file_name));
-       fn->filename = strdup(fname);
-       flist_add_tail(&fn->list, &filename_list);
+       if (flist_empty(&filename_list))
+               return 0;
+
+       flist_for_each(entry, &filename_list) {
+               filename = flist_entry(entry, struct file_name, list)->filename;
+
+               if (strcmp(filename, fname) == 0)
+                       return 1;
+       }
+
+       return 0;
 }
 
 static int is_already_allocated(const char *fname)
 {
-       struct flist_head *entry;
-       char *filename;
+       int ret;
 
-       if (!flist_empty(&filename_list))
-       {
-               flist_for_each(entry, &filename_list) {
-                       filename = flist_entry(entry, struct file_name, list)->filename;
+       fio_file_hash_lock();
+       ret = __is_already_allocated(fname);
+       fio_file_hash_unlock();
+       return ret;
+}
 
-                       if (strcmp(filename, fname) == 0)
-                               return 1;
-               }
+static void set_already_allocated(const char *fname)
+{
+       struct file_name *fn;
+
+       fn = malloc(sizeof(struct file_name));
+       fn->filename = strdup(fname);
+
+       fio_file_hash_lock();
+       if (!__is_already_allocated(fname)) {
+               flist_add_tail(&fn->list, &filename_list);
+               fn = NULL;
        }
+       fio_file_hash_unlock();
 
-       return 0;
+       if (fn) {
+               free(fn->filename);
+               free(fn);
+       }
 }
 
-static void free_already_allocated() {
+
+static void free_already_allocated(void)
+{
        struct flist_head *entry, *tmp;
        struct file_name *fn;
 
-       if (!flist_empty(&filename_list))
-       {
-               flist_for_each_safe(entry, tmp, &filename_list) {
-                       fn = flist_entry(entry, struct file_name, list);
-                       free(fn->filename);
-                       flist_del(&fn->list);
-                       free(fn);
-               }
+       if (flist_empty(&filename_list))
+               return;
+
+       fio_file_hash_lock();
+       flist_for_each_safe(entry, tmp, &filename_list) {
+               fn = flist_entry(entry, struct file_name, list);
+               free(fn->filename);
+               flist_del(&fn->list);
+               free(fn);
+       }
+
+       fio_file_hash_unlock();
+}
+
+static struct fio_file *alloc_new_file(struct thread_data *td)
+{
+       struct fio_file *f;
+
+       f = smalloc(sizeof(*f));
+       if (!f) {
+               log_err("fio: smalloc OOM\n");
+               assert(0);
+               return NULL;
        }
+
+       f->fd = -1;
+       f->shadow_fd = -1;
+       fio_file_reset(td, f);
+       return f;
 }
 
 int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
@@ -1168,15 +1220,7 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
        if (numjob && is_already_allocated(file_name))
                return 0;
 
-       f = smalloc(sizeof(*f));
-       if (!f) {
-               log_err("fio: smalloc OOM\n");
-               assert(0);
-       }
-
-       f->fd = -1;
-       f->shadow_fd = -1;
-       fio_file_reset(td, f);
+       f = alloc_new_file(td);
 
        if (td->files_size <= td->files_index) {
                unsigned int new_size = td->o.nr_files + 1;
@@ -1413,13 +1457,7 @@ void dup_files(struct thread_data *td, struct thread_data *org)
        for_each_file(org, f, i) {
                struct fio_file *__f;
 
-               __f = smalloc(sizeof(*__f));
-               if (!__f) {
-                       log_err("fio: smalloc OOM\n");
-                       assert(0);
-               }
-               __f->fd = -1;
-               fio_file_reset(td, __f);
+               __f = alloc_new_file(td);
 
                if (f->file_name) {
                        __f->file_name = smalloc_strdup(f->file_name);
@@ -1488,6 +1526,7 @@ int fio_files_done(struct thread_data *td)
 }
 
 /* free memory used in initialization phase only */
-void filesetup_mem_free() {
+void filesetup_mem_free(void)
+{
        free_already_allocated();
 }