/* SPDX-License-Identifier: BSD-3-Clause * Copyright (c) Intel Corporation. * All rights reserved. */ #ifndef FTL_MD_H #define FTL_MD_H #include "spdk/stdinc.h" #include "ftl_layout.h" struct ftl_md; struct spdk_ftl_dev; typedef void (*ftl_md_cb)(struct spdk_ftl_dev *dev, struct ftl_md *md, int status); enum ftl_md_ops { FTL_MD_OP_RESTORE, FTL_MD_OP_PERSIST, FTL_MD_OP_CLEAR, }; typedef int (*shm_open_t)(const char *, int, mode_t); typedef int (*shm_unlink_t)(const char *); /* FTL metadata container which allows to store/restore/recover */ struct ftl_md { /* Context of owner (Caller of restore/persist/clear operation) */ struct { /* Private context of the metadata's owner */ void *private; /* Additional context of the owner */ void *cb_ctx; } owner; /* Callback for signaling end of procedures like restore, persist, or clear */ ftl_md_cb cb; /* Pointer to the FTL device */ struct spdk_ftl_dev *dev; /* Region of device on which store/restore the metadata */ const struct ftl_layout_region *region; /* Pointer to data */ void *data; /* Size of buffer in FTL block size unit */ uint64_t data_blocks; /* Pointer to VSS metadata data */ void *vss_data; /* Default DMA buffer for VSS of a single entry. Used by ftl_md_persist_entry(). */ void *entry_vss_dma_buf; /* Fields for doing IO */ struct { void *data; void *md; uint64_t address; uint64_t remaining; uint64_t data_offset; int status; enum ftl_md_ops op; struct spdk_bdev_io_wait_entry bdev_io_wait; } io; /* SHM object file descriptor or -1 if heap alloc */ int shm_fd; /* Object name */ char name[NAME_MAX + 1]; /* mmap flags for the SHM object */ int shm_mmap_flags; /* Total size of SHM object (data + md) */ size_t shm_sz; /* open() for the SHM object */ shm_open_t shm_open; /* unlink() for the SHM object */ shm_unlink_t shm_unlink; /* Memory was registered to SPDK */ bool mem_reg; /* Metadata primary object */ struct ftl_md *mirror; /* This flag is used by the primary to disable mirror temporarily */ bool mirror_enabled; }; typedef void (*ftl_md_io_entry_cb)(int status, void *cb_arg); struct ftl_md_io_entry_ctx { uint32_t remaining; int status; ftl_md_io_entry_cb cb; void *cb_arg; struct ftl_md *md; uint64_t start_entry; void *buffer; void *vss_buffer; struct spdk_bdev_io_wait_entry bdev_io_wait; }; #define FTL_MD_VSS_SZ 64 union ftl_md_vss { struct { uint8_t unused[FTL_MD_VSS_SZ - sizeof(uint64_t)]; uint64_t md_version; } version; struct { uint64_t start_lba; uint64_t num_blocks; } unmap; struct { uint64_t lba; } nv_cache; }; SPDK_STATIC_ASSERT(sizeof(union ftl_md_vss) == FTL_MD_VSS_SZ, "Invalid md vss size"); /** * FTL metadata creation flags */ enum ftl_md_create_flags { /** FTL metadata will be created without memory allocation */ FTL_MD_CREATE_NO_MEM = 0x0, /** FTL metadata data buf will be allocated in SHM */ FTL_MD_CREATE_SHM = 0x1, /** Always create a new SHM obj, i.e. issue shm_unlink() before shm_open(), only valid with FTL_MD_CREATE_SHM */ FTL_MD_CREATE_SHM_NEW = 0x2, /** FTL metadata will be created on heap */ FTL_MD_CREATE_HEAP = 0x4, }; /** * @brief Creates FTL metadata * * @param dev The FTL device * @param blocks Size of buffer in FTL block size unit * @param vss_blksz Size of VSS MD * @param name Name of the object being created * @param flags Bit flags of ftl_md_create_flags type * @param region Region associated with FTL metadata * * @note if buffer is NULL, the buffer will be allocated internally by the object * * @return FTL metadata */ struct ftl_md *ftl_md_create(struct spdk_ftl_dev *dev, uint64_t blocks, uint64_t vss_blksz, const char *name, int flags, const struct ftl_layout_region *region); /** * @brief Unlinks metadata object from FS * @param dev The FTL device * @param name Name of the object being unlinked * @param flags Bit flag describing the MD object * * @note Unlink is possible only for objects created with FTL_MD_CREATE_SHM flag * * @return Operation result */ int ftl_md_unlink(struct spdk_ftl_dev *dev, const char *name, int flags); /** * @brief Destroys metadata * * @param md Metadata to be destroyed */ void ftl_md_destroy(struct ftl_md *md); /** * @brief Free the data buf associated with the metadata * * @param md Metadata object */ void ftl_md_free_buf(struct ftl_md *md); /** * @brief Sets the region of a device on which to perform IO when persisting, * restoring, or clearing. * * @param md The FTL metadata * @param region The device region to be set * * @return Operation status */ int ftl_md_set_region(struct ftl_md *md, const struct ftl_layout_region *region); /** * @brief Gets layout region on which ongoing an IO procedure is executed * * @param md Metadata object * * @return Layout region */ const struct ftl_layout_region *ftl_md_get_region(struct ftl_md *md); /** * @brief Gets metadata's data buffer * * @param md The FTL metadata * * @result FTL metadata data buffer */ void *ftl_md_get_buffer(struct ftl_md *md); /** * @brief Gets metadata object corresponding buffer size * * @param md The FTL metadata * * @return Buffer size */ uint64_t ftl_md_get_buffer_size(struct ftl_md *md); /** * @brief Heap allocate and initialize a vss buffer for MD region. * * The buffer is aligned to FTL_BLOCK_SIZE. * The buffer is zeroed. * The VSS version is inherited from the MD region. * * @param region The MD region * @param count Number of VSS items to allocate * * @return VSS buffer */ union ftl_md_vss *ftl_md_vss_buf_alloc(struct ftl_layout_region *region, uint32_t count); /** * @brief Get the VSS metadata data buffer * * @param md The FTL metadata * * @return VSS metadata data buffer */ union ftl_md_vss *ftl_md_get_vss_buffer(struct ftl_md *md); /** * Restores metadata from the region which is set * * @param md Metadata to be restored */ void ftl_md_restore(struct ftl_md *md); /** * Persists all metadata to the region which is set * * @param md Metadata to be persisted */ void ftl_md_persist(struct ftl_md *md); /** * Persists given entries in metadata to the region which is set * * @param md Metadata to be persisted * @param start_entry Starting index of entry to be persisted * @param buffer DMA buffer for writing the entry to the device * @param vss_buffer DMA buffer for writing the entry VSS to the device * @param cb Completion called on persist entry end * @param cb_arg Context returned on completion * @param ctx Operation context structure */ void ftl_md_persist_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer, ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx); /** * Retries a persist operation performed by ftl_md_persist_entry. * * @param ctx Operation context structure. */ void ftl_md_persist_entry_retry(struct ftl_md_io_entry_ctx *ctx); /** * Reads given entries from metadata region * * @param md Metadata to be read * @param start_entry Starting index of entry to be read * @param buffer DMA buffer for reading the entry from the device * @param vss_buffer DMA buffer for reading the entry VSS from the device * @param cb Completion called on read entry end * @param cb_arg Context returned on completion * @param ctx Operation context structure */ void ftl_md_read_entry(struct ftl_md *md, uint64_t start_entry, void *buffer, void *vss_buffer, ftl_md_io_entry_cb cb, void *cb_arg, struct ftl_md_io_entry_ctx *ctx); /** * @brief Clears metadata on the region which is set * * @param md Metadata to be cleared * @param pattern Pattern used to initialize metadata * @param vss_pattern Pattern used to initialize metadata VSS * * @note size of pattern needs to be aligned to FTL device transfer size */ void ftl_md_clear(struct ftl_md *md, int pattern, union ftl_md_vss *vss_pattern); /** * @brief Gets the number of blocks that are transfered in a single IO operation * * @param dev The FTL device * * @return Number of blocks */ uint64_t ftl_md_xfer_blocks(struct spdk_ftl_dev *dev); #endif /* FTL_MD_H */