xref: /spdk/test/unit/lib/nvme/nvme_io_msg.c/nvme_io_msg_ut.c (revision ea941caeaf896fdf2aef7685f86f37023060faed)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2021 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk_internal/cunit.h"
8 #include "spdk/nvme.h"
9 #include "nvme/nvme_io_msg.c"
10 #include "common/lib/nvme/common_stubs.h"
11 
12 SPDK_LOG_REGISTER_COMPONENT(nvme)
13 
14 DEFINE_STUB(spdk_nvme_ctrlr_free_io_qpair, int, (struct spdk_nvme_qpair *qpair), 0);
15 
16 DEFINE_RETURN_MOCK(spdk_nvme_ctrlr_alloc_io_qpair, struct spdk_nvme_qpair *);
17 struct spdk_nvme_qpair *
spdk_nvme_ctrlr_alloc_io_qpair(struct spdk_nvme_ctrlr * ctrlr,const struct spdk_nvme_io_qpair_opts * user_opts,size_t opts_size)18 spdk_nvme_ctrlr_alloc_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
19 			       const struct spdk_nvme_io_qpair_opts *user_opts,
20 			       size_t opts_size)
21 {
22 	HANDLE_RETURN_MOCK(spdk_nvme_ctrlr_alloc_io_qpair);
23 	return NULL;
24 }
25 
26 static void
ut_io_msg_fn(struct spdk_nvme_ctrlr * ctrlr,uint32_t nsid,void * arg)27 ut_io_msg_fn(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, void *arg)
28 {
29 	static uint32_t i = 0;
30 
31 	CU_ASSERT(arg == (void *)(0xDEADBEEF + sizeof(int *) * i));
32 	CU_ASSERT(nsid == i);
33 	CU_ASSERT(ctrlr->external_io_msgs_qpair == (struct spdk_nvme_qpair *)0xDBADBEEF);
34 	i++;
35 }
36 
37 static void
test_nvme_io_msg_process(void)38 test_nvme_io_msg_process(void)
39 {
40 	struct spdk_nvme_ctrlr ctrlr = {};
41 	struct spdk_ring external_io_msgs = {};
42 	int rc, i;
43 
44 	ctrlr.external_io_msgs = &external_io_msgs;
45 	ctrlr.external_io_msgs_qpair = (struct spdk_nvme_qpair *)0xDBADBEEF;
46 	TAILQ_INIT(&external_io_msgs.elements);
47 	pthread_mutex_init(&ctrlr.external_io_msgs_lock, NULL);
48 	pthread_mutex_init(&ctrlr.external_io_msgs->lock, NULL);
49 
50 	/* Send IO processing size requests */
51 	for (i = 0; i < SPDK_NVME_MSG_IO_PROCESS_SIZE; i ++) {
52 		nvme_io_msg_send(&ctrlr, i, ut_io_msg_fn,
53 				 (void *)(0xDEADBEEF + sizeof(int *) * i));
54 	}
55 
56 	rc = nvme_io_msg_process(&ctrlr);
57 	CU_ASSERT(rc == SPDK_NVME_MSG_IO_PROCESS_SIZE);
58 	CU_ASSERT(TAILQ_EMPTY(&external_io_msgs.elements));
59 
60 	/* Unavailable external_io_msgs and external_io_msgs_qpair */
61 	ctrlr.external_io_msgs = NULL;
62 	ctrlr.external_io_msgs_qpair = NULL;
63 
64 	rc = nvme_io_msg_process(&ctrlr);
65 	SPDK_CU_ASSERT_FATAL(rc == 0);
66 }
67 
68 static void
test_nvme_io_msg_send(void)69 test_nvme_io_msg_send(void)
70 {
71 	struct spdk_nvme_ctrlr ctrlr = {};
72 	struct spdk_nvme_io_msg *request = NULL;
73 	struct spdk_ring external_io_msgs = {};
74 	int rc;
75 	uint32_t nsid = 1;
76 	void *arg = (void *)0xDEADBEEF;
77 
78 	ctrlr.external_io_msgs = &external_io_msgs;
79 	TAILQ_INIT(&external_io_msgs.elements);
80 	pthread_mutex_init(&ctrlr.external_io_msgs_lock, NULL);
81 	pthread_mutex_init(&ctrlr.external_io_msgs->lock, NULL);
82 
83 	/* Dequeue the request after sending io message */
84 	rc = nvme_io_msg_send(&ctrlr, nsid, ut_io_msg_fn, arg);
85 	spdk_ring_dequeue(ctrlr.external_io_msgs, (void **)&request, 1);
86 	CU_ASSERT(rc == 0);
87 	CU_ASSERT(request != NULL);
88 	CU_ASSERT(request->ctrlr == &ctrlr);
89 	CU_ASSERT(request->nsid == nsid);
90 	CU_ASSERT(request->fn == ut_io_msg_fn);
91 	CU_ASSERT(request->arg == arg);
92 	CU_ASSERT(TAILQ_EMPTY(&external_io_msgs.elements));
93 
94 	free(request);
95 }
96 
97 static void
ut_stop(struct spdk_nvme_ctrlr * ctrlr)98 ut_stop(struct spdk_nvme_ctrlr *ctrlr)
99 {
100 	return;
101 }
102 
103 static void
ut_update(struct spdk_nvme_ctrlr * ctrlr)104 ut_update(struct spdk_nvme_ctrlr *ctrlr)
105 {
106 	return;
107 }
108 
109 static struct nvme_io_msg_producer ut_nvme_io_msg_producer[2] = {
110 	{
111 		.name = "ut_test1",
112 		.stop = ut_stop,
113 		.update = ut_update,
114 	}, {
115 		.name = "ut_test2",
116 		.stop = ut_stop,
117 		.update = ut_update,
118 	}
119 };
120 
121 static void
test_nvme_io_msg_ctrlr_register_unregister(void)122 test_nvme_io_msg_ctrlr_register_unregister(void)
123 {
124 	struct spdk_nvme_ctrlr ctrlr = {};
125 	int rc;
126 
127 	STAILQ_INIT(&ctrlr.io_producers);
128 	MOCK_SET(spdk_nvme_ctrlr_alloc_io_qpair, (void *)0xDEADBEEF);
129 
130 	rc = nvme_io_msg_ctrlr_register(&ctrlr, &ut_nvme_io_msg_producer[0]);
131 	CU_ASSERT(rc == 0);
132 	CU_ASSERT(ctrlr.external_io_msgs != NULL);
133 	CU_ASSERT(!STAILQ_EMPTY(&ctrlr.io_producers));
134 	CU_ASSERT(ctrlr.external_io_msgs_qpair == (void *)0xDEADBEEF);
135 
136 	nvme_io_msg_ctrlr_unregister(&ctrlr, &ut_nvme_io_msg_producer[0]);
137 	CU_ASSERT(ctrlr.external_io_msgs == NULL);
138 	CU_ASSERT(ctrlr.external_io_msgs_qpair == NULL);
139 	CU_ASSERT(STAILQ_EMPTY(&ctrlr.io_producers));
140 
141 	/* Multiple producer */
142 	rc = nvme_io_msg_ctrlr_register(&ctrlr, &ut_nvme_io_msg_producer[0]);
143 	CU_ASSERT(rc == 0);
144 
145 	rc = nvme_io_msg_ctrlr_register(&ctrlr, &ut_nvme_io_msg_producer[1]);
146 	CU_ASSERT(rc == 0);
147 	CU_ASSERT(ctrlr.external_io_msgs != NULL);
148 	CU_ASSERT(ctrlr.external_io_msgs_qpair == (void *)0xDEADBEEF);
149 	nvme_io_msg_ctrlr_unregister(&ctrlr, &ut_nvme_io_msg_producer[0]);
150 	CU_ASSERT(!STAILQ_EMPTY(&ctrlr.io_producers));
151 	nvme_io_msg_ctrlr_unregister(&ctrlr, &ut_nvme_io_msg_producer[1]);
152 	CU_ASSERT(STAILQ_EMPTY(&ctrlr.io_producers));
153 	CU_ASSERT(ctrlr.external_io_msgs == NULL);
154 	CU_ASSERT(ctrlr.external_io_msgs_qpair == NULL);
155 
156 	/* The same producer exist */
157 	rc = nvme_io_msg_ctrlr_register(&ctrlr, &ut_nvme_io_msg_producer[0]);
158 	CU_ASSERT(rc == 0);
159 	CU_ASSERT(ctrlr.external_io_msgs != NULL);
160 	CU_ASSERT(ctrlr.external_io_msgs_qpair == (void *)0xDEADBEEF);
161 
162 	rc = nvme_io_msg_ctrlr_register(&ctrlr, &ut_nvme_io_msg_producer[0]);
163 	CU_ASSERT(rc == -EEXIST);
164 	nvme_io_msg_ctrlr_unregister(&ctrlr, &ut_nvme_io_msg_producer[0]);
165 	CU_ASSERT(STAILQ_EMPTY(&ctrlr.io_producers));
166 	CU_ASSERT(ctrlr.external_io_msgs == NULL);
167 	CU_ASSERT(ctrlr.external_io_msgs_qpair == NULL);
168 	MOCK_CLEAR(spdk_nvme_ctrlr_alloc_io_qpair);
169 }
170 
171 int
main(int argc,char ** argv)172 main(int argc, char **argv)
173 {
174 	CU_pSuite	suite = NULL;
175 	unsigned int	num_failures;
176 
177 	CU_initialize_registry();
178 
179 	suite = CU_add_suite("nvme_io_msg", NULL, NULL);
180 	CU_ADD_TEST(suite, test_nvme_io_msg_send);
181 	CU_ADD_TEST(suite, test_nvme_io_msg_process);
182 	CU_ADD_TEST(suite, test_nvme_io_msg_ctrlr_register_unregister);
183 
184 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
185 	CU_cleanup_registry();
186 	return num_failures;
187 }
188