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 <konrad.sztyber@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465937
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Mateusz Kozlowski <mateusz.kozlowski@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Konrad Sztyber 2019-08-21 15:49:55 +02:00 committed by Jim Harris
parent 407e88fd2a
commit 1f133d7279
7 changed files with 46 additions and 26 deletions

View File

@ -139,11 +139,7 @@ ftl_band_write_failed(struct ftl_band *band)
band->high_prio = 1; band->high_prio = 1;
if (!dev->df_band) { ftl_reloc_add(dev->reloc, band, 0, ftl_num_band_lbks(dev), 1, true);
dev->df_band = band;
}
ftl_reloc_add(dev->reloc, band, 0, ftl_num_band_lbks(dev), 1);
ftl_band_set_state(band, FTL_BAND_STATE_CLOSED); 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 spdk_ftl_dev *dev = band->dev;
struct ftl_band *lband, *prev; struct ftl_band *lband, *prev;
if (band == dev->df_band) {
dev->df_band = NULL;
}
/* Remove the band from the closed band list */ /* Remove the band from the closed band list */
LIST_REMOVE(band, list_entry); LIST_REMOVE(band, list_entry);

View File

@ -1792,7 +1792,7 @@ ftl_dev_needs_defrag(struct spdk_ftl_dev *dev)
return false; return false;
} }
if (dev->df_band) { if (ftl_reloc_is_defrag_active(dev->reloc)) {
return false; return false;
} }
@ -1867,10 +1867,9 @@ ftl_process_relocs(struct spdk_ftl_dev *dev)
struct ftl_band *band; struct ftl_band *band;
if (ftl_dev_needs_defrag(dev)) { if (ftl_dev_needs_defrag(dev)) {
band = dev->df_band = ftl_select_defrag_band(dev); band = ftl_select_defrag_band(dev);
if (band) { 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); 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); band = ftl_band_from_ppa(dev, event->ppa);
lbkoff = ftl_band_lbkoff_from_ppa(band, 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); ftl_anm_event_complete(event);
} }

View File

@ -191,8 +191,6 @@ struct spdk_ftl_dev {
/* Array of bands */ /* Array of bands */
struct ftl_band *bands; struct ftl_band *bands;
/* Band being curently defraged */
struct ftl_band *df_band;
/* Number of operational bands */ /* Number of operational bands */
size_t num_bands; size_t num_bands;
/* Next write band */ /* Next write band */

View File

@ -87,6 +87,8 @@ struct ftl_band_reloc {
/* Indicates band being acitvely processed */ /* Indicates band being acitvely processed */
int active; int active;
/* The band is being defragged */
bool defrag;
/* Reloc map iterator */ /* Reloc map iterator */
struct { struct {
@ -124,6 +126,8 @@ struct ftl_reloc {
/* Maximum transfer size (in logical blocks) per single IO */ /* Maximum transfer size (in logical blocks) per single IO */
size_t xfer_size; size_t xfer_size;
/* Number of bands being defragged */
size_t num_defrag_bands;
/* Array of band relocates */ /* Array of band relocates */
struct ftl_band_reloc *brelocs; struct ftl_band_reloc *brelocs;
@ -141,6 +145,12 @@ struct ftl_reloc {
TAILQ_HEAD(, ftl_band_reloc) pending_queue; 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 static size_t
ftl_reloc_iter_chk_offset(struct ftl_band_reloc *breloc) 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--; breloc->num_lbks--;
} }
static void static void
ftl_reloc_read_lba_map_cb(struct ftl_io *io, void *arg, int status) 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) { if (ftl_band_empty(band) && band->state == FTL_BAND_STATE_CLOSED) {
ftl_band_set_state(breloc->band, FTL_BAND_STATE_FREE); 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_qdepth = dev->conf.max_reloc_qdepth;
reloc->max_active = dev->conf.max_active_relocs; reloc->max_active = dev->conf.max_active_relocs;
reloc->xfer_size = dev->xfer_size; reloc->xfer_size = dev->xfer_size;
reloc->num_defrag_bands = 0;
if (reloc->max_qdepth > FTL_RELOC_MAX_MOVES) { if (reloc->max_qdepth > FTL_RELOC_MAX_MOVES) {
goto error; goto error;
@ -775,7 +791,7 @@ ftl_reloc(struct ftl_reloc *reloc)
void void
ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset, 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]; struct ftl_band_reloc *breloc = &reloc->brelocs[band->id];
size_t i, prev_lbks = breloc->num_lbks; 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); pthread_spin_lock(&band->lba_map.lock);
if (band->lba_map.num_vld == 0) { if (band->lba_map.num_vld == 0) {
pthread_spin_unlock(&band->lba_map.lock); 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; return;
} }
pthread_spin_unlock(&band->lba_map.lock); 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; 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) { if (!prev_lbks && !prio && !breloc->active) {
TAILQ_INSERT_HEAD(&reloc->pending_queue, breloc, entry); TAILQ_INSERT_HEAD(&reloc->pending_queue, breloc, entry);
} }

View File

@ -43,9 +43,11 @@ struct ftl_band;
struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev); struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev);
void ftl_reloc_free(struct ftl_reloc *reloc); void ftl_reloc_free(struct ftl_reloc *reloc);
void ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, 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(struct ftl_reloc *reloc);
void ftl_reloc_halt(struct ftl_reloc *reloc); void ftl_reloc_halt(struct ftl_reloc *reloc);
void ftl_reloc_resume(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_halted(const struct ftl_reloc *reloc);
bool ftl_reloc_is_defrag_active(const struct ftl_reloc *reloc);
#endif /* FTL_RELOC_H */ #endif /* FTL_RELOC_H */

View File

@ -270,7 +270,7 @@ test_reloc_iter_full(void)
set_band_valid_map(band, 0, ftl_num_band_lbks(dev)); 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)); CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
@ -313,7 +313,7 @@ test_reloc_empty_band(void)
breloc = &reloc->brelocs[0]; breloc = &reloc->brelocs[0];
band = breloc->band; 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); 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)); 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)); 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); ftl_reloc_add_active_queue(breloc);
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev)); 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)); set_band_valid_map(band, 0, ftl_num_band_lbks(dev));
ftl_reloc_add(reloc, band, ftl_dev_lbks_in_chunk(dev) * 3, 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); ftl_reloc_add_active_queue(breloc);
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_dev_lbks_in_chunk(dev)); 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); 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)); SPDK_CU_ASSERT_FATAL(breloc == TAILQ_FIRST(&reloc->pending_queue));
ftl_reloc_add_active_queue(breloc); ftl_reloc_add_active_queue(breloc);

View File

@ -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, DEFINE_STUB_V(ftl_trace_completion, (struct spdk_ftl_dev *dev, const struct ftl_io *io,
enum ftl_trace_completion completion)); enum ftl_trace_completion completion));
DEFINE_STUB_V(ftl_reloc_add, (struct ftl_reloc *reloc, struct ftl_band *band, size_t offset, 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_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, DEFINE_STUB_V(ftl_trace_submission, (struct spdk_ftl_dev *dev, const struct ftl_io *io,
struct ftl_ppa ppa, size_t ppa_cnt)); struct ftl_ppa ppa, size_t ppa_cnt));