Jagadish reports:
----
following are the details of the bug in fio.
This bug in fio can show up as corruption of data when performing verify.
Description:
----------------
if the product of block size and queudepth is greater than 4GB, io_u
buffer will not
be assigned properly due to overflow.
fio --bsrange=256k-4m --ioengine=libaio --iodepth=2064 --direct=1
--name=job3 --offset=2GB --size=14GB --rw=write
--verify_pattern=0xdeadbeef --filename=/dev/sdb
can show false corruption.
Version:
-----------
1.58
Explanation:
-----------------
in a loop fio tries to assign the data buffer to each i/o request.
static int init_io_u(struct thread_data *td)
{
struct io_u *io_u;
unsigned int max_bs;
int cl_align, i, max_units;
char *p;
...
p = td->orig_buffer;
...
for (i = 0; i < max_units; i++) {
...
io_u->buf = p + max_bs * i;
}
}
at max_bs=4M i=1024, the integer overflows and the addresses are being
used again.
i,e i/o request 1024 will have the same data buffer as that of i/o request 0.
This is seen from fio debug log.
mem 11164 io_u alloc 0x219f530, index 0
mem 11164 io_u 0x219f530, mem 0x7f09bb62d000
mem 11164 io_u alloc 0x219f820, index 1
mem 11164 io_u 0x219f820, mem 0x7f09bba2d000
mem 11164 io_u alloc 0x225b530, index 1024
mem 11164 io_u 0x225b530, mem 0x7f09bb62d000
mem 11164 io_u alloc 0x225b820, index 1025
mem 11164 io_u 0x225b820, mem 0x7f09bba2d000
the fix is as follows:
io_u->buf = p + (unsigned long long)max_bs * i;
----
Fix this by continually incrementing 'p' instead, avoiding
the overflow as well.
Reported-by: Jagadish Kumar <jagadish.mukku@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
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;
+ io_u->buf = p;
dprint(FD_MEM, "io_u %p, mem %p\n", io_u, io_u->buf);
if (td_write(td))
io_u->index = i;
io_u->flags = IO_U_F_FREE;
flist_add(&io_u->list, &td->io_u_freelist);
+ p += max_bs;
}
return 0;