VirtualBox

Changeset 351 in vbox for trunk


Ignore:
Timestamp:
Jan 26, 2007 10:49:57 AM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
17908
Message:

Main: Fixed: HVirtualDiskImage::geAccessible() blocked all other methods, including simple getters [defect #1789].

Location:
trunk/src/VBox/Main
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/HardDiskImpl.cpp

    r132 r351  
    6767    ComObjPtr <Progress> progress;
    6868
    69     // for CreateDynamic, CreateStatic
     69    /* for CreateDynamic, CreateStatic */
    7070    uint64_t size;
    7171
    72     // for CloneToImage
     72    /* for CloneToImage */
    7373    ComObjPtr <HardDisk> source;
    7474};
     
    8484    Progress *progress = static_cast <Progress *> (pvUser);
    8585
    86     // update the progress object
     86    /* update the progress object */
    8787    if (progress)
    8888        progress->notifyProgress (uPercent);
     
    172172    Assert (isReady());
    173173
    174     // uninit all children
     174    /* uninit all children */
    175175    uninitDependentChildren();
    176176
     
    332332        HRESULT rc = S_OK;
    333333
    334         // check the accessibility state of all ancestors
     334        /* check the accessibility state of all ancestors */
    335335        ComObjPtr <HardDisk> parent = (HardDisk *) mParent;
    336336        while (parent)
     
    413413    HRESULT rc = S_OK;
    414414
    415     // create a project object
     415    /* create a project object */
    416416    ComObjPtr <Progress> progress;
    417417    progress.createObject();
     
    421421    CheckComRCReturnRC (rc);
    422422
    423     // create an imageless resulting object
     423    /* create an imageless resulting object */
    424424    ComObjPtr <HVirtualDiskImage> image;
    425425    image.createObject();
     
    427427    CheckComRCReturnRC (rc);
    428428
    429     // append the default path if only a name is given
     429    /* append the default path if only a name is given */
    430430    Bstr path = aFilePath;
    431431    {
     
    441441    }
    442442
    443     // set the desired path
     443    /* set the desired path */
    444444    rc = image->setFilePath (path);
    445445    CheckComRCReturnRC (rc);
    446446
    447     // ensure the directory exists
     447    /* ensure the directory exists */
    448448    {
    449449        Utf8Str imageDir = image->filePath();
     
    462462    }
    463463
    464     // mark as busy (being created)
    465     // (VDI task thread will unmark it)
     464    /* mark as busy (being created)
     465     * (VDI task thread will unmark it) */
    466466    image->setBusy();
    467467
    468     // fill in a VDI task data
     468    /* fill in a VDI task data */
    469469    VDITask *task = new VDITask (VDITask::CloneToImage, image, progress);
    470470    task->source = this;
    471471
    472     // increase readers until finished
    473     // (VDI task thread will decrease them)
     472    /* increase readers until finished
     473     * (VDI task thread will decrease them) */
    474474    addReader();
    475475
    476     // create the hard disk creation thread, pass operation data
     476    /* create the hard disk creation thread, pass operation data */
    477477    int vrc = RTThreadCreate (NULL, HVirtualDiskImage::vdiTaskThread,
    478478                              (void *) task, 0, RTTHREADTYPE_MAIN_HEAVY_WORKER,
     
    487487    }
    488488
    489     // return interfaces to the caller
     489    /* return interfaces to the caller */
    490490    image.queryInterfaceTo (aImage);
    491491    progress.queryInterfaceTo (aProgress);
     
    706706    AssertReturn (!mMachineId.isEmpty(), false);
    707707
    708     // check all children
     708    /* check all children */
    709709    AutoLock chLock (childrenLock());
    710710    for (HardDiskList::const_iterator it = children().begin();
     
    746746        if (child->mReaders > 0 || child->mBusy)
    747747        {
    748             // reset the busy flag of all previous children
     748            /* reset the busy flag of all previous children */
    749749            while (it != children().begin())
    750750                (*(-- it))->clearBusy();
     
    906906                                     aFolder.raw(), RTPATH_DELIMITER, id.ptr());
    907907
    908     // try to make the path relative to the vbox home dir
     908    /* try to make the path relative to the vbox home dir */
    909909    const char *filePathToRel = filePathTo;
    910910    {
     
    914914    }
    915915
    916     // first ensure the directory exists
     916    /* first ensure the directory exists */
    917917    {
    918918        Utf8Str dir = aFolder;
     
    932932    alock.leave();
    933933
    934     // call storage type specific diff creation method
     934    /* call storage type specific diff creation method */
    935935    HRESULT rc = createDiffImage (id, filePathTo, aProgress);
    936936
     
    945945    CheckComRCReturnRC (rc);
    946946
    947     // associate the created hard disk with the given machine
     947    /* associate the created hard disk with the given machine */
    948948    vdi->setMachineId (aMachineId);
    949949
     
    10111011    AssertReturn (aHDNode, E_FAIL);
    10121012
    1013     Guid uuid; // uuid (required)
     1013    Guid uuid; /* uuid (required) */
    10141014    CFGLDRQueryUUID (aHDNode, "uuid", uuid.ptr());
    10151015    mId = uuid;
     
    10171017    if (!isDifferencing())
    10181018    {
    1019         Bstr type; // type (required for <HardDisk> nodes only)
     1019        Bstr type; /* type (required for <HardDisk> nodes only) */
    10201020        CFGLDRQueryBSTR (aHDNode, "type", type.asOutParam());
    10211021        if (type == L"normal")
     
    10361036        return rc;
    10371037
    1038     // load all children
     1038    /* load all children */
    10391039    unsigned count = 0;
    10401040    CFGLDRCountChildren (aHDNode, "DiffHardDisk", &count);
     
    10831083    AssertReturn (aHDNode, E_FAIL);
    10841084
    1085     // uuid (required)
     1085    /* uuid (required) */
    10861086    CFGLDRSetUUID (aHDNode, "uuid", mId.ptr());
    10871087
    10881088    if (!isDifferencing())
    10891089    {
    1090         // type (required)
     1090        /* type (required) */
    10911091        const char *type = NULL;
    10921092        switch (mType)
     
    11071107    HRESULT rc = S_OK;
    11081108
    1109     // save all children
     1109    /* save all children */
    11101110    AutoLock chLock (childrenLock());
    11111111    for (HardDiskList::const_iterator it = children().begin();
     
    11521152
    11531153    mState = NotCreated;
     1154
     1155    mStateCheckSem = NIL_RTSEMEVENTMULTI;
     1156    mStateCheckWaiters = 0;
    11541157
    11551158    mSize = 0;
     
    13471350    CHECK_READY();
    13481351
    1349     // only a non-differencing image knows the logical size
     1352    /* only a non-differencing image knows the logical size */
    13501353    if (isDifferencing())
    13511354        return root()->COMGETTER(Size) (aSize);
     
    15211524    CHECK_READY();
    15221525
    1523     // check the basic accessibility
     1526    if (mStateCheckSem != NIL_RTSEMEVENTMULTI)
     1527    {
     1528        /* An accessibility check in progress on some other thread,
     1529         * wait for it to finish. */
     1530
     1531        ComAssertRet (mStateCheckWaiters != ~0, E_FAIL);
     1532        ++ mStateCheckWaiters;
     1533        alock.leave();
     1534       
     1535        int vrc = RTSemEventMultiWait (mStateCheckSem, RT_INDEFINITE_WAIT);
     1536
     1537        alock.enter();
     1538        AssertReturn (mStateCheckWaiters != 0, E_FAIL);
     1539        -- mStateCheckWaiters;
     1540        if (mStateCheckWaiters == 0)
     1541        {
     1542            RTSemEventMultiDestroy (mStateCheckSem);
     1543            mStateCheckSem = NIL_RTSEMEVENTMULTI;
     1544        }
     1545       
     1546        /* don't touch aAccessError, it has been already set */
     1547        return S_OK;
     1548    }
     1549
     1550    /* check the basic accessibility */
    15241551    HRESULT rc = HardDisk::getAccessible (aAccessError);
    15251552    if (FAILED (rc) || !aAccessError.isNull())
     
    15291556    {
    15301557        return queryInformation (&aAccessError);
    1531         // if we fail here, this means something like UUID mismatch.
    1532         // Do nothing, just return the failure (error info is already
    1533         // set by queryInformation()), in hope that one of subsequent
    1534         // attempts to check for acessibility will succeed
     1558        /* if we fail here, this means something like UUID mismatch.
     1559         * Do nothing, just return the failure (error info is already
     1560         * set by queryInformation()), in hope that one of subsequent
     1561         * attempts to check for acessibility will succeed */
    15351562    }
    15361563
     
    17031730    releaseReader();
    17041731
    1705     // update the UUID to correspond to the file name
     1732    /* update the UUID to correspond to the file name */
    17061733    if (VBOX_SUCCESS (vrc))
    17071734        vrc = VDISetImageUUIDs (aTargetPath, aId, NULL, NULL, NULL);
     
    17571784                                     aFolder.raw(), RTPATH_DELIMITER, id.ptr());
    17581785
    1759     // try to make the path relative to the vbox home dir
     1786    /* try to make the path relative to the vbox home dir */
    17601787    const char *filePathToRel = filePathTo;
    17611788    {
     
    17651792    }
    17661793
    1767     // first ensure the directory exists
     1794    /* first ensure the directory exists */
    17681795    {
    17691796        Utf8Str dir = aFolder;
     
    17911818    alock.enter();
    17921819
    1793     // get modification and parent UUIDs of this image
     1820    /* get modification and parent UUIDs of this image */
    17941821    RTUUID modUuid, parentUuid, parentModUuid;
    17951822    if (VBOX_SUCCESS (vrc))
     
    18151842        return rc;
    18161843
    1817     // associate the created hard disk with the given machine
     1844    /* associate the created hard disk with the given machine */
    18181845    vdi->setMachineId (aMachineId);
    18191846
     
    19001927            AutoLock childLock (child);
    19011928
    1902             // reparent the child
     1929            /* reparent the child */
    19031930            child->mParent = mParent;
    19041931            if (mParent)
    19051932                mParent->addDependentChild (child);
    19061933
    1907             // change the parent UUID in the image as well
     1934            /* change the parent UUID in the image as well */
    19081935            RTUUID parentUuid, parentModUuid;
    19091936            vrc = VDIGetImageUUIDs (Utf8Str (mParent->asVDI()->mFilePathFull),
     
    19331960    }
    19341961
    1935     // detach all our children to avoid their uninit in #uninit()
     1962    /* detach all our children to avoid their uninit in #uninit() */
    19361963    removeDependentChildren();
    19371964
     
    19772004    CHECK_READY();
    19782005
    1979     // this must be a diff image
     2006    /* this must be a diff image */
    19802007    AssertReturn (isDifferencing(), E_FAIL);
    19812008
     
    19912018        AutoLock chLock (childrenLock());
    19922019
    1993         // iterate over a copy since we will modify the list
     2020        /* iterate over a copy since we will modify the list */
    19942021        HardDiskList list = children();
    19952022
     
    20232050            }
    20242051
    2025             // reparent the child
     2052            /* reparent the child */
    20262053            child->mParent = mParent;
    20272054            if (mParent)
    20282055                mParent->addDependentChild (child);
    20292056
    2030             // change the parent UUID in the image as well
     2057            /* change the parent UUID in the image as well */
    20312058            RTUUID parentUuid, parentModUuid;
    20322059            vrc = VDIGetImageUUIDs (Utf8Str (mParent->asVDI()->mFilePathFull),
     
    20512078            }
    20522079
    2053             // detach child to avoid its uninit in #uninit()
     2080            /* detach child to avoid its uninit in #uninit() */
    20542081            removeDependentChild (child);
    20552082
    2056             // remove the busy flag
     2083            /* remove the busy flag */
    20572084            child->clearBusy();
    20582085        }
     
    20942121                                    Utf8Str (mParent->asVDI()->mFilePathFull),
    20952122                                    NULL, NULL, NULL);
    2096     // update the UUID to correspond to the file name
     2123    /* update the UUID to correspond to the file name */
    20972124    if (VBOX_SUCCESS (vrc))
    20982125        vrc = VDISetImageUUIDs (filePathFull, mId, NULL, NULL, NULL);
     
    21202147    if (aFilePath && *aFilePath)
    21212148    {
    2122         // get the full file name
     2149        /* get the full file name */
    21232150        char filePathFull [RTPATH_MAX];
    21242151        int vrc = RTPathAbsEx (mVirtualBox->homeDir(), Utf8Str (aFilePath),
     
    21412168
    21422169/**
    2143  *  Helper to query information about the VDI hard disk
     2170 *  Helper to query information about the VDI hard disk.
    21442171 *
    21452172 *  @param aAccessError not used when NULL, otherwise see #getAccessible()
    2146  *  @note
    2147  *      Must be called from under the object's lock!
     2173 *
     2174 *  @note Must be called from under the object's lock, only after
     2175 *        CHECK_BUSY_AND_READERS() succeeds.
    21482176 */
    21492177HRESULT HVirtualDiskImage::queryInformation (Bstr *aAccessError)
    21502178{
     2179    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
     2180
     2181    /* create a lock object to completely release it later */
     2182    AutoLock alock (this);
     2183
     2184    AssertReturn (mStateCheckWaiters == 0, E_FAIL);
     2185
    21512186    ComAssertRet (mState >= Created, E_FAIL);
    21522187
     
    21542189    int vrc = VINF_SUCCESS;
    21552190
    2156     /* stupid-stupid-stupid code. VBoxVHDD management is sick.
    2157      * we're opening a file three times to get three bits of information */
     2191    /* lazily create a semaphore */
     2192    vrc = RTSemEventMultiCreate (&mStateCheckSem);
     2193    ComAssertRCRet (vrc, E_FAIL);
     2194
     2195    /* go to Busy state to prevent any concurrent modifications
     2196     * after releasing the lock below (to unblock getters before
     2197     * a lengthy operation) */
     2198    setBusy();
     2199
     2200    alock.leave();
     2201   
     2202    /* VBoxVHDD management interface needs to be optimized: we're opening a
     2203     * file three times in a raw to get three bits of information. */
    21582204
    21592205    Utf8Str filePath = mFilePathFull;
     
    21652211        vrc = VDICheckImage (filePath, NULL, NULL, NULL,
    21662212                             id.ptr(), parentId.ptr(), NULL, 0);
     2213
    21672214        if (VBOX_FAILURE (vrc))
    21682215        {
     
    22522299                break;
    22532300        }
    2254 
    2255         if (aAccessError)
    2256             aAccessError->setNull();
    2257 
    2258         mState = Accessible;
    22592301    }
    22602302    while (0);
    22612303
     2304    /* enter the lock again */
     2305    alock.enter();
     2306   
     2307    /* remove the busy flag */
     2308    clearBusy();
     2309   
    22622310    if (VBOX_FAILURE (vrc) || FAILED (rc))
    22632311    {
     
    22742322        mState = Created;
    22752323    }
     2324    else
     2325    {
     2326        if (aAccessError)
     2327            aAccessError->setNull();
     2328
     2329        mState = Accessible;
     2330    }
     2331   
     2332    /* inform waiters if there are any */
     2333    if (mStateCheckWaiters > 0)
     2334    {
     2335        RTSemEventMultiSignal (mStateCheckSem);
     2336    }
     2337    else
     2338    {
     2339        /* delete the semaphore ourselves */
     2340        RTSemEventMultiDestroy (mStateCheckSem);
     2341        mStateCheckSem = NIL_RTSEMEVENTMULTI;
     2342    }
    22762343
    22772344    return rc;
     
    23022369            mFilePathFull.raw());
    23032370
    2304     // first ensure the directory exists
     2371    /* first ensure the directory exists */
    23052372    {
    23062373        Utf8Str imageDir = mFilePathFull;
     
    23192386    }
    23202387
    2321     // check whether the given file exists or not
     2388    /* check whether the given file exists or not */
    23222389    RTFILE file;
    23232390    int vrc = RTFileOpen (&file, Utf8Str (mFilePathFull),
     
    23412408    }
    23422409
    2343     // check VDI size limits
     2410    /* check VDI size limits */
    23442411    {
    23452412        HRESULT rc;
     
    23592426    HRESULT rc;
    23602427
    2361     // create a project object
     2428    /* create a project object */
    23622429    ComObjPtr <Progress> progress;
    23632430    progress.createObject();
     
    23702437    }
    23712438
    2372     // mark as busy (being created)
    2373     // (VDI task thread will unmark it)
     2439    /* mark as busy (being created)
     2440     * (VDI task thread will unmark it) */
    23742441    setBusy();
    23752442
    2376     // fill in a VDI task data
     2443    /* fill in VDI task data */
    23772444    VDITask *task = new VDITask (aDynamic ? VDITask::CreateDynamic
    23782445                                          : VDITask::CreateStatic,
    23792446                                 this, progress);
    23802447    task->size = aSize;
    2381     task->size *= 1024 * 1024; // convert to bytes
    2382 
    2383     // create the hard disk creation thread, pass operation data
     2448    task->size *= 1024 * 1024; /* convert to bytes */
     2449
     2450    /* create the hard disk creation thread, pass operation data */
    23842451    vrc = RTThreadCreate (NULL, vdiTaskThread, (void *) task, 0,
    23852452                          RTTHREADTYPE_MAIN_HEAVY_WORKER, 0, "VDITask");
     
    23932460    else
    23942461    {
    2395         // get one interface for the caller
     2462        /* get one interface for the caller */
    23962463        progress.queryInterfaceTo (aProgress);
    23972464    }
     
    24002467}
    24012468
    2402 // static
     2469/* static */
    24032470DECLCALLBACK(int) HVirtualDiskImage::vdiTaskThread (RTTHREAD thread, void *pvUser)
    24042471{
     
    24312498                                         task->progress);
    24322499
    2433         // release reader added in HardDisk::CloneToImage()
     2500        /* release reader added in HardDisk::CloneToImage() */
    24342501        task->source->releaseReader();
    24352502    }
     
    24442511        if (VBOX_SUCCESS (vrc) && task->vdi->id())
    24452512        {
    2446             // we have a non-null UUID, update the created image
     2513            /* we have a non-null UUID, update the created image */
    24472514            vrc = VDISetImageUUIDs (Utf8Str (task->vdi->filePathFull()),
    24482515                                    task->vdi->id().raw(), NULL, NULL, NULL);
     
    24622529    AutoLock alock (task->vdi);
    24632530
    2464     // clear busy set in in HardDisk::CloneToImage() or
    2465     // in HVirtualDiskImage::createImage()
     2531    /* clear busy set in in HardDisk::CloneToImage() or
     2532     * in HVirtualDiskImage::createImage() */
    24662533    task->vdi->clearBusy();
    24672534
     
    24692536    {
    24702537        task->vdi->mState = HVirtualDiskImage::Created;
    2471         // update VDI data fields
     2538        /* update VDI data fields */
    24722539        rc = task->vdi->queryInformation (NULL);
    2473         // complete the progress object
     2540        /* complete the progress object */
    24742541        task->progress->notifyComplete (rc);
    24752542    }
     
    24802547
    24812548        task->vdi->mState = HVirtualDiskImage::NotCreated;
    2482         // complete the progress object
     2549        /* complete the progress object */
    24832550        if (errorMsg)
    24842551            task->progress->notifyComplete (
     
    25542621        CheckComRCBreakRC (rc);
    25552622
    2556         // set ready to let protectedUninit() be called on failure
     2623        /* set ready to let protectedUninit() be called on failure */
    25572624        setReady (true);
    25582625
    2559         // server (required)
     2626        /* server (required) */
    25602627        CFGLDRQueryBSTR (aISCSINode, "server", mServer.asOutParam());
    2561         // target (required)
     2628        /* target (required) */
    25622629        CFGLDRQueryBSTR (aISCSINode, "target", mTarget.asOutParam());
    25632630
    2564         // port (optional)
     2631        /* port (optional) */
    25652632        CFGLDRQueryUInt16 (aISCSINode, "port", &mPort);
    2566         // lun (optional)
     2633        /* lun (optional) */
    25672634        CFGLDRQueryUInt64 (aISCSINode, "lun", &mLun);
    2568         // userName (optional)
     2635        /* userName (optional) */
    25692636        CFGLDRQueryBSTR (aISCSINode, "userName", mUserName.asOutParam());
    2570         // password (optional)
     2637        /* password (optional) */
    25712638        CFGLDRQueryBSTR (aISCSINode, "password", mPassword.asOutParam());
    25722639
     
    25752642                        mLun));
    25762643
    2577         // load basic settings and children
     2644        /* load basic settings and children */
    25782645        rc = loadSettings (aHDNode);
    25792646        CheckComRCBreakRC (rc);
     
    26182685        CheckComRCBreakRC (rc);
    26192686
    2620         // set ready to let protectedUninit() be called on failure
     2687        /* set ready to let protectedUninit() be called on failure */
    26212688        setReady (true);
    26222689
    2623         // we have to generate a new UUID
     2690        /* we have to generate a new UUID */
    26242691        mId.create();
    26252692        mType = HardDiskType_WritethroughHardDisk;
     
    29222989    CHECK_READY();
    29232990
    2924     // check the basic accessibility
     2991    /* check the basic accessibility */
    29252992    HRESULT rc = HardDisk::getAccessible (aAccessError);
    29262993    if (FAILED (rc) || !aAccessError.isNull())
     
    29443011    CHECK_READY();
    29453012
    2946     // server (required)
     3013    /* server (required) */
    29473014    CFGLDRSetBSTR (aStorageNode, "server", mServer);
    2948     // target (required)
     3015    /* target (required) */
    29493016    CFGLDRSetBSTR (aStorageNode, "target", mTarget);
    29503017
    2951     // port (optional)
     3018    /* port (optional) */
    29523019    if (mPort != 0)
    29533020        CFGLDRSetUInt16 (aStorageNode, "port", mPort);
    29543021    else
    29553022        CFGLDRDeleteAttribute (aStorageNode, "port");
    2956     // lun (optional)
     3023    /* lun (optional) */
    29573024    if (mLun != 0)
    29583025        CFGLDRSetUInt64 (aStorageNode, "lun", mLun);
    29593026    else
    29603027        CFGLDRDeleteAttribute (aStorageNode, "lun");
    2961     // userName (optional)
     3028    /* userName (optional) */
    29623029    if (!mUserName.isNull())
    29633030        CFGLDRSetBSTR (aStorageNode, "userName", mUserName);
    29643031    else
    29653032        CFGLDRDeleteAttribute (aStorageNode, "userName");
    2966     // password (optional)
     3033    /* password (optional) */
    29673034    if (!mPassword.isNull())
    29683035        CFGLDRSetBSTR (aStorageNode, "password", mPassword);
     
    29703037        CFGLDRDeleteAttribute (aStorageNode, "password");
    29713038
    2972     // save basic settings and children
     3039    /* save basic settings and children */
    29733040    return HardDisk::saveSettings (aHDNode);
    29743041}
  • trunk/src/VBox/Main/ProgressImpl.cpp

    r1 r351  
    393393        return rc;
    394394
    395     mCompletedSem = NIL_RTSEMEVENT;
     395    mCompletedSem = NIL_RTSEMEVENTMULTI;
    396396    mWaitersCount = 0;
    397397
  • trunk/src/VBox/Main/include/HardDiskImpl.h

    r132 r351  
    2828#include <VBox/cfgldr.h>
    2929
     30#include <iprt/semaphore.h>
     31
    3032#include <list>
    3133
     
    6163    HRESULT FinalConstruct();
    6264    void FinalRelease();
    63 
    64     /// @todo (dmik) remove
    65     enum InitMode { Init_New, Init_Existing, Init_Registered };
    6665
    6766protected:
     
    168167    void updatePaths (const char *aOldPath, const char *aNewPath);
    169168
    170     bool isBusy() { AutoLock alock (this); return mBusy; }
    171     unsigned readers() { AutoLock alock (this); return mReaders; }
     169    /* these must be are called from under the lock */
     170    bool isBusy() { isLockedOnCurrentThread(); return mBusy; }
     171    unsigned readers() { isLockedOnCurrentThread(); return mReaders; }
    172172
    173173    // for VirtualBoxSupportErrorInfoImpl
     
    295295        NotCreated,
    296296        Created,
    297         Accessible, // must be greater than Created
     297        /* the following must be greater than Created */
     298        Accessible,
    298299    };
    299300
    300301    State mState;
     302   
     303    RTSEMEVENTMULTI mStateCheckSem;
     304    ULONG mStateCheckWaiters;
    301305
    302306    Bstr mDescription;
Note: See TracChangeset for help on using the changeset viewer.

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