VirtualBox

source: vbox/trunk/src/VBox/Main/StorageControllerImpl.cpp@ 26156

Last change on this file since 26156 was 26156, checked in by vboxsync, 15 years ago

Main: get rid of isReallyChanged() voodoo in Machine and subclasses; instead check in the XML classes whether things really changed via operator==; documentation, cleanup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 KB
Line 
1/* $Id: StorageControllerImpl.cpp 26156 2010-02-02 16:30:28Z vboxsync $ */
2
3/** @file
4 *
5 * Implementation of IStorageController.
6 */
7
8/*
9 * Copyright (C) 2008-2009 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.215389.xyz. 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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#include "StorageControllerImpl.h"
25#include "MachineImpl.h"
26#include "VirtualBoxImpl.h"
27
28#include <iprt/string.h>
29#include <iprt/cpp/utils.h>
30
31#include <VBox/err.h>
32#include <VBox/settings.h>
33
34#include <algorithm>
35
36#include "AutoStateDep.h"
37#include "AutoCaller.h"
38#include "Logging.h"
39
40// defines
41/////////////////////////////////////////////////////////////////////////////
42
43struct BackupableStorageControllerData
44{
45 /* Constructor. */
46 BackupableStorageControllerData()
47 : mStorageBus(StorageBus_IDE),
48 mStorageControllerType(StorageControllerType_PIIX4),
49 mInstance(0),
50 mPortCount(2),
51 mPortIde0Master(0),
52 mPortIde0Slave(1),
53 mPortIde1Master(2),
54 mPortIde1Slave(3)
55 { }
56
57 bool operator==(const BackupableStorageControllerData &that) const
58 {
59 return this == &that
60 || ( (mStorageControllerType == that.mStorageControllerType)
61 && (strName == that.strName)
62 && (mPortCount == that.mPortCount)
63 && (mPortIde0Master == that.mPortIde0Master)
64 && (mPortIde0Slave == that.mPortIde0Slave)
65 && (mPortIde1Master == that.mPortIde1Master)
66 && (mPortIde1Slave == that.mPortIde1Slave));
67 }
68
69 /** Unique name of the storage controller. */
70 Utf8Str strName;
71 /** The connection type of thestorage controller. */
72 StorageBus_T mStorageBus;
73 /** Type of the Storage controller. */
74 StorageControllerType_T mStorageControllerType;
75 /** Instance number of the storage controller. */
76 ULONG mInstance;
77 /** Number of usable ports. */
78 ULONG mPortCount;
79
80 /** The following is only for the SATA controller atm. */
81 /** Port which acts as primary master for ide emulation. */
82 ULONG mPortIde0Master;
83 /** Port which acts as primary slave for ide emulation. */
84 ULONG mPortIde0Slave;
85 /** Port which acts as secondary master for ide emulation. */
86 ULONG mPortIde1Master;
87 /** Port which acts as secondary slave for ide emulation. */
88 ULONG mPortIde1Slave;
89};
90
91struct StorageController::Data
92{
93 Data()
94 { }
95
96 const ComObjPtr<Machine, ComWeakRef> pParent;
97 const ComObjPtr<StorageController> pPeer;
98
99 Backupable<BackupableStorageControllerData> bd;
100};
101
102// constructor / destructor
103/////////////////////////////////////////////////////////////////////////////
104
105HRESULT StorageController::FinalConstruct()
106{
107 return S_OK;
108}
109
110void StorageController::FinalRelease()
111{
112 uninit();
113}
114
115// public initializer/uninitializer for internal purposes only
116/////////////////////////////////////////////////////////////////////////////
117
118/**
119 * Initializes the storage controller object.
120 *
121 * @returns COM result indicator.
122 * @param aParent Pointer to our parent object.
123 * @param aName Name of the storage controller.
124 * @param aInstance Instance number of the storage controller.
125 */
126HRESULT StorageController::init(Machine *aParent,
127 const Utf8Str &aName,
128 StorageBus_T aStorageBus,
129 ULONG aInstance)
130{
131 LogFlowThisFunc(("aParent=%p aName=\"%s\" aInstance=%u\n",
132 aParent, aName.raw(), aInstance));
133
134 ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
135 if ( (aStorageBus <= StorageBus_Null)
136 || (aStorageBus > StorageBus_SAS))
137 return setError (E_INVALIDARG,
138 tr ("Invalid storage connection type"));
139
140 /* Enclose the state transition NotReady->InInit->Ready */
141 AutoInitSpan autoInitSpan(this);
142 AssertReturn(autoInitSpan.isOk(), E_FAIL);
143
144 m = new Data();
145
146 unconst(m->pParent) = aParent;
147 /* m->pPeer is left null */
148
149 /* register with parent early, since uninit() will unconditionally
150 * unregister on failure */
151 m->pParent->addDependentChild (this);
152
153 m->bd.allocate();
154
155 m->bd->strName = aName;
156 m->bd->mInstance = aInstance;
157 m->bd->mStorageBus = aStorageBus;
158
159 switch (aStorageBus)
160 {
161 case StorageBus_IDE:
162 m->bd->mPortCount = 2;
163 m->bd->mStorageControllerType = StorageControllerType_PIIX4;
164 break;
165 case StorageBus_SATA:
166 m->bd->mPortCount = 30;
167 m->bd->mStorageControllerType = StorageControllerType_IntelAhci;
168 break;
169 case StorageBus_SCSI:
170 m->bd->mPortCount = 16;
171 m->bd->mStorageControllerType = StorageControllerType_LsiLogic;
172 break;
173 case StorageBus_Floppy:
174 /** @todo allow 2 floppies later */
175 m->bd->mPortCount = 1;
176 m->bd->mStorageControllerType = StorageControllerType_I82078;
177 break;
178 case StorageBus_SAS:
179 m->bd->mPortCount = 8;
180 m->bd->mStorageControllerType = StorageControllerType_LsiLogicSas;
181 break;
182 }
183
184 /* Confirm a successful initialization */
185 autoInitSpan.setSucceeded();
186
187 return S_OK;
188}
189
190/**
191 * Initializes the object given another object
192 * (a kind of copy constructor). This object shares data with
193 * the object passed as an argument.
194 *
195 * @param aReshare
196 * When false, the original object will remain a data owner.
197 * Otherwise, data ownership will be transferred from the original
198 * object to this one.
199 *
200 * @note This object must be destroyed before the original object
201 * it shares data with is destroyed.
202 *
203 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
204 * reading if @a aReshare is false.
205 */
206HRESULT StorageController::init(Machine *aParent,
207 StorageController *aThat,
208 bool aReshare /* = false */)
209{
210 LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
211 aParent, aThat, aReshare));
212
213 ComAssertRet (aParent && aThat, E_INVALIDARG);
214
215 /* Enclose the state transition NotReady->InInit->Ready */
216 AutoInitSpan autoInitSpan(this);
217 AssertReturn(autoInitSpan.isOk(), E_FAIL);
218
219 m = new Data();
220
221 unconst(m->pParent) = aParent;
222
223 /* register with parent early, since uninit() will unconditionally
224 * unregister on failure */
225 m->pParent->addDependentChild (this);
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();
268
269 unconst(m->pParent) = aParent;
270 /* m->pPeer is left null */
271
272 m->pParent->addDependentChild (this);
273
274 AutoCaller thatCaller (aThat);
275 AssertComRCReturnRC(thatCaller.rc());
276
277 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
278 m->bd.attachCopy (aThat->m->bd);
279
280 /* Confirm a successful initialization */
281 autoInitSpan.setSucceeded();
282
283 return S_OK;
284}
285
286
287/**
288 * Uninitializes the instance and sets the ready flag to FALSE.
289 * Called either from FinalRelease() or by the parent when it gets destroyed.
290 */
291void StorageController::uninit()
292{
293 LogFlowThisFunc(("\n"));
294
295 /* Enclose the state transition Ready->InUninit->NotReady */
296 AutoUninitSpan autoUninitSpan(this);
297 if (autoUninitSpan.uninitDone())
298 return;
299
300 m->bd.free();
301
302 m->pParent->removeDependentChild (this);
303
304 unconst(m->pPeer).setNull();
305 unconst(m->pParent).setNull();
306
307 delete m;
308 m = NULL;
309}
310
311
312// IStorageController properties
313/////////////////////////////////////////////////////////////////////////////
314STDMETHODIMP StorageController::COMGETTER(Name) (BSTR *aName)
315{
316 CheckComArgOutPointerValid(aName);
317
318 AutoCaller autoCaller(this);
319 if (FAILED(autoCaller.rc())) return autoCaller.rc();
320
321 /* mName is constant during life time, no need to lock */
322 m->bd.data()->strName.cloneTo(aName);
323
324 return S_OK;
325}
326
327STDMETHODIMP StorageController::COMGETTER(Bus) (StorageBus_T *aBus)
328{
329 CheckComArgOutPointerValid(aBus);
330
331 AutoCaller autoCaller(this);
332 if (FAILED(autoCaller.rc())) return autoCaller.rc();
333
334 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
335
336 *aBus = m->bd->mStorageBus;
337
338 return S_OK;
339}
340
341STDMETHODIMP StorageController::COMGETTER(ControllerType) (StorageControllerType_T *aControllerType)
342{
343 CheckComArgOutPointerValid(aControllerType);
344
345 AutoCaller autoCaller(this);
346 if (FAILED(autoCaller.rc())) return autoCaller.rc();
347
348 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
349
350 *aControllerType = m->bd->mStorageControllerType;
351
352 return S_OK;
353}
354
355STDMETHODIMP StorageController::COMSETTER(ControllerType) (StorageControllerType_T aControllerType)
356{
357 AutoCaller autoCaller(this);
358 if (FAILED(autoCaller.rc())) return autoCaller.rc();
359
360 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
361
362 HRESULT rc = S_OK;
363
364 switch (m->bd->mStorageBus)
365 {
366 case StorageBus_IDE:
367 {
368 if ( (aControllerType != StorageControllerType_PIIX3)
369 && (aControllerType != StorageControllerType_PIIX4)
370 && (aControllerType != StorageControllerType_ICH6))
371 rc = E_INVALIDARG;
372 break;
373 }
374 case StorageBus_SATA:
375 {
376 if (aControllerType != StorageControllerType_IntelAhci)
377 rc = E_INVALIDARG;
378 break;
379 }
380 case StorageBus_SCSI:
381 {
382 if ( (aControllerType != StorageControllerType_LsiLogic)
383 && (aControllerType != StorageControllerType_BusLogic))
384 rc = E_INVALIDARG;
385 break;
386 }
387 case StorageBus_Floppy:
388 {
389 if (aControllerType != StorageControllerType_I82078)
390 rc = E_INVALIDARG;
391 break;
392 }
393 case StorageBus_SAS:
394 {
395 if (aControllerType != StorageControllerType_LsiLogicSas)
396 rc = E_INVALIDARG;
397 break;
398 }
399 default:
400 AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
401 }
402
403 if (!SUCCEEDED(rc))
404 return setError(rc,
405 tr ("Invalid controller type %d"),
406 aControllerType);
407
408 m->bd->mStorageControllerType = aControllerType;
409
410 return S_OK;
411}
412
413STDMETHODIMP StorageController::COMGETTER(MaxDevicesPerPortCount) (ULONG *aMaxDevices)
414{
415 CheckComArgOutPointerValid(aMaxDevices);
416
417 AutoCaller autoCaller(this);
418 if (FAILED(autoCaller.rc())) return autoCaller.rc();
419
420 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
421
422 ComPtr<IVirtualBox> VBox;
423 HRESULT rc = m->pParent->COMGETTER(Parent)(VBox.asOutParam());
424 if (FAILED(rc))
425 return rc;
426
427 ComPtr<ISystemProperties> sysProps;
428 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
429 if (FAILED(rc))
430 return rc;
431
432 rc = sysProps->GetMaxDevicesPerPortForStorageBus(m->bd->mStorageBus, aMaxDevices);
433 return rc;
434}
435
436STDMETHODIMP StorageController::COMGETTER(MinPortCount) (ULONG *aMinPortCount)
437{
438 CheckComArgOutPointerValid(aMinPortCount);
439
440 AutoCaller autoCaller(this);
441 if (FAILED(autoCaller.rc())) return autoCaller.rc();
442
443 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
444
445 ComPtr<IVirtualBox> VBox;
446 HRESULT rc = m->pParent->COMGETTER(Parent)(VBox.asOutParam());
447 if (FAILED(rc))
448 return rc;
449
450 ComPtr<ISystemProperties> sysProps;
451 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
452 if (FAILED(rc))
453 return rc;
454
455 rc = sysProps->GetMinPortCountForStorageBus(m->bd->mStorageBus, aMinPortCount);
456 return rc;
457}
458
459STDMETHODIMP StorageController::COMGETTER(MaxPortCount) (ULONG *aMaxPortCount)
460{
461 CheckComArgOutPointerValid(aMaxPortCount);
462
463 AutoCaller autoCaller(this);
464 if (FAILED(autoCaller.rc())) return autoCaller.rc();
465
466 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
467
468 ComPtr<IVirtualBox> VBox;
469 HRESULT rc = m->pParent->COMGETTER(Parent)(VBox.asOutParam());
470 if (FAILED(rc))
471 return rc;
472
473 ComPtr<ISystemProperties> sysProps;
474 rc = VBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
475 if (FAILED(rc))
476 return rc;
477
478 rc = sysProps->GetMaxPortCountForStorageBus(m->bd->mStorageBus, aMaxPortCount);
479 return rc;
480}
481
482
483STDMETHODIMP StorageController::COMGETTER(PortCount) (ULONG *aPortCount)
484{
485 CheckComArgOutPointerValid(aPortCount);
486
487 AutoCaller autoCaller(this);
488 if (FAILED(autoCaller.rc())) return autoCaller.rc();
489
490 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
491
492 *aPortCount = m->bd->mPortCount;
493
494 return S_OK;
495}
496
497
498STDMETHODIMP StorageController::COMSETTER(PortCount) (ULONG aPortCount)
499{
500 LogFlowThisFunc(("aPortCount=%u\n", aPortCount));
501
502 switch (m->bd->mStorageBus)
503 {
504 case StorageBus_SATA:
505 {
506 /* AHCI SATA supports a maximum of 30 ports. */
507 if ((aPortCount < 1) || (aPortCount > 30))
508 return setError (E_INVALIDARG,
509 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
510 aPortCount, 1, 30);
511 break;
512 }
513 case StorageBus_SCSI:
514 {
515 /*
516 * SCSI does not support setting different ports.
517 * (doesn't make sense here either).
518 * The maximum and minimum is 16 and unless the callee
519 * tries to set a different value we return an error.
520 */
521 if (aPortCount != 16)
522 return setError (E_INVALIDARG,
523 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
524 aPortCount, 16, 16);
525 break;
526 }
527 case StorageBus_IDE:
528 {
529 /*
530 * The port count is fixed to 2.
531 */
532 if (aPortCount != 2)
533 return setError (E_INVALIDARG,
534 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
535 aPortCount, 2, 2);
536 break;
537 }
538 case StorageBus_Floppy:
539 {
540 /** @todo allow 2 floppies later */
541 /*
542 * The port count is fixed to 1.
543 */
544 if (aPortCount != 1)
545 return setError (E_INVALIDARG,
546 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
547 aPortCount, 1, 1);
548 break;
549 }
550 case StorageBus_SAS:
551 {
552 /*
553 * The port count is fixed to 8.
554 */
555 if (aPortCount != 8)
556 return setError (E_INVALIDARG,
557 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
558 aPortCount, 8, 8);
559 break;
560 }
561 default:
562 AssertMsgFailed(("Invalid controller type %d\n", m->bd->mStorageBus));
563 }
564
565 AutoCaller autoCaller(this);
566 if (FAILED(autoCaller.rc())) return autoCaller.rc();
567
568 /* the machine needs to be mutable */
569 AutoMutableStateDependency adep(m->pParent);
570 if (FAILED(adep.rc())) return adep.rc();
571
572 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
573
574 if (m->bd->mPortCount != aPortCount)
575 {
576 m->bd.backup();
577 m->bd->mPortCount = aPortCount;
578
579 /* leave the lock for safety */
580 alock.leave();
581
582 m->pParent->onStorageControllerChange ();
583 }
584
585 return S_OK;
586}
587
588STDMETHODIMP StorageController::COMGETTER(Instance) (ULONG *aInstance)
589{
590 AutoCaller autoCaller(this);
591 if (FAILED(autoCaller.rc())) return autoCaller.rc();
592
593 /* The machine doesn't need to be mutable. */
594
595 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
596
597 *aInstance = m->bd->mInstance;
598
599 return S_OK;
600}
601
602STDMETHODIMP StorageController::COMSETTER(Instance) (ULONG aInstance)
603{
604 AutoCaller autoCaller(this);
605 if (FAILED(autoCaller.rc())) return autoCaller.rc();
606
607 /* The machine doesn't need to be mutable. */
608
609 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
610
611 m->bd->mInstance = aInstance;
612
613 return S_OK;
614}
615
616// IStorageController methods
617/////////////////////////////////////////////////////////////////////////////
618
619STDMETHODIMP StorageController::GetIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
620{
621 CheckComArgOutPointerValid(aPortNumber);
622
623 AutoCaller autoCaller(this);
624 if (FAILED(autoCaller.rc())) return autoCaller.rc();
625
626 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
627
628 if (m->bd->mStorageControllerType != StorageControllerType_IntelAhci)
629 return setError (E_NOTIMPL,
630 tr ("Invalid controller type"));
631
632 switch (DevicePosition)
633 {
634 case 0:
635 *aPortNumber = m->bd->mPortIde0Master;
636 break;
637 case 1:
638 *aPortNumber = m->bd->mPortIde0Slave;
639 break;
640 case 2:
641 *aPortNumber = m->bd->mPortIde1Master;
642 break;
643 case 3:
644 *aPortNumber = m->bd->mPortIde1Slave;
645 break;
646 default:
647 return E_INVALIDARG;
648 }
649
650 return S_OK;
651}
652
653STDMETHODIMP StorageController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
654{
655 AutoCaller autoCaller(this);
656 if (FAILED(autoCaller.rc())) return autoCaller.rc();
657
658 /* the machine needs to be mutable */
659 AutoMutableStateDependency adep(m->pParent);
660 if (FAILED(adep.rc())) return adep.rc();
661 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
662
663 if (m->bd->mStorageControllerType != StorageControllerType_IntelAhci)
664 return setError (E_NOTIMPL,
665 tr ("Invalid controller type"));
666
667 if ((aPortNumber < 0) || (aPortNumber >= 30))
668 return setError (E_INVALIDARG,
669 tr ("Invalid port number: %l (must be in range [%lu, %lu])"),
670 aPortNumber, 0, 29);
671
672 switch (DevicePosition)
673 {
674 case 0:
675 m->bd->mPortIde0Master = aPortNumber;
676 break;
677 case 1:
678 m->bd->mPortIde0Slave = aPortNumber;
679 break;
680 case 2:
681 m->bd->mPortIde1Master = aPortNumber;
682 break;
683 case 3:
684 m->bd->mPortIde1Slave = aPortNumber;
685 break;
686 default:
687 return E_INVALIDARG;
688 }
689
690 return S_OK;
691}
692
693// public methods only for internal purposes
694/////////////////////////////////////////////////////////////////////////////
695
696
697const Utf8Str& StorageController::getName() const
698{
699 return m->bd->strName;
700}
701
702StorageControllerType_T StorageController::getControllerType() const
703{
704 return m->bd->mStorageControllerType;
705}
706
707StorageBus_T StorageController::getStorageBus() const
708{
709 return m->bd->mStorageBus;
710}
711
712ULONG StorageController::getInstance() const
713{
714 return m->bd->mInstance;
715}
716
717bool StorageController::isModified()
718{
719 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
720 return m->bd.isBackedUp();
721}
722
723/** @note Locks objects for writing! */
724bool StorageController::rollback()
725{
726 AutoCaller autoCaller(this);
727 AssertComRCReturn (autoCaller.rc(), false);
728
729 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
730
731 bool dataChanged = false;
732
733 if (m->bd.isBackedUp())
734 {
735 /* we need to check all data to see whether anything will be changed
736 * after rollback */
737 dataChanged = m->bd.hasActualChanges();
738 m->bd.rollback();
739 }
740
741 return dataChanged;
742}
743
744/**
745 * @note Locks this object for writing, together with the peer object (also
746 * for writing) if there is one.
747 */
748void StorageController::commit()
749{
750 /* sanity */
751 AutoCaller autoCaller(this);
752 AssertComRCReturnVoid (autoCaller.rc());
753
754 /* sanity too */
755 AutoCaller peerCaller (m->pPeer);
756 AssertComRCReturnVoid (peerCaller.rc());
757
758 /* lock both for writing since we modify both (m->pPeer is "master" so locked
759 * first) */
760 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
761
762 if (m->bd.isBackedUp())
763 {
764 m->bd.commit();
765 if (m->pPeer)
766 {
767 // attach new data to the peer and reshare it
768 m->pPeer->m->bd.attach (m->bd);
769 }
770 }
771}
772
773/**
774 * Cancels sharing (if any) by making an independent copy of data.
775 * This operation also resets this object's peer to NULL.
776 *
777 * @note Locks this object for writing, together with the peer object
778 * represented by @a aThat (locked for reading).
779 */
780void StorageController::unshare()
781{
782 /* sanity */
783 AutoCaller autoCaller(this);
784 AssertComRCReturnVoid (autoCaller.rc());
785
786 /* sanity too */
787 AutoCaller peerCaller (m->pPeer);
788 AssertComRCReturnVoid (peerCaller.rc());
789
790 /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
791 * first) */
792 AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
793 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
794
795 if (m->bd.isShared())
796 {
797 if (!m->bd.isBackedUp())
798 m->bd.backup();
799
800 m->bd.commit();
801 }
802
803 unconst(m->pPeer).setNull();
804}
805
806const ComObjPtr<Machine, ComWeakRef>& StorageController::getMachine()
807{
808 return m->pParent;
809}
810
811ComObjPtr<StorageController> StorageController::getPeer()
812{
813 return m->pPeer;
814}
815
816// private methods
817/////////////////////////////////////////////////////////////////////////////
818
819
820/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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