Commit 1738488e authored by Artur Paszkiewicz's avatar Artur Paszkiewicz Committed by Jim Harris
Browse files

ftl: p2l checkpointing



Since base device doesn't require VSS, FTL introduces a mechanism that
will allow for recovering both the P2L and write pointer of open bands
after a dirty shutdown. After writing 1MiB of data to a band, a 4KiB
block describing the P2L will be persisted to cache device, effectively
emulating VSS for the base device.

Signed-off-by: default avatarArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: default avatarKozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: Ic6be52dc09b237297a5cda3e752d6c038e98b70e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13367


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 36049672
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -27,9 +27,10 @@ FTL_SUBDIRS := mngt utils

C_SRCS = ftl_core.c ftl_init.c ftl_layout.c ftl_debug.c ftl_io.c ftl_sb.c ftl_l2p.c ftl_l2p_flat.c
C_SRCS += ftl_nv_cache.c ftl_band.c ftl_band_ops.c ftl_writer.c ftl_rq.c ftl_reloc.c ftl_l2p_cache.c
C_SRCS += ftl_p2l.c
C_SRCS += mngt/ftl_mngt.c mngt/ftl_mngt_bdev.c mngt/ftl_mngt_shutdown.c mngt/ftl_mngt_startup.c
C_SRCS += mngt/ftl_mngt_md.c mngt/ftl_mngt_misc.c mngt/ftl_mngt_ioch.c mngt/ftl_mngt_l2p.c
C_SRCS += mngt/ftl_mngt_band.c mngt/ftl_mngt_self_test.c
C_SRCS += mngt/ftl_mngt_band.c mngt/ftl_mngt_self_test.c mngt/ftl_mngt_p2l.c
C_SRCS += utils/ftl_conf.c utils/ftl_md.c utils/ftl_mempool.c utils/ftl_bitmap.c

SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_ftl.map)
+17 −3
Original line number Diff line number Diff line
@@ -106,7 +106,9 @@ _ftl_band_set_closed_cb(struct ftl_band *band, bool valid)
		band->owner.state_change_fn(band);
	}

	/* Free the p2l map if there are no outstanding IOs */
	ftl_p2l_validate_ckpt(band);

	/* Free the P2L map if there are no outstanding IOs */
	ftl_band_release_p2l_map(band);
	assert(band->p2l_map.ref_cnt == 0);

@@ -186,7 +188,7 @@ ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type)
}

void
ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr)
ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id)
{
	struct ftl_p2l_map *p2l_map = &band->p2l_map;
	uint64_t offset;
@@ -194,7 +196,13 @@ ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr)
	offset = ftl_band_block_offset_from_addr(band, addr);

	p2l_map->band_map[offset].lba = lba;
	p2l_map->num_valid++;
	p2l_map->band_map[offset].seq_id = seq_id;
}

void
ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr)
{
	band->p2l_map.num_valid++;
	ftl_bitmap_set(band->dev->valid_map, addr);
}

@@ -374,6 +382,10 @@ ftl_band_release_p2l_map(struct ftl_band *band)
	p2l_map->ref_cnt--;

	if (p2l_map->ref_cnt == 0) {
		if (p2l_map->p2l_ckpt) {
			ftl_p2l_ckpt_release(band->dev, p2l_map->p2l_ckpt);
			p2l_map->p2l_ckpt = NULL;
		}
		ftl_band_free_p2l_map(band);
		ftl_band_free_md_entry(band);
	}
@@ -394,6 +406,8 @@ ftl_band_write_prep(struct ftl_band *band)
		return -1;
	}

	band->p2l_map.p2l_ckpt = ftl_p2l_ckpt_acquire(dev);
	band->md->p2l_md_region = ftl_p2l_ckpt_region_type(band->p2l_map.p2l_ckpt);
	ftl_band_iter_init(band);

	band->md->seq = ftl_get_next_seq_id(dev);
+5 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@

#include "utils/ftl_df.h"

#define FTL_MAX_OPEN_BANDS 4
#define FTL_MAX_OPEN_BANDS FTL_LAYOUT_REGION_TYPE_P2L_COUNT

#define FTL_BAND_VERSION_0	0
#define FTL_BAND_VERSION_1	1
@@ -61,6 +61,9 @@ struct ftl_band_md {
	/* Band type set during opening */
	enum ftl_band_type		type;

	/* nv_cache p2l md region associated with band */
	enum ftl_layout_region_type	p2l_md_region;

	/* Sequence ID when band was opened */
	uint64_t			seq;

@@ -157,6 +160,7 @@ ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t nu
ftl_addr ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset);
size_t ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset);
size_t ftl_band_user_blocks(const struct ftl_band *band);
void ftl_band_set_p2l(struct ftl_band *band, uint64_t lba, ftl_addr addr, uint64_t seq_id);
void ftl_band_set_addr(struct ftl_band *band, uint64_t lba, ftl_addr addr);
struct ftl_band *ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr);
ftl_addr ftl_band_tail_md_addr(struct ftl_band *band);
+1 −4
Original line number Diff line number Diff line
@@ -15,14 +15,11 @@ static void
write_rq_end(struct spdk_bdev_io *bdev_io, bool success, void *arg)
{
	struct ftl_rq *rq = arg;
	struct ftl_band *band = rq->io.band;

	rq->success = success;

	assert(band->queue_depth > 0);
	band->queue_depth--;
	ftl_p2l_ckpt_issue(rq);

	rq->owner.cb(rq);
	spdk_bdev_free_io(bdev_io);
}

+10 −6
Original line number Diff line number Diff line
@@ -167,6 +167,14 @@ struct spdk_ftl_dev {

	/* Retry init sequence */
	bool				init_retry;

	/* P2L checkpointing */
	struct {
		/* Free regions */
		TAILQ_HEAD(, ftl_p2l_ckpt)	free;
		/* In use regions */
		TAILQ_HEAD(, ftl_p2l_ckpt)	inuse;
	} p2l_ckpt;
};

void ftl_apply_limits(struct spdk_ftl_dev *dev);
@@ -200,12 +208,8 @@ ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
static inline uint32_t
ftl_get_write_unit_size(struct spdk_bdev *bdev)
{
	if (spdk_bdev_is_zoned(bdev)) {
		return spdk_bdev_get_write_unit_size(bdev);
	}

	/* TODO: this should be passed via input parameter */
	return 32;
	/* Full block of P2L map worth of xfer_sz is needed for P2L checkpointing */
	return FTL_NUM_LBA_IN_BLOCK;
}

static inline struct spdk_thread *
Loading