aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 0671f5b77eb8..e990d2d1ba4a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1738,39 +1738,45 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
1738 return ret; 1738 return ret;
1739} 1739}
1740 1740
1741static void btrfs_issue_discard(struct block_device *bdev, 1741static int btrfs_issue_discard(struct block_device *bdev,
1742 u64 start, u64 len) 1742 u64 start, u64 len)
1743{ 1743{
1744 blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0); 1744 return blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0);
1745} 1745}
1746 1746
1747static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, 1747static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
1748 u64 num_bytes) 1748 u64 num_bytes, u64 *actual_bytes)
1749{ 1749{
1750 int ret; 1750 int ret;
1751 u64 map_length = num_bytes; 1751 u64 discarded_bytes = 0;
1752 struct btrfs_multi_bio *multi = NULL; 1752 struct btrfs_multi_bio *multi = NULL;
1753 1753
1754 if (!btrfs_test_opt(root, DISCARD))
1755 return 0;
1756 1754
1757 /* Tell the block device(s) that the sectors can be discarded */ 1755 /* Tell the block device(s) that the sectors can be discarded */
1758 ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, 1756 ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD,
1759 bytenr, &map_length, &multi, 0); 1757 bytenr, &num_bytes, &multi, 0);
1760 if (!ret) { 1758 if (!ret) {
1761 struct btrfs_bio_stripe *stripe = multi->stripes; 1759 struct btrfs_bio_stripe *stripe = multi->stripes;
1762 int i; 1760 int i;
1763 1761
1764 if (map_length > num_bytes)
1765 map_length = num_bytes;
1766 1762
1767 for (i = 0; i < multi->num_stripes; i++, stripe++) { 1763 for (i = 0; i < multi->num_stripes; i++, stripe++) {
1768 btrfs_issue_discard(stripe->dev->bdev, 1764 ret = btrfs_issue_discard(stripe->dev->bdev,
1769 stripe->physical, 1765 stripe->physical,
1770 map_length); 1766 stripe->length);
1767 if (!ret)
1768 discarded_bytes += stripe->length;
1769 else if (ret != -EOPNOTSUPP)
1770 break;
1771 } 1771 }
1772 kfree(multi); 1772 kfree(multi);
1773 } 1773 }
1774 if (discarded_bytes && ret == -EOPNOTSUPP)
1775 ret = 0;
1776
1777 if (actual_bytes)
1778 *actual_bytes = discarded_bytes;
1779
1774 1780
1775 return ret; 1781 return ret;
1776} 1782}
@@ -4371,7 +4377,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
4371 if (ret) 4377 if (ret)
4372 break; 4378 break;
4373 4379
4374 ret = btrfs_discard_extent(root, start, end + 1 - start); 4380 if (btrfs_test_opt(root, DISCARD))
4381 ret = btrfs_discard_extent(root, start,
4382 end + 1 - start, NULL);
4375 4383
4376 clear_extent_dirty(unpin, start, end, GFP_NOFS); 4384 clear_extent_dirty(unpin, start, end, GFP_NOFS);
4377 unpin_extent_range(root, start, end); 4385 unpin_extent_range(root, start, end);
@@ -5427,7 +5435,8 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len)
5427 return -ENOSPC; 5435 return -ENOSPC;
5428 } 5436 }
5429 5437
5430 ret = btrfs_discard_extent(root, start, len); 5438 if (btrfs_test_opt(root, DISCARD))
5439 ret = btrfs_discard_extent(root, start, len, NULL);
5431 5440
5432 btrfs_add_free_space(cache, start, len); 5441 btrfs_add_free_space(cache, start, len);
5433 btrfs_update_reserved_bytes(cache, len, 0, 1); 5442 btrfs_update_reserved_bytes(cache, len, 0, 1);
@@ -8765,7 +8774,7 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
8765} 8774}
8766 8775
8767int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, 8776int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
8768 u64 num_bytes) 8777 u64 num_bytes, u64 *actual_bytes)
8769{ 8778{
8770 return btrfs_discard_extent(root, bytenr, num_bytes); 8779 return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes);
8771} 8780}