summaryrefslogtreecommitdiffstats
path: root/src/VBox/Storage/testcase/VDIoBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Storage/testcase/VDIoBackend.cpp')
-rw-r--r--src/VBox/Storage/testcase/VDIoBackend.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/VBox/Storage/testcase/VDIoBackend.cpp b/src/VBox/Storage/testcase/VDIoBackend.cpp
new file mode 100644
index 00000000..8358c06a
--- /dev/null
+++ b/src/VBox/Storage/testcase/VDIoBackend.cpp
@@ -0,0 +1,250 @@
+/* $Id: VDIoBackend.cpp $ */
+/** @file
+ * VBox HDD container test utility, I/O backend API
+ */
+
+/*
+ * Copyright (C) 2013-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+#define LOGGROUP LOGGROUP_DEFAULT /** @todo Log group */
+#include <iprt/errcore.h>
+#include <iprt/log.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/mem.h>
+#include <iprt/file.h>
+#include <iprt/string.h>
+
+#include "VDIoBackend.h"
+#include "VDMemDisk.h"
+#include "VDIoBackendMem.h"
+
+typedef struct VDIOBACKEND
+{
+ /** Memory I/O backend handle. */
+ PVDIOBACKENDMEM pIoMem;
+ /** Users of the memory backend. */
+ volatile uint32_t cRefsIoMem;
+ /** Users of the file backend. */
+ volatile uint32_t cRefsFile;
+} VDIOBACKEND;
+
+typedef struct VDIOSTORAGE
+{
+ /** Pointer to the I/O backend parent. */
+ PVDIOBACKEND pIoBackend;
+ /** Completion callback. */
+ PFNVDIOCOMPLETE pfnComplete;
+ /** Flag whether this storage is backed by a file or memory.disk. */
+ bool fMemory;
+ /** Type dependent data. */
+ union
+ {
+ /** Memory disk handle. */
+ PVDMEMDISK pMemDisk;
+ /** file handle. */
+ RTFILE hFile;
+ } u;
+} VDIOSTORAGE;
+
+
+int VDIoBackendCreate(PPVDIOBACKEND ppIoBackend)
+{
+ int rc = VINF_SUCCESS;
+ PVDIOBACKEND pIoBackend;
+
+ pIoBackend = (PVDIOBACKEND)RTMemAllocZ(sizeof(VDIOBACKEND));
+ if (pIoBackend)
+ *ppIoBackend = pIoBackend;
+ else
+ rc = VERR_NO_MEMORY;
+
+ return rc;
+}
+
+void VDIoBackendDestroy(PVDIOBACKEND pIoBackend)
+{
+ if (pIoBackend->pIoMem)
+ VDIoBackendMemDestroy(pIoBackend->pIoMem);
+ RTMemFree(pIoBackend);
+}
+
+int VDIoBackendStorageCreate(PVDIOBACKEND pIoBackend, const char *pszBackend,
+ const char *pszName, PFNVDIOCOMPLETE pfnComplete,
+ PPVDIOSTORAGE ppIoStorage)
+{
+ int rc = VINF_SUCCESS;
+ PVDIOSTORAGE pIoStorage = (PVDIOSTORAGE)RTMemAllocZ(sizeof(VDIOSTORAGE));
+
+ if (pIoStorage)
+ {
+ pIoStorage->pIoBackend = pIoBackend;
+ pIoStorage->pfnComplete = pfnComplete;
+ if (!strcmp(pszBackend, "memory"))
+ {
+ pIoStorage->fMemory = true;
+ rc = VDMemDiskCreate(&pIoStorage->u.pMemDisk, 0 /* Growing */);
+ if (RT_SUCCESS(rc))
+ {
+ uint32_t cRefs = ASMAtomicIncU32(&pIoBackend->cRefsIoMem);
+ if ( cRefs == 1
+ && !pIoBackend->pIoMem)
+ {
+ rc = VDIoBackendMemCreate(&pIoBackend->pIoMem);
+ if (RT_FAILURE(rc))
+ VDMemDiskDestroy(pIoStorage->u.pMemDisk);
+ }
+ }
+ }
+ else if (!strcmp(pszBackend, "file"))
+ {
+ /* Create file. */
+ rc = RTFileOpen(&pIoStorage->u.hFile, pszName,
+ RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_ASYNC_IO | RTFILE_O_NO_CACHE | RTFILE_O_DENY_NONE);
+
+ if (RT_FAILURE(rc))
+ ASMAtomicDecU32(&pIoBackend->cRefsFile);
+ }
+ else
+ rc = VERR_NOT_SUPPORTED;
+
+ if (RT_FAILURE(rc))
+ RTMemFree(pIoStorage);
+ else
+ *ppIoStorage = pIoStorage;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ return rc;
+}
+
+void VDIoBackendStorageDestroy(PVDIOSTORAGE pIoStorage)
+{
+ if (pIoStorage->fMemory)
+ {
+ VDMemDiskDestroy(pIoStorage->u.pMemDisk);
+ ASMAtomicDecU32(&pIoStorage->pIoBackend->cRefsIoMem);
+ }
+ else
+ {
+ RTFileClose(pIoStorage->u.hFile);
+ ASMAtomicDecU32(&pIoStorage->pIoBackend->cRefsFile);
+ }
+ RTMemFree(pIoStorage);
+}
+
+int VDIoBackendTransfer(PVDIOSTORAGE pIoStorage, VDIOTXDIR enmTxDir, uint64_t off,
+ size_t cbTransfer, PRTSGBUF pSgBuf, void *pvUser, bool fSync)
+{
+ int rc = VINF_SUCCESS;
+
+ if (pIoStorage->fMemory)
+ {
+ if (!fSync)
+ {
+ rc = VDIoBackendMemTransfer(pIoStorage->pIoBackend->pIoMem, pIoStorage->u.pMemDisk,
+ enmTxDir, off, cbTransfer, pSgBuf, pIoStorage->pfnComplete,
+ pvUser);
+ }
+ else
+ {
+ switch (enmTxDir)
+ {
+ case VDIOTXDIR_READ:
+ rc = VDMemDiskRead(pIoStorage->u.pMemDisk, off, cbTransfer, pSgBuf);
+ break;
+ case VDIOTXDIR_WRITE:
+ rc = VDMemDiskWrite(pIoStorage->u.pMemDisk, off, cbTransfer, pSgBuf);
+ break;
+ case VDIOTXDIR_FLUSH:
+ break;
+ default:
+ AssertMsgFailed(("Invalid transfer type %d\n", enmTxDir));
+ }
+ }
+ }
+ else
+ {
+ if (!fSync)
+ rc = VERR_NOT_IMPLEMENTED;
+ else
+ {
+ switch (enmTxDir)
+ {
+ case VDIOTXDIR_READ:
+ rc = RTFileSgReadAt(pIoStorage->u.hFile, off, pSgBuf, cbTransfer, NULL);
+ break;
+ case VDIOTXDIR_WRITE:
+ rc = RTFileSgWriteAt(pIoStorage->u.hFile, off, pSgBuf, cbTransfer, NULL);
+ break;
+ case VDIOTXDIR_FLUSH:
+ rc = RTFileFlush(pIoStorage->u.hFile);
+ break;
+ default:
+ AssertMsgFailed(("Invalid transfer type %d\n", enmTxDir));
+ }
+ }
+ }
+
+ return rc;
+}
+
+int VDIoBackendStorageSetSize(PVDIOSTORAGE pIoStorage, uint64_t cbSize)
+{
+ int rc = VINF_SUCCESS;
+
+ if (pIoStorage->fMemory)
+ {
+ rc = VDMemDiskSetSize(pIoStorage->u.pMemDisk, cbSize);
+ }
+ else
+ rc = RTFileSetSize(pIoStorage->u.hFile, cbSize);
+
+ return rc;
+}
+
+int VDIoBackendStorageGetSize(PVDIOSTORAGE pIoStorage, uint64_t *pcbSize)
+{
+ int rc = VINF_SUCCESS;
+
+ if (pIoStorage->fMemory)
+ {
+ rc = VDMemDiskGetSize(pIoStorage->u.pMemDisk, pcbSize);
+ }
+ else
+ rc = RTFileQuerySize(pIoStorage->u.hFile, pcbSize);
+
+ return rc;
+}
+
+DECLHIDDEN(int) VDIoBackendDumpToFile(PVDIOSTORAGE pIoStorage, const char *pszPath)
+{
+ int rc = VINF_SUCCESS;
+
+ if (pIoStorage->fMemory)
+ rc = VDMemDiskWriteToFile(pIoStorage->u.pMemDisk, pszPath);
+ else
+ rc = VERR_NOT_IMPLEMENTED;
+
+ return rc;
+}
+