Skip to content

Commit 349e120

Browse files
josefbacikkdave
authored andcommitted
btrfs: don't adjust bg flags and use default allocation profiles
btrfs/061 has been failing consistently for me recently with a transaction abort. We run out of space in the system chunk array, which means we've allocated way too many system chunks than we need. Chris added this a long time ago for balance as a poor mans restriping. If you had a single disk and then added another disk and then did a balance, update_block_group_flags would then figure out which RAID level you needed. Fast forward to today and we have restriping behavior, so we can explicitly tell the fs that we're trying to change the raid level. This is accomplished through the normal get_alloc_profile path. Furthermore this code actually causes btrfs/061 to fail, because we do things like mkfs -m dup -d single with multiple devices. This trips this check alloc_flags = update_block_group_flags(fs_info, cache->flags); if (alloc_flags != cache->flags) { ret = btrfs_chunk_alloc(trans, alloc_flags, CHUNK_ALLOC_FORCE); in btrfs_inc_block_group_ro. Because we're balancing and scrubbing, but not actually restriping, we keep forcing chunk allocation of RAID1 chunks. This eventually causes us to run out of system space and the file system aborts and flips read only. We don't need this poor mans restriping any more, simply use the normal get_alloc_profile helper, which will get the correct alloc_flags and thus make the right decision for chunk allocation. This keeps us from allocating a billion system chunks and falling over. Tested-by: Holger Hoffstätte <[email protected]> Reviewed-by: Qu Wenruo <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent ab0db04 commit 349e120

File tree

1 file changed

+2
-50
lines changed

1 file changed

+2
-50
lines changed

fs/btrfs/block-group.c

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,54 +2194,6 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
21942194
return 0;
21952195
}
21962196

2197-
static u64 update_block_group_flags(struct btrfs_fs_info *fs_info, u64 flags)
2198-
{
2199-
u64 num_devices;
2200-
u64 stripped;
2201-
2202-
/*
2203-
* if restripe for this chunk_type is on pick target profile and
2204-
* return, otherwise do the usual balance
2205-
*/
2206-
stripped = get_restripe_target(fs_info, flags);
2207-
if (stripped)
2208-
return extended_to_chunk(stripped);
2209-
2210-
num_devices = fs_info->fs_devices->rw_devices;
2211-
2212-
stripped = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID56_MASK |
2213-
BTRFS_BLOCK_GROUP_RAID1_MASK | BTRFS_BLOCK_GROUP_RAID10;
2214-
2215-
if (num_devices == 1) {
2216-
stripped |= BTRFS_BLOCK_GROUP_DUP;
2217-
stripped = flags & ~stripped;
2218-
2219-
/* turn raid0 into single device chunks */
2220-
if (flags & BTRFS_BLOCK_GROUP_RAID0)
2221-
return stripped;
2222-
2223-
/* turn mirroring into duplication */
2224-
if (flags & (BTRFS_BLOCK_GROUP_RAID1_MASK |
2225-
BTRFS_BLOCK_GROUP_RAID10))
2226-
return stripped | BTRFS_BLOCK_GROUP_DUP;
2227-
} else {
2228-
/* they already had raid on here, just return */
2229-
if (flags & stripped)
2230-
return flags;
2231-
2232-
stripped |= BTRFS_BLOCK_GROUP_DUP;
2233-
stripped = flags & ~stripped;
2234-
2235-
/* switch duplicated blocks with raid1 */
2236-
if (flags & BTRFS_BLOCK_GROUP_DUP)
2237-
return stripped | BTRFS_BLOCK_GROUP_RAID1;
2238-
2239-
/* this is drive concat, leave it alone */
2240-
}
2241-
2242-
return flags;
2243-
}
2244-
22452197
/*
22462198
* Mark one block group RO, can be called several times for the same block
22472199
* group.
@@ -2287,7 +2239,7 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
22872239
* If we are changing raid levels, try to allocate a
22882240
* corresponding block group with the new raid level.
22892241
*/
2290-
alloc_flags = update_block_group_flags(fs_info, cache->flags);
2242+
alloc_flags = btrfs_get_alloc_profile(fs_info, cache->flags);
22912243
if (alloc_flags != cache->flags) {
22922244
ret = btrfs_chunk_alloc(trans, alloc_flags,
22932245
CHUNK_ALLOC_FORCE);
@@ -2314,7 +2266,7 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
23142266
ret = inc_block_group_ro(cache, 0);
23152267
out:
23162268
if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
2317-
alloc_flags = update_block_group_flags(fs_info, cache->flags);
2269+
alloc_flags = btrfs_get_alloc_profile(fs_info, cache->flags);
23182270
mutex_lock(&fs_info->chunk_mutex);
23192271
check_system_chunk(trans, alloc_flags);
23202272
mutex_unlock(&fs_info->chunk_mutex);

0 commit comments

Comments
 (0)