filesetup: align layout buffer
authorSitsofe Wheeler <sitsofe@yahoo.com>
Mon, 21 Aug 2017 21:15:00 +0000 (22:15 +0100)
committerSitsofe Wheeler <sitsofe@yahoo.com>
Mon, 28 Aug 2017 15:11:35 +0000 (16:11 +0100)
Since commit 6e344dc3445bfec0583072e82bea728ab8d54d58 ("filesetup: keep
OS_O_DIRECT flag when pre-allocating file") when direct=1 fio will set
the OS_O_DIRECT flag during file layout. Unfortunately this makes the
following job fail with due to an "Invalid argument" on Linux:

$ rm -f fiodirect.tmp; ./fio --direct=1 --bs=4k --filename=fiodirect.tmp \
 --size=16k --name=directtest
directtest: (g=0): rw=read, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
fio-3.0-9-gb427
Starting 1 process
directtest: Laying out IO file (1 file / 0MiB)
fio: pid=35410, err=22/file:filesetup.c:227, func=write, error=Invalid argument

(where fiodirect.tmp is on a filesystem that supports O_DIRECT such as
ext4 and the job used to succeed)

The open(2) man page for Linux says:

"Under Linux 2.4, transfer sizes, and the alignment of the user buffer
and the file offset must all be multiples of the logical block size of
the filesystem.  Since Linux 2.6.0, alignment to the logical block size
of the underlying storage (typically 512 bytes) suffices."

The above is cryptic but suggests that on Linux 2.6 and above kernels
the transfer size, the *memory alignment of the user buffer* and the
file offset must all be multiples of the underlying logical block size
when using O_DIRECT.

This commit forces the memory of fio's layout I/O buffer to be aligned
to the system's page size in an attempt to meet the memory alignment
requirement. Altough approximate, this should handle all but the most
unusual setups for the near future and matches what init_io_u() does in
backend.c.

v2:
- Align buffer pointer to page size rather than maximum block size
- Update commit message, include example

Fixes https://github.com/axboe/fio/issues/429 .

Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
filesetup.c

index 0e5599ab16502e9541023af6028e9814f366a844..b9d68c458650f299f25f9eb934a1aac6722e7e65 100644 (file)
@@ -15,6 +15,7 @@
 #include "os/os.h"
 #include "hash.h"
 #include "lib/axmap.h"
+#include "lib/memalign.h"
 
 #ifdef CONFIG_LINUX_FALLOCATE
 #include <linux/falloc.h>
@@ -194,9 +195,9 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
        if (bs > left)
                bs = left;
 
-       b = malloc(bs);
+       b = fio_memalign(page_size, bs);
        if (!b) {
-               td_verror(td, errno, "malloc");
+               td_verror(td, errno, "fio_memalign");
                goto err;
        }
 
@@ -249,14 +250,14 @@ static int extend_file(struct thread_data *td, struct fio_file *f)
                        f->io_size = f->real_file_size;
        }
 
-       free(b);
+       fio_memfree(b, bs);
 done:
        return 0;
 err:
        close(f->fd);
        f->fd = -1;
        if (b)
-               free(b);
+               fio_memfree(b, bs);
        return 1;
 }