diff options
author | Li Dongyang <lidongyang@novell.com> | 2011-03-24 06:24:27 -0400 |
---|---|---|
committer | root <Chris Mason chris.mason@oracle.com> | 2011-03-28 05:37:46 -0400 |
commit | 5378e60734f5b7bfe1b43dc191aaf6131c1befe7 (patch) | |
tree | b02c78e744a2a148b60a9c8046abef3f4381f544 /fs/btrfs/extent-tree.c | |
parent | fce3bb9a1bd492793170e117c60d5718b7896af4 (diff) |
Btrfs: adjust btrfs_discard_extent() return errors and trimmed bytes
Callers of btrfs_discard_extent() should check if we are mounted with -o discard,
as we want to make fitrim to work even the fs is not mounted with -o discard.
Also we should use REQ_DISCARD to map the free extent to get a full mapping,
last we only return errors if
1. the error is not a EOPNOTSUPP
2. no device supports discard
Signed-off-by: Li Dongyang <lidongyang@novell.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 43 |
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 | ||
1741 | static void btrfs_issue_discard(struct block_device *bdev, | 1741 | static 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 | ||
1747 | static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | 1747 | static 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 | ||
8767 | int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, | 8776 | int 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 | } |