Commit Graph
95 Commits
Author SHA1 Message Date
Derek McGowan 0b641f0099 mount: honor a claimed transform as a chain suffix
A claimed transform was recorded but never actually left unapplied:
every parsed transformer in a mount's chain was applied in full
regardless of what the caller had claimed, so a shim advertising it
performs "mkdir" in "format/mkdir/overlay" never got the chance to,
since the manager silently applied it anyway. This predates the shim
capability protocol — it was reachable before through the "format/*"
annotation convention — but this series turns it into a documented,
supported way for a shim to claim a transform, so a shim relying on it
(at least one is: Kata's EROFS snapshotter shim, per its annotation
usage) would find its claim silently ignored.

A claimed transform can only be honored as a suffix of the chain: each
transform's input is the previous one's output, so an outer, unclaimed
transform must still be applied even when an inner one is claimed,
since the inner one cannot run without it. planActivation now tracks,
per mount, how much of its chain — starting from the beginning — the
manager must apply itself: through the last unclaimed transform, which
by construction covers every transform before it too. Applying only
that prefix and returning the true, contiguous claimed suffix to the
caller is what actually makes the claim meaningful. This is only
observable for mounts[firstSystemMount], the one mount partially
transformed by the manager and returned to the caller to finish; every
earlier mount is fully internal to the manager and was, and remains,
always fully transformed regardless of any claim.

While changing this expression, also guard it against the case where
firstSystemMount reaches len(mounts) — every mount consumed inside the
manager, with no system mount left to transform — which indexes out of
range today. This is a distinct, pre-existing latent panic (for
example, reachable via WithTemporary combined with a transformed mount
type), tracked separately from the claim-handling fix above; guarding
it here only prevents a crash newly reachable by touching this line,
it does not address the mount.ActivationInfo.System non-empty
invariant that scenario also violates.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Derek McGowan 8ba69faf06 mount: extract activation planning
Activate's planning phase — deciding, for each mount, which transforms
the manager must apply and whether the manager or the caller performs
the mount itself — was inline in a bolt transaction spanning hundreds
of lines, and every existing test of it goes through the full Activate
path, which needs root to mount anything for real.

Extract it into planActivation, a pure function of the mount list,
activation options, and registered transforms/handlers. No behavior
change; this is what makes the next commit's fix testable without
root.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Derek McGowan 00967ecf03 mount: add WithAllowTransform activate option
A caller that applies a mount transform itself had to say so by naming the
mount type "format/*", a sentinel the mount manager constructs internally
by concatenating a transform name with "/*". Both sides had to
independently know and agree on that convention, and the resulting string
is neither a mount type nor a transform name.

Add AllowTransforms, and WithAllowTransform to set it, so a transform can
be claimed by its own name instead. The "/*" convention is removed rather
than kept as a second accepted spelling: it existed only to be produced by
the runtime-allow-mounts annotation, which is removed in an earlier commit
in this series, and there is no other producer of it in this tree.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Maksym Pavlenko 257a5900b0 core/unpack: detect staged layers via read-only mounts
Replace the snapshots.ErrAlreadyStaged sentinel error with a
read-only-mounts signal: a snapshotter (e.g. erofs serving a layer
content cache hit) now returns Prepare mounts normally, with no
error, when the layer content is already staged into the active
snapshot. The unpacker's isStaged helper checks the last mount's
ReadOnly() to decide whether to skip fetch+apply and just commit.

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-07-31 09:18:16 -07:00
Maksym Pavlenko c792ddd46d Merge pull request #13754 from dgdegraaf/fix-fsmount-selinux
fsmount: Fix selinux mount parameter parsing
2026-07-20 00:24:48 +00:00
Daniel De Graaf dd2bcfc643 fsmount: Fix selinux mount parameter parsing
Because selinux contexts can contain commas, context strings may be
quoted in the single-syscall mount API. This quoting is not permitted
when using the fsconfig API, so strip the quotes when preparing the
system call arguments.

