StorageControllerImpl.cpp revision 8b5c19912f3e141c16afb49b7aeb9df38a309588
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Implementation of IStorageController.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Copyright (C) 2008-2015 Oracle Corporation
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * available from http://www.virtualbox.org. This file is free software;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/////////////////////////////////////////////////////////////////////////////
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Constructor. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync mStorageControllerType(StorageControllerType_PIIX4),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Unique name of the storage controller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The connection type of the storage controller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Type of the Storage controller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Instance number of the storage controller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Number of usable ports. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Whether to use the host IO caches. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Whether it is possible to boot from disks attached to this controller. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** The following is only for the SATA controller atm. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Port which acts as primary master for ide emulation. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Port which acts as primary slave for ide emulation. */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /** Port which acts as secondary master for ide emulation. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** Port which acts as secondary slave for ide emulation. */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync unconst(pVirtualBox) = aMachine->i_getVirtualBox();
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync unconst(pSystemProperties) = pVirtualBox->i_getSystemProperties();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// constructor / destructor
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync/////////////////////////////////////////////////////////////////////////////
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync// public initializer/uninitializer for internal purposes only
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync/////////////////////////////////////////////////////////////////////////////
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * Initializes the storage controller object.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * @returns COM result indicator.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param aParent Pointer to our parent object.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param aName Name of the storage controller.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param aInstance Instance number of the storage controller.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("aParent=%p aName=\"%s\" aInstance=%u\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT rc = aParent->COMGETTER(ChipsetType)(&chipsetType);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = aParent->i_getVirtualBox()->i_getSystemProperties()->
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync GetMaxInstancesOfStorageBus(chipsetType, aStorageBus, &maxInstances);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Enclose the state transition NotReady->InInit->Ready */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* m->pPeer is left null */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync m->bd->mStorageControllerType = StorageControllerType_PIIX4;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m->bd->mStorageControllerType = StorageControllerType_IntelAhci;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m->bd->mStorageControllerType = StorageControllerType_LsiLogic;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m->bd->mStorageControllerType = StorageControllerType_I82078;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m->bd->mStorageControllerType = StorageControllerType_LsiLogicSas;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync m->bd->mStorageControllerType = StorageControllerType_USB;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Confirm a successful initialization */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initializes the object given another object
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync * (a kind of copy constructor). This object shares data with
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the object passed as an argument.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param aReshare
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * When false, the original object will remain a data owner.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Otherwise, data ownership will be transferred from the original
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * object to this one.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @note This object must be destroyed before the original object
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * it shares data with is destroyed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * reading if @a aReshare is false.
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Enclose the state transition NotReady->InInit->Ready */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync /* sanity */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
d8df004f4caf4f71e78f0be1cc2e2a918358ae9fvboxsync /* Confirm successful initialization */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initializes the storage controller object given another guest object
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (a kind of copy constructor). This object makes a private copy of data
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync * of the original object passed as an argument.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::initCopy(Machine *aParent, StorageController *aThat)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Enclose the state transition NotReady->InInit->Ready */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* m->pPeer is left null */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Confirm a successful initialization */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Uninitializes the instance and sets the ready flag to FALSE.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Called either from FinalRelease() or by the parent when it gets destroyed.
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsync /* Enclose the state transition Ready->InUninit->NotReady */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// IStorageController properties
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getName(com::Utf8Str &aName)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* mName is constant during life time, no need to lock */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getBus(StorageBus_T *aBus)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getControllerType(StorageControllerType_T *aControllerType)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::setControllerType(StorageControllerType_T aControllerType)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( (aControllerType != StorageControllerType_PIIX3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (aControllerType != StorageControllerType_PIIX4)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (aControllerType != StorageControllerType_ICH6))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (aControllerType != StorageControllerType_IntelAhci)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ( (aControllerType != StorageControllerType_LsiLogic)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (aControllerType != StorageControllerType_BusLogic))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (aControllerType != StorageControllerType_I82078)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (aControllerType != StorageControllerType_LsiLogicSas)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getMaxDevicesPerPortCount(ULONG *aMaxDevicesPerPortCount)
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync CheckComArgOutPointerValid(aMaxDevicesPerPortCount);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT rc = m->pSystemProperties->GetMaxDevicesPerPortForStorageBus(m->bd->mStorageBus, aMaxDevicesPerPortCount);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getMinPortCount(ULONG *aMinPortCount)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT rc = m->pSystemProperties->GetMinPortCountForStorageBus(m->bd->mStorageBus, aMinPortCount);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getMaxPortCount(ULONG *aMaxPortCount)
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync HRESULT rc = m->pSystemProperties->GetMaxPortCountForStorageBus(m->bd->mStorageBus, aMaxPortCount);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getPortCount(ULONG *aPortCount)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::setPortCount(ULONG aPortCount)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* AHCI SATA supports a maximum of 30 ports. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * SCSI does not support setting different ports.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (doesn't make sense here either).
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync * The maximum and minimum is 16 and unless the callee
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * tries to set a different value we return an error.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The port count is fixed to 2.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The port count is fixed to 1.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* SAS supports a maximum of 255 ports. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The port count is fixed to 8.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the machine needs to be mutable */
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsync AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS); // m->pParent is const, needs no locking
a44cdd0b29504e3de7b8aa87f839ad62b6e66f51vboxsync m->pParent->i_setModified(Machine::IsModified_Storage);
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsyncHRESULT StorageController::getInstance(ULONG *aInstance)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The machine doesn't need to be mutable. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::setInstance(ULONG aInstance)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The machine doesn't need to be mutable. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getUseHostIOCache(BOOL *fUseHostIOCache)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The machine doesn't need to be mutable. */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsyncHRESULT StorageController::setUseHostIOCache(BOOL fUseHostIOCache)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the machine needs to be mutable */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS); // m->pParent is const, needs no locking
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync m->pParent->i_setModified(Machine::IsModified_Storage);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::getBootable(BOOL *fBootable)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The machine doesn't need to be mutable. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// public methods only for internal purposes
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/////////////////////////////////////////////////////////////////////////////
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::i_getIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (m->bd->mStorageControllerType != StorageControllerType_IntelAhci)
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsyncHRESULT StorageController::i_setIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* the machine needs to be mutable */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (m->bd->mStorageControllerType != StorageControllerType_IntelAhci)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("Invalid port number: %ld (must be in range [%lu, %lu])"),
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsyncStorageControllerType_T StorageController::i_getControllerType() const
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsyncStorageBus_T StorageController::i_getStorageBus() const
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Returns S_OK if the given port and device numbers are within the range supported
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * by this controller. If not, it sets an error and returns E_INVALIDARG.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ulPort
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param ulDevice
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncHRESULT StorageController::i_checkPortAndDeviceValid(LONG aControllerPort,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HRESULT rc = m->pSystemProperties->GetMaxDevicesPerPortForStorageBus(m->bd->mStorageBus, &devicesPerPort);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync tr("The port and/or device parameter are out of range: port=%d (must be in range [0, %d]), device=%d (must be in range [0, %d])"),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync (int)aControllerPort, (int)portCount-1, (int)aDevice, (int)devicesPerPort-1);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @note Locks objects for writing! */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsyncvoid StorageController::i_setBootable(BOOL fBootable)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @note Locks objects for writing! */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync * @note Locks this object for writing, together with the peer object (also
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * for writing) if there is one.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* sanity */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* sanity too */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* lock both for writing since we modify both (m->pPeer is "master" so locked
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * first) */
8dee1778d3770cdc584752c84acf4899d8bfc9f9vboxsync AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync // attach new data to the peer and reshare it
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Cancels sharing (if any) by making an independent copy of data.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This operation also resets this object's peer to NULL.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @note Locks this object for writing, together with the peer object
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * represented by @a aThat (locked for reading).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* sanity */
dd8efff5286a99cf8d9b3a5e8dd62340973f3cc1vboxsync /* sanity too */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * first) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncComObjPtr<StorageController> StorageController::i_getPeer()
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync// private methods
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/////////////////////////////////////////////////////////////////////////////
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* vi: set tabstop=4 shiftwidth=4 expandtab: */