[libvirt] [PATCH 10/10] network: internal API functions to manage assignment of physdev to guest

Laine Stump laine at laine.org
Wed Jul 20 05:38:45 UTC 2011


On 07/08/2011 04:37 PM, Eric Blake wrote:
> On 07/05/2011 01:45 AM, Laine Stump wrote:
>> The network driver needs to assign physical devices for use by modes
>> that use macvtap, keeping track of which physical devices are in use
>> (and how many instances, when the devices can be shared). Three calls
>> are added:
>>
>> networkAllocateActualDevice - finds a physical device for use by the
>> domain, and sets up the virDomainActualNetDef accordingly.
>>
>> networkNotifyActualDevice - assumes that the domain was already
>> running, but libvirtd was restarted, and needs to be notified by each
>> already-running domain about what interfaces they are using.
>>
>> networkReleaseActualDevice - decrements the usage count of the
>> allocated physical device, and frees the virDomainActualNetDef to
>> avoid later accidentally using the device.
>>
>> bridge_driver.[hc] - the new APIs
>>
>> qemu_(command|driver|hotplug|process).c - add calls to the above APIs
>>      in the appropriate places.
>>
>> tests/Makefile.am - need to include libvirt_driver_network.la whenever
>>      libvirt_driver_qemu.la is linked, to avoid unreferenced symbols
>>      (in functions that are never called by the test programs...)
>> ---
>>   src/network/bridge_driver.c |  398 +++++++++++++++++++++++++++++++++++++++++++
>>   src/network/bridge_driver.h |    6 +
>>   src/qemu/qemu_command.c     |   11 ++
>>   src/qemu/qemu_hotplug.c     |   41 +++--
>>   src/qemu/qemu_process.c     |   26 +++-
>>   tests/Makefile.am           |   12 +-
>>   6 files changed, 476 insertions(+), 18 deletions(-)
>> +
>> +        /* Find the most specific virtportprofile and copy it */
>> +        if (iface->data.network.virtPortProfile) {
>> +            virtport = iface->data.network.virtPortProfile;
>> +        } else {
>> +            virPortGroupDefPtr portgroup
>> +               = virPortGroupFindByName(netdef, iface->data.network.portgroup);
>> +            if (portgroup)
>> +                virtport = portgroup->virtPortProfile;
> Nit: Indentation looks interesting there - the line starting with = has
> one less space.  Perhaps something to do with how your preferred editor
> splits assignments.  My editor uses 4 spaces instead of 3 in that instance.


It defaults to a different style, and I sometimes forget to switch.


>> +int
>> +networkNotifyActualDevice(virDomainNetDefPtr iface)
>> +{
>> +
>> +        /* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both require
>> +         * exclusive access to a device, so current usageCount must be
>> +         * 0 in those cases.
>> +         */
>> +        if ((dev->usageCount>  0)&&
>> +            ((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) ||
>> +             ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE)&&
>> +              iface->data.network.actual->data.direct.virtPortProfile&&
>> +              (iface->data.network.actual->data.direct.virtPortProfile->virtPortType
>> +               == VIR_VIRTUALPORT_8021QBH)))) {
>> +            networkReportError(VIR_ERR_INTERNAL_ERROR,
>> +                               _("network '%s' claims dev='%s' is already in use by a different domain"),
> Do we have a data race here?
>
> Suppose that libvirtd is restarted while one VM is already using device
> 0.  Is there any chance that if I'm fast enough, I can cause the
> creation of a second domain, and that second domain will go to pick from
> the interface pool before the notification pass of the libvirtd restart
> has completed, and mistakenly claim device 0?
>
> That is, I think we need to somehow guarantee (if we don't already) that
> no new domains can be created until after all existing domains have been
> reloaded on a libvirtd restart.

I was concerned about this at first too.

Here's the call chain down to this function (it's only called from one 
place):

networkNotifyActualDevice
qemuProcessNotifyNets
qemuProcessReconnect
qemuProcessReconnectAll
qemudStartup <- aka the "initialize" function of the qemu state driver.


At the top of qemudStartup, the lock for the driver is initialized, then 
locked. After this, a ton of stuff is initialized, including calling 
qemuProcessReconnectAll(), then the worker thread pool is created, and 
finally the driver lock is released. So as far as I understand it, it's 
not possible for a new domain to be created until after this is all 
finished.




More information about the libvir-list mailing list