diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 3b0b39310..b364b211c 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -1015,83 +1015,13 @@ ftl_band_read_head_md(struct ftl_band *band, ftl_io_fn cb_fn, void *cb_ctx) cb_ctx); } -static void +void ftl_band_remove_zone(struct ftl_band *band, struct ftl_zone *zone) { CIRCLEQ_REMOVE(&band->zones, zone, circleq); band->num_zones--; } -static void -ftl_erase_fail(struct ftl_io *io, int status) -{ - struct ftl_zone *zone; - struct ftl_band *band = io->band; - char buf[128]; - - SPDK_ERRLOG("Erase failed @addr: %s, status: %d\n", - ftl_addr2str(io->addr, buf, sizeof(buf)), status); - - zone = ftl_band_zone_from_addr(band, io->addr); - zone->info.state = SPDK_BDEV_ZONE_STATE_OFFLINE; - ftl_band_remove_zone(band, zone); - band->tail_md_addr = ftl_band_tail_md_addr(band); -} - -static void -ftl_band_erase_cb(struct ftl_io *io, void *ctx, int status) -{ - struct ftl_zone *zone; - - zone = ftl_band_zone_from_addr(io->band, io->addr); - zone->busy = false; - - if (spdk_unlikely(status)) { - ftl_erase_fail(io, status); - return; - } - - zone->info.state = SPDK_BDEV_ZONE_STATE_EMPTY; - zone->info.write_pointer = zone->info.zone_id; -} - -int -ftl_band_erase(struct ftl_band *band) -{ - struct ftl_zone *zone; - struct ftl_io *io; - int rc = 0; - - assert(band->state == FTL_BAND_STATE_CLOSED || - band->state == FTL_BAND_STATE_FREE); - - ftl_band_set_state(band, FTL_BAND_STATE_PREP); - - CIRCLEQ_FOREACH(zone, &band->zones, circleq) { - if (zone->info.state == SPDK_BDEV_ZONE_STATE_EMPTY) { - continue; - } - - io = ftl_io_erase_init(band, 1, ftl_band_erase_cb); - if (!io) { - rc = -ENOMEM; - break; - } - - zone->busy = true; - io->addr.offset = zone->info.zone_id; - rc = ftl_io_erase(io); - if (rc) { - zone->busy = false; - assert(0); - /* TODO: change band's state back to close? */ - break; - } - } - - return rc; -} - int ftl_band_write_prep(struct ftl_band *band) { diff --git a/lib/ftl/ftl_band.h b/lib/ftl/ftl_band.h index 98145d75a..a7f6e65e7 100644 --- a/lib/ftl/ftl_band.h +++ b/lib/ftl/ftl_band.h @@ -214,11 +214,12 @@ struct ftl_addr ftl_band_tail_md_addr(struct ftl_band *band); struct ftl_addr ftl_band_head_md_addr(struct ftl_band *band); void ftl_band_write_failed(struct ftl_band *band); int ftl_band_full(struct ftl_band *band, size_t offset); -int ftl_band_erase(struct ftl_band *band); int ftl_band_write_prep(struct ftl_band *band); struct ftl_zone *ftl_band_next_operational_zone(struct ftl_band *band, struct ftl_zone *zone); size_t ftl_lba_map_pool_elem_size(struct spdk_ftl_dev *dev); +void ftl_band_remove_zone(struct ftl_band *band, struct ftl_zone *zone); + static inline int ftl_band_empty(const struct ftl_band *band) diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index b1f81a7a9..802005bfb 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -384,12 +384,6 @@ ftl_submit_erase(struct ftl_io *io) return rc; } -static void -_ftl_io_erase(void *ctx) -{ - ftl_io_erase((struct ftl_io *)ctx); -} - static bool ftl_check_core_thread(const struct spdk_ftl_dev *dev) { @@ -406,7 +400,15 @@ ftl_get_io_channel(const struct spdk_ftl_dev *dev) return NULL; } -int +static int ftl_io_erase(struct ftl_io *io); + +static void +_ftl_io_erase(void *ctx) +{ + ftl_io_erase((struct ftl_io *)ctx); +} + +static int ftl_io_erase(struct ftl_io *io) { struct spdk_ftl_dev *dev = io->dev; @@ -419,6 +421,76 @@ ftl_io_erase(struct ftl_io *io) return 0; } +static void +ftl_erase_fail(struct ftl_io *io, int status) +{ + struct ftl_zone *zone; + struct ftl_band *band = io->band; + char buf[128]; + + SPDK_ERRLOG("Erase failed at address: %s, status: %d\n", + ftl_addr2str(io->addr, buf, sizeof(buf)), status); + + zone = ftl_band_zone_from_addr(band, io->addr); + zone->info.state = SPDK_BDEV_ZONE_STATE_OFFLINE; + ftl_band_remove_zone(band, zone); + band->tail_md_addr = ftl_band_tail_md_addr(band); +} + +static void +ftl_zone_erase_cb(struct ftl_io *io, void *ctx, int status) +{ + struct ftl_zone *zone; + + zone = ftl_band_zone_from_addr(io->band, io->addr); + zone->busy = false; + + if (spdk_unlikely(status)) { + ftl_erase_fail(io, status); + return; + } + + zone->info.state = SPDK_BDEV_ZONE_STATE_EMPTY; + zone->info.write_pointer = zone->info.zone_id; +} + +static int +ftl_band_erase(struct ftl_band *band) +{ + struct ftl_zone *zone; + struct ftl_io *io; + int rc = 0; + + assert(band->state == FTL_BAND_STATE_CLOSED || + band->state == FTL_BAND_STATE_FREE); + + ftl_band_set_state(band, FTL_BAND_STATE_PREP); + + CIRCLEQ_FOREACH(zone, &band->zones, circleq) { + if (zone->info.state == SPDK_BDEV_ZONE_STATE_EMPTY) { + continue; + } + + io = ftl_io_erase_init(band, 1, ftl_zone_erase_cb); + if (!io) { + rc = -ENOMEM; + break; + } + + zone->busy = true; + io->addr.offset = zone->info.zone_id; + rc = ftl_io_erase(io); + if (rc) { + zone->busy = false; + assert(0); + /* TODO: change band's state back to close? */ + break; + } + } + + return rc; +} + static struct ftl_band * ftl_next_write_band(struct spdk_ftl_dev *dev) { diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index 51a51401c..77b4ba3d1 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -261,7 +261,6 @@ typedef void (*ftl_restore_fn)(struct spdk_ftl_dev *, struct ftl_restore *, int) void ftl_apply_limits(struct spdk_ftl_dev *dev); void ftl_io_read(struct ftl_io *io); void ftl_io_write(struct ftl_io *io); -int ftl_io_erase(struct ftl_io *io); int ftl_flush_rwb(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg); int ftl_current_limit(const struct spdk_ftl_dev *dev); int ftl_invalidate_addr(struct spdk_ftl_dev *dev, struct ftl_addr addr);