From 14a6ca08dbb8fa174c9e5d91b114cd7228d2fd0b Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Tue, 22 Jan 2019 12:57:09 +0100 Subject: [PATCH] vhost: call start/stop backend callbacks directly on the DPDK thread Particular backends will now be responsible for sending events to vsession->lcore. This was previously done by the generic vhost layer, but since some backends will need different lcore assignment policies soon, we need to give them more power now. Change-Id: I72cbbccb9d5a5b2358acca6d4b6bb882131937af Signed-off-by: Darek Stojaczyk Reviewed-on: https://review.gerrithub.io/c/441580 Reviewed-by: Pawel Wodkowski Reviewed-by: Jim Harris Reviewed-by: Changpeng Liu Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System --- lib/vhost/vhost.c | 13 +++++++------ lib/vhost/vhost_blk.c | 28 ++++++++++++++++++++------- lib/vhost/vhost_internal.h | 39 ++++++++++++++++++++++++++++++-------- lib/vhost/vhost_nvme.c | 35 +++++++++++++++++++++------------- lib/vhost/vhost_scsi.c | 34 ++++++++++++++++++++++----------- 5 files changed, 104 insertions(+), 45 deletions(-) diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index c97c73226..6d9d76ba9 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -819,7 +819,7 @@ spdk_vhost_allocate_reactor(struct spdk_cpuset *cpumask) } void -spdk_vhost_dev_backend_event_done(void *event_ctx, int response) +spdk_vhost_session_event_done(void *event_ctx, int response) { struct spdk_vhost_session_fn_ctx *ctx = event_ctx; @@ -883,9 +883,10 @@ out_unlock: free(ctx); } -static int -_spdk_vhost_event_send(struct spdk_vhost_session *vsession, spdk_vhost_session_fn cb_fn, - unsigned timeout_sec, const char *errmsg) +int +spdk_vhost_session_send_event(struct spdk_vhost_session *vsession, + spdk_vhost_session_fn cb_fn, unsigned timeout_sec, + const char *errmsg) { struct spdk_vhost_session_fn_ctx ev_ctx = {0}; struct spdk_event *ev; @@ -969,7 +970,7 @@ stop_device(int vid) return; } - rc = _spdk_vhost_event_send(vsession, vdev->backend->stop_session, 3, "stop session"); + rc = vdev->backend->stop_session(vsession); if (rc != 0) { SPDK_ERRLOG("Couldn't stop device with vid %d.\n", vid); pthread_mutex_unlock(&g_spdk_vhost_mutex); @@ -1064,7 +1065,7 @@ start_device(int vid) spdk_vhost_session_set_coalescing(vdev, vsession, NULL); vsession->lcore = spdk_vhost_allocate_reactor(vdev->cpumask); spdk_vhost_session_mem_register(vsession); - rc = _spdk_vhost_event_send(vsession, vdev->backend->start_session, 3, "start session"); + rc = vdev->backend->start_session(vsession); if (rc != 0) { spdk_vhost_session_mem_unregister(vsession); free(vsession->mem); diff --git a/lib/vhost/vhost_blk.c b/lib/vhost/vhost_blk.c index 80f765861..5ee2909ec 100644 --- a/lib/vhost/vhost_blk.c +++ b/lib/vhost/vhost_blk.c @@ -665,8 +665,8 @@ alloc_task_pool(struct spdk_vhost_blk_session *bvsession) } static int -spdk_vhost_blk_start(struct spdk_vhost_dev *vdev, - struct spdk_vhost_session *vsession, void *event_ctx) +spdk_vhost_blk_start_cb(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *event_ctx) { struct spdk_vhost_blk_dev *bvdev; struct spdk_vhost_blk_session *bvsession; @@ -712,10 +712,17 @@ spdk_vhost_blk_start(struct spdk_vhost_dev *vdev, SPDK_INFOLOG(SPDK_LOG_VHOST, "Started poller for vhost controller %s on lcore %d\n", vdev->name, vsession->lcore); out: - spdk_vhost_dev_backend_event_done(event_ctx, rc); + spdk_vhost_session_event_done(event_ctx, rc); return rc; } +static int +spdk_vhost_blk_start(struct spdk_vhost_session *vsession) +{ + return spdk_vhost_session_send_event(vsession, spdk_vhost_blk_start_cb, + 3, "start session"); +} + static int destroy_session_poller_cb(void *arg) { @@ -741,14 +748,14 @@ destroy_session_poller_cb(void *arg) free_task_pool(bvsession); spdk_poller_unregister(&bvsession->destroy_ctx.poller); - spdk_vhost_dev_backend_event_done(bvsession->destroy_ctx.event_ctx, 0); + spdk_vhost_session_event_done(bvsession->destroy_ctx.event_ctx, 0); return -1; } static int -spdk_vhost_blk_stop(struct spdk_vhost_dev *vdev, - struct spdk_vhost_session *vsession, void *event_ctx) +spdk_vhost_blk_stop_cb(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *event_ctx) { struct spdk_vhost_blk_session *bvsession; @@ -765,10 +772,17 @@ spdk_vhost_blk_stop(struct spdk_vhost_dev *vdev, return 0; err: - spdk_vhost_dev_backend_event_done(event_ctx, -1); + spdk_vhost_session_event_done(event_ctx, -1); return -1; } +static int +spdk_vhost_blk_stop(struct spdk_vhost_session *vsession) +{ + return spdk_vhost_session_send_event(vsession, spdk_vhost_blk_stop_cb, + 3, "stop session"); +} + static void spdk_vhost_blk_dump_info_json(struct spdk_vhost_dev *vdev, struct spdk_json_write_ctx *w) { diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index ea00e8b23..9793fc2fa 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -201,13 +201,8 @@ struct spdk_vhost_dev_backend { */ size_t session_ctx_size; - /** - * Callbacks for starting and pausing a session. - * The third param is an event context that has to be - * passed to spdk_vhost_dev_backend_event_done(). - */ - spdk_vhost_session_fn start_session; - spdk_vhost_session_fn stop_session; + int (*start_session)(struct spdk_vhost_session *vsession); + int (*stop_session)(struct spdk_vhost_session *vsession); int (*vhost_get_config)(struct spdk_vhost_dev *vdev, uint8_t *config, uint32_t len); int (*vhost_set_config)(struct spdk_vhost_dev *vdev, uint8_t *config, @@ -311,7 +306,35 @@ void spdk_vhost_dump_info_json(struct spdk_vhost_dev *vdev, struct spdk_json_wri */ void spdk_vhost_dev_foreach_session(struct spdk_vhost_dev *dev, spdk_vhost_session_fn fn, void *arg); -void spdk_vhost_dev_backend_event_done(void *event_ctx, int response); + +/** + * Call the provided function on the session's lcore and block until + * spdk_vhost_session_event_done() is called. + * + * As an optimization, this function will unlock the vhost mutex + * while it's waiting, which makes it prone to data races. + * Practically, it is only useful for session start/stop and still + * has to be used with extra caution. + * + * \param vsession vhost session + * \param cb_fn the function to call. The void *arg parameter in cb_fn + * must be passed to spdk_vhost_session_event_done(). + * \param timeout_sec timeout in seconds. This function will still + * block after the timeout expires, but will print the provided errmsg. + * \param errmsg error message to print once the timeout expires + * \return return the code passed to spdk_vhost_session_event_done(). + */ +int spdk_vhost_session_send_event(struct spdk_vhost_session *vsession, + spdk_vhost_session_fn cb_fn, unsigned timeout_sec, const char *errmsg); + +/** + * Finish a blocking spdk_vhost_session_send_event() call. + * + * \param event_ctx event context + * \param response return code + */ +void spdk_vhost_session_event_done(void *event_ctx, int response); + void spdk_vhost_lock(void); void spdk_vhost_unlock(void); int spdk_remove_vhost_controller(struct spdk_vhost_dev *vdev); diff --git a/lib/vhost/vhost_nvme.c b/lib/vhost/vhost_nvme.c index 142325f89..ed0541130 100644 --- a/lib/vhost/vhost_nvme.c +++ b/lib/vhost/vhost_nvme.c @@ -1066,12 +1066,9 @@ alloc_task_pool(struct spdk_vhost_nvme_dev *nvme) return 0; } -/* new device means enable the - * virtual NVMe controller - */ static int -spdk_vhost_nvme_start_device(struct spdk_vhost_dev *vdev, - struct spdk_vhost_session *vsession, void *event_ctx) +spdk_vhost_nvme_start_cb(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *event_ctx) { struct spdk_vhost_nvme_dev *nvme = to_nvme_dev(vdev); struct spdk_vhost_nvme_ns *ns_dev; @@ -1099,10 +1096,17 @@ spdk_vhost_nvme_start_device(struct spdk_vhost_dev *vdev, /* Start the NVMe Poller */ nvme->requestq_poller = spdk_poller_register(nvme_worker, nvme, 0); - spdk_vhost_dev_backend_event_done(event_ctx, 0); + spdk_vhost_session_event_done(event_ctx, 0); return 0; } +static int +spdk_vhost_nvme_start(struct spdk_vhost_session *vsession) +{ + return spdk_vhost_session_send_event(vsession, spdk_vhost_nvme_start_cb, + 3, "start session"); +} + static void spdk_vhost_nvme_deactive_ns(struct spdk_vhost_nvme_ns *ns) { @@ -1155,16 +1159,14 @@ destroy_device_poller_cb(void *arg) } spdk_poller_unregister(&nvme->destroy_ctx.poller); - spdk_vhost_dev_backend_event_done(nvme->destroy_ctx.event_ctx, 0); + spdk_vhost_session_event_done(nvme->destroy_ctx.event_ctx, 0); return -1; } -/* Disable NVMe controller - */ static int -spdk_vhost_nvme_stop_device(struct spdk_vhost_dev *vdev, - struct spdk_vhost_session *vsession, void *event_ctx) +spdk_vhost_nvme_stop_cb(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *event_ctx) { struct spdk_vhost_nvme_dev *nvme = to_nvme_dev(vdev); @@ -1182,6 +1184,13 @@ spdk_vhost_nvme_stop_device(struct spdk_vhost_dev *vdev, return 0; } +static int +spdk_vhost_nvme_stop(struct spdk_vhost_session *vsession) +{ + return spdk_vhost_session_send_event(vsession, spdk_vhost_nvme_stop_cb, + 3, "start session"); +} + static void spdk_vhost_nvme_dump_info_json(struct spdk_vhost_dev *vdev, struct spdk_json_write_ctx *w) { @@ -1252,8 +1261,8 @@ spdk_vhost_nvme_write_config_json(struct spdk_vhost_dev *vdev, struct spdk_json_ static const struct spdk_vhost_dev_backend spdk_vhost_nvme_device_backend = { .session_ctx_size = 0, - .start_session = spdk_vhost_nvme_start_device, - .stop_session = spdk_vhost_nvme_stop_device, + .start_session = spdk_vhost_nvme_start, + .stop_session = spdk_vhost_nvme_stop, .dump_info_json = spdk_vhost_nvme_dump_info_json, .write_config_json = spdk_vhost_nvme_write_config_json, .remove_device = spdk_vhost_nvme_dev_remove, diff --git a/lib/vhost/vhost_scsi.c b/lib/vhost/vhost_scsi.c index af2917e52..85d73eb95 100644 --- a/lib/vhost/vhost_scsi.c +++ b/lib/vhost/vhost_scsi.c @@ -113,10 +113,8 @@ struct spdk_vhost_scsi_task { struct spdk_vhost_virtqueue *vq; }; -static int spdk_vhost_scsi_start(struct spdk_vhost_dev *dev, - struct spdk_vhost_session *vsession, void *); -static int spdk_vhost_scsi_stop(struct spdk_vhost_dev *, - struct spdk_vhost_session *vsession, void *); +static int spdk_vhost_scsi_start(struct spdk_vhost_session *vsession); +static int spdk_vhost_scsi_stop(struct spdk_vhost_session *vsession); static void spdk_vhost_scsi_dump_info_json(struct spdk_vhost_dev *vdev, struct spdk_json_write_ctx *w); static void spdk_vhost_scsi_write_config_json(struct spdk_vhost_dev *vdev, @@ -1209,8 +1207,8 @@ alloc_task_pool(struct spdk_vhost_scsi_session *svsession) } static int -spdk_vhost_scsi_start(struct spdk_vhost_dev *vdev, - struct spdk_vhost_session *vsession, void *event_ctx) +spdk_vhost_scsi_start_cb(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *event_ctx) { struct spdk_vhost_scsi_dev *svdev; struct spdk_vhost_scsi_session *svsession; @@ -1261,10 +1259,17 @@ spdk_vhost_scsi_start(struct spdk_vhost_dev *vdev, MGMT_POLL_PERIOD_US); } out: - spdk_vhost_dev_backend_event_done(event_ctx, rc); + spdk_vhost_session_event_done(event_ctx, rc); return rc; } +static int +spdk_vhost_scsi_start(struct spdk_vhost_session *vsession) +{ + return spdk_vhost_session_send_event(vsession, spdk_vhost_scsi_start_cb, + 3, "start session"); +} + static int destroy_session_poller_cb(void *arg) { @@ -1295,14 +1300,14 @@ destroy_session_poller_cb(void *arg) free_task_pool(svsession); spdk_poller_unregister(&svsession->destroy_ctx.poller); - spdk_vhost_dev_backend_event_done(svsession->destroy_ctx.event_ctx, 0); + spdk_vhost_session_event_done(svsession->destroy_ctx.event_ctx, 0); return -1; } static int -spdk_vhost_scsi_stop(struct spdk_vhost_dev *vdev, - struct spdk_vhost_session *vsession, void *event_ctx) +spdk_vhost_scsi_stop_cb(struct spdk_vhost_dev *vdev, + struct spdk_vhost_session *vsession, void *event_ctx) { struct spdk_vhost_scsi_session *svsession; @@ -1321,10 +1326,17 @@ spdk_vhost_scsi_stop(struct spdk_vhost_dev *vdev, return 0; err: - spdk_vhost_dev_backend_event_done(event_ctx, -1); + spdk_vhost_session_event_done(event_ctx, -1); return -1; } +static int +spdk_vhost_scsi_stop(struct spdk_vhost_session *vsession) +{ + return spdk_vhost_session_send_event(vsession, spdk_vhost_scsi_stop_cb, + 3, "stop session"); +} + static void spdk_vhost_scsi_dump_info_json(struct spdk_vhost_dev *vdev, struct spdk_json_write_ctx *w) {