diff --git a/casadm/cas_main.c b/casadm/cas_main.c index 95e6209..a8084a1 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -200,6 +200,8 @@ int start_cache_command_handle_option(char *opt, const char **arg) command_args_values.state = CACHE_INIT_LOAD; } else if (!strcmp(opt, "bind")) { command_args_values.state = CACHE_INIT_BIND; + } else if (!strcmp(opt, "activate")) { + command_args_values.state = CACHE_INIT_ACTIVATE; } else if (!strcmp(opt, "cache-device")) { if(validate_device_name(arg[0]) == FAILURE) return FAILURE; @@ -246,6 +248,7 @@ static cli_option start_options[] = { {'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)"}, + {'a', "activate", "Activate caching device after bind"}, {'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}, diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 24003cb..cdc1790 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1785,12 +1785,8 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, struct kcas_start_cache *cmd) { int init_cache, result; - struct block_device *bdev; - int part_count; - char holder[] = "CAS START\n"; char cache_name[OCF_CACHE_NAME_SIZE]; uint16_t cache_id; - bool is_part; if (!cmd) return -OCF_ERR_INVAL; @@ -1836,6 +1832,7 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, switch (init_cache) { case CACHE_INIT_LOAD: + case CACHE_INIT_ACTIVATE: device_cfg->open_cores = true; case CACHE_INIT_NEW: case CACHE_INIT_BIND: @@ -1844,21 +1841,6 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, return -OCF_ERR_INVAL; } - bdev = blkdev_get_by_path(device_cfg->uuid.data, (FMODE_EXCL|FMODE_READ), - holder); - if (IS_ERR(bdev)) { - return (PTR_ERR(bdev) == -EBUSY) ? - -OCF_ERR_NOT_OPEN_EXC : - -OCF_ERR_INVAL_VOLUME_TYPE; - } - - is_part = (cas_bdev_whole(bdev) != bdev); - part_count = cas_blk_get_part_count(bdev); - blkdev_put(bdev, (FMODE_EXCL|FMODE_READ)); - - if (!is_part && part_count > 1 && !device_cfg->force) - return -KCAS_ERR_CONTAINS_PART; - result = cas_blk_identify_type(device_cfg->uuid.data, &device_cfg->volume_type); if (result) @@ -2088,6 +2070,9 @@ static int _cache_start_finalize(ocf_cache_t cache, } switch(cmd->init_cache) { + case CACHE_INIT_ACTIVATE: + cache_mngt_destroy_cache_exp_obj(cache); + /* fall through */ case CACHE_INIT_LOAD: result = cache_mngt_initialize_core_exported_objects(cache); if (result) { @@ -2115,6 +2100,119 @@ static int _cache_start_finalize(ocf_cache_t cache, return 0; } +int cache_mngt_check_bdev(struct ocf_mngt_cache_device_config *device_cfg) +{ + char holder[] = "CAS START\n"; + struct block_device *bdev; + int part_count; + bool is_part; + + bdev = blkdev_get_by_path(device_cfg->uuid.data, + (FMODE_EXCL|FMODE_READ), holder); + if (IS_ERR(bdev)) { + return (PTR_ERR(bdev) == -EBUSY) ? + -OCF_ERR_NOT_OPEN_EXC : + -OCF_ERR_INVAL_VOLUME_TYPE; + } + + is_part = (cas_bdev_whole(bdev) != bdev); + part_count = cas_blk_get_part_count(bdev); + blkdev_put(bdev, (FMODE_EXCL|FMODE_READ)); + + if (!is_part && part_count > 1 && !device_cfg->force) + return -KCAS_ERR_CONTAINS_PART; + + return 0; +} + +int cache_mngt_init_instance_activate(struct ocf_mngt_cache_config *cfg, + struct ocf_mngt_cache_device_config *device_cfg, + struct kcas_start_cache *cmd) +{ + struct _cache_mngt_attach_context *context; + ocf_cache_t cache; + struct cache_priv *cache_priv; + ocf_volume_t cache_volume; + const struct ocf_volume_uuid *cache_uuid; + char cache_name[OCF_CACHE_NAME_SIZE]; + int result = 0; + + if (!try_module_get(THIS_MODULE)) + return -KCAS_ERR_SYSTEM; + + cache_name_from_id(cache_name, cmd->cache_id); + + result = ocf_mngt_cache_get_by_name(cas_ctx, cache_name, + OCF_CACHE_NAME_SIZE, &cache); + if (result) + goto out_module_put; + + if (!ocf_cache_is_passive(cache)) { + result = -OCF_ERR_CACHE_EXIST; + goto out_cache_put; + } + + result = _cache_mngt_lock_sync(cache); + if (result) + goto out_cache_put; + + cache_volume = ocf_cache_get_volume(cache); + cache_uuid = ocf_volume_get_uuid(cache_volume); + if (strcmp(device_cfg->uuid.data, cache_uuid->data) != 0) { + result = cache_mngt_check_bdev(device_cfg); + if (result) + goto out_cache_unlock; + } + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) { + result = -ENOMEM; + goto out_cache_unlock; + } + + context->device_cfg = device_cfg; + context->cmd = cmd; + context->cache = cache; + + cache_priv = ocf_cache_get_priv(cache); + cache_priv->attach_context = context; + + context->rollback_thread = cas_lazy_thread_create(cache_start_rollback, + context, "cas_cache_rollback_complete"); + if (IS_ERR(context->rollback_thread)) { + result = PTR_ERR(context->rollback_thread); + goto err_free_context; + } + _cache_mngt_async_context_init(&context->async); + + ocf_mngt_cache_activate(cache, device_cfg, + _cache_mngt_start_complete, context); + result = wait_for_completion_interruptible(&context->async.cmpl); + + result = _cache_mngt_async_caller_set_result(&context->async, result); + if (result == -KCAS_ERR_WAITING_INTERRUPTED) + goto out_cache_put; + + cas_lazy_thread_stop(context->rollback_thread); + + if (result) + goto err_free_context; + + result = _cache_start_finalize(cache, cmd); + +err_free_context: + kfree(context); + cache_priv->attach_context = NULL; + +out_cache_unlock: + ocf_mngt_cache_unlock(cache); +out_cache_put: + ocf_mngt_cache_put(cache); +out_module_put: + module_put(THIS_MODULE); + return result; +} + int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, struct ocf_mngt_cache_device_config *device_cfg, struct kcas_start_cache *cmd) @@ -2124,9 +2222,18 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, struct cache_priv *cache_priv; int result = 0, rollback_result = 0; + if (cmd->init_cache == CACHE_INIT_ACTIVATE) + return cache_mngt_init_instance_activate(cfg, device_cfg, cmd); + if (!try_module_get(THIS_MODULE)) return -KCAS_ERR_SYSTEM; + result = cache_mngt_check_bdev(device_cfg); + if (result) { + module_put(THIS_MODULE); + return result; + } + if (cmd->init_cache == CACHE_INIT_LOAD) result = _cache_mngt_check_metadata(cfg, cmd->cache_path_name); if (result) { diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index d90acf2..e8cb267 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -37,6 +37,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 */ +#define CACHE_INIT_ACTIVATE 3 /**< activate cache after bind */ struct kcas_start_cache { /**