Skip to content

Commit 8c38938

Browse files
josefbacikkdave
authored andcommitted
btrfs: move the root freeing stuff into btrfs_put_root
There are a few different ways to free roots, either you allocated them yourself and you just do free_extent_buffer(root->node); free_extent_buffer(root->commit_node); btrfs_put_root(root); Which is the pattern for log roots. Or for snapshots/subvolumes that are being dropped you simply call btrfs_free_fs_root() which does all the cleanup for you. Unify this all into btrfs_put_root(), so that we don't free up things associated with the root until the last reference is dropped. This makes the root freeing code much more significant. The only caveat is at close_ctree() time we have to free the extent buffers for all of our main roots (extent_root, chunk_root, etc) because we have to drop the btree_inode and we'll run into issues if we hold onto those nodes until ->kill_sb() time. This will be addressed in the future when we kill the btree_inode. Signed-off-by: Josef Bacik <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 0e996e7 commit 8c38938

File tree

9 files changed

+50
-76
lines changed

9 files changed

+50
-76
lines changed

fs/btrfs/disk-io.c

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,11 +1255,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
12551255
return root;
12561256

12571257
fail:
1258-
if (leaf) {
1258+
if (leaf)
12591259
btrfs_tree_unlock(leaf);
1260-
free_extent_buffer(root->commit_root);
1261-
free_extent_buffer(leaf);
1262-
}
12631260
btrfs_put_root(root);
12641261

12651262
return ERR_PTR(ret);
@@ -1382,10 +1379,10 @@ struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root,
13821379
generation, level, NULL);
13831380
if (IS_ERR(root->node)) {
13841381
ret = PTR_ERR(root->node);
1382+
root->node = NULL;
13851383
goto find_fail;
13861384
} else if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
13871385
ret = -EIO;
1388-
free_extent_buffer(root->node);
13891386
goto find_fail;
13901387
}
13911388
root->commit_root = btrfs_root_node(root);
@@ -1617,14 +1614,14 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
16171614
if (ret) {
16181615
btrfs_put_root(root);
16191616
if (ret == -EEXIST) {
1620-
btrfs_free_fs_root(root);
1617+
btrfs_put_root(root);
16211618
goto again;
16221619
}
16231620
goto fail;
16241621
}
16251622
return root;
16261623
fail:
1627-
btrfs_free_fs_root(root);
1624+
btrfs_put_root(root);
16281625
return ERR_PTR(ret);
16291626
}
16301627

@@ -1996,11 +1993,35 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
19961993
free_root_extent_buffers(info->csum_root);
19971994
free_root_extent_buffers(info->quota_root);
19981995
free_root_extent_buffers(info->uuid_root);
1996+
free_root_extent_buffers(info->fs_root);
19991997
if (free_chunk_root)
20001998
free_root_extent_buffers(info->chunk_root);
20011999
free_root_extent_buffers(info->free_space_root);
20022000
}
20032001

2002+
void btrfs_put_root(struct btrfs_root *root)
2003+
{
2004+
if (!root)
2005+
return;
2006+
2007+
if (refcount_dec_and_test(&root->refs)) {
2008+
WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree));
2009+
if (root->anon_dev)
2010+
free_anon_bdev(root->anon_dev);
2011+
btrfs_drew_lock_destroy(&root->snapshot_lock);
2012+
free_extent_buffer(root->node);
2013+
free_extent_buffer(root->commit_root);
2014+
kfree(root->free_ino_ctl);
2015+
kfree(root->free_ino_pinned);
2016+
#ifdef CONFIG_BTRFS_DEBUG
2017+
spin_lock(&root->fs_info->fs_roots_radix_lock);
2018+
list_del_init(&root->leak_list);
2019+
spin_unlock(&root->fs_info->fs_roots_radix_lock);
2020+
#endif
2021+
kfree(root);
2022+
}
2023+
}
2024+
20042025
void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
20052026
{
20062027
int ret;
@@ -2012,13 +2033,10 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
20122033
struct btrfs_root, root_list);
20132034
list_del(&gang[0]->root_list);
20142035

