From 17aa424319909a302d76d78dfc7d36af649ec95a Mon Sep 17 00:00:00 2001 From: Robert Baldyga Date: Thu, 19 Aug 2021 12:31:35 +0200 Subject: [PATCH] Introduce cache bind operation Signed-off-by: Robert Baldyga --- casadm/cas_lib.c | 9 +- casadm/cas_main.c | 8 ++ modules/cas_cache/classifier.c | 3 +- modules/cas_cache/layer_cache_management.c | 144 +++++++++++++++------ modules/include/cas_ioctl_codes.h | 1 + ocf | 2 +- 6 files changed, 120 insertions(+), 47 deletions(-) diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 378ee5f..a501687 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -68,6 +68,7 @@ static const char *cache_states_name[ocf_cache_state_max + 1] = { [ocf_cache_state_stopping] = "Stopping", [ocf_cache_state_initializing] = "Initializing", [ocf_cache_state_incomplete] = "Incomplete", + [ocf_cache_state_passive] = "Passive", [ocf_cache_state_max] = "Unknown", }; @@ -2775,8 +2776,12 @@ int list_caches(unsigned int list_format, bool by_id_path) cache_mode_to_name(curr_cache->mode)); } else { tmp_status = get_cache_state_name(curr_cache->state); - snprintf(mode_string, sizeof(mode_string), "%s", - cache_mode_to_name(curr_cache->mode)); + if (curr_cache->state & (1 << ocf_cache_state_passive)) { + strncpy(mode_string, "-", sizeof(mode_string)); + } else { + snprintf(mode_string, sizeof(mode_string), "%s", + cache_mode_to_name(curr_cache->mode)); + } } fprintf(intermediate_file[1], TAG(TREE_BRANCH) diff --git a/casadm/cas_main.c b/casadm/cas_main.c index 0ae91c8..95e6209 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -198,6 +198,8 @@ int start_cache_command_handle_option(char *opt, const char **arg) command_args_values.cache_id = atoi(arg[0]); } else if (!strcmp(opt, "load")) { command_args_values.state = CACHE_INIT_LOAD; + } else if (!strcmp(opt, "bind")) { + command_args_values.state = CACHE_INIT_BIND; } else if (!strcmp(opt, "cache-device")) { if(validate_device_name(arg[0]) == FAILURE) return FAILURE; @@ -243,6 +245,7 @@ static cli_option start_options[] = { {'d', "cache-device", CACHE_DEVICE_DESC, 1, "DEVICE", CLI_OPTION_REQUIRED}, {'i', "cache-id", CACHE_ID_DESC_LONG, 1, "ID", 0}, {'l', "load", "Load cache metadata from caching device (DANGEROUS - see manual or Admin Guide for details)"}, + {'b', "bind", "Bind caching device (DANGEROUS - see manual or Admin Guide for details)"}, {'f', "force", "Force the creation of cache instance"}, {'c', "cache-mode", "Set cache mode from available: {"CAS_CLI_HELP_START_CACHE_MODES"} "CAS_CLI_HELP_START_CACHE_MODES_FULL"; without this parameter Write-Through will be set by default", 1, "NAME"}, {'x', "cache-line-size", "Set cache line size in kibibytes: {4,8,16,32,64}[KiB] (default: %d)", 1, "NUMBER", CLI_OPTION_DEFAULT_INT, 0, 0, ocf_cache_line_size_default / KiB}, @@ -293,6 +296,11 @@ int handle_start() return FAILURE; } + if (command_args_values.state == CACHE_INIT_BIND && command_args_values.force) { + cas_printf(LOG_ERR, "Use of 'bind' and 'force' simultaneously is forbidden.\n"); + return FAILURE; + } + cache_device = open(command_args_values.cache_device, O_RDONLY); if (cache_device < 0) { diff --git a/modules/cas_cache/classifier.c b/modules/cas_cache/classifier.c index 3ce7323..c82874a 100644 --- a/modules/cas_cache/classifier.c +++ b/modules/cas_cache/classifier.c @@ -1215,7 +1215,8 @@ ocf_part_id_t cas_cls_classify(ocf_cache_t cache, struct bio *bio) cas_cls_eval_t ret; cls = cas_get_classifier(cache); - ENV_BUG_ON(!cls); + if (!cls) + return 0; _cas_cls_get_bio_context(bio, &io); diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 83e5014..24003cb 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -576,7 +576,8 @@ static int exit_instance_finish(void *data) else result = ctx->error; - cas_cls_deinit(ctx->cache); + if (!ocf_cache_is_passive(ctx->cache)) + cas_cls_deinit(ctx->cache); vfree(cache_priv); @@ -1382,19 +1383,6 @@ error_affter_lock: return result; } -static int _cache_mngt_create_exported_object(ocf_core_t core, void *cntx) -{ - int result; - - result = kcas_core_create_exported_object(core); - if (result) - return result; - - result = kcas_core_activate_exported_object(core); - - return result; -} - static int _cache_mngt_remove_core_flush(ocf_cache_t cache, struct kcas_remove_core *cmd) { @@ -1726,7 +1714,20 @@ out_get: return result; } -static int _cache_mngt_destroy_exported_object(ocf_core_t core, void *cntx) +static int _cache_mngt_create_core_exp_obj(ocf_core_t core, void *cntx) +{ + int result; + + result = kcas_core_create_exported_object(core); + if (result) + return result; + + result = kcas_core_activate_exported_object(core); + + return result; +} + +static int _cache_mngt_destroy_core_exp_obj(ocf_core_t core, void *cntx) { if (kcas_core_destroy_exported_object(core)) { ocf_cache_t cache = ocf_core_get_cache(core); @@ -1739,21 +1740,46 @@ static int _cache_mngt_destroy_exported_object(ocf_core_t core, void *cntx) return 0; } -static int cache_mngt_initialize_core_objects(ocf_cache_t cache) +static int cache_mngt_initialize_core_exported_objects(ocf_cache_t cache) { int result; - result = ocf_core_visit(cache, _cache_mngt_create_exported_object, NULL, + result = ocf_core_visit(cache, _cache_mngt_create_core_exp_obj, NULL, true); if (result) { /* Need to cleanup */ - ocf_core_visit(cache, _cache_mngt_destroy_exported_object, NULL, + ocf_core_visit(cache, _cache_mngt_destroy_core_exp_obj, NULL, true); } return result; } +static void cache_mngt_destroy_cache_exp_obj(ocf_cache_t cache) +{ + if (kcas_cache_destroy_exported_object(cache)) { + printk(KERN_ERR "Cannot destroy %s exported object\n", + ocf_cache_get_name(cache)); + } +} + +static int cache_mngt_initialize_cache_exported_object(ocf_cache_t cache) +{ + int result; + + result = kcas_cache_create_exported_object(cache); + if (result) + return result; + + result = kcas_cache_activate_exported_object(cache); + if (result) { + cache_mngt_destroy_cache_exp_obj(cache); + return result; + } + + return 0; +} + int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, struct ocf_mngt_cache_device_config *device_cfg, struct kcas_start_cache *cmd) @@ -1812,6 +1838,7 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, case CACHE_INIT_LOAD: device_cfg->open_cores = true; case CACHE_INIT_NEW: + case CACHE_INIT_BIND: break; default: return -OCF_ERR_INVAL; @@ -2042,7 +2069,8 @@ out_bdev: return result; } -static int _cache_start_finalize(ocf_cache_t cache) +static int _cache_start_finalize(ocf_cache_t cache, + struct kcas_start_cache *cmd) { struct cache_priv *cache_priv = ocf_cache_get_priv(cache); struct _cache_mngt_attach_context *ctx = cache_priv->attach_context; @@ -2050,21 +2078,37 @@ static int _cache_start_finalize(ocf_cache_t cache) _cache_mngt_log_cache_device_path(cache, ctx->device_cfg); - result = cas_cls_init(cache); - if (result) { - ctx->ocf_start_error = result; - return result; - } - ctx->cls_inited = true; - - result = cache_mngt_initialize_core_objects(cache); - if (result) { - ctx->ocf_start_error = result; - return result; + if (cmd->init_cache != CACHE_INIT_BIND) { + result = cas_cls_init(cache); + if (result) { + ctx->ocf_start_error = result; + return result; + } + ctx->cls_inited = true; } - ocf_core_visit(cache, _cache_mngt_core_device_loaded_visitor, - NULL, false); + switch(cmd->init_cache) { + case CACHE_INIT_LOAD: + result = cache_mngt_initialize_core_exported_objects(cache); + if (result) { + ctx->ocf_start_error = result; + return result; + } + ocf_core_visit(cache, _cache_mngt_core_device_loaded_visitor, + NULL, false); + break; + case CACHE_INIT_BIND: + result = cache_mngt_initialize_cache_exported_object(cache); + if (result) { + ctx->ocf_start_error = result; + return result; + } + break; + case CACHE_INIT_NEW: + break; + default: + BUG(); + } init_instance_complete(ctx, cache); @@ -2079,12 +2123,11 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, ocf_cache_t cache; struct cache_priv *cache_priv; int result = 0, rollback_result = 0; - bool load = (cmd && cmd->init_cache == CACHE_INIT_LOAD); if (!try_module_get(THIS_MODULE)) return -KCAS_ERR_SYSTEM; - if (load) + if (cmd->init_cache == CACHE_INIT_LOAD) result = _cache_mngt_check_metadata(cfg, cmd->cache_path_name); if (result) { module_put(THIS_MODULE); @@ -2134,12 +2177,22 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, cache_priv = ocf_cache_get_priv(cache); cache_priv->attach_context = context; - if (load) { - ocf_mngt_cache_load(cache, device_cfg, - _cache_mngt_start_complete, context); - } else { + switch (cmd->init_cache) { + case CACHE_INIT_NEW: ocf_mngt_cache_attach(cache, device_cfg, _cache_mngt_start_complete, context); + break; + case CACHE_INIT_LOAD: + ocf_mngt_cache_load(cache, device_cfg, + _cache_mngt_start_complete, context); + break; + case CACHE_INIT_BIND: + ocf_mngt_cache_bind(cache, device_cfg, + _cache_mngt_start_complete, context); + break; + default: + result = -OCF_ERR_INVAL; + goto err; } result = wait_for_completion_interruptible(&context->async.cmpl); @@ -2150,7 +2203,7 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, if (result) goto err; - result = _cache_start_finalize(cache); + result = _cache_start_finalize(cache, cmd); if (result) goto err; @@ -2474,7 +2527,7 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush) * this time, so we need to flush cache again after disabling * exported object. The second flush should be much faster. */ - if (flush) + if (flush && ocf_cache_is_running(cache)) status = _cache_flush_with_lock(cache); if (status) goto put; @@ -2494,16 +2547,21 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush) status = kcas_cache_destroy_all_core_exported_objects(cache); if (status != 0) { printk(KERN_WARNING - "Failed to remove all cached devices\n"); + "Failed to remove all cached devices\n"); + goto stop_thread; + } + status = kcas_cache_destroy_exported_object(cache); + if (status != 0) { + printk(KERN_WARNING + "Failed to remove cache exported object\n"); goto stop_thread; } /* Flush cache again. This time we don't allow interruption. */ - if (flush) + if (flush && ocf_cache_is_running(cache)) flush_status = _cache_mngt_cache_flush_uninterruptible(cache); context->flush_status = flush_status; - if (flush && !flush_status) BUG_ON(ocf_mngt_cache_is_dirty(cache)); diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index ec30a75..d90acf2 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -36,6 +36,7 @@ #define CACHE_INIT_NEW 0 /**< initialize new metadata from fresh start */ #define CACHE_INIT_LOAD 1 /**< load existing metadata */ +#define CACHE_INIT_BIND 2 /**< bind existing metadata */ struct kcas_start_cache { /** diff --git a/ocf b/ocf index 865d29d..886c8d4 160000 --- a/ocf +++ b/ocf @@ -1 +1 @@ -Subproject commit 865d29d0cb93a71ce37a8410914c35005aa6ed54 +Subproject commit 886c8d4e31e160f36d5ca3d0698a79811c8c0eca