Commit e038e096 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Tomasz Zawadzki
Browse files

lib/thread: Fail spdk_thread_exit() if thread has active I/O channel



This is a preparation to support voluntary thread termination by
calling spdk_thread_exit().

The comment in the header file has already said that all associated
I/O channels must be released before calling spdk_thread_exit().
This patch actually checks if it is satisfied in spdk_thread_exit().

Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I56ac50b561c6ca91d3dc2d60c21c8d91d38f081b
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/823


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarAleksey Marchuk <alexeymar@mellanox.com>
parent 648d6cd5
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -349,6 +349,7 @@ int
spdk_thread_exit(struct spdk_thread *thread)
{
	struct spdk_poller *poller;
	struct spdk_io_channel *ch;

	SPDK_DEBUGLOG(SPDK_LOG_THREAD, "Exit thread %s\n", thread->name);

@@ -382,6 +383,14 @@ spdk_thread_exit(struct spdk_thread *thread)
		return -EBUSY;
	}

	TAILQ_FOREACH(ch, &thread->io_channels, tailq) {
		if (ch->ref != 0) {
			SPDK_ERRLOG("thread %s still has active channel for io_device %s\n",
				    thread->name, ch->dev->name);
			return -EBUSY;
		}
	}

	thread->exit = true;
	return 0;
}
+28 −2
Original line number Diff line number Diff line
@@ -755,7 +755,7 @@ thread_exit(void)
	bool done1 = false, done2 = false, poller_run = false;
	int rc __attribute__((unused));

	allocate_threads(5);
	allocate_threads(6);

	/* Test all pending messages are reaped for the thread marked as exited. */
	set_thread(0);
@@ -820,7 +820,7 @@ thread_exit(void)
	CU_ASSERT(spdk_thread_exit(thread) == 0);
	CU_ASSERT(spdk_thread_exit(thread) == -EINVAL);

	/* Test if spdk_thread_exit() fails when there is any not-unregistered poller,
	/* Test if spdk_thread_exit() fails when there is any registered poller,
	 * and if no poller is executed after the thread is marked as exited.
	 */
	set_thread(4);
@@ -847,6 +847,32 @@ thread_exit(void)

	CU_ASSERT(poller_run == false);

	/* Test if spdk_thread_exit() fails when there is any active I/O channel. */
	set_thread(5);
	thread = spdk_get_thread();

	spdk_io_device_register(&g_device1, create_cb_1, destroy_cb_1, sizeof(g_ctx1), NULL);

	g_create_cb_calls = 0;
	ch = spdk_get_io_channel(&g_device1);
	CU_ASSERT(g_create_cb_calls == 1);
	CU_ASSERT(ch != NULL);

	CU_ASSERT(spdk_thread_exit(thread) == -EBUSY);

	g_destroy_cb_calls = 0;
	spdk_put_io_channel(ch);
	CU_ASSERT(g_destroy_cb_calls == 0);

	CU_ASSERT(spdk_thread_exit(thread) == 0);

	poll_threads();
	CU_ASSERT(g_destroy_cb_calls == 1);

	spdk_io_device_unregister(&g_device1, NULL);

	CU_ASSERT(TAILQ_EMPTY(&thread->io_channels));

	free_threads();
}