~ubuntu-branches/ubuntu/precise/virtualbox/precise-updates

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-server/MediumImpl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-07-04 13:02:31 UTC
  • mfrom: (3.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20110704130231-l843es6wqhx614n7
Tags: 4.0.10-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Add the Modaliases control field manually for maximum backportability.

Show diffs side-by-side

added added

removed removed

Lines of Context:
238
238
 
239
239
    PVDINTERFACE mVDOperationIfaces;
240
240
 
241
 
    // Whether the caller needs to call VirtualBox::saveSettings() after
 
241
    // Whether the caller needs to call VirtualBox::saveRegistries() after
242
242
    // the task function returns. Only used in synchronous (wait) mode;
243
243
    // otherwise the task will save the settings itself.
244
244
    GuidList *m_pllRegistriesThatNeedSaving;
1307
1307
    if (FAILED(rc)) return rc;
1308
1308
    m->strDescription = aDescription;
1309
1309
 
1310
 
/// @todo generate uuid (similarly to host network interface uuid) from location and device type
1311
 
 
1312
1310
    autoInitSpan.setSucceeded();
1313
1311
    return S_OK;
1314
1312
}
2252
2250
    ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox);
2253
2251
 
2254
2252
    GuidList llRegistriesThatNeedSaving;
2255
 
    HRESULT rc = close(&llRegistriesThatNeedSaving, autoCaller);
2256
 
 
2257
 
    pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
2258
 
 
2259
 
    return rc;
 
2253
    MultiResult mrc = close(&llRegistriesThatNeedSaving, autoCaller);
 
2254
    /* Must save the registries, since an entry was most likely removed. */
 
2255
    mrc = pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
2256
 
 
2257
    return mrc;
2260
2258
}
2261
2259
 
2262
2260
STDMETHODIMP Medium::GetProperty(IN_BSTR aName, BSTR *aValue)
2471
2469
    ComObjPtr<Progress> pProgress;
2472
2470
 
2473
2471
    GuidList llRegistriesThatNeedSaving;
2474
 
    HRESULT rc = deleteStorage(&pProgress,
2475
 
                               false /* aWait */,
2476
 
                               &llRegistriesThatNeedSaving);
2477
 
    m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
2472
    MultiResult mrc = deleteStorage(&pProgress,
 
2473
                                    false /* aWait */,
 
2474
                                    &llRegistriesThatNeedSaving);
 
2475
    /* Must save the registries in any case, since an entry was removed. */
 
2476
    mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
2478
2477
 
2479
 
    if (SUCCEEDED(rc))
 
2478
    if (SUCCEEDED(mrc))
2480
2479
        pProgress.queryInterfaceTo(aProgress);
2481
2480
 
2482
 
    return rc;
 
2481
    return mrc;
2483
2482
}
2484
2483
 
2485
2484
STDMETHODIMP Medium::CreateDiffStorage(IMedium *aTarget,
3302
3301
    if (aSnapshotId.isEmpty())
3303
3302
    {
3304
3303
        /* sanity: no duplicate attachments */
3305
 
        AssertReturn(!it->fInCurState, E_FAIL);
 
3304
        if (it->fInCurState)
 
3305
            return setError(VBOX_E_OBJECT_IN_USE,
 
3306
                            tr("Cannot attach medium '%s' {%RTuuid}: medium is already associated with the current state of machine uuid {%RTuuid}!"),
 
3307
                            m->strLocationFull.c_str(),
 
3308
                            m->id.raw(),
 
3309
                            aMachineId.raw());
3306
3310
        it->fInCurState = true;
3307
3311
 
3308
3312
        return S_OK;
3326
3330
                            tr("Cannot attach medium '%s' {%RTuuid} from snapshot '%RTuuid': medium is already in use by this snapshot!"),
3327
3331
                            m->strLocationFull.c_str(),
3328
3332
                            m->id.raw(),
3329
 
                            aSnapshotId.raw(),
3330
 
                            idOldSnapshot.raw());
 
3333
                            aSnapshotId.raw());
3331
3334
        }
3332
3335
    }
3333
3336
 
3787
3790
 * @param aWait             @c true if this method should block instead of
3788
3791
 *                          creating an asynchronous thread.
3789
3792
 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs that will receive the registry IDs that need saving.
3790
 
 *                          This only works in "wait" mode; otherwise saveSettings is called automatically by the thread that
 
3793
 *                          This only works in "wait" mode; otherwise saveRegistries is called automatically by the thread that
3791
3794
 *                          was created, and this parameter is ignored.
