aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-cache-metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-cache-metadata.c')
-rw-r--r--drivers/md/dm-cache-metadata.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index fbd3625f2748..83e995fece88 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -83,6 +83,8 @@ struct cache_disk_superblock {
83 __le32 read_misses; 83 __le32 read_misses;
84 __le32 write_hits; 84 __le32 write_hits;
85 __le32 write_misses; 85 __le32 write_misses;
86
87 __le32 policy_version[CACHE_POLICY_VERSION_SIZE];
86} __packed; 88} __packed;
87 89
88struct dm_cache_metadata { 90struct dm_cache_metadata {
@@ -109,6 +111,7 @@ struct dm_cache_metadata {
109 bool clean_when_opened:1; 111 bool clean_when_opened:1;
110 112
111 char policy_name[CACHE_POLICY_NAME_SIZE]; 113 char policy_name[CACHE_POLICY_NAME_SIZE];
114 unsigned policy_version[CACHE_POLICY_VERSION_SIZE];
112 size_t policy_hint_size; 115 size_t policy_hint_size;
113 struct dm_cache_statistics stats; 116 struct dm_cache_statistics stats;
114}; 117};
@@ -268,7 +271,8 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
268 memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); 271 memset(disk_super->uuid, 0, sizeof(disk_super->uuid));
269 disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC); 272 disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC);
270 disk_super->version = cpu_to_le32(CACHE_VERSION); 273 disk_super->version = cpu_to_le32(CACHE_VERSION);
271 memset(disk_super->policy_name, 0, CACHE_POLICY_NAME_SIZE); 274 memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name));
275 memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version));
272 disk_super->policy_hint_size = 0; 276 disk_super->policy_hint_size = 0;
273 277
274 r = dm_sm_copy_root(cmd->metadata_sm, &disk_super->metadata_space_map_root, 278 r = dm_sm_copy_root(cmd->metadata_sm, &disk_super->metadata_space_map_root,
@@ -284,7 +288,6 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
284 disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); 288 disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
285 disk_super->data_block_size = cpu_to_le32(cmd->data_block_size); 289 disk_super->data_block_size = cpu_to_le32(cmd->data_block_size);
286 disk_super->cache_blocks = cpu_to_le32(0); 290 disk_super->cache_blocks = cpu_to_le32(0);
287 memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name));
288 291
289 disk_super->read_hits = cpu_to_le32(0); 292 disk_super->read_hits = cpu_to_le32(0);
290 disk_super->read_misses = cpu_to_le32(0); 293 disk_super->read_misses = cpu_to_le32(0);
@@ -478,6 +481,9 @@ static void read_superblock_fields(struct dm_cache_metadata *cmd,
478 cmd->data_block_size = le32_to_cpu(disk_super->data_block_size); 481 cmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
479 cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks)); 482 cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks));
480 strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name)); 483 strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name));
484 cmd->policy_version[0] = le32_to_cpu(disk_super->policy_version[0]);
485 cmd->policy_version[1] = le32_to_cpu(disk_super->policy_version[1]);
486 cmd->policy_version[2] = le32_to_cpu(disk_super->policy_version[2]);
481 cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size); 487 cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size);
482 488
483 cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits); 489 cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits);
@@ -572,6 +578,9 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
572 disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks)); 578 disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks));
573 disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks)); 579 disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks));
574 strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name)); 580 strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name));
581 disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]);
582 disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]);
583 disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]);
575 584
576 disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits); 585 disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits);
577 disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses); 586 disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses);
@@ -854,18 +863,43 @@ struct thunk {
854 bool hints_valid; 863 bool hints_valid;
855}; 864};
856 865
866static bool policy_unchanged(struct dm_cache_metadata *cmd,
867 struct dm_cache_policy *policy)
868{
869 const char *policy_name = dm_cache_policy_get_name(policy);
870 const unsigned *policy_version = dm_cache_policy_get_version(policy);
871 size_t policy_hint_size = dm_cache_policy_get_hint_size(policy);
872
873 /*
874 * Ensure policy names match.
875 */
876 if (strncmp(cmd->policy_name, policy_name, sizeof(cmd->policy_name)))
877 return false;
878
879 /*
880 * Ensure policy major versions match.
881 */
882 if (cmd->policy_version[0] != policy_version[0])
883 return false;
884
885 /*
886 * Ensure policy hint sizes match.
887 */
888 if (cmd->policy_hint_size != policy_hint_size)
889 return false;
890
891 return true;
892}
893
857static bool hints_array_initialized(struct dm_cache_metadata *cmd) 894static bool hints_array_initialized(struct dm_cache_metadata *cmd)
858{ 895{
859 return cmd->hint_root && cmd->policy_hint_size; 896 return cmd->hint_root && cmd->policy_hint_size;
860} 897}
861 898
862static bool hints_array_available(struct dm_cache_metadata *cmd, 899static bool hints_array_available(struct dm_cache_metadata *cmd,
863 const char *policy_name) 900 struct dm_cache_policy *policy)
864{ 901{
865 bool policy_names_match = !strncmp(cmd->policy_name, policy_name, 902 return cmd->clean_when_opened && policy_unchanged(cmd, policy) &&
866 sizeof(cmd->policy_name));
867
868 return cmd->clean_when_opened && policy_names_match &&
869 hints_array_initialized(cmd); 903 hints_array_initialized(cmd);
870} 904}
871 905
@@ -899,7 +933,8 @@ static int __load_mapping(void *context, uint64_t cblock, void *leaf)
899 return r; 933 return r;
900} 934}
901 935
902static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_name, 936static int __load_mappings(struct dm_cache_metadata *cmd,
937 struct dm_cache_policy *policy,
903 load_mapping_fn fn, void *context) 938 load_mapping_fn fn, void *context)
904{ 939{
905 struct thunk thunk; 940 struct thunk thunk;
@@ -909,18 +944,19 @@ static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_nam
909 944
910 thunk.cmd = cmd; 945 thunk.cmd = cmd;
911 thunk.respect_dirty_flags = cmd->clean_when_opened; 946 thunk.respect_dirty_flags = cmd->clean_when_opened;
912 thunk.hints_valid = hints_array_available(cmd, policy_name); 947 thunk.hints_valid = hints_array_available(cmd, policy);
913 948
914 return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk); 949 return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk);
915} 950}
916 951
917int dm_cache_load_mappings(struct dm_cache_metadata *cmd, const char *policy_name, 952int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
953 struct dm_cache_policy *policy,
918 load_mapping_fn fn, void *context) 954 load_mapping_fn fn, void *context)
919{ 955{
920 int r; 956 int r;
921 957
922 down_read(&cmd->root_lock); 958 down_read(&cmd->root_lock);
923 r = __load_mappings(cmd, policy_name, fn, context); 959 r = __load_mappings(cmd, policy, fn, context);
924 up_read(&cmd->root_lock); 960 up_read(&cmd->root_lock);
925 961
926 return r; 962 return r;
@@ -979,7 +1015,7 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty
979 /* nothing to be done */ 1015 /* nothing to be done */
980 return 0; 1016 return 0;
981 1017
982 value = pack_value(oblock, flags | (dirty ? M_DIRTY : 0)); 1018 value = pack_value(oblock, (flags & ~M_DIRTY) | (dirty ? M_DIRTY : 0));
983 __dm_bless_for_disk(&value); 1019 __dm_bless_for_disk(&value);
984 1020
985 r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock), 1021 r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock),
@@ -1070,13 +1106,15 @@ static int begin_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po
1070 __le32 value; 1106 __le32 value;
1071 size_t hint_size; 1107 size_t hint_size;
1072 const char *policy_name = dm_cache_policy_get_name(policy); 1108 const char *policy_name = dm_cache_policy_get_name(policy);
1109 const unsigned *policy_version = dm_cache_policy_get_version(policy);
1073 1110
1074 if (!policy_name[0] || 1111 if (!policy_name[0] ||
1075 (strlen(policy_name) > sizeof(cmd->policy_name) - 1)) 1112 (strlen(policy_name) > sizeof(cmd->policy_name) - 1))
1076 return -EINVAL; 1113 return -EINVAL;
1077 1114
1078 if (strcmp(cmd->policy_name, policy_name)) { 1115 if (!policy_unchanged(cmd, policy)) {
1079 strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name)); 1116 strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name));
1117 memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version));
1080 1118
1081 hint_size = dm_cache_policy_get_hint_size(policy); 1119 hint_size = dm_cache_policy_get_hint_size(policy);
1082 if (!hint_size) 1120 if (!hint_size)