#include "smalloc.h"
#include "filehash.h"
#include "os/os.h"
+#include "hash.h"
+#include "lib/axmap.h"
#ifdef FIO_HAVE_LINUX_FALLOCATE
#include <linux/falloc.h>
r = fallocate(f->fd, FALLOC_FL_KEEP_SIZE, 0,
f->real_file_size);
- if (r != 0) {
+ if (r != 0)
td_verror(td, errno, "fallocate");
- }
+
break;
#endif /* FIO_HAVE_LINUX_FALLOCATE */
default:
ret = errno;
f->fd = -1;
+
+ if (f->shadow_fd != -1) {
+ close(f->shadow_fd);
+ f->shadow_fd = -1;
+ }
+
return ret;
}
-static int file_lookup_open(struct fio_file *f, int flags)
+int file_lookup_open(struct fio_file *f, int flags)
{
struct fio_file *__f;
int from_hash;
return from_hash;
}
+static int file_close_shadow_fds(struct thread_data *td)
+{
+ struct fio_file *f;
+ int num_closed = 0;
+ unsigned int i;
+
+ for_each_file(td, f, i) {
+ if (f->shadow_fd == -1)
+ continue;
+
+ close(f->shadow_fd);
+ f->shadow_fd = -1;
+ num_closed++;
+ }
+
+ return num_closed;
+}
+
int generic_open_file(struct thread_data *td, struct fio_file *f)
{
int is_std = 0;
flags &= ~FIO_O_NOATIME;
goto open_again;
}
+ if (__e == EMFILE && file_close_shadow_fds(td))
+ goto open_again;
snprintf(buf, sizeof(buf) - 1, "open(%s)", f->file_name);
int fio_unused ret;
/*
- * OK to ignore, we haven't done anything with it
+ * Stash away descriptor for later close. This is to
+ * 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
+ * unbuffered accesses.
*/
- ret = generic_close_file(td, f);
+ if (f->shadow_fd == -1)
+ f->shadow_fd = f->fd;
+ else {
+ /*
+ * OK to ignore, we haven't done anything
+ * with it
+ */
+ ret = generic_close_file(td, f);
+ }
goto open_again;
}
}
return ret;
}
-unsigned long long get_start_offset(struct thread_data *td)
+uint64_t get_start_offset(struct thread_data *td)
{
return td->o.start_offset +
(td->thread_number - 1) * td->o.offset_increment;
if (f->io_size == -1ULL)
total_size = -1ULL;
- else
+ else {
+ if (td->o.size_percent)
+ f->io_size = (f->io_size * td->o.size_percent) / 100;
total_size += f->io_size;
+ }
if (f->filetype == FIO_TYPE_FILE &&
(f->io_size + f->file_offset) > f->real_file_size &&
}
}
- if (td->o.size_percent)
- total_size = (total_size * td->o.size_percent) / 100;
-
if (!td->o.size || td->o.size > total_size)
td->o.size = total_size;
return 1;
}
+static int __init_rand_distribution(struct thread_data *td, struct fio_file *f)
+{
+ unsigned int range_size, seed;
+ unsigned long nranges;
+ uint64_t file_size;
+
+ range_size = min(td->o.min_bs[DDIR_READ], td->o.min_bs[DDIR_WRITE]);
+ file_size = min(f->real_file_size, f->io_size);
+
+ nranges = (file_size + range_size - 1) / range_size;
+
+ seed = jhash(f->file_name, strlen(f->file_name), 0) * td->thread_number;
+ if (!td->o.rand_repeatable)
+ seed = td->rand_seeds[4];
+
+ if (td->o.random_distribution == FIO_RAND_DIST_ZIPF)
+ zipf_init(&f->zipf, nranges, td->o.zipf_theta.u.f, seed);
+ else
+ pareto_init(&f->zipf, nranges, td->o.pareto_h.u.f, seed);
+
+ return 1;
+}
+
+static int init_rand_distribution(struct thread_data *td)
+{
+ struct fio_file *f;
+ unsigned int i;
+ int state;
+
+ if (td->o.random_distribution == FIO_RAND_DIST_RANDOM)
+ return 0;
+
+ state = td->runstate;
+ td_set_runstate(td, TD_SETTING_UP);
+ for_each_file(td, f, i)
+ __init_rand_distribution(td, f);
+ td_set_runstate(td, state);
+
+ return 1;
+}
+
int init_random_map(struct thread_data *td)
{
- unsigned long long blocks, num_maps;
+ unsigned long long blocks;
struct fio_file *f;
unsigned int i;
- if (td->o.norandommap || !td_random(td))
+ if (init_rand_distribution(td))
+ return 0;
+ if (!td_random(td))
return 0;
for_each_file(td, f, i) {
blocks = (f->real_file_size + td->o.rw_min_bs - 1) /
(unsigned long long) td->o.rw_min_bs;
- num_maps = (blocks + BLOCKS_PER_MAP - 1) /
- (unsigned long long) BLOCKS_PER_MAP;
- if (num_maps == (unsigned long) num_maps) {
- f->file_map = smalloc(num_maps * sizeof(unsigned long));
- if (f->file_map) {
- f->num_maps = num_maps;
+ if (td->o.random_generator == FIO_RAND_GEN_LFSR) {
+ unsigned long seed;
+
+ seed = td->rand_seeds[FIO_RAND_BLOCK_OFF];
+
+ if (!lfsr_init(&f->lfsr, blocks, seed))
continue;
- }
- } else
- f->file_map = NULL;
+ } else if (!td->o.norandommap) {
+ f->io_axmap = axmap_new(blocks);
+ if (f->io_axmap)
+ continue;
+ } else if (td->o.norandommap)
+ continue;
if (!td->o.softrandommap) {
log_err("fio: failed allocating random map. If running"
log_info("fio: file %s failed allocating random map. Running "
"job without.\n", f->file_name);
- f->num_maps = 0;
}
return 0;
sfree(f->file_name);
f->file_name = NULL;
- sfree(f->file_map);
- f->file_map = NULL;
+ axmap_free(f->io_axmap);
+ f->io_axmap = NULL;
sfree(f);
}
}
f->fd = -1;
+ f->shadow_fd = -1;
fio_file_reset(f);
if (td->files_size <= td->files_index) {