Before starting a guest virNodeDeviceAttach() is intended
to be called on all node devices to be assigned to a guest,
followed by virNodeDeviceReset() on those devices.
Once the guest has been shutdown, virNodeDeviceReset()
followed by virNodeDeviceReAttach() should be called in
order to make the device available to the host again.
This patch merely adds the APIs and stubs out the driver
implementations.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
---
include/libvirt/libvirt.h | 4 +
include/libvirt/libvirt.h.in | 4 +
src/driver.h | 13 ++++
src/libvirt.c | 129 ++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 3 +
src/lxc_driver.c | 3 +
src/openvz_driver.c | 3 +
src/qemu_driver.c | 3 +
src/test.c | 3 +
src/uml_driver.c | 3 +
10 files changed, 168 insertions(+), 0 deletions(-)
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index e32d40b..cf39488 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -1053,6 +1053,10 @@ char * virNodeDeviceGetXMLDesc (virNodeDevicePtr
dev,
int virNodeDeviceRef (virNodeDevicePtr dev);
int virNodeDeviceFree (virNodeDevicePtr dev);
+int virNodeDeviceDettach (virNodeDevicePtr dev);
+int virNodeDeviceReAttach (virNodeDevicePtr dev);
+int virNodeDeviceReset (virNodeDevicePtr dev);
+
/*
* Domain Event Notification
*/
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index af97bfd..06361de 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1053,6 +1053,10 @@ char * virNodeDeviceGetXMLDesc (virNodeDevicePtr
dev,
int virNodeDeviceRef (virNodeDevicePtr dev);
int virNodeDeviceFree (virNodeDevicePtr dev);
+int virNodeDeviceDettach (virNodeDevicePtr dev);
+int virNodeDeviceReAttach (virNodeDevicePtr dev);
+int virNodeDeviceReset (virNodeDevicePtr dev);
+
/*
* Domain Event Notification
*/
diff --git a/src/driver.h b/src/driver.h
index 32d4257..ffb95dc 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -313,6 +313,16 @@ typedef virDomainPtr
unsigned long flags,
int retcode);
+typedef int
+ (*virDrvNodeDeviceDettach)
+ (virNodeDevicePtr dev);
+typedef int
+ (*virDrvNodeDeviceReAttach)
+ (virNodeDevicePtr dev);
+typedef int
+ (*virDrvNodeDeviceReset)
+ (virNodeDevicePtr dev);
+
/**
* _virDriver:
*
@@ -387,6 +397,9 @@ struct _virDriver {
virDrvDomainEventDeregister domainEventDeregister;
virDrvDomainMigratePrepare2 domainMigratePrepare2;
virDrvDomainMigrateFinish2 domainMigrateFinish2;
+ virDrvNodeDeviceDettach nodeDeviceDettach;
+ virDrvNodeDeviceReAttach nodeDeviceReAttach;
+ virDrvNodeDeviceReset nodeDeviceReset;
};
typedef int
diff --git a/src/libvirt.c b/src/libvirt.c
index 038a1ac..bc444dd 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -7286,6 +7286,135 @@ virNodeDeviceRef(virNodeDevicePtr dev)
return 0;
}
+/**
+ * virNodeDeviceAttach:
+ * @dev: pointer to the node device
+ *
+ * Dettach the node device from the node itself so that it may be
+ * assigned to a guest domain.
+ *
+ * Depending on the hypervisor, this may involve operations such
+ * as unbinding any device drivers from the device, binding the
+ * device to a dummy device driver and resetting the device.
+ *
+ * If the device is currently in use by the node, this method may
+ * fail.
+ *
+ * Once the device is not assigned to any guest, it may be re-attached
+ * to the node using the virNodeDeviceReattach() method.
+ */
+int
+virNodeDeviceDettach(virNodeDevicePtr dev)
+{
+ DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
+ virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
+ return (-1);
+ }
+
+ if (dev->conn->driver->nodeDeviceDettach) {
+ int ret;
+ ret = dev->conn->driver->nodeDeviceDettach (dev);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virSetConnError(dev->conn);
+ return (-1);
+}
+
+/**
+ * virNodeDeviceReAttach:
+ * @dev: pointer to the node device
+ *
+ * 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.
+ */
+int
+virNodeDeviceReAttach(virNodeDevicePtr dev)
+{
+ DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
+ virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
+ return (-1);
+ }
+
+ if (dev->conn->driver->nodeDeviceReAttach) {
+ int ret;
+ ret = dev->conn->driver->nodeDeviceReAttach (dev);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virSetConnError(dev->conn);
+ return (-1);
+}
+
+/**
+ * virNodeDeviceReset:
+ * @dev: pointer to the node device
+ *
+ * Reset a previously dettached node device to the node before or
+ * after assigning it to a guest.
+ *
+ * The exact reset semantics depends on the hypervisor and device
+ * type but, for example, KVM will attempt to reset PCI devices with
+ * a Function Level Reset, Secondary Bus Reset or a Power Management
+ * D-State reset.
+ *
+ * If the reset will affect other devices which are currently in use,
+ * this function may fail.
+ */
+int
+virNodeDeviceReset(virNodeDevicePtr dev)
+{
+ DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL);
+
+ virResetLastError();
+
+ if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) {
+ virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__);
+ return (-1);
+ }
+
+ if (dev->conn->driver->nodeDeviceReset) {
+ int ret;
+ ret = dev->conn->driver->nodeDeviceReset (dev);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virLibConnError(dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+ /* Copy to connection error object for back compatability */
+ virSetConnError(dev->conn);
+ return (-1);
+}
+
/*
* Domain Event Notification
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 1422e4c..8114073 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -251,6 +251,9 @@ LIBVIRT_0.6.1 {
global:
virFreeError;
virSaveLastError;
+ virNodeDeviceDettach;
+ virNodeDeviceReAttach;
+ virNodeDeviceReset;
} LIBVIRT_0.6.0;
# .... define new API here using predicted next version number ....
diff --git a/src/lxc_driver.c b/src/lxc_driver.c
index aa417a9..28f2c6f 100644
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -1455,6 +1455,9 @@ static virDriver lxcDriver = {
NULL, /* domainEventDeregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceAttach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
};
static virStateDriver lxcStateDriver = {
diff --git a/src/openvz_driver.c b/src/openvz_driver.c
index e004819..b4d9128 100644
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -1325,6 +1325,9 @@ static virDriver openvzDriver = {
NULL, /* domainEventDeregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceAttach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
};
int openvzRegister(void) {
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index a8a2ae7..c2dfc71 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -4542,6 +4542,9 @@ static virDriver qemuDriver = {
qemudDomainEventDeregister, /* domainEventDeregister */
qemudDomainMigratePrepare2, /* domainMigratePrepare2 */
qemudDomainMigrateFinish2, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceDettach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
};
diff --git a/src/test.c b/src/test.c
index 226fe2e..833faf0 100644
--- a/src/test.c
+++ b/src/test.c
@@ -3527,6 +3527,9 @@ static virDriver testDriver = {
testDomainEventDeregister, /* domainEventDeregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceAttach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
};
static virNetworkDriver testNetworkDriver = {
diff --git a/src/uml_driver.c b/src/uml_driver.c
index c5a06a2..aec22ec 100644
--- a/src/uml_driver.c
+++ b/src/uml_driver.c
@@ -1885,6 +1885,9 @@ static virDriver umlDriver = {
NULL, /* domainEventUnregister */
NULL, /* domainMigratePrepare2 */
NULL, /* domainMigrateFinish2 */
+ NULL, /* nodeDeviceAttach */
+ NULL, /* nodeDeviceReAttach */
+ NULL, /* nodeDeviceReset */
};
--
1.6.0.6