diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 4c3307a26..1d4093d92 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -969,6 +969,7 @@ static int _start_cache(uint16_t cache_id, unsigned int cache_init, int fd = 0; struct kcas_start_cache cmd = {}; int status; + int ioctl = start ? KCAS_IOCTL_START_CACHE : KCAS_IOCTL_ATTACH_CACHE; double min_free_ram_gb; fd = open_ctrl_device(); @@ -993,9 +994,9 @@ static int _start_cache(uint16_t cache_id, unsigned int cache_init, status = run_ioctl_interruptible_retry( fd, - KCAS_IOCTL_START_CACHE, + ioctl, &cmd, - "Starting cache", + start ? "Starting cache" : "Attaching device to cache", cache_id, OCF_CORE_ID_INVALID); cache_id = cmd.cache_id; @@ -1007,9 +1008,11 @@ static int _start_cache(uint16_t cache_id, unsigned int cache_init, min_free_ram_gb /= GiB; cas_printf(LOG_ERR, "Not enough free RAM.\n" - "You need at least %0.2fGB to start cache" + "You need at least %0.2fGB to %s cache" " with cache line size equal %llukB.\n", - min_free_ram_gb, line_size / KiB); + min_free_ram_gb, + start ? "start" : "attach a device to", + line_size / KiB); if (64 * KiB > line_size) cas_printf(LOG_ERR, "Try with greater cache line size.\n"); @@ -1030,7 +1033,9 @@ static int _start_cache(uint16_t cache_id, unsigned int cache_init, check_cache_state_incomplete(cache_id, fd); close(fd); - cas_printf(LOG_INFO, "Successfully added cache instance %u\n", cache_id); + cas_printf(LOG_INFO, "Successfully %s %u\n", + start ? "added cache instance" : "attached device to cache", + cache_id); return SUCCESS; } @@ -1043,6 +1048,12 @@ int start_cache(uint16_t cache_id, unsigned int cache_init, line_size, force, true); } +int attach_cache(uint16_t cache_id, const char *cache_device, int force) +{ + return _start_cache(cache_id, CACHE_INIT_NEW, cache_device, + ocf_cache_mode_none, ocf_cache_line_size_none, force, false); +} + int stop_cache(uint16_t cache_id, int flush) { int fd = 0; diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 8144376d2..835d8bca3 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -1,5 +1,6 @@ /* * Copyright(c) 2012-2022 Intel Corporation +* Copyright(c) 2024 Huawei Technologies * SPDX-License-Identifier: BSD-3-Clause */ @@ -116,6 +117,8 @@ int start_cache(uint16_t cache_id, unsigned int cache_init, ocf_cache_line_size_t line_size, int force); int stop_cache(uint16_t cache_id, int flush); +int attach_cache(uint16_t cache_id, const char *cache_device, int force); + #ifdef WI_AVAILABLE #define CAS_CLI_HELP_START_CACHE_MODES "wt|wb|wa|pt|wi|wo" #define CAS_CLI_HELP_SET_CACHE_MODES "wt|wb|wa|pt|wi|wo" diff --git a/casadm/cas_main.c b/casadm/cas_main.c index e6d656139..f4e592734 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -332,6 +332,13 @@ static cli_option start_options[] = { {0} }; +static cli_option attach_cache_options[] = { + {'d', "cache-device", CACHE_DEVICE_DESC, 1, "DEVICE", CLI_OPTION_REQUIRED}, + {'i', "cache-id", CACHE_ID_DESC_LONG, 1, "ID", CLI_OPTION_REQUIRED}, + {'f', "force", "Force attaching the cache device"}, + {0} +}; + static int check_fs(const char* device, bool force) { char cache_dev_path[MAX_STR_LEN]; @@ -405,6 +412,15 @@ int validate_cache_path(const char* path, bool force) return SUCCESS; } +int handle_cache_attach(void) +{ + return attach_cache( + command_args_values.cache_id, + command_args_values.cache_device, + command_args_values.force + ); +} + int handle_start() { int status; @@ -2204,6 +2220,16 @@ static cli_command cas_commands[] = { .flags = CLI_SU_REQUIRED, .help = NULL, }, + { + .name = "attach-cache", + .desc = "Attach cache device", + .long_desc = NULL, + .options = attach_cache_options, + .command_handle_opts = start_cache_command_handle_option, + .handle = handle_cache_attach, + .flags = CLI_SU_REQUIRED, + .help = NULL, + }, { .name = "stop-cache", .short_name = 'T', diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 51e8dcf34..3ba65a386 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1876,6 +1876,39 @@ static int cache_mngt_create_cache_device_cfg( return 0; } +int cache_mngt_attach_cache_cfg(char *cache_name, size_t name_len, + struct ocf_mngt_cache_config *cfg, + struct ocf_mngt_cache_attach_config *attach_cfg, + struct kcas_start_cache *cmd) +{ + int result; + + if (!cmd) + return -OCF_ERR_INVAL; + + memset(cfg, 0, sizeof(*cfg)); + memset(attach_cfg, 0, sizeof(*attach_cfg)); + + result = cache_mngt_create_cache_device_cfg(&attach_cfg->device, + cmd->cache_path_name); + if (result) + return result; + + //TODO maybe attach should allow to change cache line size? + //cfg->cache_line_size = cmd->line_size; + cfg->use_submit_io_fast = !use_io_scheduler; + cfg->locked = true; + cfg->metadata_volatile = true; + + cfg->backfill.max_queue_size = max_writeback_queue_size; + cfg->backfill.queue_unblock_size = writeback_queue_unblock_size; + attach_cfg->cache_line_size = cmd->line_size; + attach_cfg->force = cmd->force; + attach_cfg->discard_on_start = true; + + return 0; +} + static void cache_mngt_destroy_cache_device_cfg( struct ocf_mngt_cache_device_config *cfg) { @@ -2054,7 +2087,6 @@ static void init_instance_complete(struct _cache_mngt_attach_context *ctx, } - static void calculate_min_ram_size(ocf_cache_t cache, struct _cache_mngt_attach_context *ctx) { @@ -2084,6 +2116,30 @@ static void calculate_min_ram_size(ocf_cache_t cache, printk(KERN_WARNING "Cannot calculate amount of DRAM needed\n"); } +static void _cache_mngt_attach_complete(ocf_cache_t cache, void *priv, + int error) +{ + struct _cache_mngt_attach_context *ctx = priv; + int caller_status; + char *path; + + cache_mngt_destroy_cache_device_cfg(&ctx->device_cfg); + + if (!error) { + path = (char *)ocf_volume_get_uuid(ocf_cache_get_volume( + cache))->data; + printk(KERN_INFO "Succsessfully attached %s\n", path); + } + + caller_status =_cache_mngt_async_callee_set_result(&ctx->async, error); + if (caller_status != -KCAS_ERR_WAITING_INTERRUPTED) + return; + + kfree(ctx); + ocf_mngt_cache_unlock(cache); + ocf_mngt_cache_put(cache); +} + static void _cache_mngt_start_complete(ocf_cache_t cache, void *priv, int error) { struct _cache_mngt_attach_context *ctx = priv; @@ -2450,6 +2506,56 @@ int cache_mngt_create_cache_standby_activate_cfg( return 0; } +int cache_mngt_attach_device(const char *cache_name, size_t name_len, + const char *device, struct ocf_mngt_cache_attach_config *attach_cfg) +{ + struct _cache_mngt_attach_context *context; + ocf_cache_t cache; + int result = 0; + + result = ocf_mngt_cache_get_by_name(cas_ctx, cache_name, + OCF_CACHE_NAME_SIZE, &cache); + if (result) + goto err_get; + + result = _cache_mngt_lock_sync(cache); + if (result) + goto err_lock; + + result = cache_mngt_check_bdev(&attach_cfg->device, + attach_cfg->force, true, cache); + if (result) + goto err_ctx; + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) { + result = -ENOMEM; + goto err_ctx; + } + + context->device_cfg = attach_cfg->device; + + _cache_mngt_async_context_init(&context->async); + + ocf_mngt_cache_attach(cache, attach_cfg, _cache_mngt_attach_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 err_get; + + volume_set_no_merges_flag_helper(cache); + + kfree(context); +err_ctx: + ocf_mngt_cache_unlock(cache); +err_lock: + ocf_mngt_cache_put(cache); +err_get: + return result; +} + int cache_mngt_activate(struct ocf_mngt_cache_standby_activate_config *cfg, struct kcas_standby_activate *cmd) { diff --git a/modules/cas_cache/layer_cache_management.h b/modules/cas_cache/layer_cache_management.h index 24f6c66cf..8dd6bf38b 100644 --- a/modules/cas_cache/layer_cache_management.h +++ b/modules/cas_cache/layer_cache_management.h @@ -1,5 +1,6 @@ /* * Copyright(c) 2012-2022 Intel Corporation +* Copyright(c) 2024 Huawei Technologies * SPDX-License-Identifier: BSD-3-Clause */ #ifndef __LAYER_CACHE_MANAGEMENT_H__ @@ -42,6 +43,9 @@ int cache_mngt_reset_stats(const char *cache_name, size_t cache_name_len, int cache_mngt_set_partitions(const char *cache_name, size_t name_len, struct kcas_io_classes *cfg); +int cache_mngt_attach_device(const char *cache_name, size_t name_len, + const char *device, struct ocf_mngt_cache_attach_config *attach_cfg); + int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int flush); @@ -49,6 +53,11 @@ int cache_mngt_create_cache_cfg(struct ocf_mngt_cache_config *cfg, struct ocf_mngt_cache_attach_config *attach_cfg, struct kcas_start_cache *cmd); +int cache_mngt_attach_cache_cfg(char *cache_name, size_t name_len, + struct ocf_mngt_cache_config *cfg, + struct ocf_mngt_cache_attach_config *attach_cfg, + struct kcas_start_cache *cmd); + int cache_mngt_core_pool_get_paths(struct kcas_core_pool_path *cmd_info); int cache_mngt_core_pool_remove(struct kcas_core_pool_remove *cmd_info); diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index ae8fc7bd8..ef5383bd8 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -78,6 +78,27 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval); } + case KCAS_IOCTL_ATTACH_CACHE: { + struct kcas_start_cache *cmd_info; + struct ocf_mngt_cache_config cfg; + struct ocf_mngt_cache_attach_config attach_cfg; + char cache_name[OCF_CACHE_NAME_SIZE]; + + GET_CMD_INFO(cmd_info, arg); + + cache_name_from_id(cache_name, cmd_info->cache_id); + + retval = cache_mngt_attach_cache_cfg(cache_name, OCF_CACHE_NAME_SIZE, + &cfg, &attach_cfg, cmd_info); + if (retval) + RETURN_CMD_RESULT(cmd_info, arg, retval); + + retval = cache_mngt_attach_device(cache_name, OCF_CACHE_NAME_SIZE, + cmd_info->cache_path_name, &attach_cfg); + + RETURN_CMD_RESULT(cmd_info, arg, retval); + } + case KCAS_IOCTL_SET_CACHE_STATE: { struct kcas_set_cache_state *cmd_info; char cache_name[OCF_CACHE_NAME_SIZE]; diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index a9cd4a384..db1f85ca6 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -406,6 +406,7 @@ struct kcas_standby_activate * 39 * KCAS_IOCTL_STANDBY_ACTIVATE * OK * * 40 * KCAS_IOCTL_CORE_INFO * OK * * 41 * KCAS_IOCTL_START_CACHE * OK * + * 43 * KCAS_IOCTL_ATTACH_CACHE * OK * ******************************************************************************* */ @@ -504,6 +505,9 @@ struct kcas_standby_activate /** Start new cache instance, load cache or recover cache */ #define KCAS_IOCTL_START_CACHE _IOWR(KCAS_IOCTL_MAGIC, 41, struct kcas_start_cache) +/** Attach cache device */ +#define KCAS_IOCTL_ATTACH_CACHE _IOWR(KCAS_IOCTL_MAGIC, 43, struct kcas_start_cache) + /** * Extended kernel CAS error codes */