From 1f133d72795f58d39f44eaff5eb601581abf2a20 Mon Sep 17 00:00:00 2001 From: Konrad Sztyber Date: Wed, 21 Aug 2019 15:49:55 +0200 Subject: [PATCH] lib/ftl: track defragged bands in ftl_reloc Track the band under defrag inside the reloc module. This allows for multiple bands being defragged at the same time (e.g. extra one due to write fault) as well as makes it easier to handle cases when relocating a band that has no valid blocks. Change-Id: Ia54916571040f5f4dfdb8f7cdb47f28435a466d8 Signed-off-by: Konrad Sztyber Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465937 Tested-by: SPDK CI Jenkins Reviewed-by: Mateusz Kozlowski Reviewed-by: Darek Stojaczyk Reviewed-by: Jim Harris --- lib/ftl/ftl_band.c | 10 +----- lib/ftl/ftl_core.c | 9 +++--- lib/ftl/ftl_core.h | 2 -- lib/ftl/ftl_reloc.c | 33 ++++++++++++++++++-- lib/ftl/ftl_reloc.h | 4 ++- test/unit/lib/ftl/ftl_reloc.c/ftl_reloc_ut.c | 12 +++---- test/unit/lib/ftl/ftl_wptr/ftl_wptr_ut.c | 2 +- 7 files changed, 46 insertions(+), 26 deletions(-) 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));