Fix issue with td->mutex being used-after-free
[fio.git] / backend.c
index 3ac72e771cb9eaa44a17fabe70d9aee718ccd6a5..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)) ||
@@ -718,6 +724,11 @@ static uint64_t do_io(struct thread_data *td)
                else
                        td_set_runstate(td, TD_RUNNING);
 
+               /*
+                * 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 &&
@@ -1224,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.
@@ -1510,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;
 }