Signed-off-by: Daniel De Graaf <dgdegra@uwe.nsa.gov>
2026-07-17 08:51:13 -04:00
SaloniRathi 807fbc13dc core/mount/manager: improve TestMkdirHandler failure messages
Signed-off-by: SaloniRathi <45892093+SaloniRathi@users.noreply.github.com>
2026-07-16 17:43:32 -05:00
Austin VazquezandRob Murray 3bc019ea3d fix: close boltdb on metadata and mount plugin close
Co-authored-by: Rob Murray <rob.murray@docker.com>
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
2026-05-05 17:20:26 -05:00
Samuel Karp f7150e2215 Merge pull request #13126 from dmcgowan/handle-mount-already-exists
Fix mount manager activation error when already exists
2026-04-24 16:16:40 +00:00
Derek McGowan 80ec03fe7e core/mount: Fix mount manager activation error when already exists
Correctly handle cases where the mount activation still exists:
- If activation is fully activate, then just return already exists and
  allow the caller to return error or call Info to continue.
- If activation is stale or incomplete due to crash during activation,
  overwrite the identifier and cleanup the incomplete activation during
  activate.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-04-20 18:04:16 -07:00
Chris Henzie 93f7a62e50 Support both styles of volatile mount option
Kernel 6.12.80+ returns 'fsync=volatile' instead of just 'volatile'
in mount options, which breaks containerd's exact string matching
checks.

Fixes this issue by adding support for 'fsync=volatile' in addition
to the existing 'volatile' check in RemoveVolatileOption and
addVolatileOptionOnImageVolumeMount.

Assisted-by: Antigravity
Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
2026-04-20 11:50:57 -07:00
Aadhar Agarwal 6f7bb48624 core/mount: Filter X-containerd.* options before kernel mount
The X-containerd.* prefix is reserved for containerd-internal mount
options that are processed by containerd components (such as mount
transformers and handlers). These options must not be passed to the
kernel mount syscall.

This change adds filtering at the core mount layer
as a safety net to prevent kernel errors if components forget to clean
up their options.

Signed-off-by: Aadhar Agarwal <aadagarwal@microsoft.com>
2026-03-23 23:50:54 +00:00
Sebastiaan van Stijn 22fd63994e *: modernize: stringscutprefix
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-17 13:36:17 +01:00
Sebastiaan van Stijn 24012ef8f6 *: modernize: stringscut, stringsseq, slicescontains, fmtappendf
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-17 13:36:17 +01:00
Sebastiaan van Stijn 8fcf3a3cf1 *: modernize: rangeint
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-17 13:36:16 +01:00
Sebastiaan van Stijn a499b17f21 *: modernize: stringscutprefix
go install golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest
    modernize -stringscutprefix -fix ./...

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-15 18:24:16 +01:00
Sebastiaan van Stijn 18c74abd56 *: modernize: slicescontains
go install golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest
    modernize -slicescontains -fix ./...

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-15 18:24:14 +01:00
Sebastiaan van Stijn 3723a67092 core: modernize: rangeint
go install golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest
    modernize -rangeint -fix ./...

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-15 14:56:35 +01:00
user.email 1466c53196 core/mount: add test for getUnprivilegedMountFlags
Mounts a tmpfs with MS_NOEXEC, MS_NOATIME, and MS_NODIRATIME and
verifies that getUnprivilegedMountFlags detects all of them. These
three flags were the ones missed by the range-over-indices bug.

Also verifies that flags not present on the mount (MS_NOSUID,
MS_NODEV, MS_RDONLY) are not falsely reported.

Signed-off-by: Luke Hinds <luke@stacklok.com>
2026-02-26 00:13:53 -06:00
user.email 5d3b3447c7 core/mount: fix getUnprivilegedMountFlags iterating over indices instead of values
The loop `for flag := range unprivilegedFlags` iterates over slice
indices (0,1,2,3,4,5,6) rather than the actual flag values (MS_RDONLY,
MS_NODEV, etc). This was a porting error from moby/moby where the data
structure was a map (where `for k := range m` yields keys/values).

