#include "hash.h"
#include "lib/axmap.h"
#include "rwlock.h"
+#include "zbd.h"
#ifdef CONFIG_LINUX_FALLOCATE
#include <linux/falloc.h>
{
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) {
{
int r, did_open = 0, old_runstate;
unsigned long long left;
- unsigned int bs;
+ unsigned long long bs;
bool ret = true;
char *b;
{
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);
} else if (td_ioengine_flagged(td, FIO_DISKLESSIO)) {
dprint(FD_IO, "invalidate not supported by ioengine %s\n",
td->io_ops->name);
- ret = 0;
} else if (f->filetype == FIO_TYPE_FILE) {
dprint(FD_IO, "declare unneeded cache %s: %llu/%llu\n",
f->file_name, off, len);
log_err("fio: only root may flush block "
"devices. Cache flush bypassed!\n");
}
- 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;
}
/*
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);
}
} else if (f->filetype != FIO_TYPE_FILE)
continue;
- buf[255] = '\0';
- strncpy(buf, f->file_name, 255);
+ snprintf(buf, ARRAY_SIZE(buf), "%s", f->file_name);
if (stat(buf, &sb) < 0) {
if (errno != ENOENT)
continue;
fm = calloc(1, sizeof(*fm));
- strncpy(fm->__base, buf, sizeof(fm->__base) - 1);
+ snprintf(fm->__base, ARRAY_SIZE(fm->__base), "%s", buf);
fm->base = basename(fm->__base);
fm->key = sb.st_dev;
flist_add(&fm->list, &list);
uint64_t get_start_offset(struct thread_data *td, struct fio_file *f)
{
+ bool align = false;
struct thread_options *o = &td->o;
unsigned long long align_bs;
unsigned long long offset;
+ unsigned long long increment;
if (o->file_append && f->filetype == FIO_TYPE_FILE)
return f->real_file_size;
+ if (o->offset_increment_percent) {
+ assert(!o->offset_increment);
+ increment = o->offset_increment_percent * f->real_file_size / 100;
+ align = true;
+ } else
+ increment = o->offset_increment;
+
if (o->start_offset_percent > 0) {
+ /* calculate the raw offset */
+ offset = (f->real_file_size * o->start_offset_percent / 100) +
+ (td->subjob_number * increment);
+
+ align = true;
+ } else {
+ /* start_offset_percent not set */
+ offset = o->start_offset +
+ td->subjob_number * increment;
+ }
+
+ if (align) {
/*
- * if offset_align is provided, set initial offset
+ * if offset_align is provided, use it
*/
if (fio_option_is_set(o, start_offset_align)) {
align_bs = o->start_offset_align;
align_bs = td_min_bs(td);
}
- /* calculate the raw offset */
- offset = (f->real_file_size * o->start_offset_percent / 100) +
- (td->subjob_number * o->offset_increment);
-
/*
* block align the offset at the next available boundary at
* ceiling(offset / align_bs) * align_bs
*/
offset = (offset / align_bs + (offset % align_bs != 0)) * align_bs;
+ }
+
+ return offset;
+}
+
+static bool create_work_dirs(struct thread_data *td, const char *fname)
+{
+ char path[PATH_MAX];
+ char *start, *end;
+ if (td->o.directory) {
+ snprintf(path, PATH_MAX, "%s%c%s", td->o.directory,
+ FIO_OS_PATH_SEPARATOR, fname);
+ start = strstr(path, fname);
} else {
- /* start_offset_percent not set */
- offset = o->start_offset +
- td->subjob_number * o->offset_increment;
+ snprintf(path, PATH_MAX, "%s", fname);
+ start = path;
}
- return offset;
+ end = start;
+ while ((end = strchr(end, FIO_OS_PATH_SEPARATOR)) != NULL) {
+ if (end == start)
+ break;
+ *end = '\0';
+ errno = 0;
+#ifdef CONFIG_HAVE_MKDIR_TWO
+ if (mkdir(path, 0600) && errno != EEXIST) {
+#else
+ if (mkdir(path) && errno != EEXIST) {
+#endif
+ log_err("fio: failed to create dir (%s): %d\n",
+ start, errno);
+ return false;
+ }
+ *end = FIO_OS_PATH_SEPARATOR;
+ end++;
+ }
+ td->flags |= TD_F_DIRS_CREATED;
+ return true;
}
/*
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");
old_state = td_bump_runstate(td, TD_SETTING_UP);
- if (o->read_iolog_file)
- goto done;
+ for_each_file(td, f, i) {
+ if (!td_ioengine_flagged(td, FIO_DISKLESSIO) &&
+ strchr(f->file_name, FIO_OS_PATH_SEPARATOR) &&
+ !(td->flags & TD_F_DIRS_CREATED) &&
+ !create_work_dirs(td, f->file_name))
+ goto err_out;
+ }
/*
* Find out physical size of files or devices for this thread,
if (err)
goto err_out;
+ if (o->read_iolog_file)
+ goto done;
+
/*
* check sizes. if the files/devices do not exist and the size
* isn't passed to fio, abort.
}
if (f->filetype == FIO_TYPE_FILE &&
- (f->io_size + f->file_offset) > f->real_file_size &&
- !td_ioengine_flagged(td, FIO_DISKLESSIO)) {
- if (!o->create_on_open) {
+ (f->io_size + f->file_offset) > f->real_file_size) {
+ if (!td_ioengine_flagged(td, FIO_DISKLESSIO) &&
+ !o->create_on_open) {
need_extend++;
extend_size += (f->io_size + f->file_offset);
fio_file_set_extend(f);
- } else
+ } else if (!td_ioengine_flagged(td, FIO_DISKLESSIO) ||
+ (td_ioengine_flagged(td, FIO_DISKLESSIO) &&
+ td_ioengine_flagged(td, FIO_FAKEIO)))
f->real_file_size = f->io_size + f->file_offset;
}
}
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.
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:
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)
for_each_file(td, f, i) {
uint64_t fsize = min(f->real_file_size, f->io_size);
+ if (td->o.zone_mode == ZONE_MODE_STRIDED)
+ fsize = td->o.zone_range;
+
blocks = fsize / (unsigned long long) td->o.rw_min_bs;
if (check_rand_gen_limits(td, f, blocks))
return false;
if (td->o.random_generator == FIO_RAND_GEN_LFSR) {
- unsigned long seed;
+ uint64_t seed;
seed = td->rand_seeds[FIO_RAND_BLOCK_OFF];
if (!lfsr_init(&f->lfsr, blocks, seed, 0)) {
fio_file_set_lfsr(f);
continue;
+ } else {
+ log_err("fio: failed initializing LFSR\n");
+ return false;
}
} else if (!td->o.norandommap) {
f->io_axmap = axmap_new(blocks);
td_io_unlink_file(td, f);
}
+ zbd_free_zone_info(f);
+
if (use_free)
free(f->file_name);
else
return true;
}
-static bool create_work_dirs(struct thread_data *td, const char *fname)
-{
- char path[PATH_MAX];
- char *start, *end;
-
- if (td->o.directory) {
- snprintf(path, PATH_MAX, "%s%c%s", td->o.directory,
- FIO_OS_PATH_SEPARATOR, fname);
- start = strstr(path, fname);
- } else {
- snprintf(path, PATH_MAX, "%s", fname);
- start = path;
- }
-
- end = start;
- while ((end = strchr(end, FIO_OS_PATH_SEPARATOR)) != NULL) {
- if (end == start)
- break;
- *end = '\0';
- errno = 0;
-#ifdef CONFIG_HAVE_MKDIR_TWO
- if (mkdir(path, 0600) && errno != EEXIST) {
-#else
- if (mkdir(path) && errno != EEXIST) {
-#endif
- log_err("fio: failed to create dir (%s): %d\n",
- start, errno);
- return false;
- }
- *end = FIO_OS_PATH_SEPARATOR;
- end++;
- }
- td->flags |= TD_F_DIRS_CREATED;
- return true;
-}
-
int add_file(struct thread_data *td, const char *fname, int numjob, int inc)
{
int cur_files = td->files_index;
sprintf(file_name + len, "%s", fname);
- if (strchr(fname, FIO_OS_PATH_SEPARATOR) &&
- !(td->flags & TD_F_DIRS_CREATED) &&
- !create_work_dirs(td, fname))
- return 1;
-
/* clean cloned siblings using existing files */
if (numjob && is_already_allocated(file_name) &&
!exists_and_not_regfile(fname))
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);
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)
ret = f_ret;
td->nr_open_files--;
+ fio_file_clear_closing(f);
fio_file_clear_open(f);
assert(f->fd == -1);
return ret;
__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;
}
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)