DrvDiskIntegrity.cpp revision 4baafe1fca22c5d6994633d8a00278ddc4d734f1
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 /** Discard */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync DRVDISKAIOTXDIR_DISCARD
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;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Start timestamp */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint64_t tsStart;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Completion timestamp. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint64_t tsComplete;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** I/O log entry if configured. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync VDIOLOGENT hIoLogEntry;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Ranges to discard. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PCRTRANGE paRanges;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Number of ranges. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync unsigned cRanges;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync} DRVDISKAIOREQ, *PDRVDISKAIOREQ;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * I/O log entry.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsynctypedef struct IOLOGENT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Start offset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t off;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** 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
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /** 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;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Our media interface */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 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;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /** AVL tree containing the disk blocks to check. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PAVLRFOFFTREE pTreeSegments;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /** Flag whether async request tracing is enabled. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync bool fTraceRequests;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /** Interval the thread should check for expired requests (milliseconds). */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint32_t uCheckIntervalMs;
6cd65034f702d9b4122249011835e9639a7bc660vboxsync /** Expire timeout for a request (milliseconds). */
6cd65034f702d9b4122249011835e9639a7bc660vboxsync uint32_t uExpireIntervalMs;
6cd65034f702d9b4122249011835e9639a7bc660vboxsync /** Thread which checks for lost requests. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTTHREAD hThread;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Event semaphore */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSEMEVENT SemEvent;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** Flag whether the thread should run. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fRunning;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /** 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
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Allocate a new I/O request.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @returns New I/O request.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param enmTxDir Transfer direction.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param off Start offset.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param paSeg Segment array.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param cSeg Number of segments.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param cbTransfer Number of bytes to transfer.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @param pvUser User argument.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
33f7a1bbfb625f3401368928cd5e9317ca04881dvboxsyncstatic PDRVDISKAIOREQ drvdiskintIoReqAlloc(DRVDISKAIOTXDIR enmTxDir, uint64_t off, PCRTSGSEG paSeg,
8112e0942f1128329b99b22a20b395963d4abceavboxsync unsigned cSeg, size_t cbTransfer, void *pvUser)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)RTMemAlloc(sizeof(DRVDISKAIOREQ));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync if (RT_LIKELY(pIoReq))
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync {
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoReq->enmTxDir = enmTxDir;
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync pIoReq->off = off;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->cbTransfer = cbTransfer;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->paSeg = paSeg;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->cSeg = cSeg;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->pvUser = pvUser;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync pIoReq->iSlot = 0;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pIoReq->tsStart = RTTimeSystemMilliTS();
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pIoReq->tsComplete = 0;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pIoReq->hIoLogEntry = NULL;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync 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 */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic void drvdiskintIoReqFree(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->fCheckDoubleCompletion)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
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))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMsgError("Request %#p completed already!\n", pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMsgError("Start timestamp %llu Completion timestamp %llu (completed after %llu ms)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoReq->tsStart, pIoReq->tsComplete, pIoReq->tsComplete - pIoReq->tsStart);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTAssertDebugBreak();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoReq->tsComplete = RTTimeSystemMilliTS();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(!pThis->papIoReq[pThis->iEntry]);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->papIoReq[pThis->iEntry] = pIoReq;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->papIoReq[pThis->iEntry])
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTMemFree(pThis->papIoReq[pThis->iEntry]);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->papIoReq[pThis->iEntry] = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void drvdiskintIoLogEntryRelease(PIOLOGENT pIoLogEnt)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoLogEnt->cRefs--;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pIoLogEnt->cRefs)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoLogEnt);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Record a successful write to the virtual disk.
8112e0942f1128329b99b22a20b395963d4abceavboxsync *
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @returns VBox status code.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pThis Disk integrity driver instance data.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param paSeg Segment array of the write to record.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param cSeg Number of segments.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param off Start offset.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param cbWrite Number of bytes to record.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic int drvdiskintWriteRecord(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg,
8112e0942f1128329b99b22a20b395963d4abceavboxsync uint64_t off, size_t cbWrite)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc = VINF_SUCCESS;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
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;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGBUF SgBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PIOLOGENT pIoLogEnt = (PIOLOGENT)RTMemAllocZ(sizeof(IOLOGENT));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pIoLogEnt)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VERR_NO_MEMORY;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoLogEnt->off = off;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoLogEnt->cbWrite = cbWrite;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoLogEnt->cRefs = 0;
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync while (cbLeft)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbRange = 0;
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync bool fSet = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned offSeg = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pSeg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Get next segment */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ( !pSeg
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync || offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange = cbLeft;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange = pSeg->Core.Key - offCurr;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(cbRange % 512 == 0);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Create new segment */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pSeg = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbRange / 512]));
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync if (pSeg)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync {
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pSeg->Core.Key = offCurr;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pSeg->Core.KeyLast = offCurr + (RTFOFF)cbRange - 1;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pSeg->cbSeg = cbRange;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->pbSeg = (uint8_t *)RTMemAllocZ(cbRange);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->cIoLogEntries = cbRange / 512;
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync if (!pSeg->pbSeg)
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTMemFree(pSeg);
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertMsg(fInserted, ("Bug!\n"));
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync fSet = true;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync fSet = true;
8112e0942f1128329b99b22a20b395963d4abceavboxsync offSeg = offCurr - pSeg->Core.Key;
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (fSet)
500d759609a43a472c7a29b58f3479ed319a5a76vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertPtr(pSeg);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync size_t cbCopied = RTSgBufCopyToBuf(&SgBuf, pSeg->pbSeg + offSeg, cbRange);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync Assert(cbCopied == cbRange);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync /* Update the I/O log pointers */
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync Assert(offSeg % 512 == 0);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync Assert(cbRange % 512 == 0);
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync while (offSeg < cbRange)
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync {
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync uint32_t uSector = offSeg / 512;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync PIOLOGENT pIoLogOld = NULL;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync AssertMsg(uSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoLogOld = pSeg->apIoLog[uSector];
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync if (pIoLogOld)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync {
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync pIoLogOld->cRefs--;
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync if (!pIoLogOld->cRefs)
0e3950d85821ff3f0f9191f7bf0efe7b3510a808vboxsync RTMemFree(pIoLogOld);
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->apIoLog[uSector] = pIoLogEnt;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoLogEnt->cRefs++;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync offSeg += 512;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync }
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync }
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync else
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSgBufAdvance(&SgBuf, cbRange);
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync offCurr += cbRange;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync cbLeft -= cbRange;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync return rc;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync}
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * Verifies a read request.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync *
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @returns VBox status code.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pThis Disk integrity driver instance data.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param paSeg Segment array of the containing the data buffers to verify.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param cSeg Number of segments.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync * @param off Start offset.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param cbWrite Number of bytes to verify.
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync */
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsyncstatic int drvdiskintReadVerify(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg,
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync uint64_t off, size_t cbRead)
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync int rc = VINF_SUCCESS;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbRead=%u\n",
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync pThis, paSeg, cSeg, off, cbRead));
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync Assert(off % 512 == 0);
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync Assert(cbRead % 512 == 0);
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Compare read data */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync size_t cbLeft = cbRead;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync RTFOFF offCurr = (RTFOFF)off;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync RTSGBUF SgBuf;
37b83e04cd69f1fdddc315640acef2cdfddb0f46vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync while (cbLeft)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbRange = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fCmp = false;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync unsigned offSeg = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pSeg)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Get next segment */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!pSeg)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* No data in the tree for this read. Assume everything is ok. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbRange = cbLeft;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync else if (offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbRange = cbLeft;
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbRange = pSeg->Core.Key - offCurr;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync fCmp = true;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync offSeg = offCurr - pSeg->Core.Key;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (fCmp)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSGSEG Seg;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSGBUF SgBufCmp;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync size_t cbOff = 0;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Seg.cbSeg = cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync Seg.pvSeg = pSeg->pbSeg + offSeg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBufCmp, &Seg, 1);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RTSgBufCmpEx(&SgBuf, &SgBufCmp, cbRange, &cbOff, true))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Corrupted disk, print I/O log entry of the last write which accessed this range. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t cSector = (offSeg + cbOff) / 512;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsg(cSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMsgError("Corrupted disk at offset %llu (%u bytes in the current read buffer)!\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync offCurr + cbOff, cbOff);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMsgError("Last write to this sector started at offset %llu with %u bytes (%u references to this log entry)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->apIoLog[cSector]->off,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->apIoLog[cSector]->cbWrite,
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->apIoLog[cSector]->cRefs);
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTAssertDebugBreak();
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync }
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync }
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTSgBufAdvance(&SgBuf, cbRange);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync offCurr += cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbLeft -= cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Discards the given ranges from the disk.
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync *
1a1433dbc5e55f83cbcde6aa9f045c2dc7eeb9e7vboxsync * @returns VBox status code.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pThis Disk integrity driver instance data.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param paRanges Array of ranges to discard.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param cRanges Number of ranges in the array.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic int drvdiskintDiscardRecords(PDRVDISKINTEGRITY pThis, PCRTRANGE paRanges, unsigned cRanges)
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync{
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync int rc = VINF_SUCCESS;
d28bd01ede12da4a939e81a155d227ee4d6ff634vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("pThis=%#p paRanges=%#p cRanges=%u\n", pThis, paRanges, cRanges));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync for (unsigned i = 0; i < cRanges; i++)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync uint64_t offStart = paRanges[i].offStart;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync size_t cbLeft = paRanges[i].cbRange;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync LogFlowFunc(("Discarding off=%llu cbRange=%zu\n", offStart, cbLeft));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync while (cbLeft)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync size_t cbRange;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offStart);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (!pSeg)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Get next segment */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offStart, true);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if ( !pSeg
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync || (RTFOFF)offStart + (RTFOFF)cbLeft <= pSeg->Core.Key)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbRange = cbLeft;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync else
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbRange = pSeg->Core.Key - offStart;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(!(cbRange % 512));
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync else
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync size_t cbPreLeft, cbPostLeft;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbRange = RT_MIN(cbRange, pSeg->Core.KeyLast - offStart + 1);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbPreLeft = offStart - pSeg->Core.Key;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbPostLeft = pSeg->cbSeg - cbRange - cbPreLeft;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(!(cbRange % 512));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(!(cbPreLeft % 512));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(!(cbPostLeft % 512));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("cbRange=%zu cbPreLeft=%zu cbPostLeft=%zu\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRange, cbPreLeft, cbPostLeft));
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTAvlrFileOffsetRemove(pThis->pTreeSegments, pSeg->Core.Key);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (!cbPreLeft && !cbPostLeft)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* Just free the whole segment. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Freeing whole segment pSeg=%#p\n", pSeg));
8112e0942f1128329b99b22a20b395963d4abceavboxsync RTMemFree(pSeg->pbSeg);
8112e0942f1128329b99b22a20b395963d4abceavboxsync for (unsigned idx = 0; idx < pSeg->cIoLogEntries; idx++)
8112e0942f1128329b99b22a20b395963d4abceavboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync RTMemFree(pSeg);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync else if (cbPreLeft && !cbPostLeft)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Realloc to new size and insert. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync LogFlowFunc(("Realloc segment pSeg=%#p\n", pSeg));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPreLeft);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned idx = cbPreLeft / 512; idx < pSeg->cIoLogEntries; idx++)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPreLeft / 512]));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->Core.KeyLast = pSeg->Core.Key + cbPreLeft - 1;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->cbSeg = cbPreLeft;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSeg->cIoLogEntries = cbPreLeft / 512;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(fInserted);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (!cbPreLeft && cbPostLeft)
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync {
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync /* Move data to the front and realloc. */
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync LogFlowFunc(("Move data and realloc segment pSeg=%#p\n", pSeg));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync memmove(pSeg->pbSeg, pSeg->pbSeg + cbRange, cbPostLeft);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned idx = 0; idx < cbRange / 512; idx++)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync for (unsigned idx = 0; idx < cbPostLeft /512; idx++)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->apIoLog[idx] = pSeg->apIoLog[(cbRange / 512) + idx];
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPostLeft / 512]));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPostLeft);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->Core.Key += cbRange;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->cbSeg = cbPostLeft;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pSeg->cIoLogEntries = cbPostLeft / 512;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(fInserted);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync else
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Split the segment into 2 new segments. */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync LogFlowFunc(("Split segment pSeg=%#p\n", pSeg));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKSEGMENT pSegPost = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPostLeft / 512]));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pSegPost)
8112e0942f1128329b99b22a20b395963d4abceavboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSegPost->Core.Key = pSeg->Core.Key + cbPreLeft + cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSegPost->Core.KeyLast = pSeg->Core.KeyLast;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSegPost->cbSeg = cbPostLeft;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSegPost->pbSeg = (uint8_t *)RTMemAllocZ(cbPostLeft);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSegPost->cIoLogEntries = cbPostLeft / 512;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pSegPost->pbSeg)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pSegPost);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync memcpy(pSegPost->pbSeg, pSeg->pbSeg + cbPreLeft + cbRange, cbPostLeft);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned idx = 0; idx < cbPostLeft / 512; idx++)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pSegPost->apIoLog[idx] = pSeg->apIoLog[((cbPreLeft + cbRange) / 512) + idx];
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSegPost->Core);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(fInserted);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Shrink the current segment. */
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPreLeft);
8112e0942f1128329b99b22a20b395963d4abceavboxsync for (unsigned idx = cbPreLeft / 512; idx < (cbPreLeft + cbRange) / 512; idx++)
8112e0942f1128329b99b22a20b395963d4abceavboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPreLeft / 512]));
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->Core.KeyLast = pSeg->Core.Key + cbPreLeft - 1;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->cbSeg = cbPreLeft;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pSeg->cIoLogEntries = cbPreLeft / 512;
8112e0942f1128329b99b22a20b395963d4abceavboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
8112e0942f1128329b99b22a20b395963d4abceavboxsync Assert(fInserted);
8112e0942f1128329b99b22a20b395963d4abceavboxsync } /* if (cbPreLeft && cbPostLeft) */
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync offStart += cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync cbLeft -= cbRange;
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync LogFlowFunc(("returns rc=%Rrc\n", rc));
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync return rc;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync}
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync/**
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * Adds a request to the active list.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync *
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @returns nothing.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pThis The driver instance data.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * @param pIoReq The request to add.
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsyncstatic void drvdiskintIoReqAdd(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pThis->iNextFreeSlot];
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync Assert(!pReqActive->pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pReqActive->tsStart = pIoReq->tsStart;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pReqActive->pIoReq = pIoReq;
8112e0942f1128329b99b22a20b395963d4abceavboxsync pIoReq->iSlot = pThis->iNextFreeSlot;
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /* 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/**
8112e0942f1128329b99b22a20b395963d4abceavboxsync * Removes a request from the active list.
8112e0942f1128329b99b22a20b395963d4abceavboxsync *
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @returns nothing.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pThis The driver instance data.
8112e0942f1128329b99b22a20b395963d4abceavboxsync * @param pIoReq The request to remove.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic void drvdiskintIoReqRemove(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pIoReq->iSlot];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 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.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvdiskIntIoReqExpiredCheck(RTTHREAD pThread, void *pvUser)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = (PDRVDISKINTEGRITY)pvUser;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync while (pThis->fRunning)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = RTSemEventWait(pThis->SemEvent, pThis->uCheckIntervalMs);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (!pThis->fRunning)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync break;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Assert(rc == VERR_TIMEOUT);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Get current timestamp for comparison. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t tsCurr = RTTimeSystemMilliTS();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Go through the array and check for expired requests. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[i];
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ pIoReq = ASMAtomicReadPtrT(&pReqActive->pIoReq, PDRVDISKAIOREQ);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if ( pIoReq
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && (tsCurr > pReqActive->tsStart)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync && (tsCurr - pReqActive->tsStart) >= pThis->uExpireIntervalMs)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMsgError("Request %#p expired (active for %llu ms already)\n",
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pIoReq, tsCurr - pReqActive->tsStart);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTAssertDebugBreak();
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* -=-=-=-=- 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)) )
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/*******************************************************************************
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync* Media interface methods *
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync*******************************************************************************/
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnRead */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintRead(PPDMIMEDIA pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t off, void *pvBuf, size_t cbRead)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync VDIOLOGENT hIoLogEntry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGREQ_READ, off,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead, NULL, &hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, off, pvBuf, cbRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGSEG Seg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGBUF SgBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.pvSeg = pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.cbSeg = cbRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, &Seg, 1);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
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. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGSEG Seg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.cbSeg = cbRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.pvSeg = pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnWrite */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintWrite(PPDMIMEDIA pInterface,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint64_t off, const void *pvBuf,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync size_t cbWrite)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync VDIOLOGENT hIoLogEntry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGSEG Seg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGBUF SgBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.pvSeg = (void *)pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.cbSeg = cbWrite;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, &Seg, 1);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGREQ_WRITE, off,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbWrite, &SgBuf, &hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pThis->pDrvMedia->pfnWrite(pThis->pDrvMedia, off, pvBuf, cbWrite);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync }
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_FAILURE(rc))
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Record the write. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGSEG Seg;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync Seg.cbSeg = cbWrite;
c0b47c53336892431c7a2d8666600ffed91c11f1vboxsync Seg.pvSeg = (void *)pvBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
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=%llu paSeg=%#p cSeg=%u cbRead=%d pvUser=%#p\n", __FUNCTION__,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uOffset, paSeg, cSeg, cbRead, pvUser));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_READ, uOffset, paSeg, cSeg, cbRead, pvUser);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync AssertPtr(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
87d9823b393efbc674b3f3b0ff96998ca89e89b7vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGREQ_READ, uOffset,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead, NULL, &pIoReq->hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync int rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync cbRead, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
eac945b2260779f7c5d44d8015bcc4779498c6f9vboxsync /* 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
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync 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);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->hIoLogger)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTSGBUF SgBuf;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync int rc2 = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGREQ_WRITE, uOffset,
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync cbWrite, &SgBuf, &pIoReq->hIoLogEntry);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc2);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync int rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync cbWrite, pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync /* Record the write. */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->fCheckConsistency)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertRC(rc2);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
9d7572b5c359aff94b3c20fc0177e24567bdde6evboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->hIoLogger)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc2);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync if (pThis->fTraceRequests)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTMemFree(pIoReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTMemFree(pIoReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return rc;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/** @copydoc PDMIMEDIAASYNC::pfnStartFlush */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsyncstatic DECLCALLBACK(int) drvdiskintStartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync{
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync int rc = VINF_SUCCESS;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_FLUSH, 0, NULL, 0, 0, pvUser);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertPtr(pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->fTraceRequests)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (pThis->hIoLogger)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGREQ_FLUSH, 0,
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync 0, NULL, &pIoReq->hIoLogEntry);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertRC(rc);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = pThis->pDrvMediaAsync->pfnStartFlush(pThis->pDrvMediaAsync, pIoReq);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->hIoLogger)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertRC(rc2);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTMemFree(pIoReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync }
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync RTMemFree(pIoReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return rc;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync/** @copydoc PDMIMEDIAASYNC::pfnStartDiscard */
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsyncstatic DECLCALLBACK(int) drvdiskintStartDiscard(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync int rc = VINF_SUCCESS;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync VDIOLOGENT hIoLogEntry;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_DISCARD, 0, NULL, 0, 0, pvUser);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync AssertPtr(pIoReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pIoReq->paRanges = paRanges;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync pIoReq->cRanges = cRanges;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync if (pThis->hIoLogger)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStartDiscard(pThis->hIoLogger, true, paRanges, cRanges, &hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pThis->pDrvMediaAsync->pfnStartDiscard(pThis->pDrvMediaAsync, paRanges, cRanges, 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 }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintFlush(PPDMIMEDIA pInterface)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync VDIOLOGENT hIoLogEntry;
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGREQ_FLUSH, 0,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 0, NULL, &hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync rc = pThis->pDrvMedia->pfnFlush(pThis->pDrvMedia);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync if (pThis->hIoLogger)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync {
8112e0942f1128329b99b22a20b395963d4abceavboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertRC(rc2);
8112e0942f1128329b99b22a20b395963d4abceavboxsync }
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync return rc;
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(uint64_t) drvdiskintGetSize(PPDMIMEDIA pInterface)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
8112e0942f1128329b99b22a20b395963d4abceavboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(bool) drvdiskintIsReadOnly(PPDMIMEDIA pInterface)
8112e0942f1128329b99b22a20b395963d4abceavboxsync{
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return pThis->pDrvMedia->pfnIsReadOnly(pThis->pDrvMedia);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync}
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
8112e0942f1128329b99b22a20b395963d4abceavboxsync return pThis->pDrvMedia->pfnBiosGetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
8112e0942f1128329b99b22a20b395963d4abceavboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync{
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return pThis->pDrvMedia->pfnBiosSetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync{
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fdd17dc68230654ee0796918863927fca10a9f0avboxsync return pThis->pDrvMedia->pfnBiosGetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync}
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync/** @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}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** @copydoc PDMIMEDIA::pfnDiscard */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintDiscard(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync VDIOLOGENT hIoLogEntry;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = VDDbgIoLogStartDiscard(pThis->hIoLogger, false, paRanges, cRanges, &hIoLogEntry);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync rc = pThis->pDrvMedia->pfnDiscard(pThis->pDrvMedia, paRanges, cRanges);
3fe24a3690526efc4cceece3819d628caadf3140vboxsync
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync if (pThis->hIoLogger)
3fe24a3690526efc4cceece3819d628caadf3140vboxsync {
3fe24a3690526efc4cceece3819d628caadf3140vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync AssertRC(rc2);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintDiscardRecords(pThis, paRanges, cRanges);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* -=-=-=-=- IMediaAsyncPort -=-=-=-=- */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Makes a PDRVBLOCKASYNC out of a PPDMIMEDIAASYNCPORT. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define PDMIMEDIAASYNCPORT_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaAsyncPort))) )
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintAsyncTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNCPORT_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)pvUser;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc = VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync LogFlowFunc(("pIoReq=%#p\n", pIoReq));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* Remove from the active list. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->fTraceRequests)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (RT_SUCCESS(rcReq) && pThis->fCheckConsistency)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintReadVerify(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintWriteRecord(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_DISCARD)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = drvdiskintDiscardRecords(pThis, pIoReq->paRanges, pIoReq->cRanges);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync else
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertMsg(pIoReq->enmTxDir == DRVDISKAIOTXDIR_FLUSH, ("Huh?\n"));
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pThis->hIoLogger)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSGBUF SgBuf;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTSgBufInit(&SgBuf, pIoReq->paSeg, pIoReq->cSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, rc, &SgBuf);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc2);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync void *pvUserComplete = pIoReq->pvUser;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync drvdiskintIoReqFree(pThis, pIoReq);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvUserComplete, rcReq);
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync return rc;
689866c0e5e611f2db46822ae47724b55a27a1a0vboxsync}
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync/* -=-=-=-=- IMediaPort -=-=-=-=- */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/** Makes a PDRVBLOCK out of a PPDMIMEDIAPORT. */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync#define PDMIMEDIAPORT_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaPort))) )
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation}
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsyncstatic DECLCALLBACK(int) drvdiskintQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync uint32_t *piInstance, uint32_t *piLUN)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAPORT_2_DRVDISKINTEGRITY(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return pThis->pDrvMediaPort->pfnQueryDeviceLocation(pThis->pDrvMediaPort, ppcszController,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync piInstance, piLUN);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/* -=-=-=-=- IBase -=-=-=-=- */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(void *) drvdiskintQueryInterface(PPDMIBASE pInterface, const char *pszIID)
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->pDrvMediaAsync ? &pThis->IMediaAsync : NULL);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, &pThis->IMediaAsyncPort);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IMediaPort);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync/* -=-=-=-=- driver interface -=-=-=-=- */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic int drvdiskintTreeDestroy(PAVLRFOFFNODECORE pNode, void *pvUser)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync{
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)pNode;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pSeg->pbSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync RTMemFree(pSeg);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return VINF_SUCCESS;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * @copydoc FNPDMDRVDESTRUCT
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsyncstatic DECLCALLBACK(void) drvdiskintDestruct(PPDMDRVINS pDrvIns)
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync{
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
3aab9f739cebfaa93f6a5a51e293310619d55a5bvboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync if (pThis->pTreeSegments)
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTAvlrFileOffsetDestroy(pThis->pTreeSegments, drvdiskintTreeDestroy, NULL);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTMemFree(pThis->pTreeSegments);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync if (pThis->fTraceRequests)
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis->fRunning = false;
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync RTSemEventSignal(pThis->SemEvent);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTSemEventDestroy(pThis->SemEvent);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync if (pThis->fCheckDoubleCompletion)
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync /* Free all requests */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync while (pThis->papIoReq[pThis->iEntry])
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync {
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync RTMemFree(pThis->papIoReq[pThis->iEntry]);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis->papIoReq[pThis->iEntry] = NULL;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync }
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync if (pThis->hIoLogger)
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync VDDbgIoLogDestroy(pThis->hIoLogger);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync}
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync/**
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync * Construct a disk integrity driver instance.
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync *
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync * @copydoc FNPDMDRVCONSTRUCT
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsyncstatic DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync{
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync int rc = VINF_SUCCESS;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance));
8112e0942f1128329b99b22a20b395963d4abceavboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
8112e0942f1128329b99b22a20b395963d4abceavboxsync
8112e0942f1128329b99b22a20b395963d4abceavboxsync /*
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync * Validate configuration.
8112e0942f1128329b99b22a20b395963d4abceavboxsync */
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "TraceRequests\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "CheckIntervalMs\0"
8112e0942f1128329b99b22a20b395963d4abceavboxsync "ExpireIntervalMs\0"
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync "CheckDoubleCompletions\0"
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync "HistorySize\0"
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync "IoLog\0"))
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync AssertRC(rc);
bb2f3a7f00e605b890f8a8a74969f551cc9a0477vboxsync rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false);
8112e0942f1128329b99b22a20b395963d4abceavboxsync AssertRC(rc);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync AssertRC(rc);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CheckDoubleCompletions", &pThis->fCheckDoubleCompletion, false);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync AssertRC(rc);
8112e0942f1128329b99b22a20b395963d4abceavboxsync rc = CFGMR3QueryU32Def(pCfg, "HistorySize", &pThis->cEntries, 512);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync AssertRC(rc);
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync
874be5c5b701726b68fa1391022ae2f5c7768894vboxsync char *pszIoLogFilename = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync rc = CFGMR3QueryStringAlloc(pCfg, "IoLog", &pszIoLogFilename);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_CFGM_VALUE_NOT_FOUND);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /*
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync * Initialize most of the data members.
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->pDrvIns = pDrvIns;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IBase. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pDrvIns->IBase.pfnQueryInterface = drvdiskintQueryInterface;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* IMedia */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnRead = drvdiskintRead;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnWrite = drvdiskintWrite;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnFlush = drvdiskintFlush;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->IMedia.pfnGetSize = drvdiskintGetSize;
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMedia.pfnIsReadOnly = drvdiskintIsReadOnly;
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvdiskintBiosGetPCHSGeometry;
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvdiskintBiosSetPCHSGeometry;
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvdiskintBiosGetLCHSGeometry;
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvdiskintBiosSetLCHSGeometry;
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMedia.pfnGetUuid = drvdiskintGetUuid;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* IMediaAsync */
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMediaAsync.pfnStartRead = drvdiskintStartRead;
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMediaAsync.pfnStartWrite = drvdiskintStartWrite;
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMediaAsync.pfnStartFlush = drvdiskintStartFlush;
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync /* IMediaAsyncPort. */
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMediaAsyncPort.pfnTransferCompleteNotify = drvdiskintAsyncTransferCompleteNotify;
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync /* IMediaPort. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->IMediaPort.pfnQueryDeviceLocation = drvdiskintQueryDeviceLocation;
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync /* Query the media port interface above us. */
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (!pThis->pDrvMediaPort)
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
8865816a3d875ec1a036af307fbb484af107f014vboxsync N_("No media port inrerface above"));
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync /* Try to attach async media port interface above.*/
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync /*
8865816a3d875ec1a036af307fbb484af107f014vboxsync * Try attach driver below and query it's media interface.
8865816a3d875ec1a036af307fbb484af107f014vboxsync */
8865816a3d875ec1a036af307fbb484af107f014vboxsync PPDMIBASE pBase;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync if (RT_FAILURE(rc))
8865816a3d875ec1a036af307fbb484af107f014vboxsync return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
8865816a3d875ec1a036af307fbb484af107f014vboxsync N_("Failed to attach driver below us! %Rrc"), rc);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (!pThis->pDrvMedia)
8865816a3d875ec1a036af307fbb484af107f014vboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
8865816a3d875ec1a036af307fbb484af107f014vboxsync N_("No media or async media interface below"));
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC);
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pThis->pDrvMedia->pfnDiscard)
8865816a3d875ec1a036af307fbb484af107f014vboxsync pThis->IMedia.pfnDiscard = drvdiskintDiscard;
8865816a3d875ec1a036af307fbb484af107f014vboxsync if ( pThis->pDrvMediaAsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync && pThis->pDrvMediaAsync->pfnStartDiscard)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync pThis->IMediaAsync.pfnStartDiscard = drvdiskintStartDiscard;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pThis->fCheckConsistency)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync /* Create the AVL tree. */
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (!pThis->pTreeSegments)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync rc = VERR_NO_MEMORY;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync }
8865816a3d875ec1a036af307fbb484af107f014vboxsync
8865816a3d875ec1a036af307fbb484af107f014vboxsync if (pThis->fTraceRequests)
8865816a3d875ec1a036af307fbb484af107f014vboxsync {
8865816a3d875ec1a036af307fbb484af107f014vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
f8bec4d0d62cd1f6e3e5eabf8f2703aef91a6dbevboxsync {
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->apReqActive[i].pIoReq = NULL;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->apReqActive[i].tsStart = 0;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync pThis->iNextFreeSlot = 0;
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* Init event semaphore. */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync rc = RTSemEventCreate(&pThis->SemEvent);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync 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)
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync {
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync rc = VDDbgIoLogCreate(&pThis->hIoLogger, pszIoLogFilename, VDDBG_IOLOG_LOG_DATA);
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync MMR3HeapFree(pszIoLogFilename);
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync }
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync return rc;
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync}
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync/**
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync * Block driver registration record.
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsyncconst PDMDRVREG g_DrvDiskIntegrity =
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync{
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32Version */
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync PDM_DRVREG_VERSION,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* szName */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync "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 */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnReset */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnSuspend */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* pfnResume */
3fe24a3690526efc4cceece3819d628caadf3140vboxsync NULL,
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /* pfnAttach */
3fe24a3690526efc4cceece3819d628caadf3140vboxsync NULL,
0cbaa6b7062076428f638cc5afba9d16200c6076vboxsync /* pfnDetach */
3fe24a3690526efc4cceece3819d628caadf3140vboxsync NULL,
3fe24a3690526efc4cceece3819d628caadf3140vboxsync /* pfnPowerOff */
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync NULL,
eb02731cc4b3e9d61f26f793a4e27602826b0d52vboxsync /* pfnSoftReset */
3fe24a3690526efc4cceece3819d628caadf3140vboxsync NULL,
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync /* u32EndVersion */
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync PDM_DRVREG_VERSION
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync};
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync
ae0f2178b9a5aded928e0245cb830ba1d3d04c57vboxsync