VirtualBox

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

Last change on this file since 54971 was 54971, checked in by vboxsync, 10 years ago

Main/AudioAdapter+BandwidthControl+Machine+NetworkAdapter+ParallelPort+SerialPort+StorageController+USBDeviceFilter+USBDeviceFilters: Adjust rules when settings can be changed to allow as much as possible. Some changes restored the old rules (a previous change made the definition more restrictive), but many now allow changing settings when VM is saved or even at runtime when it is safe. Will resolve many complaints, especially when the GUI also is adapted accordingly.

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