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 spdk_ftl_dev;
|
||||||
struct ftl_io;
|
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 {
|
struct spdk_ftl_conf {
|
||||||
/* Device's name */
|
/* Device's name */
|
||||||
char *name;
|
char *name;
|
||||||
@ -34,6 +43,9 @@ struct spdk_ftl_conf {
|
|||||||
/* IO pool size per user thread */
|
/* IO pool size per user thread */
|
||||||
size_t user_io_pool_size;
|
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 */
|
/* FTL startup mode mask, see spdk_ftl_mode enum for possible values */
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
|
|
||||||
|
@ -26,6 +26,13 @@ spdk_ftl_io_size(void)
|
|||||||
return sizeof(struct ftl_io);
|
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
|
static bool
|
||||||
ftl_shutdown_complete(struct spdk_ftl_dev *dev)
|
ftl_shutdown_complete(struct spdk_ftl_dev *dev)
|
||||||
{
|
{
|
||||||
@ -50,6 +57,25 @@ ftl_shutdown_complete(struct spdk_ftl_dev *dev)
|
|||||||
return true;
|
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
|
void
|
||||||
ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
|
ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
|
||||||
{
|
{
|
||||||
|
@ -113,6 +113,9 @@ struct spdk_ftl_dev {
|
|||||||
/* Transfer unit size */
|
/* Transfer unit size */
|
||||||
uint64_t xfer_size;
|
uint64_t xfer_size;
|
||||||
|
|
||||||
|
/* Current user write limit */
|
||||||
|
int limit;
|
||||||
|
|
||||||
/* Inflight IO operations */
|
/* Inflight IO operations */
|
||||||
uint32_t num_inflight;
|
uint32_t num_inflight;
|
||||||
|
|
||||||
@ -137,6 +140,8 @@ struct spdk_ftl_dev {
|
|||||||
TAILQ_HEAD(, ftl_io) wr_sq;
|
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);
|
void ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr);
|
||||||
|
|
||||||
int ftl_core_poller(void *ctx);
|
int ftl_core_poller(void *ctx);
|
||||||
|
@ -8,6 +8,14 @@
|
|||||||
#include "ftl_core.h"
|
#include "ftl_core.h"
|
||||||
|
|
||||||
static const struct spdk_ftl_conf g_default_conf = {
|
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 */
|
/* 20% spare blocks */
|
||||||
.overprovisioning = 20,
|
.overprovisioning = 20,
|
||||||
/* IO pool size per user thread (this should be adjusted to thread IO qdepth) */
|
/* 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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->limit = SPDK_FTL_LIMIT_MAX;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user