Merge pull request #704 from robertbaldyga/disable-cleaner

Add disable_cleaner option
This commit is contained in:
Robert Baldyga 2022-05-10 14:07:19 +02:00 committed by GitHub
commit 703f5b7e23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 241 additions and 5 deletions

View File

@ -0,0 +1,67 @@
---
group: disable_cleaner
---
Disabling cleaner is a feature that is intented to be used with read cache
(Write-Thourgh and Write-Around modes), where no dirty data is produced, so
the cleaning is not necessary. Its major benefit is metadata memory footprint
reduction, which is result of not allocating "cleaning" metatada section,
that constitutes about 20% of total metadata capacity.
While it is possible to use disable_cleaner option Write-Back and Write-Only
modes, it may result in performance degradation due to necessity to perform
cleaning on eviction.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
title: Setting cleaner_disabled mode
id: set_cleaner_disabled
---
It shall be possible to select cleaner_disabled mode during cache attach
operation by setting apropirate field in attach config.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
title: Loading cache cleaner_disabled mode
id: load_cleaner_disabled
---
The cleaner_disabled setting should be preserved in cache metadata, i.e. on the
cache load/recovery the setting should be restored to the value it had before
the cache stop.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
title: Metadata "cleaning" section allocation
id: cleaning_section_alocation
---
When disable_cleaner option is selected the "cleaning" section in OCF metadata
shall not be allocated neither in DRAM nor on the cache drive.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
title: Starting with NOP cleaning policy
id: starting_with_nop_policy
---
When attaching/loading cache with disable_cleaner option selected, the cleaning
policy shall always be NOP.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
title: NOP cleaning policy enforcement
id: nop_enforcement
---
When disable_cleaner option is selected it shall not be possible to change the
cleaning policy to other than NOP.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
title: Default setting
id: default_setting
---
By default the disable_cleaner option shall not be selected.

View File

@ -155,7 +155,10 @@ typedef enum {
/** Operation only allowed in standby mode **/ /** Operation only allowed in standby mode **/
OCF_ERR_CACHE_NOT_STANDBY, OCF_ERR_CACHE_NOT_STANDBY,
OCF_ERR_MAX = OCF_ERR_CACHE_NOT_STANDBY, /** Operation not allowed when cleaner is disabled **/
OCF_ERR_CLEANER_DISABLED,
OCF_ERR_MAX = OCF_ERR_CLEANER_DISABLED,
} ocf_error_t; } ocf_error_t;

View File

@ -424,6 +424,21 @@ struct ocf_mngt_cache_attach_config {
* @brief If set, cache device will be discarded on cache start * @brief If set, cache device will be discarded on cache start
*/ */
bool discard_on_start; bool discard_on_start;
/**
* @brief If set, asynchronous cleaning will be disabled
*
* Has similar effect to setting cleaning policy to NOP, but
* additionally prevents allocating "cleaning" metadata section,
* which can reduce memory footprint by up to 20%.
*
* When this option is selected, any attempt to change the cleaning
* policy will fail.
*
* @note This option is meaningful only with ocf_mngt_cache_attach().
* When used with ocf_mngt_cache_load() it's ignored.
*/
bool disable_cleaner;
}; };
/** /**
@ -441,6 +456,7 @@ static inline void ocf_mngt_cache_attach_config_set_default(
cfg->open_cores = true; cfg->open_cores = true;
cfg->force = false; cfg->force = false;
cfg->discard_on_start = true; cfg->discard_on_start = true;
cfg->disable_cleaner = false;
cfg->device.perform_test = true; cfg->device.perform_test = true;
cfg->device.volume_params = NULL; cfg->device.volume_params = NULL;
} }

View File

@ -638,7 +638,8 @@ static void ocf_metadata_flush_unlock_collision_page(
* Initialize hash metadata interface * Initialize hash metadata interface
*/ */
int ocf_metadata_init_variable_size(struct ocf_cache *cache, int ocf_metadata_init_variable_size(struct ocf_cache *cache,
uint64_t device_size, ocf_cache_line_size_t line_size) uint64_t device_size, ocf_cache_line_size_t line_size,
bool cleaner_disabled)
{ {
int result = 0; int result = 0;
uint32_t i = 0; uint32_t i = 0;
@ -688,6 +689,12 @@ int ocf_metadata_init_variable_size(struct ocf_cache *cache,
raw->raw_type = metadata_raw_type_atomic; raw->raw_type = metadata_raw_type_atomic;
} }
if (i == metadata_segment_cleaning && cleaner_disabled) {
raw->entry_size = 0;
raw->entries_in_page = 1;
continue;
}
/* Entry size configuration */ /* Entry size configuration */
raw->entry_size raw->entry_size
= ocf_metadata_get_element_size(i, line_size); = ocf_metadata_get_element_size(i, line_size);
@ -715,6 +722,9 @@ int ocf_metadata_init_variable_size(struct ocf_cache *cache,
*/ */
for (i = metadata_segment_variable_size_start; for (i = metadata_segment_variable_size_start;
i < metadata_segment_max; i++) { i < metadata_segment_max; i++) {
if (i == metadata_segment_cleaning && cleaner_disabled)
continue;
if (i == metadata_segment_collision) { if (i == metadata_segment_collision) {
lock_page = lock_page =
ocf_metadata_flush_lock_collision_page; ocf_metadata_flush_lock_collision_page;
@ -779,6 +789,7 @@ finalize:
cache->conf_meta->cachelines = ctrl->cachelines; cache->conf_meta->cachelines = ctrl->cachelines;
cache->conf_meta->line_size = line_size; cache->conf_meta->line_size = line_size;
cache->conf_meta->cleaner_disabled = cleaner_disabled;
ocf_metadata_raw_info(cache, ctrl); ocf_metadata_raw_info(cache, ctrl);
@ -1620,6 +1631,7 @@ static void ocf_metadata_load_properties_cmpl(
properties.shutdown_status = superblock->clean_shutdown; properties.shutdown_status = superblock->clean_shutdown;
properties.dirty_flushed = superblock->dirty_flushed; properties.dirty_flushed = superblock->dirty_flushed;
properties.cache_name = superblock->name; properties.cache_name = superblock->name;
properties.cleaner_disabled = superblock->cleaner_disabled;
OCF_CMPL_RET(priv, 0, &properties); OCF_CMPL_RET(priv, 0, &properties);
} }

View File

@ -41,10 +41,12 @@ int ocf_metadata_init(struct ocf_cache *cache,
* @param cache - Cache instance * @param cache - Cache instance
* @param device_size - Device size in bytes * @param device_size - Device size in bytes
* @param cache_line_size Cache line size * @param cache_line_size Cache line size
* @param cleaner_disabled Cleaner is disabled
* @return 0 - Operation success otherwise failure * @return 0 - Operation success otherwise failure
*/ */
int ocf_metadata_init_variable_size(struct ocf_cache *cache, int ocf_metadata_init_variable_size(struct ocf_cache *cache,
uint64_t device_size, ocf_cache_line_size_t cache_line_size); uint64_t device_size, ocf_cache_line_size_t line_size,
bool cleaner_disabled);
/** /**
* @brief Initialize collision table * @brief Initialize collision table
@ -201,6 +203,7 @@ struct ocf_metadata_load_properties {
ocf_cache_mode_t cache_mode; ocf_cache_mode_t cache_mode;
ocf_cache_line_size_t line_size; ocf_cache_line_size_t line_size;
char *cache_name; char *cache_name;
bool cleaner_disabled;
}; };
typedef void (*ocf_metadata_load_properties_end_t)(void *priv, int error, typedef void (*ocf_metadata_load_properties_end_t)(void *priv, int error,

View File

@ -18,6 +18,8 @@ ocf_metadata_get_cleaning_policy(struct ocf_cache *cache,
struct ocf_metadata_ctrl *ctrl struct ocf_metadata_ctrl *ctrl
= (struct ocf_metadata_ctrl *) cache->metadata.priv; = (struct ocf_metadata_ctrl *) cache->metadata.priv;
ENV_BUG_ON(cache->conf_meta->cleaner_disabled);
return ocf_metadata_raw_wr_access(cache, return ocf_metadata_raw_wr_access(cache,
&(ctrl->raw_desc[metadata_segment_cleaning]), line); &(ctrl->raw_desc[metadata_segment_cleaning]), line);
} }

View File

@ -110,8 +110,11 @@ static void ocf_metadata_store_segment(ocf_pipeline_t pipeline,
int ocf_metadata_validate_superblock(ocf_ctx_t ctx, int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
struct ocf_superblock_config *superblock) struct ocf_superblock_config *superblock)
{ {
const char *segment_name;
uint32_t crc; uint32_t crc;
segment_name = ocf_metadata_segment_names[metadata_segment_sb_config];
if (superblock->magic_number != CACHE_MAGIC_NUMBER) { if (superblock->magic_number != CACHE_MAGIC_NUMBER) {
ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n"); ocf_log(ctx, log_info, "Cannot detect pre-existing metadata\n");
return -OCF_ERR_NO_METADATA; return -OCF_ERR_NO_METADATA;
@ -178,6 +181,14 @@ int ocf_metadata_validate_superblock(ocf_ctx_t ctx,
return -OCF_ERR_INVAL; return -OCF_ERR_INVAL;
} }
if (superblock->cleaner_disabled &&
superblock->cleaning_policy_type != ocf_cleaning_nop) {
ocf_log(ctx, log_err, "Loading %s: cleaner is disabled, but "
"cleaning policy is not set to nop!\n",
segment_name);
return -OCF_ERR_INVAL;
}
if (superblock->promotion_policy_type < 0 || if (superblock->promotion_policy_type < 0 ||
superblock->promotion_policy_type >= superblock->promotion_policy_type >=
ocf_promotion_max) { ocf_promotion_max) {

View File

@ -45,6 +45,7 @@ struct ocf_superblock_config {
unsigned long valid_core_bitmap[(OCF_CORE_MAX / unsigned long valid_core_bitmap[(OCF_CORE_MAX /
(sizeof(unsigned long) * 8)) + 1]; (sizeof(unsigned long) * 8)) + 1];
bool cleaner_disabled;
ocf_cleaning_t cleaning_policy_type; ocf_cleaning_t cleaning_policy_type;
struct cleaning_policy_config cleaning[CLEANING_POLICY_TYPE_MAX]; struct cleaning_policy_config cleaning[CLEANING_POLICY_TYPE_MAX];

View File

@ -162,6 +162,9 @@ struct ocf_cache_attach_context {
uint8_t dirty_flushed; uint8_t dirty_flushed;
/*!< is dirty data fully flushed */ /*!< is dirty data fully flushed */
bool cleaner_disabled;
/*!< is cleaner disabled */
} metadata; } metadata;
struct { struct {
@ -1117,6 +1120,7 @@ static void _ocf_mngt_load_read_properties_end(void *priv, int error,
context->metadata.shutdown_status = properties->shutdown_status; context->metadata.shutdown_status = properties->shutdown_status;
context->metadata.dirty_flushed = properties->dirty_flushed; context->metadata.dirty_flushed = properties->dirty_flushed;
context->metadata.line_size = properties->line_size; context->metadata.line_size = properties->line_size;
context->metadata.cleaner_disabled = properties->cleaner_disabled;
cache->conf_meta->cache_mode = properties->cache_mode; cache->conf_meta->cache_mode = properties->cache_mode;
ocf_pipeline_next(context->pipeline); ocf_pipeline_next(context->pipeline);
@ -1134,6 +1138,7 @@ static void _ocf_mngt_init_properties(ocf_pipeline_t pipeline,
context->metadata.dirty_flushed = DIRTY_FLUSHED; context->metadata.dirty_flushed = DIRTY_FLUSHED;
context->metadata.line_size = context->cfg.cache_line_size ?: context->metadata.line_size = context->cfg.cache_line_size ?:
cache->metadata.line_size; cache->metadata.line_size;
context->metadata.cleaner_disabled = context->cfg.disable_cleaner;
ocf_pipeline_next(pipeline); ocf_pipeline_next(pipeline);
} }
@ -1172,7 +1177,8 @@ static void _ocf_mngt_attach_prepare_metadata(ocf_pipeline_t pipeline,
* Initialize variable size metadata segments * Initialize variable size metadata segments
*/ */
ret = ocf_metadata_init_variable_size(cache, context->volume_size, ret = ocf_metadata_init_variable_size(cache, context->volume_size,
context->metadata.line_size); context->metadata.line_size,
context->metadata.cleaner_disabled);
if (ret) if (ret)
OCF_PL_FINISH_RET(pipeline, ret); OCF_PL_FINISH_RET(pipeline, ret);
@ -1227,6 +1233,9 @@ static void _ocf_mngt_attach_init_services(ocf_pipeline_t pipeline,
ocf_cache_t cache = context->cache; ocf_cache_t cache = context->cache;
ocf_error_t result; ocf_error_t result;
if (context->metadata.cleaner_disabled)
__set_cleaning_policy(cache, ocf_cleaning_nop);
result = __init_cleaning_policy(cache); result = __init_cleaning_policy(cache);
if (result) { if (result) {
ocf_cache_log(cache, log_err, ocf_cache_log(cache, log_err,
@ -2186,6 +2195,7 @@ static void _ocf_mngt_standby_init_properties(ocf_pipeline_t pipeline,
context->metadata.dirty_flushed = DIRTY_FLUSHED; context->metadata.dirty_flushed = DIRTY_FLUSHED;
context->metadata.line_size = context->cfg.cache_line_size ?: context->metadata.line_size = context->cfg.cache_line_size ?:
cache->metadata.line_size; cache->metadata.line_size;
context->metadata.cleaner_disabled = context->cfg.disable_cleaner;
ocf_pipeline_next(pipeline); ocf_pipeline_next(pipeline);
} }

View File

@ -1043,6 +1043,9 @@ void ocf_mngt_cache_cleaning_set_policy(ocf_cache_t cache,
OCF_CMPL_RET(priv, 0); OCF_CMPL_RET(priv, 0);
} }
if (cache->conf_meta->cleaner_disabled)
OCF_CMPL_RET(priv, -OCF_ERR_CLEANER_DISABLED);
ret = ocf_pipeline_create(&pipeline, cache, ret = ocf_pipeline_create(&pipeline, cache,
&_ocf_mngt_cache_set_cleaning_policy); &_ocf_mngt_cache_set_cleaning_policy);
if (ret) if (ret)

View File

@ -76,7 +76,7 @@ class CacheAttachConfig(Structure):
("_open_cores", c_bool), ("_open_cores", c_bool),
("_force", c_bool), ("_force", c_bool),
("_discard_on_start", c_bool), ("_discard_on_start", c_bool),
("_volume_params", c_void_p), ("_disable_cleaner", c_bool)
] ]

View File

@ -0,0 +1,108 @@
#
# Copyright(c) 2022 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#
import pytest
@pytest.mark.skip(reason="not implemented")
def test_attach_cleaner_disabled(pyocf_ctx):
"""
title: Attach cache with cleaner_disabled option set.
description: |
Check that cache can be attached when cleaner_disabled option is
selected and that "cleaning" metadata section is not allocated.
pass_criteria:
- Cache attaches properly.
- The "cleaning" metadata section is not allocated.
- Cache stops properly.
steps:
- Start the cache with default config.
- Prepare default attach config and set cleaner_disabled field to true.
- Attach cache device using prepared config.
- Verify that cache was attached properly.
- Verify that "cleaning" metadata section was not allocated.
- Stop the cache.
- Verify that the cache stopped properly.
requirements:
- disable_cleaner::set_cleaner_disabled
- disable_cleaner::cleaning_section_alocation
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_load_cleaner_disabled(pyocf_ctx):
"""
title: Load cache in cleaner_disabled mode.
description: |
Check that loading the cache that was previously attached with
cleaner_disabled option preserves cleaner_disabled setting.
pass_criteria:
- Cache loads properly.
- The "cleaning" metadata section is not allocated.
- Cache stops properly.
steps:
- Start the cache with default config.
- Prepare default attach config and set cleaner_disabled field to true.
- Attach cache device using prepared config.
- Stop the cache.
- Load the cache.
- Verify that cache was loaded properly.
- Verify that "cleaning" metadata section was not allocated.
- Stop the cache.
- Verify that the cache stopped properly.
requirements:
- disable_cleaner::load_cleaner_disabled
- disable_cleaner::cleaning_section_alocation
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_cleaner_disabled_nop(pyocf_ctx):
"""
title: NOP enfocement in cleaner_disabled mode..
description: |
Check that after attaching cache with cleaner_diabled option set, the
cleaning policy is by default set to NOP and that it is not possible
to change it.
pass_criteria:
- Cleaning policy is set to NOP after cache attach.
- It is not possible to change cleaning policy to other than NOP.
steps:
- Start the cache with default config.
- Prepare default attach config and set cleaner_disabled field to true.
- Attach cache device using prepared config.
- Verify that cleaning policy is NOP.
- Try to set cleaning policy to [ALRU, ACP] and verify that operation failed.
- Try to set cleaning policy to NOP and verify that operation succeeded.
- Stop the cache.
requirements:
- disable_cleaner::starting_with_nop_policy
- disable_cleaner::nop_enforcement
"""
pass
@pytest.mark.skip(reason="not implemented")
def test_attach_cleaner_disabled_non_default(pyocf_ctx):
"""
title: Attach cache with default config does not set clener_disabled.
description: |
Check that when attaching cache with default attach config the
cleaner_disabled option is not selected.
pass_criteria:
- Cache attaches properly.
- The "cleaning" metadata section is not allocated.
- Cache stops properly.
steps:
- Start the cache with default config.
- Attach cache device using default config.
- Verify that "cleaning" metadata section was allocated.
- Stop the cache.
requirements:
- disable_cleaner::default_setting
"""
pass