aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-thin-metadata.c
diff options
context:
space:
mode:
authorJoe Thornber <ejt@redhat.com>2012-07-27 10:08:15 -0400
committerAlasdair G Kergon <agk@redhat.com>2012-07-27 10:08:15 -0400
commitda105ed5fd7edcc5e0df7dbacef4dadda74e7ebe (patch)
tree2db9643e499e9bc9d38c7ccc4a00e01d875150c7 /drivers/md/dm-thin-metadata.c
parent12ba58af46e5973822f1cfaaf5f29a2a17a523bf (diff)
dm thin metadata: introduce dm_pool_abort_metadata
Introduce dm_pool_abort_metadata to abort the current metadata transaction. Generally this will only be called when bad things are happening and dm-thin is trying to roll back to a good state for read-only mode. It's complicated by the fact that the metadata device may have failed completely causing the abort to be unable to read the old transaction. In this case the metadata object is placed in a 'fail' mode and everything fails apart from destroying it. Signed-off-by: Joe Thornber <ejt@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-thin-metadata.c')
-rw-r--r--drivers/md/dm-thin-metadata.c207
1 files changed, 146 insertions, 61 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index d30bc09fd7c4..693e149e9727 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2011 Red Hat, Inc. 2 * Copyright (C) 2011-2012 Red Hat, Inc.
3 * 3 *
4 * This file is released under the GPL. 4 * This file is released under the GPL.
5 */ 5 */
@@ -185,6 +185,13 @@ struct dm_pool_metadata {
185 unsigned long flags; 185 unsigned long flags;
186 sector_t data_block_size; 186 sector_t data_block_size;
187 bool read_only:1; 187 bool read_only:1;
188
189 /*
190 * Set if a transaction has to be aborted but the attempt to roll back
191 * to the previous (good) transaction failed. The only pool metadata
192 * operation possible in this state is the closing of the device.
193 */
194 bool fail_io:1;
188}; 195};
189 196
190struct dm_thin_device { 197struct dm_thin_device {
@@ -193,7 +200,8 @@ struct dm_thin_device {
193 dm_thin_id id; 200 dm_thin_id id;
194 201
195 int open_count; 202 int open_count;
196 int changed; 203 bool changed:1;
204 bool aborted_with_changes:1;
197 uint64_t mapped_blocks; 205 uint64_t mapped_blocks;
198 uint64_t transaction_id; 206 uint64_t transaction_id;
199 uint32_t creation_time; 207 uint32_t creation_time;
@@ -731,9 +739,6 @@ static int __write_changed_details(struct dm_pool_metadata *pmd)
731 739
732static int __commit_transaction(struct dm_pool_metadata *pmd) 740static int __commit_transaction(struct dm_pool_metadata *pmd)
733{ 741{
734 /*
735 * FIXME: Associated pool should be made read-only on failure.
736 */
737 int r; 742 int r;
738 size_t metadata_len, data_len; 743 size_t metadata_len, data_len;
739 struct thin_disk_superblock *disk_super; 744 struct thin_disk_superblock *disk_super;
@@ -809,6 +814,7 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
809 pmd->time = 0; 814 pmd->time = 0;
810 INIT_LIST_HEAD(&pmd->thin_devices); 815 INIT_LIST_HEAD(&pmd->thin_devices);
811 pmd->read_only = false; 816 pmd->read_only = false;
817 pmd->fail_io = false;
812 pmd->bdev = bdev; 818 pmd->bdev = bdev;
813 pmd->data_block_size = data_block_size; 819 pmd->data_block_size = data_block_size;
814 820
@@ -851,16 +857,17 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
851 return -EBUSY; 857 return -EBUSY;
852 } 858 }
853 859
854 if (!pmd->read_only) { 860 if (!pmd->read_only && !pmd->fail_io) {
855 r = __commit_transaction(pmd); 861 r = __commit_transaction(pmd);
856 if (r < 0) 862 if (r < 0)
857 DMWARN("%s: __commit_transaction() failed, error = %d", 863 DMWARN("%s: __commit_transaction() failed, error = %d",
858 __func__, r); 864 __func__, r);
859 } 865 }
860 866
861 __destroy_persistent_data_objects(pmd); 867 if (!pmd->fail_io)
862 kfree(pmd); 868 __destroy_persistent_data_objects(pmd);
863 869
870 kfree(pmd);
864 return 0; 871 return 0;
865} 872}
866 873
@@ -921,6 +928,7 @@ static int __open_device(struct dm_pool_metadata *pmd,
921 (*td)->id = dev; 928 (*td)->id = dev;
922 (*td)->open_count = 1; 929 (*td)->open_count = 1;
923 (*td)->changed = changed; 930 (*td)->changed = changed;
931 (*td)->aborted_with_changes = false;
924 (*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks); 932 (*td)->mapped_blocks = le64_to_cpu(details_le.mapped_blocks);
925 (*td)->transaction_id = le64_to_cpu(details_le.transaction_id); 933 (*td)->transaction_id = le64_to_cpu(details_le.transaction_id);
926 (*td)->creation_time = le32_to_cpu(details_le.creation_time); 934 (*td)->creation_time = le32_to_cpu(details_le.creation_time);
@@ -982,10 +990,11 @@ static int __create_thin(struct dm_pool_metadata *pmd,
982 990
983int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev) 991int dm_pool_create_thin(struct dm_pool_metadata *pmd, dm_thin_id dev)
984{ 992{
985 int r; 993 int r = -EINVAL;
986 994
987 down_write(&pmd->root_lock); 995 down_write(&pmd->root_lock);
988 r = __create_thin(pmd, dev); 996 if (!pmd->fail_io)
997 r = __create_thin(pmd, dev);
989 up_write(&pmd->root_lock); 998 up_write(&pmd->root_lock);
990 999
991 return r; 1000 return r;
@@ -1072,10 +1081,11 @@ int dm_pool_create_snap(struct dm_pool_metadata *pmd,
1072 dm_thin_id dev, 1081 dm_thin_id dev,
1073 dm_thin_id origin) 1082 dm_thin_id origin)
1074{ 1083{
1075 int r; 1084 int r = -EINVAL;
1076 1085
1077 down_write(&pmd->root_lock); 1086 down_write(&pmd->root_lock);
1078 r = __create_snap(pmd, dev, origin); 1087 if (!pmd->fail_io)
1088 r = __create_snap(pmd, dev, origin);
1079 up_write(&pmd->root_lock); 1089 up_write(&pmd->root_lock);
1080 1090
1081 return r; 1091 return r;
@@ -1114,10 +1124,11 @@ static int __delete_device(struct dm_pool_metadata *pmd, dm_thin_id dev)
1114int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd, 1124int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
1115 dm_thin_id dev) 1125 dm_thin_id dev)
1116{ 1126{
1117 int r; 1127 int r = -EINVAL;
1118 1128
1119 down_write(&pmd->root_lock); 1129 down_write(&pmd->root_lock);
1120 r = __delete_device(pmd, dev); 1130 if (!pmd->fail_io)
1131 r = __delete_device(pmd, dev);
1121 up_write(&pmd->root_lock); 1132 up_write(&pmd->root_lock);
1122 1133
1123 return r; 1134 return r;
@@ -1127,27 +1138,40 @@ int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
1127 uint64_t current_id, 1138 uint64_t current_id,
1128 uint64_t new_id) 1139 uint64_t new_id)
1129{ 1140{
1141 int r = -EINVAL;
1142
1130 down_write(&pmd->root_lock); 1143 down_write(&pmd->root_lock);
1144
1145 if (pmd->fail_io)
1146 goto out;
1147
1131 if (pmd->trans_id != current_id) { 1148 if (pmd->trans_id != current_id) {
1132 up_write(&pmd->root_lock);
1133 DMERR("mismatched transaction id"); 1149 DMERR("mismatched transaction id");
1134 return -EINVAL; 1150 goto out;
1135 } 1151 }
1136 1152
1137 pmd->trans_id = new_id; 1153 pmd->trans_id = new_id;
1154 r = 0;
1155
1156out:
1138 up_write(&pmd->root_lock); 1157 up_write(&pmd->root_lock);
1139 1158
1140 return 0; 1159 return r;
1141} 1160}
1142 1161
1143int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd, 1162int dm_pool_get_metadata_transaction_id(struct dm_pool_metadata *pmd,
1144 uint64_t *result) 1163 uint64_t *result)
1145{ 1164{
1165 int r = -EINVAL;
1166
1146 down_read(&pmd->root_lock); 1167 down_read(&pmd->root_lock);
1147 *result = pmd->trans_id; 1168 if (!pmd->fail_io) {
1169 *result = pmd->trans_id;
1170 r = 0;
1171 }
1148 up_read(&pmd->root_lock); 1172 up_read(&pmd->root_lock);
1149 1173
1150 return 0; 1174 return r;
1151} 1175}
1152 1176
1153static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) 1177static int __reserve_metadata_snap(struct dm_pool_metadata *pmd)
@@ -1211,10 +1235,11 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd)
1211 1235
1212int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd) 1236int dm_pool_reserve_metadata_snap(struct dm_pool_metadata *pmd)
1213{ 1237{
1214 int r; 1238 int r = -EINVAL;
1215 1239
1216 down_write(&pmd->root_lock); 1240 down_write(&pmd->root_lock);
1217 r = __reserve_metadata_snap(pmd); 1241 if (!pmd->fail_io)
1242 r = __reserve_metadata_snap(pmd);
1218 up_write(&pmd->root_lock); 1243 up_write(&pmd->root_lock);
1219 1244
1220 return r; 1245 return r;
@@ -1256,10 +1281,11 @@ static int __release_metadata_snap(struct dm_pool_metadata *pmd)
1256 1281
1257int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd) 1282int dm_pool_release_metadata_snap(struct dm_pool_metadata *pmd)
1258{ 1283{
1259 int r; 1284 int r = -EINVAL;
1260 1285
1261 down_write(&pmd->root_lock); 1286 down_write(&pmd->root_lock);
1262 r = __release_metadata_snap(pmd); 1287 if (!pmd->fail_io)
1288 r = __release_metadata_snap(pmd);
1263 up_write(&pmd->root_lock); 1289 up_write(&pmd->root_lock);
1264 1290
1265 return r; 1291 return r;
@@ -1286,10 +1312,11 @@ static int __get_metadata_snap(struct dm_pool_metadata *pmd,
1286int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd, 1312int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd,
1287 dm_block_t *result) 1313 dm_block_t *result)
1288{ 1314{
1289 int r; 1315 int r = -EINVAL;
1290 1316
1291 down_read(&pmd->root_lock); 1317 down_read(&pmd->root_lock);
1292 r = __get_metadata_snap(pmd, result); 1318 if (!pmd->fail_io)
1319 r = __get_metadata_snap(pmd, result);
1293 up_read(&pmd->root_lock); 1320 up_read(&pmd->root_lock);
1294 1321
1295 return r; 1322 return r;
@@ -1298,10 +1325,11 @@ int dm_pool_get_metadata_snap(struct dm_pool_metadata *pmd,
1298int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev, 1325int dm_pool_open_thin_device(struct dm_pool_metadata *pmd, dm_thin_id dev,
1299 struct dm_thin_device **td) 1326 struct dm_thin_device **td)
1300{ 1327{
1301 int r; 1328 int r = -EINVAL;
1302 1329
1303 down_write(&pmd->root_lock); 1330 down_write(&pmd->root_lock);
1304 r = __open_device(pmd, dev, 0, td); 1331 if (!pmd->fail_io)
1332 r = __open_device(pmd, dev, 0, td);
1305 up_write(&pmd->root_lock); 1333 up_write(&pmd->root_lock);
1306 1334
1307 return r; 1335 return r;
@@ -1329,28 +1357,31 @@ static bool __snapshotted_since(struct dm_thin_device *td, uint32_t time)
1329int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block, 1357int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
1330 int can_block, struct dm_thin_lookup_result *result) 1358 int can_block, struct dm_thin_lookup_result *result)
1331{ 1359{
1332 int r; 1360 int r = -EINVAL;
1333 uint64_t block_time = 0; 1361 uint64_t block_time = 0;
1334 __le64 value; 1362 __le64 value;
1335 struct dm_pool_metadata *pmd = td->pmd; 1363 struct dm_pool_metadata *pmd = td->pmd;
1336 dm_block_t keys[2] = { td->id, block }; 1364 dm_block_t keys[2] = { td->id, block };
1365 struct dm_btree_info *info;
1337 1366
1338 if (can_block) { 1367 if (can_block) {
1339 down_read(&pmd->root_lock); 1368 down_read(&pmd->root_lock);
1340 r = dm_btree_lookup(&pmd->info, pmd->root, keys, &value); 1369 info = &pmd->info;
1341 if (!r) 1370 } else if (down_read_trylock(&pmd->root_lock))
1342 block_time = le64_to_cpu(value); 1371 info = &pmd->nb_info;
1343 up_read(&pmd->root_lock); 1372 else
1344
1345 } else if (down_read_trylock(&pmd->root_lock)) {
1346 r = dm_btree_lookup(&pmd->nb_info, pmd->root, keys, &value);
1347 if (!r)
1348 block_time = le64_to_cpu(value);
1349 up_read(&pmd->root_lock);
1350
1351 } else
1352 return -EWOULDBLOCK; 1373 return -EWOULDBLOCK;
1353 1374
1375 if (pmd->fail_io)
1376 goto out;
1377
1378 r = dm_btree_lookup(info, pmd->root, keys, &value);
1379 if (!r)
1380 block_time = le64_to_cpu(value);
1381
1382out:
1383 up_read(&pmd->root_lock);
1384
1354 if (!r) { 1385 if (!r) {
1355 dm_block_t exception_block; 1386 dm_block_t exception_block;
1356 uint32_t exception_time; 1387 uint32_t exception_time;
@@ -1389,10 +1420,11 @@ static int __insert(struct dm_thin_device *td, dm_block_t block,
1389int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block, 1420int dm_thin_insert_block(struct dm_thin_device *td, dm_block_t block,
1390 dm_block_t data_block) 1421 dm_block_t data_block)
1391{ 1422{
1392 int r; 1423 int r = -EINVAL;
1393 1424
1394 down_write(&td->pmd->root_lock); 1425 down_write(&td->pmd->root_lock);
1395 r = __insert(td, block, data_block); 1426 if (!td->pmd->fail_io)
1427 r = __insert(td, block, data_block);
1396 up_write(&td->pmd->root_lock); 1428 up_write(&td->pmd->root_lock);
1397 1429
1398 return r; 1430 return r;
@@ -1416,10 +1448,11 @@ static int __remove(struct dm_thin_device *td, dm_block_t block)
1416 1448
1417int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block) 1449int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block)
1418{ 1450{
1419 int r; 1451 int r = -EINVAL;
1420 1452
1421 down_write(&td->pmd->root_lock); 1453 down_write(&td->pmd->root_lock);
1422 r = __remove(td, block); 1454 if (!td->pmd->fail_io)
1455 r = __remove(td, block);
1423 up_write(&td->pmd->root_lock); 1456 up_write(&td->pmd->root_lock);
1424 1457
1425 return r; 1458 return r;
@@ -1436,12 +1469,24 @@ bool dm_thin_changed_this_transaction(struct dm_thin_device *td)
1436 return r; 1469 return r;
1437} 1470}
1438 1471
1472bool dm_thin_aborted_changes(struct dm_thin_device *td)
1473{
1474 bool r;
1475
1476 down_read(&td->pmd->root_lock);
1477 r = td->aborted_with_changes;
1478 up_read(&td->pmd->root_lock);
1479
1480 return r;
1481}
1482
1439int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result) 1483int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
1440{ 1484{
1441 int r; 1485 int r = -EINVAL;
1442 1486
1443 down_write(&pmd->root_lock); 1487 down_write(&pmd->root_lock);
1444 r = dm_sm_new_block(pmd->data_sm, result); 1488 if (!pmd->fail_io)
1489 r = dm_sm_new_block(pmd->data_sm, result);
1445 up_write(&pmd->root_lock); 1490 up_write(&pmd->root_lock);
1446 1491
1447 return r; 1492 return r;
@@ -1449,9 +1494,11 @@ int dm_pool_alloc_data_block(struct dm_pool_metadata *pmd, dm_block_t *result)
1449 1494
1450int dm_pool_commit_metadata(struct dm_pool_metadata *pmd) 1495int dm_pool_commit_metadata(struct dm_pool_metadata *pmd)
1451{ 1496{
1452 int r; 1497 int r = -EINVAL;
1453 1498
1454 down_write(&pmd->root_lock); 1499 down_write(&pmd->root_lock);
1500 if (pmd->fail_io)
1501 goto out;
1455 1502
1456 r = __commit_transaction(pmd); 1503 r = __commit_transaction(pmd);
1457 if (r <= 0) 1504 if (r <= 0)
@@ -1466,12 +1513,41 @@ out:
1466 return r; 1513 return r;
1467} 1514}
1468 1515
1516static void __set_abort_with_changes_flags(struct dm_pool_metadata *pmd)
1517{
1518 struct dm_thin_device *td;
1519
1520 list_for_each_entry(td, &pmd->thin_devices, list)
1521 td->aborted_with_changes = td->changed;
1522}
1523
1524int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
1525{
1526 int r = -EINVAL;
1527
1528 down_write(&pmd->root_lock);
1529 if (pmd->fail_io)
1530 goto out;
1531
1532 __set_abort_with_changes_flags(pmd);
1533 __destroy_persistent_data_objects(pmd);
1534 r = __create_persistent_data_objects(pmd, false);
1535 if (r)
1536 pmd->fail_io = true;
1537
1538out:
1539 up_write(&pmd->root_lock);
1540
1541 return r;
1542}
1543
1469int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result) 1544int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *result)
1470{ 1545{
1471 int r; 1546 int r = -EINVAL;
1472 1547
1473 down_read(&pmd->root_lock); 1548 down_read(&pmd->root_lock);
1474 r = dm_sm_get_nr_free(pmd->data_sm, result); 1549 if (!pmd->fail_io)
1550 r = dm_sm_get_nr_free(pmd->data_sm, result);
1475 up_read(&pmd->root_lock); 1551 up_read(&pmd->root_lock);
1476 1552
1477 return r; 1553 return r;
@@ -1480,10 +1556,11 @@ int dm_pool_get_free_block_count(struct dm_pool_metadata *pmd, dm_block_t *resul
1480int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd, 1556int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
1481 dm_block_t *result) 1557 dm_block_t *result)
1482{ 1558{
1483 int r; 1559 int r = -EINVAL;
1484 1560
1485 down_read(&pmd->root_lock); 1561 down_read(&pmd->root_lock);
1486 r = dm_sm_get_nr_free(pmd->metadata_sm, result); 1562 if (!pmd->fail_io)
1563 r = dm_sm_get_nr_free(pmd->metadata_sm, result);
1487 up_read(&pmd->root_lock); 1564 up_read(&pmd->root_lock);
1488 1565
1489 return r; 1566 return r;
@@ -1492,10 +1569,11 @@ int dm_pool_get_free_metadata_block_count(struct dm_pool_metadata *pmd,
1492int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd, 1569int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
1493 dm_block_t *result) 1570 dm_block_t *result)
1494{ 1571{
1495 int r; 1572 int r = -EINVAL;
1496 1573
1497 down_read(&pmd->root_lock); 1574 down_read(&pmd->root_lock);
1498 r = dm_sm_get_nr_blocks(pmd->metadata_sm, result); 1575 if (!pmd->fail_io)
1576 r = dm_sm_get_nr_blocks(pmd->metadata_sm, result);
1499 up_read(&pmd->root_lock); 1577 up_read(&pmd->root_lock);
1500 1578
1501 return r; 1579 return r;
@@ -1512,10 +1590,11 @@ int dm_pool_get_data_block_size(struct dm_pool_metadata *pmd, sector_t *result)
1512 1590
1513int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result) 1591int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result)
1514{ 1592{
1515 int r; 1593 int r = -EINVAL;
1516 1594
1517 down_read(&pmd->root_lock); 1595 down_read(&pmd->root_lock);
1518 r = dm_sm_get_nr_blocks(pmd->data_sm, result); 1596 if (!pmd->fail_io)
1597 r = dm_sm_get_nr_blocks(pmd->data_sm, result);
1519 up_read(&pmd->root_lock); 1598 up_read(&pmd->root_lock);
1520 1599
1521 return r; 1600 return r;
@@ -1523,13 +1602,17 @@ int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result)
1523 1602
1524int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result) 1603int dm_thin_get_mapped_count(struct dm_thin_device *td, dm_block_t *result)
1525{ 1604{
1605 int r = -EINVAL;
1526 struct dm_pool_metadata *pmd = td->pmd; 1606 struct dm_pool_metadata *pmd = td->pmd;
1527 1607
1528 down_read(&pmd->root_lock); 1608 down_read(&pmd->root_lock);
1529 *result = td->mapped_blocks; 1609 if (!pmd->fail_io) {
1610 *result = td->mapped_blocks;
1611 r = 0;
1612 }
1530 up_read(&pmd->root_lock); 1613 up_read(&pmd->root_lock);
1531 1614
1532 return 0; 1615 return r;
1533} 1616}
1534 1617
1535static int __highest_block(struct dm_thin_device *td, dm_block_t *result) 1618static int __highest_block(struct dm_thin_device *td, dm_block_t *result)
@@ -1551,11 +1634,12 @@ static int __highest_block(struct dm_thin_device *td, dm_block_t *result)
1551int dm_thin_get_highest_mapped_block(struct dm_thin_device *td, 1634int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
1552 dm_block_t *result) 1635 dm_block_t *result)
1553{ 1636{
1554 int r; 1637 int r = -EINVAL;
1555 struct dm_pool_metadata *pmd = td->pmd; 1638 struct dm_pool_metadata *pmd = td->pmd;
1556 1639
1557 down_read(&pmd->root_lock); 1640 down_read(&pmd->root_lock);
1558 r = __highest_block(td, result); 1641 if (!pmd->fail_io)
1642 r = __highest_block(td, result);
1559 up_read(&pmd->root_lock); 1643 up_read(&pmd->root_lock);
1560 1644
1561 return r; 1645 return r;
@@ -1583,10 +1667,11 @@ static int __resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
1583 1667
1584int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count) 1668int dm_pool_resize_data_dev(struct dm_pool_metadata *pmd, dm_block_t new_count)
1585{ 1669{
1586 int r; 1670 int r = -EINVAL;
1587 1671
1588 down_write(&pmd->root_lock); 1672 down_write(&pmd->root_lock);
1589 r = __resize_data_dev(pmd, new_count); 1673 if (!pmd->fail_io)
1674 r = __resize_data_dev(pmd, new_count);
1590 up_write(&pmd->root_lock); 1675 up_write(&pmd->root_lock);
1591 1676
1592 return r; 1677 return r;