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_internal/thread.h" 35 36 #include "spdk/ftl.h" 37 #include "ftl/ftl_core.h" 38 39 struct spdk_ftl_dev *test_init_ftl_dev(const struct spdk_ocssd_geometry_data *geo, 40 const struct spdk_ftl_punit_range *range); 41 struct ftl_band *test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id); 42 void test_free_ftl_dev(struct spdk_ftl_dev *dev); 43 void test_free_ftl_band(struct ftl_band *band); 44 uint64_t test_offset_from_ppa(struct ftl_ppa ppa, struct ftl_band *band); 45 46 struct spdk_ftl_dev * 47 test_init_ftl_dev(const struct spdk_ocssd_geometry_data *geo, 48 const struct spdk_ftl_punit_range *range) 49 { 50 struct spdk_ftl_dev *dev; 51 unsigned int punit; 52 53 dev = calloc(1, sizeof(*dev)); 54 SPDK_CU_ASSERT_FATAL(dev != NULL); 55 56 dev->xfer_size = geo->ws_opt; 57 dev->geo = *geo; 58 dev->range = *range; 59 dev->core_thread.thread = spdk_thread_create("unit_test_thread"); 60 spdk_set_thread(dev->core_thread.thread); 61 62 dev->bands = calloc(geo->num_chk, sizeof(*dev->bands)); 63 SPDK_CU_ASSERT_FATAL(dev->bands != NULL); 64 65 dev->punits = calloc(ftl_dev_num_punits(dev), sizeof(*dev->punits)); 66 SPDK_CU_ASSERT_FATAL(dev->punits != NULL); 67 68 for (size_t i = 0; i < ftl_dev_num_punits(dev); ++i) { 69 punit = range->begin + i; 70 dev->punits[i].dev = dev; 71 dev->punits[i].start_ppa.grp = punit % geo->num_grp; 72 dev->punits[i].start_ppa.pu = punit / geo->num_grp; 73 } 74 75 LIST_INIT(&dev->free_bands); 76 LIST_INIT(&dev->shut_bands); 77 78 return dev; 79 } 80 81 struct ftl_band * 82 test_init_ftl_band(struct spdk_ftl_dev *dev, size_t id) 83 { 84 struct ftl_band *band; 85 struct ftl_chunk *chunk; 86 87 SPDK_CU_ASSERT_FATAL(dev != NULL); 88 SPDK_CU_ASSERT_FATAL(id < dev->geo.num_chk); 89 90 band = &dev->bands[id]; 91 band->dev = dev; 92 band->id = id; 93 94 band->state = FTL_BAND_STATE_CLOSED; 95 LIST_INSERT_HEAD(&dev->shut_bands, band, list_entry); 96 CIRCLEQ_INIT(&band->chunks); 97 98 band->md.vld_map = spdk_bit_array_create(ftl_num_band_lbks(dev)); 99 SPDK_CU_ASSERT_FATAL(band->md.vld_map != NULL); 100 101 band->chunk_buf = calloc(ftl_dev_num_punits(dev), sizeof(*band->chunk_buf)); 102 SPDK_CU_ASSERT_FATAL(band->chunk_buf != NULL); 103 104 for (size_t i = 0; i < ftl_dev_num_punits(dev); ++i) { 105 chunk = &band->chunk_buf[i]; 106 chunk->pos = i; 107 chunk->state = FTL_CHUNK_STATE_CLOSED; 108 chunk->punit = &dev->punits[i]; 109 chunk->start_ppa = dev->punits[i].start_ppa; 110 chunk->start_ppa.chk = band->id; 111 CIRCLEQ_INSERT_TAIL(&band->chunks, chunk, circleq); 112 band->num_chunks++; 113 } 114 115 pthread_spin_init(&band->md.lock, PTHREAD_PROCESS_PRIVATE); 116 return band; 117 } 118 119 void 120 test_free_ftl_dev(struct spdk_ftl_dev *dev) 121 { 122 SPDK_CU_ASSERT_FATAL(dev != NULL); 123 spdk_thread_exit(dev->core_thread.thread); 124 free(dev->punits); 125 free(dev->bands); 126 free(dev); 127 } 128 129 void 130 test_free_ftl_band(struct ftl_band *band) 131 { 132 SPDK_CU_ASSERT_FATAL(band != NULL); 133 spdk_bit_array_free(&band->md.vld_map); 134 free(band->chunk_buf); 135 free(band->md.lba_map); 136 spdk_dma_free(band->md.dma_buf); 137 } 138 139 uint64_t 140 test_offset_from_ppa(struct ftl_ppa ppa, struct ftl_band *band) 141 { 142 struct spdk_ftl_dev *dev = band->dev; 143 unsigned int punit; 144 145 /* TODO: ftl_ppa_flatten_punit should return uint32_t */ 146 punit = ftl_ppa_flatten_punit(dev, ppa); 147 CU_ASSERT_EQUAL(ppa.chk, band->id); 148 149 return punit * ftl_dev_lbks_in_chunk(dev) + ppa.lbk; 150 } 151