Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) Intel Corporation. All rights reserved.
3 : : * Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 : : */
5 : :
6 : : #include "spdk_internal/rdma_utils.h"
7 : :
8 : : #include "spdk/log.h"
9 : : #include "spdk/string.h"
10 : : #include "spdk/likely.h"
11 : : #include "spdk/net.h"
12 : : #include "spdk/file.h"
13 : :
14 : : #include "spdk_internal/assert.h"
15 : :
16 : : #include <rdma/rdma_cma.h>
17 : : #include <rdma/rdma_verbs.h>
18 : :
19 : : struct rdma_utils_device {
20 : : struct ibv_pd *pd;
21 : : struct ibv_context *context;
22 : : int ref;
23 : : bool removed;
24 : : TAILQ_ENTRY(rdma_utils_device) tailq;
25 : : };
26 : :
27 : : struct spdk_rdma_utils_mem_map {
28 : : struct spdk_mem_map *map;
29 : : struct ibv_pd *pd;
30 : : struct spdk_nvme_rdma_hooks *hooks;
31 : : uint32_t ref_count;
32 : : uint32_t access_flags;
33 : : LIST_ENTRY(spdk_rdma_utils_mem_map) link;
34 : : };
35 : :
36 : : struct rdma_utils_memory_domain {
37 : : TAILQ_ENTRY(rdma_utils_memory_domain) link;
38 : : uint32_t ref;
39 : : enum spdk_dma_device_type type;
40 : : struct ibv_pd *pd;
41 : : struct spdk_memory_domain *domain;
42 : : struct spdk_memory_domain_rdma_ctx rdma_ctx;
43 : : };
44 : :
45 : : static pthread_mutex_t g_dev_mutex = PTHREAD_MUTEX_INITIALIZER;
46 : : static struct ibv_context **g_ctx_list = NULL;
47 : : static TAILQ_HEAD(, rdma_utils_device) g_dev_list = TAILQ_HEAD_INITIALIZER(g_dev_list);
48 : :
49 : : static LIST_HEAD(, spdk_rdma_utils_mem_map) g_rdma_utils_mr_maps = LIST_HEAD_INITIALIZER(
50 : : &g_rdma_utils_mr_maps);
51 : : static pthread_mutex_t g_rdma_mr_maps_mutex = PTHREAD_MUTEX_INITIALIZER;
52 : :
53 : : static TAILQ_HEAD(, rdma_utils_memory_domain) g_memory_domains = TAILQ_HEAD_INITIALIZER(
54 : : g_memory_domains);
55 : : static pthread_mutex_t g_memory_domains_lock = PTHREAD_MUTEX_INITIALIZER;
56 : :
57 : : static int
58 : 10432 : rdma_utils_mem_notify(void *cb_ctx, struct spdk_mem_map *map,
59 : : enum spdk_mem_map_notify_action action,
60 : : void *vaddr, size_t size)
61 : : {
62 : 10432 : struct spdk_rdma_utils_mem_map *rmap = cb_ctx;
63 [ # # # # ]: 10432 : struct ibv_pd *pd = rmap->pd;
64 : : struct ibv_mr *mr;
65 : : uint32_t access_flags;
66 : : int rc;
67 : :
68 [ + + - ]: 10432 : switch (action) {
69 : 5216 : case SPDK_MEM_MAP_NOTIFY_REGISTER:
70 [ + - - + : 5216 : if (rmap->hooks && rmap->hooks->get_rkey) {
# # # # #
# # # # #
# # ]
71 : 0 : rc = spdk_mem_map_set_translation(map, (uint64_t)vaddr, size,
72 [ # # # # : 0 : rmap->hooks->get_rkey(pd, vaddr, size));
# # # # #
# # # ]
73 : 0 : } else {
74 [ # # # # ]: 5216 : access_flags = rmap->access_flags;
75 : : #ifdef IBV_ACCESS_OPTIONAL_FIRST
76 [ - + ]: 5216 : access_flags |= IBV_ACCESS_RELAXED_ORDERING;
77 : : #endif
78 : 5216 : mr = ibv_reg_mr(pd, vaddr, size, access_flags);
79 [ - + ]: 5216 : if (mr == NULL) {
80 : 0 : SPDK_ERRLOG("ibv_reg_mr() failed\n");
81 : 0 : return -1;
82 : : } else {
83 : 5216 : rc = spdk_mem_map_set_translation(map, (uint64_t)vaddr, size, (uint64_t)mr);
84 : : }
85 : : }
86 : 5216 : break;
87 : 5216 : case SPDK_MEM_MAP_NOTIFY_UNREGISTER:
88 [ + - + - : 5216 : if (rmap->hooks == NULL || rmap->hooks->get_rkey == NULL) {
# # # # #
# # # # #
# # ]
89 : 5216 : mr = (struct ibv_mr *)spdk_mem_map_translate(map, (uint64_t)vaddr, NULL);
90 [ + - ]: 5216 : if (mr) {
91 : 5216 : ibv_dereg_mr(mr);
92 : 0 : }
93 : 0 : }
94 : 5216 : rc = spdk_mem_map_clear_translation(map, (uint64_t)vaddr, size);
95 : 5216 : break;
96 : 0 : default:
97 [ # # ]: 0 : SPDK_UNREACHABLE();
98 : : }
99 : :
100 : 10432 : return rc;
101 : 0 : }
102 : :
103 : : static int
104 : 447 : rdma_check_contiguous_entries(uint64_t addr_1, uint64_t addr_2)
105 : : {
106 : : /* Two contiguous mappings will point to the same address which is the start of the RDMA MR. */
107 : 447 : return addr_1 == addr_2;
108 : : }
109 : :
110 : : const struct spdk_mem_map_ops g_rdma_map_ops = {
111 : : .notify_cb = rdma_utils_mem_notify,
112 : : .are_contiguous = rdma_check_contiguous_entries
113 : : };
114 : :
115 : : static void
116 : 406 : _rdma_free_mem_map(struct spdk_rdma_utils_mem_map *map)
117 : : {
118 [ - + # # ]: 406 : assert(map);
119 : :
120 [ + - # # : 406 : if (map->hooks) {
# # ]
121 : 406 : spdk_free(map);
122 : 0 : } else {
123 : 0 : free(map);
124 : : }
125 : 406 : }
126 : :
127 : : struct spdk_rdma_utils_mem_map *
128 : 1368 : spdk_rdma_utils_create_mem_map(struct ibv_pd *pd, struct spdk_nvme_rdma_hooks *hooks,
129 : : uint32_t access_flags)
130 : : {
131 : : struct spdk_rdma_utils_mem_map *map;
132 : :
133 [ - + # # : 1368 : if (pd->context->device->transport_type == IBV_TRANSPORT_IWARP) {
# # # # #
# # # #
# ]
134 : : /* IWARP requires REMOTE_WRITE permission for RDMA_READ operation */
135 : 0 : access_flags |= IBV_ACCESS_REMOTE_WRITE;
136 : 0 : }
137 : :
138 [ - + ]: 1368 : pthread_mutex_lock(&g_rdma_mr_maps_mutex);
139 : : /* Look up existing mem map registration for this pd */
140 [ + + # # : 1425 : LIST_FOREACH(map, &g_rdma_utils_mr_maps, link) {
# # # # ]
141 [ + + + - : 1019 : if (map->pd == pd && map->access_flags == access_flags) {
# # # # #
# # # ]
142 [ # # ]: 962 : map->ref_count++;
143 [ - + ]: 962 : pthread_mutex_unlock(&g_rdma_mr_maps_mutex);
144 : 962 : return map;
145 : : }
146 : 0 : }
147 : :
148 [ + - ]: 406 : if (hooks) {
149 : 406 : map = spdk_zmalloc(sizeof(*map), 0, NULL, SPDK_ENV_NUMA_ID_ANY, SPDK_MALLOC_DMA);
150 : 0 : } else {
151 : 0 : map = calloc(1, sizeof(*map));
152 : : }
153 [ - + ]: 406 : if (!map) {
154 [ # # ]: 0 : pthread_mutex_unlock(&g_rdma_mr_maps_mutex);
155 : 0 : SPDK_ERRLOG("Memory allocation failed\n");
156 : 0 : return NULL;
157 : : }
158 [ # # # # ]: 406 : map->pd = pd;
159 [ # # # # ]: 406 : map->ref_count = 1;
160 [ # # # # ]: 406 : map->hooks = hooks;
161 [ # # # # ]: 406 : map->access_flags = access_flags;
162 [ # # # # ]: 406 : map->map = spdk_mem_map_alloc(0, &g_rdma_map_ops, map);
163 [ - + # # : 406 : if (!map->map) {
# # ]
164 : 0 : SPDK_ERRLOG("Unable to create memory map\n");
165 : 0 : _rdma_free_mem_map(map);
166 [ # # ]: 0 : pthread_mutex_unlock(&g_rdma_mr_maps_mutex);
167 : 0 : return NULL;
168 : : }
169 [ + + # # : 406 : LIST_INSERT_HEAD(&g_rdma_utils_mr_maps, map, link);
# # # # #
# # # # #
# # # # #
# # # #
# ]
170 : :
171 [ - + ]: 406 : pthread_mutex_unlock(&g_rdma_mr_maps_mutex);
172 : :
173 : 406 : return map;
174 : 0 : }
175 : :
176 : : void
177 : 1391 : spdk_rdma_utils_free_mem_map(struct spdk_rdma_utils_mem_map **_map)
178 : : {
179 : : struct spdk_rdma_utils_mem_map *map;
180 : :
181 [ - + ]: 1391 : if (!_map) {
182 : 0 : return;
183 : : }
184 : :
185 [ # # ]: 1391 : map = *_map;
186 [ + + ]: 1391 : if (!map) {
187 : 23 : return;
188 : : }
189 [ # # ]: 1368 : *_map = NULL;
190 : :
191 [ - + ]: 1368 : pthread_mutex_lock(&g_rdma_mr_maps_mutex);
192 [ - + # # : 1368 : assert(map->ref_count > 0);
# # # # ]
193 [ # # ]: 1368 : map->ref_count--;
194 [ + + # # : 1368 : if (map->ref_count != 0) {
# # ]
195 [ - + ]: 962 : pthread_mutex_unlock(&g_rdma_mr_maps_mutex);
196 : 962 : return;
197 : : }
198 : :
199 [ + + # # : 406 : LIST_REMOVE(map, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
200 [ - + ]: 406 : pthread_mutex_unlock(&g_rdma_mr_maps_mutex);
201 [ + - # # : 406 : if (map->map) {
# # ]
202 [ # # ]: 406 : spdk_mem_map_free(&map->map);
203 : 0 : }
204 : 406 : _rdma_free_mem_map(map);
205 : 0 : }
206 : :
207 : : int
208 : 21412787 : spdk_rdma_utils_get_translation(struct spdk_rdma_utils_mem_map *map, void *address,
209 : : size_t length, struct spdk_rdma_utils_memory_translation *translation)
210 : : {
211 : 21412787 : uint64_t real_length = length;
212 : :
213 [ - + # # ]: 21412787 : assert(map);
214 [ - + # # ]: 21412787 : assert(address);
215 [ - + # # ]: 21412787 : assert(translation);
216 : :
217 [ + - - + : 21412787 : if (map->hooks && map->hooks->get_rkey) {
# # # # #
# # # # #
# # ]
218 [ # # # # ]: 0 : translation->translation_type = SPDK_RDMA_UTILS_TRANSLATION_KEY;
219 [ # # # # : 0 : translation->mr_or_key.key = spdk_mem_map_translate(map->map, (uint64_t)address, &real_length);
# # # # #
# ]
220 : 0 : } else {
221 [ # # # # ]: 21412787 : translation->translation_type = SPDK_RDMA_UTILS_TRANSLATION_MR;
222 [ # # # # : 21412787 : translation->mr_or_key.mr = (struct ibv_mr *)spdk_mem_map_translate(map->map, (uint64_t)address,
# # # # #
# ]
223 : : &real_length);
224 [ - + # # : 21412787 : if (spdk_unlikely(!translation->mr_or_key.mr)) {
# # # # ]
225 : 0 : SPDK_ERRLOG("No translation for ptr %p, size %zu\n", address, length);
226 : 0 : return -EINVAL;
227 : : }
228 : : }
229 : :
230 [ - + # # ]: 21412787 : assert(real_length >= length);
231 : :
232 : 21412787 : return 0;
233 : 0 : }
234 : :
235 : :
236 : : static struct rdma_utils_device *
237 : 112 : rdma_add_dev(struct ibv_context *context)
238 : : {
239 : : struct rdma_utils_device *dev;
240 : :
241 : 112 : dev = calloc(1, sizeof(*dev));
242 [ + + ]: 112 : if (dev == NULL) {
243 : 0 : SPDK_ERRLOG("Failed to allocate RDMA device object.\n");
244 : 0 : return NULL;
245 : : }
246 : :
247 [ # # # # ]: 112 : dev->pd = ibv_alloc_pd(context);
248 [ - + # # : 112 : if (dev->pd == NULL) {
# # ]
249 [ # # # # ]: 0 : SPDK_ERRLOG("ibv_alloc_pd() failed: %s (%d)\n", spdk_strerror(errno), errno);
250 : 0 : free(dev);
251 : 0 : return NULL;
252 : : }
253 : :
254 [ # # # # ]: 112 : dev->context = context;
255 [ # # # # : 112 : TAILQ_INSERT_TAIL(&g_dev_list, dev, tailq);
# # # # #
# # # # #
# # # # #
# # # #
# ]
256 : :
257 : 112 : return dev;
258 : 3 : }
259 : :
260 : : static void
261 : 1423 : rdma_remove_dev(struct rdma_utils_device *dev)
262 : : {
263 [ + + + + : 1423 : if (!dev->removed || dev->ref > 0) {
+ + # # #
# # # #
# ]
264 : 1311 : return;
265 : : }
266 : :
267 : : /* Deallocate protection domain only if the device is already removed and
268 : : * there is no reference.
269 : : */
270 [ + + # # : 112 : TAILQ_REMOVE(&g_dev_list, dev, tailq);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
271 [ # # # # ]: 112 : ibv_dealloc_pd(dev->pd);
272 : 112 : free(dev);
273 : 5 : }
274 : :
275 : : static int
276 : 2620 : ctx_cmp(const void *_c1, const void *_c2)
277 : : {
278 [ # # ]: 2620 : struct ibv_context *c1 = *(struct ibv_context **)_c1;
279 [ # # ]: 2620 : struct ibv_context *c2 = *(struct ibv_context **)_c2;
280 : :
281 [ + + ]: 2620 : return c1 < c2 ? -1 : c1 > c2;
282 : : }
283 : :
284 : : static int
285 : 2630 : rdma_sync_dev_list(void)
286 : : {
287 : : struct ibv_context **new_ctx_list;
288 : : int i, j;
289 : 2630 : int num_devs = 0;
290 : :
291 : : /*
292 : : * rdma_get_devices() returns a NULL terminated array of opened RDMA devices,
293 : : * and sets num_devs to the number of the returned devices.
294 : : */
295 : 2630 : new_ctx_list = rdma_get_devices(&num_devs);
296 [ + + ]: 2630 : if (new_ctx_list == NULL) {
297 [ # # # # ]: 0 : SPDK_ERRLOG("rdma_get_devices() failed: %s (%d)\n", spdk_strerror(errno), errno);
298 : 0 : return -ENODEV;
299 : : }
300 : :
301 [ + + ]: 2630 : if (num_devs == 0) {
302 : 0 : rdma_free_devices(new_ctx_list);
303 : 0 : SPDK_ERRLOG("Returned RDMA device array was empty\n");
304 : 0 : return -ENODEV;
305 : : }
306 : :
307 : : /*
308 : : * Sort new_ctx_list by addresses to update devices easily.
309 : : */
310 [ - + # # ]: 2630 : qsort(new_ctx_list, num_devs, sizeof(struct ibv_context *), ctx_cmp);
311 : :
312 [ + + ]: 2630 : if (g_ctx_list == NULL) {
313 : : /* If no old array, this is the first call. Add all devices. */
314 [ + + # # : 162 : for (i = 0; new_ctx_list[i] != NULL; i++) {
# # # # ]
315 [ # # # # ]: 108 : rdma_add_dev(new_ctx_list[i]);
316 : 2 : }
317 : :
318 : 54 : goto exit;
319 : : }
320 : :
321 [ + + + + : 7720 : for (i = j = 0; new_ctx_list[i] != NULL || g_ctx_list[j] != NULL;) {
# # # # #
# # # ]
322 [ # # # # ]: 5144 : struct ibv_context *new_ctx = new_ctx_list[i];
323 [ # # # # ]: 5144 : struct ibv_context *old_ctx = g_ctx_list[j];
324 : 5144 : bool add = false, remove = false;
325 : :
326 : : /*
327 : : * If a context exists only in the new array, create a device for it,
328 : : * or if a context exists only in the old array, try removing the
329 : : * corresponding device.
330 : : */
331 : :
332 [ + + ]: 5144 : if (old_ctx == NULL) {
333 : 0 : add = true;
334 [ + + ]: 5144 : } else if (new_ctx == NULL) {
335 : 4 : remove = true;
336 [ + + ]: 5141 : } else if (new_ctx < old_ctx) {
337 : 4 : add = true;
338 [ + + ]: 5137 : } else if (old_ctx < new_ctx) {
339 : 4 : remove = true;
340 : 1 : }
341 : :
342 [ + + # # ]: 5144 : if (add) {
343 [ # # # # ]: 4 : rdma_add_dev(new_ctx_list[i]);
344 [ # # ]: 4 : i++;
345 [ + + # # ]: 5141 : } else if (remove) {
346 : : struct rdma_utils_device *dev, *tmp;
347 : :
348 [ + + + + : 28 : TAILQ_FOREACH_SAFE(dev, &g_dev_list, tailq, tmp) {
# # # # #
# ]
349 [ + + # # : 20 : if (dev->context == g_ctx_list[j]) {
# # # # #
# ]
350 [ # # # # ]: 8 : dev->removed = true;
351 : 8 : rdma_remove_dev(dev);
352 : 2 : }
353 : 5 : }
354 [ # # ]: 8 : j++;
355 : 2 : } else {
356 [ # # ]: 5132 : i++;
357 [ # # ]: 5132 : j++;
358 : : }
359 : : }
360 : :
361 : : /* Free the old array. */
362 : 2576 : rdma_free_devices(g_ctx_list);
363 : :
364 : 2624 : exit:
365 : : /*
366 : : * Keep the newly returned array so that allocated protection domains
367 : : * are not freed unexpectedly.
368 : : */
369 : 2630 : g_ctx_list = new_ctx_list;
370 : 2630 : return 0;
371 : 6 : }
372 : :
373 : : struct ibv_pd *
374 : 1319 : spdk_rdma_utils_get_pd(struct ibv_context *context)
375 : : {
376 : : struct rdma_utils_device *dev;
377 : : int rc;
378 : :
379 [ - + ]: 1319 : pthread_mutex_lock(&g_dev_mutex);
380 : :
381 : 1319 : rc = rdma_sync_dev_list();
382 [ - + ]: 1319 : if (rc != 0) {
383 [ # # ]: 0 : pthread_mutex_unlock(&g_dev_mutex);
384 : :
385 : 0 : SPDK_ERRLOG("Failed to sync RDMA device list\n");
386 : 0 : return NULL;
387 : : }
388 : :
389 [ + + # # : 1338 : TAILQ_FOREACH(dev, &g_dev_list, tailq) {
# # # # ]
390 [ + + + + : 1330 : if (dev->context == context && !dev->removed) {
+ + # # #
# # # #
# ]
391 [ # # # # ]: 1311 : dev->ref++;
392 [ - + ]: 1311 : pthread_mutex_unlock(&g_dev_mutex);
393 : :
394 [ # # # # ]: 1311 : return dev->pd;
395 : : }
396 : 4 : }
397 : :
398 [ - + ]: 8 : pthread_mutex_unlock(&g_dev_mutex);
399 : :
400 : 8 : SPDK_ERRLOG("Failed to get PD\n");
401 : 8 : return NULL;
402 : 4 : }
403 : :
404 : : void
405 : 1311 : spdk_rdma_utils_put_pd(struct ibv_pd *pd)
406 : : {
407 : : struct rdma_utils_device *dev, *tmp;
408 : :
409 [ - + ]: 1311 : pthread_mutex_lock(&g_dev_mutex);
410 : :
411 [ + + + + : 3929 : TAILQ_FOREACH_SAFE(dev, &g_dev_list, tailq, tmp) {
# # # # #
# ]
412 [ + + # # : 2618 : if (dev->pd == pd) {
# # ]
413 [ - + # # : 1311 : assert(dev->ref > 0);
# # # # ]
414 [ # # # # ]: 1311 : dev->ref--;
415 : :
416 : 1311 : rdma_remove_dev(dev);
417 : 2 : }
418 : 3 : }
419 : :
420 : 1311 : rdma_sync_dev_list();
421 : :
422 [ - + ]: 1311 : pthread_mutex_unlock(&g_dev_mutex);
423 : 1311 : }
424 : :
425 : : __attribute__((destructor)) static void
426 : 2572 : _rdma_utils_fini(void)
427 : : {
428 : : struct rdma_utils_device *dev, *tmp;
429 : :
430 [ + + + + : 2676 : TAILQ_FOREACH_SAFE(dev, &g_dev_list, tailq, tmp) {
# # # # -
+ ]
431 [ # # # # ]: 104 : dev->removed = true;
432 [ # # # # ]: 104 : dev->ref = 0;
433 : 104 : rdma_remove_dev(dev);
434 : 1 : }
435 : :
436 [ + + ]: 2572 : if (g_ctx_list != NULL) {
437 : 54 : rdma_free_devices(g_ctx_list);
438 : 54 : g_ctx_list = NULL;
439 : 1 : }
440 : 2572 : }
441 : :
442 : : struct spdk_memory_domain *
443 : 2835 : spdk_rdma_utils_get_memory_domain(struct ibv_pd *pd)
444 : : {
445 : 2835 : struct rdma_utils_memory_domain *domain = NULL;
446 : 2835 : struct spdk_memory_domain_ctx ctx = {};
447 : : int rc;
448 : :
449 [ - + ]: 2835 : pthread_mutex_lock(&g_memory_domains_lock);
450 : :
451 [ + + # # : 2954 : TAILQ_FOREACH(domain, &g_memory_domains, link) {
# # # # ]
452 [ + + # # : 2308 : if (domain->pd == pd) {
# # ]
453 [ # # ]: 2189 : domain->ref++;
454 [ - + ]: 2189 : pthread_mutex_unlock(&g_memory_domains_lock);
455 [ # # # # ]: 2189 : return domain->domain;
456 : : }
457 : 0 : }
458 : :
459 : 646 : domain = calloc(1, sizeof(*domain));
460 [ - + ]: 646 : if (!domain) {
461 : 0 : SPDK_ERRLOG("Memory allocation failed\n");
462 [ # # ]: 0 : pthread_mutex_unlock(&g_memory_domains_lock);
463 : 0 : return NULL;
464 : : }
465 : :
466 [ # # # # : 646 : domain->rdma_ctx.size = sizeof(domain->rdma_ctx);
# # ]
467 [ # # # # : 646 : domain->rdma_ctx.ibv_pd = pd;
# # ]
468 : 646 : ctx.size = sizeof(ctx);
469 [ # # # # ]: 646 : ctx.user_ctx = &domain->rdma_ctx;
470 [ # # # # : 646 : ctx.user_ctx_size = domain->rdma_ctx.size;
# # # # ]
471 : :
472 [ # # ]: 646 : rc = spdk_memory_domain_create(&domain->domain, SPDK_DMA_DEVICE_TYPE_RDMA, &ctx,
473 : : SPDK_RDMA_DMA_DEVICE);
474 [ - + ]: 646 : if (rc) {
475 : 0 : SPDK_ERRLOG("Failed to create memory domain\n");
476 : 0 : free(domain);
477 [ # # ]: 0 : pthread_mutex_unlock(&g_memory_domains_lock);
478 : 0 : return NULL;
479 : : }
480 : :
481 [ # # # # ]: 646 : domain->pd = pd;
482 [ # # # # ]: 646 : domain->ref = 1;
483 [ # # # # : 646 : TAILQ_INSERT_TAIL(&g_memory_domains, domain, link);
# # # # #
# # # # #
# # # # #
# # # #
# ]
484 : :
485 [ - + ]: 646 : pthread_mutex_unlock(&g_memory_domains_lock);
486 : :
487 [ # # # # ]: 646 : return domain->domain;
488 : 0 : }
489 : :
490 : : int
491 : 2835 : spdk_rdma_utils_put_memory_domain(struct spdk_memory_domain *_domain)
492 : : {
493 : 2835 : struct rdma_utils_memory_domain *domain = NULL;
494 : :
495 [ - + ]: 2835 : if (!_domain) {
496 : 0 : return 0;
497 : : }
498 : :
499 [ - + ]: 2835 : pthread_mutex_lock(&g_memory_domains_lock);
500 : :
501 [ + - # # : 2950 : TAILQ_FOREACH(domain, &g_memory_domains, link) {
# # # # ]
502 [ + + # # : 2950 : if (domain->domain == _domain) {
# # ]
503 : 2835 : break;
504 : : }
505 : 0 : }
506 : :
507 [ - + ]: 2835 : if (!domain) {
508 [ # # ]: 0 : pthread_mutex_unlock(&g_memory_domains_lock);
509 : 0 : return -ENODEV;
510 : : }
511 [ - + # # : 2835 : assert(domain->ref > 0);
# # # # ]
512 : :
513 [ # # ]: 2835 : domain->ref--;
514 : :
515 [ + + # # : 2835 : if (domain->ref == 0) {
# # ]
516 [ # # # # ]: 646 : spdk_memory_domain_destroy(domain->domain);
517 [ + + # # : 646 : TAILQ_REMOVE(&g_memory_domains, domain, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
518 : 646 : free(domain);
519 : 0 : }
520 : :
521 [ - + ]: 2835 : pthread_mutex_unlock(&g_memory_domains_lock);
522 : :
523 : 2835 : return 0;
524 : 0 : }
525 : :
526 : : int32_t
527 : 2835 : spdk_rdma_cm_id_get_numa_id(struct rdma_cm_id *cm_id)
528 : : {
529 : : struct sockaddr *sa;
530 : 0 : char addr[64];
531 : 0 : char ifc[64];
532 : 0 : uint32_t numa_id;
533 : : int rc;
534 : :
535 : 2835 : sa = rdma_get_local_addr(cm_id);
536 [ - + ]: 2835 : if (sa == NULL) {
537 : 0 : return SPDK_ENV_NUMA_ID_ANY;
538 : : }
539 : 2835 : rc = spdk_net_get_address_string(sa, addr, sizeof(addr));
540 [ - + ]: 2835 : if (rc) {
541 : 0 : return SPDK_ENV_NUMA_ID_ANY;
542 : : }
543 : 2835 : rc = spdk_net_get_interface_name(addr, ifc, sizeof(ifc));
544 [ - + ]: 2835 : if (rc) {
545 : 0 : return SPDK_ENV_NUMA_ID_ANY;
546 : : }
547 : 2835 : rc = spdk_read_sysfs_attribute_uint32(&numa_id,
548 : 0 : "/sys/class/net/%s/device/numa_node", ifc);
549 [ + - - + ]: 2835 : if (rc || numa_id > INT32_MAX) {
550 : 0 : return SPDK_ENV_NUMA_ID_ANY;
551 : : }
552 : 2835 : return (int32_t)numa_id;
553 : 0 : }
|