Changeset 66378 in vbox for trunk/src/VBox/Storage
- Timestamp:
- Mar 31, 2017 11:20:50 AM (8 years ago)
- Location:
- trunk/src/VBox/Storage
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/Makefile.kmk
r66140 r66378 38 38 StorageLib_SOURCES = \ 39 39 VD.cpp \ 40 VDPlugin.cpp \ 40 41 VDVfs.cpp \ 41 42 VDIfVfs.cpp \ -
trunk/src/VBox/Storage/VD.cpp
r66250 r66378 1 1 /* $Id$ */ 2 2 /** @file 3 * V BoxHDD - VBox HDD Container implementation.3 * VD - Virtual disk container implementation. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-201 6Oracle Corporation7 * Copyright (C) 2006-2017 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 32 32 #include <iprt/string.h> 33 33 #include <iprt/asm.h> 34 #include <iprt/ldr.h> 35 #include <iprt/dir.h> 34 #include <iprt/param.h> 36 35 #include <iprt/path.h> 37 #include <iprt/param.h>38 #include <iprt/memcache.h>39 36 #include <iprt/sg.h> 40 #include <iprt/list.h>41 #include <iprt/avl.h>42 37 #include <iprt/semaphore.h> 43 38 44 #include <VBox/vd-plugin.h> 45 46 #include "VDBackends.h" 47 48 /** Disable dynamic backends on non x86 architectures. This feature 49 * requires the SUPR3 library which is not available there. 50 */ 51 #if !defined(VBOX_HDD_NO_DYNAMIC_BACKENDS) && !defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64) 52 # define VBOX_HDD_NO_DYNAMIC_BACKENDS 53 #endif 54 55 /** Magic number contained in the VDISK instance data, used for checking that the passed 56 * pointer contains a valid instance in debug builds. */ 57 #define VDISK_SIGNATURE 0x6f0e2a7d 39 #include "VDInternal.h" 58 40 59 41 /** Buffer size used for merging images. */ … … 80 62 81 63 /** 82 * Structure containing everything I/O related83 * for the image and cache descriptors.84 */85 typedef struct VDIO86 {87 /** I/O interface to the upper layer. */88 PVDINTERFACEIO pInterfaceIo;89 90 /** Per image internal I/O interface. */91 VDINTERFACEIOINT VDIfIoInt;92 93 /** Fallback I/O interface, only used if the caller doesn't provide it. */94 VDINTERFACEIO VDIfIo;95 96 /** Opaque backend data. */97 void *pBackendData;98 /** Disk this image is part of */99 PVDISK pDisk;100 /** Flag whether to ignore flush requests. */101 bool fIgnoreFlush;102 } VDIO, *PVDIO;103 104 /** Forward declaration of an I/O task */105 typedef struct VDIOTASK *PVDIOTASK;106 107 /**108 * VBox HDD Container image descriptor.109 */110 typedef struct VDIMAGE111 {112 /** Link to parent image descriptor, if any. */113 struct VDIMAGE *pPrev;114 /** Link to child image descriptor, if any. */115 struct VDIMAGE *pNext;116 /** Container base filename. (UTF-8) */117 char *pszFilename;118 /** Data managed by the backend which keeps the actual info. */119 void *pBackendData;120 /** Cached sanitized image flags. */121 unsigned uImageFlags;122 /** Image open flags (only those handled generically in this code and which123 * the backends will never ever see). */124 unsigned uOpenFlags;125 126 /** Function pointers for the various backend methods. */127 PCVDIMAGEBACKEND Backend;128 /** Pointer to list of VD interfaces, per-image. */129 PVDINTERFACE pVDIfsImage;130 /** I/O related things. */131 VDIO VDIo;132 } VDIMAGE, *PVDIMAGE;133 134 /**135 64 * uModified bit flags. 136 65 */ … … 139 68 #define VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE RT_BIT(2) 140 69 141 142 /**143 * VBox HDD Cache image descriptor.144 */145 typedef struct VDCACHE146 {147 /** Cache base filename. (UTF-8) */148 char *pszFilename;149 /** Data managed by the backend which keeps the actual info. */150 void *pBackendData;151 /** Cached sanitized image flags. */152 unsigned uImageFlags;153 /** Image open flags (only those handled generically in this code and which154 * the backends will never ever see). */155 unsigned uOpenFlags;156 157 /** Function pointers for the various backend methods. */158 PCVDCACHEBACKEND Backend;159 160 /** Pointer to list of VD interfaces, per-cache. */161 PVDINTERFACE pVDIfsCache;162 /** I/O related things. */163 VDIO VDIo;164 } VDCACHE, *PVDCACHE;165 166 /**167 * A block waiting for a discard.168 */169 typedef struct VDDISCARDBLOCK170 {171 /** AVL core. */172 AVLRU64NODECORE Core;173 /** LRU list node. */174 RTLISTNODE NodeLru;175 /** Number of bytes to discard. */176 size_t cbDiscard;177 /** Bitmap of allocated sectors. */178 void *pbmAllocated;179 } VDDISCARDBLOCK, *PVDDISCARDBLOCK;180 181 /**182 * VD discard state.183 */184 typedef struct VDDISCARDSTATE185 {186 /** Number of bytes waiting for a discard. */187 size_t cbDiscarding;188 /** AVL tree with blocks waiting for a discard.189 * The uOffset + cbDiscard range is the search key. */190 PAVLRU64TREE pTreeBlocks;191 /** LRU list of the least frequently discarded blocks.192 * If there are to many blocks waiting the least frequently used193 * will be removed and the range will be set to 0.194 */195 RTLISTNODE ListLru;196 } VDDISCARDSTATE, *PVDDISCARDSTATE;197 198 /**199 * VD filter instance.200 */201 typedef struct VDFILTER202 {203 /** List node for the read filter chain. */204 RTLISTNODE ListNodeChainRead;205 /** List node for the write filter chain. */206 RTLISTNODE ListNodeChainWrite;207 /** Number of references to this filter. */208 uint32_t cRefs;209 /** Opaque VD filter backend instance data. */210 void *pvBackendData;211 /** Pointer to the filter backend interface. */212 PCVDFILTERBACKEND pBackend;213 /** Pointer to list of VD interfaces, per-filter. */214 PVDINTERFACE pVDIfsFilter;215 /** I/O related things. */216 VDIO VDIo;217 } VDFILTER;218 /** Pointer to a VD filter instance. */219 typedef VDFILTER *PVDFILTER;220 221 /**222 * VBox HDD Container main structure, private part.223 */224 struct VDISK225 {226 /** Structure signature (VDISK_SIGNATURE). */227 uint32_t u32Signature;228 229 /** Image type. */230 VDTYPE enmType;231 232 /** Number of opened images. */233 unsigned cImages;234 235 /** Base image. */236 PVDIMAGE pBase;237 238 /** Last opened image in the chain.239 * The same as pBase if only one image is used. */240 PVDIMAGE pLast;241 242 /** If a merge to one of the parents is running this may be non-NULL243 * to indicate to what image the writes should be additionally relayed. */244 PVDIMAGE pImageRelay;245 246 /** Flags representing the modification state. */247 unsigned uModified;248 249 /** Cached size of this disk. */250 uint64_t cbSize;251 /** Cached PCHS geometry for this disk. */252 VDGEOMETRY PCHSGeometry;253 /** Cached LCHS geometry for this disk. */254 VDGEOMETRY LCHSGeometry;255 256 /** Pointer to list of VD interfaces, per-disk. */257 PVDINTERFACE pVDIfsDisk;258 /** Pointer to the common interface structure for error reporting. */259 PVDINTERFACEERROR pInterfaceError;260 /** Pointer to the optional thread synchronization callbacks. */261 PVDINTERFACETHREADSYNC pInterfaceThreadSync;262 263 /** Memory cache for I/O contexts */264 RTMEMCACHE hMemCacheIoCtx;265 /** Memory cache for I/O tasks. */266 RTMEMCACHE hMemCacheIoTask;267 /** An I/O context is currently using the disk structures268 * Every I/O context must be placed on one of the lists below. */269 volatile bool fLocked;270 /** Head of pending I/O tasks waiting for completion - LIFO order. */271 volatile PVDIOTASK pIoTasksPendingHead;272 /** Head of newly queued I/O contexts - LIFO order. */273 volatile PVDIOCTX pIoCtxHead;274 /** Head of halted I/O contexts which are given back to generic275 * disk framework by the backend. - LIFO order. */276 volatile PVDIOCTX pIoCtxHaltedHead;277 278 /** Head of blocked I/O contexts, processed only279 * after pIoCtxLockOwner was freed - LIFO order. */280 volatile PVDIOCTX pIoCtxBlockedHead;281 /** I/O context which locked the disk for a growing write or flush request.282 * Other flush or growing write requests need to wait until283 * the current one completes. - NIL_VDIOCTX if unlocked. */284 volatile PVDIOCTX pIoCtxLockOwner;285 /** If the disk was locked by a growing write, flush or discard request this286 * contains the start offset to check for interfering I/O while it is in progress. */287 uint64_t uOffsetStartLocked;288 /** If the disk was locked by a growing write, flush or discard request this contains289 * the first non affected offset to check for interfering I/O while it is in progress. */290 uint64_t uOffsetEndLocked;291 292 /** Pointer to the L2 disk cache if any. */293 PVDCACHE pCache;294 /** Pointer to the discard state if any. */295 PVDDISCARDSTATE pDiscard;296 297 /** Read filter chain - PVDFILTER. */298 RTLISTANCHOR ListFilterChainRead;299 /** Write filter chain - PVDFILTER. */300 RTLISTANCHOR ListFilterChainWrite;301 };302 70 303 71 # define VD_IS_LOCKED(a_pDisk) \ … … 350 118 struct VDIOCTX * volatile pIoCtxNext; 351 119 /** Disk this is request is for. */ 352 PVDISK pDisk;120 PVDISK pDisk; 353 121 /** Return code. */ 354 122 int rcReq; … … 606 374 #define VDMETAXFER_TXDIR_SET(flags, dir) ((flags) = (flags & ~VDMETAXFER_TXDIR_MASK) | (dir)) 607 375 608 /**609 * Plugin structure.610 */611 typedef struct VDPLUGIN612 {613 /** Pointer to the next plugin structure. */614 RTLISTNODE NodePlugin;615 /** Handle of loaded plugin library. */616 RTLDRMOD hPlugin;617 /** Filename of the loaded plugin. */618 char *pszFilename;619 } VDPLUGIN;620 /** Pointer to a plugin structure. */621 typedef VDPLUGIN *PVDPLUGIN;622 623 /** Head of loaded plugin list. */624 static RTLISTANCHOR g_ListPluginsLoaded;625 626 /** Number of image backends supported. */627 static unsigned g_cBackends = 0;628 /** Array of pointers to the image backends. */629 static PCVDIMAGEBACKEND *g_apBackends = NULL;630 /** Array of handles to the corresponding plugin. */631 static RTLDRMOD *g_ahBackendPlugins = NULL;632 /** Builtin image backends. */633 static PCVDIMAGEBACKEND aStaticBackends[] =634 {635 &g_VmdkBackend,636 &g_VDIBackend,637 &g_VhdBackend,638 &g_ParallelsBackend,639 &g_DmgBackend,640 &g_QedBackend,641 &g_QCowBackend,642 &g_VhdxBackend,643 &g_RawBackend,644 &g_CueBackend,645 &g_ISCSIBackend646 };647 648 /** Number of supported cache backends. */649 static unsigned g_cCacheBackends = 0;650 /** Array of pointers to the cache backends. */651 static PCVDCACHEBACKEND *g_apCacheBackends = NULL;652 /** Array of handles to the corresponding plugin. */653 static RTLDRMOD *g_ahCacheBackendPlugins = NULL;654 /** Builtin cache backends. */655 static PCVDCACHEBACKEND aStaticCacheBackends[] =656 {657 &g_VciCacheBackend658 };659 660 /** Number of supported filter backends. */661 static unsigned g_cFilterBackends = 0;662 /** Array of pointers to the filters backends. */663 static PCVDFILTERBACKEND *g_apFilterBackends = NULL;664 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS665 /** Array of handles to the corresponding plugin. */666 static PRTLDRMOD g_pahFilterBackendPlugins = NULL;667 #endif668 669 376 /** Forward declaration of the async discard helper. */ 670 377 static DECLCALLBACK(int) vdDiscardHelperAsync(PVDIOCTX pIoCtx); … … 675 382 676 383 /** 677 * internal: add several backends.678 */679 static int vdAddBackends(RTLDRMOD hPlugin, PCVDIMAGEBACKEND *ppBackends, unsigned cBackends)680 {681 PCVDIMAGEBACKEND *pTmp = (PCVDIMAGEBACKEND *)RTMemRealloc(g_apBackends,682 (g_cBackends + cBackends) * sizeof(PCVDIMAGEBACKEND));683 if (RT_UNLIKELY(!pTmp))684 return VERR_NO_MEMORY;685 g_apBackends = pTmp;686 687 RTLDRMOD *pTmpPlugins = (RTLDRMOD*)RTMemRealloc(g_ahBackendPlugins,688 (g_cBackends + cBackends) * sizeof(RTLDRMOD));689 if (RT_UNLIKELY(!pTmpPlugins))690 return VERR_NO_MEMORY;691 g_ahBackendPlugins = pTmpPlugins;692 memcpy(&g_apBackends[g_cBackends], ppBackends, cBackends * sizeof(PCVDIMAGEBACKEND));693 for (unsigned i = g_cBackends; i < g_cBackends + cBackends; i++)694 g_ahBackendPlugins[i] = hPlugin;695 g_cBackends += cBackends;696 return VINF_SUCCESS;697 }698 699 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS700 /**701 * internal: add single backend.702 */703 DECLINLINE(int) vdAddBackend(RTLDRMOD hPlugin, PCVDIMAGEBACKEND pBackend)704 {705 return vdAddBackends(hPlugin, &pBackend, 1);706 }707 #endif708 709 /**710 * internal: add several cache backends.711 */712 static int vdAddCacheBackends(RTLDRMOD hPlugin, PCVDCACHEBACKEND *ppBackends, unsigned cBackends)713 {714 PCVDCACHEBACKEND *pTmp = (PCVDCACHEBACKEND*)RTMemRealloc(g_apCacheBackends,715 (g_cCacheBackends + cBackends) * sizeof(PCVDCACHEBACKEND));716 if (RT_UNLIKELY(!pTmp))717 return VERR_NO_MEMORY;718 g_apCacheBackends = pTmp;719 720 RTLDRMOD *pTmpPlugins = (RTLDRMOD*)RTMemRealloc(g_ahCacheBackendPlugins,721 (g_cCacheBackends + cBackends) * sizeof(RTLDRMOD));722 if (RT_UNLIKELY(!pTmpPlugins))723 return VERR_NO_MEMORY;724 g_ahCacheBackendPlugins = pTmpPlugins;725 memcpy(&g_apCacheBackends[g_cCacheBackends], ppBackends, cBackends * sizeof(PCVDCACHEBACKEND));726 for (unsigned i = g_cCacheBackends; i < g_cCacheBackends + cBackends; i++)727 g_ahCacheBackendPlugins[i] = hPlugin;728 g_cCacheBackends += cBackends;729 return VINF_SUCCESS;730 }731 732 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS733 734 /**735 * internal: add single cache backend.736 */737 DECLINLINE(int) vdAddCacheBackend(RTLDRMOD hPlugin, PCVDCACHEBACKEND pBackend)738 {739 return vdAddCacheBackends(hPlugin, &pBackend, 1);740 }741 742 743 /**744 * Add several filter backends.745 *746 * @returns VBox status code.747 * @param hPlugin Plugin handle to add.748 * @param ppBackends Array of filter backends to add.749 * @param cBackends Number of backends to add.750 */751 static int vdAddFilterBackends(RTLDRMOD hPlugin, PCVDFILTERBACKEND *ppBackends, unsigned cBackends)752 {753 PCVDFILTERBACKEND *pTmp = (PCVDFILTERBACKEND *)RTMemRealloc(g_apFilterBackends,754 (g_cFilterBackends + cBackends) * sizeof(PCVDFILTERBACKEND));755 if (RT_UNLIKELY(!pTmp))756 return VERR_NO_MEMORY;757 g_apFilterBackends = pTmp;758 759 PRTLDRMOD pTmpPlugins = (PRTLDRMOD)RTMemRealloc(g_pahFilterBackendPlugins,760 (g_cFilterBackends + cBackends) * sizeof(RTLDRMOD));761 if (RT_UNLIKELY(!pTmpPlugins))762 return VERR_NO_MEMORY;763 764 g_pahFilterBackendPlugins = pTmpPlugins;765 memcpy(&g_apFilterBackends[g_cFilterBackends], ppBackends, cBackends * sizeof(PCVDFILTERBACKEND));766 for (unsigned i = g_cFilterBackends; i < g_cFilterBackends + cBackends; i++)767 g_pahFilterBackendPlugins[i] = hPlugin;768 g_cFilterBackends += cBackends;769 return VINF_SUCCESS;770 }771 772 773 /**774 * Add a single filter backend to the list of supported filters.775 *776 * @returns VBox status code.777 * @param hPlugin Plugin handle to add.778 * @param pBackend The backend to add.779 */780 DECLINLINE(int) vdAddFilterBackend(RTLDRMOD hPlugin, PCVDFILTERBACKEND pBackend)781 {782 return vdAddFilterBackends(hPlugin, &pBackend, 1);783 }784 785 #endif /* VBOX_HDD_NO_DYNAMIC_BACKENDS*/786 787 /**788 384 * internal: issue error message. 789 385 */ … … 842 438 return rc; 843 439 } 844 845 /**846 * internal: find image format backend.847 */848 static int vdFindBackend(const char *pszBackend, PCVDIMAGEBACKEND *ppBackend)849 {850 int rc = VINF_SUCCESS;851 PCVDIMAGEBACKEND pBackend = NULL;852 853 if (!g_apBackends)854 VDInit();855 856 for (unsigned i = 0; i < g_cBackends; i++)857 {858 if (!RTStrICmp(pszBackend, g_apBackends[i]->pszBackendName))859 {860 pBackend = g_apBackends[i];861 break;862 }863 }864 *ppBackend = pBackend;865 return rc;866 }867 868 /**869 * internal: find cache format backend.870 */871 static int vdFindCacheBackend(const char *pszBackend, PCVDCACHEBACKEND *ppBackend)872 {873 int rc = VINF_SUCCESS;874 PCVDCACHEBACKEND pBackend = NULL;875 876 if (!g_apCacheBackends)877 VDInit();878 879 for (unsigned i = 0; i < g_cCacheBackends; i++)880 {881 if (!RTStrICmp(pszBackend, g_apCacheBackends[i]->pszBackendName))882 {883 pBackend = g_apCacheBackends[i];884 break;885 }886 }887 *ppBackend = pBackend;888 return rc;889 }890 891 /**892 * internal: find filter backend.893 */894 static int vdFindFilterBackend(const char *pszFilter, PCVDFILTERBACKEND *ppBackend)895 {896 int rc = VINF_SUCCESS;897 PCVDFILTERBACKEND pBackend = NULL;898 899 for (unsigned i = 0; i < g_cFilterBackends; i++)900 {901 if (!RTStrICmp(pszFilter, g_apFilterBackends[i]->pszBackendName))902 {903 pBackend = g_apFilterBackends[i];904 break;905 }906 }907 *ppBackend = pBackend;908 return rc;909 }910 911 440 912 441 /** … … 3541 3070 } 3542 3071 3543 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS3544 3545 /**3546 * @interface_method_impl{VDBACKENDREGISTER,pfnRegisterImage}3547 */3548 static DECLCALLBACK(int) vdPluginRegisterImage(void *pvUser, PCVDIMAGEBACKEND pBackend)3549 {3550 int rc = VINF_SUCCESS;3551 3552 if (VD_VERSION_ARE_COMPATIBLE(VD_IMGBACKEND_VERSION, pBackend->u32Version))3553 vdAddBackend((RTLDRMOD)pvUser, pBackend);3554 else3555 {3556 LogFunc(("ignored plugin: pBackend->u32Version=%u rc=%Rrc\n", pBackend->u32Version, rc));3557 rc = VERR_IGNORED;3558 }3559 3560 return rc;3561 }3562 3563 /**3564 * @interface_method_impl{VDBACKENDREGISTER,pfnRegisterCache}3565 */3566 static DECLCALLBACK(int) vdPluginRegisterCache(void *pvUser, PCVDCACHEBACKEND pBackend)3567 {3568 int rc = VINF_SUCCESS;3569 3570 if (VD_VERSION_ARE_COMPATIBLE(VD_CACHEBACKEND_VERSION, pBackend->u32Version))3571 vdAddCacheBackend((RTLDRMOD)pvUser, pBackend);3572 else3573 {3574 LogFunc(("ignored plugin: pBackend->u32Version=%u rc=%Rrc\n", pBackend->u32Version, rc));3575 rc = VERR_IGNORED;3576 }3577 3578 return rc;3579 }3580 3581 /**3582 * @interface_method_impl{VDBACKENDREGISTER,pfnRegisterFilter}3583 */3584 static DECLCALLBACK(int) vdPluginRegisterFilter(void *pvUser, PCVDFILTERBACKEND pBackend)3585 {3586 int rc = VINF_SUCCESS;3587 3588 if (VD_VERSION_ARE_COMPATIBLE(VD_FLTBACKEND_VERSION, pBackend->u32Version))3589 vdAddFilterBackend((RTLDRMOD)pvUser, pBackend);3590 else3591 {3592 LogFunc(("ignored plugin: pBackend->u32Version=%u rc=%Rrc\n", pBackend->u32Version, rc));3593 rc = VERR_IGNORED;3594 }3595 3596 return rc;3597 }3598 3599 /**3600 * Checks whether the given plugin filename was already loaded.3601 *3602 * @returns Pointer to already loaded plugin, NULL if not found.3603 * @param pszFilename The filename to check.3604 */3605 static PVDPLUGIN vdPluginFind(const char *pszFilename)3606 {3607 PVDPLUGIN pIt;3608 RTListForEach(&g_ListPluginsLoaded, pIt, VDPLUGIN, NodePlugin)3609 {3610 if (!RTStrCmp(pIt->pszFilename, pszFilename))3611 return pIt;3612 }3613 3614 return NULL;3615 }3616 3617 /**3618 * Adds a plugin to the list of loaded plugins.3619 *3620 * @returns VBox status code.3621 * @param hPlugin Plugin handle to add.3622 * @param pszFilename The associated filename, used for finding duplicates.3623 */3624 static int vdAddPlugin(RTLDRMOD hPlugin, const char *pszFilename)3625 {3626 int rc = VINF_SUCCESS;3627 PVDPLUGIN pPlugin = (PVDPLUGIN)RTMemAllocZ(sizeof(VDPLUGIN));3628 3629 if (pPlugin)3630 {3631 pPlugin->hPlugin = hPlugin;3632 pPlugin->pszFilename = RTStrDup(pszFilename);3633 if (pPlugin->pszFilename)3634 RTListAppend(&g_ListPluginsLoaded, &pPlugin->NodePlugin);3635 else3636 {3637 RTMemFree(pPlugin);3638 rc = VERR_NO_MEMORY;3639 }3640 }3641 else3642 rc = VERR_NO_MEMORY;3643 3644 return rc;3645 }3646 3647 static int vdRemovePlugin(const char *pszFilename)3648 {3649 /* Find plugin to be removed from the list. */3650 PVDPLUGIN pIt = vdPluginFind(pszFilename);3651 if (!pIt)3652 return VINF_SUCCESS;3653 3654 /** @todo r=klaus: need to add a plugin entry point for unregistering the3655 * backends. Only if this doesn't exist (or fails to work) we should fall3656 * back to the following uncoordinated backend cleanup. */3657 for (unsigned i = 0; i < g_cBackends; i++)3658 {3659 while (i < g_cBackends && g_ahBackendPlugins[i] == pIt->hPlugin)3660 {3661 memcpy(&g_apBackends[i], &g_apBackends[i + 1], (g_cBackends - i - 1) * sizeof(PCVDIMAGEBACKEND));3662 memcpy(&g_ahBackendPlugins[i], &g_ahBackendPlugins[i + 1], (g_cBackends - i - 1) * sizeof(RTLDRMOD));3663 /** @todo for now skip reallocating, doesn't save much */3664 g_cBackends--;3665 }3666 }3667 for (unsigned i = 0; i < g_cCacheBackends; i++)3668 {3669 while (i < g_cCacheBackends && g_ahCacheBackendPlugins[i] == pIt->hPlugin)3670 {3671 memcpy(&g_apCacheBackends[i], &g_apCacheBackends[i + 1], (g_cCacheBackends - i - 1) * sizeof(PCVDCACHEBACKEND));3672 memcpy(&g_ahCacheBackendPlugins[i], &g_ahCacheBackendPlugins[i + 1], (g_cCacheBackends - i - 1) * sizeof(RTLDRMOD));3673 /** @todo for now skip reallocating, doesn't save much */3674 g_cCacheBackends--;3675 }3676 }3677 for (unsigned i = 0; i < g_cFilterBackends; i++)3678 {3679 while (i < g_cFilterBackends && g_pahFilterBackendPlugins[i] == pIt->hPlugin)3680 {3681 memcpy(&g_apFilterBackends[i], &g_apFilterBackends[i + 1], (g_cFilterBackends - i - 1) * sizeof(PCVDFILTERBACKEND));3682 memcpy(&g_pahFilterBackendPlugins[i], &g_pahFilterBackendPlugins[i + 1], (g_cFilterBackends - i - 1) * sizeof(RTLDRMOD));3683 /** @todo for now skip reallocating, doesn't save much */3684 g_cFilterBackends--;3685 }3686 }3687 3688 /* Remove the plugin node now, all traces of it are gone. */3689 RTListNodeRemove(&pIt->NodePlugin);3690 RTLdrClose(pIt->hPlugin);3691 RTStrFree(pIt->pszFilename);3692 RTMemFree(pIt);3693 3694 return VINF_SUCCESS;3695 }3696 3697 #endif /* !VBOX_HDD_NO_DYNAMIC_BACKENDS */3698 3699 /**3700 * Worker for VDPluginLoadFromFilename() and vdPluginLoadFromPath().3701 *3702 * @returns VBox status code.3703 * @param pszFilename The plugin filename to load.3704 */3705 static int vdPluginLoadFromFilename(const char *pszFilename)3706 {3707 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS3708 /* Plugin loaded? Nothing to do. */3709 if (vdPluginFind(pszFilename))3710 return VINF_SUCCESS;3711 3712 RTLDRMOD hPlugin = NIL_RTLDRMOD;3713 int rc = SUPR3HardenedLdrLoadPlugIn(pszFilename, &hPlugin, NULL);3714 if (RT_SUCCESS(rc))3715 {3716 VDBACKENDREGISTER BackendRegister;3717 PFNVDPLUGINLOAD pfnVDPluginLoad = NULL;3718 3719 BackendRegister.u32Version = VD_BACKENDREG_CB_VERSION;3720 BackendRegister.pfnRegisterImage = vdPluginRegisterImage;3721 BackendRegister.pfnRegisterCache = vdPluginRegisterCache;3722 BackendRegister.pfnRegisterFilter = vdPluginRegisterFilter;3723 3724 rc = RTLdrGetSymbol(hPlugin, VD_PLUGIN_LOAD_NAME, (void**)&pfnVDPluginLoad);3725 if (RT_FAILURE(rc) || !pfnVDPluginLoad)3726 {3727 LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnVDPluginLoad=%#p\n",3728 VD_PLUGIN_LOAD_NAME, pszFilename, rc, pfnVDPluginLoad));3729 if (RT_SUCCESS(rc))3730 rc = VERR_SYMBOL_NOT_FOUND;3731 }3732 3733 if (RT_SUCCESS(rc))3734 {3735 /* Get the function table. */3736 rc = pfnVDPluginLoad(hPlugin, &BackendRegister);3737 }3738 else3739 LogFunc(("ignored plugin '%s': rc=%Rrc\n", pszFilename, rc));3740 3741 /* Create a plugin entry on success. */3742 if (RT_SUCCESS(rc))3743 vdAddPlugin(hPlugin, pszFilename);3744 else3745 RTLdrClose(hPlugin);3746 }3747 3748 return rc;3749 #else3750 RT_NOREF1(pszFilename);3751 return VERR_NOT_IMPLEMENTED;3752 #endif3753 }3754 3755 /**3756 * Worker for VDPluginLoadFromPath() and vdLoadDynamicBackends().3757 *3758 * @returns VBox status code.3759 * @param pszPath The path to load plugins from.3760 */3761 static int vdPluginLoadFromPath(const char *pszPath)3762 {3763 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS3764 /* To get all entries with VBoxHDD as prefix. */3765 char *pszPluginFilter = RTPathJoinA(pszPath, VD_PLUGIN_PREFIX "*");3766 if (!pszPluginFilter)3767 return VERR_NO_STR_MEMORY;3768 3769 PRTDIRENTRYEX pPluginDirEntry = NULL;3770 PRTDIR pPluginDir = NULL;3771 size_t cbPluginDirEntry = sizeof(RTDIRENTRYEX);3772 int rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT, 0);3773 if (RT_SUCCESS(rc))3774 {3775 pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(sizeof(RTDIRENTRYEX));3776 if (pPluginDirEntry)3777 {3778 while ( (rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK))3779 != VERR_NO_MORE_FILES)3780 {3781 char *pszPluginPath = NULL;3782 3783 if (rc == VERR_BUFFER_OVERFLOW)3784 {3785 /* allocate new buffer. */3786 RTMemFree(pPluginDirEntry);3787 pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(cbPluginDirEntry);3788 if (!pPluginDirEntry)3789 {3790 rc = VERR_NO_MEMORY;3791 break;3792 }3793 /* Retry. */3794 rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);3795 if (RT_FAILURE(rc))3796 break;3797 }3798 else if (RT_FAILURE(rc))3799 break;3800 3801 /* We got the new entry. */3802 if (!RTFS_IS_FILE(pPluginDirEntry->Info.Attr.fMode))3803 continue;3804 3805 /* Prepend the path to the libraries. */3806 pszPluginPath = RTPathJoinA(pszPath, pPluginDirEntry->szName);3807 if (!pszPluginPath)3808 {3809 rc = VERR_NO_STR_MEMORY;3810 break;3811 }3812 3813 rc = vdPluginLoadFromFilename(pszPluginPath);3814 RTStrFree(pszPluginPath);3815 }3816 3817 RTMemFree(pPluginDirEntry);3818 }3819 else3820 rc = VERR_NO_MEMORY;3821 3822 RTDirClose(pPluginDir);3823 }3824 else3825 {3826 /* On Windows the above immediately signals that there are no3827 * files matching, while on other platforms enumerating the3828 * files below fails. Either way: no plugins. */3829 }3830 3831 if (rc == VERR_NO_MORE_FILES)3832 rc = VINF_SUCCESS;3833 RTStrFree(pszPluginFilter);3834 return rc;3835 #else3836 RT_NOREF1(pszPath);3837 return VERR_NOT_IMPLEMENTED;3838 #endif3839 }3840 3841 /**3842 * internal: scans plugin directory and loads found plugins.3843 */3844 static int vdLoadDynamicBackends(void)3845 {3846 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS3847 /*3848 * Enumerate plugin backends from the application directory where the other3849 * shared libraries are.3850 */3851 char szPath[RTPATH_MAX];3852 int rc = RTPathAppPrivateArch(szPath, sizeof(szPath));3853 if (RT_FAILURE(rc))3854 return rc;3855 3856 return vdPluginLoadFromPath(szPath);3857 #else3858 return VINF_SUCCESS;3859 #endif3860 }3861 3862 /**3863 * Worker for VDPluginUnloadFromFilename() and vdPluginUnloadFromPath().3864 *3865 * @returns VBox status code.3866 * @param pszFilename The plugin filename to unload.3867 */3868 static int vdPluginUnloadFromFilename(const char *pszFilename)3869 {3870 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS3871 return vdRemovePlugin(pszFilename);3872 #else3873 RT_NOREF1(pszFilename);3874 return VERR_NOT_IMPLEMENTED;3875 #endif3876 }3877 3878 /**3879 * Worker for VDPluginUnloadFromPath().3880 *3881 * @returns VBox status code.3882 * @param pszPath The path to unload plugins from.3883 */3884 static int vdPluginUnloadFromPath(const char *pszPath)3885 {3886 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS3887 /* To get all entries with VBoxHDD as prefix. */3888 char *pszPluginFilter = RTPathJoinA(pszPath, VD_PLUGIN_PREFIX "*");3889 if (!pszPluginFilter)3890 return VERR_NO_STR_MEMORY;3891 3892 PRTDIRENTRYEX pPluginDirEntry = NULL;3893 PRTDIR pPluginDir = NULL;3894 size_t cbPluginDirEntry = sizeof(RTDIRENTRYEX);3895 int rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT, 0);3896 if (RT_SUCCESS(rc))3897 {3898 pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(sizeof(RTDIRENTRYEX));3899 if (pPluginDirEntry)3900 {3901 while ((rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK)) != VERR_NO_MORE_FILES)3902 {3903 char *pszPluginPath = NULL;3904 3905 if (rc == VERR_BUFFER_OVERFLOW)3906 {3907 /* allocate new buffer. */3908 RTMemFree(pPluginDirEntry);3909 pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(cbPluginDirEntry);3910 if (!pPluginDirEntry)3911 {3912 rc = VERR_NO_MEMORY;3913 break;3914 }3915 /* Retry. */3916 rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);3917 if (RT_FAILURE(rc))3918 break;3919 }3920 else if (RT_FAILURE(rc))3921 break;3922 3923 /* We got the new entry. */3924 if (!RTFS_IS_FILE(pPluginDirEntry->Info.Attr.fMode))3925 continue;3926 3927 /* Prepend the path to the libraries. */3928 pszPluginPath = RTPathJoinA(pszPath, pPluginDirEntry->szName);3929 if (!pszPluginPath)3930 {3931 rc = VERR_NO_STR_MEMORY;3932 break;3933 }3934 3935 rc = vdPluginUnloadFromFilename(pszPluginPath);3936 RTStrFree(pszPluginPath);3937 }3938 3939 RTMemFree(pPluginDirEntry);3940 }3941 else3942 rc = VERR_NO_MEMORY;3943 3944 RTDirClose(pPluginDir);3945 }3946 else3947 {3948 /* On Windows the above immediately signals that there are no3949 * files matching, while on other platforms enumerating the3950 * files below fails. Either way: no plugins. */3951 }3952 3953 if (rc == VERR_NO_MORE_FILES)3954 rc = VINF_SUCCESS;3955 RTStrFree(pszPluginFilter);3956 return rc;3957 #else3958 RT_NOREF1(pszPath);3959 return VERR_NOT_IMPLEMENTED;3960 #endif3961 }3962 3963 3072 /** 3964 3073 * VD async I/O interface open callback. … … 5848 4957 VBOXDDU_DECL(int) VDInit(void) 5849 4958 { 5850 int rc = vdAddBackends(NIL_RTLDRMOD, aStaticBackends, RT_ELEMENTS(aStaticBackends)); 5851 if (RT_SUCCESS(rc)) 5852 { 5853 rc = vdAddCacheBackends(NIL_RTLDRMOD, aStaticCacheBackends, RT_ELEMENTS(aStaticCacheBackends)); 5854 if (RT_SUCCESS(rc)) 5855 { 5856 RTListInit(&g_ListPluginsLoaded); 5857 rc = vdLoadDynamicBackends(); 5858 } 5859 } 5860 LogRel(("VD: VDInit finished\n")); 4959 int rc = vdPluginInit(); 4960 LogRel(("VD: VDInit finished with %Rrc\n", rc)); 5861 4961 return rc; 5862 4962 } … … 5869 4969 VBOXDDU_DECL(int) VDShutdown(void) 5870 4970 { 5871 if (!g_apBackends) 5872 return VERR_INTERNAL_ERROR; 5873 5874 if (g_apCacheBackends) 5875 RTMemFree(g_apCacheBackends); 5876 RTMemFree(g_apBackends); 5877 5878 g_cBackends = 0; 5879 g_apBackends = NULL; 5880 5881 /* Clear the supported cache backends. */ 5882 g_cCacheBackends = 0; 5883 g_apCacheBackends = NULL; 5884 5885 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS 5886 PVDPLUGIN pPlugin, pPluginNext; 5887 RTListForEachSafe(&g_ListPluginsLoaded, pPlugin, pPluginNext, VDPLUGIN, NodePlugin) 5888 { 5889 RTLdrClose(pPlugin->hPlugin); 5890 RTStrFree(pPlugin->pszFilename); 5891 RTListNodeRemove(&pPlugin->NodePlugin); 5892 RTMemFree(pPlugin); 5893 } 5894 #endif 5895 5896 return VINF_SUCCESS; 4971 return vdPluginTerm(); 5897 4972 } 5898 4973 … … 5905 4980 VBOXDDU_DECL(int) VDPluginLoadFromFilename(const char *pszFilename) 5906 4981 { 5907 if (! g_apBackends)4982 if (!vdPluginIsInitialized()) 5908 4983 { 5909 4984 int rc = VDInit(); … … 5923 4998 VBOXDDU_DECL(int) VDPluginLoadFromPath(const char *pszPath) 5924 4999 { 5925 if (! g_apBackends)5000 if (!vdPluginIsInitialized()) 5926 5001 { 5927 5002 int rc = VDInit(); … … 5941 5016 VBOXDDU_DECL(int) VDPluginUnloadFromFilename(const char *pszFilename) 5942 5017 { 5943 if (! g_apBackends)5018 if (!vdPluginIsInitialized()) 5944 5019 { 5945 5020 int rc = VDInit(); … … 5959 5034 VBOXDDU_DECL(int) VDPluginUnloadFromPath(const char *pszPath) 5960 5035 { 5961 if (! g_apBackends)5036 if (!vdPluginIsInitialized()) 5962 5037 { 5963 5038 int rc = VDInit(); … … 5994 5069 ("pcEntriesUsed=%#p\n", pcEntriesUsed), 5995 5070 VERR_INVALID_PARAMETER); 5996 if (! g_apBackends)5071 if (!vdPluginIsInitialized()) 5997 5072 VDInit(); 5998 5073 5999 if (cEntriesAlloc < g_cBackends) 6000 { 6001 *pcEntriesUsed = g_cBackends; 5074 uint32_t cBackends = vdGetImageBackendCount(); 5075 if (cEntriesAlloc < cBackends) 5076 { 5077 *pcEntriesUsed = cBackends; 6002 5078 return VERR_BUFFER_OVERFLOW; 6003 5079 } 6004 5080 6005 for (unsigned i = 0; i < g_cBackends; i++) 6006 { 6007 pEntries[i].pszBackend = g_apBackends[i]->pszBackendName; 6008 pEntries[i].uBackendCaps = g_apBackends[i]->uBackendCaps; 6009 pEntries[i].paFileExtensions = g_apBackends[i]->paFileExtensions; 6010 pEntries[i].paConfigInfo = g_apBackends[i]->paConfigInfo; 6011 pEntries[i].pfnComposeLocation = g_apBackends[i]->pfnComposeLocation; 6012 pEntries[i].pfnComposeName = g_apBackends[i]->pfnComposeName; 6013 } 6014 6015 LogFlowFunc(("returns %Rrc *pcEntriesUsed=%u\n", rc, g_cBackends)); 6016 *pcEntriesUsed = g_cBackends; 5081 for (unsigned i = 0; i < cBackends; i++) 5082 { 5083 PCVDIMAGEBACKEND pBackend; 5084 rc = vdQueryImageBackend(i, &pBackend); 5085 AssertRC(rc); 5086 5087 pEntries[i].pszBackend = pBackend->pszBackendName; 5088 pEntries[i].uBackendCaps = pBackend->uBackendCaps; 5089 pEntries[i].paFileExtensions = pBackend->paFileExtensions; 5090 pEntries[i].paConfigInfo = pBackend->paConfigInfo; 5091 pEntries[i].pfnComposeLocation = pBackend->pfnComposeLocation; 5092 pEntries[i].pfnComposeName = pBackend->pfnComposeName; 5093 } 5094 5095 LogFlowFunc(("returns %Rrc *pcEntriesUsed=%u\n", rc, cBackends)); 5096 *pcEntriesUsed = cBackends; 6017 5097 return rc; 6018 5098 } … … 6035 5115 ("pEntry=%#p\n", pEntry), 6036 5116 VERR_INVALID_PARAMETER); 6037 if (! g_apBackends)5117 if (!vdPluginIsInitialized()) 6038 5118 VDInit(); 6039 5119 6040 /* Go through loaded backends. */ 6041 for (unsigned i = 0; i < g_cBackends; i++) 6042 { 6043 if (!RTStrICmp(pszBackend, g_apBackends[i]->pszBackendName)) 6044 { 6045 pEntry->pszBackend = g_apBackends[i]->pszBackendName; 6046 pEntry->uBackendCaps = g_apBackends[i]->uBackendCaps; 6047 pEntry->paFileExtensions = g_apBackends[i]->paFileExtensions; 6048 pEntry->paConfigInfo = g_apBackends[i]->paConfigInfo; 6049 return VINF_SUCCESS; 6050 } 6051 } 6052 6053 return VERR_NOT_FOUND; 5120 PCVDIMAGEBACKEND pBackend; 5121 int rc = vdFindImageBackend(pszBackend, &pBackend); 5122 if (RT_SUCCESS(rc)) 5123 { 5124 pEntry->pszBackend = pBackend->pszBackendName; 5125 pEntry->uBackendCaps = pBackend->uBackendCaps; 5126 pEntry->paFileExtensions = pBackend->paFileExtensions; 5127 pEntry->paConfigInfo = pBackend->paConfigInfo; 5128 } 5129 5130 return rc; 6054 5131 } 6055 5132 … … 6079 5156 ("pcEntriesUsed=%#p\n", pcEntriesUsed), 6080 5157 VERR_INVALID_PARAMETER); 6081 if (! g_apBackends)5158 if (!vdPluginIsInitialized()) 6082 5159 VDInit(); 6083 5160 6084 if (cEntriesAlloc < g_cFilterBackends) 6085 { 6086 *pcEntriesUsed = g_cFilterBackends; 5161 uint32_t cBackends = vdGetFilterBackendCount(); 5162 if (cEntriesAlloc < cBackends) 5163 { 5164 *pcEntriesUsed = cBackends; 6087 5165 return VERR_BUFFER_OVERFLOW; 6088 5166 } 6089 5167 6090 for (unsigned i = 0; i < g_cFilterBackends; i++) 6091 { 6092 pEntries[i].pszFilter = g_apFilterBackends[i]->pszBackendName; 6093 pEntries[i].paConfigInfo = g_apFilterBackends[i]->paConfigInfo; 6094 } 6095 6096 LogFlowFunc(("returns %Rrc *pcEntriesUsed=%u\n", rc, g_cFilterBackends)); 6097 *pcEntriesUsed = g_cFilterBackends; 5168 for (unsigned i = 0; i < cBackends; i++) 5169 { 5170 PCVDFILTERBACKEND pBackend; 5171 rc = vdQueryFilterBackend(i, &pBackend); 5172 pEntries[i].pszFilter = pBackend->pszBackendName; 5173 pEntries[i].paConfigInfo = pBackend->paConfigInfo; 5174 } 5175 5176 LogFlowFunc(("returns %Rrc *pcEntriesUsed=%u\n", rc, cBackends)); 5177 *pcEntriesUsed = cBackends; 6098 5178 return rc; 6099 5179 } … … 6116 5196 ("pEntry=%#p\n", pEntry), 6117 5197 VERR_INVALID_PARAMETER); 6118 if (! g_apBackends)5198 if (!vdPluginIsInitialized()) 6119 5199 VDInit(); 6120 5200 6121 /* Go through loaded backends. */ 6122 for (unsigned i = 0; i < g_cFilterBackends; i++) 6123 { 6124 if (!RTStrICmp(pszFilter, g_apFilterBackends[i]->pszBackendName)) 6125 { 6126 pEntry->pszFilter = g_apFilterBackends[i]->pszBackendName; 6127 pEntry->paConfigInfo = g_apFilterBackends[i]->paConfigInfo; 6128 return VINF_SUCCESS; 6129 } 6130 } 6131 6132 return VERR_NOT_FOUND; 5201 PCVDFILTERBACKEND pBackend; 5202 int rc = vdFindFilterBackend(pszFilter, &pBackend); 5203 if (RT_SUCCESS(rc)) 5204 { 5205 pEntry->pszFilter = pBackend->pszBackendName; 5206 pEntry->paConfigInfo = pBackend->paConfigInfo; 5207 } 5208 5209 return rc; 6133 5210 } 6134 5211 … … 6282 5359 VERR_INVALID_PARAMETER); 6283 5360 6284 if (! g_apBackends)5361 if (!vdPluginIsInitialized()) 6285 5362 VDInit(); 6286 5363 … … 6316 5393 6317 5394 /* Find the backend supporting this file format. */ 6318 for (unsigned i = 0; i < g_cBackends; i++) 6319 { 6320 if (g_apBackends[i]->pfnProbe) 6321 { 6322 rc = g_apBackends[i]->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage, penmType); 5395 for (unsigned i = 0; i < vdGetImageBackendCount(); i++) 5396 { 5397 PCVDIMAGEBACKEND pBackend; 5398 rc = vdQueryImageBackend(i, &pBackend); 5399 AssertRC(rc); 5400 5401 if (pBackend->pfnProbe) 5402 { 5403 rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage, penmType); 6323 5404 if ( RT_SUCCESS(rc) 6324 5405 /* The correct backend has been found, but there is a small … … 6340 5421 { 6341 5422 /* Copy the name into the new string. */ 6342 char *pszFormat = RTStrDup( g_apBackends[i]->pszBackendName);5423 char *pszFormat = RTStrDup(pBackend->pszBackendName); 6343 5424 if (!pszFormat) 6344 5425 { … … 6362 5443 if (rc == VERR_NOT_SUPPORTED) 6363 5444 { 6364 for (unsigned i = 0; i < g_cCacheBackends; i++) 6365 { 6366 if (g_apCacheBackends[i]->pfnProbe) 5445 for (unsigned i = 0; i < vdGetCacheBackendCount(); i++) 5446 { 5447 PCVDCACHEBACKEND pBackend; 5448 rc = vdQueryCacheBackend(i, &pBackend); 5449 AssertRC(rc); 5450 5451 if (pBackend->pfnProbe) 6367 5452 { 6368 rc = g_apCacheBackends[i]->pfnProbe(pszFilename, pVDIfsDisk, 6369 pVDIfsImage); 5453 rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage); 6370 5454 if ( RT_SUCCESS(rc) 6371 5455 || (rc != VERR_VD_GEN_INVALID_HEADER)) 6372 5456 { 6373 5457 /* Copy the name into the new string. */ 6374 char *pszFormat = RTStrDup( g_apBackends[i]->pszBackendName);5458 char *pszFormat = RTStrDup(pBackend->pszBackendName); 6375 5459 if (!pszFormat) 6376 5460 { … … 6476 5560 pImage->pVDIfsImage = pVDIfsImage; 6477 5561 6478 rc = vdFind Backend(pszBackend, &pImage->Backend);5562 rc = vdFindImageBackend(pszBackend, &pImage->Backend); 6479 5563 if (RT_FAILURE(rc)) 6480 5564 break; … … 7140 6224 AssertRC(rc); 7141 6225 7142 rc = vdFind Backend(pszBackend, &pImage->Backend);6226 rc = vdFindImageBackend(pszBackend, &pImage->Backend); 7143 6227 if (RT_FAILURE(rc)) 7144 6228 break; … … 7405 6489 } 7406 6490 7407 rc = vdFind Backend(pszBackend, &pImage->Backend);6491 rc = vdFindImageBackend(pszBackend, &pImage->Backend); 7408 6492 if (RT_FAILURE(rc)) 7409 6493 break; … … 11347 10431 AssertRC(rc); 11348 10432 11349 rc = vdFind Backend(pszBackend, &pBackend);10433 rc = vdFindImageBackend(pszBackend, &pBackend); 11350 10434 if (RT_SUCCESS(rc)) 11351 10435 { -
trunk/src/VBox/Storage/VDBackends.h
r66140 r66378 24 24 #include <VBox/vd-plugin.h> 25 25 26 #include <iprt/cdefs.h> 27 26 28 RT_C_DECLS_BEGIN 27 29 -
trunk/src/VBox/Storage/testcase/Makefile.kmk
r66140 r66378 121 121 vbox-img.cpp \ 122 122 ../VD.cpp \ 123 ../VDPlugin.cpp \ 123 124 ../VDVfs.cpp \ 124 125 ../VDI.cpp \
Note:
See TracChangeset
for help on using the changeset viewer.