Add --mount flag for 9p host directory sharing #9

Merged
hulthe merged 3 commits from feature/9p-mount into master 2026-09-11 09:36:00 +02:00
Collaborator

Summary

Adds a --mount <host_path> flag to slim run that shares a host directory into the VM via QEMU 9p (virtio-9p). The directory appears at the same absolute path inside the VM. Can be repeated for multiple mounts.

How it works

Since 9p mount tags have a ~31-byte limit, the full path can't be used as the tag. Instead:

  1. QEMU side (src/qemu.rs): Each --mount gets a short tag (slim0, slim1, …) via -virtfs local,path=<host_path>,mount_tag=slimN,security_model=mapped-xattr.
  2. Kernel cmdline: The full destination path is passed as slim.mount=<tag>:<base64(path)> — base64 encoding avoids issues with spaces or special characters in paths. Multiple mounts produce multiple slim.mount= entries.
  3. Init script (src/scripts/slim-init.sh): After networking setup, parses slim.mount= entries from the kernel cmdline, creates the target directory with mkdir -p, and mounts with mount -t 9p <tag> <dest> -o trans=virtio,version=9p2000.L.

Test results

The test verifies the user's requested snippet — 9p share detection via sysfs mount_tag, 9p in mount -v output, and file accessibility:

=== Testing --mount (9p shares) ===
-- Building container image...
-- Building slim VM...
-- Booting VM with --mount /tmp/tmp.XXX/share ...
  PASS: --mount 9p share detected
  PASS: --mount 9p filesystem in mount list
  PASS: --mount file accessible in VM
  PASS: --mount VM ran to completion

All 9 alpine + mount tests pass. cargo clippy, cargo fmt --check, and cargo test all clean.

## Summary Adds a `--mount <host_path>` flag to `slim run` that shares a host directory into the VM via QEMU 9p (virtio-9p). The directory appears at the same absolute path inside the VM. Can be repeated for multiple mounts. ## How it works Since 9p mount tags have a ~31-byte limit, the full path can't be used as the tag. Instead: 1. **QEMU side** (`src/qemu.rs`): Each `--mount` gets a short tag (`slim0`, `slim1`, …) via `-virtfs local,path=<host_path>,mount_tag=slimN,security_model=mapped-xattr`. 2. **Kernel cmdline**: The full destination path is passed as `slim.mount=<tag>:<base64(path)>` — base64 encoding avoids issues with spaces or special characters in paths. Multiple mounts produce multiple `slim.mount=` entries. 3. **Init script** (`src/scripts/slim-init.sh`): After networking setup, parses `slim.mount=` entries from the kernel cmdline, creates the target directory with `mkdir -p`, and mounts with `mount -t 9p <tag> <dest> -o trans=virtio,version=9p2000.L`. ## Test results The test verifies the user's requested snippet — 9p share detection via sysfs `mount_tag`, 9p in `mount -v` output, and file accessibility: ``` === Testing --mount (9p shares) === -- Building container image... -- Building slim VM... -- Booting VM with --mount /tmp/tmp.XXX/share ... PASS: --mount 9p share detected PASS: --mount 9p filesystem in mount list PASS: --mount file accessible in VM PASS: --mount VM ran to completion ``` All 9 alpine + mount tests pass. `cargo clippy`, `cargo fmt --check`, and `cargo test` all clean.
Owner

The --mount flag should support the same <host-path>:<guest-path> style that docker does. Non-absolute guest paths should be relative to the working directory configured in the containerfile

The --mount flag should support the same `<host-path>:<guest-path>` style that docker does. Non-absolute guest paths should be relative to the working directory configured in the containerfile
Author
Collaborator

Done. --mount now accepts <host-path>:<guest-path> (Docker-style). When the guest path is omitted, the host path is used. Non-absolute guest paths are resolved against the image WORKINGDIR (written to /slim/workdir at build time, read by slim-init.sh at boot).

Tests cover both absolute guest paths (multi-mount with slim0+slim1) and relative guest paths resolved against WORKINGDIR.

Commit f2b6800 pushed to this PR.

Done. ``--mount`` now accepts ``<host-path>:<guest-path>`` (Docker-style). When the guest path is omitted, the host path is used. Non-absolute guest paths are resolved against the image WORKINGDIR (written to /slim/workdir at build time, read by slim-init.sh at boot). Tests cover both absolute guest paths (multi-mount with slim0+slim1) and relative guest paths resolved against WORKINGDIR. Commit f2b6800 pushed to this PR.
marvin added 3 commits 2026-09-10 12:22:30 +02:00
Add support for sharing host directories into the VM via QEMU 9p
(virtio-9p).  The --mount flag can be repeated; each host directory
appears at the same absolute path inside the VM.

Design:
- QEMU: each --mount gets a short 9p tag (slim0, slim1, …) via
  -virtfs local,path=…,mount_tag=slimN,security_model=mapped-xattr.
  Tags are kept short because 9p mount_tag has a ~31-byte limit.
- Kernel cmdline: the full destination path is passed as
  slim.mount=<tag>:<base64(path)> so the init script knows where to
  mount each tag.  Base64 avoids issues with spaces/special chars.
- slim-init.sh: after networking, parse slim.mount= entries, mkdir -p
  the destination, and mount -t 9p <tag> <dest> -o trans=virtio,version=9p2000.L

Tests verify: 9p share detection via sysfs mount_tag, 9p entry in
mount output, file content accessible at the expected path, and clean
VM exit.
QEMU QemuOpts splits on commas; escape literal commas in the host
path as ,, per QEMU convention to prevent option injection and
boot failures on paths containing commas.

Fix U5: extract b64dec() helper in slim-init.sh

Deduplicate the 3-line base64 fallback decode block used by both
the slim.mount and slim.cmd handlers into a single b64dec() function.

Fix U6: add multi-mount test case

test_mount now passes two --mount flags and asserts both slim0
and slim1 9p tags appear, covering the multi-mount tag-generation
path.
Support host:guest mount syntax with WORKINGDIR resolution
CI / build (pull_request) Successful in 13s
CI / build (push) Successful in 13s
93cbf7ca47
--mount now accepts <host-path>:<guest-path> (Docker-style). When the
guest path is omitted, the host path is used. Non-absolute guest paths
are resolved against the image WORKINGDIR, which is written to
/slim/workdir at build time and read by slim-init.sh at boot.

Changes:
- qemu.rs: Parse host:guest spec, pass guest path (not host path) on
  the kernel cmdline as slim.mount=<tag>:<base64(guest_path)>
- inject.rs: Accept working_dir param, write /slim/workdir into rootfs
- build.rs: Pass config.working_dir to inject()
- slim-init.sh: Read /slim/workdir, resolve relative guest paths
  against it before mounting
- test.sh: Test host:guest absolute paths (multi-mount) and relative
  guest path resolved against WORKINGDIR

Addresses PR #9 review comment from @hulthe.
marvin force-pushed feature/9p-mount from f2b68004ae to 93cbf7ca47 2026-09-10 12:22:30 +02:00 Compare
hulthe approved these changes 2026-09-11 09:35:45 +02:00
hulthe merged commit 93cbf7ca47 into master 2026-09-11 09:36:00 +02:00
hulthe deleted branch feature/9p-mount 2026-09-11 09:36:00 +02:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: hulthe/boco#9