Add support for the iomem_align option
authorJens Axboe <jens.axboe@oracle.com>
Wed, 1 Jul 2009 08:33:03 +0000 (10:33 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Wed, 1 Jul 2009 08:33:03 +0000 (10:33 +0200)
This allows detailed control of the alignment of the IO buffers
that fio uses.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
HOWTO
fio.1
fio.c
fio.h
init.c
io_u.c
memory.c
options.c

diff --git a/HOWTO b/HOWTO
index f323c204d3c67be97e98926ae8efd0ae1d82314d..3107d3a15e6b4488dcd8626264b791d078459d1e 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -704,6 +704,15 @@ mem=str            Fio can use various types of memory as the io unit buffer.
                location should point there. So if it's mounted in /huge,
                you would use mem=mmaphuge:/huge/somefile.
 
                location should point there. So if it's mounted in /huge,
                you would use mem=mmaphuge:/huge/somefile.
 
+iomem_align=int        This indiciates the memory alignment of the IO memory buffers.
+               Note that the given alignment is applied to the first IO unit
+               buffer, if using iodepth the alignment of the following buffers
+               are given by the bs used. In other words, if using a bs that is
+               a multiple of the page sized in the system, all buffers will
+               be aligned to this value. If using a bs that is not page
+               aligned, the alignment of subsequent IO memory buffers is the
+               sum of the iomem_align and bs used.
+
 hugepage-size=int
                Defines the size of a huge page. Must at least be equal
                to the system setting, see /proc/meminfo. Defaults to 4MiB.
 hugepage-size=int
                Defines the size of a huge page. Must at least be equal
                to the system setting, see /proc/meminfo. Defaults to 4MiB.
diff --git a/fio.1 b/fio.1
index fc055e4d8cb2dbd1e4b763ffd316aedcba4d667b..aa7b9d6767ed9a0136a2282c133878383356d143 100644 (file)
--- a/fio.1
+++ b/fio.1
@@ -512,6 +512,15 @@ the system must have free huge pages allocated.  \fBmmaphuge\fR also needs to
 have hugetlbfs mounted, and \fIfile\fR must point there.
 .RE
 .TP
 have hugetlbfs mounted, and \fIfile\fR must point there.
 .RE
 .TP
+.BI iomem_align \fR=\fPint
+This indiciates the memory alignment of the IO memory buffers. Note that the
+given alignment is applied to the first IO unit buffer, if using \fBiodepth\fR
+the alignment of the following buffers are given by the \fBbs\fR used. In
+other words, if using a \fBbs\fR that is a multiple of the page sized in the
+system, all buffers will be aligned to this value. If using a \fBbs\fR that
+is not page aligned, the alignment of subsequent IO memory buffers is the
+sum of the \fBiomem_align\fR and \fBbs\fR used.
+.TP
 .BI hugepage\-size \fR=\fPint
 Defines the size of a huge page.  Must be at least equal to the system setting.
 Should be a multiple of 1MiB. Default: 4MiB.
 .BI hugepage\-size \fR=\fPint
 Defines the size of a huge page.  Must be at least equal to the system setting.
 Should be a multiple of 1MiB. Default: 4MiB.
diff --git a/fio.c b/fio.c
index 4927f1c6142fe078de0176f708ad57a34a8feec3..63d9a1b7ab434ca4eba416ab2fe71bbc9e71385a 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -42,7 +42,8 @@
 
 unsigned long page_mask;
 unsigned long page_size;
 
 unsigned long page_mask;
 unsigned long page_size;
-#define ALIGN(buf)     \
+
+#define PAGE_ALIGN(buf)        \
        (char *) (((unsigned long) (buf) + page_mask) & ~page_mask)
 
 int groupid = 0;
        (char *) (((unsigned long) (buf) + page_mask) & ~page_mask)
 
 int groupid = 0;
@@ -790,8 +791,8 @@ static int init_io_u(struct thread_data *td)
        if (allocate_io_mem(td))
                return 1;
 
        if (allocate_io_mem(td))
                return 1;
 
-       if (td->o.odirect)
-               p = ALIGN(td->orig_buffer);
+       if (td->o.mem_align)
+               p = PAGE_ALIGN(td->orig_buffer) + td->o.mem_align;
        else
                p = td->orig_buffer;
 
        else
                p = td->orig_buffer;
 
@@ -811,9 +812,11 @@ static int init_io_u(struct thread_data *td)
                io_u = ptr;
                memset(io_u, 0, sizeof(*io_u));
                INIT_FLIST_HEAD(&io_u->list);
                io_u = ptr;
                memset(io_u, 0, sizeof(*io_u));
                INIT_FLIST_HEAD(&io_u->list);
+               dprint(FD_MEM, "io_u alloc %p, index %u\n", io_u, i);
 
                if (!(td->io_ops->flags & FIO_NOIO)) {
                        io_u->buf = p + max_bs * i;
 
                if (!(td->io_ops->flags & FIO_NOIO)) {
                        io_u->buf = p + max_bs * i;
+                       dprint(FD_MEM, "io_u %p, mem %p\n", io_u, io_u->buf);
 
                        if (td_write(td) && !td->o.refill_buffers)
                                io_u_fill_buffer(td, io_u, max_bs);
 
                        if (td_write(td) && !td->o.refill_buffers)
                                io_u_fill_buffer(td, io_u, max_bs);
diff --git a/fio.h b/fio.h
index 71ae71db2c876749e1445996a8a980d8aafe0253..b19101c20a4924892610bd78b0f6d645f3b93e9b 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -202,6 +202,7 @@ struct thread_options {
        unsigned long long zone_size;
        unsigned long long zone_skip;
        enum fio_memtype mem_type;
        unsigned long long zone_size;
        unsigned long long zone_skip;
        enum fio_memtype mem_type;
+       unsigned int mem_align;
 
        unsigned int stonewall;
        unsigned int new_group;
 
        unsigned int stonewall;
        unsigned int new_group;
@@ -655,4 +656,9 @@ static inline int should_check_rate(struct thread_data *td,
        return ret;
 }
 
        return ret;
 }
 
+static inline int is_power_of_2(unsigned int val)
+{
+       return (val != 0 && ((val & (val - 1)) == 0));
+}
+
 #endif
 #endif
diff --git a/init.c b/init.c
index 02e544a004290130e56a5d30ab430514eaeeb5a8..84c312f9d2194cc878dff29137003bf0d0f05ee5 100644 (file)
--- a/init.c
+++ b/init.c
@@ -367,6 +367,14 @@ static int fixup_options(struct thread_data *td)
        if (td->o.pre_read)
                td->o.invalidate_cache = 0;
 
        if (td->o.pre_read)
                td->o.invalidate_cache = 0;
 
+       if (td->o.mem_align) {
+               if (td->o.odirect && !is_power_of_2(td->o.mem_align)) {
+                       log_err("fio: given IO mem alignment conflicts with"
+                                       " direct=1. Resetting.\n");
+                       td->o.mem_align = page_mask;
+               }
+       }
+                       
        return 0;
 }
 
        return 0;
 }
 
diff --git a/io_u.c b/io_u.c
index 41b5cdbb04894192cb06e2d86a49bdf28d48be9d..2e9dac0db6b4aa0adae673a3b21d26173e48da3e 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -231,11 +231,6 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u)
        return 0;
 }
 
        return 0;
 }
 
