| From 1aa3e0ebfb045e723eb7207e398b7fdd8712c48d Mon Sep 17 00:00:00 2001 |
| From: Juan Casse <jcasse@chromium.org> |
| Date: Mon, 16 Sep 2013 08:58:24 -0700 |
| Subject: [PATCH] Add condition to stop issuing io in do_io(). |
| |
| Problem: |
| When specifying iodepth > 1 while doing random async io |
| without a random map (and using the default random generator), the |
| main while loop in do_io() will issue extra io in the amount of io |
| allowed to accumulate in the queue. For example, a job with size=24k |
| and bs=8k will perform 4 io instead of the expected 3. |
| |
| Reason: |
| The above behavior occurs because the while loop in do_io() |
| will continue until the amount of "completed io" >= size, but io |
| in the queue are not accounted for because they have not been |
| completed by io_u_queued_complete(). |
| |
| Exceptions: |
| The above behavior does not manifest itself when: |
| using random_generator=lfsr bacause lfsr knows when to stop |
| generating, and get_io_u() inside the while loop returns NULL, |
| breaking out of the loop. |
| using random map because random map ensures that all blocks |
| are hit, and after they are all hit, no more are generated. |
| |
| Proposed Solution: |
| Stop while loop based on bytes issued instead of bytes completed. |
| --- |
| backend.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| diff --git a/backend.c b/backend.c |
| index b9c1c12..180a487 100644 |
| --- a/backend.c |
| +++ b/backend.c |
| @@ -642,6 +642,7 @@ static uint64_t do_io(struct thread_data *td) |
| uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 }; |
| unsigned int i; |
| int ret = 0; |
| + uint64_t bytes_issued = 0; |
| |
| if (in_ramp_time(td)) |
| td_set_runstate(td, TD_RAMP); |
| @@ -675,6 +676,9 @@ static uint64_t do_io(struct thread_data *td) |
| if (flow_threshold_exceeded(td)) |
| continue; |
| |
| + if (bytes_issued >= (uint64_t) td->o.size) |
| + break; |
| + |
| io_u = get_io_u(td); |
| if (!io_u) |
| break; |
| @@ -708,6 +712,7 @@ static uint64_t do_io(struct thread_data *td) |
| int bytes = io_u->xfer_buflen - io_u->resid; |
| struct fio_file *f = io_u->file; |
| |
| + bytes_issued += bytes; |
| /* |
| * zero read, fail |
| */ |
| @@ -738,6 +743,7 @@ sync_done: |
| ret = io_u_sync_complete(td, io_u, bytes_done); |
| if (ret < 0) |
| break; |
| + bytes_issued += io_u->xfer_buflen; |
| } |
| break; |
| case FIO_Q_QUEUED: |
| @@ -748,6 +754,7 @@ sync_done: |
| */ |
| if (td->io_ops->commit == NULL) |
| io_u_queued(td, io_u); |
| + bytes_issued += io_u->xfer_buflen; |
| break; |
| case FIO_Q_BUSY: |
| requeue_io_u(td, &io_u); |
| -- |
| 1.7.12.4 |
| |