From 05d77610fd2c878b834fe2bec7ca4dd3f6d02757 Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Mon, 2 Nov 2026 00:08:09 +0100 Subject: [PATCH] Introduce core refcount Prevent race conditions between core remove/detach path and handing of in-flight I/O to that core (especially prefetch path). Signed-off-by: Robert Baldyga --- src/mngt/ocf_mngt_cache.c | 9 +++++++++ src/mngt/ocf_mngt_common.c | 1 + src/mngt/ocf_mngt_core.c | 25 +++++++++++++++++++++++++ src/ocf_core_priv.h | 2 ++ src/ocf_request.c | 9 +++++++++ src/ocf_request.h | 3 +++ 6 files changed, 49 insertions(+) diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index 4f259075..7505e680 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -427,6 +427,8 @@ static void _ocf_mngt_deinit_added_cores( ocf_core_seq_cutoff_deinit(core); ocf_core_seq_detect_deinit(core); + if (core->counters) + env_refcnt_deinit(&core->refcnt); env_free(core->counters); core->counters = NULL; core->added = false; @@ -511,6 +513,13 @@ static void _ocf_mngt_load_add_cores(ocf_pipeline_t pipeline, if (!core->counters) goto err; + ret = env_refcnt_init(&core->refcnt, "core", sizeof("core")); + if (ret) { + env_free(core->counters); + core->counters = NULL; + goto err; + } + ret = ocf_core_seq_detect_init(core); if (ret < 0) goto err; diff --git a/src/mngt/ocf_mngt_common.c b/src/mngt/ocf_mngt_common.c index 2b2cfd01..0012eb1a 100644 --- a/src/mngt/ocf_mngt_common.c +++ b/src/mngt/ocf_mngt_common.c @@ -136,6 +136,7 @@ void cache_mngt_core_remove_from_cache(ocf_core_t core) ocf_prefetch_deinit(cache, core); ocf_core_seq_cutoff_deinit(core); ocf_core_seq_detect_deinit(core); + env_refcnt_deinit(&core->refcnt); env_free(core->counters); core->counters = NULL; core->added = false; diff --git a/src/mngt/ocf_mngt_core.c b/src/mngt/ocf_mngt_core.c index 6f4dc435..03de906a 100644 --- a/src/mngt/ocf_mngt_core.c +++ b/src/mngt/ocf_mngt_core.c @@ -151,6 +151,7 @@ static void _ocf_mngt_cache_add_core_handle_error( core->added = false; core->opened = false; + env_refcnt_deinit(&core->refcnt); env_free(core->counters); core->counters = NULL; } @@ -497,6 +498,13 @@ static void ocf_mngt_cache_add_core_insert(ocf_pipeline_t pipeline, if (!core->counters) OCF_PL_FINISH_RET(context->pipeline, -OCF_ERR_NO_MEM); + result = env_refcnt_init(&core->refcnt, "core", sizeof("core")); + if (result) { + env_free(core->counters); + core->counters = NULL; + OCF_PL_FINISH_RET(context->pipeline, result); + } + context->flags.counters_allocated = true; /* When adding new core to cache, reset all core/cache statistics */ @@ -665,6 +673,7 @@ struct ocf_mngt_cache_remove_core_context { ocf_core_t core; const char *core_name; struct ocf_cleaner_wait_context cleaner_wait; + bool core_frozen; }; static void ocf_mngt_cache_remove_core_finish(ocf_pipeline_t pipeline, @@ -681,6 +690,9 @@ static void ocf_mngt_cache_remove_core_finish(ocf_pipeline_t pipeline, context->core_name); } + if (context->core_frozen) + env_refcnt_unfreeze(&context->core->refcnt); + if (ocf_cache_is_device_attached(cache)) { ocf_cleaner_refcnt_unfreeze(cache); } @@ -741,6 +753,7 @@ static void _ocf_mngt_cache_remove_core(ocf_pipeline_t pipeline, void *priv, cache_mngt_core_remove_from_cleaning_pol(core); cache_mngt_core_remove_from_meta(core); + context->core_frozen = false; cache_mngt_core_remove_from_cache(core); cache_mngt_core_deinit(core); @@ -752,6 +765,17 @@ static void _ocf_mngt_cache_remove_core(ocf_pipeline_t pipeline, void *priv, context); } +static void ocf_mngt_cache_remove_core_wait_requests(ocf_pipeline_t pipeline, + void *priv, ocf_pipeline_arg_t arg) +{ + struct ocf_mngt_cache_remove_core_context *context = priv; + ocf_core_t core = context->core; + + env_refcnt_freeze(&core->refcnt); + context->core_frozen = true; + ocf_pipeline_continue_on_zero_refcnt(pipeline, &core->refcnt); +} + static void ocf_mngt_cache_remove_core_wait_cleaning_complete(void *priv) { ocf_pipeline_t pipeline = priv; @@ -778,6 +802,7 @@ struct ocf_pipeline_properties ocf_mngt_cache_remove_core_pipeline_props = { .finish = ocf_mngt_cache_remove_core_finish, .steps = { OCF_PL_STEP(ocf_mngt_cache_remove_core_wait_cleaning), + OCF_PL_STEP(ocf_mngt_cache_remove_core_wait_requests), OCF_PL_STEP(_ocf_mngt_cache_remove_core_mapping), OCF_PL_STEP(_ocf_mngt_cache_remove_core), OCF_PL_STEP_TERMINATOR(), diff --git a/src/ocf_core_priv.h b/src/ocf_core_priv.h index b91c61f7..5f800354 100644 --- a/src/ocf_core_priv.h +++ b/src/ocf_core_priv.h @@ -51,6 +51,8 @@ struct ocf_core { struct ocf_counters_core *counters; + struct env_refcnt refcnt; + void *priv; }; diff --git a/src/ocf_request.c b/src/ocf_request.c index 2be21d3c..0aa867fa 100644 --- a/src/ocf_request.c +++ b/src/ocf_request.c @@ -197,6 +197,9 @@ struct ocf_request *ocf_req_new(ocf_queue_t queue, ocf_core_t core, ENV_BUG_ON(ocf_queue_is_mngt(queue)); + if (!env_refcnt_inc(&core->refcnt)) + return NULL; + ocf_queue_get(queue); if (!env_refcnt_inc(&cache->refcnt.metadata)) { @@ -205,6 +208,7 @@ struct ocf_request *ocf_req_new(ocf_queue_t queue, ocf_core_t core, req = ocf_req_new_d2c(queue, core, addr, bytes, rw); if (unlikely(!req)) { ocf_queue_put(queue); + env_refcnt_dec(&core->refcnt); return NULL; } return req; @@ -229,6 +233,7 @@ struct ocf_request *ocf_req_new(ocf_queue_t queue, ocf_core_t core, if (unlikely(!req)) { env_refcnt_dec(&cache->refcnt.metadata); ocf_queue_put(queue); + env_refcnt_dec(&core->refcnt); return NULL; } @@ -304,6 +309,7 @@ struct ocf_request *ocf_req_new_cache(ocf_cache_t cache, ocf_queue_t queue, ocf_req_init(req, cache, queue, NULL, addr, bytes, rw); req->lock_idx = ocf_metadata_concurrency_next_idx(queue); + req->is_cache = true; return req; } @@ -398,6 +404,9 @@ void ocf_req_put(struct ocf_request *req) else if (!req->is_mngt || req->cleaner) env_refcnt_dec(&req->cache->refcnt.metadata); + if (!req->is_mngt && !req->cleaner && !req->is_cache) + env_refcnt_dec(&req->core->refcnt); + if (unlikely(req->is_mngt)) { env_free(req); } else { diff --git a/src/ocf_request.h b/src/ocf_request.h index 867378d7..37807676 100644 --- a/src/ocf_request.h +++ b/src/ocf_request.h @@ -303,6 +303,9 @@ struct ocf_request { uint8_t is_mngt : 1; /* !< It's a management path request */ + uint8_t is_cache : 1; + /* !< It's a cache volume request */ + ocf_req_cache_mode_t cache_mode; ocf_queue_t io_queue;