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:
parent
c7213b9c6d
commit
0f99700db9
@ -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,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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user