Per-execution-context freelists

Global free cacheline list is divided into a set of freelists, one
per execution context. When attempting to map addres to cache, first
the freelist for current execution context is considered (fast path).
If current execution context freelist is empty (fast path failure),
mapping function attempts to get freelist from other execution context
list (slow path).

The purpose of this change is improve concurrency in freelist access.
It is part of fine granularity metadata lock implementation.

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski
2019-08-26 14:54:19 -04:00
parent f892bb962d
commit 13cf871a13
21 changed files with 545 additions and 204 deletions

View File

@@ -53,18 +53,18 @@ int ocf_metadata_init_variable_size(struct ocf_cache *cache, uint64_t device_siz
cache_line_size, layout);
}
void ocf_metadata_init_freelist_partition(struct ocf_cache *cache)
{
OCF_DEBUG_TRACE(cache);
cache->metadata.iface.init_freelist(cache);
}
void ocf_metadata_init_hash_table(struct ocf_cache *cache)
{
OCF_DEBUG_TRACE(cache);
cache->metadata.iface.init_hash_table(cache);
}
void ocf_metadata_init_collision(struct ocf_cache *cache)
{
OCF_DEBUG_TRACE(cache);
cache->metadata.iface.init_collision(cache);
}
void ocf_metadata_deinit(struct ocf_cache *cache)
{
OCF_DEBUG_TRACE(cache);

View File

@@ -60,6 +60,13 @@ void ocf_metadata_init_freelist_partition(struct ocf_cache *cache);
*/
void ocf_metadata_init_hash_table(struct ocf_cache *cache);
/**
* @brief Initialize collision table
*
* @param cache - Cache instance
*/
void ocf_metadata_init_collision(struct ocf_cache *cache);
/**
* @brief De-Initialize metadata
*
@@ -207,4 +214,10 @@ typedef void (*ocf_metadata_load_properties_end_t)(void *priv, int error,
void ocf_metadata_load_properties(ocf_volume_t volume,
ocf_metadata_load_properties_end_t cmpl, void *priv);
static inline ocf_cache_line_t ocf_metadata_collision_table_entries(
struct ocf_cache *cache)
{
return cache->device->collision_table_entries;
}
#endif /* METADATA_H_ */

View File

@@ -13,6 +13,7 @@
#include "../utils/utils_pipeline.h"
#include "../ocf_def_priv.h"
#include "../ocf_priv.h"
#include "../ocf_freelist.h"
#define OCF_METADATA_HASH_DEBUG 0
@@ -1025,14 +1026,10 @@ finalize:
}
static inline void _ocf_init_collision_entry(struct ocf_cache *cache,
ocf_cache_line_t idx, ocf_cache_line_t next,
ocf_cache_line_t prev)
ocf_cache_line_t idx)
{
ocf_cache_line_t invalid_idx = cache->device->collision_table_entries;
ocf_part_id_t invalid_part_id = PARTITION_INVALID;
ocf_metadata_set_partition_info(cache, idx,
invalid_part_id, next, prev);
ocf_metadata_set_collision_info(cache, idx, invalid_idx, invalid_idx);
ocf_metadata_set_core_info(cache, idx,
OCF_CORE_MAX, ULONG_MAX);
@@ -1040,36 +1037,17 @@ static inline void _ocf_init_collision_entry(struct ocf_cache *cache,
}
/*
* Modified initialization of freelist partition
* Initialize collision table
*/
static void ocf_metadata_hash_init_freelist(struct ocf_cache *cache)
static void ocf_metadata_hash_init_collision(struct ocf_cache *cache)
{
uint32_t step = 0;
unsigned int i;
ocf_cache_line_t prev, next;
ocf_cache_line_t idx;
ocf_cache_line_t collision_table_entries =
cache->device->collision_table_entries;
prev = collision_table_entries;
idx = 0;
for (i = 0; i < cache->device->collision_table_entries - 1; i++) {
next = ocf_metadata_map_phy2lg(cache, i + 1);
_ocf_init_collision_entry(cache, idx, next, prev);
prev = idx;
idx = next;
OCF_COND_RESCHED_DEFAULT(step);
for (i = 0; i < cache->device->collision_table_entries; i++) {
_ocf_init_collision_entry(cache, i);
}
_ocf_init_collision_entry(cache, idx, collision_table_entries, prev);
/* Initialize freelist partition */
cache->device->freelist_part->head = 0;
cache->device->freelist_part->tail = idx;
cache->device->freelist_part->curr_size = cache->device->
collision_table_entries;
}
/*
* Initialize hash table
*/
@@ -1850,8 +1828,6 @@ static void _recovery_rebuild_cline_metadata(ocf_cache_t cache,
part_id = PARTITION_DEFAULT;
ocf_metadata_remove_from_free_list(cache, cache_line);
ocf_metadata_add_to_partition(cache, part_id, cache_line);
hash_index = ocf_metadata_hash_func(cache, core_line, core_id);
@@ -1917,10 +1893,12 @@ static void _recovery_rebuild_metadata(ocf_pipeline_t pipeline,
ocf_core_id_t core_id;
uint64_t core_line;
unsigned char step = 0;
const uint64_t collision_table_entries =
ocf_metadata_collision_table_entries(cache);
OCF_METADATA_LOCK_WR();
for (cline = 0; cline < cache->device->collision_table_entries; cline++) {
for (cline = 0; cline < collision_table_entries; cline++) {
ocf_metadata_get_core_info(cache, cline, &core_id, &core_line);
if (core_id != OCF_CORE_MAX &&
(!dirty_only || metadata_test_dirty(cache,
@@ -2648,7 +2626,7 @@ static const struct ocf_metadata_iface metadata_hash_iface = {
.init_variable_size = ocf_metadata_hash_init_variable_size,
.deinit_variable_size = ocf_metadata_hash_deinit_variable_size,
.init_hash_table = ocf_metadata_hash_init_hash_table,
.init_freelist = ocf_metadata_hash_init_freelist,
.init_collision = ocf_metadata_hash_init_collision,
.layout_iface = NULL,
.pages = ocf_metadata_hash_pages,

View File

@@ -5,6 +5,7 @@
#include "ocf/ocf.h"
#include "metadata.h"
#include "../ocf_freelist.h"
#include "../utils/utils_cache_line.h"
static bool _is_cache_line_acting(struct ocf_cache *cache,
@@ -100,7 +101,7 @@ void ocf_metadata_sparse_cache_line(struct ocf_cache *cache,
ocf_metadata_remove_from_partition(cache, partition_id, cache_line);
ocf_metadata_add_to_free_list(cache, cache_line);
ocf_freelist_put_cache_line(cache->freelist, cache_line);
}
static void _ocf_metadata_sparse_cache_line(struct ocf_cache *cache,

View File

@@ -16,99 +16,6 @@ static void update_partition_head(struct ocf_cache *cache,
part->runtime->head = line;
}
void ocf_metadata_remove_from_free_list(struct ocf_cache *cache,
ocf_cache_line_t cline)
{
struct ocf_part *free_list = cache->device->freelist_part;
int is_head, is_tail;
ocf_part_id_t invalid_part_id = PARTITION_INVALID;
ocf_cache_line_t prev, next;
ocf_cache_line_t line_entries = cache->device->collision_table_entries;
ENV_BUG_ON(cline >= line_entries);
/* Get Partition info */
ocf_metadata_get_partition_info(cache, cline, NULL, &next, &prev);
/* Find out if this node is Partition _head_ */
is_head = (prev == line_entries);
is_tail = (next == line_entries);
/* Case 1: If we are head and there is only one node. So unlink node
* and set that there is no node left in the list.
*/
if (is_head && (free_list->curr_size == 1)) {
ocf_metadata_set_partition_info(cache, cline, invalid_part_id,
line_entries, line_entries);
free_list->head = line_entries;
free_list->tail = line_entries;
} else if (is_head) {
/* Case 2: else if this collision_index is partition list head,
* but many nodes, update head and return
*/
ENV_BUG_ON(next >= line_entries);
free_list->head = next;
ocf_metadata_set_partition_prev(cache, next, line_entries);
ocf_metadata_set_partition_next(cache, cline, line_entries);
} else if (is_tail) {
/* Case 3: else if this cline is partition list tail */
ENV_BUG_ON(prev >= line_entries);
free_list->tail = prev;
ocf_metadata_set_partition_prev(cache, cline, line_entries);
ocf_metadata_set_partition_next(cache, prev, line_entries);
} else {
/* Case 4: else this collision_index is a middle node.
* There is no change to the head and the tail pointers.
*/
ENV_BUG_ON(next >= line_entries || prev >= line_entries);
/* Update prev and next nodes */
ocf_metadata_set_partition_prev(cache, next, prev);
ocf_metadata_set_partition_next(cache, prev, next);
/* Update the given node */
ocf_metadata_set_partition_info(cache, cline, invalid_part_id,
line_entries, line_entries);
}
free_list->curr_size--;
}
void ocf_metadata_add_to_free_list(struct ocf_cache *cache,
ocf_cache_line_t line)
{
struct ocf_part *free_list = cache->device->freelist_part;
ocf_cache_line_t tail;
ocf_cache_line_t line_entries = cache->device->collision_table_entries;
ocf_part_id_t invalid_part_id = PARTITION_INVALID;
ENV_BUG_ON(line >= line_entries);
if (free_list->curr_size == 0) {
free_list->head = line;
free_list->tail = line;
ocf_metadata_set_partition_info(cache, line, invalid_part_id,
line_entries, line_entries);
} else {
tail = free_list->tail;
ENV_BUG_ON(tail >= line_entries);
ocf_metadata_set_partition_info(cache, line, invalid_part_id,
line_entries, tail);
ocf_metadata_set_partition_next(cache, tail, line);
free_list->tail = line;
}
free_list->curr_size++;
}
/* Adds the given collision_index to the _head_ of the Partition list */
void ocf_metadata_add_to_partition(struct ocf_cache *cache,
ocf_part_id_t part_id, ocf_cache_line_t line)

View File

@@ -75,12 +75,6 @@ static inline void ocf_metadata_set_partition_info(
next_line, prev_line);
}
void ocf_metadata_add_to_free_list(struct ocf_cache *cache,
ocf_cache_line_t cline);
void ocf_metadata_remove_from_free_list(struct ocf_cache *cache,
ocf_cache_line_t cline);
void ocf_metadata_add_to_partition(struct ocf_cache *cache,
ocf_part_id_t part_id, ocf_cache_line_t line);

View File

@@ -10,12 +10,6 @@
#include "../cleaning/cleaning.h"
#include "../eviction/eviction.h"
struct ocf_part {
ocf_cache_line_t head;
ocf_cache_line_t tail;
uint32_t curr_size;
};
struct ocf_user_part_config {
char name[OCF_IO_CLASS_NAME_MAX];
uint32_t min_size;

View File

@@ -124,13 +124,6 @@ struct ocf_metadata_iface {
struct ocf_volume_uuid *uuid, uint32_t count,
ocf_metadata_query_cores_end_t cmpl, void *priv);
/**
* @brief Initialize freelist partition
*
* @param cache - Cache instance
*/
void (*init_freelist)(struct ocf_cache *cache);
/**
* @brief Metadata cache line location on pages interface
@@ -144,6 +137,13 @@ struct ocf_metadata_iface {
*/
void (*init_hash_table)(struct ocf_cache *cache);
/**
* @brief Initialize collision table
*
* @param cache - Cache instance
*/
void (*init_collision)(struct ocf_cache *cache);
/**
* @brief De-Initialize metadata
*

View File

@@ -59,8 +59,6 @@ struct ocf_superblock_config {
* @brief OCF cache metadata runtime superblock
*/
struct ocf_superblock_runtime {
struct ocf_part freelist_part;
uint32_t cleaning_thread_access;
};