ocf: Add management context

Add structure vbdev_ocf_mngt_ctx that is going to be used
  for asynchronous management operations.
Using such context, dynamic memory allocations are no longer required
  (except for one time poller registration)

This patch also adds functions to modify context in a predictable way.
They are very important for complex flow of management operations in OCF bdev
  especially after whole OCF API gets changed to asynchronous.

Change-Id: Ia402d51665330a553f7f3d74000e3636f0d6a598
Signed-off-by: Vitaliy Mysak <vitaliy.mysak@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/449556
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>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
Vitaliy Mysak 2019-03-29 21:49:31 +00:00 committed by Jim Harris
parent bb64a7e511
commit 25df73f5d2
3 changed files with 114 additions and 0 deletions

View File

@ -34,6 +34,7 @@
#include "spdk/stdinc.h" #include "spdk/stdinc.h"
#include "utils.h" #include "utils.h"
#include "vbdev_ocf.h"
static char *cache_modes[ocf_cache_mode_max] = { static char *cache_modes[ocf_cache_mode_max] = {
[ocf_cache_mode_wt] = "wt", [ocf_cache_mode_wt] = "wt",
@ -66,3 +67,71 @@ ocf_get_cache_modename(ocf_cache_mode_t mode)
return NULL; 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));
}

View File

@ -35,8 +35,25 @@
#define VBDEV_OCF_UTILS_H #define VBDEV_OCF_UTILS_H
#include <ocf/ocf.h> #include <ocf/ocf.h>
#include "vbdev_ocf.h"
ocf_cache_mode_t ocf_get_cache_mode(const char *cache_mode); ocf_cache_mode_t ocf_get_cache_mode(const char *cache_mode);
const char *ocf_get_cache_modename(ocf_cache_mode_t 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 #endif

View File

@ -81,6 +81,31 @@ struct vbdev_ocf_config {
struct ocf_mngt_core_config core; 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 */ /* Base device info */
struct vbdev_ocf_base { struct vbdev_ocf_base {
/* OCF unique internal id */ /* OCF unique internal id */
@ -125,6 +150,9 @@ struct vbdev_ocf {
struct vbdev_ocf_config cfg; struct vbdev_ocf_config cfg;
struct vbdev_ocf_state state; struct vbdev_ocf_state state;
/* Management context */
struct vbdev_ocf_mngt_ctx mngt_ctx;
/* Exposed SPDK bdev. Registered in bdev layer */ /* Exposed SPDK bdev. Registered in bdev layer */
struct spdk_bdev exp_bdev; struct spdk_bdev exp_bdev;