Re: core dump in fio-1.16.9

From: Jens Axboe <jens.axboe_at_oracle.com>
Date: Thu, 26 Jul 2007 10:46:13 +0200

On Thu, Jul 26 2007, ljzhang,Yaxin Hu,Jianchao Tang wrote:
> 1. The job file causing the problem:
> ----------ranmap-------------------
> [global]
> directory=./temp
> nrfiles=1
> rw=randread
> size=64K
> bsrange=1k-32k
> thread
> [ranmap]
> description="Over-bounded in mark_random_map()."
> -----------------------------------------
>
> Running the job file, we have a high possibility to get a core dump like
> this:
> ----------------------------------------
> nonggia_at_nonggia-desktop:~/fio$ fio --version
> fio 1.16.9
> nonggia_at_nonggia-desktop:~/fio$ fio ranmap
> ranmap: (g=0): rw=randread, bs=1K-32K/4K-4K, ioengine=sync, iodepth=1
> Starting 1 thread
> file:io_u.c:64, assert idx < f->num_maps failed
> Segmentation fault (core dumped)
> nonggia_at_nonggia-desktop:~/fio$ gdb fio core.6135
> ... ...
> Core was generated by `fio ranmap'.
> Program terminated with signal 11, Segmentation fault.
> #0 0x0805b69f in mark_random_map (td=0xb7be3000, io_u=0x8073f08) at
> io_u.c:64
> 64 fio_assert(td, idx < f->num_maps);
> (gdb) bt
> #0 0x0805b69f in mark_random_map (td=0xb7be3000, io_u=0x8073f08) at
> io_u.c:64
> #1 0x0805c42c in fill_io_u (td=0xb7be3000, io_u=0x8073f08) at
> io_u.c:348
> #2 0x0805cb5f in set_io_u_file (td=0xb7be3000, io_u=0x8073f08) at
> io_u.c:588
> #3 0x0805cde4 in get_io_u (td=0xb7be3000) at io_u.c:672
> #4 0x0804cadd in do_io (td=0xb7be3000) at fio.c:437
> #5 0x0804e1b1 in thread_main (data=0xb7be3000) at fio.c:873
> #6 0xb7ef7504 in start_thread ()
> from /lib/tls/i686/cmov/libpthread.so.0
> #7 0xb7e5551e in clone () from /lib/tls/i686/cmov/libc.so.6
> (gdb) p io_u->offset
> $1 = 41984
> (gdb) p io_u->buflen
> $2 = 27648
> (gdb) p io_u->file->real_file_size
> $3 = 65536
>
>
> 2. Reason for the core dump:
> The io_u->offset+io_u->buflen was too large to be map in the map file.
> They just produced an idx out of the file_map's range.

Thanks for the excellent bug report! I think your fix isn't entirely
great though. We really should not generate such an illegal io_u to
begin with. How about the below? It makes sure that any io_u that we
pass on is valid, within the range of the file.

diff --git a/io_u.c b/io_u.c
index 136dc04..8acc0c3 100644
--- a/io_u.c
+++ b/io_u.c
@@ -190,6 +190,9 @@ static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u)
                         buflen = (buflen + td->o.min_bs[ddir] - 1) & ~(td->o.min_bs[ddir] - 1);
         }
 
+ if (io_u->offset + buflen > io_u->file->real_file_size)
+ buflen = td->o.min_bs[ddir];
+
         return buflen;
 }
 
@@ -341,6 +344,9 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u)
         if (!io_u->buflen)
                 return 1;
 
+ if (io_u->offset + io_u->buflen > io_u->file->real_file_size)
+ return 1;
+
         /*
          * mark entry before potentially trimming io_u
          */

-- 
Jens Axboe
Received on Thu Jul 26 2007 - 10:46:13 CEST

This archive was generated by hypermail 2.2.0 : Thu Jul 26 2007 - 11:00:02 CEST