VirtualBox

Changeset 66378 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Mar 31, 2017 11:20:50 AM (8 years ago)
Author:
vboxsync
Message:

Storage/VD: Some cleanup (part 1), move the code related to plugin and backend management into a separate file to make navigation in VD.cpp easier

Location:
trunk/src/VBox/Storage
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/Makefile.kmk

    r66140 r66378  
    3838 StorageLib_SOURCES  = \
    3939        VD.cpp \
     40        VDPlugin.cpp \
    4041        VDVfs.cpp \
    4142        VDIfVfs.cpp \
  • trunk/src/VBox/Storage/VD.cpp

    r66250 r66378  
    11/* $Id$ */
    22/** @file
    3  * VBoxHDD - VBox HDD Container implementation.
     3 * VD - Virtual disk container implementation.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2016 Oracle Corporation
     7 * Copyright (C) 2006-2017 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3232#include <iprt/string.h>
    3333#include <iprt/asm.h>
    34 #include <iprt/ldr.h>
    35 #include <iprt/dir.h>
     34#include <iprt/param.h>
    3635#include <iprt/path.h>
    37 #include <iprt/param.h>
    38 #include <iprt/memcache.h>
    3936#include <iprt/sg.h>
    40 #include <iprt/list.h>
    41 #include <iprt/avl.h>
    4237#include <iprt/semaphore.h>
    4338
    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"
    5840
    5941/** Buffer size used for merging images. */
     
    8062
    8163/**
    82  * Structure containing everything I/O related
    83  * for the image and cache descriptors.
    84  */
    85 typedef struct VDIO
    86 {
    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 VDIMAGE
    111 {
    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 which
    123      * 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 /**
    13564 * uModified bit flags.
    13665 */
     
    13968#define VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE   RT_BIT(2)
    14069
    141 
    142 /**
    143  * VBox HDD Cache image descriptor.
    144  */
    145 typedef struct VDCACHE
    146 {
    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 which
    154      * 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 VDDISCARDBLOCK
    170 {
    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 VDDISCARDSTATE
    185 {
    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 used
    193      * 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 VDFILTER
    202 {
    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 VDISK
    225 {
    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-NULL
    243      * 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 structures
    268      * 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 generic
    275      * disk framework by the backend. - LIFO order. */
    276     volatile PVDIOCTX      pIoCtxHaltedHead;
    277 
    278     /** Head of blocked I/O contexts, processed only
    279      * 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 until
    283      * 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 this
    286      * 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 contains
    289      * 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 };
    30270
    30371# define VD_IS_LOCKED(a_pDisk) \
     
    350118    struct VDIOCTX * volatile    pIoCtxNext;
    351119    /** Disk this is request is for. */
    352     PVDISK                     pDisk;
     120    PVDISK                       pDisk;
    353121    /** Return code. */
    354122    int                          rcReq;
     
    606374#define VDMETAXFER_TXDIR_SET(flags, dir) ((flags) = (flags & ~VDMETAXFER_TXDIR_MASK) | (dir))
    607375
    608 /**
    609  * Plugin structure.
    610  */
    611 typedef struct VDPLUGIN
    612 {
    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_ISCSIBackend
    646 };
    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_VciCacheBackend
    658 };
    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_BACKENDS
    665 /** Array of handles to the corresponding plugin. */
    666 static PRTLDRMOD g_pahFilterBackendPlugins = NULL;
    667 #endif
    668 
    669376/** Forward declaration of the async discard helper. */
    670377static DECLCALLBACK(int) vdDiscardHelperAsync(PVDIOCTX pIoCtx);
     
    675382
    676383/**
    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_BACKENDS
    700 /**
    701  * internal: add single backend.
    702  */
    703 DECLINLINE(int) vdAddBackend(RTLDRMOD hPlugin, PCVDIMAGEBACKEND pBackend)
    704 {
    705     return vdAddBackends(hPlugin, &pBackend, 1);
    706 }
    707 #endif
    708 
    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_BACKENDS
    733 
    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 /**
    788384 * internal: issue error message.
    789385 */
     
    842438    return rc;
    843439}
    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 
    911440
    912441/**
     
    35413070}
    35423071
    3543 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS
    3544 
    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     else
    3555     {
    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     else
    3573     {
    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     else
    3591     {
    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         else
    3636         {
    3637             RTMemFree(pPlugin);
    3638             rc = VERR_NO_MEMORY;
    3639         }
    3640     }
    3641     else
    3642         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 the
    3655      * backends. Only if this doesn't exist (or fails to work) we should fall
    3656      * 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_BACKENDS
    3708     /* 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         else
    3739             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         else
    3745             RTLdrClose(hPlugin);
    3746     }
    3747 
    3748     return rc;
    3749 #else
    3750     RT_NOREF1(pszFilename);
    3751     return VERR_NOT_IMPLEMENTED;
    3752 #endif
    3753 }
    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_BACKENDS
    3764     /* 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         else
    3820             rc = VERR_NO_MEMORY;
    3821 
    3822         RTDirClose(pPluginDir);
    3823     }
    3824     else
    3825     {
    3826         /* On Windows the above immediately signals that there are no
    3827          * files matching, while on other platforms enumerating the
    3828          * 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 #else
    3836     RT_NOREF1(pszPath);
    3837     return VERR_NOT_IMPLEMENTED;
    3838 #endif
    3839 }
    3840 
    3841 /**
    3842  * internal: scans plugin directory and loads found plugins.
    3843  */
    3844 static int vdLoadDynamicBackends(void)
    3845 {
    3846 #ifndef VBOX_HDD_NO_DYNAMIC_BACKENDS
    3847     /*
    3848      * Enumerate plugin backends from the application directory where the other
    3849      * 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 #else
    3858     return VINF_SUCCESS;
    3859 #endif
    3860 }
    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_BACKENDS
    3871     return vdRemovePlugin(pszFilename);
    3872 #else
    3873     RT_NOREF1(pszFilename);
    3874     return VERR_NOT_IMPLEMENTED;
    3875 #endif
    3876 }
    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_BACKENDS
    3887     /* 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         else
    3942             rc = VERR_NO_MEMORY;
    3943 
    3944         RTDirClose(pPluginDir);
    3945     }
    3946     else
    3947     {
    3948         /* On Windows the above immediately signals that there are no
    3949          * files matching, while on other platforms enumerating the
    3950          * 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 #else
    3958     RT_NOREF1(pszPath);
    3959     return VERR_NOT_IMPLEMENTED;
    3960 #endif
    3961 }
    3962 
    39633072/**
    39643073 * VD async I/O interface open callback.
     
    58484957VBOXDDU_DECL(int) VDInit(void)
    58494958{
    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));
    58614961    return rc;
    58624962}
     
    58694969VBOXDDU_DECL(int) VDShutdown(void)
    58704970{
    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();
    58974972}
    58984973
     
    59054980VBOXDDU_DECL(int) VDPluginLoadFromFilename(const char *pszFilename)
    59064981{
    5907     if (!g_apBackends)
     4982    if (!vdPluginIsInitialized())
    59084983    {
    59094984        int rc = VDInit();
     
    59234998VBOXDDU_DECL(int) VDPluginLoadFromPath(const char *pszPath)
    59244999{
    5925     if (!g_apBackends)
     5000    if (!vdPluginIsInitialized())
    59265001    {
    59275002        int rc = VDInit();
     
    59415016VBOXDDU_DECL(int) VDPluginUnloadFromFilename(const char *pszFilename)
    59425017{
    5943     if (!g_apBackends)
     5018    if (!vdPluginIsInitialized())
    59445019    {
    59455020        int rc = VDInit();
     
    59595034VBOXDDU_DECL(int) VDPluginUnloadFromPath(const char *pszPath)
    59605035{
    5961     if (!g_apBackends)
     5036    if (!vdPluginIsInitialized())
    59625037    {
    59635038        int rc = VDInit();
     
    59945069                    ("pcEntriesUsed=%#p\n", pcEntriesUsed),
    59955070                    VERR_INVALID_PARAMETER);
    5996     if (!g_apBackends)
     5071    if (!vdPluginIsInitialized())
    59975072        VDInit();
    59985073
    5999     if (cEntriesAlloc < g_cBackends)
    6000     {
    6001         *pcEntriesUsed = g_cBackends;
     5074    uint32_t cBackends = vdGetImageBackendCount();
     5075    if (cEntriesAlloc < cBackends)
     5076    {
     5077        *pcEntriesUsed = cBackends;
    60025078        return VERR_BUFFER_OVERFLOW;
    60035079    }
    60045080
    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;
    60175097    return rc;
    60185098}
     
    60355115                    ("pEntry=%#p\n", pEntry),
    60365116                    VERR_INVALID_PARAMETER);
    6037     if (!g_apBackends)
     5117    if (!vdPluginIsInitialized())
    60385118        VDInit();
    60395119
    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;
    60545131}
    60555132
     
    60795156                    ("pcEntriesUsed=%#p\n", pcEntriesUsed),
    60805157                    VERR_INVALID_PARAMETER);
    6081     if (!g_apBackends)
     5158    if (!vdPluginIsInitialized())
    60825159        VDInit();
    60835160
    6084     if (cEntriesAlloc < g_cFilterBackends)
    6085     {
    6086         *pcEntriesUsed = g_cFilterBackends;
     5161    uint32_t cBackends = vdGetFilterBackendCount();
     5162    if (cEntriesAlloc < cBackends)
     5163    {
     5164        *pcEntriesUsed = cBackends;
    60875165        return VERR_BUFFER_OVERFLOW;
    60885166    }
    60895167
    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;
    60985178    return rc;
    60995179}
     
    61165196                    ("pEntry=%#p\n", pEntry),
    61175197                    VERR_INVALID_PARAMETER);
    6118     if (!g_apBackends)
     5198    if (!vdPluginIsInitialized())
    61195199        VDInit();
    61205200
    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;
    61335210}
    61345211
     
    62825359                    VERR_INVALID_PARAMETER);
    62835360
    6284     if (!g_apBackends)
     5361    if (!vdPluginIsInitialized())
    62855362        VDInit();
    62865363
     
    63165393
    63175394    /* 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);
    63235404            if (    RT_SUCCESS(rc)
    63245405                /* The correct backend has been found, but there is a small
     
    63405421            {
    63415422                /* Copy the name into the new string. */
    6342                 char *pszFormat = RTStrDup(g_apBackends[i]->pszBackendName);
     5423                char *pszFormat = RTStrDup(pBackend->pszBackendName);
    63435424                if (!pszFormat)
    63445425                {
     
    63625443    if (rc == VERR_NOT_SUPPORTED)
    63635444    {
    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)
    63675452            {
    6368                 rc = g_apCacheBackends[i]->pfnProbe(pszFilename, pVDIfsDisk,
    6369                                                     pVDIfsImage);
     5453                rc = pBackend->pfnProbe(pszFilename, pVDIfsDisk, pVDIfsImage);
    63705454                if (    RT_SUCCESS(rc)
    63715455                    ||  (rc != VERR_VD_GEN_INVALID_HEADER))
    63725456                {
    63735457                    /* Copy the name into the new string. */
    6374                     char *pszFormat = RTStrDup(g_apBackends[i]->pszBackendName);
     5458                    char *pszFormat = RTStrDup(pBackend->pszBackendName);
    63755459                    if (!pszFormat)
    63765460                    {
     
    64765560        pImage->pVDIfsImage = pVDIfsImage;
    64775561
    6478         rc = vdFindBackend(pszBackend, &pImage->Backend);
     5562        rc = vdFindImageBackend(pszBackend, &pImage->Backend);
    64795563        if (RT_FAILURE(rc))
    64805564            break;
     
    71406224        AssertRC(rc);
    71416225
    7142         rc = vdFindBackend(pszBackend, &pImage->Backend);
     6226        rc = vdFindImageBackend(pszBackend, &pImage->Backend);
    71436227        if (RT_FAILURE(rc))
    71446228            break;
     
    74056489        }
    74066490
    7407         rc = vdFindBackend(pszBackend, &pImage->Backend);
     6491        rc = vdFindImageBackend(pszBackend, &pImage->Backend);
    74086492        if (RT_FAILURE(rc))
    74096493            break;
     
    1134710431    AssertRC(rc);
    1134810432
    11349     rc = vdFindBackend(pszBackend, &pBackend);
     10433    rc = vdFindImageBackend(pszBackend, &pBackend);
    1135010434    if (RT_SUCCESS(rc))
    1135110435    {
  • trunk/src/VBox/Storage/VDBackends.h

    r66140 r66378  
    2424#include <VBox/vd-plugin.h>
    2525
     26#include <iprt/cdefs.h>
     27
    2628RT_C_DECLS_BEGIN
    2729
  • trunk/src/VBox/Storage/testcase/Makefile.kmk

    r66140 r66378  
    121121        vbox-img.cpp \
    122122        ../VD.cpp \
     123        ../VDPlugin.cpp \
    123124        ../VDVfs.cpp \
    124125        ../VDI.cpp \
Note: See TracChangeset for help on using the changeset viewer.

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