mirror of
https://github.com/kdave/btrfs-progs
synced 2025-04-09 02:31:19 +00:00
pin freed blocks from the FS tree too
This commit is contained in:
parent
80fabe2ee0
commit
3d8c87f4f7
14
ctree.c
14
ctree.c
@ -55,13 +55,13 @@ static int btrfs_cow_block(struct btrfs_root *root,
|
|||||||
root->node = cow;
|
root->node = cow;
|
||||||
cow->count++;
|
cow->count++;
|
||||||
if (buf != root->commit_root)
|
if (buf != root->commit_root)
|
||||||
btrfs_free_extent(root, buf->blocknr, 1);
|
btrfs_free_extent(root, buf->blocknr, 1, 1);
|
||||||
btrfs_block_release(root, buf);
|
btrfs_block_release(root, buf);
|
||||||
} else {
|
} else {
|
||||||
btrfs_set_node_blockptr(&parent->node, parent_slot,
|
btrfs_set_node_blockptr(&parent->node, parent_slot,
|
||||||
cow->blocknr);
|
cow->blocknr);
|
||||||
BUG_ON(list_empty(&parent->dirty));
|
BUG_ON(list_empty(&parent->dirty));
|
||||||
btrfs_free_extent(root, buf->blocknr, 1);
|
btrfs_free_extent(root, buf->blocknr, 1, 1);
|
||||||
}
|
}
|
||||||
btrfs_block_release(root, buf);
|
btrfs_block_release(root, buf);
|
||||||
return 0;
|
return 0;
|
||||||
@ -311,7 +311,7 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
/* once for the root ptr */
|
/* once for the root ptr */
|
||||||
btrfs_block_release(root, mid_buf);
|
btrfs_block_release(root, mid_buf);
|
||||||
clean_tree_block(root, mid_buf);
|
clean_tree_block(root, mid_buf);
|
||||||
return btrfs_free_extent(root, blocknr, 1);
|
return btrfs_free_extent(root, blocknr, 1, 1);
|
||||||
}
|
}
|
||||||
parent = &parent_buf->node;
|
parent = &parent_buf->node;
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
wret = del_ptr(root, path, level + 1, pslot + 1);
|
wret = del_ptr(root, path, level + 1, pslot + 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
wret = btrfs_free_extent(root, blocknr, 1);
|
wret = btrfs_free_extent(root, blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
} else {
|
} else {
|
||||||
@ -388,7 +388,7 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
wret = del_ptr(root, path, level + 1, pslot);
|
wret = del_ptr(root, path, level + 1, pslot);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
wret = btrfs_free_extent(root, blocknr, 1);
|
wret = btrfs_free_extent(root, blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
} else {
|
} else {
|
||||||
@ -1310,7 +1310,7 @@ int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path)
|
|||||||
wret = del_ptr(root, path, 1, path->slots[1]);
|
wret = del_ptr(root, path, 1, path->slots[1]);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
wret = btrfs_free_extent(root, leaf_buf->blocknr, 1);
|
wret = btrfs_free_extent(root, leaf_buf->blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
}
|
}
|
||||||
@ -1348,7 +1348,7 @@ int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path)
|
|||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
btrfs_block_release(root, leaf_buf);
|
btrfs_block_release(root, leaf_buf);
|
||||||
wret = btrfs_free_extent(root, blocknr, 1);
|
wret = btrfs_free_extent(root, blocknr, 1, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
} else {
|
} else {
|
||||||
|
3
ctree.h
3
ctree.h
@ -658,7 +658,8 @@ static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l)
|
|||||||
|
|
||||||
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root);
|
struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root);
|
||||||
int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf);
|
int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf);
|
||||||
int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks);
|
int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
||||||
|
int pin);
|
||||||
int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key,
|
||||||
struct btrfs_path *p, int ins_len, int cow);
|
struct btrfs_path *p, int ins_len, int cow);
|
||||||
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
|
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
|
||||||
|
@ -95,6 +95,7 @@ int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf)
|
|||||||
int btrfs_finish_extent_commit(struct btrfs_root *root)
|
int btrfs_finish_extent_commit(struct btrfs_root *root)
|
||||||
{
|
{
|
||||||
unsigned long gang[8];
|
unsigned long gang[8];
|
||||||
|
u64 first = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -104,11 +105,13 @@ int btrfs_finish_extent_commit(struct btrfs_root *root)
|
|||||||
ARRAY_SIZE(gang));
|
ARRAY_SIZE(gang));
|
||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
|
if (!first)
|
||||||
|
first = gang[0];
|
||||||
for (i = 0; i < ret; i++) {
|
for (i = 0; i < ret; i++) {
|
||||||
radix_tree_delete(&root->pinned_radix, gang[i]);
|
radix_tree_delete(&root->pinned_radix, gang[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
root->last_insert.objectid = 0;
|
root->last_insert.objectid = first;
|
||||||
root->last_insert.offset = 0;
|
root->last_insert.offset = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -140,7 +143,8 @@ static int finish_current_insert(struct btrfs_root *extent_root)
|
|||||||
/*
|
/*
|
||||||
* remove an extent from the root, returns 0 on success
|
* remove an extent from the root, returns 0 on success
|
||||||
*/
|
*/
|
||||||
static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks)
|
static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
||||||
|
int pin)
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
@ -150,6 +154,7 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks)
|
|||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
u32 refs;
|
u32 refs;
|
||||||
|
|
||||||
|
BUG_ON(pin && num_blocks != 1);
|
||||||
key.objectid = blocknr;
|
key.objectid = blocknr;
|
||||||
key.flags = 0;
|
key.flags = 0;
|
||||||
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||||
@ -170,7 +175,7 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks)
|
|||||||
refs = btrfs_extent_refs(ei) - 1;
|
refs = btrfs_extent_refs(ei) - 1;
|
||||||
btrfs_set_extent_refs(ei, refs);
|
btrfs_set_extent_refs(ei, refs);
|
||||||
if (refs == 0) {
|
if (refs == 0) {
|
||||||
if (!root->ref_cows) {
|
if (pin) {
|
||||||
int err;
|
int err;
|
||||||
radix_tree_preload(GFP_KERNEL);
|
radix_tree_preload(GFP_KERNEL);
|
||||||
err = radix_tree_insert(&extent_root->pinned_radix,
|
err = radix_tree_insert(&extent_root->pinned_radix,
|
||||||
@ -179,8 +184,7 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks)
|
|||||||
radix_tree_preload_end();
|
radix_tree_preload_end();
|
||||||
}
|
}
|
||||||
ret = btrfs_del_item(extent_root, &path);
|
ret = btrfs_del_item(extent_root, &path);
|
||||||
if (root != extent_root &&
|
if (!pin && extent_root->last_insert.objectid > blocknr)
|
||||||
extent_root->last_insert.objectid > blocknr)
|
|
||||||
extent_root->last_insert.objectid = blocknr;
|
extent_root->last_insert.objectid = blocknr;
|
||||||
if (ret)
|
if (ret)
|
||||||
BUG();
|
BUG();
|
||||||
@ -208,7 +212,8 @@ static int del_pending_extents(struct btrfs_root *extent_root)
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
for (i = 0; i < ret; i++) {
|
for (i = 0; i < ret; i++) {
|
||||||
ret = __free_extent(extent_root, gang[i]->blocknr, 1);
|
ret = __free_extent(extent_root,
|
||||||
|
gang[i]->blocknr, 1, 1);
|
||||||
radix_tree_tag_clear(&extent_root->cache_radix,
|
radix_tree_tag_clear(&extent_root->cache_radix,
|
||||||
gang[i]->blocknr,
|
gang[i]->blocknr,
|
||||||
CTREE_EXTENT_PENDING_DEL);
|
CTREE_EXTENT_PENDING_DEL);
|
||||||
@ -230,7 +235,8 @@ static int run_pending(struct btrfs_root *extent_root)
|
|||||||
/*
|
/*
|
||||||
* remove an extent from the root, returns 0 on success
|
* remove an extent from the root, returns 0 on success
|
||||||
*/
|
*/
|
||||||
int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks)
|
int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks,
|
||||||
|
int pin)
|
||||||
{
|
{
|
||||||
struct btrfs_root *extent_root = root->extent_root;
|
struct btrfs_root *extent_root = root->extent_root;
|
||||||
struct btrfs_buffer *t;
|
struct btrfs_buffer *t;
|
||||||
@ -243,7 +249,7 @@ int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks)
|
|||||||
CTREE_EXTENT_PENDING_DEL);
|
CTREE_EXTENT_PENDING_DEL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ret = __free_extent(root, blocknr, num_blocks);
|
ret = __free_extent(root, blocknr, num_blocks, pin);
|
||||||
pending_ret = run_pending(root->extent_root);
|
pending_ret = run_pending(root->extent_root);
|
||||||
return ret ? ret : pending_ret;
|
return ret ? ret : pending_ret;
|
||||||
}
|
}
|
||||||
@ -451,7 +457,7 @@ static int walk_down_tree(struct btrfs_root *root,
|
|||||||
ret = lookup_block_ref(root, blocknr, &refs);
|
ret = lookup_block_ref(root, blocknr, &refs);
|
||||||
if (refs != 1 || *level == 1) {
|
if (refs != 1 || *level == 1) {
|
||||||
path->slots[*level]++;
|
path->slots[*level]++;
|
||||||
ret = btrfs_free_extent(root, blocknr, 1);
|
ret = btrfs_free_extent(root, blocknr, 1, 1);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -464,7 +470,7 @@ static int walk_down_tree(struct btrfs_root *root,
|
|||||||
path->slots[*level] = 0;
|
path->slots[*level] = 0;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
ret = btrfs_free_extent(root, path->nodes[*level]->blocknr, 1);
|
ret = btrfs_free_extent(root, path->nodes[*level]->blocknr, 1, 1);
|
||||||
btrfs_block_release(root, path->nodes[*level]);
|
btrfs_block_release(root, path->nodes[*level]);
|
||||||
path->nodes[*level] = NULL;
|
path->nodes[*level] = NULL;
|
||||||
*level += 1;
|
*level += 1;
|
||||||
@ -492,7 +498,7 @@ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path,
|
|||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
ret = btrfs_free_extent(root,
|
ret = btrfs_free_extent(root,
|
||||||
path->nodes[*level]->blocknr, 1);
|
path->nodes[*level]->blocknr, 1, 1);
|
||||||
btrfs_block_release(root, path->nodes[*level]);
|
btrfs_block_release(root, path->nodes[*level]);
|
||||||
path->nodes[*level] = NULL;
|
path->nodes[*level] = NULL;
|
||||||
*level = i + 1;
|
*level = i + 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user