Fix crash with file locking and dup'ed files
[fio.git] / filesetup.c
index 9edcac17a822301093d0cbab9068b65e0936857e..d1702e29c75bf1b1f73dd0d2dc3ade1ac35f9e12 100644 (file)
@@ -121,13 +121,14 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
                dprint(FD_FILE, "truncate file %s, size %llu\n", f->file_name,
                                        (unsigned long long) f->real_file_size);
                if (ftruncate(f->fd, f->real_file_size) == -1) {
-                       td_verror(td, errno, "ftruncate");
-                       goto err;
+                       if (errno != EFBIG) {
+                               td_verror(td, errno, "ftruncate");
+                               goto err;
+                       }
                }
        }
 
        b = malloc(td->o.max_bs[DDIR_WRITE]);
-       memset(b, 0, td->o.max_bs[DDIR_WRITE]);
 
        left = f->real_file_size;
        while (left && !td->terminate) {
@@ -135,6 +136,8 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
                if (bs > left)
                        bs = left;
 
+               fill_io_buffer(td, b, bs, bs);
+
                r = write(f->fd, b, bs);
 
                if (r > 0) {
@@ -355,7 +358,8 @@ static int get_file_size(struct thread_data *td, struct fio_file *f)
 
        if (f->file_offset > f->real_file_size) {
                log_err("%s: offset extends end (%llu > %llu)\n", td->o.name,
-                                       f->file_offset, f->real_file_size);
+                                       (unsigned long long) f->file_offset,
+                                       (unsigned long long) f->real_file_size);
                return 1;
        }
 
@@ -386,7 +390,8 @@ static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
        if (f->mmap_ptr) {
                ret = posix_madvise(f->mmap_ptr, f->mmap_sz, POSIX_MADV_DONTNEED);
 #ifdef FIO_MADV_FREE
-               (void) posix_madvise(f->mmap_ptr, f->mmap_sz, FIO_MADV_FREE);
+               if (f->filetype == FIO_TYPE_BD)
+                       (void) posix_madvise(f->mmap_ptr, f->mmap_sz, FIO_MADV_FREE);
 #endif
        } else if (f->filetype == FIO_TYPE_FILE) {
                ret = posix_fadvise(f->fd, off, len, POSIX_FADV_DONTNEED);
@@ -441,6 +446,7 @@ int generic_close_file(struct thread_data fio_unused *td, struct fio_file *f)
                f->shadow_fd = -1;
        }
 
+       f->engine_data = 0;
        return ret;
 }
 
@@ -515,6 +521,13 @@ int generic_open_file(struct thread_data *td, struct fio_file *f)
                goto skip_flags;
        if (td->o.odirect)
                flags |= OS_O_DIRECT;
+       if (td->o.oatomic) {
+               if (!FIO_O_ATOMIC) {
+                       td_verror(td, EINVAL, "OS does not support atomic IO");
+                       return 1;
+               }
+               flags |= OS_O_DIRECT | FIO_O_ATOMIC;
+       }
        if (td->o.sync_io)
                flags |= O_SYNC;
        if (td->o.create_on_open)
@@ -580,7 +593,7 @@ open_again:
                         * work-around a "feature" on Linux, where a close of
                         * an fd that has been opened for write will trigger
                         * udev to call blkid to check partitions, fs id, etc.
-                        * That polutes the device cache, which can slow down
+                        * That pollutes the device cache, which can slow down
                         * unbuffered accesses.
                         */
                        if (f->shadow_fd == -1)
@@ -723,9 +736,13 @@ int setup_files(struct thread_data *td)
        struct fio_file *f;
        unsigned int i;
        int err = 0, need_extend;
+       int old_state;
 
        dprint(FD_FILE, "setup files\n");
 
+       old_state = td->runstate;
+       td_set_runstate(td, TD_SETTING_UP);
+
        if (o->read_iolog_file)
                goto done;
 
@@ -740,7 +757,7 @@ int setup_files(struct thread_data *td)
                err = get_file_sizes(td);
 
        if (err)
-               return err;
+               goto err_out;
 
        /*
         * check sizes. if the files/devices do not exist and the size
@@ -765,7 +782,7 @@ int setup_files(struct thread_data *td)
            !(o->nr_files && (o->file_size_low || o->file_size_high))) {
                log_err("%s: you need to specify size=\n", o->name);
                td_verror(td, EINVAL, "total_file_size");
-               return 1;
+               goto err_out;
        }
 
        /*
@@ -866,7 +883,7 @@ int setup_files(struct thread_data *td)
        }
 
        if (err)
-               return err;
+               goto err_out;
 
        if (!o->zone_size)
                o->zone_size = o->size;
@@ -882,9 +899,12 @@ done:
        if (o->create_only)
                td->done = 1;
 
+       td_set_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);
        return 1;
 }
 
@@ -1030,6 +1050,7 @@ void close_and_free_files(struct thread_data *td)
        td->files_index = 0;
        td->files = NULL;
        td->file_locks = NULL;
+       td->o.file_lock_mode = FILE_LOCK_NONE;
        td->o.nr_files = 0;
 }
 
@@ -1222,6 +1243,8 @@ void unlock_file(struct thread_data *td, struct fio_file *f)
 
 void unlock_file_all(struct thread_data *td, struct fio_file *f)
 {
+       if (td->o.file_lock_mode == FILE_LOCK_NONE)
+               return;
        if (td->file_locks[f->fileno] != FILE_LOCK_NONE)
                unlock_file(td, f);
 }
@@ -1320,6 +1343,11 @@ void dup_files(struct thread_data *td, struct thread_data *org)
                        __f->filetype = f->filetype;
                }
 
+               if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE)
+                       __f->lock = f->lock;
+               else if (td->o.file_lock_mode == FILE_LOCK_READWRITE)
+                       __f->rwlock = f->rwlock;
+
                td->files[i] = __f;
        }
 }