xref: /spdk/test/unit/lib/ftl/common/utils.c (revision 0098e636761237b77c12c30c2408263a5d2260cc)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/ftl.h"
7 #include "ftl/ftl_core.h"
8 #include "thread/thread_internal.h"
9 
10 struct base_bdev_geometry {
11 	size_t write_unit_size;
12 	size_t zone_size;
13 	size_t optimal_open_zones;
14 	size_t blockcnt;
15 };
16 
17 extern struct base_bdev_geometry g_geo;
18 
19 struct spdk_ftl_dev *test_init_ftl_dev(const struct base_bdev_geometry *geo);
20 struct ftl_band *test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id, size_t zone_size);
21 void test_free_ftl_dev(struct spdk_ftl_dev *dev);
22 void test_free_ftl_band(struct ftl_band *band);
23 uint64_t test_offset_from_addr(struct ftl_addr addr, struct ftl_band *band);
24 
25 DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *, (struct spdk_bdev_desc *desc), NULL);
26 
27 uint64_t
28 spdk_bdev_get_zone_size(const struct spdk_bdev *bdev)
29 {
30 	return g_geo.zone_size;
31 }
32 
33 uint32_t
34 spdk_bdev_get_optimal_open_zones(const struct spdk_bdev *bdev)
35 {
36 	return g_geo.optimal_open_zones;
37 }
38 
39 struct spdk_ftl_dev *
40 test_init_ftl_dev(const struct base_bdev_geometry *geo)
41 {
42 	struct spdk_ftl_dev *dev;
43 
44 	dev = calloc(1, sizeof(*dev));
45 	SPDK_CU_ASSERT_FATAL(dev != NULL);
46 
47 	dev->xfer_size = geo->write_unit_size;
48 	dev->core_thread = spdk_thread_create("unit_test_thread", NULL);
49 	spdk_set_thread(dev->core_thread);
50 	dev->ioch = calloc(1, sizeof(*dev->ioch)
51 			   + sizeof(struct ftl_io_channel *));
52 	dev->num_bands = geo->blockcnt / (geo->zone_size * geo->optimal_open_zones);
53 	dev->bands = calloc(dev->num_bands, sizeof(*dev->bands));
54 	SPDK_CU_ASSERT_FATAL(dev->bands != NULL);
55 
56 	dev->lba_pool = spdk_mempool_create("ftl_ut", 2, 0x18000,
57 					    SPDK_MEMPOOL_DEFAULT_CACHE_SIZE,
58 					    SPDK_ENV_SOCKET_ID_ANY);
59 	SPDK_CU_ASSERT_FATAL(dev->lba_pool != NULL);
60 
61 	LIST_INIT(&dev->free_bands);
62 	LIST_INIT(&dev->shut_bands);
63 
64 	return dev;
65 }
66 
67 struct ftl_band *
68 test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id, size_t zone_size)
69 {
70 	struct ftl_band *band;
71 	struct ftl_zone *zone;
72 
73 	SPDK_CU_ASSERT_FATAL(dev != NULL);
74 	SPDK_CU_ASSERT_FATAL(id < dev->num_bands);
75 
76 	band = &dev->bands[id];
77 	band->dev = dev;
78 	band->id = id;
79 
80 	band->state = FTL_BAND_STATE_CLOSED;
81 	LIST_INSERT_HEAD(&dev->shut_bands, band, list_entry);
82 	CIRCLEQ_INIT(&band->zones);
83 
84 	band->lba_map.vld = spdk_bit_array_create(ftl_get_num_blocks_in_band(dev));
85 	SPDK_CU_ASSERT_FATAL(band->lba_map.vld != NULL);
86 
87 	band->zone_buf = calloc(ftl_get_num_punits(dev), sizeof(*band->zone_buf));
88 	SPDK_CU_ASSERT_FATAL(band->zone_buf != NULL);
89 
90 	band->reloc_bitmap = spdk_bit_array_create(ftl_get_num_bands(dev));
91 	SPDK_CU_ASSERT_FATAL(band->reloc_bitmap != NULL);
92 
93 	for (size_t i = 0; i < ftl_get_num_punits(dev); ++i) {
94 		zone = &band->zone_buf[i];
95 		zone->info.state = SPDK_BDEV_ZONE_STATE_FULL;
96 		zone->info.zone_id = zone_size * (id * ftl_get_num_punits(dev) + i);
97 		CIRCLEQ_INSERT_TAIL(&band->zones, zone, circleq);
98 		band->num_zones++;
99 	}
100 
101 	pthread_spin_init(&band->lba_map.lock, PTHREAD_PROCESS_PRIVATE);
102 	return band;
103 }
104 
105 void
106 test_free_ftl_dev(struct spdk_ftl_dev *dev)
107 {
108 	struct spdk_thread *thread;
109 
110 	SPDK_CU_ASSERT_FATAL(dev != NULL);
111 	free(dev->ioch);
112 
113 	thread = dev->core_thread;
114 
115 	spdk_set_thread(thread);
116 	spdk_thread_exit(thread);
117 	while (!spdk_thread_is_exited(thread)) {
118 		spdk_thread_poll(thread, 0, 0);
119 	}
120 	spdk_thread_destroy(thread);
121 	spdk_mempool_free(dev->lba_pool);
122 	free(dev->bands);
123 	free(dev);
124 }
125 
126 void
127 test_free_ftl_band(struct ftl_band *band)
128 {
129 	SPDK_CU_ASSERT_FATAL(band != NULL);
130 	spdk_bit_array_free(&band->lba_map.vld);
131 	spdk_bit_array_free(&band->reloc_bitmap);
132 	free(band->zone_buf);
133 	spdk_dma_free(band->lba_map.dma_buf);
134 }
135 
136 uint64_t
137 test_offset_from_addr(struct ftl_addr addr, struct ftl_band *band)
138 {
139 	struct spdk_ftl_dev *dev = band->dev;
140 
141 	CU_ASSERT_EQUAL(ftl_addr_get_band(dev, addr), band->id);
142 
143 	return addr.offset - band->id * ftl_get_num_blocks_in_band(dev);
144 }
145