On Tue, 19 Sept 2023 at 02:38, Matthew House <mattlloydhouse@xxxxxxxxx> wrote: > One natural solution is to set either of the two lengths to the expected > size if the provided buffer are too small. That way, the caller learns both > which of the buffers is too small, and how large they need to be. Replacing > a provided size with an expected size in this way already has precedent in > existing syscalls: This is where the thread started. Knowing the size of the buffer is no good, since the needed buffer could change between calls. We are trying to create a simple interface, no? My proposal would need a helper like this: struct statmnt *statmount(uint64_t mnt_id, uint64_t mask, unsigned int flags) { size_t bufsize = 1 << 15; void *buf; int ret; for (;;) { buf = malloc(bufsize <<= 1); if (!buf) return NULL; ret = syscall(__NR_statmnt, mnt_id, mask, buf, bufsize, flags); if (!ret) return buf; free(buf); if (errno != EOVERFLOW) return NULL; } } Christian's would be (ignoring .fs_type for now): int statmount(uint64_t mnt_id, uint64_t mask, struct statmnt *st, unsigned int flags) { int ret; st->mnt_root_size = 1 << 15; st->mountpoint_size = 1 << 15; for (;;) { st->mnt_root = malloc(st->mnt_root_size <<= 1); st->mountpoint = malloc(st->mountpoint <<= 1); if (!st->mnt_root || !st->mountpoint) { free(st->mnt_root); free(st->mountpoint); return -1; } ret = syscall(__NR_statmnt, mnt_id, mask, st, sizeof(*st), flags); if (!ret || errno != EOVERFLOW) return ret; free(st->mnt_root); free(st->mountpoint); } } It's not hugely more complex, but more complex nonetheless. Also having the helper allocate buffers inside the struct could easily result in leaks since it's not obvious what the caller needs to free, while in the first example it is. Note that I'm not against having the prototype on the kernel interface take a typed pointer. If strings are not needed, both interfaces would work in exactly the same way. Thanks, Miklos