3792
3795
 *
3793
3796
 * @note Locks this object and @a aTarget for writing.
3924
3927
 
3925
3928
/**
3926
3929
 * Implementation for the public Medium::Close() with the exception of calling
3927
 
 * VirtualBox::saveSettings(), in case someone wants to call this for several
 
3930
 * VirtualBox::saveRegistries(), in case someone wants to call this for several
3928
3931
 * media.
3929
3932
 *
3930
3933
 * After this returns with success, uninit() has been called on the medium, and
4008
4011
 * @param aWait         @c true if this method should block instead of creating
4009
4012
 *                      an asynchronous thread.
4010
4013
 * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
4011
 
 *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
4012
 
 *                This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
 
4014
 *                by this function if the caller should invoke VirtualBox::saveRegistries() because the global settings have changed.
 
4015
 *                This only works in "wait" mode; otherwise saveRegistries gets called automatically by the thread that was created,
4013
4016
 *                and this parameter is ignored.
4014
4017
 *
4015
4018
 * @note Locks mVirtualBox and this object for writing. Locks medium tree for
4626
4629
 * @param aWait         @c true if this method should block instead of creating
4627
4630
 *                      an asynchronous thread.
4628
4631
 * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
4629
 
 *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
4630
 
 *                This only works in "wait" mode; otherwise saveSettings gets called automatically by the thread that was created,
 
4632
 *                by this function if the caller should invoke VirtualBox::saveRegistries() because the global settings have changed.
 
4633
 *                This only works in "wait" mode; otherwise saveRegistries gets called automatically by the thread that was created,
4631
4634
 *                and this parameter is ignored.
4632
4635
 *
4633
4636
 * @note Locks the tree lock for writing. Locks the media from the chain
4840
4843
        catch (HRESULT aRC) { rc = aRC; }
4841
4844
        catch (int aVRC)
4842
4845
        {
4843
 
            throw setError(E_FAIL,
4844
 
                            tr("Could not update medium UUID references to parent '%s' (%s)"),
4845
 
                            m->strLocationFull.c_str(),
4846
 
                            vdError(aVRC).c_str());
 
4846
            rc = setError(E_FAIL,
 
4847
                          tr("Could not update medium UUID references to parent '%s' (%s)"),
 
4848
                          m->strLocationFull.c_str(),
 
4849
                          vdError(aVRC).c_str());
4847
4850
        }
4848
4851
 
4849
4852
        VDDestroy(hdd);
6269
6272
 */
6270
6273
HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task)
6271
6274
{
6272
 
    HRESULT rc = S_OK;
 
6275
    HRESULT rcTmp = S_OK;
6273
6276
 
6274
6277
    const ComObjPtr<Medium> &pTarget = task.mTarget;
6275
6278
 
6352
6355
            /* ensure the target directory exists */
6353
6356
            if (capabilities & VD_CAP_FILE)
6354
6357
            {
6355
 
                rc = VirtualBox::ensureFilePathExists(targetLocation);
 
6358
                HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation);
6356
6359
                if (FAILED(rc))
6357
6360
                    throw rc;
6358
6361
            }
6379
6382
            if (RT_SUCCESS(vrc))
6380
6383
                variant = (MediumVariant_T)uImageFlags;
6381
6384
        }
6382
 
        catch (HRESULT aRC) { rc = aRC; }
 
6385
        catch (HRESULT aRC) { rcTmp = aRC; }
6383
6386
 
6384
6387
        VDDestroy(hdd);
6385
6388
    }
6386
 
    catch (HRESULT aRC) { rc = aRC; }
6387
 
 
6388
 
    if (SUCCEEDED(rc))
 
6389
    catch (HRESULT aRC) { rcTmp = aRC; }
 
6390
 
 
6391
    MultiResult mrc(rcTmp);
 
6392
 
 
6393
    if (SUCCEEDED(mrc))
