3939enum superblock_flag_bits {
4040 /* for spotting crashes that would invalidate the dirty bitset */
4141 CLEAN_SHUTDOWN ,
42+ /* metadata must be checked using the tools */
43+ NEEDS_CHECK ,
4244};
4345
4446/*
@@ -107,6 +109,7 @@ struct dm_cache_metadata {
107109 struct dm_disk_bitset discard_info ;
108110
109111 struct rw_semaphore root_lock ;
112+ unsigned long flags ;
110113 dm_block_t root ;
111114 dm_block_t hint_root ;
112115 dm_block_t discard_root ;
@@ -129,6 +132,14 @@ struct dm_cache_metadata {
129132 * buffer before the superblock is locked and updated.
130133 */
131134 __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 ;
132143};
133144
134145/*-------------------------------------------------------------------
@@ -527,6 +538,7 @@ static unsigned long clear_clean_shutdown(unsigned long flags)
527538static void read_superblock_fields (struct dm_cache_metadata * cmd ,
528539 struct cache_disk_superblock * disk_super )
529540{
541+ cmd -> flags = le32_to_cpu (disk_super -> flags );
530542 cmd -> root = le64_to_cpu (disk_super -> mapping_root );
531543 cmd -> hint_root = le64_to_cpu (disk_super -> hint_root );
532544 cmd -> discard_root = le64_to_cpu (disk_super -> discard_root );
@@ -625,6 +637,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
625637 if (mutator )
626638 update_flags (disk_super , mutator );
627639
640+ disk_super -> flags = cpu_to_le32 (cmd -> flags );
628641 disk_super -> mapping_root = cpu_to_le64 (cmd -> root );
629642 disk_super -> hint_root = cpu_to_le64 (cmd -> hint_root );
630643 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,
693706 cmd -> cache_blocks = 0 ;
694707 cmd -> policy_hint_size = policy_hint_size ;
695708 cmd -> changed = true;
709+ cmd -> fail_io = false;
696710
697711 r = __create_persistent_data_objects (cmd , may_format_device );
698712 if (r ) {
@@ -796,7 +810,8 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd)
796810 list_del (& cmd -> list );
797811 mutex_unlock (& table_lock );
798812
799- __destroy_persistent_data_objects (cmd );
813+ if (!cmd -> fail_io )
814+ __destroy_persistent_data_objects (cmd );
800815 kfree (cmd );
801816 }
802817}
@@ -848,13 +863,26 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd,
848863 return 0 ;
849864}
850865
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+
851879int dm_cache_resize (struct dm_cache_metadata * cmd , dm_cblock_t new_cache_size )
852880{
853881 int r ;
854882 bool clean ;
855883 __le64 null_mapping = pack_value (0 , 0 );
856884
857- down_write ( & cmd -> root_lock );
885+ WRITE_LOCK ( cmd );
858886 __dm_bless_for_disk (& null_mapping );
859887
860888 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)
880908 cmd -> changed = true;
881909
882910out :
883- up_write ( & cmd -> root_lock );
911+ WRITE_UNLOCK ( cmd );
884912
885913 return r ;
886914}
@@ -891,7 +919,7 @@ int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
891919{
892920 int r ;
893921
894- down_write ( & cmd -> root_lock );
922+ WRITE_LOCK ( cmd );
895923 r = dm_bitset_resize (& cmd -> discard_info ,
896924 cmd -> discard_root ,
897925 from_dblock (cmd -> discard_nr_blocks ),
@@ -903,7 +931,7 @@ int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
903931 }
904932
905933 cmd -> changed = true;
906- up_write ( & cmd -> root_lock );
934+ WRITE_UNLOCK ( cmd );
907935
908936 return r ;
909937}
@@ -946,9 +974,9 @@ int dm_cache_set_discard(struct dm_cache_metadata *cmd,
946974{
947975 int r ;
948976
949- down_write ( & cmd -> root_lock );
977+ WRITE_LOCK ( cmd );
950978 r = __discard (cmd , dblock , discard );
951- up_write ( & cmd -> root_lock );
979+ WRITE_UNLOCK ( cmd );
952980
953981 return r ;
954982}
@@ -1020,9 +1048,9 @@ int dm_cache_remove_mapping(struct dm_cache_metadata *cmd, dm_cblock_t cblock)
10201048{
10211049 int r ;
10221050
1023- down_write ( & cmd -> root_lock );
1051+ WRITE_LOCK ( cmd );
10241052 r = __remove (cmd , cblock );
1025- up_write ( & cmd -> root_lock );
1053+ WRITE_UNLOCK ( cmd );
10261054
10271055 return r ;
10281056}
@@ -1048,9 +1076,9 @@ int dm_cache_insert_mapping(struct dm_cache_metadata *cmd,
10481076{
10491077 int r ;
10501078
1051- down_write ( & cmd -> root_lock );
1079+ WRITE_LOCK ( cmd );
10521080 r = __insert (cmd , cblock , oblock );
1053- up_write ( & cmd -> root_lock );
1081+ WRITE_UNLOCK ( cmd );
10541082
10551083 return r ;
10561084}
@@ -1234,9 +1262,9 @@ int dm_cache_set_dirty(struct dm_cache_metadata *cmd,
12341262{
12351263 int r ;
12361264
1237- down_write ( & cmd -> root_lock );
1265+ WRITE_LOCK ( cmd );
12381266 r = __dirty (cmd , cblock , dirty );
1239- up_write ( & cmd -> root_lock );
1267+ WRITE_UNLOCK ( cmd );
12401268
12411269 return r ;
12421270}
@@ -1252,9 +1280,9 @@ void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
12521280void dm_cache_metadata_set_stats (struct dm_cache_metadata * cmd ,
12531281 struct dm_cache_statistics * stats )
12541282{
1255- down_write ( & cmd -> root_lock );
1283+ WRITE_LOCK_VOID ( cmd );
12561284 cmd -> stats = * stats ;
1257- up_write ( & cmd -> root_lock );
1285+ WRITE_UNLOCK ( cmd );
12581286}
12591287
12601288int dm_cache_commit (struct dm_cache_metadata * cmd , bool clean_shutdown )
@@ -1263,15 +1291,15 @@ int dm_cache_commit(struct dm_cache_metadata *cmd, bool clean_shutdown)
12631291 flags_mutator mutator = (clean_shutdown ? set_clean_shutdown :
12641292 clear_clean_shutdown );
12651293
1266- down_write ( & cmd -> root_lock );
1294+ WRITE_LOCK ( cmd );
12671295 r = __commit_transaction (cmd , mutator );
12681296 if (r )
12691297 goto out ;
12701298
12711299 r = __begin_transaction (cmd );
12721300
12731301out :
1274- up_write ( & cmd -> root_lock );
1302+ WRITE_UNLOCK ( cmd );
12751303 return r ;
12761304}
12771305
@@ -1376,9 +1404,9 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
13761404{
13771405 int r ;
13781406
1379- down_write ( & cmd -> root_lock );
1407+ WRITE_LOCK ( cmd );
13801408 r = write_hints (cmd , policy );
1381- up_write ( & cmd -> root_lock );
1409+ WRITE_UNLOCK ( cmd );
13821410
13831411 return r ;
13841412}
@@ -1387,3 +1415,70 @@ int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result)
13871415{
13881416 return blocks_are_unmapped_or_clean (cmd , 0 , cmd -> cache_blocks , result );
13891417}
1418+
1419+ void 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+
1426+ void 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+
1433+ int 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+
1456+ out :
1457+ up_write (& cmd -> root_lock );
1458+ return r ;
1459+ }
1460+
1461+ bool 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+
1472+ int 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+ }
0 commit comments