Merge pull request #863 from Deixx/detach-zero-superblock
Zero metadata superblock on detach
This commit is contained in:
commit
ba4b81a94c
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright(c) 2012-2022 Intel Corporation
|
* Copyright(c) 2012-2022 Intel Corporation
|
||||||
|
* Copyright(c) 2025 Huawei Technologies
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -21,9 +22,8 @@
|
|||||||
* @brief Metadata shutdown status
|
* @brief Metadata shutdown status
|
||||||
*/
|
*/
|
||||||
enum ocf_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_dirty_shutdown = 0, /*!< Dirty OCF shutdown*/
|
||||||
ocf_metadata_detached = 2, /*!< Cache device detached */
|
ocf_metadata_clean_shutdown = 1, /*!< OCF shutdown graceful*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright(c) 2012-2022 Intel Corporation
|
* Copyright(c) 2012-2022 Intel Corporation
|
||||||
* Copyright(c) 2023-2024 Huawei Technologies
|
* Copyright(c) 2023-2025 Huawei Technologies
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1760,7 +1760,7 @@ static void _ocf_mngt_init_promotion(ocf_pipeline_t pipeline,
|
|||||||
ocf_pipeline_next(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;
|
struct ocf_cache_attach_context *context = priv;
|
||||||
ocf_cache_t cache = context->cache;
|
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);
|
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)
|
void *priv, ocf_pipeline_arg_t arg)
|
||||||
{
|
{
|
||||||
struct ocf_cache_attach_context *context = priv;
|
struct ocf_cache_attach_context *context = priv;
|
||||||
ocf_cache_t cache = context->cache;
|
ocf_cache_t cache = context->cache;
|
||||||
|
|
||||||
ocf_metadata_zero_superblock(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)
|
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_init_metadata),
|
||||||
OCF_PL_STEP(_ocf_mngt_attach_populate_free),
|
OCF_PL_STEP(_ocf_mngt_attach_populate_free),
|
||||||
OCF_PL_STEP(_ocf_mngt_attach_init_services),
|
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_flush_metadata),
|
||||||
OCF_PL_STEP(_ocf_mngt_attach_discard),
|
OCF_PL_STEP(_ocf_mngt_attach_discard),
|
||||||
OCF_PL_STEP(_ocf_mngt_attach_flush),
|
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);
|
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)
|
static void _ocf_mngt_cache_put_io_queues(ocf_cache_t cache)
|
||||||
{
|
{
|
||||||
ocf_queue_t queue, tmp_queue;
|
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_attach_populate_free),
|
||||||
OCF_PL_STEP(_ocf_mngt_standby_prepare_mempool),
|
OCF_PL_STEP(_ocf_mngt_standby_prepare_mempool),
|
||||||
OCF_PL_STEP(_ocf_mngt_standby_init_pio_concurrency),
|
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_flush_metadata),
|
||||||
OCF_PL_STEP(_ocf_mngt_attach_discard),
|
OCF_PL_STEP(_ocf_mngt_attach_discard),
|
||||||
OCF_PL_STEP(_ocf_mngt_attach_flush),
|
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,
|
struct _ocf_mngt_cache_unplug_context *context,
|
||||||
_ocf_mngt_cache_unplug_end_t cmpl, void *priv)
|
_ocf_mngt_cache_unplug_end_t cmpl, void *priv)
|
||||||
{
|
{
|
||||||
|
struct ocf_mngt_cache_unplug_context *ctx = priv;
|
||||||
|
|
||||||
context->cmpl = cmpl;
|
context->cmpl = cmpl;
|
||||||
context->priv = priv;
|
context->priv = priv;
|
||||||
context->cache = cache;
|
context->cache = cache;
|
||||||
@ -3157,14 +3184,13 @@ static void _ocf_mngt_cache_unplug(ocf_cache_t cache, bool stop,
|
|||||||
__deinit_promotion_policy(cache);
|
__deinit_promotion_policy(cache);
|
||||||
|
|
||||||
if (!stop) {
|
if (!stop) {
|
||||||
/* Just set correct shutdown status */
|
/* Skip metadata update - will be zeroed later in the detach pipeline */
|
||||||
ocf_metadata_set_shutdown_status(cache, ocf_metadata_detached,
|
OCF_PL_NEXT_RET(ctx->pipeline);
|
||||||
_ocf_mngt_cache_unplug_complete, context);
|
|
||||||
} else {
|
|
||||||
/* Flush metadata */
|
|
||||||
ocf_metadata_flush_all(cache,
|
|
||||||
_ocf_mngt_cache_unplug_complete, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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)
|
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_stop_check_dirty),
|
||||||
OCF_PL_STEP(ocf_mngt_cache_detach_update_metadata),
|
OCF_PL_STEP(ocf_mngt_cache_detach_update_metadata),
|
||||||
OCF_PL_STEP(ocf_mngt_cache_detach_unplug),
|
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_close_cache_volume),
|
||||||
OCF_PL_STEP(ocf_mngt_cache_deinit_metadata),
|
OCF_PL_STEP(ocf_mngt_cache_deinit_metadata),
|
||||||
OCF_PL_STEP(ocf_mngt_cache_deinit_cache_volume),
|
OCF_PL_STEP(ocf_mngt_cache_deinit_cache_volume),
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
#
|
#
|
||||||
# Copyright(c) 2019-2022 Intel Corporation
|
# Copyright(c) 2019-2022 Intel Corporation
|
||||||
# Copyright(c) 2024 Huawei Technologies
|
# Copyright(c) 2024-2025 Huawei Technologies
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from ctypes import c_int, c_void_p, byref, c_uint32, memmove, cast
|
from ctypes import c_void_p, memmove, cast
|
||||||
from random import randrange
|
|
||||||
from itertools import count
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pyocf.types.cache import (
|
from pyocf.types.cache import (
|
||||||
Cache,
|
Cache,
|
||||||
CacheMode,
|
CacheMode,
|
||||||
@ -70,12 +67,32 @@ def test_detach_cache_twice(pyocf_ctx):
|
|||||||
cache.stop()
|
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("cls", CacheLineSize)
|
||||||
@pytest.mark.parametrize("mode", [CacheMode.WB, CacheMode.WT, CacheMode.WO])
|
@pytest.mark.parametrize("mode", [CacheMode.WB, CacheMode.WT, CacheMode.WO])
|
||||||
@pytest.mark.parametrize("new_cache_size", [80, 120])
|
@pytest.mark.parametrize("new_cache_size", [80, 120])
|
||||||
def test_attach_different_size(pyocf_ctx, new_cache_size, mode: CacheMode, cls: CacheLineSize):
|
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,
|
"""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.
|
respected with both original and new cache device.
|
||||||
"""
|
"""
|
||||||
cache_device = RamVolume(Size.from_MiB(100))
|
cache_device = RamVolume(Size.from_MiB(100))
|
||||||
|
Loading…
Reference in New Issue
Block a user