[libvirt PATCH 2/7] nodedev: implement virNodeDevice(Get|Set)Autostart()
Jonathon Jongsma
jjongsma at redhat.com
Fri Jun 4 16:48:03 UTC 2021
On Fri, Jun 4, 2021 at 3:07 AM Daniel P. Berrangé <berrange at redhat.com> wrote:
>
> On Thu, Jun 03, 2021 at 03:11:51PM -0500, Jonathon Jongsma wrote:
> > Implement autostart functionality for mediated devices.
> >
> > Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
> > ---
> > src/conf/virnodedeviceobj.c | 16 ++++
> > src/conf/virnodedeviceobj.h | 6 ++
> > src/libvirt_private.syms | 2 +
> > src/node_device/node_device_driver.c | 116 +++++++++++++++++++++++++++
> > src/node_device/node_device_driver.h | 13 +++
> > src/node_device/node_device_udev.c | 19 ++++-
> > 6 files changed, 171 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c
> > index b213592b56..deee796440 100644
> > --- a/src/conf/virnodedeviceobj.c
> > +++ b/src/conf/virnodedeviceobj.c
> > @@ -41,6 +41,7 @@ struct _virNodeDeviceObj {
> > used by testdriver */
> > bool active;
> > bool persistent;
> > + bool autostart;
> > };
> >
> > struct _virNodeDeviceObjList {
> > @@ -1026,6 +1027,21 @@ virNodeDeviceObjSetPersistent(virNodeDeviceObj *obj,
> > }
> >
> >
> > +bool
> > +virNodeDeviceObjIsAutostart(virNodeDeviceObj *obj)
> > +{
> > + return obj->autostart;
> > +}
> > +
> > +
> > +void
> > +virNodeDeviceObjSetAutostart(virNodeDeviceObj *obj,
> > + bool autostart)
> > +{
> > + obj->autostart = autostart;
> > +}
> > +
> > +
> > struct virNodeDeviceObjListRemoveHelperData
> > {
> > virNodeDeviceObjListRemoveIterator callback;
> > diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h
> > index 7353e4619b..78188be2a2 100644
> > --- a/src/conf/virnodedeviceobj.h
> > +++ b/src/conf/virnodedeviceobj.h
> > @@ -135,6 +135,12 @@ virNodeDeviceObjIsPersistent(virNodeDeviceObj *obj);
> > void
> > virNodeDeviceObjSetPersistent(virNodeDeviceObj *obj,
> > bool persistent);
> > +bool
> > +virNodeDeviceObjIsAutostart(virNodeDeviceObj *obj);
> > +
> > +void
> > +virNodeDeviceObjSetAutostart(virNodeDeviceObj *obj,
> > + bool autostart);
> >
> > typedef bool (*virNodeDeviceObjListRemoveIterator)(virNodeDeviceObj *obj,
> > const void *opaque);
> > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> > index 0ced2a7990..dd46fe8750 100644
> > --- a/src/libvirt_private.syms
> > +++ b/src/libvirt_private.syms
> > @@ -1278,6 +1278,7 @@ virNetworkPortDefSaveStatus;
> > virNodeDeviceObjEndAPI;
> > virNodeDeviceObjGetDef;
> > virNodeDeviceObjIsActive;
> > +virNodeDeviceObjIsAutostart;
> > virNodeDeviceObjIsPersistent;
> > virNodeDeviceObjListAssignDef;
> > virNodeDeviceObjListExport;
> > @@ -1294,6 +1295,7 @@ virNodeDeviceObjListNumOfDevices;
> > virNodeDeviceObjListRemove;
> > virNodeDeviceObjListRemoveLocked;
> > virNodeDeviceObjSetActive;
> > +virNodeDeviceObjSetAutostart;
> > virNodeDeviceObjSetPersistent;
> >
> >
> > diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
> > index 8a0a2c3847..9ebe609aa4 100644
> > --- a/src/node_device/node_device_driver.c
> > +++ b/src/node_device/node_device_driver.c
> > @@ -962,6 +962,46 @@ virMdevctlStart(virNodeDeviceDef *def, char **errmsg)
> > }
> >
> >
> > +/* gets a virCommand object that executes a mdevctl command to set the
> > + * 'autostart' property of the device to the specified value
> > + */
> > +virCommand*
> > +nodeDeviceGetMdevctlSetAutostartCommand(virNodeDeviceDef *def,
> > + bool autostart,
> > + char **errmsg)
> > +{
> > + virCommand *cmd = virCommandNewArgList(MDEVCTL,
> > + "modify",
> > + "--uuid",
> > + def->caps->data.mdev.uuid,
> > + NULL);
> > +
> > + if (autostart)
> > + virCommandAddArg(cmd, "--auto");
> > + else
> > + virCommandAddArg(cmd, "--manual");
> > +
> > + virCommandSetErrorBuffer(cmd, errmsg);
> > +
> > + return cmd;
> > +}
> > +
> > +
> > +static int
> > +virMdevctlSetAutostart(virNodeDeviceDef *def, bool autostart, char **errmsg)
> > +{
> > + int status;
> > + g_autoptr(virCommand) cmd = NULL;
> > +
> > + cmd = nodeDeviceGetMdevctlSetAutostartCommand(def, autostart, errmsg);
> > +
> > + if (virCommandRun(cmd, &status) < 0 || status != 0)
> > + return -1;
> > +
> > + return 0;
> > +}
> > +
> > +
> > virCommand*
> > nodeDeviceGetMdevctlListCommand(bool defined,
> > char **output,
> > @@ -1688,3 +1728,79 @@ nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
> >
> > return ret;
> > }
> > +
> > +
> > +int
> > +nodeDeviceSetAutostart(virNodeDevice *device,
> > + int autostart)
> > +{
> > + int ret = -1;
> > + virNodeDeviceObj *obj = NULL;
> > + virNodeDeviceDef *def = NULL;
> > +
> > + if (nodeDeviceInitWait() < 0)
> > + return -1;
> > +
> > + if (!(obj = nodeDeviceObjFindByName(device->name)))
> > + return -1;
> > + def = virNodeDeviceObjGetDef(obj);
> > +
> > + if (virNodeDeviceSetAutostartEnsureACL(device->conn, def) < 0)
> > + goto cleanup;
> > +
> > + if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
> > + if (!virNodeDeviceObjIsPersistent(obj)) {
> > + virReportError(VIR_ERR_OPERATION_INVALID,
> > + "%s", _("cannot set autostart for transient device"));
> > + goto cleanup;
> > + }
> > +
> > + if (autostart != virNodeDeviceObjIsAutostart(obj)) {
> > + g_autofree char *errmsg = NULL;
> > +
> > + if (virMdevctlSetAutostart(def, autostart, &errmsg) < 0) {
> > + virReportError(VIR_ERR_INTERNAL_ERROR,
> > + _("Unable to set autostart on '%s': %s"),
> > + def->name,
> > + errmsg && errmsg[0] != '\0' ? errmsg : _("Unknown Error"));
> > + goto cleanup;
> > + }
> > + virNodeDeviceObjSetAutostart(obj, autostart);
> > + }
> > + ret = 0;
> > + } else {
> > + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
> > + _("Unsupported device type"));
> > + }
> > +
> > + cleanup:
> > + virNodeDeviceObjEndAPI(&obj);
> > + return ret;
> > +}
> > +
> > +
> > +int
> > +nodeDeviceGetAutostart(virNodeDevice *device,
> > + int *autostart)
> > +{
> > + virNodeDeviceObj *obj = NULL;
> > + virNodeDeviceDef *def = NULL;
> > + int ret = -1;
> > +
> > + if (nodeDeviceInitWait() < 0)
> > + return -1;
> > +
> > + if (!(obj = nodeDeviceObjFindByName(device->name)))
> > + return -1;
> > + def = virNodeDeviceObjGetDef(obj);
> > +
> > + if (virNodeDeviceGetAutostartEnsureACL(device->conn, def) < 0)
> > + goto cleanup;
> > +
> > + *autostart = virNodeDeviceObjIsAutostart(obj);
> > + ret = 0;
> > +
> > + cleanup:
> > + virNodeDeviceObjEndAPI(&obj);
> > + return ret;
> > +}
> > diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h
> > index edd763f0e4..d178a18180 100644
> > --- a/src/node_device/node_device_driver.h
> > +++ b/src/node_device/node_device_driver.h
> > @@ -171,3 +171,16 @@ bool nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
> > int
> > nodeDeviceCreate(virNodeDevice *dev,
> > unsigned int flags);
> > +
> > +int
> > +nodeDeviceSetAutostart(virNodeDevice *dev,
> > + int autostart);
> > +
> > +int
> > +nodeDeviceGetAutostart(virNodeDevice *dev,
> > + int *autostart);
> > +
> > +virCommand*
> > +nodeDeviceGetMdevctlSetAutostartCommand(virNodeDeviceDef *def,
> > + bool autostart,
> > + char **errmsg);
> > diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
> > index f99578414d..21273083a6 100644
> > --- a/src/node_device/node_device_udev.c
> > +++ b/src/node_device/node_device_udev.c
> > @@ -1488,6 +1488,8 @@ udevAddOneDevice(struct udev_device *device)
> > bool new_device = true;
> > int ret = -1;
> > bool was_persistent = false;
> > + bool autostart = true;
> > + bool is_mdev;
> >
> > def = g_new0(virNodeDeviceDef, 1);
> >
> > @@ -1509,17 +1511,28 @@ udevAddOneDevice(struct udev_device *device)
> > if (udevSetParent(device, def) != 0)
> > goto cleanup;
> >
> > + is_mdev = def->caps->data.type == VIR_NODE_DEV_CAP_MDEV;
> > +
> > if ((obj = virNodeDeviceObjListFindByName(driver->devs, def->name))) {
> > objdef = virNodeDeviceObjGetDef(obj);
> >
> > - if (def->caps->data.type == VIR_NODE_DEV_CAP_MDEV)
> > + if (is_mdev)
> > nodeDeviceDefCopyFromMdevctl(def, objdef);
> > was_persistent = virNodeDeviceObjIsPersistent(obj);
> > + autostart = virNodeDeviceObjIsAutostart(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... */
> > new_device = (objdef->sysfs_path == NULL);
> >
> > virNodeDeviceObjEndAPI(&obj);
> > + } else {
> > + /* All non-mdev devices report themselves as autostart since they
> > + * should still be present and active after a reboot unless the device
> > + * is removed from the host. Mediated devices can only be persistent if
> > + * they are in already in the device list from parsing the mdevctl
> > + * output. */
> > + autostart = !is_mdev;
>
> Don't we need to be querying the mdevctl configuration to see if it is
> autostart or manual ?
Yes, clearly. I accidentally left it out of this patch. New version
coming shortly.
Jonathon
More information about the libvir-list
mailing list