filesetup: use 64-bit type for file size generation
[fio.git] / filesetup.c
index 1efffa8febb19d1a7f19ccc3110212f05686b6dd..c0fa3cdae882b0a738dce77c07a585616c31e937 100644 (file)
@@ -5,8 +5,6 @@
 #include <dirent.h>
 #include <libgen.h>
 #include <sys/stat.h>
-#include <sys/mman.h>
-#include <sys/types.h>
 
 #include "fio.h"
 #include "smalloc.h"
 #include "os/os.h"
 #include "hash.h"
 #include "lib/axmap.h"
+#include "rwlock.h"
+#include "zbd.h"
 
 #ifdef CONFIG_LINUX_FALLOCATE
 #include <linux/falloc.h>
 #endif
 
-static int root_warn;
-
 static FLIST_HEAD(filename_list);
 
 /*
@@ -59,8 +57,6 @@ static int native_fallocate(struct thread_data *td, struct fio_file *f)
 
 static void fallocate_file(struct thread_data *td, struct fio_file *f)
 {
-       int r;
-
        if (td->o.fill_device)
                return;
 
@@ -71,7 +67,9 @@ static void fallocate_file(struct thread_data *td, struct fio_file *f)
        case FIO_FALLOCATE_NONE:
                break;
 #ifdef CONFIG_POSIX_FALLOCATE
-       case FIO_FALLOCATE_POSIX:
+       case FIO_FALLOCATE_POSIX: {
+               int r;
+
                dprint(FD_FILE, "posix_fallocate file %s size %llu\n",
                                 f->file_name,
                                 (unsigned long long) f->real_file_size);
@@ -80,9 +78,12 @@ static void fallocate_file(struct thread_data *td, struct fio_file *f)
                if (r > 0)
                        log_err("fio: posix_fallocate fails: %s\n", strerror(r));
                break;
+               }
 #endif /* CONFIG_POSIX_FALLOCATE */
 #ifdef CONFIG_LINUX_FALLOCATE
-       case FIO_FALLOCATE_KEEP_SIZE:
+       case FIO_FALLOCATE_KEEP_SIZE: {
+               int r;
+
                dprint(FD_FILE, "fallocate(FALLOC_FL_KEEP_SIZE) "
                                "file %s size %llu\n", f->file_name,
                                (unsigned long long) f->real_file_size);
@@ -92,6 +93,7 @@ static void fallocate_file(struct thread_data *td, struct fio_file *f)
                        td_verror(td, errno, "fallocate");
 
                break;
+               }
 #endif /* CONFIG_LINUX_FALLOCATE */
        default:
                log_err("fio: unknown fallocate mode: %d\n", td->o.fallocate_mode);
