Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 : : */
4 : :
5 : : #include "spdk/stdinc.h"
6 : : #include "spdk_internal/cunit.h"
7 : : #include "spdk_internal/mock.h"
8 : : #include "common/lib/test_env.c"
9 : : #include "rdma/common.c"
10 : :
11 : 0 : DEFINE_STUB(spdk_mem_map_alloc, struct spdk_mem_map *, (uint64_t default_translation,
12 : : const struct spdk_mem_map_ops *ops, void *cb_ctx), NULL);
13 : 0 : DEFINE_STUB_V(spdk_mem_map_free, (struct spdk_mem_map **pmap));
14 : 0 : DEFINE_STUB(spdk_mem_map_set_translation, int, (struct spdk_mem_map *map, uint64_t vaddr,
15 : : uint64_t size, uint64_t translation), 0);
16 : 0 : DEFINE_STUB(spdk_mem_map_clear_translation, int, (struct spdk_mem_map *map, uint64_t vaddr,
17 : : uint64_t size), 0);
18 : 0 : DEFINE_STUB(spdk_mem_map_translate, uint64_t, (const struct spdk_mem_map *map, uint64_t vaddr,
19 : : uint64_t *size), 0);
20 : :
21 : : struct ut_rdma_device {
22 : : struct ibv_context *context;
23 : : bool removed;
24 : : TAILQ_ENTRY(ut_rdma_device) tailq;
25 : : };
26 : :
27 : : static TAILQ_HEAD(, ut_rdma_device) g_ut_dev_list = TAILQ_HEAD_INITIALIZER(g_ut_dev_list);
28 : :
29 : : struct ibv_context **
30 : : rdma_get_devices(int *num_devices)
31 : : {
32 : : struct ibv_context **ctx_list;
33 : : struct ut_rdma_device *ut_dev;
34 : 24 : int num_ut_devs = 0;
35 : 24 : int i = 0;
36 : :
37 [ + + ]: 96 : TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
38 [ + + + + ]: 72 : if (!ut_dev->removed) {
39 : 32 : num_ut_devs++;
40 : : }
41 : : }
42 : :
43 : 24 : ctx_list = malloc(sizeof(*ctx_list) * (num_ut_devs + 1));
44 [ - + ]: 24 : SPDK_CU_ASSERT_FATAL(ctx_list);
45 : :
46 [ + + ]: 96 : TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
47 [ + + + + ]: 72 : if (!ut_dev->removed) {
48 : 32 : ctx_list[i++] = ut_dev->context;
49 : : }
50 : : }
51 : 24 : ctx_list[i] = NULL;
52 : :
53 [ + - ]: 24 : if (num_devices) {
54 : 24 : *num_devices = num_ut_devs;
55 : : }
56 : :
57 : 24 : return ctx_list;
58 : : }
59 : :
60 : : void
61 : : rdma_free_devices(struct ibv_context **list)
62 : : {
63 : 24 : free(list);
64 : 24 : }
65 : :
66 : : struct ibv_pd *
67 : : ibv_alloc_pd(struct ibv_context *context)
68 : : {
69 : : struct ibv_pd *pd;
70 : : struct ut_rdma_device *ut_dev;
71 : :
72 [ + - ]: 24 : TAILQ_FOREACH(ut_dev, &g_ut_dev_list, tailq) {
73 [ + + + + : 24 : if (ut_dev->context == context && !ut_dev->removed) {
+ - ]
74 : 12 : break;
75 : : }
76 : : }
77 : :
78 [ - + ]: 12 : if (!ut_dev) {
79 : 0 : return NULL;
80 : : }
81 : :
82 : 12 : pd = calloc(1, sizeof(*pd));
83 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(pd);
84 : :
85 : 12 : pd->context = context;
86 : :
87 : 12 : return pd;
88 : : }
89 : :
90 : : int
91 : : ibv_dealloc_pd(struct ibv_pd *pd)
92 : : {
93 : 12 : free(pd);
94 : :
95 : 12 : return 0;
96 : : }
97 : :
98 : : static struct ut_rdma_device *
99 : 12 : ut_rdma_add_dev(struct ibv_context *context)
100 : : {
101 : : struct ut_rdma_device *ut_dev;
102 : :
103 : 12 : ut_dev = calloc(1, sizeof(*ut_dev));
104 [ - + ]: 12 : if (!ut_dev) {
105 : 0 : return NULL;
106 : : }
107 : :
108 : 12 : ut_dev->context = context;
109 : 12 : TAILQ_INSERT_TAIL(&g_ut_dev_list, ut_dev, tailq);
110 : :
111 : 12 : return ut_dev;
112 : : }
113 : :
114 : : static void
115 : 12 : ut_rdma_remove_dev(struct ut_rdma_device *ut_dev)
116 : : {
117 [ + + ]: 12 : TAILQ_REMOVE(&g_ut_dev_list, ut_dev, tailq);
118 : 12 : free(ut_dev);
119 : 12 : }
120 : :
121 : : static struct spdk_rdma_device *
122 : 60 : _rdma_get_dev(struct ibv_context *context)
123 : : {
124 : : struct spdk_rdma_device *dev;
125 : :
126 [ + + ]: 112 : TAILQ_FOREACH(dev, &g_dev_list, tailq) {
127 [ + + ]: 84 : if (dev->context == context) {
128 : 32 : break;
129 : : }
130 : : }
131 : :
132 : 60 : return dev;
133 : : }
134 : :
135 : : static void
136 : 4 : test_spdk_rdma_pd(void)
137 : : {
138 : : struct ut_rdma_device *ut_dev0, *ut_dev1, *ut_dev2;
139 : : struct ibv_pd *pd1, *pd1_1, *pd2;
140 : :
141 : 4 : ut_dev0 = ut_rdma_add_dev((struct ibv_context *)0xface);
142 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(ut_dev0 != NULL);
143 : :
144 : 4 : ut_dev1 = ut_rdma_add_dev((struct ibv_context *)0xc0ffee);
145 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(ut_dev1 != NULL);
146 : :
147 : 4 : ut_dev2 = ut_rdma_add_dev((struct ibv_context *)0xf00d);
148 [ - + ]: 4 : SPDK_CU_ASSERT_FATAL(ut_dev2 != NULL);
149 : :
150 : : /* There are ut_dev0 and ut_dev1. */
151 : 4 : ut_dev2->removed = true;
152 : :
153 : : /* Call spdk_rdma_get_pd() to non-existent ut_dev2. */
154 : 4 : pd2 = spdk_rdma_get_pd(ut_dev2->context);
155 : :
156 : : /* Then, spdk_rdma_get_pd() should return NULL and g_dev_list should have dev0 and dev1. */
157 : 4 : CU_ASSERT(pd2 == NULL);
158 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) != NULL);
159 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
160 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) == NULL);
161 : :
162 : : /* Remove ut_dev0 and add ut_dev2. */
163 : 4 : ut_dev0->removed = true;
164 : 4 : ut_dev2->removed = false;
165 : :
166 : : /* Call spdk_rdma_get_pd() to ut_dev1. */
167 : 4 : pd1 = spdk_rdma_get_pd(ut_dev1->context);
168 : :
169 : : /* Then, spdk_rdma_get_pd() should return pd1 and g_dev_list should have dev1 and dev2. */
170 : 4 : CU_ASSERT(pd1 != NULL);
171 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
172 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
173 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
174 : :
175 : : /* Remove ut_dev1. */
176 : 4 : ut_dev1->removed = true;
177 : :
178 : : /* Call spdk_rdma_get_pd() again to ut_dev1 which does not exist anymore. */
179 : 4 : pd1_1 = spdk_rdma_get_pd(ut_dev1->context);
180 : :
181 : : /* Then, spdk_rdma_get_pd() should return NULL and g_dev_list should still have dev1. */
182 : 4 : CU_ASSERT(pd1_1 == NULL);
183 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
184 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) != NULL);
185 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
186 : :
187 : : /* Call spdk_rdma_put_pd() to pd1. */
188 : 4 : spdk_rdma_put_pd(pd1);
189 : :
190 : : /* Then, dev1 should be removed from g_dev_list. */
191 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
192 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
193 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
194 : :
195 : : /* Call spdk_rdma_get_pd() to ut_dev2. */
196 : 4 : pd2 = spdk_rdma_get_pd(ut_dev2->context);
197 : :
198 : : /* spdk_rdma_get_pd() should succeed and g_dev_list should still have dev2
199 : : * even after spdk_rdma_put_pd() is called to pd2.
200 : : */
201 : 4 : CU_ASSERT(pd2 != NULL);
202 : :
203 : 4 : spdk_rdma_put_pd(pd2);
204 : :
205 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev0->context) == NULL);
206 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev1->context) == NULL);
207 : 4 : CU_ASSERT(_rdma_get_dev(ut_dev2->context) != NULL);
208 : :
209 : 4 : _rdma_fini();
210 : :
211 : 4 : ut_rdma_remove_dev(ut_dev0);
212 : 4 : ut_rdma_remove_dev(ut_dev1);
213 : 4 : ut_rdma_remove_dev(ut_dev2);
214 : 4 : }
215 : :
216 : : int
217 : 4 : main(int argc, char **argv)
218 : : {
219 : 4 : CU_pSuite suite = NULL;
220 : : unsigned int num_failures;
221 : :
222 : 4 : CU_initialize_registry();
223 : :
224 : 4 : suite = CU_add_suite("rdma_common", NULL, NULL);
225 : 4 : CU_ADD_TEST(suite, test_spdk_rdma_pd);
226 : :
227 : 4 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
228 : 4 : CU_cleanup_registry();
229 : 4 : return num_failures;
230 : : }
|