VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/StorageControllerImpl.cpp@ 57415

Last change on this file since 57415 was 56820, checked in by vboxsync, 9 years ago

Main/StorageController: Fix storage controller renaming, it needs updating all corresponding attachments (otherwise they get instantly lost). Also eliminates some Utf8Str/Bstr conversions, and a bit of whitespace cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.8 KB
Line 
1/* $Id: StorageControllerImpl.cpp 56820 2015-07-06 15:05:40Z vboxsync $ */
2
3/** @file
4 *
5 * Implementation of IStorageController.
6 */
7
8/*
9 * Copyright (C) 2008-2015 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#include "StorageControllerImpl.h"
21#include "MachineImpl.h"
22#include "VirtualBoxImpl.h"
23#include "SystemPropertiesImpl.h"
24
25#include <iprt/string.h>
26#include <iprt/cpp/utils.h>
27
28#include <VBox/err.h>
29#include <VBox/settings.h>
30
31#include <algorithm>
32
33#include "AutoStateDep.h"
34#include "AutoCaller.h"
35#include "Logging.h"
36
37// defines
38/////////////////////////////////////////////////////////////////////////////
39//
40//
41DEFINE_EMPTY_CTOR_DTOR(StorageController)
42
43struct BackupableStorageControllerData
44{
45 /* Constructor. */
46 BackupableStorageControllerData()
47 : mStorageBus(StorageBus_IDE),
48 mStorageControllerType(StorageControllerType_PIIX4),
49 mInstance(0),
50 mPortCount(2),
51 fUseHostIOCache(true),
52 fBootable(false)
53 { }
54
55 /** Unique name of the storage controller. */
56 Utf8Str strName;
57 /** The connection type of the storage controller. */
58 StorageBus_T mStorageBus;
59 /** Type of the Storage controller. */
60 StorageControllerType_T mStorageControllerType;
61 /** Instance number of the storage controller. */
62 ULONG mInstance;
63 /** Number of usable ports. */
64 ULONG mPortCount;
65 /** Whether to use the host IO caches. */
66 BOOL fUseHostIOCache;
67 /** Whether it is possible to boot from disks attached to this controller. */
68 BOOL fBootable;
69};
70
71struct StorageController::Data
72{
73 Data(Machine * const aMachine)
74 : pVirtualBox(NULL),
75 pSystemProperties(NULL),
76 pParent(aMachine)
77 {
78 unconst(pVirtualBox) = aMachine->i_getVirtualBox();
79 unconst(pSystemProperties) = pVirtualBox->i_getSystemProperties();
80 }
81
82 VirtualBox * const pVirtualBox;
83 SystemProperties * const pSystemProperties;
84 Machine * const pParent;
85 const ComObjPtr<StorageController> pPeer;
86
87 Backupable<BackupableStorageControllerData> bd;
88};
89
90
91// constructor / destructor
92/////////////////////////////////////////////////////////////////////////////
93
94HRESULT StorageController::FinalConstruct()
95{
96 return BaseFinalConstruct();
97}
98
99void StorageController::FinalRelease()
100{
101 uninit();
102 BaseFinalRelease();
103}
104
105// public initializer/uninitializer for internal purposes only
106/////////////////////////////////////////////////////////////////////////////
107
108/**
109 * Initializes the storage controller object.
110 *
111 * @returns COM result indicator.
112 * @param aParent Pointer to our parent object.
113 * @param aName Name of the storage controller.
114 * @param aInstance Instance number of the storage controller.
115 */
116HRESULT StorageController::init(Machine *aParent,
117 const Utf8Str &aName,
118 StorageBus_T aStorageBus,
119 ULONG aInstance, bool fBootable)
120{
121 LogFlowThisFunc(("aParent=%p aName=\"%s\" aInstance=%u\n",
122 aParent, aName.c_str(), aInstance));
123
124 ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
125 if ( (aStorageBus <= StorageBus_Null)
126 || (aStorageBus > StorageBus_USB))
127 return setError(E_INVALIDARG,
128 tr("Invalid storage connection type"));
129
130 ULONG maxInstances;
131 ChipsetType_T chipsetType;
132 HRESULT rc = aParent->COMGETTER(ChipsetType)(&chipsetType);
133 if (FAILED(rc))
134 return rc;
135 rc = aParent->i_getVirtualBox()->i_getSystemProperties()->
136 GetMaxInstancesOfStorageBus(chipsetType, aStorageBus, &maxInstances);
137 if (FAILED(rc))
138 return rc;
139 if (aInstance >= maxInstances)
140 return setError(E_INVALIDARG,
141 tr("Too many storage controllers of this type"));
142
143 /* Enclose the state transition NotReady->InInit->Ready */
144 AutoInitSpan autoInitSpan(this);
145 AssertReturn(autoInitSpan.isOk(), E_FAIL);
146
147 m = new Data(aParent);
148
149 /* m->pPeer is left null */
150
151 m->bd.allocate();
152
153 m->bd->strName = aName;
154 m->bd->mInstance = aInstance;
155 m->bd->fBootable = fBootable;
156 m->bd->mStorageBus = aStorageBus;
157 if ( aStorageBus != StorageBus_IDE
158 && aStorageBus != StorageBus_Floppy)
159 m->bd->fUseHostIOCache = false;
160 else
161 m->bd->fUseHostIOCache = true;
162
163 switch (aStorageBus)
164 {
165 case StorageBus_IDE:
166 m->bd->mPortCount = 2;
167 m->bd->mStorageControllerType = StorageControllerType_PIIX4;
168 break;
169 case StorageBus_SATA:
170 m->bd->mPortCount = 30;
171 m->bd->mStorageControllerType = StorageControllerType_IntelAhci;
172 break;
173 case StorageBus_SCSI:
174 m->bd->mPortCount = 16;
175 m->bd->mStorageControllerType = StorageControllerType_LsiLogic;
176 break;
177 case StorageBus_Floppy:
178 m->bd->mPortCount = 1;
179 m->bd->mStorageControllerType = StorageControllerType_I82078;
180 break;
181 case StorageBus_SAS:
182 m->bd->mPortCount = 8;
183 m->bd->mStorageControllerType = StorageControllerType_LsiLogicSas;
184 case StorageBus_USB:
185 m->bd->mPortCount = 8;
186 m->bd->mStorageControllerType = StorageControllerType_USB;
187 break;
188 }
189
190 /* Confirm a successful initialization */
191 autoInitSpan.setSucceeded();
192
193 return S_OK;
194}
195
196/**
197 * Initializes the object given another object
198 * (a kind of copy constructor). This object shares data with
199 * the object passed as an argument.
200 *
201 * @param aReshare
202 * When false, the original object will remain a data owner.
203 * Otherwise, data ownership will be transferred from the original
204 * object to this one.
205 *
206 * @note This object must be destroyed before the original object
207 * it shares data with is destroyed.
208 *
209 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
210 * reading if @a aReshare is false.
211 */
212HRESULT StorageController::init(Machine *aParent,
213 StorageController *aThat,
214 bool aReshare /* = false */)
215{
216 LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
217 aParent, aThat, aReshare));
218
219 ComAssertRet(aParent && aThat, E_INVALIDARG);
220
221 /* Enclose the state transition NotReady->InInit->Ready */
222 AutoInitSpan autoInitSpan(this);
223 AssertReturn(autoInitSpan.isOk(), E_FAIL);
224
225 m = new Data(aParent);
226
227 /* sanity */
228 AutoCaller thatCaller(aThat);
229 AssertComRCReturnRC(thatCaller.rc());
230
231 if (aReshare)
232 {
233 AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
234
235 unconst(aThat->m->pPeer) = this;
236 m->bd.attach(aThat->m->bd);
237 }
238 else
239 {
240 unconst(m->pPeer) = aThat;
241
242 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
243 m->bd.share(aThat->m->bd);
244 }
245
246 /* Confirm successful initialization */
247 autoInitSpan.setSucceeded();
248
249 return S_OK;
250}
251
252/**
253 * Initializes the storage controller object given another guest object
254 * (a kind of copy constructor). This object makes a private copy of data
255 * of the original object passed as an argument.
256 */
257HRESULT StorageController::initCopy(Machine *aParent, StorageController *aThat)
258{
259 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
260
261 ComAssertRet(aParent && aThat, E_INVALIDARG);
262
263 /* Enclose the state transition NotReady->InInit->Ready */
264 AutoInitSpan autoInitSpan(this);
265 AssertReturn(autoInitSpan.isOk(), E_FAIL);
266
267 m = new Data(aParent);
268 /* m->pPeer is left null */
269
270 AutoCaller thatCaller(aThat);
271 AssertComRCReturnRC(thatCaller.rc());
272
273 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
274 m->bd.attachCopy(aThat->m->bd);
275
276 /* Confirm a successful initialization */
277 autoInitSpan.setSucceeded();
278
279 return S_OK;
280}
281
282
283/**
284 * Uninitializes the instance and sets the ready flag to FALSE.
285 * Called either from FinalRelease() or by the parent when it gets destroyed.
286 */
287void StorageController::uninit()
288{
289 LogFlowThisFunc(("\n"));
290
291 /* Enclose the state transition Ready->InUninit->NotReady */
292 AutoUninitSpan autoUninitSpan(this);
293 if (autoUninitSpan.uninitDone())
294 return;
295
296 m->bd.free();
297
298 unconst(m->pPeer) = NULL;
299 unconst(m->pParent) = NULL;
300
301 delete m;
302 m = NULL;
303}
304
305
306// IStorageController properties
307HRESULT StorageController::getName(com::Utf8Str &aName)
308{
309 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
310
311 aName = m->bd->strName;
312
313 return S_OK;
314}
315
316HRESULT StorageController::setName(const com::Utf8Str &aName)
317{
318 /* the machine needs to be mutable */
319 AutoMutableStateDependency adep(m->pParent);
320 if (FAILED(adep.rc())) return adep.rc();
321
322 AutoMultiWriteLock2 alock(m->pParent, this COMMA_LOCKVAL_SRC_POS);
323
324 if (m->bd->strName != aName)
325 {
326 ComObjPtr<StorageController> ctrl;
327 HRESULT rc = m->pParent->i_getStorageControllerByName(aName, ctrl, false /* aSetError */);
328 if (SUCCEEDED(rc))
329 return setError(VBOX_E_OBJECT_IN_USE,
330 tr("Storage controller named '%s' already exists"),
331 aName.c_str());
332
333 Machine::MediaData::AttachmentList atts;
334 rc = m->pParent->i_getMediumAttachmentsOfController(m->bd->strName, atts);
335 for (Machine::MediaData::AttachmentList::const_iterator it = atts.begin();
336 it != atts.end();
337 ++it)
338 {
339 IMediumAttachment *iA = *it;
340 MediumAttachment *pAttach = static_cast<MediumAttachment *>(iA);
341 AutoWriteLock attlock(pAttach COMMA_LOCKVAL_SRC_POS);
342 pAttach->i_updateName(aName);
343 }
344
345
346 m->bd.backup();
347 m->bd->strName = aName;
348
349 m->pParent->i_setModified(Machine::IsModified_Storage);
350 alock.release();
351
352 m->pParent->i_onStorageControllerChange();
353 }
354
355 return S_OK;
356}
357
358HRESULT StorageController::getBus(StorageBus_T *aBus)
359{
360 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
361
362 *aBus = m->bd->mStorageBus;
363
364 return S_OK;
365}
366
367HRESULT StorageController::getControllerType(StorageControllerType_T *aControllerType)
368{
369 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
370
371 *aControllerType = m->bd->mStorageControllerType;
372
373 return S_OK;
374}
375
376HRESULT StorageController::setControllerType(StorageControllerType_T aControllerType)
377{
378 /* the machine needs to be mutable */
379 AutoMutableStateDependency adep(m->pParent);
380 if (FAILED(adep.rc())) return adep.rc();
381
382 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
383
384 HRESULT rc = S_OK;
385
386 switch (m->bd->mStorageBus)
387 {
388 case StorageBus_IDE:
389 {
390 if ( (aControllerType != StorageControllerType_PIIX3)
391 && (aControllerType != StorageControllerType_PIIX4)
392 && (aControllerType != StorageControllerType_ICH6))
393 rc = E_INVALIDARG;
394 break;
395 }
396 case StorageBus_SATA:
397 {
398 if (aControllerType != StorageControllerType_IntelAhci)
399 rc = E_INVALIDARG;
400 break;
401 }
402 case StorageBus_SCSI:
403 {
404 if ( (aControllerType != StorageControllerType_LsiLogic)
405 && (aControllerType != StorageControllerType_BusLogic))
406 rc = E_INVALIDARG;
407 break;
408 }
409 case StorageBus_Floppy:
410 {
411 if (aControllerType != StorageControllerType_I82078)
412 rc = E_INVALIDARG;
413 break;
414 }
415 case StorageBus_SAS:
416 {
417 if (aControllerType != StorageControllerType_LsiLogicSas)
418 rc = E_INVALIDARG;
419 break;
420 }
421 case StorageBus_USB:
422 {
423 if (aControllerType != StorageControllerType_USB)
424 rc = E_INVALIDARG;
425 break;
426 }
427 default:
428 AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
429 rc = E_INVALIDARG;
430 }
431
432 if (!SUCCEEDED(rc))
433 return setError(rc,
434 tr("Invalid controller type %d"),
435 aControllerType);
436
437 if (m->bd->mStorageControllerType != aControllerType)
438 {
439 m->bd.backup();
440 m->bd->mStorageControllerType = aControllerType;
441
442 alock.release();
443 AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS); // m->pParent is const, needs no locking
444 m->pParent->i_setModified(Machine::IsModified_Storage);
445 mlock.release();
446
447 m->pParent->i_onStorageControllerChange();
448 }
449
450 return S_OK;
451}
452
453HRESULT StorageController::getMaxDevicesPerPortCount(ULONG *aMaxDevicesPerPortCount)
454{
455 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
456
457 HRESULT rc = m->pSystemProperties->GetMaxDevicesPerPortForStorageBus(m->bd->mStorageBus, aMaxDevicesPerPortCount);
458
459 return rc;
460}
461
462HRESULT StorageController::getMinPortCount(ULONG *aMinPortCount)
463{
464 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
465
466 HRESULT rc = m->pSystemProperties->GetMinPortCountForStorageBus(m->bd->mStorageBus, aMinPortCount);
467 return rc;
468}
469
470HRESULT StorageController::getMaxPortCount(ULONG *aMaxPortCount)
471{
472 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
473 HRESULT rc = m->pSystemProperties->GetMaxPortCountForStorageBus(m->bd->mStorageBus, aMaxPortCount);
474
475 return rc;
476}
477
478HRESULT StorageController::getPortCount(ULONG *aPortCount)
479{
480 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
481
482 *aPortCount = m->bd->mPortCount;
483
484 return S_OK;
485}
486
487HRESULT StorageController::setPortCount(ULONG aPortCount)
488{
489 /* the machine needs to be mutable */
490 AutoMutableStateDependency adep(m->pParent);
491 if (FAILED(adep.rc())) return adep.rc();
492
493 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
494
495 switch (m->bd->mStorageBus)
496 {
497 case StorageBus_SATA:
498 {
499 /* AHCI SATA supports a maximum of 30 ports. */
500 if (aPortCount < 1 || aPortCount > 30)
501 return setError(E_INVALIDARG,
502 tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
503 aPortCount, 1, 30);
504 break;
505 }
506 case StorageBus_SCSI:
507 {
508 /*
509 * SCSI does not support setting different ports.
510 * (doesn't make sense here either).
511 * The maximum and minimum is 16 and unless the callee
512 * tries to set a different value we return an error.
513 */
514 if (aPortCount != 16)
515 return setError(E_INVALIDARG,
516 tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
517 aPortCount, 16, 16);
518 break;
519 }
520 case StorageBus_IDE:
521 {
522 /*
523 * The port count is fixed to 2.
524 */
525 if (aPortCount != 2)
526 return setError(E_INVALIDARG,
527 tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
528 aPortCount, 2, 2);
529 break;
530 }
531 case StorageBus_Floppy:
532 {
533 /*
534 * The port count is fixed to 1.
535 */
536 if (aPortCount != 1)
537 return setError(E_INVALIDARG,
538 tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
539 aPortCount, 1, 1);
540 break;
541 }
542 case StorageBus_SAS:
543 {
544 /* SAS supports a maximum of 255 ports. */
545 if (aPortCount < 1 || aPortCount > 255)
546 return setError(E_INVALIDARG,
547 tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
548 aPortCount, 1, 255);
549 break;
550 }
551 case StorageBus_USB:
552 {
553 /*
554 * The port count is fixed to 8.
555 */
556 if (aPortCount != 8)
557 return setError(E_INVALIDARG,
558 tr("Invalid port count: %lu (must be in range [%lu, %lu])"),
559 aPortCount, 8, 8);
560 break;
561 }
562 default:
563 AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
564 }
565
566 if (m->bd->mPortCount != aPortCount)
567 {
568 m->bd.backup();
569 m->bd->mPortCount = aPortCount;
570
571 alock.release();
572 AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS); // m->pParent is const, needs no locking
573 m->pParent->i_setModified(Machine::IsModified_Storage);
574 mlock.release();
575
576 m->pParent->i_onStorageControllerChange();
577 }
578
579 return S_OK;
580}
581
582HRESULT StorageController::getInstance(ULONG *aInstance)
583{
584 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
585
586 *aInstance = m->bd->mInstance;
587
588 return S_OK;
589}
590
591HRESULT StorageController::setInstance(ULONG aInstance)
592{
593 /* the machine needs to be mutable */
594 AutoMutableStateDependency adep(m->pParent);
595 if (FAILED(adep.rc())) return adep.rc();
596
597 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
598
599 if (m->bd->mInstance != aInstance)
600 {
601 m->bd.backup();
602 m->bd->mInstance = aInstance;
603
604 alock.release();
605 AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS); // m->pParent is const, needs no locking
606 m->pParent->i_setModified(Machine::IsModified_Storage);
607 mlock.release();
608
609 m->pParent->i_onStorageControllerChange();
610 }
611
612 return S_OK;
613}
614
615HRESULT StorageController::getUseHostIOCache(BOOL *fUseHostIOCache)
616{
617 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
618
619 *fUseHostIOCache = m->bd->fUseHostIOCache;
620
621 return S_OK;
622}
623
624HRESULT StorageController::setUseHostIOCache(BOOL fUseHostIOCache)
625{
626 /* the machine needs to be mutable */
627 AutoMutableStateDependency adep(m->pParent);
628 if (FAILED(adep.rc())) return adep.rc();
629
630 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
631
632 if (m->bd->fUseHostIOCache != !!fUseHostIOCache)
633 {
634 m->bd.backup();
635 m->bd->fUseHostIOCache = !!fUseHostIOCache;
636
637 alock.release();
638 AutoWriteLock mlock(m->pParent COMMA_LOCKVAL_SRC_POS); // m->pParent is const, needs no locking
639 m->pParent->i_setModified(Machine::IsModified_Storage);
640 mlock.release();
641
642 m->pParent->i_onStorageControllerChange();
643 }
644
645 return S_OK;
646}
647
648HRESULT StorageController::getBootable(BOOL *fBootable)
649{
650 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
651
652 *fBootable = m->bd->fBootable;
653
654 return S_OK;
655}
656
657// public methods only for internal purposes
658/////////////////////////////////////////////////////////////////////////////
659
660const Utf8Str& StorageController::i_getName() const
661{
662 return m->bd->strName;
663}
664
665StorageControllerType_T StorageController::i_getControllerType() const
666{
667 return m->bd->mStorageControllerType;
668}
669
670StorageBus_T StorageController::i_getStorageBus() const
671{
672 return m->bd->mStorageBus;
673}
674
675ULONG StorageController::i_getInstance() const
676{
677 return m->bd->mInstance;
678}
679
680bool StorageController::i_getBootable() const
681{
682 return !!m->bd->fBootable;
683}
684
685/**
686 * Returns S_OK if the given port and device numbers are within the range supported
687 * by this controller. If not, it sets an error and returns E_INVALIDARG.
688 * @param ulPort
689 * @param ulDevice
690 * @return
691 */
692HRESULT StorageController::i_checkPortAndDeviceValid(LONG aControllerPort,
693 LONG aDevice)
694{
695 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
696
697 ULONG portCount = m->bd->mPortCount;
698 ULONG devicesPerPort;
699 HRESULT rc = m->pSystemProperties->GetMaxDevicesPerPortForStorageBus(m->bd->mStorageBus, &devicesPerPort);
700 if (FAILED(rc)) return rc;
701
702 if ( aControllerPort < 0
703 || aControllerPort >= (LONG)portCount
704 || aDevice < 0
705 || aDevice >= (LONG)devicesPerPort
706 )
707 return setError(E_INVALIDARG,
708 tr("The port and/or device parameter are out of range: port=%d (must be in range [0, %d]), device=%d (must be in range [0, %d])"),
709 (int)aControllerPort, (int)portCount-1, (int)aDevice, (int)devicesPerPort-1);
710
711 return S_OK;
712}
713
714/** @note Locks objects for writing! */
715void StorageController::i_setBootable(BOOL fBootable)
716{
717 AutoCaller autoCaller(this);
718 AssertComRCReturnVoid(autoCaller.rc());
719
720 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
721
722 m->bd.backup();
723 m->bd->fBootable = fBootable;
724}
725
726/** @note Locks objects for writing! */
727void StorageController::i_rollback()
728{
729 AutoCaller autoCaller(this);
730 AssertComRCReturnVoid(autoCaller.rc());
731
732 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
733
734 m->bd.rollback();
735}
736
737/**
738 * @note Locks this object for writing, together with the peer object (also
739 * for writing) if there is one.
740 */
741void StorageController::i_commit()
742{
743 /* sanity */
744 AutoCaller autoCaller(this);
745 AssertComRCReturnVoid(autoCaller.rc());
746
747 /* sanity too */
748 AutoCaller peerCaller(m->pPeer);
749 AssertComRCReturnVoid(peerCaller.rc());
750
751 /* lock both for writing since we modify both (m->pPeer is "master" so locked
752 * first) */
753 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
754
755 if (m->bd.isBackedUp())
756 {
757 m->bd.commit();
758 if (m->pPeer)
759 {
760 // attach new data to the peer and reshare it
761 m->pPeer->m->bd.attach(m->bd);
762 }
763 }
764}
765
766/**
767 * Cancels sharing (if any) by making an independent copy of data.
768 * This operation also resets this object's peer to NULL.
769 *
770 * @note Locks this object for writing, together with the peer object
771 * represented by @a aThat (locked for reading).
772 */
773void StorageController::i_unshare()
774{
775 /* sanity */
776 AutoCaller autoCaller(this);
777 AssertComRCReturnVoid(autoCaller.rc());
778
779 /* sanity too */
780 AutoCaller peerCaller(m->pPeer);
781 AssertComRCReturnVoid(peerCaller.rc());
782
783 /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
784 * first) */
785 AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
786 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
787
788 if (m->bd.isShared())
789 {
790 if (!m->bd.isBackedUp())
791 m->bd.backup();
792
793 m->bd.commit();
794 }
795
796 unconst(m->pPeer) = NULL;
797}
798
799Machine* StorageController::i_getMachine()
800{
801 return m->pParent;
802}
803
804ComObjPtr<StorageController> StorageController::i_getPeer()
805{
806 return m->pPeer;
807}
808
809// private methods
810/////////////////////////////////////////////////////////////////////////////
811
812
813/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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