[libvirt] [PATCH 4/4] qemu: hot-unplug of watchdog

Michal Privoznik mprivozn at redhat.com
Tue Sep 26 12:02:27 UTC 2017


On 09/26/2017 01:34 PM, John Ferlan wrote:
> 
> 
> On 09/26/2017 05:38 AM, Michal Privoznik wrote:
>> On 09/12/2017 04:29 PM, John Ferlan wrote:
>>>
>>>
>>> On 09/05/2017 07:45 AM, Michal Privoznik wrote:
>>>> https://bugzilla.redhat.com/show_bug.cgi?id=1447169
>>>>
>>>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>>>> ---
>>>>  src/qemu/qemu_driver.c                             |  4 +-
>>>>  src/qemu/qemu_hotplug.c                            | 61 ++++++++++++++++++++++
>>>>  src/qemu/qemu_hotplug.h                            |  3 ++
>>>>  tests/qemuhotplugtest.c                            |  7 ++-
>>>>  .../qemuhotplug-watchdog-full.xml                  |  3 ++
>>>>  5 files changed, 76 insertions(+), 2 deletions(-)
>>>>  create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-watchdog-full.xml
>>>>
>>>> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
>>>> index 626148dba..4c636b956 100644
>>>> --- a/src/qemu/qemu_driver.c
>>>> +++ b/src/qemu/qemu_driver.c
>>>> @@ -7692,12 +7692,14 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
>>>>      case VIR_DOMAIN_DEVICE_SHMEM:
>>>>          ret = qemuDomainDetachShmemDevice(driver, vm, dev->data.shmem);
>>>>          break;
>>>> +    case VIR_DOMAIN_DEVICE_WATCHDOG:
>>>> +        ret = qemuDomainDetachWatchdog(driver, vm, dev->data.watchdog);
>>>> +        break;
>>>>  
>>>>      case VIR_DOMAIN_DEVICE_FS:
>>>>      case VIR_DOMAIN_DEVICE_INPUT:
>>>>      case VIR_DOMAIN_DEVICE_SOUND:
>>>>      case VIR_DOMAIN_DEVICE_VIDEO:
>>>> -    case VIR_DOMAIN_DEVICE_WATCHDOG:
>>>>      case VIR_DOMAIN_DEVICE_GRAPHICS:
>>>>      case VIR_DOMAIN_DEVICE_HUB:
>>>>      case VIR_DOMAIN_DEVICE_SMARTCARD:
>>>> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
>>>> index 989146eb9..44472ce9f 100644
>>>> --- a/src/qemu/qemu_hotplug.c
>>>> +++ b/src/qemu/qemu_hotplug.c
>>>> @@ -4360,6 +4360,25 @@ qemuDomainRemoveShmemDevice(virQEMUDriverPtr driver,
>>>>  }
>>>>  
>>>>  
>>>> +static int
>>>> +qemuDomainRemoveWatchdog(virQEMUDriverPtr driver,
>>>> +                         virDomainObjPtr vm,
>>>> +                         virDomainWatchdogDefPtr watchdog)
>>>> +{
>>>> +    virObjectEventPtr event = NULL;
>>>> +
>>>> +    VIR_DEBUG("Removing watchdog %s from domain %p %s",
>>>
>>> Is "Removing watchdog watchdog0 from ..." a bit superfluous?
>>>
>>> Perhaps just "Removing '%s' from ..."
>>>
>>>> +              watchdog->info.alias, vm, vm->def->name);
>>>> +
>>>
>>> This would/could be the place for the virDomainAuditWatchdog for
>>> "detach" too.
>>>
>>>> +    event = virDomainEventDeviceRemovedNewFromObj(vm, watchdog->info.alias);
>>>> +    qemuDomainEventQueue(driver, event);
>>>> +    qemuDomainReleaseDeviceAddress(vm, &watchdog->info, NULL);
>>>> +    virDomainWatchdogDefFree(vm->def->watchdog);
>>>> +    vm->def->watchdog = NULL;
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +
>>>>  int
>>>>  qemuDomainRemoveDevice(virQEMUDriverPtr driver,
>>>>                         virDomainObjPtr vm,
>>>> @@ -5076,6 +5095,48 @@ qemuDomainDetachShmemDevice(virQEMUDriverPtr driver,
>>>>  }
>>>>  
>>>>  
>>>> +int
>>>> +qemuDomainDetachWatchdog(virQEMUDriverPtr driver,
>>>> +                         virDomainObjPtr vm,
>>>> +                         virDomainWatchdogDefPtr dev)
>>>> +{
>>>> +    int ret = -1;
>>>> +    virDomainWatchdogDefPtr watchdog;
>>>
>>> Why not watchdog = vm->def->watchdog; here?
>>>
>>>> +    qemuDomainObjPrivatePtr priv = vm->privateData;
>>>> +
>>>> +    /* While domains can have up to one watchdog, the one supplied by user
>>>
>>> s/by/by the/
>>>
>>>> +     * doesn't necessarily match the one domain has. Refuse to detach in such
>>>> +     * case. */
>>>> +    if (!(vm->def->watchdog &&
>>>> +          STREQ_NULLABLE(dev->info.alias,
>>>> +                         vm->def->watchdog->info.alias))) {
>>>
>>> if (!watchdog || STRNEQ_NULLABLE(dev->info.alias, watchdog->info.alias))
>>>
>>> Trying to think why NULLABLE would be necessary... So it seems it's
>>> required that that input XML has the alias - something not quite right
>>> with that...
>>
>> Is that so? We match devices based on their alias in a lot of places.
>> Users are expected to pass the full device XML anyway. So it's up to us
>> how we pick the right device to be detached. For instance, when
>> detaching a vNIC we match MAC addresses and ignore the rest, since MAC
>> identifies the device uniquely. So for instance, if the detach XML
>> provided by user has <bandwidth/> set but the one in domain doesn't have
>> it, we detach the device anyway. One can argue this is a buggy
>> behaviour. But I just don't think we should care. There's a line we have
>> to draw between protecting users from themselves and too complex and
>> mostly useless code. So we've documented that users are supposed to pass
>> the device XML as is in the domain XML.
>>
> 
> Can the alias be user supplied and not be overwritten on attach?  IOW:
> If someone supplies watchdog5 on hot plug, would supplying the same XML
> work on hot unplug?

No, it wouldn't work. Because there's no watchdog5. However, what you're
doing is flawed according to the documentation. You're misusing the
APIs, because you know how they work internally and that's okay for the
testing we do when developing new feature. But in production, users are
required to:

1) write the device XML
2) hotplug it
3) dump the domain XML
4) find the device they want to detach
5) provide full device XML

