RFC on FileStore and /proc/mounts on Linux in a chroot jail, Docker overlayfs and with btrfs

David M. Lloyd david.lloyd at redhat.com
Tue Jun 20 20:10:18 UTC 2017

Another fun fact.  You can create a bind mount of a regular file, not 
just a filesystem, meaning a regular file shows up as a mount point in 
the various mount table files.  When traversing up the filesystem tree, 
it might be necessary to follow bind mount links.

On 06/15/2017 08:10 AM, David M. Lloyd wrote:
> Sorry for the late response on this.  I asked around a bit and so far 
> have turned up at least one possibly useful insight: 
> /proc/self/mountinfo might be a more useful source of information than 
> /proc[/self]/mounts.
> This is because mountinfo correlates the major:minor device number with 
> the mount point/filesystem.  So you can lstat a file and derive useful 
> information by correlating the major/minor fields in mountinfo with 
> st_dev.  You could perhaps iterate all the matching filesystems looking 
> for one which is a prefix match.
> The fields in mountinfo are also interesting in that they contain a 
> unique (for at least that particular iteration of the file) ID for each 
> mount, plus a link to the "parent" ID.  More info on this file is in the 
> proc(5) manpage.
> If the question is "what is the mount point", and nothing matches, then 
> I think it's (probably?) safe to conclude that the mount point is "/". 
> Using lstat and mountinfo, even if there is no "/" entry, you will know 
> the de-facto mount point (which must be "/") and the device major:minor. 
>   You won't have the mount options, but maybe there are ways you can 
> infer them.
> One other oddball thing I remember from my initramfs-tinkering days is 
> that you can end up in a situation where there are multiple mounts on 
> the same mount point.  Using mountinfo also helps this case because you 
> can use the device number to eliminate the wrong answer.
> The btrfs problem seems to be evidence that the assumption that there is 
> a mount entry for every device major:minor might be flawed.  If there's 
> a device ID transition and there is no matching mountinfo entry, perhaps 
> the best option is to simply continue traversing upwards until an 
> existent device ID is found.
> Hope this helps.
> On 10/06/2016 07:18 PM, Brian Burkhalter wrote:
>> I would be interested in any ideas anyone would like to share on this 
>> topic. There are three related issues [1, 2, 3] which have been filed. 
>> The most generic issue is [3] which has been observed in three 
>> different contexts:
>> A) chroot environment [1]
>> B) Docker container with overlay and overlay2 storage drivers [2]
>> C) btrfs file system with an unmounted sub-volume [2]
>> In all cases the failure was the IOException with message “Mount point 
>> not found” at line 91 in LinuxFileStore::findMountEntry [4]. This 
>> occurred because the directory identified in step 2 as the mount point 
>> of the path was not found in /proc/mounts in step 3. The mount point 
>> is either the root (/) of the path or the longest sub-path which has a 
>> different device ID from its parent. The device ID is obtained from 
>> the st_dev member of the struct stat populated by stat(2) [5].
>> In the chroot environment the contents of /proc/mounts was just
>> none /proc proc rw,relatime 0 0
>> and the mount point was determined to be “/“ which is not contained in 
>> /proc/mounts so the code falls through to the IOException.
>> In the overlayfs cases, when step 2 breaks out of the parent traversal 
>> loop, the device ID of the given path is valid in the operating system 
>> file system, but the device ID of the parent is not and apparently 
>> corresponds instead to a device ID in the overlayfs itself. As there 
>> is no entry in /proc/mounts for the identified mount point we get the 
>> IOException.
>> In the btrfs unmounted sub-volume case, for example, a btrfs file 
>> system is mounted on /mnt and contains a sub-volume /mnt/new_subvol 
>> which is not mounted. If an attempt is made to obtain the FileStore 
>> for example corresponding to /mnt/new_subvol/junk/junk.txt, step 2 
>> traverses upwards and breaks when it finds that the device IDs of /mnt 
>> and /mnt/new_subvol differ. As /mnt/new_subvol is not in /proc/mounts 
>> the exception ensues.
>> In thinking about this I was wondering whether it could be solved by 
>> creating some “spoofed” mount entry not in /proc/mounts. This however 
>> does not seem like an inherently great idea and would probably create 
>> problems elsewhere.
>> Viewing it from a different angle, one could instead say that the 
>> chroot jail and btrfs sub-volume problems are actually due to 
>> incorrect or incomplete configurations and this is not an issue with 
>> findMountEntry() at all. The overlayfs problem could be viewed as a 
>> bug in the overlay and overlay2 storage driver implementations. This 
>> problem for example does not manifest when the aufs storage driver is 
>> used with Docker.
>> Comments and suggestions welcome.
>> Thanks,
>> Brian
>> [1] https://bugs.openjdk.java.net/browse/JDK-8165323 - cannot get 
>> FileStore in chroot environment (*)
>> [2] https://bugs.openjdk.java.net/browse/JDK-8165852 - cannot get 
>> FileStore for a file in overlayfs in Docker
>> [3] https://bugs.openjdk.java.net/browse/JDK-8166162 - cannot get 
>> FileStore if device of path is not in /proc/mounts
>> [4] 
>> http://hg.openjdk.java.net/jdk9/dev/jdk/file/65042b713b12/src/java.base/linux/classes/sun/nio/fs/LinuxFileStore.java 
>> [5] https://linux.die.net/man/2/stat
>> (*) The immediate problem caused by [1] was fixed and [3] was filed to 
>> track the underlying cause.


More information about the nio-dev mailing list