aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Levon <john.levon@nutanix.com>2021-04-06 15:55:02 +0100
committerGitHub <noreply@github.com>2021-04-06 15:55:02 +0100
commitc42ac841ad1d0094d6f6173e4f8bb4f231f8962b (patch)
tree050ed4bbd37d65dc8e71ede1ce310a6efd285d8f
parent0b722b79212dfd4a5fb6f7b9137c27f27bd46105 (diff)
downloadlibvfio-user-c42ac841ad1d0094d6f6173e4f8bb4f231f8962b.zip
libvfio-user-c42ac841ad1d0094d6f6173e4f8bb4f231f8962b.tar.gz
libvfio-user-c42ac841ad1d0094d6f6173e4f8bb4f231f8962b.tar.bz2
call reset callback on losing client connection (#419)
Give API users an opportunity to clean up when a client disconnects from the vfio-user socket. Signed-off-by: John Levon <john.levon@nutanix.com> Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
-rw-r--r--include/libvfio-user.h34
-rw-r--r--lib/libvfio-user.c8
-rw-r--r--samples/server.c2
3 files changed, 33 insertions, 11 deletions
diff --git a/include/libvfio-user.h b/include/libvfio-user.h
index 925550a..7413db8 100644
--- a/include/libvfio-user.h
+++ b/include/libvfio-user.h
@@ -187,7 +187,7 @@ void
vfu_log(vfu_ctx_t *vfu_ctx, int level, const char *fmt, ...);
/**
- * Setup logging information.
+ * Set up logging information.
* @vfu_ctx: the libvfio-user context
* @log: logging function
* @level: logging level as defined in syslog(3)
@@ -303,15 +303,35 @@ vfu_setup_region(vfu_ctx_t *vfu_ctx, int region_idx, size_t size,
size_t
vfu_get_migr_register_area_size(void);
+typedef enum vfu_reset_type {
+ /*
+ * Client requested a device reset (for example, as part of a guest VM
+ * reboot). The vfio-user context remains valid, but it's expected that all
+ * ongoing operations are completed or cancelled, and any device state is
+ * reset to a known-good initial state (including any PCI register state).
+ */
+ VFU_RESET_DEVICE,
+ /*
+ * The vfio-user socket client connection was closed or reset. The attached
+ * context is cleaned up after returning from the reset callback, and
+ * vfu_attach_ctx() must be called to establish a new client.
+ */
+ VFU_RESET_LOST_CONN
+} vfu_reset_type_t;
+
/*
- * Callback function that is called when the guest resets the device.
+ * Callback function that is called when the device must be reset.
*/
-typedef int (vfu_reset_cb_t)(vfu_ctx_t *vfu_ctx);
+typedef int (vfu_reset_cb_t)(vfu_ctx_t *vfu_ctx, vfu_reset_type_t type);
/**
- * Setup device reset callback.
+ * Set up device reset callback.
+ *
+ * A reset should ensure that all on-going use of device IRQs or guest memory is
+ * completed or cancelled before returning from the callback.
+ *
* @vfu_ctx: the libvfio-user context
- * @reset: device reset callback (optional)
+ * @reset: device reset callback
*/
int
vfu_setup_device_reset_cb(vfu_ctx_t *vfu_ctx, vfu_reset_cb_t *reset);
@@ -389,7 +409,7 @@ typedef void (vfu_dma_register_cb_t)(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info);
typedef int (vfu_dma_unregister_cb_t)(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info);
/**
- * Setup device DMA registration callbacks. When libvfio-user is notified of a
+ * Set up device DMA registration callbacks. When libvfio-user is notified of a
* DMA range addition or removal, these callbacks will be invoked.
*
* If this function is not called, guest DMA regions are not accessible via
@@ -417,7 +437,7 @@ enum vfu_dev_irq_type {
};
/**
- * Setup device IRQ counts.
+ * Set up device IRQ counts.
* @vfu_ctx: the libvfio-user context
* @type: IRQ type (VFU_DEV_INTX_IRQ ... VFU_DEV_REQ_IRQ)
* @count: number of irqs
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index d9e58e0..b5c7739 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -567,7 +567,7 @@ handle_device_reset(vfu_ctx_t *vfu_ctx)
{
vfu_log(vfu_ctx, LOG_DEBUG, "Device reset called by client");
if (vfu_ctx->reset != NULL) {
- return vfu_ctx->reset(vfu_ctx);
+ return vfu_ctx->reset(vfu_ctx, VFU_RESET_DEVICE);
}
return 0;
}
@@ -1112,6 +1112,10 @@ vfu_reset_ctx(vfu_ctx_t *vfu_ctx, const char *reason)
{
vfu_log(vfu_ctx, LOG_INFO, "%s: %s", __func__, reason);
+ if (vfu_ctx->reset != NULL) {
+ vfu_ctx->reset(vfu_ctx, VFU_RESET_LOST_CONN);
+ }
+
if (vfu_ctx->dma != NULL) {
dma_controller_remove_regions(vfu_ctx->dma);
}
@@ -1413,10 +1417,8 @@ out:
int
vfu_setup_device_reset_cb(vfu_ctx_t *vfu_ctx, vfu_reset_cb_t *reset)
{
-
assert(vfu_ctx != NULL);
vfu_ctx->reset = reset;
-
return 0;
}
diff --git a/samples/server.c b/samples/server.c
index 476b669..a299c87 100644
--- a/samples/server.c
+++ b/samples/server.c
@@ -249,7 +249,7 @@ static void do_dma_io(vfu_ctx_t *vfu_ctx, struct server_data *server_data)
}
}
-static int device_reset(vfu_ctx_t *vfu_ctx UNUSED)
+static int device_reset(vfu_ctx_t *vfu_ctx UNUSED, vfu_reset_type_t type UNUSED)
{
vfu_log(vfu_ctx, LOG_DEBUG, "device reset callback");
return 0;