VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/MediumAttachmentImpl.cpp@ 72919

Last change on this file since 72919 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 16.3 KB
Line 
1/* $Id: MediumAttachmentImpl.cpp 69500 2017-10-28 15:14:05Z vboxsync $ */
2/** @file
3 *
4 * VirtualBox COM class implementation
5 */
6
7/*
8 * Copyright (C) 2006-2017 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "MediumAttachmentImpl.h"
20#include "MachineImpl.h"
21#include "MediumImpl.h"
22#include "Global.h"
23
24#include "AutoCaller.h"
25#include "Logging.h"
26
27#include <iprt/cpp/utils.h>
28
29////////////////////////////////////////////////////////////////////////////////
30//
31// private member data definition
32//
33////////////////////////////////////////////////////////////////////////////////
34
35struct BackupableMediumAttachmentData
36{
37 BackupableMediumAttachmentData()
38 : fImplicit(false)
39 { }
40
41 ComObjPtr<Medium> pMedium;
42 /* Since MediumAttachment is not a first class citizen when it
43 * comes to managing settings, having a reference to the storage
44 * controller will not work - when settings are changed it will point
45 * to the old, uninitialized instance. Changing this requires
46 * substantial changes to MediumImpl.cpp. */
47 /* Same counts for the assigned bandwidth group */
48 bool fImplicit;
49 const Utf8Str strControllerName;
50 settings::AttachedDevice mData;
51};
52
53struct MediumAttachment::Data
54{
55 Data(Machine * const aMachine = NULL)
56 : pMachine(aMachine),
57 fIsEjected(false)
58 { }
59
60 /** Reference to Machine object, for checking mutable state. */
61 Machine * const pMachine;
62 /* later: const ComObjPtr<MediumAttachment> mPeer; */
63 bool fIsEjected;
64 Backupable<BackupableMediumAttachmentData> bd;
65};
66
67// constructor / destructor
68/////////////////////////////////////////////////////////////////////////////
69
70DEFINE_EMPTY_CTOR_DTOR(MediumAttachment)
71
72HRESULT MediumAttachment::FinalConstruct()
73{
74 LogFlowThisFunc(("\n"));
75 return BaseFinalConstruct();
76}
77
78void MediumAttachment::FinalRelease()
79{
80 LogFlowThisFuncEnter();
81 uninit();
82 BaseFinalRelease();
83 LogFlowThisFuncLeave();
84}
85
86// public initializer/uninitializer for internal purposes only
87/////////////////////////////////////////////////////////////////////////////
88
89/**
90 * Initializes the medium attachment object.
91 *
92 * @param aParent Machine object.
93 * @param aMedium Medium object.
94 * @param aControllerName Controller the hard disk is attached to.
95 * @param aPort Port number.
96 * @param aDevice Device number on the port.
97 * @param aType Device type.
98 * @param aImplicit
99 * @param aPassthrough Whether accesses are directly passed to the host drive.
100 * @param aTempEject Whether guest-triggered eject results in unmounting the medium.
101 * @param aNonRotational Whether this medium is non-rotational (aka SSD).
102 * @param aDiscard Whether this medium supports discarding unused blocks.
103 * @param aHotPluggable Whether this medium is hot-pluggable.
104 * @param strBandwidthGroup Bandwidth group.
105 */
106HRESULT MediumAttachment::init(Machine *aParent,
107 Medium *aMedium,
108 const Utf8Str &aControllerName,
109 LONG aPort,
110 LONG aDevice,
111 DeviceType_T aType,
112 bool aImplicit,
113 bool aPassthrough,
114 bool aTempEject,
115 bool aNonRotational,
116 bool aDiscard,
117 bool aHotPluggable,
118 const Utf8Str &strBandwidthGroup)
119{
120 LogFlowThisFuncEnter();
121 LogFlowThisFunc(("aParent=%p aMedium=%p aControllerName=%s aPort=%d aDevice=%d aType=%d aImplicit=%d aPassthrough=%d aTempEject=%d aNonRotational=%d aDiscard=%d aHotPluggable=%d strBandwithGroup=%s\n", aParent, aMedium, aControllerName.c_str(), aPort, aDevice, aType, aImplicit, aPassthrough, aTempEject, aNonRotational, aDiscard, aHotPluggable, strBandwidthGroup.c_str()));
122
123 if (aType == DeviceType_HardDisk)
124 AssertReturn(aMedium, E_INVALIDARG);
125
126 /* Enclose the state transition NotReady->InInit->Ready */
127 AutoInitSpan autoInitSpan(this);
128 AssertReturn(autoInitSpan.isOk(), E_FAIL);
129
130 m = new Data();
131
132 unconst(m->pMachine) = aParent;
133
134 m->bd.allocate();
135 m->bd->pMedium = aMedium;
136 m->bd->mData.strBwGroup = strBandwidthGroup;
137 unconst(m->bd->strControllerName) = aControllerName;
138 m->bd->mData.lPort = aPort;
139 m->bd->mData.lDevice = aDevice;
140 m->bd->mData.deviceType = aType;
141
142 m->bd->mData.fPassThrough = aPassthrough;
143 m->bd->mData.fTempEject = aTempEject;
144 m->bd->mData.fNonRotational = aNonRotational;
145 m->bd->mData.fDiscard = aDiscard;
146 m->bd->fImplicit = aImplicit;
147 m->bd->mData.fHotPluggable = aHotPluggable;
148
149 /* Confirm a successful initialization when it's the case */
150 autoInitSpan.setSucceeded();
151
152 /* Construct a short log name for this attachment. */
153 i_updateLogName();
154
155 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
156 return S_OK;
157}
158
159/**
160 * Initializes the medium attachment object given another guest object
161 * (a kind of copy constructor). This object makes a private copy of data
162 * of the original object passed as an argument.
163 */
164HRESULT MediumAttachment::initCopy(Machine *aParent, MediumAttachment *aThat)
165{
166 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
167
168 ComAssertRet(aParent && aThat, E_INVALIDARG);
169
170 /* Enclose the state transition NotReady->InInit->Ready */
171 AutoInitSpan autoInitSpan(this);
172 AssertReturn(autoInitSpan.isOk(), E_FAIL);
173
174 m = new Data(aParent);
175 /* m->pPeer is left null */
176
177 AutoCaller thatCaller(aThat);
178 AssertComRCReturnRC(thatCaller.rc());
179
180 AutoReadLock thatlock(aThat COMMA_LOCKVAL_SRC_POS);
181 m->bd.attachCopy(aThat->m->bd);
182
183 /* Confirm a successful initialization */
184 autoInitSpan.setSucceeded();
185
186 /* Construct a short log name for this attachment. */
187 i_updateLogName();
188
189 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
190 return S_OK;
191}
192
193/**
194 * Uninitializes the instance.
195 * Called from FinalRelease().
196 */
197void MediumAttachment::uninit()
198{
199 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
200
201 /* Enclose the state transition Ready->InUninit->NotReady */
202 AutoUninitSpan autoUninitSpan(this);
203 if (autoUninitSpan.uninitDone())
204 return;
205
206 m->bd.free();
207
208 unconst(m->pMachine) = NULL;
209
210 delete m;
211 m = NULL;
212
213 LogFlowThisFuncLeave();
214}
215
216// IHardDiskAttachment properties
217/////////////////////////////////////////////////////////////////////////////
218
219
220HRESULT MediumAttachment::getMedium(ComPtr<IMedium> &aHardDisk)
221{
222 LogFlowThisFuncEnter();
223
224 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
225
226 aHardDisk = m->bd->pMedium;
227
228 LogFlowThisFuncLeave();
229 return S_OK;
230}
231
232
233HRESULT MediumAttachment::getController(com::Utf8Str &aController)
234{
235 LogFlowThisFuncEnter();
236
237 /* m->controller is constant during life time, no need to lock */
238 aController = Utf8Str(m->bd->strControllerName);
239
240 LogFlowThisFuncLeave();
241 return S_OK;
242}
243
244
245HRESULT MediumAttachment::getPort(LONG *aPort)
246{
247 LogFlowThisFuncEnter();
248
249 /* m->bd->port is constant during life time, no need to lock */
250 *aPort = m->bd->mData.lPort;
251
252 LogFlowThisFuncLeave();
253 return S_OK;
254}
255
256HRESULT MediumAttachment::getDevice(LONG *aDevice)
257{
258 LogFlowThisFuncEnter();
259
260 /* m->bd->device is constant during life time, no need to lock */
261 *aDevice = m->bd->mData.lDevice;
262
263 LogFlowThisFuncLeave();
264 return S_OK;
265}
266
267HRESULT MediumAttachment::getType(DeviceType_T *aType)
268{
269 LogFlowThisFuncEnter();
270
271 /* m->bd->type is constant during life time, no need to lock */
272 *aType = m->bd->mData.deviceType;
273
274 LogFlowThisFuncLeave();
275 return S_OK;
276}
277
278
279HRESULT MediumAttachment::getPassthrough(BOOL *aPassthrough)
280{
281 LogFlowThisFuncEnter();
282
283 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
284
285 *aPassthrough = m->bd->mData.fPassThrough;
286
287 LogFlowThisFuncLeave();
288 return S_OK;
289}
290
291
292HRESULT MediumAttachment::getTemporaryEject(BOOL *aTemporaryEject)
293{
294 LogFlowThisFuncEnter();
295
296 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
297
298 *aTemporaryEject = m->bd->mData.fTempEject;
299
300 LogFlowThisFuncLeave();
301 return S_OK;
302}
303
304
305HRESULT MediumAttachment::getIsEjected(BOOL *aEjected)
306{
307 LogFlowThisFuncEnter();
308
309 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
310
311 *aEjected = m->fIsEjected;
312
313 LogFlowThisFuncLeave();
314 return S_OK;
315}
316
317
318HRESULT MediumAttachment::getNonRotational(BOOL *aNonRotational)
319{
320 LogFlowThisFuncEnter();
321
322 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
323
324 *aNonRotational = m->bd->mData.fNonRotational;
325
326 LogFlowThisFuncLeave();
327 return S_OK;
328}
329
330HRESULT MediumAttachment::getDiscard(BOOL *aDiscard)
331{
332 LogFlowThisFuncEnter();
333
334 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
335
336 *aDiscard = m->bd->mData.fDiscard;
337
338 LogFlowThisFuncLeave();
339 return S_OK;
340}
341
342
343HRESULT MediumAttachment::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
344{
345 LogFlowThisFuncEnter();
346
347 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
348
349 HRESULT hrc = S_OK;
350 if (m->bd->mData.strBwGroup.isNotEmpty())
351 {
352 ComObjPtr<BandwidthGroup> pBwGroup;
353 hrc = m->pMachine->i_getBandwidthGroup(m->bd->mData.strBwGroup, pBwGroup, true /* fSetError */);
354
355 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the
356 group was checked when it was attached. */
357
358 if (SUCCEEDED(hrc))
359 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
360 }
361
362 LogFlowThisFuncLeave();
363 return hrc;
364}
365
366HRESULT MediumAttachment::getHotPluggable(BOOL *aHotPluggable)
367{
368 LogFlowThisFuncEnter();
369
370 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
371
372 *aHotPluggable = m->bd->mData.fHotPluggable;
373
374 LogFlowThisFuncLeave();
375 return S_OK;
376}
377
378/**
379 * @note Locks this object for writing.
380 */
381void MediumAttachment::i_rollback()
382{
383 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
384
385 /* sanity */
386 AutoCaller autoCaller(this);
387 AssertComRCReturnVoid(autoCaller.rc());
388
389 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
390
391 m->bd.rollback();
392
393 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
394}
395
396/**
397 * @note Locks this object for writing.
398 */
399void MediumAttachment::i_commit()
400{
401 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
402
403 /* sanity */
404 AutoCaller autoCaller(this);
405 AssertComRCReturnVoid(autoCaller.rc());
406
407 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
408
409 if (m->bd.isBackedUp())
410 m->bd.commit();
411
412 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
413}
414
415bool MediumAttachment::i_isImplicit() const
416{
417 return m->bd->fImplicit;
418}
419
420void MediumAttachment::i_setImplicit(bool aImplicit)
421{
422 Assert(!m->pMachine->i_isSnapshotMachine());
423 m->bd->fImplicit = aImplicit;
424
425 /* Construct a short log name for this attachment. */
426 i_updateLogName();
427}
428
429const ComObjPtr<Medium>& MediumAttachment::i_getMedium() const
430{
431 return m->bd->pMedium;
432}
433
434const Utf8Str &MediumAttachment::i_getControllerName() const
435{
436 return m->bd->strControllerName;
437}
438
439LONG MediumAttachment::i_getPort() const
440{
441 return m->bd->mData.lPort;
442}
443
444LONG MediumAttachment::i_getDevice() const
445{
446 return m->bd->mData.lDevice;
447}
448
449DeviceType_T MediumAttachment::i_getType() const
450{
451 return m->bd->mData.deviceType;
452}
453
454bool MediumAttachment::i_getPassthrough() const
455{
456 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
457 return m->bd->mData.fPassThrough;
458}
459
460bool MediumAttachment::i_getTempEject() const
461{
462 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
463 return m->bd->mData.fTempEject;
464}
465
466bool MediumAttachment::i_getNonRotational() const
467{
468 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
469 return m->bd->mData.fNonRotational;
470}
471
472bool MediumAttachment::i_getDiscard() const
473{
474 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
475 return m->bd->mData.fDiscard;
476}
477
478bool MediumAttachment::i_getHotPluggable() const
479{
480 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
481 return m->bd->mData.fHotPluggable;
482}
483
484Utf8Str& MediumAttachment::i_getBandwidthGroup() const
485{
486 return m->bd->mData.strBwGroup;
487}
488
489bool MediumAttachment::i_matches(const Utf8Str &aControllerName, LONG aPort, LONG aDevice)
490{
491 return ( aControllerName == m->bd->strControllerName
492 && aPort == m->bd->mData.lPort
493 && aDevice == m->bd->mData.lDevice);
494}
495
496/** Must be called from under this object's write lock. */
497void MediumAttachment::i_updateName(const Utf8Str &aName)
498{
499 Assert(isWriteLockOnCurrentThread());
500 Assert(!m->pMachine->i_isSnapshotMachine());
501
502 m->bd.backup();
503 unconst(m->bd->strControllerName) = aName;
504
505 /* Construct a short log name for this attachment. */
506 i_updateLogName();
507}
508
509/**
510 * Sets the medium of this attachment and unsets the "implicit" flag.
511 * @param aMedium
512 */
513void MediumAttachment::i_updateMedium(const ComObjPtr<Medium> &aMedium)
514{
515 Assert(isWriteLockOnCurrentThread());
516 /* No assertion for a snapshot. Method used in deleting snapshot. */
517
518 m->bd.backup();
519 m->bd->pMedium = aMedium;
520 m->bd->fImplicit = false;
521 m->fIsEjected = false;
522}
523
524/** Must be called from under this object's write lock. */
525void MediumAttachment::i_updatePassthrough(bool aPassthrough)
526{
527 Assert(isWriteLockOnCurrentThread());
528 Assert(!m->pMachine->i_isSnapshotMachine());
529
530 m->bd.backup();
531 m->bd->mData.fPassThrough = aPassthrough;
532}
533
534/** Must be called from under this object's write lock. */
535void MediumAttachment::i_updateTempEject(bool aTempEject)
536{
537 Assert(isWriteLockOnCurrentThread());
538 Assert(!m->pMachine->i_isSnapshotMachine());
539
540 m->bd.backup();
541 m->bd->mData.fTempEject = aTempEject;
542}
543
544/** Must be called from under this object's write lock. */
545void MediumAttachment::i_updateEjected()
546{
547 Assert(isWriteLockOnCurrentThread());
548 Assert(!m->pMachine->i_isSnapshotMachine());
549
550 m->fIsEjected = true;
551}
552
553/** Must be called from under this object's write lock. */
554void MediumAttachment::i_updateNonRotational(bool aNonRotational)
555{
556 Assert(isWriteLockOnCurrentThread());
557 Assert(!m->pMachine->i_isSnapshotMachine());
558
559 m->bd.backup();
560 m->bd->mData.fNonRotational = aNonRotational;
561}
562
563/** Must be called from under this object's write lock. */
564void MediumAttachment::i_updateDiscard(bool aDiscard)
565{
566 Assert(isWriteLockOnCurrentThread());
567 Assert(!m->pMachine->i_isSnapshotMachine());
568
569 m->bd.backup();
570 m->bd->mData.fDiscard = aDiscard;
571}
572
573/** Must be called from under this object's write lock. */
574void MediumAttachment::i_updateHotPluggable(bool aHotPluggable)
575{
576 Assert(isWriteLockOnCurrentThread());
577 Assert(!m->pMachine->i_isSnapshotMachine());
578
579 m->bd.backup();
580 m->bd->mData.fHotPluggable = aHotPluggable;
581}
582
583void MediumAttachment::i_updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
584{
585 LogFlowThisFuncEnter();
586 Assert(isWriteLockOnCurrentThread());
587 Assert(!m->pMachine->i_isSnapshotMachine());
588
589 m->bd.backup();
590 m->bd->mData.strBwGroup = aBandwidthGroup;
591
592 LogFlowThisFuncLeave();
593}
594
595void MediumAttachment::i_updateParentMachine(Machine * const pMachine)
596{
597 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
598 /* sanity */
599 AutoCaller autoCaller(this);
600 AssertComRCReturnVoid(autoCaller.rc());
601 Assert(!m->pMachine->i_isSnapshotMachine());
602
603 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
604
605 unconst(m->pMachine) = pMachine;
606
607 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
608}
609
610void MediumAttachment::i_updateLogName()
611{
612 const char *pszName = m->bd->strControllerName.c_str();
613 const char *pszEndNick = strpbrk(pszName, " \t:-");
614 mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
615 this,
616 pszEndNick ? pszEndNick - pszName : 4, pszName,
617 m->bd->mData.lPort, m->bd->mData.lDevice, Global::stringifyDeviceType(m->bd->mData.deviceType),
618 m->bd->fImplicit ? ":I" : "");
619}
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