iolog: fix double free when verified I/O overlaps
authorSitsofe Wheeler <sitsofe@yahoo.com>
Thu, 27 Apr 2017 06:29:56 +0000 (07:29 +0100)
committerSitsofe Wheeler <sitsofe@yahoo.com>
Mon, 14 Aug 2017 03:43:35 +0000 (04:43 +0100)
When running
valgrind ./fio --randseed=1 --ioengine=libaio --thread --rw=randrw \
 --random_distribution=zipf:1.4 --filename=/tmp/fiofile --io_limit=50M \
 --verify=crc32c --name=verifyfree --iodepth=32 --bsrange=512-1M --size=100M

valgrind reports:
==29301== Invalid read of size 4
==29301==    at 0x44ADFC: io_completed (io_u.c:1835)
==29301==    by 0x44B215: ios_completed (io_u.c:1924)
==29301==    by 0x44B683: io_u_queued_complete (io_u.c:1983)
==29301==    by 0x46FA6F: wait_for_completions (backend.c:455)
==29301==    by 0x471568: do_io (backend.c:1046)
==29301==    by 0x474405: thread_main (backend.c:1746)
==29301==    by 0x576E6B9: start_thread (pthread_create.c:333)
==29301==    by 0x5C8E82C: clone (clone.S:109)
==29301==  Address 0x62cf988 is 72 bytes inside a block of size 88 free'd
==29301==    at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

When the __ipo is still in-flight we shouldn't free it when it overlaps
because it will be used at I/O completion time. Fixes
https://github.com/axboe/fio/issues/336 .

Tested-by: Jeff Furlong <jeff.furlong@wdc.com>
Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
iolog.c

diff --git a/iolog.c b/iolog.c
index 27c14eb3630fda9179722d17bf0229374190e042..18ae4369dcad96190bac5e3974366f6be41d413d 100644 (file)
--- a/iolog.c
+++ b/iolog.c
@@ -284,7 +284,8 @@ restart:
                        td->io_hist_len--;
                        rb_erase(parent, &td->io_hist_tree);
                        remove_trim_entry(td, __ipo);
                        td->io_hist_len--;
                        rb_erase(parent, &td->io_hist_tree);
                        remove_trim_entry(td, __ipo);
-                       free(__ipo);
+                       if (!(__ipo->flags & IP_F_IN_FLIGHT))
+                               free(__ipo);
                        goto restart;
                }
        }
                        goto restart;
                }
        }