Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk_internal/cunit.h"
8 : :
9 : : #include "nvme/nvme_poll_group.c"
10 : : #include "common/lib/test_env.c"
11 : :
12 : 6 : SPDK_LOG_REGISTER_COMPONENT(nvme)
13 : :
14 : : struct spdk_nvme_transport {
15 : : const char name[32];
16 : : TAILQ_ENTRY(spdk_nvme_transport) link;
17 : : };
18 : :
19 : : struct spdk_nvme_transport t1 = {
20 : : .name = "transport1",
21 : : };
22 : :
23 : : struct spdk_nvme_transport t2 = {
24 : : .name = "transport2",
25 : : };
26 : :
27 : : struct spdk_nvme_transport t3 = {
28 : : .name = "transport3",
29 : : };
30 : :
31 : : struct spdk_nvme_transport t4 = {
32 : : .name = "transport4",
33 : : };
34 : :
35 : : int64_t g_process_completions_return_value = 0;
36 : : int g_destroy_return_value = 0;
37 : :
38 : : TAILQ_HEAD(nvme_transport_list, spdk_nvme_transport) g_spdk_nvme_transports =
39 : : TAILQ_HEAD_INITIALIZER(g_spdk_nvme_transports);
40 : :
41 [ # # ]: 0 : DEFINE_STUB(nvme_transport_qpair_get_optimal_poll_group,
42 : : struct spdk_nvme_transport_poll_group *,
43 : : (const struct spdk_nvme_transport *transport,
44 : : struct spdk_nvme_qpair *qpair),
45 : : NULL);
46 [ - + ]: 36 : DEFINE_STUB(nvme_transport_get_trtype,
47 : : enum spdk_nvme_transport_type,
48 : : (const struct spdk_nvme_transport *transport),
49 : : SPDK_NVME_TRANSPORT_PCIE);
50 : :
51 : : int
52 : 18 : nvme_transport_poll_group_get_stats(struct spdk_nvme_transport_poll_group *tgroup,
53 : : struct spdk_nvme_transport_poll_group_stat **stats)
54 : : {
55 : 18 : *stats = calloc(1, sizeof(**stats));
56 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(*stats != NULL);
57 : 18 : (*stats)->trtype = nvme_transport_get_trtype(NULL);
58 : :
59 : 18 : return 0;
60 : : }
61 : :
62 : : void
63 : 18 : nvme_transport_poll_group_free_stats(struct spdk_nvme_transport_poll_group *tgroup,
64 : : struct spdk_nvme_transport_poll_group_stat *stats)
65 : : {
66 : 18 : free(stats);
67 : 18 : }
68 : :
69 : : static void
70 : 0 : unit_test_disconnected_qpair_cb(struct spdk_nvme_qpair *qpair, void *poll_group_ctx)
71 : : {
72 : :
73 : 0 : }
74 : :
75 : : const struct spdk_nvme_transport *
76 : 42 : nvme_get_first_transport(void)
77 : : {
78 : 42 : return TAILQ_FIRST(&g_spdk_nvme_transports);
79 : : }
80 : :
81 : : const struct spdk_nvme_transport *
82 : 60 : nvme_get_next_transport(const struct spdk_nvme_transport *transport)
83 : : {
84 : 60 : return TAILQ_NEXT(transport, link);
85 : : }
86 : :
87 : : int
88 : 0 : nvme_transport_poll_group_disconnect_qpair(struct spdk_nvme_qpair *qpair)
89 : : {
90 : : struct spdk_nvme_transport_poll_group *tgroup;
91 : : struct spdk_nvme_qpair *iter_qp, *tmp_iter_qp;
92 : :
93 : 0 : tgroup = qpair->poll_group;
94 : :
95 [ # # ]: 0 : STAILQ_FOREACH_SAFE(iter_qp, &tgroup->connected_qpairs, poll_group_stailq, tmp_iter_qp) {
96 [ # # ]: 0 : if (qpair == iter_qp) {
97 [ # # # # : 0 : STAILQ_REMOVE(&tgroup->connected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
# # # # ]
98 : 0 : STAILQ_INSERT_TAIL(&tgroup->disconnected_qpairs, qpair, poll_group_stailq);
99 : 0 : return 0;
100 : : }
101 : : }
102 : :
103 [ # # ]: 0 : STAILQ_FOREACH(iter_qp, &tgroup->disconnected_qpairs, poll_group_stailq) {
104 [ # # ]: 0 : if (qpair == iter_qp) {
105 : 0 : return 0;
106 : : }
107 : : }
108 : :
109 : 0 : return -EINVAL;
110 : : }
111 : :
112 : : int
113 : 6 : nvme_transport_poll_group_connect_qpair(struct spdk_nvme_qpair *qpair)
114 : : {
115 : : struct spdk_nvme_transport_poll_group *tgroup;
116 : : struct spdk_nvme_qpair *iter_qp, *tmp_iter_qp;
117 : :
118 : 6 : tgroup = qpair->poll_group;
119 : :
120 [ - + ]: 6 : STAILQ_FOREACH_SAFE(iter_qp, &tgroup->disconnected_qpairs, poll_group_stailq, tmp_iter_qp) {
121 [ # # ]: 0 : if (qpair == iter_qp) {
122 [ # # # # : 0 : STAILQ_REMOVE(&tgroup->disconnected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
# # # # ]
123 : 0 : STAILQ_INSERT_TAIL(&tgroup->connected_qpairs, qpair, poll_group_stailq);
124 : 0 : return 0;
125 : : }
126 : : }
127 : :
128 [ + - ]: 6 : STAILQ_FOREACH(iter_qp, &tgroup->connected_qpairs, poll_group_stailq) {
129 [ + - ]: 6 : if (qpair == iter_qp) {
130 : 6 : return 0;
131 : : }
132 : : }
133 : :
134 : 0 : return -EINVAL;
135 : : }
136 : :
137 : : struct spdk_nvme_transport_poll_group *
138 : 30 : nvme_transport_poll_group_create(const struct spdk_nvme_transport *transport)
139 : : {
140 : 30 : struct spdk_nvme_transport_poll_group *group = NULL;
141 : :
142 : : /* TODO: separate this transport function table from the transport specific one. */
143 : 30 : group = calloc(1, sizeof(*group));
144 [ + - ]: 30 : if (group) {
145 : 30 : group->transport = transport;
146 : 30 : STAILQ_INIT(&group->connected_qpairs);
147 : 30 : STAILQ_INIT(&group->disconnected_qpairs);
148 : : }
149 : :
150 : 30 : return group;
151 : : }
152 : :
153 : : int
154 : 12 : nvme_transport_poll_group_destroy(struct spdk_nvme_transport_poll_group *tgroup)
155 : : {
156 : 12 : return g_destroy_return_value;
157 : : }
158 : :
159 : : int
160 : 42 : nvme_transport_poll_group_add(struct spdk_nvme_transport_poll_group *tgroup,
161 : : struct spdk_nvme_qpair *qpair)
162 : : {
163 : 42 : STAILQ_INSERT_TAIL(&tgroup->connected_qpairs, qpair, poll_group_stailq);
164 : 42 : qpair->poll_group = tgroup;
165 : :
166 : 42 : return 0;
167 : : }
168 : :
169 : : int
170 : 36 : nvme_transport_poll_group_remove(struct spdk_nvme_transport_poll_group *tgroup,
171 : : struct spdk_nvme_qpair *qpair)
172 : : {
173 : : struct spdk_nvme_qpair *iter_qp, *tmp_iter_qp;
174 : :
175 [ + - ]: 36 : STAILQ_FOREACH_SAFE(iter_qp, &tgroup->connected_qpairs, poll_group_stailq, tmp_iter_qp) {
176 [ + - ]: 36 : if (qpair == iter_qp) {
177 [ + - + + : 36 : STAILQ_REMOVE(&tgroup->connected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
- - - - ]
178 : 36 : return 0;
179 : : }
180 : : }
181 : :
182 [ # # ]: 0 : STAILQ_FOREACH_SAFE(iter_qp, &tgroup->disconnected_qpairs, poll_group_stailq, tmp_iter_qp) {
183 [ # # ]: 0 : if (qpair == iter_qp) {
184 [ # # # # : 0 : STAILQ_REMOVE(&tgroup->disconnected_qpairs, qpair, spdk_nvme_qpair, poll_group_stailq);
# # # # ]
185 : 0 : return 0;
186 : : }
187 : : }
188 : :
189 : 0 : return -ENODEV;
190 : : }
191 : :
192 : : int64_t
193 : 6 : nvme_transport_poll_group_process_completions(struct spdk_nvme_transport_poll_group *group,
194 : : uint32_t completions_per_qpair, spdk_nvme_disconnected_qpair_cb disconnected_qpair_cb)
195 : : {
196 : 6 : return g_process_completions_return_value;
197 : : }
198 : :
199 : : static void
200 : 6 : test_spdk_nvme_poll_group_create(void)
201 : : {
202 : : struct spdk_nvme_poll_group *group;
203 : :
204 : : /* basic case - create a poll group with no internal transport poll groups. */
205 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
206 : :
207 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
208 : 6 : CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
209 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
210 : :
211 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
212 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
213 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
214 : :
215 : : /* advanced case - create a poll group with three internal poll groups. */
216 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
217 : 6 : CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
218 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
219 : :
220 : : /* Failing case - failed to allocate a poll group. */
221 : 6 : MOCK_SET(calloc, NULL);
222 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
223 : 6 : CU_ASSERT(group == NULL);
224 [ - - - + ]: 6 : MOCK_CLEAR(calloc);
225 : :
226 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t1, link);
227 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t2, link);
228 [ - + ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t3, link);
229 : 6 : }
230 : :
231 : : static void
232 : 6 : test_spdk_nvme_poll_group_add_remove(void)
233 : : {
234 : : struct spdk_nvme_poll_group *group;
235 : 6 : struct spdk_nvme_transport_poll_group *tgroup = NULL, *tmp_tgroup, *tgroup_1 = NULL,
236 : 6 : *tgroup_2 = NULL,
237 : 6 : *tgroup_4 = NULL;
238 : : struct spdk_nvme_qpair *qpair;
239 : 6 : struct spdk_nvme_qpair qpair1_1 = {0};
240 : 6 : struct spdk_nvme_qpair qpair1_2 = {0};
241 : 6 : struct spdk_nvme_qpair qpair2_1 = {0};
242 : 6 : struct spdk_nvme_qpair qpair2_2 = {0};
243 : 6 : struct spdk_nvme_qpair qpair4_1 = {0};
244 : 6 : struct spdk_nvme_qpair qpair4_2 = {0};
245 : 6 : int i = 0;
246 : :
247 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
248 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
249 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
250 : :
251 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
252 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
253 : 6 : CU_ASSERT(STAILQ_EMPTY(&group->tgroups));
254 : :
255 : : /* Add qpairs to a single transport. */
256 : 6 : qpair1_1.transport = &t1;
257 : 6 : qpair1_1.state = NVME_QPAIR_DISCONNECTED;
258 : 6 : qpair1_2.transport = &t1;
259 : 6 : qpair1_2.state = NVME_QPAIR_ENABLED;
260 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
261 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_2) == -EINVAL);
262 [ + + ]: 12 : STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
263 [ + - ]: 6 : if (tmp_tgroup->transport == &t1) {
264 : 6 : tgroup = tmp_tgroup;
265 : : } else {
266 : 0 : CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
267 : : }
268 : 6 : i++;
269 : : }
270 : 6 : CU_ASSERT(i == 1);
271 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(tgroup != NULL);
272 : 6 : qpair = STAILQ_FIRST(&tgroup->connected_qpairs);
273 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
274 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
275 : 6 : CU_ASSERT(qpair == NULL);
276 : :
277 : : /* Add qpairs to a second transport. */
278 : 6 : qpair2_1.transport = &t2;
279 : 6 : qpair2_2.transport = &t2;
280 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair2_1) == 0);
281 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair2_2) == 0);
282 : 6 : qpair4_1.transport = &t4;
283 : 6 : qpair4_2.transport = &t4;
284 : : /* Add qpairs for a transport that doesn't exist. */
285 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_1) == -ENODEV);
286 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_2) == -ENODEV);
287 : 6 : i = 0;
288 [ + + ]: 18 : STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
289 [ + + ]: 12 : if (tmp_tgroup->transport == &t1) {
290 : 6 : tgroup_1 = tmp_tgroup;
291 [ + - ]: 6 : } else if (tmp_tgroup->transport == &t2) {
292 : 6 : tgroup_2 = tmp_tgroup;
293 : : } else {
294 : 0 : CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
295 : : }
296 : 12 : i++;
297 : : }
298 : 6 : CU_ASSERT(i == 2);
299 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(tgroup_1 != NULL);
300 : 6 : qpair = STAILQ_FIRST(&tgroup_1->connected_qpairs);
301 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
302 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
303 : 6 : CU_ASSERT(qpair == NULL);
304 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(tgroup_2 != NULL);
305 : 6 : qpair = STAILQ_FIRST(&tgroup_2->connected_qpairs);
306 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair2_1);
307 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
308 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair2_2);
309 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
310 : 6 : CU_ASSERT(qpair == NULL);
311 : :
312 : : /* Try removing a qpair that belongs to a transport not in our poll group. */
313 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair4_1) == -ENODEV);
314 : :
315 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t4, link);
316 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_1) == 0);
317 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair4_2) == 0);
318 [ + + ]: 24 : STAILQ_FOREACH(tmp_tgroup, &group->tgroups, link) {
319 [ + + ]: 18 : if (tmp_tgroup->transport == &t1) {
320 : 6 : tgroup_1 = tmp_tgroup;
321 [ + + ]: 12 : } else if (tmp_tgroup->transport == &t2) {
322 : 6 : tgroup_2 = tmp_tgroup;
323 [ + - ]: 6 : } else if (tmp_tgroup->transport == &t4) {
324 : 6 : tgroup_4 = tmp_tgroup;
325 : : } else {
326 : 0 : CU_ASSERT(STAILQ_EMPTY(&tmp_tgroup->connected_qpairs));
327 : : }
328 : : }
329 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(tgroup_1 != NULL);
330 : 6 : qpair = STAILQ_FIRST(&tgroup_1->connected_qpairs);
331 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair1_1);
332 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
333 : 6 : CU_ASSERT(qpair == NULL);
334 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(tgroup_2 != NULL);
335 : 6 : qpair = STAILQ_FIRST(&tgroup_2->connected_qpairs);
336 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair2_1);
337 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
338 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair2_2);
339 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
340 : 6 : CU_ASSERT(qpair == NULL);
341 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(tgroup_4 != NULL);
342 : 6 : qpair = STAILQ_FIRST(&tgroup_4->connected_qpairs);
343 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair4_1);
344 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
345 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(qpair == &qpair4_2);
346 : 6 : qpair = STAILQ_NEXT(qpair, poll_group_stailq);
347 : 6 : CU_ASSERT(qpair == NULL);
348 : :
349 : : /* remove all qpairs */
350 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair1_1) == 0);
351 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair2_1) == 0);
352 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair2_2) == 0);
353 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair4_1) == 0);
354 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair4_2) == 0);
355 : : /* Confirm the fourth transport group was created. */
356 : 6 : i = 0;
357 [ + + ]: 24 : STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
358 : 18 : CU_ASSERT(STAILQ_EMPTY(&tgroup->connected_qpairs));
359 [ + - + + : 18 : STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
- - - - ]
360 : 18 : free(tgroup);
361 : 18 : i++;
362 : : }
363 : 6 : CU_ASSERT(i == 3);
364 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
365 : :
366 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t1, link);
367 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t2, link);
368 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t3, link);
369 [ - + ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t4, link);
370 : 6 : }
371 : :
372 : : static void
373 : 6 : test_spdk_nvme_poll_group_process_completions(void)
374 : : {
375 : : struct spdk_nvme_poll_group *group;
376 : : struct spdk_nvme_transport_poll_group *tgroup, *tmp_tgroup;
377 : 6 : struct spdk_nvme_qpair qpair1_1 = {0};
378 : :
379 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
380 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
381 : :
382 : : /* If we don't have any transport poll groups, we shouldn't get any completions. */
383 : 6 : g_process_completions_return_value = 32;
384 : 6 : CU_ASSERT(spdk_nvme_poll_group_process_completions(group, 128,
385 : : unit_test_disconnected_qpair_cb) == 0);
386 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
387 : :
388 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
389 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
390 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
391 : :
392 : : /* try it with three transport poll groups. */
393 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
394 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
395 : 6 : qpair1_1.state = NVME_QPAIR_DISCONNECTED;
396 : 6 : qpair1_1.transport = &t1;
397 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
398 : 6 : qpair1_1.state = NVME_QPAIR_ENABLED;
399 : 6 : CU_ASSERT(nvme_poll_group_connect_qpair(&qpair1_1) == 0);
400 : 6 : CU_ASSERT(spdk_nvme_poll_group_process_completions(group, 128,
401 : : unit_test_disconnected_qpair_cb) == 32);
402 : 6 : CU_ASSERT(spdk_nvme_poll_group_remove(group, &qpair1_1) == 0);
403 [ + + ]: 12 : STAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp_tgroup) {
404 : 6 : CU_ASSERT(STAILQ_EMPTY(&tgroup->connected_qpairs));
405 [ + - + - : 6 : STAILQ_REMOVE(&group->tgroups, tgroup, spdk_nvme_transport_poll_group, link);
- - - - ]
406 : 6 : free(tgroup);
407 : : }
408 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
409 : :
410 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t1, link);
411 [ + - ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t2, link);
412 [ - + ]: 6 : TAILQ_REMOVE(&g_spdk_nvme_transports, &t3, link);
413 : 6 : }
414 : :
415 : : static void
416 : 6 : test_spdk_nvme_poll_group_destroy(void)
417 : : {
418 : : struct spdk_nvme_poll_group *group;
419 : : struct spdk_nvme_transport_poll_group *tgroup, *tgroup_1, *tgroup_2;
420 : 6 : struct spdk_nvme_qpair qpair1_1 = {0};
421 : 6 : int num_tgroups = 0;
422 : :
423 : : /* Simple destruction of empty poll group. */
424 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
425 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
426 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
427 : :
428 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t1, link);
429 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t2, link);
430 : 6 : TAILQ_INSERT_TAIL(&g_spdk_nvme_transports, &t3, link);
431 : 6 : group = spdk_nvme_poll_group_create(NULL, NULL);
432 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(group != NULL);
433 : :
434 : 6 : qpair1_1.transport = &t1;
435 : 6 : CU_ASSERT(spdk_nvme_poll_group_add(group, &qpair1_1) == 0);
436 : :
437 : : /* Don't remove busy poll groups. */
438 : 6 : g_destroy_return_value = -EBUSY;
439 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == -EBUSY);
440 [ + + ]: 12 : STAILQ_FOREACH(tgroup, &group->tgroups, link) {
441 : 6 : num_tgroups++;
442 : : }
443 : 6 : CU_ASSERT(num_tgroups == 1);
444 : :
445 : : /* destroy poll group with internal poll groups. */
446 : 6 : g_destroy_return_value = 0;
447 : 6 : tgroup_1 = STAILQ_FIRST(&group->tgroups);
448 : 6 : tgroup_2 = STAILQ_NEXT(tgroup_1, link);
449 : 6 : CU_ASSERT(tgroup_2 == NULL)
450 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(spdk_nvme_poll_group_destroy(group) == 0);
451 : 6 : free(tgroup_1);
452 : 6 : }
453 : :
454 : : static void
455 : 6 : test_spdk_nvme_poll_group_get_free_stats(void)
456 : : {
457 : 6 : struct spdk_nvme_poll_group group = {};
458 : 6 : struct spdk_nvme_poll_group_stat *stats = NULL;
459 : 6 : struct spdk_nvme_transport_poll_group tgroup[3] = {};
460 : : int rc, i;
461 : :
462 : : /* Multiple tgroups */
463 : 6 : STAILQ_INIT(&group.tgroups);
464 [ + + ]: 24 : for (i = 0; i < 3; i++) {
465 : 18 : STAILQ_INSERT_TAIL(&group.tgroups, &tgroup[i], link);
466 : : }
467 : :
468 : 6 : rc = spdk_nvme_poll_group_get_stats(&group, &stats);
469 : 6 : CU_ASSERT(rc == 0);
470 : 6 : CU_ASSERT(stats->num_transports == 3);
471 : :
472 : 6 : spdk_nvme_poll_group_free_stats(&group, stats);
473 [ + + ]: 24 : for (i = 0; i < 3; i++) {
474 [ + - + + : 18 : STAILQ_REMOVE(&group.tgroups, &tgroup[i], spdk_nvme_transport_poll_group, link);
- - - - ]
475 : : }
476 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(STAILQ_EMPTY(&group.tgroups));
477 : :
478 : : /* No available tgroup */
479 : 6 : rc = spdk_nvme_poll_group_get_stats(&group, &stats);
480 : 6 : CU_ASSERT(rc == -ENOTSUP);
481 : 6 : }
482 : :
483 : : int
484 : 6 : main(int argc, char **argv)
485 : : {
486 : 6 : CU_pSuite suite = NULL;
487 : : unsigned int num_failures;
488 : :
489 [ - + ]: 6 : if (CU_initialize_registry() != CUE_SUCCESS) {
490 : 0 : return CU_get_error();
491 : : }
492 : :
493 : 6 : suite = CU_add_suite("nvme_ns_cmd", NULL, NULL);
494 [ - + ]: 6 : if (suite == NULL) {
495 : 0 : CU_cleanup_registry();
496 : 0 : return CU_get_error();
497 : : }
498 : :
499 [ + - ]: 6 : if (
500 [ + - ]: 12 : CU_add_test(suite, "nvme_poll_group_create_test", test_spdk_nvme_poll_group_create) == NULL ||
501 : 6 : CU_add_test(suite, "nvme_poll_group_add_remove_test",
502 [ + - ]: 6 : test_spdk_nvme_poll_group_add_remove) == NULL ||
503 : 6 : CU_add_test(suite, "nvme_poll_group_process_completions",
504 [ + - ]: 6 : test_spdk_nvme_poll_group_process_completions) == NULL ||
505 [ - + ]: 12 : CU_add_test(suite, "nvme_poll_group_destroy_test", test_spdk_nvme_poll_group_destroy) == NULL ||
506 : 6 : CU_add_test(suite, "nvme_poll_group_get_free_stats",
507 : : test_spdk_nvme_poll_group_get_free_stats) == NULL
508 : : ) {
509 : 0 : CU_cleanup_registry();
510 : 0 : return CU_get_error();
511 : : }
512 : :
513 : 6 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
514 : 6 : CU_cleanup_registry();
515 : 6 : return num_failures;
516 : : }
|