Change-Id: I7d2fd31620481cf66f5f4400e6de4fc736ee3dad Signed-off-by: Mateusz Kozlowski <mateusz.kozlowski@solidigm.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/17608 Reviewed-by: Ben Walker <benjamin.walker@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
167 lines
4.2 KiB
C
167 lines
4.2 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright (C) 2022 Intel Corporation.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#ifndef FTL_INTERNAL_H
|
|
#define FTL_INTERNAL_H
|
|
|
|
#include "spdk/stdinc.h"
|
|
#include "spdk/crc32.h"
|
|
#include "spdk/util.h"
|
|
#include "spdk/uuid.h"
|
|
|
|
#include "utils/ftl_bitmap.h"
|
|
|
|
/* Marks address as invalid */
|
|
#define FTL_ADDR_INVALID ((ftl_addr)-1)
|
|
/* Marks LBA as invalid */
|
|
#define FTL_LBA_INVALID ((uint64_t)-1)
|
|
/* Smallest data unit size */
|
|
#define FTL_BLOCK_SIZE 4096ULL
|
|
|
|
#define FTL_P2L_VERSION_0 0
|
|
#define FTL_P2L_VERSION_1 1
|
|
|
|
#define FTL_P2L_VERSION_CURRENT FTL_P2L_VERSION_1
|
|
|
|
/*
|
|
* This type represents address in the ftl address space. Values from 0 to based bdev size are
|
|
* mapped directly to base device lbas. Values above that represent nv cache lbas.
|
|
*/
|
|
typedef uint64_t ftl_addr;
|
|
|
|
struct spdk_ftl_dev;
|
|
|
|
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
|
|
};
|
|
|
|
struct ftl_p2l_map_entry {
|
|
uint64_t lba;
|
|
uint64_t seq_id;
|
|
};
|
|
|
|
/* Number of LBAs that could be stored in a single block */
|
|
#define FTL_NUM_LBA_IN_BLOCK (FTL_BLOCK_SIZE / sizeof(struct ftl_p2l_map_entry))
|
|
|
|
/*
|
|
* Mapping of physical (actual location on disk) to logical (user's POV) addresses. Used in two main scenarios:
|
|
* - during relocation FTL needs to pin L2P pages (this allows to check which pages to pin) and move still valid blocks
|
|
* (valid map allows for preliminary elimination of invalid physical blocks, but user data could invalidate a location
|
|
* during read/write operation, so actual comparison against L2P needs to be done)
|
|
* - After dirty shutdown the state of the L2P is unknown and needs to be rebuilt - it is done by applying all P2L, taking
|
|
* into account ordering of user writes
|
|
*/
|
|
struct ftl_p2l_map {
|
|
/* Number of valid LBAs */
|
|
size_t num_valid;
|
|
|
|
/* P2L map's reference count, prevents premature release of resources during dirty shutdown recovery for open bands */
|
|
size_t ref_cnt;
|
|
|
|
/* Bitmap of valid LBAs */
|
|
struct ftl_bitmap *valid;
|
|
|
|
/* P2L map (only valid for open/relocating bands) */
|
|
union {
|
|
struct ftl_p2l_map_entry *band_map;
|
|
void *chunk_map;
|
|
};
|
|
|
|
/* DMA buffer for region's metadata entry */
|
|
union {
|
|
struct ftl_band_md *band_dma_md;
|
|
|
|
struct ftl_nv_cache_chunk_md *chunk_dma_md;
|
|
};
|
|
|
|
/* P2L checkpointing region */
|
|
struct ftl_p2l_ckpt *p2l_ckpt;
|
|
};
|
|
|
|
struct ftl_p2l_sync_ctx {
|
|
struct ftl_band *band;
|
|
uint64_t page_start;
|
|
uint64_t page_end;
|
|
int md_region;
|
|
};
|
|
|
|
struct ftl_p2l_ckpt_page {
|
|
struct ftl_p2l_map_entry map[FTL_NUM_LBA_IN_BLOCK];
|
|
};
|
|
|
|
struct ftl_p2l_ckpt;
|
|
struct ftl_band;
|
|
struct spdk_ftl_dev;
|
|
struct ftl_mngt_process;
|
|
struct ftl_rq;
|
|
|
|
int ftl_p2l_ckpt_init(struct spdk_ftl_dev *dev);
|
|
|
|
void ftl_p2l_ckpt_deinit(struct spdk_ftl_dev *dev);
|
|
|
|
void ftl_p2l_ckpt_issue(struct ftl_rq *rq);
|
|
|
|
struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire(struct spdk_ftl_dev *dev);
|
|
|
|
struct ftl_p2l_ckpt *ftl_p2l_ckpt_acquire_region_type(struct spdk_ftl_dev *dev,
|
|
uint32_t region_type);
|
|
|
|
void ftl_p2l_ckpt_release(struct spdk_ftl_dev *dev, struct ftl_p2l_ckpt *ckpt);
|
|
|
|
enum ftl_layout_region_type ftl_p2l_ckpt_region_type(const struct ftl_p2l_ckpt *ckpt);
|
|
|
|
#if defined(DEBUG)
|
|
void ftl_p2l_validate_ckpt(struct ftl_band *band);
|
|
#else
|
|
static inline void
|
|
ftl_p2l_validate_ckpt(struct ftl_band *band)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
uint64_t ftl_mngt_p2l_ckpt_get_seq_id(struct spdk_ftl_dev *dev, int md_region);
|
|
|
|
int ftl_mngt_p2l_ckpt_restore(struct ftl_band *band, uint32_t md_region, uint64_t seq_id);
|
|
|
|
int ftl_mngt_p2l_ckpt_restore_clean(struct ftl_band *band);
|
|
|
|
void ftl_mngt_p2l_ckpt_restore_shm_clean(struct ftl_band *band);
|
|
|
|
void ftl_mngt_persist_bands_p2l(struct ftl_mngt_process *mngt);
|
|
|
|
struct ftl_reloc *ftl_reloc_init(struct spdk_ftl_dev *dev);
|
|
|
|
void ftl_reloc_free(struct ftl_reloc *reloc);
|
|
|
|
void ftl_reloc(struct ftl_reloc *reloc);
|
|
|
|
void ftl_reloc_halt(struct ftl_reloc *reloc);
|
|
|
|
void ftl_reloc_resume(struct ftl_reloc *reloc);
|
|
|
|
bool ftl_reloc_is_halted(const struct ftl_reloc *reloc);
|
|
|
|
#endif /* FTL_INTERNAL_H */
|