1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * Copyright 2023 Solidigm All Rights Reserved 4 * All rights reserved. 5 */ 6 7 #ifndef FTL_INTERNAL_H 8 #define FTL_INTERNAL_H 9 10 #include "spdk/stdinc.h" 11 #include "spdk/crc32.h" 12 #include "spdk/util.h" 13 #include "spdk/uuid.h" 14 15 #include "utils/ftl_bitmap.h" 16 #include "utils/ftl_md.h" 17 18 /* Marks address as invalid */ 19 #define FTL_ADDR_INVALID ((ftl_addr)-1) 20 /* Marks LBA as invalid */ 21 #define FTL_LBA_INVALID ((uint64_t)-1) 22 /* Smallest data unit size */ 23 #define FTL_BLOCK_SIZE 4096ULL 24 25 #define FTL_P2L_VERSION_0 0 26 #define FTL_P2L_VERSION_1 1 27 #define FTL_P2L_VERSION_2 2 28 29 #define FTL_P2L_VERSION_CURRENT FTL_P2L_VERSION_2 30 31 /* 32 * This type represents address in the ftl address space. Values from 0 to based bdev size are 33 * mapped directly to base device lbas. Values above that represent nv cache lbas. 34 */ 35 typedef uint64_t ftl_addr; 36 37 struct spdk_ftl_dev; 38 39 enum ftl_md_type { 40 FTL_MD_TYPE_BAND, 41 FTL_MD_TYPE_CHUNK 42 }; 43 44 enum ftl_band_type { 45 FTL_BAND_TYPE_GC = 1, 46 FTL_BAND_TYPE_COMPACTION 47 }; 48 49 enum ftl_md_status { 50 FTL_MD_SUCCESS, 51 /* Metadata read failure */ 52 FTL_MD_IO_FAILURE, 53 /* Invalid version */ 54 FTL_MD_INVALID_VER, 55 /* UUID doesn't match */ 56 FTL_MD_NO_MD, 57 /* UUID and version matches but CRC doesn't */ 58 FTL_MD_INVALID_CRC, 59 /* Vld or p2l map size doesn't match */ 60 FTL_MD_INVALID_SIZE 61 }; 62 63 struct ftl_p2l_map_entry { 64 uint64_t lba; 65 uint64_t seq_id; 66 }; 67 68 /* Number of p2l entries that could be stored in a single block for bands */ 69 #define FTL_NUM_LBA_IN_BLOCK (FTL_BLOCK_SIZE / sizeof(struct ftl_p2l_map_entry)) 70 71 /* 72 * Mapping of physical (actual location on disk) to logical (user's POV) addresses. Used in two main scenarios: 73 * - during relocation FTL needs to pin L2P pages (this allows to check which pages to pin) and move still valid blocks 74 * (valid map allows for preliminary elimination of invalid physical blocks, but user data could invalidate a location 75 * during read/write operation, so actual comparison against L2P needs to be done) 76 * - After dirty shutdown the state of the L2P is unknown and needs to be rebuilt - it is done by applying all P2L, taking 77 * into account ordering of user writes 78 */ 79 struct ftl_p2l_map { 80 /* Number of valid LBAs */ 81 size_t num_valid; 82 83 /* P2L map's reference count, prevents premature release of resources during dirty shutdown recovery for open bands */ 84 size_t ref_cnt; 85 86 /* Bitmap of valid LBAs */ 87 struct ftl_bitmap *valid; 88 89 /* P2L map (only valid for open/relocating bands) */ 90 union { 91 struct ftl_p2l_map_entry *band_map; 92 void *chunk_map; 93 }; 94 95 /* DMA buffer for region's metadata entry */ 96 union { 97 struct ftl_band_md *band_dma_md; 98 99 struct ftl_nv_cache_chunk_md *chunk_dma_md; 100 }; 101 102 /* P2L checkpointing region */ 103 struct ftl_p2l_ckpt *p2l_ckpt; 104 }; 105 106 struct ftl_p2l_sync_ctx { 107 struct ftl_band *band; 108 uint64_t xfer_start; 109 uint64_t xfer_end; 110 int md_region; 111 }; 112 113 struct ftl_p2l_ckpt_page { 114 struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK]; 115 }; 116 117 struct ftl_p2l_ckpt_page_no_vss { 118 union ftl_md_vss metadata; 119 struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK - sizeof(union ftl_md_vss) / sizeof( 120 struct ftl_p2l_map_entry)]; 121 } __attribute__((packed)); 122 SPDK_STATIC_ASSERT(sizeof(struct ftl_p2l_ckpt_page_no_vss) == FTL_BLOCK_SIZE, 123 "ftl_p2l_ckpt_page_no_vss incorrect size"); 124 125 #define FTL_NUM_P2L_ENTRIES_NO_VSS (SPDK_COUNTOF_MEMBER(struct ftl_p2l_ckpt_page_no_vss, map)) 126 127 #define FTL_TRIM_LOG_VERSION_0 0 128 #define FTL_TRIM_LOG_VERSION_1 1 129 #define FTL_TRIM_LOG_VERSION_CURRENT FTL_TRIM_LOG_VERSION_1 130 131 struct ftl_trim_log { 132 union ftl_md_vss hdr; 133 char reserved[FTL_BLOCK_SIZE - sizeof(union ftl_md_vss)]; 134 }; 135 SPDK_STATIC_ASSERT(sizeof(struct ftl_trim_log) == FTL_BLOCK_SIZE, "Invalid trim log page size"); 136 137 struct ftl_p2l_ckpt; 138 struct ftl_band; 139 struct spdk_ftl_dev; 140 struct ftl_mngt_process; 141 struct ftl_rq; 142 143 int ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev); 144 145 void ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev); 146 147 void ftl_p2l_ckpt_issue(struct ftl_rq *rq); 148 149 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev); 150 151 struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev, 152 uint32_t region_type); 153 154 void ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt); 155 156 enum ftl_layout_region_type ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt); 157 158 #if defined(DEBUG) 159 void ftl_p2l_validate_ckpt(struct ftl_band *band); 160 #else 161 static inline void 162 ftl_p2l_validate_ckpt(struct ftl_band *band) 163 { 164 } 165 #endif 166 167 uint64_t ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region); 168 169 int ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id); 170 171 int ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band); 172 173 void ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band); 174 175 void ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt); 176 177 struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev); 178 179 void ftl_reloc_free(struct ftl_reloc *reloc); 180 181 void ftl_reloc(struct ftl_reloc *reloc); 182 183 void ftl_reloc_halt(struct ftl_reloc *reloc); 184 185 void ftl_reloc_resume(struct ftl_reloc *reloc); 186 187 bool ftl_reloc_is_halted(const struct ftl_reloc *reloc); 188 189 #endif /* FTL_INTERNAL_H */ 190