Re: [RFC PATCH] btrfs: Write as many copies as possible if the current RAID1 profile is unreachable

Qu Wenruo <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs
Message-ID <[email protected]>

在 2026/8/12 08:34, Logan Finley 写道:
> While testing a three-disk btrfs filesystem consisting of only RAID1C3
> block groups, I noticed that if I unmounted the filesystem, wiped one of
> the disks, and then remounted the filesystem from the remaining two disks
> with `-o degraded`, after a certain point new data begins to be written
> into a "single" block group.
> 
> It appears that some data is initially written into the existing RAID1C3
> chunks, but once enough data is written such that a new chunk needs to
> be allocated, the next chunk allocated uses the "single" profile.
> 
> I'm not sure of a good way to fill up the System and Metadata block groups
> enough to trigger a new chunk to be allocated, so I wasn't able to see
> whether they also allocate "single"-profile chunks.

For meta, go fill a subvolume with inlined data, that will easily bump 
up the metadata usage.

For system it's harder, but you can still use fallocate to take a lot of 
space, which will trigger new chunk allocation that will increase system 
usage.
But it's very hard if your fs has limited space.


> 
> This was unexpected, since, to me, one of the benefits of RAID1C3 was more
> time to keep operating safely (albeit in a degraded state) while an
> operator makes their way to a machine to physically replace the failed
> disk. With the current behavior, it seems that this isn't a valid use case
> because any further disk failure could lead to the loss of newly written
> data.
> 
> This (admittedly naive) patch modifies this behavior so that the RAID1
> family of profiles writes as many copies as possible in a degraded state
> when there are not enough disks present to write data in the configured
> RAID profile.
> 
> Signed-off-by: Logan Finley <[email protected]>
> ---
> What I'm looking for is feedback on whether this sort of patch is
> desired upstream, whether the approach is valid, and whether or not
> there are any gotchas I may have missed in the implementation.

I think this downgrade from RAID1C4 to C3/C2 and from C3 to C2 is safe, 
and it's a good middle ground solution.

Although it has the side effect that there will be new RAID1* profiles 
which will require balance to remove after the missing device is dealt with.



The root problem is in how we handle chunk allocation in degraded mode.
When a device is missing, it's very instinctive to assume we should not 
use that device for new chunks.

But that may not be the case, we may still want to allocate chunk on 
that missing device, and rely on the chunk's mirrors/duplications to 
handle it.

There will be extra problems involved for using such missing device, 
e.g. we should not use the missing device for profiles without 
duplication on other devices, like SINGLE/DUP on that missing device.

In the long run, that would allow us to still use whatever profile even 
if there is a missing device, and requires no extra balance after all 
devices are online again.


Now the question is, should we go the long-term solution directly (if 
some one is going to work on it), or go the middle ground first?

Thanks,
Qu
> 
> Testing was done on an x86_64 qemu vm at commit a13307e97d5c ("Merge tag
> 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf")
> on the kdave/linux tree.
> ---
>   fs/btrfs/block-group.c | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
> index 8def7abb728f..50a21a0d8765 100644
> --- a/fs/btrfs/block-group.c
> +++ b/fs/btrfs/block-group.c
> @@ -176,6 +176,12 @@ u64 btrfs_get_alloc_profile(struct btrfs_fs_info *fs_info, u64 orig_flags)
>   			flags |= fs_info->avail_metadata_alloc_bits;
>   	} while (read_seqretry(&fs_info->profiles_lock, seq));
>   
> +	/* Degrade to a less redundant, but still redundant, RAID1 profile if possible. */
> +	if (flags & BTRFS_BLOCK_GROUP_RAID1C4)
> +		flags |= BTRFS_BLOCK_GROUP_RAID1C3 | BTRFS_BLOCK_GROUP_RAID1;
> +	else if (flags & BTRFS_BLOCK_GROUP_RAID1C3)
> +		flags |= BTRFS_BLOCK_GROUP_RAID1;
> +
>   	return btrfs_reduce_alloc_profile(fs_info, flags);
>   }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.