diff options
author | John Levon <john.levon@nutanix.com> | 2021-04-06 15:55:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-06 15:55:02 +0100 |
commit | c42ac841ad1d0094d6f6173e4f8bb4f231f8962b (patch) | |
tree | 050ed4bbd37d65dc8e71ede1ce310a6efd285d8f | |
parent | 0b722b79212dfd4a5fb6f7b9137c27f27bd46105 (diff) | |
download | libvfio-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.h | 34 | ||||
-rw-r--r-- | lib/libvfio-user.c | 8 | ||||
-rw-r--r-- | samples/server.c | 2 |
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; |