]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/test/common/lib/test_env.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / test / common / lib / test_env.c
CommitLineData
11fdf7f2
TL
1/*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include "spdk/stdinc.h"
35
36#include "spdk_internal/mock.h"
37
38#include "spdk/env.h"
39#include "spdk/queue.h"
9f95a23c 40#include "spdk/util.h"
11fdf7f2 41
f67539c2
TL
42static uint32_t g_ut_num_cores;
43static bool *g_ut_cores;
44
45void allocate_cores(uint32_t num_cores);
46void free_cores(void);
47
11fdf7f2
TL
48DEFINE_STUB(spdk_process_is_primary, bool, (void), true)
49DEFINE_STUB(spdk_memzone_lookup, void *, (const char *name), NULL)
f67539c2
TL
50DEFINE_STUB_V(spdk_pci_driver_register, (const char *name, struct spdk_pci_id *id_table,
51 uint32_t flags));
9f95a23c
TL
52DEFINE_STUB(spdk_pci_nvme_get_driver, struct spdk_pci_driver *, (void), NULL)
53DEFINE_STUB(spdk_pci_ioat_get_driver, struct spdk_pci_driver *, (void), NULL)
54DEFINE_STUB(spdk_pci_virtio_get_driver, struct spdk_pci_driver *, (void), NULL)
11fdf7f2 55
f67539c2
TL
56void
57allocate_cores(uint32_t num_cores)
58{
59 uint32_t i;
60
61 g_ut_num_cores = num_cores;
62
63 g_ut_cores = calloc(num_cores, sizeof(bool));
64 assert(g_ut_cores != NULL);
65
66 for (i = 0; i < num_cores; i++) {
67 g_ut_cores[i] = true;
68 }
69}
70
71void
72free_cores(void)
73{
74 free(g_ut_cores);
75 g_ut_cores = NULL;
76 g_ut_num_cores = 0;
77}
78
79static uint32_t
80ut_get_next_core(uint32_t i)
81{
82 i++;
83
84 while (i < g_ut_num_cores) {
85 if (!g_ut_cores[i]) {
86 i++;
87 continue;
88 }
89 break;
90 }
91
92 if (i < g_ut_num_cores) {
93 return i;
94 } else {
95 return UINT32_MAX;
96 }
97}
98
99uint32_t
100spdk_env_get_first_core(void)
101{
102 return ut_get_next_core(-1);
103}
104
105uint32_t
106spdk_env_get_next_core(uint32_t prev_core)
107{
108 return ut_get_next_core(prev_core);
109}
110
111uint32_t
112spdk_env_get_core_count(void)
113{
114 return g_ut_num_cores;
115}
116
117uint32_t
118spdk_env_get_last_core(void)
119{
120 uint32_t i;
121 uint32_t last_core = UINT32_MAX;
122
123 SPDK_ENV_FOREACH_CORE(i) {
124 last_core = i;
125 }
126
127 return last_core;
128}
129
130DEFINE_RETURN_MOCK(spdk_env_get_current_core, uint32_t);
131uint32_t
132spdk_env_get_current_core(void)
133{
134 HANDLE_RETURN_MOCK(spdk_env_get_current_core);
135
136 return UINT32_MAX;
137}
138
139DEFINE_RETURN_MOCK(spdk_env_get_socket_id, uint32_t);
140uint32_t
141spdk_env_get_socket_id(uint32_t core)
142{
143 HANDLE_RETURN_MOCK(spdk_env_get_socket_id);
144
145 return SPDK_ENV_SOCKET_ID_ANY;
146}
147
11fdf7f2
TL
148/*
149 * These mocks don't use the DEFINE_STUB macros because
150 * their default implementation is more complex.
151 */
152
153DEFINE_RETURN_MOCK(spdk_memzone_reserve, void *);
154void *
155spdk_memzone_reserve(const char *name, size_t len, int socket_id, unsigned flags)
156{
157 HANDLE_RETURN_MOCK(spdk_memzone_reserve);
158
159 return malloc(len);
160}
161
162DEFINE_RETURN_MOCK(spdk_memzone_reserve_aligned, void *);
163void *
164spdk_memzone_reserve_aligned(const char *name, size_t len, int socket_id,
165 unsigned flags, unsigned align)
166{
167 HANDLE_RETURN_MOCK(spdk_memzone_reserve_aligned);
168
169 return malloc(len);
170}
171
172DEFINE_RETURN_MOCK(spdk_malloc, void *);
173void *
174spdk_malloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags)
175{
176 HANDLE_RETURN_MOCK(spdk_malloc);
177
178 void *buf = NULL;
9f95a23c
TL
179
180 if (align == 0) {
181 align = 8;
182 }
183
11fdf7f2
TL
184 if (posix_memalign(&buf, align, size)) {
185 return NULL;
186 }
187 if (phys_addr) {
188 *phys_addr = (uint64_t)buf;
189 }
190
191 return buf;
192}
193
194DEFINE_RETURN_MOCK(spdk_zmalloc, void *);
195void *
196spdk_zmalloc(size_t size, size_t align, uint64_t *phys_addr, int socket_id, uint32_t flags)
197{
198 HANDLE_RETURN_MOCK(spdk_zmalloc);
199
200 void *buf = spdk_malloc(size, align, phys_addr, -1, 1);
201
202 if (buf != NULL) {
203 memset(buf, 0, size);
204 }
205 return buf;
206}
207
208DEFINE_RETURN_MOCK(spdk_dma_malloc, void *);
209void *
210spdk_dma_malloc(size_t size, size_t align, uint64_t *phys_addr)
211{
212 HANDLE_RETURN_MOCK(spdk_dma_malloc);
213
214 return spdk_malloc(size, align, phys_addr, -1, 1);
215}
216
9f95a23c
TL
217DEFINE_RETURN_MOCK(spdk_realloc, void *);
218void *
219spdk_realloc(void *buf, size_t size, size_t align)
220{
221 HANDLE_RETURN_MOCK(spdk_realloc);
222
223 return realloc(buf, size);
224}
225
11fdf7f2
TL
226DEFINE_RETURN_MOCK(spdk_dma_zmalloc, void *);
227void *
228spdk_dma_zmalloc(size_t size, size_t align, uint64_t *phys_addr)
229{
230 HANDLE_RETURN_MOCK(spdk_dma_zmalloc);
231
232 return spdk_zmalloc(size, align, phys_addr, -1, 1);
233}
234
235DEFINE_RETURN_MOCK(spdk_dma_malloc_socket, void *);
236void *
237spdk_dma_malloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
238{
239 HANDLE_RETURN_MOCK(spdk_dma_malloc_socket);
240
241 return spdk_dma_malloc(size, align, phys_addr);
242}
243
244DEFINE_RETURN_MOCK(spdk_dma_zmalloc_socket, void *);
245void *
246spdk_dma_zmalloc_socket(size_t size, size_t align, uint64_t *phys_addr, int socket_id)
247{
248 HANDLE_RETURN_MOCK(spdk_dma_zmalloc_socket);
249
250 return spdk_dma_zmalloc(size, align, phys_addr);
251}
252
253DEFINE_RETURN_MOCK(spdk_dma_realloc, void *);
254void *
255spdk_dma_realloc(void *buf, size_t size, size_t align, uint64_t *phys_addr)
256{
257 HANDLE_RETURN_MOCK(spdk_dma_realloc);
258
259 return realloc(buf, size);
260}
261
262void
263spdk_free(void *buf)
264{
9f95a23c
TL
265 /* fix for false-positives in *certain* static analysis tools. */
266 assert((uintptr_t)buf != UINTPTR_MAX);
11fdf7f2
TL
267 free(buf);
268}
269
270void
271spdk_dma_free(void *buf)
272{
273 return spdk_free(buf);
274}
275
9f95a23c 276#ifndef UNIT_TEST_NO_VTOPHYS
11fdf7f2
TL
277DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t);
278uint64_t
9f95a23c 279spdk_vtophys(void *buf, uint64_t *size)
11fdf7f2
TL
280{
281 HANDLE_RETURN_MOCK(spdk_vtophys);
282
283 return (uintptr_t)buf;
284}
9f95a23c 285#endif
11fdf7f2
TL
286
287void
288spdk_memzone_dump(FILE *f)
289{
290 return;
291}
292
293DEFINE_RETURN_MOCK(spdk_memzone_free, int);
294int
295spdk_memzone_free(const char *name)
296{
297 HANDLE_RETURN_MOCK(spdk_memzone_free);
298
299 return 0;
300}
301
302struct test_mempool {
303 size_t count;
9f95a23c 304 size_t ele_size;
11fdf7f2
TL
305};
306
307DEFINE_RETURN_MOCK(spdk_mempool_create, struct spdk_mempool *);
308struct spdk_mempool *
309spdk_mempool_create(const char *name, size_t count,
310 size_t ele_size, size_t cache_size, int socket_id)
311{
312 struct test_mempool *mp;
313
314 HANDLE_RETURN_MOCK(spdk_mempool_create);
315
316 mp = calloc(1, sizeof(*mp));
317 if (mp == NULL) {
318 return NULL;
319 }
320
321 mp->count = count;
9f95a23c 322 mp->ele_size = ele_size;
11fdf7f2
TL
323
324 return (struct spdk_mempool *)mp;
325}
326
327void
328spdk_mempool_free(struct spdk_mempool *_mp)
329{
330 struct test_mempool *mp = (struct test_mempool *)_mp;
331
332 free(mp);
333}
334
335DEFINE_RETURN_MOCK(spdk_mempool_get, void *);
336void *
337spdk_mempool_get(struct spdk_mempool *_mp)
338{
339 struct test_mempool *mp = (struct test_mempool *)_mp;
9f95a23c 340 size_t ele_size = 0x10000;
11fdf7f2
TL
341 void *buf;
342
343 HANDLE_RETURN_MOCK(spdk_mempool_get);
344
345 if (mp && mp->count == 0) {
346 return NULL;
347 }
348
9f95a23c
TL
349 if (mp) {
350 ele_size = mp->ele_size;
351 }
352
353 if (posix_memalign(&buf, 64, spdk_align32pow2(ele_size))) {
11fdf7f2
TL
354 return NULL;
355 } else {
356 if (mp) {
357 mp->count--;
358 }
359 return buf;
360 }
361}
362
363int
364spdk_mempool_get_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
365{
366 for (size_t i = 0; i < count; i++) {
367 ele_arr[i] = spdk_mempool_get(mp);
368 if (ele_arr[i] == NULL) {
369 return -1;
370 }
371 }
372 return 0;
373}
374
375void
376spdk_mempool_put(struct spdk_mempool *_mp, void *ele)
377{
378 struct test_mempool *mp = (struct test_mempool *)_mp;
379
380 if (mp) {
381 mp->count++;
382 }
383 free(ele);
384}
385
386void
387spdk_mempool_put_bulk(struct spdk_mempool *mp, void **ele_arr, size_t count)
388{
389 for (size_t i = 0; i < count; i++) {
390 spdk_mempool_put(mp, ele_arr[i]);
391 }
392}
393
394DEFINE_RETURN_MOCK(spdk_mempool_count, size_t);
395size_t
396spdk_mempool_count(const struct spdk_mempool *_mp)
397{
398 struct test_mempool *mp = (struct test_mempool *)_mp;
399
400 HANDLE_RETURN_MOCK(spdk_mempool_count);
401
402 if (mp) {
403 return mp->count;
404 } else {
405 return 1024;
406 }
407}
408
409struct spdk_ring_ele {
410 void *ele;
411 TAILQ_ENTRY(spdk_ring_ele) link;
412};
413
414struct spdk_ring {
415 TAILQ_HEAD(, spdk_ring_ele) elements;
9f95a23c
TL
416 pthread_mutex_t lock;
417 size_t count;
11fdf7f2
TL
418};
419
420DEFINE_RETURN_MOCK(spdk_ring_create, struct spdk_ring *);
421struct spdk_ring *
422spdk_ring_create(enum spdk_ring_type type, size_t count, int socket_id)
423{
424 struct spdk_ring *ring;
425
426 HANDLE_RETURN_MOCK(spdk_ring_create);
427
428 ring = calloc(1, sizeof(*ring));
9f95a23c
TL
429 if (!ring) {
430 return NULL;
431 }
432
433 if (pthread_mutex_init(&ring->lock, NULL)) {
434 free(ring);
435 return NULL;
11fdf7f2
TL
436 }
437
9f95a23c 438 TAILQ_INIT(&ring->elements);
11fdf7f2
TL
439 return ring;
440}
441
442void
443spdk_ring_free(struct spdk_ring *ring)
444{
9f95a23c
TL
445 struct spdk_ring_ele *ele, *tmp;
446
447 if (!ring) {
448 return;
449 }
450
451 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
452 free(ele);
453 }
454
455 pthread_mutex_destroy(&ring->lock);
11fdf7f2
TL
456 free(ring);
457}
458
459DEFINE_RETURN_MOCK(spdk_ring_enqueue, size_t);
460size_t
9f95a23c
TL
461spdk_ring_enqueue(struct spdk_ring *ring, void **objs, size_t count,
462 size_t *free_space)
11fdf7f2
TL
463{
464 struct spdk_ring_ele *ele;
465 size_t i;
466
467 HANDLE_RETURN_MOCK(spdk_ring_enqueue);
468
9f95a23c
TL
469 pthread_mutex_lock(&ring->lock);
470
11fdf7f2
TL
471 for (i = 0; i < count; i++) {
472 ele = calloc(1, sizeof(*ele));
473 if (!ele) {
474 break;
475 }
476
477 ele->ele = objs[i];
478 TAILQ_INSERT_TAIL(&ring->elements, ele, link);
9f95a23c 479 ring->count++;
11fdf7f2
TL
480 }
481
9f95a23c 482 pthread_mutex_unlock(&ring->lock);
11fdf7f2
TL
483 return i;
484}
485
486DEFINE_RETURN_MOCK(spdk_ring_dequeue, size_t);
487size_t
488spdk_ring_dequeue(struct spdk_ring *ring, void **objs, size_t count)
489{
490 struct spdk_ring_ele *ele, *tmp;
491 size_t i = 0;
492
493 HANDLE_RETURN_MOCK(spdk_ring_dequeue);
494
495 if (count == 0) {
496 return 0;
497 }
498
9f95a23c
TL
499 pthread_mutex_lock(&ring->lock);
500
11fdf7f2
TL
501 TAILQ_FOREACH_SAFE(ele, &ring->elements, link, tmp) {
502 TAILQ_REMOVE(&ring->elements, ele, link);
9f95a23c 503 ring->count--;
11fdf7f2
TL
504 objs[i] = ele->ele;
505 free(ele);
506 i++;
507 if (i >= count) {
508 break;
509 }
510 }
511
9f95a23c 512 pthread_mutex_unlock(&ring->lock);
11fdf7f2
TL
513 return i;
514
515}
516
9f95a23c
TL
517
518DEFINE_RETURN_MOCK(spdk_ring_count, size_t);
519size_t
520spdk_ring_count(struct spdk_ring *ring)
521{
522 HANDLE_RETURN_MOCK(spdk_ring_count);
523 return ring->count;
524}
525
11fdf7f2
TL
526DEFINE_RETURN_MOCK(spdk_get_ticks, uint64_t);
527uint64_t
528spdk_get_ticks(void)
529{
530 HANDLE_RETURN_MOCK(spdk_get_ticks);
531
532 return ut_spdk_get_ticks;
533}
534
535DEFINE_RETURN_MOCK(spdk_get_ticks_hz, uint64_t);
536uint64_t
537spdk_get_ticks_hz(void)
538{
539 HANDLE_RETURN_MOCK(spdk_get_ticks_hz);
540
541 return 1000000;
542}
543
544void
545spdk_delay_us(unsigned int us)
546{
547 /* spdk_get_ticks_hz is 1000000, meaning 1 tick per us. */
548 ut_spdk_get_ticks += us;
549}
550
9f95a23c 551#ifndef UNIT_TEST_NO_PCI_ADDR
11fdf7f2
TL
552DEFINE_RETURN_MOCK(spdk_pci_addr_parse, int);
553int
554spdk_pci_addr_parse(struct spdk_pci_addr *addr, const char *bdf)
555{
556 unsigned domain, bus, dev, func;
557
558 HANDLE_RETURN_MOCK(spdk_pci_addr_parse);
559
560 if (addr == NULL || bdf == NULL) {
561 return -EINVAL;
562 }
563
564 if ((sscanf(bdf, "%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) ||
565 (sscanf(bdf, "%x.%x.%x.%x", &domain, &bus, &dev, &func) == 4)) {
566 /* Matched a full address - all variables are initialized */
567 } else if (sscanf(bdf, "%x:%x:%x", &domain, &bus, &dev) == 3) {
568 func = 0;
569 } else if ((sscanf(bdf, "%x:%x.%x", &bus, &dev, &func) == 3) ||
570 (sscanf(bdf, "%x.%x.%x", &bus, &dev, &func) == 3)) {
571 domain = 0;
572 } else if ((sscanf(bdf, "%x:%x", &bus, &dev) == 2) ||
573 (sscanf(bdf, "%x.%x", &bus, &dev) == 2)) {
574 domain = 0;
575 func = 0;
576 } else {
577 return -EINVAL;
578 }
579
580 if (bus > 0xFF || dev > 0x1F || func > 7) {
581 return -EINVAL;
582 }
583
584 addr->domain = domain;
585 addr->bus = bus;
586 addr->dev = dev;
587 addr->func = func;
588
589 return 0;
590}
591
592DEFINE_RETURN_MOCK(spdk_pci_addr_fmt, int);
593int
594spdk_pci_addr_fmt(char *bdf, size_t sz, const struct spdk_pci_addr *addr)
595{
596 int rc;
597
598 HANDLE_RETURN_MOCK(spdk_pci_addr_fmt);
599
600 rc = snprintf(bdf, sz, "%04x:%02x:%02x.%x",
601 addr->domain, addr->bus,
602 addr->dev, addr->func);
603
604 if (rc > 0 && (size_t)rc < sz) {
605 return 0;
606 }
607
608 return -1;
609}
610
611DEFINE_RETURN_MOCK(spdk_pci_addr_compare, int);
612int
613spdk_pci_addr_compare(const struct spdk_pci_addr *a1, const struct spdk_pci_addr *a2)
614{
615 HANDLE_RETURN_MOCK(spdk_pci_addr_compare);
616
617 if (a1->domain > a2->domain) {
618 return 1;
619 } else if (a1->domain < a2->domain) {
620 return -1;
621 } else if (a1->bus > a2->bus) {
622 return 1;
623 } else if (a1->bus < a2->bus) {
624 return -1;
625 } else if (a1->dev > a2->dev) {
626 return 1;
627 } else if (a1->dev < a2->dev) {
628 return -1;
629 } else if (a1->func > a2->func) {
630 return 1;
631 } else if (a1->func < a2->func) {
632 return -1;
633 }
634
635 return 0;
636}
9f95a23c 637#endif