diff options
Diffstat (limited to 'drivers/md/dm-thin-metadata.c')
-rw-r--r-- | drivers/md/dm-thin-metadata.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c index 1fa45695b68a..c219a053c7f6 100644 --- a/drivers/md/dm-thin-metadata.c +++ b/drivers/md/dm-thin-metadata.c | |||
@@ -1207,6 +1207,12 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd) | |||
1207 | dm_block_t held_root; | 1207 | dm_block_t held_root; |
1208 | 1208 | ||
1209 | /* | 1209 | /* |
1210 | * We commit to ensure the btree roots which we increment in a | ||
1211 | * moment are up to date. | ||
1212 | */ | ||
1213 | __commit_transaction(pmd); | ||
1214 | |||
1215 | /* | ||
1210 | * Copy the superblock. | 1216 | * Copy the superblock. |
1211 | */ | 1217 | */ |
1212 | dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); | 1218 | dm_sm_inc_block(pmd->metadata_sm, THIN_SUPERBLOCK_LOCATION); |
@@ -1538,7 +1544,7 @@ static int __remove(struct dm_thin_device *td, dm_block_t block) | |||
1538 | static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end) | 1544 | static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end) |
1539 | { | 1545 | { |
1540 | int r; | 1546 | int r; |
1541 | unsigned count; | 1547 | unsigned count, total_count = 0; |
1542 | struct dm_pool_metadata *pmd = td->pmd; | 1548 | struct dm_pool_metadata *pmd = td->pmd; |
1543 | dm_block_t keys[1] = { td->id }; | 1549 | dm_block_t keys[1] = { td->id }; |
1544 | __le64 value; | 1550 | __le64 value; |
@@ -1561,11 +1567,29 @@ static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_ | |||
1561 | if (r) | 1567 | if (r) |
1562 | return r; | 1568 | return r; |
1563 | 1569 | ||
1564 | r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count); | 1570 | /* |
1565 | if (r) | 1571 | * Remove leaves stops at the first unmapped entry, so we have to |
1566 | return r; | 1572 | * loop round finding mapped ranges. |
1573 | */ | ||
1574 | while (begin < end) { | ||
1575 | r = dm_btree_lookup_next(&pmd->bl_info, mapping_root, &begin, &begin, &value); | ||
1576 | if (r == -ENODATA) | ||
1577 | break; | ||
1578 | |||
1579 | if (r) | ||
1580 | return r; | ||
1581 | |||
1582 | if (begin >= end) | ||
1583 | break; | ||
1584 | |||
1585 | r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count); | ||
1586 | if (r) | ||
1587 | return r; | ||
1588 | |||
1589 | total_count += count; | ||
1590 | } | ||
1567 | 1591 | ||
1568 | td->mapped_blocks -= count; | 1592 | td->mapped_blocks -= total_count; |
1569 | td->changed = 1; | 1593 | td->changed = 1; |
1570 | 1594 | ||
1571 | /* | 1595 | /* |