Line data Source code
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 : #include "ftl_mngt.h" 8 : #include "ftl_mngt_steps.h" 9 : #include "ftl_internal.h" 10 : #include "ftl_core.h" 11 : 12 : struct ftl_mngt_p2l_md_ctx { 13 : struct ftl_mngt_process *mngt; 14 : int md_region; 15 : int md_region_min; 16 : int md_region_max; 17 : int status; 18 : }; 19 : 20 : static void ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx); 21 : 22 : void 23 0 : ftl_mngt_p2l_init_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 24 : { 25 0 : if (!ftl_p2l_ckpt_init(dev)) { 26 0 : ftl_mngt_next_step(mngt); 27 : } else { 28 0 : ftl_mngt_fail_step(mngt); 29 : } 30 0 : } 31 : 32 : void 33 0 : ftl_mngt_p2l_deinit_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 34 : { 35 0 : ftl_p2l_ckpt_deinit(dev); 36 0 : ftl_mngt_next_step(mngt); 37 0 : } 38 : 39 : static void 40 0 : ftl_p2l_wipe_md_region_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 41 : { 42 0 : struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx; 43 : 44 0 : if (status) { 45 0 : ftl_mngt_fail_step(ctx->mngt); 46 0 : return; 47 : } 48 : 49 0 : if (ctx->md_region == ctx->md_region_max) { 50 0 : ftl_mngt_next_step(ctx->mngt); 51 0 : return; 52 : } 53 : 54 0 : ctx->md_region++; 55 0 : ftl_p2l_wipe_md_region(dev, ctx); 56 : } 57 : 58 : static void 59 0 : ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx) 60 : { 61 0 : struct ftl_layout *layout = &dev->layout; 62 0 : struct ftl_md *md = layout->md[ctx->md_region]; 63 : 64 0 : assert(ctx->md_region >= ctx->md_region_min); 65 0 : assert(ctx->md_region <= ctx->md_region_max); 66 : 67 0 : if (!md) { 68 0 : ftl_mngt_fail_step(ctx->mngt); 69 0 : return; 70 : } 71 : 72 0 : md->owner.cb_ctx = ctx; 73 0 : md->cb = ftl_p2l_wipe_md_region_cb; 74 0 : ftl_md_clear(md, 0, NULL); 75 : } 76 : 77 : static void 78 0 : ftl_mngt_p2l_wipe_range(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, int min, int max) 79 : { 80 : struct ftl_mngt_p2l_md_ctx *ctx; 81 : 82 0 : if (ftl_mngt_alloc_step_ctx(mngt, sizeof(struct ftl_mngt_p2l_md_ctx))) { 83 0 : ftl_mngt_fail_step(mngt); 84 0 : return; 85 : } 86 0 : ctx = ftl_mngt_get_step_ctx(mngt); 87 0 : ctx->mngt = mngt; 88 0 : ctx->md_region_min = min; 89 0 : ctx->md_region_max = max; 90 0 : ctx->md_region = ctx->md_region_min; 91 0 : ftl_p2l_wipe_md_region(dev, ctx); 92 : } 93 : 94 : void 95 0 : ftl_mngt_p2l_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 96 : { 97 0 : ftl_mngt_p2l_wipe_range(dev, mngt, FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN, 98 : FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX); 99 0 : } 100 : 101 : void 102 0 : ftl_mngt_p2l_log_io_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 103 : { 104 : struct ftl_layout_region *region; 105 0 : bool wipe = false; 106 : 107 : /* Check if P2L IO logs are enabled and we have to clear this MD and region */ 108 0 : for (int i = FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN; i <= FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX; 109 0 : i++) { 110 0 : region = &dev->layout.region[i]; 111 0 : if (region->current.blocks) { 112 0 : wipe = true; 113 0 : break; 114 : } 115 : } 116 : 117 0 : if (!wipe) { 118 0 : ftl_mngt_skip_step(mngt); 119 0 : return; 120 : } 121 : 122 0 : ftl_mngt_p2l_wipe_range(dev, mngt, FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN, 123 : FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX); 124 : } 125 : 126 : void 127 0 : ftl_mngt_p2l_free_bufs(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 128 : { 129 : struct ftl_md *md; 130 : int region_type; 131 : 132 0 : for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 133 0 : region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; 134 0 : region_type++) { 135 0 : md = dev->layout.md[region_type]; 136 0 : assert(md); 137 0 : ftl_md_free_buf(md, ftl_md_destroy_region_flags(dev, dev->layout.region[region_type].type)); 138 : } 139 0 : ftl_mngt_next_step(mngt); 140 0 : } 141 : 142 : static void 143 0 : ftl_mngt_p2l_restore_ckpt_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 144 : { 145 0 : struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx; 146 0 : assert(ctx); 147 0 : if (status) { 148 0 : ctx->status = status; 149 : } 150 : 151 0 : if (++ctx->md_region == FTL_LAYOUT_REGION_TYPE_P2L_COUNT) { 152 0 : if (!ctx->status) { 153 0 : ftl_mngt_next_step(ctx->mngt); 154 : } else { 155 0 : ftl_mngt_fail_step(ctx->mngt); 156 : } 157 : } 158 0 : } 159 : 160 : void 161 0 : ftl_mngt_p2l_restore_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 162 : { 163 0 : struct ftl_layout *layout = &dev->layout; 164 : struct ftl_md *md; 165 : struct ftl_mngt_p2l_md_ctx *ctx; 166 : int md_region; 167 : 168 0 : if (ftl_fast_startup(dev)) { 169 0 : FTL_NOTICELOG(dev, "SHM: skipping p2l ckpt restore\n"); 170 0 : ftl_mngt_next_step(mngt); 171 0 : return; 172 : } 173 : 174 0 : if (ftl_mngt_alloc_step_ctx(mngt, sizeof(struct ftl_mngt_p2l_md_ctx))) { 175 0 : ftl_mngt_fail_step(mngt); 176 0 : return; 177 : } 178 0 : ctx = ftl_mngt_get_step_ctx(mngt); 179 0 : ctx->mngt = mngt; 180 0 : ctx->md_region = 0; 181 0 : ctx->status = 0; 182 : 183 0 : for (md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 184 0 : md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; md_region++) { 185 0 : md = layout->md[md_region]; 186 0 : assert(md); 187 0 : md->owner.cb_ctx = ctx; 188 0 : md->cb = ftl_mngt_p2l_restore_ckpt_cb; 189 0 : ftl_md_restore(md); 190 : } 191 : }