#define DEF_STONEWALL (0)
#define DEF_NUMJOBS (1)
#define DEF_USE_THREAD (0)
+#define DEF_USE_MMAP (0)
static int repeatable = DEF_RAND_REPEAT;
static char *ini_file;
td->stonewall = parent->stonewall;
td->numjobs = parent->numjobs;
td->use_thread = parent->use_thread;
+ td->use_mmap = parent->use_mmap;
memcpy(&td->cpumask, &parent->cpumask, sizeof(td->cpumask));
return td;
run_str[td->thread_number - 1] = 'P';
- if (td->use_aio && !td->aio_depth)
- td->aio_depth = 1;
+ if (td->use_aio) {
+ if (!td->aio_depth)
+ td->aio_depth = 1;
+ if (td->use_mmap)
+ td->use_mmap = 0;
+ }
if (td->min_bs == -1U)
td->min_bs = td->bs;
fgetpos(f, &off);
continue;
}
+ if (!check_int(p, "mmap", &td->use_mmap)) {
+ fgetpos(f, &off);
+ continue;
+ }
if (!check_range(p, "bsrange", &ul1, &ul2)) {
if (ul1 & 511)
printf("bad min block size, must be a multiple of 512\n");
def_thread.stonewall = DEF_STONEWALL;
def_thread.numjobs = DEF_NUMJOBS;
def_thread.use_thread = DEF_USE_THREAD;
+ def_thread.use_mmap = DEF_USE_MMAP;
return 0;
}
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <asm/unistd.h>
#include "fio.h"
io_u = __get_io_u(td);
if (!td->odirect) {
- if (fadvise(td->fd, td->file_offset, td->io_size, POSIX_FADV_DONTNEED) < 0) {
- td->error = errno;
- goto out;
+ if (!td->use_mmap) {
+ if (fadvise(td->fd, td->file_offset, td->io_size, POSIX_FADV_DONTNEED) < 0) {
+ td->error = errno;
+ goto out;
+ }
+ } else {
+ if (madvise(td->mmap, td->io_size, MADV_DONTNEED)) {
+ td->error = errno;
+ goto out;
+ }
}
}
put_io_u(td, io_u);
}
+static int __do_sync_mmap(struct thread_data *td, struct io_u *io_u)
+{
+ unsigned long long real_off = io_u->offset - td->file_offset;
+
+ if (td_read(td))
+ memcpy(io_u->buf, td->mmap + real_off, io_u->buflen);
+ else
+ memcpy(td->mmap + real_off, io_u->buf, io_u->buflen);
+
+ return io_u->buflen;
+}
+
+static int __do_sync_rw(struct thread_data *td, struct io_u *io_u)
+{
+ if (td->cur_off != io_u->offset) {
+ if (lseek(td->fd, io_u->offset, SEEK_SET) == -1) {
+ td->error = errno;
+ return 1;
+ }
+ }
+
+ if (td_read(td))
+ return read(td->fd, io_u->buf, io_u->buflen);
+ else
+ return write(td->fd, io_u->buf, io_u->buflen);
+}
+
+static void sync_td(struct thread_data *td)
+{
+ if (!td->use_mmap)
+ fsync(td->fd);
+ else
+ msync(td->mmap, td->file_size, MS_SYNC);
+}
+
static void do_sync_io(struct thread_data *td)
{
unsigned long msec, usec;
if (!io_u)
break;
- if (td->cur_off != io_u->offset) {
- if (lseek(td->fd, io_u->offset, SEEK_SET) == -1) {
- td->error = errno;
- break;
- }
- }
-
- if (td_read(td))
- ret = read(td->fd, io_u->buf, io_u->buflen);
+ if (!td->use_mmap)
+ ret = __do_sync_rw(td, io_u);
else
- ret = write(td->fd, io_u->buf, io_u->buflen);
+ ret = __do_sync_mmap(td, io_u);
if (ret < (int) io_u->buflen) {
if (ret == -1)
if (should_fsync(td) && td->fsync_blocks &&
(td->io_blocks % td->fsync_blocks) == 0)
- fsync(td->fd);
+ sync_td(td);
}
if (io_u)
put_io_u(td, io_u);
if (should_fsync(td))
- fsync(td->fd);
+ sync_td(td);
}
static int io_u_getevents(struct thread_data *td, int min, int max,
return 0;
}
+static int setup_file_mmap(struct thread_data *td)
+{
+ int flags;
+
+ if (td_read(td))
+ flags = PROT_READ;
+ else {
+ flags = PROT_WRITE;
+
+ if (td->verify)
+ flags |= PROT_READ;
+ }
+
+ td->mmap = mmap(NULL, td->file_size, flags, MAP_SHARED, td->fd, td->file_offset);
+ if (td->mmap == MAP_FAILED) {
+ td->mmap = NULL;
+ td->error = errno;
+ return 1;
+ }
+
+ if (td->invalidate_cache) {
+ if (madvise(td->mmap, td->file_size, MADV_DONTNEED) < 0) {
+ td->error = errno;
+ return 1;
+ }
+ }
+
+ if (td->sequential) {
+ if (madvise(td->mmap, td->file_size, MADV_SEQUENTIAL) < 0) {
+ td->error = errno;
+ return 1;
+ }
+ } else {
+ if (madvise(td->mmap, td->file_size, MADV_RANDOM) < 0) {
+ td->error = errno;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int setup_file_plain(struct thread_data *td)
+{
+ if (td->invalidate_cache) {
+ if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_DONTNEED) < 0) {
+ td->error = errno;
+ return 1;
+ }
+ }
+
+ if (td->sequential) {
+ if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_SEQUENTIAL) < 0) {
+ td->error = errno;
+ return 1;
+ }
+ } else {
+ if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_RANDOM) < 0) {
+ td->error = errno;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static int setup_file(struct thread_data *td)
{
int flags = 0;
flags |= O_TRUNC;
if (td->sync_io)
flags |= O_SYNC;
- if (td->verify)
- flags |= O_RDWR;
- else
- flags |= O_WRONLY;
+
+ flags |= O_RDWR;
td->fd = open(td->file_name, flags | O_CREAT, 0600);
}
return 1;
}
- if (td->invalidate_cache) {
- if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_DONTNEED) < 0) {
- td->error = errno;
- return 1;
- }
- }
-
- return 0;
+ if (!td->use_mmap)
+ return setup_file_plain(td);
+ else
+ return setup_file_mmap(td);
}
static void clear_io_state(struct thread_data *td)
close(td->fd);
td->fd = -1;
}
+ if (td->mmap)
+ munmap(td->mmap, td->file_size);
if (td->use_aio)
cleanup_aio(td);
cleanup_io_u(td);