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: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: I1aab98503c2e79e97f8e4e9fb1257530fa9770e2
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13326
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Artur Paszkiewicz 2022-06-14 12:01:11 +02:00 committed by Jim Harris
parent c7213b9c6d
commit 0f99700db9
4 changed files with 52 additions and 0 deletions

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}