btrfs: implement Volume::NumFreeBlocks()

info->free_blocks in btrfs_read_fs_info() was hardcoded to 0,
which made df and any statvfs() based tool report a btrfs volume
as completely full regardless of actual usage.

Add btrfs_super_block::UsedSize() alongside the existing
TotalSize(), and use it to implement Volume::NumFreeBlocks() as
(TotalSize() - UsedSize()) / BlockSize().

Verified against btrfs-progs ground truth using fs_shell on a
freshly formatted 512 MB volume, free size reports 511.8MiB,
after writing a 200 MB file, free size drops to 311.6 MB,
matching real usage (200.75 MB per 'btrfs filesystem usage') to
within ~350 KB of B-tree metadata overhead.

Fixes #20182

Change-Id: Iffe9802480b1b8fa8cdb65f0c27a46ba921138b0
Reviewed-on: https://review.haiku-os.org/c/haiku/+/11258
Reviewed-by: Adrien Destugues <[email protected]>
Tested-by: Commit checker robot <[email protected]>
Haiku-Format: Haiku-format Bot <[email protected]>
This commit is contained in:
Abdullah Zulfiqar
2026-07-15 08:08:57 +00:00
committed by Adrien Destugues
parent 942f4ddcbb
commit c6c24b3e3a
2 changed files with 3 additions and 1 deletions
@@ -258,6 +258,7 @@ struct btrfs_super_block {
void Initialize(const char* name, off_t numBlocks,
uint32 blockSize, uint32 sectorSize);
uint64 TotalSize() const { return B_LENDIAN_TO_HOST_INT64(total_size); }
uint64 UsedSize() const { return B_LENDIAN_TO_HOST_INT64(used_size); }
uint32 BlockSize() const { return B_LENDIAN_TO_HOST_INT32(node_size); }
uint32 SectorSize() const { return B_LENDIAN_TO_HOST_INT32(sector_size); }
uint64 RootDirObjectID() const
@@ -169,7 +169,8 @@ btrfs_read_fs_info(fs_volume* _volume, struct fs_info* info)
info->io_size = BTRFS_IO_SIZE;
info->block_size = volume->BlockSize();
info->total_blocks = volume->SuperBlock().TotalSize() / volume->BlockSize();
info->free_blocks = 0; // volume->NumFreeBlocks();
info->free_blocks = (volume->SuperBlock().TotalSize() - volume->SuperBlock().UsedSize())
/ volume->BlockSize();
// Volume name
strlcpy(info->volume_name, volume->Name(), sizeof(info->volume_name));