VirtualBox

source: vbox/trunk/src/VBox/Storage/testcase/VDIoBackend.cpp@ 49439

Last change on this file since 49439 was 46247, checked in by vboxsync, 12 years ago

Storage/tstVDIo: Integrate runtime async I/O manager and add a file based storage backend in addition to the memory based backend

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/** $Id: VDIoBackend.cpp 46247 2013-05-23 19:19:42Z vboxsync $ */
2/** @file
3 *
4 * VBox HDD container test utility, I/O backend API
5 */
6
7/*
8 * Copyright (C) 2013 Oracle Corporation
9 *
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.
17 */
18#define LOGGROUP LOGGROUP_DEFAULT /** @todo: Log group */
19#include <iprt/err.h>
20#include <iprt/log.h>
21#include <iprt/assert.h>
22#include <iprt/asm.h>
23#include <iprt/mem.h>
24#include <iprt/file.h>
25#include <iprt/aiomgr.h>
26#include <iprt/string.h>
27
28#include "VDIoBackend.h"
29#include "VDMemDisk.h"
30#include "VDIoBackendMem.h"
31
32typedef struct VDIOBACKEND
33{
34 /** Memory I/O backend handle. */
35 PVDIOBACKENDMEM pIoMem;
36 /** Async I/O manager. */
37 RTAIOMGR hAioMgr;
38 /** Users of the memory backend. */
39 volatile uint32_t cRefsIoMem;
40 /** Users of the file backend. */
41 volatile uint32_t cRefsFile;
42} VDIOBACKEND;
43
44typedef struct VDIOSTORAGE
45{
46 /** Pointer to the I/O backend parent. */
47 PVDIOBACKEND pIoBackend;
48 /** Completion callback. */
49 PFNVDIOCOMPLETE pfnComplete;
50 /** Flag whether this storage is backed by a file or memory.disk. */
51 bool fMemory;
52 /** Type dependent data. */
53 union
54 {
55 /** Memory disk handle. */
56 PVDMEMDISK pMemDisk;
57 struct
58 {
59 /** file handle. */
60 RTFILE hFile;
61 /** I/O manager file handle. */
62 RTAIOMGRFILE hAioMgrFile;
63 } File;
64 } u;
65} VDIOSTORAGE;
66
67static DECLCALLBACK(void) vdIoBackendFileIoComplete(RTAIOMGRFILE hAioMgrFile, int rcReq, void *pvUser)
68{
69 PVDIOSTORAGE pIoStorage = (PVDIOSTORAGE)RTAioMgrFileGetUser(hAioMgrFile);
70 pIoStorage->pfnComplete(pvUser, rcReq);
71}
72
73int VDIoBackendCreate(PPVDIOBACKEND ppIoBackend)
74{
75 int rc = VINF_SUCCESS;
76 PVDIOBACKEND pIoBackend;
77
78 pIoBackend = (PVDIOBACKEND)RTMemAllocZ(sizeof(VDIOBACKEND));
79 if (pIoBackend)
80 {
81 pIoBackend->hAioMgr = NIL_RTAIOMGR;
82 *ppIoBackend = pIoBackend;
83 }
84 else
85 rc = VERR_NO_MEMORY;
86
87 return rc;
88}
89
90void VDIoBackendDestroy(PVDIOBACKEND pIoBackend)
91{
92 if (pIoBackend->pIoMem)
93 VDIoBackendMemDestroy(pIoBackend->pIoMem);
94 if (pIoBackend->hAioMgr)
95 RTAioMgrRelease(pIoBackend->hAioMgr);
96 RTMemFree(pIoBackend);
97}
98
99int VDIoBackendStorageCreate(PVDIOBACKEND pIoBackend, const char *pszBackend,
100 const char *pszName, PFNVDIOCOMPLETE pfnComplete,
101 PPVDIOSTORAGE ppIoStorage)
102{
103 int rc = VINF_SUCCESS;
104 PVDIOSTORAGE pIoStorage = (PVDIOSTORAGE)RTMemAllocZ(sizeof(VDIOSTORAGE));
105
106 if (pIoStorage)
107 {
108 pIoStorage->pIoBackend = pIoBackend;
109 pIoStorage->pfnComplete = pfnComplete;
110 if (!strcmp(pszBackend, "memory"))
111 {
112 pIoStorage->fMemory = true;
113 rc = VDMemDiskCreate(&pIoStorage->u.pMemDisk, 0 /* Growing */);
114 if (RT_SUCCESS(rc))
115 {
116 uint32_t cRefs = ASMAtomicIncU32(&pIoBackend->cRefsIoMem);
117 if ( cRefs == 1
118 && !pIoBackend->pIoMem)
119 {
120 rc = VDIoBackendMemCreate(&pIoBackend->pIoMem);
121 if (RT_FAILURE(rc))
122 VDMemDiskDestroy(pIoStorage->u.pMemDisk);
123 }
124 }
125 }
126 else if (!strcmp(pszBackend, "file"))
127 {
128 pIoStorage->fMemory = false;
129 uint32_t cRefs = ASMAtomicIncU32(&pIoBackend->cRefsFile);
130 if ( cRefs == 1
131 && pIoBackend->hAioMgr == NIL_RTAIOMGR)
132 rc = RTAioMgrCreate(&pIoBackend->hAioMgr, 1024);
133
134 if (RT_SUCCESS(rc))
135 {
136 /* Create file. */
137 rc = RTFileOpen(&pIoStorage->u.File.hFile, pszName,
138 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_ASYNC_IO | RTFILE_O_NO_CACHE | RTFILE_O_DENY_NONE);
139 if (RT_SUCCESS(rc))
140 {
141 /* Create file handle for I/O manager. */
142 rc = RTAioMgrFileCreate(pIoBackend->hAioMgr, pIoStorage->u.File.hFile,
143 vdIoBackendFileIoComplete, pIoStorage,
144 &pIoStorage->u.File.hAioMgrFile);
145 if (RT_FAILURE(rc))
146 RTFileClose(pIoStorage->u.File.hFile);
147 }
148 }
149
150 if (RT_FAILURE(rc))
151 ASMAtomicDecU32(&pIoBackend->cRefsFile);
152 }
153 else
154 rc = VERR_NOT_SUPPORTED;
155
156 if (RT_FAILURE(rc))
157 RTMemFree(pIoStorage);
158 else
159 *ppIoStorage = pIoStorage;
160 }
161 else
162 rc = VERR_NO_MEMORY;
163
164 return rc;
165}
166
167void VDIoBackendStorageDestroy(PVDIOSTORAGE pIoStorage)
168{
169 if (pIoStorage->fMemory)
170 {
171 VDMemDiskDestroy(pIoStorage->u.pMemDisk);
172 ASMAtomicDecU32(&pIoStorage->pIoBackend->cRefsIoMem);
173 }
174 else
175 {
176 RTAioMgrFileRelease(pIoStorage->u.File.hAioMgrFile);
177 RTFileClose(pIoStorage->u.File.hFile);
178 ASMAtomicDecU32(&pIoStorage->pIoBackend->cRefsFile);
179 }
180 RTMemFree(pIoStorage);
181}
182
183int VDIoBackendTransfer(PVDIOSTORAGE pIoStorage, VDIOTXDIR enmTxDir, uint64_t off,
184 size_t cbTransfer, PRTSGBUF pSgBuf, void *pvUser, bool fSync)
185{
186 int rc = VINF_SUCCESS;
187
188 if (pIoStorage->fMemory)
189 {
190 if (!fSync)
191 {
192 rc = VDIoBackendMemTransfer(pIoStorage->pIoBackend->pIoMem, pIoStorage->u.pMemDisk,
193 enmTxDir, off, cbTransfer, pSgBuf, pIoStorage->pfnComplete,
194 pvUser);
195 }
196 else
197 {
198 switch (enmTxDir)
199 {
200 case VDIOTXDIR_READ:
201 rc = VDMemDiskRead(pIoStorage->u.pMemDisk, off, cbTransfer, pSgBuf);
202 break;
203 case VDIOTXDIR_WRITE:
204 rc = VDMemDiskWrite(pIoStorage->u.pMemDisk, off, cbTransfer, pSgBuf);
205 break;
206 case VDIOTXDIR_FLUSH:
207 break;
208 default:
209 AssertMsgFailed(("Invalid transfer type %d\n", enmTxDir));
210 }
211 }
212 }
213 else
214 {
215 if (!fSync)
216 {
217 switch (enmTxDir)
218 {
219 case VDIOTXDIR_READ:
220 rc = RTAioMgrFileRead(pIoStorage->u.File.hAioMgrFile, off, pSgBuf, cbTransfer, pvUser);
221 break;
222 case VDIOTXDIR_WRITE:
223 rc = RTAioMgrFileWrite(pIoStorage->u.File.hAioMgrFile, off, pSgBuf, cbTransfer, pvUser);
224 break;
225 case VDIOTXDIR_FLUSH:
226 rc = RTAioMgrFileFlush(pIoStorage->u.File.hAioMgrFile, pvUser);
227 break;
228 default:
229 AssertMsgFailed(("Invalid transfer type %d\n", enmTxDir));
230 }
231 if (rc == VERR_FILE_AIO_IN_PROGRESS)
232 rc = VINF_SUCCESS;
233 }
234 else
235 {
236 switch (enmTxDir)
237 {
238 case VDIOTXDIR_READ:
239 rc = RTFileSgReadAt(pIoStorage->u.File.hFile, off, pSgBuf, cbTransfer, NULL);
240 break;
241 case VDIOTXDIR_WRITE:
242 rc = RTFileSgWriteAt(pIoStorage->u.File.hFile, off, pSgBuf, cbTransfer, NULL);
243 break;
244 case VDIOTXDIR_FLUSH:
245 rc = RTFileFlush(pIoStorage->u.File.hFile);
246 break;
247 default:
248 AssertMsgFailed(("Invalid transfer type %d\n", enmTxDir));
249 }
250 }
251 }
252
253 return rc;
254}
255
256int VDIoBackendStorageSetSize(PVDIOSTORAGE pIoStorage, uint64_t cbSize)
257{
258 int rc = VINF_SUCCESS;
259
260 if (pIoStorage->fMemory)
261 {
262 rc = VDMemDiskSetSize(pIoStorage->u.pMemDisk, cbSize);
263 }
264 else
265 rc = RTFileSetSize(pIoStorage->u.File.hFile, cbSize);
266
267 return rc;
268}
269
270int VDIoBackendStorageGetSize(PVDIOSTORAGE pIoStorage, uint64_t *pcbSize)
271{
272 int rc = VINF_SUCCESS;
273
274 if (pIoStorage->fMemory)
275 {
276 rc = VDMemDiskGetSize(pIoStorage->u.pMemDisk, pcbSize);
277 }
278 else
279 rc = RTFileGetSize(pIoStorage->u.File.hFile, pcbSize);
280
281 return rc;
282}
283
Note: See TracBrowser for help on using the repository browser.

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