/* * Copyright(c) 2012-2018 Intel Corporation * SPDX-License-Identifier: BSD-3-Clause-Clear */ #ifndef __METADATA_H__ #define __METADATA_H__ #include "metadata_common.h" #include "../ocf_cache_priv.h" #include "../ocf_ctx_priv.h" static inline void ocf_metadata_eviction_lock(struct ocf_cache *cache) { env_spinlock_lock(&cache->metadata.lock.eviction); } static inline void ocf_metadata_eviction_unlock(struct ocf_cache *cache) { env_spinlock_unlock(&cache->metadata.lock.eviction); } #define OCF_METADATA_EVICTION_LOCK() \ ocf_metadata_eviction_lock(cache) #define OCF_METADATA_EVICTION_UNLOCK() \ ocf_metadata_eviction_unlock(cache) static inline void ocf_metadata_lock(struct ocf_cache *cache, int rw) { if (rw == OCF_METADATA_WR) env_rwsem_down_write(&cache->metadata.lock.collision); else if (rw == OCF_METADATA_RD) env_rwsem_down_read(&cache->metadata.lock.collision); else ENV_BUG(); } static inline void ocf_metadata_unlock(struct ocf_cache *cache, int rw) { if (rw == OCF_METADATA_WR) env_rwsem_up_write(&cache->metadata.lock.collision); else if (rw == OCF_METADATA_RD) env_rwsem_up_read(&cache->metadata.lock.collision); else ENV_BUG(); } static inline int ocf_metadata_try_lock(struct ocf_cache *cache, int rw) { int result = 0; if (rw == OCF_METADATA_WR) { result = env_rwsem_down_write_trylock( &cache->metadata.lock.collision); } else if (rw == OCF_METADATA_RD) { result = env_rwsem_down_read_trylock( &cache->metadata.lock.collision); } else { ENV_BUG(); } if (result) return -1; return 0; } static inline void ocf_metadata_status_bits_lock( struct ocf_cache *cache, int rw) { if (rw == OCF_METADATA_WR) env_rwlock_write_lock(&cache->metadata.lock.status); else if (rw == OCF_METADATA_RD) env_rwlock_read_lock(&cache->metadata.lock.status); else ENV_BUG(); } static inline void ocf_metadata_status_bits_unlock( struct ocf_cache *cache, int rw) { if (rw == OCF_METADATA_WR) env_rwlock_write_unlock(&cache->metadata.lock.status); else if (rw == OCF_METADATA_RD) env_rwlock_read_unlock(&cache->metadata.lock.status); else ENV_BUG(); } #define OCF_METADATA_LOCK_RD() \ ocf_metadata_lock(cache, OCF_METADATA_RD) #define OCF_METADATA_UNLOCK_RD() \ ocf_metadata_unlock(cache, OCF_METADATA_RD) #define OCF_METADATA_LOCK_RD_TRY() \ ocf_metadata_try_lock(cache, OCF_METADATA_RD) #define OCF_METADATA_LOCK_WR() \ ocf_metadata_lock(cache, OCF_METADATA_WR) #define OCF_METADATA_LOCK_WR_TRY() \ ocf_metadata_try_lock(cache, OCF_METADATA_WR) #define OCF_METADATA_UNLOCK_WR() \ ocf_metadata_unlock(cache, OCF_METADATA_WR) #define OCF_METADATA_BITS_LOCK_RD() \ ocf_metadata_status_bits_lock(cache, OCF_METADATA_RD) #define OCF_METADATA_BITS_UNLOCK_RD() \ ocf_metadata_status_bits_unlock(cache, OCF_METADATA_RD) #define OCF_METADATA_BITS_LOCK_WR() \ ocf_metadata_status_bits_lock(cache, OCF_METADATA_WR) #define OCF_METADATA_BITS_UNLOCK_WR() \ ocf_metadata_status_bits_unlock(cache, OCF_METADATA_WR) #define OCF_METADATA_FLUSH_LOCK() \ ocf_metadata_flush_lock(cache) #define OCF_METADATA_FLUSH_UNLOCK() \ ocf_metadata_flush_unlock(cache) #include "metadata_cleaning_policy.h" #include "metadata_eviction_policy.h" #include "metadata_partition.h" #include "metadata_hash.h" #include "metadata_superblock.h" #include "metadata_status.h" #include "metadata_collision.h" #include "metadata_core.h" #include "metadata_misc.h" #define INVALID 0 #define VALID 1 #define CLEAN 2 #define DIRTY 3 /** * @brief Initialize metadata * * @param cache - Cache instance * @param cache_line_size Cache line size * @return 0 - Operation success otherwise failure */ int ocf_metadata_init(struct ocf_cache *cache, ocf_cache_line_size_t cache_line_size); /** * @brief Initialize per-cacheline metadata * * @param cache - Cache instance * @param device_size - Device size in bytes * @param cache_line_size Cache line size * @return 0 - Operation success otherwise failure */ int ocf_metadata_init_variable_size(struct ocf_cache *cache, uint64_t device_size, ocf_cache_line_size_t cache_line_size, ocf_metadata_layout_t layout); /** * @brief Initialize collision table * * @param cache - Cache instance */ void ocf_metadata_init_freelist_partition(struct ocf_cache *cache); /** * @brief Initialize hash table * * @param cache - Cache instance */ void ocf_metadata_init_hash_table(struct ocf_cache *cache); /** * @brief De-Initialize metadata * * @param cache - Cache instance */ void ocf_metadata_deinit(struct ocf_cache *cache); /** * @brief De-Initialize per-cacheline metadata * * @param cache - Cache instance */ void ocf_metadata_deinit_variable_size(struct ocf_cache *cache); /** * @brief Get memory footprint * * @param cache - Cache instance * @return 0 - memory footprint */ size_t ocf_metadata_size_of(struct ocf_cache *cache); /** * @brief Handle metadata error * * @param cache - Cache instance */ void ocf_metadata_error(struct ocf_cache *cache); /** * @brief Get amount of cache lines * * @param cache - Cache instance * @return Amount of cache lines (cache device lines - metadata space) */ ocf_cache_line_t ocf_metadata_get_cachelines_count(struct ocf_cache *cache); /** * @brief Get amount of pages required for metadata * * @param cache - Cache instance * @return Pages required for store metadata on cache device */ ocf_cache_line_t ocf_metadata_get_pages_count(struct ocf_cache *cache); /** * @brief Flush metadata * * @param cache - Cache instance * @param cmpl - Completion callback * @param priv - Completion context */ void ocf_metadata_flush_all(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); /** * @brief Mark specified cache line to be flushed * * @param[in] cache - Cache instance * @param[in] line - cache line which to be flushed */ void ocf_metadata_flush_mark(struct ocf_cache *cache, struct ocf_request *req, uint32_t map_idx, int to_state, uint8_t start, uint8_t stop); /** * @brief Flush marked cache lines asynchronously * * @param cache - Cache instance * @param queue - I/O queue to which metadata flush should be submitted * @param remaining - request remaining * @param complete - flushing request callback * @param context - context that will be passed into callback */ void ocf_metadata_flush_do_asynch(struct ocf_cache *cache, struct ocf_request *req, ocf_req_end_t complete); /** * @brief Load metadata * * @param cache - Cache instance * @param cmpl - Completion callback * @param priv - Completion context */ void ocf_metadata_load_all(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); /** * @brief Load metadata required for recovery procedure * * @param cache Cache instance * @param cmpl - Completion callback * @param priv - Completion context */ void ocf_metadata_load_recovery(ocf_cache_t cache, ocf_metadata_end_t cmpl, void *priv); /** * @brief Get reserved area lba * * @param cache Cache instance */ static inline uint64_t ocf_metadata_get_reserved_lba(ocf_cache_t cache) { return cache->metadata.iface.get_reserved_lba(cache); } /* * NOTE Hash table is specific for hash table metadata service implementation * and should be used internally by metadata service. * At the moment there is no high level metadata interface because of that * temporary defined in this file. */ static inline ocf_cache_line_t ocf_metadata_get_hash(struct ocf_cache *cache, ocf_cache_line_t index) { return cache->metadata.iface.get_hash(cache, index); } static inline void ocf_metadata_set_hash(struct ocf_cache *cache, ocf_cache_line_t index, ocf_cache_line_t line) { cache->metadata.iface.set_hash(cache, index, line); } static inline ocf_cache_line_t ocf_metadata_entries_hash( struct ocf_cache *cache) { return cache->metadata.iface.entries_hash(cache); } struct ocf_metadata_load_properties { enum ocf_metadata_shutdown_status shutdown_status; uint8_t dirty_flushed; ocf_metadata_layout_t layout; ocf_cache_line_size_t line_size; ocf_cache_mode_t cache_mode; }; typedef void (*ocf_metadata_load_properties_end_t)(void *priv, int error, struct ocf_metadata_load_properties *properties); void ocf_metadata_load_properties(ocf_volume_t volume, ocf_metadata_load_properties_end_t cmpl, void *priv); /** * @brief Validate cache line size * * @param size Cache line size * @return true - cache line size is valid, false - cache line is invalid */ static inline bool ocf_metadata_line_size_is_valid(uint32_t size) { switch (size) { case 4 * KiB: case 8 * KiB: case 16 * KiB: case 32 * KiB: case 64 * KiB: return true; default: return false; } } #endif /* METADATA_H_ */