From 807bbcbcd41276feae7d31efbaba3b78cab03356 Mon Sep 17 00:00:00 2001 From: MJ Pooladkhay Date: Thu, 29 Oct 2026 20:03:41 +0000 Subject: [PATCH] add the ability to have read-only virtio-fs shares Signed-off-by: MJ Pooladkhay --- mk/virtiofs.mk | 6 ++++-- scripts/virtiofs-run.sh | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/mk/virtiofs.mk b/mk/virtiofs.mk index f86517bfa..ea5a156bd 100644 --- a/mk/virtiofs.mk +++ b/mk/virtiofs.mk @@ -5,16 +5,18 @@ # make qemu share="tag_1=/path/a tag_2=/path/b" # several shares: tag=dir ... # make qemu share=redox # this build tree, tag "redox" # make qemu share="redox=/other/path" # ordinary share, tag "redox" +# make qemu share=/path/to/dir:ro # read-only, also tag=dir:ro and redox:ro # make ch share=... # the same, on Cloud Hypervisor # # Each share gets its own host-side virtiofsd daemon (started and stopped by # scripts/virtiofs-run.sh), a vhost-user-fs device, and a virtio-fsd scheme # process on Redox. In the guest, a share appears at /scheme/virtio-fsd.. # The emulator flags for each share are added in mk/qemu.mk and mk/ch.mk. +# Shared directories must exist. The guest cannot change anything in a :ro share. # # WARNING: share=redox exposes the whole build tree to the guest, including # the harddrive.img Redox is booted from, .git and .config. Writing to them -# from Redox can corrupt the build system. +# from Redox can corrupt the build system. share=redox:ro avoids that. share?= share_tag?=host @@ -22,7 +24,7 @@ share_sockdir?=$(BUILD) VIRTIOFS_RUN= ifneq ($(strip $(share)),) - share_norm:=$(foreach s,$(share),$(if $(filter redox,$(s)),redox=$(ROOT),$(s))) + share_norm:=$(foreach s,$(share),$(if $(filter redox redox:ro,$(s)),redox=$(ROOT)$(if $(filter %:ro,$(s)),:ro),$(s))) ifeq ($(words $(share_norm)),1) share_list:=$(if $(findstring =,$(share_norm)),$(share_norm),$(share_tag)=$(share_norm)) else diff --git a/scripts/virtiofs-run.sh b/scripts/virtiofs-run.sh index 16ca5b753..5c87d036f 100755 --- a/scripts/virtiofs-run.sh +++ b/scripts/virtiofs-run.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Runs a command next to one virtiofsd per shared directory, for # `make qemu share=...` and `make ch share=...`. -# virtiofs-run.sh --share .sock = [--share ...] -- +# virtiofs-run.sh --share .sock =[:ro] [--share ...] -- set -euo pipefail @@ -13,19 +13,27 @@ die() { } usage() { - echo "usage: $0 --share .sock = [--share ...] -- " >&2 + echo "usage: $0 --share .sock =[:ro] [--share ...] -- " >&2 exit 2 } SOCKS=() TAGS=() DIRS=() +OPTS=() +LABELS=() while [[ "${1:-}" == --share ]]; do [[ $# -ge 3 ]] || usage [[ "$3" == *=* ]] || die "share '$3': expected =" + entry="$3" opt="" label="" + if [[ "${entry}" == *:ro ]]; then + entry="${entry%:ro}" opt=--readonly label=" (read-only)" + fi + OPTS+=("${opt}") + LABELS+=("${label}") SOCKS+=("$2") - TAGS+=("${3%%=*}") - DIRS+=("${3#*=}") + TAGS+=("${entry%%=*}") + DIRS+=("${entry#*=}") shift 3 done [[ ${#SOCKS[@]} -gt 0 && "${1:-}" == -- && $# -ge 2 ]] || usage @@ -48,6 +56,7 @@ validate_share() { [[ -n "${dir}" ]] || die "share '${tag}': empty directory" [[ "${dir}" != *[[:space:]]* ]] \ || die "share '${tag}': directories containing whitespace are not supported ('${dir}')" + [[ -d "${dir}" ]] || die "share '${tag}': ${dir} is not a directory" [[ "${sock}" == *.sock ]] || die "socket '${sock}' must end in .sock" [[ ${#sock} -lt 108 ]] \ || die "socket path too long (${#sock} bytes): ${sock}; use a shorter share_sockdir" @@ -93,7 +102,7 @@ trap 'exit 143' TERM declare -A SHARED_DIRS=() start_virtiofsd() { local sock="${SOCKS[$1]}" dir - mkdir -p "${DIRS[$1]}" "$(dirname "${sock}")" + mkdir -p "$(dirname "${sock}")" dir="$(cd "${DIRS[$1]}" && pwd)" if [[ -n "${SHARED_DIRS[${dir}]:-}" ]]; then echo "virtiofs: warning: ${dir} is shared more than once; the instances do not share caches" >&2 @@ -107,6 +116,7 @@ start_virtiofsd() { --log-level warn \ --translate-uid="map:0:$(id -u):1" \ --translate-gid="map:0:$(id -g):1" \ + ${OPTS[$1]} \ "${sock%.sock}.log" 2>&1 & PIDS+=("$!") } @@ -133,7 +143,7 @@ for i in "${!SOCKS[@]}"; do done wait_for_sockets for i in "${!SOCKS[@]}"; do - echo "virtiofs: sharing '${TAGS[$i]}' = ${DIRS[$i]} (log: ${SOCKS[$i]%.sock}.log)" >&2 + echo "virtiofs: sharing '${TAGS[$i]}' = ${DIRS[$i]}${LABELS[$i]} (log: ${SOCKS[$i]%.sock}.log)" >&2 done # Not exec'd, so cleanup runs when the command ends.