diff --git a/Guide/src/reference/openvmm/management/cli.md b/Guide/src/reference/openvmm/management/cli.md index a7c94c204e..24e6c24b54 100644 --- a/Guide/src/reference/openvmm/management/cli.md +++ b/Guide/src/reference/openvmm/management/cli.md @@ -20,7 +20,7 @@ as well as the generated CLI help (via `cargo run -- --help`). * `--virtio-console`: Enables a virtio serial device (via the MMIO transport) for Linux console access instead of COM1. * `--virtio-console-pci`: Uses the PCI transport for the virtio serial console. * `--gfx`: Enable a graphical console over VNC (see below) -* `--virtio-9p`: Expose a virtio 9p file system. Uses the format `tag:root_path`, e.g. `myfs:C:\\`. +* `--virtio-9p`: Expose a virtio 9p file system. Uses the format `tag,root_path`, e.g. `myfs,C:\\`. The file system can be mounted in a Linux guest using `mount -t 9p -o trans=virtio tag /mnt/point`. You can specify this argument multiple times to create multiple file systems. * `--virtio-fs`: Expose a virtio-fs file system. The format is the same as `--virtio-9p`. The diff --git a/openvmm/openvmm_entry/src/cli_args.rs b/openvmm/openvmm_entry/src/cli_args.rs index f4a797f0e8..d73703d4b8 100644 --- a/openvmm/openvmm_entry/src/cli_args.rs +++ b/openvmm/openvmm_entry/src/cli_args.rs @@ -316,21 +316,21 @@ flags: #[clap(long, requires("igvm"), default_value = "auto=filesize", value_parser = parse_vtl2_relocation)] pub igvm_vtl2_relocation_type: Vtl2BaseAddressType, - /// add a virtio_9p device (e.g. myfs:C:\) - #[clap(long, value_name = "tag:root_path", value_parser = parse_fs_arg)] - pub virtio_9p: Vec<(String, String)>, + /// add a virtio_9p device (e.g. myfs,C:\) + #[clap(long, value_name = "tag,root_path")] + pub virtio_9p: Vec, /// output debug info from the 9p server #[clap(long)] pub virtio_9p_debug: bool, - /// add a virtio_fs device (e.g. myfs:C:\) - #[clap(long, value_name = "tag:root_path", value_parser = parse_fs_arg)] - pub virtio_fs: Vec<(String, String)>, + /// add a virtio_fs device (e.g. myfs,C:\,uid=1000,gid=2000) + #[clap(long, value_name = "tag,root_path,[options]")] + pub virtio_fs: Vec, - /// add a virtio_fs device for sharing memory (e.g. myfs:\SectionDirectoryPath) - #[clap(long, value_name = "tag:root_path", value_parser = parse_fs_arg)] - pub virtio_fs_shmem: Vec<(String, String)>, + /// add a virtio_fs device for sharing memory (e.g. myfs,\SectionDirectoryPath) + #[clap(long, value_name = "tag,root_path")] + pub virtio_fs_shmem: Vec, /// add a virtio_fs device under either the PCI or MMIO bus, or whatever the hypervisor supports (pci | mmio | auto) #[clap(long, value_name = "BUS", default_value = "auto")] @@ -525,9 +525,52 @@ flags: pub uefi_console_mode: Option, } -fn parse_fs_arg(opt: &str) -> Result<(String, String), &'static str> { - let (tag, root_path) = opt.split_once(':').ok_or("invalid value")?; - Ok((tag.to_owned(), root_path.to_owned())) +#[derive(Clone)] +pub struct FsArgs { + pub tag: String, + pub path: String, +} + +impl FromStr for FsArgs { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut s = s.split(','); + let (Some(tag), Some(path), None) = (s.next(), s.next(), s.next()) else { + anyhow::bail!("expected ,"); + }; + Ok(Self { + tag: tag.to_owned(), + path: path.to_owned(), + }) + } +} + +#[derive(Clone)] +pub struct FsArgsWithOptions { + /// The file system tag. + pub tag: String, + /// The root path. + pub path: String, + /// The extra options, joined with ';'. + pub options: String, +} + +impl FromStr for FsArgsWithOptions { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut s = s.split(','); + let (Some(tag), Some(path)) = (s.next(), s.next()) else { + anyhow::bail!("expected ,[,]"); + }; + let options = s.collect::>().join(";"); + Ok(Self { + tag: tag.to_owned(), + path: path.to_owned(), + options, + }) + } } #[derive(Copy, Clone, clap::ValueEnum)] diff --git a/openvmm/openvmm_entry/src/lib.rs b/openvmm/openvmm_entry/src/lib.rs index f592cd4759..5f0b613313 100644 --- a/openvmm/openvmm_entry/src/lib.rs +++ b/openvmm/openvmm_entry/src/lib.rs @@ -1172,38 +1172,39 @@ fn vm_config_from_command_line( ); } - for (tag, root_path) in &opt.virtio_fs { + for args in &opt.virtio_fs { add_virtio_device( opt.virtio_fs_bus, virtio_resources::fs::VirtioFsHandle { - tag: tag.clone(), + tag: args.tag.clone(), fs: virtio_resources::fs::VirtioFsBackend::HostFs { - root_path: root_path.clone(), + root_path: args.path.clone(), + mount_options: args.options.clone(), }, } .into_resource(), ); } - for (tag, root_path) in &opt.virtio_fs_shmem { + for args in &opt.virtio_fs_shmem { add_virtio_device( opt.virtio_fs_bus, virtio_resources::fs::VirtioFsHandle { - tag: tag.clone(), + tag: args.tag.clone(), fs: virtio_resources::fs::VirtioFsBackend::SectionFs { - root_path: root_path.clone(), + root_path: args.path.clone(), }, } .into_resource(), ); } - for (tag, root_path) in &opt.virtio_9p { + for args in &opt.virtio_9p { add_virtio_device( VirtioBusCli::Auto, virtio_resources::p9::VirtioPlan9Handle { - tag: tag.clone(), - root_path: root_path.clone(), + tag: args.tag.clone(), + root_path: args.path.clone(), debug: opt.virtio_9p_debug, } .into_resource(), diff --git a/openvmm/openvmm_entry/src/ttrpc/mod.rs b/openvmm/openvmm_entry/src/ttrpc/mod.rs index d1ed4c1755..e05dd54989 100644 --- a/openvmm/openvmm_entry/src/ttrpc/mod.rs +++ b/openvmm/openvmm_entry/src/ttrpc/mod.rs @@ -546,6 +546,7 @@ impl VmService { tag: virtiofs.tag, fs: virtio_resources::fs::VirtioFsBackend::HostFs { root_path: virtiofs.root_path, + mount_options: String::new(), }, } .into_resource(); diff --git a/vm/devices/virtio/virtio_resources/src/lib.rs b/vm/devices/virtio/virtio_resources/src/lib.rs index c14c25d8e9..d0ff58587e 100644 --- a/vm/devices/virtio/virtio_resources/src/lib.rs +++ b/vm/devices/virtio/virtio_resources/src/lib.rs @@ -52,8 +52,13 @@ pub mod fs { #[derive(MeshPayload)] pub enum VirtioFsBackend { - HostFs { root_path: String }, - SectionFs { root_path: String }, + HostFs { + root_path: String, + mount_options: String, + }, + SectionFs { + root_path: String, + }, } impl ResourceId for VirtioFsHandle { diff --git a/vm/devices/virtio/virtiofs/src/resolver.rs b/vm/devices/virtio/virtiofs/src/resolver.rs index 22ed6240e3..3463864a57 100644 --- a/vm/devices/virtio/virtiofs/src/resolver.rs +++ b/vm/devices/virtio/virtiofs/src/resolver.rs @@ -5,6 +5,7 @@ use crate::virtio::VirtioFsDevice; use crate::VirtioFs; +use lxutil::LxVolumeOptions; use virtio::resolve::ResolvedVirtioDevice; use virtio::resolve::VirtioResolveInput; use virtio_resources::fs::VirtioFsBackend; @@ -31,10 +32,16 @@ impl ResolveResource for VirtioFsResolver { input: VirtioResolveInput<'_>, ) -> Result { let device = match &resource.fs { - VirtioFsBackend::HostFs { root_path } => VirtioFsDevice::new( + VirtioFsBackend::HostFs { + root_path, + mount_options, + } => VirtioFsDevice::new( input.driver_source, &resource.tag, - VirtioFs::new(root_path, None)?, + VirtioFs::new( + root_path, + Some(&LxVolumeOptions::from_option_string(mount_options)), + )?, input.guest_memory.clone(), 0, None,