vhost: use external event API in get_vhost_controllers RPC call

Added spdk_vhost_call_external_event_foreach.

Continuation of patch I689226c [1]

[1] vhost: added API to call external spdk_events on vdev reactor

Change-Id: I5a404ec9de586d197e84eeda82009a803b4fa623
Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/373262
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Dariusz Stojaczyk 2017-08-08 18:52:53 +02:00 committed by Jim Harris
parent 9f6f73d420
commit 8323be7df8
4 changed files with 136 additions and 45 deletions

View File

@ -57,12 +57,6 @@ struct spdk_vhost_dev;
typedef int (*spdk_vhost_event_fn)(struct spdk_vhost_dev *, void *); typedef int (*spdk_vhost_event_fn)(struct spdk_vhost_dev *, void *);
/**
* Get handle to next controller.
* \param prev Previous controller or NULL to get first one.
* \return handle to next controller ot NULL if prev was the last one.
*/
struct spdk_vhost_dev *spdk_vhost_dev_next(struct spdk_vhost_dev *prev);
struct spdk_vhost_dev *spdk_vhost_dev_find(const char *ctrlr_name); struct spdk_vhost_dev *spdk_vhost_dev_find(const char *ctrlr_name);
const char *spdk_vhost_dev_get_name(struct spdk_vhost_dev *ctrl); const char *spdk_vhost_dev_get_name(struct spdk_vhost_dev *ctrl);
uint64_t spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *ctrl); uint64_t spdk_vhost_dev_get_cpumask(struct spdk_vhost_dev *ctrl);
@ -99,4 +93,22 @@ bool spdk_vhost_blk_get_readonly(struct spdk_vhost_dev *vdev);
*/ */
void spdk_vhost_call_external_event(const char *ctrlr_name, spdk_vhost_event_fn fn, void *arg); void spdk_vhost_call_external_event(const char *ctrlr_name, spdk_vhost_event_fn fn, void *arg);
/**
* Call function for each available vhost controller on
* it's reactor. This will call given function in a chain,
* meaning that each callback will be called after the
* previous one has finished. After given function has
* been called for all controllers, it will be called
* once again with first param - vhost controller - set
* to NULL.
*
* This function is thread safe.
*
* \param fn function to be called for each controller.
* The first param will be either vdev pointer or NULL.
* The second param is user provided argument *arg*.
* \param arg parameter to be passed to *fn*.
*/
void spdk_vhost_call_external_event_foreach(spdk_vhost_event_fn fn, void *arg);
#endif /* SPDK_VHOST_H */ #endif /* SPDK_VHOST_H */

View File

