diff --git a/src/concurrency/ocf_metadata_concurrency.c b/src/concurrency/ocf_metadata_concurrency.c index 7952ac2..2d0a551 100644 --- a/src/concurrency/ocf_metadata_concurrency.c +++ b/src/concurrency/ocf_metadata_concurrency.c @@ -4,6 +4,7 @@ */ #include "ocf_metadata_concurrency.h" +#include "../metadata/metadata_misc.h" void ocf_metadata_concurrency_init(struct ocf_metadata_lock *metadata_lock) { @@ -20,11 +21,12 @@ void ocf_metadata_concurrency_deinit(struct ocf_metadata_lock *metadata_lock) } int ocf_metadata_concurrency_attached_init( - struct ocf_metadata_lock *metadata_lock, + struct ocf_metadata_lock *metadata_lock, ocf_cache_t cache, uint64_t hash_table_entries) { uint64_t i; + metadata_lock->cache = cache; metadata_lock->num_hash_entries = hash_table_entries; metadata_lock->hash = env_vzalloc(sizeof(env_rwsem) * hash_table_entries); @@ -132,6 +134,49 @@ int ocf_metadata_hash_try_lock(struct ocf_metadata_lock *metadata_lock, return 0; } +/* NOTE: attempt to acquire hash lock for multiple core lines may end up + * in deadlock. In order to hash lock multiple core lines safely, use + * ocf_req_hash_lock_* functions */ +void ocf_metadata_hash_lock_rd(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line) +{ + ocf_cache_line_t hash = ocf_metadata_hash_func(metadata_lock->cache, + core_line, core_id); + + ocf_metadata_start_shared_access(metadata_lock); + ocf_metadata_hash_lock(metadata_lock, hash, OCF_METADATA_RD); +} + +void ocf_metadata_hash_unlock_rd(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line) +{ + ocf_cache_line_t hash = ocf_metadata_hash_func(metadata_lock->cache, + core_line, core_id); + + ocf_metadata_hash_unlock(metadata_lock, hash, OCF_METADATA_RD); + ocf_metadata_end_shared_access(metadata_lock); +} + +void ocf_metadata_hash_lock_wr(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line) +{ + ocf_cache_line_t hash = ocf_metadata_hash_func(metadata_lock->cache, + core_line, core_id); + + ocf_metadata_start_shared_access(metadata_lock); + ocf_metadata_hash_lock(metadata_lock, hash, OCF_METADATA_WR); +} + +void ocf_metadata_hash_unlock_wr(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line) +{ + ocf_cache_line_t hash = ocf_metadata_hash_func(metadata_lock->cache, + core_line, core_id); + + ocf_metadata_hash_unlock(metadata_lock, hash, OCF_METADATA_WR); + ocf_metadata_end_shared_access(metadata_lock); +} + #define _NUM_HASH_ENTRIES req->cache->metadata.lock.num_hash_entries /* diff --git a/src/concurrency/ocf_metadata_concurrency.h b/src/concurrency/ocf_metadata_concurrency.h index ccd996b..c085c97 100644 --- a/src/concurrency/ocf_metadata_concurrency.h +++ b/src/concurrency/ocf_metadata_concurrency.h @@ -15,7 +15,7 @@ void ocf_metadata_concurrency_init(struct ocf_metadata_lock *metadata_lock); void ocf_metadata_concurrency_deinit(struct ocf_metadata_lock *metadata_lock); int ocf_metadata_concurrency_attached_init( - struct ocf_metadata_lock *metadata_lock, + struct ocf_metadata_lock *metadata_lock, ocf_cache_t cache, uint64_t hash_table_entries); void ocf_metadata_concurrency_attached_deinit( @@ -113,6 +113,16 @@ static inline void ocf_metadata_status_bits_unlock( ocf_metadata_status_bits_unlock(&cache->metadata.lock, \ OCF_METADATA_WR) +void ocf_metadata_hash_lock_rd(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line); +void ocf_metadata_hash_unlock_rd(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line); +void ocf_metadata_hash_lock_wr(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line); +void ocf_metadata_hash_unlock_wr(struct ocf_metadata_lock *metadata_lock, + uint32_t core_id, uint64_t core_line); + +/* lock entire request in deadlock-free manner */ void ocf_req_hash_lock_rd(struct ocf_request *req); void ocf_req_hash_unlock_rd(struct ocf_request *req); void ocf_req_hash_lock_wr(struct ocf_request *req); diff --git a/src/metadata/metadata_structs.h b/src/metadata/metadata_structs.h index ccea1a0..22b3703 100644 --- a/src/metadata/metadata_structs.h +++ b/src/metadata/metadata_structs.h @@ -435,6 +435,7 @@ struct ocf_metadata_lock env_spinlock eviction; /*!< Fast lock for eviction policy */ env_rwsem *hash; /*!< Hash bucket locks */ uint32_t num_hash_entries; /*!< Hash bucket count */ + ocf_cache_t cache; /*!< Parent cache object */ }; /** diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 847efef..22b8558 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -987,7 +987,7 @@ static void _ocf_mngt_attach_prepare_metadata(ocf_pipeline_t pipeline, context->flags.attached_metadata_inited = true; if (ocf_metadata_concurrency_attached_init(&cache->metadata.lock, - cache->device->hash_table_entries)) { + cache, cache->device->hash_table_entries)) { ocf_cache_log(cache, log_err, "Failed to initialize attached " "metadata concurrency\n"); OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_START_CACHE_FAIL);