stat: fix corruption in histogram logs
authorSitsofe Wheeler <sitsofe@yahoo.com>
Sun, 13 Oct 2019 08:55:51 +0000 (09:55 +0100)
committerSitsofe Wheeler <sitsofe@yahoo.com>
Sun, 13 Oct 2019 16:48:32 +0000 (17:48 +0100)
Commit 6cc0e5aa9eddd2487dfa9ac80be1264151058409 ("Fix overflow of
counters incremented on each I/O operation") changed various structures
from [unsigned] int -> [u]int64_t but the size used when memcpy-ing
histogram data was still the older (smaller) size. This led to un-copied
values and usage of uninitialised data. An example job that demonstrates
the issue is:

$ valgrind ./fio --size=256k --thread=1 --rate_iops=5 --direct=1 \
 --number_ios=15 --name=hist_test --filename=fio.test \
 --log_hist_msec=1000 --write_hist_log=fio.test --log_hist_coarseness=6
==1743== Memcheck, a memory error detector
[...]
fio-3.16-8-gf951
Starting 1 thread
==1743== Thread 3: IOPS: [R(1)][23.1%][r=20KiB/s][r=5 IOPS][eta 00m:10s]
==1743== Use of uninitialised value of size 8
==1743==    at 0x609D86B: _itoa_word (_itoa.c:179)
==1743==    by 0x60A0F0D: vfprintf (vfprintf.c:1642)
==1743==    by 0x60A9E53: fprintf (fprintf.c:32)
==1743==    by 0x47FA6C: flush_hist_samples (iolog.c:869)
==1743==    by 0x47F637: flush_log (iolog.c:1212)
==1743==    by 0x4813C5: finish_log (iolog.c:1238)
==1743==    by 0x4812CD: __write_log (iolog.c:1571)
==1743==    by 0x481202: write_clat_hist_log (iolog.c:1625)
==1743==    by 0x480045: td_writeout_logs (iolog.c:1721)
==1743==    by 0x485C7A: thread_main (backend.c:1889)
==1743==    by 0x5C296DA: start_thread (pthread_create.c:463)
==1743==    by 0x616688E: clone (clone.S:95)

This commit fixes the issue by using the new size in the memcpy.

Fixes: https://github.com/axboe/fio/issues/827
Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
stat.c

diff --git a/stat.c b/stat.c
index 33637900df622c2fae42841f19fc0ed5cd9ebdc1..05663e07b4379f7850a022b82ae96c19041cd27f 100644 (file)
--- a/stat.c
+++ b/stat.c
@@ -2580,7 +2580,7 @@ void add_clat_sample(struct thread_data *td, enum fio_ddir ddir,
                        io_u_plat = (uint64_t *) td->ts.io_u_plat[ddir];
                        dst = malloc(sizeof(struct io_u_plat_entry));
                        memcpy(&(dst->io_u_plat), io_u_plat,
-                               FIO_IO_U_PLAT_NR * sizeof(unsigned int));
+                               FIO_IO_U_PLAT_NR * sizeof(uint64_t));
                        flist_add(&dst->list, &hw->list);
                        __add_log_sample(iolog, sample_plat(dst), ddir, bs,
                                                elapsed, offset);