lib/ftl: Keep state of single band relocation

Added states for keeping track on which reloc
queue band actually is.

Change-Id: Ib05ac4e925002728ddfed3195891f5328eebb0d0
Signed-off-by: Wojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465072
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
Wojciech Malikowski 2019-08-13 10:54:44 -04:00 committed by Tomasz Zawadzki
parent 7012a2760e
commit 93402cd144
2 changed files with 85 additions and 63 deletions

View File

@ -54,6 +54,13 @@ enum ftl_reloc_move_state {
FTL_RELOC_STATE_WRITE,
};
enum ftl_band_reloc_state {
FTL_BAND_RELOC_STATE_INACTIVE,
FTL_BAND_RELOC_STATE_PENDING,
FTL_BAND_RELOC_STATE_ACTIVE,
FTL_BAND_RELOC_STATE_HIGH_PRIO
};
struct ftl_reloc_move {
struct ftl_band_reloc *breloc;
@ -85,8 +92,9 @@ struct ftl_band_reloc {
/* Bitmap of logical blocks to be relocated */
struct spdk_bit_array *reloc_map;
/* Indicates band being acitvely processed */
int active;
/* State of the band reloc */
enum ftl_band_reloc_state state;
/* The band is being defragged */
bool defrag;
@ -209,7 +217,6 @@ ftl_reloc_prep(struct ftl_band_reloc *breloc)
struct ftl_reloc_move *move;
size_t i;
breloc->active = 1;
reloc->num_active++;
if (!band->high_prio) {
@ -220,6 +227,8 @@ ftl_reloc_prep(struct ftl_band_reloc *breloc)
} else {
ftl_band_acquire_lba_map(band);
}
} else {
ftl_band_acquire_lba_map(band);
}
for (i = 0; i < reloc->max_qdepth; ++i) {
@ -551,24 +560,28 @@ ftl_reloc_release(struct ftl_band_reloc *breloc)
struct ftl_reloc *reloc = breloc->parent;
struct ftl_band *band = breloc->band;
if (band->high_prio && breloc->num_lbks == 0) {
band->high_prio = 0;
TAILQ_REMOVE(&reloc->prio_queue, breloc, entry);
} else if (!band->high_prio) {
TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
}
ftl_reloc_iter_reset(breloc);
ftl_band_release_lba_map(band);
breloc->active = 0;
reloc->num_active--;
if (!band->high_prio && breloc->num_lbks) {
if (breloc->state == FTL_BAND_RELOC_STATE_HIGH_PRIO) {
/* High prio band must be relocated as a whole and ANM events will be ignored */
assert(breloc->num_lbks == 0 && ftl_band_empty(band));
TAILQ_REMOVE(&reloc->prio_queue, breloc, entry);
band->high_prio = 0;
breloc->state = FTL_BAND_RELOC_STATE_INACTIVE;
} else {
assert(breloc->state == FTL_BAND_RELOC_STATE_ACTIVE);
TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
breloc->state = FTL_BAND_RELOC_STATE_INACTIVE;
/* If we got ANM event during relocation put such band back to pending queue */
if (breloc->num_lbks != 0) {
breloc->state = FTL_BAND_RELOC_STATE_PENDING;
TAILQ_INSERT_TAIL(&reloc->pending_queue, breloc, entry);
return;
}
}
if (ftl_band_empty(band) && band->state == FTL_BAND_STATE_CLOSED) {
ftl_band_set_state(breloc->band, FTL_BAND_STATE_FREE);
@ -642,7 +655,8 @@ ftl_band_reloc_free(struct ftl_band_reloc *breloc)
reloc = breloc->parent;
/* Drain write queue if there is active band relocation during shutdown */
if (breloc->active) {
if (breloc->state == FTL_BAND_RELOC_STATE_ACTIVE ||
breloc->state == FTL_BAND_RELOC_STATE_HIGH_PRIO) {
assert(reloc->halt);
num_moves = spdk_ring_dequeue(breloc->move_queue, (void **)&moves, reloc->max_qdepth);
for (i = 0; i < num_moves; ++i) {
@ -656,16 +670,6 @@ ftl_band_reloc_free(struct ftl_band_reloc *breloc)
free(breloc->moves);
}
static void
ftl_reloc_add_active_queue(struct ftl_band_reloc *breloc)
{
struct ftl_reloc *reloc = breloc->parent;
TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
TAILQ_INSERT_HEAD(&reloc->active_queue, breloc, entry);
ftl_reloc_prep(breloc);
}
struct ftl_reloc *
ftl_reloc_init(struct spdk_ftl_dev *dev)
{
@ -756,9 +760,6 @@ ftl_reloc(struct ftl_reloc *reloc)
/* Process first band from priority queue and return */
breloc = TAILQ_FIRST(&reloc->prio_queue);
if (breloc) {
if (!breloc->active) {
ftl_reloc_prep(breloc);
}
ftl_process_reloc(breloc);
return;
}
@ -773,10 +774,15 @@ ftl_reloc(struct ftl_reloc *reloc)
continue;
}
ftl_reloc_add_active_queue(breloc);
ftl_reloc_prep(breloc);
assert(breloc->state == FTL_BAND_RELOC_STATE_PENDING);
TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
breloc->state = FTL_BAND_RELOC_STATE_ACTIVE;
TAILQ_INSERT_HEAD(&reloc->active_queue, breloc, entry);
}
TAILQ_FOREACH_SAFE(breloc, &reloc->active_queue, entry, tbreloc) {
assert(breloc->state == FTL_BAND_RELOC_STATE_ACTIVE);
ftl_process_reloc(breloc);
}
}
@ -786,7 +792,7 @@ ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset,
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;
size_t i;
/* No need to add anything if already at high prio - whole band should be relocated */
if (!prio && band->high_prio) {
@ -814,10 +820,6 @@ ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset,
breloc->num_lbks++;
}
if (!prio && prev_lbks == breloc->num_lbks) {
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));
@ -825,29 +827,35 @@ ftl_reloc_add(struct ftl_reloc *reloc, struct ftl_band *band, size_t offset,
breloc->defrag = true;
}
if (!prev_lbks && !prio && !breloc->active) {
if (!prio) {
if (breloc->state == FTL_BAND_RELOC_STATE_INACTIVE) {
breloc->state = FTL_BAND_RELOC_STATE_PENDING;
TAILQ_INSERT_HEAD(&reloc->pending_queue, breloc, entry);
}
if (prio) {
struct ftl_band_reloc *iter_breloc;
} else {
bool active = false;
/* If priority band is already on pending or active queue, remove it from it */
TAILQ_FOREACH(iter_breloc, &reloc->pending_queue, entry) {
if (breloc == iter_breloc) {
switch (breloc->state) {
case FTL_BAND_RELOC_STATE_PENDING:
TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
break;
}
}
TAILQ_FOREACH(iter_breloc, &reloc->active_queue, entry) {
if (breloc == iter_breloc) {
case FTL_BAND_RELOC_STATE_ACTIVE:
active = true;
TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
break;
}
default:
break;
}
breloc->state = FTL_BAND_RELOC_STATE_HIGH_PRIO;
TAILQ_INSERT_TAIL(&reloc->prio_queue, breloc, entry);
ftl_band_acquire_lba_map(breloc->band);
/*
* If band has been already on active queue it doesn't need any additional
* resources
*/
if (!active) {
ftl_reloc_prep(breloc);
}
}
}

View File

@ -195,6 +195,14 @@ single_reloc_move(struct ftl_band_reloc *breloc)
ftl_process_reloc(breloc);
}
static void
add_to_active_queue(struct ftl_reloc *reloc, struct ftl_band_reloc *breloc)
{
TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
breloc->state = FTL_BAND_RELOC_STATE_ACTIVE;
TAILQ_INSERT_HEAD(&reloc->active_queue, breloc, entry);
}
static void
setup_reloc(struct spdk_ftl_dev **_dev, struct ftl_reloc **_reloc,
const struct spdk_ocssd_geometry_data *geo, const struct spdk_ftl_punit_range *range)
@ -228,7 +236,7 @@ cleanup_reloc(struct spdk_ftl_dev *dev, struct ftl_reloc *reloc)
size_t i;
for (i = 0; i < ftl_dev_num_bands(reloc->dev); ++i) {
SPDK_CU_ASSERT_FATAL(reloc->brelocs[i].active == false);
SPDK_CU_ASSERT_FATAL(reloc->brelocs[i].state == FTL_BAND_RELOC_STATE_INACTIVE);
}
ftl_reloc_free(reloc);
@ -296,6 +304,7 @@ test_reloc_iter_full(void)
/* num_lbks should remain intact since all the blocks are valid */
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
breloc->state = FTL_BAND_RELOC_STATE_INACTIVE;
cleanup_reloc(dev, reloc);
}
@ -342,7 +351,8 @@ test_reloc_full_band(void)
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
ftl_reloc_add_active_queue(breloc);
ftl_reloc_prep(breloc);
add_to_active_queue(reloc, breloc);
for (i = 1; i <= num_iters; ++i) {
single_reloc_move(breloc);
@ -376,7 +386,7 @@ test_reloc_scatter_band(void)
breloc = &reloc->brelocs[0];
band = breloc->band;
num_iters = ftl_num_band_lbks(dev) / MAX_RELOC_QDEPTH;
num_iters = spdk_divide_round_up(ftl_num_band_lbks(dev), MAX_RELOC_QDEPTH * 2);
for (i = 0; i < ftl_num_band_lbks(dev); ++i) {
if (i % 2) {
@ -385,7 +395,8 @@ test_reloc_scatter_band(void)
}
ftl_reloc_add(reloc, band, 0, ftl_num_band_lbks(dev), 0, true);
ftl_reloc_add_active_queue(breloc);
ftl_reloc_prep(breloc);
add_to_active_queue(reloc, breloc);
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
@ -393,9 +404,9 @@ test_reloc_scatter_band(void)
single_reloc_move(breloc);
}
ftl_process_reloc(breloc);
CU_ASSERT_EQUAL(breloc->num_lbks, 0);
CU_ASSERT_TRUE(ftl_reloc_done(breloc));
ftl_reloc_release(breloc);
cleanup_reloc(dev, reloc);
}
@ -423,7 +434,9 @@ test_reloc_chunk(void)
ftl_reloc_add(reloc, band, ftl_dev_lbks_in_chunk(dev) * 3,
ftl_dev_lbks_in_chunk(dev), 1, false);
ftl_reloc_add_active_queue(breloc);
ftl_reloc_prep(breloc);
add_to_active_queue(reloc, breloc);
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_dev_lbks_in_chunk(dev));
@ -464,7 +477,8 @@ test_reloc_single_lbk(void)
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);
ftl_reloc_prep(breloc);
add_to_active_queue(reloc, breloc);
CU_ASSERT_EQUAL(breloc->num_lbks, 1);