From da2fd6651a9cd4732b0910d30291821e77f4d643 Mon Sep 17 00:00:00 2001 From: MengjinWu Date: Wed, 9 Jun 2021 10:07:42 +0800 Subject: [PATCH] lib/nbd: fix conflict between nbd start and stop Now nbd stop will not be processed if this nbd is not fully started. However, it will remember the stop command and do it asychronously until nbd is fully started. Signed-off-by: MengjinWu Change-Id: Iea5ba143332c7d3fd85f816726788f05e7ae3c8d Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8037 Reviewed-by: Shuhei Matsumoto Reviewed-by: Ziye Yang Reviewed-by: Changpeng Liu Tested-by: SPDK CI Jenkins Community-CI: Broadcom CI --- lib/nbd/nbd.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/lib/nbd/nbd.c b/lib/nbd/nbd.c index 1651dd0e24..0448ed816f 100644 --- a/lib/nbd/nbd.c +++ b/lib/nbd/nbd.c @@ -87,14 +87,6 @@ struct nbd_io { TAILQ_ENTRY(nbd_io) tailq; }; -enum nbd_disk_state_t { - NBD_DISK_STATE_RUNNING = 0, - /* soft disconnection caused by receiving nbd_cmd_disc */ - NBD_DISK_STATE_SOFTDISC, - /* hard disconnection caused by mandatory conditions */ - NBD_DISK_STATE_HARDDISC, -}; - struct spdk_nbd_disk { struct spdk_bdev *bdev; struct spdk_bdev_desc *bdev_desc; @@ -117,7 +109,8 @@ struct spdk_nbd_disk { TAILQ_HEAD(, nbd_io) received_io_list; TAILQ_HEAD(, nbd_io) executed_io_list; - enum nbd_disk_state_t state; + bool is_started; + bool is_closing; /* count of nbd_io in spdk_nbd_disk */ int io_count; @@ -152,9 +145,8 @@ _nbd_fini(void *arg1) { struct spdk_nbd_disk *nbd, *nbd_tmp; - /* Change all nbds into closing state */ TAILQ_FOREACH_SAFE(nbd, &g_spdk_nbd.disk_head, tailq, nbd_tmp) { - if (nbd->state != NBD_DISK_STATE_HARDDISC) { + if (!nbd->is_closing) { spdk_nbd_stop(nbd); } } @@ -422,7 +414,12 @@ spdk_nbd_stop(struct spdk_nbd_disk *nbd) return rc; } - nbd->state = NBD_DISK_STATE_HARDDISC; + nbd->is_closing = true; + + /* if nbd is not started, it will continue to call nbd stop later */ + if (!nbd->is_started) { + return 1; + } /* * Stop action should be called only after all nbd_io are executed. @@ -548,7 +545,7 @@ nbd_submit_bdev_io(struct spdk_nbd_disk *nbd, struct nbd_io *io) break; #endif case NBD_CMD_DISC: - nbd->state = NBD_DISK_STATE_SOFTDISC; + nbd->is_closing = true; rc = spdk_bdev_abort(desc, ch, io, nbd_io_done, io); /* when there begins to have executed_io to send, enable socket writable notice */ @@ -663,7 +660,7 @@ nbd_io_recv_internal(struct spdk_nbd_disk *nbd) io->state = NBD_IO_RECV_PAYLOAD; } else { io->state = NBD_IO_XMIT_RESP; - if (spdk_likely(nbd->state == NBD_DISK_STATE_RUNNING)) { + if (spdk_likely((!nbd->is_closing) && nbd->is_started)) { TAILQ_INSERT_TAIL(&nbd->received_io_list, io, tailq); } else { nbd_io_done(NULL, false, io); @@ -688,7 +685,7 @@ nbd_io_recv_internal(struct spdk_nbd_disk *nbd) if (io->offset == io->payload_size) { io->offset = 0; io->state = NBD_IO_XMIT_RESP; - if (spdk_likely(nbd->state == NBD_DISK_STATE_RUNNING)) { + if (spdk_likely((!nbd->is_closing) && nbd->is_started)) { TAILQ_INSERT_TAIL(&nbd->received_io_list, io, tailq); } else { nbd_io_done(NULL, false, io); @@ -707,10 +704,9 @@ nbd_io_recv(struct spdk_nbd_disk *nbd) int i, rc, ret = 0; /* - * nbd server should not accept request in both soft and hard - * disconnect states. + * nbd server should not accept request after closing command */ - if (nbd->state != NBD_DISK_STATE_RUNNING) { + if (nbd->is_closing) { return 0; } @@ -854,16 +850,13 @@ nbd_poll(void *arg) SPDK_INFOLOG(nbd, "nbd_poll() returned %s (%d); closing connection\n", spdk_strerror(-rc), rc); _nbd_stop(nbd); + return SPDK_POLLER_IDLE; } - if (nbd->state != NBD_DISK_STATE_RUNNING) { - if (nbd->state == NBD_DISK_STATE_HARDDISC && !nbd_cleanup_io(nbd)) { - _nbd_stop(nbd); - } else if (nbd->state == NBD_DISK_STATE_SOFTDISC) { - spdk_nbd_stop(nbd); - } + if (nbd->is_closing) { + spdk_nbd_stop(nbd); } - return rc > 0 ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE; + return SPDK_POLLER_BUSY; } static void * @@ -989,6 +982,9 @@ nbd_start_complete(struct spdk_nbd_start_ctx *ctx) ctx->cb_fn(ctx->cb_arg, ctx->nbd, 0); } + /* nbd will possibly receive stop command while initing */ + ctx->nbd->is_started = true; + free(ctx); return;