ocf: finish OCF reqs after put_io_channel

Relaunch queue poller on put_io_channel callback of OCF bdev
  to delay thread shutdown. New poller will finish all pending
  OCF requests as there might be some even after all SPDK IOs
  completed.

This solves the issue of OCF not being able to
  complete all its work because of queue poller getting
  unregistered in callback of put_io_channel.

This patch also changes unregister procedure:
  we call ocf_cache_stop in callback of io_device_unregister
  instead of in callback of bdev_unregister.

Change-Id: Ib7e41fc25e71029a73bb76a62e39e6bf4b8189ce
Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/444276
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Vitaliy Mysak 2019-02-19 20:57:49 +00:00 committed by Jim Harris
parent 9977424df1
commit 4fad4b86dd

View File

@ -140,10 +140,6 @@ stop_vbdev(struct vbdev_ocf *vbdev)
return rc;
}
/* This function blocks execution until all OCF requests are finished
* But we don't have to worry about possible deadlocks because in
* supported modes (WT and PT) all OCF requests are finished before
* SPDK bdev io requests */
rc = ocf_mngt_cache_stop(vbdev->ocf_cache);
ocf_mngt_cache_unlock(vbdev->ocf_cache);
if (rc) {
@ -199,13 +195,31 @@ close_spdk_dev:
return rc;
}
/* Free OCF resources, close base bdevs, unregister io device
/* Free OCF resources, close base bdevs */
static void
unregister_cb(void *opaque)
{
struct vbdev_ocf *vbdev = opaque;
int status;
status = stop_vbdev(vbdev);
if (vbdev->core.attached) {
remove_base(&vbdev->core);
}
if (vbdev->cache.attached) {
remove_base(&vbdev->cache);
}
spdk_bdev_destruct_done(&vbdev->exp_bdev, status);
}
/* Unregister io device with callback to unregister_cb
* This function is called during spdk_bdev_unregister */
static int
vbdev_ocf_destruct(void *opaque)
{
struct vbdev_ocf *vbdev = opaque;
int status = 0;
if (vbdev->state.doing_finish) {
return -EALREADY;
@ -213,7 +227,9 @@ vbdev_ocf_destruct(void *opaque)
vbdev->state.doing_finish = true;
if (vbdev->state.started) {
status = stop_vbdev(vbdev);
spdk_io_device_unregister(vbdev, unregister_cb);
/* Return 1 because unregister is delayed */
return 1;
}
if (vbdev->core.attached) {
@ -223,11 +239,7 @@ vbdev_ocf_destruct(void *opaque)
remove_base(&vbdev->cache);
}
if (vbdev->state.started) {
spdk_io_device_unregister(vbdev, NULL);
}
return status;
return 0;
}
/* Stop OCF cache and unregister SPDK bdev */
@ -616,6 +628,13 @@ vbdev_ocf_ctx_queue_kick(ocf_queue_t q)
static void
vbdev_ocf_ctx_queue_stop(ocf_queue_t q)
{
struct vbdev_ocf_qcxt *qctx = ocf_queue_get_priv(q);
if (qctx) {
spdk_put_io_channel(qctx->cache_ch);
spdk_put_io_channel(qctx->core_ch);
spdk_poller_unregister(&qctx->poller);
}
}
/* Queue ops is an interface for running queue thread
@ -651,16 +670,24 @@ io_device_create_cb(void *io_device, void *ctx_buf)
}
/* Called per thread
* We free resources associated with OCF queue here
* and close base devices channels */
* Put OCF queue and relaunch poller with new context to finish pending requests */
static void
io_device_destroy_cb(void *io_device, void *ctx_buf)
{
/* Making a copy of context to use it after io channel will be destroyed */
struct vbdev_ocf_qcxt *copy = malloc(sizeof(*copy));
struct vbdev_ocf_qcxt *qctx = ctx_buf;
spdk_put_io_channel(qctx->cache_ch);
spdk_put_io_channel(qctx->core_ch);
spdk_poller_unregister(&qctx->poller);
if (copy) {
ocf_queue_set_priv(qctx->queue, copy);
memcpy(copy, qctx, sizeof(*copy));
spdk_poller_unregister(&qctx->poller);
copy->poller = spdk_poller_register(queue_poll, copy, 0);
} else {
SPDK_ERRLOG("Unable to stop OCF queue properly: %s\n",
spdk_strerror(ENOMEM));
}
ocf_queue_put(qctx->queue);
}