diff --git a/lib/bdev/ocf/utils.c b/lib/bdev/ocf/utils.c index 9f7307d50..f26ed8ab1 100644 --- a/lib/bdev/ocf/utils.c +++ b/lib/bdev/ocf/utils.c @@ -34,6 +34,7 @@ #include "spdk/stdinc.h" #include "utils.h" +#include "vbdev_ocf.h" static char *cache_modes[ocf_cache_mode_max] = { [ocf_cache_mode_wt] = "wt", @@ -66,3 +67,71 @@ ocf_get_cache_modename(ocf_cache_mode_t mode) return NULL; } } + +static int +mngt_poll_fn(void *opaque) +{ + struct vbdev_ocf *vbdev = opaque; + + if (vbdev->mngt_ctx.poller_fn) { + vbdev->mngt_ctx.poller_fn(vbdev); + } + + return 0; +} + +int +vbdev_ocf_mngt_start(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn *path, + vbdev_ocf_mngt_callback cb, void *cb_arg) +{ + if (vbdev->mngt_ctx.current_step) { + return -EBUSY; + } + + memset(&vbdev->mngt_ctx, 0, sizeof(vbdev->mngt_ctx)); + + vbdev->mngt_ctx.poller = spdk_poller_register(mngt_poll_fn, vbdev, 200); + if (vbdev->mngt_ctx.poller == NULL) { + return -ENOMEM; + } + + vbdev->mngt_ctx.current_step = path; + vbdev->mngt_ctx.cb = cb; + vbdev->mngt_ctx.cb_arg = cb_arg; + + (*vbdev->mngt_ctx.current_step)(vbdev); + + return 0; +} + +void +vbdev_ocf_mngt_poll(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn fn) +{ + assert(vbdev->mngt_ctx.poller != NULL); + vbdev->mngt_ctx.poller_fn = fn; +} + +void +vbdev_ocf_mngt_continue(struct vbdev_ocf *vbdev, int status) +{ + if (vbdev->mngt_ctx.current_step == NULL) { + return; + } + + assert((*vbdev->mngt_ctx.current_step) != NULL); + + vbdev->mngt_ctx.status = status; + vbdev->mngt_ctx.poller_fn = NULL; + + vbdev->mngt_ctx.current_step++; + if (*vbdev->mngt_ctx.current_step) { + (*vbdev->mngt_ctx.current_step)(vbdev); + return; + } + + spdk_poller_unregister(&vbdev->mngt_ctx.poller); + if (vbdev->mngt_ctx.cb) { + vbdev->mngt_ctx.cb(vbdev->mngt_ctx.status, vbdev->mngt_ctx.cb_arg); + } + memset(&vbdev->mngt_ctx, 0, sizeof(vbdev->mngt_ctx)); +} diff --git a/lib/bdev/ocf/utils.h b/lib/bdev/ocf/utils.h index c8966cb3e..22439c9aa 100644 --- a/lib/bdev/ocf/utils.h +++ b/lib/bdev/ocf/utils.h @@ -35,8 +35,25 @@ #define VBDEV_OCF_UTILS_H #include +#include "vbdev_ocf.h" ocf_cache_mode_t ocf_get_cache_mode(const char *cache_mode); const char *ocf_get_cache_modename(ocf_cache_mode_t mode); +/* Initiate management operation + * Receives NULL terminated array of functions (path) + * and callback (cb) + * and callback argument (cb_arg) + * This function may fail with ENOMEM or EBUSY */ +int vbdev_ocf_mngt_start(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn *path, + vbdev_ocf_mngt_callback cb, void *cb_arg); + +/* Continue execution with polling operation (fn) + * fn must invoke vbdev_ocf_mngt_continue() to stop polling */ +void vbdev_ocf_mngt_poll(struct vbdev_ocf *vbdev, vbdev_ocf_mngt_fn fn); + +/* Continue execution with next function that is on path + * If next function is NULL, finish management operation and invoke callback */ +void vbdev_ocf_mngt_continue(struct vbdev_ocf *vbdev, int status); + #endif diff --git a/lib/bdev/ocf/vbdev_ocf.h b/lib/bdev/ocf/vbdev_ocf.h index c9fc7ffbe..7b014645c 100644 --- a/lib/bdev/ocf/vbdev_ocf.h +++ b/lib/bdev/ocf/vbdev_ocf.h @@ -81,6 +81,31 @@ struct vbdev_ocf_config { struct ocf_mngt_core_config core; }; +/* Types for management operations */ +typedef void (*vbdev_ocf_mngt_fn)(struct vbdev_ocf *); +typedef void (*vbdev_ocf_mngt_callback)(int, void *); + +/* Context for asynchronous management operations + * Single management operation usually contains a list of sub procedures, + * this structure handles sharing between those sub procedures */ +struct vbdev_ocf_mngt_ctx { + /* Pointer to function that is currently being executed + * It gets incremented on each step until it dereferences to NULL */ + vbdev_ocf_mngt_fn *current_step; + + /* Poller, registered once per whole management operation */ + struct spdk_poller *poller; + /* Function that gets invoked by poller on each iteration */ + vbdev_ocf_mngt_fn poller_fn; + + /* Status of management operation */ + int status; + + /* External callback and its argument */ + vbdev_ocf_mngt_callback cb; + void *cb_arg; +}; + /* Base device info */ struct vbdev_ocf_base { /* OCF unique internal id */ @@ -125,6 +150,9 @@ struct vbdev_ocf { struct vbdev_ocf_config cfg; struct vbdev_ocf_state state; + /* Management context */ + struct vbdev_ocf_mngt_ctx mngt_ctx; + /* Exposed SPDK bdev. Registered in bdev layer */ struct spdk_bdev exp_bdev;