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:
parent
7012a2760e
commit
93402cd144
@ -54,6 +54,13 @@ enum ftl_reloc_move_state {
|
|||||||
FTL_RELOC_STATE_WRITE,
|
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_reloc_move {
|
||||||
struct ftl_band_reloc *breloc;
|
struct ftl_band_reloc *breloc;
|
||||||
|
|
||||||
@ -85,8 +92,9 @@ struct ftl_band_reloc {
|
|||||||
/* Bitmap of logical blocks to be relocated */
|
/* Bitmap of logical blocks to be relocated */
|
||||||
struct spdk_bit_array *reloc_map;
|
struct spdk_bit_array *reloc_map;
|
||||||
|
|
||||||
/* Indicates band being acitvely processed */
|
/* State of the band reloc */
|
||||||
int active;
|
enum ftl_band_reloc_state state;
|
||||||
|
|
||||||
/* The band is being defragged */
|
/* The band is being defragged */
|
||||||
bool defrag;
|
bool defrag;
|
||||||
|
|
||||||
@ -209,7 +217,6 @@ ftl_reloc_prep(struct ftl_band_reloc *breloc)
|
|||||||
struct ftl_reloc_move *move;
|
struct ftl_reloc_move *move;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
breloc->active = 1;
|
|
||||||
reloc->num_active++;
|
reloc->num_active++;
|
||||||
|
|
||||||
if (!band->high_prio) {
|
if (!band->high_prio) {
|
||||||
@ -220,6 +227,8 @@ ftl_reloc_prep(struct ftl_band_reloc *breloc)
|
|||||||
} else {
|
} else {
|
||||||
ftl_band_acquire_lba_map(band);
|
ftl_band_acquire_lba_map(band);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ftl_band_acquire_lba_map(band);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < reloc->max_qdepth; ++i) {
|
for (i = 0; i < reloc->max_qdepth; ++i) {
|
||||||
@ -551,23 +560,27 @@ ftl_reloc_release(struct ftl_band_reloc *breloc)
|
|||||||
struct ftl_reloc *reloc = breloc->parent;
|
struct ftl_reloc *reloc = breloc->parent;
|
||||||
struct ftl_band *band = breloc->band;
|
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_reloc_iter_reset(breloc);
|
||||||
|
|
||||||
ftl_band_release_lba_map(band);
|
ftl_band_release_lba_map(band);
|
||||||
|
|
||||||
breloc->active = 0;
|
|
||||||
reloc->num_active--;
|
reloc->num_active--;
|
||||||
|
|
||||||
if (!band->high_prio && breloc->num_lbks) {
|
if (breloc->state == FTL_BAND_RELOC_STATE_HIGH_PRIO) {
|
||||||
TAILQ_INSERT_TAIL(&reloc->pending_queue, breloc, entry);
|
/* High prio band must be relocated as a whole and ANM events will be ignored */
|
||||||
return;
|
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) {
|
if (ftl_band_empty(band) && band->state == FTL_BAND_STATE_CLOSED) {
|
||||||
@ -642,7 +655,8 @@ ftl_band_reloc_free(struct ftl_band_reloc *breloc)
|
|||||||
reloc = breloc->parent;
|
reloc = breloc->parent;
|
||||||
|
|
||||||
/* Drain write queue if there is active band relocation during shutdown */
|
/* 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);
|
assert(reloc->halt);
|
||||||
num_moves = spdk_ring_dequeue(breloc->move_queue, (void **)&moves, reloc->max_qdepth);
|
num_moves = spdk_ring_dequeue(breloc->move_queue, (void **)&moves, reloc->max_qdepth);
|
||||||
for (i = 0; i < num_moves; ++i) {
|
for (i = 0; i < num_moves; ++i) {
|
||||||
@ -656,16 +670,6 @@ ftl_band_reloc_free(struct ftl_band_reloc *breloc)
|
|||||||
free(breloc->moves);
|
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 *
|
struct ftl_reloc *
|
||||||
ftl_reloc_init(struct spdk_ftl_dev *dev)
|
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 */
|
/* Process first band from priority queue and return */
|
||||||
breloc = TAILQ_FIRST(&reloc->prio_queue);
|
breloc = TAILQ_FIRST(&reloc->prio_queue);
|
||||||
if (breloc) {
|
if (breloc) {
|
||||||
if (!breloc->active) {
|
|
||||||
ftl_reloc_prep(breloc);
|
|
||||||
}
|
|
||||||
ftl_process_reloc(breloc);
|
ftl_process_reloc(breloc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -773,10 +774,15 @@ ftl_reloc(struct ftl_reloc *reloc)
|
|||||||
continue;
|
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) {
|
TAILQ_FOREACH_SAFE(breloc, &reloc->active_queue, entry, tbreloc) {
|
||||||
|
assert(breloc->state == FTL_BAND_RELOC_STATE_ACTIVE);
|
||||||
ftl_process_reloc(breloc);
|
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)
|
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;
|
||||||
|
|
||||||
/* No need to add anything if already at high prio - whole band should be relocated */
|
/* No need to add anything if already at high prio - whole band should be relocated */
|
||||||
if (!prio && band->high_prio) {
|
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++;
|
breloc->num_lbks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prio && prev_lbks == breloc->num_lbks) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the band is coming from the defrag process, mark it appropriately */
|
/* If the band is coming from the defrag process, mark it appropriately */
|
||||||
if (is_defrag) {
|
if (is_defrag) {
|
||||||
assert(offset == 0 && num_lbks == ftl_num_band_lbks(band->dev));
|
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;
|
breloc->defrag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prev_lbks && !prio && !breloc->active) {
|
if (!prio) {
|
||||||
TAILQ_INSERT_HEAD(&reloc->pending_queue, breloc, entry);
|
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 */
|
/* If priority band is already on pending or active queue, remove it from it */
|
||||||
TAILQ_FOREACH(iter_breloc, &reloc->pending_queue, entry) {
|
switch (breloc->state) {
|
||||||
if (breloc == iter_breloc) {
|
case FTL_BAND_RELOC_STATE_PENDING:
|
||||||
TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
|
TAILQ_REMOVE(&reloc->pending_queue, breloc, entry);
|
||||||
break;
|
break;
|
||||||
}
|
case FTL_BAND_RELOC_STATE_ACTIVE:
|
||||||
}
|
active = true;
|
||||||
|
TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
|
||||||
TAILQ_FOREACH(iter_breloc, &reloc->active_queue, entry) {
|
break;
|
||||||
if (breloc == iter_breloc) {
|
default:
|
||||||
TAILQ_REMOVE(&reloc->active_queue, breloc, entry);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
breloc->state = FTL_BAND_RELOC_STATE_HIGH_PRIO;
|
||||||
TAILQ_INSERT_TAIL(&reloc->prio_queue, breloc, entry);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,6 +195,14 @@ single_reloc_move(struct ftl_band_reloc *breloc)
|
|||||||
ftl_process_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
|
static void
|
||||||
setup_reloc(struct spdk_ftl_dev **_dev, struct ftl_reloc **_reloc,
|
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)
|
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;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < ftl_dev_num_bands(reloc->dev); ++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);
|
ftl_reloc_free(reloc);
|
||||||
@ -296,6 +304,7 @@ test_reloc_iter_full(void)
|
|||||||
|
|
||||||
/* num_lbks should remain intact since all the blocks are valid */
|
/* num_lbks should remain intact since all the blocks are valid */
|
||||||
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
|
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
|
||||||
|
breloc->state = FTL_BAND_RELOC_STATE_INACTIVE;
|
||||||
|
|
||||||
cleanup_reloc(dev, reloc);
|
cleanup_reloc(dev, reloc);
|
||||||
}
|
}
|
||||||
@ -342,7 +351,8 @@ test_reloc_full_band(void)
|
|||||||
|
|
||||||
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
|
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) {
|
for (i = 1; i <= num_iters; ++i) {
|
||||||
single_reloc_move(breloc);
|
single_reloc_move(breloc);
|
||||||
@ -376,7 +386,7 @@ test_reloc_scatter_band(void)
|
|||||||
|
|
||||||
breloc = &reloc->brelocs[0];
|
breloc = &reloc->brelocs[0];
|
||||||
band = breloc->band;
|
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) {
|
for (i = 0; i < ftl_num_band_lbks(dev); ++i) {
|
||||||
if (i % 2) {
|
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(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));
|
CU_ASSERT_EQUAL(breloc->num_lbks, ftl_num_band_lbks(dev));
|
||||||
|
|
||||||
@ -393,9 +404,9 @@ test_reloc_scatter_band(void)
|
|||||||
single_reloc_move(breloc);
|
single_reloc_move(breloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ftl_process_reloc(breloc);
|
||||||
CU_ASSERT_EQUAL(breloc->num_lbks, 0);
|
CU_ASSERT_EQUAL(breloc->num_lbks, 0);
|
||||||
CU_ASSERT_TRUE(ftl_reloc_done(breloc));
|
CU_ASSERT_TRUE(ftl_reloc_done(breloc));
|
||||||
ftl_reloc_release(breloc);
|
|
||||||
|
|
||||||
cleanup_reloc(dev, reloc);
|
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_reloc_add(reloc, band, ftl_dev_lbks_in_chunk(dev) * 3,
|
||||||
ftl_dev_lbks_in_chunk(dev), 1, false);
|
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));
|
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);
|
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_prep(breloc);
|
||||||
|
add_to_active_queue(reloc, breloc);
|
||||||
|
|
||||||
CU_ASSERT_EQUAL(breloc->num_lbks, 1);
|
CU_ASSERT_EQUAL(breloc->num_lbks, 1);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user