VirtualBox

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

Last change on this file since 85672 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 16.6 KB
Line 
1/* $Id: MediumAttachmentImpl.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_MEDIUMATTACHMENT
19#include "MediumAttachmentImpl.h"
20#include "MachineImpl.h"
21#include "MediumImpl.h"
22#include "Global.h"
23
24#include "AutoCaller.h"
25#include "LoggingNew.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::getMachine(ComPtr<IMachine> &aMachine)
221{
222 LogFlowThisFuncEnter();
223
224 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
225
226 ComObjPtr<Machine> pMachine(m->pMachine);
227 pMachine.queryInterfaceTo(aMachine.asOutParam());
228
229 LogFlowThisFuncLeave();
230 return S_OK;
231}
232
233
234HRESULT MediumAttachment::getMedium(ComPtr<IMedium> &aHardDisk)
235{
236 LogFlowThisFuncEnter();
237
238 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
239
240 aHardDisk = m->bd->pMedium;
241
242 LogFlowThisFuncLeave();
243 return S_OK;
244}
245
246
247HRESULT MediumAttachment::getController(com::Utf8Str &aController)
248{
249 LogFlowThisFuncEnter();
250
251 /* m->controller is constant during life time, no need to lock */
252 aController = Utf8Str(m->bd->strControllerName);
253
254 LogFlowThisFuncLeave();
255 return S_OK;
256}
257
258
259HRESULT MediumAttachment::getPort(LONG *aPort)
260{
261 LogFlowThisFuncEnter();
262
263 /* m->bd->port is constant during life time, no need to lock */
264 *aPort = m->bd->mData.lPort;
265
266 LogFlowThisFuncLeave();
267 return S_OK;
268}
269
270HRESULT MediumAttachment::getDevice(LONG *aDevice)
271{
272 LogFlowThisFuncEnter();
273
274 /* m->bd->device is constant during life time, no need to lock */
275 *aDevice = m->bd->mData.lDevice;
276
277 LogFlowThisFuncLeave();
278 return S_OK;
279}
280
281HRESULT MediumAttachment::getType(DeviceType_T *aType)
282{
283 LogFlowThisFuncEnter();
284
285 /* m->bd->type is constant during life time, no need to lock */
286 *aType = m->bd->mData.deviceType;
287
288 LogFlowThisFuncLeave();
289 return S_OK;
290}
291
292
293HRESULT MediumAttachment::getPassthrough(BOOL *aPassthrough)
294{
295 LogFlowThisFuncEnter();
296
297 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
298
299 *aPassthrough = m->bd->mData.fPassThrough;
300
301 LogFlowThisFuncLeave();
302 return S_OK;
303}
304
305
306HRESULT MediumAttachment::getTemporaryEject(BOOL *aTemporaryEject)
307{
308 LogFlowThisFuncEnter();
309
310 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
311
312 *aTemporaryEject = m->bd->mData.fTempEject;
313
314 LogFlowThisFuncLeave();
315 return S_OK;
316}
317
318
319HRESULT MediumAttachment::getIsEjected(BOOL *aEjected)
320{
321 LogFlowThisFuncEnter();
322
323 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
324
325 *aEjected = m->fIsEjected;
326
327 LogFlowThisFuncLeave();
328 return S_OK;
329}
330
331
332HRESULT MediumAttachment::getNonRotational(BOOL *aNonRotational)
333{
334 LogFlowThisFuncEnter();
335
336 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
337
338 *aNonRotational = m->bd->mData.fNonRotational;
339
340 LogFlowThisFuncLeave();
341 return S_OK;
342}
343
344HRESULT MediumAttachment::getDiscard(BOOL *aDiscard)
345{
346 LogFlowThisFuncEnter();
347
348 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
349
350 *aDiscard = m->bd->mData.fDiscard;
351
352 LogFlowThisFuncLeave();
353 return S_OK;
354}
355
356
357HRESULT MediumAttachment::getBandwidthGroup(ComPtr<IBandwidthGroup> &aBandwidthGroup)
358{
359 LogFlowThisFuncEnter();
360
361 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
362
363 HRESULT hrc = S_OK;
364 if (m->bd->mData.strBwGroup.isNotEmpty())
365 {
366 ComObjPtr<BandwidthGroup> pBwGroup;
367 hrc = m->pMachine->i_getBandwidthGroup(m->bd->mData.strBwGroup, pBwGroup, true /* fSetError */);
368
369 Assert(SUCCEEDED(hrc)); /* This is not allowed to fail because the existence of the
370 group was checked when it was attached. */
371
372 if (SUCCEEDED(hrc))
373 pBwGroup.queryInterfaceTo(aBandwidthGroup.asOutParam());
374 }
375
376 LogFlowThisFuncLeave();
377 return hrc;
378}
379
380HRESULT MediumAttachment::getHotPluggable(BOOL *aHotPluggable)
381{
382 LogFlowThisFuncEnter();
383
384 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
385
386 *aHotPluggable = m->bd->mData.fHotPluggable;
387
388 LogFlowThisFuncLeave();
389 return S_OK;
390}
391
392/**
393 * @note Locks this object for writing.
394 */
395void MediumAttachment::i_rollback()
396{
397 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
398
399 /* sanity */
400 AutoCaller autoCaller(this);
401 AssertComRCReturnVoid(autoCaller.rc());
402
403 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
404
405 m->bd.rollback();
406
407 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
408}
409
410/**
411 * @note Locks this object for writing.
412 */
413void MediumAttachment::i_commit()
414{
415 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
416
417 /* sanity */
418 AutoCaller autoCaller(this);
419 AssertComRCReturnVoid(autoCaller.rc());
420
421 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
422
423 if (m->bd.isBackedUp())
424 m->bd.commit();
425
426 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
427}
428
429bool MediumAttachment::i_isImplicit() const
430{
431 return m->bd->fImplicit;
432}
433
434void MediumAttachment::i_setImplicit(bool aImplicit)
435{
436 Assert(!m->pMachine->i_isSnapshotMachine());
437 m->bd->fImplicit = aImplicit;
438
439 /* Construct a short log name for this attachment. */
440 i_updateLogName();
441}
442
443const ComObjPtr<Medium>& MediumAttachment::i_getMedium() const
444{
445 return m->bd->pMedium;
446}
447
448const Utf8Str &MediumAttachment::i_getControllerName() const
449{
450 return m->bd->strControllerName;
451}
452
453LONG MediumAttachment::i_getPort() const
454{
455 return m->bd->mData.lPort;
456}
457
458LONG MediumAttachment::i_getDevice() const
459{
460 return m->bd->mData.lDevice;
461}
462
463DeviceType_T MediumAttachment::i_getType() const
464{
465 return m->bd->mData.deviceType;
466}
467
468bool MediumAttachment::i_getPassthrough() const
469{
470 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
471 return m->bd->mData.fPassThrough;
472}
473
474bool MediumAttachment::i_getTempEject() const
475{
476 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
477 return m->bd->mData.fTempEject;
478}
479
480bool MediumAttachment::i_getNonRotational() const
481{
482 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
483 return m->bd->mData.fNonRotational;
484}
485
486bool MediumAttachment::i_getDiscard() const
487{
488 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
489 return m->bd->mData.fDiscard;
490}
491
492bool MediumAttachment::i_getHotPluggable() const
493{
494 AutoReadLock lock(this COMMA_LOCKVAL_SRC_POS);
495 return m->bd->mData.fHotPluggable;
496}
497
498Utf8Str& MediumAttachment::i_getBandwidthGroup() const
499{
500 return m->bd->mData.strBwGroup;
501}
502
503bool MediumAttachment::i_matches(const Utf8Str &aControllerName, LONG aPort, LONG aDevice)
504{
505 return ( aControllerName == m->bd->strControllerName
506 && aPort == m->bd->mData.lPort
507 && aDevice == m->bd->mData.lDevice);
508}
509
510/** Must be called from under this object's write lock. */
511void MediumAttachment::i_updateName(const Utf8Str &aName)
512{
513 Assert(isWriteLockOnCurrentThread());
514 Assert(!m->pMachine->i_isSnapshotMachine());
515
516 m->bd.backup();
517 unconst(m->bd->strControllerName) = aName;
518
519 /* Construct a short log name for this attachment. */
520 i_updateLogName();
521}
522
523/**
524 * Sets the medium of this attachment and unsets the "implicit" flag.
525 * @param aMedium
526 */
527void MediumAttachment::i_updateMedium(const ComObjPtr<Medium> &aMedium)
528{
529 Assert(isWriteLockOnCurrentThread());
530 /* No assertion for a snapshot. Method used in deleting snapshot. */
531
532 m->bd.backup();
533 m->bd->pMedium = aMedium;
534 m->bd->fImplicit = false;
535 m->fIsEjected = false;
536}
537
538/** Must be called from under this object's write lock. */
539void MediumAttachment::i_updatePassthrough(bool aPassthrough)
540{
541 Assert(isWriteLockOnCurrentThread());
542 Assert(!m->pMachine->i_isSnapshotMachine());
543
544 m->bd.backup();
545 m->bd->mData.fPassThrough = aPassthrough;
546}
547
548/** Must be called from under this object's write lock. */
549void MediumAttachment::i_updateTempEject(bool aTempEject)
550{
551 Assert(isWriteLockOnCurrentThread());
552 Assert(!m->pMachine->i_isSnapshotMachine());
553
554 m->bd.backup();
555 m->bd->mData.fTempEject = aTempEject;
556}
557
558/** Must be called from under this object's write lock. */
559void MediumAttachment::i_updateEjected()
560{
561 Assert(isWriteLockOnCurrentThread());
562 Assert(!m->pMachine->i_isSnapshotMachine());
563
564 m->fIsEjected = true;
565}
566
567/** Must be called from under this object's write lock. */
568void MediumAttachment::i_updateNonRotational(bool aNonRotational)
569{
570 Assert(isWriteLockOnCurrentThread());
571 Assert(!m->pMachine->i_isSnapshotMachine());
572
573 m->bd.backup();
574 m->bd->mData.fNonRotational = aNonRotational;
575}
576
577/** Must be called from under this object's write lock. */
578void MediumAttachment::i_updateDiscard(bool aDiscard)
579{
580 Assert(isWriteLockOnCurrentThread());
581 Assert(!m->pMachine->i_isSnapshotMachine());
582
583 m->bd.backup();
584 m->bd->mData.fDiscard = aDiscard;
585}
586
587/** Must be called from under this object's write lock. */
588void MediumAttachment::i_updateHotPluggable(bool aHotPluggable)
589{
590 Assert(isWriteLockOnCurrentThread());
591 Assert(!m->pMachine->i_isSnapshotMachine());
592
593 m->bd.backup();
594 m->bd->mData.fHotPluggable = aHotPluggable;
595}
596
597void MediumAttachment::i_updateBandwidthGroup(const Utf8Str &aBandwidthGroup)
598{
599 LogFlowThisFuncEnter();
600 Assert(isWriteLockOnCurrentThread());
601 Assert(!m->pMachine->i_isSnapshotMachine());
602
603 m->bd.backup();
604 m->bd->mData.strBwGroup = aBandwidthGroup;
605
606 LogFlowThisFuncLeave();
607}
608
609void MediumAttachment::i_updateParentMachine(Machine * const pMachine)
610{
611 LogFlowThisFunc(("ENTER - %s\n", i_getLogName()));
612 /* sanity */
613 AutoCaller autoCaller(this);
614 AssertComRCReturnVoid(autoCaller.rc());
615 Assert(!m->pMachine->i_isSnapshotMachine());
616
617 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
618
619 unconst(m->pMachine) = pMachine;
620
621 LogFlowThisFunc(("LEAVE - %s\n", i_getLogName()));
622}
623
624void MediumAttachment::i_updateLogName()
625{
626 const char *pszName = m->bd->strControllerName.c_str();
627 const char *pszEndNick = strpbrk(pszName, " \t:-");
628 mLogName = Utf8StrFmt("MA%p[%.*s:%u:%u:%s%s]",
629 this,
630 pszEndNick ? pszEndNick - pszName : 4, pszName,
631 m->bd->mData.lPort, m->bd->mData.lDevice, Global::stringifyDeviceType(m->bd->mData.deviceType),
632 m->bd->fImplicit ? ":I" : "");
633}
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