nbd: get nbd_stop procedure in async
It is possible that nbd pthread is created but not executed, then spdk_nbd_stop is call before nbd_pthread's execution, but nbd pthread starts to execute while nbd is totally stopped. This patch can get spdk_stop_nbd aligned with nbd pthread. Change-Id: I57cc92b94d36cd706616c9058134f716f0812892 Signed-off-by: Liu Xiaodong <xiaodong.liu@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6278 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: <dongx.yi@intel.com>
This commit is contained in:
parent
4c6c794be3
commit
22412af1d2
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#define GET_IO_LOOP_COUNT 16
|
#define GET_IO_LOOP_COUNT 16
|
||||||
#define NBD_START_BUSY_WAITING_MS 1000
|
#define NBD_START_BUSY_WAITING_MS 1000
|
||||||
|
#define NBD_STOP_BUSY_WAITING_MS 10000
|
||||||
#define NBD_BUSY_POLLING_INTERVAL_US 20000
|
#define NBD_BUSY_POLLING_INTERVAL_US 20000
|
||||||
#define NBD_IO_TIMEOUT_S 60
|
#define NBD_IO_TIMEOUT_S 60
|
||||||
|
|
||||||
@ -108,6 +109,8 @@ struct spdk_nbd_disk {
|
|||||||
|
|
||||||
struct spdk_poller *retry_poller;
|
struct spdk_poller *retry_poller;
|
||||||
int retry_count;
|
int retry_count;
|
||||||
|
/* Synchronize nbd_start_kernel pthread and nbd_stop */
|
||||||
|
bool has_nbd_pthread;
|
||||||
|
|
||||||
struct nbd_io *io_in_recv;
|
struct nbd_io *io_in_recv;
|
||||||
TAILQ_HEAD(, nbd_io) received_io_list;
|
TAILQ_HEAD(, nbd_io) received_io_list;
|
||||||
@ -370,9 +373,11 @@ nbd_cleanup_io(struct spdk_nbd_disk *nbd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
_nbd_stop(struct spdk_nbd_disk *nbd)
|
_nbd_stop(void *arg)
|
||||||
{
|
{
|
||||||
|
struct spdk_nbd_disk *nbd = arg;
|
||||||
|
|
||||||
if (nbd->nbd_poller) {
|
if (nbd->nbd_poller) {
|
||||||
spdk_poller_unregister(&nbd->nbd_poller);
|
spdk_poller_unregister(&nbd->nbd_poller);
|
||||||
}
|
}
|
||||||
@ -383,10 +388,32 @@ _nbd_stop(struct spdk_nbd_disk *nbd)
|
|||||||
|
|
||||||
if (nbd->spdk_sp_fd >= 0) {
|
if (nbd->spdk_sp_fd >= 0) {
|
||||||
close(nbd->spdk_sp_fd);
|
close(nbd->spdk_sp_fd);
|
||||||
|
nbd->spdk_sp_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbd->kernel_sp_fd >= 0) {
|
if (nbd->kernel_sp_fd >= 0) {
|
||||||
close(nbd->kernel_sp_fd);
|
close(nbd->kernel_sp_fd);
|
||||||
|
nbd->kernel_sp_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Continue the stop procedure after the exit of nbd_start_kernel pthread */
|
||||||
|
if (nbd->has_nbd_pthread) {
|
||||||
|
if (nbd->retry_poller == NULL) {
|
||||||
|
nbd->retry_count = NBD_STOP_BUSY_WAITING_MS * 1000ULL / NBD_BUSY_POLLING_INTERVAL_US;
|
||||||
|
nbd->retry_poller = SPDK_POLLER_REGISTER(_nbd_stop, nbd,
|
||||||
|
NBD_BUSY_POLLING_INTERVAL_US);
|
||||||
|
return SPDK_POLLER_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbd->retry_count-- > 0) {
|
||||||
|
return SPDK_POLLER_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPDK_ERRLOG("Failed to wait for returning of NBD_DO_IT ioctl.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nbd->retry_poller) {
|
||||||
|
spdk_poller_unregister(&nbd->retry_poller);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbd->dev_fd >= 0) {
|
if (nbd->dev_fd >= 0) {
|
||||||
@ -404,15 +431,19 @@ _nbd_stop(struct spdk_nbd_disk *nbd)
|
|||||||
|
|
||||||
if (nbd->ch) {
|
if (nbd->ch) {
|
||||||
spdk_put_io_channel(nbd->ch);
|
spdk_put_io_channel(nbd->ch);
|
||||||
|
nbd->ch = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbd->bdev_desc) {
|
if (nbd->bdev_desc) {
|
||||||
spdk_bdev_close(nbd->bdev_desc);
|
spdk_bdev_close(nbd->bdev_desc);
|
||||||
|
nbd->bdev_desc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbd_disk_unregister(nbd);
|
nbd_disk_unregister(nbd);
|
||||||
|
|
||||||
free(nbd);
|
free(nbd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -876,12 +907,14 @@ nbd_poll(void *arg)
|
|||||||
static void *
|
static void *
|
||||||
nbd_start_kernel(void *arg)
|
nbd_start_kernel(void *arg)
|
||||||
{
|
{
|
||||||
int dev_fd = (int)(intptr_t)arg;
|
struct spdk_nbd_disk *nbd = arg;
|
||||||
|
|
||||||
spdk_unaffinitize_thread();
|
spdk_unaffinitize_thread();
|
||||||
|
|
||||||
/* This will block in the kernel until we close the spdk_sp_fd. */
|
/* This will block in the kernel until we close the spdk_sp_fd. */
|
||||||
ioctl(dev_fd, NBD_DO_IT);
|
ioctl(nbd->dev_fd, NBD_DO_IT);
|
||||||
|
|
||||||
|
nbd->has_nbd_pthread = false;
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
@ -960,8 +993,10 @@ nbd_start_complete(struct spdk_nbd_start_ctx *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = pthread_create(&tid, NULL, nbd_start_kernel, (void *)(intptr_t)ctx->nbd->dev_fd);
|
ctx->nbd->has_nbd_pthread = true;
|
||||||
|
rc = pthread_create(&tid, NULL, nbd_start_kernel, ctx->nbd);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
|
ctx->nbd->has_nbd_pthread = false;
|
||||||
SPDK_ERRLOG("could not create thread: %s\n", spdk_strerror(rc));
|
SPDK_ERRLOG("could not create thread: %s\n", spdk_strerror(rc));
|
||||||
rc = -rc;
|
rc = -rc;
|
||||||
goto err;
|
goto err;
|
||||||
|
Loading…
Reference in New Issue
Block a user