]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/test/unit/lib/bdev/pmem/bdev_pmem_ut.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / test / unit / lib / bdev / pmem / bdev_pmem_ut.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_cunit.h"
35
9f95a23c 36#include "common/lib/ut_multithread.c"
11fdf7f2
TL
37#include "unit/lib/json_mock.c"
38
9f95a23c
TL
39#include "spdk_internal/thread.h"
40
11fdf7f2
TL
41#include "bdev/pmem/bdev_pmem.c"
42
43DEFINE_STUB(spdk_conf_find_section, struct spdk_conf_section *,
44 (struct spdk_conf *cp, const char *name), NULL);
45DEFINE_STUB(spdk_conf_section_get_nval, char *,
46 (struct spdk_conf_section *sp, const char *key, int idx), NULL);
47DEFINE_STUB(spdk_conf_section_get_nmval, char *,
48 (struct spdk_conf_section *sp, const char *key, int idx1, int idx2), NULL);
49
50static struct spdk_bdev_module *g_bdev_pmem_module;
51static int g_bdev_module_cnt;
52
53struct pmemblk {
54 const char *name;
55 bool is_open;
56 bool is_consistent;
57 size_t bsize;
58 long long nblock;
59
60 uint8_t *buffer;
61};
62
63static const char *g_bdev_name = "pmem0";
64
65/* PMEMblkpool is a typedef of struct pmemblk */
66static PMEMblkpool g_pool_ok = {
67 .name = "/pools/ok_pool",
68 .is_open = false,
69 .is_consistent = true,
70 .bsize = 4096,
71 .nblock = 150
72};
73
74static PMEMblkpool g_pool_nblock_0 = {
75 .name = "/pools/nblock_0",
76 .is_open = false,
77 .is_consistent = true,
78 .bsize = 4096,
79 .nblock = 0
80};
81
82static PMEMblkpool g_pool_bsize_0 = {
83 .name = "/pools/nblock_0",
84 .is_open = false,
85 .is_consistent = true,
86 .bsize = 0,
87 .nblock = 100
88};
89
90static PMEMblkpool g_pool_inconsistent = {
91 .name = "/pools/inconsistent",
92 .is_open = false,
93 .is_consistent = false,
94 .bsize = 512,
95 .nblock = 1
96};
97
98static int g_opened_pools;
99static struct spdk_bdev *g_bdev;
100static const char *g_check_version_msg;
101static bool g_pmemblk_open_allow_open = true;
102
11fdf7f2
TL
103static PMEMblkpool *
104find_pmemblk_pool(const char *path)
105{
106 if (path == NULL) {
107 errno = EINVAL;
108 return NULL;
109 } else if (strcmp(g_pool_ok.name, path) == 0) {
110 return &g_pool_ok;
111 } else if (strcmp(g_pool_nblock_0.name, path) == 0) {
112 return &g_pool_nblock_0;
113 } else if (strcmp(g_pool_bsize_0.name, path) == 0) {
114 return &g_pool_bsize_0;
115 } else if (strcmp(g_pool_inconsistent.name, path) == 0) {
116 return &g_pool_inconsistent;
117 }
118
119 errno = ENOENT;
120 return NULL;
121}
122
123PMEMblkpool *
124pmemblk_open(const char *path, size_t bsize)
125{
126 PMEMblkpool *pool;
127
128 if (!g_pmemblk_open_allow_open) {
129 errno = EIO;
130 return NULL;
131 }
132
133 pool = find_pmemblk_pool(path);
134 if (!pool) {
135 errno = ENOENT;
136 return NULL;
137 }
138
139 CU_ASSERT_TRUE_FATAL(pool->is_consistent);
140 CU_ASSERT_FALSE(pool->is_open);
141 if (pool->is_open == false) {
142 pool->is_open = true;
143 g_opened_pools++;
144 } else {
145 errno = EBUSY;
146 pool = NULL;
147 }
148
149 return pool;
150}
151void
152spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb, uint64_t len)
153{
9f95a23c 154 cb(NULL, bdev_io, true);
11fdf7f2
TL
155}
156
157static void
158check_open_pool_fatal(PMEMblkpool *pool)
159{
160 SPDK_CU_ASSERT_FATAL(pool != NULL);
161 SPDK_CU_ASSERT_FATAL(find_pmemblk_pool(pool->name) == pool);
162 SPDK_CU_ASSERT_FATAL(pool->is_open == true);
163}
164
165void
166pmemblk_close(PMEMblkpool *pool)
167{
168 check_open_pool_fatal(pool);
169 pool->is_open = false;
170 CU_ASSERT(g_opened_pools > 0);
171 g_opened_pools--;
172}
173
174size_t
175pmemblk_bsize(PMEMblkpool *pool)
176{
177 check_open_pool_fatal(pool);
178 return pool->bsize;
179}
180
181size_t
182pmemblk_nblock(PMEMblkpool *pool)
183{
184 check_open_pool_fatal(pool);
185 return pool->nblock;
186}
187
188int
189pmemblk_read(PMEMblkpool *pool, void *buf, long long blockno)
190{
191 check_open_pool_fatal(pool);
192 if (blockno >= pool->nblock) {
193 errno = EINVAL;
194 return -1;
195 }
196
197 memcpy(buf, &pool->buffer[blockno * pool->bsize], pool->bsize);
198 return 0;
199}
200
201int
202pmemblk_write(PMEMblkpool *pool, const void *buf, long long blockno)
203{
204 check_open_pool_fatal(pool);
205 if (blockno >= pool->nblock) {
206 errno = EINVAL;
207 return -1;
208 }
209
210 memcpy(&pool->buffer[blockno * pool->bsize], buf, pool->bsize);
211 return 0;
212}
213
214int
215pmemblk_set_zero(PMEMblkpool *pool, long long blockno)
216{
217 check_open_pool_fatal(pool);
218 if (blockno >= pool->nblock) {
219
220 errno = EINVAL;
221 return -1;
222 }
223
224 memset(&pool->buffer[blockno * pool->bsize], 0, pool->bsize);
225 return 0;
226}
227
228const char *
229pmemblk_errormsg(void)
230{
231 return strerror(errno);
232}
233
234const char *
235pmemblk_check_version(unsigned major_required, unsigned minor_required)
236{
237 return g_check_version_msg;
238}
239
240int
241pmemblk_check(const char *path, size_t bsize)
242{
243 PMEMblkpool *pool = find_pmemblk_pool(path);
244
245 if (!pool) {
246 errno = ENOENT;
247 return -1;
248 }
249
250 if (!pool->is_consistent) {
251 /* errno ? */
252 return 0;
253 }
254
255 if (bsize != 0 && pool->bsize != bsize) {
256 /* errno ? */
257 return 0;
258 }
259
260 return 1;
261}
262
263void
264spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
265{
266 bdev_io->internal.status = status;
267}
268
269int
270spdk_bdev_register(struct spdk_bdev *bdev)
271{
272 CU_ASSERT_PTR_NULL(g_bdev);
273 g_bdev = bdev;
274
275 return 0;
276}
277
278void
279spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
280{
281}
282
283void
284spdk_bdev_module_finish_done(void)
285{
286}
287
288int
289spdk_bdev_notify_blockcnt_change(struct spdk_bdev *bdev, uint64_t size)
290{
291 bdev->blockcnt = size;
292 return 0;
293}
294
295static void
296ut_bdev_pmem_destruct(struct spdk_bdev *bdev)
297{
298 SPDK_CU_ASSERT_FATAL(g_bdev != NULL);
299 CU_ASSERT_EQUAL(bdev_pmem_destruct(bdev->ctxt), 0);
300 g_bdev = NULL;
301}
302
303void
304spdk_bdev_module_list_add(struct spdk_bdev_module *bdev_module)
305{
306 g_bdev_pmem_module = bdev_module;
307 g_bdev_module_cnt++;
308}
309
310static int
311bdev_submit_request(struct spdk_bdev *bdev, int16_t io_type, uint64_t offset_blocks,
312 uint64_t num_blocks, struct iovec *iovs, size_t iov_cnt)
313{
314 struct spdk_bdev_io bio = { 0 };
315
316 switch (io_type) {
317 case SPDK_BDEV_IO_TYPE_READ:
318 bio.u.bdev.iovs = iovs;
319 bio.u.bdev.iovcnt = iov_cnt;
320 bio.u.bdev.offset_blocks = offset_blocks;
321 bio.u.bdev.num_blocks = num_blocks;
322 break;
323 case SPDK_BDEV_IO_TYPE_WRITE:
324 bio.u.bdev.iovs = iovs;
325 bio.u.bdev.iovcnt = iov_cnt;
326 bio.u.bdev.offset_blocks = offset_blocks;
327 bio.u.bdev.num_blocks = num_blocks;
328 break;
329 case SPDK_BDEV_IO_TYPE_FLUSH:
330 bio.u.bdev.offset_blocks = offset_blocks;
331 bio.u.bdev.num_blocks = num_blocks;
332 break;
333 case SPDK_BDEV_IO_TYPE_RESET:
334 break;
335 case SPDK_BDEV_IO_TYPE_UNMAP:
336 bio.u.bdev.offset_blocks = offset_blocks;
337 bio.u.bdev.num_blocks = num_blocks;
338 break;
339 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
340 bio.u.bdev.offset_blocks = offset_blocks;
341 bio.u.bdev.num_blocks = num_blocks;
342 break;
343 default:
344 CU_FAIL_FATAL("BUG:Unexpected IO type");
345 break;
346 }
347
348 /*
349 * Set status to value that shouldn't be returned
350 */
351 bio.type = io_type;
352 bio.internal.status = SPDK_BDEV_IO_STATUS_PENDING;
353 bio.bdev = bdev;
354 bdev_pmem_submit_request(NULL, &bio);
355 return bio.internal.status;
356}
357
358
359static int
360ut_pmem_blk_clean(void)
361{
362 free(g_pool_ok.buffer);
363 g_pool_ok.buffer = NULL;
364
365 /* Unload module to free IO channel */
366 g_bdev_pmem_module->module_fini();
9f95a23c 367 poll_threads();
11fdf7f2 368
9f95a23c 369 free_threads();
11fdf7f2
TL
370
371 return 0;
372}
373
374static int
375ut_pmem_blk_init(void)
376{
377 errno = 0;
378
9f95a23c
TL
379 allocate_threads(1);
380 set_thread(0);
11fdf7f2
TL
381
382 g_pool_ok.buffer = calloc(g_pool_ok.nblock, g_pool_ok.bsize);
383 if (g_pool_ok.buffer == NULL) {
384 ut_pmem_blk_clean();
385 return -1;
386 }
387
388 return 0;
389}
390
391static void
392ut_pmem_init(void)
393{
394 SPDK_CU_ASSERT_FATAL(g_bdev_pmem_module != NULL);
395 CU_ASSERT_EQUAL(g_bdev_module_cnt, 1);
396
397 /* Make pmemblk_check_version fail with provided error message */
398 g_check_version_msg = "TEST FAIL MESSAGE";
399 CU_ASSERT_NOT_EQUAL(g_bdev_pmem_module->module_init(), 0);
400
401 /* This init must success */
402 g_check_version_msg = NULL;
403 CU_ASSERT_EQUAL(g_bdev_pmem_module->module_init(), 0);
404}
405
406static void
407ut_pmem_open_close(void)
408{
409 struct spdk_bdev *bdev = NULL;
410 int pools_cnt;
411 int rc;
412
413 pools_cnt = g_opened_pools;
414
415 /* Try opening with NULL name */
f67539c2 416 rc = create_pmem_disk(NULL, NULL, &bdev);
11fdf7f2
TL
417 CU_ASSERT_PTR_NULL(bdev);
418 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
419 CU_ASSERT_NOT_EQUAL(rc, 0);
420
421 /* Open non-existent pool */
f67539c2 422 rc = create_pmem_disk("non existent pool", NULL, &bdev);
11fdf7f2
TL
423 CU_ASSERT_PTR_NULL(bdev);
424 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
425 CU_ASSERT_NOT_EQUAL(rc, 0);
426
427 /* Open inconsistent pool */
f67539c2 428 rc = create_pmem_disk(g_pool_inconsistent.name, NULL, &bdev);
11fdf7f2
TL
429 CU_ASSERT_PTR_NULL(bdev);
430 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
431 CU_ASSERT_NOT_EQUAL(rc, 0);
432
433 /* Open consistent pool fail the open from unknown reason. */
434 g_pmemblk_open_allow_open = false;
f67539c2 435 rc = create_pmem_disk(g_pool_inconsistent.name, NULL, &bdev);
11fdf7f2
TL
436 g_pmemblk_open_allow_open = true;
437 CU_ASSERT_PTR_NULL(bdev);
438 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
439 CU_ASSERT_NOT_EQUAL(rc, 0);
440
441 /* Open pool with nblocks = 0 */
f67539c2 442 rc = create_pmem_disk(g_pool_nblock_0.name, NULL, &bdev);
11fdf7f2
TL
443 CU_ASSERT_PTR_NULL(bdev);
444 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
445 CU_ASSERT_NOT_EQUAL(rc, 0);
446
447 /* Open pool with bsize = 0 */
f67539c2 448 rc = create_pmem_disk(g_pool_bsize_0.name, NULL, &bdev);
11fdf7f2
TL
449 CU_ASSERT_PTR_NULL(bdev);
450 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
451 CU_ASSERT_NOT_EQUAL(rc, 0);
452
453 /* Open pool with NULL name */
f67539c2 454 rc = create_pmem_disk(g_pool_ok.name, NULL, &bdev);
11fdf7f2
TL
455 CU_ASSERT_PTR_NULL(bdev);
456 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
457 CU_ASSERT_NOT_EQUAL(rc, 0);
458
459 /* Open good pool */
f67539c2 460 rc = create_pmem_disk(g_pool_ok.name, g_bdev_name, &bdev);
11fdf7f2
TL
461 SPDK_CU_ASSERT_FATAL(bdev != NULL);
462 CU_ASSERT_TRUE(g_pool_ok.is_open);
463 CU_ASSERT_EQUAL(pools_cnt + 1, g_opened_pools);
464 CU_ASSERT_EQUAL(rc, 0);
465
466 /* Now remove this bdev */
467 ut_bdev_pmem_destruct(bdev);
468 CU_ASSERT_FALSE(g_pool_ok.is_open);
469 CU_ASSERT_EQUAL(pools_cnt, g_opened_pools);
470}
471
472static void
473ut_pmem_write_read(void)
474{
475 uint8_t *write_buf, *read_buf;
476 struct spdk_bdev *bdev;
477 int rc;
478 size_t unaligned_aligned_size = 100;
479 size_t buf_size = g_pool_ok.bsize * g_pool_ok.nblock;
480 size_t i;
481 const uint64_t nblock_offset = 10;
482 uint64_t offset;
483 size_t io_size, nblock, total_io_size, bsize;
484
485 bsize = 4096;
486 struct iovec iov[] = {
487 { 0, 2 * bsize },
488 { 0, 3 * bsize },
489 { 0, 4 * bsize },
490 };
491
f67539c2 492 rc = create_pmem_disk(g_pool_ok.name, g_bdev_name, &bdev);
11fdf7f2
TL
493 CU_ASSERT_EQUAL(rc, 0);
494
495 SPDK_CU_ASSERT_FATAL(g_pool_ok.nblock > 40);
496
497 write_buf = calloc(1, buf_size);
498 read_buf = calloc(1, buf_size);
499
500 SPDK_CU_ASSERT_FATAL(bdev != NULL);
501 SPDK_CU_ASSERT_FATAL(write_buf != NULL);
502 SPDK_CU_ASSERT_FATAL(read_buf != NULL);
503
504 total_io_size = 0;
505 offset = nblock_offset * g_pool_ok.bsize;
506 for (i = 0; i < 3; i++) {
507 iov[i].iov_base = &write_buf[offset + total_io_size];
508 total_io_size += iov[i].iov_len;
509 }
510
511 for (i = 0; i < total_io_size + unaligned_aligned_size; i++) {
512 write_buf[offset + i] = 0x42 + i;
513 }
514
515 SPDK_CU_ASSERT_FATAL(total_io_size < buf_size);
516
517 /*
518 * Write outside pool.
519 */
520 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_WRITE, g_pool_ok.nblock, 1, &iov[0], 2);
521 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
522
523 /*
524 * Write with insufficient IOV buffers length.
525 */
526 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_WRITE, 0, g_pool_ok.nblock, &iov[0], 2);
527 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
528
529 /*
530 * Try to write two IOV with first one iov_len % bsize != 0.
531 */
532 io_size = iov[0].iov_len + iov[1].iov_len;
533 nblock = io_size / g_pool_ok.bsize;
534 iov[0].iov_len += unaligned_aligned_size;
535 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_WRITE, 0, nblock, &iov[0], 2);
536 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
537 iov[0].iov_len -= unaligned_aligned_size;
538
539 /*
540 * Try to write one IOV.
541 */
542 nblock = iov[0].iov_len / g_pool_ok.bsize;
543 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_WRITE, nblock_offset, nblock, &iov[0], 1);
544 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
545
546 /*
547 * Try to write 2 IOV.
548 * Sum of IOV length is larger than IO size and last IOV is larger and iov_len % bsize != 0
549 */
550 offset = iov[0].iov_len / g_pool_ok.bsize;
551 io_size = iov[1].iov_len + iov[2].iov_len;
552 nblock = io_size / g_pool_ok.bsize;
553 iov[2].iov_len += unaligned_aligned_size;
554 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_WRITE, nblock_offset + offset, nblock,
555 &iov[1], 2);
556 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
557 iov[2].iov_len -= unaligned_aligned_size;
558
559 /*
560 * Examine pool state:
561 * 1. Written area should have expected values.
562 * 2. Anything else should contain zeros.
563 */
564 offset = nblock_offset * g_pool_ok.bsize + total_io_size;
565 rc = memcmp(&g_pool_ok.buffer[0], write_buf, offset);
566 CU_ASSERT_EQUAL(rc, 0);
567
568 for (i = offset; i < buf_size; i++) {
569 if (g_pool_ok.buffer[i] != 0) {
570 CU_ASSERT_EQUAL(g_pool_ok.buffer[i], 0);
571 break;
572 }
573 }
574
575 /* Setup IOV for reads */
576 memset(read_buf, 0xAB, buf_size);
577 offset = nblock_offset * g_pool_ok.bsize;
578 for (i = 0; i < 3; i++) {
579 iov[i].iov_base = &read_buf[offset];
580 offset += iov[i].iov_len;
581 }
582
583 /*
584 * Write outside pool.
585 */
586 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_READ, g_pool_ok.nblock, 1, &iov[0], 2);
587 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
588
589 /*
590 * Read with insufficient IOV buffers length.
591 */
592 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_READ, 0, g_pool_ok.nblock, &iov[0], 2);
593 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
594
595 /*
596 * Try to read two IOV with first one iov_len % bsize != 0.
597 */
598 io_size = iov[0].iov_len + iov[1].iov_len;
599 nblock = io_size / g_pool_ok.bsize;
600 iov[0].iov_len += unaligned_aligned_size;
601 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_READ, 0, nblock, &iov[0], 2);
602 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
603 iov[0].iov_len -= unaligned_aligned_size;
604
605 /*
606 * Try to write one IOV.
607 */
608 nblock = iov[0].iov_len / g_pool_ok.bsize;
609 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_READ, nblock_offset, nblock, &iov[0], 1);
610 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
611
612 /*
613 * Try to read 2 IOV.
614 * Sum of IOV length is larger than IO size and last IOV is larger and iov_len % bsize != 0
615 */
616 offset = iov[0].iov_len / g_pool_ok.bsize;
617 io_size = iov[1].iov_len + iov[2].iov_len;
618 nblock = io_size / g_pool_ok.bsize;
619 iov[2].iov_len += unaligned_aligned_size;
620 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_READ, nblock_offset + offset, nblock,
621 &iov[1], 2);
622 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
623 iov[2].iov_len -= unaligned_aligned_size;
624
625
626 /*
627 * Examine what we read state:
628 * 1. Written area should have expected values.
629 * 2. Anything else should contain zeros.
630 */
631 offset = nblock_offset * g_pool_ok.bsize;
632 for (i = 0; i < offset; i++) {
633 if (read_buf[i] != 0xAB) {
634 CU_ASSERT_EQUAL(read_buf[i], 0xAB);
635 break;
636 }
637 }
638
639 rc = memcmp(&read_buf[offset], &write_buf[offset], total_io_size);
640 CU_ASSERT_EQUAL(rc, 0);
641
642 offset += total_io_size;
643 for (i = offset; i < buf_size; i++) {
644 if (read_buf[i] != 0xAB) {
645 CU_ASSERT_EQUAL(read_buf[i], 0xAB);
646 break;
647 }
648 }
649
650 memset(g_pool_ok.buffer, 0, g_pool_ok.bsize * g_pool_ok.nblock);
651 free(write_buf);
652 free(read_buf);
653
654 /* Now remove this bdev */
655 ut_bdev_pmem_destruct(bdev);
656 CU_ASSERT_FALSE(g_pool_ok.is_open);
657 CU_ASSERT_EQUAL(g_opened_pools, 0);
658}
659
660static void
661ut_pmem_reset(void)
662{
663 struct spdk_bdev *bdev;
664 int rc;
665
f67539c2 666 rc = create_pmem_disk(g_pool_ok.name, g_bdev_name, &bdev);
11fdf7f2
TL
667 CU_ASSERT_EQUAL(rc, 0);
668 SPDK_CU_ASSERT_FATAL(bdev != NULL);
669
670 rc = bdev_submit_request(bdev, SPDK_BDEV_IO_TYPE_RESET, 0, 0, NULL, 0);
671 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
672
673 ut_bdev_pmem_destruct(bdev);
674}
675
676static void
677ut_pmem_unmap_write_zero(int16_t io_type)
678{
679 struct spdk_bdev *bdev;
680 size_t buff_size = g_pool_ok.nblock * g_pool_ok.bsize;
681 size_t i;
682 uint8_t *buffer;
683 int rc;
684
685 CU_ASSERT(io_type == SPDK_BDEV_IO_TYPE_UNMAP || io_type == SPDK_BDEV_IO_TYPE_WRITE_ZEROES);
f67539c2 686 rc = create_pmem_disk(g_pool_ok.name, g_bdev_name, &bdev);
11fdf7f2
TL
687 CU_ASSERT_EQUAL(rc, 0);
688 SPDK_CU_ASSERT_FATAL(bdev != NULL);
689 SPDK_CU_ASSERT_FATAL(g_pool_ok.nblock > 40);
690
691 buffer = calloc(1, buff_size);
692 SPDK_CU_ASSERT_FATAL(buffer != NULL);
693
694 for (i = 10 * g_pool_ok.bsize; i < 30 * g_pool_ok.bsize; i++) {
695 buffer[i] = 0x30 + io_type + i;
696 }
697 memcpy(g_pool_ok.buffer, buffer, buff_size);
698
699 /*
700 * Block outside of pool.
701 */
702 rc = bdev_submit_request(bdev, io_type, g_pool_ok.nblock, 1, NULL, 0);
703 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_FAILED);
704
705 rc = memcmp(buffer, g_pool_ok.buffer, buff_size);
706 CU_ASSERT_EQUAL(rc, 0);
707
708 /*
709 * Blocks 15 to 25
710 */
711 memset(&buffer[15 * g_pool_ok.bsize], 0, 10 * g_pool_ok.bsize);
712 rc = bdev_submit_request(bdev, io_type, 15, 10, NULL, 0);
713 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
714
715 rc = memcmp(buffer, g_pool_ok.buffer, buff_size);
716 CU_ASSERT_EQUAL(rc, 0);
717
718 /*
719 * All blocks.
720 */
721 memset(buffer, 0, buff_size);
722 rc = bdev_submit_request(bdev, io_type, 0, g_pool_ok.nblock, NULL, 0);
723 CU_ASSERT_EQUAL(rc, SPDK_BDEV_IO_STATUS_SUCCESS);
724
725 rc = memcmp(buffer, g_pool_ok.buffer, buff_size);
726 CU_ASSERT_EQUAL(rc, 0);
727
728 /* Now remove this bdev */
729 ut_bdev_pmem_destruct(bdev);
730 CU_ASSERT_FALSE(g_pool_ok.is_open);
731 CU_ASSERT_EQUAL(g_opened_pools, 0);
732
733 free(buffer);
734}
735
736static void
737ut_pmem_write_zero(void)
738{
739 ut_pmem_unmap_write_zero(SPDK_BDEV_IO_TYPE_WRITE_ZEROES);
740}
741
742static void
743ut_pmem_unmap(void)
744{
745 ut_pmem_unmap_write_zero(SPDK_BDEV_IO_TYPE_UNMAP);
746}
747
748int
749main(int argc, char **argv)
750{
751 CU_pSuite suite = NULL;
752 unsigned int num_failures;
753
f67539c2
TL
754 CU_set_error_action(CUEA_ABORT);
755 CU_initialize_registry();
11fdf7f2
TL
756
757 suite = CU_add_suite("bdev_pmem", ut_pmem_blk_init, ut_pmem_blk_clean);
11fdf7f2 758
f67539c2
TL
759 CU_ADD_TEST(suite, ut_pmem_init);
760 CU_ADD_TEST(suite, ut_pmem_open_close);
761 CU_ADD_TEST(suite, ut_pmem_write_read);
762 CU_ADD_TEST(suite, ut_pmem_reset);
763 CU_ADD_TEST(suite, ut_pmem_write_zero);
764 CU_ADD_TEST(suite, ut_pmem_unmap);
11fdf7f2
TL
765
766 CU_basic_set_mode(CU_BRM_VERBOSE);
767 CU_basic_run_tests();
768 num_failures = CU_get_number_of_failures();
769 CU_cleanup_registry();
9f95a23c 770
11fdf7f2
TL
771 return num_failures;
772}