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 "spdk/bdev_module.h"
8 #include "spdk/crc32.h"
9
10 #include "ftl_internal.h"
11 #include "ftl_band.h"
12 #include "ftl_core.h"
13 #include "ftl_layout.h"
14 #include "ftl_nv_cache_io.h"
15 #include "ftl_writer.h"
16 #include "mngt/ftl_mngt.h"
17
18 struct ftl_p2l_ckpt {
19 TAILQ_ENTRY(ftl_p2l_ckpt) link;
20 union ftl_md_vss *vss_md_page;
21 struct ftl_md *md;
22 struct ftl_layout_region *layout_region;
23 uint64_t num_pages;
24 uint64_t pages_per_xfer;
25
26 #if defined(DEBUG)
27 uint64_t dbg_bmp_sz;
28 void *dbg_bmp;
29 struct ftl_bitmap *bmp;
30 #endif
31 };
32
33 static struct ftl_p2l_ckpt *
ftl_p2l_ckpt_new(struct spdk_ftl_dev * dev,int region_type)34 ftl_p2l_ckpt_new(struct spdk_ftl_dev *dev, int region_type)
35 {
36 struct ftl_p2l_ckpt *ckpt;
37 struct ftl_layout_region *region = ftl_layout_region_get(dev, region_type);
38
39 ckpt = calloc(1, sizeof(struct ftl_p2l_ckpt));
40 if (!ckpt) {
41 return NULL;
42 }
43
44 ckpt->layout_region = region;
45 ckpt->md = dev->layout.md[region_type];
46 ckpt->pages_per_xfer = dev->layout.p2l.pages_per_xfer;
47 ckpt->num_pages = dev->layout.p2l.ckpt_pages;
48 if (dev->nv_cache.md_size) {
49 ckpt->vss_md_page = ftl_md_vss_buf_alloc(region, region->num_entries);
50 if (!ckpt->vss_md_page) {
51 free(ckpt);
52 return NULL;
53 }
54 }
55
56 #if defined(DEBUG)
57 /* The bitmap size must be a multiple of word size (8b) - round up */
58 ckpt->dbg_bmp_sz = spdk_divide_round_up(ckpt->num_pages, 8);
59
60 ckpt->dbg_bmp = calloc(1, ckpt->dbg_bmp_sz);
61 assert(ckpt->dbg_bmp);
62 ckpt->bmp = ftl_bitmap_create(ckpt->dbg_bmp, ckpt->dbg_bmp_sz);
63 assert(ckpt->bmp);
64 #endif
65
66 return ckpt;
67 }
68
69 static void
ftl_p2l_ckpt_destroy(struct ftl_p2l_ckpt * ckpt)70 ftl_p2l_ckpt_destroy(struct ftl_p2l_ckpt *ckpt)
71 {
72 #if defined(DEBUG)
73 ftl_bitmap_destroy(ckpt->bmp);
74 free(ckpt->dbg_bmp);
75 #endif
76 spdk_dma_free(ckpt->vss_md_page);
77 free(ckpt);
78 }
79
80 int
ftl_p2l_ckpt_init(struct spdk_ftl_dev * dev)81 ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev)
82 {
83 int region_type;
84 struct ftl_p2l_ckpt *ckpt;
85
86 TAILQ_INIT(&dev->p2l_ckpt.free);
87 TAILQ_INIT(&dev->p2l_ckpt.inuse);
88 for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN;
89 region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX;
90 region_type++) {
91 ckpt = ftl_p2l_ckpt_new(dev, region_type);
92 if (!ckpt) {
93 return -1;
94 }
95 TAILQ_INSERT_TAIL(&dev->p2l_ckpt.free, ckpt, link);
96 }
97 return 0;
98 }
99
100 void
ftl_p2l_ckpt_deinit(struct spdk_ftl_dev * dev)101 ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev)
102 {
103 struct ftl_p2l_ckpt *ckpt, *ckpt_next;
104
105 TAILQ_FOREACH_SAFE(ckpt, &dev->p2l_ckpt.free, link, ckpt_next) {
106 TAILQ_REMOVE(&dev->p2l_ckpt.free, ckpt, link);
107 ftl_p2l_ckpt_destroy(ckpt);
108 }
109
110 TAILQ_FOREACH_SAFE(ckpt, &dev->p2l_ckpt.inuse, link, ckpt_next) {
111 TAILQ_REMOVE(&dev->p2l_ckpt.inuse, ckpt, link);
112 ftl_p2l_ckpt_destroy(ckpt);
113 }
114 }
115
116 struct ftl_p2l_ckpt *
ftl_p2l_ckpt_acquire(struct spdk_ftl_dev * dev)117 ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev)
118 {
119 struct ftl_p2l_ckpt *ckpt;
120
121 ckpt = TAILQ_FIRST(&dev->p2l_ckpt.free);
122 assert(ckpt);
123 TAILQ_REMOVE(&dev->p2l_ckpt.free, ckpt, link);
124 TAILQ_INSERT_TAIL(&dev->p2l_ckpt.inuse, ckpt, link);
125 return ckpt;
126 }
127
128 void
ftl_p2l_ckpt_release(struct spdk_ftl_dev * dev,struct ftl_p2l_ckpt * ckpt)129 ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt)
130 {
131 assert(ckpt);
132 #if defined(DEBUG)
133 memset(ckpt->dbg_bmp, 0, ckpt->dbg_bmp_sz);
134 #endif
135 TAILQ_REMOVE(&dev->p2l_ckpt.inuse, ckpt, link);
136 TAILQ_INSERT_TAIL(&dev->p2l_ckpt.free, ckpt, link);
137 }
138
139 static void
ftl_p2l_ckpt_issue_end(int status,void * arg)140 ftl_p2l_ckpt_issue_end(int status, void *arg)
141 {
142 struct ftl_rq *rq = arg;
143 assert(rq);
144
145 if (status) {
146 #ifdef SPDK_FTL_RETRY_ON_ERROR
147 /* retry */
148 ftl_md_persist_entry_retry(&rq->md_persist_entry_ctx);
149 return;
150 #else
151 ftl_abort();
152 #endif
153 }
154
155 assert(rq->io.band->queue_depth > 0);
156 rq->io.band->queue_depth--;
157
158 rq->owner.cb(rq);
159 }
160
161 void
ftl_p2l_ckpt_issue(struct ftl_rq * rq)162 ftl_p2l_ckpt_issue(struct ftl_rq *rq)
163 {
164 struct ftl_rq_entry *iter = rq->entries;
165 struct spdk_ftl_dev *dev = rq->dev;
166 ftl_addr addr = rq->io.addr;
167 struct ftl_p2l_ckpt *ckpt = NULL;
168 struct ftl_p2l_ckpt_page_no_vss *map_page;
169 struct ftl_band *band;
170 uint64_t band_offs, p2l_map_page_no, cur_page, i, j;
171
172 assert(rq);
173 band = rq->io.band;
174 ckpt = band->p2l_map.p2l_ckpt;
175 assert(ckpt);
176 assert(rq->num_blocks == dev->xfer_size);
177
178 /* Derive the P2L map page no */
179 band_offs = ftl_band_block_offset_from_addr(band, rq->io.addr);
180 p2l_map_page_no = band_offs / dev->xfer_size * ckpt->pages_per_xfer;
181 assert(p2l_map_page_no < ckpt->num_pages);
182
183 /* Get the corresponding P2L map page - the underlying stored data has the same entries as in the end metadata of band P2L (ftl_p2l_map_entry),
184 * however we're interested in a whole page (4KiB) worth of content and submit it in two requests with additional metadata
185 */
186 map_page = ftl_md_get_buffer(ckpt->md);
187 assert(map_page);
188 map_page += p2l_map_page_no;
189 i = 0;
190 for (cur_page = 0; cur_page < ckpt->pages_per_xfer; cur_page++) {
191 struct ftl_p2l_ckpt_page_no_vss *page = map_page + cur_page;
192 /* Update the band P2L map */
193 for (j = 0; i < rq->num_blocks && j < FTL_NUM_P2L_ENTRIES_NO_VSS; i++, iter++, j++) {
194 if (iter->lba != FTL_LBA_INVALID) {
195 /* This is compaction or reloc */
196 assert(!ftl_addr_in_nvc(rq->dev, addr));
197 ftl_band_set_p2l(band, iter->lba, addr, iter->seq_id);
198 }
199 page->map[j].lba = iter->lba;
200 page->map[j].seq_id = iter->seq_id;
201 addr = ftl_band_next_addr(band, addr, 1);
202 }
203
204 /* Set up the md */
205 page->metadata.p2l_ckpt.seq_id = band->md->seq;
206 page->metadata.p2l_ckpt.count = j;
207
208 #if defined(DEBUG)
209 ftl_bitmap_set(ckpt->bmp, p2l_map_page_no + cur_page);
210 #endif
211 page->metadata.p2l_ckpt.p2l_checksum = spdk_crc32c_update(page->map,
212 FTL_NUM_P2L_ENTRIES_NO_VSS * sizeof(struct ftl_p2l_map_entry), 0);
213 }
214 /* Save the P2L map entry */
215 ftl_md_persist_entries(ckpt->md, p2l_map_page_no, ckpt->pages_per_xfer, map_page, NULL,
216 ftl_p2l_ckpt_issue_end, rq, &rq->md_persist_entry_ctx);
217 }
218
219 #if defined(DEBUG)
220 static void
ftl_p2l_validate_pages(struct ftl_band * band,struct ftl_p2l_ckpt * ckpt,uint64_t page_begin,uint64_t page_end,bool val)221 ftl_p2l_validate_pages(struct ftl_band *band, struct ftl_p2l_ckpt *ckpt,
222 uint64_t page_begin, uint64_t page_end, bool val)
223 {
224 uint64_t page_no;
225
226 for (page_no = page_begin; page_no < page_end; page_no++) {
227 assert(ftl_bitmap_get(ckpt->bmp, page_no) == val);
228 }
229 }
230
231 void
ftl_p2l_validate_ckpt(struct ftl_band * band)232 ftl_p2l_validate_ckpt(struct ftl_band *band)
233 {
234 struct ftl_p2l_ckpt *ckpt = band->p2l_map.p2l_ckpt;
235 uint64_t num_blks_tail_md = ftl_tail_md_num_blocks(band->dev);
236 uint64_t num_pages_tail_md;
237
238 if (!ckpt) {
239 return;
240 }
241
242 num_pages_tail_md = num_blks_tail_md / band->dev->xfer_size * ckpt->pages_per_xfer;
243
244 assert(num_blks_tail_md % band->dev->xfer_size == 0);
245
246 /* all data pages written */
247 ftl_p2l_validate_pages(band, ckpt,
248 0, ckpt->num_pages - num_pages_tail_md, true);
249
250 /* tail md pages not written */
251 ftl_p2l_validate_pages(band, ckpt, ckpt->num_pages - num_pages_tail_md,
252 ckpt->num_pages, false);
253 }
254 #endif
255
256 static struct ftl_band *
ftl_get_band_from_region(struct spdk_ftl_dev * dev,enum ftl_layout_region_type type)257 ftl_get_band_from_region(struct spdk_ftl_dev *dev, enum ftl_layout_region_type type)
258 {
259 struct ftl_band *band = NULL;
260 uint64_t i;
261
262 assert(type >= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN);
263 assert(type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX);
264
265 for (i = 0; i < ftl_get_num_bands(dev); i++) {
266 band = &dev->bands[i];
267 if ((band->md->state == FTL_BAND_STATE_OPEN ||
268 band->md->state == FTL_BAND_STATE_FULL) &&
269 band->md->p2l_md_region == type) {
270 return band;
271 }
272 }
273
274 return NULL;
275 }
276
277 static void ftl_mngt_persist_band_p2l(struct ftl_mngt_process *mngt, struct ftl_p2l_sync_ctx *ctx);
278
279 static void
ftl_p2l_ckpt_persist_end(int status,void * arg)280 ftl_p2l_ckpt_persist_end(int status, void *arg)
281 {
282 struct ftl_mngt_process *mngt = arg;
283 struct ftl_p2l_sync_ctx *ctx;
284
285 assert(mngt);
286
287 if (status) {
288 ftl_mngt_fail_step(mngt);
289 return;
290 }
291
292 ctx = ftl_mngt_get_step_ctx(mngt);
293 ctx->xfer_start++;
294
295 if (ctx->xfer_start == ctx->xfer_end) {
296 ctx->md_region++;
297 ftl_mngt_continue_step(mngt);
298 } else {
299 ftl_mngt_persist_band_p2l(mngt, ctx);
300 }
301 }
302
303 static void
ftl_mngt_persist_band_p2l(struct ftl_mngt_process * mngt,struct ftl_p2l_sync_ctx * ctx)304 ftl_mngt_persist_band_p2l(struct ftl_mngt_process *mngt, struct ftl_p2l_sync_ctx *ctx)
305 {
306 struct ftl_band *band = ctx->band;
307 struct ftl_p2l_ckpt_page_no_vss *map_page;
308 struct ftl_p2l_map_entry *band_entries;
309 struct ftl_p2l_ckpt *ckpt;
310 struct spdk_ftl_dev *dev = band->dev;
311 uint64_t cur_page;
312 uint64_t lbas_synced = 0;
313
314 ckpt = band->p2l_map.p2l_ckpt;
315
316 map_page = ftl_md_get_buffer(ckpt->md);
317 assert(map_page);
318
319 map_page += ctx->xfer_start * ckpt->pages_per_xfer;
320
321 for (cur_page = 0; cur_page < ckpt->pages_per_xfer; cur_page++) {
322 struct ftl_p2l_ckpt_page_no_vss *page = map_page + cur_page;
323 uint64_t lbas_to_copy = spdk_min(FTL_NUM_P2L_ENTRIES_NO_VSS, dev->xfer_size - lbas_synced);
324
325 band_entries = band->p2l_map.band_map + ctx->xfer_start * dev->xfer_size + lbas_synced;
326 memcpy(page->map, band_entries, lbas_to_copy * sizeof(struct ftl_p2l_map_entry));
327
328 page->metadata.p2l_ckpt.seq_id = band->md->seq;
329 page->metadata.p2l_ckpt.p2l_checksum = spdk_crc32c_update(page->map,
330 FTL_NUM_P2L_ENTRIES_NO_VSS * sizeof(struct ftl_p2l_map_entry), 0);
331 page->metadata.p2l_ckpt.count = lbas_to_copy;
332 lbas_synced += lbas_to_copy;
333 }
334
335 assert(lbas_synced == dev->xfer_size);
336 /* Save the P2L map entry */
337 ftl_md_persist_entries(ckpt->md, ctx->xfer_start * ckpt->pages_per_xfer, ckpt->pages_per_xfer,
338 map_page, NULL,
339 ftl_p2l_ckpt_persist_end, mngt, &band->md_persist_entry_ctx);
340 }
341
342 void
ftl_mngt_persist_bands_p2l(struct ftl_mngt_process * mngt)343 ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt)
344 {
345 struct ftl_p2l_sync_ctx *ctx = ftl_mngt_get_step_ctx(mngt);
346 struct ftl_band *band;
347 uint64_t band_offs, num_xfers;
348
349 if (ctx->md_region > FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX) {
350 ftl_mngt_next_step(mngt);
351 return;
352 }
353
354 band = ftl_get_band_from_region(ftl_mngt_get_dev(mngt), ctx->md_region);
355
356 /* No band has the md region assigned (shutdown happened before next_band was assigned) */
357 if (!band) {
358 ctx->xfer_start = 0;
359 ctx->xfer_end = 0;
360 ctx->md_region++;
361 ftl_mngt_continue_step(mngt);
362 return;
363 }
364
365 band_offs = ftl_band_block_offset_from_addr(band, band->md->iter.addr);
366 num_xfers = band_offs / band->dev->xfer_size;
367
368 ctx->xfer_start = 0;
369 ctx->xfer_end = num_xfers;
370 ctx->band = band;
371
372 /* Band wasn't written to - no need to sync its P2L */
373 if (ctx->xfer_end == 0) {
374 ctx->md_region++;
375 ftl_mngt_continue_step(mngt);
376 return;
377 }
378
379 ftl_mngt_persist_band_p2l(mngt, ctx);
380 }
381
382 uint64_t
ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev * dev,int md_region)383 ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region)
384 {
385 struct ftl_layout *layout = &dev->layout;
386 struct ftl_md *md = layout->md[md_region];
387 struct ftl_p2l_ckpt_page_no_vss *page = ftl_md_get_buffer(md);
388 uint64_t page_no, seq_id = 0;
389
390 for (page_no = 0; page_no < layout->p2l.ckpt_pages; page_no++, page++) {
391 if (seq_id < page->metadata.p2l_ckpt.seq_id) {
392 seq_id = page->metadata.p2l_ckpt.seq_id;
393 }
394 }
395 return seq_id;
396 }
397
398 int
ftl_mngt_p2l_ckpt_restore(struct ftl_band * band,uint32_t md_region,uint64_t seq_id)399 ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id)
400 {
401 struct ftl_layout *layout = &band->dev->layout;
402 struct ftl_md *md = layout->md[md_region];
403 struct ftl_p2l_ckpt_page_no_vss *page = ftl_md_get_buffer(md);
404 struct ftl_p2l_map_entry *band_entries;
405 struct spdk_ftl_dev *dev = band->dev;
406 uint64_t page_no, page_max = 0, xfer_count, lbas_synced;
407 uint64_t pages_per_xfer = spdk_divide_round_up(dev->xfer_size, FTL_NUM_P2L_ENTRIES_NO_VSS);
408 bool page_found = false;
409
410 assert(band->md->p2l_md_region == md_region);
411 if (band->md->p2l_md_region != md_region) {
412 return -EINVAL;
413 }
414
415 assert(band->md->seq == seq_id);
416 if (band->md->seq != seq_id) {
417 return -EINVAL;
418 }
419
420 for (page_no = 0; page_no < layout->p2l.ckpt_pages; page_no++, page++) {
421 if (page->metadata.p2l_ckpt.seq_id != seq_id) {
422 continue;
423 }
424
425 page_max = page_no;
426 page_found = true;
427
428 if (page->metadata.p2l_ckpt.p2l_checksum &&
429 page->metadata.p2l_ckpt.p2l_checksum != spdk_crc32c_update(page->map,
430 FTL_NUM_P2L_ENTRIES_NO_VSS * sizeof(struct ftl_p2l_map_entry), 0)) {
431 ftl_stats_crc_error(band->dev, FTL_STATS_TYPE_MD_NV_CACHE);
432 return -EINVAL;
433 }
434
435 xfer_count = page_no / pages_per_xfer;
436 lbas_synced = (page_no % pages_per_xfer) * FTL_NUM_P2L_ENTRIES_NO_VSS;
437
438 /* Restore the page from P2L checkpoint */
439 band_entries = band->p2l_map.band_map + xfer_count * dev->xfer_size + lbas_synced;
440
441 memcpy(band_entries, page->map, page->metadata.p2l_ckpt.count * sizeof(struct ftl_p2l_map_entry));
442 }
443
444 assert(page_found);
445 if (!page_found) {
446 return -EINVAL;
447 }
448
449 /* Restore check point in band P2L map */
450 band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(
451 band->dev, md_region);
452
453 /* Align page_max to xfer_size aligned pages */
454 if ((page_max + 1) % pages_per_xfer != 0) {
455 page_max += (pages_per_xfer - page_max % pages_per_xfer - 1);
456 }
457 #ifdef DEBUG
458 /* Set check point valid map for validation */
459 struct ftl_p2l_ckpt *ckpt = band->p2l_map.p2l_ckpt;
460 for (uint64_t i = 0; i <= page_max; i++) {
461 ftl_bitmap_set(ckpt->bmp, i);
462 }
463 #endif
464
465 ftl_band_iter_init(band);
466 /* Align page max to xfer size and set iter */
467 ftl_band_iter_set(band, (page_max / band->p2l_map.p2l_ckpt->pages_per_xfer + 1) * dev->xfer_size);
468
469 return 0;
470 }
471
472 enum ftl_layout_region_type
ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt * ckpt)473 ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt) {
474 return ckpt->layout_region->type;
475 }
476
477 struct ftl_p2l_ckpt *
ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev * dev,uint32_t region_type)478 ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev, uint32_t region_type)
479 {
480 struct ftl_p2l_ckpt *ckpt = NULL;
481
482 TAILQ_FOREACH(ckpt, &dev->p2l_ckpt.free, link) {
483 if (ckpt->layout_region->type == region_type) {
484 break;
485 }
486 }
487
488 assert(ckpt);
489
490 TAILQ_REMOVE(&dev->p2l_ckpt.free, ckpt, link);
491 TAILQ_INSERT_TAIL(&dev->p2l_ckpt.inuse, ckpt, link);
492
493 return ckpt;
494 }
495
496 int
ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band * band)497 ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band)
498 {
499 struct spdk_ftl_dev *dev = band->dev;
500 struct ftl_layout *layout = &dev->layout;
501 struct ftl_p2l_ckpt_page_no_vss *page;
502 enum ftl_layout_region_type md_region = band->md->p2l_md_region;
503 struct ftl_p2l_ckpt *ckpt;
504 uint64_t page_no;
505 uint64_t num_written_pages, lbas_synced;
506
507 if (md_region < FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN ||
508 md_region > FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX) {
509 return -EINVAL;
510 }
511
512 assert(band->md->iter.offset % dev->xfer_size == 0);
513
514 /* Associate band with md region before shutdown */
515 if (!band->p2l_map.p2l_ckpt) {
516 band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(dev, md_region);
517 }
518
519 /* Band was opened but no data was written */
520 if (band->md->iter.offset == 0) {
521 return 0;
522 }
523
524 ckpt = band->p2l_map.p2l_ckpt;
525 num_written_pages = band->md->iter.offset / dev->xfer_size * ckpt->pages_per_xfer;
526
527 page_no = 0;
528 lbas_synced = 0;
529
530 /* Restore P2L map up to last written page */
531 page = ftl_md_get_buffer(layout->md[md_region]);
532
533
534 for (; page_no < num_written_pages; page_no++, page++) {
535 assert(page->metadata.p2l_ckpt.seq_id == band->md->seq);
536 /* Restore the page from P2L checkpoint */
537 memcpy(band->p2l_map.band_map + lbas_synced, page->map,
538 page->metadata.p2l_ckpt.count * sizeof(struct ftl_p2l_map_entry));
539
540 lbas_synced += page->metadata.p2l_ckpt.count;
541
542 #if defined(DEBUG)
543 assert(ftl_bitmap_get(band->p2l_map.p2l_ckpt->bmp, page_no) == false);
544 ftl_bitmap_set(band->p2l_map.p2l_ckpt->bmp, page_no);
545 #endif
546 }
547
548 assert(lbas_synced % dev->xfer_size == 0);
549
550 assert(page->metadata.p2l_ckpt.seq_id < band->md->seq);
551
552 return 0;
553 }
554
555 void
ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band * band)556 ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band)
557 {
558 struct spdk_ftl_dev *dev = band->dev;
559 enum ftl_layout_region_type md_region = band->md->p2l_md_region;
560
561 /* Associate band with md region before shutdown */
562 if (!band->p2l_map.p2l_ckpt) {
563 band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire_region_type(dev, md_region);
564 }
565
566 #if defined(DEBUG)
567 uint64_t page_no;
568 uint64_t num_written_pages;
569
570 assert(band->md->iter.offset % dev->xfer_size == 0);
571 num_written_pages = band->md->iter.offset / dev->xfer_size * band->p2l_map.p2l_ckpt->pages_per_xfer;
572
573 /* Band was opened but no data was written */
574 if (band->md->iter.offset == 0) {
575 return;
576 }
577
578 /* Set page number to first data page - skip head md */
579 page_no = 0;
580
581 for (; page_no < num_written_pages; page_no++) {
582 assert(ftl_bitmap_get(band->p2l_map.p2l_ckpt->bmp, page_no) == false);
583 ftl_bitmap_set(band->p2l_map.p2l_ckpt->bmp, page_no);
584 }
585 #endif
586 }
587