6389
6394
    {
6390
6395
        AutoWriteLock treeLock(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
6391
6396
 
6403
6408
        /* register with mVirtualBox as the last step and move to
6404
6409
         * Created state only on success (leaving an orphan file is
6405
6410
         * better than breaking media registry consistency) */
6406
 
        rc = m->pVirtualBox->registerHardDisk(pTarget, &llRegistriesThatNeedSaving);
 
6411
        mrc = m->pVirtualBox->registerHardDisk(pTarget, &llRegistriesThatNeedSaving);
6407
6412
 
6408
 
        if (FAILED(rc))
 
6413
        if (FAILED(mrc))
6409
6414
            /* break the parent association on failure to register */
6410
6415
            deparent();
6411
6416
    }
6412
6417
 
6413
6418
    AutoMultiWriteLock2 mediaLock(this, pTarget COMMA_LOCKVAL_SRC_POS);
6414
6419
 
6415
 
    if (SUCCEEDED(rc))
 
6420
    if (SUCCEEDED(mrc))
6416
6421
    {
6417
6422
        pTarget->m->state = MediumState_Created;
6418
6423
 
6439
6444
    if (task.isAsync())
6440
6445
    {
6441
6446
        mediaLock.release();
6442
 
        m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
6447
        mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
6443
6448
    }
6444
6449
    else
6445
6450
        // synchronous mode: report save settings result to caller
6449
6454
    /* Note that in sync mode, it's the caller's responsibility to
6450
6455
     * unlock the medium. */
6451
6456
 
6452
 
    return rc;
 
6457
    return mrc;
6453
6458
}
6454
6459
 
6455
6460
/**
6466
6471
 */
6467
6472
HRESULT Medium::taskMergeHandler(Medium::MergeTask &task)
6468
6473
{
6469
 
    HRESULT rc = S_OK;
 
6474
    HRESULT rcTmp = S_OK;
6470
6475
 
6471
6476
    const ComObjPtr<Medium> &pTarget = task.mTarget;
6472
6477
 
6593
6598
                }
6594
6599
            }
6595
6600
        }
6596
 
        catch (HRESULT aRC) { rc = aRC; }
 
6601
        catch (HRESULT aRC) { rcTmp = aRC; }
6597
6602
        catch (int aVRC)
6598
6603
        {
6599
 
            throw setError(VBOX_E_FILE_ERROR,
6600
 
                            tr("Could not merge the medium '%s' to '%s'%s"),
6601
 
                            m->strLocationFull.c_str(),
6602
 
                            pTarget->m->strLocationFull.c_str(),
6603
 
                            vdError(aVRC).c_str());
 
6604
            rcTmp = setError(VBOX_E_FILE_ERROR,
 
6605
                             tr("Could not merge the medium '%s' to '%s'%s"),
 
6606
                             m->strLocationFull.c_str(),
 
6607
                             pTarget->m->strLocationFull.c_str(),
 
6608
                             vdError(aVRC).c_str());
6604
6609
        }
6605
6610
 
6606
6611
        VDDestroy(hdd);
6607
6612
    }
6608
 
    catch (HRESULT aRC) { rc = aRC; }
 
6613
    catch (HRESULT aRC) { rcTmp = aRC; }
6609
6614
 
 
6615
    ErrorInfoKeeper eik;
 
6616
    MultiResult mrc(rcTmp);
6610
6617
    HRESULT rc2;
6611
6618
 
6612
 
    if (SUCCEEDED(rc))
 
6619
    if (SUCCEEDED(mrc))
6613
6620
    {
6614
6621
        /* all media but the target were successfully deleted by
6615
6622
         * VDMerge; reparent the last one and uninitialize deleted media. */
6726
6733
        // in asynchronous mode, save settings now
6727
6734
        GuidList llRegistriesThatNeedSaving;
6728
6735
        addToRegistryIDList(llRegistriesThatNeedSaving);
6729
 
        rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
6736
        /* collect multiple errors */
 
6737
        eik.restore();
 
6738
        mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
6739
        eik.fetch();
6730
6740
    }
6731
6741
    else
6732
6742
        // synchronous mode: report save settings result to caller
6733
6743
        if (task.m_pllRegistriesThatNeedSaving)
6734
6744
            pTarget->addToRegistryIDList(*task.m_pllRegistriesThatNeedSaving);
6735
6745
 
6736
 
    if (FAILED(rc))
 
6746
    if (FAILED(mrc))