-static inline int is_power_of_2(unsigned int val)
-{
-       return (val != 0 && ((val & (val - 1)) == 0));
-}
-
 static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u)
 {
        const int ddir = io_u->ddir;
 static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u)
 {
        const int ddir = io_u->ddir;
index d3ef2cba9adda00bf9ab4f8d7bff9a7a47889665..00339e42663f25522ca1269c35883610a0d1e552 100644 (file)
--- a/memory.c
+++ b/memory.c
@@ -188,8 +188,12 @@ int allocate_io_mem(struct thread_data *td)
                return 0;
 
        total_mem = td->orig_buffer_size;
                return 0;
 
        total_mem = td->orig_buffer_size;
-       if (td->o.odirect)
+
+       if (td->o.odirect || td->o.mem_align) {
                total_mem += page_mask;
                total_mem += page_mask;
+               if (td->o.mem_align && td->o.mem_align > page_size)
+                       total_mem += td->o.mem_align - page_size;
+       }
 
        if (td->o.mem_type == MEM_MALLOC)
                ret = alloc_mem_malloc(td, total_mem);
 
        if (td->o.mem_type == MEM_MALLOC)
                ret = alloc_mem_malloc(td, total_mem);
index 394472a4dadf61512e6c49f8495f97f248b357f5..7135231eefeed59b73cf720c73aab14c5c66a3c8 100644 (file)
--- a/options.c
+++ b/options.c
@@ -1036,6 +1036,16 @@ static struct fio_option options[] = {
 #endif
                  },
        },
 #endif
                  },
        },
+       {
+               .name   = "iomem_align",
+               .alias  = "mem_align",
+               .type   = FIO_OPT_INT,
+               .off1   = td_var_offset(mem_align),
+               .minval = 0,
+               .help   = "IO memory buffer offset alignment",
+               .def    = "0",
+               .parent = "iomem",
+       },
        {
                .name   = "verify",
                .type   = FIO_OPT_STR,
        {
                .name   = "verify",
                .type   = FIO_OPT_STR,