aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorLi Dongyang <lidongyang@novell.com>2011-03-24 06:24:27 -0400
committerroot <Chris Mason chris.mason@oracle.com>2011-03-28 05:37:46 -0400
commit5378e60734f5b7bfe1b43dc191aaf6131c1befe7 (patch)
treeb02c78e744a2a148b60a9c8046abef3f4381f544 /fs/btrfs
parentfce3bb9a1bd492793170e117c60d5718b7896af4 (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')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/disk-io.c5
-rw-r--r--fs/btrfs/extent-tree.c43
3 files changed, 31 insertions, 19 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 9e21176cdf57..a18b7bc2b22c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2229,7 +2229,7 @@ u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
2229int btrfs_error_unpin_extent_range(struct btrfs_root *root, 2229int btrfs_error_unpin_extent_range(struct btrfs_root *root,
2230 u64 start, u64 end); 2230 u64 start, u64 end);
2231int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, 2231int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
2232 u64 num_bytes); 2232 u64 num_bytes, u64 *actual_bytes);
2233int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, 2233int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
2234 struct btrfs_root *root, u64 type); 2234 struct btrfs_root *root, u64 type);
2235 2235
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 125639ddaffe..8ecc5419d8b6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3054,7 +3054,10 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root,
3054 break; 3054 break;
3055 3055
3056 /* opt_discard */ 3056 /* opt_discard */
3057 ret = btrfs_error_discard_extent(root, start, end + 1 - start); 3057 if (btrfs_test_opt(root, DISCARD))
3058 ret = btrfs_error_discard_extent(root, start,
3059 end + 1 - start,
3060 NULL);
3058 3061
3059 clear_extent_dirty(unpin, start, end, GFP_NOFS); 3062 clear_extent_dirty(unpin, start, end, GFP_NOFS);
3060 btrfs_error_unpin_extent_range(root, start, end); 3063 btrfs_error_unpin_extent_range(root, start, end);
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}