Merge pull request #863 from Deixx/detach-zero-superblock

Zero metadata superblock on detach
This commit is contained in:
Robert Baldyga 2025-02-06 11:22:55 +01:00 committed by GitHub
commit ba4b81a94c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 21 deletions

View File

@ -1,5 +1,6 @@
/*
* Copyright(c) 2012-2022 Intel Corporation
* Copyright(c) 2025 Huawei Technologies
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -21,9 +22,8 @@
* @brief Metadata shutdown status
*/
enum ocf_metadata_shutdown_status {
ocf_metadata_clean_shutdown = 1, /*!< OCF shutdown graceful*/
ocf_metadata_dirty_shutdown = 0, /*!< Dirty OCF shutdown*/
ocf_metadata_detached = 2, /*!< Cache device detached */
ocf_metadata_clean_shutdown = 1, /*!< OCF shutdown graceful*/
};
/**

View File

@ -1,6 +1,6 @@
/*
* Copyright(c) 2012-2022 Intel Corporation
* Copyright(c) 2023-2024 Huawei Technologies
* Copyright(c) 2023-2025 Huawei Technologies
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -1760,7 +1760,7 @@ static void _ocf_mngt_init_promotion(ocf_pipeline_t pipeline,
ocf_pipeline_next(pipeline);
}
static void _ocf_mngt_zero_superblock_complete(void *priv, int error)
static void _ocf_mngt_attach_zero_superblock_complete(void *priv, int error)
{
struct ocf_cache_attach_context *context = priv;
ocf_cache_t cache = context->cache;
@ -1774,14 +1774,14 @@ static void _ocf_mngt_zero_superblock_complete(void *priv, int error)
ocf_pipeline_next(context->pipeline);
}
static void _ocf_mngt_zero_superblock(ocf_pipeline_t pipeline,
static void _ocf_mngt_attach_zero_superblock(ocf_pipeline_t pipeline,
void *priv, ocf_pipeline_arg_t arg)
{
struct ocf_cache_attach_context *context = priv;
ocf_cache_t cache = context->cache;
ocf_metadata_zero_superblock(cache,
_ocf_mngt_zero_superblock_complete, context);
_ocf_mngt_attach_zero_superblock_complete, context);
}
static void _ocf_mngt_attach_flush_metadata_complete(void *priv, int error)
@ -2011,7 +2011,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_attach_pipeline_properties = {
OCF_PL_STEP(_ocf_mngt_attach_init_metadata),
OCF_PL_STEP(_ocf_mngt_attach_populate_free),
OCF_PL_STEP(_ocf_mngt_attach_init_services),
OCF_PL_STEP(_ocf_mngt_zero_superblock),
OCF_PL_STEP(_ocf_mngt_attach_zero_superblock),
OCF_PL_STEP(_ocf_mngt_attach_flush_metadata),
OCF_PL_STEP(_ocf_mngt_attach_discard),
OCF_PL_STEP(_ocf_mngt_attach_flush),
@ -2172,6 +2172,31 @@ static void ocf_mngt_cache_stop_unplug(ocf_pipeline_t pipeline,
ocf_mngt_cache_stop_unplug_complete, context);
}
static void _ocf_mngt_detach_zero_superblock_complete(void *priv, int error)
{
struct ocf_mngt_cache_unplug_context *context = priv;
ocf_cache_t cache = context->cache;
if (error) {
ocf_cache_log(cache, log_err,
"ERROR: Failed to clear the superblock on the detached device\n"
"The metadata on the device is in an invalid state"
" - manual superblock clearing is recommended.\n");
}
ocf_pipeline_next(context->pipeline);
}
static void _ocf_mngt_detach_zero_superblock(ocf_pipeline_t pipeline,
void *priv, ocf_pipeline_arg_t arg)
{
struct ocf_mngt_cache_unplug_context *context = priv;
ocf_cache_t cache = context->cache;
ocf_metadata_zero_superblock(cache,
_ocf_mngt_detach_zero_superblock_complete, context);
}
static void _ocf_mngt_cache_put_io_queues(ocf_cache_t cache)
{
ocf_queue_t queue, tmp_queue;
@ -2443,7 +2468,7 @@ struct ocf_pipeline_properties _ocf_mngt_cache_standby_attach_pipeline_propertie
OCF_PL_STEP(_ocf_mngt_attach_populate_free),
OCF_PL_STEP(_ocf_mngt_standby_prepare_mempool),
OCF_PL_STEP(_ocf_mngt_standby_init_pio_concurrency),
OCF_PL_STEP(_ocf_mngt_zero_superblock),
OCF_PL_STEP(_ocf_mngt_attach_zero_superblock),
OCF_PL_STEP(_ocf_mngt_attach_flush_metadata),
OCF_PL_STEP(_ocf_mngt_attach_discard),
OCF_PL_STEP(_ocf_mngt_attach_flush),
@ -3147,6 +3172,8 @@ static void _ocf_mngt_cache_unplug(ocf_cache_t cache, bool stop,
struct _ocf_mngt_cache_unplug_context *context,
_ocf_mngt_cache_unplug_end_t cmpl, void *priv)
{
struct ocf_mngt_cache_unplug_context *ctx = priv;
context->cmpl = cmpl;
context->priv = priv;
context->cache = cache;
@ -3157,14 +3184,13 @@ static void _ocf_mngt_cache_unplug(ocf_cache_t cache, bool stop,
__deinit_promotion_policy(cache);
if (!stop) {
/* Just set correct shutdown status */
ocf_metadata_set_shutdown_status(cache, ocf_metadata_detached,
_ocf_mngt_cache_unplug_complete, context);
} else {
/* Skip metadata update - will be zeroed later in the detach pipeline */
OCF_PL_NEXT_RET(ctx->pipeline);
}
/* Flush metadata */
ocf_metadata_flush_all(cache,
_ocf_mngt_cache_unplug_complete, context);
}
}
static int _ocf_mngt_cache_load_core_log(ocf_core_t core, void *cntx)
@ -3850,6 +3876,7 @@ struct ocf_pipeline_properties ocf_mngt_cache_detach_pipeline_properties = {
OCF_PL_STEP(ocf_mngt_cache_stop_check_dirty),
OCF_PL_STEP(ocf_mngt_cache_detach_update_metadata),
OCF_PL_STEP(ocf_mngt_cache_detach_unplug),
OCF_PL_STEP(_ocf_mngt_detach_zero_superblock),
OCF_PL_STEP(ocf_mngt_cache_close_cache_volume),
OCF_PL_STEP(ocf_mngt_cache_deinit_metadata),
OCF_PL_STEP(ocf_mngt_cache_deinit_cache_volume),

View File

@ -1,16 +1,13 @@
#
# Copyright(c) 2019-2022 Intel Corporation
# Copyright(c) 2024 Huawei Technologies
# Copyright(c) 2024-2025 Huawei Technologies
# SPDX-License-Identifier: BSD-3-Clause
#
import logging
from ctypes import c_int, c_void_p, byref, c_uint32, memmove, cast
from random import randrange
from itertools import count
from ctypes import c_void_p, memmove, cast
import pytest
from pyocf.types.cache import (
Cache,
CacheMode,
@ -70,12 +67,32 @@ def test_detach_cache_twice(pyocf_ctx):
cache.stop()
def test_detach_cache_zero_superblock(pyocf_ctx):
"""Check if superblock is zeroed after detach and the cache device can be reattached without
--force option.
"""
cache_device = RamVolume(Size.from_MiB(50))
cache = Cache.start_on_device(cache_device)
cache.detach_device()
data = cache_device.get_bytes()
page_size = 4096
assert data[:page_size] == b'\x00'*page_size
cache.attach_device(cache_device, force=False)
cache.detach_device()
cache.stop()
@pytest.mark.parametrize("cls", CacheLineSize)
@pytest.mark.parametrize("mode", [CacheMode.WB, CacheMode.WT, CacheMode.WO])
@pytest.mark.parametrize("new_cache_size", [80, 120])
def test_attach_different_size(pyocf_ctx, new_cache_size, mode: CacheMode, cls: CacheLineSize):
"""Start cache and add partition with limited occupancy. Fill partition with data,
attach cache with different size and trigger IO. Verify if occupancy thresold is
attach cache with different size and trigger IO. Verify if occupancy threshold is
respected with both original and new cache device.
"""
cache_device = RamVolume(Size.from_MiB(100))