Fix infinite loop on platforms with severely limited aio resources
authorJens Axboe <jaxboe@fusionio.com>
Thu, 14 Jul 2011 10:45:13 +0000 (12:45 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Thu, 14 Jul 2011 10:45:13 +0000 (12:45 +0200)
Problem hit on OSX, where with 4 jobs each with a queue depth larger
than what the system supports, you can get into a situation where
any given process can get EAGAIN on queueing AIO even if it has
nothing queued already. Check for this condition to avoid fio's
IO loop going into a death spiral.

Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
fio.c

diff --git a/fio.c b/fio.c
index 9e9106d..120431e 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -550,9 +550,10 @@ sync_done:
 
                /*
                 * if we can queue more, do so. but check if there are
-                * completed io_u's first.
+                * completed io_u's first. Note that we can get BUSY even
+                * without IO queued, if the system is resource starved.
                 */
-               full = queue_full(td) || ret == FIO_Q_BUSY;
+               full = queue_full(td) || (ret == FIO_Q_BUSY && td->cur_depth);
                if (full || !td->o.iodepth_batch_complete) {
                        min_events = min(td->o.iodepth_batch_complete,
                                         td->cur_depth);
@@ -710,9 +711,11 @@ sync_done:
                        break;
 
                /*
-                * See if we need to complete some commands
+                * See if we need to complete some commands. Note that we
+                * can get BUSY even without IO queued, if the system is
+                * resource starved.
                 */
-               full = queue_full(td) || ret == FIO_Q_BUSY;
+               full = queue_full(td) || (ret == FIO_Q_BUSY && td->cur_depth);
                if (full || !td->o.iodepth_batch_complete) {
                        min_evts = min(td->o.iodepth_batch_complete,
                                        td->cur_depth);