On Thu, Dec 24, 2020 at 08:14:30AM -0600, Jonathon Jongsma wrote:
Since a mediated device can be persistently defined by the mdevctl
backend, we need additional lifecycle events beyond CREATED/DELETED to
indicate that e.g. the device has been stopped but the device definition
still exists.
This doesn't feel right to me. STARTED/STOPPED are esstentially
the same as CREATED/DELETED semantically. None of the other APIs
emit different events for persistent vs transient objects.
We're adding the ability to define/undefine inactive mdev configs,
so what is missing is the DEFINED/UNDEFINED events I believe.
Signed-off-by: Jonathon Jongsma <jjongsma(a)redhat.com>
---
examples/c/misc/event-test.c | 4 ++++
include/libvirt/libvirt-nodedev.h | 2 ++
src/conf/node_device_conf.h | 1 +
src/node_device/node_device_driver.c | 1 +
src/node_device/node_device_udev.c | 25 +++++++++++++++++++++++--
tools/virsh-nodedev.c | 4 +++-
6 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c
index f164e825e1..d6eec648ec 100644
--- a/examples/c/misc/event-test.c
+++ b/examples/c/misc/event-test.c
@@ -381,6 +381,10 @@ nodeDeviceEventToString(int event)
return "Created";
case VIR_NODE_DEVICE_EVENT_DELETED:
return "Deleted";
+ case VIR_NODE_DEVICE_EVENT_STOPPED:
+ return "Stopped";
+ case VIR_NODE_DEVICE_EVENT_STARTED:
+ return "Started";
case VIR_NODE_DEVICE_EVENT_LAST:
break;
}
diff --git a/include/libvirt/libvirt-nodedev.h b/include/libvirt/libvirt-nodedev.h
index d304283871..a473563857 100644
--- a/include/libvirt/libvirt-nodedev.h
+++ b/include/libvirt/libvirt-nodedev.h
@@ -197,6 +197,8 @@ int virConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
typedef enum {
VIR_NODE_DEVICE_EVENT_CREATED = 0,
VIR_NODE_DEVICE_EVENT_DELETED = 1,
+ VIR_NODE_DEVICE_EVENT_STOPPED = 2,
+ VIR_NODE_DEVICE_EVENT_STARTED = 3,
# ifdef VIR_ENUM_SENTINELS
VIR_NODE_DEVICE_EVENT_LAST
diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
index 3d7872fd6e..bbc28cf2b9 100644
--- a/src/conf/node_device_conf.h
+++ b/src/conf/node_device_conf.h
@@ -157,6 +157,7 @@ struct _virNodeDevCapMdev {
char *uuid;
virMediatedDeviceAttrPtr *attributes;
size_t nattributes;
+ bool persistent;
};
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index bbd373e32e..5309b8abd5 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -899,6 +899,7 @@ nodeDeviceParseMdevctlChildDevice(const char *parent,
child->caps->data.type = VIR_NODE_DEV_CAP_MDEV;
mdev = &child->caps->data.mdev;
+ mdev->persistent = true;
mdev->uuid = g_strdup(uuid);
mdev->type =
g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index be59e6c6bc..632413d046 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1401,6 +1401,8 @@ udevRemoveOneDeviceSysPath(const char *path)
virNodeDeviceObjPtr obj = NULL;
virNodeDeviceDefPtr def;
virObjectEventPtr event = NULL;
+ virNodeDevCapsDefPtr cap;
+ int event_type = VIR_NODE_DEVICE_EVENT_DELETED;
if (!(obj = virNodeDeviceObjListFindBySysfsPath(driver->devs, path))) {
VIR_DEBUG("Failed to find device to remove that has udev path
'%s'",
@@ -1409,13 +1411,32 @@ udevRemoveOneDeviceSysPath(const char *path)
}
def = virNodeDeviceObjGetDef(obj);
+ /* If the device is a mediated device that has been 'stopped', it may still
+ * be defined by mdevctl and can therefore be started again. Don't drop it
+ * from the list of node devices */
+ cap = def->caps;
+ while (cap != NULL) {
+ if (cap->data.type == VIR_NODE_DEV_CAP_MDEV) {
+ if (cap->data.mdev.persistent) {
+ VIR_FREE(def->sysfs_path);
+ event_type = VIR_NODE_DEVICE_EVENT_STOPPED;
+ break;
+ }
+ }
+ cap = cap->next;
+ }
+
event = virNodeDeviceEventLifecycleNew(def->name,
- VIR_NODE_DEVICE_EVENT_DELETED,
+ event_type,
0);
VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
def->name, path);
- virNodeDeviceObjListRemove(driver->devs, obj);
+
+ if (event_type == VIR_NODE_DEVICE_EVENT_DELETED)
+ virNodeDeviceObjListRemove(driver->devs, obj);
+ else
+ virNodeDeviceObjSetActive(obj, false);
virNodeDeviceObjEndAPI(&obj);
virObjectEventStateQueue(driver->nodeDeviceEventState, event);
diff --git a/tools/virsh-nodedev.c b/tools/virsh-nodedev.c
index 69422e20f5..35117585ff 100644
--- a/tools/virsh-nodedev.c
+++ b/tools/virsh-nodedev.c
@@ -775,7 +775,9 @@ VIR_ENUM_DECL(virshNodeDeviceEvent);
VIR_ENUM_IMPL(virshNodeDeviceEvent,
VIR_NODE_DEVICE_EVENT_LAST,
N_("Created"),
- N_("Deleted"));
+ N_("Deleted"),
+ N_("Stopped"),
+ N_("Started"));
static const char *
virshNodeDeviceEventToString(int event)
--
2.26.2
Regards,
Daniel
--
|:
https://berrange.com -o-
https://www.flickr.com/photos/dberrange :|
|:
https://libvirt.org -o-
https://fstop138.berrange.com :|
|:
https://entangle-photo.org -o-
https://www.instagram.com/dberrange :|