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 <marcin.dziegielewski@intel.com>
Change-Id: Iebef80989ea22ccea7f1b6ba4d734a40c1d5cc5d
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465675
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
This commit is contained in:
Marcin Dziegielewski 2019-10-04 16:15:23 +02:00 committed by Darek Stojaczyk
parent 7ed0ec6832
commit 1ee2e81b30
3 changed files with 71 additions and 10 deletions

View File

@ -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)

View File

@ -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 */

View File

@ -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",