@@ -106,7 +108,7 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
 {
        int new_layout = 0, unlink_file = 0, flags;
        unsigned long long left;
-       unsigned int bs;
+       unsigned long long bs;
        char *b = NULL;
 
        if (read_only) {
@@ -259,7 +261,7 @@ static bool pre_read_file(struct thread_data *td, struct fio_file *f)
 {
        int r, did_open = 0, old_runstate;
        unsigned long long left;
-       unsigned int bs;
+       unsigned long long bs;
        bool ret = true;
        char *b;
 
@@ -329,7 +331,7 @@ unsigned long long get_rand_file_size(struct thread_data *td)
 {
        unsigned long long ret, sized;
        uint64_t frand_max;
-       unsigned long r;
+       uint64_t r;
 
        frand_max = rand_max(&td->file_size_state);
        r = __rand(&td->file_size_state);
@@ -431,8 +433,12 @@ static int get_file_size(struct thread_data *td, struct fio_file *f)
                ret = bdev_size(td, f);
        else if (f->filetype == FIO_TYPE_CHAR)
                ret = char_size(td, f);
-       else
-               f->real_file_size = -1ULL;
+       else {
+               f->real_file_size = -1;
+               log_info("%s: failed to get file size of %s\n", td->o.name,
+                                       f->file_name);
+               return 1; /* avoid offset extends end error message */
+       }
 
        /*
         * Leave ->real_file_size with 0 since it could be expectation
@@ -441,23 +447,11 @@ static int get_file_size(struct thread_data *td, struct fio_file *f)
        if (ret)
                return ret;
 
-       /*
-        * If ->real_file_size is -1, a conditional for the message
-        * "offset extends end" is always true, but it makes no sense,
-        * so just return the same value here.
-        */
-       if (f->real_file_size == -1ULL) {
-               log_info("%s: failed to get file size of %s\n", td->o.name,
-                                       f->file_name);
-               return 1;
-       }
-
-       if (td->o.start_offset && f->file_offset == 0)
-               dprint(FD_FILE, "offset of file %s not initialized yet\n",
-                                       f->file_name);
        /*
         * ->file_offset normally hasn't been initialized yet, so this
-        * is basically always false.
+        * is basically always false unless ->real_file_size is -1, but
+        * if ->real_file_size is -1 this message doesn't make sense.
+        * As a result, this message is basically useless.
         */
        if (f->file_offset > f->real_file_size) {
                log_err("%s: offset extends end (%llu > %llu)\n", td->o.name,
@@ -494,6 +488,9 @@ static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
                ret = td->io_ops->invalidate(td, f);
                if (ret < 0)
                        errval = -ret;
+       } else if (td_ioengine_flagged(td, FIO_DISKLESSIO)) {
+               dprint(FD_IO, "invalidate not supported by ioengine %s\n",
+                      td->io_ops->name);
        } else if (f->filetype == FIO_TYPE_FILE) {
                dprint(FD_IO, "declare unneeded cache %s: %llu/%llu\n",
                        f->file_name, off, len);
@@ -516,19 +513,16 @@ static int __file_invalidate_cache(struct thread_data *td, struct fio_file *f,
                        ret = blockdev_invalidate_cache(f);
                }
                if (ret < 0 && errno == EACCES && geteuid()) {
-                       if (!root_warn) {
+                       if (!fio_did_warn(FIO_WARN_ROOT_FLUSH)) {
                                log_err("fio: only root may flush block "
                                        "devices. Cache flush bypassed!\n");
-                               root_warn = 1;
                        }
-                       ret = 0;
                }
                if (ret < 0)
                        errval = errno;
        } else if (f->filetype == FIO_TYPE_CHAR ||
                   f->filetype == FIO_TYPE_PIPE) {
                dprint(FD_IO, "invalidate not supported %s\n", f->file_name);
-               ret = 0;
        }
 
        /*
@@ -681,7 +675,8 @@ open_again:
                        from_hash = file_lookup_open(f, flags);
        } else if (td_trim(td)) {
                assert(!td_rw(td)); /* should have matched above */
-               flags |= O_RDWR;
+               if (!read_only)
+                       flags |= O_RDWR;
                from_hash = file_lookup_open(f, flags);
        }
 
@@ -906,7 +901,7 @@ int setup_files(struct thread_data *td)
        unsigned int i, nr_fs_extra = 0;
        int err = 0, need_extend;
        int old_state;
-       const unsigned int bs = td_min_bs(td);
+       const unsigned long long bs = td_min_bs(td);
        uint64_t fs = 0;
 
        dprint(FD_FILE, "setup files\n");
@@ -1039,7 +1034,7 @@ int setup_files(struct thread_data *td)
                if (f->io_size == -1ULL)
                        total_size = -1ULL;
                else {
-                        if (o->size_percent) {
+                        if (o->size_percent && o->size_percent != 100) {
                                uint64_t file_size;
 
                                file_size = f->io_size + f->file_offset;
@@ -1148,9 +1143,6 @@ int setup_files(struct thread_data *td)
        if (err)
                goto err_out;
 
-       if (!o->zone_size)
-               o->zone_size = o->size;
-
        /*
         * iolog already set the total io size, if we read back
         * stored entries.
@@ -1167,7 +1159,14 @@ done:
                td->done = 1;
 
        td_restore_runstate(td, old_state);
+
+       if (td->o.zone_mode == ZONE_MODE_ZBD) {
+               err = zbd_init(td);
+               if (err)
+                       goto err_out;
+       }
        return 0;
+
 err_offset:
        log_err("%s: you need to specify valid offset=\n", o->name);
 err_out:
@@ -1193,13 +1192,13 @@ bool pre_read_files(struct thread_data *td)
 static void __init_rand_distribution(struct thread_data *td, struct fio_file *f)
 {
        unsigned int range_size, seed;
-       unsigned long nranges;
+       uint64_t nranges;
        uint64_t fsize;
 
        range_size = min(td->o.min_bs[DDIR_READ], td->o.min_bs[DDIR_WRITE]);
        fsize = min(f->real_file_size, f->io_size);
 
-       nranges = (fsize + range_size - 1) / range_size;
+       nranges = (fsize + range_size - 1ULL) / range_size;
 
        seed = jhash(f->file_name, strlen(f->file_name), 0) * td->thread_number;
        if (!td->o.rand_repeatable)
@@ -1355,6 +1354,8 @@ void close_and_free_files(struct thread_data *td)
                        td_io_unlink_file(td, f);
                }
 
+               zbd_free_zone_info(f);
+
                if (use_free)
                        free(f->file_name);
                else
@@ -1484,7 +1485,7 @@ static struct fio_file *alloc_new_file(struct thread_data *td)
        if (td_ioengine_flagged(td, FIO_NOFILEHASH))
                f = calloc(1, sizeof(*f));
        else
-               f = smalloc(sizeof(*f));
+               f = scalloc(1, sizeof(*f));
        if (!f) {
                assert(0);
                return NULL;
@@ -1516,7 +1517,7 @@ bool exists_and_not_regfile(const char *filename)
        return true;
 }
 
-static int create_work_dirs(struct thread_data *td, const char *fname)
+static bool create_work_dirs(struct thread_data *td, const char *fname)
 {
        char path[PATH_MAX];
        char *start, *end;
@@ -1543,13 +1544,13 @@ static int create_work_dirs(struct thread_data *td, const char *fname)
 #endif
                        log_err("fio: failed to create dir (%s): %d\n",
                                start, errno);
-                       return 1;
+                       return false;
                }
                *end = FIO_OS_PATH_SEPARATOR;
                end++;
        }
        td->flags |= TD_F_DIRS_CREATED;
-       return 0;
+       return true;
 }
 
 int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
@@ -1569,7 +1570,7 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
 
        if (strchr(fname, FIO_OS_PATH_SEPARATOR) &&
            !(td->flags & TD_F_DIRS_CREATED) &&
-           create_work_dirs(td, fname))
+           !create_work_dirs(td, fname))
                return 1;
 
        /* clean cloned siblings using existing files */
@@ -1612,8 +1613,9 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
                f->file_name = strdup(file_name);
        else
                f->file_name = smalloc_strdup(file_name);
-       if (!f->file_name)
-               assert(0);
+
+       /* can't handle smalloc failure from here */
+       assert(f->file_name);
 
        get_file_type(f);
 
@@ -1624,7 +1626,7 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
                f->rwlock = fio_rwlock_init();
                break;
        case FILE_LOCK_EXCLUSIVE:
-               f->lock = fio_mutex_init(FIO_MUTEX_UNLOCKED);
+               f->lock = fio_sem_init(FIO_SEM_UNLOCKED);
                break;
        default:
                log_err("fio: unknown lock mode: %d\n", td->o.file_lock_mode);
@@ -1632,8 +1634,6 @@ int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
        }
 
        td->files_index++;
-       if (f->filetype == FIO_TYPE_FILE)
-               td->nr_normal_files++;
 
        if (td->o.numjobs > 1)
                set_already_allocated(file_name);
@@ -1682,6 +1682,11 @@ int put_file(struct thread_data *td, struct fio_file *f)
        if (--f->references)
                return 0;
 
+       disk_util_dec(f->du);
+
+       if (td->o.file_lock_mode != FILE_LOCK_NONE)
+               unlock_file_all(td, f);
+
        if (should_fsync(td) && td->o.fsync_on_close) {
                f_ret = fsync(f->fd);
                if (f_ret < 0)
@@ -1695,6 +1700,7 @@ int put_file(struct thread_data *td, struct fio_file *f)
                ret = f_ret;
 
        td->nr_open_files--;
+       fio_file_clear_closing(f);
        fio_file_clear_open(f);
        assert(f->fd == -1);
        return ret;
@@ -1711,7 +1717,7 @@ void lock_file(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir)
                else
                        fio_rwlock_write(f->rwlock);
        } else if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE)
-               fio_mutex_down(f->lock);
+               fio_sem_down(f->lock);
 
        td->file_locks[f->fileno] = td->o.file_lock_mode;
 }
@@ -1724,7 +1730,7 @@ void unlock_file(struct thread_data *td, struct fio_file *f)
        if (td->o.file_lock_mode == FILE_LOCK_READWRITE)
                fio_rwlock_unlock(f->rwlock);
        else if (td->o.file_lock_mode == FILE_LOCK_EXCLUSIVE)
-               fio_mutex_up(f->lock);
+               fio_sem_up(f->lock);
 
        td->file_locks[f->fileno] = FILE_LOCK_NONE;
 }
@@ -1737,10 +1743,10 @@ void unlock_file_all(struct thread_data *td, struct fio_file *f)
                unlock_file(td, f);
 }
 
-static int recurse_dir(struct thread_data *td, const char *dirname)
+static bool recurse_dir(struct thread_data *td, const char *dirname)
 {
        struct dirent *dir;
-       int ret = 0;
+       bool ret = false;
        DIR *D;
 
        D = opendir(dirname);
@@ -1749,7 +1755,7 @@ static int recurse_dir(struct thread_data *td, const char *dirname)
 
                snprintf(buf, FIO_VERROR_SIZE, "opendir(%s)", dirname);
                td_verror(td, errno, buf);
-               return 1;
+               return true;
        }
 
        while ((dir = readdir(D)) != NULL) {
@@ -1764,7 +1770,7 @@ static int recurse_dir(struct thread_data *td, const char *dirname)
                if (lstat(full_path, &sb) == -1) {
                        if (errno != ENOENT) {
                                td_verror(td, errno, "stat");
-                               ret = 1;
+                               ret = true;
                                break;
                        }
                }
@@ -1820,9 +1826,9 @@ void dup_files(struct thread_data *td, struct thread_data *org)
                                __f->file_name = strdup(f->file_name);
                        else
                                __f->file_name = smalloc_strdup(f->file_name);
-                       if (!__f->file_name)
-                               assert(0);
 
+                       /* can't handle smalloc failure from here */
+                       assert(__f->file_name);
                        __f->filetype = f->filetype;
                }
 
@@ -1859,7 +1865,6 @@ void free_release_files(struct thread_data *td)
        td->o.nr_files = 0;
        td->o.open_files = 0;
        td->files_index = 0;
-       td->nr_normal_files = 0;
 }
 
 void fio_file_reset(struct thread_data *td, struct fio_file *f)
@@ -1875,6 +1880,8 @@ void fio_file_reset(struct thread_data *td, struct fio_file *f)
                axmap_reset(f->io_axmap);
        else if (fio_file_lfsr(f))
                lfsr_reset(&f->lfsr, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
+
+       zbd_file_reset(td, f);
 }
 
 bool fio_files_done(struct thread_data *td)