As a result, MS_NOEXEC, MS_NOATIME, MS_RELATIME, and MS_NODIRATIME are
never detected or preserved. In user namespaces, this causes bind-mount
remounts to fail with EPERM when any of these flags are locked on the
parent mount, because the kernel requires all CL_UNPRIVILEGED locked
flags to be preserved during remount.

MS_RDONLY (0x1), MS_NOSUID (0x2), and MS_NODEV (0x4) happened to work
by coincidence because their values equal low index numbers.

Fix by using `for _, flag := range` to iterate over values.

Signed-off-by: Luke Hinds <luke@stacklok.com>
2026-02-26 00:13:53 -06:00
Akihiro Suda 317286ac00 Merge pull request #12581 from ticpu/fix-12549-ctr-image-mount-fails-no-such-device
Fix ctr image mount failing with no such device
2026-01-28 02:50:36 +00:00
Andrew Halaney 5525003608 core/mount/*linux: Do idmap bind mounts as private and recursive
Recursive is needed to catch mounts under the bind mount, for example
erofs mount points. i.e. with that in place things like:

    /foo/erofs1
    /foo/erofs2

    bind mount + idmap /foo/ -> /foo-idmapped/

makes it so erofs1 and erofs2 are at /foo-idmapped/, allowing us to use
that when constructing the final overlay mount erofs snapshotters use.
This let's the snapshotter claim to support idmap support later without
issue (right now it goes through remapfs).

As part of this, we want to make the bind mount have private mount
propagation. If you umount /foo-idmapped/erofs1 it shouldn't affect
/foo/erofs1, which could be reused in another container's lowerdirs and
idmapped bind mount.

Signed-off-by: Andrew Halaney <ahalaney@netflix.com>
2026-01-02 09:44:53 -06:00
Andrew Halaney 44751e28b3 core/mount: Don't apply uidmap/gidmap during ro instrospection
containerd will do a read only mount of the mount string to inspect
things like /etc/passwd for a username to uid mapping. It doesn't need
to do a uidmap/gidmap for this, that's entirely for the actual container
mount later.

Let's stop doing the idmap here, its extra work and not necessary.
Further, it causes complications when the mount manager is involved.
Mount manager will by default create erofs layers at
/run/containerd/io.containerd.mount-manager.v1.bolt/t/8103/1, and the
snapshotter's upperdir is at (if configured to use a different path)
/mnt/containerd/io.containerd.snapshotter.v1.erofs/snapshots/25795/fs.

During the read only mount this upperdir is shoved into the lowerdirs
list, and then the idmap code tries to find the common parent directory of
all lowerdirs. In this case its "/", which is invalid, so the process
fails.

Let's stop doing the extra work and get away from this class of
problems by doing less.

Signed-off-by: Andrew Halaney <ahalaney@netflix.com>
2026-01-02 09:44:53 -06:00
Akihiro Suda f37f951f56 Merge pull request #12545 from erofs/fixes
Avoid using redundant loop devices to run mkfs for mount manager tests.
2025-11-28 07:13:24 +00:00
Jérôme Poulin 776e50aa21 core/mount/manager: fix bind mount missing rbind option
The bind mount created for temporary activations was missing the
Options field, causing mount to fail with "no such device" because
the MS_BIND flag wasn't being set.

Fixes #12549

Signed-off-by: Jérôme Poulin <jeromepoulin@gmail.com>
2025-11-26 18:42:38 -05:00
Jérôme Poulin d2593b6477 core/mount/manager: add tests for WithTemporary option
Add tests for the WithTemporary mount activation used by `ctr images mount`.
Covers bind mount and overlay scenarios to catch regressions like #12549.

Signed-off-by: Jérôme Poulin <jeromepoulin@gmail.com>
2025-11-26 18:42:38 -05:00
Wei Fu a5c84021c8 core/mount: should not call removeLoop when set autoclear
In CI we run make root-test via gotestsum, which executes multiple
package tests concurrently. TestAutoclearTrueLoop attempts to invoke
LOOP_CLR_FD using a device name, which introduces a race condition.

Example race:

Process P1 represents mount.test which runs TestAutoclearTrueLoop
Process P2 represents manager.test which runs TestLoopbackMount

T1: P1 closes fd of loop-device (loop3) (kernel unsets backing-file on close)
T2: P2 gets loop3 from /dev/loop-control
T3: P2 configures loop3 with backing file successfully
T4: P1 invokes removeLoop to clear backing file for loop3

You might see that failure like this

```
=== FAIL: core/mount/manager TestLoopbackMount (0.05s)
    log_hook.go:47: time="2025-10-23T21:49:22.532811960Z" level=debug msg="activating mount" func="manager.(*mountManager).Activate" file="/home/runner/work/containerd/containerd/core/mount/manager/manager.go:134" mounts="[{loop /tmp/TestLoopbackMount989607109/001/fs-1621892597  []} {format/ext4 {{ mount 0 }}  []}]" name=id1 testcase=TestLoopbackMount
    helpers.go💯 unmount /tmp/TestLoopbackMount989607109/001/test-mount-3030342351
    manager_linux_test.go:80:
        	Error Trace:	/home/runner/work/containerd/containerd/core/mount/manager/manager_linux_test.go:80
        	            				/home/runner/work/containerd/containerd/core/mount/manager/manager_linux_test.go:105
        	Error:      	Received unexpected error:
        	            	failed to get loop device info: no such device or address
        	Test:       	TestLoopbackMount
```

To fix this, the test now compares backing-file's inode directly and does
not call removeLoop when autoclear is set.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
2025-11-23 21:31:08 -05:00
Gao Xiang 190ed6b677 Avoid using redundant loop devices to run mkfs for mount manager tests.
mkfs.ext4 supports creating filesystems from regular files.

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
2025-11-19 11:50:01 +08:00
Gao Xiang 5b9d871fea Add EROFS mount handler plugin
Commit ee8ae9d569 ("Update erofs snapshotter to use mount manager")
temporarily removed the file-backed mount feature to adapt to the new
mount manager infrastructure as a quick start.

After the mount manager was introduced, a specific mount type can be
handled with a mount handler plugin to provide a dedicated mount
process (e.g. setup loopback devices in advance or calling external
mount helpers).

This commit adds a default EROFS mount handler for the Linux hosts
to set up loop devices for mount sources and "device=" external file
blobs if necessary (i.e. when file-backed mounts are unavailable),
allowing common runtimes such as runC to work directly, e.g.
 ``` sh
 mount -t erofs /var/lib/containerd/io.containerd.snapshotter.v1.erofs/snapshots/1/layer.erofs \
  /run/containerd/io.containerd.mount-manager.v1.bolt/t/346/1
 ```
 will be handled as
 ``` sh
 mount -t erofs /dev/loop1 /run/containerd/io.containerd.mount-manager.v1.bolt/t/346/1
 ```
and
 ``` sh
 mount -t erofs /var/lib/containerd/io.containerd.snapshotter.v1.erofs/snapshots/7/fsmeta.erofs \
   -odevice=/var/lib/containerd/io.containerd.snapshotter.v1.erofs/snapshots/1/layer.erofs,\
     device=/var/lib/containerd/io.containerd.snapshotter.v1.erofs/snapshots/2/layer.erofs,\
     ...
     device=/var/lib/containerd/io.containerd.snapshotter.v1.erofs/snapshots/7/layer.erofs
   /run/containerd/io.containerd.mount-manager.v1.bolt/t/335/1
 ```
 will be handled as
 ``` sh
 mount -t erofs /dev/loop1 -odevice=/dev/loop2,device=/dev/loop3,... \
   /run/containerd/io.containerd.mount-manager.v1.bolt/t/335/1
 ```
if file-backed mounts are unavailable.

For other host platforms (e.g. Darwin hosts) or specific runtimes
that require EROFS raw mounts instead of parsed mounts, this plugin
can be explicitly masked off by users.

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
2025-10-22 22:57:42 +08:00
Gao Xiang 8a6e6263f8 Support arbitary mkfs size (not only in MiB)
Rename `default_size_mb` to `default_size` so that it's similar to
Docker's `--storage-opt size=30G` flag.  For example,

``` toml
[plugins."io.containerd.snapshotter.v1.erofs"]
  default_size = "5GB"
```

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
2025-10-21 15:35:05 +08:00
Gao Xiang 3cc411c8b2 Fix backreference support for mount manager
The mount manager GC seems to be broken on my local setup.

According to commit df87a8f71b ("Add support for backreferences
in gc"), the interface name should be "ActiveWithBackRefs" instead.

After this patch, erofs and ext4 mounts won't be GCed in advance.

Fixes: 184fae60fc ("Add backreference support to mount manager")
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
2025-10-21 15:06:20 +08:00
Derek McGowan 0d62c71885 Update loopback test to make initialization more robust
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-10-19 13:38:40 -07:00
Derek McGowan 25c3871baa Switch mount manager tests to ext4
Reduce the size of the test files. Even using sparse files, the reported
large size may cause issues in some test environments.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-10-16 16:58:37 -07:00
Derek McGowan 55d5d5b500 Add Close method to mount manager
Adding a close method allows the mount manager to close any open file
descriptors. The method will also be called automatically by containerd
on shutdown.

Ensure the tests call Close to avoid leaking file descriptors or errors
on Windows cleaning up directories that are in use.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-10-16 16:01:29 -07:00
Derek McGowan be9f183f45 Add mount transformers to mount manager
Extend the mount manager to support more transformers than format. The
transformers allow altering the mount before it is passed to the mount
handlers. These could be one-time actions which are needed to perform
the mount.

Adds mkdir and mkfs actions which can be used to prepare the arguments
for a mount. The actions can be limited to actions within the target
mount directory or plugin directories.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-10-14 16:35:53 -07:00
Derek McGowan c7b3114ebb Update mount manager code documentation
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-30 13:37:11 -07:00
Derek McGowan 94e6bcea50 Add support for allowing custom types through mount manager
Allow the mount manager to skip handling of custom types. Ensure that
custom types are still working with formatted mounts.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:38 -07:00
Derek McGowan dd9c43150a Add option to allow formatted mounts
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:38 -07:00
Derek McGowan 9c21e867ed Handle flaky case for loop autoclear
The autoclear may take a bit of time to clear out the file, check
multiple times for the file to get removed before returning an error.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:37 -07:00
Derek McGowan f7b77e649c Update mount manager cleanup logic
Avoid keeping file descriptor open to directory which is getting
removed. Update error handling and wrapping to provide more clarity
around failures.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:37 -07:00
Derek McGowan fa327566bb Fix mount manager deactivate errors
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:36 -07:00
Derek McGowan 9c0cc4a424 Add mount manager format test
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:36 -07:00
Derek McGowan 5b4de2c34f Add implementation of list and get mount activation
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:34 -07:00
Derek McGowan 184fae60fc Add backreference support to mount manager
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:34 -07:00
Derek McGowan 9794addcea Add mount formatting test
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:34 -07:00
Derek McGowan d8e5cdd76a Fix gc cleanup and add unit tests for gc
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:34 -07:00
Derek McGowan c8e7674cc9 Add temporary mount support to manager
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:33 -07:00
Derek McGowan 75ed5e0037 Fix mount manager gc
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:32 -07:00
Derek McGowan 8db3010865 Add mounts api service
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:31 -07:00
Derek McGowan 4d34b01ce0 Add loopback and overlay mount manager tests
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-09-29 17:08:31 -07:00