From 610374cd49edad5c80e9967498a3c24d72f39173 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Wed, 2 Aug 2017 10:40:38 -0700 Subject: [PATCH] nbd: allow exporting more than one NBD at once Change-Id: Ib6245e981d550e951a518176730a0e8d88378207 Signed-off-by: Daniel Verkamp Reviewed-on: https://review.gerrithub.io/372341 Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- include/spdk/nbd.h | 7 ++-- lib/nbd/nbd.c | 92 ++++++++++++++++++++++++++++------------- test/lib/bdev/nbd/nbd.c | 10 ++--- 3 files changed, 73 insertions(+), 36 deletions(-) diff --git a/include/spdk/nbd.h b/include/spdk/nbd.h index 629e74b70c..adb9aef9c5 100644 --- a/include/spdk/nbd.h +++ b/include/spdk/nbd.h @@ -35,16 +35,17 @@ #define SPDK_NBD_H_ struct spdk_bdev; +struct spdk_nbd_disk; -int spdk_nbd_start(struct spdk_bdev *bdev, const char *nbd_path); +struct spdk_nbd_disk *spdk_nbd_start(struct spdk_bdev *bdev, const char *nbd_path); /** * Poll an NBD instance. * * \return 0 on success or negated errno values on error (e.g. connection closed). */ -int spdk_nbd_poll(void); +int spdk_nbd_poll(struct spdk_nbd_disk *nbd); -void spdk_nbd_stop(void); +void spdk_nbd_stop(struct spdk_nbd_disk *nbd); #endif diff --git a/lib/nbd/nbd.c b/lib/nbd/nbd.c index ed014ab118..cdaaf8a16c 100644 --- a/lib/nbd/nbd.c +++ b/lib/nbd/nbd.c @@ -65,7 +65,7 @@ struct nbd_io { uint32_t offset; }; -struct nbd_disk { +struct spdk_nbd_disk { struct spdk_bdev *bdev; struct spdk_bdev_desc *bdev_desc; struct spdk_io_channel *ch; @@ -74,8 +74,6 @@ struct nbd_disk { uint32_t buf_align; }; -struct nbd_disk g_nbd_disk = {}; - static bool is_read(enum spdk_bdev_io_type io_type) { @@ -99,11 +97,25 @@ is_write(enum spdk_bdev_io_type io_type) } void -spdk_nbd_stop(void) +spdk_nbd_stop(struct spdk_nbd_disk *nbd) { - spdk_put_io_channel(g_nbd_disk.ch); - spdk_bdev_close(g_nbd_disk.bdev_desc); - close(g_nbd_disk.fd); + if (nbd == NULL) { + return; + } + + if (nbd->ch) { + spdk_put_io_channel(nbd->ch); + } + + if (nbd->bdev_desc) { + spdk_bdev_close(nbd->bdev_desc); + } + + if (nbd->fd >= 0) { + close(nbd->fd); + } + + free(nbd); } static int64_t @@ -192,7 +204,7 @@ nbd_submit_bdev_io(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, } static int -process_request(struct nbd_disk *nbd) +process_request(struct spdk_nbd_disk *nbd) { struct nbd_io *io = &nbd->io; @@ -239,9 +251,8 @@ process_request(struct nbd_disk *nbd) } int -spdk_nbd_poll(void) +spdk_nbd_poll(struct spdk_nbd_disk *nbd) { - struct nbd_disk *nbd = &g_nbd_disk; struct nbd_io *io = &nbd->io; int fd = nbd->fd; int64_t ret; @@ -338,50 +349,57 @@ nbd_start_kernel(int nbd_fd, int *sp) exit(0); } -int +struct spdk_nbd_disk * spdk_nbd_start(struct spdk_bdev *bdev, const char *nbd_path) { + struct spdk_nbd_disk *nbd; int rc; - int sp[2], nbd_fd; + int sp[2] = { -1, -1 }, nbd_fd = -1; - rc = spdk_bdev_open(bdev, true, NULL, NULL, &g_nbd_disk.bdev_desc); + nbd = calloc(1, sizeof(*nbd)); + if (nbd == NULL) { + return NULL; + } + nbd->fd = -1; + + rc = spdk_bdev_open(bdev, true, NULL, NULL, &nbd->bdev_desc); if (rc != 0) { SPDK_ERRLOG("could not open bdev %s, error=%d\n", spdk_bdev_get_name(bdev), rc); - return -1; + goto err; } - g_nbd_disk.bdev = bdev; - g_nbd_disk.ch = spdk_bdev_get_io_channel(g_nbd_disk.bdev_desc); - g_nbd_disk.buf_align = spdk_max(spdk_bdev_get_buf_align(bdev), 64); + nbd->bdev = bdev; + nbd->ch = spdk_bdev_get_io_channel(nbd->bdev_desc); + nbd->buf_align = spdk_max(spdk_bdev_get_buf_align(bdev), 64); rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sp); if (rc != 0) { SPDK_ERRLOG("socketpair failed\n"); - return -1; + goto err; } nbd_fd = open(nbd_path, O_RDWR); if (nbd_fd == -1) { SPDK_ERRLOG("open(\"%s\") failed: %s\n", nbd_path, strerror(errno)); - return -1; + goto err; } rc = ioctl(nbd_fd, NBD_SET_BLKSIZE, spdk_bdev_get_block_size(bdev)); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_SET_BLKSIZE) failed: %s\n", strerror(errno)); - return -1; + goto err; } rc = ioctl(nbd_fd, NBD_SET_SIZE_BLOCKS, spdk_bdev_get_num_blocks(bdev)); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_SET_SIZE_BLOCKS) failed: %s\n", strerror(errno)); - return -1; + goto err; } rc = ioctl(nbd_fd, NBD_CLEAR_SOCK); if (rc == -1) { SPDK_ERRLOG("ioctl(NBD_CLEAR_SOCK) failed: %s\n", strerror(errno)); - return -1; + goto err; } printf("Enabling kernel access to bdev %s via %s\n", spdk_bdev_get_name(bdev), nbd_path); @@ -394,18 +412,36 @@ spdk_nbd_start(struct spdk_bdev *bdev, const char *nbd_path) break; case -1: SPDK_ERRLOG("could not fork: %s\n", strerror(errno)); - return -1; + goto err; default: + close(nbd_fd); break; } close(sp[1]); - g_nbd_disk.fd = sp[0]; - fcntl(g_nbd_disk.fd, F_SETFL, O_NONBLOCK); + nbd->fd = sp[0]; + fcntl(nbd->fd, F_SETFL, O_NONBLOCK); - to_be32(&g_nbd_disk.io.resp.magic, NBD_REPLY_MAGIC); - g_nbd_disk.io.req_in_progress = true; + to_be32(&nbd->io.resp.magic, NBD_REPLY_MAGIC); + nbd->io.req_in_progress = true; - return 0; + return nbd; + +err: + if (sp[0] >= 0) { + close(sp[0]); + } + + if (sp[1] >= 0) { + close(sp[1]); + } + + if (nbd_fd >= 0) { + close(nbd_fd); + } + + spdk_nbd_stop(nbd); + + return NULL; } diff --git a/test/lib/bdev/nbd/nbd.c b/test/lib/bdev/nbd/nbd.c index a2db07465d..730819b4b4 100644 --- a/test/lib/bdev/nbd/nbd.c +++ b/test/lib/bdev/nbd/nbd.c @@ -43,6 +43,7 @@ #include "spdk/util.h" static struct spdk_poller *g_nbd_poller; +static struct spdk_nbd_disk *g_nbd_disk; static char *g_bdev_name; static char *g_nbd_name = "/dev/nbd0"; @@ -52,7 +53,7 @@ static void nbd_shutdown(void) { spdk_poller_unregister(&g_nbd_poller, NULL); - spdk_nbd_stop(); + spdk_nbd_stop(g_nbd_disk); spdk_app_stop(0); } @@ -61,7 +62,7 @@ nbd_poll(void *arg) { int rc; - rc = spdk_nbd_poll(); + rc = spdk_nbd_poll(g_nbd_disk); if (rc < 0) { SPDK_NOTICELOG("spdk_nbd_poll() returned %d; shutting down", rc); nbd_shutdown(); @@ -72,7 +73,6 @@ static void nbd_start(void *arg1, void *arg2) { struct spdk_bdev *bdev; - int rc; bdev = spdk_bdev_get_by_name(g_bdev_name); if (bdev == NULL) { @@ -81,8 +81,8 @@ nbd_start(void *arg1, void *arg2) return; } - rc = spdk_nbd_start(bdev, g_nbd_name); - if (rc != 0) { + g_nbd_disk = spdk_nbd_start(bdev, g_nbd_name); + if (g_nbd_disk == NULL) { spdk_app_stop(-1); return; }