DrvDiskIntegrity.cpp revision 2531fa93e6b9dd1b60eac57f360a47e38aaf4d41
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* $Id$ */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @file
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * VBox storage devices: Disk integrity check.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
c58f1213e628a545081c70e26c6b67a841cff880vboxsync/*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Copyright (C) 2006-2010 Oracle Corporation
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync *
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * available from http://www.virtualbox.org. This file is free software;
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * you can redistribute it and/or modify it under the terms of the GNU
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * General Public License (GPL) as published by the Free Software
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
82bcaaf8077ba892f39afb721dca149353c63d2cvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
b6cba2c351e97805b97998ebe48e03ecef16b59avboxsync* Header Files *
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define LOG_GROUP LOG_GROUP_DRV_DISK_INTEGRITY
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/vmm/pdmdrv.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <VBox/vddbg.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/assert.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/string.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/uuid.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/avl.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/mem.h>
3fe24a3690526efc4cceece3819d628caadf3140vboxsync#include <iprt/message.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/sg.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/time.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/semaphore.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include <iprt/asm.h>
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#include "VBoxDD.h"
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/*******************************************************************************
8112e0942f1128329b99b22a20b395963d4abceavboxsync* Structures and Typedefs *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Transfer direction.
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef enum DRVDISKAIOTXDIR
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Read */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DRVDISKAIOTXDIR_READ = 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Write */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DRVDISKAIOTXDIR_WRITE,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Flush */
8112e0942f1128329b99b22a20b395963d4abceavboxsync DRVDISKAIOTXDIR_FLUSH
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} DRVDISKAIOTXDIR;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * async I/O request.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct DRVDISKAIOREQ
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Transfer direction. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DRVDISKAIOTXDIR enmTxDir;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Start offset. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t off;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Transfer size. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbTransfer;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Segment array. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PCRTSGSEG paSeg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Number of array entries. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned cSeg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** User argument */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync void *pvUser;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Slot in the array. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned iSlot;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Start timestamp */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t tsStart;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Completion timestamp. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint64_t tsComplete;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** I/O log entry if configured. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync VDIOLOGENT hIoLogEntry;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync} DRVDISKAIOREQ, *PDRVDISKAIOREQ;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * I/O log entry.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsynctypedef struct IOLOGENT
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Start offset */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint64_t off;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Write size */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbWrite;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Number of references to this entry. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned cRefs;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} IOLOGENT, *PIOLOGENT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Disk segment.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct DRVDISKSEGMENT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** AVL core. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AVLRFOFFNODECORE Core;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Size of the segment */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbSeg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Data for this segment */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint8_t *pbSeg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Number of entries in the I/O array. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned cIoLogEntries;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Array of I/O log references. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PIOLOGENT apIoLog[1];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} DRVDISKSEGMENT, *PDRVDISKSEGMENT;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Active requests list entry.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct DRVDISKAIOREQACTIVE
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer to the request. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync volatile PDRVDISKAIOREQ pIoReq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Start timestamp. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t tsStart;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} DRVDISKAIOREQACTIVE, *PDRVDISKAIOREQACTIVE;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Disk integrity driver instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @implements PDMIMEDIA
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct DRVDISKINTEGRITY
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer driver instance. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMDRVINS pDrvIns;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer to the media driver below us.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * This is NULL if the media is not mounted. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMIMEDIA pDrvMedia;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /** Our media interface */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PDMIMEDIA IMedia;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The media port interface above. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMIMEDIAPORT pDrvMediaPort;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Media port interface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIMEDIAPORT IMediaPort;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Pointer to the media async driver below us.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * This is NULL if the media is not mounted. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMIMEDIAASYNC pDrvMediaAsync;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Our media async interface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIMEDIAASYNC IMediaAsync;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** The async media port interface above. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Our media async port interface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIMEDIAASYNCPORT IMediaAsyncPort;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Flag whether consistency checks are enabled. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fCheckConsistency;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** AVL tree containing the disk blocks to check. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PAVLRFOFFTREE pTreeSegments;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Flag whether async request tracing is enabled. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fTraceRequests;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Interval the thread should check for expired requests (milliseconds). */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync uint32_t uCheckIntervalMs;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Expire timeout for a request (milliseconds). */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t uExpireIntervalMs;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /** Thread which checks for lost requests. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTTHREAD hThread;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Event semaphore */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSEMEVENT SemEvent;
6cd65034f702d9b4122249011835e9639a7bc660vboxsync /** Flag whether the thread should run. */
6cd65034f702d9b4122249011835e9639a7bc660vboxsync bool fRunning;
6cd65034f702d9b4122249011835e9639a7bc660vboxsync /** Array containing active requests. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DRVDISKAIOREQACTIVE apReqActive[128];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Next free slot in the array */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync volatile unsigned iNextFreeSlot;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Flag whether we check for requests completing twice. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fCheckDoubleCompletion;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Number of requests we go back. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned cEntries;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Array of completed but still observed requests. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ *papIoReq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Current entry in the array. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned iEntry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** I/O logger to use if enabled. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync VDIOLOGGER hIoLogger;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync} DRVDISKINTEGRITY, *PDRVDISKINTEGRITY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Allocate a new I/O request.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns New I/O request.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param enmTxDir Transfer direction.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param off Start offset.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param paSeg Segment array.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param cSeg Number of segments.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param cbTransfer Number of bytes to transfer.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pvUser User argument.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic PDRVDISKAIOREQ drvdiskintIoReqAlloc(DRVDISKAIOTXDIR enmTxDir, uint64_t off, PCRTSGSEG paSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned cSeg, size_t cbTransfer, void *pvUser)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)RTMemAlloc(sizeof(DRVDISKAIOREQ));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (RT_LIKELY(pIoReq))
33f7a1bbfb625f3401368928cd5e9317ca04881dvboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->enmTxDir = enmTxDir;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->off = off;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->cbTransfer = cbTransfer;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->paSeg = paSeg;
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync pIoReq->cSeg = cSeg;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoReq->pvUser = pvUser;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoReq->iSlot = 0;
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync pIoReq->tsStart = RTTimeSystemMilliTS();
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->tsComplete = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->hIoLogEntry = NULL;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return pIoReq;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync}
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * Free a async I/O request.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync *
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @returns nothing.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pThis Disk driver.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pIoReq The I/O request to free.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic void drvdiskintIoReqFree(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->fCheckDoubleCompletion)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Search if the I/O request completed already. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync for (unsigned i = 0; i < pThis->cEntries; i++)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (RT_UNLIKELY(pThis->papIoReq[i] == pIoReq))
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTMsgError("Request %#p completed already!\n", pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTMsgError("Start timestamp %llu Completion timestamp %llu (completed after %llu ms)\n",
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pIoReq->tsStart, pIoReq->tsComplete, pIoReq->tsComplete - pIoReq->tsStart);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTAssertDebugBreak();
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoReq->tsComplete = RTTimeSystemMilliTS();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(!pThis->papIoReq[pThis->iEntry]);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->papIoReq[pThis->iEntry] = pIoReq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pThis->papIoReq[pThis->iEntry])
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pThis->papIoReq[pThis->iEntry]);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->papIoReq[pThis->iEntry] = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Record a successful write to the virtual disk.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns VBox status code.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pThis Disk integrity driver instance data.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param paSeg Segment array of the write to record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param cSeg Number of segments.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param off Start offset.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param cbWrite Number of bytes to record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvdiskintWriteRecord(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t off, size_t cbWrite)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbWrite=%u\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis, paSeg, cSeg, off, cbWrite));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Update the segments */
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbLeft = cbWrite;
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTFOFF offCurr = (RTFOFF)off;
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGBUF SgBuf;
8112e0942f1128329b99b22a20b395963d4abceavboxsync PIOLOGENT pIoLogEnt = (PIOLOGENT)RTMemAllocZ(sizeof(IOLOGENT));
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!pIoLogEnt)
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VERR_NO_MEMORY;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoLogEnt->off = off;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoLogEnt->cbWrite = cbWrite;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoLogEnt->cRefs = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (cbLeft)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbRange = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fSet = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned offSeg = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pSeg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Get next segment */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ( !pSeg
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync || offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync cbRange = cbLeft;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange = pSeg->Core.Key - offCurr;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync Assert(cbRange % 512 == 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Create new segment */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbRange / 512]));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pSeg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->Core.Key = offCurr;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->Core.KeyLast = offCurr + (RTFOFF)cbRange - 1;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->cbSeg = cbRange;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->pbSeg = (uint8_t *)RTMemAllocZ(cbRange);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->cIoLogEntries = cbRange / 512;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pSeg->pbSeg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync AssertMsg(fInserted, ("Bug!\n"));
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync fSet = true;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync }
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync }
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync }
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync else
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync fSet = true;
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync offSeg = offCurr - pSeg->Core.Key;
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (fSet)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync AssertPtr(pSeg);
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbCopied = RTSgBufCopyToBuf(&SgBuf, pSeg->pbSeg + offSeg, cbRange);
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(cbCopied == cbRange);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Update the I/O log pointers */
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync Assert(offSeg % 512 == 0);
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(cbRange % 512 == 0);
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (offSeg < cbRange)
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint32_t uSector = offSeg / 512;
8112e0942f1128329b99b22a20b395963d4abceavboxsync PIOLOGENT pIoLogOld = NULL;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync AssertMsg(uSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoLogOld = pSeg->apIoLog[uSector];
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync if (pIoLogOld)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync {
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoLogOld->cRefs--;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync if (!pIoLogOld->cRefs)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync RTMemFree(pIoLogOld);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync }
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync pSeg->apIoLog[uSector] = pIoLogEnt;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoLogEnt->cRefs++;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync offSeg += 512;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync }
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync }
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync else
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync RTSgBufAdvance(&SgBuf, cbRange);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync offCurr += cbRange;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync cbLeft -= cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync/**
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * Verifies a read request.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync *
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * @returns VBox status code.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pThis Disk integrity driver instance data.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * @param paSeg Segment array of the containing the data buffers to verify.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * @param cSeg Number of segments.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * @param off Start offset.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * @param cbWrite Number of bytes to verify.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsyncstatic int drvdiskintReadVerify(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg,
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync uint64_t off, size_t cbRead)
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync{
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync int rc = VINF_SUCCESS;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbRead=%u\n",
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis, paSeg, cSeg, off, cbRead));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(off % 512 == 0);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(cbRead % 512 == 0);
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Compare read data */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync size_t cbLeft = cbRead;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync RTFOFF offCurr = (RTFOFF)off;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync RTSGBUF SgBuf;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync while (cbLeft)
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync {
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync size_t cbRange = 0;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync bool fCmp = false;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync unsigned offSeg = 0;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (!pSeg)
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync {
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync /* Get next segment */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (!pSeg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* No data in the tree for this read. Assume everything is ok. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange = cbLeft;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange = cbLeft;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange = pSeg->Core.Key - offCurr;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync fCmp = true;
8112e0942f1128329b99b22a20b395963d4abceavboxsync offSeg = offCurr - pSeg->Core.Key;
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (fCmp)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGSEG Seg;
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGBUF SgBufCmp;
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbOff = 0;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync Seg.cbSeg = cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync Seg.pvSeg = pSeg->pbSeg + offSeg;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSgBufInit(&SgBufCmp, &Seg, 1);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (RTSgBufCmpEx(&SgBuf, &SgBufCmp, cbRange, &cbOff, true))
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Corrupted disk, print I/O log entry of the last write which accessed this range. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint32_t cSector = (offSeg + cbOff) / 512;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertMsg(cSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTMsgError("Corrupted disk at offset %llu (%u bytes in the current read buffer)!\n",
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync offCurr + cbOff, cbOff);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTMsgError("Last write to this sector started at offset %llu with %u bytes (%u references to this log entry)\n",
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->apIoLog[cSector]->off,
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->apIoLog[cSector]->cbWrite,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->apIoLog[cSector]->cRefs);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTAssertDebugBreak();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufAdvance(&SgBuf, cbRange);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync offCurr += cbRange;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbLeft -= cbRange;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync * Adds a request to the active list.
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync *
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync * @returns nothing.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pThis The driver instance data.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pIoReq The request to add.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic void drvdiskintIoReqAdd(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pThis->iNextFreeSlot];
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(!pReqActive->pIoReq);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pReqActive->tsStart = pIoReq->tsStart;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pReqActive->pIoReq = pIoReq;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->iSlot = pThis->iNextFreeSlot;
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync /* Search for the next one. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (pThis->apReqActive[pThis->iNextFreeSlot].pIoReq)
8112e0942f1128329b99b22a20b395963d4abceavboxsync pThis->iNextFreeSlot = (pThis->iNextFreeSlot+1) % RT_ELEMENTS(pThis->apReqActive);
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync * Removes a request from the active list.
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync *
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync * @returns nothing.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pThis The driver instance data.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pIoReq The request to remove.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic void drvdiskintIoReqRemove(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pIoReq->iSlot];
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(pReqActive->pIoReq == pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync ASMAtomicWriteNullPtr(&pReqActive->pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync}
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * Thread checking for expired requests.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync *
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @returns IPRT status code.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pThread Thread handle.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pvUser Opaque user data.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic int drvdiskIntIoReqExpiredCheck(RTTHREAD pThread, void *pvUser)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKINTEGRITY pThis = (PDRVDISKINTEGRITY)pvUser;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (pThis->fRunning)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = RTSemEventWait(pThis->SemEvent, pThis->uCheckIntervalMs);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!pThis->fRunning)
8112e0942f1128329b99b22a20b395963d4abceavboxsync break;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(rc == VERR_TIMEOUT);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Get current timestamp for comparison. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint64_t tsCurr = RTTimeSystemMilliTS();
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Go through the array and check for expired requests. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[i];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ pIoReq = ASMAtomicReadPtrT(&pReqActive->pIoReq, PDRVDISKAIOREQ);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if ( pIoReq
8112e0942f1128329b99b22a20b395963d4abceavboxsync && (tsCurr > pReqActive->tsStart)
8112e0942f1128329b99b22a20b395963d4abceavboxsync && (tsCurr - pReqActive->tsStart) >= pThis->uExpireIntervalMs)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTMsgError("Request %#p expired (active for %llu ms already)\n",
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq, tsCurr - pReqActive->tsStart);
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTAssertDebugBreak();
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/* -=-=-=-=- IMedia -=-=-=-=- */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Makes a PDRVDISKINTEGRITY out of a PPDMIMEDIA. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY)((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMedia)) )
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Makes a PDRVDISKINTEGRITY out of a PPDMIMEDIAASYNC. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY)((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaAsync)) )
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Media interface methods *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnRead */
874be5c5b701726b68fa1391022ae2f5c7768894vboxsyncstatic DECLCALLBACK(int) drvdiskintRead(PPDMIMEDIA pInterface,
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync uint64_t off, void *pvBuf, size_t cbRead)
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync VDIOLOGENT hIoLogEntry;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->hIoLogger)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGTXDIR_READ, off,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbRead, NULL, &hIoLogEntry);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertRC(rc);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, off, pvBuf, cbRead);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->hIoLogger)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSGSEG Seg;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSGBUF SgBuf;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Seg.pvSeg = pvBuf;
8112e0942f1128329b99b22a20b395963d4abceavboxsync Seg.cbSeg = cbRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, &Seg, 1);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, &SgBuf);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Verify the read. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGSEG Seg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.cbSeg = cbRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.pvSeg = pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/** @copydoc PDMIMEDIA::pfnWrite */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvdiskintWrite(PPDMIMEDIA pInterface,
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint64_t off, const void *pvBuf,
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbWrite)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync VDIOLOGENT hIoLogEntry;
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pThis->hIoLogger)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGSEG Seg;
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGBUF SgBuf;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Seg.pvSeg = (void *)pvBuf;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Seg.cbSeg = cbWrite;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSgBufInit(&SgBuf, &Seg, 1);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGTXDIR_WRITE, off,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbWrite, &SgBuf, &hIoLogEntry);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertRC(rc);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = pThis->pDrvMedia->pfnWrite(pThis->pDrvMedia, off, pvBuf, cbWrite);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->hIoLogger)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertRC(rc2);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (RT_FAILURE(rc))
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pThis->fCheckConsistency)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Record the write. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSGSEG Seg;
8112e0942f1128329b99b22a20b395963d4abceavboxsync Seg.cbSeg = cbWrite;
8112e0942f1128329b99b22a20b395963d4abceavboxsync Seg.pvSeg = (void *)pvBuf;
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite);
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PCRTSGSEG paSeg, unsigned cSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbRead, void *pvUser)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d pvUser=%#p\n", __FUNCTION__,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uOffset, paSeg, cSeg, cbRead, pvUser));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_READ, uOffset, paSeg, cSeg, cbRead, pvUser);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertPtr(pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->fTraceRequests)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->hIoLogger)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync int rc2 = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGTXDIR_READ, uOffset,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead, NULL, &pIoReq->hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Verify the read now. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = drvdiskintReadVerify(pThis, paSeg, cSeg, uOffset, cbRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGBUF SgBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, &SgBuf);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PCRTSGSEG paSeg, unsigned cSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbWrite, void *pvUser)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n", __FUNCTION__,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uOffset, paSeg, cSeg, cbWrite, pvUser));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_WRITE, uOffset, paSeg, cSeg, cbWrite, pvUser);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtr(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGBUF SgBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGTXDIR_WRITE, uOffset,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbWrite, &SgBuf, &pIoReq->hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbWrite, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Record the write. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIAASYNC::pfnStartFlush */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintStartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_FLUSH, 0, NULL, 0, 0, pvUser);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtr(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGTXDIR_FLUSH, 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0, NULL, &pIoReq->hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pThis->pDrvMediaAsync->pfnStartFlush(pThis->pDrvMediaAsync, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintFlush(PPDMIMEDIA pInterface)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync VDIOLOGENT hIoLogEntry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
c0b47c53336892431c7a2d8666600ffed91c11f1vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGTXDIR_FLUSH, 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0, NULL, &hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pThis->pDrvMedia->pfnFlush(pThis->pDrvMedia);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync }
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
87d9823b393efbc674b3f3b0ff96998ca89e89b7vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(uint64_t) drvdiskintGetSize(PPDMIMEDIA pInterface)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsyncstatic DECLCALLBACK(bool) drvdiskintIsReadOnly(PPDMIMEDIA pInterface)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnIsReadOnly(pThis->pDrvMedia);
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnBiosGetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnBiosSetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnBiosGetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PCPDMMEDIAGEOMETRY pLCHSGeometry)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnBiosSetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMedia->pfnGetUuid(pThis->pDrvMedia, pUuid);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/* -=-=-=-=- IMediaAsyncPort -=-=-=-=- */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/** Makes a PDRVBLOCKASYNC out of a PPDMIMEDIAASYNCPORT. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync#define PDMIMEDIAASYNCPORT_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaAsyncPort))) )
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic DECLCALLBACK(int) drvdiskintAsyncTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNCPORT_2_DRVDISKINTEGRITY(pInterface);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)pvUser;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync int rc = VINF_SUCCESS;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync LogFlowFunc(("pIoReq=%#p\n", pIoReq));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Remove from the active list. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->fTraceRequests)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (RT_SUCCESS(rcReq) && pThis->fCheckConsistency)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = drvdiskintReadVerify(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = drvdiskintWriteRecord(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync else
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertMsg(pIoReq->enmTxDir == DRVDISKAIOTXDIR_FLUSH, ("Huh?\n"));
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync if (pThis->hIoLogger)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSGBUF SgBuf;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTSgBufInit(&SgBuf, pIoReq->paSeg, pIoReq->cSeg);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, rc, &SgBuf);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc2);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync void *pvUserComplete = pIoReq->pvUser;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync drvdiskintIoReqFree(pThis, pIoReq);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvUserComplete, rcReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync return rc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync}
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/* -=-=-=-=- IMediaPort -=-=-=-=- */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/** Makes a PDRVBLOCK out of a PPDMIMEDIAPORT. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync#define PDMIMEDIAPORT_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaPort))) )
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation}
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic DECLCALLBACK(int) drvdiskintQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint32_t *piInstance, uint32_t *piLUN)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAPORT_2_DRVDISKINTEGRITY(pInterface);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return pThis->pDrvMediaPort->pfnQueryDeviceLocation(pThis->pDrvMediaPort, ppcszController,
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync piInstance, piLUN);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/* -=-=-=-=- IBase -=-=-=-=- */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/**
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic DECLCALLBACK(void *) drvdiskintQueryInterface(PPDMIBASE pInterface, const char *pszIID)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->pDrvMediaAsync ? &pThis->IMediaAsync : NULL);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, &pThis->IMediaAsyncPort);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IMediaPort);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return NULL;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/* -=-=-=-=- driver interface -=-=-=-=- */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic int drvdiskintTreeDestroy(PAVLRFOFFNODECORE pNode, void *pvUser)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)pNode;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pSeg->pbSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc FNPDMDRVDESTRUCT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void) drvdiskintDestruct(PPDMDRVINS pDrvIns)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->pTreeSegments)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTAvlrFileOffsetDestroy(pThis->pTreeSegments, drvdiskintTreeDestroy, NULL);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pThis->pTreeSegments);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->fRunning = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSemEventSignal(pThis->SemEvent);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSemEventDestroy(pThis->SemEvent);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckDoubleCompletion)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Free all requests */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (pThis->papIoReq[pThis->iEntry])
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pThis->papIoReq[pThis->iEntry]);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->papIoReq[pThis->iEntry] = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->hIoLogger)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync VDDbgIoLogDestroy(pThis->hIoLogger);
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Construct a disk integrity driver instance.
8112e0942f1128329b99b22a20b395963d4abceavboxsync *
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @copydoc FNPDMDRVCONSTRUCT
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance));
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /*
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Validate configuration.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "TraceRequests\0"
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync "CheckIntervalMs\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "ExpireIntervalMs\0"
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync "CheckDoubleCompletions\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "HistorySize\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "IoLog\0"))
8112e0942f1128329b99b22a20b395963d4abceavboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CheckDoubleCompletions", &pThis->fCheckDoubleCompletion, false);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertRC(rc);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = CFGMR3QueryU32Def(pCfg, "HistorySize", &pThis->cEntries, 512);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync char *pszIoLogFilename = NULL;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = CFGMR3QueryStringAlloc(pCfg, "IoLog", &pszIoLogFilename);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_CFGM_VALUE_NOT_FOUND);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /*
fdd17dc68230654ee0796918863927fca10a9f0avboxsync * Initialize most of the data members.
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->pDrvIns = pDrvIns;
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IBase. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pDrvIns->IBase.pfnQueryInterface = drvdiskintQueryInterface;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IMedia */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnRead = drvdiskintRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnWrite = drvdiskintWrite;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnFlush = drvdiskintFlush;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnGetSize = drvdiskintGetSize;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnIsReadOnly = drvdiskintIsReadOnly;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvdiskintBiosGetPCHSGeometry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvdiskintBiosSetPCHSGeometry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvdiskintBiosGetLCHSGeometry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvdiskintBiosSetLCHSGeometry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnGetUuid = drvdiskintGetUuid;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IMediaAsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMediaAsync.pfnStartRead = drvdiskintStartRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMediaAsync.pfnStartWrite = drvdiskintStartWrite;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMediaAsync.pfnStartFlush = drvdiskintStartFlush;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* IMediaAsyncPort. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->IMediaAsyncPort.pfnTransferCompleteNotify = drvdiskintAsyncTransferCompleteNotify;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IMediaPort. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMediaPort.pfnQueryDeviceLocation = drvdiskintQueryDeviceLocation;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
3fe24a3690526efc4cceece3819d628caadf3140vboxsync /* Query the media port interface above us. */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
3fe24a3690526efc4cceece3819d628caadf3140vboxsync if (!pThis->pDrvMediaPort)
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
3fe24a3690526efc4cceece3819d628caadf3140vboxsync N_("No media port inrerface above"));
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* Try to attach async media port interface above.*/
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Try attach driver below and query it's media interface.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMIBASE pBase;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync N_("Failed to attach driver below us! %Rrc"), rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pThis->pDrvMedia)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync N_("No media or async media interface below"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Create the AVL tree. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pThis->pTreeSegments)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VERR_NO_MEMORY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->apReqActive[i].pIoReq = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->apReqActive[i].tsStart = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->iNextFreeSlot = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Init event semaphore. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = RTSemEventCreate(&pThis->SemEvent);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->fRunning = true;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = RTThreadCreate(&pThis->hThread, drvdiskIntIoReqExpiredCheck, pThis,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0, RTTHREADTYPE_INFREQUENT_POLLER, 0, "DiskIntegrity");
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckDoubleCompletion)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->iEntry = 0;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->papIoReq = (PDRVDISKAIOREQ *)RTMemAllocZ(pThis->cEntries * sizeof(PDRVDISKAIOREQ));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertPtr(pThis->papIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pszIoLogFilename)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogCreate(&pThis->hIoLogger, pszIoLogFilename, VDDBG_IOLOG_LOG_DATA);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTStrFree(pszIoLogFilename);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync return rc;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Block driver registration record.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncconst PDMDRVREG g_DrvDiskIntegrity =
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync{
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* u32Version */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_DRVREG_VERSION,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szName */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "DiskIntegrity",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szRCMod */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* szR0Mod */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pszDescription */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync "Disk integrity driver.",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fFlags */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* fClass. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_DRVREG_CLASS_BLOCK,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cMaxInstances */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync ~0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* cbInstance */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync sizeof(DRVDISKINTEGRITY),
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnConstruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintConstruct,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDestruct */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintDestruct,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnRelocate */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnIOCtl */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnPowerOn */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync NULL,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* pfnReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnSuspend */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync NULL,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* pfnResume */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnAttach */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnDetach */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnPowerOff */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnSoftReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync /* u32EndVersion */
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync PDM_DRVREG_VERSION
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync};
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync