Skip to content
52 changes: 52 additions & 0 deletions src/metadata/layout/cleaning_policy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright(c) 2026 Unvertical
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "cleaning_policy.h"

void ocf_alru_cleaning_policy_config_validate(
const struct alru_cleaning_policy_config *config,
struct alru_cleaning_policy_config_validity *valid)
{
env_memset(valid, sizeof(*valid), 0);

valid->thread_wakeup_time =
config->thread_wakeup_time >= OCF_ALRU_MIN_WAKE_UP &&
config->thread_wakeup_time <= OCF_ALRU_MAX_WAKE_UP;

valid->stale_buffer_time =
config->stale_buffer_time >= OCF_ALRU_MIN_STALENESS_TIME &&
config->stale_buffer_time <= OCF_ALRU_MAX_STALENESS_TIME;

valid->flush_max_buffers =
config->flush_max_buffers >= OCF_ALRU_MIN_FLUSH_MAX_BUFFERS &&
config->flush_max_buffers <= OCF_ALRU_MAX_FLUSH_MAX_BUFFERS;

valid->activity_threshold =
config->activity_threshold >=
OCF_ALRU_MIN_ACTIVITY_THRESHOLD &&
config->activity_threshold <=
OCF_ALRU_MAX_ACTIVITY_THRESHOLD;

valid->dirty_ratio_threshold =
config->dirty_ratio_threshold >=
OCF_ALRU_MIN_DIRTY_RATIO_THRESHOLD &&
config->dirty_ratio_threshold <=
OCF_ALRU_MAX_DIRTY_RATIO_THRESHOLD;
}

void ocf_acp_cleaning_policy_config_validate(
const struct acp_cleaning_policy_config *config,
struct acp_cleaning_policy_config_validity *valid)
{
env_memset(valid, sizeof(*valid), 0);

valid->thread_wakeup_time =
config->thread_wakeup_time >= OCF_ACP_MIN_WAKE_UP &&
config->thread_wakeup_time <= OCF_ACP_MAX_WAKE_UP;

valid->flush_max_buffers =
config->flush_max_buffers >= OCF_ACP_MIN_FLUSH_MAX_BUFFERS &&
config->flush_max_buffers <= OCF_ACP_MAX_FLUSH_MAX_BUFFERS;
}
121 changes: 121 additions & 0 deletions src/metadata/layout/cleaning_policy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright(c) 2012-2021 Intel Corporation
* Copyright(c) 2026 Unvertical
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef __METADATA_LAYOUT_CLEANING_POLICY_H__
#define __METADATA_LAYOUT_CLEANING_POLICY_H__

#include "ocf/ocf.h"

/* Cleaning policy configuration (stored in superblock) */

#define CLEANING_POLICY_CONFIG_BYTES 256
#define CLEANING_POLICY_TYPE_MAX 4

struct cleaning_policy_config {
uint8_t data[CLEANING_POLICY_CONFIG_BYTES];
} __attribute__((aligned(4)));

struct alru_cleaning_policy_config {
uint32_t thread_wakeup_time; /* in seconds */
uint32_t stale_buffer_time; /* in seconds */
uint32_t flush_max_buffers; /* in lines */
uint32_t activity_threshold; /* in milliseconds */
uint32_t dirty_ratio_threshold; /* percent */
uint32_t dirty_ratio_inertia; /* bytes */
};

struct acp_cleaning_policy_config {
uint32_t thread_wakeup_time; /* in milliseconds*/
uint32_t flush_max_buffers; /* in lines */
};

/**
* @brief Validity of ALRU cleaning policy config fields
*/
struct alru_cleaning_policy_config_validity {
bool thread_wakeup_time;
bool stale_buffer_time;
bool flush_max_buffers;
bool activity_threshold;
bool dirty_ratio_threshold;
};

/**
* @brief Validate ALRU cleaning policy config
*
* @param config - ALRU cleaning policy config
* @param valid - Validity of ALRU cleaning policy config fields
*/
void ocf_alru_cleaning_policy_config_validate(
const struct alru_cleaning_policy_config *config,
struct alru_cleaning_policy_config_validity *valid);

/**
* @brief Validity of ACP cleaning policy config fields
*/
struct acp_cleaning_policy_config_validity {
bool thread_wakeup_time;
bool flush_max_buffers;
};

/**
* @brief Validate ACP cleaning policy config
*
* @param config - ACP cleaning policy config
* @param valid - Validity of ACP cleaning policy config fields
*/
void ocf_acp_cleaning_policy_config_validate(
const struct acp_cleaning_policy_config *config,
struct acp_cleaning_policy_config_validity *valid);

/* Cleaning policy metadata per partition */

struct nop_cleaning_policy {
};

struct alru_cleaning_policy {
env_atomic size;
uint32_t lru_head;
uint32_t lru_tail;
};

struct acp_cleaning_policy {
};

struct cleaning_policy {
union {
struct nop_cleaning_policy nop;
struct alru_cleaning_policy alru;
struct acp_cleaning_policy acp;
} policy;
};

/* Cleaning policy metadata per cache line */

struct nop_cleaning_policy_meta {
} __attribute__((packed));

struct alru_cleaning_policy_meta {
/* Lru pointers 2*4=8 bytes */
uint32_t timestamp;
uint32_t lru_prev;
uint32_t lru_next;
} __attribute__((packed));

/* TODO: remove acp metadata */
struct acp_cleaning_policy_meta {
uint8_t dirty : 1;
};

struct cleaning_policy_meta {
union {
struct nop_cleaning_policy_meta nop;
struct alru_cleaning_policy_meta alru;
struct acp_cleaning_policy_meta acp;
} meta;
};

#endif /* __METADATA_LAYOUT_CLEANING_POLICY_H__ */
104 changes: 104 additions & 0 deletions src/metadata/layout/collision.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright(c) 2012-2022 Intel Corporation
* Copyright(c) 2022-2023 Huawei Technologies
* Copyright(c) 2026 Unvertical
* SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef __METADATA_LAYOUT_COLLISION_H__
#define __METADATA_LAYOUT_COLLISION_H__

#include "../../ocf_def_priv.h"

/**
* @brief Metadata map structure
*/

struct ocf_metadata_list_info {
union {
struct {
/* Previous cache line in collision list */
ocf_cache_line_t prev_col : OCF_CACHE_LINE_BITS;
ocf_cache_line_t unused : 3;
/* Next cache line in collision list*/
ocf_cache_line_t next_col : OCF_CACHE_LINE_BITS;
ocf_cache_line_t unused2 : 3;
} __attribute__((packed));
uint64_t entry;
};
};

/* Keep the struct ocf_metadata_list_info size of 8 bytes */
_Static_assert(sizeof(struct ocf_metadata_list_info) == sizeof(uint64_t),
"Size of struct ocf_metadata_list_info is not equal to 8 bytes");

struct ocf_hash_entry {
union {
struct {
uint32_t line : OCF_CACHE_LINE_BITS;
/* Hash lock bits */
uint32_t rd : 2;
uint32_t wr : 1;
};
uint32_t raw;
};
};

/**
* @brief Hash bucket of core line
*
* Hash function intentionally returns consecutive (modulo @hash_entries)
* values for consecutive @core_line. This way it is trivial to sort all
* core lines within a single request in ascending hash value order. This kind
* of sorting is required to assure that (future) hash bucket metadata locks are
* always acquired in fixed order, eliminating the risk of dead locks.
*
* @param hash_entries - Number of entries in hash segment
* @param core_line - Core line number
* @param core_id - Core id
*/
static inline ocf_cache_line_t ocf_metadata_collision_hash(
ocf_cache_line_t hash_entries, uint64_t core_line,
ocf_core_id_t core_id)
{
return (ocf_cache_line_t) ((core_line + (core_id * (hash_entries / 32)))
% hash_entries);
}

/**
* @brief Hash bucket following given one
*
* @param hash_entries - Number of entries in hash segment
* @param hash - Hash bucket
*/
static inline ocf_cache_line_t ocf_metadata_collision_hash_next(
ocf_cache_line_t hash_entries, ocf_cache_line_t hash)
{
hash++;
return likely(hash < hash_entries) ? hash : 0;
}

/**
* @brief Metadata map structure
*/

struct ocf_metadata_map {
uint64_t core_line : OCF_CORE_LINE_BITS;
/*!< Core line address on cache mapped by this structure */

uint64_t core_id : OCF_CORE_ID_BITS;
/*!< ID of core where is assigned this cache line*/

#ifdef OCF_BLOCK_SIZE_4K
uint64_t _valid : 1;
/*!< valid bit for 4K cache line */

uint64_t _dirty : 1;
/*!< dirty bit for 4K cache line */
#endif

uint8_t status[];
/*!< Entry status structure e.g. valid, dirty...*/
} __attribute__((packed));

#endif /* __METADATA_LAYOUT_COLLISION_H__ */
107 changes: 107 additions & 0 deletions src/metadata/layout/core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright(c) 2026 Unvertical
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "core.h"

void ocf_core_meta_config_validate(
const struct ocf_superblock_config *superblock,
ocf_core_id_t core_id,
const struct ocf_core_meta_config *core_config,
struct ocf_core_meta_config_validity *valid)
{
uint32_t seq_cutoff_threshold, seq_detect_promotion_count;
uint32_t seq_detect_promotion_threshold;
int seq_cutoff_policy;

if (!env_bit_test(core_id, superblock->valid_core_bitmap)) {
/* Core is not in use - there is nothing to check */
env_memset(valid, sizeof(*valid), true);
return;
}

env_memset(valid, sizeof(*valid), 0);

valid->name =
core_config->name[0] != '\0' &&
env_strnlen(core_config->name, sizeof(core_config->name)) <
OCF_CORE_NAME_SIZE;

valid->seq_no =
core_config->seq_no <= superblock->curr_core_seq_no;

seq_cutoff_threshold =
env_atomic_read(&core_config->seq_cutoff_threshold);
valid->seq_cutoff_threshold =
seq_cutoff_threshold >= OCF_SEQ_CUTOFF_MIN_THRESHOLD &&
seq_cutoff_threshold <= OCF_SEQ_CUTOFF_MAX_THRESHOLD;

seq_cutoff_policy =
env_atomic_read(&core_config->seq_cutoff_policy);
valid->seq_cutoff_policy =
seq_cutoff_policy >= 0 &&
seq_cutoff_policy < ocf_seq_cutoff_policy_max;

seq_detect_promotion_count =
env_atomic_read(&core_config->seq_detect_promotion_count);
valid->seq_detect_promotion_count =
seq_detect_promotion_count >=
OCF_SEQ_DETECT_MIN_PROMOTION_COUNT &&
seq_detect_promotion_count <=
OCF_SEQ_DETECT_MAX_PROMOTION_COUNT;

seq_detect_promotion_threshold =
env_atomic_read(&core_config->seq_detect_promotion_threshold);
valid->seq_detect_promotion_threshold =
seq_detect_promotion_threshold <=
OCF_SEQ_DETECT_MAX_PROMOTION_THRESHOLD;
}

void ocf_cores_validate(const struct ocf_superblock_config *superblock,
const struct ocf_core_meta_config *core_config,
struct ocf_cores_validity *valid)
{
ocf_core_id_t i, j;

env_memset(valid, sizeof(*valid), 0);

/*
* Sequence number is assigned only on atomic cache device, otherwise
* it is OCF_SEQ_NO_INVALID for all cores.
*/
for (i = 0; i < OCF_CORE_NUM; i++) {
if (!env_bit_test(i, superblock->valid_core_bitmap))
continue;

if (core_config[i].seq_no == OCF_SEQ_NO_INVALID)
continue;

for (j = i + 1; j < OCF_CORE_NUM; j++) {
if (!env_bit_test(j, superblock->valid_core_bitmap))
continue;

if (core_config[i].seq_no == core_config[j].seq_no)
return;
}
}

valid->seq_no = true;
}

void ocf_metadata_uuid_validate(
const struct ocf_superblock_config *superblock,
ocf_core_id_t core_id,
const struct ocf_metadata_uuid *uuid,
struct ocf_metadata_uuid_validity *valid)
{
if (!env_bit_test(core_id, superblock->valid_core_bitmap)) {
/* Core is not in use - there is nothing to check */
env_memset(valid, sizeof(*valid), true);
return;
}

env_memset(valid, sizeof(*valid), 0);

valid->size = uuid->size <= OCF_VOLUME_UUID_MAX_SIZE;
}
Loading
Loading