Commit 86b9f2eca5e0984145e3c7698a7cd6dd65c2a93f

Authored by Yan, Zheng
Committed by Chris Mason
1 parent 55ef689900

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

... ... @@ -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 /*
... ... @@ -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 }
... ... @@ -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 }