Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2018 Intel Corporation.
3 : * Copyright 2023 Solidigm All Rights Reserved
4 : * All rights reserved.
5 : */
6 :
7 : #include "spdk/stdinc.h"
8 : #include "spdk/crc32.h"
9 : #include "spdk/likely.h"
10 : #include "spdk/util.h"
11 : #include "spdk/ftl.h"
12 :
13 : #include "ftl_band.h"
14 : #include "ftl_io.h"
15 : #include "ftl_core.h"
16 : #include "ftl_debug.h"
17 : #include "ftl_internal.h"
18 : #include "utils/ftl_md.h"
19 : #include "utils/ftl_defs.h"
20 :
21 : static uint64_t
22 0 : ftl_band_tail_md_offset(const struct ftl_band *band)
23 : {
24 0 : return ftl_get_num_blocks_in_band(band->dev) -
25 0 : ftl_tail_md_num_blocks(band->dev);
26 : }
27 :
28 : int
29 0 : ftl_band_filled(struct ftl_band *band, size_t offset)
30 : {
31 0 : return offset == ftl_band_tail_md_offset(band);
32 : }
33 :
34 : static void
35 6 : ftl_band_free_p2l_map(struct ftl_band *band)
36 : {
37 6 : struct spdk_ftl_dev *dev = band->dev;
38 6 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
39 :
40 6 : assert(band->md->state == FTL_BAND_STATE_CLOSED ||
41 : band->md->state == FTL_BAND_STATE_FREE);
42 6 : assert(p2l_map->ref_cnt == 0);
43 6 : assert(p2l_map->band_map != NULL);
44 :
45 6 : band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
46 6 : ftl_mempool_put(dev->p2l_pool, p2l_map->band_map);
47 6 : p2l_map->band_map = NULL;
48 6 : }
49 :
50 :
51 : static void
52 6 : ftl_band_free_md_entry(struct ftl_band *band)
53 : {
54 6 : struct spdk_ftl_dev *dev = band->dev;
55 6 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
56 :
57 6 : assert(band->md->state == FTL_BAND_STATE_CLOSED ||
58 : band->md->state == FTL_BAND_STATE_FREE);
59 6 : assert(p2l_map->band_dma_md != NULL);
60 :
61 6 : ftl_mempool_put(dev->band_md_pool, p2l_map->band_dma_md);
62 6 : p2l_map->band_dma_md = NULL;
63 6 : }
64 :
65 : static void
66 0 : _ftl_band_set_free(struct ftl_band *band)
67 : {
68 0 : struct spdk_ftl_dev *dev = band->dev;
69 :
70 : /* Add the band to the free band list */
71 0 : TAILQ_INSERT_TAIL(&dev->free_bands, band, queue_entry);
72 0 : band->md->close_seq_id = 0;
73 0 : band->reloc = false;
74 :
75 0 : dev->num_free++;
76 0 : ftl_apply_limits(dev);
77 :
78 0 : band->md->p2l_map_checksum = 0;
79 0 : }
80 :
81 : static void
82 0 : _ftl_band_set_preparing(struct ftl_band *band)
83 : {
84 0 : struct spdk_ftl_dev *dev = band->dev;
85 :
86 : /* Remove band from free list */
87 0 : TAILQ_REMOVE(&dev->free_bands, band, queue_entry);
88 :
89 0 : band->md->wr_cnt++;
90 :
91 0 : assert(dev->num_free > 0);
92 0 : dev->num_free--;
93 :
94 0 : ftl_apply_limits(dev);
95 0 : }
96 :
97 : static void
98 0 : _ftl_band_set_closed_cb(struct ftl_band *band, bool valid)
99 : {
100 0 : struct spdk_ftl_dev *dev = band->dev;
101 :
102 0 : assert(valid == true);
103 :
104 : /* Set the state as free_md() checks for that */
105 0 : band->md->state = FTL_BAND_STATE_CLOSED;
106 0 : if (band->owner.state_change_fn) {
107 0 : band->owner.state_change_fn(band);
108 : }
109 :
110 0 : ftl_p2l_validate_ckpt(band);
111 :
112 : /* Free the P2L map if there are no outstanding IOs */
113 0 : ftl_band_release_p2l_map(band);
114 0 : assert(band->p2l_map.ref_cnt == 0);
115 :
116 0 : TAILQ_INSERT_TAIL(&dev->shut_bands, band, queue_entry);
117 0 : }
118 :
119 : static void
120 0 : _ftl_band_set_closed(struct ftl_band *band)
121 : {
122 : /* Verify that band's metadata is consistent with l2p */
123 0 : ftl_band_validate_md(band, _ftl_band_set_closed_cb);
124 0 : }
125 :
126 : ftl_addr
127 0 : ftl_band_tail_md_addr(struct ftl_band *band)
128 : {
129 : ftl_addr addr;
130 :
131 : /* Metadata should be aligned to xfer size */
132 0 : assert(ftl_band_tail_md_offset(band) % band->dev->xfer_size == 0);
133 :
134 0 : addr = ftl_band_tail_md_offset(band) + band->start_addr;
135 :
136 0 : return addr;
137 : }
138 :
139 : const char *
140 0 : ftl_band_get_state_name(struct ftl_band *band)
141 : {
142 : static const char *names[] = {
143 : "FREE", "PREPARING", "OPENING", "OPEN", "FULL", "CLOSING",
144 : "CLOSED",
145 : };
146 :
147 0 : assert(band->md->state < SPDK_COUNTOF(names));
148 0 : if (band->md->state < SPDK_COUNTOF(names)) {
149 0 : return names[band->md->state];
150 : } else {
151 0 : assert(false);
152 : return "?";
153 : }
154 : }
155 :
156 : void
157 0 : ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state)
158 : {
159 0 : switch (state) {
160 0 : case FTL_BAND_STATE_FREE:
161 0 : assert(band->md->state == FTL_BAND_STATE_CLOSED);
162 0 : _ftl_band_set_free(band);
163 0 : break;
164 :
165 0 : case FTL_BAND_STATE_PREP:
166 0 : assert(band->md->state == FTL_BAND_STATE_FREE);
167 0 : _ftl_band_set_preparing(band);
168 0 : break;
169 :
170 0 : case FTL_BAND_STATE_CLOSED:
171 0 : if (band->md->state != FTL_BAND_STATE_CLOSED) {
172 0 : assert(band->md->state == FTL_BAND_STATE_CLOSING);
173 0 : _ftl_band_set_closed(band);
174 0 : return; /* state can be changed asynchronously */
175 : }
176 0 : break;
177 :
178 0 : case FTL_BAND_STATE_OPEN:
179 0 : band->md->p2l_map_checksum = 0;
180 0 : break;
181 0 : case FTL_BAND_STATE_OPENING:
182 : case FTL_BAND_STATE_FULL:
183 : case FTL_BAND_STATE_CLOSING:
184 0 : break;
185 0 : default:
186 0 : FTL_ERRLOG(band->dev, "Unknown band state, %u", state);
187 0 : assert(false);
188 : break;
189 : }
190 :
191 0 : band->md->state = state;
192 : }
193 :
194 : void
195 0 : ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type)
196 : {
197 0 : switch (type) {
198 0 : case FTL_BAND_TYPE_COMPACTION:
199 : case FTL_BAND_TYPE_GC:
200 0 : band->md->type = type;
201 0 : break;
202 0 : default:
203 0 : assert(false);
204 : break;
205 : }
206 0 : }
207 :
208 : void
209 5 : ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id)
210 : {
211 5 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
212 : uint64_t offset;
213 :
214 5 : offset = ftl_band_block_offset_from_addr(band, addr);
215 :
216 5 : p2l_map->band_map[offset].lba = lba;
217 5 : p2l_map->band_map[offset].seq_id = seq_id;
218 5 : }
219 :
220 : void
221 5 : ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr)
222 : {
223 5 : band->p2l_map.num_valid++;
224 5 : ftl_bitmap_set(band->dev->valid_map, addr);
225 5 : }
226 :
227 : size_t
228 0 : ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset)
229 : {
230 0 : size_t tail_md_offset = ftl_band_tail_md_offset(band);
231 :
232 0 : if (spdk_unlikely(offset > tail_md_offset)) {
233 0 : return 0;
234 : }
235 :
236 0 : return tail_md_offset - offset;
237 : }
238 :
239 : size_t
240 0 : ftl_band_user_blocks(const struct ftl_band *band)
241 : {
242 0 : return ftl_get_num_blocks_in_band(band->dev) -
243 0 : ftl_tail_md_num_blocks(band->dev);
244 : }
245 :
246 : static inline uint64_t
247 30026 : ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
248 : {
249 30026 : return (addr - dev->bands->start_addr) / ftl_get_num_blocks_in_band(dev);
250 : }
251 :
252 : struct ftl_band *
253 2 : ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
254 : {
255 2 : uint64_t band_id = ftl_addr_get_band(dev, addr);
256 :
257 2 : assert(band_id < ftl_get_num_bands(dev));
258 2 : return &dev->bands[band_id];
259 : }
260 :
261 : uint64_t
262 20006 : ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr)
263 : {
264 20006 : assert(ftl_addr_get_band(band->dev, addr) == band->id);
265 20006 : return addr - band->start_addr;
266 : }
267 :
268 : ftl_addr
269 3 : ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks)
270 : {
271 3 : struct spdk_ftl_dev *dev = band->dev;
272 : size_t num_xfers;
273 : uint64_t offset;
274 :
275 3 : assert(ftl_addr_get_band(dev, addr) == band->id);
276 :
277 3 : offset = addr - band->start_addr;
278 :
279 : /* In case starting address wasn't aligned to xfer_size, we'll align for consistent calculation
280 : * purposes - the unaligned value will be preserved at the end however.
281 : */
282 3 : num_blocks += (offset % dev->xfer_size);
283 3 : offset -= (offset % dev->xfer_size);
284 :
285 : /* Calculate offset based on xfer_size aligned writes */
286 3 : num_xfers = (num_blocks / dev->xfer_size);
287 3 : offset += num_xfers * dev->xfer_size;
288 3 : num_blocks -= num_xfers * dev->xfer_size;
289 :
290 3 : if (offset > ftl_get_num_blocks_in_band(dev)) {
291 0 : return FTL_ADDR_INVALID;
292 : }
293 :
294 : /* If there's any unalignment (either starting addr value or num_blocks), reintroduce it to the final address
295 : */
296 3 : if (num_blocks) {
297 2 : offset += num_blocks;
298 2 : if (offset > ftl_get_num_blocks_in_band(dev)) {
299 0 : return FTL_ADDR_INVALID;
300 : }
301 : }
302 :
303 3 : addr = band->start_addr + offset;
304 3 : return addr;
305 : }
306 :
307 : ftl_addr
308 10000 : ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off)
309 : {
310 : ftl_addr addr;
311 :
312 10000 : addr = block_off + band->start_addr;
313 10000 : return addr;
314 : }
315 :
316 : ftl_addr
317 0 : ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset)
318 : {
319 0 : uint64_t block_off = ftl_band_block_offset_from_addr(band, addr);
320 :
321 0 : return ftl_band_addr_from_block_offset(band, block_off + offset);
322 : }
323 :
324 : void
325 6 : ftl_band_acquire_p2l_map(struct ftl_band *band)
326 : {
327 6 : assert(band->p2l_map.band_map != NULL);
328 6 : band->p2l_map.ref_cnt++;
329 6 : }
330 :
331 : static int
332 6 : ftl_band_alloc_md_entry(struct ftl_band *band)
333 : {
334 6 : struct spdk_ftl_dev *dev = band->dev;
335 6 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
336 6 : struct ftl_layout_region *region = ftl_layout_region_get(dev, FTL_LAYOUT_REGION_TYPE_BAND_MD);
337 :
338 6 : p2l_map->band_dma_md = ftl_mempool_get(dev->band_md_pool);
339 :
340 6 : if (!p2l_map->band_dma_md) {
341 0 : return -1;
342 : }
343 :
344 6 : memset(p2l_map->band_dma_md, 0, region->entry_size * FTL_BLOCK_SIZE);
345 6 : return 0;
346 : }
347 :
348 : int
349 6 : ftl_band_alloc_p2l_map(struct ftl_band *band)
350 : {
351 6 : struct spdk_ftl_dev *dev = band->dev;
352 6 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
353 :
354 6 : assert(p2l_map->ref_cnt == 0);
355 6 : assert(p2l_map->band_map == NULL);
356 :
357 6 : assert(band->md->df_p2l_map == FTL_DF_OBJ_ID_INVALID);
358 6 : p2l_map->band_map = ftl_mempool_get(dev->p2l_pool);
359 6 : if (!p2l_map->band_map) {
360 0 : return -1;
361 : }
362 :
363 6 : if (ftl_band_alloc_md_entry(band)) {
364 0 : ftl_band_free_p2l_map(band);
365 0 : return -1;
366 : }
367 :
368 6 : band->md->df_p2l_map = ftl_mempool_get_df_obj_id(dev->p2l_pool, p2l_map->band_map);
369 :
370 : /* Set the P2L to FTL_LBA_INVALID */
371 6 : memset(p2l_map->band_map, -1, FTL_BLOCK_SIZE * ftl_p2l_map_num_blocks(band->dev));
372 :
373 6 : ftl_band_acquire_p2l_map(band);
374 6 : return 0;
375 : }
376 :
377 : int
378 0 : ftl_band_open_p2l_map(struct ftl_band *band)
379 : {
380 0 : struct spdk_ftl_dev *dev = band->dev;
381 0 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
382 :
383 0 : assert(p2l_map->ref_cnt == 0);
384 0 : assert(p2l_map->band_map == NULL);
385 :
386 0 : assert(band->md->df_p2l_map != FTL_DF_OBJ_ID_INVALID);
387 :
388 0 : if (ftl_band_alloc_md_entry(band)) {
389 0 : p2l_map->band_map = NULL;
390 0 : return -1;
391 : }
392 :
393 0 : p2l_map->band_map = ftl_mempool_claim_df(dev->p2l_pool, band->md->df_p2l_map);
394 :
395 0 : ftl_band_acquire_p2l_map(band);
396 0 : return 0;
397 : }
398 :
399 : void
400 6 : ftl_band_release_p2l_map(struct ftl_band *band)
401 : {
402 6 : struct ftl_p2l_map *p2l_map = &band->p2l_map;
403 :
404 6 : assert(p2l_map->band_map != NULL);
405 6 : assert(p2l_map->ref_cnt > 0);
406 6 : p2l_map->ref_cnt--;
407 :
408 6 : if (p2l_map->ref_cnt == 0) {
409 6 : if (p2l_map->p2l_ckpt) {
410 0 : ftl_p2l_ckpt_release(band->dev, p2l_map->p2l_ckpt);
411 0 : p2l_map->p2l_ckpt = NULL;
412 : }
413 6 : ftl_band_free_p2l_map(band);
414 6 : ftl_band_free_md_entry(band);
415 : }
416 6 : }
417 :
418 : ftl_addr
419 0 : ftl_band_p2l_map_addr(struct ftl_band *band)
420 : {
421 0 : return band->tail_md_addr;
422 : }
423 :
424 : int
425 0 : ftl_band_write_prep(struct ftl_band *band)
426 : {
427 0 : struct spdk_ftl_dev *dev = band->dev;
428 :
429 0 : if (ftl_band_alloc_p2l_map(band)) {
430 0 : return -1;
431 : }
432 :
433 0 : band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire(dev);
434 0 : band->md->p2l_md_region = ftl_p2l_ckpt_region_type(band->p2l_map.p2l_ckpt);
435 0 : ftl_band_iter_init(band);
436 :
437 0 : band->md->seq = ftl_get_next_seq_id(dev);
438 :
439 0 : FTL_DEBUGLOG(dev, "Band to write, id %u seq %"PRIu64"\n", band->id, band->md->seq);
440 0 : return 0;
441 : }
442 :
443 : size_t
444 0 : ftl_p2l_map_pool_elem_size(struct spdk_ftl_dev *dev)
445 : {
446 : /* Map pool element holds the whole tail md */
447 0 : return ftl_tail_md_num_blocks(dev) * FTL_BLOCK_SIZE;
448 : }
449 :
450 : double
451 0 : ftl_band_invalidity(struct ftl_band *band)
452 : {
453 0 : double valid = band->p2l_map.num_valid;
454 0 : double count = ftl_band_user_blocks(band);
455 :
456 0 : return 1.0 - (valid / count);
457 : }
458 :
459 : static void
460 0 : dump_bands_under_relocation(struct spdk_ftl_dev *dev)
461 : {
462 0 : uint64_t i = dev->sb_shm->gc_info.current_band_id;
463 0 : uint64_t end = dev->sb_shm->gc_info.current_band_id + dev->num_logical_bands_in_physical;
464 :
465 0 : for (; i < end; i++) {
466 0 : struct ftl_band *band = &dev->bands[i];
467 :
468 0 : FTL_DEBUGLOG(dev, "Band, id %u, phys_is %u, wr cnt = %u, invalidity = %u%%\n",
469 : band->id, band->phys_id, (uint32_t)band->md->wr_cnt,
470 : (uint32_t)(ftl_band_invalidity(band) * 100));
471 : }
472 0 : }
473 :
474 : static bool
475 0 : is_band_relocateable(struct ftl_band *band)
476 : {
477 : /* Can only move data from closed bands */
478 0 : if (FTL_BAND_STATE_CLOSED != band->md->state) {
479 0 : return false;
480 : }
481 :
482 : /* Band is already under relocation, skip it */
483 0 : if (band->reloc) {
484 0 : return false;
485 : }
486 :
487 0 : return true;
488 : }
489 :
490 : static void
491 0 : get_band_phys_info(struct spdk_ftl_dev *dev, uint64_t phys_id,
492 : double *invalidity, double *wr_cnt)
493 : {
494 : struct ftl_band *band;
495 0 : uint64_t band_id = phys_id * dev->num_logical_bands_in_physical;
496 :
497 0 : *wr_cnt = *invalidity = 0.0L;
498 0 : for (; band_id < ftl_get_num_bands(dev); band_id++) {
499 0 : band = &dev->bands[band_id];
500 :
501 0 : if (phys_id != band->phys_id) {
502 0 : break;
503 : }
504 :
505 0 : *wr_cnt += band->md->wr_cnt;
506 :
507 0 : if (!is_band_relocateable(band)) {
508 0 : continue;
509 : }
510 :
511 0 : *invalidity += ftl_band_invalidity(band);
512 : }
513 :
514 0 : *invalidity /= dev->num_logical_bands_in_physical;
515 0 : *wr_cnt /= dev->num_logical_bands_in_physical;
516 0 : }
517 :
518 : static bool
519 0 : band_cmp(double a_invalidity, double a_wr_cnt,
520 : double b_invalidity, double b_wr_cnt,
521 : uint64_t a_id, uint64_t b_id)
522 : {
523 0 : assert(a_id != FTL_BAND_PHYS_ID_INVALID);
524 0 : assert(b_id != FTL_BAND_PHYS_ID_INVALID);
525 0 : double diff = a_invalidity - b_invalidity;
526 0 : if (diff < 0.0L) {
527 0 : diff *= -1.0L;
528 : }
529 :
530 : /* Use the following metrics for picking bands for GC (in order):
531 : * - relative invalidity
532 : * - if invalidity is similar (within 10% points), then their write counts (how many times band was written to)
533 : * - if write count is equal, then pick based on their placement on base device (lower LBAs win)
534 : */
535 0 : if (diff > 0.1L) {
536 0 : return a_invalidity > b_invalidity;
537 : }
538 :
539 0 : if (a_wr_cnt != b_wr_cnt) {
540 0 : return a_wr_cnt < b_wr_cnt;
541 : }
542 :
543 0 : return a_id < b_id;
544 : }
545 :
546 : static void
547 0 : band_start_gc(struct spdk_ftl_dev *dev, struct ftl_band *band)
548 : {
549 0 : ftl_bug(false == is_band_relocateable(band));
550 :
551 0 : TAILQ_REMOVE(&dev->shut_bands, band, queue_entry);
552 0 : band->reloc = true;
553 :
554 0 : FTL_DEBUGLOG(dev, "Band to GC, id %u\n", band->id);
555 0 : }
556 :
557 : static struct ftl_band *
558 0 : gc_high_priority_band(struct spdk_ftl_dev *dev)
559 : {
560 : struct ftl_band *band;
561 0 : uint64_t high_prio_id = dev->sb_shm->gc_info.band_id_high_prio;
562 :
563 0 : if (FTL_BAND_ID_INVALID != high_prio_id) {
564 0 : ftl_bug(high_prio_id >= dev->num_bands);
565 :
566 0 : band = &dev->bands[high_prio_id];
567 0 : dev->sb_shm->gc_info.band_id_high_prio = FTL_BAND_ID_INVALID;
568 :
569 0 : band_start_gc(dev, band);
570 0 : FTL_NOTICELOG(dev, "GC takes high priority band, id %u\n", band->id);
571 0 : return band;
572 : }
573 :
574 0 : return 0;
575 : }
576 :
577 : static void
578 0 : ftl_band_reset_gc_iter(struct spdk_ftl_dev *dev)
579 : {
580 0 : dev->sb->gc_info.is_valid = 0;
581 0 : dev->sb->gc_info.current_band_id = FTL_BAND_ID_INVALID;
582 0 : dev->sb->gc_info.band_id_high_prio = FTL_BAND_ID_INVALID;
583 0 : dev->sb->gc_info.band_phys_id = FTL_BAND_PHYS_ID_INVALID;
584 :
585 0 : dev->sb_shm->gc_info = dev->sb->gc_info;
586 0 : }
587 :
588 : struct ftl_band *
589 0 : ftl_band_search_next_to_reloc(struct spdk_ftl_dev *dev)
590 : {
591 0 : double invalidity, max_invalidity = 0.0L;
592 0 : double wr_cnt, max_wr_cnt = 0.0L;
593 0 : uint64_t phys_id = FTL_BAND_PHYS_ID_INVALID;
594 : struct ftl_band *band;
595 : uint64_t i, band_count;
596 : uint64_t phys_count;
597 :
598 0 : band = gc_high_priority_band(dev);
599 0 : if (spdk_unlikely(NULL != band)) {
600 0 : return band;
601 : }
602 :
603 0 : phys_count = dev->num_logical_bands_in_physical;
604 0 : band_count = ftl_get_num_bands(dev);
605 :
606 0 : for (; dev->sb_shm->gc_info.current_band_id < band_count;) {
607 0 : band = &dev->bands[dev->sb_shm->gc_info.current_band_id];
608 0 : if (band->phys_id != dev->sb_shm->gc_info.band_phys_id) {
609 0 : break;
610 : }
611 :
612 0 : if (false == is_band_relocateable(band)) {
613 0 : dev->sb_shm->gc_info.current_band_id++;
614 0 : continue;
615 : }
616 :
617 0 : band_start_gc(dev, band);
618 0 : return band;
619 : }
620 :
621 0 : for (i = 0; i < band_count; i += phys_count) {
622 0 : band = &dev->bands[i];
623 :
624 : /* Calculate entire band physical group invalidity */
625 0 : get_band_phys_info(dev, band->phys_id, &invalidity, &wr_cnt);
626 :
627 0 : if (invalidity != 0.0L) {
628 0 : if (phys_id == FTL_BAND_PHYS_ID_INVALID ||
629 0 : band_cmp(invalidity, wr_cnt, max_invalidity, max_wr_cnt,
630 0 : band->phys_id, phys_id)) {
631 0 : max_wr_cnt = wr_cnt;
632 0 : phys_id = band->phys_id;
633 :
634 0 : if (invalidity > max_invalidity) {
635 0 : max_invalidity = invalidity;
636 : }
637 : }
638 : }
639 : }
640 :
641 0 : if (FTL_BAND_PHYS_ID_INVALID != phys_id) {
642 0 : FTL_DEBUGLOG(dev, "Band physical id %"PRIu64" to GC\n", phys_id);
643 0 : dev->sb_shm->gc_info.is_valid = 0;
644 0 : dev->sb_shm->gc_info.current_band_id = phys_id * phys_count;
645 0 : dev->sb_shm->gc_info.band_phys_id = phys_id;
646 0 : dev->sb_shm->gc_info.is_valid = 1;
647 0 : dump_bands_under_relocation(dev);
648 0 : return ftl_band_search_next_to_reloc(dev);
649 : } else {
650 0 : ftl_band_reset_gc_iter(dev);
651 : }
652 :
653 0 : return NULL;
654 : }
655 :
656 : void
657 0 : ftl_band_init_gc_iter(struct spdk_ftl_dev *dev)
658 : {
659 0 : if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
660 0 : ftl_band_reset_gc_iter(dev);
661 0 : return;
662 : }
663 :
664 0 : if (dev->sb->clean) {
665 0 : dev->sb_shm->gc_info = dev->sb->gc_info;
666 0 : return;
667 : }
668 :
669 0 : if (ftl_fast_startup(dev) || ftl_fast_recovery(dev)) {
670 0 : return;
671 : }
672 :
673 : /* We lost GC state due to dirty shutdown, reset GC state to start over */
674 0 : ftl_band_reset_gc_iter(dev);
675 : }
676 :
677 : void
678 0 : ftl_valid_map_load_state(struct spdk_ftl_dev *dev)
679 : {
680 : uint64_t i;
681 : struct ftl_band *band;
682 :
683 0 : for (i = 0; i < dev->num_bands; i++) {
684 0 : band = &dev->bands[i];
685 0 : band->p2l_map.num_valid = ftl_bitmap_count_set(band->p2l_map.valid);
686 : }
687 0 : }
688 :
689 : void
690 0 : ftl_band_initialize_free_state(struct ftl_band *band)
691 : {
692 : /* All bands start on the shut list during startup, removing it manually here */
693 0 : TAILQ_REMOVE(&band->dev->shut_bands, band, queue_entry);
694 0 : _ftl_band_set_free(band);
695 0 : }
696 :
697 : int
698 0 : ftl_bands_load_state(struct spdk_ftl_dev *dev)
699 : {
700 : uint64_t i;
701 : struct ftl_band *band;
702 :
703 0 : for (i = 0; i < dev->num_bands; i++) {
704 0 : band = &dev->bands[i];
705 :
706 0 : if (band->md->version != FTL_BAND_VERSION_CURRENT) {
707 0 : FTL_ERRLOG(dev, "Invalid band version detected, %"PRIu64" (expected %d)\n",
708 : band->md->version, FTL_BAND_VERSION_CURRENT);
709 0 : return -1;
710 : }
711 :
712 0 : if (band->md->state == FTL_BAND_STATE_FREE) {
713 0 : ftl_band_initialize_free_state(band);
714 : }
715 : }
716 :
717 0 : return 0;
718 : }
|