The virNodeDeviceDettach() API recently required an update via the
addition of a "driver" and "flags" argument in the new
virNodeDeviceDetachFlags() API. This was initially done so that the
user could specify which stub driver was to be attached (with a new
"driver" char* argument), and a flags argument was added for good
measure. The flags argument has now been put to good use in order to
specify whether all devices in the same group as the specified device
should also be detached.
It turns out that, although the driver name isn't required for
virNodeDeviceReAttach() (since it can be found by looking at the
device's driver binding), it *is* necessary to provide a "reattach
entire group" flag. Because of this, we now also need a new
virNodeDeviceReAttachFlags() API, which is otherwise identical to
virNodeDeviceReAttach(). A single flag is defined for this new API:
VIR_NODE_DEVICE_REATTACH_GROUP
The effect of this flag is the following: If this device was bound to
the vfio-pci driver, only re-attach it to its host driver if all other
devices in the same group are also not assigned to any guest, and in
that case re-attach *all* devices in the group that are currently
attached to the vfio-pci driver to their respective host drivers. (In
practice this is actually much less confusing than it sounds in this
explanation).
---
include/libvirt/libvirt.h.in | 8 ++++++
src/driver.h | 5 ++++
src/libvirt.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 4 +++
4 files changed, 77 insertions(+)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index ba471b2..7343665 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -3305,7 +3305,15 @@ int virNodeDeviceDettach (virNodeDevicePtr
dev);
int virNodeDeviceDetachFlags(virNodeDevicePtr dev,
const char *driverName,
unsigned int flags);
+
+typedef enum {
+ VIR_NODE_DEVICE_REATTACH_GROUP = 1 << 0, /* reattach all devices in same group
*/
+} virNodeDeviceReAttachFlagsType;
+
int virNodeDeviceReAttach (virNodeDevicePtr dev);
+int virNodeDeviceReAttachFlags(virNodeDevicePtr dev,
+ unsigned int flags);
+
int virNodeDeviceReset (virNodeDevicePtr dev);
virNodeDevicePtr virNodeDeviceCreateXML (virConnectPtr conn,
diff --git a/src/driver.h b/src/driver.h
index ec5fc53..f5b7005 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -626,6 +626,10 @@ typedef int
(*virDrvNodeDeviceReAttach)(virNodeDevicePtr dev);
typedef int
+(*virDrvNodeDeviceReAttachFlags)(virNodeDevicePtr dev,
+ unsigned int flags);
+
+typedef int
(*virDrvNodeDeviceReset)(virNodeDevicePtr dev);
typedef int
@@ -1173,6 +1177,7 @@ struct _virDriver {
virDrvNodeDeviceDettach nodeDeviceDettach;
virDrvNodeDeviceDetachFlags nodeDeviceDetachFlags;
virDrvNodeDeviceReAttach nodeDeviceReAttach;
+ virDrvNodeDeviceReAttachFlags nodeDeviceReAttachFlags;
virDrvNodeDeviceReset nodeDeviceReset;
virDrvDomainMigratePrepareTunnel domainMigratePrepareTunnel;
virDrvConnectIsEncrypted connectIsEncrypted;
diff --git a/src/libvirt.c b/src/libvirt.c
index db120b7..4144998 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -14839,6 +14839,10 @@ error:
*
* If the device is currently in use by a guest, this method may fail.
*
+ * If the caller needs control over any options during the reattach
+ * then the newer virNodeDeviceReAttachFlags() API should be used
+ * instead.
+ *
* Returns 0 in case of success, -1 in case of failure.
*/
int
@@ -14875,6 +14879,62 @@ error:
}
/**
+ * virNodeDeviceReAttachFlags:
+ * @dev: pointer to the node device
+ * @flags: extra flags; Currently there is one possible flag:
+ *
+ * VIR_NODE_DEVICE_REATTACH_GROUP: If this device was bound to the
+ * vfio-pci driver, only re-attach it to its host driver if all
+ * other devices in the same group are also not assigned to any
+ * guest, and in that case re-attach *all* devices in the group
+ * that are currently attached to the vfio-pci driver to their
+ * respective host drivers.
+ *
+ * Re-attach a previously dettached node device to the node so that it
+ * may be used by the node again.
+ *
+ * Depending on the hypervisor, this may involve operations such
+ * as resetting the device, unbinding it from a dummy device driver
+ * and binding it to its appropriate driver.
+ *
+ * If the device is currently in use by a guest, this method may fail.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+int
+virNodeDeviceReAttachFlags(virNodeDevicePtr dev, unsigned int flags)
+{
+ VIR_DEBUG("dev=%p, conn=%p flags=%x", dev, dev ? dev->conn : NULL,
flags);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
+ virLibNodeDeviceError(VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (dev->conn->flags & VIR_CONNECT_RO) {
+ virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+ goto error;
+ }
+
+ if (dev->conn->driver->nodeDeviceReAttachFlags) {
+ int ret;
+ ret = dev->conn->driver->nodeDeviceReAttachFlags(dev, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ virDispatchError(dev->conn);
+ return -1;
+}
+
+/**
* virNodeDeviceReset:
* @dev: pointer to the node device
*
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 4ee2d27..82968a0 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -621,4 +621,8 @@ LIBVIRT_1.0.6 {
virGetLastErrorMessage;
} LIBVIRT_1.0.5;
+LIBVIRT_1.0.7 {
+ global:
+ virNodeDeviceReAttachFlags;
+} LIBVIRT_1.0.6;
# .... define new API here using predicted next version number ....
--
1.7.11.7