lib/ftl: flush the write buffer during nv_cache recovery

When recovering the data from the non-volatile cache, the data inside
the volatile cache needs to be flushed before flushing active bands.
Otherwise, if the number of blocks in a band is smaller than the number
of blocks inside the volatile cache, part of the data may not get
flushed.

Change-Id: I4e99709c8c2a526a928578870d7fbd5fef37db02
Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/466883
Reviewed-by: Mateusz Kozlowski <mateusz.kozlowski@intel.com>
Reviewed-by: Wojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Konrad Sztyber 2019-08-30 10:21:10 +02:00 committed by Ben Walker
parent a33e2a84d5
commit cf3d42961b
3 changed files with 35 additions and 8 deletions

View File

@ -2095,14 +2095,10 @@ _ftl_flush(void *ctx)
}
int
spdk_ftl_flush(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
ftl_flush_rwb(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
{
struct ftl_flush *flush;
if (!dev->initialized) {
return -EBUSY;
}
flush = ftl_flush_init(dev, cb_fn, cb_arg);
if (!flush) {
return -ENOMEM;
@ -2112,6 +2108,16 @@ spdk_ftl_flush(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
return 0;
}
int
spdk_ftl_flush(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
{
if (!dev->initialized) {
return -EBUSY;
}
return ftl_flush_rwb(dev, cb_fn, cb_arg);
}
static void
_ftl_process_anm_event(void *ctx)
{

View File

@ -275,7 +275,7 @@ void ftl_apply_limits(struct spdk_ftl_dev *dev);
void ftl_io_read(struct ftl_io *io);
void ftl_io_write(struct ftl_io *io);
int ftl_io_erase(struct ftl_io *io);
int ftl_io_flush(struct ftl_io *io);
int ftl_flush_rwb(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg);
int ftl_current_limit(const struct spdk_ftl_dev *dev);
int ftl_invalidate_addr(struct spdk_ftl_dev *dev, struct ftl_ppa ppa);
int ftl_task_core(void *ctx);

View File

@ -543,6 +543,27 @@ ftl_nv_cache_band_flush_cb(void *ctx, int status)
}
}
static void
ftl_nv_cache_rwb_flush_cb(void *ctx, int status)
{
struct ftl_nv_cache_restore *restore = ctx;
struct ftl_nv_cache *nv_cache = restore->nv_cache;
struct spdk_ftl_dev *dev = SPDK_CONTAINEROF(nv_cache, struct spdk_ftl_dev, nv_cache);
int rc;
if (spdk_unlikely(status != 0)) {
SPDK_ERRLOG("Flushing the write buffer failed: %s\n", spdk_strerror(-status));
ftl_nv_cache_restore_complete(restore, status);
return;
}
rc = ftl_flush_active_bands(dev, ftl_nv_cache_band_flush_cb, restore);
if (spdk_unlikely(rc != 0)) {
SPDK_ERRLOG("Unable to flush active bands: %s\n", spdk_strerror(-rc));
ftl_nv_cache_restore_complete(restore, rc);
}
}
static void
ftl_nv_cache_recovery_done(struct ftl_nv_cache_restore *restore)
{
@ -566,9 +587,9 @@ ftl_nv_cache_recovery_done(struct ftl_nv_cache_restore *restore)
range_current->start_addr < range_prev->last_addr)) {
SPDK_DEBUGLOG(SPDK_LOG_FTL_INIT, "Non-volatile cache inconsistency detected\n");
rc = ftl_flush_active_bands(dev, ftl_nv_cache_band_flush_cb, restore);
rc = ftl_flush_rwb(dev, ftl_nv_cache_rwb_flush_cb, restore);
if (spdk_unlikely(rc != 0)) {
SPDK_ERRLOG("Unable to flush active bands: %s\n", spdk_strerror(-rc));
SPDK_ERRLOG("Unable to flush the write buffer: %s\n", spdk_strerror(-rc));
ftl_nv_cache_restore_complete(restore, rc);
}