Branch data 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 : 27 : ftl_mngt_p2l_init_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
24 : : {
25 [ + - ]: 27 : if (!ftl_p2l_ckpt_init(dev)) {
26 : 27 : ftl_mngt_next_step(mngt);
27 : 0 : } else {
28 : 0 : ftl_mngt_fail_step(mngt);
29 : : }
30 : 27 : }
31 : :
32 : : void
33 : 27 : ftl_mngt_p2l_deinit_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
34 : : {
35 : 27 : ftl_p2l_ckpt_deinit(dev);
36 : 27 : ftl_mngt_next_step(mngt);
37 : 27 : }
38 : :
39 : : static void
40 : 24 : ftl_p2l_wipe_md_region_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
41 : : {
42 [ # # # # : 24 : struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx;
# # ]
43 : :
44 [ - + ]: 24 : if (status) {
45 [ # # # # ]: 0 : ftl_mngt_fail_step(ctx->mngt);
46 : 0 : return;
47 : : }
48 : :
49 [ + + # # : 24 : if (ctx->md_region == ctx->md_region_max) {
# # # # #
# ]
50 [ # # # # ]: 6 : ftl_mngt_next_step(ctx->mngt);
51 : 6 : return;
52 : : }
53 : :
54 [ # # # # ]: 18 : ctx->md_region++;
55 : 18 : ftl_p2l_wipe_md_region(dev, ctx);
56 : 0 : }
57 : :
58 : : static void
59 : 24 : ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx)
60 : : {
61 [ # # ]: 24 : struct ftl_layout *layout = &dev->layout;
62 [ # # # # : 24 : struct ftl_md *md = layout->md[ctx->md_region];
# # # # #
# ]
63 : :
64 [ - + # # : 24 : assert(ctx->md_region >= ctx->md_region_min);
# # # # #
# # # ]
65 [ - + # # : 24 : assert(ctx->md_region <= ctx->md_region_max);
# # # # #
# # # ]
66 : :
67 [ - + ]: 24 : if (!md) {
68 [ # # # # ]: 0 : ftl_mngt_fail_step(ctx->mngt);
69 : 0 : return;
70 : : }
71 : :
72 [ # # # # : 24 : md->owner.cb_ctx = ctx;
# # ]
73 [ # # # # ]: 24 : md->cb = ftl_p2l_wipe_md_region_cb;
74 : 24 : ftl_md_clear(md, 0, NULL);
75 : 0 : }
76 : :
77 : : static void
78 : 6 : 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 [ - + ]: 6 : 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 : 6 : ctx = ftl_mngt_get_step_ctx(mngt);
87 [ # # # # ]: 6 : ctx->mngt = mngt;
88 [ # # # # ]: 6 : ctx->md_region_min = min;
89 [ # # # # ]: 6 : ctx->md_region_max = max;
90 [ # # # # : 6 : ctx->md_region = ctx->md_region_min;
# # # # ]
91 : 6 : ftl_p2l_wipe_md_region(dev, ctx);
92 : 0 : }
93 : :
94 : : void
95 : 6 : ftl_mngt_p2l_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
96 : : {
97 : 6 : ftl_mngt_p2l_wipe_range(dev, mngt, FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN,
98 : : FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX);
99 : 6 : }
100 : :
101 : : void
102 : 6 : ftl_mngt_p2l_log_io_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
103 : : {
104 : : struct ftl_layout_region *region;
105 : 6 : bool wipe = false;
106 : :
107 : : /* Check if P2L IO logs are enabled and we have to clear this MD and region */
108 [ + + ]: 18 : for (int i = FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN; i <= FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX;
109 [ # # ]: 12 : i++) {
110 [ # # # # : 12 : region = &dev->layout.region[i];
# # # # ]
111 [ - + # # : 12 : if (region->current.blocks) {
# # # # ]
112 : 0 : wipe = true;
113 : 0 : break;
114 : : }
115 : 0 : }
116 : :
117 [ + - # # ]: 6 : if (!wipe) {
118 : 6 : ftl_mngt_skip_step(mngt);
119 : 6 : 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 : 0 : }
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 : 0 : }
139 : 0 : ftl_mngt_next_step(mngt);
140 : 0 : }
141 : :
142 : : static void
143 : 72 : ftl_mngt_p2l_restore_ckpt_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
144 : : {
145 [ # # # # : 72 : struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx;
# # ]
146 [ - + # # ]: 72 : assert(ctx);
147 [ - + ]: 72 : if (status) {
148 [ # # # # ]: 0 : ctx->status = status;
149 : 0 : }
150 : :
151 [ + + # # : 72 : if (++ctx->md_region == FTL_LAYOUT_REGION_TYPE_P2L_COUNT) {
# # ]
152 [ + - # # : 18 : if (!ctx->status) {
# # ]
153 [ # # # # ]: 18 : ftl_mngt_next_step(ctx->mngt);
154 : 0 : } else {
155 [ # # # # ]: 0 : ftl_mngt_fail_step(ctx->mngt);
156 : : }
157 : 0 : }
158 : 72 : }
159 : :
160 : : void
161 : 21 : ftl_mngt_p2l_restore_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
162 : : {
163 [ # # ]: 21 : 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 [ + + ]: 21 : if (ftl_fast_startup(dev)) {
169 [ + - # # : 3 : FTL_NOTICELOG(dev, "SHM: skipping p2l ckpt restore\n");
# # # # ]
170 : 3 : ftl_mngt_next_step(mngt);
171 : 3 : return;
172 : : }
173 : :
174 [ - + ]: 18 : 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 : 18 : ctx = ftl_mngt_get_step_ctx(mngt);
179 [ # # # # ]: 18 : ctx->mngt = mngt;
180 [ # # # # ]: 18 : ctx->md_region = 0;
181 [ # # # # ]: 18 : ctx->status = 0;
182 : :
183 [ # # ]: 18 : for (md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
184 [ + + ]: 90 : md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; md_region++) {
185 [ # # # # : 72 : md = layout->md[md_region];
# # ]
186 [ - + # # ]: 72 : assert(md);
187 [ # # # # : 72 : md->owner.cb_ctx = ctx;
# # ]
188 [ # # # # ]: 72 : md->cb = ftl_mngt_p2l_restore_ckpt_cb;
189 : 72 : ftl_md_restore(md);
190 : 0 : }
191 : 0 : }
|