2015-
if (test_bit(BTRFS_ROOT_IN_RADIX, &gang[0]->state)) {
2036+
if (test_bit(BTRFS_ROOT_IN_RADIX, &gang[0]->state))
20162037
btrfs_drop_and_free_fs_root(fs_info, gang[0]);
2017-
} else {
2018-
free_extent_buffer(gang[0]->node);
2019-
free_extent_buffer(gang[0]->commit_root);
2038+
else
20202039
btrfs_put_root(gang[0]);
2021-
}
20222040
}
20232041

20242042
while (1) {
@@ -2223,11 +2241,11 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
22232241
if (IS_ERR(log_tree_root->node)) {
22242242
btrfs_warn(fs_info, "failed to read log tree");
22252243
ret = PTR_ERR(log_tree_root->node);
2244+
log_tree_root->node = NULL;
22262245
btrfs_put_root(log_tree_root);
22272246
return ret;
22282247
} else if (!extent_buffer_uptodate(log_tree_root->node)) {
22292248
btrfs_err(fs_info, "failed to read log tree");
2230-
free_extent_buffer(log_tree_root->node);
22312249
btrfs_put_root(log_tree_root);
22322250
return -EIO;
22332251
}
@@ -2236,7 +2254,6 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
22362254
if (ret) {
22372255
btrfs_handle_fs_error(fs_info, ret,
22382256
"Failed to recover log tree");
2239-
free_extent_buffer(log_tree_root->node);
22402257
btrfs_put_root(log_tree_root);
22412258
return ret;
22422259
}
@@ -3901,8 +3918,6 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
39013918
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
39023919
btrfs_free_log(NULL, root);
39033920
if (root->reloc_root) {
3904-
free_extent_buffer(root->reloc_root->node);
3905-
free_extent_buffer(root->reloc_root->commit_root);
39063921
btrfs_put_root(root->reloc_root);
39073922
root->reloc_root = NULL;
39083923
}
@@ -3916,19 +3931,6 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
39163931
iput(root->ino_cache_inode);
39173932
root->ino_cache_inode = NULL;
39183933
}
3919-
btrfs_free_fs_root(root);
3920-
}
3921-
3922-
void btrfs_free_fs_root(struct btrfs_root *root)
3923-
{
3924-
WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree));
3925-
if (root->anon_dev)
3926-
free_anon_bdev(root->anon_dev);
3927-
btrfs_drew_lock_destroy(&root->snapshot_lock);
3928-
free_extent_buffer(root->node);
3929-
free_extent_buffer(root->commit_root);
3930-
kfree(root->free_ino_ctl);
3931-
kfree(root->free_ino_pinned);
39323934
btrfs_put_root(root);
39333935
}
39343936

@@ -4093,8 +4095,6 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
40934095
btrfs_sysfs_remove_mounted(fs_info);
40944096
btrfs_sysfs_remove_fsid(fs_info->fs_devices);
40954097

4096-
btrfs_free_fs_roots(fs_info);
4097-
40984098
btrfs_put_block_group_cache(fs_info);
40994099

