VirtualBox

source: vbox/trunk/src/VBox/Storage/Debug/VDDbgIoLog.cpp@ 38631

最後變更 在這個檔案從38631是 38631,由 vboxsync 提交於 14 年 前

IoLog+DrvDiskIntegrity: Add logging of discard requests

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 24.3 KB
 
1/* $Id: VDDbgIoLog.cpp 38631 2011-09-05 10:53:16Z vboxsync $ */
2/** @file
3 *
4 * VD Debug library - I/O logger.
5 */
6
7/*
8 * Copyright (C) 2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.alldomusa.eu.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.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOGGROUP LOGGROUP_DEFAULT
23#include <VBox/vddbg.h>
24#include <VBox/err.h>
25#include <VBox/log.h>
26#include <iprt/mem.h>
27#include <iprt/memcache.h>
28#include <iprt/file.h>
29#include <iprt/string.h>
30#include <iprt/semaphore.h>
31
32/*******************************************************************************
33* Structures in a I/O log file, little endian *
34*******************************************************************************/
35
36/**
37 * I/O log header.
38 */
39#pragma pack(1)
40typedef struct IoLogHeader
41{
42 /** Magic string */
43 char szMagic[8];
44 /** Flags for the log file. */
45 uint32_t fFlags;
46 /** Id counter. */
47 uint64_t u64Id;
48} IoLogHeader;
49#pragma pack()
50
51#define VDIOLOG_MAGIC "VDIOLOG"
52
53/** Event type - I/O request start. */
54#define VDIOLOG_EVENT_START 0x01
55/** Event type - I/O request complete. */
56#define VDIOLOG_EVENT_COMPLETE 0x02
57
58/**
59 * I/O log entry marking the start of a new I/O transaction.
60 */
61#pragma pack(1)
62typedef struct IoLogEntryStart
63{
64 /** Event type. */
65 uint32_t u32Type;
66 /** Transfer type. */
67 uint32_t u32ReqType;
68 /** Flag whether this is a sync or async request. */
69 uint8_t u8AsyncIo;
70 /** Id of the entry. */
71 uint64_t u64Id;
72 /** Type dependent data. */
73 union
74 {
75 /** I/O. */
76 struct
77 {
78 /** Start offset. */
79 uint64_t u64Off;
80 /** Size of the request. */
81 uint64_t u64IoSize;
82 } Io;
83 /** Discard */
84 struct
85 {
86 /** Number of ranges to discard. */
87 uint32_t cRanges;
88 } Discard;
89 };
90} IoLogEntryStart;
91#pragma pack()
92
93/**
94 * I/O log entry markign the completion of an I/O transaction.
95 */
96#pragma pack(1)
97typedef struct IoLogEntryComplete
98{
99 /** Event type. */
100 uint8_t u32Type;
101 /** Id of the matching start entry. */
102 uint64_t u64Id;
103 /** Status code the request completed with */
104 int32_t i32Rc;
105 /** Number of milliseconds the request needed to complete. */
106 uint64_t msDuration;
107 /** Number of bytes of data following this entry. */
108 uint64_t u64IoBuffer;
109} IoLogEntryComplete;
110#pragma pack()
111
112#pragma pack(1)
113typedef struct IoLogEntryDiscard
114{
115 /** Start offset. */
116 uint64_t u64Off;
117 /** Number of bytes to discard. */
118 uint32_t u32Discard;
119} IoLogEntryDiscard;
120#pragma pack()
121
122/*******************************************************************************
123* Constants And Macros, Structures and Typedefs *
124*******************************************************************************/
125
126/**
127 * I/O logger instance data.
128 */
129typedef struct VDIOLOGGERINT
130{
131 /** File handle. */
132 RTFILE hFile;
133 /** Current offset to append new entries to. */
134 uint64_t offWriteNext;
135 /** Offset to read the next entry from. */
136 uint64_t offReadNext;
137 /** Flags given during creation. */
138 uint32_t fFlags;
139 /** Id for the next entry. */
140 uint64_t idNext;
141 /** Memory cache for the I/O log entries. */
142 RTMEMCACHE hMemCacheIoLogEntries;
143 /** Mutex section protecting the logger. */
144 RTSEMFASTMUTEX hMtx;
145 /** Cached event type of the next event. */
146 uint32_t u32EventTypeNext;
147 /** Cached request type of the next request. */
148 VDDBGIOLOGREQ enmReqTypeNext;
149} VDIOLOGGERINT;
150/** Pointer to the internal I/O logger instance data. */
151typedef VDIOLOGGERINT *PVDIOLOGGERINT;
152
153/**
154 * I/O log entry data.
155 */
156typedef struct VDIOLOGENTINT
157{
158 /** Id of the start entry. */
159 uint64_t idStart;
160 /** Timestamnp when the request started. */
161 uint64_t tsStart;
162 /** Size of the buffer to write on success. */
163 size_t cbIo;
164} VDIOLOGENTINT;
165/** Pointer to the internal I/O log entry data. */
166typedef VDIOLOGENTINT *PVDIOLOGENTINT;
167
168/*******************************************************************************
169* Internal Functions *
170*******************************************************************************/
171
172/**
173 * Creates a new empty I/O logger.
174 *
175 * @returns VBox status code.
176 * @param ppIoLogger Where to store the new I/O logger handle.
177 */
178static int vddbgIoLoggerCreate(PVDIOLOGGERINT *ppIoLogger)
179{
180 int rc = VINF_SUCCESS;
181 PVDIOLOGGERINT pIoLogger = NULL;
182
183 pIoLogger = (PVDIOLOGGERINT)RTMemAllocZ(sizeof(VDIOLOGGERINT));
184 if (pIoLogger)
185 {
186 rc = RTSemFastMutexCreate(&pIoLogger->hMtx);
187 if (RT_SUCCESS(rc))
188 {
189 rc = RTMemCacheCreate(&pIoLogger->hMemCacheIoLogEntries, sizeof(VDIOLOGENTINT),
190 0, UINT32_MAX, NULL, NULL, NULL, 0);
191 if (RT_SUCCESS(rc))
192 {
193 *ppIoLogger = pIoLogger;
194 return rc;
195 }
196 }
197 RTMemFree(pIoLogger);
198 }
199 else
200 rc = VERR_NO_MEMORY;
201
202 return rc;
203}
204
205/**
206 * Update the header of the I/O logger to the current state.
207 *
208 * @returns VBox status code.
209 * @param pIoLogger The I/O logger to update.
210 */
211static int vddbgIoLoggerHeaderUpdate(PVDIOLOGGERINT pIoLogger)
212{
213 int rc = VINF_SUCCESS;
214 IoLogHeader Hdr;
215
216 memcpy(Hdr.szMagic, VDIOLOG_MAGIC, sizeof(Hdr.szMagic));
217 Hdr.fFlags = RT_H2LE_U32(pIoLogger->fFlags);
218 Hdr.u64Id = RT_H2LE_U64(pIoLogger->idNext);
219 rc = RTFileWriteAt(pIoLogger->hFile, 0, &Hdr, sizeof(Hdr), NULL);
220
221 return rc;
222}
223
224/**
225 * Writes data from the given S/G buffer into the I/O log.
226 *
227 * @returns VBox status code.
228 * @param pIoLogger The I/O logger to use.
229 * @param off The start offset in the log to write to.
230 * @param pSgBuf The S/G buffer to write.
231 * @param cbSgBuf How much data to write.
232 */
233static int vddbgIoLogWriteSgBuf(PVDIOLOGGERINT pIoLogger, uint64_t off, PCRTSGBUF pSgBuf, size_t cbSgBuf)
234{
235 int rc = VINF_SUCCESS;
236 RTSGBUF SgBuf;
237
238 RTSgBufClone(&SgBuf, pSgBuf);
239
240 while (cbSgBuf)
241 {
242 void *pvSeg;
243 size_t cbSeg = cbSgBuf;
244
245 pvSeg = RTSgBufGetNextSegment(&SgBuf, &cbSeg);
246 AssertPtrBreakStmt(pvSeg, rc = VERR_INTERNAL_ERROR);
247
248 rc = RTFileWriteAt(pIoLogger->hFile, off, pvSeg, cbSeg, NULL);
249 if (RT_FAILURE(rc))
250 break;
251
252 cbSgBuf -= cbSeg;
253 off += cbSeg;
254 }
255
256 return rc;
257}
258
259VBOXDDU_DECL(int) VDDbgIoLogCreate(PVDIOLOGGER phIoLogger, const char *pszFilename, uint32_t fFlags)
260{
261 int rc = VINF_SUCCESS;
262 PVDIOLOGGERINT pIoLogger = NULL;
263
264 AssertPtrReturn(phIoLogger, VERR_INVALID_POINTER);
265 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
266 AssertReturn(!(fFlags & ~VDDBG_IOLOG_VALID_MASK), VERR_INVALID_PARAMETER);
267
268 rc = vddbgIoLoggerCreate(&pIoLogger);
269 if (RT_SUCCESS(rc))
270 {
271 pIoLogger->fFlags = fFlags;
272 pIoLogger->hFile = NIL_RTFILE;
273
274 /* Create new log. */
275 rc = RTFileOpen(&pIoLogger->hFile, pszFilename, RTFILE_O_DENY_NONE | RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_READ);
276 if (RT_SUCCESS(rc))
277 {
278 rc = vddbgIoLoggerHeaderUpdate(pIoLogger);
279 if (RT_SUCCESS(rc))
280 {
281 pIoLogger->offWriteNext = sizeof(IoLogHeader);
282 pIoLogger->offReadNext = sizeof(IoLogHeader);
283 }
284 }
285
286 if (RT_SUCCESS(rc))
287 *phIoLogger = pIoLogger;
288 else
289 {
290 if (pIoLogger->hFile != NIL_RTFILE)
291 RTFileClose(pIoLogger->hFile);
292 RTMemFree(pIoLogger);
293 }
294 }
295
296 return rc;
297}
298
299VBOXDDU_DECL(int) VDDbgIoLogOpen(PVDIOLOGGER phIoLogger, const char *pszFilename)
300{
301 int rc = VINF_SUCCESS;
302 PVDIOLOGGERINT pIoLogger = NULL;
303
304 AssertPtrReturn(phIoLogger, VERR_INVALID_POINTER);
305 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
306
307 rc = vddbgIoLoggerCreate(&pIoLogger);
308 if (RT_SUCCESS(rc))
309 {
310 /* open existing log. */
311 rc = RTFileOpen(&pIoLogger->hFile, pszFilename, RTFILE_O_DENY_NONE | RTFILE_O_OPEN | RTFILE_O_WRITE | RTFILE_O_READ);
312 if (RT_SUCCESS(rc))
313 {
314 IoLogHeader Hdr;
315 uint64_t cbLog;
316
317 rc = RTFileGetSize(pIoLogger->hFile, &cbLog);
318
319 /* Read the header. */
320 if (RT_SUCCESS(rc))
321 rc = RTFileRead(pIoLogger->hFile, &Hdr, sizeof(Hdr), NULL);
322
323 if ( RT_SUCCESS(rc)
324 && !memcmp(Hdr.szMagic, VDIOLOG_MAGIC, sizeof(Hdr.szMagic)))
325 {
326 pIoLogger->fFlags = RT_LE2H_U32(Hdr.fFlags);
327 pIoLogger->offWriteNext = cbLog;
328 pIoLogger->offReadNext = sizeof(Hdr);
329 pIoLogger->idNext = RT_LE2H_U64(Hdr.u64Id);
330 }
331 else if (RT_SUCCESS(rc))
332 rc = VERR_INVALID_PARAMETER;
333 }
334 }
335
336 return rc;
337}
338
339VBOXDDU_DECL(void) VDDbgIoLogDestroy(VDIOLOGGER hIoLogger)
340{
341 PVDIOLOGGERINT pIoLogger = hIoLogger;
342
343 AssertPtrReturnVoid(pIoLogger);
344
345 vddbgIoLoggerHeaderUpdate(pIoLogger);
346 RTFileFlush(pIoLogger->hFile);
347 RTFileClose(pIoLogger->hFile);
348 RTMemCacheDestroy(pIoLogger->hMemCacheIoLogEntries);
349 RTSemFastMutexDestroy(pIoLogger->hMtx);
350 RTMemFree(pIoLogger);
351}
352
353VBOXDDU_DECL(int) VDDbgIoLogCommit(VDIOLOGGER hIoLogger)
354{
355 int rc = VINF_SUCCESS;
356 PVDIOLOGGERINT pIoLogger = hIoLogger;
357
358 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
359
360 rc = vddbgIoLoggerHeaderUpdate(pIoLogger);
361 if (RT_SUCCESS(rc))
362 rc = RTFileFlush(pIoLogger->hFile);
363
364 return rc;
365}
366
367VBOXDDU_DECL(uint32_t) VDDbgIoLogGetFlags(VDIOLOGGER hIoLogger)
368{
369 PVDIOLOGGERINT pIoLogger = hIoLogger;
370
371 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
372
373 return pIoLogger->fFlags;
374}
375
376VBOXDDU_DECL(int) VDDbgIoLogStart(VDIOLOGGER hIoLogger, bool fAsync, VDDBGIOLOGREQ enmTxDir, uint64_t off, size_t cbIo, PCRTSGBUF pSgBuf,
377 PVDIOLOGENT phIoLogEntry)
378{
379 int rc = VINF_SUCCESS;
380 PVDIOLOGGERINT pIoLogger = hIoLogger;
381 PVDIOLOGENTINT pIoLogEntry = NULL;
382
383 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
384 AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER);
385 AssertReturn(enmTxDir > VDDBGIOLOGREQ_INVALID && enmTxDir <= VDDBGIOLOGREQ_FLUSH, VERR_INVALID_PARAMETER);
386
387 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
388 AssertRCReturn(rc, rc);
389
390 pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries);
391 if (pIoLogEntry)
392 {
393 IoLogEntryStart Entry;
394
395 pIoLogEntry->idStart = pIoLogger->idNext++;
396
397 Entry.u32Type = VDIOLOG_EVENT_START;
398 Entry.u8AsyncIo = fAsync ? 1 : 0;
399 Entry.u32ReqType = enmTxDir;
400 Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart);
401 Entry.Io.u64Off = RT_H2LE_U64(off);
402 Entry.Io.u64IoSize = RT_H2LE_U64(cbIo);
403
404 /* Write new entry. */
405 rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
406 if (RT_SUCCESS(rc))
407 {
408 pIoLogger->offWriteNext += sizeof(Entry);
409
410 if ( enmTxDir == VDDBGIOLOGREQ_WRITE
411 && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN))
412 {
413 /* Write data. */
414 rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, cbIo);
415 if (RT_FAILURE(rc))
416 {
417 pIoLogger->offWriteNext -= sizeof(Entry);
418 rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
419 }
420 else
421 pIoLogger->offWriteNext += cbIo;
422 }
423 }
424
425 if (RT_SUCCESS(rc))
426 {
427 pIoLogEntry->tsStart = RTTimeProgramMilliTS();
428
429 if ( enmTxDir == VDDBGIOLOGREQ_READ
430 && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_READ))
431 pIoLogEntry->cbIo = cbIo;
432 else
433 pIoLogEntry->cbIo = 0;
434
435 *phIoLogEntry = pIoLogEntry;
436 }
437 else
438 {
439 pIoLogger->idNext--;
440 RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
441 }
442 }
443 else
444 rc = VERR_NO_MEMORY;
445
446 RTSemFastMutexRelease(pIoLogger->hMtx);
447 return rc;
448}
449
450VBOXDDU_DECL(int) VDDbgIoLogStartDiscard(VDIOLOGGER hIoLogger, bool fAsync, PVDRANGE paRanges, unsigned cRanges,
451 PVDIOLOGENT phIoLogEntry)
452{
453 int rc = VINF_SUCCESS;
454 PVDIOLOGGERINT pIoLogger = hIoLogger;
455 PVDIOLOGENTINT pIoLogEntry = NULL;
456
457 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
458 AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER);
459
460 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
461 AssertRCReturn(rc, rc);
462
463 pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries);
464 if (pIoLogEntry)
465 {
466 IoLogEntryStart Entry;
467
468 pIoLogEntry->idStart = pIoLogger->idNext++;
469
470 Entry.u32Type = VDIOLOG_EVENT_START;
471 Entry.u8AsyncIo = fAsync ? 1 : 0;
472 Entry.u32ReqType = VDDBGIOLOGREQ_DISCARD;
473 Entry.Discard.cRanges = RT_H2LE_U32(cRanges);
474
475 /* Write new entry. */
476 rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
477 if (RT_SUCCESS(rc))
478 {
479 pIoLogger->offWriteNext += sizeof(Entry);
480
481 IoLogEntryDiscard DiscardRange;
482
483 for (unsigned i = 0; i < cRanges; i++)
484 {
485 DiscardRange.u64Off = RT_H2LE_U64(paRanges[i].offStart);
486 DiscardRange.u32Discard = RT_H2LE_U32(paRanges[i].cbRange);
487 rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext + i*sizeof(DiscardRange),
488 &DiscardRange, sizeof(DiscardRange), NULL);
489 if (RT_FAILURE(rc))
490 break;
491 }
492
493 if (RT_FAILURE(rc))
494 {
495 pIoLogger->offWriteNext -= sizeof(Entry);
496 rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
497 }
498 else
499 pIoLogger->offWriteNext += cRanges * sizeof(DiscardRange);
500 }
501
502 if (RT_SUCCESS(rc))
503 {
504 pIoLogEntry->tsStart = RTTimeProgramMilliTS();
505 pIoLogEntry->cbIo = 0;
506
507 *phIoLogEntry = pIoLogEntry;
508 }
509 else
510 {
511 pIoLogger->idNext--;
512 RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
513 }
514 }
515 else
516 rc = VERR_NO_MEMORY;
517
518 RTSemFastMutexRelease(pIoLogger->hMtx);
519 return rc;
520}
521
522VBOXDDU_DECL(int) VDDbgIoLogComplete(VDIOLOGGER hIoLogger, VDIOLOGENT hIoLogEntry, int rcReq, PCRTSGBUF pSgBuf)
523{
524 int rc = VINF_SUCCESS;
525 PVDIOLOGGERINT pIoLogger = hIoLogger;
526 PVDIOLOGENTINT pIoLogEntry = hIoLogEntry;
527
528 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
529 AssertPtrReturn(pIoLogEntry, VERR_INVALID_HANDLE);
530
531 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
532 AssertRCReturn(rc, rc);
533
534 IoLogEntryComplete Entry;
535
536 Entry.u32Type = VDIOLOG_EVENT_COMPLETE;
537 Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart);
538 Entry.msDuration = RTTimeProgramMilliTS() - RT_H2LE_U64(pIoLogEntry->tsStart);
539 Entry.i32Rc = (int32_t)RT_H2LE_U32((uint32_t)rcReq);
540 Entry.u64IoBuffer = RT_H2LE_U64(pIoLogEntry->cbIo);
541
542 /* Write new entry. */
543 rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL);
544 if (RT_SUCCESS(rc))
545 {
546 pIoLogger->offWriteNext += sizeof(Entry);
547
548 if (pIoLogEntry->cbIo)
549 {
550 rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, pIoLogEntry->cbIo);
551 if (RT_SUCCESS(rc))
552 pIoLogger->offWriteNext += pIoLogEntry->cbIo;
553 else
554 {
555 pIoLogger->offWriteNext -= sizeof(Entry);
556 rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext);
557 }
558 }
559 }
560
561 RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry);
562 RTSemFastMutexRelease(pIoLogger->hMtx);
563 return rc;
564}
565
566VBOXDDU_DECL(int) VDDbgIoLogEventTypeGetNext(VDIOLOGGER hIoLogger, VDIOLOGEVENT *penmEvent)
567{
568 int rc = VINF_SUCCESS;
569 PVDIOLOGGERINT pIoLogger = hIoLogger;
570
571 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
572 AssertPtrReturn(penmEvent, VERR_INVALID_POINTER);
573
574 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
575 AssertRCReturn(rc, rc);
576
577 if (pIoLogger->offReadNext == pIoLogger->offWriteNext)
578 {
579 *penmEvent = VDIOLOGEVENT_END;
580 RTSemFastMutexRelease(pIoLogger->hMtx);
581 return VINF_SUCCESS;
582 }
583
584 if (!pIoLogger->u32EventTypeNext)
585 {
586 uint32_t abBuf[2];
587 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &abBuf, sizeof(abBuf), NULL);
588 if (RT_SUCCESS(rc))
589 {
590 pIoLogger->u32EventTypeNext = (VDIOLOGEVENT)abBuf[0];
591 pIoLogger->enmReqTypeNext = (VDDBGIOLOGREQ)abBuf[1];
592 }
593 }
594
595 if (RT_SUCCESS(rc))
596 {
597 Assert(pIoLogger->u32EventTypeNext != VDIOLOGEVENT_INVALID);
598
599 switch (pIoLogger->u32EventTypeNext)
600 {
601 case VDIOLOG_EVENT_START:
602 *penmEvent = VDIOLOGEVENT_START;
603 break;
604 case VDIOLOG_EVENT_COMPLETE:
605 *penmEvent = VDIOLOGEVENT_COMPLETE;
606 break;
607 default:
608 AssertMsgFailed(("Invalid event type %d\n", pIoLogger->u32EventTypeNext));
609 }
610 }
611
612 RTSemFastMutexRelease(pIoLogger->hMtx);
613 return rc;
614}
615
616VBOXDDU_DECL(int) VDDbgIoLogReqTypeGetNext(VDIOLOGGER hIoLogger, PVDDBGIOLOGREQ penmReq)
617{
618 int rc = VINF_SUCCESS;
619 PVDIOLOGGERINT pIoLogger = hIoLogger;
620
621 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
622 AssertPtrReturn(penmReq, VERR_INVALID_POINTER);
623
624 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
625 AssertRCReturn(rc, rc);
626
627 if (pIoLogger->offReadNext == pIoLogger->offWriteNext)
628 {
629 *penmReq = VDDBGIOLOGREQ_INVALID;
630 RTSemFastMutexRelease(pIoLogger->hMtx);
631 return VERR_INVALID_STATE;
632 }
633
634 if (RT_SUCCESS(rc))
635 {
636 Assert(pIoLogger->enmReqTypeNext != VDDBGIOLOGREQ_INVALID);
637 *penmReq = pIoLogger->enmReqTypeNext;
638 }
639
640 RTSemFastMutexRelease(pIoLogger->hMtx);
641 return rc;
642}
643
644VBOXDDU_DECL(int) VDDbgIoLogEventGetStart(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync,
645 uint64_t *poff, size_t *pcbIo, size_t cbBuf, void *pvBuf)
646{
647 int rc = VINF_SUCCESS;
648 PVDIOLOGGERINT pIoLogger = hIoLogger;
649
650 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
651 AssertPtrReturn(pidEvent, VERR_INVALID_POINTER);
652 AssertPtrReturn(pfAsync, VERR_INVALID_POINTER);
653 AssertPtrReturn(poff, VERR_INVALID_POINTER);
654 AssertPtrReturn(pcbIo, VERR_INVALID_POINTER);
655
656 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
657 AssertRCReturn(rc, rc);
658
659 if (pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START)
660 {
661 IoLogEntryStart Entry;
662 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL);
663 if (RT_SUCCESS(rc))
664 {
665 *pfAsync = (bool)Entry.u8AsyncIo;
666 *pidEvent = RT_LE2H_U64(Entry.u64Id);
667 *poff = RT_LE2H_U64(Entry.Io.u64Off);
668 *pcbIo = RT_LE2H_U64(Entry.Io.u64IoSize);
669
670 if ( pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_WRITE
671 && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN))
672 {
673 /* Read data. */
674 if (cbBuf < *pcbIo)
675 rc = VERR_BUFFER_OVERFLOW;
676 else
677 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + sizeof(Entry), pvBuf, *pcbIo, NULL);
678
679 if (rc != VERR_BUFFER_OVERFLOW)
680 pIoLogger->offReadNext += *pcbIo + sizeof(Entry);
681 }
682 else
683 pIoLogger->offReadNext += sizeof(Entry);
684 }
685 }
686 else
687 rc = VERR_INVALID_STATE;
688
689 RTSemFastMutexRelease(pIoLogger->hMtx);
690 return rc;
691}
692
693VBOXDDU_DECL(int) VDDbgIoLogEventGetStartDiscard(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync,
694 PVDRANGE *ppaRanges, unsigned *pcRanges)
695{
696 int rc = VINF_SUCCESS;
697 PVDIOLOGGERINT pIoLogger = hIoLogger;
698
699 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
700 AssertPtrReturn(pidEvent, VERR_INVALID_POINTER);
701 AssertPtrReturn(pfAsync, VERR_INVALID_POINTER);
702
703 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
704 AssertRCReturn(rc, rc);
705
706 if ( pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START
707 && pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_DISCARD)
708 {
709 IoLogEntryStart Entry;
710 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL);
711 if (RT_SUCCESS(rc))
712 {
713 PVDRANGE paRanges = NULL;
714 IoLogEntryDiscard DiscardRange;
715
716 pIoLogger->offReadNext += sizeof(Entry);
717 *pfAsync = (bool)Entry.u8AsyncIo;
718 *pidEvent = RT_LE2H_U64(Entry.u64Id);
719 *pcRanges = RT_LE2H_U32(Entry.Discard.cRanges);
720
721 paRanges = (PVDRANGE)RTMemAllocZ(*pcRanges * sizeof(VDRANGE));
722 if (paRanges)
723 {
724 for (unsigned i = 0; i < *pcRanges; i++)
725 {
726 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + i*sizeof(DiscardRange),
727 &DiscardRange, sizeof(DiscardRange), NULL);
728 if (RT_FAILURE(rc))
729 break;
730
731 paRanges[i].offStart = RT_LE2H_U64(DiscardRange.u64Off);
732 paRanges[i].cbRange = RT_LE2H_U32(DiscardRange.u32Discard);
733 }
734
735 if (RT_SUCCESS(rc))
736 {
737 pIoLogger->offReadNext += *pcRanges * sizeof(DiscardRange);
738 *ppaRanges = paRanges;
739 }
740 else
741 pIoLogger->offReadNext -= sizeof(Entry);
742 }
743 else
744 rc = VERR_NO_MEMORY;
745 }
746 }
747 else
748 rc = VERR_INVALID_STATE;
749
750 RTSemFastMutexRelease(pIoLogger->hMtx);
751 return rc;
752
753}
754
755VBOXDDU_DECL(int) VDDbgIoLogEventGetComplete(VDIOLOGGER hIoLogger, uint64_t *pidEvent, int *pRc,
756 uint64_t *pmsDuration, size_t *pcbIo, size_t cbBuf, void *pvBuf)
757{
758 int rc = VINF_SUCCESS;
759 PVDIOLOGGERINT pIoLogger = hIoLogger;
760
761 AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE);
762 AssertPtrReturn(pidEvent, VERR_INVALID_POINTER);
763 AssertPtrReturn(pmsDuration, VERR_INVALID_POINTER);
764 AssertPtrReturn(pcbIo, VERR_INVALID_POINTER);
765
766 rc = RTSemFastMutexRequest(pIoLogger->hMtx);
767 AssertRCReturn(rc, rc);
768
769 if (pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_COMPLETE)
770 {
771 IoLogEntryComplete Entry;
772 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL);
773 if (RT_SUCCESS(rc))
774 {
775 *pidEvent = RT_LE2H_U64(Entry.u64Id);
776 *pRc = (int)RT_LE2H_U32((int32_t)Entry.i32Rc);
777 *pmsDuration = RT_LE2H_U64(Entry.msDuration);
778 *pcbIo = RT_LE2H_U64(Entry.u64IoBuffer);
779
780 if (*pcbIo)
781 {
782 /* Read data. */
783 if (cbBuf < *pcbIo)
784 rc = VERR_BUFFER_OVERFLOW;
785 else
786 rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + sizeof(Entry), pvBuf, *pcbIo, NULL);
787
788 if (rc != VERR_BUFFER_OVERFLOW)
789 pIoLogger->offReadNext += *pcbIo + sizeof(Entry);
790 }
791 else
792 pIoLogger->offReadNext += sizeof(Entry);
793 }
794 }
795 else
796 rc = VERR_INVALID_STATE;
797
798 RTSemFastMutexRelease(pIoLogger->hMtx);
799 return rc;
800}
801
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette