Index: trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp	(revision 80066)
+++ trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp	(revision 80178)
@@ -80,8 +80,8 @@
     IOPERFTEST_SEQ_READ,
     IOPERFTEST_SEQ_WRITE,
+    IOPERFTEST_REV_READ,
+    IOPERFTEST_REV_WRITE,
     IOPERFTEST_RND_READ,
     IOPERFTEST_RND_WRITE,
-    IOPERFTEST_REV_READ,
-    IOPERFTEST_REV_WRITE,
     IOPERFTEST_SEQ_READWRITE,
     IOPERFTEST_RND_READWRITE,
@@ -174,4 +174,6 @@
     /** Size of the random write buffer in 512 byte blocks. */
     uint32_t                    cRandWriteBlocks512B;
+    /** Start timestamp. */
+    uint64_t                    tsStart;
     /** Test dependent data. */
     union
@@ -279,5 +281,6 @@
 /** Maximum number of concurrent requests for each job. */
 static uint32_t     g_cReqsMax     = 16;
-
+/** Flag whether to open the file without caching enabled. */
+static bool         g_fNoCache     = true;
 
 /** @name Configured tests, this must match the IOPERFTEST order.
@@ -290,8 +293,8 @@
     IOPERFTEST_SEQ_READ,
     IOPERFTEST_SEQ_WRITE,
+    IOPERFTEST_REV_READ,
+    IOPERFTEST_REV_WRITE,
     IOPERFTEST_RND_READ,
     IOPERFTEST_RND_WRITE,
-    IOPERFTEST_REV_READ,
-    IOPERFTEST_REV_WRITE,
     IOPERFTEST_SEQ_READWRITE,
     IOPERFTEST_RND_READWRITE,
@@ -331,5 +334,5 @@
     AssertReturn(g_idxTest < RT_ELEMENTS(g_aenmTests), IOPERFTEST_SHUTDOWN);
 
-    return g_aenmTests[g_idxTest];
+    return g_aenmTests[g_idxTest++];
 }
 
@@ -386,7 +389,12 @@
             pJob->Tst.offNextSeq += pJob->cbIoBlock;
             break;
-
         case IOPERFTEST_REV_WRITE:
         case IOPERFTEST_REV_READ:
+            offNext = pJob->Tst.offNextSeq;
+            if (pJob->Tst.offNextSeq == 0)
+                pJob->Tst.offNextSeq = pJob->cbTestSet;
+            else
+                pJob->Tst.offNextSeq -= pJob->cbIoBlock;
+            break;
         case IOPERFTEST_RND_WRITE:
         case IOPERFTEST_RND_READ:
@@ -448,4 +456,41 @@
 
 /**
+ * Returns a stringified version of the test given.
+ *
+ * @returns Pointer to string representation of the test.
+ * @param   enmTest             The test to stringify.
+ */
+static const char *ioPerfJobTestStringify(IOPERFTEST enmTest)
+{
+    switch (enmTest)
+    {
+        case IOPERFTEST_FIRST_WRITE:
+            return "FirstWrite";
+        case IOPERFTEST_SEQ_WRITE:
+            return "SequentialWrite";
+        case IOPERFTEST_SEQ_READ:
+            return "SequentialRead";
+        case IOPERFTEST_REV_WRITE:
+            return "ReverseWrite";
+        case IOPERFTEST_REV_READ:
+            return "ReverseRead";
+        case IOPERFTEST_RND_WRITE:
+            return "RandomWrite";
+        case IOPERFTEST_RND_READ:
+            return "RandomRead";
+        case IOPERFTEST_SEQ_READWRITE:
+            return "SequentialReadWrite";
+        case IOPERFTEST_RND_READWRITE:
+            return "RandomReadWrite";
+        default:
+            AssertMsgFailed(("Invalid/unknown test selected: %d\n", enmTest));
+            break;
+    }
+
+    return "INVALID_TEST";
+}
+
+
+/**
  * Initializes the test state for the current test.
  *
@@ -462,7 +507,8 @@
             pJob->Tst.offNextSeq = 0;
             break;
-
         case IOPERFTEST_REV_WRITE:
         case IOPERFTEST_REV_READ:
+            pJob->Tst.offNextSeq = pJob->cbTestSet - pJob->cbIoBlock;
+            break;
         case IOPERFTEST_RND_WRITE:
         case IOPERFTEST_RND_READ:
@@ -476,4 +522,6 @@
     }
 
+    RTTestISub(ioPerfJobTestStringify(pJob->enmTest));
+    pJob->tsStart = RTTimeNanoTS();
     return VINF_SUCCESS;
 }
@@ -488,4 +536,7 @@
 static void ioPerfJobTestFinish(PIOPERFJOB pJob)
 {
+    uint64_t nsRuntime = RTTimeNanoTS() - pJob->tsStart;
+    RTTestIValue("Runtime", nsRuntime, RTTESTUNIT_NS);
+
     switch (pJob->enmTest)
     {
@@ -493,8 +544,8 @@
         case IOPERFTEST_SEQ_WRITE:
         case IOPERFTEST_SEQ_READ:
-            break; /* Nothing to do. */
-
         case IOPERFTEST_REV_WRITE:
         case IOPERFTEST_REV_READ:
