diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index 88867f44a..b2119a713 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -2909,7 +2909,8 @@ int check_cache_device(const char *device_path) return SUCCESS; } -int zero_md(const char *cache_device){ +int zero_md(const char *cache_device, bool force) +{ struct kcas_cache_check_device cmd_info = {}; char zero_page[4096] = {0}; int fd = 0; @@ -2937,6 +2938,37 @@ int zero_md(const char *cache_device){ return FAILURE; } + if (!cmd_info.metadata_compatible) { + if (!force) { + cas_printf(LOG_ERR, "Unable to determine whether cache contains dirty data due to metadata mismatch.\n" + "Clearing metadata might result in loss of dirty data. In order to inspect cache content\n" + "please load cache instance using matching OpenCAS version. Alternatively, if you wish to clear\n" + "metadata anyway, please use '--force' option.\n"); + return FAILURE; + } else { + cas_printf(LOG_WARNING, "Clearing metadata with unknown version - potential loss of dirty data.\n"); + } + } else if (!cmd_info.clean_shutdown) { + if (!force) { + cas_printf(LOG_ERR, "Cache instance did not shut down cleanly. It might contain dirty data. \n" + "Clearing metadata might result in loss of dirty data. Please recover cache instance\n" + "by loading it and flush dirty data in order to preserve then on the core device.\n" + "Alternatively, if you wish to clear metadata anyway, please use '--force' option. \n"); + return FAILURE; + } else { + cas_printf(LOG_WARNING, "Clearing metadata after dirty shutdown - potential loss of dirty data.\n"); + } + } else if (cmd_info.cache_dirty) { + if (!force) { + cas_printf(LOG_ERR, "Cache instance contains dirty data. Clearing metadata will result in loss of dirty data.\n" + "Please load cache instance and flush dirty data in order to preserve them on the core device.\n" + "Alternatively, if you wish to clear metadata anyway, please use '--force' option. \n"); + return FAILURE; + } else { + cas_printf(LOG_WARNING, "Clearing metadata for dirty pages - dirty cache data is being discarded. \n"); + } + } + fd = open(cache_device, O_WRONLY | O_SYNC | O_EXCL); if (fd < 0) { cas_printf(LOG_ERR, "Error while opening '%s'exclusively. This can be due to\n" diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 19161e995..5bf3d347e 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -266,9 +266,11 @@ int validate_str_metadata_mode(const char* s); * @brief clear metadata * * @param[in] cache_device device to which zeroing cache's metadata applies + * @param[in] force enforce metadata erasure despite dirty data, metadata + * mistmatch and/or dirty shutdown * @return 0 if succeed, 1 if failed */ -int zero_md(const char *cache_device); +int zero_md(const char *cache_device, bool force); /** * @brief calculate flush progress diff --git a/casadm/cas_main.c b/casadm/cas_main.c index e30e7e7d6..61f5cc2d8 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -1832,12 +1832,15 @@ static int handle_help(); struct { const char *device; + bool force; } static zero_params = { - .device = "" + .device = "", + .force = false }; static cli_option zero_options[] = { {'d', "device", "Path to device on which metadata would be cleared", 1, "DEVICE", CLI_OPTION_REQUIRED}, + {'f', "force", "Ignore potential dirty data on cache device"}, {0} }; @@ -1848,7 +1851,8 @@ int zero_handle_option(char *opt, const char **arg) if(validate_device_name(arg[0]) == FAILURE) return FAILURE; zero_params.device = arg[0]; - + } else if (!strcmp(opt, "force")){ + zero_params.force = 1; } else { return FAILURE; } @@ -1872,7 +1876,7 @@ int handle_zero() return FAILURE; } - return zero_md(zero_params.device); + return zero_md(zero_params.device, zero_params.force); } static cli_command cas_commands[] = {