aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c122
-rw-r--r--fs/btrfs/tree-log.c12
3 files changed, 99 insertions, 37 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 80ab1a6f4fe3..0049fe0f3f74 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3067,6 +3067,8 @@ int btrfs_pin_extent(struct btrfs_root *root,
3067 u64 bytenr, u64 num, int reserved); 3067 u64 bytenr, u64 num, int reserved);
3068int btrfs_pin_extent_for_log_replay(struct btrfs_root *root, 3068int btrfs_pin_extent_for_log_replay(struct btrfs_root *root,
3069 u64 bytenr, u64 num_bytes); 3069 u64 bytenr, u64 num_bytes);
3070int btrfs_exclude_logged_extents(struct btrfs_root *root,
3071 struct extent_buffer *eb);
3070int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans, 3072int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
3071 struct btrfs_root *root, 3073 struct btrfs_root *root,
3072 u64 objectid, u64 offset, u64 bytenr); 3074 u64 objectid, u64 offset, u64 bytenr);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e14f8bd4b310..f84d53bc2f5d 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5214,6 +5214,80 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_root *root,
5214 return ret; 5214 return ret;
5215} 5215}
5216 5216
5217static int __exclude_logged_extent(struct btrfs_root *root, u64 start, u64 num_bytes)
5218{
5219 int ret;
5220 struct btrfs_block_group_cache *block_group;
5221 struct btrfs_caching_control *caching_ctl;
5222
5223 block_group = btrfs_lookup_block_group(root->fs_info, start);
5224 if (!block_group)
5225 return -EINVAL;
5226
5227 cache_block_group(block_group, 0);
5228 caching_ctl = get_caching_control(block_group);
5229
5230 if (!caching_ctl) {
5231 /* Logic error */
5232 BUG_ON(!block_group_cache_done(block_group));
5233 ret = btrfs_remove_free_space(block_group, start, num_bytes);
5234 } else {
5235 mutex_lock(&caching_ctl->mutex);
5236
5237 if (start >= caching_ctl->progress) {
5238 ret = add_excluded_extent(root, start, num_bytes);
5239 } else if (start + num_bytes <= caching_ctl->progress) {
5240 ret = btrfs_remove_free_space(block_group,
5241 start, num_bytes);
5242 } else {
5243 num_bytes = caching_ctl->progress - start;
5244 ret = btrfs_remove_free_space(block_group,
5245 start, num_bytes);
5246 if (ret)
5247 goto out_lock;
5248
5249 num_bytes = (start + num_bytes) -
5250 caching_ctl->progress;
5251 start = caching_ctl->progress;
5252 ret = add_excluded_extent(root, start, num_bytes);
5253 }
5254out_lock:
5255 mutex_unlock(&caching_ctl->mutex);
5256 put_caching_control(caching_ctl);
5257 }
5258 btrfs_put_block_group(block_group);
5259 return ret;
5260}
5261
5262int btrfs_exclude_logged_extents(struct btrfs_root *log,
5263 struct extent_buffer *eb)
5264{
5265 struct btrfs_file_extent_item *item;
5266 struct btrfs_key key;
5267 int found_type;
5268 int i;
5269
5270 if (!btrfs_fs_incompat(log->fs_info, MIXED_GROUPS))
5271 return 0;
5272
5273 for (i = 0; i < btrfs_header_nritems(eb); i++) {
5274 btrfs_item_key_to_cpu(eb, &key, i);
5275 if (key.type != BTRFS_EXTENT_DATA_KEY)
5276 continue;
5277 item = btrfs_item_ptr(eb, i, struct btrfs_file_extent_item);
5278 found_type = btrfs_file_extent_type(eb, item);
5279 if (found_type == BTRFS_FILE_EXTENT_INLINE)
5280 continue;
5281 if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
5282 continue;
5283 key.objectid = btrfs_file_extent_disk_bytenr(eb, item);
5284 key.offset = btrfs_file_extent_disk_num_bytes(eb, item);
5285 __exclude_logged_extent(log, key.objectid, key.offset);
5286 }
5287
5288 return 0;
5289}
5290
5217/** 5291/**
5218 * btrfs_update_reserved_bytes - update the block_group and space info counters 5292 * btrfs_update_reserved_bytes - update the block_group and space info counters
5219 * @cache: The cache we are manipulating 5293 * @cache: The cache we are manipulating
@@ -6585,52 +6659,26 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
6585{ 6659{
6586 int ret; 6660 int ret;
6587 struct btrfs_block_group_cache *block_group; 6661 struct btrfs_block_group_cache *block_group;
6588 struct btrfs_caching_control *caching_ctl;
6589 u64 start = ins->objectid;
6590 u64 num_bytes = ins->offset;
6591
6592 block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
6593 cache_block_group(block_group, 0);
6594 caching_ctl = get_caching_control(block_group);
6595 6662
6596 if (!caching_ctl) { 6663 /*
6597 BUG_ON(!block_group_cache_done(block_group)); 6664 * Mixed block groups will exclude before processing the log so we only
6598 ret = btrfs_remove_free_space(block_group, start, num_bytes); 6665 * need to do the exlude dance if this fs isn't mixed.
6599 if (ret) 6666 */
6600 goto out; 6667 if (!btrfs_fs_incompat(root->fs_info, MIXED_GROUPS)) {
6601 } else { 6668 ret = __exclude_logged_extent(root, ins->objectid, ins->offset);
6602 mutex_lock(&caching_ctl->mutex);
6603
6604 if (start >= caching_ctl->progress) {
6605 ret = add_excluded_extent(root, start, num_bytes);
6606 } else if (start + num_bytes <= caching_ctl->progress) {
6607 ret = btrfs_remove_free_space(block_group,
6608 start, num_bytes);
6609 } else {
6610 num_bytes = caching_ctl->progress - start;
6611 ret = btrfs_remove_free_space(block_group,
6612 start, num_bytes);
6613 if (ret)
6614 goto out_lock;
6615
6616 start = caching_ctl->progress;
6617 num_bytes = ins->objectid + ins->offset -
6618 caching_ctl->progress;
6619 ret = add_excluded_extent(root, start, num_bytes);
6620 }
6621out_lock:
6622 mutex_unlock(&caching_ctl->mutex);
6623 put_caching_control(caching_ctl);
6624 if (ret) 6669 if (ret)
6625 goto out; 6670 return ret;
6626 } 6671 }
6627 6672
6673 block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
6674 if (!block_group)
6675 return -EINVAL;
6676
6628 ret = btrfs_update_reserved_bytes(block_group, ins->offset, 6677 ret = btrfs_update_reserved_bytes(block_group, ins->offset,
6629 RESERVE_ALLOC_NO_ACCOUNT); 6678 RESERVE_ALLOC_NO_ACCOUNT);
6630 BUG_ON(ret); /* logic error */ 6679 BUG_ON(ret); /* logic error */
6631 ret = alloc_reserved_file_extent(trans, root, 0, root_objectid, 6680 ret = alloc_reserved_file_extent(trans, root, 0, root_objectid,
6632 0, owner, offset, ins, 1); 6681 0, owner, offset, ins, 1);
6633out:
6634 btrfs_put_block_group(block_group); 6682 btrfs_put_block_group(block_group);
6635 return ret; 6683 return ret;
6636} 6684}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 831ddd4bf897..2c6791493637 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -280,11 +280,23 @@ static int process_one_buffer(struct btrfs_root *log,
280{ 280{
281 int ret = 0; 281 int ret = 0;
282 282
283 /*
284 * If this fs is mixed then we need to be able to process the leaves to
285 * pin down any logged extents, so we have to read the block.
286 */
287 if (btrfs_fs_incompat(log->fs_info, MIXED_GROUPS)) {
288 ret = btrfs_read_buffer(eb, gen);
289 if (ret)
290 return ret;
291 }
292
283 if (wc->pin) 293 if (wc->pin)
284 ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root, 294 ret = btrfs_pin_extent_for_log_replay(log->fs_info->extent_root,
285 eb->start, eb->len); 295 eb->start, eb->len);
286 296
287 if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) { 297 if (!ret && btrfs_buffer_uptodate(eb, gen, 0)) {
298 if (wc->pin && btrfs_header_level(eb) == 0)
299 ret = btrfs_exclude_logged_extents(log, eb);
288 if (wc->write) 300 if (wc->write)
289 btrfs_write_tree_block(eb); 301 btrfs_write_tree_block(eb);
290 if (wc->wait) 302 if (wc->wait)