Commit 0f99700d authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Jim Harris
Browse files

ftl: user write limits



Calculates general priorities and trigger points for writers
(gc and compaction) dependent on number of free bands. GC will
be started at SPDK_FTL_LIMIT_START level, while at SPDK_FTL_LIMIT_CRIT
compaction needs to be stopped and only GC is allowed to work.
This is done to make sure FTL doesn't run out of free bands and deadlock
itself.

Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: default avatarKozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: I1aab98503c2e79e97f8e4e9fb1257530fa9770e2
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13326


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent c7213b9c
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -18,6 +18,15 @@ extern "C" {
struct spdk_ftl_dev;
struct ftl_io;

/* Limit thresholds */
enum {
	SPDK_FTL_LIMIT_CRIT,
	SPDK_FTL_LIMIT_HIGH,
	SPDK_FTL_LIMIT_LOW,
	SPDK_FTL_LIMIT_START,
	SPDK_FTL_LIMIT_MAX
};

struct spdk_ftl_conf {
	/* Device's name */
	char					*name;
@@ -34,6 +43,9 @@ struct spdk_ftl_conf {
	/* IO pool size per user thread */
	size_t					user_io_pool_size;

	/* User writes limits */
	size_t			                limits[SPDK_FTL_LIMIT_MAX];

	/* FTL startup mode mask, see spdk_ftl_mode enum for possible values */
	uint32_t				mode;

+26 −0
Original line number Diff line number Diff line
@@ -26,6 +26,13 @@ spdk_ftl_io_size(void)
	return sizeof(struct ftl_io);
}

static size_t
ftl_get_limit(const struct spdk_ftl_dev *dev, int type)
{
	assert(type < SPDK_FTL_LIMIT_MAX);
	return dev->conf.limits[type];
}

static bool
ftl_shutdown_complete(struct spdk_ftl_dev *dev)
{
@@ -50,6 +57,25 @@ ftl_shutdown_complete(struct spdk_ftl_dev *dev)
	return true;
}

void
ftl_apply_limits(struct spdk_ftl_dev *dev)
{
	size_t limit;
	int i;

	/*  Clear existing limit */
	dev->limit = SPDK_FTL_LIMIT_MAX;

	for (i = SPDK_FTL_LIMIT_CRIT; i < SPDK_FTL_LIMIT_MAX; ++i) {
		limit = ftl_get_limit(dev, i);

		if (dev->num_free <= limit) {
			dev->limit = i;
			break;
		}
	}
}

void
ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
{
+5 −0
Original line number Diff line number Diff line
@@ -113,6 +113,9 @@ struct spdk_ftl_dev {
	/* Transfer unit size */
	uint64_t			xfer_size;

	/* Current user write limit */
	int				limit;

	/* Inflight IO operations */
	uint32_t			num_inflight;

@@ -137,6 +140,8 @@ struct spdk_ftl_dev {
	TAILQ_HEAD(, ftl_io)		wr_sq;
};

void ftl_apply_limits(struct spdk_ftl_dev *dev);

void ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr);

int ftl_core_poller(void *ctx);
+9 −0
Original line number Diff line number Diff line
@@ -8,6 +8,14 @@
#include "ftl_core.h"

static const struct spdk_ftl_conf g_default_conf = {
	/* 2 free bands - compaction is blocked, gc only */
	.limits[SPDK_FTL_LIMIT_CRIT]	= 2,
	/* 3 free bands */
	.limits[SPDK_FTL_LIMIT_HIGH]	= 3,
	/* 4 free bands */
	.limits[SPDK_FTL_LIMIT_LOW]	= 4,
	/* 5 free bands - gc starts running */
	.limits[SPDK_FTL_LIMIT_START]	= 5,
	/* 20% spare blocks */
	.overprovisioning = 20,
	/* IO pool size per user thread (this should be adjusted to thread IO qdepth) */
@@ -105,6 +113,7 @@ ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf)
		return rc;
	}

	dev->limit = SPDK_FTL_LIMIT_MAX;
	return 0;
}