Changeset 25886 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jan 18, 2010 11:43:20 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 56695
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MediumImpl.cpp
r25882 r25886 4865 4865 } 4866 4866 4867 /** 4868 * Implementation code called from Medium::taskThread for the "create base" task. 4869 * @param task 4870 * @param pvdOperationIfaces 4871 * @return 4872 */ 4867 4873 HRESULT Medium::taskThreadCreateBase(Task &task, void *pvdOperationIfaces) 4868 4874 { 4875 HRESULT rc = S_OK; 4876 4869 4877 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces; 4870 4871 HRESULT rc = S_OK;4872 4878 4873 4879 /* The lock is also used as a signal from the task initiator (which … … 4969 4975 } 4970 4976 4977 /** 4978 * Implementation code called from Medium::taskThread for the "create diff" task. 4979 * @param task 4980 * @param pvdOperationIfaces 4981 * @return 4982 */ 4983 HRESULT Medium::taskThreadCreateDiff(Task &task, void *pvdOperationIfaces, bool fIsAsync) 4984 { 4985 HRESULT rc = S_OK; 4986 4987 PVDINTERFACE vdOperationIfaces = (PVDINTERFACE)pvdOperationIfaces; 4988 4989 ComObjPtr<Medium> &pTarget = task.d.target; 4990 4991 /* Lock both in {parent,child} order. The lock is also used as a 4992 * signal from the task initiator (which releases it only after 4993 * RTThreadCreate()) that we can start the job*/ 4994 AutoMultiWriteLock2 thisLock(this, pTarget COMMA_LOCKVAL_SRC_POS); 4995 4996 uint64_t size = 0, logicalSize = 0; 4997 4998 /* The object may request a specific UUID (through a special form of 4999 * the setLocation() argument). Otherwise we have to generate it */ 5000 Guid targetId = pTarget->m->id; 5001 bool generateUuid = targetId.isEmpty(); 5002 if (generateUuid) 5003 { 5004 targetId.create(); 5005 /* VirtualBox::registerHardDisk() will need UUID */ 5006 unconst(pTarget->m->id) = targetId; 5007 } 5008 5009 try 5010 { 5011 PVBOXHDD hdd; 5012 int vrc = VDCreate(m->vdDiskIfaces, &hdd); 5013 ComAssertRCThrow(vrc, E_FAIL); 5014 5015 Guid id = m->id; 5016 Utf8Str format(m->strFormat); 5017 Utf8Str location(m->strLocationFull); 5018 5019 Utf8Str targetFormat(pTarget->m->strFormat); 5020 Utf8Str targetLocation(pTarget->m->strLocationFull); 5021 5022 Assert(pTarget->m->state == MediumState_Creating); 5023 5024 /* Note: MediumState_LockedWrite is ok when taking an online 5025 * snapshot */ 5026 Assert( m->state == MediumState_LockedRead 5027 || m->state == MediumState_LockedWrite); 5028 5029 /* unlock before the potentially lengthy operation */ 5030 thisLock.leave(); 5031 5032 try 5033 { 5034 vrc = VDOpen(hdd, 5035 format.c_str(), 5036 location.c_str(), 5037 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5038 m->vdDiskIfaces); 5039 if (RT_FAILURE(vrc)) 5040 throw setError(E_FAIL, 5041 tr("Could not open the hard disk storage unit '%s'%s"), 5042 location.raw(), vdError(vrc).raw()); 5043 5044 /* ensure the target directory exists */ 5045 rc = VirtualBox::ensureFilePathExists(targetLocation); 5046 if (FAILED(rc)) throw rc; 5047 5048 /** @todo add VD_IMAGE_FLAGS_DIFF to the image flags, to 5049 * be on the safe side. */ 5050 vrc = VDCreateDiff(hdd, 5051 targetFormat.c_str(), 5052 targetLocation.c_str(), 5053 task.d.variant, 5054 NULL, 5055 targetId.raw(), 5056 id.raw(), 5057 VD_OPEN_FLAGS_NORMAL, 5058 pTarget->m->vdDiskIfaces, 5059 vdOperationIfaces); 5060 if (RT_FAILURE(vrc)) 5061 throw setError(E_FAIL, 5062 tr("Could not create the differencing hard disk storage unit '%s'%s"), 5063 targetLocation.raw(), vdError(vrc).raw()); 5064 5065 size = VDGetFileSize(hdd, 1); 5066 logicalSize = VDGetSize(hdd, 1) / _1M; 5067 } 5068 catch (HRESULT aRC) { rc = aRC; } 5069 5070 VDDestroy(hdd); 5071 } 5072 catch (HRESULT aRC) { rc = aRC; } 5073 5074 if (SUCCEEDED(rc)) 5075 { 5076 /* we set mParent & children() (note that thatLock is released 5077 * here), but lock VirtualBox first to follow the rule */ 5078 AutoWriteLock alock1(m->pVirtualBox COMMA_LOCKVAL_SRC_POS); 5079 AutoWriteLock alock2(m->pVirtualBox->hardDiskTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5080 5081 Assert(pTarget->m->pParent.isNull()); 5082 5083 /* associate the child with the parent */ 5084 pTarget->m->pParent = this; 5085 m->llChildren.push_back(pTarget); 5086 5087 /** @todo r=klaus neither target nor base() are locked, 5088 * potential race! */ 5089 /* diffs for immutable hard disks are auto-reset by default */ 5090 pTarget->m->autoReset = getBase()->m->type == MediumType_Immutable 5091 ? TRUE 5092 : FALSE; 5093 5094 /* register with mVirtualBox as the last step and move to 5095 * Created state only on success (leaving an orphan file is 5096 * better than breaking media registry consistency) */ 5097 rc = m->pVirtualBox->registerHardDisk(pTarget); 5098 5099 if (FAILED(rc)) 5100 /* break the parent association on failure to register */ 5101 deparent(); 5102 } 5103 5104 thisLock.maybeEnter(); 5105 5106 if (SUCCEEDED(rc)) 5107 { 5108 pTarget->m->state = MediumState_Created; 5109 5110 pTarget->m->size = size; 5111 pTarget->m->logicalSize = logicalSize; 5112 } 5113 else 5114 { 5115 /* back to NotCreated on failure */ 5116 pTarget->m->state = MediumState_NotCreated; 5117 5118 pTarget->m->autoReset = FALSE; 5119 5120 /* reset UUID to prevent it from being reused next time */ 5121 if (generateUuid) 5122 unconst(pTarget->m->id).clear(); 5123 } 5124 5125 if (fIsAsync) 5126 { 5127 /* unlock ourselves when done (unless in MediumState_LockedWrite 5128 * state because of taking the online snapshot*/ 5129 if (m->state != MediumState_LockedWrite) 5130 { 5131 HRESULT rc2 = UnlockRead(NULL); 5132 AssertComRC(rc2); 5133 } 5134 } 5135 5136 /* deregister the task registered in createDiffStorage() */ 5137 Assert(m->numCreateDiffTasks != 0); 5138 --m->numCreateDiffTasks; 5139 5140 /* Note that in sync mode, it's the caller's responsibility to 5141 * unlock the hard disk */ 5142 5143 return rc; 5144 } 4971 5145 4972 5146 /** … … 4984 5158 AssertReturn(task.get(), VERR_GENERAL_FAILURE); 4985 5159 4986 bool isAsync = thread != NIL_RTTHREAD;5160 bool fIsAsync = thread != NIL_RTTHREAD; 4987 5161 4988 5162 Medium *that = task->that; … … 5022 5196 break; 5023 5197 5024 ////////////////////////////////////////////////////////////////////////5025 5026 5198 case Task::CreateDiff: 5027 { 5028 ComObjPtr<Medium> &target = task->d.target; 5029 5030 /* Lock both in {parent,child} order. The lock is also used as a 5031 * signal from the task initiator (which releases it only after 5032 * RTThreadCreate()) that we can start the job*/ 5033 AutoMultiWriteLock2 thatLock(that, target COMMA_LOCKVAL_SRC_POS); 5034 5035 uint64_t size = 0, logicalSize = 0; 5036 5037 /* The object may request a specific UUID (through a special form of 5038 * the setLocation() argument). Otherwise we have to generate it */ 5039 Guid targetId = target->m->id; 5040 bool generateUuid = targetId.isEmpty(); 5041 if (generateUuid) 5042 { 5043 targetId.create(); 5044 /* VirtualBox::registerHardDisk() will need UUID */ 5045 unconst(target->m->id) = targetId; 5046 } 5047 5048 try 5049 { 5050 PVBOXHDD hdd; 5051 int vrc = VDCreate(that->m->vdDiskIfaces, &hdd); 5052 ComAssertRCThrow(vrc, E_FAIL); 5053 5054 Guid id = that->m->id; 5055 Utf8Str format(that->m->strFormat); 5056 Utf8Str location(that->m->strLocationFull); 5057 5058 Utf8Str targetFormat(target->m->strFormat); 5059 Utf8Str targetLocation(target->m->strLocationFull); 5060 5061 Assert(target->m->state == MediumState_Creating); 5062 5063 /* Note: MediumState_LockedWrite is ok when taking an online 5064 * snapshot */ 5065 Assert(that->m->state == MediumState_LockedRead || 5066 that->m->state == MediumState_LockedWrite); 5067 5068 /* unlock before the potentially lengthy operation */ 5069 thatLock.leave(); 5070 5071 try 5072 { 5073 vrc = VDOpen(hdd, format.c_str(), location.c_str(), 5074 VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO, 5075 that->m->vdDiskIfaces); 5076 if (RT_FAILURE(vrc)) 5077 { 5078 throw setError(E_FAIL, 5079 tr("Could not open the hard disk storage unit '%s'%s"), 5080 location.raw(), that->vdError(vrc).raw()); 5081 } 5082 5083 /* ensure the target directory exists */ 5084 rc = VirtualBox::ensureFilePathExists(targetLocation); 5085 if (FAILED(rc)) throw rc; 5086 5087 /** @todo add VD_IMAGE_FLAGS_DIFF to the image flags, to 5088 * be on the safe side. */ 5089 vrc = VDCreateDiff(hdd, targetFormat.c_str(), 5090 targetLocation.c_str(), 5091 task->d.variant, 5092 NULL, targetId.raw(), 5093 id.raw(), 5094 VD_OPEN_FLAGS_NORMAL, 5095 target->m->vdDiskIfaces, 5096 vdOperationIfaces); 5097 if (RT_FAILURE(vrc)) 5098 { 5099 throw setError(E_FAIL, 5100 tr("Could not create the differencing hard disk storage unit '%s'%s"), 5101 targetLocation.raw(), that->vdError(vrc).raw()); 5102 } 5103 5104 size = VDGetFileSize(hdd, 1); 5105 logicalSize = VDGetSize(hdd, 1) / _1M; 5106 } 5107 catch (HRESULT aRC) { rc = aRC; } 5108 5109 VDDestroy(hdd); 5110 } 5111 catch (HRESULT aRC) { rc = aRC; } 5112 5113 if (SUCCEEDED(rc)) 5114 { 5115 /* we set mParent & children() (note that thatLock is released 5116 * here), but lock VirtualBox first to follow the rule */ 5117 AutoWriteLock alock1(that->m->pVirtualBox COMMA_LOCKVAL_SRC_POS); 5118 AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5119 5120 Assert(target->m->pParent.isNull()); 5121 5122 /* associate the child with the parent */ 5123 target->m->pParent = that; 5124 that->m->llChildren.push_back(target); 5125 5126 /** @todo r=klaus neither target nor that->base() are locked, 5127 * potential race! */ 5128 /* diffs for immutable hard disks are auto-reset by default */ 5129 target->m->autoReset = 5130 that->getBase()->m->type == MediumType_Immutable ? 5131 TRUE : FALSE; 5132 5133 /* register with mVirtualBox as the last step and move to 5134 * Created state only on success (leaving an orphan file is 5135 * better than breaking media registry consistency) */ 5136 rc = that->m->pVirtualBox->registerHardDisk(target); 5137 5138 if (FAILED(rc)) 5139 /* break the parent association on failure to register */ 5140 that->deparent(); 5141 } 5142 5143 thatLock.maybeEnter(); 5144 5145 if (SUCCEEDED(rc)) 5146 { 5147 target->m->state = MediumState_Created; 5148 5149 target->m->size = size; 5150 target->m->logicalSize = logicalSize; 5151 } 5152 else 5153 { 5154 /* back to NotCreated on failure */ 5155 target->m->state = MediumState_NotCreated; 5156 5157 target->m->autoReset = FALSE; 5158 5159 /* reset UUID to prevent it from being reused next time */ 5160 if (generateUuid) 5161 unconst(target->m->id).clear(); 5162 } 5163 5164 if (isAsync) 5165 { 5166 /* unlock ourselves when done (unless in MediumState_LockedWrite 5167 * state because of taking the online snapshot*/ 5168 if (that->m->state != MediumState_LockedWrite) 5169 { 5170 HRESULT rc2 = that->UnlockRead(NULL); 5171 AssertComRC(rc2); 5172 } 5173 } 5174 5175 /* deregister the task registered in createDiffStorage() */ 5176 Assert(that->m->numCreateDiffTasks != 0); 5177 --that->m->numCreateDiffTasks; 5178 5179 /* Note that in sync mode, it's the caller's responsibility to 5180 * unlock the hard disk */ 5181 5182 break; 5183 } 5199 rc = that->taskThreadCreateDiff(*task, (void*)vdOperationIfaces, fIsAsync); 5200 break; 5184 5201 5185 5202 //////////////////////////////////////////////////////////////////////// … … 5329 5346 AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5330 5347 5331 Medium * source = chain->source();5332 Medium * target = chain->target();5348 Medium *pSource = chain->source(); 5349 Medium *pTarget = chain->target(); 5333 5350 5334 5351 if (chain->isForward()) … … 5336 5353 /* first, unregister the target since it may become a base 5337 5354 * hard disk which needs re-registration */ 5338 rc2 = target->m->pVirtualBox->unregisterHardDisk(target, false /* aSaveSettings */);5355 rc2 = pTarget->m->pVirtualBox->unregisterHardDisk(pTarget, false /* aSaveSettings */); 5339 5356 AssertComRC(rc2); 5340 5357 5341 5358 /* then, reparent it and disconnect the deleted branch at 5342 5359 * both ends (chain->parent() is source's parent) */ 5343 target->deparent();5344 target->m->pParent = chain->parent();5345 if ( target->m->pParent)5360 pTarget->deparent(); 5361 pTarget->m->pParent = chain->parent(); 5362 if (pTarget->m->pParent) 5346 5363 { 5347 target->m->pParent->m->llChildren.push_back(target);5348 source->deparent();5364 pTarget->m->pParent->m->llChildren.push_back(pTarget); 5365 pSource->deparent(); 5349 5366 } 5350 5367 5351 5368 /* then, register again */ 5352 rc2 = target->m->pVirtualBox-> 5353 registerHardDisk(target, false /* aSaveSettings */); 5369 rc2 = pTarget->m->pVirtualBox->registerHardDisk(pTarget, false /* aSaveSettings */); 5354 5370 AssertComRC(rc2); 5355 5371 } 5356 5372 else 5357 5373 { 5358 Assert( target->getChildren().size() == 1);5359 Medium *targetChild = target->getChildren().front();5374 Assert(pTarget->getChildren().size() == 1); 5375 Medium *targetChild = pTarget->getChildren().front(); 5360 5376 5361 5377 /* disconnect the deleted branch at the elder end */ … … 5369 5385 { 5370 5386 /* obey {parent,child} lock order */ 5371 AutoWriteLock sourceLock( source COMMA_LOCKVAL_SRC_POS);5387 AutoWriteLock sourceLock(pSource COMMA_LOCKVAL_SRC_POS); 5372 5388 5373 5389 for (MediaList::const_iterator it = children.begin(); … … 5379 5395 Medium *p = *it; 5380 5396 p->deparent(); // removes p from source 5381 target->m->llChildren.push_back(p);5382 p->m->pParent = target;5397 pTarget->m->llChildren.push_back(p); 5398 p->m->pParent = pTarget; 5383 5399 } 5384 5400 } … … 5425 5441 (*it)->releaseCaller(); 5426 5442 5427 if ( isAsync || *it != that)5443 if (fIsAsync || *it != that) 5428 5444 (*it)->uninit(); 5429 5445 … … 5463 5479 * don't own the merge chain, so release it in this case. */ 5464 5480 5465 if (! isAsync)5481 if (!fIsAsync) 5466 5482 task->d.chain.release(); 5467 5483 … … 5476 5492 case Task::Clone: 5477 5493 { 5478 ComObjPtr<Medium> & target = task->d.target;5479 ComObjPtr<Medium> &p arent = task->d.parentDisk;5494 ComObjPtr<Medium> &pTarget = task->d.target; 5495 ComObjPtr<Medium> &pParent = task->d.parentDisk; 5480 5496 5481 5497 /* Lock all in {parent,child} order. The lock is also used as a 5482 5498 * signal from the task initiator (which releases it only after 5483 5499 * RTThreadCreate()) that we can start the job. */ 5484 AutoMultiWriteLock3 thatLock(that, target, parent COMMA_LOCKVAL_SRC_POS);5500 AutoMultiWriteLock3 thatLock(that, pTarget, pParent COMMA_LOCKVAL_SRC_POS); 5485 5501 5486 5502 ImageChain *srcChain = task->d.source.get(); … … 5491 5507 /* The object may request a specific UUID (through a special form of 5492 5508 * the setLocation() argument). Otherwise we have to generate it */ 5493 Guid targetId = target->m->id;5509 Guid targetId = pTarget->m->id; 5494 5510 bool generateUuid = targetId.isEmpty(); 5495 5511 if (generateUuid) … … 5497 5513 targetId.create(); 5498 5514 /* VirtualBox::registerHardDisk() will need UUID */ 5499 unconst( target->m->id) = targetId;5515 unconst(pTarget->m->id) = targetId; 5500 5516 } 5501 5517 … … 5530 5546 } 5531 5547 5532 Utf8Str targetFormat( target->m->strFormat);5533 Utf8Str targetLocation( target->m->strLocationFull);5534 5535 Assert( target->m->state == MediumState_Creating5536 || target->m->state == MediumState_LockedWrite);5548 Utf8Str targetFormat(pTarget->m->strFormat); 5549 Utf8Str targetLocation(pTarget->m->strLocationFull); 5550 5551 Assert( pTarget->m->state == MediumState_Creating 5552 || pTarget->m->state == MediumState_LockedWrite); 5537 5553 Assert(that->m->state == MediumState_LockedRead); 5538 Assert(p arent.isNull() || parent->m->state == MediumState_LockedRead);5554 Assert(pParent.isNull() || pParent->m->state == MediumState_LockedRead); 5539 5555 5540 5556 /* unlock before the potentially lengthy operation */ … … 5579 5595 vrc = VDCopy(hdd, VD_LAST_IMAGE, targetHdd, 5580 5596 targetFormat.c_str(), 5581 target->m->state == MediumState_Creating ? targetLocation.raw() : (char *)NULL,5597 pTarget->m->state == MediumState_Creating ? targetLocation.raw() : (char *)NULL, 5582 5598 false, 0, 5583 5599 task->d.variant, targetId.raw(), NULL, 5584 target->m->vdDiskIfaces,5600 pTarget->m->vdDiskIfaces, 5585 5601 vdOperationIfaces); 5586 5602 if (RT_FAILURE(vrc)) … … 5604 5620 5605 5621 /* Only do the parent changes for newly created images. */ 5606 if ( target->m->state == MediumState_Creating)5622 if (pTarget->m->state == MediumState_Creating) 5607 5623 { 5608 5624 if (SUCCEEDED(rc)) … … 5613 5629 AutoWriteLock alock2(that->m->pVirtualBox->hardDiskTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 5614 5630 5615 Assert( target->m->pParent.isNull());5616 5617 if (p arent)5631 Assert(pTarget->m->pParent.isNull()); 5632 5633 if (pParent) 5618 5634 { 5619 5635 /* associate the clone with the parent and deassociate 5620 5636 * from VirtualBox */ 5621 target->m->pParent = parent;5622 p arent->m->llChildren.push_back(target);5637 pTarget->m->pParent = pParent; 5638 pParent->m->llChildren.push_back(pTarget); 5623 5639 5624 5640 /* register with mVirtualBox as the last step and move to 5625 5641 * Created state only on success (leaving an orphan file is 5626 5642 * better than breaking media registry consistency) */ 5627 rc = p arent->m->pVirtualBox->registerHardDisk(target);5643 rc = pParent->m->pVirtualBox->registerHardDisk(pTarget); 5628 5644 5629 5645 if (FAILED(rc)) 5630 5646 /* break parent association on failure to register */ 5631 target->deparent(); // removes target from parent5647 pTarget->deparent(); // removes target from parent 5632 5648 } 5633 5649 else 5634 5650 { 5635 5651 /* just register */ 5636 rc = that->m->pVirtualBox->registerHardDisk( target);5652 rc = that->m->pVirtualBox->registerHardDisk(pTarget); 5637 5653 } 5638 5654 } … … 5641 5657 thatLock.maybeEnter(); 5642 5658 5643 if ( target->m->state == MediumState_Creating)5659 if (pTarget->m->state == MediumState_Creating) 5644 5660 { 5645 5661 if (SUCCEEDED(rc)) 5646 5662 { 5647 target->m->state = MediumState_Created;5648 5649 target->m->size = size;5650 target->m->logicalSize = logicalSize;5663 pTarget->m->state = MediumState_Created; 5664 5665 pTarget->m->size = size; 5666 pTarget->m->logicalSize = logicalSize; 5651 5667 } 5652 5668 else 5653 5669 { 5654 5670 /* back to NotCreated on failure */ 5655 target->m->state = MediumState_NotCreated;5671 pTarget->m->state = MediumState_NotCreated; 5656 5672 5657 5673 /* reset UUID to prevent it from being reused next time */ 5658 5674 if (generateUuid) 5659 unconst( target->m->id).clear();5675 unconst(pTarget->m->id).clear(); 5660 5676 } 5661 5677 } … … 5816 5832 that->m->logicalSize = logicalSize; 5817 5833 5818 if ( isAsync)5834 if (fIsAsync) 5819 5835 { 5820 5836 /* unlock ourselves when done */ … … 5917 5933 5918 5934 /* complete the progress if run asynchronously */ 5919 if ( isAsync)5935 if (fIsAsync) 5920 5936 { 5921 5937 if (!task->m_pProgress.isNull()) -
trunk/src/VBox/Main/include/MediumImpl.h
r25882 r25886 310 310 311 311 HRESULT taskThreadCreateBase(Task &task, void *pvdOperationIfaces); 312 HRESULT taskThreadCreateDiff(Task &task, void *pvdOperationIfaces, bool fIsAsync); 312 313 313 314 static DECLCALLBACK(int) taskThread(RTTHREAD thread, void *pvUser);
Note:
See TracChangeset
for help on using the changeset viewer.