From 1f20593b87ea4af0e5da5291b2ee5787210d84cf Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Mon, 19 Nov 2018 14:03:26 -0700 Subject: [PATCH] nbd: Wait for kernel module to become ready on start up The ioctl NBD_SET_SOCK can return EBUSY if the kernel module hasn't loaded entirely yet. Wait for it to become ready. Change-Id: If3c6d0d8bb678ef8cab0efc1c5e800e95e19133e Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/433939 Chandler-Test-Pool: SPDK Automated Test System Tested-by: SPDK CI Jenkins Reviewed-by: Darek Stojaczyk Reviewed-by: Jim Harris --- lib/nbd/nbd.c | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/lib/nbd/nbd.c b/lib/nbd/nbd.c index 7d34f97f20..715277073a 100644 --- a/lib/nbd/nbd.c +++ b/lib/nbd/nbd.c @@ -841,6 +841,7 @@ struct spdk_nbd_start_ctx { struct spdk_nbd_disk *nbd; spdk_nbd_start_cb cb_fn; void *cb_arg; + struct spdk_poller *poller; }; static void @@ -896,6 +897,47 @@ err: free(ctx); } +static int +spdk_nbd_enable_kernel(void *arg) +{ + struct spdk_nbd_start_ctx *ctx = arg; + int rc; + + rc = ioctl(ctx->nbd->dev_fd, NBD_SET_SOCK, ctx->nbd->kernel_sp_fd); + if (rc == -1) { + if (errno == EBUSY) { + if (ctx->poller == NULL) { + ctx->poller = spdk_poller_register(spdk_nbd_enable_kernel, ctx, 20000); + } + /* If the kernel is busy, check back later */ + return 0; + } + + + SPDK_ERRLOG("ioctl(NBD_SET_SOCK) failed: %s\n", spdk_strerror(errno)); + if (ctx->poller) { + spdk_poller_unregister(&ctx->poller); + } + + spdk_nbd_stop(ctx->nbd); + + if (ctx->cb_fn) { + ctx->cb_fn(ctx->cb_arg, NULL, -errno); + } + + free(ctx); + return 1; + } + + if (ctx->poller) { + spdk_poller_unregister(&ctx->poller); + } + + spdk_nbd_start_complete(ctx); + + return 1; +} + void spdk_nbd_start(const char *bdev_name, const char *nbd_path, spdk_nbd_start_cb cb_fn, void *cb_arg) @@ -999,14 +1041,7 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path, SPDK_INFOLOG(SPDK_LOG_NBD, "Enabling kernel access to bdev %s via %s\n", spdk_bdev_get_name(bdev), 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; - } - - spdk_nbd_start_complete(ctx); + spdk_nbd_enable_kernel(ctx); return; err: