Query usage of multi-device bcachefs file systems correctly

Create an uneven used space multi-device bcachefs file system like this,
where sdb1 is about 1/2 used and sdb2 is almost empty:
    # bcachefs format /dev/sdb1
    # mount /dev/sdb1 /mnt/1
    # dd if=/dev/zero bs=1M count=512 of=/mnt/1/zeros.bin
    # bcachefs device add /mnt/1 /dev/sdb2

GParted reports both devices as having the same usage:
    Partition   File System   Mount Point   Size       Used         Unused       Flags
    /dev/sdb1   bcachefs      /mnt/1        1.00 GiB   526.00 MiB   498.00 MiB
    /dev/sdb2   bcachefs      /mnt/1        1.00 GiB   526.00 MiB   498.00 MiB

When in fact the used space is significantly different for each device:
    # bcachefs fs usage /mnt/1 | egrep ' \(device |free:|capacity:'
    (no label) (device 0):          sdb1              rw
      free:                    522190848            3984
      capacity:               1073741824            8192
    (no label) (device 1):          sdb2              rw
      free:                   1061945344            8102
      capacity:               1073741824            8192

This is because bcachefs::set_used_sectors() is always searching for the
first "free:" and "capacity:" figures.  Fix by reading the figures for
the correct device.
This commit is contained in:
Mike Fleetwood 2024-03-25 21:15:10 +00:00
parent 562f951aaf
commit ab2c269597
1 changed files with 30 additions and 0 deletions

View File

@ -16,6 +16,7 @@
#include "bcachefs.h"
#include "BlockSpecial.h"
#include "FileSystem.h"
#include "OperationDetail.h"
#include "Partition.h"
@ -73,6 +74,35 @@ void bcachefs::set_used_sectors(Partition& partition)
return;
}
// Example output:
// # bcachefs fs usage /mnt/1 | egrep ' \(device |free:|capacity:'
// (no label) (device 0): sdb1 rw
// free: 522190848 3984
// capacity: 1073741824 8192
// (no label) (device 1): sdb2 rw
// free: 1061945344 8102
// capacity: 1073741824 8192
//
// Substring the output down to just the device section for this partition.
BlockSpecial wanted = BlockSpecial(partition.get_path());
bool found = false;
Glib::ustring::size_type start_offset = output.find(" (device ");
while (start_offset != Glib::ustring::npos)
{
Glib::ustring device_name = Utils::regexp_label(output.substr(start_offset),
" \\(device [[:digit:]]+\\):[[:blank:]]+([[:graph:]]+)");
Glib::ustring::size_type end_offset = output.find(" (device ", start_offset + 9);
if (wanted == BlockSpecial("/dev/" + device_name))
{
output = output.substr(start_offset, end_offset - start_offset);
found = true;
break;
}
start_offset = end_offset;
}
if (! found)
return;
// Device specific free space in bytes
long long dev_free_bytes = -1;
Glib::ustring::size_type index = output.find("free:");