aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2016-03-10 11:20:58 -0500
committerMike Snitzer <snitzer@redhat.com>2016-03-10 17:12:12 -0500
commitd14fcf3dd79c0b8a8d0ba469c44a6b04f3a1403b (patch)
tree077898b2913e1b3d330317129ac91015d01bff12 /drivers/md
parent3f0680402c2d0da58a8b06f7e55d387591b55e61 (diff)
dm cache: make sure every metadata function checks fail_io
Otherwise operations may be attempted that will only ever go on to crash (since the metadata device is either missing or unreliable if 'fail_io' is set). Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-cache-metadata.c98
-rw-r--r--drivers/md/dm-cache-metadata.h4
-rw-r--r--drivers/md/dm-cache-target.c12
3 files changed, 71 insertions, 43 deletions
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index f6543f3a970f..27f2ef300f8b 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -867,19 +867,40 @@ static int blocks_are_unmapped_or_clean(struct dm_cache_metadata *cmd,
867 return 0; 867 return 0;
868} 868}
869 869
870#define WRITE_LOCK(cmd) \ 870#define WRITE_LOCK(cmd) \
871 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \ 871 down_write(&cmd->root_lock); \
872 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
873 up_write(&cmd->root_lock); \
872 return -EINVAL; \ 874 return -EINVAL; \
873 down_write(&cmd->root_lock) 875 }
874 876
875#define WRITE_LOCK_VOID(cmd) \ 877#define WRITE_LOCK_VOID(cmd) \
876 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) \ 878 down_write(&cmd->root_lock); \
879 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
880 up_write(&cmd->root_lock); \
877 return; \ 881 return; \
878 down_write(&cmd->root_lock) 882 }
879 883
880#define WRITE_UNLOCK(cmd) \ 884#define WRITE_UNLOCK(cmd) \
881 up_write(&cmd->root_lock) 885 up_write(&cmd->root_lock)
882 886
887#define READ_LOCK(cmd) \
888 down_read(&cmd->root_lock); \
889 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
890 up_read(&cmd->root_lock); \
891 return -EINVAL; \
892 }
893
894#define READ_LOCK_VOID(cmd) \
895 down_read(&cmd->root_lock); \
896 if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) { \
897 up_read(&cmd->root_lock); \
898 return; \
899 }
900
901#define READ_UNLOCK(cmd) \
902 up_read(&cmd->root_lock)
903
883int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size) 904int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size)
884{ 905{
885 int r; 906 int r;
@@ -1015,22 +1036,20 @@ int dm_cache_load_discards(struct dm_cache_metadata *cmd,
1015{ 1036{
1016 int r; 1037 int r;
1017 1038
1018 down_read(&cmd->root_lock); 1039 READ_LOCK(cmd);
1019 r = __load_discards(cmd, fn, context); 1040 r = __load_discards(cmd, fn, context);
1020 up_read(&cmd->root_lock); 1041 READ_UNLOCK(cmd);
1021 1042
1022 return r; 1043 return r;
1023} 1044}
1024 1045
1025dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd) 1046int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result)
1026{ 1047{
1027 dm_cblock_t r; 1048 READ_LOCK(cmd);
1049 *result = cmd->cache_blocks;
1050 READ_UNLOCK(cmd);
1028 1051
1029 down_read(&cmd->root_lock); 1052 return 0;
1030 r = cmd->cache_blocks;
1031 up_read(&cmd->root_lock);
1032
1033 return r;
1034} 1053}
1035 1054
1036static int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock) 1055static int __remove(struct dm_cache_metadata *cmd, dm_cblock_t cblock)
@@ -1188,9 +1207,9 @@ int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
1188{ 1207{
1189 int r; 1208 int r;
1190 1209
1191 down_read(&cmd->root_lock); 1210 READ_LOCK(cmd);
1192 r = __load_mappings(cmd, policy, fn, context); 1211 r = __load_mappings(cmd, policy, fn, context);
1193 up_read(&cmd->root_lock); 1212 READ_UNLOCK(cmd);
1194 1213
1195 return r; 1214 return r;
1196} 1215}
@@ -1215,18 +1234,18 @@ static int __dump_mappings(struct dm_cache_metadata *cmd)
1215 1234
1216void dm_cache_dump(struct dm_cache_metadata *cmd) 1235void dm_cache_dump(struct dm_cache_metadata *cmd)
1217{ 1236{
1218 down_read(&cmd->root_lock); 1237 READ_LOCK_VOID(cmd);
1219 __dump_mappings(cmd); 1238 __dump_mappings(cmd);
1220 up_read(&cmd->root_lock); 1239 READ_UNLOCK(cmd);
1221} 1240}
1222 1241
1223int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd) 1242int dm_cache_changed_this_transaction(struct dm_cache_metadata *cmd)
1224{ 1243{
1225 int r; 1244 int r;
1226 1245
1227 down_read(&cmd->root_lock); 1246 READ_LOCK(cmd);
1228 r = cmd->changed; 1247 r = cmd->changed;
1229 up_read(&cmd->root_lock); 1248 READ_UNLOCK(cmd);
1230 1249
1231 return r; 1250 return r;
1232} 1251}
@@ -1276,9 +1295,9 @@ int dm_cache_set_dirty(struct dm_cache_metadata *cmd,
1276void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd, 1295void dm_cache_metadata_get_stats(struct dm_cache_metadata *cmd,
1277 struct dm_cache_statistics *stats) 1296 struct dm_cache_statistics *stats)
1278{ 1297{
1279 down_read(&cmd->root_lock); 1298 READ_LOCK_VOID(cmd);
1280 *stats = cmd->stats; 1299 *stats = cmd->stats;
1281 up_read(&cmd->root_lock); 1300 READ_UNLOCK(cmd);
1282} 1301}
1283 1302
1284void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd, 1303void dm_cache_metadata_set_stats(struct dm_cache_metadata *cmd,
@@ -1312,9 +1331,9 @@ int dm_cache_get_free_metadata_block_count(struct dm_cache_metadata *cmd,
1312{ 1331{
1313 int r = -EINVAL; 1332 int r = -EINVAL;
1314 1333
1315 down_read(&cmd->root_lock); 1334 READ_LOCK(cmd);
1316 r = dm_sm_get_nr_free(cmd->metadata_sm, result); 1335 r = dm_sm_get_nr_free(cmd->metadata_sm, result);
1317 up_read(&cmd->root_lock); 1336 READ_UNLOCK(cmd);
1318 1337
1319 return r; 1338 return r;
1320} 1339}
@@ -1324,9 +1343,9 @@ int dm_cache_get_metadata_dev_size(struct dm_cache_metadata *cmd,
1324{ 1343{
1325 int r = -EINVAL; 1344 int r = -EINVAL;
1326 1345
1327 down_read(&cmd->root_lock); 1346 READ_LOCK(cmd);
1328 r = dm_sm_get_nr_blocks(cmd->metadata_sm, result); 1347 r = dm_sm_get_nr_blocks(cmd->metadata_sm, result);
1329 up_read(&cmd->root_lock); 1348 READ_UNLOCK(cmd);
1330 1349
1331 return r; 1350 return r;
1332} 1351}
@@ -1417,7 +1436,13 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
1417 1436
1418int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result) 1437int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result)
1419{ 1438{
1420 return blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result); 1439 int r;
1440
1441 READ_LOCK(cmd);
1442 r = blocks_are_unmapped_or_clean(cmd, 0, cmd->cache_blocks, result);
1443 READ_UNLOCK(cmd);
1444
1445 return r;
1421} 1446}
1422 1447
1423void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd) 1448void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd)
@@ -1440,10 +1465,7 @@ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd)
1440 struct dm_block *sblock; 1465 struct dm_block *sblock;
1441 struct cache_disk_superblock *disk_super; 1466 struct cache_disk_superblock *disk_super;
1442 1467
1443 /* 1468 WRITE_LOCK(cmd);
1444 * We ignore fail_io for this function.
1445 */
1446 down_write(&cmd->root_lock);
1447 set_bit(NEEDS_CHECK, &cmd->flags); 1469 set_bit(NEEDS_CHECK, &cmd->flags);
1448 1470
1449 r = superblock_lock(cmd, &sblock); 1471 r = superblock_lock(cmd, &sblock);
@@ -1458,19 +1480,17 @@ int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd)
1458 dm_bm_unlock(sblock); 1480 dm_bm_unlock(sblock);
1459 1481
1460out: 1482out:
1461 up_write(&cmd->root_lock); 1483 WRITE_UNLOCK(cmd);
1462 return r; 1484 return r;
1463} 1485}
1464 1486
1465bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd) 1487int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result)
1466{ 1488{
1467 bool needs_check; 1489 READ_LOCK(cmd);
1490 *result = !!test_bit(NEEDS_CHECK, &cmd->flags);
1491 READ_UNLOCK(cmd);
1468 1492
1469 down_read(&cmd->root_lock); 1493 return 0;
1470 needs_check = !!test_bit(NEEDS_CHECK, &cmd->flags);
1471 up_read(&cmd->root_lock);
1472
1473 return needs_check;
1474} 1494}
1475 1495
1476int dm_cache_metadata_abort(struct dm_cache_metadata *cmd) 1496int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h
index 2ffee21f318d..8528744195e5 100644
--- a/drivers/md/dm-cache-metadata.h
+++ b/drivers/md/dm-cache-metadata.h
@@ -66,7 +66,7 @@ void dm_cache_metadata_close(struct dm_cache_metadata *cmd);
66 * origin blocks to map to. 66 * origin blocks to map to.
67 */ 67 */
68int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size); 68int dm_cache_resize(struct dm_cache_metadata *cmd, dm_cblock_t new_cache_size);
69dm_cblock_t dm_cache_size(struct dm_cache_metadata *cmd); 69int dm_cache_size(struct dm_cache_metadata *cmd, dm_cblock_t *result);
70 70
71int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd, 71int dm_cache_discard_bitset_resize(struct dm_cache_metadata *cmd,
72 sector_t discard_block_size, 72 sector_t discard_block_size,
@@ -137,7 +137,7 @@ int dm_cache_write_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *
137 */ 137 */
138int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result); 138int dm_cache_metadata_all_clean(struct dm_cache_metadata *cmd, bool *result);
139 139
140bool dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd); 140int dm_cache_metadata_needs_check(struct dm_cache_metadata *cmd, bool *result);
141int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd); 141int dm_cache_metadata_set_needs_check(struct dm_cache_metadata *cmd);
142void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd); 142void dm_cache_metadata_set_read_only(struct dm_cache_metadata *cmd);
143void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd); 143void dm_cache_metadata_set_read_write(struct dm_cache_metadata *cmd);
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 2238d6f484fe..43d9e9a39f81 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -984,9 +984,14 @@ static void notify_mode_switch(struct cache *cache, enum cache_metadata_mode mod
984 984
985static void set_cache_mode(struct cache *cache, enum cache_metadata_mode new_mode) 985static void set_cache_mode(struct cache *cache, enum cache_metadata_mode new_mode)
986{ 986{
987 bool needs_check = dm_cache_metadata_needs_check(cache->cmd); 987 bool needs_check;
988 enum cache_metadata_mode old_mode = get_cache_mode(cache); 988 enum cache_metadata_mode old_mode = get_cache_mode(cache);
989 989
990 if (dm_cache_metadata_needs_check(cache->cmd, &needs_check)) {
991 DMERR("unable to read needs_check flag, setting failure mode");
992 new_mode = CM_FAIL;
993 }
994
990 if (new_mode == CM_WRITE && needs_check) { 995 if (new_mode == CM_WRITE && needs_check) {
991 DMERR("%s: unable to switch cache to write mode until repaired.", 996 DMERR("%s: unable to switch cache to write mode until repaired.",
992 cache_device_name(cache)); 997 cache_device_name(cache));
@@ -3510,6 +3515,7 @@ static void cache_status(struct dm_target *ti, status_type_t type,
3510 char buf[BDEVNAME_SIZE]; 3515 char buf[BDEVNAME_SIZE];
3511 struct cache *cache = ti->private; 3516 struct cache *cache = ti->private;
3512 dm_cblock_t residency; 3517 dm_cblock_t residency;
3518 bool needs_check;
3513 3519
3514 switch (type) { 3520 switch (type) {
3515 case STATUSTYPE_INFO: 3521 case STATUSTYPE_INFO:
@@ -3583,7 +3589,9 @@ static void cache_status(struct dm_target *ti, status_type_t type,
3583 else 3589 else
3584 DMEMIT("rw "); 3590 DMEMIT("rw ");
3585 3591
3586 if (dm_cache_metadata_needs_check(cache->cmd)) 3592 r = dm_cache_metadata_needs_check(cache->cmd, &needs_check);
3593
3594 if (r || needs_check)
3587 DMEMIT("needs_check "); 3595 DMEMIT("needs_check ");
3588 else 3596 else
3589 DMEMIT("- "); 3597 DMEMIT("- ");