From 799441286648bdced4f42d3040f37fd2e35eaf1d Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 24 May 2011 11:26:16 +0200 Subject: [PATCH] Fix overlap io_u into outside regions Test case is a job file ala this: [global] ioengine=posixaio direct=0 filename=testfile iodepth=128 size=50M loops=10000000000 group_reporting=1 readwrite=randwrite do_verify=1 verify=md5 verify_fatal=1 numjobs=1 thread bsrange=4k:1M [thread0] offset=0G [thread1] offset=50M [thread2] offset=100M [thread3] offset=150M [thread4] offset=200M [thread5] offset=250M [thread6] offset=300M [thread7] offset=350M where io_u units from threadN ends up crossing into the zone of threadN+1. This is due to using file->real_file_size as the boundary check for the buffer length, where the offset itself is correctly calculated. When using mixed block sizes, this can cause a blocksize larger than the minimum size to span into the next region. Fix this by using file->io_size + offset as the end delimeter. Also improve the logic of dropping to a smaller allowed block size if we do end up being close to spanning into the next region. Signed-off-by: Jens Axboe --- io_u.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/io_u.c b/io_u.c index d35b8441..51da223d 100644 --- a/io_u.c +++ b/io_u.c @@ -341,6 +341,14 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u) return __get_next_offset(td, io_u); } +static inline int io_u_fits(struct thread_data *td, struct io_u *io_u, + unsigned int buflen) +{ + struct fio_file *f = io_u->file; + + return io_u->offset + buflen <= f->io_size + td->o.start_offset; +} + static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) { const int ddir = io_u->ddir; @@ -353,14 +361,15 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) minbs = td->o.min_bs[ddir]; maxbs = td->o.max_bs[ddir]; + if (minbs == maxbs) + return minbs; + if (td->o.use_os_rand) rand_max = OS_RAND_MAX; else rand_max = FRAND_MAX; - if (minbs == maxbs) - buflen = minbs; - else { + do { if (td->o.use_os_rand) r = os_random_long(&td->bsrange_state); else @@ -380,19 +389,16 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) buflen = bsp->bs; perc += bsp->perc; - if (r <= ((rand_max / 100L) * perc)) + if ((r <= ((rand_max / 100L) * perc)) && + io_u_fits(td, io_u, buflen)) break; } } + if (!td->o.bs_unaligned && is_power_of_2(minbs)) buflen = (buflen + minbs - 1) & ~(minbs - 1); - } - if (io_u->offset + buflen > io_u->file->real_file_size) { - dprint(FD_IO, "lower buflen %u -> %u (ddir=%d)\n", buflen, - minbs, ddir); - buflen = minbs; - } + } while (!io_u_fits(td, io_u, buflen)); return buflen; } -- 2.25.1