Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c41761f authored by David Sterba's avatar David Sterba Committed by Chris Mason
Browse files

btrfs: separate superblock items out of fs_info



fs_info has now ~9kb, more than fits into one page. This will cause
mount failure when memory is too fragmented. Top space consumers are
super block structures super_copy and super_for_commit, ~2.8kb each.
Allocate them dynamically. fs_info will be ~3.5kb. (measured on x86_64)

Add a wrapper for freeing fs_info and all of it's dynamically allocated
members.

Signed-off-by: default avatarDavid Sterba <dsterba@suse.cz>
parent c8174313
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ struct compressed_bio {
static inline int compressed_bio_size(struct btrfs_root *root,
				      unsigned long disk_size)
{
	u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);

	return sizeof(struct compressed_bio) +
		((disk_size + root->sectorsize - 1) / root->sectorsize) *
		csum_size;
+14 −2
Original line number Diff line number Diff line
@@ -936,8 +936,8 @@ struct btrfs_fs_info {
	wait_queue_head_t transaction_blocked_wait;
	wait_queue_head_t async_submit_wait;

	struct btrfs_super_block super_copy;
	struct btrfs_super_block super_for_commit;
	struct btrfs_super_block *super_copy;
	struct btrfs_super_block *super_for_commit;
	struct block_device *__bdev;
	struct super_block *sb;
	struct inode *btree_inode;
@@ -2387,6 +2387,18 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
	smp_mb();
	return fs_info->closing;
}
static inline void free_fs_info(struct btrfs_fs_info *fs_info)
{
	kfree(fs_info->delayed_root);
	kfree(fs_info->extent_root);
	kfree(fs_info->tree_root);
	kfree(fs_info->chunk_root);
	kfree(fs_info->dev_root);
	kfree(fs_info->csum_root);
	kfree(fs_info->super_copy);
	kfree(fs_info->super_for_commit);
	kfree(fs_info);
}

/* root-item.c */
int btrfs_find_root_ref(struct btrfs_root *tree_root,
+10 −23
Original line number Diff line number Diff line
@@ -256,8 +256,7 @@ void btrfs_csum_final(u32 crc, char *result)
static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
			   int verify)
{
	u16 csum_size =
		btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
	char *result = NULL;
	unsigned long len;
	unsigned long cur_len;
@@ -1766,14 +1765,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,
		goto fail_alloc;
	}

	memcpy(&fs_info->super_copy, bh->b_data, sizeof(fs_info->super_copy));
	memcpy(&fs_info->super_for_commit, &fs_info->super_copy,
	       sizeof(fs_info->super_for_commit));
	memcpy(fs_info->super_copy, bh->b_data, sizeof(*fs_info->super_copy));
	memcpy(fs_info->super_for_commit, fs_info->super_copy,
	       sizeof(*fs_info->super_for_commit));
	brelse(bh);

	memcpy(fs_info->fsid, fs_info->super_copy.fsid, BTRFS_FSID_SIZE);
	memcpy(fs_info->fsid, fs_info->super_copy->fsid, BTRFS_FSID_SIZE);

	disk_super = &fs_info->super_copy;
	disk_super = fs_info->super_copy;
	if (!btrfs_super_root(disk_super))
		goto fail_alloc;

@@ -2152,7 +2151,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	btrfs_stop_workers(&fs_info->delayed_workers);
	btrfs_stop_workers(&fs_info->caching_workers);
fail_alloc:
	kfree(fs_info->delayed_root);
fail_iput:
	invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
	iput(fs_info->btree_inode);
@@ -2164,12 +2162,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
fail_srcu:
	cleanup_srcu_struct(&fs_info->subvol_srcu);
fail:
	kfree(extent_root);
	kfree(tree_root);
	kfree(fs_info);
	kfree(chunk_root);
	kfree(dev_root);
	kfree(csum_root);
	free_fs_info(fs_info);
	return ERR_PTR(err);
}

@@ -2338,10 +2331,10 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
	int total_errors = 0;
	u64 flags;

	max_errors = btrfs_super_num_devices(&root->fs_info->super_copy) - 1;
	max_errors = btrfs_super_num_devices(root->fs_info->super_copy) - 1;
	do_barriers = !btrfs_test_opt(root, NOBARRIER);

	sb = &root->fs_info->super_for_commit;
	sb = root->fs_info->super_for_commit;
	dev_item = &sb->dev_item;

	mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
@@ -2603,7 +2596,6 @@ int close_ctree(struct btrfs_root *root)
	del_fs_roots(fs_info);

	iput(fs_info->btree_inode);
	kfree(fs_info->delayed_root);

	btrfs_stop_workers(&fs_info->generic_worker);
	btrfs_stop_workers(&fs_info->fixup_workers);
