diff options
author | Felix Geyer <debfx-pkg@fobos.de> | 2011-10-17 14:18:31 +0200 |
---|---|---|
committer | Felix Geyer <debfx-pkg@fobos.de> | 2011-10-17 14:18:31 +0200 |
commit | 1cf00a61132b69bc7e27254fdd74bf105d2da28c (patch) | |
tree | a7d314cc5ec77b4ce3e1f037af600b53ae1d43f8 /src/VBox/Main/src-server/MediumImpl.cpp | |
parent | f8fd93b0b6b13ba94584bb61c1efd1a761f438c9 (diff) | |
download | virtualbox-1cf00a61132b69bc7e27254fdd74bf105d2da28c.tar.gz |
Imported Upstream version 4.1.4-dfsgupstream/4.1.4-dfsg
Diffstat (limited to 'src/VBox/Main/src-server/MediumImpl.cpp')
-rw-r--r-- | src/VBox/Main/src-server/MediumImpl.cpp | 142 |
1 files changed, 80 insertions, 62 deletions
diff --git a/src/VBox/Main/src-server/MediumImpl.cpp b/src/VBox/Main/src-server/MediumImpl.cpp index 7e335a06b..5d46be866 100644 --- a/src/VBox/Main/src-server/MediumImpl.cpp +++ b/src/VBox/Main/src-server/MediumImpl.cpp @@ -1,4 +1,4 @@ -/* $Id: MediumImpl.cpp 38452 2011-08-15 08:50:33Z vboxsync $ */ +/* $Id: MediumImpl.cpp $ */ /** @file * VirtualBox COM class implementation */ @@ -2935,7 +2935,12 @@ STDMETHODIMP Medium::Reset(IProgress **aProgress) throw rc; } + /* Temporary leave this lock, cause IMedium::LockWrite, will wait for + * an running IMedium::queryInfo. If there is one running it might be + * it tries to acquire a MediaTreeLock as well -> dead-lock. */ + multilock.leave(); rc = pMediumLockList->Lock(); + multilock.enter(); if (FAILED(rc)) { delete pMediumLockList; @@ -3135,9 +3140,7 @@ Utf8Str Medium::getName() * one registry, which causes trouble with keeping diff images in sync. * See getFirstRegistryMachineId() for details. * - * Must have caller + locking! - * - * If fRecurse == true, then additionally the media tree lock must be held for reading. + * If fRecurse == true, then the media tree lock must be held for reading. * * @param id * @param fRecurse If true, recurses into child media to make sure the whole tree has registries in sync. @@ -3145,55 +3148,59 @@ Utf8Str Medium::getName() */ bool Medium::addRegistry(const Guid& id, bool fRecurse) { - // hard disks cannot be in more than one registry - if ( m->devType == DeviceType_HardDisk - && m->llRegistryIDs.size() > 0 - ) + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) return false; + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + + bool fAdd = true; + + // hard disks cannot be in more than one registry + if ( m->devType == DeviceType_HardDisk + && m->llRegistryIDs.size() > 0) + fAdd = false; // no need to add the UUID twice - for (GuidList::const_iterator it = m->llRegistryIDs.begin(); - it != m->llRegistryIDs.end(); - ++it) + if (fAdd) { - if ((*it) == id) - return false; + for (GuidList::const_iterator it = m->llRegistryIDs.begin(); + it != m->llRegistryIDs.end(); + ++it) + { + if ((*it) == id) + { + fAdd = false; + break; + } + } } - addRegistryImpl(id, fRecurse); - - return true; -} - -/** - * Private implementation for addRegistry() so we can recurse more efficiently. - * @param id - * @param fRecurse - */ -void Medium::addRegistryImpl(const Guid& id, bool fRecurse) -{ - m->llRegistryIDs.push_back(id); + if (fAdd) + m->llRegistryIDs.push_back(id); if (fRecurse) { - for (MediaList::iterator it = m->llChildren.begin(); - it != m->llChildren.end(); + // Get private list of children and release medium lock straight away. + MediaList llChildren(m->llChildren); + alock.release(); + + for (MediaList::iterator it = llChildren.begin(); + it != llChildren.end(); ++it) { Medium *pChild = *it; - // recurse! - pChild->addRegistryImpl(id, fRecurse); + fAdd |= pChild->addRegistry(id, true); } } + + return fAdd; } /** * Removes the given UUID from the list of media registry UUIDs. Returns true * if found or false if not. * - * Must have caller + locking! - * - * If fRecurse == true, then additionally the media tree lock must be held for reading. + * If fRecurse == true, then the media tree lock must be held for reading. * * @param id * @param fRecurse If true, recurses into child media to make sure the whole tree has registries in sync. @@ -3201,6 +3208,13 @@ void Medium::addRegistryImpl(const Guid& id, bool fRecurse) */ bool Medium::removeRegistry(const Guid& id, bool fRecurse) { + AutoCaller autoCaller(this); + if (FAILED(autoCaller.rc())) + return false; + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + + bool fRemove = false; + for (GuidList::iterator it = m->llRegistryIDs.begin(); it != m->llRegistryIDs.end(); ++it) @@ -3208,40 +3222,39 @@ bool Medium::removeRegistry(const Guid& id, bool fRecurse) if ((*it) == id) { m->llRegistryIDs.erase(it); + fRemove = true; + break; + } + } - if (fRecurse) - { - for (MediaList::iterator it2 = m->llChildren.begin(); - it2 != m->llChildren.end(); - ++it2) - { - Medium *pChild = *it2; - pChild->removeRegistry(id, true); - } - } + if (fRecurse) + { + // Get private list of children and release medium lock straight away. + MediaList llChildren(m->llChildren); + alock.release(); - return true; + for (MediaList::iterator it = llChildren.begin(); + it != llChildren.end(); + ++it) + { + Medium *pChild = *it; + fRemove |= pChild->removeRegistry(id, true); } } - return false; + return fRemove; } /** * Returns true if id is in the list of media registries for this medium. * - * Must have caller + locking! + * Must have caller + read locking! * * @param id * @return */ bool Medium::isInRegistry(const Guid& id) { - AutoCaller autoCaller(this); - if (FAILED(autoCaller.rc())) return false; - - AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); - for (GuidList::const_iterator it = m->llRegistryIDs.begin(); it != m->llRegistryIDs.end(); ++it) @@ -4251,6 +4264,11 @@ HRESULT Medium::deleteStorage(ComObjPtr<Progress> *aProgress, /* Undo deleting state if necessary. */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); + /* Make sure that any error signalled by unmarkForDeletion() is not + * ending up in the error list (if the caller uses MultiResult). It + * usually is spurious, as in most cases the medium hasn't been marked + * for deletion when the error was thrown above. */ + ErrorInfoKeeper eik; unmarkForDeletion(); } @@ -6401,7 +6419,7 @@ HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task) /* ensure the directory exists */ if (capabilities & MediumFormatCapabilities_File) { - rc = VirtualBox::ensureFilePathExists(location); + rc = VirtualBox::ensureFilePathExists(location, !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */); if (FAILED(rc)) throw rc; } @@ -6412,7 +6430,7 @@ HRESULT Medium::taskCreateBaseHandler(Medium::CreateBaseTask &task) format.c_str(), location.c_str(), task.mSize, - task.mVariant, + task.mVariant & ~MediumVariant_NoCreateDir, NULL, &geo, &geo, @@ -6568,7 +6586,7 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task) /* ensure the target directory exists */ if (capabilities & MediumFormatCapabilities_File) { - HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation); + HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation, !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */); if (FAILED(rc)) throw rc; } @@ -6576,7 +6594,7 @@ HRESULT Medium::taskCreateDiffHandler(Medium::CreateDiffTask &task) vrc = VDCreateDiff(hdd, targetFormat.c_str(), targetLocation.c_str(), - task.mVariant | VD_IMAGE_FLAGS_DIFF, + (task.mVariant & ~MediumVariant_NoCreateDir) | VD_IMAGE_FLAGS_DIFF, NULL, targetId.raw(), id.raw(), @@ -7071,7 +7089,7 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task) /* ensure the target directory exists */ if (capabilities & MediumFormatCapabilities_File) { - HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation); + HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation, !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */); if (FAILED(rc)) throw rc; } @@ -7134,7 +7152,7 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task) (fCreatingTarget) ? targetLocation.c_str() : (char *)NULL, false /* fMoveByRename */, 0 /* cbSize */, - task.mVariant, + task.mVariant & ~MediumVariant_NoCreateDir, targetId.raw(), VD_OPEN_FLAGS_NORMAL, NULL /* pVDIfsOperation */, @@ -7152,7 +7170,7 @@ HRESULT Medium::taskCloneHandler(Medium::CloneTask &task) 0 /* cbSize */, task.midxSrcImageSame, task.midxDstImageSame, - task.mVariant, + task.mVariant & ~MediumVariant_NoCreateDir, targetId.raw(), VD_OPEN_FLAGS_NORMAL, NULL /* pVDIfsOperation */, @@ -7742,7 +7760,7 @@ HRESULT Medium::taskExportHandler(Medium::ExportTask &task) /* ensure the target directory exists */ if (capabilities & MediumFormatCapabilities_File) { - rc = VirtualBox::ensureFilePathExists(targetLocation); + rc = VirtualBox::ensureFilePathExists(targetLocation, !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */); if (FAILED(rc)) throw rc; } @@ -7760,7 +7778,7 @@ HRESULT Medium::taskExportHandler(Medium::ExportTask &task) targetLocation.c_str(), false /* fMoveByRename */, 0 /* cbSize */, - task.mVariant, + task.mVariant & ~MediumVariant_NoCreateDir, NULL /* pDstUuid */, VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_SEQUENTIAL, NULL /* pVDIfsOperation */, @@ -7867,7 +7885,7 @@ HRESULT Medium::taskImportHandler(Medium::ImportTask &task) /* ensure the target directory exists */ if (capabilities & MediumFormatCapabilities_File) { - HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation); + HRESULT rc = VirtualBox::ensureFilePathExists(targetLocation, !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */); if (FAILED(rc)) throw rc; } @@ -7928,7 +7946,7 @@ HRESULT Medium::taskImportHandler(Medium::ImportTask &task) (fCreatingTarget) ? targetLocation.c_str() : (char *)NULL, false /* fMoveByRename */, 0 /* cbSize */, - task.mVariant, + task.mVariant & ~MediumVariant_NoCreateDir, targetId.raw(), VD_OPEN_FLAGS_NORMAL, NULL /* pVDIfsOperation */, |