Commit 86b9f2eca5e0984145e3c7698a7cd6dd65c2a93f
Committed by
Chris Mason
1 parent
55ef689900
Exists in
master
and in
7 other branches
Btrfs: Fix per root used space accounting
The bytes_used field in root item was originally planned to trace the amount of used data and tree blocks. But it never worked right since we can't trace freeing of data accurately. This patch changes it to only trace the amount of tree blocks. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Showing 5 changed files with 47 additions and 27 deletions Side-by-side Diff
fs/btrfs/ctree.c
... | ... | @@ -456,9 +456,8 @@ |
456 | 456 | extent_buffer_get(cow); |
457 | 457 | spin_unlock(&root->node_lock); |
458 | 458 | |
459 | - btrfs_free_extent(trans, root, buf->start, buf->len, | |
460 | - parent_start, root->root_key.objectid, | |
461 | - level, 0); | |
459 | + btrfs_free_tree_block(trans, root, buf->start, buf->len, | |
460 | + parent_start, root->root_key.objectid, level); | |
462 | 461 | free_extent_buffer(buf); |
463 | 462 | add_root_to_dirty_list(root); |
464 | 463 | } else { |
... | ... | @@ -473,9 +472,8 @@ |
473 | 472 | btrfs_set_node_ptr_generation(parent, parent_slot, |
474 | 473 | trans->transid); |
475 | 474 | btrfs_mark_buffer_dirty(parent); |
476 | - btrfs_free_extent(trans, root, buf->start, buf->len, | |
477 | - parent_start, root->root_key.objectid, | |
478 | - level, 0); | |
475 | + btrfs_free_tree_block(trans, root, buf->start, buf->len, | |
476 | + parent_start, root->root_key.objectid, level); | |
479 | 477 | } |
480 | 478 | if (unlock_orig) |
481 | 479 | btrfs_tree_unlock(buf); |
... | ... | @@ -1035,8 +1033,8 @@ |
1035 | 1033 | btrfs_tree_unlock(mid); |
1036 | 1034 | /* once for the path */ |
1037 | 1035 | free_extent_buffer(mid); |
1038 | - ret = btrfs_free_extent(trans, root, mid->start, mid->len, | |
1039 | - 0, root->root_key.objectid, level, 1); | |
1036 | + ret = btrfs_free_tree_block(trans, root, mid->start, mid->len, | |
1037 | + 0, root->root_key.objectid, level); | |
1040 | 1038 | /* once for the root ptr */ |
1041 | 1039 | free_extent_buffer(mid); |
1042 | 1040 | return ret; |
... | ... | @@ -1100,10 +1098,10 @@ |
1100 | 1098 | 1); |
1101 | 1099 | if (wret) |
1102 | 1100 | ret = wret; |
1103 | - wret = btrfs_free_extent(trans, root, bytenr, | |
1104 | - blocksize, 0, | |
1105 | - root->root_key.objectid, | |
1106 | - level, 0); | |
1101 | + wret = btrfs_free_tree_block(trans, root, | |
1102 | + bytenr, blocksize, 0, | |
1103 | + root->root_key.objectid, | |
1104 | + level); | |
1107 | 1105 | if (wret) |
1108 | 1106 | ret = wret; |
1109 | 1107 | } else { |
... | ... | @@ -1148,9 +1146,8 @@ |
1148 | 1146 | wret = del_ptr(trans, root, path, level + 1, pslot); |
1149 | 1147 | if (wret) |
1150 | 1148 | ret = wret; |
1151 | - wret = btrfs_free_extent(trans, root, bytenr, blocksize, | |
1152 | - 0, root->root_key.objectid, | |
1153 | - level, 0); | |
1149 | + wret = btrfs_free_tree_block(trans, root, bytenr, blocksize, | |
1150 | + 0, root->root_key.objectid, level); | |
1154 | 1151 | if (wret) |
1155 | 1152 | ret = wret; |
1156 | 1153 | } else { |
... | ... | @@ -3794,8 +3791,8 @@ |
3794 | 3791 | */ |
3795 | 3792 | btrfs_unlock_up_safe(path, 0); |
3796 | 3793 | |
3797 | - ret = btrfs_free_extent(trans, root, leaf->start, leaf->len, | |
3798 | - 0, root->root_key.objectid, 0, 0); | |
3794 | + ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len, | |
3795 | + 0, root->root_key.objectid, 0); | |
3799 | 3796 | return ret; |
3800 | 3797 | } |
3801 | 3798 | /* |
fs/btrfs/ctree.h
... | ... | @@ -1982,6 +1982,10 @@ |
1982 | 1982 | u64 parent, u64 root_objectid, |
1983 | 1983 | struct btrfs_disk_key *key, int level, |
1984 | 1984 | u64 hint, u64 empty_size); |
1985 | +int btrfs_free_tree_block(struct btrfs_trans_handle *trans, | |
1986 | + struct btrfs_root *root, | |
1987 | + u64 bytenr, u32 blocksize, | |
1988 | + u64 parent, u64 root_objectid, int level); | |
1985 | 1989 | struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, |
1986 | 1990 | struct btrfs_root *root, |
1987 | 1991 | u64 bytenr, u32 blocksize, |
fs/btrfs/extent-tree.c
... | ... | @@ -3454,14 +3454,6 @@ |
3454 | 3454 | else |
3455 | 3455 | old_val -= num_bytes; |
3456 | 3456 | btrfs_set_super_bytes_used(&info->super_copy, old_val); |
3457 | - | |
3458 | - /* block accounting for root item */ | |
3459 | - old_val = btrfs_root_used(&root->root_item); | |
3460 | - if (alloc) | |
3461 | - old_val += num_bytes; | |
3462 | - else | |
3463 | - old_val -= num_bytes; | |
3464 | - btrfs_set_root_used(&root->root_item, old_val); | |
3465 | 3457 | spin_unlock(&info->delalloc_lock); |
3466 | 3458 | |
3467 | 3459 | while (total) { |
... | ... | @@ -4049,6 +4041,21 @@ |
4049 | 4041 | return ret; |
4050 | 4042 | } |
4051 | 4043 | |
4044 | +int btrfs_free_tree_block(struct btrfs_trans_handle *trans, | |
4045 | + struct btrfs_root *root, | |
4046 | + u64 bytenr, u32 blocksize, | |
4047 | + u64 parent, u64 root_objectid, int level) | |
4048 | +{ | |
4049 | + u64 used; | |
4050 | + spin_lock(&root->node_lock); | |
4051 | + used = btrfs_root_used(&root->root_item) - blocksize; | |
4052 | + btrfs_set_root_used(&root->root_item, used); | |
4053 | + spin_unlock(&root->node_lock); | |
4054 | + | |
4055 | + return btrfs_free_extent(trans, root, bytenr, blocksize, | |
4056 | + parent, root_objectid, level, 0); | |
4057 | +} | |
4058 | + | |
4052 | 4059 | static u64 stripe_align(struct btrfs_root *root, u64 val) |
4053 | 4060 | { |
4054 | 4061 | u64 mask = ((u64)root->stripesize - 1); |
... | ... | @@ -4896,6 +4903,14 @@ |
4896 | 4903 | level, BTRFS_ADD_DELAYED_EXTENT, |
4897 | 4904 | extent_op); |
4898 | 4905 | BUG_ON(ret); |
4906 | + } | |
4907 | + | |
4908 | + if (root_objectid == root->root_key.objectid) { | |
4909 | + u64 used; | |
4910 | + spin_lock(&root->node_lock); | |
4911 | + used = btrfs_root_used(&root->root_item) + num_bytes; | |
4912 | + btrfs_set_root_used(&root->root_item, used); | |
4913 | + spin_unlock(&root->node_lock); | |
4899 | 4914 | } |
4900 | 4915 | return ret; |
4901 | 4916 | } |
fs/btrfs/ioctl.c
... | ... | @@ -289,7 +289,7 @@ |
289 | 289 | btrfs_set_root_generation(&root_item, trans->transid); |
290 | 290 | btrfs_set_root_level(&root_item, 0); |
291 | 291 | btrfs_set_root_refs(&root_item, 1); |
292 | - btrfs_set_root_used(&root_item, 0); | |
292 | + btrfs_set_root_used(&root_item, leaf->len); | |
293 | 293 | btrfs_set_root_last_snapshot(&root_item, 0); |
294 | 294 | |
295 | 295 | memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); |
fs/btrfs/transaction.c
... | ... | @@ -501,13 +501,16 @@ |
501 | 501 | { |
502 | 502 | int ret; |
503 | 503 | u64 old_root_bytenr; |
504 | + u64 old_root_used; | |
504 | 505 | struct btrfs_root *tree_root = root->fs_info->tree_root; |
505 | 506 | |
507 | + old_root_used = btrfs_root_used(&root->root_item); | |
506 | 508 | btrfs_write_dirty_block_groups(trans, root); |
507 | 509 | |
508 | 510 | while (1) { |
509 | 511 | old_root_bytenr = btrfs_root_bytenr(&root->root_item); |
510 | - if (old_root_bytenr == root->node->start) | |
512 | + if (old_root_bytenr == root->node->start && | |
513 | + old_root_used == btrfs_root_used(&root->root_item)) | |
511 | 514 | break; |
512 | 515 | |
513 | 516 | btrfs_set_root_node(&root->root_item, root->node); |
... | ... | @@ -516,6 +519,7 @@ |
516 | 519 | &root->root_item); |
517 | 520 | BUG_ON(ret); |
518 | 521 | |
522 | + old_root_used = btrfs_root_used(&root->root_item); | |
519 | 523 | ret = btrfs_write_dirty_block_groups(trans, root); |
520 | 524 | BUG_ON(ret); |
521 | 525 | } |