From 36e8c20fe96ff4fa92cfc0a289677ffc2b1ecc25 Mon Sep 17 00:00:00 2001 From: Xiaodong Liu Date: Thu, 14 Feb 2019 20:27:08 +0800 Subject: [PATCH] nbd: avoid impact to device setup by other task Use NBD_SET_SOCK to check whether the nbd device is setup by other process or whether nbd kernel module is ready before other nbd ioctl operations. This can avoid bad influence to the nbd device setup by other process. Change-Id: Ic12acbfddb8c4388e25731c39159b1ce559b8f23 Signed-off-by: Xiaodong Liu Reviewed-on: https://review.gerrithub.io/c/444805 Tested-by: SPDK CI Jenkins Reviewed-by: Pawel Wodkowski Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- lib/nbd/nbd.c | 66 ++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/lib/nbd/nbd.c b/lib/nbd/nbd.c index 00e104f1b2..ff850196b2 100644 --- a/lib/nbd/nbd.c +++ b/lib/nbd/nbd.c @@ -355,10 +355,6 @@ _nbd_stop(struct spdk_nbd_disk *nbd) spdk_bdev_close(nbd->bdev_desc); } - if (nbd->nbd_path) { - free(nbd->nbd_path); - } - if (nbd->spdk_sp_fd >= 0) { close(nbd->spdk_sp_fd); } @@ -368,11 +364,18 @@ _nbd_stop(struct spdk_nbd_disk *nbd) } if (nbd->dev_fd >= 0) { - ioctl(nbd->dev_fd, NBD_CLEAR_QUE); - ioctl(nbd->dev_fd, NBD_CLEAR_SOCK); + /* Clear nbd device only if it is occupied by SPDK app */ + if (nbd->nbd_path && spdk_nbd_disk_find_by_nbd_path(nbd->nbd_path)) { + ioctl(nbd->dev_fd, NBD_CLEAR_QUE); + ioctl(nbd->dev_fd, NBD_CLEAR_SOCK); + } close(nbd->dev_fd); } + if (nbd->nbd_path) { + free(nbd->nbd_path); + } + if (nbd->nbd_poller) { spdk_poller_unregister(&nbd->nbd_poller); } @@ -854,6 +857,28 @@ spdk_nbd_start_complete(struct spdk_nbd_start_ctx *ctx) pthread_t tid; int flag; + /* Add nbd_disk to the end of disk list */ + rc = spdk_nbd_disk_register(ctx->nbd); + if (rc != 0) { + SPDK_ERRLOG("Failed to register %s, it should not happen.\n", ctx->nbd->nbd_path); + assert(false); + goto err; + } + + rc = ioctl(ctx->nbd->dev_fd, NBD_SET_BLKSIZE, spdk_bdev_get_block_size(ctx->nbd->bdev)); + if (rc == -1) { + SPDK_ERRLOG("ioctl(NBD_SET_BLKSIZE) failed: %s\n", spdk_strerror(errno)); + rc = -errno; + goto err; + } + + rc = ioctl(ctx->nbd->dev_fd, NBD_SET_SIZE_BLOCKS, spdk_bdev_get_num_blocks(ctx->nbd->bdev)); + if (rc == -1) { + SPDK_ERRLOG("ioctl(NBD_SET_SIZE_BLOCKS) failed: %s\n", spdk_strerror(errno)); + rc = -errno; + goto err; + } + #ifdef NBD_FLAG_SEND_TRIM rc = ioctl(ctx->nbd->dev_fd, NBD_SET_FLAGS, NBD_FLAG_SEND_TRIM); if (rc == -1) { @@ -908,6 +933,7 @@ spdk_nbd_enable_kernel(void *arg) struct spdk_nbd_start_ctx *ctx = arg; int rc; + /* Declare device setup by this process */ rc = ioctl(ctx->nbd->dev_fd, NBD_SET_SOCK, ctx->nbd->kernel_sp_fd); if (rc == -1) { if (errno == EBUSY && ctx->polling_count-- > 0) { @@ -1011,9 +1037,10 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path, TAILQ_INIT(&nbd->received_io_list); TAILQ_INIT(&nbd->executed_io_list); - /* Add nbd_disk to the end of disk list */ - rc = spdk_nbd_disk_register(nbd); - if (rc != 0) { + /* Make sure nbd_path is not used in this SPDK app */ + if (spdk_nbd_disk_find_by_nbd_path(nbd->nbd_path)) { + SPDK_NOTICELOG("%s is already exported\n", nbd->nbd_path); + rc = -EBUSY; goto err; } @@ -1024,27 +1051,6 @@ spdk_nbd_start(const char *bdev_name, const char *nbd_path, 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; - } - SPDK_INFOLOG(SPDK_LOG_NBD, "Enabling kernel access to bdev %s via %s\n", spdk_bdev_get_name(bdev), nbd_path);