xref: /spdk/lib/ftl/mngt/ftl_mngt_band.c (revision cb00e90aee3bcd300f2672ca2baab5257e5e389e)
19dbdb029SKozlowski Mateusz /*   SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse  *   Copyright (C) 2022 Intel Corporation.
39dbdb029SKozlowski Mateusz  *   All rights reserved.
49dbdb029SKozlowski Mateusz  */
59dbdb029SKozlowski Mateusz 
69dbdb029SKozlowski Mateusz #include "ftl_core.h"
79dbdb029SKozlowski Mateusz #include "ftl_mngt_steps.h"
89dbdb029SKozlowski Mateusz #include "ftl_band.h"
99dbdb029SKozlowski Mateusz #include "ftl_internal.h"
109dbdb029SKozlowski Mateusz 
119dbdb029SKozlowski Mateusz static int
ftl_band_init_md(struct ftl_band * band)129dbdb029SKozlowski Mateusz ftl_band_init_md(struct ftl_band *band)
139dbdb029SKozlowski Mateusz {
149dbdb029SKozlowski Mateusz 	struct spdk_ftl_dev *dev = band->dev;
15cea8dadeSArtur Paszkiewicz 	struct ftl_p2l_map *p2l_map = &band->p2l_map;
169dbdb029SKozlowski Mateusz 	struct ftl_md *band_info_md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_BAND_MD];
17cea8dadeSArtur Paszkiewicz 	struct ftl_md *valid_map_md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_VALID_MAP];
18cea8dadeSArtur Paszkiewicz 	uint64_t band_num_blocks = ftl_get_num_blocks_in_band(band->dev);
19cea8dadeSArtur Paszkiewicz 	size_t band_valid_map_bytes;
209dbdb029SKozlowski Mateusz 	struct ftl_band_md *band_md = ftl_md_get_buffer(band_info_md);
219dbdb029SKozlowski Mateusz 
22cea8dadeSArtur Paszkiewicz 	if (band_num_blocks % (ftl_bitmap_buffer_alignment * 8)) {
23cea8dadeSArtur Paszkiewicz 		FTL_ERRLOG(dev, "The number of blocks in band is not divisible by bitmap word bits\n");
24cea8dadeSArtur Paszkiewicz 		return -EINVAL;
25cea8dadeSArtur Paszkiewicz 	}
26cea8dadeSArtur Paszkiewicz 	band_valid_map_bytes = band_num_blocks / 8;
27cea8dadeSArtur Paszkiewicz 
28cea8dadeSArtur Paszkiewicz 	p2l_map->valid = ftl_bitmap_create(ftl_md_get_buffer(valid_map_md) +
29c3321813SKozlowski Mateusz 					   band->start_addr / 8, band_valid_map_bytes);
30cea8dadeSArtur Paszkiewicz 	if (!p2l_map->valid) {
31cea8dadeSArtur Paszkiewicz 		return -ENOMEM;
32cea8dadeSArtur Paszkiewicz 	}
33cea8dadeSArtur Paszkiewicz 
349dbdb029SKozlowski Mateusz 	band->md = &band_md[band->id];
35*cb00e90aSMateusz Kozlowski 	band->md->version = FTL_BAND_VERSION_CURRENT;
361e904e2bSArtur Paszkiewicz 	if (!ftl_fast_startup(dev)) {
37101a0399SKozlowski Mateusz 		band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
381e904e2bSArtur Paszkiewicz 	}
399dbdb029SKozlowski Mateusz 
409dbdb029SKozlowski Mateusz 	return 0;
419dbdb029SKozlowski Mateusz }
429dbdb029SKozlowski Mateusz 
439dbdb029SKozlowski Mateusz static int
ftl_dev_init_bands(struct spdk_ftl_dev * dev)449dbdb029SKozlowski Mateusz ftl_dev_init_bands(struct spdk_ftl_dev *dev)
459dbdb029SKozlowski Mateusz {
469dbdb029SKozlowski Mateusz 	struct ftl_band *band;
47102d266dSKozlowski Mateusz 	uint64_t i, blocks, md_blocks, md_bands;
48102d266dSKozlowski Mateusz 
49102d266dSKozlowski Mateusz 	/* Calculate initial number of bands */
50102d266dSKozlowski Mateusz 	blocks = spdk_bdev_get_num_blocks(spdk_bdev_desc_get_bdev(dev->base_bdev_desc));
51102d266dSKozlowski Mateusz 	dev->num_bands = blocks / ftl_get_num_blocks_in_band(dev);
52102d266dSKozlowski Mateusz 
53102d266dSKozlowski Mateusz 	/* Calculate number of bands considering base device metadata size requirement */
54102d266dSKozlowski Mateusz 	md_blocks = ftl_layout_base_md_blocks(dev);
55102d266dSKozlowski Mateusz 	md_bands = spdk_divide_round_up(md_blocks, dev->num_blocks_in_band);
56102d266dSKozlowski Mateusz 
57102d266dSKozlowski Mateusz 	if (dev->num_bands > md_bands) {
58102d266dSKozlowski Mateusz 		/* Save a band worth of space for metadata */
59102d266dSKozlowski Mateusz 		dev->num_bands -= md_bands;
60102d266dSKozlowski Mateusz 	} else {
61102d266dSKozlowski Mateusz 		FTL_ERRLOG(dev, "Base device too small to store metadata\n");
62102d266dSKozlowski Mateusz 		return -1;
63102d266dSKozlowski Mateusz 	}
649dbdb029SKozlowski Mateusz 
659dbdb029SKozlowski Mateusz 	TAILQ_INIT(&dev->free_bands);
669dbdb029SKozlowski Mateusz 	TAILQ_INIT(&dev->shut_bands);
679dbdb029SKozlowski Mateusz 
689dbdb029SKozlowski Mateusz 	dev->num_free = 0;
699dbdb029SKozlowski Mateusz 	dev->bands = calloc(ftl_get_num_bands(dev), sizeof(*dev->bands));
709dbdb029SKozlowski Mateusz 	if (!dev->bands) {
719dbdb029SKozlowski Mateusz 		return -ENOMEM;
729dbdb029SKozlowski Mateusz 	}
739dbdb029SKozlowski Mateusz 
749dbdb029SKozlowski Mateusz 	for (i = 0; i < ftl_get_num_bands(dev); ++i) {
759dbdb029SKozlowski Mateusz 		band = &dev->bands[i];
769dbdb029SKozlowski Mateusz 		band->id = i;
779dbdb029SKozlowski Mateusz 		band->dev = dev;
789dbdb029SKozlowski Mateusz 
799dbdb029SKozlowski Mateusz 		/* Adding to shut_bands is necessary - see ftl_restore_band_close_cb() */
809dbdb029SKozlowski Mateusz 		TAILQ_INSERT_TAIL(&dev->shut_bands, band, queue_entry);
819dbdb029SKozlowski Mateusz 	}
829dbdb029SKozlowski Mateusz 
839dbdb029SKozlowski Mateusz 	return 0;
849dbdb029SKozlowski Mateusz }
859dbdb029SKozlowski Mateusz 
869dbdb029SKozlowski Mateusz static int
ftl_dev_init_bands_md(struct spdk_ftl_dev * dev)879dbdb029SKozlowski Mateusz ftl_dev_init_bands_md(struct spdk_ftl_dev *dev)
889dbdb029SKozlowski Mateusz {
899dbdb029SKozlowski Mateusz 	uint64_t i;
909dbdb029SKozlowski Mateusz 	int rc = 0;
919dbdb029SKozlowski Mateusz 
929dbdb029SKozlowski Mateusz 	for (i = 0; i < ftl_get_num_bands(dev); ++i) {
939dbdb029SKozlowski Mateusz 		rc = ftl_band_init_md(&dev->bands[i]);
949dbdb029SKozlowski Mateusz 		if (rc) {
959dbdb029SKozlowski Mateusz 			FTL_ERRLOG(dev, "Failed to initialize metadata structures for band [%lu]\n", i);
969dbdb029SKozlowski Mateusz 			break;
979dbdb029SKozlowski Mateusz 		}
989dbdb029SKozlowski Mateusz 	}
999dbdb029SKozlowski Mateusz 
1009dbdb029SKozlowski Mateusz 	return rc;
1019dbdb029SKozlowski Mateusz }
1029dbdb029SKozlowski Mateusz 
1039dbdb029SKozlowski Mateusz static void
ftl_dev_deinit_bands(struct spdk_ftl_dev * dev)1049dbdb029SKozlowski Mateusz ftl_dev_deinit_bands(struct spdk_ftl_dev *dev)
1059dbdb029SKozlowski Mateusz {
1069dbdb029SKozlowski Mateusz 	free(dev->bands);
1079dbdb029SKozlowski Mateusz }
1089dbdb029SKozlowski Mateusz 
109cea8dadeSArtur Paszkiewicz static void
ftl_dev_deinit_bands_md(struct spdk_ftl_dev * dev)110cea8dadeSArtur Paszkiewicz ftl_dev_deinit_bands_md(struct spdk_ftl_dev *dev)
111cea8dadeSArtur Paszkiewicz {
112cea8dadeSArtur Paszkiewicz 	if (dev->bands) {
113cea8dadeSArtur Paszkiewicz 		uint64_t i;
114cea8dadeSArtur Paszkiewicz 		for (i = 0; i < dev->num_bands; ++i) {
115cea8dadeSArtur Paszkiewicz 			struct ftl_band *band = &dev->bands[i];
116cea8dadeSArtur Paszkiewicz 
117cea8dadeSArtur Paszkiewicz 			ftl_bitmap_destroy(band->p2l_map.valid);
118cea8dadeSArtur Paszkiewicz 			band->p2l_map.valid = NULL;
119cea8dadeSArtur Paszkiewicz 
120cea8dadeSArtur Paszkiewicz 			band->md = NULL;
121cea8dadeSArtur Paszkiewicz 		}
122cea8dadeSArtur Paszkiewicz 	}
123cea8dadeSArtur Paszkiewicz }
124cea8dadeSArtur Paszkiewicz 
1259dbdb029SKozlowski Mateusz void
ftl_mngt_init_bands(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)1269dbdb029SKozlowski Mateusz ftl_mngt_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1279dbdb029SKozlowski Mateusz {
1289dbdb029SKozlowski Mateusz 	if (ftl_dev_init_bands(dev)) {
1299dbdb029SKozlowski Mateusz 		ftl_mngt_fail_step(mngt);
1309dbdb029SKozlowski Mateusz 	} else {
1319dbdb029SKozlowski Mateusz 		ftl_mngt_next_step(mngt);
1329dbdb029SKozlowski Mateusz 	}
1339dbdb029SKozlowski Mateusz }
1349dbdb029SKozlowski Mateusz 
1359dbdb029SKozlowski Mateusz void
ftl_mngt_init_bands_md(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)1369dbdb029SKozlowski Mateusz ftl_mngt_init_bands_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1379dbdb029SKozlowski Mateusz {
1389dbdb029SKozlowski Mateusz 	if (ftl_dev_init_bands_md(dev)) {
1399dbdb029SKozlowski Mateusz 		ftl_mngt_fail_step(mngt);
1409dbdb029SKozlowski Mateusz 	} else {
1419dbdb029SKozlowski Mateusz 		ftl_mngt_next_step(mngt);
1429dbdb029SKozlowski Mateusz 	}
1439dbdb029SKozlowski Mateusz }
1449dbdb029SKozlowski Mateusz 
1459dbdb029SKozlowski Mateusz void
ftl_mngt_deinit_bands(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)1469dbdb029SKozlowski Mateusz ftl_mngt_deinit_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
1479dbdb029SKozlowski Mateusz {
1489dbdb029SKozlowski Mateusz 	ftl_dev_deinit_bands(dev);
1499dbdb029SKozlowski Mateusz 	ftl_mngt_next_step(mngt);
1509dbdb029SKozlowski Mateusz }
1519dbdb029SKozlowski Mateusz 
152cea8dadeSArtur Paszkiewicz void
ftl_mngt_deinit_bands_md(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)153cea8dadeSArtur Paszkiewicz ftl_mngt_deinit_bands_md(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
154cea8dadeSArtur Paszkiewicz {
155cea8dadeSArtur Paszkiewicz 	ftl_dev_deinit_bands_md(dev);
156cea8dadeSArtur Paszkiewicz 	ftl_mngt_next_step(mngt);
157cea8dadeSArtur Paszkiewicz }
158cea8dadeSArtur Paszkiewicz 
1599dbdb029SKozlowski Mateusz /*
1609dbdb029SKozlowski Mateusz  * For grouping multiple logical bands (1GiB) to make any IOs more sequential from the drive's
1619dbdb029SKozlowski Mateusz  * perspective. Improves WAF.
1629dbdb029SKozlowski Mateusz  */
1639dbdb029SKozlowski Mateusz #define BASE_BDEV_RECLAIM_UNIT_SIZE (72 * GiB)
1649dbdb029SKozlowski Mateusz 
1659dbdb029SKozlowski Mateusz static void
decorate_bands(struct spdk_ftl_dev * dev)1669dbdb029SKozlowski Mateusz decorate_bands(struct spdk_ftl_dev *dev)
1679dbdb029SKozlowski Mateusz {
1689dbdb029SKozlowski Mateusz 	struct ftl_band *band;
1699dbdb029SKozlowski Mateusz 	uint64_t i, num_to_drop, phys_id = 0;
1709dbdb029SKozlowski Mateusz 	uint64_t num_blocks, num_bands;
1719dbdb029SKozlowski Mateusz 	uint64_t num_blocks_in_band = ftl_get_num_blocks_in_band(dev);
1729dbdb029SKozlowski Mateusz 	uint64_t reclaim_unit_num_blocks = BASE_BDEV_RECLAIM_UNIT_SIZE / FTL_BLOCK_SIZE;
1739dbdb029SKozlowski Mateusz 	uint32_t num_logical_in_phys = 2;
1749dbdb029SKozlowski Mateusz 
1759dbdb029SKozlowski Mateusz 	assert(reclaim_unit_num_blocks % num_blocks_in_band == 0);
1769dbdb029SKozlowski Mateusz 
1779dbdb029SKozlowski Mateusz 	num_blocks = spdk_bdev_get_num_blocks(spdk_bdev_desc_get_bdev(dev->base_bdev_desc));
1789dbdb029SKozlowski Mateusz 
1799dbdb029SKozlowski Mateusz 	/* For base bdev bigger than 1TB take reclaim uint size for grouping GC bands */
1809dbdb029SKozlowski Mateusz 	if (num_blocks > (TiB / FTL_BLOCK_SIZE)) {
1819dbdb029SKozlowski Mateusz 		assert(reclaim_unit_num_blocks < num_blocks);
1829dbdb029SKozlowski Mateusz 		num_logical_in_phys = reclaim_unit_num_blocks / num_blocks_in_band;
1839dbdb029SKozlowski Mateusz 	}
1849dbdb029SKozlowski Mateusz 
1859dbdb029SKozlowski Mateusz 	num_to_drop = ftl_get_num_bands(dev) % num_logical_in_phys;
1869dbdb029SKozlowski Mateusz 
1879dbdb029SKozlowski Mateusz 	i = 0;
1889dbdb029SKozlowski Mateusz 	while (i < ftl_get_num_bands(dev) - num_to_drop) {
1899dbdb029SKozlowski Mateusz 		band = &dev->bands[i];
1909dbdb029SKozlowski Mateusz 
1919dbdb029SKozlowski Mateusz 		band->phys_id = phys_id;
1929dbdb029SKozlowski Mateusz 		i++;
1939dbdb029SKozlowski Mateusz 		if (i % num_logical_in_phys == 0) {
1949dbdb029SKozlowski Mateusz 			phys_id++;
1959dbdb029SKozlowski Mateusz 		}
1969dbdb029SKozlowski Mateusz 	}
1979dbdb029SKozlowski Mateusz 
1989dbdb029SKozlowski Mateusz 	/* Mark not aligned logical bands as broken */
1999dbdb029SKozlowski Mateusz 	num_bands = ftl_get_num_bands(dev);
2009dbdb029SKozlowski Mateusz 	while (i < num_bands) {
2019dbdb029SKozlowski Mateusz 		band = &dev->bands[i];
2029dbdb029SKozlowski Mateusz 		dev->num_bands--;
2039dbdb029SKozlowski Mateusz 		TAILQ_REMOVE(&dev->shut_bands, band, queue_entry);
2049dbdb029SKozlowski Mateusz 		i++;
2059dbdb029SKozlowski Mateusz 	}
206711759a0SKozlowski Mateusz 
207711759a0SKozlowski Mateusz 	dev->num_logical_bands_in_physical = num_logical_in_phys;
2089dbdb029SKozlowski Mateusz }
2099dbdb029SKozlowski Mateusz 
2109dbdb029SKozlowski Mateusz void
ftl_mngt_decorate_bands(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)2119dbdb029SKozlowski Mateusz ftl_mngt_decorate_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
2129dbdb029SKozlowski Mateusz {
2139dbdb029SKozlowski Mateusz 	decorate_bands(dev);
2149dbdb029SKozlowski Mateusz 	ftl_mngt_next_step(mngt);
2159dbdb029SKozlowski Mateusz }
2169dbdb029SKozlowski Mateusz 
21736049672SArtur Paszkiewicz void
ftl_mngt_initialize_band_address(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)218c3321813SKozlowski Mateusz ftl_mngt_initialize_band_address(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
219c3321813SKozlowski Mateusz {
220c3321813SKozlowski Mateusz 	struct ftl_band *band;
221c3321813SKozlowski Mateusz 	struct ftl_md *data_md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_DATA_BASE];
222c3321813SKozlowski Mateusz 	uint64_t i;
223c3321813SKozlowski Mateusz 
224c3321813SKozlowski Mateusz 	for (i = 0; i < ftl_get_num_bands(dev); i++) {
225c3321813SKozlowski Mateusz 		band = &dev->bands[i];
226c3321813SKozlowski Mateusz 		band->start_addr = data_md->region->current.offset + i * dev->num_blocks_in_band;
227c3321813SKozlowski Mateusz 		band->tail_md_addr = ftl_band_tail_md_addr(band);
228c3321813SKozlowski Mateusz 	}
229c3321813SKozlowski Mateusz 
230c3321813SKozlowski Mateusz 	ftl_mngt_next_step(mngt);
231c3321813SKozlowski Mateusz }
232c3321813SKozlowski Mateusz 
233c3321813SKozlowski Mateusz void
ftl_recover_max_seq(struct spdk_ftl_dev * dev)23436049672SArtur Paszkiewicz ftl_recover_max_seq(struct spdk_ftl_dev *dev)
23536049672SArtur Paszkiewicz {
23636049672SArtur Paszkiewicz 	struct ftl_band *band;
237ca0c4dcdSMateusz Kozlowski 	uint64_t band_close_seq_id = 0, band_open_seq_id = 0;
238ca0c4dcdSMateusz Kozlowski 	uint64_t chunk_close_seq_id = 0, chunk_open_seq_id = 0;
239ca0c4dcdSMateusz Kozlowski 	uint64_t max = 0;
24036049672SArtur Paszkiewicz 
24136049672SArtur Paszkiewicz 	TAILQ_FOREACH(band, &dev->shut_bands, queue_entry) {
24236049672SArtur Paszkiewicz 		band_open_seq_id = spdk_max(band_open_seq_id, band->md->seq);
24336049672SArtur Paszkiewicz 		band_close_seq_id = spdk_max(band_close_seq_id, band->md->close_seq_id);
24436049672SArtur Paszkiewicz 	}
24536049672SArtur Paszkiewicz 	ftl_nv_cache_get_max_seq_id(&dev->nv_cache, &chunk_open_seq_id, &chunk_close_seq_id);
24636049672SArtur Paszkiewicz 
24736049672SArtur Paszkiewicz 
24836049672SArtur Paszkiewicz 	dev->nv_cache.last_seq_id = chunk_close_seq_id;
24936049672SArtur Paszkiewicz 	dev->writer_gc.last_seq_id = band_close_seq_id;
25036049672SArtur Paszkiewicz 	dev->writer_user.last_seq_id = band_close_seq_id;
25136049672SArtur Paszkiewicz 
25236049672SArtur Paszkiewicz 	max = spdk_max(max, band_open_seq_id);
25336049672SArtur Paszkiewicz 	max = spdk_max(max, band_close_seq_id);
25436049672SArtur Paszkiewicz 	max = spdk_max(max, chunk_open_seq_id);
25536049672SArtur Paszkiewicz 	max = spdk_max(max, chunk_close_seq_id);
25636049672SArtur Paszkiewicz 
25736049672SArtur Paszkiewicz 	dev->sb->seq_id = max;
25836049672SArtur Paszkiewicz }
25936049672SArtur Paszkiewicz 
26036049672SArtur Paszkiewicz static int
_band_cmp(const void * _a,const void * _b)26136049672SArtur Paszkiewicz _band_cmp(const void *_a, const void *_b)
26236049672SArtur Paszkiewicz {
26336049672SArtur Paszkiewicz 	struct ftl_band *a, *b;
26436049672SArtur Paszkiewicz 
26536049672SArtur Paszkiewicz 	a = *((struct ftl_band **)_a);
26636049672SArtur Paszkiewicz 	b = *((struct ftl_band **)_b);
26736049672SArtur Paszkiewicz 
26836049672SArtur Paszkiewicz 	return a->md->seq - b->md->seq;
26936049672SArtur Paszkiewicz }
27036049672SArtur Paszkiewicz 
271711759a0SKozlowski Mateusz static struct ftl_band *
next_high_prio_band(struct spdk_ftl_dev * dev)272711759a0SKozlowski Mateusz next_high_prio_band(struct spdk_ftl_dev *dev)
273711759a0SKozlowski Mateusz {
274711759a0SKozlowski Mateusz 	struct ftl_band *result = NULL, *band;
275711759a0SKozlowski Mateusz 	uint64_t validity = UINT64_MAX;
276711759a0SKozlowski Mateusz 
277711759a0SKozlowski Mateusz 	TAILQ_FOREACH(band, &dev->shut_bands, queue_entry) {
278711759a0SKozlowski Mateusz 		if (band->p2l_map.num_valid < validity) {
279711759a0SKozlowski Mateusz 			result = band;
280711759a0SKozlowski Mateusz 			validity = result->p2l_map.num_valid;
281711759a0SKozlowski Mateusz 		}
282711759a0SKozlowski Mateusz 	}
283711759a0SKozlowski Mateusz 
284711759a0SKozlowski Mateusz 	return result;
285711759a0SKozlowski Mateusz }
286711759a0SKozlowski Mateusz 
287711759a0SKozlowski Mateusz static int
finalize_init_gc(struct spdk_ftl_dev * dev)288711759a0SKozlowski Mateusz finalize_init_gc(struct spdk_ftl_dev *dev)
289711759a0SKozlowski Mateusz {
290711759a0SKozlowski Mateusz 	struct ftl_band *band;
291711759a0SKozlowski Mateusz 	uint64_t free_blocks, blocks_to_move;
292711759a0SKozlowski Mateusz 
293711759a0SKozlowski Mateusz 	ftl_band_init_gc_iter(dev);
294711759a0SKozlowski Mateusz 	dev->sb_shm->gc_info.band_id_high_prio = FTL_BAND_ID_INVALID;
295711759a0SKozlowski Mateusz 
296711759a0SKozlowski Mateusz 	if (0 == dev->num_free) {
297711759a0SKozlowski Mateusz 		/* Get number of available blocks in writer */
298711759a0SKozlowski Mateusz 		free_blocks = ftl_writer_get_free_blocks(&dev->writer_gc);
299711759a0SKozlowski Mateusz 
300711759a0SKozlowski Mateusz 		/*
301711759a0SKozlowski Mateusz 		 * First, check a band candidate to GC
302711759a0SKozlowski Mateusz 		 */
303711759a0SKozlowski Mateusz 		band = ftl_band_search_next_to_reloc(dev);
304711759a0SKozlowski Mateusz 		ftl_bug(NULL == band);
305711759a0SKozlowski Mateusz 		blocks_to_move = band->p2l_map.num_valid;
306711759a0SKozlowski Mateusz 		if (blocks_to_move <= free_blocks) {
307711759a0SKozlowski Mateusz 			/* This GC band can be moved */
308711759a0SKozlowski Mateusz 			return 0;
309711759a0SKozlowski Mateusz 		}
310711759a0SKozlowski Mateusz 
311711759a0SKozlowski Mateusz 		/*
312711759a0SKozlowski Mateusz 		 * The GC candidate cannot be moved because no enough space. We need to find
313711759a0SKozlowski Mateusz 		 * another band.
314711759a0SKozlowski Mateusz 		 */
315711759a0SKozlowski Mateusz 		band = next_high_prio_band(dev);
316711759a0SKozlowski Mateusz 		ftl_bug(NULL == band);
317711759a0SKozlowski Mateusz 
318711759a0SKozlowski Mateusz 		if (band->p2l_map.num_valid > free_blocks) {
319711759a0SKozlowski Mateusz 			FTL_ERRLOG(dev, "CRITICAL ERROR, no more free bands and cannot start\n");
320711759a0SKozlowski Mateusz 			return -1;
321711759a0SKozlowski Mateusz 		} else {
322711759a0SKozlowski Mateusz 			/* GC needs to start using this band */
323711759a0SKozlowski Mateusz 			dev->sb_shm->gc_info.band_id_high_prio = band->id;
324711759a0SKozlowski Mateusz 		}
325711759a0SKozlowski Mateusz 	}
326711759a0SKozlowski Mateusz 
327711759a0SKozlowski Mateusz 	return 0;
328711759a0SKozlowski Mateusz }
329711759a0SKozlowski Mateusz 
330b5cf795bSMateusz Kozlowski static void
ftl_property_dump_base_dev(struct spdk_ftl_dev * dev,const struct ftl_property * property,struct spdk_json_write_ctx * w)331b5cf795bSMateusz Kozlowski ftl_property_dump_base_dev(struct spdk_ftl_dev *dev, const struct ftl_property *property,
332b5cf795bSMateusz Kozlowski 			   struct spdk_json_write_ctx *w)
333b5cf795bSMateusz Kozlowski {
334b5cf795bSMateusz Kozlowski 	uint64_t i;
335b5cf795bSMateusz Kozlowski 	struct ftl_band *band;
336b5cf795bSMateusz Kozlowski 
337b5cf795bSMateusz Kozlowski 	spdk_json_write_named_array_begin(w, "bands");
338b5cf795bSMateusz Kozlowski 	for (i = 0, band = dev->bands; i < ftl_get_num_bands(dev); i++, band++) {
339b5cf795bSMateusz Kozlowski 		spdk_json_write_object_begin(w);
340b5cf795bSMateusz Kozlowski 		spdk_json_write_named_uint64(w, "id", i);
341b5cf795bSMateusz Kozlowski 		spdk_json_write_named_string(w, "state", ftl_band_get_state_name(band));
342b5cf795bSMateusz Kozlowski 		spdk_json_write_named_double(w, "validity", 1.0 - ftl_band_invalidity(band));
343b5cf795bSMateusz Kozlowski 		spdk_json_write_object_end(w);
344b5cf795bSMateusz Kozlowski 	}
345b5cf795bSMateusz Kozlowski 	spdk_json_write_array_end(w);
346b5cf795bSMateusz Kozlowski }
347b5cf795bSMateusz Kozlowski 
3489dbdb029SKozlowski Mateusz void
ftl_mngt_finalize_init_bands(struct spdk_ftl_dev * dev,struct ftl_mngt_process * mngt)3499dbdb029SKozlowski Mateusz ftl_mngt_finalize_init_bands(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
3509dbdb029SKozlowski Mateusz {
35131cf6336SKozlowski Mateusz 	struct ftl_band *band, *temp_band, *open_bands[FTL_MAX_OPEN_BANDS];
352dcf30711SSzulik, Maciej 	struct ftl_writer *writer = NULL;
35331cf6336SKozlowski Mateusz 	uint64_t i, num_open = 0, num_shut = 0;
35431cf6336SKozlowski Mateusz 	uint64_t offset;
3551e904e2bSArtur Paszkiewicz 	bool fast_startup = ftl_fast_startup(dev);
3569dbdb029SKozlowski Mateusz 
35736049672SArtur Paszkiewicz 	ftl_recover_max_seq(dev);
358b5cf795bSMateusz Kozlowski 	ftl_property_register(dev, "base_device", NULL, 0, NULL, NULL, ftl_property_dump_base_dev, NULL,
359b5cf795bSMateusz Kozlowski 			      NULL, true);
36036049672SArtur Paszkiewicz 
361101a0399SKozlowski Mateusz 	TAILQ_FOREACH_SAFE(band, &dev->free_bands, queue_entry, temp_band) {
362101a0399SKozlowski Mateusz 		band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
363101a0399SKozlowski Mateusz 	}
364101a0399SKozlowski Mateusz 
3659dbdb029SKozlowski Mateusz 	TAILQ_FOREACH_SAFE(band, &dev->shut_bands, queue_entry, temp_band) {
3669dbdb029SKozlowski Mateusz 		if (band->md->state == FTL_BAND_STATE_OPEN ||
3679dbdb029SKozlowski Mateusz 		    band->md->state == FTL_BAND_STATE_FULL) {
3689dbdb029SKozlowski Mateusz 			TAILQ_REMOVE(&dev->shut_bands, band, queue_entry);
36931cf6336SKozlowski Mateusz 			open_bands[num_open++] = band;
3709dbdb029SKozlowski Mateusz 			assert(num_open <= FTL_MAX_OPEN_BANDS);
3719dbdb029SKozlowski Mateusz 			continue;
3729dbdb029SKozlowski Mateusz 		}
3739dbdb029SKozlowski Mateusz 
3749dbdb029SKozlowski Mateusz 		if (dev->conf.mode & SPDK_FTL_MODE_CREATE) {
3759dbdb029SKozlowski Mateusz 			TAILQ_REMOVE(&dev->shut_bands, band, queue_entry);
3769dbdb029SKozlowski Mateusz 			assert(band->md->state == FTL_BAND_STATE_FREE);
3779dbdb029SKozlowski Mateusz 			band->md->state = FTL_BAND_STATE_CLOSED;
3789dbdb029SKozlowski Mateusz 			ftl_band_set_state(band, FTL_BAND_STATE_FREE);
3799dbdb029SKozlowski Mateusz 		} else {
3809dbdb029SKozlowski Mateusz 			num_shut++;
3819dbdb029SKozlowski Mateusz 		}
382101a0399SKozlowski Mateusz 
383101a0399SKozlowski Mateusz 		band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
3849dbdb029SKozlowski Mateusz 	}
3859dbdb029SKozlowski Mateusz 
38631cf6336SKozlowski Mateusz 	/* Assign open bands to writers and alloc necessary resources */
38736049672SArtur Paszkiewicz 	qsort(open_bands, num_open, sizeof(open_bands[0]), _band_cmp);
38836049672SArtur Paszkiewicz 
38931cf6336SKozlowski Mateusz 	for (i = 0; i < num_open; ++i) {
39031cf6336SKozlowski Mateusz 		band = open_bands[i];
39131cf6336SKozlowski Mateusz 
39231cf6336SKozlowski Mateusz 		if (band->md->type == FTL_BAND_TYPE_COMPACTION) {
39331cf6336SKozlowski Mateusz 			writer = &dev->writer_user;
39431cf6336SKozlowski Mateusz 		} else if (band->md->type == FTL_BAND_TYPE_GC) {
39531cf6336SKozlowski Mateusz 			writer = &dev->writer_gc;
39631cf6336SKozlowski Mateusz 		} else {
39731cf6336SKozlowski Mateusz 			assert(false);
39831cf6336SKozlowski Mateusz 		}
39931cf6336SKozlowski Mateusz 
40031cf6336SKozlowski Mateusz 		if (band->md->state == FTL_BAND_STATE_FULL) {
40131cf6336SKozlowski Mateusz 			TAILQ_INSERT_TAIL(&writer->full_bands, band, queue_entry);
40231cf6336SKozlowski Mateusz 		} else {
40331cf6336SKozlowski Mateusz 			if (writer->band == NULL) {
40431cf6336SKozlowski Mateusz 				writer->band = band;
40531cf6336SKozlowski Mateusz 			} else {
40631cf6336SKozlowski Mateusz 				writer->next_band = band;
40731cf6336SKozlowski Mateusz 			}
40831cf6336SKozlowski Mateusz 		}
40931cf6336SKozlowski Mateusz 
41031cf6336SKozlowski Mateusz 		writer->num_bands++;
41131cf6336SKozlowski Mateusz 		ftl_band_set_owner(band, ftl_writer_band_state_change, writer);
41231cf6336SKozlowski Mateusz 
4131e904e2bSArtur Paszkiewicz 		if (fast_startup) {
4141e904e2bSArtur Paszkiewicz 			FTL_NOTICELOG(dev, "SHM: band open P2L map df_id 0x%"PRIx64"\n", band->md->df_p2l_map);
4151e904e2bSArtur Paszkiewicz 			if (ftl_band_open_p2l_map(band)) {
4161e904e2bSArtur Paszkiewicz 				ftl_mngt_fail_step(mngt);
4171e904e2bSArtur Paszkiewicz 				return;
4181e904e2bSArtur Paszkiewicz 			}
4191e904e2bSArtur Paszkiewicz 
4201e904e2bSArtur Paszkiewicz 			offset = band->md->iter.offset;
4211e904e2bSArtur Paszkiewicz 			ftl_band_iter_init(band);
4221e904e2bSArtur Paszkiewicz 			ftl_band_iter_set(band, offset);
4231738488eSArtur Paszkiewicz 			ftl_mngt_p2l_ckpt_restore_shm_clean(band);
4241e904e2bSArtur Paszkiewicz 		} else if (dev->sb->clean) {
425101a0399SKozlowski Mateusz 			band->md->df_p2l_map = FTL_DF_OBJ_ID_INVALID;
42631cf6336SKozlowski Mateusz 			if (ftl_band_alloc_p2l_map(band)) {
42731cf6336SKozlowski Mateusz 				ftl_mngt_fail_step(mngt);
42831cf6336SKozlowski Mateusz 				return;
42931cf6336SKozlowski Mateusz 			}
43031cf6336SKozlowski Mateusz 
43131cf6336SKozlowski Mateusz 			offset = band->md->iter.offset;
43231cf6336SKozlowski Mateusz 			ftl_band_iter_init(band);
43331cf6336SKozlowski Mateusz 			ftl_band_iter_set(band, offset);
4341738488eSArtur Paszkiewicz 
4351738488eSArtur Paszkiewicz 			if (ftl_mngt_p2l_ckpt_restore_clean(band)) {
4361738488eSArtur Paszkiewicz 				ftl_mngt_fail_step(mngt);
4371738488eSArtur Paszkiewicz 				return;
4381738488eSArtur Paszkiewicz 			}
43931cf6336SKozlowski Mateusz 		}
44031cf6336SKozlowski Mateusz 	}
44131cf6336SKozlowski Mateusz 
4421e904e2bSArtur Paszkiewicz 	if (fast_startup) {
4431e904e2bSArtur Paszkiewicz 		ftl_mempool_initialize_ext(dev->p2l_pool);
4441e904e2bSArtur Paszkiewicz 	}
4451e904e2bSArtur Paszkiewicz 
4461e904e2bSArtur Paszkiewicz 
4479dbdb029SKozlowski Mateusz 	/* Recalculate number of free bands */
4489dbdb029SKozlowski Mateusz 	dev->num_free = 0;
4499dbdb029SKozlowski Mateusz 	TAILQ_FOREACH(band, &dev->free_bands, queue_entry) {
4509dbdb029SKozlowski Mateusz 		assert(band->md->state == FTL_BAND_STATE_FREE);
4519dbdb029SKozlowski Mateusz 		dev->num_free++;
4529dbdb029SKozlowski Mateusz 	}
4539dbdb029SKozlowski Mateusz 	ftl_apply_limits(dev);
4549dbdb029SKozlowski Mateusz 
4559dbdb029SKozlowski Mateusz 	if ((num_shut + num_open + dev->num_free) != ftl_get_num_bands(dev)) {
4569dbdb029SKozlowski Mateusz 		FTL_ERRLOG(dev, "ERROR, band list inconsistent state\n");
4579dbdb029SKozlowski Mateusz 		ftl_mngt_fail_step(mngt);
4589dbdb029SKozlowski Mateusz 		return;
4599dbdb029SKozlowski Mateusz 	}
4609dbdb029SKozlowski Mateusz 
461711759a0SKozlowski Mateusz 	if (finalize_init_gc(dev)) {
462711759a0SKozlowski Mateusz 		ftl_mngt_fail_step(mngt);
463711759a0SKozlowski Mateusz 	} else {
4649dbdb029SKozlowski Mateusz 		ftl_mngt_next_step(mngt);
4659dbdb029SKozlowski Mateusz 	}
466711759a0SKozlowski Mateusz }
467