1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "ftl_mngt.h" 7 #include "ftl_mngt_steps.h" 8 #include "ftl_internal.h" 9 #include "ftl_core.h" 10 11 struct ftl_mngt_p2l_md_ctx { 12 struct ftl_mngt_process *mngt; 13 int md_region; 14 int status; 15 }; 16 17 static void ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx); 18 19 void 20 ftl_mngt_p2l_init_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 21 { 22 if (!ftl_p2l_ckpt_init(dev)) { 23 ftl_mngt_next_step(mngt); 24 } else { 25 ftl_mngt_fail_step(mngt); 26 } 27 } 28 29 void 30 ftl_mngt_p2l_deinit_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 31 { 32 ftl_p2l_ckpt_deinit(dev); 33 ftl_mngt_next_step(mngt); 34 } 35 36 static void 37 ftl_p2l_wipe_md_region_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 38 { 39 struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx; 40 41 if (status) { 42 ftl_mngt_fail_step(ctx->mngt); 43 return; 44 } 45 46 if (ctx->md_region == FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX) { 47 ftl_mngt_next_step(ctx->mngt); 48 return; 49 } 50 51 ctx->md_region++; 52 ftl_p2l_wipe_md_region(dev, ctx); 53 } 54 55 static void 56 ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx) 57 { 58 struct ftl_layout *layout = &dev->layout; 59 struct ftl_md *md = layout->md[ctx->md_region]; 60 61 assert(ctx->md_region >= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN); 62 assert(ctx->md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX); 63 64 if (!md) { 65 ftl_mngt_fail_step(ctx->mngt); 66 return; 67 } 68 69 md->owner.cb_ctx = ctx; 70 md->cb = ftl_p2l_wipe_md_region_cb; 71 ftl_md_persist(md); 72 } 73 74 void 75 ftl_mngt_p2l_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 76 { 77 struct ftl_mngt_p2l_md_ctx *ctx; 78 79 if (ftl_mngt_alloc_step_ctx(mngt, sizeof(struct ftl_mngt_p2l_md_ctx))) { 80 ftl_mngt_fail_step(mngt); 81 return; 82 } 83 ctx = ftl_mngt_get_step_ctx(mngt); 84 ctx->mngt = mngt; 85 ctx->md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 86 ftl_p2l_wipe_md_region(dev, ctx); 87 } 88 89 void 90 ftl_mngt_p2l_free_bufs(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 91 { 92 struct ftl_md *md; 93 int region_type; 94 95 for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 96 region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; 97 region_type++) { 98 md = dev->layout.md[region_type]; 99 assert(md); 100 ftl_md_free_buf(md, ftl_md_destroy_region_flags(dev, dev->layout.region[region_type].type)); 101 } 102 ftl_mngt_next_step(mngt); 103 } 104 105 static void 106 ftl_mngt_p2l_restore_ckpt_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 107 { 108 struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx; 109 assert(ctx); 110 if (status) { 111 ctx->status = status; 112 } 113 114 if (++ctx->md_region == FTL_LAYOUT_REGION_TYPE_P2L_COUNT) { 115 if (!ctx->status) { 116 ftl_mngt_next_step(ctx->mngt); 117 } else { 118 ftl_mngt_fail_step(ctx->mngt); 119 } 120 } 121 } 122 123 void 124 ftl_mngt_p2l_restore_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 125 { 126 struct ftl_layout *layout = &dev->layout; 127 struct ftl_md *md; 128 struct ftl_mngt_p2l_md_ctx *ctx; 129 int md_region; 130 131 if (ftl_fast_startup(dev)) { 132 FTL_NOTICELOG(dev, "SHM: skipping p2l ckpt restore\n"); 133 ftl_mngt_next_step(mngt); 134 return; 135 } 136 137 if (ftl_mngt_alloc_step_ctx(mngt, sizeof(struct ftl_mngt_p2l_md_ctx))) { 138 ftl_mngt_fail_step(mngt); 139 return; 140 } 141 ctx = ftl_mngt_get_step_ctx(mngt); 142 ctx->mngt = mngt; 143 ctx->md_region = 0; 144 ctx->status = 0; 145 146 for (md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 147 md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; md_region++) { 148 md = layout->md[md_region]; 149 assert(md); 150 md->owner.cb_ctx = ctx; 151 md->cb = ftl_mngt_p2l_restore_ckpt_cb; 152 ftl_md_restore(md); 153 } 154 } 155