VirtualBox

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

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

LsiLogic: Add SAS support for Main and Frontends

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