diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2011-04-26 04:22:15 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-04-26 04:22:59 -0400 |
| commit | 07f9479a40cc778bc1462ada11f95b01360ae4ff (patch) | |
| tree | 0676cf38df3844004bb3ebfd99dfa67a4a8998f5 /fs/btrfs/extent-tree.c | |
| parent | 9d5e6bdb3013acfb311ab407eeca0b6a6a3dedbf (diff) | |
| parent | cd2e49e90f1cae7726c9a2c54488d881d7f1cd1c (diff) | |
Merge branch 'master' into for-next
Fast-forwarded to current state of Linus' tree as there are patches to be
applied for files that didn't exist on the old branch.
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 354 |
1 files changed, 275 insertions, 79 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 7b3089b5c2df..31f33ba56fe8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -33,11 +33,28 @@ | |||
| 33 | #include "locking.h" | 33 | #include "locking.h" |
| 34 | #include "free-space-cache.h" | 34 | #include "free-space-cache.h" |
| 35 | 35 | ||
| 36 | /* control flags for do_chunk_alloc's force field | ||
| 37 | * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk | ||
| 38 | * if we really need one. | ||
| 39 | * | ||
| 40 | * CHUNK_ALLOC_FORCE means it must try to allocate one | ||
| 41 | * | ||
| 42 | * CHUNK_ALLOC_LIMITED means to only try and allocate one | ||
| 43 | * if we have very few chunks already allocated. This is | ||
| 44 | * used as part of the clustering code to help make sure | ||
| 45 | * we have a good pool of storage to cluster in, without | ||
| 46 | * filling the FS with empty chunks | ||
| 47 | * | ||
| 48 | */ | ||
| 49 | enum { | ||
| 50 | CHUNK_ALLOC_NO_FORCE = 0, | ||
| 51 | CHUNK_ALLOC_FORCE = 1, | ||
| 52 | CHUNK_ALLOC_LIMITED = 2, | ||
| 53 | }; | ||
| 54 | |||
| 36 | static int update_block_group(struct btrfs_trans_handle *trans, | 55 | static int update_block_group(struct btrfs_trans_handle *trans, |
| 37 | struct btrfs_root *root, | 56 | struct btrfs_root *root, |
| 38 | u64 bytenr, u64 num_bytes, int alloc); | 57 | u64 bytenr, u64 num_bytes, int alloc); |
| 39 | static int update_reserved_bytes(struct btrfs_block_group_cache *cache, | ||
| 40 | u64 num_bytes, int reserve, int sinfo); | ||
| 41 | static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | 58 | static int __btrfs_free_extent(struct btrfs_trans_handle *trans, |
| 42 | struct btrfs_root *root, | 59 | struct btrfs_root *root, |
| 43 | u64 bytenr, u64 num_bytes, u64 parent, | 60 | u64 bytenr, u64 num_bytes, u64 parent, |
| @@ -442,7 +459,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, | |||
| 442 | * allocate blocks for the tree root we can't do the fast caching since | 459 | * allocate blocks for the tree root we can't do the fast caching since |
| 443 | * we likely hold important locks. | 460 | * we likely hold important locks. |
| 444 | */ | 461 | */ |
| 445 | if (!trans->transaction->in_commit && | 462 | if (trans && (!trans->transaction->in_commit) && |
| 446 | (root && root != root->fs_info->tree_root)) { | 463 | (root && root != root->fs_info->tree_root)) { |
| 447 | spin_lock(&cache->lock); | 464 | spin_lock(&cache->lock); |
| 448 | if (cache->cached != BTRFS_CACHE_NO) { | 465 | if (cache->cached != BTRFS_CACHE_NO) { |
| @@ -471,7 +488,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache, | |||
| 471 | if (load_cache_only) | 488 | if (load_cache_only) |
| 472 | return 0; | 489 | return 0; |
| 473 | 490 | ||
| 474 | caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_KERNEL); | 491 | caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS); |
| 475 | BUG_ON(!caching_ctl); | 492 | BUG_ON(!caching_ctl); |
| 476 | 493 | ||
| 477 | INIT_LIST_HEAD(&caching_ctl->list); | 494 | INIT_LIST_HEAD(&caching_ctl->list); |
| @@ -1740,39 +1757,45 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans, | |||
| 1740 | return ret; | 1757 | return ret; |
| 1741 | } | 1758 | } |
| 1742 | 1759 | ||
| 1743 | static void btrfs_issue_discard(struct block_device *bdev, | 1760 | static int btrfs_issue_discard(struct block_device *bdev, |
| 1744 | u64 start, u64 len) | 1761 | u64 start, u64 len) |
| 1745 | { | 1762 | { |
| 1746 | blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0); | 1763 | return blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_NOFS, 0); |
| 1747 | } | 1764 | } |
| 1748 | 1765 | ||
| 1749 | static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, | 1766 | static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, |
| 1750 | u64 num_bytes) | 1767 | u64 num_bytes, u64 *actual_bytes) |
| 1751 | { | 1768 | { |
| 1752 | int ret; | 1769 | int ret; |
| 1753 | u64 map_length = num_bytes; | 1770 | u64 discarded_bytes = 0; |
| 1754 | struct btrfs_multi_bio *multi = NULL; | 1771 | struct btrfs_multi_bio *multi = NULL; |
| 1755 | 1772 | ||
| 1756 | if (!btrfs_test_opt(root, DISCARD)) | ||
| 1757 | return 0; | ||
| 1758 | 1773 | ||
| 1759 | /* Tell the block device(s) that the sectors can be discarded */ | 1774 | /* Tell the block device(s) that the sectors can be discarded */ |
| 1760 | ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, | 1775 | ret = btrfs_map_block(&root->fs_info->mapping_tree, REQ_DISCARD, |
| 1761 | bytenr, &map_length, &multi, 0); | 1776 | bytenr, &num_bytes, &multi, 0); |
| 1762 | if (!ret) { | 1777 | if (!ret) { |
| 1763 | struct btrfs_bio_stripe *stripe = multi->stripes; | 1778 | struct btrfs_bio_stripe *stripe = multi->stripes; |
| 1764 | int i; | 1779 | int i; |
| 1765 | 1780 | ||
| 1766 | if (map_length > num_bytes) | ||
| 1767 | map_length = num_bytes; | ||
| 1768 | 1781 | ||
| 1769 | for (i = 0; i < multi->num_stripes; i++, stripe++) { | 1782 | for (i = 0; i < multi->num_stripes; i++, stripe++) { |
| 1770 | btrfs_issue_discard(stripe->dev->bdev, | 1783 | ret = btrfs_issue_discard(stripe->dev->bdev, |
| 1771 | stripe->physical, | 1784 | stripe->physical, |
| 1772 | map_length); | 1785 | stripe->length); |
| 1786 | if (!ret) | ||
| 1787 | discarded_bytes += stripe->length; | ||
| 1788 | else if (ret != -EOPNOTSUPP) | ||
| 1789 | break; | ||
| 1773 | } | 1790 | } |
| 1774 | kfree(multi); | 1791 | kfree(multi); |
| 1775 | } | 1792 | } |
| 1793 | if (discarded_bytes && ret == -EOPNOTSUPP) | ||
| 1794 | ret = 0; | ||
| 1795 | |||
| 1796 | if (actual_bytes) | ||
| 1797 | *actual_bytes = discarded_bytes; | ||
| 1798 | |||
| 1776 | 1799 | ||
| 1777 | return ret; | 1800 | return ret; |
| 1778 | } | 1801 | } |
| @@ -3015,7 +3038,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags, | |||
| 3015 | found->bytes_readonly = 0; | 3038 | found->bytes_readonly = 0; |
| 3016 | found->bytes_may_use = 0; | 3039 | found->bytes_may_use = 0; |
| 3017 | found->full = 0; | 3040 | found->full = 0; |
| 3018 | found->force_alloc = 0; | 3041 | found->force_alloc = CHUNK_ALLOC_NO_FORCE; |
| 3042 | found->chunk_alloc = 0; | ||
| 3019 | *space_info = found; | 3043 | *space_info = found; |
| 3020 | list_add_rcu(&found->list, &info->space_info); | 3044 | list_add_rcu(&found->list, &info->space_info); |
| 3021 | atomic_set(&found->caching_threads, 0); | 3045 | atomic_set(&found->caching_threads, 0); |
| @@ -3146,7 +3170,7 @@ again: | |||
| 3146 | if (!data_sinfo->full && alloc_chunk) { | 3170 | if (!data_sinfo->full && alloc_chunk) { |
| 3147 | u64 alloc_target; | 3171 | u64 alloc_target; |
| 3148 | 3172 | ||
| 3149 | data_sinfo->force_alloc = 1; | 3173 | data_sinfo->force_alloc = CHUNK_ALLOC_FORCE; |
| 3150 | spin_unlock(&data_sinfo->lock); | 3174 | spin_unlock(&data_sinfo->lock); |
| 3151 | alloc: | 3175 | alloc: |
| 3152 | alloc_target = btrfs_get_alloc_profile(root, 1); | 3176 | alloc_target = btrfs_get_alloc_profile(root, 1); |
| @@ -3156,7 +3180,8 @@ alloc: | |||
| 3156 | 3180 | ||
| 3157 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 3181 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
| 3158 | bytes + 2 * 1024 * 1024, | 3182 | bytes + 2 * 1024 * 1024, |
| 3159 | alloc_target, 0); | 3183 | alloc_target, |
| 3184 | CHUNK_ALLOC_NO_FORCE); | ||
| 3160 | btrfs_end_transaction(trans, root); | 3185 | btrfs_end_transaction(trans, root); |
| 3161 | if (ret < 0) { | 3186 | if (ret < 0) { |
| 3162 | if (ret != -ENOSPC) | 3187 | if (ret != -ENOSPC) |
| @@ -3235,31 +3260,56 @@ static void force_metadata_allocation(struct btrfs_fs_info *info) | |||
| 3235 | rcu_read_lock(); | 3260 | rcu_read_lock(); |
| 3236 | list_for_each_entry_rcu(found, head, list) { | 3261 | list_for_each_entry_rcu(found, head, list) { |
| 3237 | if (found->flags & BTRFS_BLOCK_GROUP_METADATA) | 3262 | if (found->flags & BTRFS_BLOCK_GROUP_METADATA) |
| 3238 | found->force_alloc = 1; | 3263 | found->force_alloc = CHUNK_ALLOC_FORCE; |
| 3239 | } | 3264 | } |
| 3240 | rcu_read_unlock(); | 3265 | rcu_read_unlock(); |
| 3241 | } | 3266 | } |
| 3242 | 3267 | ||
| 3243 | static int should_alloc_chunk(struct btrfs_root *root, | 3268 | static int should_alloc_chunk(struct btrfs_root *root, |
| 3244 | struct btrfs_space_info *sinfo, u64 alloc_bytes) | 3269 | struct btrfs_space_info *sinfo, u64 alloc_bytes, |
| 3270 | int force) | ||
| 3245 | { | 3271 | { |
| 3246 | u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; | 3272 | u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly; |
| 3273 | u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved; | ||
| 3247 | u64 thresh; | 3274 | u64 thresh; |
| 3248 | 3275 | ||
| 3249 | if (sinfo->bytes_used + sinfo->bytes_reserved + | 3276 | if (force == CHUNK_ALLOC_FORCE) |
| 3250 | alloc_bytes + 256 * 1024 * 1024 < num_bytes) | 3277 | return 1; |
| 3278 | |||
| 3279 | /* | ||
| 3280 | * in limited mode, we want to have some free space up to | ||
| 3281 | * about 1% of the FS size. | ||
| 3282 | */ | ||
| 3283 | if (force == CHUNK_ALLOC_LIMITED) { | ||
| 3284 | thresh = btrfs_super_total_bytes(&root->fs_info->super_copy); | ||
| 3285 | thresh = max_t(u64, 64 * 1024 * 1024, | ||
| 3286 | div_factor_fine(thresh, 1)); | ||
| 3287 | |||
| 3288 | if (num_bytes - num_allocated < thresh) | ||
| 3289 | return 1; | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | /* | ||
| 3293 | * we have two similar checks here, one based on percentage | ||
| 3294 | * and once based on a hard number of 256MB. The idea | ||
| 3295 | * is that if we have a good amount of free | ||
| 3296 | * room, don't allocate a chunk. A good mount is | ||
| 3297 | * less than 80% utilized of the chunks we have allocated, | ||
| 3298 | * or more than 256MB free | ||
| 3299 | */ | ||
| 3300 | if (num_allocated + alloc_bytes + 256 * 1024 * 1024 < num_bytes) | ||
| 3251 | return 0; | 3301 | return 0; |
| 3252 | 3302 | ||
| 3253 | if (sinfo->bytes_used + sinfo->bytes_reserved + | 3303 | if (num_allocated + alloc_bytes < div_factor(num_bytes, 8)) |
| 3254 | alloc_bytes < div_factor(num_bytes, 8)) | ||
| 3255 | return 0; | 3304 | return 0; |
| 3256 | 3305 | ||
| 3257 | thresh = btrfs_super_total_bytes(&root->fs_info->super_copy); | 3306 | thresh = btrfs_super_total_bytes(&root->fs_info->super_copy); |
| 3307 | |||
| 3308 | /* 256MB or 5% of the FS */ | ||
| 3258 | thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5)); | 3309 | thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5)); |
| 3259 | 3310 | ||
| 3260 | if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3)) | 3311 | if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3)) |
| 3261 | return 0; | 3312 | return 0; |
| 3262 | |||
| 3263 | return 1; | 3313 | return 1; |
| 3264 | } | 3314 | } |
| 3265 | 3315 | ||
| @@ -3269,10 +3319,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
| 3269 | { | 3319 | { |
| 3270 | struct btrfs_space_info *space_info; | 3320 | struct btrfs_space_info *space_info; |
| 3271 | struct btrfs_fs_info *fs_info = extent_root->fs_info; | 3321 | struct btrfs_fs_info *fs_info = extent_root->fs_info; |
| 3322 | int wait_for_alloc = 0; | ||
| 3272 | int ret = 0; | 3323 | int ret = 0; |
| 3273 | 3324 | ||
| 3274 | mutex_lock(&fs_info->chunk_mutex); | ||
| 3275 | |||
| 3276 | flags = btrfs_reduce_alloc_profile(extent_root, flags); | 3325 | flags = btrfs_reduce_alloc_profile(extent_root, flags); |
| 3277 | 3326 | ||
| 3278 | space_info = __find_space_info(extent_root->fs_info, flags); | 3327 | space_info = __find_space_info(extent_root->fs_info, flags); |
| @@ -3283,21 +3332,40 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
| 3283 | } | 3332 | } |
| 3284 | BUG_ON(!space_info); | 3333 | BUG_ON(!space_info); |
| 3285 | 3334 | ||
| 3335 | again: | ||
| 3286 | spin_lock(&space_info->lock); | 3336 | spin_lock(&space_info->lock); |
| 3287 | if (space_info->force_alloc) | 3337 | if (space_info->force_alloc) |
| 3288 | force = 1; | 3338 | force = space_info->force_alloc; |
| 3289 | if (space_info->full) { | 3339 | if (space_info->full) { |
| 3290 | spin_unlock(&space_info->lock); | 3340 | spin_unlock(&space_info->lock); |
| 3291 | goto out; | 3341 | return 0; |
| 3292 | } | 3342 | } |
| 3293 | 3343 | ||
| 3294 | if (!force && !should_alloc_chunk(extent_root, space_info, | 3344 | if (!should_alloc_chunk(extent_root, space_info, alloc_bytes, force)) { |
| 3295 | alloc_bytes)) { | ||
| 3296 | spin_unlock(&space_info->lock); | 3345 | spin_unlock(&space_info->lock); |
| 3297 | goto out; | 3346 | return 0; |
| 3347 | } else if (space_info->chunk_alloc) { | ||
| 3348 | wait_for_alloc = 1; | ||
| 3349 | } else { | ||
| 3350 | space_info->chunk_alloc = 1; | ||
| 3298 | } | 3351 | } |
| 3352 | |||
| 3299 | spin_unlock(&space_info->lock); | 3353 | spin_unlock(&space_info->lock); |
| 3300 | 3354 | ||
| 3355 | mutex_lock(&fs_info->chunk_mutex); | ||
| 3356 | |||
| 3357 | /* | ||
| 3358 | * The chunk_mutex is held throughout the entirety of a chunk | ||
| 3359 | * allocation, so once we've acquired the chunk_mutex we know that the | ||
| 3360 | * other guy is done and we need to recheck and see if we should | ||
| 3361 | * allocate. | ||
| 3362 | */ | ||
| 3363 | if (wait_for_alloc) { | ||
| 3364 | mutex_unlock(&fs_info->chunk_mutex); | ||
| 3365 | wait_for_alloc = 0; | ||
| 3366 | goto again; | ||
| 3367 | } | ||
| 3368 | |||
| 3301 | /* | 3369 | /* |
| 3302 | * If we have mixed data/metadata chunks we want to make sure we keep | 3370 | * If we have mixed data/metadata chunks we want to make sure we keep |
| 3303 | * allocating mixed chunks instead of individual chunks. | 3371 | * allocating mixed chunks instead of individual chunks. |
| @@ -3323,9 +3391,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans, | |||
| 3323 | space_info->full = 1; | 3391 | space_info->full = 1; |
| 3324 | else | 3392 | else |
| 3325 | ret = 1; | 3393 | ret = 1; |
| 3326 | space_info->force_alloc = 0; | 3394 | |
| 3395 | space_info->force_alloc = CHUNK_ALLOC_NO_FORCE; | ||
| 3396 | space_info->chunk_alloc = 0; | ||
| 3327 | spin_unlock(&space_info->lock); | 3397 | spin_unlock(&space_info->lock); |
| 3328 | out: | ||
| 3329 | mutex_unlock(&extent_root->fs_info->chunk_mutex); | 3398 | mutex_unlock(&extent_root->fs_info->chunk_mutex); |
| 3330 | return ret; | 3399 | return ret; |
| 3331 | } | 3400 | } |
| @@ -3996,6 +4065,7 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
| 3996 | struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; | 4065 | struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; |
| 3997 | u64 to_reserve; | 4066 | u64 to_reserve; |
| 3998 | int nr_extents; | 4067 | int nr_extents; |
| 4068 | int reserved_extents; | ||
| 3999 | int ret; | 4069 | int ret; |
| 4000 | 4070 | ||
| 4001 | if (btrfs_transaction_in_commit(root->fs_info)) | 4071 | if (btrfs_transaction_in_commit(root->fs_info)) |
| @@ -4003,25 +4073,24 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
| 4003 | 4073 | ||
| 4004 | num_bytes = ALIGN(num_bytes, root->sectorsize); | 4074 | num_bytes = ALIGN(num_bytes, root->sectorsize); |
| 4005 | 4075 | ||
| 4006 | spin_lock(&BTRFS_I(inode)->accounting_lock); | ||
| 4007 | nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1; | 4076 | nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents) + 1; |
| 4008 | if (nr_extents > BTRFS_I(inode)->reserved_extents) { | 4077 | reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents); |
| 4009 | nr_extents -= BTRFS_I(inode)->reserved_extents; | 4078 | |
| 4079 | if (nr_extents > reserved_extents) { | ||
| 4080 | nr_extents -= reserved_extents; | ||
| 4010 | to_reserve = calc_trans_metadata_size(root, nr_extents); | 4081 | to_reserve = calc_trans_metadata_size(root, nr_extents); |
| 4011 | } else { | 4082 | } else { |
| 4012 | nr_extents = 0; | 4083 | nr_extents = 0; |
| 4013 | to_reserve = 0; | 4084 | to_reserve = 0; |
| 4014 | } | 4085 | } |
| 4015 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | 4086 | |
| 4016 | to_reserve += calc_csum_metadata_size(inode, num_bytes); | 4087 | to_reserve += calc_csum_metadata_size(inode, num_bytes); |
| 4017 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); | 4088 | ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1); |
| 4018 | if (ret) | 4089 | if (ret) |
| 4019 | return ret; | 4090 | return ret; |
| 4020 | 4091 | ||
| 4021 | spin_lock(&BTRFS_I(inode)->accounting_lock); | 4092 | atomic_add(nr_extents, &BTRFS_I(inode)->reserved_extents); |
| 4022 | BTRFS_I(inode)->reserved_extents += nr_extents; | ||
| 4023 | atomic_inc(&BTRFS_I(inode)->outstanding_extents); | 4093 | atomic_inc(&BTRFS_I(inode)->outstanding_extents); |
| 4024 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | ||
| 4025 | 4094 | ||
| 4026 | block_rsv_add_bytes(block_rsv, to_reserve, 1); | 4095 | block_rsv_add_bytes(block_rsv, to_reserve, 1); |
| 4027 | 4096 | ||
| @@ -4036,20 +4105,30 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes) | |||
| 4036 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4105 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 4037 | u64 to_free; | 4106 | u64 to_free; |
| 4038 | int nr_extents; | 4107 | int nr_extents; |
| 4108 | int reserved_extents; | ||
| 4039 | 4109 | ||
| 4040 | num_bytes = ALIGN(num_bytes, root->sectorsize); | 4110 | num_bytes = ALIGN(num_bytes, root->sectorsize); |
| 4041 | atomic_dec(&BTRFS_I(inode)->outstanding_extents); | 4111 | atomic_dec(&BTRFS_I(inode)->outstanding_extents); |
| 4042 | WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0); | 4112 | WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0); |
| 4043 | 4113 | ||
| 4044 | spin_lock(&BTRFS_I(inode)->accounting_lock); | 4114 | reserved_extents = atomic_read(&BTRFS_I(inode)->reserved_extents); |
| 4045 | nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); | 4115 | do { |
| 4046 | if (nr_extents < BTRFS_I(inode)->reserved_extents) { | 4116 | int old, new; |
| 4047 | nr_extents = BTRFS_I(inode)->reserved_extents - nr_extents; | 4117 | |
| 4048 | BTRFS_I(inode)->reserved_extents -= nr_extents; | 4118 | nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents); |
| 4049 | } else { | 4119 | if (nr_extents >= reserved_extents) { |
| 4050 | nr_extents = 0; | 4120 | nr_extents = 0; |
| 4051 | } | 4121 | break; |
| 4052 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | 4122 | } |
| 4123 | old = reserved_extents; | ||
| 4124 | nr_extents = reserved_extents - nr_extents; | ||
| 4125 | new = reserved_extents - nr_extents; | ||
| 4126 | old = atomic_cmpxchg(&BTRFS_I(inode)->reserved_extents, | ||
| 4127 | reserved_extents, new); | ||
| 4128 | if (likely(old == reserved_extents)) | ||
| 4129 | break; | ||
| 4130 | reserved_extents = old; | ||
| 4131 | } while (1); | ||
| 4053 | 4132 | ||
| 4054 | to_free = calc_csum_metadata_size(inode, num_bytes); | 4133 | to_free = calc_csum_metadata_size(inode, num_bytes); |
| 4055 | if (nr_extents > 0) | 4134 | if (nr_extents > 0) |
| @@ -4223,8 +4302,8 @@ int btrfs_pin_extent(struct btrfs_root *root, | |||
| 4223 | * update size of reserved extents. this function may return -EAGAIN | 4302 | * update size of reserved extents. this function may return -EAGAIN |
| 4224 | * if 'reserve' is true or 'sinfo' is false. | 4303 | * if 'reserve' is true or 'sinfo' is false. |
| 4225 | */ | 4304 | */ |
| 4226 | static int update_reserved_bytes(struct btrfs_block_group_cache *cache, | 4305 | int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache, |
| 4227 | u64 num_bytes, int reserve, int sinfo) | 4306 | u64 num_bytes, int reserve, int sinfo) |
| 4228 | { | 4307 | { |
| 4229 | int ret = 0; | 4308 | int ret = 0; |
| 4230 | if (sinfo) { | 4309 | if (sinfo) { |
| @@ -4363,7 +4442,9 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
| 4363 | if (ret) | 4442 | if (ret) |
| 4364 | break; | 4443 | break; |
| 4365 | 4444 | ||
| 4366 | ret = btrfs_discard_extent(root, start, end + 1 - start); | 4445 | if (btrfs_test_opt(root, DISCARD)) |
| 4446 | ret = btrfs_discard_extent(root, start, | ||
| 4447 | end + 1 - start, NULL); | ||
| 4367 | 4448 | ||
| 4368 | clear_extent_dirty(unpin, start, end, GFP_NOFS); | 4449 | clear_extent_dirty(unpin, start, end, GFP_NOFS); |
| 4369 | unpin_extent_range(root, start, end); | 4450 | unpin_extent_range(root, start, end); |
| @@ -4704,10 +4785,10 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, | |||
| 4704 | WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); | 4785 | WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); |
| 4705 | 4786 | ||
| 4706 | btrfs_add_free_space(cache, buf->start, buf->len); | 4787 | btrfs_add_free_space(cache, buf->start, buf->len); |
| 4707 | ret = update_reserved_bytes(cache, buf->len, 0, 0); | 4788 | ret = btrfs_update_reserved_bytes(cache, buf->len, 0, 0); |
| 4708 | if (ret == -EAGAIN) { | 4789 | if (ret == -EAGAIN) { |
| 4709 | /* block group became read-only */ | 4790 | /* block group became read-only */ |
| 4710 | update_reserved_bytes(cache, buf->len, 0, 1); | 4791 | btrfs_update_reserved_bytes(cache, buf->len, 0, 1); |
| 4711 | goto out; | 4792 | goto out; |
| 4712 | } | 4793 | } |
| 4713 | 4794 | ||
| @@ -4744,6 +4825,11 @@ pin: | |||
| 4744 | } | 4825 | } |
| 4745 | } | 4826 | } |
| 4746 | out: | 4827 | out: |
| 4828 | /* | ||
| 4829 | * Deleting the buffer, clear the corrupt flag since it doesn't matter | ||
| 4830 | * anymore. | ||
| 4831 | */ | ||
| 4832 | clear_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags); | ||
| 4747 | btrfs_put_block_group(cache); | 4833 | btrfs_put_block_group(cache); |
| 4748 | } | 4834 | } |
| 4749 | 4835 | ||
| @@ -5191,7 +5277,7 @@ checks: | |||
| 5191 | search_start - offset); | 5277 | search_start - offset); |
| 5192 | BUG_ON(offset > search_start); | 5278 | BUG_ON(offset > search_start); |
| 5193 | 5279 | ||
| 5194 | ret = update_reserved_bytes(block_group, num_bytes, 1, | 5280 | ret = btrfs_update_reserved_bytes(block_group, num_bytes, 1, |
| 5195 | (data & BTRFS_BLOCK_GROUP_DATA)); | 5281 | (data & BTRFS_BLOCK_GROUP_DATA)); |
| 5196 | if (ret == -EAGAIN) { | 5282 | if (ret == -EAGAIN) { |
| 5197 | btrfs_add_free_space(block_group, offset, num_bytes); | 5283 | btrfs_add_free_space(block_group, offset, num_bytes); |
| @@ -5282,11 +5368,13 @@ loop: | |||
| 5282 | 5368 | ||
| 5283 | if (allowed_chunk_alloc) { | 5369 | if (allowed_chunk_alloc) { |
| 5284 | ret = do_chunk_alloc(trans, root, num_bytes + | 5370 | ret = do_chunk_alloc(trans, root, num_bytes + |
| 5285 | 2 * 1024 * 1024, data, 1); | 5371 | 2 * 1024 * 1024, data, |
| 5372 | CHUNK_ALLOC_LIMITED); | ||
| 5286 | allowed_chunk_alloc = 0; | 5373 | allowed_chunk_alloc = 0; |
| 5287 | done_chunk_alloc = 1; | 5374 | done_chunk_alloc = 1; |
| 5288 | } else if (!done_chunk_alloc) { | 5375 | } else if (!done_chunk_alloc && |
| 5289 | space_info->force_alloc = 1; | 5376 | space_info->force_alloc == CHUNK_ALLOC_NO_FORCE) { |
| 5377 | space_info->force_alloc = CHUNK_ALLOC_LIMITED; | ||
| 5290 | } | 5378 | } |
| 5291 | 5379 | ||
| 5292 | if (loop < LOOP_NO_EMPTY_SIZE) { | 5380 | if (loop < LOOP_NO_EMPTY_SIZE) { |
| @@ -5372,7 +5460,8 @@ again: | |||
| 5372 | */ | 5460 | */ |
| 5373 | if (empty_size || root->ref_cows) | 5461 | if (empty_size || root->ref_cows) |
| 5374 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 5462 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
| 5375 | num_bytes + 2 * 1024 * 1024, data, 0); | 5463 | num_bytes + 2 * 1024 * 1024, data, |
| 5464 | CHUNK_ALLOC_NO_FORCE); | ||
| 5376 | 5465 | ||
| 5377 | WARN_ON(num_bytes < root->sectorsize); | 5466 | WARN_ON(num_bytes < root->sectorsize); |
| 5378 | ret = find_free_extent(trans, root, num_bytes, empty_size, | 5467 | ret = find_free_extent(trans, root, num_bytes, empty_size, |
| @@ -5384,7 +5473,7 @@ again: | |||
| 5384 | num_bytes = num_bytes & ~(root->sectorsize - 1); | 5473 | num_bytes = num_bytes & ~(root->sectorsize - 1); |
| 5385 | num_bytes = max(num_bytes, min_alloc_size); | 5474 | num_bytes = max(num_bytes, min_alloc_size); |
| 5386 | do_chunk_alloc(trans, root->fs_info->extent_root, | 5475 | do_chunk_alloc(trans, root->fs_info->extent_root, |
| 5387 | num_bytes, data, 1); | 5476 | num_bytes, data, CHUNK_ALLOC_FORCE); |
| 5388 | goto again; | 5477 | goto again; |
| 5389 | } | 5478 | } |
| 5390 | if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { | 5479 | if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) { |
| @@ -5397,6 +5486,8 @@ again: | |||
| 5397 | dump_space_info(sinfo, num_bytes, 1); | 5486 | dump_space_info(sinfo, num_bytes, 1); |
| 5398 | } | 5487 | } |
| 5399 | 5488 | ||
| 5489 | trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset); | ||
| 5490 | |||
| 5400 | return ret; | 5491 | return ret; |
| 5401 | } | 5492 | } |
| 5402 | 5493 | ||
| @@ -5412,12 +5503,15 @@ int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len) | |||
| 5412 | return -ENOSPC; | 5503 | return -ENOSPC; |
| 5413 | } | 5504 | } |
| 5414 | 5505 | ||
| 5415 | ret = btrfs_discard_extent(root, start, len); | 5506 | if (btrfs_test_opt(root, DISCARD)) |
| 5507 | ret = btrfs_discard_extent(root, start, len, NULL); | ||
| 5416 | 5508 | ||
| 5417 | btrfs_add_free_space(cache, start, len); | 5509 | btrfs_add_free_space(cache, start, len); |
| 5418 | update_reserved_bytes(cache, len, 0, 1); | 5510 | btrfs_update_reserved_bytes(cache, len, 0, 1); |
| 5419 | btrfs_put_block_group(cache); | 5511 | btrfs_put_block_group(cache); |
| 5420 | 5512 | ||
| 5513 | trace_btrfs_reserved_extent_free(root, start, len); | ||
| 5514 | |||
| 5421 | return ret; | 5515 | return ret; |
| 5422 | } | 5516 | } |
| 5423 | 5517 | ||
| @@ -5444,7 +5538,8 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
| 5444 | size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type); | 5538 | size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type); |
| 5445 | 5539 | ||
| 5446 | path = btrfs_alloc_path(); | 5540 | path = btrfs_alloc_path(); |
| 5447 | BUG_ON(!path); | 5541 | if (!path) |
| 5542 | return -ENOMEM; | ||
| 5448 | 5543 | ||
| 5449 | path->leave_spinning = 1; | 5544 | path->leave_spinning = 1; |
| 5450 | ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, | 5545 | ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, |
| @@ -5614,7 +5709,7 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans, | |||
| 5614 | put_caching_control(caching_ctl); | 5709 | put_caching_control(caching_ctl); |
| 5615 | } | 5710 | } |
| 5616 | 5711 | ||
| 5617 | ret = update_reserved_bytes(block_group, ins->offset, 1, 1); | 5712 | ret = btrfs_update_reserved_bytes(block_group, ins->offset, 1, 1); |
| 5618 | BUG_ON(ret); | 5713 | BUG_ON(ret); |
| 5619 | btrfs_put_block_group(block_group); | 5714 | btrfs_put_block_group(block_group); |
| 5620 | ret = alloc_reserved_file_extent(trans, root, 0, root_objectid, | 5715 | ret = alloc_reserved_file_extent(trans, root, 0, root_objectid, |
| @@ -6047,6 +6142,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans, | |||
| 6047 | if (reada && level == 1) | 6142 | if (reada && level == 1) |
| 6048 | reada_walk_down(trans, root, wc, path); | 6143 | reada_walk_down(trans, root, wc, path); |
| 6049 | next = read_tree_block(root, bytenr, blocksize, generation); | 6144 | next = read_tree_block(root, bytenr, blocksize, generation); |
| 6145 | if (!next) | ||
| 6146 | return -EIO; | ||
| 6050 | btrfs_tree_lock(next); | 6147 | btrfs_tree_lock(next); |
| 6051 | btrfs_set_lock_blocking(next); | 6148 | btrfs_set_lock_blocking(next); |
| 6052 | } | 6149 | } |
| @@ -6438,10 +6535,14 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, | |||
| 6438 | BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); | 6535 | BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID); |
| 6439 | 6536 | ||
| 6440 | path = btrfs_alloc_path(); | 6537 | path = btrfs_alloc_path(); |
| 6441 | BUG_ON(!path); | 6538 | if (!path) |
| 6539 | return -ENOMEM; | ||
| 6442 | 6540 | ||
| 6443 | wc = kzalloc(sizeof(*wc), GFP_NOFS); | 6541 | wc = kzalloc(sizeof(*wc), GFP_NOFS); |
| 6444 | BUG_ON(!wc); | 6542 | if (!wc) { |
| 6543 | btrfs_free_path(path); | ||
| 6544 | return -ENOMEM; | ||
| 6545 | } | ||
| 6445 | 6546 | ||
| 6446 | btrfs_assert_tree_locked(parent); | 6547 | btrfs_assert_tree_locked(parent); |
| 6447 | parent_level = btrfs_header_level(parent); | 6548 | parent_level = btrfs_header_level(parent); |
| @@ -6899,7 +7000,11 @@ static noinline int get_new_locations(struct inode *reloc_inode, | |||
| 6899 | } | 7000 | } |
| 6900 | 7001 | ||
| 6901 | path = btrfs_alloc_path(); | 7002 | path = btrfs_alloc_path(); |
| 6902 | BUG_ON(!path); | 7003 | if (!path) { |
| 7004 | if (exts != *extents) | ||
| 7005 | kfree(exts); | ||
| 7006 | return -ENOMEM; | ||
| 7007 | } | ||
| 6903 | 7008 | ||
| 6904 | cur_pos = extent_key->objectid - offset; | 7009 | cur_pos = extent_key->objectid - offset; |
| 6905 | last_byte = extent_key->objectid + extent_key->offset; | 7010 | last_byte = extent_key->objectid + extent_key->offset; |
| @@ -6941,6 +7046,10 @@ static noinline int get_new_locations(struct inode *reloc_inode, | |||
| 6941 | struct disk_extent *old = exts; | 7046 | struct disk_extent *old = exts; |
| 6942 | max *= 2; | 7047 | max *= 2; |
| 6943 | exts = kzalloc(sizeof(*exts) * max, GFP_NOFS); | 7048 | exts = kzalloc(sizeof(*exts) * max, GFP_NOFS); |
| 7049 | if (!exts) { | ||
| 7050 | ret = -ENOMEM; | ||
| 7051 | goto out; | ||
| 7052 | } | ||
| 6944 | memcpy(exts, old, sizeof(*exts) * nr); | 7053 | memcpy(exts, old, sizeof(*exts) * nr); |
| 6945 | if (old != *extents) | 7054 | if (old != *extents) |
| 6946 | kfree(old); | 7055 | kfree(old); |
| @@ -7423,7 +7532,8 @@ static noinline int replace_extents_in_leaf(struct btrfs_trans_handle *trans, | |||
| 7423 | int ret; | 7532 | int ret; |
| 7424 | 7533 | ||
| 7425 | new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS); | 7534 | new_extent = kmalloc(sizeof(*new_extent), GFP_NOFS); |
| 7426 | BUG_ON(!new_extent); | 7535 | if (!new_extent) |
| 7536 | return -ENOMEM; | ||
| 7427 | 7537 | ||
| 7428 | ref = btrfs_lookup_leaf_ref(root, leaf->start); | 7538 | ref = btrfs_lookup_leaf_ref(root, leaf->start); |
| 7429 | BUG_ON(!ref); | 7539 | BUG_ON(!ref); |
| @@ -7609,7 +7719,8 @@ int btrfs_cleanup_reloc_trees(struct btrfs_root *root) | |||
| 7609 | 7719 | ||
| 7610 | reloc_root = btrfs_read_fs_root_no_name(root->fs_info, &location); | 7720 | reloc_root = btrfs_read_fs_root_no_name(root->fs_info, &location); |
| 7611 | BUG_ON(!reloc_root); | 7721 | BUG_ON(!reloc_root); |
| 7612 | btrfs_orphan_cleanup(reloc_root); | 7722 | ret = btrfs_orphan_cleanup(reloc_root); |
| 7723 | BUG_ON(ret); | ||
| 7613 | return 0; | 7724 | return 0; |
| 7614 | } | 7725 | } |
| 7615 | 7726 | ||
| @@ -7627,7 +7738,8 @@ static noinline int init_reloc_tree(struct btrfs_trans_handle *trans, | |||
| 7627 | return 0; | 7738 | return 0; |
| 7628 | 7739 | ||
| 7629 | root_item = kmalloc(sizeof(*root_item), GFP_NOFS); | 7740 | root_item = kmalloc(sizeof(*root_item), GFP_NOFS); |
| 7630 | BUG_ON(!root_item); | 7741 | if (!root_item) |
| 7742 | return -ENOMEM; | ||
| 7631 | 7743 | ||
| 7632 | ret = btrfs_copy_root(trans, root, root->commit_root, | 7744 | ret = btrfs_copy_root(trans, root, root->commit_root, |
| 7633 | &eb, BTRFS_TREE_RELOC_OBJECTID); | 7745 | &eb, BTRFS_TREE_RELOC_OBJECTID); |
| @@ -7653,7 +7765,7 @@ static noinline int init_reloc_tree(struct btrfs_trans_handle *trans, | |||
| 7653 | 7765 | ||
| 7654 | reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root, | 7766 | reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root, |
| 7655 | &root_key); | 7767 | &root_key); |
| 7656 | BUG_ON(!reloc_root); | 7768 | BUG_ON(IS_ERR(reloc_root)); |
| 7657 | reloc_root->last_trans = trans->transid; | 7769 | reloc_root->last_trans = trans->transid; |
| 7658 | reloc_root->commit_root = NULL; | 7770 | reloc_root->commit_root = NULL; |
| 7659 | reloc_root->ref_tree = &root->fs_info->reloc_ref_tree; | 7771 | reloc_root->ref_tree = &root->fs_info->reloc_ref_tree; |
| @@ -7906,6 +8018,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root, | |||
| 7906 | 8018 | ||
| 7907 | eb = read_tree_block(found_root, block_start, | 8019 | eb = read_tree_block(found_root, block_start, |
| 7908 | block_size, 0); | 8020 | block_size, 0); |
| 8021 | if (!eb) { | ||
| 8022 | ret = -EIO; | ||
| 8023 | goto out; | ||
| 8024 | } | ||
| 7909 | btrfs_tree_lock(eb); | 8025 | btrfs_tree_lock(eb); |
| 7910 | BUG_ON(level != btrfs_header_level(eb)); | 8026 | BUG_ON(level != btrfs_header_level(eb)); |
| 7911 | 8027 | ||
| @@ -8061,13 +8177,15 @@ int btrfs_set_block_group_ro(struct btrfs_root *root, | |||
| 8061 | 8177 | ||
| 8062 | alloc_flags = update_block_group_flags(root, cache->flags); | 8178 | alloc_flags = update_block_group_flags(root, cache->flags); |
| 8063 | if (alloc_flags != cache->flags) | 8179 | if (alloc_flags != cache->flags) |
| 8064 | do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); | 8180 | do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, |
| 8181 | CHUNK_ALLOC_FORCE); | ||
| 8065 | 8182 | ||
| 8066 | ret = set_block_group_ro(cache); | 8183 | ret = set_block_group_ro(cache); |
| 8067 | if (!ret) | 8184 | if (!ret) |
| 8068 | goto out; | 8185 | goto out; |
| 8069 | alloc_flags = get_alloc_profile(root, cache->space_info->flags); | 8186 | alloc_flags = get_alloc_profile(root, cache->space_info->flags); |
| 8070 | ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); | 8187 | ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, |
| 8188 | CHUNK_ALLOC_FORCE); | ||
| 8071 | if (ret < 0) | 8189 | if (ret < 0) |
| 8072 | goto out; | 8190 | goto out; |
| 8073 | ret = set_block_group_ro(cache); | 8191 | ret = set_block_group_ro(cache); |
| @@ -8080,7 +8198,8 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans, | |||
| 8080 | struct btrfs_root *root, u64 type) | 8198 | struct btrfs_root *root, u64 type) |
| 8081 | { | 8199 | { |
| 8082 | u64 alloc_flags = get_alloc_profile(root, type); | 8200 | u64 alloc_flags = get_alloc_profile(root, type); |
| 8083 | return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1); | 8201 | return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, |
| 8202 | CHUNK_ALLOC_FORCE); | ||
| 8084 | } | 8203 | } |
| 8085 | 8204 | ||
| 8086 | /* | 8205 | /* |
| @@ -8621,6 +8740,12 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, | |||
| 8621 | BUG_ON(!block_group); | 8740 | BUG_ON(!block_group); |
| 8622 | BUG_ON(!block_group->ro); | 8741 | BUG_ON(!block_group->ro); |
| 8623 | 8742 | ||
| 8743 | /* | ||
| 8744 | * Free the reserved super bytes from this block group before | ||
| 8745 | * remove it. | ||
| 8746 | */ | ||
| 8747 | free_excluded_extents(root, block_group); | ||
| 8748 | |||
| 8624 | memcpy(&key, &block_group->key, sizeof(key)); | 8749 | memcpy(&key, &block_group->key, sizeof(key)); |
| 8625 | if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | | 8750 | if (block_group->flags & (BTRFS_BLOCK_GROUP_DUP | |
| 8626 | BTRFS_BLOCK_GROUP_RAID1 | | 8751 | BTRFS_BLOCK_GROUP_RAID1 | |
| @@ -8724,13 +8849,84 @@ out: | |||
| 8724 | return ret; | 8849 | return ret; |
| 8725 | } | 8850 | } |
| 8726 | 8851 | ||
| 8852 | int btrfs_init_space_info(struct btrfs_fs_info *fs_info) | ||
| 8853 | { | ||
| 8854 | struct btrfs_space_info *space_info; | ||
| 8855 | int ret; | ||
| 8856 | |||
| 8857 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0, | ||
| 8858 | &space_info); | ||
| 8859 | if (ret) | ||
| 8860 | return ret; | ||
| 8861 | |||
| 8862 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0, | ||
| 8863 | &space_info); | ||
| 8864 | if (ret) | ||
| 8865 | return ret; | ||
| 8866 | |||
| 8867 | ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0, | ||
| 8868 | &space_info); | ||
| 8869 | if (ret) | ||
| 8870 | return ret; | ||
| 8871 | |||
| 8872 | return ret; | ||
| 8873 | } | ||
| 8874 | |||
| 8727 | int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) | 8875 | int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) |
| 8728 | { | 8876 | { |
| 8729 | return unpin_extent_range(root, start, end); | 8877 | return unpin_extent_range(root, start, end); |
| 8730 | } | 8878 | } |
| 8731 | 8879 | ||
| 8732 | int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, | 8880 | int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr, |
| 8733 | u64 num_bytes) | 8881 | u64 num_bytes, u64 *actual_bytes) |
| 8882 | { | ||
| 8883 | return btrfs_discard_extent(root, bytenr, num_bytes, actual_bytes); | ||
| 8884 | } | ||
| 8885 | |||
| 8886 | int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) | ||
| 8734 | { | 8887 | { |
| 8735 | return btrfs_discard_extent(root, bytenr, num_bytes); | 8888 | struct btrfs_fs_info *fs_info = root->fs_info; |
| 8889 | struct btrfs_block_group_cache *cache = NULL; | ||
| 8890 | u64 group_trimmed; | ||
| 8891 | u64 start; | ||
| 8892 | u64 end; | ||
| 8893 | u64 trimmed = 0; | ||
| 8894 | int ret = 0; | ||
| 8895 | |||
| 8896 | cache = btrfs_lookup_block_group(fs_info, range->start); | ||
| 8897 | |||
| 8898 | while (cache) { | ||
| 8899 | if (cache->key.objectid >= (range->start + range->len)) { | ||
| 8900 | btrfs_put_block_group(cache); | ||
| 8901 | break; | ||
| 8902 | } | ||
| 8903 | |||
| 8904 | start = max(range->start, cache->key.objectid); | ||
| 8905 | end = min(range->start + range->len, | ||
| 8906 | cache->key.objectid + cache->key.offset); | ||
| 8907 | |||
| 8908 | if (end - start >= range->minlen) { | ||
| 8909 | if (!block_group_cache_done(cache)) { | ||
| 8910 | ret = cache_block_group(cache, NULL, root, 0); | ||
| 8911 | if (!ret) | ||
| 8912 | wait_block_group_cache_done(cache); | ||
| 8913 | } | ||
| 8914 | ret = btrfs_trim_block_group(cache, | ||
| 8915 | &group_trimmed, | ||
| 8916 | start, | ||
| 8917 | end, | ||
| 8918 | range->minlen); | ||
| 8919 | |||
| 8920 | trimmed += group_trimmed; | ||
| 8921 | if (ret) { | ||
| 8922 | btrfs_put_block_group(cache); | ||
| 8923 | break; | ||
| 8924 | } | ||
| 8925 | } | ||
| 8926 | |||
| 8927 | cache = next_block_group(fs_info->tree_root, cache); | ||
| 8928 | } | ||
| 8929 | |||
| 8930 | range->len = trimmed; | ||
| 8931 | return ret; | ||
| 8736 | } | 8932 | } |
