Merge pull request #649 from arutk/zero-md-old-meta

Zero metadata if on-disk version differs from current
This commit is contained in:
Robert Baldyga 2021-01-21 17:54:29 +01:00 committed by GitHub
commit af664f9917
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 8 deletions

View File

@ -2894,7 +2894,7 @@ int check_cache_device(const char *device_path)
fprintf(intermediate_file[1], TAG(TABLE_HEADER) "Is cache,Clean Shutdown,Cache dirty\n"); fprintf(intermediate_file[1], TAG(TABLE_HEADER) "Is cache,Clean Shutdown,Cache dirty\n");
fprintf(intermediate_file[1], TAG(TABLE_ROW)); fprintf(intermediate_file[1], TAG(TABLE_ROW));
if (cmd_info.is_cache_device) { if (cmd_info.is_cache_device && cmd_info.metadata_compatible) {
fprintf(intermediate_file[1], "yes,%s,%s\n", fprintf(intermediate_file[1], "yes,%s,%s\n",
cmd_info.clean_shutdown ? "yes" : "no", cmd_info.clean_shutdown ? "yes" : "no",
cmd_info.cache_dirty ? "yes" : "no"); cmd_info.cache_dirty ? "yes" : "no");
@ -2909,7 +2909,8 @@ int check_cache_device(const char *device_path)
return SUCCESS; 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 = {}; struct kcas_cache_check_device cmd_info = {};
char zero_page[4096] = {0}; char zero_page[4096] = {0};
int fd = 0; int fd = 0;
@ -2937,6 +2938,37 @@ int zero_md(const char *cache_device){
return FAILURE; 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); fd = open(cache_device, O_WRONLY | O_SYNC | O_EXCL);
if (fd < 0) { if (fd < 0) {
cas_printf(LOG_ERR, "Error while opening '%s'exclusively. This can be due to\n" cas_printf(LOG_ERR, "Error while opening '%s'exclusively. This can be due to\n"

View File

@ -266,9 +266,11 @@ int validate_str_metadata_mode(const char* s);
* @brief clear metadata * @brief clear metadata
* *
* @param[in] cache_device device to which zeroing cache's metadata applies * @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 * @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 * @brief calculate flush progress

View File

@ -1832,12 +1832,15 @@ static int handle_help();
struct { struct {
const char *device; const char *device;
bool force;
} static zero_params = { } static zero_params = {
.device = "" .device = "",
.force = false
}; };
static cli_option zero_options[] = { static cli_option zero_options[] = {
{'d', "device", "Path to device on which metadata would be cleared", 1, "DEVICE", CLI_OPTION_REQUIRED}, {'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} {0}
}; };
@ -1848,7 +1851,8 @@ int zero_handle_option(char *opt, const char **arg)
if(validate_device_name(arg[0]) == FAILURE) if(validate_device_name(arg[0]) == FAILURE)
return FAILURE; return FAILURE;
zero_params.device = arg[0]; zero_params.device = arg[0];
} else if (!strcmp(opt, "force")){
zero_params.force = 1;
} else { } else {
return FAILURE; return FAILURE;
} }
@ -1872,7 +1876,7 @@ int handle_zero()
return FAILURE; return FAILURE;
} }
return zero_md(zero_params.device); return zero_md(zero_params.device, zero_params.force);
} }
static cli_command cas_commands[] = { static cli_command cas_commands[] = {

View File

@ -1012,11 +1012,17 @@ static void cache_mngt_metadata_probe_end(void *priv, int error,
*context->result = error; *context->result = error;
if (error == -OCF_ERR_NO_METADATA || error == -OCF_ERR_METADATA_VER) { if (error == -OCF_ERR_NO_METADATA) {
cmd_info->is_cache_device = false; cmd_info->is_cache_device = false;
cmd_info->metadata_compatible = false;
*context->result = 0;
} else if (error == -OCF_ERR_METADATA_VER) {
cmd_info->is_cache_device = true;
cmd_info->metadata_compatible = false;
*context->result = 0; *context->result = 0;
} else if (error == 0) { } else if (error == 0) {
cmd_info->is_cache_device = true; cmd_info->is_cache_device = true;
cmd_info->metadata_compatible = true;
cmd_info->clean_shutdown = status->clean_shutdown; cmd_info->clean_shutdown = status->clean_shutdown;
cmd_info->cache_dirty = status->cache_dirty; cmd_info->cache_dirty = status->cache_dirty;
} }

View File

@ -314,7 +314,12 @@ struct kcas_core_pool_remove {
struct kcas_cache_check_device { struct kcas_cache_check_device {
char path_name[MAX_STR_LEN]; /**< path to a device */ char path_name[MAX_STR_LEN]; /**< path to a device */
bool is_cache_device; bool is_cache_device; /* OCF metadata detected */
/* following bool flags are defined is_cache_device == 1 */
bool metadata_compatible; /* OCF metadata is in current version */
/* following bool flags are defined iff is_metadata_compatible == 1 */
bool clean_shutdown; bool clean_shutdown;
bool cache_dirty; bool cache_dirty;
bool format_atomic; bool format_atomic;

View File

@ -154,6 +154,10 @@ Atomic mode exploits extended NVMe metadata features. In this mode namespace
uses 520 bytes LBA allowing to write cache data and metadata in a single uses 520 bytes LBA allowing to write cache data and metadata in a single
request (atomically). request (atomically).
.TP
.B --zero-metadata
Remove metadata from previously used cache device.
.TP .TP
.B -H, --help .B -H, --help
Print help. Print help.
@ -586,6 +590,15 @@ Identifier of cache instance <1-16384>.
Defines output format for printed IO class configuration. It can be either Defines output format for printed IO class configuration. It can be either
\fBtable\fR (default) or \fBcsv\fR. \fBtable\fR (default) or \fBcsv\fR.
.SH Options that are valid with --zero-metadata are:
.TP
.B -d, --device <DEVICE>
Path to block device containing Open CAS metadata.
.TP
.B -f, --force
Ignore potential dirty data on cache device.
.SH Command --help (-H) does not accept any options. .SH Command --help (-H) does not accept any options.
.BR .BR