Don't re-create/unlink write file for append workload
[fio.git] / filesetup.c
index f0e3b34fd8ae1e90424c04a37ec1cba4b71e4a38..5ce0f6803ae7d952c262d25728b1a60ec7bff86f 100644 (file)
@@ -50,10 +50,11 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
         * does that for operations involving reads, or for writes
         * where overwrite is set
         */
-       if (td_read(td) || (td_write(td) && td->o.overwrite) ||
+       if (td_read(td) ||
+          (td_write(td) && td->o.overwrite && !td->o.file_append) ||
            (td_write(td) && td->io_ops->flags & FIO_NOEXTEND))
                new_layout = 1;
-       if (td_write(td) && !td->o.overwrite)
+       if (td_write(td) && !td->o.overwrite && !td->o.file_append)
                unlink_file = 1;
 
        if (unlink_file || new_layout) {
@@ -209,8 +210,7 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
                did_open = 1;
        }
 
-       old_runstate = td->runstate;
-       td_set_runstate(td, TD_PRE_READING);
+       old_runstate = td_bump_runstate(td, TD_PRE_READING);
 
        bs = td->o.max_bs[DDIR_READ];
        b = malloc(bs);
@@ -234,7 +234,7 @@ static int pre_read_file(struct thread_data *td, struct fio_file *f)
                }
        }
 
-       td_set_runstate(td, old_runstate);
+       td_restore_runstate(td, old_runstate);
 
        if (did_open)
                td->io_ops->close_file(td, f);
@@ -723,8 +723,13 @@ static unsigned long long get_fs_free_counts(struct thread_data *td)
        return ret;
 }
 
-uint64_t get_start_offset(struct thread_data *td)
+uint64_t get_start_offset(struct thread_data *td, struct fio_file *f)
 {
+       struct thread_options *o = &td->o;
+
+       if (o->file_append && f->filetype == FIO_TYPE_FILE)
+               return f->real_file_size;
+
        return td->o.start_offset +
                (td->thread_number - 1) * td->o.offset_increment;
 }
@@ -745,8 +750,7 @@ int setup_files(struct thread_data *td)
 
        dprint(FD_FILE, "setup files\n");
 
-       old_state = td->runstate;
-       td_set_runstate(td, TD_SETTING_UP);
+       old_state = td_bump_runstate(td, TD_SETTING_UP);
 
        if (o->read_iolog_file)
                goto done;
@@ -812,7 +816,7 @@ int setup_files(struct thread_data *td)
        extend_size = total_size = 0;
        need_extend = 0;
        for_each_file(td, f, i) {
-               f->file_offset = get_start_offset(td);
+               f->file_offset = get_start_offset(td, f);
 
                if (!o->file_size_low) {
                        /*
@@ -925,12 +929,12 @@ done:
        if (o->create_only)
                td->done = 1;
 
-       td_set_runstate(td, old_state);
+       td_restore_runstate(td, old_state);
        return 0;
 err_offset:
        log_err("%s: you need to specify valid offset=\n", o->name);
 err_out:
-       td_set_runstate(td, old_state);
+       td_restore_runstate(td, old_state);
        return 1;
 }
 
@@ -980,11 +984,12 @@ static int init_rand_distribution(struct thread_data *td)
        if (td->o.random_distribution == FIO_RAND_DIST_RANDOM)
                return 0;
 
-       state = td->runstate;
-       td_set_runstate(td, TD_SETTING_UP);
+       state = td_bump_runstate(td, TD_SETTING_UP);
+
        for_each_file(td, f, i)
                __init_rand_distribution(td, f);
-       td_set_runstate(td, state);
+
+       td_restore_runstate(td, state);
 
        return 1;
 }
@@ -1010,7 +1015,7 @@ int init_random_map(struct thread_data *td)
 
                        seed = td->rand_seeds[FIO_RAND_BLOCK_OFF];
                        
-                       if (!lfsr_init(&f->lfsr, blocks, seed, seed & 0xF))
+                       if (!lfsr_init(&f->lfsr, blocks, seed, 0))
                                continue;
                } else if (!td->o.norandommap) {
                        f->io_axmap = axmap_new(blocks);
@@ -1053,16 +1058,16 @@ void close_and_free_files(struct thread_data *td)
        dprint(FD_FILE, "close files\n");
 
        for_each_file(td, f, i) {
-               if (td->o.unlink && f->filetype == FIO_TYPE_FILE) {
-                       dprint(FD_FILE, "free unlink %s\n", f->file_name);
-                       unlink(f->file_name);
-               }
-
                if (fio_file_open(f))
                        td_io_close_file(td, f);
 
                remove_file_hash(f);
 
+               if (td->o.unlink && f->filetype == FIO_TYPE_FILE) {
+                       dprint(FD_FILE, "free unlink %s\n", f->file_name);
+                       unlink(f->file_name);
+               }
+
                sfree(f->file_name);
                f->file_name = NULL;
                axmap_free(f->io_axmap);
@@ -1145,7 +1150,7 @@ static void free_already_allocated() {
        }
 }
 
-int add_file(struct thread_data *td, const char *fname, int numjob)
+int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
 {
        int cur_files = td->files_index;
        char file_name[PATH_MAX];
@@ -1230,6 +1235,16 @@ int add_file(struct thread_data *td, const char *fname, int numjob)
 
        set_already_allocated(file_name);
 
+       /*
+        * For adding files after the fact - if openfiles= isn't
+        * given as an option, ensure we allow at least one file open
+        */
+       if (!td->o.open_files)
+               td->o.open_files = 1;
+
+       if (inc)
+               td->o.nr_files++;
+
        dprint(FD_FILE, "file %p \"%s\" added at %d\n", f, f->file_name,
                                                        cur_files);
 
@@ -1246,7 +1261,7 @@ int add_file_exclusive(struct thread_data *td, const char *fname)
                        return i;
        }
 
-       return add_file(td, fname, 0);
+       return add_file(td, fname, 0, 1);
 }
 
 void get_file(struct fio_file *f)
@@ -1355,8 +1370,7 @@ static int recurse_dir(struct thread_data *td, const char *dirname)
                }
 
                if (S_ISREG(sb.st_mode)) {
-                       add_file(td, full_path, 0);
-                       td->o.nr_files++;
+                       add_file(td, full_path, 0, 1);
                        continue;
                }
                if (!S_ISDIR(sb.st_mode))