41004100
/*
@@ -4106,6 +4106,7 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
41064106

41074107
clear_bit(BTRFS_FS_OPEN, &fs_info->flags);
41084108
free_root_pointers(fs_info, true);
4109+
btrfs_free_fs_roots(fs_info);
41094110

41104111
/*
41114112
* We must free the block groups after dropping the fs_roots as we could

fs/btrfs/disk-io.h

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ void btrfs_btree_balance_dirty(struct btrfs_fs_info *fs_info);
7676
void btrfs_btree_balance_dirty_nodelay(struct btrfs_fs_info *fs_info);
7777
void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
7878
struct btrfs_root *root);
79-
void btrfs_free_fs_root(struct btrfs_root *root);
8079

8180
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
8281
struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info);
@@ -98,20 +97,7 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root)
9897
return NULL;
9998
}
10099

101-
static inline void btrfs_put_root(struct btrfs_root *root)
102-
{
103-
if (!root)
104-
return;
105-
if (refcount_dec_and_test(&root->refs)) {
106-
#ifdef CONFIG_BTRFS_DEBUG
107-
spin_lock(&root->fs_info->fs_roots_radix_lock);
108-
list_del_init(&root->leak_list);
109-
spin_unlock(&root->fs_info->fs_roots_radix_lock);
110-
#endif
111-
kfree(root);
112-
}
113-
}
114-
100+
void btrfs_put_root(struct btrfs_root *root);
115101
void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
116102
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
117103
int atomic);

fs/btrfs/extent-tree.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5485,13 +5485,10 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc)
54855485
}
54865486
}
54875487

5488-
if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state)) {
5488+
if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state))
54895489
btrfs_add_dropped_root(trans, root);
5490-
} else {
5491-
free_extent_buffer(root->node);
5492-
free_extent_buffer(root->commit_root);
5490+
else
54935491
btrfs_put_root(root);
5494-
}
54955492
root_dropped = true;
54965493
out_end_trans:
54975494
btrfs_end_transaction_throttle(trans);

fs/btrfs/extent_io.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,21 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info)
6464
struct extent_buffer *eb;
6565
unsigned long flags;
6666

67+
/*
68+
* If we didn't get into open_ctree our allocated_ebs will not be
69+
* initialized, so just skip this.
70+
*/
71+
if (!fs_info->allocated_ebs.next)
72+
return;
73+
6774
spin_lock_irqsave(&fs_info->eb_leak_lock, flags);
6875
while (!list_empty(&fs_info->allocated_ebs)) {
6976
eb = list_first_entry(&fs_info->allocated_ebs,
7077
struct extent_buffer, leak_list);
71-
pr_err("BTRFS: buffer leak start %llu len %lu refs %d bflags %lu\n",
72-
eb->start, eb->len, atomic_read(&eb->refs), eb->bflags);
78+
pr_err(
79+
"BTRFS: buffer leak start %llu len %lu refs %d bflags %lu owner %llu\n",
80+
eb->start, eb->len, atomic_read(&eb->refs), eb->bflags,
81+
btrfs_header_owner(eb));
7382
list_del(&eb->leak_list);
7483
kmem_cache_free(extent_buffer_cache, eb);
7584
}
@@ -4875,7 +4884,6 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
48754884

48764885
static void __free_extent_buffer(struct extent_buffer *eb)
48774886
{
4878-
btrfs_leak_debug_del(&eb->fs_info->eb_leak_lock, &eb->leak_list);
48794887
kmem_cache_free(extent_buffer_cache, eb);
48804888
}
48814889

@@ -4941,6 +4949,7 @@ static void btrfs_release_extent_buffer_pages(struct extent_buffer *eb)
49414949
static inline void btrfs_release_extent_buffer(struct extent_buffer *eb)
49424950
{
49434951
btrfs_release_extent_buffer_pages(eb);
4952+
btrfs_leak_debug_del(&eb->fs_info->eb_leak_lock, &eb->leak_list);
49444953
__free_extent_buffer(eb);
49454954
}
49464955

@@ -5329,6 +5338,7 @@ static int release_extent_buffer(struct extent_buffer *eb)
53295338
spin_unlock(&eb->refs_lock);
53305339
}
53315340

5341+
btrfs_leak_debug_del(&eb->fs_info->eb_leak_lock, &eb->leak_list);
53325342
/* Should be safe to release our pages at this point */
53335343
btrfs_release_extent_buffer_pages(eb);
53345344
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS

