fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* $Id$ */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @file
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * VBox storage devices: Disk integrity check.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2013 Oracle Corporation
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * available from http://www.virtualbox.org. This file is free software;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * you can redistribute it and/or modify it under the terms of the GNU
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * General Public License (GPL) as published by the Free Software
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*******************************************************************************
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync* Header Files *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync*******************************************************************************/
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#define LOG_GROUP LOG_GROUP_DRV_DISK_INTEGRITY
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync#include <VBox/vmm/pdmdrv.h>
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync#include <VBox/vddbg.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/assert.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/string.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/uuid.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/avl.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/mem.h>
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync#include <iprt/message.h>
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync#include <iprt/sg.h>
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync#include <iprt/time.h>
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync#include <iprt/semaphore.h>
3eef103be36a8f4828d69cfec3cea9bcefc9fd92vboxsync#include <iprt/asm.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
f5e53763b0a581b0299e98028c6c52192eb06785vboxsync#include "VBoxDD.h"
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*******************************************************************************
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync* Structures and Typedefs *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync*******************************************************************************/
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync/**
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync * Transfer direction.
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync */
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsynctypedef enum DRVDISKAIOTXDIR
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync{
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync /** Read */
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync DRVDISKAIOTXDIR_READ = 0,
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync /** Write */
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync DRVDISKAIOTXDIR_WRITE,
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync /** Flush */
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync DRVDISKAIOTXDIR_FLUSH,
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync /** Discard */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync DRVDISKAIOTXDIR_DISCARD,
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync /** Read after write for immediate verification. */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync DRVDISKAIOTXDIR_READ_AFTER_WRITE
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync} DRVDISKAIOTXDIR;
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/**
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * async I/O request.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsynctypedef struct DRVDISKAIOREQ
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync /** Transfer direction. */
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync DRVDISKAIOTXDIR enmTxDir;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Start offset. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync uint64_t off;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Transfer size. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync size_t cbTransfer;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Segment array. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync PCRTSGSEG paSeg;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Number of array entries. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync unsigned cSeg;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** User argument */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync void *pvUser;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Slot in the array. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync unsigned iSlot;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /** Start timestamp */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync uint64_t tsStart;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /** Completion timestamp. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync uint64_t tsComplete;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync /** I/O log entry if configured. */
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync VDIOLOGENT hIoLogEntry;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync /** Ranges to discard. */
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync PCRTRANGE paRanges;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync /** Number of ranges. */
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync unsigned cRanges;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync} DRVDISKAIOREQ, *PDRVDISKAIOREQ;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync/**
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync * I/O log entry.
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsynctypedef struct IOLOGENT
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync{
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Start offset */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync uint64_t off;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Write size */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync size_t cbWrite;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Number of references to this entry. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync unsigned cRefs;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync} IOLOGENT, *PIOLOGENT;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Disk segment.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsynctypedef struct DRVDISKSEGMENT
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** AVL core. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync AVLRFOFFNODECORE Core;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Size of the segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbSeg;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Data for this segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync uint8_t *pbSeg;
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /** Number of entries in the I/O array. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync unsigned cIoLogEntries;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Array of I/O log references. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync PIOLOGENT apIoLog[1];
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync} DRVDISKSEGMENT, *PDRVDISKSEGMENT;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync/**
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * Active requests list entry.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsynctypedef struct DRVDISKAIOREQACTIVE
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync{
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Pointer to the request. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync volatile PDRVDISKAIOREQ pIoReq;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Start timestamp. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync uint64_t tsStart;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync} DRVDISKAIOREQACTIVE, *PDRVDISKAIOREQACTIVE;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Disk integrity driver instance data.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @implements PDMIMEDIA
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsynctypedef struct DRVDISKINTEGRITY
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Pointer driver instance. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMDRVINS pDrvIns;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Pointer to the media driver below us.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * This is NULL if the media is not mounted. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMIMEDIA pDrvMedia;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Our media interface */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMIMEDIA IMedia;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /** The media port interface above. */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync PPDMIMEDIAPORT pDrvMediaPort;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /** Media port interface */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync PDMIMEDIAPORT IMediaPort;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Pointer to the media async driver below us.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * This is NULL if the media is not mounted. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PPDMIMEDIAASYNC pDrvMediaAsync;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Our media async interface */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDMIMEDIAASYNC IMediaAsync;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** The async media port interface above. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /** Our media async port interface */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDMIMEDIAASYNCPORT IMediaAsyncPort;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Flag whether consistency checks are enabled. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync bool fCheckConsistency;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync /** Flag whether the RAM disk was prepopulated. */
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync bool fPrepopulateRamDisk;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** AVL tree containing the disk blocks to check. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PAVLRFOFFTREE pTreeSegments;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Flag whether async request tracing is enabled. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync bool fTraceRequests;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Interval the thread should check for expired requests (milliseconds). */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync uint32_t uCheckIntervalMs;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Expire timeout for a request (milliseconds). */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync uint32_t uExpireIntervalMs;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Thread which checks for lost requests. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTTHREAD hThread;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Event semaphore */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTSEMEVENT SemEvent;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Flag whether the thread should run. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync bool fRunning;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Array containing active requests. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync DRVDISKAIOREQACTIVE apReqActive[128];
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /** Next free slot in the array */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync volatile unsigned iNextFreeSlot;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /** Flag whether we check for requests completing twice. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync bool fCheckDoubleCompletion;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /** Number of requests we go back. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync unsigned cEntries;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /** Array of completed but still observed requests. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync PDRVDISKAIOREQ *papIoReq;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /** Current entry in the array. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync unsigned iEntry;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync /** Flag whether to do a immediate read after write for verification. */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync bool fReadAfterWrite;
288880cd72661161e8204e0ba61baa692c50bcccvboxsync /** Flag whether to record the data to write before the write completed successfully.
288880cd72661161e8204e0ba61baa692c50bcccvboxsync * Useful in case the data is modified in place later on (encryption for instance). */
288880cd72661161e8204e0ba61baa692c50bcccvboxsync bool fRecordWriteBeforeCompletion;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync /** I/O logger to use if enabled. */
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync VDIOLOGGER hIoLogger;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync} DRVDISKINTEGRITY, *PDRVDISKINTEGRITY;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/**
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * Allocate a new I/O request.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync *
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @returns New I/O request.
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync * @param enmTxDir Transfer direction.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param off Start offset.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param paSeg Segment array.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param cSeg Number of segments.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param cbTransfer Number of bytes to transfer.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param pvUser User argument.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync */
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsyncstatic PDRVDISKAIOREQ drvdiskintIoReqAlloc(DRVDISKAIOTXDIR enmTxDir, uint64_t off, PCRTSGSEG paSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync unsigned cSeg, size_t cbTransfer, void *pvUser)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)RTMemAlloc(sizeof(DRVDISKAIOREQ));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (RT_LIKELY(pIoReq))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->enmTxDir = enmTxDir;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->off = off;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->cbTransfer = cbTransfer;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->paSeg = paSeg;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->cSeg = cSeg;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->pvUser = pvUser;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->iSlot = 0;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->tsStart = RTTimeSystemMilliTS();
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->tsComplete = 0;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync pIoReq->hIoLogEntry = NULL;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return pIoReq;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync/**
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync * Free a async I/O request.
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync *
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync * @returns nothing.
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync * @param pThis Disk driver.
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync * @param pIoReq The I/O request to free.
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsyncstatic void drvdiskintIoReqFree(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync{
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync if (pThis->fCheckDoubleCompletion)
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /* Search if the I/O request completed already. */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync for (unsigned i = 0; i < pThis->cEntries; i++)
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync if (RT_UNLIKELY(pThis->papIoReq[i] == pIoReq))
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync RTMsgError("Request %#p completed already!\n", pIoReq);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync RTMsgError("Start timestamp %llu Completion timestamp %llu (completed after %llu ms)\n",
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pIoReq->tsStart, pIoReq->tsComplete, pIoReq->tsComplete - pIoReq->tsStart);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync RTAssertDebugBreak();
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pIoReq->tsComplete = RTTimeSystemMilliTS();
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync Assert(!pThis->papIoReq[pThis->iEntry]);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->papIoReq[pThis->iEntry] = pIoReq;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync if (pThis->papIoReq[pThis->iEntry])
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync RTMemFree(pThis->papIoReq[pThis->iEntry]);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->papIoReq[pThis->iEntry] = NULL;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync else
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync RTMemFree(pIoReq);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync}
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsyncstatic void drvdiskintIoLogEntryRelease(PIOLOGENT pIoLogEnt)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync{
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pIoLogEnt->cRefs--;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if (!pIoLogEnt->cRefs)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync RTMemFree(pIoLogEnt);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync}
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/**
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * Record a successful write to the virtual disk.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync *
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @returns VBox status code.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param pThis Disk integrity driver instance data.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param paSeg Segment array of the write to record.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param cSeg Number of segments.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param off Start offset.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param cbWrite Number of bytes to record.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsyncstatic int drvdiskintWriteRecord(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync uint64_t off, size_t cbWrite)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync int rc = VINF_SUCCESS;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbWrite=%u\n",
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync pThis, paSeg, cSeg, off, cbWrite));
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Update the segments */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbLeft = cbWrite;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTFOFF offCurr = (RTFOFF)off;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSGBUF SgBuf;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync PIOLOGENT pIoLogEnt = (PIOLOGENT)RTMemAllocZ(sizeof(IOLOGENT));
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync if (!pIoLogEnt)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync return VERR_NO_MEMORY;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->off = off;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->cbWrite = cbWrite;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->cRefs = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync while (cbLeft)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbRange = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync bool fSet = false;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync unsigned offSeg = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Get next segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if ( !pSeg
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync || offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = cbLeft;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = pSeg->Core.Key - offCurr;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(cbRange % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Create new segment */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbRange / 512]));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (pSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->Core.Key = offCurr;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->Core.KeyLast = offCurr + (RTFOFF)cbRange - 1;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->cbSeg = cbRange;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->pbSeg = (uint8_t *)RTMemAllocZ(cbRange);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->cIoLogEntries = cbRange / 512;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pSeg->pbSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync AssertMsg(fInserted, ("Bug!\n"));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync fSet = true;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync fSet = true;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync offSeg = offCurr - pSeg->Core.Key;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (fSet)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync AssertPtr(pSeg);
e93dfb5368911523b10cd2f506c44f5fbd47abf3vboxsync size_t cbCopied = RTSgBufCopyToBuf(&SgBuf, pSeg->pbSeg + offSeg, cbRange);
e93dfb5368911523b10cd2f506c44f5fbd47abf3vboxsync Assert(cbCopied == cbRange);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /* Update the I/O log pointers */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(offSeg % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(cbRange % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync while (offSeg < cbRange)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync uint32_t uSector = offSeg / 512;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync PIOLOGENT pIoLogOld = NULL;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync AssertMsg(uSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogOld = pSeg->apIoLog[uSector];
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync if (pIoLogOld)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogOld->cRefs--;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync if (!pIoLogOld->cRefs)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync RTMemFree(pIoLogOld);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync }
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->apIoLog[uSector] = pIoLogEnt;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->cRefs++;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync offSeg += 512;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync else
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSgBufAdvance(&SgBuf, cbRange);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync offCurr += cbRange;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbLeft -= cbRange;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync}
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/**
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * Verifies a read request.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync *
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @returns VBox status code.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param pThis Disk integrity driver instance data.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param paSeg Segment array of the containing the data buffers to verify.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param cSeg Number of segments.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param off Start offset.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync * @param cbWrite Number of bytes to verify.
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsyncstatic int drvdiskintReadVerify(PDRVDISKINTEGRITY pThis, PCRTSGSEG paSeg, unsigned cSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync uint64_t off, size_t cbRead)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync int rc = VINF_SUCCESS;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync LogFlowFunc(("pThis=%#p paSeg=%#p cSeg=%u off=%llx cbRead=%u\n",
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync pThis, paSeg, cSeg, off, cbRead));
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync Assert(off % 512 == 0);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync Assert(cbRead % 512 == 0);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /* Compare read data */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync size_t cbLeft = cbRead;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTFOFF offCurr = (RTFOFF)off;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSGBUF SgBuf;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync while (cbLeft)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync size_t cbRange = 0;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync bool fCmp = false;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync unsigned offSeg = 0;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (!pSeg)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /* Get next segment */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (!pSeg)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /* No data in the tree for this read. Assume everything is ok. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbRange = cbLeft;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync else if (offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbRange = cbLeft;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync else
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbRange = pSeg->Core.Key - offCurr;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (pThis->fPrepopulateRamDisk)
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync {
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync /* No segment means everything should be 0 for this part. */
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (!RTSgBufIsZero(&SgBuf, cbRange))
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync {
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync RTMsgError("Corrupted disk at offset %llu (expected everything to be 0)!\n",
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync offCurr);
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync RTAssertDebugBreak();
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync }
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync else
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync fCmp = true;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync offSeg = offCurr - pSeg->Core.Key;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (fCmp)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSGSEG Seg;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSGBUF SgBufCmp;
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync size_t cbOff = 0;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync Seg.cbSeg = cbRange;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync Seg.pvSeg = pSeg->pbSeg + offSeg;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTSgBufInit(&SgBufCmp, &Seg, 1);
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync if (RTSgBufCmpEx(&SgBuf, &SgBufCmp, cbRange, &cbOff, true))
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync /* Corrupted disk, print I/O log entry of the last write which accessed this range. */
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync uint32_t cSector = (offSeg + cbOff) / 512;
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync AssertMsg(cSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync RTMsgError("Corrupted disk at offset %llu (%u bytes in the current read buffer)!\n",
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync offCurr + cbOff, cbOff);
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync RTMsgError("Last write to this sector started at offset %llu with %u bytes (%u references to this log entry)\n",
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync pSeg->apIoLog[cSector]->off,
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync pSeg->apIoLog[cSector]->cbWrite,
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync pSeg->apIoLog[cSector]->cRefs);
1426407ebd84624dd10808b452b19d1fc4f6835avboxsync RTAssertDebugBreak();
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
e93dfb5368911523b10cd2f506c44f5fbd47abf3vboxsync else
e93dfb5368911523b10cd2f506c44f5fbd47abf3vboxsync RTSgBufAdvance(&SgBuf, cbRange);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync offCurr += cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbLeft -= cbRange;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync}
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync/**
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync * Discards the given ranges from the disk.
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync *
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync * @returns VBox status code.
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync * @param pThis Disk integrity driver instance data.
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync * @param paRanges Array of ranges to discard.
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync * @param cRanges Number of ranges in the array.
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync */
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsyncstatic int drvdiskintDiscardRecords(PDRVDISKINTEGRITY pThis, PCRTRANGE paRanges, unsigned cRanges)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync{
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync int rc = VINF_SUCCESS;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("pThis=%#p paRanges=%#p cRanges=%u\n", pThis, paRanges, cRanges));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned i = 0; i < cRanges; i++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync uint64_t offStart = paRanges[i].offStart;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync size_t cbLeft = paRanges[i].cbRange;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("Discarding off=%llu cbRange=%zu\n", offStart, cbLeft));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync while (cbLeft)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync size_t cbRange;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offStart);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if (!pSeg)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync /* Get next segment */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offStart, true);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if ( !pSeg
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync || (RTFOFF)offStart + (RTFOFF)cbLeft <= pSeg->Core.Key)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync cbRange = cbLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync else
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync cbRange = pSeg->Core.Key - offStart;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(!(cbRange % 512));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync else
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync size_t cbPreLeft, cbPostLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a320d427b79ea4374e1ad8d05eaecbab7bc4ceb3vboxsync cbRange = RT_MIN(cbLeft, pSeg->Core.KeyLast - offStart + 1);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync cbPreLeft = offStart - pSeg->Core.Key;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync cbPostLeft = pSeg->cbSeg - cbRange - cbPreLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(!(cbRange % 512));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(!(cbPreLeft % 512));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(!(cbPostLeft % 512));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("cbRange=%zu cbPreLeft=%zu cbPostLeft=%zu\n",
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync cbRange, cbPreLeft, cbPostLeft));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync RTAvlrFileOffsetRemove(pThis->pTreeSegments, pSeg->Core.Key);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if (!cbPreLeft && !cbPostLeft)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync /* Just free the whole segment. */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("Freeing whole segment pSeg=%#p\n", pSeg));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync RTMemFree(pSeg->pbSeg);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned idx = 0; idx < pSeg->cIoLogEntries; idx++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync RTMemFree(pSeg);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync else if (cbPreLeft && !cbPostLeft)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync /* Realloc to new size and insert. */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("Realloc segment pSeg=%#p\n", pSeg));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPreLeft);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned idx = cbPreLeft / 512; idx < pSeg->cIoLogEntries; idx++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPreLeft / 512]));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->Core.KeyLast = pSeg->Core.Key + cbPreLeft - 1;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->cbSeg = cbPreLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->cIoLogEntries = cbPreLeft / 512;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(fInserted);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync else if (!cbPreLeft && cbPostLeft)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync /* Move data to the front and realloc. */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("Move data and realloc segment pSeg=%#p\n", pSeg));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync memmove(pSeg->pbSeg, pSeg->pbSeg + cbRange, cbPostLeft);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned idx = 0; idx < cbRange / 512; idx++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned idx = 0; idx < cbPostLeft /512; idx++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->apIoLog[idx] = pSeg->apIoLog[(cbRange / 512) + idx];
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPostLeft / 512]));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPostLeft);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->Core.Key += cbRange;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->cbSeg = cbPostLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->cIoLogEntries = cbPostLeft / 512;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(fInserted);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync else
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync /* Split the segment into 2 new segments. */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("Split segment pSeg=%#p\n", pSeg));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync PDRVDISKSEGMENT pSegPost = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPostLeft / 512]));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if (pSegPost)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSegPost->Core.Key = pSeg->Core.Key + cbPreLeft + cbRange;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSegPost->Core.KeyLast = pSeg->Core.KeyLast;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSegPost->cbSeg = cbPostLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSegPost->pbSeg = (uint8_t *)RTMemAllocZ(cbPostLeft);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSegPost->cIoLogEntries = cbPostLeft / 512;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if (!pSegPost->pbSeg)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync RTMemFree(pSegPost);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync else
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync {
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync memcpy(pSegPost->pbSeg, pSeg->pbSeg + cbPreLeft + cbRange, cbPostLeft);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned idx = 0; idx < cbPostLeft / 512; idx++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSegPost->apIoLog[idx] = pSeg->apIoLog[((cbPreLeft + cbRange) / 512) + idx];
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSegPost->Core);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(fInserted);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync /* Shrink the current segment. */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPreLeft);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync for (unsigned idx = cbPreLeft / 512; idx < (cbPreLeft + cbRange) / 512; idx++)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPreLeft / 512]));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->Core.KeyLast = pSeg->Core.Key + cbPreLeft - 1;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->cbSeg = cbPreLeft;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync pSeg->cIoLogEntries = cbPreLeft / 512;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync Assert(fInserted);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync } /* if (cbPreLeft && cbPostLeft) */
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync offStart += cbRange;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync cbLeft -= cbRange;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync }
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync LogFlowFunc(("returns rc=%Rrc\n", rc));
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync return rc;
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync}
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync/**
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * Adds a request to the active list.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync *
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @returns nothing.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @param pThis The driver instance data.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @param pIoReq The request to add.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsyncstatic void drvdiskintIoReqAdd(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync{
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pThis->iNextFreeSlot];
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Assert(!pReqActive->pIoReq);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pReqActive->tsStart = pIoReq->tsStart;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pReqActive->pIoReq = pIoReq;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pIoReq->iSlot = pThis->iNextFreeSlot;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Search for the next one. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync while (pThis->apReqActive[pThis->iNextFreeSlot].pIoReq)
7de81a482cdfc1bbf53600a4f6cdd4c892ee460cvboxsync pThis->iNextFreeSlot = (pThis->iNextFreeSlot+1) % RT_ELEMENTS(pThis->apReqActive);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync}
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync/**
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * Removes a request from the active list.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync *
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @returns nothing.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @param pThis The driver instance data.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @param pIoReq The request to remove.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsyncstatic void drvdiskintIoReqRemove(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync{
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[pIoReq->iSlot];
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Assert(pReqActive->pIoReq == pIoReq);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
060db742c6ecb43560beec8754fb5b9c13bd7856vboxsync ASMAtomicWriteNullPtr(&pReqActive->pIoReq);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync}
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync/**
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * Thread checking for expired requests.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync *
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @returns IPRT status code.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @param pThread Thread handle.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync * @param pvUser Opaque user data.
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsyncstatic int drvdiskIntIoReqExpiredCheck(RTTHREAD pThread, void *pvUser)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync{
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync PDRVDISKINTEGRITY pThis = (PDRVDISKINTEGRITY)pvUser;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync while (pThis->fRunning)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync int rc = RTSemEventWait(pThis->SemEvent, pThis->uCheckIntervalMs);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (!pThis->fRunning)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync break;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Assert(rc == VERR_TIMEOUT);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Get current timestamp for comparison. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync uint64_t tsCurr = RTTimeSystemMilliTS();
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Go through the array and check for expired requests. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync PDRVDISKAIOREQACTIVE pReqActive = &pThis->apReqActive[i];
c7ff622115966b69b482bd2896662e40d823b22fvboxsync PDRVDISKAIOREQ pIoReq = ASMAtomicReadPtrT(&pReqActive->pIoReq, PDRVDISKAIOREQ);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if ( pIoReq
c5f009d280c87ab513356eb5585eff8b4cd26db7vboxsync && (tsCurr > pReqActive->tsStart)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync && (tsCurr - pReqActive->tsStart) >= pThis->uExpireIntervalMs)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTMsgError("Request %#p expired (active for %llu ms already)\n",
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pIoReq, tsCurr - pReqActive->tsStart);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTAssertDebugBreak();
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync return VINF_SUCCESS;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync}
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync/**
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync * Verify a completed read after write request.
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync *
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync * @returns VBox status code.
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync * @param pThis The driver instance data.
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync * @param pIoReq The request to be verified.
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsyncstatic int drvdiskintReadAfterWriteVerify(PDRVDISKINTEGRITY pThis, PDRVDISKAIOREQ pIoReq)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync{
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync int rc = VINF_SUCCESS;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync if (pThis->fCheckConsistency)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = drvdiskintReadVerify(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync else /** @todo: Implement read after write verification without a memory based image of the disk. */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync AssertMsgFailed(("TODO\n"));
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync return rc;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync}
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/* -=-=-=-=- IMedia -=-=-=-=- */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/** Makes a PDRVDISKINTEGRITY out of a PPDMIMEDIA. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync#define PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY)((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMedia)) )
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/** Makes a PDRVDISKINTEGRITY out of a PPDMIMEDIAASYNC. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync#define PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY)((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaAsync)) )
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/*******************************************************************************
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync* Media interface methods *
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync*******************************************************************************/
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/** @copydoc PDMIMEDIA::pfnRead */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsyncstatic DECLCALLBACK(int) drvdiskintRead(PPDMIMEDIA pInterface,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync uint64_t off, void *pvBuf, size_t cbRead)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc = VINF_SUCCESS;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync VDIOLOGENT hIoLogEntry;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGREQ_READ, off,
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync cbRead, NULL, &hIoLogEntry);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, off, pvBuf, cbRead);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGSEG Seg;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGBUF SgBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync Seg.pvSeg = pvBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync Seg.cbSeg = cbRead;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSgBufInit(&SgBuf, &Seg, 1);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, &SgBuf);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (RT_FAILURE(rc))
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fCheckConsistency)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Verify the read. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTSGSEG Seg;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Seg.cbSeg = cbRead;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Seg.pvSeg = pvBuf;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = drvdiskintReadVerify(pThis, &Seg, 1, off, cbRead);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync}
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/** @copydoc PDMIMEDIA::pfnWrite */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsyncstatic DECLCALLBACK(int) drvdiskintWrite(PPDMIMEDIA pInterface,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync uint64_t off, const void *pvBuf,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync size_t cbWrite)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc = VINF_SUCCESS;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync VDIOLOGENT hIoLogEntry;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGSEG Seg;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGBUF SgBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync Seg.pvSeg = (void *)pvBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync Seg.cbSeg = cbWrite;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSgBufInit(&SgBuf, &Seg, 1);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGREQ_WRITE, off,
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync cbWrite, &SgBuf, &hIoLogEntry);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
288880cd72661161e8204e0ba61baa692c50bcccvboxsync if (pThis->fRecordWriteBeforeCompletion)
288880cd72661161e8204e0ba61baa692c50bcccvboxsync {
288880cd72661161e8204e0ba61baa692c50bcccvboxsync RTSGSEG Seg;
288880cd72661161e8204e0ba61baa692c50bcccvboxsync Seg.cbSeg = cbWrite;
288880cd72661161e8204e0ba61baa692c50bcccvboxsync Seg.pvSeg = (void *)pvBuf;
288880cd72661161e8204e0ba61baa692c50bcccvboxsync
288880cd72661161e8204e0ba61baa692c50bcccvboxsync rc = drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite);
288880cd72661161e8204e0ba61baa692c50bcccvboxsync if (RT_FAILURE(rc))
288880cd72661161e8204e0ba61baa692c50bcccvboxsync return rc;
288880cd72661161e8204e0ba61baa692c50bcccvboxsync }
288880cd72661161e8204e0ba61baa692c50bcccvboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync rc = pThis->pDrvMedia->pfnWrite(pThis->pDrvMedia, off, pvBuf, cbWrite);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (RT_FAILURE(rc))
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
288880cd72661161e8204e0ba61baa692c50bcccvboxsync if ( pThis->fCheckConsistency
288880cd72661161e8204e0ba61baa692c50bcccvboxsync && !pThis->fRecordWriteBeforeCompletion)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Record the write. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTSGSEG Seg;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Seg.cbSeg = cbWrite;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync Seg.pvSeg = (void *)pvBuf;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = drvdiskintWriteRecord(pThis, &Seg, 1, off, cbWrite);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync}
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsyncstatic DECLCALLBACK(int) drvdiskintStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PCRTSGSEG paSeg, unsigned cSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync size_t cbRead, void *pvUser)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsync LogFlow(("%s: uOffset=%llu paSeg=%#p cSeg=%u cbRead=%d pvUser=%#p\n", __FUNCTION__,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync uOffset, paSeg, cSeg, cbRead, pvUser));
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_READ, uOffset, paSeg, cSeg, cbRead, pvUser);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync AssertPtr(pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync int rc2 = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGREQ_READ, uOffset,
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync cbRead, NULL, &pIoReq->hIoLogEntry);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync int rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbRead, pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /* Verify the read now. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fCheckConsistency)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync int rc2 = drvdiskintReadVerify(pThis, paSeg, cSeg, uOffset, cbRead);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc2);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGBUF SgBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, &SgBuf);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTMemFree(pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTMemFree(pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync}
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsyncstatic DECLCALLBACK(int) drvdiskintStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PCRTSGSEG paSeg, unsigned cSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync size_t cbWrite, void *pvUser)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
7de81a482cdfc1bbf53600a4f6cdd4c892ee460cvboxsync LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n", __FUNCTION__,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync uOffset, paSeg, cSeg, cbWrite, pvUser));
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_WRITE, uOffset, paSeg, cSeg, cbWrite, pvUser);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync AssertPtr(pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGBUF SgBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSgBufInit(&SgBuf, paSeg, cSeg);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync int rc2 = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGREQ_WRITE, uOffset,
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync cbWrite, &SgBuf, &pIoReq->hIoLogEntry);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
288880cd72661161e8204e0ba61baa692c50bcccvboxsync if (pThis->fRecordWriteBeforeCompletion)
288880cd72661161e8204e0ba61baa692c50bcccvboxsync {
288880cd72661161e8204e0ba61baa692c50bcccvboxsync int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite);
288880cd72661161e8204e0ba61baa692c50bcccvboxsync AssertRC(rc2);
288880cd72661161e8204e0ba61baa692c50bcccvboxsync }
288880cd72661161e8204e0ba61baa692c50bcccvboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync int rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset, paSeg, cSeg,
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync cbWrite, pIoReq);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync /* Record the write. */
288880cd72661161e8204e0ba61baa692c50bcccvboxsync if ( pThis->fCheckConsistency
288880cd72661161e8204e0ba61baa692c50bcccvboxsync && !pThis->fRecordWriteBeforeCompletion)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync int rc2 = drvdiskintWriteRecord(pThis, paSeg, cSeg, uOffset, cbWrite);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc2);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTMemFree(pIoReq);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync RTMemFree(pIoReq);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync/** @copydoc PDMIMEDIAASYNC::pfnStartFlush */
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsyncstatic DECLCALLBACK(int) drvdiskintStartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser)
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync{
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc = VINF_SUCCESS;
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNC_2_DRVDISKINTEGRITY(pInterface);
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_FLUSH, 0, NULL, 0, 0, pvUser);
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync AssertPtr(pIoReq);
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync
54597c35ab7fe470ca07560969c437982854e5devboxsync if (pThis->fTraceRequests)
54597c35ab7fe470ca07560969c437982854e5devboxsync drvdiskintIoReqAdd(pThis, pIoReq);
54597c35ab7fe470ca07560969c437982854e5devboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, true, VDDBGIOLOGREQ_FLUSH, 0,
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync 0, NULL, &pIoReq->hIoLogEntry);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync rc = pThis->pDrvMediaAsync->pfnStartFlush(pThis->pDrvMediaAsync, pIoReq);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTMemFree(pIoReq);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTMemFree(pIoReq);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync return rc;
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync}
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync/** @copydoc PDMIMEDIAASYNC::pfnStartDiscard */
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsyncstatic DECLCALLBACK(int) drvdiskintStartDiscard(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync{
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync int rc = VINF_SUCCESS;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync VDIOLOGENT hIoLogEntry;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_DISCARD, 0, NULL, 0, 0, pvUser);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AssertPtr(pIoReq);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pIoReq->paRanges = paRanges;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pIoReq->cRanges = cRanges;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (pThis->hIoLogger)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsync rc = VDDbgIoLogStartDiscard(pThis->hIoLogger, true, paRanges, cRanges, &hIoLogEntry);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AssertRC(rc);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsync rc = pThis->pDrvMediaAsync->pfnStartDiscard(pThis->pDrvMediaAsync, paRanges, cRanges, pIoReq);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if (pThis->hIoLogger)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync {
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync AssertRC(rc2);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync RTMemFree(pIoReq);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync }
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync RTMemFree(pIoReq);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync return rc;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync}
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnFlush */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintFlush(PPDMIMEDIA pInterface)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc = VINF_SUCCESS;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync VDIOLOGENT hIoLogEntry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = VDDbgIoLogStart(pThis->hIoLogger, false, VDDBGIOLOGREQ_FLUSH, 0,
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync 0, NULL, &hIoLogEntry);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync rc = pThis->pDrvMedia->pfnFlush(pThis->pDrvMedia);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(uint64_t) drvdiskintGetSize(PPDMIMEDIA pInterface)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(bool) drvdiskintIsReadOnly(PPDMIMEDIA pInterface)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnIsReadOnly(pThis->pDrvMedia);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosGetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosSetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosGetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PCPDMMEDIAGEOMETRY pLCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosSetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnGetUuid(pThis->pDrvMedia, pUuid);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync/** @copydoc PDMIMEDIA::pfnGetSectorSize */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsyncstatic DECLCALLBACK(uint32_t) drvdiskintGetSectorSize(PPDMIMEDIA pInterface)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync{
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync return pThis->pDrvMedia->pfnGetSectorSize(pThis->pDrvMedia);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync}
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync/** @copydoc PDMIMEDIA::pfnDiscard */
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsyncstatic DECLCALLBACK(int) drvdiskintDiscard(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync{
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync int rc = VINF_SUCCESS;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync VDIOLOGENT hIoLogEntry;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (pThis->hIoLogger)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsync rc = VDDbgIoLogStartDiscard(pThis->hIoLogger, false, paRanges, cRanges, &hIoLogEntry);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync AssertRC(rc);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync rc = pThis->pDrvMedia->pfnDiscard(pThis->pDrvMedia, paRanges, cRanges);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (pThis->hIoLogger)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync {
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, hIoLogEntry, rc, NULL);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync AssertRC(rc2);
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync }
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync if (pThis->fCheckConsistency)
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync rc = drvdiskintDiscardRecords(pThis, paRanges, cRanges);
a7a3c9676ea7ad004abad2b8dda301e0e733ff7dvboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync return rc;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync}
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/* -=-=-=-=- IMediaAsyncPort -=-=-=-=- */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync/** Makes a PDRVBLOCKASYNC out of a PPDMIMEDIAASYNCPORT. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync#define PDMIMEDIAASYNCPORT_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaAsyncPort))) )
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsyncstatic DECLCALLBACK(int) drvdiskintAsyncTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq)
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync{
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAASYNCPORT_2_DRVDISKINTEGRITY(pInterface);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync PDRVDISKAIOREQ pIoReq = (PDRVDISKAIOREQ)pvUser;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync int rc = VINF_SUCCESS;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync LogFlowFunc(("pIoReq=%#p\n", pIoReq));
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Remove from the active list. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (RT_SUCCESS(rcReq) && pThis->fCheckConsistency)
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync {
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ)
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync rc = drvdiskintReadVerify(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
288880cd72661161e8204e0ba61baa692c50bcccvboxsync else if ( pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE
288880cd72661161e8204e0ba61baa692c50bcccvboxsync && !pThis->fRecordWriteBeforeCompletion)
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync rc = drvdiskintWriteRecord(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_DISCARD)
4baafe1fca22c5d6994633d8a00278ddc4d734f1vboxsync rc = drvdiskintDiscardRecords(pThis, pIoReq->paRanges, pIoReq->cRanges);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ_AFTER_WRITE)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = drvdiskintReadAfterWriteVerify(pThis, pIoReq);
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync else
288880cd72661161e8204e0ba61baa692c50bcccvboxsync AssertMsg( pIoReq->enmTxDir == DRVDISKAIOTXDIR_FLUSH
288880cd72661161e8204e0ba61baa692c50bcccvboxsync || ( pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE
288880cd72661161e8204e0ba61baa692c50bcccvboxsync && pThis->fRecordWriteBeforeCompletion), ("Huh?\n"));
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync AssertRC(rc);
f687f34bd232be13744edbc0cc5155fa5d4540edvboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSGBUF SgBuf;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_READ)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync RTSgBufInit(&SgBuf, pIoReq->paSeg, pIoReq->cSeg);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, rc, &SgBuf);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync AssertRC(rc2);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync if ( pThis->fReadAfterWrite
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync && pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync {
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync pIoReq->enmTxDir = DRVDISKAIOTXDIR_READ_AFTER_WRITE;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync /* Readd because it was rmeoved above. */
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync if (pThis->fTraceRequests)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync drvdiskintIoReqAdd(pThis, pIoReq);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, pIoReq->off, pIoReq->paSeg, pIoReq->cSeg,
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync pIoReq->cbTransfer, pIoReq);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync if (rc == VINF_VD_ASYNC_IO_FINISHED)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync {
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = drvdiskintReadAfterWriteVerify(pThis, pIoReq);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync if (pThis->fTraceRequests)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync drvdiskintIoReqRemove(pThis, pIoReq);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync RTMemFree(pIoReq);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync }
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = VINF_SUCCESS;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync else if (RT_FAILURE(rc))
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync RTMemFree(pIoReq);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync }
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync else
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync {
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync void *pvUserComplete = pIoReq->pvUser;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync drvdiskintIoReqFree(pThis, pIoReq);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvUserComplete, rcReq);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync }
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync return rc;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync}
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync/* -=-=-=-=- IMediaPort -=-=-=-=- */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync/** Makes a PDRVBLOCK out of a PPDMIMEDIAPORT. */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync#define PDMIMEDIAPORT_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMediaPort))) )
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync/**
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation}
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsyncstatic DECLCALLBACK(int) drvdiskintQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync uint32_t *piInstance, uint32_t *piLUN)
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync{
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIAPORT_2_DRVDISKINTEGRITY(pInterface);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync return pThis->pDrvMediaPort->pfnQueryDeviceLocation(pThis->pDrvMediaPort, ppcszController,
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync piInstance, piLUN);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync}
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* -=-=-=-=- IBase -=-=-=-=- */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(void *) drvdiskintQueryInterface(PPDMIBASE pInterface, const char *pszIID)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNC, pThis->pDrvMediaAsync ? &pThis->IMediaAsync : NULL);
6114ff5789db75ff28460a056ed422ee03d8f0ebvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, &pThis->IMediaAsyncPort);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IMediaPort);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return NULL;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* -=-=-=-=- driver interface -=-=-=-=- */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic int drvdiskintTreeDestroy(PAVLRFOFFNODECORE pNode, void *pvUser)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)pNode;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pSeg->pbSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return VINF_SUCCESS;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @copydoc FNPDMDRVDESTRUCT
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(void) drvdiskintDestruct(PPDMDRVINS pDrvIns)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (pThis->pTreeSegments)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTAvlrFileOffsetDestroy(pThis->pTreeSegments, drvdiskintTreeDestroy, NULL);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pThis->pTreeSegments);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pThis->fRunning = false;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTSemEventSignal(pThis->SemEvent);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync RTSemEventDestroy(pThis->SemEvent);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync if (pThis->fCheckDoubleCompletion)
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync /* Free all requests */
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync while (pThis->papIoReq[pThis->iEntry])
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync RTMemFree(pThis->papIoReq[pThis->iEntry]);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->papIoReq[pThis->iEntry] = NULL;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->iEntry = (pThis->iEntry+1) % pThis->cEntries;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pThis->hIoLogger)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync VDDbgIoLogDestroy(pThis->hIoLogger);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Construct a disk integrity driver instance.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @copydoc FNPDMDRVCONSTRUCT
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync int rc = VINF_SUCCESS;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Validate configuration.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (!CFGMR3AreValuesValid(pCfg, "CheckConsistency\0"
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync "TraceRequests\0"
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync "CheckIntervalMs\0"
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync "ExpireIntervalMs\0"
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync "CheckDoubleCompletions\0"
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync "HistorySize\0"
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync "IoLog\0"
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync "PrepopulateRamDisk\0"
288880cd72661161e8204e0ba61baa692c50bcccvboxsync "ReadAfterWrite\0"
288880cd72661161e8204e0ba61baa692c50bcccvboxsync "RecordWriteBeforeCompletion\0"))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CheckConsistency", &pThis->fCheckConsistency, false);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = CFGMR3QueryBoolDef(pCfg, "TraceRequests", &pThis->fTraceRequests, false);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = CFGMR3QueryU32Def(pCfg, "CheckIntervalMs", &pThis->uCheckIntervalMs, 5000); /* 5 seconds */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = CFGMR3QueryU32Def(pCfg, "ExpireIntervalMs", &pThis->uExpireIntervalMs, 20000); /* 20 seconds */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync rc = CFGMR3QueryBoolDef(pCfg, "CheckDoubleCompletions", &pThis->fCheckDoubleCompletion, false);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync AssertRC(rc);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync rc = CFGMR3QueryU32Def(pCfg, "HistorySize", &pThis->cEntries, 512);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync AssertRC(rc);
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync rc = CFGMR3QueryBoolDef(pCfg, "PrepopulateRamDisk", &pThis->fPrepopulateRamDisk, false);
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync AssertRC(rc);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync rc = CFGMR3QueryBoolDef(pCfg, "ReadAfterWrite", &pThis->fReadAfterWrite, false);
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync AssertRC(rc);
288880cd72661161e8204e0ba61baa692c50bcccvboxsync rc = CFGMR3QueryBoolDef(pCfg, "RecordWriteBeforeCompletion", &pThis->fRecordWriteBeforeCompletion, false);
288880cd72661161e8204e0ba61baa692c50bcccvboxsync AssertRC(rc);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync char *pszIoLogFilename = NULL;
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync rc = CFGMR3QueryStringAlloc(pCfg, "IoLog", &pszIoLogFilename);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync Assert(RT_SUCCESS(rc) || rc == VERR_CFGM_VALUE_NOT_FOUND);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Initialize most of the data members.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->pDrvIns = pDrvIns;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* IBase. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pDrvIns->IBase.pfnQueryInterface = drvdiskintQueryInterface;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* IMedia */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnRead = drvdiskintRead;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnWrite = drvdiskintWrite;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnFlush = drvdiskintFlush;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnGetSize = drvdiskintGetSize;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnIsReadOnly = drvdiskintIsReadOnly;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvdiskintBiosGetPCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvdiskintBiosSetPCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvdiskintBiosGetLCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvdiskintBiosSetLCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnGetUuid = drvdiskintGetUuid;
f6fdefaddb6f26679be416ad6b10ca166d2a89e4vboxsync pThis->IMedia.pfnGetSectorSize = drvdiskintGetSectorSize;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /* IMediaAsync */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync pThis->IMediaAsync.pfnStartRead = drvdiskintStartRead;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync pThis->IMediaAsync.pfnStartWrite = drvdiskintStartWrite;
34b5a73592441cbfacb85c2f2261648c1d25ad31vboxsync pThis->IMediaAsync.pfnStartFlush = drvdiskintStartFlush;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync /* IMediaAsyncPort. */
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync pThis->IMediaAsyncPort.pfnTransferCompleteNotify = drvdiskintAsyncTransferCompleteNotify;
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /* IMediaPort. */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync pThis->IMediaPort.pfnQueryDeviceLocation = drvdiskintQueryDeviceLocation;
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /* Query the media port interface above us. */
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync if (!pThis->pDrvMediaPort)
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync N_("No media port inrerface above"));
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync /* Try to attach async media port interface above.*/
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync pThis->pDrvMediaAsyncPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAASYNCPORT);
cab115cfa31c584def7069312a1e23c3fc88533bvboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Try attach driver below and query it's media interface.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMIBASE pBase;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (RT_FAILURE(rc))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync N_("Failed to attach driver below us! %Rrc"), rc);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pThis->pDrvMedia)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync N_("No media or async media interface below"));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC);
b26de2ddb274b0e52de6652ad8b45259be2b9913vboxsync
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync if (pThis->pDrvMedia->pfnDiscard)
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync pThis->IMedia.pfnDiscard = drvdiskintDiscard;
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync if ( pThis->pDrvMediaAsync
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync && pThis->pDrvMediaAsync->pfnStartDiscard)
f4aad55f8addd816ef005845842a2418bbdc3ea2vboxsync pThis->IMediaAsync.pfnStartDiscard = drvdiskintStartDiscard;
f0c94ab153ce14e9218d36949f474a37a94ede9cvboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fCheckConsistency)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Create the AVL tree. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (!pThis->pTreeSegments)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = VERR_NO_MEMORY;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync if (pThis->fTraceRequests)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pThis->apReqActive); i++)
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync {
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pThis->apReqActive[i].pIoReq = NULL;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pThis->apReqActive[i].tsStart = 0;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pThis->iNextFreeSlot = 0;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync /* Init event semaphore. */
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = RTSemEventCreate(&pThis->SemEvent);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync pThis->fRunning = true;
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync rc = RTThreadCreate(&pThis->hThread, drvdiskIntIoReqExpiredCheck, pThis,
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync 0, RTTHREADTYPE_INFREQUENT_POLLER, 0, "DiskIntegrity");
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync AssertRC(rc);
3e88c818fff5c64b5eff43d5daf4596bd87230c5vboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync if (pThis->fCheckDoubleCompletion)
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync {
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->iEntry = 0;
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync pThis->papIoReq = (PDRVDISKAIOREQ *)RTMemAllocZ(pThis->cEntries * sizeof(PDRVDISKAIOREQ));
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync AssertPtr(pThis->papIoReq);
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync }
a98c2afd05b2949737f73ec954d227712f3b0146vboxsync
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync if (pszIoLogFilename)
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync {
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync rc = VDDbgIoLogCreate(&pThis->hIoLogger, pszIoLogFilename, VDDBG_IOLOG_LOG_DATA);
81c87bd7ea74d6f5a3a5aa28d5af33f5a7a989d5vboxsync MMR3HeapFree(pszIoLogFilename);
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync }
2531fa93e6b9dd1b60eac57f360a47e38aaf4d41vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync /* Read in all data before the start if requested. */
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (pThis->fPrepopulateRamDisk)
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync {
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync uint64_t cbDisk = 0;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync LogRel(("DiskIntegrity: Prepopulating RAM disk, this will take some time...\n"));
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync cbDisk = pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (cbDisk)
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync {
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync uint64_t off = 0;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync uint8_t abBuffer[_64K];
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync RTSGSEG Seg;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync Seg.pvSeg = abBuffer;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync while (cbDisk)
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync {
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync size_t cbThisRead = RT_MIN(cbDisk, sizeof(abBuffer));
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, off, abBuffer, cbThisRead);
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (RT_FAILURE(rc))
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync break;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (ASMBitFirstSet(abBuffer, sizeof(abBuffer) * 8) != -1)
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync {
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync Seg.cbSeg = cbThisRead;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync rc = drvdiskintWriteRecord(pThis, &Seg, 1,
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync off, cbThisRead);
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync if (RT_FAILURE(rc))
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync break;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync }
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync cbDisk -= cbThisRead;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync off += cbThisRead;
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync }
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync LogRel(("DiskIntegrity: Prepopulating RAM disk finished with %Rrc\n", rc));
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync }
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync else
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_INTERNAL_ERROR,
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync N_("DiskIntegrity: Error querying the media size below"));
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync }
20c3d72e5fbe893733ccbce7226540534f96aa07vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Block driver registration record.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncconst PDMDRVREG g_DrvDiskIntegrity =
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* u32Version */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_VERSION,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* szName */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "DiskIntegrity",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* szRCMod */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* szR0Mod */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pszDescription */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "Disk integrity driver.",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* fFlags */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* fClass. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_CLASS_BLOCK,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* cMaxInstances */
ad48e47654d22f79b025dc4b21cb162cb123801avboxsync ~0U,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* cbInstance */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync sizeof(DRVDISKINTEGRITY),
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnConstruct */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync drvdiskintConstruct,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnDestruct */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync drvdiskintDestruct,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnRelocate */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnIOCtl */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnPowerOn */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnReset */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnSuspend */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnResume */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnAttach */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnDetach */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnPowerOff */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnSoftReset */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* u32EndVersion */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_VERSION
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync};
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync