...
> > + bool changed;
> > + virNodeDeviceDefPtr olddef =
> > virNodeDeviceObjGetDef(obj); +
> > + was_defined = virNodeDeviceObjIsPersistent(obj);
>
> "defined" as a name will do just fine
>
> > + /* Active devices contain some additional information
> > (e.g. sysfs
> > + * path) that is not provided by mdevctl, so re-use
> > the existing
> > + * definition and copy over new mdev data */
> > + changed = nodeDeviceDefCopyFromMdevctl(olddef, def);
> > +
> > + /* Re-use the existing definition (after merging new
> > data from
> > + * mdevctl), so def needs to be freed at the end of
> > the function */
> > + tofree = g_list_prepend(tofree, def);
>
> I'm not a fan of ^this. Plain g_autoptr on virNodeDeviceDef would
> do just fine.
I'm not a fan of it either, but g_autoptr is not ideal here either.
The def must not be freed if it is a new device (because
virNodeDeviceObjListAssignDef() takes ownership of the def). So we'd
have to make sure we steal the autoptr in that case. But we have to use
it after we'd need to clear it (in order to emit the lifecycle event,
etc).
But there's also another reason I took this approach. In patch 11
("handle mdevs that disappear..."), we need to use the entire list of
devices ('defs') to scan for devices that have disappeared. So I had
to keep the entire list of defs until the end of the function where we
traversed the list looking for removed devices to emit a lifecycle
event. I could potentially move this check to the beginning of the
function to get around the need to keep the defs around until the end
of the function, though...
I can try to rework it if you think it necessary.
I think purging non-existent devices at the beginning of the function is fine,
maybe even desirable. As for the ownership, you only need def->name for events
so I think it would still be easily doable by dropping the 'tofree' list.
...
> > + if
(STRNEQ_NULLABLE(src->attributes[i]->value,
> > + dst->attributes[i]->value)) {
> > + ret = true;
> > + dst->attributes[i]->value =
> > + g_strdup(src->attributes[i]->value);
> > + }
> > + }
>
> I think we can just straight overwrite all the data in question, yes,
> some CPU cycles will be wasted, but time complexity remains at O(n)
> and readability improves significantly. These are mdev devices, so I
> doubt this is an RT critical feature. The function can then remain as
> void.
It's perhaps not obvious, but I specifically added these checks and
return value in order to avoid an issue that Daniel pointed out where I
was emitting update events for every device regardless of whether they
had changed or not. So rather than inventing a new function to check for
node device equality and only copy over the new data if they weren't
equal, I incorporated the equality check into the update function so
that I could check it and update it in the same call. See above where I
use the 'changed' variable in nodeDeviceUpdateMediatedDevices().
Darn...yeah, I missed that, it's fine as it is then.
...
> > + if (def->caps->data.type ==
VIR_NODE_DEV_CAP_MDEV)
> > + nodeDeviceDefCopyFromMdevctl(def, objdef);
> > + was_persistent = virNodeDeviceObjIsPersistent(obj);
> > + /* If the device was defined by mdevctl and was never
> > instantiated, it
> > + * won't have a sysfs path. We need to emit a CREATED
> > event... */
>
> Why CREATED instead of DEFINED?
Because this is handling a udev event. udev only deals with with
instantiated mdevs, not persistent mdev definitions.
In other words, mdevctl determines whether a mdev is DEFINED or
UNDEFINED, and udev determines whether a devices is CREATED or DELETED.
Okay, thanks for refreshing my memory.
Erik