From 0f99700db902880d30a28471aeda282578ab11f9 Mon Sep 17 00:00:00 2001 From: Artur Paszkiewicz Date: Tue, 14 Jun 2022 12:01:11 +0200 Subject: [PATCH] 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 Signed-off-by: Kozlowski Mateusz Change-Id: I1aab98503c2e79e97f8e4e9fb1257530fa9770e2 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13326 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris --- include/spdk/ftl.h | 12 ++++++++++++ lib/ftl/ftl_core.c | 26 ++++++++++++++++++++++++++ lib/ftl/ftl_core.h | 5 +++++ lib/ftl/utils/ftl_conf.c | 9 +++++++++ 4 files changed, 52 insertions(+) diff --git a/include/spdk/ftl.h b/include/spdk/ftl.h index 9e323ab05..512f6191b 100644 --- a/include/spdk/ftl.h +++ b/include/spdk/ftl.h @@ -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; diff --git a/lib/ftl/ftl_core.c b/lib/ftl/ftl_core.c index 4f2bda6fa..989ade21e 100644 --- a/lib/ftl/ftl_core.c +++ b/lib/ftl/ftl_core.c @@ -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) { diff --git a/lib/ftl/ftl_core.h b/lib/ftl/ftl_core.h index 77f2580d6..b5d14193c 100644 --- a/lib/ftl/ftl_core.h +++ b/lib/ftl/ftl_core.h @@ -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); diff --git a/lib/ftl/utils/ftl_conf.c b/lib/ftl/utils/ftl_conf.c index 9e4a4bb47..152510aef 100644 --- a/lib/ftl/utils/ftl_conf.c +++ b/lib/ftl/utils/ftl_conf.c @@ -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; }