From 1ee2e81b30ce09b81289a4d1e8aeb1d1a11e4b51 Mon Sep 17 00:00:00 2001 From: Marcin Dziegielewski Date: Fri, 4 Oct 2019 16:15:23 +0200 Subject: [PATCH] lib/bdev/ocf: add possibility to remove ocf instance In current code there is no possibility to remove ocf instance permanently, even we call delete_ocf_bdev rpc command, on next examine this instance will be loaded. This patch introduces changes to delete_ocf_bdev rpc command. When we call this command via rpc, core related to particular vbdev will be removed from ocf cache before removing this cache instance. Thanks to that, on next examine we will not detect this core in cache metadata and therefore we will not create this instance on next load. However, in any other situation, we will not touch metadata, so in case of dirty shutdown/hot remove, on next load, we will recovery this instance. Signed-off-by: Marcin Dziegielewski Change-Id: Iebef80989ea22ccea7f1b6ba4d734a40c1d5cc5d Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465675 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Darek Stojaczyk Community-CI: Broadcom SPDK FC-NVMe CI --- module/bdev/ocf/vbdev_ocf.c | 75 +++++++++++++++++++++++++++++---- module/bdev/ocf/vbdev_ocf.h | 4 ++ module/bdev/ocf/vbdev_ocf_rpc.c | 2 +- 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/module/bdev/ocf/vbdev_ocf.c b/module/bdev/ocf/vbdev_ocf.c index 58b67a161..aacf3ef06 100644 --- a/module/bdev/ocf/vbdev_ocf.c +++ b/module/bdev/ocf/vbdev_ocf.c @@ -339,8 +339,8 @@ flush_vbdev(struct vbdev_ocf *vbdev) vbdev_ocf_mngt_poll(vbdev, flush_vbdev_poll); } -/* Procedures called during unregister */ -vbdev_ocf_mngt_fn unregister_path[] = { +/* Procedures called during dirty unregister */ +vbdev_ocf_mngt_fn unregister_path_dirty[] = { flush_vbdev, wait_for_requests, stop_vbdev, @@ -352,13 +352,30 @@ vbdev_ocf_mngt_fn unregister_path[] = { NULL }; +/* Procedures called during clean unregister */ +vbdev_ocf_mngt_fn unregister_path_clean[] = { + flush_vbdev, + wait_for_requests, + detach_core, + close_core_bdev, + stop_vbdev, + detach_cache, + close_cache_bdev, + unregister_finish, + NULL +}; + /* Start asynchronous management operation using unregister_path */ static void unregister_cb(void *opaque) { struct vbdev_ocf *vbdev = opaque; + vbdev_ocf_mngt_fn *unregister_path; int rc; + unregister_path = vbdev->state.doing_clean_delete ? + unregister_path_clean : unregister_path_dirty; + rc = vbdev_ocf_mngt_start(vbdev, unregister_path, NULL, NULL); if (rc) { SPDK_ERRLOG("Unable to unregister OCF bdev: %d\n", rc); @@ -366,6 +383,38 @@ unregister_cb(void *opaque) } } +/* Clean remove case - remove core and then cache, this order + * will remove instance permanently */ +static void +_vbdev_ocf_destruct_clean(struct vbdev_ocf *vbdev) +{ + if (vbdev->core.attached) { + detach_core(vbdev); + close_core_bdev(vbdev); + } + + if (vbdev->cache.attached) { + detach_cache(vbdev); + close_cache_bdev(vbdev); + } +} + +/* Dirty shutdown/hot remove case - remove cache and then core, this order + * will allow us to recover this instance in the future */ +static void +_vbdev_ocf_destruct_dirty(struct vbdev_ocf *vbdev) +{ + if (vbdev->cache.attached) { + detach_cache(vbdev); + close_cache_bdev(vbdev); + } + + if (vbdev->core.attached) { + detach_core(vbdev); + close_core_bdev(vbdev); + } +} + /* Unregister io device with callback to unregister_cb * This function is called during spdk_bdev_unregister */ static int @@ -391,13 +440,10 @@ vbdev_ocf_destruct(void *opaque) return 1; } - if (vbdev->cache.attached) { - detach_cache(vbdev); - close_cache_bdev(vbdev); - } - if (vbdev->core.attached) { - detach_core(vbdev); - close_core_bdev(vbdev); + if (vbdev->state.doing_clean_delete) { + _vbdev_ocf_destruct_clean(vbdev); + } else { + _vbdev_ocf_destruct_dirty(vbdev); } return 0; @@ -421,6 +467,17 @@ vbdev_ocf_delete(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_arg) return rc; } +/* Remove cores permanently and then stop OCF cache and unregister SPDK bdev */ +int +vbdev_ocf_delete_clean(struct vbdev_ocf *vbdev, void (*cb)(void *, int), + void *cb_arg) +{ + vbdev->state.doing_clean_delete = true; + + return vbdev_ocf_delete(vbdev, cb, cb_arg); +} + + /* If vbdev is online, return its object */ struct vbdev_ocf * vbdev_ocf_get_by_name(const char *name) diff --git a/module/bdev/ocf/vbdev_ocf.h b/module/bdev/ocf/vbdev_ocf.h index 9666186b5..b0cf6fb49 100644 --- a/module/bdev/ocf/vbdev_ocf.h +++ b/module/bdev/ocf/vbdev_ocf.h @@ -63,6 +63,8 @@ struct vbdev_ocf_qcxt { /* Important states */ struct vbdev_ocf_state { + /* From the moment when clean delete started */ + bool doing_clean_delete; /* From the moment when finish started */ bool doing_finish; /* From the moment when reset IO recieved, until it is completed */ @@ -200,6 +202,8 @@ struct vbdev_ocf_base *vbdev_ocf_get_base_by_name(const char *name); /* Stop OCF cache and unregister SPDK bdev */ int vbdev_ocf_delete(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_arg); +int vbdev_ocf_delete_clean(struct vbdev_ocf *vbdev, void (*cb)(void *, int), void *cb_arg); + typedef void (*vbdev_ocf_foreach_fn)(struct vbdev_ocf *, void *); /* Execute fn for each OCF device that is online or waits for base devices */ diff --git a/module/bdev/ocf/vbdev_ocf_rpc.c b/module/bdev/ocf/vbdev_ocf_rpc.c index 649865159..5a1325062 100644 --- a/module/bdev/ocf/vbdev_ocf_rpc.c +++ b/module/bdev/ocf/vbdev_ocf_rpc.c @@ -160,7 +160,7 @@ spdk_rpc_bdev_ocf_delete(struct spdk_jsonrpc_request *request, goto end; } - status = vbdev_ocf_delete(vbdev, delete_cb, request); + status = vbdev_ocf_delete_clean(vbdev, delete_cb, request); if (status) { spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Could not delete OCF vbdev: %s",