Closed matoro closed 11 months ago
Note that psutil has the correct size data, but the wrong block device.
Why is it wrong? (I don't mean related to this test, but in general) Do you think it should be changed? If yes, how?
Note that psutil has the correct size data, but the wrong block device.
Why is it wrong? (I don't mean related to this test, but in general) Do you think it should be changed? If yes, how?
Because /usr/src
is not on /dev/loop0
. I see that psutil is just passing along getmntent()
here, I'm not sure why getmntent()
is returning this wrong block device. /etc/mtab
seems to have correct information:
$ grep "^/dev" /etc/mtab
/dev/loop0 / ext4 rw,relatime 0 0
/dev/root /usr/src ext4 ro,noatime 0 0
So maybe that is the correct thing to do? This SO answer says:
There's no portable way to programmatically get the list of mounted filesystems. (
getmntent()
getsfstab
entries, which is not the same thing.)
But I'm not really sure.
Hmm, interesting. It must be noted that we use getmntent()
on Linux, AIX and SunOS. On BSD* and macOS we use something else, so probably they are fine. This answer suggests that we may use the /sys filesystem to get the correct info.
I'm tempted not to merge your PR since the test failure reliably reproduces the problem, so it's good we have it. I'd rather try to fix the problem itself.
Hmm, interesting. It must be noted that we use
getmntent()
on Linux, AIX and SunOS. On BSD* and macOS we use something else, so probably they are fine. This answer suggests that we may use the /sys filesystem to get the correct info.I'm tempted not to merge your PR since the test failure reliably reproduces the problem, so it's good we have it. I'd rather try to fix the problem itself.
That only tells us how to go from major/minor to block name, but what call would we use to go from mountpoint to major/minor? If we switch from getmntent()
to something else, we also need a way to iterate over the mountpoints.
What about if we left getmntent()
alone for everything except the block device (since it seems correct), and then parsed /etc/mtab
for the block device?
Edit: This might not work on SunOS or HP-UX.
coreutils uses /proc/self/mountinfo
on Linux: https://github.com/coreutils/gnulib/blob/master/lib/mountlist.c#L480-L481
This appears to have major/minor numbers available, AND true block device names.
grep "/dev" /proc/self/mountinfo
54 57 7:0 / / rw,relatime - ext4 /dev/loop0 rw
56 54 0:5 / /dev rw,nosuid,noexec,relatime - devtmpfs devtmpfs rw,size=10240k,nr_inodes=97648,mode=755
58 56 0:17 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw
59 56 0:23 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000
60 56 0:24 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw
67 54 254:2 /usr/src /usr/src ro,noatime - ext4 /dev/root rw
But this is again Linux-specific and not for other Unix.
After research here I have come to conclusion that the root of the issue is indeed using /proc/self/mounts
instead of /proc/self/mountinfo
and while not formally designated as such, the former is deprecated in favor of the latter, which is also strictly a superset of the former. mountinfo
was introduced in 2008 specifically to solve this bind-mount problem. GNOME ran into this problem in 2009 for their disks utility and even downstream now considers mountinfo
"the authoritative source to check your mounts". Golang uses this file to back their mountinfo
package in their stdlib.
Therefore I believe the correct approach to this is to prioritize /proc/self/mountinfo
(which needs a new parser due to its differing format) and keep the old /proc/self/mounts
logic as a fallback.
Can you please open a new issue pointing to this one which contains a lot of useful info?
Summary
Description
Otherwise this test fails for environments with active bind-mounts. For example, consider the following:
Note that psutil has the correct size data, but the wrong block device. If we pass the path to
df(1)
instead of the incorrect block device, thendf(1)
will return results from the correct filesystem.