Ensure that we have no IO pending when sleeping
authorJens Axboe <axboe@kernel.dk>
Fri, 17 May 2013 10:39:53 +0000 (12:39 +0200)
committerJens Axboe <axboe@kernel.dk>
Fri, 17 May 2013 10:39:53 +0000 (12:39 +0200)
For rate limiting or thinktime handling, ensure that we have
no busy IO when we do spin or sleep. Otherwise we potentially
skew the latencies a lot, since events could have been reaped.

Already working for rate iops, just abstracted it out and
ensure that we do the same for thinktime. Only a problem for
certain workloads, those with queuedepth > 1.

Signed-off-by: Jens Axboe <axboe@kernel.dk>
backend.c
io_u.c
ioengine.h

index 89ffee1277f5ad47f733b56e9bf5c86ad9b39fc8..6b6da67645870b74a59eb6c619d82ed870aee60b 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -822,6 +822,8 @@ sync_done:
                        if (!(b % td->o.thinktime_blocks)) {
                                int left;
 
                        if (!(b % td->o.thinktime_blocks)) {
                                int left;
 
+                               io_u_quiesce(td);
+
                                if (td->o.thinktime_spin)
                                        usec_spin(td->o.thinktime_spin);
 
                                if (td->o.thinktime_spin)
                                        usec_spin(td->o.thinktime_spin);
 
diff --git a/io_u.c b/io_u.c
index 2cf2b8d0e398923590c01281b5082361d8c7eca1..f0b6170535d2a77a07861a4a0760d72a4130412e 100644 (file)
--- a/io_u.c
+++ b/io_u.c
@@ -511,6 +511,24 @@ static inline enum fio_ddir get_rand_ddir(struct thread_data *td)
        return DDIR_WRITE;
 }
 
        return DDIR_WRITE;
 }
 
+void io_u_quiesce(struct thread_data *td)
+{
+       /*
+        * We are going to sleep, ensure that we flush anything pending as
+        * not to skew our latency numbers.
+        *
+        * Changed to only monitor 'in flight' requests here instead of the
+        * td->cur_depth, b/c td->cur_depth does not accurately represent
+        * io's that have been actually submitted to an async engine,
+        * and cur_depth is meaningless for sync engines.
+        */
+       while (td->io_u_in_flight) {
+               int fio_unused ret;
+
+               ret = io_u_queued_complete(td, 1, NULL);
+       }
+}
+
 static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
 {
        enum fio_ddir odir = ddir ^ 1;
 static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
 {
        enum fio_ddir odir = ddir ^ 1;
@@ -547,20 +565,7 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir)
        } else
                usec = td->rate_pending_usleep[ddir];
 
        } else
                usec = td->rate_pending_usleep[ddir];
 
-       /*
-        * We are going to sleep, ensure that we flush anything pending as
-        * not to skew our latency numbers.
-        *
-        * Changed to only monitor 'in flight' requests here instead of the
-        * td->cur_depth, b/c td->cur_depth does not accurately represent
-        * io's that have been actually submitted to an async engine,
-        * and cur_depth is meaningless for sync engines.
-        */
-       while (td->io_u_in_flight) {
-               int fio_unused ret;
-
-               ret = io_u_queued_complete(td, 1, NULL);
-       }
+       io_u_quiesce(td);
 
        fio_gettime(&t, NULL);
        usec_sleep(td, usec);
 
        fio_gettime(&t, NULL);
        usec_sleep(td, usec);
index 362ab3e5d6bd8c923b66b8316b1386a2f8b761c9..0be905f950268967abdd87406649722b2b72bb17 100644 (file)
@@ -196,6 +196,7 @@ extern void requeue_io_u(struct thread_data *, struct io_u **);
 extern int __must_check io_u_sync_complete(struct thread_data *, struct io_u *, uint64_t *);
 extern int __must_check io_u_queued_complete(struct thread_data *, int, uint64_t *);
 extern void io_u_queued(struct thread_data *, struct io_u *);
 extern int __must_check io_u_sync_complete(struct thread_data *, struct io_u *, uint64_t *);
 extern int __must_check io_u_queued_complete(struct thread_data *, int, uint64_t *);
 extern void io_u_queued(struct thread_data *, struct io_u *);
+extern void io_u_quiesce(struct thread_data *);
 extern void io_u_log_error(struct thread_data *, struct io_u *);
 extern void io_u_mark_depth(struct thread_data *, unsigned int);
 extern void fill_io_buffer(struct thread_data *, void *, unsigned int, unsigned int);
 extern void io_u_log_error(struct thread_data *, struct io_u *);
 extern void io_u_mark_depth(struct thread_data *, unsigned int);
 extern void fill_io_buffer(struct thread_data *, void *, unsigned int, unsigned int);