Commit 93402cd1 authored by Wojciech Malikowski's avatar Wojciech Malikowski Committed by Tomasz Zawadzki
Browse files

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: default avatarWojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/465072


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent 7012a276
Loading
Loading
Loading
Loading
+64 −56
Original line number Diff line number Diff line
@@ -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);
		}
	}
}
+21 −7
Original line number Diff line number Diff line
@@ -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);