On 4/26/22 5:53 AM, Andrey Albershteyn wrote: > On Tue, Apr 26, 2022 at 10:21:04AM +0200, Karel Zak wrote: >> On Mon, Apr 25, 2022 at 10:38:02AM -0500, Eric Sandeen wrote: >>> On 4/25/22 8:43 AM, Karel Zak wrote: >>>> >>>> Thanks Andrey, >>>> >>>> the code looks good. >>>> >>>> On Thu, Apr 21, 2022 at 03:09:44PM +0200, Andrey Albershteyn wrote: >>>>> I had a look into other fs, like ext4 and btrfs, to implement FSSIZE >>>>> for them, but I think I don't have enough expertize to do that as >>>>> they have not so trivial metadata overhead calculation :) >>>> >>>> But it would be nice to have ext4 and btrfs too. Maybe Eric can help >>>> you :-) >>>> >>>> Karel >>> >>> For ext4 something like e2fsprogs does is probably ok: >>> >>> static __u64 e2p_free_blocks_count(struct ext2_super_block *super) >>> { >>> return super->s_free_blocks_count | >>> (ext2fs_has_feature_64bit(super) ? >>> (__u64) super->s_free_blocks_hi << 32 : 0); >>> } Whoops, I mis-pasted, that should have been: static __u64 e2p_blocks_count(struct ext2_super_block *super) { return super->s_blocks_count | (ext2fs_has_feature_64bit(super) ? (__u64) super->s_blocks_count_hi << 32 : 0); } (blocks count, not free blocks count) > If we want to mimic statfs(2) + lsblk, then, I think this one won't > be exactly it. I suppose s_free_blocks_count contains number of not > used blocks which will vary with utilization... The statfs() > calculates total number of blocks as total_blocks - (journalsize + > each group free space). As far as I got it, both journalsize and > group free space is not so trivial to calculate. (Sorry for mixing this up by pasting e2p_free_blocks_count) Ok, so I'm remembering what FSSIZE does in lsblk now :) it simply returns: dev->fsstat.f_frsize * dev->fsstat.f_blocks i.e. calculating the value based on statfs values. This does get a little tricky for ext4, because statfs "f_blocks" is affected by the minixdf/bsddf mount options. ext4's f_blocks statfs calculation looks like this: buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, overhead); the default behavior, bsddf, subtracts out the overhead. The overhead is a little tricky to calculate, but I /think/ it's precomputed and stored in the superblock as well for (newer?) ext4, in the s_overhead_clusters field. So I *think* you can just do: (block size) * (blocks count - overhead) and get the same answer as statfs and lsblk. Does that work? (Getting block count is a little tricky, because it may be split across 2 fields; s_blocks_count_lo for the lower 32 bits on smaller filesystems, and s_blocks_count_hi only if EXT4_FEATURE_INCOMPAT_64BIT is set.) (ext2 is messier, as a precomputed overhead value is not stored on disk. Perhaps returning FSSIZE only if the type is ext4 might make sense.) If I'm wrong about s_overhead_clusters being pre-calculated and stored, perhaps just ignoring "overhead' altogether and treating FSSIZE in the "minixdf" sense, and simply return s_blocks_count_lo & s_blocks_count_hi for an answer. Thanks, -Eric