Note, that after step 2, there are going to be differences between user
supplied XML and the device XML in domain XML. For instance, user are
not required to provide PCI address they want to attach the device at.
Libvirt calculates its own.

> 
> Typically I pass/use the same XML for my disk/hostdev hot plug/unplug.
> Some of those aliases could be tricky unless of course someone's looked
> at the process arguments.

Since there can be one watchdog per domain at most, passing "watchdog5"
as device alias would be unwise. But as I say, you're kind of misusing
the attach/detach APIs. I'm doing the same thing, because we both know
the internals. BTW: This approach does not work with all the devices -
just try to unplug a dimm module with such 'generic' XML. Dimm's alias
is checked explicitly.

Anyway, to raise chances of me getting this in, I've already added
checks for model & action.

> 
> And of course I now see the NULLABLE is being used because even the
> input XML doesn't require it, you're checking that it is provided and
> using that as the sole determination of matching the input XML against
> what's been loaded into QEMU either via cold or hot plug.

Yes.

> 
>>>
>>> I would think for unplug there'd be something that would compare the
>>> input "model" and "action" values to whatever watchdog is currently
>>> present and if they don't match, then fail. Not sure why comparing the
>>> alias is "right". It's not something we require of other unplugs, is it?
>>
>> Sort of. For instance when detaching disks we only care about the
>> target. And for a lot of other devices we require alias too.
>>
> 
> But we also seem to make use of whatever alias exists for the device in
> many places... I looked at a few and I couldn't find a case where the
> alias was required on input for the detach.

/**
 * virDomainDetachDeviceFlags:
 * @domain: pointer to domain object
 * @xml: pointer to XML description of one device
 * @flags: bitwise-OR of virDomainDeviceModifyFlags
 *
 * ..
 *
 * The supplied XML description of the device should be as specific
 * as its definition in the domain XML. The set of attributes used
 * to match the device are internal to the drivers. Using a partial
definition,
 * or attempting to detach a device that is not present in the domain XML,
 * but shares some specific attributes with one that is present,
 * may lead to unexpected results.
 */

I'm open for discussion though.

Michal




More information about the libvir-list mailing list