6737
6747
    {
6738
6748
        /* Here we come if either VDMerge() failed (in which case we
6739
6749
         * assume that it tried to do everything to make a further
6740
6750
         * retry possible -- e.g. not deleted intermediate media
6741
 
         * and so on) or VirtualBox::saveSettings() failed (where we
 
6751
         * and so on) or VirtualBox::saveRegistries() failed (where we
6742
6752
         * should have the original tree but with intermediate storage
6743
6753
         * units deleted by VDMerge()). We have to only restore states
6744
6754
         * (through the MergeChain dtor) unless we are run synchronously
6752
6762
        }
6753
6763
    }
6754
6764
 
6755
 
    return rc;
 
6765
    return mrc;
6756
6766
}
6757
6767
 
6758
6768
/**
6766
6776
 */
6767
6777
HRESULT Medium::taskCloneHandler(Medium::CloneTask &task)
6768
6778
{
6769
 
    HRESULT rc = S_OK;
 
6779
    HRESULT rcTmp = S_OK;
6770
6780
 
6771
6781
    const ComObjPtr<Medium> &pTarget = task.mTarget;
6772
6782
    const ComObjPtr<Medium> &pParent = task.mParent;
6848
6858
            /* ensure the target directory exists */
6849
6859
            if (capabilities & VD_CAP_FILE)
6850
6860
            {
6851
 
                rc = VirtualBox::ensureFilePathExists(targetLocation);
 
6861
                HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation);
6852
6862
                if (FAILED(rc))
6853
6863
                    throw rc;
6854
6864
            }
6927
6937
                if (RT_SUCCESS(vrc))
6928
6938
                    variant = (MediumVariant_T)uImageFlags;
6929
6939
            }
6930
 
            catch (HRESULT aRC) { rc = aRC; }
 
6940
            catch (HRESULT aRC) { rcTmp = aRC; }
6931
6941
 
6932
6942
            VDDestroy(targetHdd);
6933
6943
        }
6934
 
        catch (HRESULT aRC) { rc = aRC; }
 
6944
        catch (HRESULT aRC) { rcTmp = aRC; }
6935
6945
 
6936
6946
        VDDestroy(hdd);
6937
6947
    }
6938
 
    catch (HRESULT aRC) { rc = aRC; }
 
6948
    catch (HRESULT aRC) { rcTmp = aRC; }
 
6949
 
 
6950
    ErrorInfoKeeper eik;
 
6951
    MultiResult mrc(rcTmp);
6939
6952
 
6940
6953
    /* Only do the parent changes for newly created media. */
6941
 
    if (SUCCEEDED(rc) && fCreatingTarget)
 
6954
    if (SUCCEEDED(mrc) && fCreatingTarget)
6942
6955
    {
6943
6956
        /* we set mParent & children() */
6944
6957
        AutoWriteLock alock2(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
6955
6968
            /* register with mVirtualBox as the last step and move to
6956
6969
             * Created state only on success (leaving an orphan file is
6957
6970
             * better than breaking media registry consistency) */
6958
 
            rc = pParent->m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
 
6971
            eik.restore();
 
6972
            mrc = pParent->m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
 
6973
            eik.fetch();
6959
6974
 
6960
 
            if (FAILED(rc))
 
6975
            if (FAILED(mrc))
6961
6976
                /* break parent association on failure to register */
6962
6977
                pTarget->deparent();     // removes target from parent
6963
6978
        }
6964
6979
        else
6965
6980
        {
6966
6981
            /* just register  */
6967
 
            rc = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
 
6982
            eik.restore();
 
6983
            mrc = m->pVirtualBox->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
 
6984
            eik.fetch();
6968
6985
        }
6969
6986
    }
6970
6987
 
6972
6989
    {
6973
6990
        AutoWriteLock mLock(pTarget COMMA_LOCKVAL_SRC_POS);
6974
6991
 
6975
 
        if (SUCCEEDED(rc))
 
6992
        if (SUCCEEDED(mrc))
6976
6993
        {
6977
6994
            pTarget->m->state = MediumState_Created;
6978
6995
 
6996
7013
        // save the settings
6997
7014
        GuidList llRegistriesThatNeedSaving;
6998
7015
        addToRegistryIDList(llRegistriesThatNeedSaving);
6999
 
        rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
7016
        /* collect multiple errors */
 
7017
        eik.restore();
 
7018
        mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
7019
        eik.fetch();
7000
7020
    }
7001
7021
 
7002
7022
    /* Everything is explicitly unlocked when the task exits,
7007
7027
     * is called & the source chain is released at the same time. */
7008
7028
    task.mpSourceMediumLockList->Clear();
7009
7029
 
7010
 
    return rc;
 
7030
    return mrc;
7011
7031
}
7012
7032
 
7013
7033
/**
7507
7527
                             0 /* cbSize */,
7508
7528
                             task.mVariant,
7509
7529
                             NULL /* pDstUuid */,
7510
 
                             VD_OPEN_FLAGS_NORMAL,
 
7530
                             VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_SEQUENTIAL,
7511
7531
                             NULL /* pVDIfsOperation */,
7512
7532
                             task.mVDImageIfaces,
7513
7533
                             task.mVDOperationIfaces);