@ -482,30 +482,18 @@ spdk_vhost_dev_remove(struct spdk_vhost_dev *vdev)
return 0; return 0;
} }
struct spdk_vhost_dev * static int
spdk_vhost_dev_next(struct spdk_vhost_dev *prev) spdk_vhost_dev_next(int i)
{ {
int i = 0; for (i++; i < MAX_VHOST_DEVICES; i++) {
if (prev != NULL) {
for (; i < MAX_VHOST_DEVICES; i++) {
if (g_spdk_vhost_devices[i] == prev) {
break;
}
}
i++;
}
for (; i < MAX_VHOST_DEVICES; i++) {
if (g_spdk_vhost_devices[i] == NULL) { if (g_spdk_vhost_devices[i] == NULL) {
continue; continue;
} }
return g_spdk_vhost_devices[i]; return i;
} }
return NULL; return -1;
} }
const char * const char *
@ -594,6 +582,34 @@ spdk_vhost_event_async_fn(void *arg1, void *arg2)
free(ctx); free(ctx);
} }
static void spdk_vhost_external_event_foreach_continue(int vdev_id,
spdk_vhost_event_fn fn, void *arg);
static void
spdk_vhost_event_async_foreach_fn(void *arg1, void *arg2)
{
struct spdk_vhost_dev_event_ctx *ctx = arg1;
struct spdk_vhost_dev *vdev;
struct spdk_event *ev;
if (pthread_mutex_trylock(&g_spdk_vhost_mutex) != 0) {
ev = spdk_event_allocate(spdk_env_get_current_core(),
spdk_vhost_event_async_foreach_fn, arg1, arg2);
spdk_event_call(ev);
return;
}
vdev = g_spdk_vhost_devices[ctx->vdev_id];
if (vdev == ctx->vdev) {
ctx->cb_fn(vdev, arg2);
}
spdk_vhost_external_event_foreach_continue(ctx->vdev_id, ctx->cb_fn, arg2);
pthread_mutex_unlock(&g_spdk_vhost_mutex);
free(ctx);
}
static int static int
spdk_vhost_event_send(struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn, spdk_vhost_event_send(struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn,
unsigned timeout_sec, const char *errmsg) unsigned timeout_sec, const char *errmsg)
@ -630,10 +646,12 @@ spdk_vhost_event_send(struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn,
} }
static int static int
spdk_vhost_event_async_send(unsigned vdev_id, spdk_vhost_event_fn cb_fn, void *arg) spdk_vhost_event_async_send(unsigned vdev_id, spdk_vhost_event_fn cb_fn, void *arg,
bool foreach)
{ {
struct spdk_vhost_dev_event_ctx *ev_ctx; struct spdk_vhost_dev_event_ctx *ev_ctx;
struct spdk_event *ev; struct spdk_event *ev;
spdk_event_fn fn;
ev_ctx = calloc(1, sizeof(*ev_ctx)); ev_ctx = calloc(1, sizeof(*ev_ctx));
if (ev_ctx == NULL) { if (ev_ctx == NULL) {
@ -645,7 +663,8 @@ spdk_vhost_event_async_send(unsigned vdev_id, spdk_vhost_event_fn cb_fn, void *a
ev_ctx->vdev_id = vdev_id; ev_ctx->vdev_id = vdev_id;
ev_ctx->cb_fn = cb_fn; ev_ctx->cb_fn = cb_fn;
ev = spdk_event_allocate(ev_ctx->vdev->lcore, spdk_vhost_event_async_fn, ev_ctx, arg); fn = foreach ? spdk_vhost_event_async_foreach_fn : spdk_vhost_event_async_fn;
ev = spdk_event_allocate(ev_ctx->vdev->lcore, fn, ev_ctx, arg);
assert(ev); assert(ev);
spdk_event_call(ev); spdk_event_call(ev);
@ -919,12 +938,45 @@ spdk_vhost_call_external_event(const char *ctrlr_name, spdk_vhost_event_fn fn, v
if (vdev->lcore == -1) { if (vdev->lcore == -1) {
fn(vdev, arg); fn(vdev, arg);
} else { } else {
spdk_vhost_event_async_send(vdev_id, fn, arg); spdk_vhost_event_async_send(vdev_id, fn, arg, false);
} }
pthread_mutex_unlock(&g_spdk_vhost_mutex); pthread_mutex_unlock(&g_spdk_vhost_mutex);
} }
static void
spdk_vhost_external_event_foreach_continue(int vdev_id, spdk_vhost_event_fn fn, void *arg)
{
struct spdk_vhost_dev *vdev;
vdev_id = spdk_vhost_dev_next(vdev_id);
if (vdev_id == -1) {
fn(NULL, arg);
return;
}
vdev = g_spdk_vhost_devices[vdev_id];
while (vdev->lcore == -1) {
fn(vdev, arg);
vdev_id = spdk_vhost_dev_next(vdev_id);
if (vdev_id == -1) {
fn(NULL, arg);
return;
}
vdev = g_spdk_vhost_devices[vdev_id];
}
spdk_vhost_event_async_send(vdev_id, fn, arg, true);
}
void
spdk_vhost_call_external_event_foreach(spdk_vhost_event_fn fn, void *arg)
{
pthread_mutex_lock(&g_spdk_vhost_mutex);
spdk_vhost_external_event_foreach_continue(-1, fn, arg);
pthread_mutex_unlock(&g_spdk_vhost_mutex);
}
void void
spdk_vhost_lock(void) spdk_vhost_lock(void)
{ {

View File

@ -460,12 +460,49 @@ invalid:
} }
SPDK_RPC_REGISTER("remove_vhost_controller", spdk_rpc_remove_vhost_controller) SPDK_RPC_REGISTER("remove_vhost_controller", spdk_rpc_remove_vhost_controller)
struct rpc_get_vhost_ctrlrs {
struct spdk_json_write_ctx *w;
struct spdk_jsonrpc_request *request;
};
static int
spdk_rpc_get_vhost_controllers_cb(struct spdk_vhost_dev *vdev, void *arg)
{
struct rpc_get_vhost_ctrlrs *ctx = arg;
if (vdev == NULL) {
spdk_json_write_array_end(ctx->w);
spdk_jsonrpc_end_result(ctx->request, ctx->w);
free(ctx);
return 0;
}
spdk_json_write_object_begin(ctx->w);
spdk_json_write_name(ctx->w, "ctrlr");
spdk_json_write_string(ctx->w, spdk_vhost_dev_get_name(vdev));
spdk_json_write_name(ctx->w, "cpumask");
spdk_json_write_string_fmt(ctx->w, "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev));
spdk_json_write_name(ctx->w, "backend_specific");
spdk_json_write_object_begin(ctx->w);
spdk_vhost_dump_config_json(vdev, ctx->w);
spdk_json_write_object_end(ctx->w);
spdk_json_write_object_end(ctx->w); // ctrl
return 0;
}
static void static void
spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request, spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request,
const struct spdk_json_val *params) const struct spdk_json_val *params)
{ {
struct rpc_get_vhost_ctrlrs *ctx;
struct spdk_json_write_ctx *w; struct spdk_json_write_ctx *w;
struct spdk_vhost_dev *vdev = NULL;
if (params != NULL) { if (params != NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
@ -479,26 +516,16 @@ spdk_rpc_get_vhost_controllers(struct spdk_jsonrpc_request *request,
} }
spdk_json_write_array_begin(w); spdk_json_write_array_begin(w);
while ((vdev = spdk_vhost_dev_next(vdev)) != NULL) {
spdk_json_write_object_begin(w);
spdk_json_write_name(w, "ctrlr"); ctx = calloc(1, sizeof(*ctx));
spdk_json_write_string(w, spdk_vhost_dev_get_name(vdev)); if (ctx == NULL) {
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, strerror(-ENOMEM));
spdk_json_write_name(w, "cpumask"); return;
spdk_json_write_string_fmt(w, "%#" PRIx64, spdk_vhost_dev_get_cpumask(vdev));
spdk_json_write_name(w, "backend_specific");
spdk_json_write_object_begin(w);
spdk_vhost_dump_config_json(vdev, w);
spdk_json_write_object_end(w);
spdk_json_write_object_end(w);
} }
spdk_json_write_array_end(w); ctx->w = w;
spdk_jsonrpc_end_result(request, w); ctx->request = request;
spdk_vhost_call_external_event_foreach(spdk_rpc_get_vhost_controllers_cb, ctx);
} }
SPDK_RPC_REGISTER("get_vhost_controllers", spdk_rpc_get_vhost_controllers) SPDK_RPC_REGISTER("get_vhost_controllers", spdk_rpc_get_vhost_controllers)

View File

@ -36,6 +36,7 @@
#include "CUnit/Basic.h" #include "CUnit/Basic.h"
#include "spdk_cunit.h" #include "spdk_cunit.h"
#include "spdk_internal/mock.h" #include "spdk_internal/mock.h"
#include "lib/test_env.c"
#include "vhost.c" #include "vhost.c"
@ -44,7 +45,6 @@ DEFINE_STUB(spdk_event_allocate, struct spdk_event *,
(uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL); (uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL);
DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0); DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0); DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
DEFINE_STUB(spdk_vtophys, uint64_t, (void *vaddr), 1);
DEFINE_STUB(spdk_app_get_core_mask, uint64_t, (void), 0); DEFINE_STUB(spdk_app_get_core_mask, uint64_t, (void), 0);
DEFINE_STUB_V(spdk_app_stop, (int rc)); DEFINE_STUB_V(spdk_app_stop, (int rc));
DEFINE_STUB_V(spdk_event_call, (struct spdk_event *event)); DEFINE_STUB_V(spdk_event_call, (struct spdk_event *event));