Changeset 61483 in vbox
- Timestamp:
- Jun 6, 2016 8:54:30 AM (9 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp
r57358 r61483 478 478 { "compact", 'c', RTGETOPT_REQ_NOTHING }, // deprecated 479 479 { "--resize", 'r', RTGETOPT_REQ_UINT64 }, 480 { "--resizebyte", 'R', RTGETOPT_REQ_UINT64 } 480 { "--resizebyte", 'R', RTGETOPT_REQ_UINT64 }, 481 { "--move", 'm', RTGETOPT_REQ_STRING } 481 482 }; 482 483 … … 501 502 bool fModifyCompact = false; 502 503 bool fModifyResize = false; 504 bool fModifyLocation = false; 503 505 uint64_t cbResize = 0; 504 506 const char *pszFilenameOrUuid = NULL; 507 const char *pszNewLocation = NULL; 505 508 506 509 int c; … … 592 595 break; 593 596 597 case 'm': // --move 598 /* Get a new location */ 599 pszNewLocation = RTStrDup(ValueUnion.psz); 600 fModifyLocation = true; 601 break; 602 594 603 case VINF_GETOPT_NOT_OPTION: 595 604 if (!pszFilenameOrUuid) … … 622 631 return errorSyntax(USAGE_MODIFYMEDIUM, "Medium name or UUID required"); 623 632 624 if (!fModifyMediumType && !fModifyAutoReset && !fModifyProperties && !fModifyCompact && !fModifyResize )633 if (!fModifyMediumType && !fModifyAutoReset && !fModifyProperties && !fModifyCompact && !fModifyResize && !fModifyLocation) 625 634 return errorSyntax(USAGE_MODIFYMEDIUM, "No operation specified"); 626 635 … … 703 712 RTMsgError("Failed to resize medium!"); 704 713 } 714 } 715 716 if (fModifyLocation) 717 { 718 do 719 { 720 ComPtr<IProgress> pProgress; 721 Utf8Str strLocation(pszNewLocation); 722 CHECK_ERROR(pMedium, SetLocation(Bstr(pszNewLocation).raw(), pProgress.asOutParam())); 723 724 if (SUCCEEDED(rc) && !pProgress.isNull()) 725 { 726 rc = showProgress(pProgress); 727 CHECK_PROGRESS_ERROR(pProgress, ("Failed to move medium")); 728 } 729 730 Bstr uuid; 731 CHECK_ERROR_BREAK(pMedium, COMGETTER(Id)(uuid.asOutParam())); 732 733 RTPrintf("Move medium with UUID %s finished \n", Utf8Str(uuid).c_str()); 734 } 735 while (0); 705 736 } 706 737 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
r61226 r61483 1135 1135 " [--compact]\n" 1136 1136 " [--resize <megabytes>|--resizebyte <bytes>]\n" 1137 " [--move <full path to a new location>]" 1137 1138 "\n", SEP); 1138 1139 -
trunk/src/VBox/Main/include/MediumImpl.h
r61137 r61483 317 317 std::vector<com::Utf8Str> &aReturnValues); 318 318 319 HRESULT i_preparationForMoving(const Utf8Str &aLocation); 320 bool i_isMoveOperation(const ComObjPtr<Medium> &pTarget) const; 321 bool i_resetMoveOperationData(); 322 Utf8Str i_getNewLocationForMoving() const; 323 319 324 static DECLCALLBACK(void) i_vdErrorCall(void *pvUser, int rc, RT_SRC_POS_DECL, 320 325 const char *pszFormat, va_list va); … … 360 365 class CreateDiffTask; 361 366 class CloneTask; 367 class MoveTask; 362 368 class CompactTask; 363 369 class ResizeTask; … … 372 378 friend class CreateDiffTask; 373 379 friend class CloneTask; 380 friend class MoveTask; 374 381 friend class CompactTask; 375 382 friend class ResizeTask; … … 388 395 HRESULT i_taskMergeHandler(Medium::MergeTask &task); 389 396 HRESULT i_taskCloneHandler(Medium::CloneTask &task); 397 HRESULT i_taskMoveHandler(Medium::MoveTask &task); 390 398 HRESULT i_taskDeleteHandler(Medium::DeleteTask &task); 391 399 HRESULT i_taskResetHandler(Medium::ResetTask &task); -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r61174 r61483 108 108 numCreateDiffTasks(0), 109 109 vdDiskIfaces(NULL), 110 vdImageIfaces(NULL) 110 vdImageIfaces(NULL), 111 fMoveThisMedium(false) 111 112 { } 112 113 … … 181 182 PVDINTERFACE vdDiskIfaces; 182 183 PVDINTERFACE vdImageIfaces; 184 185 /** Flag if the medium is going to move to a new 186 * location. */ 187 bool fMoveThisMedium; 188 /** new location path */ 189 Utf8Str strNewLocationFull; 183 190 }; 184 191 … … 405 412 }; 406 413 414 class Medium::MoveTask : public Medium::Task 415 { 416 public: 417 MoveTask(Medium *aMedium, 418 Progress *aProgress, 419 MediumVariant_T aVariant, 420 MediumLockList *aMediumLockList, 421 bool fKeepMediumLockList = false) 422 : Medium::Task(aMedium, aProgress), 423 mpMediumLockList(aMediumLockList), 424 mVariant(aVariant), 425 mfKeepMediumLockList(fKeepMediumLockList) 426 { 427 AssertReturnVoidStmt(aMediumLockList != NULL, mRC = E_FAIL); 428 } 429 430 ~MoveTask() 431 { 432 if (!mfKeepMediumLockList && mpMediumLockList) 433 delete mpMediumLockList; 434 } 435 436 MediumLockList *mpMediumLockList; 437 MediumVariant_T mVariant; 438 439 private: 440 virtual HRESULT handler(); 441 442 bool mfKeepMediumLockList; 443 }; 444 407 445 class Medium::CompactTask : public Medium::Task 408 446 { … … 854 892 { 855 893 return mMedium->i_taskCloneHandler(*this); 894 } 895 896 /** 897 * Implementation code for the "move" task. 898 */ 899 HRESULT Medium::MoveTask::handler() 900 { 901 return mMedium->i_taskMoveHandler(*this); 856 902 } 857 903 … … 2899 2945 HRESULT Medium::setLocation(const com::Utf8Str &aLocation, ComPtr<IProgress> &aProgress) 2900 2946 { 2901 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2902 NOREF(aLocation); 2903 NOREF(aProgress); 2904 2947 2948 ComObjPtr<Medium> pParent; 2949 ComObjPtr<Progress> pProgress; 2950 HRESULT rc = S_OK; 2951 Medium::Task *pTask = NULL; 2952 2953 try 2954 { 2905 2955 /// @todo NEWMEDIA for file names, add the default extension if no extension 2906 2956 /// is present (using the information from the VD backend which also implies … … 2912 2962 /// this medium), this will also require to add the mRegistered flag to data 2913 2963 2914 ReturnComNotImplemented(); 2964 // locking: we need the tree lock first because we access parent pointers 2965 // and we need to write-lock the media involved 2966 uint32_t cHandles = 2; 2967 LockHandle* pHandles[2] = { &m->pVirtualBox->i_getMediaTreeLockHandle(), 2968 this->lockHandle() }; 2969 2970 AutoWriteLock alock(cHandles, 2971 pHandles 2972 COMMA_LOCKVAL_SRC_POS); 2973 2974 /* Set needed variables for "moving" procedure. It'll be used later in separate thread task */ 2975 rc = i_preparationForMoving(aLocation); 2976 if (FAILED(rc)) 2977 { 2978 rc = setError(VERR_NO_CHANGE, 2979 tr("Medium '%s' is already in the correct location"), 2980 i_getLocationFull().c_str()); 2981 return rc; 2982 } 2983 2984 /* Check VMs which have this medium attached to*/ 2985 std::vector<com::Guid> aMachineIds; 2986 rc = getMachineIds(aMachineIds); 2987 std::vector<com::Guid>::const_iterator currMachineID = aMachineIds.begin(); 2988 std::vector<com::Guid>::const_iterator lastMachineID = aMachineIds.end(); 2989 2990 while(currMachineID != lastMachineID) 2991 { 2992 Guid id(*currMachineID); 2993 ComObjPtr<Machine> aMachine; 2994 2995 alock.release(); 2996 rc = m->pVirtualBox->i_findMachine(id, false, true, &aMachine); 2997 alock.acquire(); 2998 2999 if (SUCCEEDED(rc)) 3000 { 3001 MachineState_T aState; 3002 ComObjPtr<SessionMachine> sm; 3003 ComPtr<IInternalSessionControl> ctl; 3004 3005 alock.release(); 3006 bool ses = aMachine->i_isSessionOpenVM(sm, &ctl); 3007 alock.acquire(); 3008 3009 if (ses) 3010 { 3011 rc = setError(VERR_VM_UNEXPECTED_VM_STATE, 3012 tr("At least VM '%s' to whom this medium '%s' attached has the opened session now. " 3013 "Stop all needed VM before set a new location."), 3014 id.toString().c_str(), 3015 i_getLocationFull().c_str()); 3016 throw rc; 3017 } 3018 } 3019 ++currMachineID; 3020 } 3021 3022 /* Build the source lock list. */ 3023 MediumLockList *pMediumLockList(new MediumLockList()); 3024 alock.release(); 3025 rc = i_createMediumLockList(true /* fFailIfInaccessible */, 3026 this /* pToLockWrite */, 3027 true /* fMediumLockWriteAll */, 3028 NULL, 3029 *pMediumLockList); 3030 alock.acquire(); 3031 if (FAILED(rc)) 3032 { 3033 delete pMediumLockList; 3034 throw setError(rc, 3035 tr("Failed to create medium lock list for '%s'"), 3036 i_getLocationFull().c_str()); 3037 } 3038 alock.release(); 3039 rc = pMediumLockList->Lock(); 3040 alock.acquire(); 3041 if (FAILED(rc)) 3042 { 3043 delete pMediumLockList; 3044 throw setError(rc, 3045 tr("Failed to lock media '%s'"), 3046 i_getLocationFull().c_str()); 3047 } 3048 3049 pProgress.createObject(); 3050 rc = pProgress->init(m->pVirtualBox, 3051 static_cast <IMedium *>(this), 3052 BstrFmt(tr("Moving medium '%s'"), m->strLocationFull.c_str()).raw(), 3053 TRUE /* aCancelable */); 3054 3055 /* Do the disk moving. */ 3056 if(SUCCEEDED(rc)) 3057 { 3058 ULONG mediumVariantFlags = i_getVariant(); 3059 3060 /* setup task object to carry out the operation asynchronously */ 3061 pTask = new Medium::MoveTask(this, pProgress, 3062 (MediumVariant_T)mediumVariantFlags, 3063 pMediumLockList); 3064 rc = pTask->rc(); 3065 AssertComRC(rc); 3066 if (FAILED(rc)) 3067 throw rc; 3068 } 3069 3070 } 3071 catch (HRESULT aRC) { rc = aRC; } 3072 3073 if (SUCCEEDED(rc)) 3074 { 3075 rc = i_startThread(pTask); 3076 3077 if (SUCCEEDED(rc)) 3078 pProgress.queryInterfaceTo(aProgress.asOutParam()); 3079 } 3080 else 3081 { 3082 if (pTask != NULL) 3083 delete pTask; 3084 } 3085 3086 return rc; 2915 3087 } 2916 3088 … … 6099 6271 } 6100 6272 6273 /** 6274 * Preparation to move this medium to a new location 6275 * 6276 * @param aLocation Location of the storage unit. If the location is a FS-path, 6277 * then it can be relative to the VirtualBox home directory. 6278 * 6279 * @note Must be called from under this object's write lock. 6280 */ 6281 HRESULT Medium::i_preparationForMoving(const Utf8Str &aLocation) 6282 { 6283 HRESULT rc = E_FAIL; 6284 6285 if (i_getLocationFull() != aLocation) 6286 { 6287 m->strNewLocationFull = aLocation; 6288 m->fMoveThisMedium = true; 6289 rc = S_OK; 6290 } 6291 6292 return rc; 6293 } 6294 6295 /** 6296 * Checking whether current operation "moving" or not 6297 */ 6298 bool Medium::i_isMoveOperation(const ComObjPtr<Medium> &aTarget) const 6299 { 6300 return (this == aTarget && m->fMoveThisMedium == true) ? true:false; 6301 } 6302 6303 bool Medium::i_resetMoveOperationData() 6304 { 6305 m->strNewLocationFull.setNull(); 6306 m->fMoveThisMedium = false; 6307 return true; 6308 } 6309 6310 Utf8Str Medium::i_getNewLocationForMoving() const 6311 { 6312 if(m->fMoveThisMedium == true) 6313 return m->strNewLocationFull; 6314 else 6315 return Utf8Str(); 6316 } 6101 6317 //////////////////////////////////////////////////////////////////////////////// 6102 6318 // … … 8220 8436 { 8221 8437 if (!pParent.isNull()) 8438 { 8439 8222 8440 if (pParent->i_getDepth() >= SETTINGS_MEDIUM_DEPTH_MAX) 8223 8441 { … … 8227 8445 pParent->m->strLocationFull.c_str()); 8228 8446 } 8447 } 8229 8448 8230 8449 /* Lock all in {parent,child} order. The lock is also used as a … … 8520 8739 8521 8740 /** 8741 * Implementation code for the "move" task. 8742 * 8743 * This only gets started from Medium::SetLocation() and always 8744 * runs asynchronously. 8745 * 8746 * @param task 8747 * @return 8748 */ 8749 HRESULT Medium::i_taskMoveHandler(Medium::MoveTask &task) 8750 { 8751 8752 HRESULT rcOut = S_OK; 8753 8754 /* pTarget is equal "this" in our case */ 8755 const ComObjPtr<Medium> &pTarget = task.mMedium; 8756 8757 uint64_t size = 0, logicalSize = 0; 8758 MediumVariant_T variant = MediumVariant_Standard; 8759 8760 /* 8761 * it's exactly moving, not cloning 8762 */ 8763 if (!i_isMoveOperation(pTarget)) 8764 { 8765 HRESULT rc = setError(VBOX_E_FILE_ERROR, 8766 tr("Wrong preconditions for moving the medium %s"), 8767 pTarget->m->strLocationFull.c_str()); 8768 return rc; 8769 } 8770 8771 try 8772 { 8773 /* Lock all in {parent,child} order. The lock is also used as a 8774 * signal from the task initiator (which releases it only after 8775 * RTThreadCreate()) that we can start the job. */ 8776 8777 AutoWriteLock thisLock(this COMMA_LOCKVAL_SRC_POS); 8778 8779 PVBOXHDD hdd; 8780 int vrc = VDCreate(m->vdDiskIfaces, i_convertDeviceType(), &hdd); 8781 ComAssertRCThrow(vrc, E_FAIL); 8782 8783 try 8784 { 8785 /* Open all media in the source chain. */ 8786 MediumLockList::Base::const_iterator sourceListBegin = 8787 task.mpMediumLockList->GetBegin(); 8788 MediumLockList::Base::const_iterator sourceListEnd = 8789 task.mpMediumLockList->GetEnd(); 8790 for (MediumLockList::Base::const_iterator it = sourceListBegin; 8791 it != sourceListEnd; 8792 ++it) 8793 { 8794 const MediumLock &mediumLock = *it; 8795 const ComObjPtr<Medium> &pMedium = mediumLock.GetMedium(); 8796 AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS); 8797 8798 /* sanity check */ 8799 Assert(pMedium->m->state == MediumState_LockedWrite); 8800 8801 vrc = VDOpen(hdd, 8802 pMedium->m->strFormat.c_str(), 8803 pMedium->m->strLocationFull.c_str(), 8804 VD_OPEN_FLAGS_NORMAL, 8805 pMedium->m->vdImageIfaces); 8806 if (RT_FAILURE(vrc)) 8807 throw setError(VBOX_E_FILE_ERROR, 8808 tr("Could not open the medium storage unit '%s'%s"), 8809 pMedium->m->strLocationFull.c_str(), 8810 i_vdError(vrc).c_str()); 8811 } 8812 8813 /* we can directly use pTarget->m->"variables" but for better reading we use local copies */ 8814 Guid targetId = pTarget->m->id; 8815 Utf8Str targetFormat(pTarget->m->strFormat); 8816 uint64_t targetCapabilities = pTarget->m->formatObj->i_getCapabilities(); 8817 8818 /* 8819 * change target location 8820 * m->strNewLocationFull has been set already together with m->fMoveThisMedium in 8821 * i_preparationForMoving() 8822 */ 8823 Utf8Str targetLocation = i_getNewLocationForMoving(); 8824 8825 /* unlock before the potentially lengthy operation */ 8826 thisLock.release(); 8827 8828 /* ensure the target directory exists */ 8829 if (targetCapabilities & MediumFormatCapabilities_File) 8830 { 8831 HRESULT rc = VirtualBox::i_ensureFilePathExists(targetLocation, 8832 !(task.mVariant & MediumVariant_NoCreateDir) /* fCreate */); 8833 if (FAILED(rc)) 8834 throw rc; 8835 } 8836 8837 try 8838 { 8839 vrc = VDCopy(hdd, 8840 VD_LAST_IMAGE, 8841 hdd, 8842 targetFormat.c_str(), 8843 targetLocation.c_str(), 8844 true /* fMoveByRename */, 8845 0 /* cbSize */, 8846 VD_IMAGE_FLAGS_NONE, 8847 targetId.raw(), 8848 VD_OPEN_FLAGS_NORMAL, 8849 NULL /* pVDIfsOperation */, 8850 NULL, 8851 NULL); 8852 if (RT_FAILURE(vrc)) 8853 throw setError(VBOX_E_FILE_ERROR, 8854 tr("Could not move medium '%s'%s"), 8855 targetLocation.c_str(), i_vdError(vrc).c_str()); 8856 size = VDGetFileSize(hdd, VD_LAST_IMAGE); 8857 logicalSize = VDGetSize(hdd, VD_LAST_IMAGE); 8858 unsigned uImageFlags; 8859 vrc = VDGetImageFlags(hdd, 0, &uImageFlags); 8860 if (RT_SUCCESS(vrc)) 8861 variant = (MediumVariant_T)uImageFlags; 8862 8863 /* 8864 * set current location, because VDCopy\VDCopyEx doesn't do it. 8865 * also reset moving flag 8866 */ 8867 i_resetMoveOperationData(); 8868 m->strLocationFull = targetLocation; 8869 8870 } 8871 catch (HRESULT aRC) { rcOut = aRC; } 8872 8873 } 8874 catch (HRESULT aRC) { rcOut = aRC; } 8875 8876 VDDestroy(hdd); 8877 } 8878 catch (HRESULT aRC) { rcOut = aRC; } 8879 8880 ErrorInfoKeeper eik; 8881 MultiResult mrc(rcOut); 8882 8883 // now, at the end of this task (always asynchronous), save the settings 8884 if (SUCCEEDED(mrc)) 8885 { 8886 // save the settings 8887 i_markRegistriesModified(); 8888 /* collect multiple errors */ 8889 eik.restore(); 8890 m->pVirtualBox->i_saveModifiedRegistries(); 8891 eik.fetch(); 8892 } 8893 8894 /* Everything is explicitly unlocked when the task exits, 8895 * as the task destruction also destroys the source chain. */ 8896 8897 task.mpMediumLockList->Clear(); 8898 8899 return mrc; 8900 } 8901 8902 /** 8522 8903 * Implementation code for the "delete" task. 8523 8904 *
Note:
See TracChangeset
for help on using the changeset viewer.