From d0bdaf49eb3f4faa941d02274f2bd875a187e7d7 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 20 Dec 2006 14:40:44 +0100 Subject: [PATCH] [PATCH] Support for mmap of hugetlb files as memory backing Signed-off-by: Jens Axboe --- HOWTO | 4 ++++ fio.c | 2 +- fio.h | 3 +++ init.c | 25 ++++++++++++++++++++++++- memory.c | 35 +++++++++++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/HOWTO b/HOWTO index 6ac744cd..f5e2449c 100644 --- a/HOWTO +++ b/HOWTO @@ -362,6 +362,10 @@ mem=str Fio can use various types of memory as the io unit buffer. mmap Use anonymous memory maps as the buffers. Allocated through mmap(2). + mmaphuge Use a memory mapped huge file as the buffer + backing. Append filename after mmaphuge, ala + mem=mmaphuge:/hugetlbfs/file + The area allocated is a function of the maximum allowed bs size for the job, multiplied by the io depth given. diff --git a/fio.c b/fio.c index 41b60202..8a4a44dc 100644 --- a/fio.c +++ b/fio.c @@ -509,7 +509,7 @@ static int init_io_u(struct thread_data *td) max_bs = max(td->max_bs[DDIR_READ], td->max_bs[DDIR_WRITE]); td->orig_buffer_size = max_bs * max_units; - if (td->mem_type == MEM_SHMHUGE) + if (td->mem_type == MEM_SHMHUGE || td->mem_type == MEM_MMAPHUGE) td->orig_buffer_size = (td->orig_buffer_size + FIO_HUGE_PAGE - 1) & ~(FIO_HUGE_PAGE - 1); else td->orig_buffer_size += MASK; diff --git a/fio.h b/fio.h index c4facfbe..432c0988 100644 --- a/fio.h +++ b/fio.h @@ -125,6 +125,7 @@ enum fio_memtype { MEM_SHM, /* use shared memory segments */ MEM_SHMHUGE, /* use shared memory segments with huge pages */ MEM_MMAP, /* use anonynomous mmap */ + MEM_MMAPHUGE, /* memory mapped huge file */ }; /* @@ -224,6 +225,8 @@ struct thread_data { unsigned long long zone_size; unsigned long long zone_skip; enum fio_memtype mem_type; + char *hugefile; + int hugefd; unsigned int stonewall; unsigned int numjobs; unsigned int iodepth; diff --git a/init.c b/init.c index 0c888b8f..edaec144 100644 --- a/init.c +++ b/init.c @@ -833,6 +833,29 @@ static int str_mem_cb(void *data, const char *mem) if (!strncmp(mem, "malloc", 6)) { td->mem_type = MEM_MALLOC; return 0; + } else if (!strncmp(mem, "mmaphuge", 8)) { +#ifdef FIO_HAVE_HUGETLB + char *hugefile; + + /* + * mmaphuge must be appended with the actual file + */ + hugefile = strstr(mem, ":"); + if (!hugefile) { + log_err("fio: mmaphuge:/path/to/file\n"); + return 1; + } + + hugefile++; + strip_blank_front(&hugefile); + strip_blank_end(hugefile); + td->hugefile = strdup(hugefile); + td->mem_type = MEM_MMAPHUGE; + return 0; +#else + log_err("fio: mmaphuge not available\n"); + return 1; +#endif } else if (!strncmp(mem, "mmap", 4)) { td->mem_type = MEM_MMAP; return 0; @@ -849,7 +872,7 @@ static int str_mem_cb(void *data, const char *mem) return 0; } - log_err("fio: mem type: malloc, shm, mmap, shmhuge\n"); + log_err("fio: mem type: malloc, shm, shmhuge, mmap, mmaphuge\n"); return 1; } diff --git a/memory.c b/memory.c index d336c2bc..5f3c4fa5 100644 --- a/memory.c +++ b/memory.c @@ -81,12 +81,34 @@ int allocate_io_mem(struct thread_data *td) td->orig_buffer = NULL; return 1; } - } else if (td->mem_type == MEM_MMAP) { - td->orig_buffer = mmap(NULL, td->orig_buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, 0, 0); + } else if (td->mem_type == MEM_MMAP || td->mem_type == MEM_MMAPHUGE) { + int flags = MAP_PRIVATE; + + td->hugefd = 0; + + if (td->mem_type == MEM_MMAPHUGE) { + fprintf(stderr, "file=%s\n", td->hugefile); + td->hugefd = open(td->hugefile, O_RDWR|O_CREAT, 0644); + + if (td->hugefd < 0) { + td_verror(td, errno); + perror("open huge file"); + td->orig_buffer = NULL; + return 1; + } + } else + flags |= OS_MAP_ANON; + + fprintf(stderr, "mmaping %lu\n", (unsigned long) td->orig_buffer_size); + td->orig_buffer = mmap(NULL, td->orig_buffer_size, PROT_READ | PROT_WRITE, flags, td->hugefd, 0); + fprintf(stderr, "mmaped %p\n", td->orig_buffer); if (td->orig_buffer == MAP_FAILED) { td_verror(td, errno); perror("mmap"); td->orig_buffer = NULL; + if (td->hugefd) + close(td->hugefd); + return 1; } } @@ -103,9 +125,14 @@ void free_io_mem(struct thread_data *td) shmdt(td->orig_buffer); shmctl(td->shm_id, IPC_RMID, &sbuf); - } else if (td->mem_type == MEM_MMAP) + } else if (td->mem_type == MEM_MMAP || td->mem_type == MEM_MMAPHUGE) { munmap(td->orig_buffer, td->orig_buffer_size); - else + if (td->mem_type == MEM_MMAPHUGE) { + close(td->hugefd); + unlink(td->hugefile); + free(td->hugefile); + } + } else log_err("Bad memory type %u\n", td->mem_type); td->orig_buffer = NULL; -- 2.25.1