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>
This commit is contained in:
Yan, Zheng 2009-11-12 09:36:50 +00:00 committed by Chris Mason
parent 55ef689900
commit 86b9f2eca5
5 changed files with 47 additions and 27 deletions

View File

@ -456,9 +456,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
extent_buffer_get(cow); extent_buffer_get(cow);
spin_unlock(&root->node_lock); spin_unlock(&root->node_lock);
btrfs_free_extent(trans, root, buf->start, buf->len, btrfs_free_tree_block(trans, root, buf->start, buf->len,
parent_start, root->root_key.objectid, parent_start, root->root_key.objectid, level);
level, 0);
free_extent_buffer(buf); free_extent_buffer(buf);
add_root_to_dirty_list(root); add_root_to_dirty_list(root);
} else { } else {
@ -473,9 +472,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
btrfs_set_node_ptr_generation(parent, parent_slot, btrfs_set_node_ptr_generation(parent, parent_slot,
trans->transid); trans->transid);
btrfs_mark_buffer_dirty(parent); btrfs_mark_buffer_dirty(parent);
btrfs_free_extent(trans, root, buf->start, buf->len, btrfs_free_tree_block(trans, root, buf->start, buf->len,
parent_start, root->root_key.objectid, parent_start, root->root_key.objectid, level);
level, 0);
} }
if (unlock_orig) if (unlock_orig)
btrfs_tree_unlock(buf); btrfs_tree_unlock(buf);
@ -1035,8 +1033,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
btrfs_tree_unlock(mid); btrfs_tree_unlock(mid);
/* once for the path */ /* once for the path */
free_extent_buffer(mid); free_extent_buffer(mid);
ret = btrfs_free_extent(trans, root, mid->start, mid->len, ret = btrfs_free_tree_block(trans, root, mid->start, mid->len,
0, root->root_key.objectid, level, 1); 0, root->root_key.objectid, level);
/* once for the root ptr */ /* once for the root ptr */
free_extent_buffer(mid); free_extent_buffer(mid);
return ret; return ret;
@ -1100,10 +1098,10 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
1); 1);
if (wret) if (wret)
ret = wret; ret = wret;
wret = btrfs_free_extent(trans, root, bytenr, wret = btrfs_free_tree_block(trans, root,
blocksize, 0, bytenr, blocksize, 0,
root->root_key.objectid, root->root_key.objectid,
level, 0); level);
if (wret) if (wret)
ret = wret; ret = wret;
} else { } else {
@ -1148,9 +1146,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
wret = del_ptr(trans, root, path, level + 1, pslot); wret = del_ptr(trans, root, path, level + 1, pslot);
if (wret) if (wret)
ret = wret; ret = wret;
wret = btrfs_free_extent(trans, root, bytenr, blocksize, wret = btrfs_free_tree_block(trans, root, bytenr, blocksize,
0, root->root_key.objectid, 0, root->root_key.objectid, level);
level, 0);
if (wret) if (wret)
ret = wret; ret = wret;
} else { } else {
@ -3794,8 +3791,8 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
*/ */
btrfs_unlock_up_safe(path, 0); btrfs_unlock_up_safe(path, 0);
ret = btrfs_free_extent(trans, root, leaf->start, leaf->len, ret = btrfs_free_tree_block(trans, root, leaf->start, leaf->len,
0, root->root_key.objectid, 0, 0); 0, root->root_key.objectid, 0);
return ret; return ret;
} }
/* /*

View File

@ -1982,6 +1982,10 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
u64 parent, u64 root_objectid, u64 parent, u64 root_objectid,
struct btrfs_disk_key *key, int level, struct btrfs_disk_key *key, int level,
u64 hint, u64 empty_size); u64 hint, u64 empty_size);
int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 bytenr, u32 blocksize,
u64 parent, u64 root_objectid, int level);
struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
u64 bytenr, u32 blocksize, u64 bytenr, u32 blocksize,

View File

@ -3454,14 +3454,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
else else
old_val -= num_bytes; old_val -= num_bytes;
btrfs_set_super_bytes_used(&info->super_copy, old_val); btrfs_set_super_bytes_used(&info->super_copy, old_val);
/* block accounting for root item */
old_val = btrfs_root_used(&root->root_item);
if (alloc)
old_val += num_bytes;
else
old_val -= num_bytes;
btrfs_set_root_used(&root->root_item, old_val);
spin_unlock(&info->delalloc_lock); spin_unlock(&info->delalloc_lock);
while (total) { while (total) {
@ -4049,6 +4041,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
return ret; return ret;
} }
int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 bytenr, u32 blocksize,
u64 parent, u64 root_objectid, int level)
{
u64 used;
spin_lock(&root->node_lock);
used = btrfs_root_used(&root->root_item) - blocksize;
btrfs_set_root_used(&root->root_item, used);
spin_unlock(&root->node_lock);
return btrfs_free_extent(trans, root, bytenr, blocksize,
parent, root_objectid, level, 0);
}
static u64 stripe_align(struct btrfs_root *root, u64 val) static u64 stripe_align(struct btrfs_root *root, u64 val)
{ {
u64 mask = ((u64)root->stripesize - 1); u64 mask = ((u64)root->stripesize - 1);
@ -4897,6 +4904,14 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans,
extent_op); extent_op);
BUG_ON(ret); BUG_ON(ret);
} }
if (root_objectid == root->root_key.objectid) {
u64 used;
spin_lock(&root->node_lock);
used = btrfs_root_used(&root->root_item) + num_bytes;
btrfs_set_root_used(&root->root_item, used);
spin_unlock(&root->node_lock);
}
return ret; return ret;
} }

View File

@ -289,7 +289,7 @@ static noinline int create_subvol(struct btrfs_root *root,
btrfs_set_root_generation(&root_item, trans->transid); btrfs_set_root_generation(&root_item, trans->transid);
btrfs_set_root_level(&root_item, 0); btrfs_set_root_level(&root_item, 0);
btrfs_set_root_refs(&root_item, 1); btrfs_set_root_refs(&root_item, 1);
btrfs_set_root_used(&root_item, 0); btrfs_set_root_used(&root_item, leaf->len);
btrfs_set_root_last_snapshot(&root_item, 0); btrfs_set_root_last_snapshot(&root_item, 0);
memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress)); memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));

View File

@ -501,13 +501,16 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
{ {
int ret; int ret;
u64 old_root_bytenr; u64 old_root_bytenr;
u64 old_root_used;
struct btrfs_root *tree_root = root->fs_info->tree_root; struct btrfs_root *tree_root = root->fs_info->tree_root;
old_root_used = btrfs_root_used(&root->root_item);
btrfs_write_dirty_block_groups(trans, root); btrfs_write_dirty_block_groups(trans, root);
while (1) { while (1) {
old_root_bytenr = btrfs_root_bytenr(&root->root_item); old_root_bytenr = btrfs_root_bytenr(&root->root_item);
if (old_root_bytenr == root->node->start) if (old_root_bytenr == root->node->start &&
old_root_used == btrfs_root_used(&root->root_item))
break; break;
btrfs_set_root_node(&root->root_item, root->node); btrfs_set_root_node(&root->root_item, root->node);
@ -516,6 +519,7 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
&root->root_item); &root->root_item);
BUG_ON(ret); BUG_ON(ret);
old_root_used = btrfs_root_used(&root->root_item);
ret = btrfs_write_dirty_block_groups(trans, root); ret = btrfs_write_dirty_block_groups(trans, root);
BUG_ON(ret); BUG_ON(ret);
} }