On 3/16/19 5:34 PM, Hans van Kranenburg wrote:
> On 3/16/19 7:07 AM, Andrei Borzenkov wrote:
>> [...]
>> This thread actually made me wonder - is there any guarantee (or even
>> tentative promise) about RAID stripe width from btrfs at all? Is it
>> possible that RAID5 degrades to mirror by itself due to unfortunate
>> space distribution?
>
> For RAID5, minimum is two disks. So yes, if you add two disks and don't
> forcibly rewrite all your data, it will happily start adding two-disk
> RAID5 block groups if the other disks are full.
Attached an example that shows a list of used physical and virtual space
ordered by chunk type (== block group flags) and also num_stripes (how
many disks (or, dev extents)) are used. The btrfs-usage-report does not
add this level of detail. (But maybe it would be interesting to add, but
then I would add it into the btrfs.fs_usage code...)
For the RAID56 with a big mess of different block groups with different
"horizontal size" this will be more interesting than what it shows here
as test:
-# ./chunks_stripes_report.py /
flags num_stripes physical virtual
----- ----------- -------- -------
DATA 1 759.00GiB 759.00GiB
SYSTEM|DUP 2 64.00MiB 32.00MiB
METADATA|DUP 2 7.00GiB 3.50GiB
Hans
#!/usr/bin/python3
import btrfs
from collections import defaultdict, Counter
physical_bytes = defaultdict(Counter)
virtual_bytes = defaultdict(Counter)
with btrfs.FileSystem('/') as fs:
for chunk in fs.chunks():
physical_bytes[chunk.type][chunk.num_stripes] += \
btrfs.volumes.chunk_to_dev_extent_length(chunk) * chunk.num_stripes
virtual_bytes[chunk.type][chunk.num_stripes] += chunk.length
report_lines = [
('flags', 'num_stripes', 'physical', 'virtual'),
('-----', '-----------', '--------', '-------'),
]
for flags, counter in physical_bytes.items():
for num_stripes, pbytes in counter.items():
report_lines.append((
btrfs.utils.block_group_flags_str(flags),
num_stripes,
btrfs.utils.pretty_size(pbytes),
btrfs.utils.pretty_size(virtual_bytes[flags][num_stripes]),
))
for report_line in report_lines:
print("{: <16} {: >11} {: >12} {: >12}".format(*report_line))