Commit 257d0ce3 authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Allow large data extents in a single file to span into metadata block groups

parent 09be207d
Loading
Loading
Loading
Loading
+30 −6
Original line number Diff line number Diff line
@@ -168,6 +168,7 @@ static u64 find_search_start(struct btrfs_root *root,
	u64 last;
	u64 start = 0;
	u64 end = 0;
	u64 cache_miss = 0;
	int wrapped = 0;

again:
@@ -181,14 +182,20 @@ static u64 find_search_start(struct btrfs_root *root,
		ret = find_first_extent_bit(&root->fs_info->free_space_cache,
					    last, &start, &end, EXTENT_DIRTY);
		if (ret) {
			if (!cache_miss)
				cache_miss = last;
			goto new_group;
		}

		start = max(last, start);
		last = end + 1;
		if (end + 1 - start < num)
		if (last - start < num) {
			if (last == cache->key.objectid + cache->key.offset)
				cache_miss = start;
			continue;
		if (start + num >= cache->key.objectid + cache->key.offset)
		}
		if (data != BTRFS_BLOCK_GROUP_MIXED &&
		    start + num >= cache->key.objectid + cache->key.offset)
			goto new_group;
		return start;
	}
@@ -208,13 +215,22 @@ static u64 find_search_start(struct btrfs_root *root,
		}
		return search_start;
	}
	if (cache_miss && !cache->cached) {
		cache_block_group(root, cache);
		last = cache_miss;

		cache = btrfs_lookup_block_group(root->fs_info, last);
	}
	cache = btrfs_find_block_group(root, cache, last, data, 0);
	*cache_ret = cache;
	cache_miss = 0;
	goto again;
}

static u64 div_factor(u64 num, int factor)
{
	if (factor == 10)
		return num;
	num *= factor;
	do_div(num, 10);
	return num;
@@ -247,9 +263,10 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
	if (!owner)
		factor = 8;

	if (data == BTRFS_BLOCK_GROUP_MIXED)
	if (data == BTRFS_BLOCK_GROUP_MIXED) {
		bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA;
	else if (data)
		factor = 10;
	} else if (data)
		bit = BLOCK_GROUP_DATA;
	else
		bit = BLOCK_GROUP_METADATA;
@@ -918,6 +935,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root

	level = btrfs_header_level(root->node);

	if (num_bytes >= 96 * 1024 * 1024 && hint_byte) {
		data = BTRFS_BLOCK_GROUP_MIXED;
	}

	if (search_end == (u64)-1)
		search_end = btrfs_super_total_bytes(&info->super_copy);
	if (hint_byte) {
@@ -937,6 +958,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
	search_start = find_search_start(root, &block_group,
					 search_start, total_needed, data);
	cached_start = search_start;

	btrfs_init_path(path);
	ins->objectid = search_start;
	ins->offset = 0;
@@ -1021,7 +1043,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
		start_found = 1;
		last_byte = key.objectid + key.offset;

		if (!full_scan && last_byte >= block_group->key.objectid +
		if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED &&
		    last_byte >= block_group->key.objectid +
		    block_group->key.offset) {
			btrfs_release_path(root, path);
			search_start = block_group->key.objectid +
@@ -1042,7 +1065,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
	if (ins->objectid + num_bytes >= search_end)
		goto enospc;

	if (!full_scan && ins->objectid + num_bytes >= block_group->
	if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED &&
	    ins->objectid + num_bytes >= block_group->
	    key.objectid + block_group->key.offset) {
		search_start = block_group->key.objectid +
			block_group->key.offset;
+6 −0
Original line number Diff line number Diff line
@@ -439,6 +439,12 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
						struct btrfs_file_extent_item);
			found_type = btrfs_file_extent_type(leaf, extent);
			if (found_type == BTRFS_FILE_EXTENT_REG) {
				extent_end =
				     btrfs_file_extent_disk_bytenr(leaf,
								   extent);
				if (extent_end)
					*hint_byte = extent_end;

				extent_end = key.offset +
				     btrfs_file_extent_num_bytes(leaf, extent);
				found_extent = 1;