summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-cache-metadata.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2015-04-22 16:42:35 -0400
committerMike Snitzer <snitzer@redhat.com>2015-06-11 17:13:00 -0400
commit028ae9f76f2935e8cf9974bff9a4587e3a995ff3 (patch)
tree1bd3984690e112d03cf1e56d43b32c000e420ab4 /drivers/md/dm-cache-metadata.c
parent88bf5184fa5861e766e39fd34fc6d21557ac7be8 (diff)
dm cache: add fail io mode and needs_check flag
If a cache metadata operation fails (e.g. transaction commit) the cache's metadata device will abort the current transaction, set a new needs_check flag, and the cache will transition to "read-only" mode. If aborting the transaction or setting the needs_check flag fails the cache will transition to "fail-io" mode. Once needs_check is set the cache device will not be allowed to activate. Activation requires write access to metadata. Future work is needed to add proper support for running the cache in read-only mode. Once in fail-io mode the cache will report a status of "Fail". Also, add commit() wrapper that will disallow commits if in read_only or fail mode. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-cache-metadata.c')
-rw-r--r--drivers/md/dm-cache-metadata.c133
1 files changed, 114 insertions, 19 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index c1c010498a21..20cc36b01b77 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -39,6 +39,8 @@
39enum superblock_flag_bits { 39enum superblock_flag_bits {
40 /* for spotting crashes that would invalidate the dirty bitset */ 40 /* for spotting crashes that would invalidate the dirty bitset */
41 CLEAN_SHUTDOWN, 41 CLEAN_SHUTDOWN,
42 /* metadata must be checked using the tools */
43 NEEDS_CHECK,
42}; 44};
43 45
44/* 46/*
@@ -107,6 +109,7 @@ struct dm_cache_metadata {
107 struct dm_disk_bitset discard_info; 109 struct dm_disk_bitset discard_info;
108 110
109 struct rw_semaphore root_lock; 111 struct rw_semaphore root_lock;
112 unsigned long flags;
110 dm_block_t root; 113 dm_block_t root;
111 dm_block_t hint_root; 114 dm_block_t hint_root;
112 dm_block_t discard_root; 115 dm_block_t discard_root;
@@ -129,6 +132,14 @@ struct dm_cache_metadata {
129 * buffer before the superblock is locked and updated. 132 * buffer before the superblock is locked and updated.
130 */ 133 */
131 __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE]; 134 __u8 metadata_space_map_root[SPACE_MAP_ROOT_SIZE];
135
136 /*
137 * Set if a transaction has to be aborted but the attempt to roll
138 * back to the previous (good) transaction failed. The only
139 * metadata operation permissible in this state is the closing of
140 * the device.
141 */
142 bool fail_io:1;
132}; 143};
133 144
134/*------------------------------------------------------------------- 145/*-------------------------------------------------------------------
@@ -527,6 +538,7 @@ static unsigned long clear_clean_shutdown(unsigned long flags)
527static void read_superblock_fields(struct dm_cache_metadata *cmd, 538static void read_superblock_fields(struct dm_cache_metadata *cmd,
528 struct cache_disk_superblock *disk_super) 539 struct cache_disk_superblock *disk_super)
529{ 540{
541 cmd->flags = le32_to_cpu(disk_super->flags);
530 cmd->root = le64_to_cpu(disk_super->mapping_root); 542 cmd->root = le64_to_cpu(disk_super->mapping_root);
531 cmd->hint_root = le64_to_cpu(disk_super->hint_root); 543 cmd->hint_root = le64_to_cpu(disk_super->hint_root);
532 cmd->discard_root = le64_to_cpu(disk_super->discard_root); 544 cmd->discard_root = le64_to_cpu(disk_super->discard_root);
@@ -625,6 +637,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
625 if (mutator) 637 if (mutator)
626 update_flags(disk_super, mutator); 638 update_flags(disk_super, mutator);
627 639
640 disk_super->flags = cpu_to_le32(cmd->flags);
628 disk_super->mapping_root = cpu_to_le64(cmd->root); 641 disk_super->mapping_root = cpu_to_le64(cmd->root);
629 disk_super->hint_root = cpu_to_le64(cmd->hint_root); 642 disk_super->hint_root = cpu_to_le64(cmd->hint_root);
630 disk_super->discard_root = cpu_to_le64(cmd->discard_root); 643 disk_super->discard_root = cpu_to_le64(cmd->discard_root);
@@ -693,6 +706,7 @@ static struct dm_cache_metadata *metadata_open(struct block_device *bdev,
693 cmd->cache_blocks = 0; 706 cmd->cache_blocks = 0;
694 cmd->policy_hint_size = policy_hint_size; 707 cmd->policy_hint_size = policy_hint_size;
695 cmd->changed = true; 708 cmd->changed = true;
709 cmd->fail_io = false;
696 710
697 r = __create_persistent_data_objects(cmd, may_format_device); 711 r = __create_persistent_data_objects(cmd, may_format_device);
698 if (r) { 712 if (r) {
@@ -796,7 +810,8 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd)
796 list_del(&cmd->list); 810 list_del(&cmd->list);
797 mutex_unlock(&table_lock); 811 mutex_unlock(&table_lock);
798 812
799 __destroy_persistent_data_objects(cmd); 813 if (!cmd->fail_io)
814 __destroy_persistent_data_objects(cmd);
800 kfree(cmd); 815 kfree(cmd);
801 } 816 }
802} 817}
@@ -848,13 +863,26 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd,
848 return 0; 863 return 0;
849} 864}
850 865
866#define WRITE_LOCK(cmd) \
867 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \
868 return -EINVAL; \
869 down_write(&cmd->root_lock)
870
871#define WRITE_LOCK_VOID(cmd) \
872 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \
873 return; \
874 down_write(&cmd->root_lock)
875
876#define WRITE_UNLOCK(cmd) \
877 up_write(&cmd->root_lock)
878
851int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) 879int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size)
852{ 880{
853 int r; 881 int r;
854 bool clean; 882 bool clean;
855 __le64 null_mapping = pack_value(0, 0); 883 __le64 null_mapping = pack_value(0, 0);
856 884
857 down_write(&cmd->root_lock); 885 WRITE_LOCK(cmd);
858 __dm_bless_for_disk(&null_mapping); 886 __dm_bless_for_disk(&null_mapping);
859 887
860 if (from_cblock(new_cache_size) < from_cblock(cmd->cache_blocks)) { 888 if (from_cblock(new_cache_size) < from_cblock(cmd->cache_blocks)) {
@@ -880,7 +908,7 @@ int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size)
880 cmd->changed = true; 908 cmd->changed = true;
881 909
882out: 910out:
883 up_write(&cmd->root_lock); 911 WRITE_UNLOCK(cmd);
884 912
885 return r; 913 return r;
886} 914}
@@ -891,7 +919,7 @@ int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
891{ 919{
892 int r; 920 int r;
893 921
894 down_write(&cmd->root_lock); 922 WRITE_LOCK(cmd);
895 r = dm_bitset_resize(&cmd->discard_info, 923 r = dm_bitset_resize(&cmd->discard_info,
896 cmd->discard_root, 924 cmd->discard_root,
897 from_dblock(cmd->discard_nr_blocks), 925 from_dblock(cmd->discard_nr_blocks),
@@ -903,7 +931,7 @@ int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
903 } 931 }
904 932
905 cmd->changed = true; 933 cmd->changed = true;
906 up_write(&cmd->root_lock); 934 WRITE_UNLOCK(cmd);
907 935
908 return r; 936 return r;
909} 937}
@@ -946,9 +974,9 @@ int dm_cache_set_discard(struct dm_cache_metadata *cmd,
946{ 974{
947 int r; 975 int r;
948 976
949 down_write(&cmd->root_lock); 977 WRITE_LOCK(cmd);
950 r = __discard(cmd, dblock, discard); 978 r = __discard(cmd, dblock, discard);
951 up_write(&cmd->root_lock); 979 WRITE_UNLOCK(cmd);
952 980
953 return r; 981 return r;
954} 982}
@@ -1020,9 +1048,9 @@ int dm_cache_remove_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock)
1020{ 1048{
1021 int r; 1049 int r;
1022 1050
1023 down_write(&cmd->root_lock); 1051 WRITE_LOCK(cmd);
1024 r = __remove(cmd, cblock); 1052 r = __remove(cmd, cblock);
1025 up_write(&cmd->root_lock); 1053 WRITE_UNLOCK(cmd);
1026 1054
1027 return r; 1055 return r;
1028} 1056}
@@ -1048,9 +1076,9 @@ int dm_cache_insert_mapping(struct dm_cache_metadata *cmd,
1048{ 1076{
1049 int r; 1077 int r;
1050 1078
1051 down_write(&cmd->root_lock); 1079 WRITE_LOCK(cmd);
1052 r = __insert(cmd, cblock, oblock); 1080 r = __insert(cmd, cblock, oblock);
1053 up_write(&cmd->root_lock); 1081 WRITE_UNLOCK(cmd);
1054 1082
1055 return r; 1083 return r;
1056} 1084}
@@ -1234,9 +1262,9 @@ int dm_cache_set_dirty(struct dm_cache_metadata *cmd,
1234{ 1262{
1235 int r; 1263 int r;
1236 1264
1237 down_write(&cmd->root_lock); 1265 WRITE_LOCK(cmd);
1238 r = __dirty(cmd, cblock, dirty); 1266 r = __dirty(cmd, cblock, dirty);
1239 up_write(&cmd->root_lock); 1267 WRITE_UNLOCK(cmd);
1240 1268
1241 return r; 1269 return r;
1242} 1270}
@@ -1252,9 +1280,9 @@ void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
1252void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, 1280void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd,
1253 struct dm_cache_statistics *stats) 1281 struct dm_cache_statistics *stats)
1254{ 1282{
1255 down_write(&cmd->root_lock); 1283 WRITE_LOCK_VOID(cmd);
1256 cmd->stats = *stats; 1284 cmd->stats = *stats;
1257 up_write(&cmd->root_lock); 1285 WRITE_UNLOCK(cmd);
1258} 1286}
1259 1287
1260int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown) 1288int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown)
@@ -1263,7 +1291,7 @@ int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown)
1263 flags_mutator mutator = (clean_shutdown ? set_clean_shutdown : 1291 flags_mutator mutator = (clean_shutdown ? set_clean_shutdown :
1264 clear_clean_shutdown); 1292 clear_clean_shutdown);
1265 1293
1266 down_write(&cmd->root_lock); 1294 WRITE_LOCK(cmd);
1267 r = __commit_transaction(cmd, mutator); 1295 r = __commit_transaction(cmd, mutator);
1268 if (r) 1296 if (r)
1269 goto out; 1297 goto out;
@@ -1271,7 +1299,7 @@ int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown)
1271 r = __begin_transaction(cmd); 1299 r = __begin_transaction(cmd);
1272 1300
1273out: 1301out:
1274 up_write(&cmd->root_lock); 1302 WRITE_UNLOCK(cmd);
1275 return r; 1303 return r;
1276} 1304}
1277 1305
@@ -1376,9 +1404,9 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
1376{ 1404{
1377 int r; 1405 int r;
1378 1406
1379 down_write(&cmd->root_lock); 1407 WRITE_LOCK(cmd);
1380 r = write_hints(cmd, policy); 1408 r = write_hints(cmd, policy);
1381 up_write(&cmd->root_lock); 1409 WRITE_UNLOCK(cmd);
1382 1410
1383 return r; 1411 return r;
1384} 1412}
@@ -1387,3 +1415,70 @@ int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result)
1387{ 1415{
1388 return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result); 1416 return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
1389} 1417}
1418
1419void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd)
1420{
1421 WRITE_LOCK_VOID(cmd);
1422 dm_bm_set_read_only(cmd->bm);
1423 WRITE_UNLOCK(cmd);
1424}
1425
1426void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd)
1427{
1428 WRITE_LOCK_VOID(cmd);
1429 dm_bm_set_read_write(cmd->bm);
1430 WRITE_UNLOCK(cmd);
1431}
1432
1433int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd)
1434{
1435 int r;
1436 struct dm_block *sblock;
1437 struct cache_disk_superblock *disk_super;
1438
1439 /*
1440 * We ignore fail_io for this function.
1441 */
1442 down_write(&cmd->root_lock);
1443 set_bit(NEEDS_CHECK, &cmd->flags);
1444
1445 r = superblock_lock(cmd, &sblock);
1446 if (r) {
1447 DMERR("couldn't read superblock");
1448 goto out;
1449 }
1450
1451 disk_super = dm_block_data(sblock);
1452 disk_super->flags = cpu_to_le32(cmd->flags);
1453
1454 dm_bm_unlock(sblock);
1455
1456out:
1457 up_write(&cmd->root_lock);
1458 return r;
1459}
1460
1461bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd)
1462{
1463 bool needs_check;
1464
1465 down_read(&cmd->root_lock);
1466 needs_check = !!test_bit(NEEDS_CHECK, &cmd->flags);
1467 up_read(&cmd->root_lock);
1468
1469 return needs_check;
1470}
1471
1472int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
1473{
1474 int r;
1475
1476 WRITE_LOCK(cmd);
1477 __destroy_persistent_data_objects(cmd);
1478 r = __create_persistent_data_objects(cmd, false);
1479 if (r)
1480 cmd->fail_io = true;
1481 WRITE_UNLOCK(cmd);
1482
1483 return r;
1484}