Index: trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp
===================================================================
--- trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp	(revision 80220)
+++ trunk/src/VBox/ValidationKit/utils/storage/IoPerf.cpp	(revision 80221)
@@ -191,4 +191,6 @@
     /** Chance in percent to get a write. */
     unsigned                    uWriteChance;
+    /** Flag whether to verify read data. */
+    bool                        fVerifyReads;
     /** Start timestamp. */
     uint64_t                    tsStart;
@@ -199,5 +201,5 @@
     /** Index of the next free statistics record to use. */
     uint32_t                    idxReqStatNext;
-    /** Array of request statisc records for the whole test. */
+    /** Array of request statistic records for the whole test. */
     PIOPERFREQSTAT              paReqStats;
     /** Test dependent data. */
@@ -276,4 +278,5 @@
     { "--block-size",               'b',                            RTGETOPT_REQ_UINT32  },
     { "--maximum-requests",         'm',                            RTGETOPT_REQ_UINT32  },
+    { "--verify-reads",             'y',                            RTGETOPT_REQ_BOOL    },
 
     { "--first-write",              kCmdOpt_FirstWrite,             RTGETOPT_REQ_NOTHING },
@@ -320,4 +323,6 @@
 /** Write chance for mixed read/write tests. */
 static unsigned     g_uWriteChance = 50;
+/** Flag whether to verify read data. */
+static bool         g_fVerifyReads = true;
 
 /** @name Configured tests, this must match the IOPERFTEST order.
@@ -741,4 +746,17 @@
                                 pReq->pStats->tsComplete = RTTimeNanoTS();
 
+                            if (   pJob->fVerifyReads
+                                && pReq->enmOp == RTIOQUEUEOP_READ)
+                            {
+                                const void *pvBuf = ioPerfJobTestGetWriteBufForOffset(pJob, pReq->offXfer);
+                                if (memcmp(pReq->pvXferRead, pvBuf, pReq->cbXfer))
+                                {
+                                    if (g_uVerbosity > 1)
+                                        RTTestIFailed("IoPerf: Corrupted data detected by read at offset %#llu (sz: %zu)", pReq->offXfer, pReq->cbXfer);
+                                    else
+                                        RTTestIErrorInc();
+                                }
+                            }
+
                             if (!ioPerfJobTestIsDone(pJob))
                             {
@@ -951,4 +969,5 @@
  * @param   cReqsMax            Maximum number of concurrent requests for this job.
  * @param   uWriteChance        The write chance for mixed read/write tests.
+ * @param   fVerifyReads        Flag whether to verify read data.
  */
 static int ioPerfJobInit(PIOPERFJOB pJob, PIOPERFMASTER pMaster, uint32_t idJob,
@@ -956,5 +975,5 @@
                          IOPERFTESTSETPREP enmPrepMethod,
                          uint64_t cbTestSet, size_t cbIoBlock, uint32_t cReqsMax,
-                         unsigned uWriteChance)
+                         unsigned uWriteChance, bool fVerifyReads)
 {
     pJob->pMaster        = pMaster;
@@ -968,4 +987,5 @@
     pJob->cbIoReqReadBuf = cReqsMax * cbIoBlock;
     pJob->uWriteChance   = uWriteChance;
+    pJob->fVerifyReads   = fVerifyReads;
     pJob->cReqStats      = (uint32_t)(pJob->cbTestSet / pJob->cbIoBlock + ((pJob->cbTestSet % pJob->cbIoBlock) ? 1 : 0));
     pJob->idxReqStatNext = 0;
@@ -1117,5 +1137,5 @@
                            g_szDir, IOPERFTESTSETPREP_SET_SZ,
                            g_cbTestSet, g_cbIoBlock, g_cReqsMax,
-                           g_uWriteChance);
+                           g_uWriteChance, g_fVerifyReads);
     if (RT_SUCCESS(rc))
     {
@@ -1162,4 +1182,5 @@
             case 'd':                           pszHelp = "The directory to use for testing.            default: CWD/fstestdir"; break;
             case 'r':                           pszHelp = "Don't abspath test dir (good for deep dirs). default: disabled"; break;
+            case 'y':                           pszHelp = "Flag whether to verify read data.            default: enabled"; break;
             case 'v':                           pszHelp = "More verbose execution."; break;
             case 'q':                           pszHelp = "Quiet execution."; break;
@@ -1238,4 +1259,63 @@
                 break;
 
+            case 'y':
+                g_fVerifyReads = ValueUnion.f;
+                break;
+
+            case kCmdOpt_FirstWrite:
+                g_aenmTests[IOPERFTEST_FIRST_WRITE] = IOPERFTEST_FIRST_WRITE;
+                break;
+            case kCmdOpt_NoFirstWrite:
+                g_aenmTests[IOPERFTEST_FIRST_WRITE] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_SeqRead:
+                g_aenmTests[IOPERFTEST_SEQ_READ] = IOPERFTEST_SEQ_READ;
+                break;
+            case kCmdOpt_NoSeqRead:
+                g_aenmTests[IOPERFTEST_SEQ_READ] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_SeqWrite:
+                g_aenmTests[IOPERFTEST_SEQ_WRITE] = IOPERFTEST_SEQ_WRITE;
+                break;
+            case kCmdOpt_NoSeqWrite:
+                g_aenmTests[IOPERFTEST_SEQ_WRITE] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_RndRead:
+                g_aenmTests[IOPERFTEST_RND_READ] = IOPERFTEST_RND_READ;
+                break;
+            case kCmdOpt_NoRndRead:
+                g_aenmTests[IOPERFTEST_RND_READ] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_RndWrite:
+                g_aenmTests[IOPERFTEST_RND_WRITE] = IOPERFTEST_RND_WRITE;
+                break;
+            case kCmdOpt_NoRndWrite:
+                g_aenmTests[IOPERFTEST_RND_WRITE] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_RevRead:
+                g_aenmTests[IOPERFTEST_REV_READ] = IOPERFTEST_REV_READ;
+                break;
+            case kCmdOpt_NoRevRead:
+                g_aenmTests[IOPERFTEST_REV_READ] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_RevWrite:
+                g_aenmTests[IOPERFTEST_REV_WRITE] = IOPERFTEST_REV_WRITE;
+                break;
+            case kCmdOpt_NoRevWrite:
+                g_aenmTests[IOPERFTEST_REV_WRITE] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_SeqReadWrite:
+                g_aenmTests[IOPERFTEST_SEQ_READWRITE] = IOPERFTEST_SEQ_READWRITE;
+                break;
+            case kCmdOpt_NoSeqReadWrite:
+                g_aenmTests[IOPERFTEST_SEQ_READWRITE] = IOPERFTEST_DISABLED;
+                break;
+            case kCmdOpt_RndReadWrite:
+                g_aenmTests[IOPERFTEST_RND_READWRITE] = IOPERFTEST_RND_READWRITE;
+                break;
+            case kCmdOpt_NoRndReadWrite:
+                g_aenmTests[IOPERFTEST_RND_READWRITE] = IOPERFTEST_DISABLED;
+                break;
+
             case 'q':
                 g_uVerbosity = 0;
