diff options
author | John Levon <john.levon@nutanix.com> | 2023-01-03 12:23:43 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-03 12:23:43 +0000 |
commit | 3eb7ff6579740a5b962c1a52804b0ec5b29a4c42 (patch) | |
tree | f7a519153645a4560eae19e3e9843adafef3cd9c /lib/libvfio-user.c | |
parent | ad96efb02c27ec22116fb5800b48a6c9df27958f (diff) | |
download | libvfio-user-3eb7ff6579740a5b962c1a52804b0ec5b29a4c42.zip libvfio-user-3eb7ff6579740a5b962c1a52804b0ec5b29a4c42.tar.gz libvfio-user-3eb7ff6579740a5b962c1a52804b0ec5b29a4c42.tar.bz2 |
fix FLR reset callback (#729)
A reset callback is allowed to call functions disallowed in quiescent
state. However, the FLR reset path neglected to account for this
properly, causing an incorrect assert to be triggered if, for example,
vfu_sgl_put() is called. To fix this, make sure all reset paths go
through call_reset_cb().
Signed-off-by: John Levon <john.levon@nutanix.com>
Reviewed-by: Thanos Makatos <thanos.makatos@nutanix.com>
Diffstat (limited to 'lib/libvfio-user.c')
-rw-r--r-- | lib/libvfio-user.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c index be4be95..5a6269a 100644 --- a/lib/libvfio-user.c +++ b/lib/libvfio-user.c @@ -887,19 +887,32 @@ out: return ret; } +int +call_reset_cb(vfu_ctx_t *vfu_ctx, vfu_reset_type_t reason) +{ + int ret; + + if (vfu_ctx->reset == NULL) { + return 0; + } + + vfu_ctx->in_cb = CB_RESET; + ret = vfu_ctx->reset(vfu_ctx, reason); + vfu_ctx->in_cb = CB_NONE; + + return ret; +} + static int -do_device_reset(vfu_ctx_t *vfu_ctx, vfu_reset_type_t reason) +device_reset(vfu_ctx_t *vfu_ctx, vfu_reset_type_t reason) { int ret; - if (vfu_ctx->reset != NULL) { - vfu_ctx->in_cb = CB_RESET; - ret = vfu_ctx->reset(vfu_ctx, reason); - vfu_ctx->in_cb = CB_NONE; - if (ret < 0) { - return ret; - } + ret = call_reset_cb(vfu_ctx, reason); + if (ret < 0) { + return ret; } + if (vfu_ctx->migration != NULL) { return handle_device_state(vfu_ctx, vfu_ctx->migration, VFIO_DEVICE_STATE_V1_RUNNING, false); @@ -907,12 +920,6 @@ do_device_reset(vfu_ctx_t *vfu_ctx, vfu_reset_type_t reason) return 0; } -int -handle_device_reset(vfu_ctx_t *vfu_ctx, vfu_reset_type_t reason) -{ - return do_device_reset(vfu_ctx, reason); -} - static int handle_dirty_pages_get(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg) { @@ -1189,7 +1196,7 @@ handle_request(vfu_ctx_t *vfu_ctx, vfu_msg_t *msg) case VFIO_USER_DEVICE_RESET: vfu_log(vfu_ctx, LOG_INFO, "device reset by client"); - ret = handle_device_reset(vfu_ctx, VFU_RESET_DEVICE); + ret = device_reset(vfu_ctx, VFU_RESET_DEVICE); break; case VFIO_USER_DIRTY_PAGES: @@ -1495,6 +1502,7 @@ vfu_run_ctx(vfu_ctx_t *vfu_ctx) * be called at all. */ if (vfu_ctx->quiesced) { + // FIXME? vfu_log(vfu_ctx, LOG_DEBUG, "device unquiesced"); vfu_ctx->quiesced = false; } @@ -1614,7 +1622,7 @@ vfu_reset_ctx_quiesced(vfu_ctx_t *vfu_ctx) } /* FIXME what happens if the device reset callback fails? */ - do_device_reset(vfu_ctx, VFU_RESET_LOST_CONN); + device_reset(vfu_ctx, VFU_RESET_LOST_CONN); if (vfu_ctx->irqs != NULL) { irqs_reset(vfu_ctx); |