FTL: Add band structure and helper functions
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com> Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Change-Id: I986746a008e716705304906ab4f2bdabce0a84c3 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13324 Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
1bbefed63b
commit
6448f33672
@ -22,7 +22,7 @@ CFLAGS += -I.
|
||||
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
|
||||
C_SRCS += ftl_nv_cache.c ftl_band.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 += utils/ftl_conf.c utils/ftl_md.c utils/ftl_mempool.c
|
||||
|
147
lib/ftl/ftl_band.c
Normal file
147
lib/ftl/ftl_band.c
Normal file
@ -0,0 +1,147 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/crc32.h"
|
||||
#include "spdk/likely.h"
|
||||
#include "spdk/util.h"
|
||||
#include "spdk/ftl.h"
|
||||
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_io.h"
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_internal.h"
|
||||
#include "utils/ftl_md.h"
|
||||
#include "utils/ftl_defs.h"
|
||||
|
||||
static uint64_t
|
||||
ftl_band_tail_md_offset(const struct ftl_band *band)
|
||||
{
|
||||
return ftl_get_num_blocks_in_band(band->dev) -
|
||||
ftl_tail_md_num_blocks(band->dev);
|
||||
}
|
||||
|
||||
int
|
||||
ftl_band_filled(struct ftl_band *band, size_t offset)
|
||||
{
|
||||
return offset == ftl_band_tail_md_offset(band);
|
||||
}
|
||||
|
||||
ftl_addr
|
||||
ftl_band_tail_md_addr(struct ftl_band *band)
|
||||
{
|
||||
ftl_addr addr;
|
||||
|
||||
/* Metadata should be aligned to xfer size */
|
||||
assert(ftl_band_tail_md_offset(band) % band->dev->xfer_size == 0);
|
||||
|
||||
addr = ftl_band_tail_md_offset(band) + band->start_addr;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void
|
||||
ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case FTL_BAND_TYPE_COMPACTION:
|
||||
case FTL_BAND_TYPE_GC:
|
||||
band->md->type = type;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
ftl_band_user_blocks_left(const struct ftl_band *band, size_t offset)
|
||||
{
|
||||
size_t tail_md_offset = ftl_band_tail_md_offset(band);
|
||||
|
||||
if (spdk_unlikely(offset > tail_md_offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tail_md_offset - offset;
|
||||
}
|
||||
|
||||
struct ftl_band *
|
||||
ftl_band_from_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
|
||||
{
|
||||
size_t band_id = ftl_addr_get_band(dev, addr);
|
||||
|
||||
assert(band_id < ftl_get_num_bands(dev));
|
||||
return &dev->bands[band_id];
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr)
|
||||
{
|
||||
assert(ftl_addr_get_band(band->dev, addr) == band->id);
|
||||
return addr % ftl_get_num_blocks_in_band(band->dev);
|
||||
}
|
||||
|
||||
ftl_addr
|
||||
ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks)
|
||||
{
|
||||
struct spdk_ftl_dev *dev = band->dev;
|
||||
size_t num_xfers;
|
||||
uint64_t offset;
|
||||
|
||||
assert(ftl_addr_get_band(dev, addr) == band->id);
|
||||
|
||||
offset = addr - band->start_addr;
|
||||
|
||||
/* In case starting address wasn't aligned to xfer_size, we'll align for consistent calculation
|
||||
* purposes - the unaligned value will be preserved at the end however.
|
||||
*/
|
||||
num_blocks += (offset % dev->xfer_size);
|
||||
offset -= (offset % dev->xfer_size);
|
||||
|
||||
/* Calculate offset based on xfer_size aligned writes */
|
||||
num_xfers = (num_blocks / dev->xfer_size);
|
||||
offset += num_xfers * dev->xfer_size;
|
||||
num_blocks -= num_xfers * dev->xfer_size;
|
||||
|
||||
if (offset > ftl_get_num_blocks_in_band(dev)) {
|
||||
return FTL_ADDR_INVALID;
|
||||
}
|
||||
|
||||
/* If there's any unalignment (either starting addr value or num_blocks), reintroduce it to the final address
|
||||
*/
|
||||
if (num_blocks) {
|
||||
offset += num_blocks;
|
||||
if (offset > ftl_get_num_blocks_in_band(dev)) {
|
||||
return FTL_ADDR_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
addr = band->start_addr + offset;
|
||||
return addr;
|
||||
}
|
||||
|
||||
ftl_addr
|
||||
ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off)
|
||||
{
|
||||
ftl_addr addr;
|
||||
|
||||
addr = block_off + band->id * ftl_get_num_blocks_in_band(band->dev);
|
||||
return addr;
|
||||
}
|
||||
|
||||
ftl_addr
|
||||
ftl_band_next_addr(struct ftl_band *band, ftl_addr addr, size_t offset)
|
||||
{
|
||||
uint64_t block_off = ftl_band_block_offset_from_addr(band, addr);
|
||||
|
||||
return ftl_band_addr_from_block_offset(band, block_off + offset);
|
||||
}
|
||||
|
||||
ftl_addr
|
||||
ftl_band_p2l_map_addr(struct ftl_band *band)
|
||||
{
|
||||
return band->tail_md_addr;
|
||||
}
|
202
lib/ftl/ftl_band.h
Normal file
202
lib/ftl/ftl_band.h
Normal file
@ -0,0 +1,202 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef FTL_BAND_H
|
||||
#define FTL_BAND_H
|
||||
|
||||
#include "spdk/stdinc.h"
|
||||
#include "spdk/bit_array.h"
|
||||
#include "spdk/queue.h"
|
||||
#include "spdk/crc32.h"
|
||||
|
||||
#include "ftl_io.h"
|
||||
#include "ftl_internal.h"
|
||||
#include "ftl_core.h"
|
||||
|
||||
#define FTL_MAX_OPEN_BANDS 4
|
||||
|
||||
#define FTL_BAND_VERSION_0 0
|
||||
#define FTL_BAND_VERSION_1 1
|
||||
|
||||
#define FTL_BAND_VERSION_CURRENT FTL_BAND_VERSION_1
|
||||
|
||||
struct spdk_ftl_dev;
|
||||
struct ftl_band;
|
||||
struct ftl_rq;
|
||||
struct ftl_basic_rq;
|
||||
|
||||
enum ftl_band_state {
|
||||
FTL_BAND_STATE_FREE,
|
||||
FTL_BAND_STATE_PREP,
|
||||
FTL_BAND_STATE_OPENING,
|
||||
FTL_BAND_STATE_OPEN,
|
||||
FTL_BAND_STATE_FULL,
|
||||
FTL_BAND_STATE_CLOSING,
|
||||
FTL_BAND_STATE_CLOSED,
|
||||
FTL_BAND_STATE_MAX
|
||||
};
|
||||
|
||||
typedef void (*ftl_band_state_change_fn)(struct ftl_band *band);
|
||||
typedef void (*ftl_band_ops_cb)(struct ftl_band *band, void *ctx, bool status);
|
||||
typedef void (*ftl_band_md_cb)(struct ftl_band *band, void *ctx, enum ftl_md_status status);
|
||||
|
||||
struct ftl_band_md {
|
||||
/* Band iterator for writing */
|
||||
struct {
|
||||
/* Current physical address of the write pointer */
|
||||
ftl_addr addr;
|
||||
|
||||
/* Offset from the band's start of the write pointer */
|
||||
uint64_t offset;
|
||||
} iter;
|
||||
|
||||
/* Band's state */
|
||||
enum ftl_band_state state;
|
||||
|
||||
/* Band type set during opening */
|
||||
enum ftl_band_type type;
|
||||
|
||||
/* Number of times band was fully written (ie. number of free -> closed state cycles) */
|
||||
uint64_t wr_cnt;
|
||||
|
||||
/* CRC32 checksum of the associated P2L map when band is in closed state */
|
||||
uint32_t p2l_map_checksum;
|
||||
} __attribute__((aligned(FTL_BLOCK_SIZE)));
|
||||
|
||||
SPDK_STATIC_ASSERT(sizeof(struct ftl_band_md) == FTL_BLOCK_SIZE, "Incorrect metadata size");
|
||||
|
||||
struct ftl_band {
|
||||
/* Device this band belongs to */
|
||||
struct spdk_ftl_dev *dev;
|
||||
|
||||
struct ftl_band_md *md;
|
||||
|
||||
/* IO queue depth (outstanding IOs) */
|
||||
uint64_t queue_depth;
|
||||
|
||||
/* Fields for owner of the band - compaction, or gc */
|
||||
struct {
|
||||
/* Callback context for the owner */
|
||||
void *priv;
|
||||
|
||||
/* State change callback */
|
||||
ftl_band_state_change_fn state_change_fn;
|
||||
|
||||
/* Callback for the owner */
|
||||
union {
|
||||
ftl_band_ops_cb ops_fn;
|
||||
ftl_band_md_cb md_fn;
|
||||
};
|
||||
|
||||
/* Reference counter */
|
||||
uint64_t cnt;
|
||||
} owner;
|
||||
|
||||
/* P2L map */
|
||||
struct ftl_p2l_map p2l_map;
|
||||
|
||||
/* Band's index */
|
||||
uint32_t id;
|
||||
|
||||
/* Band's NAND id - a group multiple bands may be part of the same physical band on base device
|
||||
* This way the write access pattern will match the actual physical layout more closely, leading
|
||||
* to lower overall write amplification factor
|
||||
*/
|
||||
uint32_t phys_id;
|
||||
|
||||
/* Band start addr */
|
||||
ftl_addr start_addr;
|
||||
|
||||
/* End metadata start addr */
|
||||
ftl_addr tail_md_addr;
|
||||
|
||||
/* Metadata request */
|
||||
struct ftl_basic_rq metadata_rq;
|
||||
|
||||
/* Free/shut bands' lists
|
||||
* Open bands are kept and managed directly by the writer (either GC or compaction). Each writer only
|
||||
* needs to keep two bands (one currently written to, and a pre-assigned reserve band to make sure flow
|
||||
* of data is always ongoing as the current one is closing).
|
||||
*/
|
||||
TAILQ_ENTRY(ftl_band) queue_entry;
|
||||
|
||||
/* For writing metadata */
|
||||
struct ftl_md_io_entry_ctx md_persist_entry_ctx;
|
||||
};
|
||||
|
||||
|
||||
uint64_t ftl_band_block_offset_from_addr(struct ftl_band *band, ftl_addr addr);
|
||||
ftl_addr ftl_band_addr_from_block_offset(struct ftl_band *band, uint64_t block_off);
|
||||
void ftl_band_set_type(struct ftl_band *band, enum ftl_band_type type);
|
||||
void ftl_band_set_state(struct ftl_band *band, enum ftl_band_state state);
|
||||
ftl_addr ftl_band_next_xfer_addr(struct ftl_band *band, ftl_addr addr, size_t num_blocks);
|
||||
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);
|
||||
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);
|
||||
int ftl_band_filled(struct ftl_band *band, size_t offset);
|
||||
ftl_addr ftl_band_p2l_map_addr(struct ftl_band *band);
|
||||
|
||||
static inline void
|
||||
ftl_band_set_owner(struct ftl_band *band,
|
||||
ftl_band_state_change_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
assert(NULL == band->owner.priv);
|
||||
assert(NULL == band->owner.state_change_fn);
|
||||
|
||||
band->owner.state_change_fn = fn;
|
||||
band->owner.priv = priv;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ftl_band_clear_owner(struct ftl_band *band,
|
||||
ftl_band_state_change_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
assert(priv == band->owner.priv);
|
||||
assert(fn == band->owner.state_change_fn);
|
||||
|
||||
band->owner.state_change_fn = NULL;
|
||||
band->owner.priv = NULL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ftl_band_empty(const struct ftl_band *band)
|
||||
{
|
||||
return band->p2l_map.num_valid == 0;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ftl_band_qd(const struct ftl_band *band)
|
||||
{
|
||||
return band->queue_depth;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ftl_band_iter_init(struct ftl_band *band)
|
||||
{
|
||||
/* Initialize band iterator to begin state */
|
||||
band->md->iter.addr = band->start_addr;
|
||||
band->md->iter.offset = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ftl_band_iter_advance(struct ftl_band *band, uint64_t num_blocks)
|
||||
{
|
||||
band->md->iter.offset += num_blocks;
|
||||
band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks);
|
||||
assert(band->md->iter.addr != FTL_ADDR_INVALID);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ftl_band_iter_set(struct ftl_band *band, uint64_t num_blocks)
|
||||
{
|
||||
band->md->iter.offset = num_blocks;
|
||||
band->md->iter.addr = ftl_band_next_xfer_addr(band, band->md->iter.addr, num_blocks);
|
||||
assert(band->md->iter.addr != FTL_ADDR_INVALID);
|
||||
}
|
||||
|
||||
#endif /* FTL_BAND_H */
|
@ -13,6 +13,7 @@
|
||||
#include "spdk/crc32.h"
|
||||
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_io.h"
|
||||
#include "ftl_debug.h"
|
||||
#include "ftl_internal.h"
|
||||
|
@ -23,6 +23,13 @@
|
||||
#include "ftl_l2p.h"
|
||||
#include "utils/ftl_log.h"
|
||||
|
||||
/*
|
||||
* We need to reserve at least 2 buffers for band close / open sequence
|
||||
* alone, plus additional (8) buffers for handling relocations.
|
||||
*
|
||||
*/
|
||||
#define P2L_MEMPOOL_SIZE (2 + 8)
|
||||
|
||||
/* When using VSS on nvcache, FTL sometimes doesn't require the contents of metadata.
|
||||
* Some devices have bugs when sending a NULL pointer as part of metadata when namespace
|
||||
* is formatted with VSS. This buffer is passed to such calls to avoid the bug. */
|
||||
@ -71,9 +78,21 @@ struct spdk_ftl_dev {
|
||||
3. base bdev read/write */
|
||||
uint64_t io_activity_total;
|
||||
|
||||
/* Array of bands */
|
||||
struct ftl_band *bands;
|
||||
|
||||
/* Number of operational bands */
|
||||
uint64_t num_bands;
|
||||
|
||||
/* Next write band */
|
||||
struct ftl_band *next_band;
|
||||
|
||||
/* Free band list */
|
||||
TAILQ_HEAD(, ftl_band) free_bands;
|
||||
|
||||
/* Closed bands list */
|
||||
TAILQ_HEAD(, ftl_band) shut_bands;
|
||||
|
||||
/* Number of free bands */
|
||||
uint64_t num_free;
|
||||
|
||||
@ -127,6 +146,12 @@ ftl_get_num_blocks_in_band(const struct spdk_ftl_dev *dev)
|
||||
return dev->num_blocks_in_band;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ftl_addr_get_band(const struct spdk_ftl_dev *dev, ftl_addr addr)
|
||||
{
|
||||
return addr / ftl_get_num_blocks_in_band(dev);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
ftl_get_write_unit_size(struct spdk_bdev *bdev)
|
||||
{
|
||||
@ -182,4 +207,19 @@ ftl_addr_from_nvc_offset(const struct spdk_ftl_dev *dev, uint64_t cache_offset)
|
||||
return cache_offset + dev->layout.base.total_blocks;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
ftl_p2l_map_num_blocks(const struct spdk_ftl_dev *dev)
|
||||
{
|
||||
return spdk_divide_round_up(ftl_get_num_blocks_in_band(dev) * sizeof(uint64_t),
|
||||
FTL_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
ftl_tail_md_num_blocks(const struct spdk_ftl_dev *dev)
|
||||
{
|
||||
return spdk_divide_round_up(
|
||||
ftl_p2l_map_num_blocks(dev),
|
||||
dev->xfer_size) * dev->xfer_size;
|
||||
}
|
||||
|
||||
#endif /* FTL_CORE_H */
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_io.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_debug.h"
|
||||
#include "ftl_nv_cache.h"
|
||||
#include "ftl_utils.h"
|
||||
|
@ -24,6 +24,30 @@
|
||||
*/
|
||||
typedef uint64_t ftl_addr;
|
||||
|
||||
enum ftl_md_type {
|
||||
FTL_MD_TYPE_BAND,
|
||||
FTL_MD_TYPE_CHUNK
|
||||
};
|
||||
|
||||
enum ftl_band_type {
|
||||
FTL_BAND_TYPE_GC = 1,
|
||||
FTL_BAND_TYPE_COMPACTION
|
||||
};
|
||||
|
||||
enum ftl_md_status {
|
||||
FTL_MD_SUCCESS,
|
||||
/* Metadata read failure */
|
||||
FTL_MD_IO_FAILURE,
|
||||
/* Invalid version */
|
||||
FTL_MD_INVALID_VER,
|
||||
/* UUID doesn't match */
|
||||
FTL_MD_NO_MD,
|
||||
/* UUID and version matches but CRC doesn't */
|
||||
FTL_MD_INVALID_CRC,
|
||||
/* Vld or p2l map size doesn't match */
|
||||
FTL_MD_INVALID_SIZE
|
||||
};
|
||||
|
||||
/* Number of LBAs that could be stored in a single block */
|
||||
#define FTL_NUM_LBA_IN_BLOCK (FTL_BLOCK_SIZE / sizeof(uint64_t))
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "utils/ftl_md.h"
|
||||
|
||||
struct spdk_ftl_dev;
|
||||
struct ftl_band;
|
||||
struct ftl_io;
|
||||
|
||||
typedef void (*ftl_io_fn)(struct ftl_io *, void *, int);
|
||||
@ -147,6 +148,11 @@ struct ftl_rq_entry {
|
||||
void *priv;
|
||||
} owner;
|
||||
|
||||
/* If request issued in iterative way, it contains IO information */
|
||||
struct {
|
||||
struct ftl_band *band;
|
||||
} io;
|
||||
|
||||
/* For l2p pinning */
|
||||
struct ftl_l2p_pin_ctx l2p_pin_ctx;
|
||||
|
||||
@ -194,6 +200,10 @@ struct ftl_rq {
|
||||
/* End request callback */
|
||||
void (*cb)(struct ftl_rq *rq);
|
||||
|
||||
/* IO error request callback */
|
||||
void (*error)(struct ftl_rq *rq, struct ftl_band *band,
|
||||
uint64_t idx, uint64_t count);
|
||||
|
||||
/* Owner context */
|
||||
void *priv;
|
||||
|
||||
@ -219,6 +229,9 @@ struct ftl_rq {
|
||||
/* Request physical address, on IO completion set for append device */
|
||||
ftl_addr addr;
|
||||
|
||||
/* Band to which IO is issued */
|
||||
struct ftl_band *band;
|
||||
|
||||
struct spdk_bdev_io_wait_entry bdev_io_wait;
|
||||
} io;
|
||||
|
||||
@ -228,7 +241,7 @@ struct ftl_rq {
|
||||
struct ftl_rq_entry entries[];
|
||||
};
|
||||
|
||||
/* Used for reading/writing LBA map during runtime and recovery */
|
||||
/* Used for reading/writing P2L map during runtime and recovery */
|
||||
struct ftl_basic_rq {
|
||||
struct spdk_ftl_dev *dev;
|
||||
|
||||
@ -258,6 +271,9 @@ struct ftl_basic_rq {
|
||||
/* Request physical address, on IO completion set for append device */
|
||||
ftl_addr addr;
|
||||
|
||||
/* Band to which IO is issued */
|
||||
struct ftl_band *band;
|
||||
|
||||
/* Chunk to which IO is issued */
|
||||
struct ftl_nv_cache_chunk *chunk;
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
*/
|
||||
|
||||
#include "ftl_l2p.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_nv_cache.h"
|
||||
#include "ftl_l2p_flat.h"
|
||||
#include "ftl_core.h"
|
||||
|
||||
|
||||
/* TODO: Verify why function pointers had worse performance than compile time constants */
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "ftl_l2p.h"
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_utils.h"
|
||||
#include "ftl_l2p_flat.h"
|
||||
#include "utils/ftl_addr_utils.h"
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_utils.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_layout.h"
|
||||
#include "ftl_nv_cache.h"
|
||||
#include "ftl_sb.h"
|
||||
@ -158,6 +159,34 @@ setup_layout_nvc(struct spdk_ftl_dev *dev)
|
||||
set_region_bdev_nvc(region, dev);
|
||||
offset += region->current.blocks;
|
||||
|
||||
/* Initialize band info metadata */
|
||||
if (offset >= layout->nvc.total_blocks) {
|
||||
goto error;
|
||||
}
|
||||
region = &layout->region[FTL_LAYOUT_REGION_TYPE_BAND_MD];
|
||||
region->type = FTL_LAYOUT_REGION_TYPE_BAND_MD;
|
||||
region->mirror_type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR;
|
||||
region->name = "band_md";
|
||||
region->current.version = region->prev.version = FTL_BAND_VERSION_CURRENT;
|
||||
region->current.offset = offset;
|
||||
region->current.blocks = blocks_region(ftl_get_num_bands(dev) * sizeof(struct ftl_band_md));
|
||||
region->entry_size = sizeof(struct ftl_band_md) / FTL_BLOCK_SIZE;
|
||||
region->num_entries = ftl_get_num_bands(dev);
|
||||
set_region_bdev_nvc(region, dev);
|
||||
offset += region->current.blocks;
|
||||
|
||||
/* Initialize band info metadata mirror */
|
||||
if (offset >= layout->nvc.total_blocks) {
|
||||
goto error;
|
||||
}
|
||||
mirror = &layout->region[FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR];
|
||||
*mirror = *region;
|
||||
mirror->type = FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR;
|
||||
mirror->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID;
|
||||
mirror->name = "band_md_mirror";
|
||||
mirror->current.offset += region->current.blocks;
|
||||
offset += mirror->current.blocks;
|
||||
|
||||
if (offset >= layout->nvc.total_blocks) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -23,6 +23,11 @@ enum ftl_layout_region_type {
|
||||
/* If using cached L2P, this region stores the serialized instance of it */
|
||||
FTL_LAYOUT_REGION_TYPE_L2P,
|
||||
|
||||
/* State of bands */
|
||||
FTL_LAYOUT_REGION_TYPE_BAND_MD,
|
||||
/* Mirrored instance of bands state */
|
||||
FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR,
|
||||
|
||||
/* State of chunks */
|
||||
FTL_LAYOUT_REGION_TYPE_NVC_MD,
|
||||
/* Mirrored instance of the state of chunks */
|
||||
@ -99,6 +104,8 @@ struct ftl_layout {
|
||||
/* Organization for base device */
|
||||
struct {
|
||||
uint64_t total_blocks;
|
||||
uint64_t num_usable_blocks;
|
||||
uint64_t user_blocks;
|
||||
} base;
|
||||
|
||||
/* Organization for NV cache */
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "ftl_nv_cache.h"
|
||||
#include "ftl_nv_cache_io.h"
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_band.h"
|
||||
#include "utils/ftl_addr_utils.h"
|
||||
#include "mngt/ftl_mngt.h"
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_mngt.h"
|
||||
#include "ftl_mngt_steps.h"
|
||||
#include "ftl_band.h"
|
||||
|
||||
struct ftl_io_channel_ctx {
|
||||
struct ftl_io_channel *ioch;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ftl_core.h"
|
||||
#include "ftl_mngt.h"
|
||||
#include "ftl_mngt_steps.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_l2p.h"
|
||||
|
||||
static void
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "ftl_mngt.h"
|
||||
#include "ftl_mngt_steps.h"
|
||||
#include "ftl_utils.h"
|
||||
#include "ftl_band.h"
|
||||
#include "ftl_internal.h"
|
||||
#include "ftl_sb.h"
|
||||
|
||||
@ -30,12 +31,12 @@ is_buffer_needed(enum ftl_layout_region_type type)
|
||||
#ifdef SPDK_FTL_VSS_EMU
|
||||
case FTL_LAYOUT_REGION_TYPE_VSS:
|
||||
#endif
|
||||
|
||||
case FTL_LAYOUT_REGION_TYPE_SB:
|
||||
case FTL_LAYOUT_REGION_TYPE_SB_BASE:
|
||||
case FTL_LAYOUT_REGION_TYPE_DATA_NVC:
|
||||
case FTL_LAYOUT_REGION_TYPE_DATA_BASE:
|
||||
case FTL_LAYOUT_REGION_TYPE_NVC_MD_MIRROR:
|
||||
case FTL_LAYOUT_REGION_TYPE_BAND_MD_MIRROR:
|
||||
return false;
|
||||
|
||||
default:
|
||||
|
@ -37,4 +37,8 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FTL_INVALID_VALUE ((uint64_t)-1)
|
||||
#define FTL_BAND_ID_INVALID FTL_INVALID_VALUE
|
||||
#define FTL_BAND_PHYS_ID_INVALID FTL_INVALID_VALUE
|
||||
|
||||
#endif /* FTL_DEFS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user