@@ -2624,12 +2616,7 @@ int close_ctree(struct btrfs_root *root)
	bdi_destroy(&fs_info->bdi);
	cleanup_srcu_struct(&fs_info->subvol_srcu);

	kfree(fs_info->extent_root);
	kfree(fs_info->tree_root);
	kfree(fs_info->chunk_root);
	kfree(fs_info->dev_root);
	kfree(fs_info->csum_root);
	kfree(fs_info);
	free_fs_info(fs_info);

	return 0;
}
+8 −8
Original line number Diff line number Diff line
@@ -3209,7 +3209,7 @@ static int should_alloc_chunk(struct btrfs_root *root,
	 * about 1% of the FS size.
	 */
	if (force == CHUNK_ALLOC_LIMITED) {
		thresh = btrfs_super_total_bytes(&root->fs_info->super_copy);
		thresh = btrfs_super_total_bytes(root->fs_info->super_copy);
		thresh = max_t(u64, 64 * 1024 * 1024,
			       div_factor_fine(thresh, 1));

@@ -3231,7 +3231,7 @@ static int should_alloc_chunk(struct btrfs_root *root,
	if (num_allocated + alloc_bytes < div_factor(num_bytes, 8))
		return 0;

	thresh = btrfs_super_total_bytes(&root->fs_info->super_copy);
	thresh = btrfs_super_total_bytes(root->fs_info->super_copy);

	/* 256MB or 5% of the FS */
	thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5));
@@ -3843,7 +3843,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
	u64 num_bytes;
	u64 meta_used;
	u64 data_used;
	int csum_size = btrfs_super_csum_size(&fs_info->super_copy);
	int csum_size = btrfs_super_csum_size(fs_info->super_copy);

	sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
	spin_lock(&sinfo->lock);
@@ -4222,12 +4222,12 @@ static int update_block_group(struct btrfs_trans_handle *trans,

	/* block accounting for super block */
	spin_lock(&info->delalloc_lock);
	old_val = btrfs_super_bytes_used(&info->super_copy);
	old_val = btrfs_super_bytes_used(info->super_copy);
	if (alloc)
		old_val += num_bytes;
	else
		old_val -= num_bytes;
	btrfs_set_super_bytes_used(&info->super_copy, old_val);
	btrfs_set_super_bytes_used(info->super_copy, old_val);
	spin_unlock(&info->delalloc_lock);

	while (total) {
@@ -7127,9 +7127,9 @@ int btrfs_read_block_groups(struct btrfs_root *root)
		return -ENOMEM;
	path->reada = 1;

	cache_gen = btrfs_super_cache_generation(&root->fs_info->super_copy);
	cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
	if (btrfs_test_opt(root, SPACE_CACHE) &&
	    btrfs_super_generation(&root->fs_info->super_copy) != cache_gen)
	    btrfs_super_generation(root->fs_info->super_copy) != cache_gen)
		need_clear = 1;
	if (btrfs_test_opt(root, CLEAR_CACHE))
		need_clear = 1;
@@ -7458,7 +7458,7 @@ int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
	int mixed = 0;
	int ret;

	disk_super = &fs_info->super_copy;
	disk_super = fs_info->super_copy;
	if (!btrfs_super_root(disk_super))
		return 1;

+6 −11
Original line number Diff line number Diff line
@@ -91,8 +91,7 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
	struct btrfs_csum_item *item;
	struct extent_buffer *leaf;
	u64 csum_offset = 0;
	u16 csum_size =
		btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
	int csums_in_item;

	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
@@ -162,8 +161,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
	u64 item_last_offset = 0;
	u64 disk_bytenr;
	u32 diff;
	u16 csum_size =
		btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
	int ret;
	struct btrfs_path *path;
	struct btrfs_csum_item *item = NULL;
@@ -290,7 +288,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
	int ret;
	size_t size;
	u64 csum_end;
	u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);

	path = btrfs_alloc_path();
	if (!path)
@@ -492,8 +490,7 @@ static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
				      u64 bytenr, u64 len)
{
	struct extent_buffer *leaf;
	u16 csum_size =
		btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
	u64 csum_end;
	u64 end_byte = bytenr + len;
	u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits;
@@ -549,8 +546,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
	u64 csum_end;
	struct extent_buffer *leaf;
	int ret;
	u16 csum_size =
		btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
	int blocksize_bits = root->fs_info->sb->s_blocksize_bits;

	root = root->fs_info->csum_root;
@@ -676,8 +672,7 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
	struct btrfs_sector_sum *sector_sum;
	u32 nritems;
	u32 ins_size;
	u16 csum_size =
		btrfs_super_csum_size(&root->fs_info->super_copy);
	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);

	path = btrfs_alloc_path();
	if (!path)
Loading