diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 00b0c87..57b664d 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -2926,3 +2926,47 @@ int check_cache_device(const char *device_path) return SUCCESS; } + +int zero_md(const char *cache_device){ + struct kcas_cache_check_device cmd_info; + char zero_page[4096] = {0}; + int fd = 0; + + /* check if given cache device exists */ + fd = open(cache_device, O_RDONLY); + if (fd < 0) { + cas_printf(LOG_ERR, "Device '%s' not found.\n", cache_device); + return FAILURE; + } + close(fd); + + /* don't delete metadata if cache is in use */ + if (check_cache_already_added(cache_device) == FAILURE) { + cas_printf(LOG_ERR, "Cache device '%s' is already used as cache. " + "Please stop cache to clear metadata.\n", cache_device); + return FAILURE; + } + + /* don't delete metadata if device hasn't got CAS's metadata */ + _check_cache_device(cache_device, &cmd_info); + if (!cmd_info.is_cache_device) { + cas_printf(LOG_ERR, "Device '%s' does not contain OpenCAS's metadata.\n", cache_device); + return FAILURE; + } + + fd = open(cache_device, O_WRONLY | O_SYNC); + if (fd < 0) { + cas_printf(LOG_ERR, "Error while opening '%s' to purge metadata.\n", cache_device); + return FAILURE; + } + + if(write(fd, zero_page, 4096) != 4096) { + close(fd); + cas_printf(LOG_ERR, "Error while wiping out metadata from device '%s'.\n", cache_device); + return FAILURE; + } + + close(fd); + cas_printf(LOG_INFO, "OpenCAS's metadata wiped succesfully from device '%s'.\n", cache_device); + return SUCCESS; +} diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 4fbbd55..776b0f0 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -267,6 +267,14 @@ int validate_str_stats_filters(const char* s); int validate_str_output_format(const char* s); int validate_str_metadata_mode(const char* s); +/** + * @brief clear metadata + * + * @param[in] cache_device device to which zeroing cache's metadata applies + * @return 0 if succeed, 1 if failed + */ +int zero_md(const char *cache_device); + /** * @brief calculate flush progress * diff --git a/casadm/cas_main.c b/casadm/cas_main.c index ea5daa3..3414586 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -1945,6 +1945,51 @@ void io_class_help(app *app_values, cli_command *cmd) static int handle_help(); +struct { + const char *device; +} static zero_params = { + .device = "" +}; + +static cli_option zero_options[] = { + {'d', "device", "Path to device on which metadata would be cleared", 1, "DEVICE", CLI_OPTION_REQUIRED}, + {0} +}; + +/* Parser of option for zeroing metadata command */ +int zero_handle_option(char *opt, const char **arg) +{ + if (!strcmp(opt, "device")) { + if(validate_device_name(arg[0]) == FAILURE) + return FAILURE; + zero_params.device = arg[0]; + + } else { + return FAILURE; + } + + return 0; +} + +int handle_zero() +{ + int cache_device = 0; + + cache_device = open(zero_params.device, O_RDONLY); + + if (cache_device < 0) { + cas_printf(LOG_ERR, "Couldn't open cache device %s.\n", zero_params.device); + return FAILURE; + } + + if (close(cache_device) < 0) { + cas_printf(LOG_ERR, "Couldn't close the cache device.\n"); + return FAILURE; + } + + return zero_md(zero_params.device); +} + static cli_command cas_commands[] = { { .name = "start-cache", @@ -2132,6 +2177,16 @@ static cli_command cas_commands[] = { .handle = handle_help, .help = NULL }, + { + .name = "zero-metadata", + .desc = "Clear metadata from caching device", + .long_desc = NULL, + .options = zero_options, + .command_handle_opts = zero_handle_option, + .handle = handle_zero, + .flags = CLI_SU_REQUIRED, + .help = NULL + }, { .name = "script", .options = script_params_options,