Changeset 28902 in vbox
- Timestamp:
- Apr 29, 2010 2:54:08 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvDiskIntegrity.cpp
r28800 r28902 29 29 #include <iprt/message.h> 30 30 #include <iprt/sg.h> 31 #include <iprt/time.h> 32 #include <iprt/semaphore.h> 31 33 32 34 #include "Builtins.h" … … 54 56 /** User argument */ 55 57 void *pvUser; 58 /** Slot in the array. */ 59 unsigned iSlot; 56 60 } DRVDISKAIOREQ, *PDRVDISKAIOREQ; 57 61 … … 87 91 88 92 /** 93 * Active requests list entry. 94 */ 95 typedef struct DRVDISKAIOREQACTIVE 96 { 97 /** Pointer to the request. */ 98 volatile PDRVDISKAIOREQ pIoReq; 99 /** Start timestamp. */ 100 uint64_t tsStart; 101 } DRVDISKAIOREQACTIVE, *PDRVDISKAIOREQACTIVE; 102 103 /** 89 104 * Disk integrity driver instance data. 90 105 * … … 112 127 PDMIMEDIAASYNCPORT IMediaAsyncPort; 113 128 129 /** Flag whether consistency checks are enabled. */ 130 bool fCheckConsistency; 114 131 /** AVL tree containing the disk blocks to check. */ 115 132 PAVLRFOFFTREE pTreeSegments; 133 134 /** Flag whether async request tracing is enabled. */ 135 bool fTraceRequests; 136 /** Interval the thread should check for expired requests (milliseconds). */ 137 uint32_t uCheckIntervalMs; 138 /** Expire timeout for a request (milliseconds). */ 139 uint32_t uExpireIntervalMs; 140 /** Thread which checks for lost requests. */ 141 RTTHREAD hThread; 142 /** Event semaphore */ 143 RTSEMEVENT SemEvent; 144 /** Flag whether the thread should run. */ 145 bool fRunning; 146 /** Array containing active requests. */ 147 DRVDISKAIOREQACTIVE apReqActive[128]; 148 /** Next free slot in the array */ 149 volatile unsigned iNextFreeSlot; 116 150 } DRVDISKINTEGRITY, *PDRVDISKINTEGRITY; 117 151 … … 354 388 } 355 389 390 /** 391 * Adds a request to the active list. 392 * 393 * @returns nothing. 394 * @param pThis The driver instance data. 395 * @param pIoReq The request to add. 396 */ 397 static void drvdiskintIoReqAdd(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq) 398 { 399 PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pThis->iNextFreeSlot]; 400 401 Assert(!pReqActive->pIoReq); 402 pReqActive->tsStart = RTTimeSystemMilliTS(); 403 pReqActive->pIoReq = pIoReq; 404 pIoReq->iSlot = pThis->iNextFreeSlot; 405 406 /* Search for the next one. */ 407 pThis->iNextFreeSlot++; 408 while (pThis->apReqActive[pThis->iNextFreeSlot].pIoReq) 409 pThis->iNextFreeSlot = pThis->iNextFreeSlot++ % RT_ELEMENTS(pThis->apReqActive); 410 } 411 412 /** 413 * Removes a request from the active list. 414 * 415 * @returns nothing. 416 * @param pThis The driver instance data. 417 * @param pIoReq The request to remove. 418 */ 419 static void drvdiskintIoReqRemove(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq) 420 { 421 PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pIoReq->iSlot]; 422 423 Assert(pReqActive->pIoReq == pIoReq); 424 425 ASMAtomicXchgPtr((void * volatile *)&pReqActive->pIoReq, NULL); 426 } 427 428 /** 429 * Thread checking for expired requests. 430 * 431 * @returns IPRT status code. 432 * @param pThread Thread handle. 433 * @param pvUser Opaque user data. 434 */ 435 static int drvdiskIntIoReqExpiredCheck(RTTHREAD pThread, void *pvUser) 436 { 437 PDRVDISKINTEGRITY pThis = (PDRVDISKINTEGRITY)pvUser; 438 439 while (pThis->fRunning) 440 { 441 int rc = RTSemEventWait(pThis->SemEvent, pThis->uCheckIntervalMs); 442 443 if (!pThis->fRunning) 444 break; 445 446 Assert(rc == VERR_TIMEOUT); 447 448 /* Get current timestamp for comparison. */ 449 uint64_t tsCurr = RTTimeSystemMilliTS(); 450 451 /* Go through the array and check for expired requests. */ 452 for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++) 453 { 454 PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[i]; 455 PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)ASMAtomicReadPtr((void * volatile *)&pReqActive->pIoReq); 456 457 if ( pIoReq 458 && (tsCurr - pReqActive->tsStart) >= pThis->uExpireIntervalMs) 459 { 460 RTMsgError("Request %#p expired (active for %llu ms already)\n", 461 pIoReq, tsCurr - pReqActive->tsStart); 462 RTAssertDebugBreak(); 463 } 464 } 465 } 466 467 return VINF_SUCCESS; 468 } 469 356 470 /* -=-=-=-=- IMedia -=-=-=-=- */ 357 471 … … 374 488 return rc; 375 489 376 /* Verify the read. */ 377 RTSGSEG Seg; 378 Seg.cbSeg = cbRead; 379 Seg.pvSeg = pvBuf; 380 return drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead); 490 if (pThis->fCheckConsistency) 491 { 492 /* Verify the read. */ 493 RTSGSEG Seg; 494 Seg.cbSeg = cbRead; 495 Seg.pvSeg = pvBuf; 496 rc = drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead); 497 } 498 499 return rc; 381 500 } 382 501 … … 391 510 return rc; 392 511 393 /* Record the write. */ 394 RTSGSEG Seg; 395 Seg.cbSeg = cbWrite; 396 Seg.pvSeg = (void *)pvBuf; 397 return drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite); 512 if (pThis->fCheckConsistency) 513 { 514 /* Record the write. */ 515 RTSGSEG Seg; 516 Seg.cbSeg = cbWrite; 517 Seg.pvSeg = (void *)pvBuf; 518 rc = drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite); 519 } 520 521 return rc; 398 522 } 399 523 … … 408 532 AssertPtr(pIoReq); 409 533 534 if (pThis->fTraceRequests) 535 drvdiskintIoReqAdd(pThis, pIoReq); 536 410 537 int rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg, 411 538 cbRead, pIoReq); … … 413 540 { 414 541 /* Verify the read now. */ 415 int rc2 = drvdiskintReadVerify(pThis, paSeg, cSeg, uOffset, cbRead); 416 AssertRC(rc2); 542 if (pThis->fCheckConsistency) 543 { 544 int rc2 = drvdiskintReadVerify(pThis, paSeg, cSeg, uOffset, cbRead); 545 AssertRC(rc2); 546 } 547 548 if (pThis->fTraceRequests) 549 drvdiskintIoReqRemove(pThis, pIoReq); 417 550 RTMemFree(pIoReq); 418 551 } … … 434 567 AssertPtr(pIoReq); 435 568 569 if (pThis->fTraceRequests) 570 drvdiskintIoReqAdd(pThis, pIoReq); 571 436 572 int rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg, 437 573 cbWrite, pIoReq); … … 439 575 { 440 576 /* Verify the read now. */ 441 int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite); 442 AssertRC(rc2); 577 if (pThis->fCheckConsistency) 578 { 579 int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite); 580 AssertRC(rc2); 581 } 582 583 if (pThis->fTraceRequests) 584 drvdiskintIoReqRemove(pThis, pIoReq); 585 443 586 RTMemFree(pIoReq); 444 587 } … … 523 666 LogFlowFunc(("pIoReq=%#p\n", pIoReq)); 524 667 525 if (RT_SUCCESS(rcReq)) 668 /* Remove from the active list. */ 669 if (pThis->fTraceRequests) 670 drvdiskintIoReqRemove(pThis, pIoReq); 671 672 if (RT_SUCCESS(rcReq) && pThis->fCheckConsistency) 526 673 { 527 674 if (pIoReq->fRead) … … 580 727 RTMemFree(pThis->pTreeSegments); 581 728 } 729 730 if (pThis->fTraceRequests) 731 { 732 pThis->fRunning = false; 733 RTSemEventSignal(pThis->SemEvent); 734 RTSemEventDestroy(pThis->SemEvent); 735 } 582 736 } 583 737 … … 589 743 static DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 590 744 { 745 int rc = VINF_SUCCESS; 591 746 PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY); 592 747 LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance)); … … 596 751 * Validate configuration. 597 752 */ 598 if (!CFGMR3AreValuesValid(pCfg, "")) 753 if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0" 754 "TraceRequests\0" 755 "CheckIntervalMs\0" 756 "ExpireIntervalMs\0")) 599 757 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; 758 759 rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false); 760 AssertRC(rc); 761 rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false); 762 AssertRC(rc); 763 rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */ 764 AssertRC(rc); 765 rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */ 766 AssertRC(rc); 600 767 601 768 /* … … 630 797 */ 631 798 PPDMIBASE pBase; 632 intrc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);799 rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase); 633 800 if (RT_FAILURE(rc)) 634 801 return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, 635 N_("Failed to attach driver below us! %Rr f"), rc);802 N_("Failed to attach driver below us! %Rrc"), rc); 636 803 637 804 pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA); … … 645 812 pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT); 646 813 647 /* Create the AVL tree. */ 648 pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE)); 649 if (!pThis->pTreeSegments) 650 rc = VERR_NO_MEMORY; 814 if (pThis->fCheckConsistency) 815 { 816 /* Create the AVL tree. */ 817 pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE)); 818 if (!pThis->pTreeSegments) 819 rc = VERR_NO_MEMORY; 820 } 821 822 if (pThis->fTraceRequests) 823 { 824 for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++) 825 { 826 pThis->apReqActive[i].pIoReq = NULL; 827 pThis->apReqActive[i].tsStart = 0; 828 } 829 830 pThis->iNextFreeSlot = 0; 831 832 /* Init event semaphore. */ 833 rc = RTSemEventCreate(&pThis->SemEvent); 834 AssertRC(rc); 835 pThis->fRunning = true; 836 rc = RTThreadCreate(&pThis->hThread, drvdiskIntIoReqExpiredCheck, pThis, 837 0, RTTHREADTYPE_INFREQUENT_POLLER, 0, "DiskIntegrity"); 838 AssertRC(rc); 839 } 651 840 652 841 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.