fs/btrfs/free-space-tree.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,8 +1251,6 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
12511251
btrfs_free_tree_block(trans, free_space_root, free_space_root->node,
12521252
0, 1);
12531253

1254-
free_extent_buffer(free_space_root->node);
1255-
free_extent_buffer(free_space_root->commit_root);
12561254
btrfs_put_root(free_space_root);
12571255

12581256
return btrfs_commit_transaction(trans);

fs/btrfs/qgroup.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,11 +1038,8 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
10381038
out_free_path:
10391039
btrfs_free_path(path);
10401040
out_free_root:
1041-
if (ret) {
1042-
free_extent_buffer(quota_root->node);
1043-
free_extent_buffer(quota_root->commit_root);
1041+
if (ret)
10441042
btrfs_put_root(quota_root);
1045-
}
10461043
out:
10471044
if (ret) {
10481045
ulist_free(fs_info->qgroup_ulist);
@@ -1105,8 +1102,6 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
11051102
btrfs_tree_unlock(quota_root->node);
11061103
btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);
11071104

1108-
free_extent_buffer(quota_root->node);
1109-
free_extent_buffer(quota_root->commit_root);
11101105
btrfs_put_root(quota_root);
11111106

11121107
end_trans:

fs/btrfs/relocation.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2579,10 +2579,6 @@ void free_reloc_roots(struct list_head *list)
25792579
reloc_root = list_entry(list->next, struct btrfs_root,
25802580
root_list);
25812581
__del_reloc_root(reloc_root);
2582-
free_extent_buffer(reloc_root->node);
2583-
free_extent_buffer(reloc_root->commit_root);
2584-
reloc_root->node = NULL;
2585-
reloc_root->commit_root = NULL;
25862582
}
25872583
}
25882584

fs/btrfs/tests/btrfs-tests.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
194194
cleanup_srcu_struct(&fs_info->subvol_srcu);
195195
kfree(fs_info->super_copy);
196196
btrfs_check_leaked_roots(fs_info);
197+
btrfs_extent_buffer_leak_debug_check(fs_info);
197198
kfree(fs_info->fs_devices);
198199
kfree(fs_info);
199200
}
@@ -205,10 +206,6 @@ void btrfs_free_dummy_root(struct btrfs_root *root)
205206
/* Will be freed by btrfs_free_fs_roots */
206207
if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
207208
return;
208-
if (root->node) {
209-
/* One for allocate_extent_buffer */
210-
free_extent_buffer(root->node);
211-
}
212209
btrfs_put_root(root);
213210
}
214211

fs/btrfs/tree-log.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3299,7 +3299,6 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
32993299

33003300
clear_extent_bits(&log->dirty_log_pages, 0, (u64)-1,
33013301
EXTENT_DIRTY | EXTENT_NEW | EXTENT_NEED_WAIT);
3302-
free_extent_buffer(log->node);
33033302
btrfs_put_root(log);
33043303
}
33053304

@@ -6246,8 +6245,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
62466245
ret = btrfs_pin_extent_for_log_replay(trans,
62476246
log->node->start,
62486247
log->node->len);
6249-
free_extent_buffer(log->node);
6250-
free_extent_buffer(log->commit_root);
62516248
btrfs_put_root(log);
62526249

62536250
if (!ret)
@@ -6285,8 +6282,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
62856282

62866283
wc.replay_dest->log_root = NULL;
62876284
btrfs_put_root(wc.replay_dest);
6288-
free_extent_buffer(log->node);
6289-
free_extent_buffer(log->commit_root);
62906285
btrfs_put_root(log);
62916286

62926287
if (ret)
@@ -6318,7 +6313,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree)
63186313
if (ret)
63196314
return ret;
63206315

6321-
free_extent_buffer(log_root_tree->node);
63226316
log_root_tree->log_root = NULL;
63236317
clear_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags);
63246318
btrfs_put_root(log_root_tree);

0 commit comments

Comments
 (0)