[libvirt] [PATCH 1/3] nodedev: Add driver callback mechanism to add/remove devices

John Ferlan jferlan at redhat.com
Thu Feb 9 20:41:09 UTC 2017



On 02/09/2017 07:52 AM, Bjoern Walk wrote:

[...]

>> virNodeDeviceObjListFree(virNodeDeviceObjListPtr devs)
>> virNodeDeviceObjPtr virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs,
>>                                            virNodeDeviceDefPtr def)
>> {
>> +    size_t i;
>>     virNodeDeviceObjPtr device;
>>
>>     if ((device = virNodeDeviceFindByName(devs, def->name))) {
>> @@ -315,6 +417,18 @@ virNodeDeviceObjPtr
>> virNodeDeviceAssignDef(virNodeDeviceObjListPtr devs,
>>     }
>>     device->def = def;
>>
>> +    /* Call any registered drivers that want to be notified of a new
>> device */
>> +    for (i = 0; i < nodeDeviceCallbackDriver; i++) {
>> +        if (nodeDeviceDrvArray[i]->nodeDeviceAdd(def, false) < 0) {
>> +            VIR_DELETE_ELEMENT(devs->objs, devs->count - 1,
>> devs->count);
> 
> I don't understand the reasoning why a failure to process the device on
> one listening driver leads to the complete rejection of the device in
> the node device driver.
> 

That's why there's a code review ;-)  If I write this without a failure,
someone could query why I chose that!

One can consider this like an event - failing to fail means the event
isn't delivered. If there are nodedev types that rely on one another
that could be a problem.

For example, a scsi_target relies on a scsi_host being present. If we
skip/ignore the scsi_host event, then the subsequent scsi_target event
will fail to find the scsi_host and fail as well.

So how does one "fix" that? That is how to "re"-enumerate. In any case,
at least a way to message a failure via VIR_WARN I think would be
necessary. I'm fine with not failing out.

>> +            virNodeDeviceObjUnlock(device);
>> +            virNodeDeviceObjFree(device);
>> +            /* NB: If we fail to remove from one driver - it's not a
>> problem
>> +             * since adding a new device wouldn't fail if already
>> found */
>> +            return NULL;
>> +        }
>> +    }
>> +
>>     return device;

[...]

>> diff --git a/src/node_device/node_device_udev.c
>> b/src/node_device/node_device_udev.c
>> index 4b81312..ea6970b 100644
>> --- a/src/node_device/node_device_udev.c
>> +++ b/src/node_device/node_device_udev.c
>> @@ -1457,6 +1457,33 @@ static int udevPCITranslateInit(bool privileged
>> ATTRIBUTE_UNUSED)
>>     return 0;
>> }
>>
>> +
>> +/*
>> + * @deviceAddCb: Callback routine for adding a device
>> + *
>> + * Enumerate all known devices calling the add device callback function
>> + *
>> + * Returns 0 on success, -1 on failure
>> + */
>> +static int
>> +udevEnumerateAddDevices(virNodeDeviceAdd deviceAddCb)
>> +{
>> +    size_t i;
>> +    int ret = 0;
>> +
>> +    nodeDeviceLock();
>> +    for (i = 0; i < driver->devs.count && ret >= 0; i++) {
>> +        virNodeDeviceObjPtr obj = driver->devs.objs[i];
>> +        virNodeDeviceObjLock(obj);
>> +        ret = deviceAddCb(obj->def, true);
>> +        virNodeDeviceObjUnlock(obj);
>> +    }
>> +    nodeDeviceUnlock();
>> +
>> +    return ret;
>> +}
>> +
>> +
>> static int nodeStateInitialize(bool privileged,
>>                                virStateInhibitCallback callback
>> ATTRIBUTE_UNUSED,
>>                                void *opaque ATTRIBUTE_UNUSED)
>> @@ -1535,6 +1562,8 @@ static int nodeStateInitialize(bool privileged,
>>     if (udevEnumerateDevices(udev) != 0)
>>         goto cleanup;
>>
>> +    virNodeDeviceConfEnumerateInit(udevEnumerateAddDevices);
> 
> I don't quite see the need for this callback indirection. What other
> drivers want to implement a different enumeration method for devices?
> 

I struggled with a couple of different mechanisms in order to enumerate
the "existing" node devices as the node devices are discovered/added in
virNodeDeviceAssignDef before qemu is started.

The one thing I really needed was a way to traverse the node device
objects in order to grab/pass the node device def since vHBA creation
would need to know the wwnn/wwpn to search/match a domain definition
with the same wwnn/wwpn.

So one option was to call the virConnectListAllNodeDevices in order to
get a list of all devices by name (and well parent if the other patch is
ACK'd and pushed). Having the name/parent wasn't quite enough as I
needed to get the virNodeDeviceDefPtr (because I'd need the wwnn/wwpn).
There is a virNodeDeviceGetWWNs API, but it requires a node device ptr.

Another option would be to add an API that would take a name and perform
the wwnn/wwpn fetch based on that. Similar to the virConnect API - that
would require having a connection pointer.

So I chose this methodology which allowed the udev driver to provide the
enumeration API that virNodeDeviceRegisterCallbackDriver would be able
to call.  But of course I see your point (now) - how would a different
driver registration be able to delineate which cb API to call. Of course
it solved *my* problem, but isn't quite generic enough I guess <sigh>.

Going to need to think of a different mechanism I guess... Drat.  Any
suggestions? ;-)


John
>> +
>>     ret = 0;
>>
>>  cleanup:
>> -- 
>> 2.7.4
>>
>> -- 
>> libvir-list mailing list
>> libvir-list at redhat.com
>> https://www.redhat.com/mailman/listinfo/libvir-list
>>
> 




More information about the libvir-list mailing list