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.
>>
>
>
--
- DML
More information about the nio-dev
mailing list