diff --git a/lib/ftl/ftl_band.c b/lib/ftl/ftl_band.c index 6e649f6fc..ba49e30e0 100644 --- a/lib/ftl/ftl_band.c +++ b/lib/ftl/ftl_band.c @@ -139,11 +139,7 @@ ftl_band_write_failed(struct ftl_band *band) band->high_prio = 1; - if (!dev->df_band) { - dev->df_band = band; - } - - ftl_reloc_add(dev->reloc, band, 0, ftl_num_band_lbks(dev), 1); + ftl_reloc_add(dev->reloc, band, 0, ftl_num_band_lbks(dev), 1, true); ftl_band_set_state(band, FTL_BAND_STATE_CLOSED); } @@ -175,10 +171,6 @@ _ftl_band_set_free(struct ftl_band *band) struct spdk_ftl_dev *dev = band->dev; struct ftl_band *lband, *prev; - if (band == dev->df_band) { - dev->df_band = NULL; - } - /* Remove the band from the closed band list */ LIST_REMOVE(band, list_entry); diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 825bedeaf..07398ed12 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -1792,7 +1792,7 @@ ftl_dev_needs_defrag(struct spdk_ftl_dev *dev) return false; } - if (dev->df_band) { + if (ftl_reloc_is_defrag_active(dev->reloc)) { return false; } @@ -1867,10 +1867,9 @@ ftl_process_relocs(struct spdk_ftl_dev *dev) struct ftl_band *band; if (ftl_dev_needs_defrag(dev)) { - band = dev->df_band = ftl_select_defrag_band(dev); - + band = ftl_select_defrag_band(dev); if (band) { - ftl_reloc_add(dev->reloc, band, 0, ftl_num_band_lbks(dev), 0); + ftl_reloc_add(dev->reloc, band, 0, ftl_num_band_lbks(dev), 0, true); ftl_trace_defrag_band(dev, band); } } @@ -2135,7 +2134,7 @@ ftl_process_anm_event(struct ftl_anm_event *event) band = ftl_band_from_ppa(dev, event->ppa); lbkoff = ftl_band_lbkoff_from_ppa(band, event->ppa); - ftl_reloc_add(dev->reloc, band, lbkoff, event->num_lbks, 0); + ftl_reloc_add(dev->reloc, band, lbkoff, event->num_lbks, 0, false); ftl_anm_event_complete(event); } diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index e07f7867e..0684ea49b 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -191,8 +191,6 @@ struct spdk_ftl_dev { /* Array of bands */ struct ftl_band *bands; - /* Band being curently defraged */ - struct ftl_band *df_band; /* Number of operational bands */ size_t num_bands; /* Next write band */ diff --git a/lib/ftl/ftl_reloc.c b/lib/ftl/ftl_reloc.c index 12c1ab40a..9748264f5 100644 --- a/lib/ftl/ftl_reloc.c +++ b/lib/ftl/ftl_reloc.c @@ -87,6 +87,8 @@ struct ftl_band_reloc { /* Indicates band being acitvely processed */ int active; + /* The band is being defragged */ + bool defrag; /* Reloc map iterator */ struct { @@ -124,6 +126,8 @@ struct ftl_reloc { /* Maximum transfer size (in logical blocks) per single IO */ size_t xfer_size; + /* Number of bands being defragged */ + size_t num_defrag_bands; /* Array of band relocates */ struct ftl_band_reloc *brelocs; @@ -141,6 +145,12 @@ struct ftl_reloc { TAILQ_HEAD(, ftl_band_reloc) pending_queue; }; +bool +ftl_reloc_is_defrag_active(const struct ftl_reloc *reloc) +{ + return reloc->num_defrag_bands > 0; +} + static size_t ftl_reloc_iter_chk_offset(struct ftl_band_reloc *breloc) { @@ -169,7 +179,6 @@ ftl_reloc_clr_lbk(struct ftl_band_reloc *breloc, size_t lbkoff) breloc->num_lbks--; } - static void ftl_reloc_read_lba_map_cb(struct ftl_io *io, void *arg, int status) { @@ -563,6 +572,12 @@ ftl_reloc_release(struct ftl_band_reloc *breloc) if (ftl_band_empty(band) && band->state == FTL_BAND_STATE_CLOSED) { ftl_band_set_state(breloc->band, FTL_BAND_STATE_FREE); + + if (breloc->defrag) { + breloc->defrag = false; + assert(reloc->num_defrag_bands > 0); + reloc->num_defrag_bands--; + } } } @@ -670,6 +685,7 @@ ftl_reloc_init(struct spdk_ftl_dev *dev) reloc->max_qdepth = dev->conf.max_reloc_qdepth; reloc->max_active = dev->conf.max_active_relocs; reloc->xfer_size = dev->xfer_size; + reloc->num_defrag_bands = 0; if (reloc->max_qdepth > FTL_RELOC_MAX_MOVES) { goto error; @@ -775,7 +791,7 @@ ftl_reloc(struct ftl_reloc *reloc) void ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset, - size_t num_lbks, int prio) + size_t num_lbks, int prio, bool is_defrag) { struct ftl_band_reloc *breloc = &reloc->brelocs[band->id]; size_t i, prev_lbks = breloc->num_lbks; @@ -788,6 +804,12 @@ ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset, pthread_spin_lock(&band->lba_map.lock); if (band->lba_map.num_vld == 0) { pthread_spin_unlock(&band->lba_map.lock); + + /* If the band is closed and has no valid blocks, free it */ + if (band->state == FTL_BAND_STATE_CLOSED) { + ftl_band_set_state(band, FTL_BAND_STATE_FREE); + } + return; } pthread_spin_unlock(&band->lba_map.lock); @@ -804,6 +826,13 @@ ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset, return; } + /* If the band is coming from the defrag process, mark it appropriately */ + if (is_defrag) { + assert(offset == 0 && num_lbks == ftl_num_band_lbks(band->dev)); + reloc->num_defrag_bands++; + breloc->defrag = true; + } + if (!prev_lbks && !prio && !breloc->active) { TAILQ_INSERT_HEAD(&reloc->pending_queue, breloc, entry); } diff --git a/lib/ftl/ftl_reloc.h b/lib/ftl/ftl_reloc.h index fa50b8e1f..0dc772d32 100644 --- a/lib/ftl/ftl_reloc.h +++ b/lib/ftl/ftl_reloc.h @@ -43,9 +43,11 @@ struct ftl_band; struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev); void ftl_reloc_free(struct ftl_reloc *reloc); void ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, - size_t offset, size_t num_lbks, int prio); + size_t offset, size_t num_lbks, int prio, bool is_defrag); void ftl_reloc(struct ftl_reloc *reloc); void ftl_reloc_halt(struct ftl_reloc *reloc); void ftl_reloc_resume(struct ftl_reloc *reloc); bool ftl_reloc_is_halted(const struct ftl_reloc *reloc); +bool ftl_reloc_is_defrag_active(const struct ftl_reloc *reloc); + #endif /* FTL_RELOC_H */ diff --git a/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c b/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c index f28609307..53eeb11c4 100644 --- a/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c +++ b/test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c @@ -270,7 +270,7 @@ test_reloc_iter_full(void) set_band_valid_map(band, 0, ftl_num_band_lbks(dev)); - ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0); + ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0, true); CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev)); @@ -313,7 +313,7 @@ test_reloc_empty_band(void) breloc = &reloc->brelocs[0]; band = breloc->band; - ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0); + ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0, true); CU_ASSERT_EQUAL(breloc->num_lbks, 0); @@ -338,7 +338,7 @@ test_reloc_full_band(void) set_band_valid_map(band, 0, ftl_num_band_lbks(dev)); - ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0); + ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0, true); CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev)); @@ -384,7 +384,7 @@ test_reloc_scatter_band(void) } } - ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0); + ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0, true); ftl_reloc_add_active_queue(breloc); CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev)); @@ -422,7 +422,7 @@ test_reloc_chunk(void) set_band_valid_map(band, 0, ftl_num_band_lbks(dev)); ftl_reloc_add(reloc, band, ftl_dev_lbks_in_chunk(dev) * 3, - ftl_dev_lbks_in_chunk(dev), 1); + ftl_dev_lbks_in_chunk(dev), 1, false); ftl_reloc_add_active_queue(breloc); CU_ASSERT_EQUAL(breloc->num_lbks, ftl_dev_lbks_in_chunk(dev)); @@ -462,7 +462,7 @@ test_reloc_single_lbk(void) set_band_valid_map(band, TEST_RELOC_OFFSET, 1); - ftl_reloc_add(reloc, band, TEST_RELOC_OFFSET, 1, 0); + ftl_reloc_add(reloc, band, TEST_RELOC_OFFSET, 1, 0, false); SPDK_CU_ASSERT_FATAL(breloc == TAILQ_FIRST(&reloc->pending_queue)); ftl_reloc_add_active_queue(breloc); diff --git a/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c b/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c index ddd20bde4..3d1b33314 100644 --- a/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c +++ b/test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c @@ -63,7 +63,7 @@ DEFINE_STUB_V(ftl_io_fail, (struct ftl_io *io, int status)); DEFINE_STUB_V(ftl_trace_completion, (struct spdk_ftl_dev *dev, const struct ftl_io *io, enum ftl_trace_completion completion)); DEFINE_STUB_V(ftl_reloc_add, (struct ftl_reloc *reloc, struct ftl_band *band, size_t offset, - size_t num_lbks, int prio)); + size_t num_lbks, int prio, bool defrag)); DEFINE_STUB_V(ftl_trace_write_band, (struct spdk_ftl_dev *dev, const struct ftl_band *band)); DEFINE_STUB_V(ftl_trace_submission, (struct spdk_ftl_dev *dev, const struct ftl_io *io, struct ftl_ppa ppa, size_t ppa_cnt));