Fix race condition when using asynch verify
authorRadha Ramachandran <radha@google.com>
Tue, 3 Nov 2009 20:45:31 +0000 (21:45 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 3 Nov 2009 20:45:31 +0000 (21:45 +0100)
I discovered the race condition when using asynch verify with libaio engine.
The code assumes that because the td->cur_depth value is not 0 that
there is still I/O pending and issues io_getevents when the I/O was
actually being verified by the asynchronous verify thread. This causes
the code to hang.

(Updated by Jens to use a new io_u->flag bitfield instead of adding a new
 integer to struct io_u).

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
io_u.c
ioengine.h
verify.c

diff --git a/io_u.c b/io_u.c
index da9d95054bcf58b8a42985d327439e001d26221c..232f6a6f6929ff9514e035336b6ba9626c0a45fd 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -421,9 +421,10 @@ void put_io_u(struct thread_data *td, struct io_u *io_u)
                put_file_log(td, io_u->file);
 
        io_u->file = NULL;
+       if (io_u->flags & IO_U_F_IN_CUR_DEPTH)
+               td->cur_depth--;
        flist_del_init(&io_u->list);
        flist_add(&io_u->list, &td->io_u_freelist);
-       td->cur_depth--;
        td_io_u_unlock(td);
        td_io_u_free_notify(td);
 }
@@ -447,10 +448,10 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u)
                td->io_issues[__io_u->ddir]--;
 
        __io_u->flags &= ~IO_U_F_FLIGHT;
-
+       if (__io_u->flags & IO_U_F_IN_CUR_DEPTH)
+               td->cur_depth--;
        flist_del(&__io_u->list);
        flist_add_tail(&__io_u->list, &td->io_u_requeues);
-       td->cur_depth--;
        td_io_u_unlock(td);
        *io_u = NULL;
 }
@@ -867,6 +868,7 @@ again:
                flist_del(&io_u->list);
                flist_add(&io_u->list, &td->io_u_busylist);
                td->cur_depth++;
+               io_u->flags |= IO_U_F_IN_CUR_DEPTH;
        }
 
        td_io_u_unlock(td);
index 3df0944a30ed30cec9a54b9d4fa464506e311885..eb6655d165cad381e747a332cfee5b93736e7fd8 100644 (file)
@@ -4,9 +4,10 @@
 #define FIO_IOOPS_VERSION      10
 
 enum {
-       IO_U_F_FREE     = 1 << 0,
-       IO_U_F_FLIGHT   = 1 << 1,
-       IO_U_F_FREE_DEF = 1 << 2,
+       IO_U_F_FREE             = 1 << 0,
+       IO_U_F_FLIGHT           = 1 << 1,
+       IO_U_F_FREE_DEF         = 1 << 2,
+       IO_U_F_IN_CUR_DEPTH     = 1 << 3,
 };
 
 /*
index faa5684d9dafa369551c41c4faf045b2fa4ad469..7d675e46de6b110c25b0145bd00b1453eba60e2f 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -437,6 +437,11 @@ int verify_io_u_async(struct thread_data *td, struct io_u *io_u)
        io_u->file = NULL;
 
        pthread_mutex_lock(&td->io_u_lock);
+       
+       if (io_u->flags & IO_U_F_IN_CUR_DEPTH) {
+               td->cur_depth--;
+               io_u->flags &= ~IO_U_F_IN_CUR_DEPTH;
+       }
        flist_del(&io_u->list);
        flist_add_tail(&io_u->list, &td->verify_list);
        pthread_mutex_unlock(&td->io_u_lock);