Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: getmntinfo compatibility question
On Fri, Feb 14, 2025 at 07:34:51AM +0100, Martin Husemann wrote:
> On Thu, Feb 13, 2025 at 11:13:07PM +0100, Thomas Klausner wrote:
> > and versioned the statvfs syscall. I'm not sure how the syscall
> > compatibility works, but rust's libc crate still has the old
> > definition of the struct
>
> Where is that struct definition?
https://github.com/rust-lang/libc/blob/2258bf0fb96767bcffbe3ed09b29a31ee54b549b/src/unix/bsd/netbsdlike/netbsd/mod.rs#L853
> It seems to be wrong somehow. I tried your program on a powerpc machine
> and get:
>
> Breakpoint 3, rust_getmntinfo::get_mount_points () at src/main.rs:20
> 20 let mut fs_infos: *mut libc::statvfs = std::ptr::null_mut();
> (gdb) n
> 21 let count = unsafe { libc::getmntinfo(&mut fs_infos, libc::MNT_WAIT) };
> (gdb)
> 22 if count < 1 {
> (gdb) p count
> $1 = 7
> (gdb) p fs_infos[0]
> $3 = libc::unix::bsd::netbsdlike::netbsd::statvfs {f_flag: 86016, f_bsize: 4096, f_frsize: 32768, f_iosize: 116136549, f_blocks: 481244119186087439, f_bfree: 124951791354018455, f_bavail: 184717953468299, f_bresvd: 20480, f_files: 52110838204711, f_ffree: 1717990144, f_favail: 0, f_fresvd: 788529152, f_syncreads: 0, f_syncwrites: 0, f_asyncreads: 0, f_asyncwrites: 0, f_fsidx: libc::unix::bsd::fsid_t {__fsid_val: [0,
> 0]}, f_fsid: 0, f_namemax: 0, f_owner: 0, f_spare: [0, 0, 0, 0], f_fstypename: [
> 0 <repeats 18 times>, 47, 100, 101, 118, 47, 100, 107, 48, 0, 0, 0, 0, 0, 0], f_mntonname: [
> 0 <repeats 77 times>, 7, 16, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0 <repeats 18 times>, 139, 1, 0,
> 1, 210, 139, 0, 0, 0, 0, 0, 0, 16, 0 <repeats 13 times>, 107, 101, 114, 110, 102, 115, 0, 0, 0, 0, 0,
> 0, 0, 0, 0, 0, 47, 107, 101, 114, 110, 0 <repeats 85 times>, 107, 101, 114, 110, 102, 115,
> 0 <repeats 86 times>, 16, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0 <repeats 18 times>, 123, 2, 0, 0,
> 107, 123, 0, 0, 0, 0, 0, 0, 16, 0 <repeats 13 times>, 112, 116, 121, 102, 115, 0 <repeats 11 times>,
> 47, 100, 101, 118, 47, 112, 116, 115, 0 <repeats 82 times>, 112, 116, 121, 102, 115,
> 0 <repeats 87 times>...], f_mntfromname: [0 <repeats 77 times>, 2, 0, 0, 0, 0, 2, 0, 0, 0, 32, 0, 127,
> 255, 255, 255, 127, 255, 255, 255, 96, 61, 106, 120, 21, 103, 253, 254, 21, 86, 181, 164, 0, 0, 11, 5,
> 0, 0, 7, 11, 0 <repeats 20 times>, 110, 102, 115, 0 <repeats 13 times>, 47, 109, 112, 51,
> 0 <repeats 86 times>, 101, 109, 109, 97, 115, 58, 47, 110, 111, 114, 97, 105, 100, 47, 109, 112, 51,
> 0 <repeats 74 times>, 2, 0, 0, 0, 0, 2, 0, 0, 0, 32, 0, 127, 255, 255, 255, 127, 255, 255, 255, 96,
> 61, 106, 120, 21, 103, 253, 254, 21, 86, 181, 164, 0, 0, 11, 6, 0, 0, 7, 11, 0 <repeats 20 times>,
> 110, 102, 115, 0 <repeats 13 times>, 47, 109, 110, 116, 0 <repeats 86 times>, 101, 109, 109, 97, 115,
> 58, 47, 110, 101, 108, 108...]}
> (gdb) p sizeof(fs_infos[0].f_flag)
> $5 = 4
>
> Compare with:
>
> > df -G /
> / (/dev/dk0 ): 32768 block size 4096 frag size
> 116136549 total blocks 112048377 free blocks 106241550 available
> 29092606 total files 28605079 free files a800 filesys id
> ffs fstype 0x5000 flag 255 filename length
> 0 owner 12151 syncwrites 2684 asyncwrites
Yes, it's similarly broken on my system:
(gdb) p fs_infos[0]
$2 = libc::unix::bsd::netbsdlike::netbsd::statvfs {f_flag: 1342177281, f_bsize: 4096, f_frsize: 32768, f_iosize: 207559395, f_blocks: 152865344, f_bfree: 142487375, f_bavail: 52001278, f_bresvd: 50758388, f_files: 8293581891585, f_ffree: 0, f_favail: 20480, f_fresvd: 1819408, f_syncreads: 297679, f_syncwrites: 0, f_asyncreads: 7562854, f_asyncwrites: 0, f_fsidx: libc::unix::bsd::fsid_t {__fsid_val: [47,
0]}, f_fsid: 0, f_namemax: 0, f_owner: 0, f_spare: [0, 0, 0, 0], f_fstypename: [0 <repeats 32 times>], f_mntonname: [0 <repeats 14 times>, 47, 100, 101, 118, 47, 100, 107, 49, 0 <repeats 86 times>, 7, 0, 0, 16,
0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0 <repeats 39 times>, 1, -117, 0, 0, -117, -46, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0 <repeats 30 times>, 107, 101, 114, 110, 102, 115, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 47, 107, 101, 114, 110, 0 <repeats 85 times>, 107, 101, 114, 110, 102, 115, 0 <repeats 91 times>, 16, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0 <repeats 39 times>, 2, 123, 0,
0, 123, 107, 0 <repeats 11 times>, 16, 0 <repeats 30 times>, 112, 116, 121...], f_mntfromname: [0 <repeats 23 times>, 16, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, -43,
-17, 23, 0, 0, 0, 0, 0, -43, -17, 23, 0, 0, 0, 0, 0, 3, 0, 96, 0, 0, 0, 0, 0, 116, -1, 95, 0, 0, 0, 0, 0, 4, -85, 0, 0, -85, 105, 0 <repeats 11 times>, 16, 0 <repeats 30 times>, 116, 109, 112, 102, 115,
0 <repeats 11 times>, 47, 116, 109, 112, 0 <repeats 86 times>, 116, 109, 112, 102, 115, 0 <repeats 92 times>, 16, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 22, -29, 50, 0, 0, 0, 0, 0, 22, -29,
50, 0, 0, 0, 0, 0, 22, -29, 50, 0, 0, 0, 0, 0, 93, -116, -53, 0, 0, 0, 0, 0, 92, -116, -53, 0, 0...]}
> df -G /
/ (/dev/dk1 ): 32768 block size 4096 frag size
207559395 total blocks 152865277 free blocks 142487308 available
52001278 total files 50758387 free files a801 filesys id
ffs fstype 0x5000 flag 255 filename length
0 owner 1819515 syncwrites 299458 asyncwrites
> Nearly all fields are wrong or swapped with others (like f_bsize <->
> f_frsize) and the f_mntonname field starts 18 bytes early (mountname
> should be /dev/dk0, aka 47, 100, 101, 118, 47, 100, 107, 48, 0)
>
> It would be good to compare with a C version calling __getvfsstat90
> explicitly (e.g. via syscall()) or a static binary with debug info
> compiled on netbsd-9, so we can find out if the error is in the compat
> code or the C structure mapping in rust.
I've tried running this in qemu yesterday, but qemu just hung my machine.
How does one use syscall?
> The kernel compat part works by calling do_sys_getvfsstat() with entry_sz =
> sizeof (struct statvfs) and copyfn = copyout. This just copies mnt_stat
> from each mountpoint out to userland (in the not-chrooted case). I see
> no kind of translation happen anywhere here.
I found lib/libc/compat/gen/compat___getmntinfo13.c which calls
__compat_getvfsstat and ./lib/libc/compat/gen/compat_getmntinfo.c
which calls __compat_getfsstat (no 'v'). So perhaps rust gets the even
older getmntinfo which provides statfs (no 'v') information?
Perhaps we need to add code like FreeBSD has (to rust libc):
https://github.com/rust-lang/libc/blob/2258bf0fb96767bcffbe3ed09b29a31ee54b549b/src/unix/bsd/freebsdlike/freebsd/mod.rs#L5340
#[cfg_attr(
all(target_os = "freebsd", freebsd11),
link_name = "getmntinfo@FBSD_1.0"
)]
pub fn getmntinfo(mntbufp: *mut *mut crate::statfs, mode: c_int) -> c_int;
to use the proper version of getmntinfo, the one with the first
version of statvfs. What name would that be now, '__getmntinfo13'?
Thomas
Home |
Main Index |
Thread Index |
Old Index