From 2fe6d1d5d44f903c9ae0917905567c1967abe5b3 Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Mon, 19 Nov 2018 13:44:03 -0700 Subject: [PATCH] nbd: Make spdk_nbd_start asynchronous Add a callback to spdk_nbd_start so that it can complete asynchronously. As of this patch, it always calls the callback immediately. Change-Id: I6156fb203145362afa5e4102183b6cf143051c0c Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/433937 Tested-by: Darek Stojaczyk Reviewed-by: Darek Stojaczyk Reviewed-by: Jim Harris --- include/spdk/nbd.h | 14 +++++++++++--- lib/nbd/nbd.c | 35 +++++++++++++++++++++++++++-------- lib/nbd/nbd_rpc.c | 35 ++++++++++++++++++++++------------- 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/include/spdk/nbd.h b/include/spdk/nbd.h index 0e63ec1b0..00133fd5e 100644 --- a/include/spdk/nbd.h +++ b/include/spdk/nbd.h @@ -59,16 +59,24 @@ int spdk_nbd_init(void); */ void spdk_nbd_fini(void); +/** + * Called when an NBD device has been started. + */ +typedef void (*spdk_nbd_start_cb)(void *cb_arg, struct spdk_nbd_disk *nbd, + int rc); + /** * Start a network block device backed by the bdev. * * \param bdev_name Name of bdev exposed as a network block device. * \param nbd_path Path to the registered network block device. + * \param cb_fn Called when the device has been started. + * \param cb_arg Passed to cb_fn. * - * \return a pointer to the configuration of the registered network block device - * on success, or NULL on failure. + * \return A negated error number is passed to cb_fn on failure. */ -struct spdk_nbd_disk *spdk_nbd_start(const char *bdev_name, const char *nbd_path); +void spdk_nbd_start(const char *bdev_name, const char *nbd_path, + spdk_nbd_start_cb cb_fn, void *cb_arg); /** * Stop the running network block device safely. diff --git a/lib/nbd/nbd.c b/lib/nbd/nbd.c index 77c2d6daa..d20dc78e2 100644 --- a/lib/nbd/nbd.c +++ b/lib/nbd/nbd.c @@ -837,10 +837,11 @@ spdk_nbd_bdev_hot_remove(void *remove_ctx) spdk_nbd_stop(nbd); } -struct spdk_nbd_disk * -spdk_nbd_start(const char *bdev_name, const char *nbd_path) +void +spdk_nbd_start(const char *bdev_name, const char *nbd_path, + spdk_nbd_start_cb cb_fn, void *cb_arg) { - struct spdk_nbd_disk *nbd; + struct spdk_nbd_disk *nbd = NULL; struct spdk_bdev *bdev; pthread_t tid; int rc; @@ -850,12 +851,14 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path) bdev = spdk_bdev_get_by_name(bdev_name); if (bdev == NULL) { SPDK_ERRLOG("no bdev %s exists\n", bdev_name); - return NULL; + rc = -EINVAL; + goto err; } nbd = calloc(1, sizeof(*nbd)); if (nbd == NULL) { - return NULL; + rc = -ENOMEM; + goto err; } nbd->dev_fd = -1; @@ -884,6 +887,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path) nbd->nbd_path = strdup(nbd_path); if (!nbd->nbd_path) { SPDK_ERRLOG("strdup allocation failure\n"); + rc = -ENOMEM; goto err; } @@ -899,24 +903,28 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path) nbd->dev_fd = open(nbd_path, O_RDWR); if (nbd->dev_fd == -1) { SPDK_ERRLOG("open(\"%s\") failed: %s\n", nbd_path, spdk_strerror(errno)); + rc = -errno; goto err; } rc = ioctl(nbd->dev_fd, NBD_SET_BLKSIZE, spdk_bdev_get_block_size(bdev)); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_SET_BLKSIZE) failed: %s\n", spdk_strerror(errno)); + rc = -errno; goto err; } rc = ioctl(nbd->dev_fd, NBD_SET_SIZE_BLOCKS, spdk_bdev_get_num_blocks(bdev)); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_SET_SIZE_BLOCKS) failed: %s\n", spdk_strerror(errno)); + rc = -errno; goto err; } rc = ioctl(nbd->dev_fd, NBD_CLEAR_SOCK); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_CLEAR_SOCK) failed: %s\n", spdk_strerror(errno)); + rc = -errno; goto err; } @@ -926,6 +934,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path) rc = ioctl(nbd->dev_fd, NBD_SET_SOCK, nbd->kernel_sp_fd); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_SET_SOCK) failed: %s\n", spdk_strerror(errno)); + rc = -errno; goto err; } @@ -933,6 +942,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path) rc = ioctl(nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_SET_FLAGS) failed: %s\n", spdk_strerror(errno)); + rc = -errno; goto err; } #endif @@ -953,17 +963,26 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path) if (fcntl(nbd->spdk_sp_fd, F_SETFL, flag | O_NONBLOCK) < 0) { SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%s)\n", nbd->spdk_sp_fd, spdk_strerror(errno)); + rc = -errno; goto err; } nbd->nbd_poller = spdk_poller_register(spdk_nbd_poll, nbd, 0); - return nbd; + if (cb_fn) { + cb_fn(cb_arg, nbd, 0); + } + + return; err: - spdk_nbd_stop(nbd); + if (nbd) { + spdk_nbd_stop(nbd); + } - return NULL; + if (cb_fn) { + cb_fn(cb_arg, NULL, rc); + } } const char * diff --git a/lib/nbd/nbd_rpc.c b/lib/nbd/nbd_rpc.c index bec64a131..9382e86a5 100644 --- a/lib/nbd/nbd_rpc.c +++ b/lib/nbd/nbd_rpc.c @@ -58,12 +58,31 @@ static const struct spdk_json_object_decoder rpc_start_nbd_disk_decoders[] = { {"nbd_device", offsetof(struct rpc_start_nbd_disk, nbd_device), spdk_json_decode_string}, }; +static void +spdk_rpc_start_nbd_done(void *cb_arg, struct spdk_nbd_disk *nbd, int rc) +{ + struct spdk_jsonrpc_request *request = cb_arg; + struct spdk_json_write_ctx *w; + + if (rc) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); + return; + } + + w = spdk_jsonrpc_begin_result(request); + if (w == NULL) { + return; + } + + spdk_json_write_string(w, spdk_nbd_get_path(nbd)); + spdk_jsonrpc_end_result(request, w); +} + static void spdk_rpc_start_nbd_disk(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) { struct rpc_start_nbd_disk req = {}; - struct spdk_json_write_ctx *w; struct spdk_nbd_disk *nbd; if (spdk_json_decode_object(params, rpc_start_nbd_disk_decoders, @@ -83,19 +102,9 @@ spdk_rpc_start_nbd_disk(struct spdk_jsonrpc_request *request, goto invalid; } - nbd = spdk_nbd_start(req.bdev_name, req.nbd_device); - if (!nbd) { - goto invalid; - } + spdk_nbd_start(req.bdev_name, req.nbd_device, + spdk_rpc_start_nbd_done, request); - w = spdk_jsonrpc_begin_result(request); - if (w == NULL) { - free_rpc_start_nbd_disk(&req); - return; - } - - spdk_json_write_string(w, req.nbd_device); - spdk_jsonrpc_end_result(request, w); free_rpc_start_nbd_disk(&req); return;