1
/* $Id: VDDbgIoLog.cpp $ */
4
* VD Debug library - I/O logger.
8
* Copyright (C) 2011-2012 Oracle Corporation
10
* This file is part of VirtualBox Open Source Edition (OSE), as
11
* available from http://www.virtualbox.org. This file is free software;
12
* you can redistribute it and/or modify it under the terms of the GNU
13
* General Public License (GPL) as published by the Free Software
14
* Foundation, in version 2 as it comes in the "COPYING" file of the
15
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
/*******************************************************************************
21
*******************************************************************************/
22
#define LOGGROUP LOGGROUP_DEFAULT
23
#include <VBox/vddbg.h>
27
#include <iprt/memcache.h>
28
#include <iprt/file.h>
29
#include <iprt/string.h>
30
#include <iprt/semaphore.h>
33
/*******************************************************************************
34
* Structures in a I/O log file, little endian *
35
*******************************************************************************/
41
typedef struct IoLogHeader
45
/** Flags for the log file. */
52
#define VDIOLOG_MAGIC "VDIOLOG"
54
/** Event type - I/O request start. */
55
#define VDIOLOG_EVENT_START 0x01
56
/** Event type - I/O request complete. */
57
#define VDIOLOG_EVENT_COMPLETE 0x02
60
* I/O log entry marking the start of a new I/O transaction.
63
typedef struct IoLogEntryStart
69
/** Flag whether this is a sync or async request. */
71
/** Id of the entry. */
73
/** Type dependent data. */
81
/** Size of the request. */
87
/** Number of ranges to discard. */
95
* I/O log entry markign the completion of an I/O transaction.
98
typedef struct IoLogEntryComplete
102
/** Id of the matching start entry. */
104
/** Status code the request completed with */
106
/** Number of milliseconds the request needed to complete. */
108
/** Number of bytes of data following this entry. */
109
uint64_t u64IoBuffer;
110
} IoLogEntryComplete;
114
typedef struct IoLogEntryDiscard
118
/** Number of bytes to discard. */
123
/*******************************************************************************
124
* Constants And Macros, Structures and Typedefs *
125
*******************************************************************************/
128
* I/O logger instance data.
130
typedef struct VDIOLOGGERINT
134
/** Current offset to append new entries to. */
135
uint64_t offWriteNext;
136
/** Offset to read the next entry from. */
137
uint64_t offReadNext;
138
/** Flags given during creation. */
140
/** Id for the next entry. */
142
/** Memory cache for the I/O log entries. */
143
RTMEMCACHE hMemCacheIoLogEntries;
144
/** Mutex section protecting the logger. */
146
/** Cached event type of the next event. */
147
uint32_t u32EventTypeNext;
148
/** Cached request type of the next request. */
149
VDDBGIOLOGREQ enmReqTypeNext;
151
/** Pointer to the internal I/O logger instance data. */
152
typedef VDIOLOGGERINT *PVDIOLOGGERINT;
155
* I/O log entry data.
157
typedef struct VDIOLOGENTINT
159
/** Id of the start entry. */
161
/** Timestamnp when the request started. */
163
/** Size of the buffer to write on success. */
166
/** Pointer to the internal I/O log entry data. */
167
typedef VDIOLOGENTINT *PVDIOLOGENTINT;
169
/*******************************************************************************
170
* Internal Functions *
171
*******************************************************************************/
174
* Creates a new empty I/O logger.
176
* @returns VBox status code.
177
* @param ppIoLogger Where to store the new I/O logger handle.
179
static int vddbgIoLoggerCreate(PVDIOLOGGERINT *ppIoLogger)
181
int rc = VINF_SUCCESS;
182
PVDIOLOGGERINT pIoLogger = NULL;
184
pIoLogger = (PVDIOLOGGERINT)RTMemAllocZ(sizeof(VDIOLOGGERINT));
187
rc = RTSemFastMutexCreate(&pIoLogger->hMtx);
190
rc = RTMemCacheCreate(&pIoLogger->hMemCacheIoLogEntries, sizeof(VDIOLOGENTINT),
191
0, UINT32_MAX, NULL, NULL, NULL, 0);
194
*ppIoLogger = pIoLogger;
198
RTMemFree(pIoLogger);
207
* Update the header of the I/O logger to the current state.
209
* @returns VBox status code.
210
* @param pIoLogger The I/O logger to update.
212
static int vddbgIoLoggerHeaderUpdate(PVDIOLOGGERINT pIoLogger)
214
int rc = VINF_SUCCESS;
217
memcpy(Hdr.szMagic, VDIOLOG_MAGIC, sizeof(Hdr.szMagic));
218
Hdr.fFlags = RT_H2LE_U32(pIoLogger->fFlags);
219
Hdr.u64Id = RT_H2LE_U64(pIoLogger->idNext);
220
rc = RTFileWriteAt(pIoLogger->hFile, 0, &Hdr, sizeof(Hdr), NULL);
226
* Writes data from the given S/G buffer into the I/O log.
228
* @returns VBox status code.
229
* @param pIoLogger The I/O logger to use.
230
* @param off The start offset in the log to write to.
231
* @param pSgBuf The S/G buffer to write.
232
* @param cbSgBuf How much data to write.
234
static int vddbgIoLogWriteSgBuf(PVDIOLOGGERINT pIoLogger, uint64_t off, PCRTSGBUF pSgBuf, size_t cbSgBuf)
236
int rc = VINF_SUCCESS;
239
RTSgBufClone(&SgBuf, pSgBuf);
244
size_t cbSeg = cbSgBuf;
246
pvSeg = RTSgBufGetNextSegment(&SgBuf, &cbSeg);
247
AssertPtrBreakStmt(pvSeg, rc = VERR_INTERNAL_ERROR);
249
rc = RTFileWriteAt(pIoLogger->hFile, off, pvSeg, cbSeg, NULL);
260
VBOXDDU_DECL(int) VDDbgIoLogCreate(PVDIOLOGGER phIoLogger, const char *pszFilename, uint32_t fFlags)
262
int rc = VINF_SUCCESS;
263
PVDIOLOGGERINT pIoLogger = NULL;
265
AssertPtrReturn(phIoLogger, VERR_INVALID_POINTER);
266
AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
267
AssertReturn(!(fFlags & ~VDDBG_IOLOG_VALID_MASK), VERR_INVALID_PARAMETER);
269
rc = vddbgIoLoggerCreate(&pIoLogger);
272
pIoLogger->fFlags = fFlags;
273
pIoLogger->hFile = NIL_RTFILE;
275
/* Create new log. */
276
rc = RTFileOpen(&pIoLogger->hFile, pszFilename, RTFILE_O_DENY_NONE | RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_READ);
279
rc = vddbgIoLoggerHeaderUpdate(pIoLogger);
282
pIoLogger->offWriteNext = sizeof(IoLogHeader);
283
pIoLogger->offReadNext = sizeof(IoLogHeader);
288
*phIoLogger = pIoLogger;
291
if (pIoLogger->hFile != NIL_RTFILE)
292
RTFileClose(pIoLogger->hFile);
293
RTMemFree(pIoLogger);
300
VBOXDDU_DECL(int) VDDbgIoLogOpen(PVDIOLOGGER phIoLogger, const char *pszFilename)
302
int rc = VINF_SUCCESS;
303
PVDIOLOGGERINT pIoLogger = NULL;
305
AssertPtrReturn(phIoLogger, VERR_INVALID_POINTER);
306
AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
308
rc = vddbgIoLoggerCreate(&pIoLogger);
311
/* open existing log. */
312
rc = RTFileOpen(&pIoLogger->hFile, pszFilename, RTFILE_O_DENY_NONE | RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_READ);
318
rc = RTFileGetSize(pIoLogger->hFile, &cbLog);
320
/* Read the header. */
322
rc = RTFileRead(pIoLogger->hFile, &Hdr, sizeof(Hdr), NULL);
325
&& !memcmp(Hdr.szMagic, VDIOLOG_MAGIC, sizeof(Hdr.szMagic)))
327
pIoLogger->fFlags = RT_LE2H_U32(Hdr.fFlags);
328
pIoLogger->offWriteNext = cbLog;
329
pIoLogger->offReadNext = sizeof(Hdr);
330
pIoLogger->idNext = RT_LE2H_U64(Hdr.u64Id);
331
*phIoLogger = pIoLogger;
333
else if (RT_SUCCESS(rc))
334
rc = VERR_INVALID_PARAMETER;
341
VBOXDDU_DECL(void) VDDbgIoLogDestroy(VDIOLOGGER hIoLogger)
343
PVDIOLOGGERINT pIoLogger = hIoLogger;
345
AssertPtrReturnVoid(pIoLogger);
347
vddbgIoLoggerHeaderUpdate(pIoLogger);
348
RTFileFlush(pIoLogger->hFile);
349
RTFileClose(pIoLogger->hFile);
350
RTMemCacheDestroy(pIoLogger->hMemCacheIoLogEntries);
351
RTSemFastMutexDestroy(pIoLogger->hMtx);
352
RTMemFree(pIoLogger);
355
VBOXDDU_DECL(int) VDDbgIoLogCommit(VDIOLOGGER hIoLogger)
357
int rc = VINF_SUCCESS;
358
PVDIOLOGGERINT pIoLogger = hIoLogger;
360
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
362
rc = vddbgIoLoggerHeaderUpdate(pIoLogger);
364
rc = RTFileFlush(pIoLogger->hFile);
369
VBOXDDU_DECL(uint32_t) VDDbgIoLogGetFlags(VDIOLOGGER hIoLogger)
371
PVDIOLOGGERINT pIoLogger = hIoLogger;
373
AssertPtrReturn(pIoLogger, 0);
375
return pIoLogger->fFlags;
378
VBOXDDU_DECL(int) VDDbgIoLogStart(VDIOLOGGER hIoLogger, bool fAsync, VDDBGIOLOGREQ enmTxDir, uint64_t off, size_t cbIo, PCRTSGBUF pSgBuf,
379
PVDIOLOGENT phIoLogEntry)
381
int rc = VINF_SUCCESS;
382
PVDIOLOGGERINT pIoLogger = hIoLogger;
383
PVDIOLOGENTINT pIoLogEntry = NULL;
385
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
386
AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER);
387
AssertReturn(enmTxDir > VDDBGIOLOGREQ_INVALID && enmTxDir <= VDDBGIOLOGREQ_FLUSH, VERR_INVALID_PARAMETER);
389
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
390
AssertRCReturn(rc, rc);
392
pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries);
395
IoLogEntryStart Entry;
397
pIoLogEntry->idStart = pIoLogger->idNext++;
399
Entry.u32Type = VDIOLOG_EVENT_START;
400
Entry.u8AsyncIo = fAsync ? 1 : 0;
401
Entry.u32ReqType = enmTxDir;
402
Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart);
403
Entry.Io.u64Off = RT_H2LE_U64(off);
404
Entry.Io.u64IoSize = RT_H2LE_U64(cbIo);
406
/* Write new entry. */
407
rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
410
pIoLogger->offWriteNext += sizeof(Entry);
412
if ( enmTxDir == VDDBGIOLOGREQ_WRITE
413
&& (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN))
416
rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, cbIo);
419
pIoLogger->offWriteNext -= sizeof(Entry);
420
rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
423
pIoLogger->offWriteNext += cbIo;
429
pIoLogEntry->tsStart = RTTimeProgramMilliTS();
431
if ( enmTxDir == VDDBGIOLOGREQ_READ
432
&& (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_READ))
433
pIoLogEntry->cbIo = cbIo;
435
pIoLogEntry->cbIo = 0;
437
*phIoLogEntry = pIoLogEntry;
442
RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
448
RTSemFastMutexRelease(pIoLogger->hMtx);
452
VBOXDDU_DECL(int) VDDbgIoLogStartDiscard(VDIOLOGGER hIoLogger, bool fAsync, PCRTRANGE paRanges, unsigned cRanges,
453
PVDIOLOGENT phIoLogEntry)
455
int rc = VINF_SUCCESS;
456
PVDIOLOGGERINT pIoLogger = hIoLogger;
457
PVDIOLOGENTINT pIoLogEntry = NULL;
459
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
460
AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER);
462
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
463
AssertRCReturn(rc, rc);
465
pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries);
468
IoLogEntryStart Entry;
470
pIoLogEntry->idStart = pIoLogger->idNext++;
472
Entry.u32Type = VDIOLOG_EVENT_START;
473
Entry.u8AsyncIo = fAsync ? 1 : 0;
474
Entry.u32ReqType = VDDBGIOLOGREQ_DISCARD;
475
Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart);
476
Entry.Discard.cRanges = RT_H2LE_U32(cRanges);
478
/* Write new entry. */
479
rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
482
pIoLogger->offWriteNext += sizeof(Entry);
484
IoLogEntryDiscard DiscardRange;
486
for (unsigned i = 0; i < cRanges; i++)
488
DiscardRange.u64Off = RT_H2LE_U64(paRanges[i].offStart);
489
DiscardRange.u32Discard = RT_H2LE_U32(paRanges[i].cbRange);
490
rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext + i*sizeof(DiscardRange),
491
&DiscardRange, sizeof(DiscardRange), NULL);
498
pIoLogger->offWriteNext -= sizeof(Entry);
499
rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
502
pIoLogger->offWriteNext += cRanges * sizeof(DiscardRange);
507
pIoLogEntry->tsStart = RTTimeProgramMilliTS();
508
pIoLogEntry->cbIo = 0;
510
*phIoLogEntry = pIoLogEntry;
515
RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
521
RTSemFastMutexRelease(pIoLogger->hMtx);
525
VBOXDDU_DECL(int) VDDbgIoLogComplete(VDIOLOGGER hIoLogger, VDIOLOGENT hIoLogEntry, int rcReq, PCRTSGBUF pSgBuf)
527
int rc = VINF_SUCCESS;
528
PVDIOLOGGERINT pIoLogger = hIoLogger;
529
PVDIOLOGENTINT pIoLogEntry = hIoLogEntry;
531
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
532
AssertPtrReturn(pIoLogEntry, VERR_INVALID_HANDLE);
534
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
535
AssertRCReturn(rc, rc);
537
IoLogEntryComplete Entry;
539
Entry.u32Type = VDIOLOG_EVENT_COMPLETE;
540
Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart);
541
Entry.msDuration = RTTimeProgramMilliTS() - RT_H2LE_U64(pIoLogEntry->tsStart);
542
Entry.i32Rc = (int32_t)RT_H2LE_U32((uint32_t)rcReq);
543
Entry.u64IoBuffer = RT_H2LE_U64(pIoLogEntry->cbIo);
545
/* Write new entry. */
546
rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
549
pIoLogger->offWriteNext += sizeof(Entry);
551
if (pIoLogEntry->cbIo)
553
rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, pIoLogEntry->cbIo);
555
pIoLogger->offWriteNext += pIoLogEntry->cbIo;
558
pIoLogger->offWriteNext -= sizeof(Entry);
559
rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
564
RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
565
RTSemFastMutexRelease(pIoLogger->hMtx);
569
VBOXDDU_DECL(int) VDDbgIoLogEventTypeGetNext(VDIOLOGGER hIoLogger, VDIOLOGEVENT *penmEvent)
571
int rc = VINF_SUCCESS;
572
PVDIOLOGGERINT pIoLogger = hIoLogger;
574
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
575
AssertPtrReturn(penmEvent, VERR_INVALID_POINTER);
577
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
578
AssertRCReturn(rc, rc);
580
if (pIoLogger->offReadNext == pIoLogger->offWriteNext)
582
*penmEvent = VDIOLOGEVENT_END;
583
RTSemFastMutexRelease(pIoLogger->hMtx);
587
if (!pIoLogger->u32EventTypeNext)
590
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &abBuf, sizeof(abBuf), NULL);
593
pIoLogger->u32EventTypeNext = abBuf[0];
594
pIoLogger->enmReqTypeNext = (VDDBGIOLOGREQ)abBuf[1];
600
Assert(pIoLogger->u32EventTypeNext != VDIOLOGEVENT_INVALID);
602
switch (pIoLogger->u32EventTypeNext)
604
case VDIOLOG_EVENT_START:
605
*penmEvent = VDIOLOGEVENT_START;
607
case VDIOLOG_EVENT_COMPLETE:
608
*penmEvent = VDIOLOGEVENT_COMPLETE;
611
AssertMsgFailed(("Invalid event type %d\n", pIoLogger->u32EventTypeNext));
615
RTSemFastMutexRelease(pIoLogger->hMtx);
619
VBOXDDU_DECL(int) VDDbgIoLogReqTypeGetNext(VDIOLOGGER hIoLogger, PVDDBGIOLOGREQ penmReq)
621
int rc = VINF_SUCCESS;
622
PVDIOLOGGERINT pIoLogger = hIoLogger;
624
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
625
AssertPtrReturn(penmReq, VERR_INVALID_POINTER);
627
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
628
AssertRCReturn(rc, rc);
630
if (pIoLogger->offReadNext == pIoLogger->offWriteNext)
632
*penmReq = VDDBGIOLOGREQ_INVALID;
633
RTSemFastMutexRelease(pIoLogger->hMtx);
634
return VERR_INVALID_STATE;
639
Assert(pIoLogger->enmReqTypeNext != VDDBGIOLOGREQ_INVALID);
640
*penmReq = pIoLogger->enmReqTypeNext;
643
RTSemFastMutexRelease(pIoLogger->hMtx);
647
VBOXDDU_DECL(int) VDDbgIoLogEventGetStart(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync,
648
uint64_t *poff, size_t *pcbIo, size_t cbBuf, void *pvBuf)
650
int rc = VINF_SUCCESS;
651
PVDIOLOGGERINT pIoLogger = hIoLogger;
653
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
654
AssertPtrReturn(pidEvent, VERR_INVALID_POINTER);
655
AssertPtrReturn(pfAsync, VERR_INVALID_POINTER);
656
AssertPtrReturn(poff, VERR_INVALID_POINTER);
657
AssertPtrReturn(pcbIo, VERR_INVALID_POINTER);
659
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
660
AssertRCReturn(rc, rc);
662
if (pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START)
664
IoLogEntryStart Entry;
665
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL);
668
*pfAsync = (bool)Entry.u8AsyncIo;
669
*pidEvent = RT_LE2H_U64(Entry.u64Id);
670
*poff = RT_LE2H_U64(Entry.Io.u64Off);
671
*pcbIo = RT_LE2H_U64(Entry.Io.u64IoSize);
673
if ( pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_WRITE
674
&& (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN))
678
rc = VERR_BUFFER_OVERFLOW;
680
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + sizeof(Entry), pvBuf, *pcbIo, NULL);
682
if (rc != VERR_BUFFER_OVERFLOW)
683
pIoLogger->offReadNext += *pcbIo + sizeof(Entry);
686
pIoLogger->offReadNext += sizeof(Entry);
690
rc = VERR_INVALID_STATE;
693
pIoLogger->u32EventTypeNext = 0;
695
RTSemFastMutexRelease(pIoLogger->hMtx);
699
VBOXDDU_DECL(int) VDDbgIoLogEventGetStartDiscard(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync,
700
PRTRANGE *ppaRanges, unsigned *pcRanges)
702
int rc = VINF_SUCCESS;
703
PVDIOLOGGERINT pIoLogger = hIoLogger;
705
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
706
AssertPtrReturn(pidEvent, VERR_INVALID_POINTER);
707
AssertPtrReturn(pfAsync, VERR_INVALID_POINTER);
709
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
710
AssertRCReturn(rc, rc);
712
if ( pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START
713
&& pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_DISCARD)
715
IoLogEntryStart Entry;
716
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL);
719
PRTRANGE paRanges = NULL;
720
IoLogEntryDiscard DiscardRange;
722
pIoLogger->offReadNext += sizeof(Entry);
723
*pfAsync = (bool)Entry.u8AsyncIo;
724
*pidEvent = RT_LE2H_U64(Entry.u64Id);
725
*pcRanges = RT_LE2H_U32(Entry.Discard.cRanges);
727
paRanges = (PRTRANGE)RTMemAllocZ(*pcRanges * sizeof(RTRANGE));
730
for (unsigned i = 0; i < *pcRanges; i++)
732
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + i*sizeof(DiscardRange),
733
&DiscardRange, sizeof(DiscardRange), NULL);
737
paRanges[i].offStart = RT_LE2H_U64(DiscardRange.u64Off);
738
paRanges[i].cbRange = RT_LE2H_U32(DiscardRange.u32Discard);
743
pIoLogger->offReadNext += *pcRanges * sizeof(DiscardRange);
744
*ppaRanges = paRanges;
747
pIoLogger->offReadNext -= sizeof(Entry);
754
rc = VERR_INVALID_STATE;
757
pIoLogger->u32EventTypeNext = 0;
759
RTSemFastMutexRelease(pIoLogger->hMtx);
764
VBOXDDU_DECL(int) VDDbgIoLogEventGetComplete(VDIOLOGGER hIoLogger, uint64_t *pidEvent, int *pRc,
765
uint64_t *pmsDuration, size_t *pcbIo, size_t cbBuf, void *pvBuf)
767
int rc = VINF_SUCCESS;
768
PVDIOLOGGERINT pIoLogger = hIoLogger;
770
AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
771
AssertPtrReturn(pidEvent, VERR_INVALID_POINTER);
772
AssertPtrReturn(pmsDuration, VERR_INVALID_POINTER);
773
AssertPtrReturn(pcbIo, VERR_INVALID_POINTER);
775
rc = RTSemFastMutexRequest(pIoLogger->hMtx);
776
AssertRCReturn(rc, rc);
778
if (pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_COMPLETE)
780
IoLogEntryComplete Entry;
781
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL);
784
*pidEvent = RT_LE2H_U64(Entry.u64Id);
785
*pRc = (int)RT_LE2H_U32((int32_t)Entry.i32Rc);
786
*pmsDuration = RT_LE2H_U64(Entry.msDuration);
787
*pcbIo = RT_LE2H_U64(Entry.u64IoBuffer);
793
rc = VERR_BUFFER_OVERFLOW;
795
rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + sizeof(Entry), pvBuf, *pcbIo, NULL);
797
if (rc != VERR_BUFFER_OVERFLOW)
798
pIoLogger->offReadNext += *pcbIo + sizeof(Entry);
801
pIoLogger->offReadNext += sizeof(Entry);
805
rc = VERR_INVALID_STATE;
808
pIoLogger->u32EventTypeNext = 0;
810
RTSemFastMutexRelease(pIoLogger->hMtx);