1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "ftl_core.h" 7 #include "ftl_utils.h" 8 #include "ftl_mngt.h" 9 #include "ftl_mngt_steps.h" 10 #include "ftl_band.h" 11 #include "ftl_internal.h" 12 #include "ftl_nv_cache.h" 13 #include "ftl_debug.h" 14 15 void 16 ftl_mngt_check_conf(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 17 { 18 if (ftl_conf_is_valid(&dev->conf)) { 19 ftl_mngt_next_step(mngt); 20 } else { 21 ftl_mngt_fail_step(mngt); 22 } 23 } 24 25 static int 26 init_p2l_map_pool(struct spdk_ftl_dev *dev) 27 { 28 size_t p2l_pool_el_blks = spdk_divide_round_up(ftl_p2l_map_pool_elem_size(dev), FTL_BLOCK_SIZE); 29 30 dev->p2l_pool = ftl_mempool_create(P2L_MEMPOOL_SIZE, 31 p2l_pool_el_blks * FTL_BLOCK_SIZE, 32 FTL_BLOCK_SIZE, 33 SPDK_ENV_SOCKET_ID_ANY); 34 if (!dev->p2l_pool) { 35 return -ENOMEM; 36 } 37 38 return 0; 39 } 40 41 static int 42 init_band_md_pool(struct spdk_ftl_dev *dev) 43 { 44 dev->band_md_pool = ftl_mempool_create(P2L_MEMPOOL_SIZE, 45 sizeof(struct ftl_band_md), 46 FTL_BLOCK_SIZE, 47 SPDK_ENV_SOCKET_ID_ANY); 48 if (!dev->band_md_pool) { 49 return -ENOMEM; 50 } 51 52 return 0; 53 } 54 55 void 56 ftl_mngt_init_mem_pools(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 57 { 58 if (init_p2l_map_pool(dev)) { 59 ftl_mngt_fail_step(mngt); 60 } 61 62 if (init_band_md_pool(dev)) { 63 ftl_mngt_fail_step(mngt); 64 } 65 66 ftl_mngt_next_step(mngt); 67 } 68 69 void 70 ftl_mngt_deinit_mem_pools(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 71 { 72 if (dev->p2l_pool) { 73 ftl_mempool_destroy(dev->p2l_pool); 74 dev->p2l_pool = NULL; 75 } 76 77 if (dev->band_md_pool) { 78 ftl_mempool_destroy(dev->band_md_pool); 79 dev->band_md_pool = NULL; 80 } 81 82 ftl_mngt_next_step(mngt); 83 } 84 85 void 86 ftl_mngt_init_nv_cache(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 87 { 88 if (ftl_nv_cache_init(dev)) { 89 FTL_ERRLOG(dev, "Unable to initialize persistent cache\n"); 90 ftl_mngt_fail_step(mngt); 91 return; 92 } 93 94 ftl_mngt_next_step(mngt); 95 } 96 97 void 98 ftl_mngt_deinit_nv_cache(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 99 { 100 ftl_nv_cache_deinit(dev); 101 ftl_mngt_next_step(mngt); 102 } 103 104 static void 105 user_clear_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 106 { 107 struct ftl_mngt_process *mngt = md->owner.cb_ctx; 108 109 if (status) { 110 FTL_ERRLOG(ftl_mngt_get_dev(mngt), "FTL NV Cache: ERROR of clearing user cache data\n"); 111 ftl_mngt_fail_step(mngt); 112 } else { 113 ftl_mngt_next_step(mngt); 114 } 115 } 116 117 void 118 ftl_mngt_scrub_nv_cache(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 119 { 120 struct ftl_layout_region *region = &dev->layout.region[FTL_LAYOUT_REGION_TYPE_DATA_NVC]; 121 struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_DATA_NVC]; 122 union ftl_md_vss vss; 123 124 FTL_NOTICELOG(dev, "First startup needs to scrub nv cache data region, this may take some time.\n"); 125 FTL_NOTICELOG(dev, "Scrubbing %lluGiB\n", region->current.blocks * FTL_BLOCK_SIZE / GiB); 126 127 /* Need to scrub user data, so in case of dirty shutdown the recovery won't 128 * pull in data during open chunks recovery from any previous instance 129 */ 130 md->cb = user_clear_cb; 131 md->owner.cb_ctx = mngt; 132 133 vss.version.md_version = region->current.version; 134 vss.nv_cache.lba = FTL_ADDR_INVALID; 135 ftl_md_clear(md, 0, &vss); 136 } 137 138 void 139 ftl_mngt_finalize_startup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 140 { 141 dev->initialized = 1; 142 dev->sb_shm->shm_ready = true; 143 144 ftl_writer_resume(&dev->writer_user); 145 ftl_writer_resume(&dev->writer_gc); 146 ftl_nv_cache_resume(&dev->nv_cache); 147 148 ftl_mngt_next_step(mngt); 149 } 150 151 void 152 ftl_mngt_start_core_poller(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 153 { 154 dev->core_poller = SPDK_POLLER_REGISTER(ftl_core_poller, dev, 0); 155 if (!dev->core_poller) { 156 FTL_ERRLOG(dev, "Unable to register core poller\n"); 157 ftl_mngt_fail_step(mngt); 158 return; 159 } 160 161 ftl_mngt_next_step(mngt); 162 } 163 164 void 165 ftl_mngt_stop_core_poller(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 166 { 167 dev->halt = true; 168 169 if (dev->core_poller) { 170 ftl_mngt_continue_step(mngt); 171 } else { 172 ftl_mngt_next_step(mngt); 173 } 174 } 175 176 void 177 ftl_mngt_dump_stats(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 178 { 179 ftl_dev_dump_bands(dev); 180 ftl_dev_dump_stats(dev); 181 ftl_mngt_next_step(mngt); 182 } 183