|
|
@@ -2113,6 +2113,7 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
|
|
|
u64 bytenr, u64 num_bytes, u64 parent,
|
|
|
u64 root_objectid, u64 owner, u64 offset)
|
|
|
{
|
|
|
+ int old_ref_mod, new_ref_mod;
|
|
|
int ret;
|
|
|
|
|
|
BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID &&
|
|
|
@@ -2123,14 +2124,18 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
|
|
|
num_bytes, parent,
|
|
|
root_objectid, (int)owner,
|
|
|
BTRFS_ADD_DELAYED_REF, NULL,
|
|
|
- NULL, NULL);
|
|
|
+ &old_ref_mod, &new_ref_mod);
|
|
|
} else {
|
|
|
ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
|
|
|
num_bytes, parent,
|
|
|
root_objectid, owner, offset,
|
|
|
- 0, BTRFS_ADD_DELAYED_REF, NULL,
|
|
|
- NULL);
|
|
|
+ 0, BTRFS_ADD_DELAYED_REF,
|
|
|
+ &old_ref_mod, &new_ref_mod);
|
|
|
}
|
|
|
+
|
|
|
+ if (ret == 0 && old_ref_mod < 0 && new_ref_mod >= 0)
|
|
|
+ add_pinned_bytes(fs_info, -num_bytes, owner, root_objectid);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
@@ -2434,6 +2439,16 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
|
|
|
head = btrfs_delayed_node_to_head(node);
|
|
|
trace_run_delayed_ref_head(fs_info, node, head, node->action);
|
|
|
|
|
|
+ if (head->total_ref_mod < 0) {
|
|
|
+ struct btrfs_block_group_cache *cache;
|
|
|
+
|
|
|
+ cache = btrfs_lookup_block_group(fs_info, node->bytenr);
|
|
|
+ ASSERT(cache);
|
|
|
+ percpu_counter_add(&cache->space_info->total_bytes_pinned,
|
|
|
+ -node->num_bytes);
|
|
|
+ btrfs_put_block_group(cache);
|
|
|
+ }
|
|
|
+
|
|
|
if (insert_reserved) {
|
|
|
btrfs_pin_extent(fs_info, node->bytenr,
|
|
|
node->num_bytes, 1);
|
|
|
@@ -6284,6 +6299,8 @@ static int update_block_group(struct btrfs_trans_handle *trans,
|
|
|
trace_btrfs_space_reservation(info, "pinned",
|
|
|
cache->space_info->flags,
|
|
|
num_bytes, 1);
|
|
|
+ percpu_counter_add(&cache->space_info->total_bytes_pinned,
|
|
|
+ num_bytes);
|
|
|
set_extent_dirty(info->pinned_extents,
|
|
|
bytenr, bytenr + num_bytes - 1,
|
|
|
GFP_NOFS | __GFP_NOFAIL);
|
|
|
@@ -7053,8 +7070,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
|
- add_pinned_bytes(info, -num_bytes, owner_objectid,
|
|
|
- root_objectid);
|
|
|
} else {
|
|
|
if (found_extent) {
|
|
|
BUG_ON(is_data && refs_to_drop !=
|
|
|
@@ -7186,13 +7201,16 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
|
|
|
int ret;
|
|
|
|
|
|
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
|
|
|
+ int old_ref_mod, new_ref_mod;
|
|
|
+
|
|
|
ret = btrfs_add_delayed_tree_ref(fs_info, trans, buf->start,
|
|
|
buf->len, parent,
|
|
|
root->root_key.objectid,
|
|
|
btrfs_header_level(buf),
|
|
|
BTRFS_DROP_DELAYED_REF, NULL,
|
|
|
- NULL, NULL);
|
|
|
+ &old_ref_mod, &new_ref_mod);
|
|
|
BUG_ON(ret); /* -ENOMEM */
|
|
|
+ pin = old_ref_mod >= 0 && new_ref_mod < 0;
|
|
|
}
|
|
|
|
|
|
if (last_ref && btrfs_header_generation(buf) == trans->transid) {
|
|
|
@@ -7241,12 +7259,12 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
|
|
|
u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
|
|
|
u64 owner, u64 offset)
|
|
|
{
|
|
|
+ int old_ref_mod, new_ref_mod;
|
|
|
int ret;
|
|
|
|
|
|
if (btrfs_is_testing(fs_info))
|
|
|
return 0;
|
|
|
|
|
|
- add_pinned_bytes(fs_info, num_bytes, owner, root_objectid);
|
|
|
|
|
|
/*
|
|
|
* tree log blocks never actually go into the extent allocation
|
|
|
@@ -7256,20 +7274,25 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
|
|
|
WARN_ON(owner >= BTRFS_FIRST_FREE_OBJECTID);
|
|
|
/* unlocks the pinned mutex */
|
|
|
btrfs_pin_extent(fs_info, bytenr, num_bytes, 1);
|
|
|
+ old_ref_mod = new_ref_mod = 0;
|
|
|
ret = 0;
|
|
|
} else if (owner < BTRFS_FIRST_FREE_OBJECTID) {
|
|
|
ret = btrfs_add_delayed_tree_ref(fs_info, trans, bytenr,
|
|
|
num_bytes, parent,
|
|
|
root_objectid, (int)owner,
|
|
|
BTRFS_DROP_DELAYED_REF, NULL,
|
|
|
- NULL, NULL);
|
|
|
+ &old_ref_mod, &new_ref_mod);
|
|
|
} else {
|
|
|
ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr,
|
|
|
num_bytes, parent,
|
|
|
root_objectid, owner, offset,
|
|
|
0, BTRFS_DROP_DELAYED_REF,
|
|
|
- NULL, NULL);
|
|
|
+ &old_ref_mod, &new_ref_mod);
|
|
|
}
|
|
|
+
|
|
|
+ if (ret == 0 && old_ref_mod >= 0 && new_ref_mod < 0)
|
|
|
+ add_pinned_bytes(fs_info, num_bytes, owner, root_objectid);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|