Add filesystem stats in ContainerStatistics - #930
Conversation
* Add `filesystem (usedBytes, inodesUsed)` field to protobuf `ContainerStats` * Add `ManagedContainer.filesystemStats` which stats the file system using `statfs` syscall. `vminitd` in guest uses this to get the measurement on `containerStatistics` calls * Update `ContainerStatistics` to include `filesystem` fields.
`statfs` isn't reliably importable from Swift via the Musl/Glibc system modulemap across architectures.
* It should not do anything clever
* Expose blockSize, blocks, freeBlocks, inodes, freeInodes * usedBytes and inodesUsed can be computed using those fields.
adityaramani
left a comment
There was a problem hiding this comment.
I think this looks good. Will want another reviewer to also +1 though
6cbdebb to
7e54b0f
Compare
| /// Memory event counters (OOM kills, pressure events, etc.). | ||
| public static let memoryEvents = StatCategory(rawValue: 1 << 5) | ||
| /// Filesystem occupancy statistics. | ||
| public static let filesystem = StatCategory(rawValue: 1 << 6) |
There was a problem hiding this comment.
What does this 1 << 6 mean
There was a problem hiding this comment.
Followed the convention. Internally, the guest side checks that bit to stat filesystem or not.
There was a problem hiding this comment.
Though it'd be better using a named variable instead of a number..
There was a problem hiding this comment.
Yeah I agree variable is better than magic number. I was just trying other understand why these StatCategories are bit based type not an enum or something else
| // struct statfs itself isn't reliably importable from Swift across all | ||
| // target architectures via the Musl/Glibc modulemaps, so this wraps |
There was a problem hiding this comment.
glibc's struct statfs (bits/statfs.h) branches its field types based on a preprocessor macro:
struct statfs {
__fsword_t f_type;
__fsword_t f_bsize;
#ifndef __USE_FILE_OFFSET64
__fsblkcnt_t f_blocks; ... // 32-bit variant
#else
__fsblkcnt64_t f_blocks; ... // 64-bit variant
#endif
...
};
__USE_FILE_OFFSET64 is controlled by _FILE_OFFSET_BITS at compile time — the same header name struct statfs describes two different memory layouts depending on what macros the including translation unit had set. There's also a second name, struct statfs64, gated behind a different macro (__USE_LARGEFILE64).
musl's struct statfs has no such branching — musl never had a 32-bit legacy off_t/blkcnt_t story, so there's exactly one unconditional layout, and statfs64/fstatfs64 are just #define aliases to the same functions, not a different struct.
That's the discrepancy: a Clang module (which is what a modulemap builds) is precompiled once, with one fixed macro configuration baked into its PCM. A type whose layout depends on _FILE_OFFSET_BITS isn't safe to modularize that way — whichever macro state the module happened to be built with becomes "the" struct statfs for every importer, silently disagreeing with any C code compiled under the other setting. musl's single, macro-independent layout has no such hazard, so its modulemap can freely declare sys_statfs/sys_vfs as real submodules. glibc's toolchain-maintained glibc.modulemap most likely just never added sys/vfs.h/sys/statfs.h for exactly this reason (or nobody has patched it in, since these modulemaps are hand-curated, not auto-generated from every header).
cfb6c9a to
7cc912d
Compare
Add
filesystem (block_size, blocks, free_blocks, inodes, free_inodes)field to protobufContainerStats.files,ffreetoinodesandfree_inodesas those are POSIX's abstract.Add
ManagedContainer.filesystemStatswhich stats the file system usingstatfssyscall. This exposes all fields instatfsstruct.Update
ContainerStatisticsto includefilesystemfields.usedBytes = (blocks - freeBlocks) * blockSize,inodesUsed = inodes - freeInodes.FS capacity = blocks * blockSize).Added
CZ_statfsinLCShim/syscall.cinstead of usingmuslorglibcbecause it fails to importstatfswhen compiling for x86_64 linux.