Skip to content

Commit 3d7db6e

Browse files
fdmananakdave
authored andcommitted
btrfs: don't allocate file extent tree for non regular files
When not using the NO_HOLES feature we always allocate an io tree for an inode's file_extent_tree. This is wasteful because that io tree is only used for regular files, so we allocate more memory than needed for inodes that represent directories or symlinks for example, or for inodes that correspond to free space inodes. So improve on this by allocating the io tree only for inodes of regular files that are not free space inodes. Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent d9891ae commit 3d7db6e

File tree

2 files changed

+42
-24
lines changed

2 files changed

+42
-24
lines changed

fs/btrfs/file-item.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,12 @@
4545
*/
4646
void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_size)
4747
{
48-
struct btrfs_fs_info *fs_info = inode->root->fs_info;
4948
u64 start, end, i_size;
5049
int ret;
5150

5251
spin_lock(&inode->lock);
5352
i_size = new_i_size ?: i_size_read(&inode->vfs_inode);
54-
if (btrfs_fs_incompat(fs_info, NO_HOLES)) {
53+
if (!inode->file_extent_tree) {
5554
inode->disk_i_size = i_size;
5655
goto out_unlock;
5756
}
@@ -84,13 +83,14 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz
8483
int btrfs_inode_set_file_extent_range(struct btrfs_inode *inode, u64 start,
8584
u64 len)
8685
{
86+
if (!inode->file_extent_tree)
87+
return 0;
88+
8789
if (len == 0)
8890
return 0;
8991

9092
ASSERT(IS_ALIGNED(start + len, inode->root->fs_info->sectorsize));
9193

92-
if (btrfs_fs_incompat(inode->root->fs_info, NO_HOLES))
93-
return 0;
9494
return set_extent_bit(inode->file_extent_tree, start, start + len - 1,
9595
EXTENT_DIRTY, NULL);
9696
}
@@ -112,14 +112,15 @@ int btrfs_inode_set_file_extent_range(struct btrfs_inode *inode, u64 start,
112112
int btrfs_inode_clear_file_extent_range(struct btrfs_inode *inode, u64 start,
113113
u64 len)
114114
{
115+
if (!inode->file_extent_tree)
116+
return 0;
117+
115118
if (len == 0)
116119
return 0;
117120

118121
ASSERT(IS_ALIGNED(start + len, inode->root->fs_info->sectorsize) ||
119122
len == (u64)-1);
120123

121-
if (btrfs_fs_incompat(inode->root->fs_info, NO_HOLES))
122-
return 0;
123124
return clear_extent_bit(inode->file_extent_tree, start,
124125
start + len - 1, EXTENT_DIRTY, NULL);
125126
}

fs/btrfs/inode.c

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3781,6 +3781,30 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
37813781
return 1;
37823782
}
37833783

3784+
static int btrfs_init_file_extent_tree(struct btrfs_inode *inode)
3785+
{
3786+
struct btrfs_fs_info *fs_info = inode->root->fs_info;
3787+
3788+
if (WARN_ON_ONCE(inode->file_extent_tree))
3789+
return 0;
3790+
if (btrfs_fs_incompat(fs_info, NO_HOLES))
3791+
return 0;
3792+
if (!S_ISREG(inode->vfs_inode.i_mode))
3793+
return 0;
3794+
if (btrfs_is_free_space_inode(inode))
3795+
return 0;
3796+
3797+
inode->file_extent_tree = kmalloc(sizeof(struct extent_io_tree), GFP_KERNEL);
3798+
if (!inode->file_extent_tree)
3799+
return -ENOMEM;
3800+
3801+
extent_io_tree_init(fs_info, inode->file_extent_tree, IO_TREE_INODE_FILE_EXTENT);
3802+
/* Lockdep class is set only for the file extent tree. */
3803+
lockdep_set_class(&inode->file_extent_tree->lock, &file_extent_tree_class);
3804+
3805+
return 0;
3806+
}
3807+
37843808
/*
37853809
* read an inode from the btree into the in-memory inode
37863810
*/
@@ -3800,6 +3824,10 @@ static int btrfs_read_locked_inode(struct inode *inode,
38003824
bool filled = false;
38013825
int first_xattr_slot;
38023826

3827+
ret = btrfs_init_file_extent_tree(BTRFS_I(inode));
3828+
if (ret)
3829+
return ret;
3830+
38033831
ret = btrfs_fill_inode(inode, &rdev);
38043832
if (!ret)
38053833
filled = true;
@@ -6247,6 +6275,10 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
62476275
BTRFS_I(inode)->root = btrfs_grab_root(BTRFS_I(dir)->root);
62486276
root = BTRFS_I(inode)->root;
62496277

6278+
ret = btrfs_init_file_extent_tree(BTRFS_I(inode));
6279+
if (ret)
6280+
goto out;
6281+
62506282
ret = btrfs_get_free_objectid(root, &objectid);
62516283
if (ret)
62526284
goto out;
@@ -8413,20 +8445,10 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
84138445
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
84148446
struct btrfs_inode *ei;
84158447
struct inode *inode;
8416-
struct extent_io_tree *file_extent_tree = NULL;
8417-
8418-
/* Self tests may pass a NULL fs_info. */
8419-
if (fs_info && !btrfs_fs_incompat(fs_info, NO_HOLES)) {
8420-
file_extent_tree = kmalloc(sizeof(struct extent_io_tree), GFP_KERNEL);
8421-
if (!file_extent_tree)
8422-
return NULL;
8423-
}
84248448

84258449
ei = alloc_inode_sb(sb, btrfs_inode_cachep, GFP_KERNEL);
8426-
if (!ei) {
8427-
kfree(file_extent_tree);
8450+
if (!ei)
84288451
return NULL;
8429-
}
84308452

84318453
ei->root = NULL;
84328454
ei->generation = 0;
@@ -8471,13 +8493,8 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
84718493
extent_io_tree_init(fs_info, &ei->io_tree, IO_TREE_INODE_IO);
84728494
ei->io_tree.inode = ei;
84738495

8474-
ei->file_extent_tree = file_extent_tree;
8475-
if (file_extent_tree) {
8476-
extent_io_tree_init(fs_info, ei->file_extent_tree,
8477-
IO_TREE_INODE_FILE_EXTENT);
8478-
/* Lockdep class is set only for the file extent tree. */
8479-
lockdep_set_class(&ei->file_extent_tree->lock, &file_extent_tree_class);
8480-
}
8496+
ei->file_extent_tree = NULL;
8497+
84818498
mutex_init(&ei->log_mutex);
84828499
spin_lock_init(&ei->ordered_tree_lock);
84838500
ei->ordered_tree = RB_ROOT;

0 commit comments

Comments
 (0)