diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 55dae1689..098fe0928 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -59,6 +59,52 @@ ftl_band_free_md_entry(struct ftl_band *band) p2l_map->band_dma_md = NULL; } +static void +_ftl_band_set_free(struct ftl_band *band) +{ + struct spdk_ftl_dev *dev = band->dev; + + /* Add the band to the free band list */ + TAILQ_INSERT_TAIL(&dev->free_bands, band, queue_entry); + + dev->num_free++; + ftl_apply_limits(dev); +} + +static void +_ftl_band_set_preparing(struct ftl_band *band) +{ + struct spdk_ftl_dev *dev = band->dev; + + /* Remove band from free list */ + TAILQ_REMOVE(&dev->free_bands, band, queue_entry); + + band->md->wr_cnt++; + + assert(dev->num_free > 0); + dev->num_free--; + + ftl_apply_limits(dev); +} + +static void +_ftl_band_set_closed(struct ftl_band *band) +{ + struct spdk_ftl_dev *dev = band->dev; + + /* Set the state as free_md() checks for that */ + band->md->state = FTL_BAND_STATE_CLOSED; + if (band->owner.state_change_fn) { + band->owner.state_change_fn(band); + } + + /* Free the p2l map if there are no outstanding IOs */ + ftl_band_release_p2l_map(band); + assert(band->p2l_map.ref_cnt == 0); + + TAILQ_INSERT_TAIL(&dev->shut_bands, band, queue_entry); +} + ftl_addr ftl_band_tail_md_addr(struct ftl_band *band) { @@ -72,6 +118,46 @@ ftl_band_tail_md_addr(struct ftl_band *band) return addr; } +void +ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state) +{ + switch (state) { + case FTL_BAND_STATE_FREE: + assert(band->md->state == FTL_BAND_STATE_CLOSED); + _ftl_band_set_free(band); + + band->md->p2l_map_checksum = 0; + break; + + case FTL_BAND_STATE_PREP: + assert(band->md->state == FTL_BAND_STATE_FREE); + _ftl_band_set_preparing(band); + break; + + case FTL_BAND_STATE_CLOSED: + if (band->md->state != FTL_BAND_STATE_CLOSED) { + assert(band->md->state == FTL_BAND_STATE_CLOSING); + _ftl_band_set_closed(band); + return; /* state can be changed asynchronously */ + } + break; + + case FTL_BAND_STATE_OPEN: + band->md->p2l_map_checksum = 0; + break; + case FTL_BAND_STATE_OPENING: + case FTL_BAND_STATE_FULL: + case FTL_BAND_STATE_CLOSING: + break; + default: + FTL_ERRLOG(band->dev, "Unknown band state, %u", state); + assert(false); + break; + } + + band->md->state = state; +} + void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type) { diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 989ade21e..c5b4db087 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -26,6 +26,15 @@ spdk_ftl_io_size(void) return sizeof(struct ftl_io); } +static void +ftl_band_erase(struct ftl_band *band) +{ + assert(band->md->state == FTL_BAND_STATE_CLOSED || + band->md->state == FTL_BAND_STATE_FREE); + + ftl_band_set_state(band, FTL_BAND_STATE_PREP); +} + static size_t ftl_get_limit(const struct spdk_ftl_dev *dev, int type) { @@ -263,6 +272,20 @@ ftl_core_poller(void *ctx) return SPDK_POLLER_IDLE; } +struct ftl_band * +ftl_band_get_next_free(struct spdk_ftl_dev *dev) +{ + struct ftl_band *band = NULL; + + if (!TAILQ_EMPTY(&dev->free_bands)) { + band = TAILQ_FIRST(&dev->free_bands); + TAILQ_REMOVE(&dev->free_bands, band, queue_entry); + ftl_band_erase(band); + } + + return band; +} + void *g_ftl_write_buf; void *g_ftl_read_buf; diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index b5d14193c..a3b0a39c5 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -150,6 +150,8 @@ int ftl_io_channel_poll(void *arg); struct ftl_io_channel *ftl_io_channel_get_ctx(struct spdk_io_channel *ioch); +struct ftl_band *ftl_band_get_next_free(struct spdk_ftl_dev *dev); + static inline uint64_t ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev) { diff --git a/lib/ftl/ftl_io.c b/lib/ftl/ftl_io.c index 778367045..68c25a693 100644 --- a/lib/ftl/ftl_io.c +++ b/lib/ftl/ftl_io.c @@ -10,6 +10,7 @@ #include "ftl_io.h" #include "ftl_core.h" +#include "ftl_band.h" #include "ftl_debug.h" void @@ -238,4 +239,5 @@ ftl_io_clear(struct ftl_io *io) io->done = false; io->status = 0; io->flags = 0; + io->band = NULL; } diff --git a/lib/ftl/ftl_io.h b/lib/ftl/ftl_io.h index cfc620c24..50aed3cc7 100644 --- a/lib/ftl/ftl_io.h +++ b/lib/ftl/ftl_io.h @@ -88,6 +88,9 @@ struct ftl_io { /* Offset within the iovec (in blocks) */ size_t iov_off; + /* Band this IO is being written to */ + struct ftl_band *band; + /* Request status */ int status;