+            break; /* Nothing to do. */
+
         case IOPERFTEST_RND_WRITE:
         case IOPERFTEST_RND_READ:
@@ -522,8 +573,7 @@
         case IOPERFTEST_SEQ_WRITE:
         case IOPERFTEST_SEQ_READ:
-            return pJob->Tst.offNextSeq == pJob->cbTestSet;
-
         case IOPERFTEST_REV_WRITE:
         case IOPERFTEST_REV_READ:
+            return pJob->Tst.offNextSeq == pJob->cbTestSet;
         case IOPERFTEST_RND_WRITE:
         case IOPERFTEST_RND_READ:
@@ -564,7 +614,7 @@
                 PIOPERFREQ pReq = &pJob->paIoReqs[cReqsQueued];
                 ioPerfJobTestReqInit(pJob, pReq);
-                rc = RTIoQueueRequestPrepare(pJob->hIoQueue, &pJob->Hnd, pReq->enmOp,
-                                             pReq->offXfer, pReq->pvXfer, pReq->cbXfer, 0 /*fReqFlags*/,
-                                             pReq);
+                RTTESTI_CHECK_RC(RTIoQueueRequestPrepare(pJob->hIoQueue, &pJob->Hnd, pReq->enmOp,
+                                                         pReq->offXfer, pReq->pvXfer, pReq->cbXfer, 0 /*fReqFlags*/,
+                                                         pReq), VINF_SUCCESS);
                 cReqsQueued++;
             }
@@ -573,5 +623,7 @@
             if (   RT_SUCCESS(rc)
                 && cReqsQueued)
-                rc = RTIoQueueCommit(pJob->hIoQueue);
+            {
+                RTTESTI_CHECK_RC(RTIoQueueCommit(pJob->hIoQueue), VINF_SUCCESS);
+            }
 
             /* Enter wait loop and process completed requests. */
@@ -581,6 +633,6 @@
                 uint32_t cCEvtCompleted = 0;
 
-                rc = RTIoQueueEvtWait(pJob->hIoQueue, paIoQCEvt, pJob->cReqsMax, 1 /*cMinWait*/,
-                                      &cCEvtCompleted, 0 /*fFlags*/);
+                RTTESTI_CHECK_RC(RTIoQueueEvtWait(pJob->hIoQueue, paIoQCEvt, pJob->cReqsMax, 1 /*cMinWait*/,
+                                                  &cCEvtCompleted, 0 /*fFlags*/), VINF_SUCCESS);
                 if (RT_SUCCESS(rc))
                 {
@@ -600,7 +652,7 @@
                             {
                                 ioPerfJobTestReqInit(pJob, pReq);
-                                rc = RTIoQueueRequestPrepare(pJob->hIoQueue, &pJob->Hnd, pReq->enmOp,
-                                                             pReq->offXfer, pReq->pvXfer, pReq->cbXfer, 0 /*fReqFlags*/,
-                                                             pReq);
+                                RTTESTI_CHECK_RC(RTIoQueueRequestPrepare(pJob->hIoQueue, &pJob->Hnd, pReq->enmOp,
+                                                                         pReq->offXfer, pReq->pvXfer, pReq->cbXfer, 0 /*fReqFlags*/,
+                                                                         pReq), VINF_SUCCESS);
                                 cReqsThisQueued++;
                             }
@@ -612,5 +664,7 @@
                     if (   cReqsThisQueued
                         && RT_SUCCESS(rc))
-                        rc = RTIoQueueCommit(pJob->hIoQueue);
+                    {
+                        RTTESTI_CHECK_RC(RTIoQueueCommit(pJob->hIoQueue), VINF_SUCCESS);
+                    }
                 }
             }
@@ -780,5 +834,8 @@
             if (RT_LIKELY(pJob->pszFilename))
             {
-                rc = RTFileOpen(&pJob->Hnd.u.hFile, pJob->pszFilename, RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE);
+                uint32_t fOpen = RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE | RTFILE_O_READWRITE | RTFILE_O_ASYNC_IO;
+                if (g_fNoCache)
+                    fOpen |= RTFILE_O_NO_CACHE;
+                rc = RTFileOpen(&pJob->Hnd.u.hFile, pJob->pszFilename, fOpen);
                 if (RT_SUCCESS(rc))
                 {
