[PATCH] Support for mmap of hugetlb files as memory backing
authorJens Axboe <jens.axboe@oracle.com>
Wed, 20 Dec 2006 13:40:44 +0000 (14:40 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Wed, 20 Dec 2006 13:40:44 +0000 (14:40 +0100)
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
fio.c
fio.h
init.c
memory.c

diff --git a/HOWTO b/HOWTO
index 6ac744cd3d436124f8474ff135c7a842fb92136b..f5e2449c22d64956015d983c04c1f93aa8dc9840 100644 (file)
--- 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 41b602020b9c93a68a13a0b02bbcf945102f3dcc..8a4a44dc902f0f0dde0695deceaefb1dbab9ae4a 100644 (file)
--- 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 c4facfbe995b2f0ed20e88353fb645a528721ec9..432c098863978840779dc280e146b74109da8b47 100644 (file)
--- 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 0c888b8fcdca83a0bdc7691d2eb38202393ebcbb..edaec144f3aaaa5895339df4f2a703bdff7d9c48 100644 (file)
--- 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;
 }
 
index d336c2bcb8cea017b6d9db980e3c39a95d70c717..5f3c4fa56c3d54b7bfe5a797a67776e1027d7cd3 100644 (file)
--- 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;