Topics from the virtual filesystem layer
In the first filesystem-track session at the 2025 Linux Storage, Filesystem, Memory Management, and BPF Summit (LSFMM+BPF), virtual filesystem (VFS) layer co-maintainer Christian Brauner had a few different topics he wanted to talk about. Issues on the agenda included iterating through anonymous mount namespaces, a needed feature for ID-mapped mounts, the perennial unprivileged mounts topic, potentially using hazard pointers for file reference counting, and Rust bindings. He did not expect to get through all of them in the 30 minutes allotted, but the session did move along pretty quickly to at least introduce them to the assembled filesystem developers.
$ sudo subscribe todaySubscribe today and elevate your LWN privileges. You’ll have access to all of LWN’s high-quality articles as soon as they’re published, and help support LWN in the process. Act now and you can start with a free trial subscription.
He noted that one of the accomplishments for the filesystem community over the last few years was in reworking the mount process and API. He was hopeful that mount notifications would be merged during the 6.15 merge window that was taking place during the summit—and they were. That feature will be useful for getting notifications of changes to mount trees, rather than having to frequently query the kernel or /proc files to keep track.
Anonymous mount namespaces
In the VFS, there is a notion of anonymous mount namespaces ("or
'detached mount trees', however you want to look at it
") where a mount
namespace exists, but processes cannot use setns()
to enter it; it is not attached to anything else. Oddly, though, a process
can chroot()
to a directory in it, but then cannot list the mounts in the namespace.
These mount namespaces do not have a representation in
/proc/PID/mountinfo, which makes them "completely opaque to
user space
"; there is no way to interact with them, he said. That is a
problem because, for example, a process can have a file descriptor for such
a namespace, which pins various things into memory, but there is no way for
user space to
figure out what is responsible for pinning the memory.
So there is a need to expand the listmount() and statmount() system calls to be able to interact with anonymous mount namespaces. There is now a way to iterate through all mounts in all mount namespaces, except those attached to anonymous mount namespaces. Container workloads, under Kubernetes in particular, can have hundreds of mount namespaces; prior to the addition of listmount() and statmount(), listing all of the mounts would have required concatenating the output from all of the /proc/PID/mountinfo files. Extending that to the anonymous mount namespaces will help complete the API, he said.
Jeff Layton asked if the anonymous mount namespaces are collected onto a list in the kernel somewhere, but Brauner said they are not currently. There is a red-black tree for the mount namespaces, but that is indexed by the sequence number assigned to the namespace; anonymous mount namespaces all have a sequence number of zero. Instead of using the zero to recognize anonymous entries, a flag or something should be used, then a regular sequence number can be assigned and the entries can be added to the tree, Brauner said.
Layton said that he has been running into a similar problem with network namespaces; NFS can take a reference to a disconnected network namespace that then stays alive with no way to track down what has the reference. Brauner said that he had discussed this problem with Josef Bacik recently and they agreed that all namespaces should follow the plan for mount namespaces and assign a sequence number for each; the struct ns_common that holds namespaces would have the sequence number (or some kind of identifier) added to it, so that namespaces can be added to data structures and operated upon. It is a generic problem for namespaces that should be solved in a unified way, Brauner said.
ID-mapped mounts
Another thing he has been working on is a follow-on to the ID-mapped mounts feature that was merged into the 5.12 kernel in 2021. In 6.15, the ability to change UID and GID mappings for an ID-mapped filesystem by performing another ID-mapped mount on it was added. Now there is a need for various squashing options, where, for example, a range of IDs all map to a single ID.
One of the problems with the existing ID-mapping mechanism is that every ID present in the filesystem needs to be explicitly mapped to another ID or a file with an unmapped ID has no ID—it cannot be interacted with at all. For efficiency reasons, there may need to be limits on the number of squashed ranges that can be supported, but some kind of simple range squashing is needed. In addition, a way to say that any unlisted IDs map to a single specific ID should be supported.
The interface for specifying mappings currently follows the model that user namespace mappings use, where mapping information is written to /proc files. That works, but Brauner does not think it will scale to the needs of ID-mapped mounts. His immediate focus is to add a way to squash all of the unmapped IDs to a specified ID; he has a proof-of-concept implementation in his tree that passes all of his tests. It will make things much simpler for use cases like mapping all of the IDs on a filesystem to a single ID as no lookup will be needed.
Unprivileged mounts
Brauner informally polled the audience for which topic the attendees wanted
him to talk about next: unprivileged mounts or file reference counts.
Several spoke up for the mount topic and any reference-count fans were
notably silent. "Dammit, I wanted to pitch hazard pointers
", he said
with a laugh, though he did eventually get to the topic.
There are two
aspects to the unprivileged-mount problem; the first is to allow
unprivileged users to mount "a random USB stick
", which is "a
really terrible idea
".
The other is to mark a specific filesystem as being mountable inside of a user
namespace, "which adds a bit more protection, at least in terms of
setuid binaries and all that kind of stuff
", he said, but it does not
help with the problems of malicious filesystem images. He does not think
that there is any solution for allowing unprivileged users to mount random
filesystem images; "I don't believe that Rust will solve this problem, I
think that's a pipe dream
".
Brauner pointed to the solution described in an LSFMM+BPF session from 2023, which allows user space to
"safely delegate mounting of filesystems to unprivileged users
"
using systemd-mountfsd.
That solution does not work for network filesystems, but Layton said that
was simply a policy decision; the same mechanism could be used but network
filesystems would need to add some capabilities to enable it.
For the USB-stick case, Brauner said, the solution should be to use Filesystem
in Userspace (FUSE) and "don't mount untrusted stuff
". Over the
remote link, Jan Kara said that the solution for USB mounts does not lie in
the kernel. OpenSUSE has started looking into mounting
USB sticks using the Linux Kernel Library (LKL), which is somewhat
similar to User
Mode Linux; it has a FUSE daemon that uses LKL to mount the
filesystem and expose it to the kernel, which "provides additional
isolation
". For USB sticks, performance is not particularly important,
he said, so this "seems like a promising solution
"
Reference counts
Last year, Brauner said, he added
a reference-count mechanism for struct
file; the patch set uses something similar to rcuref with dead zones
so that an unconditional increment can be done when taking a reference to
an entry in the files table via the file descriptor. It provides a 3-5%
performance increase when there is a lot of contention, "which is great
obviously
", but he thinks the scalability problem has just been pushed
out further.
So there is a need to explore other options. There was a patch set implementing hazard pointers for the kernel that he has been experimenting with, but that implementation is not suitable for struct file. It does scanning in the background and memory allocation. If hazard pointers were to be used, though, the file-reference path may need to allocate memory, which would add another possible error path.
He would like to explore the idea further, but it is "a very vague
idea
" at this point; it might lead to regressions in the
single-threaded case, though, which would not be desirable. Amir Goldstein
asked where the scalability problem lies; Brauner said that it comes from
contention with socket file descriptors in highly threaded workloads.
"It's not fantasized, it's actually an issue
", but is not likely to
be one for highly threaded writes, because there are other synchronization
activities present for those workloads.
Wrapping up in his final 30 seconds, Brauner said that the Rust inode
bindings should be discussed at some point. He plans to pick up those
patches in the hopes of "getting something like that merged
" within
the next two years.
| Index entries for this article | |
|---|---|
| Kernel | Filesystems/Virtual filesystem layer |
| Conference | Storage, Filesystem, Memory-Management and BPF Summit/2025 |