devices/virtio/vhost_user_backend/block/sys/
linux.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::Context;
6use argh::FromArgs;
7use base::RawDescriptor;
8use cros_async::Executor;
9use hypervisor::ProtectionType;
10
11use crate::virtio::base_features;
12use crate::virtio::block::DiskOption;
13use crate::virtio::vhost_user_backend::BackendConnection;
14use crate::virtio::BlockAsync;
15
16#[derive(FromArgs)]
17#[argh(subcommand, name = "block")]
18/// Block device
19pub struct Options {
20    #[argh(option, arg_name = "PATH", hidden_help)]
21    /// deprecated - please use --socket-path instead
22    socket: Option<String>,
23    #[argh(option, arg_name = "PATH")]
24    /// path to the vhost-user socket to bind to.
25    /// If this flag is set, --fd cannot be specified.
26    socket_path: Option<String>,
27    #[argh(option, arg_name = "FD")]
28    /// file descriptor of a connected vhost-user socket.
29    /// If this flag is set, --socket-path cannot be specified.
30    fd: Option<RawDescriptor>,
31
32    #[argh(option, arg_name = "PATH<:read-only>")]
33    /// path and options of the disk file.
34    file: String,
35}
36
37/// Starts a vhost-user block device.
38/// Returns an error if the given `args` is invalid or the device fails to run.
39pub fn start_device(opts: Options) -> anyhow::Result<()> {
40    let ex = Executor::new().context("failed to create executor")?;
41
42    let mut fileopts = opts.file.split(':').collect::<Vec<_>>();
43    let filename = fileopts.remove(0);
44
45    let disk = DiskOption {
46        path: filename.into(),
47        read_only: fileopts.contains(&"read-only"),
48        sparse: false,
49        ..DiskOption::default()
50    };
51
52    let block = Box::new(BlockAsync::new(
53        base_features(ProtectionType::Unprotected),
54        disk.open()?,
55        &disk,
56        None,
57        None,
58        None,
59    )?);
60
61    let conn =
62        BackendConnection::from_opts(opts.socket.as_deref(), opts.socket_path.as_deref(), opts.fd)?;
63
64    conn.run_device(ex, block)
65}