dm cache: policy ignore hints if generated by different version

When reading the dm cache metadata from disk, ignore the policy hints
unless they were generated by the same major version number of the same
policy module.

The hints are considered to be private data belonging to the specific
module that generated them and there is no requirement for them to make
sense to different versions of the policy that generated them.
Policy modules are all required to work fine if no previous hints are
supplied (or if existing hints are lost).

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
This commit is contained in:
Mike Snitzer 2013-03-20 17:21:28 +00:00 committed by Alasdair G Kergon
parent 4e7f506f64
commit ea2dd8c1ed
3 changed files with 39 additions and 13 deletions

View File

@ -863,18 +863,43 @@ struct thunk {
bool hints_valid; bool hints_valid;
}; };
static bool policy_unchanged(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy)
{
const char *policy_name = dm_cache_policy_get_name(policy);
const unsigned *policy_version = dm_cache_policy_get_version(policy);
size_t policy_hint_size = dm_cache_policy_get_hint_size(policy);
/*
* Ensure policy names match.
*/
if (strncmp(cmd->policy_name, policy_name, sizeof(cmd->policy_name)))
return false;
/*
* Ensure policy major versions match.
*/
if (cmd->policy_version[0] != policy_version[0])
return false;
/*
* Ensure policy hint sizes match.
*/
if (cmd->policy_hint_size != policy_hint_size)
return false;
return true;
}
static bool hints_array_initialized(struct dm_cache_metadata *cmd) static bool hints_array_initialized(struct dm_cache_metadata *cmd)
{ {
return cmd->hint_root && cmd->policy_hint_size; return cmd->hint_root && cmd->policy_hint_size;
} }
static bool hints_array_available(struct dm_cache_metadata *cmd, static bool hints_array_available(struct dm_cache_metadata *cmd,
const char *policy_name) struct dm_cache_policy *policy)
{ {
bool policy_names_match = !strncmp(cmd->policy_name, policy_name, return cmd->clean_when_opened && policy_unchanged(cmd, policy) &&
sizeof(cmd->policy_name));
return cmd->clean_when_opened && policy_names_match &&
hints_array_initialized(cmd); hints_array_initialized(cmd);
} }
@ -908,7 +933,8 @@ static int __load_mapping(void *context, uint64_t cblock, void *leaf)
return r; return r;
} }
static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_name, static int __load_mappings(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy,
load_mapping_fn fn, void *context) load_mapping_fn fn, void *context)
{ {
struct thunk thunk; struct thunk thunk;
@ -918,18 +944,19 @@ static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_nam
thunk.cmd = cmd; thunk.cmd = cmd;
thunk.respect_dirty_flags = cmd->clean_when_opened; thunk.respect_dirty_flags = cmd->clean_when_opened;
thunk.hints_valid = hints_array_available(cmd, policy_name); thunk.hints_valid = hints_array_available(cmd, policy);
return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk); return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk);
} }
int dm_cache_load_mappings(struct dm_cache_metadata *cmd, const char *policy_name, int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
struct dm_cache_policy *policy,
load_mapping_fn fn, void *context) load_mapping_fn fn, void *context)
{ {
int r; int r;
down_read(&cmd->root_lock); down_read(&cmd->root_lock);
r = __load_mappings(cmd, policy_name, fn, context); r = __load_mappings(cmd, policy, fn, context);
up_read(&cmd->root_lock); up_read(&cmd->root_lock);
return r; return r;
@ -1085,7 +1112,7 @@ static int begin_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po
(strlen(policy_name) > sizeof(cmd->policy_name) - 1)) (strlen(policy_name) > sizeof(cmd->policy_name) - 1))
return -EINVAL; return -EINVAL;
if (strcmp(cmd->policy_name, policy_name)) { if (!policy_unchanged(cmd, policy)) {
strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name)); strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name));
memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version)); memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version));

View File

@ -89,7 +89,7 @@ typedef int (*load_mapping_fn)(void *context, dm_oblock_t oblock,
dm_cblock_t cblock, bool dirty, dm_cblock_t cblock, bool dirty,
uint32_t hint, bool hint_valid); uint32_t hint, bool hint_valid);
int dm_cache_load_mappings(struct dm_cache_metadata *cmd, int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
const char *policy_name, struct dm_cache_policy *policy,
load_mapping_fn fn, load_mapping_fn fn,
void *context); void *context);

View File

@ -2369,8 +2369,7 @@ static int cache_preresume(struct dm_target *ti)
} }
if (!cache->loaded_mappings) { if (!cache->loaded_mappings) {
r = dm_cache_load_mappings(cache->cmd, r = dm_cache_load_mappings(cache->cmd, cache->policy,
dm_cache_policy_get_name(cache->policy),
load_mapping, cache); load_mapping, cache);
if (r) { if (r) {
DMERR("could not load cache mappings"); DMERR("could not load cache mappings");