Changeset 38469 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Aug 16, 2011 10:34:32 AM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 73520
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r37641 r38469 85 85 /** Pointer to list of VD interfaces. Per-image. */ 86 86 PVDINTERFACE pVDIfsImage; 87 /** Co mmon structure for the configuration information interface. */88 VDINTERFACE VDIConfig;89 /** Common structure for the supportedTCP network stack interface. */90 VDINTERFACE VDITcpNet;91 /** Common structure for the supportedI/O interface. */92 VDINTERFACE VDIIO;87 /** Configuration information interface. */ 88 VDINTERFACECONFIG VDIfConfig; 89 /** TCP network stack interface. */ 90 VDINTERFACETCPNET VDIfTcpNet; 91 /** I/O interface. */ 92 VDINTERFACEIO VDIfIo; 93 93 } VBOXIMAGE, *PVBOXIMAGE; 94 94 … … 125 125 { 126 126 /** The VBox disk container. */ 127 PVBOXHDD pDisk;127 PVBOXHDD pDisk; 128 128 /** The media interface. */ 129 PDMIMEDIA IMedia;129 PDMIMEDIA IMedia; 130 130 /** Media port. */ 131 PPDMIMEDIAPORT pDrvMediaPort;131 PPDMIMEDIAPORT pDrvMediaPort; 132 132 /** Pointer to the driver instance. */ 133 PPDMDRVINS pDrvIns;133 PPDMDRVINS pDrvIns; 134 134 /** Flag whether suspend has changed image open mode to read only. */ 135 bool fTempReadOnly;135 bool fTempReadOnly; 136 136 /** Flag whether to use the runtime (true) or startup error facility. */ 137 bool fErrorUseRuntime;137 bool fErrorUseRuntime; 138 138 /** Pointer to list of VD interfaces. Per-disk. */ 139 PVDINTERFACE pVDIfsDisk; 140 /** Common structure for the supported error interface. */ 141 VDINTERFACE VDIError; 142 /** Callback table for error interface. */ 143 VDINTERFACEERROR VDIErrorCallbacks; 144 /** Common structure for the supported thread synchronization interface. */ 145 VDINTERFACE VDIThreadSync; 146 /** Callback table for thread synchronization interface. */ 147 VDINTERFACETHREADSYNC VDIThreadSyncCallbacks; 148 149 /** Callback table for the configuration information interface. */ 150 VDINTERFACECONFIG VDIConfigCallbacks; 151 /** Callback table for TCP network stack interface. */ 152 VDINTERFACETCPNET VDITcpNetCallbacks; 153 /** Callback table for I/O interface. */ 154 VDINTERFACEIO VDIIOCallbacks; 139 PVDINTERFACE pVDIfsDisk; 140 /** Error interface. */ 141 VDINTERFACEERROR VDIfError; 142 /** Thread synchronization interface. */ 143 VDINTERFACETHREADSYNC VDIfThreadSync; 155 144 156 145 /** Flag whether opened disk supports async I/O operations. */ 157 bool fAsyncIOSupported;146 bool fAsyncIOSupported; 158 147 /** The async media interface. */ 159 148 PDMIMEDIAASYNC IMediaAsync; … … 163 152 PVBOXIMAGE pImages; 164 153 /** Flag whether the media should allow concurrent open for writing. */ 165 bool fShareable;154 bool fShareable; 166 155 /** Flag whether a merge operation has been set up. */ 167 bool fMergePending;156 bool fMergePending; 168 157 /** Synchronization to prevent destruction before merge finishes. */ 169 RTSEMFASTMUTEX MergeCompleteMutex;158 RTSEMFASTMUTEX MergeCompleteMutex; 170 159 /** Synchronization between merge and other image accesses. */ 171 RTSEMRW MergeLock;160 RTSEMRW MergeLock; 172 161 /** Source image index for merging. */ 173 unsigned uMergeSource;162 unsigned uMergeSource; 174 163 /** Target image index for merging. */ 175 unsigned uMergeTarget;164 unsigned uMergeTarget; 176 165 177 166 /** Flag whether boot acceleration is enabled. */ 178 bool fBootAccelEnabled;167 bool fBootAccelEnabled; 179 168 /** Flag whether boot acceleration is currently active. */ 180 bool fBootAccelActive;169 bool fBootAccelActive; 181 170 /** Size of the disk, used for read truncation. */ 182 size_t cbDisk;171 size_t cbDisk; 183 172 /** Size of the configured buffer. */ 184 size_t cbBootAccelBuffer;173 size_t cbBootAccelBuffer; 185 174 /** Start offset for which the buffer holds data. */ 186 uint64_t offDisk;175 uint64_t offDisk; 187 176 /** Number of valid bytes in the buffer. */ 188 size_t cbDataValid;177 size_t cbDataValid; 189 178 /** The disk buffer. */ 190 uint8_t *pbData;179 uint8_t *pbData; 191 180 /** Bandwidth group the disk is assigned to. */ 192 char *pszBwGroup;181 char *pszBwGroup; 193 182 /** Flag whether async I/O using the host cache is enabled. */ 194 bool fAsyncIoWithHostCache;183 bool fAsyncIoWithHostCache; 195 184 196 185 /** I/O interface for a cache image. */ 197 VDINTERFACE VDIIOCache;186 VDINTERFACEIO VDIfIoCache; 198 187 /** Interface list for the cache image. */ 199 PVDINTERFACE pVDIfsCache;188 PVDINTERFACE pVDIfsCache; 200 189 201 190 /** The block cache handle if configured. */ 202 PPDMBLKCACHE pBlkCache;191 PPDMBLKCACHE pBlkCache; 203 192 } VBOXDISK, *PVBOXDISK; 204 193 … … 1556 1545 /** @todo maybe introduce a conversion which limits update frequency. */ 1557 1546 PVDINTERFACE pVDIfsOperation = NULL; 1558 VDINTERFACE VDIProgress; 1559 VDINTERFACEPROGRESS VDIProgressCallbacks; 1560 VDIProgressCallbacks.cbSize = sizeof(VDINTERFACEPROGRESS); 1561 VDIProgressCallbacks.enmInterface = VDINTERFACETYPE_PROGRESS; 1562 VDIProgressCallbacks.pfnProgress = pfnProgress; 1563 rc2 = VDInterfaceAdd(&VDIProgress, "DrvVD_VDIProgress", VDINTERFACETYPE_PROGRESS, 1564 &VDIProgressCallbacks, pvUser, &pVDIfsOperation); 1547 VDINTERFACEPROGRESS VDIfProgress; 1548 VDIfProgress.pfnProgress = pfnProgress; 1549 rc2 = VDInterfaceAdd(&VDIfProgress.Core, "DrvVD_VDIProgress", VDINTERFACETYPE_PROGRESS, 1550 pvUser, sizeof(VDINTERFACEPROGRESS), &pVDIfsOperation); 1565 1551 AssertRC(rc2); 1566 1552 pThis->fMergePending = false; … … 2082 2068 pThis->pVDIfsDisk = NULL; 2083 2069 2084 pThis->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 2085 pThis->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 2086 pThis->VDIErrorCallbacks.pfnError = drvvdErrorCallback; 2087 pThis->VDIErrorCallbacks.pfnMessage = NULL; 2088 2089 rc = VDInterfaceAdd(&pThis->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR, 2090 &pThis->VDIErrorCallbacks, pDrvIns, &pThis->pVDIfsDisk); 2070 pThis->VDIfError.pfnError = drvvdErrorCallback; 2071 pThis->VDIfError.pfnMessage = NULL; 2072 rc = VDInterfaceAdd(&pThis->VDIfError.Core, "DrvVD_VDIError", VDINTERFACETYPE_ERROR, 2073 pDrvIns, sizeof(VDINTERFACEERROR), &pThis->pVDIfsDisk); 2091 2074 AssertRC(rc); 2092 2093 /* This is just prepared here, the actual interface is per-image, so it's2094 * added later. No need to have separate callback tables. */2095 pThis->VDIConfigCallbacks.cbSize = sizeof(VDINTERFACECONFIG);2096 pThis->VDIConfigCallbacks.enmInterface = VDINTERFACETYPE_CONFIG;2097 pThis->VDIConfigCallbacks.pfnAreKeysValid = drvvdCfgAreKeysValid;2098 pThis->VDIConfigCallbacks.pfnQuerySize = drvvdCfgQuerySize;2099 pThis->VDIConfigCallbacks.pfnQuery = drvvdCfgQuery;2100 2075 2101 2076 /* List of images is empty now. */ … … 2313 2288 if (RT_SUCCESS(rc)) 2314 2289 { 2290 /* 2291 * The image has a bandwidth group but the host cache is enabled. 2292 * Use the async I/O framework but tell it to enable the host cache. 2293 */ 2294 if (!fUseNewIo && pThis->pszBwGroup) 2295 { 2296 pThis->fAsyncIoWithHostCache = true; 2297 fUseNewIo = true; 2298 } 2299 2300 /** @todo quick hack to work around problems in the async I/O 2301 * implementation (rw semaphore thread ownership problem) 2302 * while a merge is running. Remove once this is fixed. */ 2303 if (pThis->fMergePending) 2304 fUseNewIo = false; 2305 2306 if (RT_SUCCESS(rc) && pThis->fMergePending) 2307 { 2308 rc = RTSemFastMutexCreate(&pThis->MergeCompleteMutex); 2309 if (RT_SUCCESS(rc)) 2310 rc = RTSemRWCreate(&pThis->MergeLock); 2311 if (RT_SUCCESS(rc)) 2312 { 2313 pThis->VDIfThreadSync.pfnStartRead = drvvdThreadStartRead; 2314 pThis->VDIfThreadSync.pfnFinishRead = drvvdThreadFinishRead; 2315 pThis->VDIfThreadSync.pfnStartWrite = drvvdThreadStartWrite; 2316 pThis->VDIfThreadSync.pfnFinishWrite = drvvdThreadFinishWrite; 2317 2318 rc = VDInterfaceAdd(&pThis->VDIfThreadSync.Core, "DrvVD_ThreadSync", VDINTERFACETYPE_THREADSYNC, 2319 pThis, sizeof(VDINTERFACETHREADSYNC), &pThis->pVDIfsDisk); 2320 } 2321 else 2322 { 2323 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2324 N_("DrvVD: Failed to create semaphores for \"MergePending\"")); 2325 } 2326 } 2327 2328 if (RT_SUCCESS(rc)) 2329 { 2330 rc = VDCreate(pThis->pVDIfsDisk, enmType, &pThis->pDisk); 2331 /* Error message is already set correctly. */ 2332 } 2333 } 2334 2335 if (pThis->pDrvMediaAsyncPort && fUseNewIo) 2336 pThis->fAsyncIOSupported = true; 2337 2338 unsigned iImageIdx = 0; 2339 while (pCurNode && RT_SUCCESS(rc)) 2340 { 2341 /* Allocate per-image data. */ 2342 PVBOXIMAGE pImage = drvvdNewImage(pThis); 2343 if (!pImage) 2344 { 2345 rc = VERR_NO_MEMORY; 2346 break; 2347 } 2348 2349 /* 2350 * Read the image configuration. 2351 */ 2352 rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName); 2353 if (RT_FAILURE(rc)) 2354 { 2355 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2356 N_("DrvVD: Configuration error: Querying \"Path\" as string failed")); 2357 break; 2358 } 2359 2360 rc = CFGMR3QueryStringAlloc(pCurNode, "Format", &pszFormat); 2361 if (RT_FAILURE(rc)) 2362 { 2363 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2364 N_("DrvVD: Configuration error: Querying \"Format\" as string failed")); 2365 break; 2366 } 2367 2368 bool fMergeSource; 2369 rc = CFGMR3QueryBoolDef(pCurNode, "MergeSource", &fMergeSource, false); 2370 if (RT_FAILURE(rc)) 2371 { 2372 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2373 N_("DrvVD: Configuration error: Querying \"MergeSource\" as boolean failed")); 2374 break; 2375 } 2376 if (fMergeSource) 2377 { 2378 if (pThis->uMergeSource == VD_LAST_IMAGE) 2379 pThis->uMergeSource = iImageIdx; 2380 else 2381 { 2382 rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES, 2383 N_("DrvVD: Configuration error: Multiple \"MergeSource\" occurrences")); 2384 break; 2385 } 2386 } 2387 2388 bool fMergeTarget; 2389 rc = CFGMR3QueryBoolDef(pCurNode, "MergeTarget", &fMergeTarget, false); 2390 if (RT_FAILURE(rc)) 2391 { 2392 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2393 N_("DrvVD: Configuration error: Querying \"MergeTarget\" as boolean failed")); 2394 break; 2395 } 2396 if (fMergeTarget) 2397 { 2398 if (pThis->uMergeTarget == VD_LAST_IMAGE) 2399 pThis->uMergeTarget = iImageIdx; 2400 else 2401 { 2402 rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES, 2403 N_("DrvVD: Configuration error: Multiple \"MergeTarget\" occurrences")); 2404 break; 2405 } 2406 } 2407 2408 PCFGMNODE pCfgVDConfig = CFGMR3GetChild(pCurNode, "VDConfig"); 2409 pImage->VDIfConfig.pfnAreKeysValid = drvvdCfgAreKeysValid; 2410 pImage->VDIfConfig.pfnQuerySize = drvvdCfgQuerySize; 2411 pImage->VDIfConfig.pfnQuery = drvvdCfgQuery; 2412 rc = VDInterfaceAdd(&pImage->VDIfConfig.Core, "DrvVD_Config", VDINTERFACETYPE_CONFIG, 2413 pCfgVDConfig, sizeof(VDINTERFACECONFIG), &pImage->pVDIfsImage); 2414 AssertRC(rc); 2415 2416 /* Unconditionally insert the TCPNET interface, don't bother to check 2417 * if an image really needs it. Will be ignored. Since the TCPNET 2418 * interface is per image we could make this more flexible in the 2419 * future if we want to. */ 2315 2420 /* Construct TCPNET callback table depending on the config. This is 2316 2421 * done unconditionally, as uninterested backends will ignore it. */ 2317 2422 if (fHostIP) 2318 2423 { 2319 pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET); 2320 pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET; 2321 pThis->VDITcpNetCallbacks.pfnSocketCreate = drvvdTcpSocketCreate; 2322 pThis->VDITcpNetCallbacks.pfnSocketDestroy = drvvdTcpSocketDestroy; 2323 pThis->VDITcpNetCallbacks.pfnClientConnect = drvvdTcpClientConnect; 2324 pThis->VDITcpNetCallbacks.pfnIsClientConnected = drvvdTcpIsClientConnected; 2325 pThis->VDITcpNetCallbacks.pfnClientClose = drvvdTcpClientClose; 2326 pThis->VDITcpNetCallbacks.pfnSelectOne = drvvdTcpSelectOne; 2327 pThis->VDITcpNetCallbacks.pfnRead = drvvdTcpRead; 2328 pThis->VDITcpNetCallbacks.pfnWrite = drvvdTcpWrite; 2329 pThis->VDITcpNetCallbacks.pfnSgWrite = drvvdTcpSgWrite; 2330 pThis->VDITcpNetCallbacks.pfnReadNB = drvvdTcpReadNB; 2331 pThis->VDITcpNetCallbacks.pfnWriteNB = drvvdTcpWriteNB; 2332 pThis->VDITcpNetCallbacks.pfnSgWriteNB = drvvdTcpSgWriteNB; 2333 pThis->VDITcpNetCallbacks.pfnFlush = drvvdTcpFlush; 2334 pThis->VDITcpNetCallbacks.pfnSetSendCoalescing = drvvdTcpSetSendCoalescing; 2335 pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdTcpGetLocalAddress; 2336 pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdTcpGetPeerAddress; 2424 pImage->VDIfTcpNet.pfnSocketCreate = drvvdTcpSocketCreate; 2425 pImage->VDIfTcpNet.pfnSocketDestroy = drvvdTcpSocketDestroy; 2426 pImage->VDIfTcpNet.pfnClientConnect = drvvdTcpClientConnect; 2427 pImage->VDIfTcpNet.pfnIsClientConnected = drvvdTcpIsClientConnected; 2428 pImage->VDIfTcpNet.pfnClientClose = drvvdTcpClientClose; 2429 pImage->VDIfTcpNet.pfnSelectOne = drvvdTcpSelectOne; 2430 pImage->VDIfTcpNet.pfnRead = drvvdTcpRead; 2431 pImage->VDIfTcpNet.pfnWrite = drvvdTcpWrite; 2432 pImage->VDIfTcpNet.pfnSgWrite = drvvdTcpSgWrite; 2433 pImage->VDIfTcpNet.pfnReadNB = drvvdTcpReadNB; 2434 pImage->VDIfTcpNet.pfnWriteNB = drvvdTcpWriteNB; 2435 pImage->VDIfTcpNet.pfnSgWriteNB = drvvdTcpSgWriteNB; 2436 pImage->VDIfTcpNet.pfnFlush = drvvdTcpFlush; 2437 pImage->VDIfTcpNet.pfnSetSendCoalescing = drvvdTcpSetSendCoalescing; 2438 pImage->VDIfTcpNet.pfnGetLocalAddress = drvvdTcpGetLocalAddress; 2439 pImage->VDIfTcpNet.pfnGetPeerAddress = drvvdTcpGetPeerAddress; 2337 2440 2338 2441 /* … … 2351 2454 { 2352 2455 LogRel(("VD: Detected Windows XP, disabled poll based waiting for TCP\n")); 2353 p This->VDITcpNetCallbacks.pfnSelectOneEx = drvvdTcpSelectOneExNoPoll;2456 pImage->VDIfTcpNet.pfnSelectOneEx = drvvdTcpSelectOneExNoPoll; 2354 2457 } 2355 2458 else 2356 p This->VDITcpNetCallbacks.pfnSelectOneEx = drvvdTcpSelectOneExPoll;2357 2358 p This->VDITcpNetCallbacks.pfnPoke = drvvdTcpPoke;2459 pImage->VDIfTcpNet.pfnSelectOneEx = drvvdTcpSelectOneExPoll; 2460 2461 pImage->VDIfTcpNet.pfnPoke = drvvdTcpPoke; 2359 2462 } 2360 2463 else … … 2364 2467 RT_SRC_POS, N_("DrvVD: Configuration error: TCP over Internal Networking not compiled in")); 2365 2468 #else /* VBOX_WITH_INIP */ 2366 pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET); 2367 pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET; 2368 pThis->VDITcpNetCallbacks.pfnSocketCreate = drvvdINIPSocketCreate; 2369 pThis->VDITcpNetCallbacks.pfnSocketDestroy = drvvdINIPSocketDestroy; 2370 pThis->VDITcpNetCallbacks.pfnClientConnect = drvvdINIPClientConnect; 2371 pThis->VDITcpNetCallbacks.pfnClientClose = drvvdINIPClientClose; 2372 pThis->VDITcpNetCallbacks.pfnIsClientConnected = drvvdINIPIsClientConnected; 2373 pThis->VDITcpNetCallbacks.pfnSelectOne = drvvdINIPSelectOne; 2374 pThis->VDITcpNetCallbacks.pfnRead = drvvdINIPRead; 2375 pThis->VDITcpNetCallbacks.pfnWrite = drvvdINIPWrite; 2376 pThis->VDITcpNetCallbacks.pfnSgWrite = drvvdINIPSgWrite; 2377 pThis->VDITcpNetCallbacks.pfnFlush = drvvdINIPFlush; 2378 pThis->VDITcpNetCallbacks.pfnSetSendCoalescing = drvvdINIPSetSendCoalescing; 2379 pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdINIPGetLocalAddress; 2380 pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdINIPGetPeerAddress; 2381 pThis->VDITcpNetCallbacks.pfnSelectOneEx = drvvdINIPSelectOneEx; 2382 pThis->VDITcpNetCallbacks.pfnPoke = drvvdINIPPoke; 2469 pImage->VDIfTcpNet.pfnSocketCreate = drvvdINIPSocketCreate; 2470 pImage->VDIfTcpNet.pfnSocketDestroy = drvvdINIPSocketDestroy; 2471 pImage->VDIfTcpNet.pfnClientConnect = drvvdINIPClientConnect; 2472 pImage->VDIfTcpNet.pfnClientClose = drvvdINIPClientClose; 2473 pImage->VDIfTcpNet.pfnIsClientConnected = drvvdINIPIsClientConnected; 2474 pImage->VDIfTcpNet.pfnSelectOne = drvvdINIPSelectOne; 2475 pImage->VDIfTcpNet.pfnRead = drvvdINIPRead; 2476 pImage->VDIfTcpNet.pfnWrite = drvvdINIPWrite; 2477 pImage->VDIfTcpNet.pfnSgWrite = drvvdINIPSgWrite; 2478 pImage->VDIfTcpNet.pfnFlush = drvvdINIPFlush; 2479 pImage->VDIfTcpNet.pfnSetSendCoalescing = drvvdINIPSetSendCoalescing; 2480 pImage->VDIfTcpNet.pfnGetLocalAddress = drvvdINIPGetLocalAddress; 2481 pImage->VDIfTcpNet.pfnGetPeerAddress = drvvdINIPGetPeerAddress; 2482 pImage->VDIfTcpNet.pfnSelectOneEx = drvvdINIPSelectOneEx; 2483 pImage->VDIfTcpNet.pfnPoke = drvvdINIPPoke; 2383 2484 #endif /* VBOX_WITH_INIP */ 2384 2485 } 2385 2386 /* 2387 * The image has a bandwidth group but the host cache is enabled. 2388 * Use the async I/O framework but tell it to enable the host cache. 2389 */ 2390 if (!fUseNewIo && pThis->pszBwGroup) 2391 { 2392 pThis->fAsyncIoWithHostCache = true; 2393 fUseNewIo = true; 2394 } 2395 2396 /** @todo quick hack to work around problems in the async I/O 2397 * implementation (rw semaphore thread ownership problem) 2398 * while a merge is running. Remove once this is fixed. */ 2399 if (pThis->fMergePending) 2400 fUseNewIo = false; 2401 2402 if (RT_SUCCESS(rc) && fUseNewIo) 2486 rc = VDInterfaceAdd(&pImage->VDIfTcpNet.Core, "DrvVD_TCPNET", 2487 VDINTERFACETYPE_TCPNET, NULL, 2488 sizeof(VDINTERFACETCPNET), &pImage->pVDIfsImage); 2489 AssertRC(rc); 2490 2491 /* Insert the custom I/O interface only if we're told to use new IO. 2492 * Since the I/O interface is per image we could make this more 2493 * flexible in the future if we want to. */ 2494 if (fUseNewIo) 2403 2495 { 2404 2496 #ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 2405 pThis->VDIIOCallbacks.cbSize = sizeof(VDINTERFACEIO); 2406 pThis->VDIIOCallbacks.enmInterface = VDINTERFACETYPE_IO; 2407 pThis->VDIIOCallbacks.pfnOpen = drvvdAsyncIOOpen; 2408 pThis->VDIIOCallbacks.pfnClose = drvvdAsyncIOClose; 2409 pThis->VDIIOCallbacks.pfnGetSize = drvvdAsyncIOGetSize; 2410 pThis->VDIIOCallbacks.pfnSetSize = drvvdAsyncIOSetSize; 2411 pThis->VDIIOCallbacks.pfnReadSync = drvvdAsyncIOReadSync; 2412 pThis->VDIIOCallbacks.pfnWriteSync = drvvdAsyncIOWriteSync; 2413 pThis->VDIIOCallbacks.pfnFlushSync = drvvdAsyncIOFlushSync; 2414 pThis->VDIIOCallbacks.pfnReadAsync = drvvdAsyncIOReadAsync; 2415 pThis->VDIIOCallbacks.pfnWriteAsync = drvvdAsyncIOWriteAsync; 2416 pThis->VDIIOCallbacks.pfnFlushAsync = drvvdAsyncIOFlushAsync; 2497 pImage->VDIfIo.pfnOpen = drvvdAsyncIOOpen; 2498 pImage->VDIfIo.pfnClose = drvvdAsyncIOClose; 2499 pImage->VDIfIo.pfnGetSize = drvvdAsyncIOGetSize; 2500 pImage->VDIfIo.pfnSetSize = drvvdAsyncIOSetSize; 2501 pImage->VDIfIo.pfnReadSync = drvvdAsyncIOReadSync; 2502 pImage->VDIfIo.pfnWriteSync = drvvdAsyncIOWriteSync; 2503 pImage->VDIfIo.pfnFlushSync = drvvdAsyncIOFlushSync; 2504 pImage->VDIfIo.pfnReadAsync = drvvdAsyncIOReadAsync; 2505 pImage->VDIfIo.pfnWriteAsync = drvvdAsyncIOWriteAsync; 2506 pImage->VDIfIo.pfnFlushAsync = drvvdAsyncIOFlushAsync; 2417 2507 #else /* !VBOX_WITH_PDM_ASYNC_COMPLETION */ 2418 2508 rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, 2419 2509 RT_SRC_POS, N_("DrvVD: Configuration error: Async Completion Framework not compiled in")); 2420 2510 #endif /* !VBOX_WITH_PDM_ASYNC_COMPLETION */ 2421 }2422 2423 if (RT_SUCCESS(rc) && pThis->fMergePending)2424 {2425 rc = RTSemFastMutexCreate(&pThis->MergeCompleteMutex);2426 2511 if (RT_SUCCESS(rc)) 2427 rc = RTSemRWCreate(&pThis->MergeLock); 2428 if (RT_SUCCESS(rc)) 2429 { 2430 pThis->VDIThreadSyncCallbacks.cbSize = sizeof(VDINTERFACETHREADSYNC); 2431 pThis->VDIThreadSyncCallbacks.enmInterface = VDINTERFACETYPE_THREADSYNC; 2432 pThis->VDIThreadSyncCallbacks.pfnStartRead = drvvdThreadStartRead; 2433 pThis->VDIThreadSyncCallbacks.pfnFinishRead = drvvdThreadFinishRead; 2434 pThis->VDIThreadSyncCallbacks.pfnStartWrite = drvvdThreadStartWrite; 2435 pThis->VDIThreadSyncCallbacks.pfnFinishWrite = drvvdThreadFinishWrite; 2436 2437 rc = VDInterfaceAdd(&pThis->VDIThreadSync, "DrvVD_ThreadSync", VDINTERFACETYPE_THREADSYNC, 2438 &pThis->VDIThreadSyncCallbacks, pThis, &pThis->pVDIfsDisk); 2439 } 2440 else 2441 { 2442 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2443 N_("DrvVD: Failed to create semaphores for \"MergePending\"")); 2444 } 2445 } 2446 2447 if (RT_SUCCESS(rc)) 2448 { 2449 rc = VDCreate(pThis->pVDIfsDisk, enmType, &pThis->pDisk); 2450 /* Error message is already set correctly. */ 2451 } 2452 } 2453 2454 if (pThis->pDrvMediaAsyncPort && fUseNewIo) 2455 pThis->fAsyncIOSupported = true; 2456 2457 unsigned iImageIdx = 0; 2458 while (pCurNode && RT_SUCCESS(rc)) 2459 { 2460 /* Allocate per-image data. */ 2461 PVBOXIMAGE pImage = drvvdNewImage(pThis); 2462 if (!pImage) 2463 { 2464 rc = VERR_NO_MEMORY; 2465 break; 2466 } 2467 2468 /* 2469 * Read the image configuration. 2470 */ 2471 rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName); 2472 if (RT_FAILURE(rc)) 2473 { 2474 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2475 N_("DrvVD: Configuration error: Querying \"Path\" as string failed")); 2476 break; 2477 } 2478 2479 rc = CFGMR3QueryStringAlloc(pCurNode, "Format", &pszFormat); 2480 if (RT_FAILURE(rc)) 2481 { 2482 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2483 N_("DrvVD: Configuration error: Querying \"Format\" as string failed")); 2484 break; 2485 } 2486 2487 bool fMergeSource; 2488 rc = CFGMR3QueryBoolDef(pCurNode, "MergeSource", &fMergeSource, false); 2489 if (RT_FAILURE(rc)) 2490 { 2491 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2492 N_("DrvVD: Configuration error: Querying \"MergeSource\" as boolean failed")); 2493 break; 2494 } 2495 if (fMergeSource) 2496 { 2497 if (pThis->uMergeSource == VD_LAST_IMAGE) 2498 pThis->uMergeSource = iImageIdx; 2499 else 2500 { 2501 rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES, 2502 N_("DrvVD: Configuration error: Multiple \"MergeSource\" occurrences")); 2503 break; 2504 } 2505 } 2506 2507 bool fMergeTarget; 2508 rc = CFGMR3QueryBoolDef(pCurNode, "MergeTarget", &fMergeTarget, false); 2509 if (RT_FAILURE(rc)) 2510 { 2511 rc = PDMDRV_SET_ERROR(pDrvIns, rc, 2512 N_("DrvVD: Configuration error: Querying \"MergeTarget\" as boolean failed")); 2513 break; 2514 } 2515 if (fMergeTarget) 2516 { 2517 if (pThis->uMergeTarget == VD_LAST_IMAGE) 2518 pThis->uMergeTarget = iImageIdx; 2519 else 2520 { 2521 rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES, 2522 N_("DrvVD: Configuration error: Multiple \"MergeTarget\" occurrences")); 2523 break; 2524 } 2525 } 2526 2527 PCFGMNODE pCfgVDConfig = CFGMR3GetChild(pCurNode, "VDConfig"); 2528 rc = VDInterfaceAdd(&pImage->VDIConfig, "DrvVD_Config", VDINTERFACETYPE_CONFIG, 2529 &pThis->VDIConfigCallbacks, pCfgVDConfig, &pImage->pVDIfsImage); 2530 AssertRC(rc); 2531 2532 /* Unconditionally insert the TCPNET interface, don't bother to check 2533 * if an image really needs it. Will be ignored. Since the TCPNET 2534 * interface is per image we could make this more flexible in the 2535 * future if we want to. */ 2536 rc = VDInterfaceAdd(&pImage->VDITcpNet, "DrvVD_TCPNET", 2537 VDINTERFACETYPE_TCPNET, &pThis->VDITcpNetCallbacks, 2538 NULL, &pImage->pVDIfsImage); 2539 AssertRC(rc); 2540 2541 /* Insert the custom I/O interface only if we're told to use new IO. 2542 * Since the I/O interface is per image we could make this more 2543 * flexible in the future if we want to. */ 2544 if (fUseNewIo) 2545 { 2546 rc = VDInterfaceAdd(&pImage->VDIIO, "DrvVD_IO", VDINTERFACETYPE_IO, 2547 &pThis->VDIIOCallbacks, pThis, 2548 &pImage->pVDIfsImage); 2512 rc = VDInterfaceAdd(&pImage->VDIfIo.Core, "DrvVD_IO", VDINTERFACETYPE_IO, 2513 pThis, sizeof(VDINTERFACEIO), &pImage->pVDIfsImage); 2549 2514 AssertRC(rc); 2550 2515 } … … 2620 2585 if (fUseNewIo) 2621 2586 { 2622 rc = VDInterfaceAdd(&pThis->VDIIOCache, "DrvVD_IO", VDINTERFACETYPE_IO, 2623 &pThis->VDIIOCallbacks, pThis, 2624 &pThis->pVDIfsCache); 2587 #ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 2588 pThis->VDIfIoCache.pfnOpen = drvvdAsyncIOOpen; 2589 pThis->VDIfIoCache.pfnClose = drvvdAsyncIOClose; 2590 pThis->VDIfIoCache.pfnGetSize = drvvdAsyncIOGetSize; 2591 pThis->VDIfIoCache.pfnSetSize = drvvdAsyncIOSetSize; 2592 pThis->VDIfIoCache.pfnReadSync = drvvdAsyncIOReadSync; 2593 pThis->VDIfIoCache.pfnWriteSync = drvvdAsyncIOWriteSync; 2594 pThis->VDIfIoCache.pfnFlushSync = drvvdAsyncIOFlushSync; 2595 pThis->VDIfIoCache.pfnReadAsync = drvvdAsyncIOReadAsync; 2596 pThis->VDIfIoCache.pfnWriteAsync = drvvdAsyncIOWriteAsync; 2597 pThis->VDIfIoCache.pfnFlushAsync = drvvdAsyncIOFlushAsync; 2598 #else /* !VBOX_WITH_PDM_ASYNC_COMPLETION */ 2599 rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, 2600 RT_SRC_POS, N_("DrvVD: Configuration error: Async Completion Framework not compiled in")); 2601 #endif /* !VBOX_WITH_PDM_ASYNC_COMPLETION */ 2602 if (RT_SUCCESS(rc)) 2603 rc = VDInterfaceAdd(&pThis->VDIfIoCache.Core, "DrvVD_IO", VDINTERFACETYPE_IO, 2604 pThis, sizeof(VDINTERFACEIO), &pThis->pVDIfsCache); 2625 2605 AssertRC(rc); 2626 2606 }
Note:
See TracChangeset
for help on using the changeset viewer.