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(a)redhat.com
>
https://www.redhat.com/mailman/listinfo/libvir-list
>