aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorLi Dongyang <lidongyang@novell.com>2011-03-24 06:24:28 -0400
committerroot <Chris Mason chris.mason@oracle.com>2011-03-28 05:37:47 -0400
commitf7039b1d5c32241f87a513e33120db36bf30264d (patch)
treee911bc79c795fceb3e9a618d8f18571c2a776307 /fs/btrfs/extent-tree.c
parent5378e60734f5b7bfe1b43dc191aaf6131c1befe7 (diff)
Btrfs: add btrfs_trim_fs() to handle FITRIM
We take an free extent out from allocator, trim it, then put it back, but before we trim the block group, we should make sure the block group is cached, so plus a little change to make cache_block_group() run without a transaction. 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.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e990d2d1ba4a..1efeda3b2f6f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -440,7 +440,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
440 * allocate blocks for the tree root we can't do the fast caching since 440 * allocate blocks for the tree root we can't do the fast caching since
441 * we likely hold important locks. 441 * we likely hold important locks.
442 */ 442 */
443 if (!trans->transaction->in_commit && 443 if (trans && (!trans->transaction->in_commit) &&
444 (root && root != root->fs_info->tree_root)) { 444 (root && root != root->fs_info->tree_root)) {
445 spin_lock(&cache->lock); 445 spin_lock(&cache->lock);
446 if (cache->cached != BTRFS_CACHE_NO) { 446 if (cache->cached != BTRFS_CACHE_NO) {
@@ -8778,3 +8778,51 @@ int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
8778{ 8778{
8779 return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes); 8779 return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes);
8780} 8780}
8781
8782int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
8783{
8784 struct btrfs_fs_info *fs_info = root->fs_info;
8785 struct btrfs_block_group_cache *cache = NULL;
8786 u64 group_trimmed;
8787 u64 start;
8788 u64 end;
8789 u64 trimmed = 0;
8790 int ret = 0;
8791
8792 cache = btrfs_lookup_block_group(fs_info, range->start);
8793
8794 while (cache) {
8795 if (cache->key.objectid >= (range->start + range->len)) {
8796 btrfs_put_block_group(cache);
8797 break;
8798 }
8799
8800 start = max(range->start, cache->key.objectid);
8801 end = min(range->start + range->len,
8802 cache->key.objectid + cache->key.offset);
8803
8804 if (end - start >= range->minlen) {
8805 if (!block_group_cache_done(cache)) {
8806 ret = cache_block_group(cache, NULL, root, 0);
8807 if (!ret)
8808 wait_block_group_cache_done(cache);
8809 }
8810 ret = btrfs_trim_block_group(cache,
8811 &group_trimmed,
8812 start,
8813 end,
8814 range->minlen);
8815
8816 trimmed += group_trimmed;
8817 if (ret) {
8818 btrfs_put_block_group(cache);
8819 break;
8820 }
8821 }
8822
8823 cache = next_block_group(fs_info->tree_root, cache);
8824 }
8825
8826 range->len = trimmed;
8827 return ret;
8828}