diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 133 |
1 files changed, 107 insertions, 26 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index acf3ed11cfb6..c4661db2b72a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -124,7 +124,7 @@ static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) | |||
124 | return (cache->flags & bits) == bits; | 124 | return (cache->flags & bits) == bits; |
125 | } | 125 | } |
126 | 126 | ||
127 | static void btrfs_get_block_group(struct btrfs_block_group_cache *cache) | 127 | void btrfs_get_block_group(struct btrfs_block_group_cache *cache) |
128 | { | 128 | { |
129 | atomic_inc(&cache->count); | 129 | atomic_inc(&cache->count); |
130 | } | 130 | } |
@@ -5915,19 +5915,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
5915 | set_extent_dirty(info->pinned_extents, | 5915 | set_extent_dirty(info->pinned_extents, |
5916 | bytenr, bytenr + num_bytes - 1, | 5916 | bytenr, bytenr + num_bytes - 1, |
5917 | GFP_NOFS | __GFP_NOFAIL); | 5917 | GFP_NOFS | __GFP_NOFAIL); |
5918 | /* | ||
5919 | * No longer have used bytes in this block group, queue | ||
5920 | * it for deletion. | ||
5921 | */ | ||
5922 | if (old_val == 0) { | ||
5923 | spin_lock(&info->unused_bgs_lock); | ||
5924 | if (list_empty(&cache->bg_list)) { | ||
5925 | btrfs_get_block_group(cache); | ||
5926 | list_add_tail(&cache->bg_list, | ||
5927 | &info->unused_bgs); | ||
5928 | } | ||
5929 | spin_unlock(&info->unused_bgs_lock); | ||
5930 | } | ||
5931 | } | 5918 | } |
5932 | 5919 | ||
5933 | spin_lock(&trans->transaction->dirty_bgs_lock); | 5920 | spin_lock(&trans->transaction->dirty_bgs_lock); |
@@ -5939,6 +5926,22 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
5939 | } | 5926 | } |
5940 | spin_unlock(&trans->transaction->dirty_bgs_lock); | 5927 | spin_unlock(&trans->transaction->dirty_bgs_lock); |
5941 | 5928 | ||
5929 | /* | ||
5930 | * No longer have used bytes in this block group, queue it for | ||
5931 | * deletion. We do this after adding the block group to the | ||
5932 | * dirty list to avoid races between cleaner kthread and space | ||
5933 | * cache writeout. | ||
5934 | */ | ||
5935 | if (!alloc && old_val == 0) { | ||
5936 | spin_lock(&info->unused_bgs_lock); | ||
5937 | if (list_empty(&cache->bg_list)) { | ||
5938 | btrfs_get_block_group(cache); | ||
5939 | list_add_tail(&cache->bg_list, | ||
5940 | &info->unused_bgs); | ||
5941 | } | ||
5942 | spin_unlock(&info->unused_bgs_lock); | ||
5943 | } | ||
5944 | |||
5942 | btrfs_put_block_group(cache); | 5945 | btrfs_put_block_group(cache); |
5943 | total -= num_bytes; | 5946 | total -= num_bytes; |
5944 | bytenr += num_bytes; | 5947 | bytenr += num_bytes; |
@@ -8105,21 +8108,47 @@ reada: | |||
8105 | } | 8108 | } |
8106 | 8109 | ||
8107 | /* | 8110 | /* |
8108 | * TODO: Modify related function to add related node/leaf to dirty_extent_root, | 8111 | * These may not be seen by the usual inc/dec ref code so we have to |
8109 | * for later qgroup accounting. | 8112 | * add them here. |
8110 | * | ||
8111 | * Current, this function does nothing. | ||
8112 | */ | 8113 | */ |
8114 | static int record_one_subtree_extent(struct btrfs_trans_handle *trans, | ||
8115 | struct btrfs_root *root, u64 bytenr, | ||
8116 | u64 num_bytes) | ||
8117 | { | ||
8118 | struct btrfs_qgroup_extent_record *qrecord; | ||
8119 | struct btrfs_delayed_ref_root *delayed_refs; | ||
8120 | |||
8121 | qrecord = kmalloc(sizeof(*qrecord), GFP_NOFS); | ||
8122 | if (!qrecord) | ||
8123 | return -ENOMEM; | ||
8124 | |||
8125 | qrecord->bytenr = bytenr; | ||
8126 | qrecord->num_bytes = num_bytes; | ||
8127 | qrecord->old_roots = NULL; | ||
8128 | |||
8129 | delayed_refs = &trans->transaction->delayed_refs; | ||
8130 | spin_lock(&delayed_refs->lock); | ||
8131 | if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord)) | ||
8132 | kfree(qrecord); | ||
8133 | spin_unlock(&delayed_refs->lock); | ||
8134 | |||
8135 | return 0; | ||
8136 | } | ||
8137 | |||
8113 | static int account_leaf_items(struct btrfs_trans_handle *trans, | 8138 | static int account_leaf_items(struct btrfs_trans_handle *trans, |
8114 | struct btrfs_root *root, | 8139 | struct btrfs_root *root, |
8115 | struct extent_buffer *eb) | 8140 | struct extent_buffer *eb) |
8116 | { | 8141 | { |
8117 | int nr = btrfs_header_nritems(eb); | 8142 | int nr = btrfs_header_nritems(eb); |
8118 | int i, extent_type; | 8143 | int i, extent_type, ret; |
8119 | struct btrfs_key key; | 8144 | struct btrfs_key key; |
8120 | struct btrfs_file_extent_item *fi; | 8145 | struct btrfs_file_extent_item *fi; |
8121 | u64 bytenr, num_bytes; | 8146 | u64 bytenr, num_bytes; |
8122 | 8147 | ||
8148 | /* We can be called directly from walk_up_proc() */ | ||
8149 | if (!root->fs_info->quota_enabled) | ||
8150 | return 0; | ||
8151 | |||
8123 | for (i = 0; i < nr; i++) { | 8152 | for (i = 0; i < nr; i++) { |
8124 | btrfs_item_key_to_cpu(eb, &key, i); | 8153 | btrfs_item_key_to_cpu(eb, &key, i); |
8125 | 8154 | ||
@@ -8138,6 +8167,10 @@ static int account_leaf_items(struct btrfs_trans_handle *trans, | |||
8138 | continue; | 8167 | continue; |
8139 | 8168 | ||
8140 | num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); | 8169 | num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); |
8170 | |||
8171 | ret = record_one_subtree_extent(trans, root, bytenr, num_bytes); | ||
8172 | if (ret) | ||
8173 | return ret; | ||
8141 | } | 8174 | } |
8142 | return 0; | 8175 | return 0; |
8143 | } | 8176 | } |
@@ -8206,8 +8239,6 @@ static int adjust_slots_upwards(struct btrfs_root *root, | |||
8206 | 8239 | ||
8207 | /* | 8240 | /* |
8208 | * root_eb is the subtree root and is locked before this function is called. | 8241 | * root_eb is the subtree root and is locked before this function is called. |
8209 | * TODO: Modify this function to mark all (including complete shared node) | ||
8210 | * to dirty_extent_root to allow it get accounted in qgroup. | ||
8211 | */ | 8242 | */ |
8212 | static int account_shared_subtree(struct btrfs_trans_handle *trans, | 8243 | static int account_shared_subtree(struct btrfs_trans_handle *trans, |
8213 | struct btrfs_root *root, | 8244 | struct btrfs_root *root, |
@@ -8285,6 +8316,11 @@ walk_down: | |||
8285 | btrfs_tree_read_lock(eb); | 8316 | btrfs_tree_read_lock(eb); |
8286 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | 8317 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); |
8287 | path->locks[level] = BTRFS_READ_LOCK_BLOCKING; | 8318 | path->locks[level] = BTRFS_READ_LOCK_BLOCKING; |
8319 | |||
8320 | ret = record_one_subtree_extent(trans, root, child_bytenr, | ||
8321 | root->nodesize); | ||
8322 | if (ret) | ||
8323 | goto out; | ||
8288 | } | 8324 | } |
8289 | 8325 | ||
8290 | if (level == 0) { | 8326 | if (level == 0) { |
@@ -10256,6 +10292,47 @@ out: | |||
10256 | return ret; | 10292 | return ret; |
10257 | } | 10293 | } |
10258 | 10294 | ||
10295 | struct btrfs_trans_handle * | ||
10296 | btrfs_start_trans_remove_block_group(struct btrfs_fs_info *fs_info, | ||
10297 | const u64 chunk_offset) | ||
10298 | { | ||
10299 | struct extent_map_tree *em_tree = &fs_info->mapping_tree.map_tree; | ||
10300 | struct extent_map *em; | ||
10301 | struct map_lookup *map; | ||
10302 | unsigned int num_items; | ||
10303 | |||
10304 | read_lock(&em_tree->lock); | ||
10305 | em = lookup_extent_mapping(em_tree, chunk_offset, 1); | ||
10306 | read_unlock(&em_tree->lock); | ||
10307 | ASSERT(em && em->start == chunk_offset); | ||
10308 | |||
10309 | /* | ||
10310 | * We need to reserve 3 + N units from the metadata space info in order | ||
10311 | * to remove a block group (done at btrfs_remove_chunk() and at | ||
10312 | * btrfs_remove_block_group()), which are used for: | ||
10313 | * | ||
10314 | * 1 unit for adding the free space inode's orphan (located in the tree | ||
10315 | * of tree roots). | ||
10316 | * 1 unit for deleting the block group item (located in the extent | ||
10317 | * tree). | ||
10318 | * 1 unit for deleting the free space item (located in tree of tree | ||
10319 | * roots). | ||
10320 | * N units for deleting N device extent items corresponding to each | ||
10321 | * stripe (located in the device tree). | ||
10322 | * | ||
10323 | * In order to remove a block group we also need to reserve units in the | ||
10324 | * system space info in order to update the chunk tree (update one or | ||
10325 | * more device items and remove one chunk item), but this is done at | ||
10326 | * btrfs_remove_chunk() through a call to check_system_chunk(). | ||
10327 | */ | ||
10328 | map = (struct map_lookup *)em->bdev; | ||
10329 | num_items = 3 + map->num_stripes; | ||
10330 | free_extent_map(em); | ||
10331 | |||
10332 | return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root, | ||
10333 | num_items, 1); | ||
10334 | } | ||
10335 | |||
10259 | /* | 10336 | /* |
10260 | * Process the unused_bgs list and remove any that don't have any allocated | 10337 | * Process the unused_bgs list and remove any that don't have any allocated |
10261 | * space inside of them. | 10338 | * space inside of them. |
@@ -10322,8 +10399,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
10322 | * Want to do this before we do anything else so we can recover | 10399 | * Want to do this before we do anything else so we can recover |
10323 | * properly if we fail to join the transaction. | 10400 | * properly if we fail to join the transaction. |
10324 | */ | 10401 | */ |
10325 | /* 1 for btrfs_orphan_reserve_metadata() */ | 10402 | trans = btrfs_start_trans_remove_block_group(fs_info, |
10326 | trans = btrfs_start_transaction(root, 1); | 10403 | block_group->key.objectid); |
10327 | if (IS_ERR(trans)) { | 10404 | if (IS_ERR(trans)) { |
10328 | btrfs_dec_block_group_ro(root, block_group); | 10405 | btrfs_dec_block_group_ro(root, block_group); |
10329 | ret = PTR_ERR(trans); | 10406 | ret = PTR_ERR(trans); |
@@ -10403,11 +10480,15 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
10403 | * until transaction commit to do the actual discard. | 10480 | * until transaction commit to do the actual discard. |
10404 | */ | 10481 | */ |
10405 | if (trimming) { | 10482 | if (trimming) { |
10406 | WARN_ON(!list_empty(&block_group->bg_list)); | 10483 | spin_lock(&fs_info->unused_bgs_lock); |
10407 | spin_lock(&trans->transaction->deleted_bgs_lock); | 10484 | /* |
10485 | * A concurrent scrub might have added us to the list | ||
10486 | * fs_info->unused_bgs, so use a list_move operation | ||
10487 | * to add the block group to the deleted_bgs list. | ||
10488 | */ | ||
10408 | list_move(&block_group->bg_list, | 10489 | list_move(&block_group->bg_list, |
10409 | &trans->transaction->deleted_bgs); | 10490 | &trans->transaction->deleted_bgs); |
10410 | spin_unlock(&trans->transaction->deleted_bgs_lock); | 10491 | spin_unlock(&fs_info->unused_bgs_lock); |
10411 | btrfs_get_block_group(block_group); | 10492 | btrfs_get_block_group(block_group); |
10412 | } | 10493 | } |
10413 | end_trans: | 10494 | end_trans: |