7548
7568
 */
7549
7569
HRESULT Medium::taskImportHandler(Medium::ImportTask &task)
7550
7570
{
7551
 
    HRESULT rc = S_OK;
 
7571
    HRESULT rcTmp = S_OK;
7552
7572
 
7553
7573
    const ComObjPtr<Medium> &pParent = task.mParent;
7554
7574
 
7612
7632
            /* ensure the target directory exists */
7613
7633
            if (capabilities & VD_CAP_FILE)
7614
7634
            {
7615
 
                rc = VirtualBox::ensureFilePathExists(targetLocation);
 
7635
                HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation);
7616
7636
                if (FAILED(rc))
7617
7637
                    throw rc;
7618
7638
            }
7691
7711
                if (RT_SUCCESS(vrc))
7692
7712
                    variant = (MediumVariant_T)uImageFlags;
7693
7713
            }
7694
 
            catch (HRESULT aRC) { rc = aRC; }
 
7714
            catch (HRESULT aRC) { rcTmp = aRC; }
7695
7715
 
7696
7716
            VDDestroy(targetHdd);
7697
7717
        }
7698
 
        catch (HRESULT aRC) { rc = aRC; }
 
7718
        catch (HRESULT aRC) { rcTmp = aRC; }
7699
7719
 
7700
7720
        VDDestroy(hdd);
7701
7721
    }
7702
 
    catch (HRESULT aRC) { rc = aRC; }
 
7722
    catch (HRESULT aRC) { rcTmp = aRC; }
 
7723
 
 
7724
    ErrorInfoKeeper eik;
 
7725
    MultiResult mrc(rcTmp);
7703
7726
 
7704
7727
    /* Only do the parent changes for newly created media. */
7705
 
    if (SUCCEEDED(rc) && fCreatingTarget)
 
7728
    if (SUCCEEDED(mrc) && fCreatingTarget)
7706
7729
    {
7707
7730
        /* we set mParent & children() */
7708
7731
        AutoWriteLock alock2(m->pVirtualBox->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
7719
7742
            /* register with mVirtualBox as the last step and move to
7720
7743
             * Created state only on success (leaving an orphan file is
7721
7744
             * better than breaking media registry consistency) */
7722
 
            rc = pParent->m->pVirtualBox->registerHardDisk(this, NULL /* llRegistriesThatNeedSaving */);
 
7745
            eik.restore();
 
7746
            mrc = pParent->m->pVirtualBox->registerHardDisk(this, NULL /* llRegistriesThatNeedSaving */);
 
7747
            eik.fetch();
7723
7748
 
7724
 
            if (FAILED(rc))
 
7749
            if (FAILED(mrc))
7725
7750
                /* break parent association on failure to register */
7726
7751
                this->deparent();     // removes target from parent
7727
7752
        }
7728
7753
        else
7729
7754
        {
7730
7755
            /* just register  */
7731
 
            rc = m->pVirtualBox->registerHardDisk(this, NULL /* pllRegistriesThatNeedSaving */);
 
7756
            eik.restore();
 
7757
            mrc = m->pVirtualBox->registerHardDisk(this, NULL /* pllRegistriesThatNeedSaving */);
 
7758
            eik.fetch();
7732
7759
        }
7733
7760
    }
7734
7761
 
7736
7763
    {
7737
7764
        AutoWriteLock mLock(this COMMA_LOCKVAL_SRC_POS);
7738
7765
 
7739
 
        if (SUCCEEDED(rc))
 
7766
        if (SUCCEEDED(mrc))
7740
7767
        {
7741
7768
            m->state = MediumState_Created;
7742
7769
 
7760
7787
        // save the settings
7761
7788
        GuidList llRegistriesThatNeedSaving;
7762
7789
        addToRegistryIDList(llRegistriesThatNeedSaving);
7763
 
        rc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
7790
        /* collect multiple errors */
 
7791
        eik.restore();
 
7792
        mrc = m->pVirtualBox->saveRegistries(llRegistriesThatNeedSaving);
 
7793
        eik.fetch();
7764
7794
    }
7765
7795
 
7766
7796
    /* Everything is explicitly unlocked when the task exits,
7770
7800
     * lead to deadlocks with concurrent IAppliance activities. */
7771
7801
    task.mpTargetMediumLockList->Clear();
7772
7802
 
7773
 
    return rc;
 
7803
    return mrc;
7774
7804
}
7775
7805
 
7776
7806
/* vi: set tabstop=4 shiftwidth=4 expandtab: */