diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 99 |
1 files changed, 48 insertions, 51 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index fe0e59ab33cc..780c1eeb8299 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -876,6 +876,38 @@ static void btrfs_issue_discard(struct block_device *bdev, | |||
876 | } | 876 | } |
877 | #endif | 877 | #endif |
878 | 878 | ||
879 | static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | ||
880 | u64 num_bytes) | ||
881 | { | ||
882 | #ifdef BIO_RW_DISCARD | ||
883 | int ret; | ||
884 | u64 map_length = num_bytes; | ||
885 | struct btrfs_multi_bio *multi = NULL; | ||
886 | |||
887 | /* Tell the block device(s) that the sectors can be discarded */ | ||
888 | ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, | ||
889 | bytenr, &map_length, &multi, 0); | ||
890 | if (!ret) { | ||
891 | struct btrfs_bio_stripe *stripe = multi->stripes; | ||
892 | int i; | ||
893 | |||
894 | if (map_length > num_bytes) | ||
895 | map_length = num_bytes; | ||
896 | |||
897 | for (i = 0; i < multi->num_stripes; i++, stripe++) { | ||
898 | btrfs_issue_discard(stripe->dev->bdev, | ||
899 | stripe->physical, | ||
900 | map_length); | ||
901 | } | ||
902 | kfree(multi); | ||
903 | } | ||
904 | |||
905 | return ret; | ||
906 | #else | ||
907 | return 0; | ||
908 | #endif | ||
909 | } | ||
910 | |||
879 | static int noinline free_extents(struct btrfs_trans_handle *trans, | 911 | static int noinline free_extents(struct btrfs_trans_handle *trans, |
880 | struct btrfs_root *extent_root, | 912 | struct btrfs_root *extent_root, |
881 | struct list_head *del_list) | 913 | struct list_head *del_list) |
@@ -1069,10 +1101,6 @@ search: | |||
1069 | for (pos = cur, n = pos->next; pos != end; | 1101 | for (pos = cur, n = pos->next; pos != end; |
1070 | pos = n, n = pos->next) { | 1102 | pos = n, n = pos->next) { |
1071 | struct pending_extent_op *tmp; | 1103 | struct pending_extent_op *tmp; |
1072 | #ifdef BIO_RW_DISCARD | ||
1073 | u64 map_length; | ||
1074 | struct btrfs_multi_bio *multi = NULL; | ||
1075 | #endif | ||
1076 | tmp = list_entry(pos, struct pending_extent_op, list); | 1104 | tmp = list_entry(pos, struct pending_extent_op, list); |
1077 | 1105 | ||
1078 | /* | 1106 | /* |
@@ -1084,28 +1112,6 @@ search: | |||
1084 | tmp->del); | 1112 | tmp->del); |
1085 | BUG_ON(ret); | 1113 | BUG_ON(ret); |
1086 | 1114 | ||
1087 | #ifdef BIO_RW_DISCARD | ||
1088 | map_length = tmp->num_bytes; | ||
1089 | ret = btrfs_map_block(&info->mapping_tree, READ, | ||
1090 | tmp->bytenr, &map_length, &multi, | ||
1091 | 0); | ||
1092 | if (!ret) { | ||
1093 | struct btrfs_bio_stripe *stripe; | ||
1094 | int i; | ||
1095 | |||
1096 | stripe = multi->stripes; | ||
1097 | |||
1098 | if (map_length > tmp->num_bytes) | ||
1099 | map_length = tmp->num_bytes; | ||
1100 | |||
1101 | for (i = 0; i < multi->num_stripes; | ||
1102 | i++, stripe++) | ||
1103 | btrfs_issue_discard(stripe->dev->bdev, | ||
1104 | stripe->physical, | ||
1105 | map_length); | ||
1106 | kfree(multi); | ||
1107 | } | ||
1108 | #endif | ||
1109 | list_del_init(&tmp->list); | 1115 | list_del_init(&tmp->list); |
1110 | unlock_extent(&info->extent_ins, tmp->bytenr, | 1116 | unlock_extent(&info->extent_ins, tmp->bytenr, |
1111 | tmp->bytenr + tmp->num_bytes - 1, | 1117 | tmp->bytenr + tmp->num_bytes - 1, |
@@ -1965,6 +1971,11 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1965 | spin_unlock(&cache->space_info->lock); | 1971 | spin_unlock(&cache->space_info->lock); |
1966 | if (mark_free) { | 1972 | if (mark_free) { |
1967 | int ret; | 1973 | int ret; |
1974 | |||
1975 | ret = btrfs_discard_extent(root, bytenr, | ||
1976 | num_bytes); | ||
1977 | WARN_ON(ret); | ||
1978 | |||
1968 | ret = btrfs_add_free_space(cache, bytenr, | 1979 | ret = btrfs_add_free_space(cache, bytenr, |
1969 | num_bytes); | 1980 | num_bytes); |
1970 | WARN_ON(ret); | 1981 | WARN_ON(ret); |
@@ -2104,8 +2115,12 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
2104 | EXTENT_DIRTY); | 2115 | EXTENT_DIRTY); |
2105 | if (ret) | 2116 | if (ret) |
2106 | break; | 2117 | break; |
2118 | |||
2119 | ret = btrfs_discard_extent(root, start, end + 1 - start); | ||
2120 | |||
2107 | btrfs_update_pinned_extents(root, start, end + 1 - start, 0); | 2121 | btrfs_update_pinned_extents(root, start, end + 1 - start, 0); |
2108 | clear_extent_dirty(unpin, start, end, GFP_NOFS); | 2122 | clear_extent_dirty(unpin, start, end, GFP_NOFS); |
2123 | |||
2109 | if (need_resched()) { | 2124 | if (need_resched()) { |
2110 | mutex_unlock(&root->fs_info->pinned_mutex); | 2125 | mutex_unlock(&root->fs_info->pinned_mutex); |
2111 | cond_resched(); | 2126 | cond_resched(); |
@@ -2113,7 +2128,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
2113 | } | 2128 | } |
2114 | } | 2129 | } |
2115 | mutex_unlock(&root->fs_info->pinned_mutex); | 2130 | mutex_unlock(&root->fs_info->pinned_mutex); |
2116 | return 0; | 2131 | return ret; |
2117 | } | 2132 | } |
2118 | 2133 | ||
2119 | static int finish_current_insert(struct btrfs_trans_handle *trans, | 2134 | static int finish_current_insert(struct btrfs_trans_handle *trans, |
@@ -2458,10 +2473,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2458 | if (refs == 0) { | 2473 | if (refs == 0) { |
2459 | u64 super_used; | 2474 | u64 super_used; |
2460 | u64 root_used; | 2475 | u64 root_used; |
2461 | #ifdef BIO_RW_DISCARD | ||
2462 | u64 map_length = num_bytes; | ||
2463 | struct btrfs_multi_bio *multi = NULL; | ||
2464 | #endif | ||
2465 | 2476 | ||
2466 | if (pin) { | 2477 | if (pin) { |
2467 | mutex_lock(&root->fs_info->pinned_mutex); | 2478 | mutex_lock(&root->fs_info->pinned_mutex); |
@@ -2496,25 +2507,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, | |||
2496 | ret = update_block_group(trans, root, bytenr, num_bytes, 0, | 2507 | ret = update_block_group(trans, root, bytenr, num_bytes, 0, |
2497 | mark_free); | 2508 | mark_free); |
2498 | BUG_ON(ret); | 2509 | BUG_ON(ret); |
2499 | #ifdef BIO_RW_DISCARD | ||
2500 | /* Tell the block device(s) that the sectors can be discarded */ | ||
2501 | ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, | ||
2502 | bytenr, &map_length, &multi, 0); | ||
2503 | if (!ret) { | ||
2504 | struct btrfs_bio_stripe *stripe = multi->stripes; | ||
2505 | int i; | ||
2506 | |||
2507 | if (map_length > num_bytes) | ||
2508 | map_length = num_bytes; | ||
2509 | |||
2510 | for (i = 0; i < multi->num_stripes; i++, stripe++) { | ||
2511 | btrfs_issue_discard(stripe->dev->bdev, | ||
2512 | stripe->physical, | ||
2513 | map_length); | ||
2514 | } | ||
2515 | kfree(multi); | ||
2516 | } | ||
2517 | #endif | ||
2518 | } | 2510 | } |
2519 | btrfs_free_path(path); | 2511 | btrfs_free_path(path); |
2520 | finish_current_insert(trans, extent_root, 0); | 2512 | finish_current_insert(trans, extent_root, 0); |
@@ -3112,16 +3104,21 @@ again: | |||
3112 | int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) | 3104 | int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) |
3113 | { | 3105 | { |
3114 | struct btrfs_block_group_cache *cache; | 3106 | struct btrfs_block_group_cache *cache; |
3107 | int ret = 0; | ||
3115 | 3108 | ||
3116 | cache = btrfs_lookup_block_group(root->fs_info, start); | 3109 | cache = btrfs_lookup_block_group(root->fs_info, start); |
3117 | if (!cache) { | 3110 | if (!cache) { |
3118 | printk(KERN_ERR "Unable to find block group for %Lu\n", start); | 3111 | printk(KERN_ERR "Unable to find block group for %Lu\n", start); |
3119 | return -ENOSPC; | 3112 | return -ENOSPC; |
3120 | } | 3113 | } |
3114 | |||
3115 | ret = btrfs_discard_extent(root, start, len); | ||
3116 | |||
3121 | btrfs_add_free_space(cache, start, len); | 3117 | btrfs_add_free_space(cache, start, len); |
3122 | put_block_group(cache); | 3118 | put_block_group(cache); |
3123 | update_reserved_extents(root, start, len, 0); | 3119 | update_reserved_extents(root, start, len, 0); |
3124 | return 0; | 3120 | |
3121 | return ret; | ||
3125 | } | 3122 | } |
3126 | 3123 | ||
3127 | int btrfs_reserve_extent(struct btrfs_trans_handle *trans, | 3124 | int btrfs_reserve_extent(struct btrfs_trans_handle *trans, |