Fix issue with td->mutex being used-after-free
[fio.git] / backend.c
index 8450957543ed2c466a2de78029f01538cfd39f2e..a607134b878d4603fcb0d3e32e6273847fa2dc7a 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -651,8 +651,14 @@ static uint64_t do_io(struct thread_data *td)
 
        lat_target_init(td);
 
+       /*
+        * If verify_backlog is enabled, we'll run the verify in this
+        * handler as well. For that case, we may need up to twice the
+        * amount of bytes.
+        */
        total_bytes = td->o.size;
-       if (td->o.verify != VERIFY_NONE && td_write(td))
+       if (td->o.verify != VERIFY_NONE &&
+          (td_write(td) && td->o.verify_backlog))
                total_bytes += td->o.size;
 
        while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
@@ -719,14 +725,14 @@ static uint64_t do_io(struct thread_data *td)
                        td_set_runstate(td, TD_RUNNING);
 
                /*
-                * Verify_backlog disabled: We need to log rand seed before the
-                * actual IO to be able to replay it correctly in the verify phase.
+                * Always log IO before it's issued, so we know the specific
+                * order of it. The logged unit will track when the IO has
+                * completed.
                 */
                if (td_write(td) && io_u->ddir == DDIR_WRITE &&
                    td->o.do_verify &&
                    td->o.verify != VERIFY_NONE &&
-                   !td->o.experimental_verify &&
-                   !(td->flags & TD_F_VER_BACKLOG))
+                   !td->o.experimental_verify)
                        log_io_piece(td, io_u);
 
                ret = td_io_queue(td, io_u);
@@ -1229,13 +1235,6 @@ static void *thread_main(void *data)
        fio_mutex_down(td->mutex);
        dprint(FD_MUTEX, "done waiting on td->mutex\n");
 
-       /*
-        * the ->mutex mutex is now no longer used, close it to avoid
-        * eating a file descriptor
-        */
-       fio_mutex_remove(td->mutex);
-       td->mutex = NULL;
-
        /*
         * A new gid requires privilege, so we need to do this before setting
         * the uid.
@@ -1515,6 +1514,9 @@ err:
        fio_mutex_remove(td->rusage_sem);
        td->rusage_sem = NULL;
 
+       fio_mutex_remove(td->mutex);
+       td->mutex = NULL;
+
        td_set_runstate(td, TD_EXITED);
        return (void *) (uintptr_t) td->error;
 }