aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-thin-metadata.c207
-rw-r--r--drivers/md/dm-thin-metadata.h12
2 files changed, 158 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;
diff --git a/drivers/md/dm-thin-metadata.h b/drivers/md/dm-thin-metadata.h
index 2bbe622f299d..0cecc3702885 100644
--- a/drivers/md/dm-thin-metadata.h
+++ b/drivers/md/dm-thin-metadata.h
@@ -80,6 +80,16 @@ int dm_pool_delete_thin_device(struct dm_pool_metadata *pmd,
80int dm_pool_commit_metadata(struct dm_pool_metadata *pmd); 80int dm_pool_commit_metadata(struct dm_pool_metadata *pmd);
81 81
82/* 82/*
83 * Discards all uncommitted changes. Rereads the superblock, rolling back
84 * to the last good transaction. Thin devices remain open.
85 * dm_thin_aborted_changes() tells you if they had uncommitted changes.
86 *
87 * If this call fails it's only useful to call dm_pool_metadata_close().
88 * All other methods will fail with -EINVAL.
89 */
90int dm_pool_abort_metadata(struct dm_pool_metadata *pmd);
91
92/*
83 * Set/get userspace transaction id. 93 * Set/get userspace transaction id.
84 */ 94 */
85int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd, 95int dm_pool_set_metadata_transaction_id(struct dm_pool_metadata *pmd,
@@ -150,6 +160,8 @@ int dm_thin_remove_block(struct dm_thin_device *td, dm_block_t block);
150 */ 160 */
151bool dm_thin_changed_this_transaction(struct dm_thin_device *td); 161bool dm_thin_changed_this_transaction(struct dm_thin_device *td);
152 162
163bool dm_thin_aborted_changes(struct dm_thin_device *td);
164
153int dm_thin_get_highest_mapped_block(struct dm_thin_device *td, 165int dm_thin_get_highest_mapped_block(struct dm_thin_device *td,
154 dm_block_t *highest_mapped); 166 dm_block_t *highest_mapped);
155 167