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